1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_BROWSER_EVENT_ROUTER_H_ 6 #define CHROME_BROWSER_EXTENSIONS_EXTENSION_BROWSER_EVENT_ROUTER_H_ 7 #pragma once 8 9 #include <map> 10 #include <string> 11 12 #include "base/basictypes.h" 13 #include "chrome/browser/extensions/extension_tabs_module.h" 14 #include "chrome/browser/tabs/tab_strip_model_observer.h" 15 #include "chrome/browser/ui/browser_list.h" 16 #include "content/common/notification_registrar.h" 17 #if defined(TOOLKIT_VIEWS) 18 #include "views/focus/focus_manager.h" 19 #include "views/view.h" 20 #elif defined(TOOLKIT_GTK) 21 #include "ui/base/x/active_window_watcher_x.h" 22 #endif 23 24 // The ExtensionBrowserEventRouter listens to Browser window & tab events 25 // and routes them to listeners inside extension process renderers. 26 // ExtensionBrowserEventRouter listens to *all* events, but will only route 27 // events from windows/tabs within a profile to extension processes in the same 28 // profile. 29 class ExtensionBrowserEventRouter : public TabStripModelObserver, 30 #if defined(TOOLKIT_VIEWS) 31 public views::WidgetFocusChangeListener, 32 #elif defined(TOOLKIT_GTK) 33 public ui::ActiveWindowWatcherX::Observer, 34 #endif 35 public BrowserList::Observer, 36 public NotificationObserver { 37 public: 38 explicit ExtensionBrowserEventRouter(Profile* profile); 39 ~ExtensionBrowserEventRouter(); 40 41 // Must be called once. Subsequent calls have no effect. 42 void Init(); 43 44 // BrowserList::Observer 45 virtual void OnBrowserAdded(const Browser* browser); 46 virtual void OnBrowserRemoved(const Browser* browser); 47 virtual void OnBrowserSetLastActive(const Browser* browser); 48 49 #if defined(TOOLKIT_VIEWS) 50 virtual void NativeFocusWillChange(gfx::NativeView focused_before, 51 gfx::NativeView focused_now); 52 #elif defined(TOOLKIT_GTK) 53 virtual void ActiveWindowChanged(GdkWindow* active_window); 54 #endif 55 56 // Called from Observe() on BROWSER_WINDOW_READY (not a part of 57 // BrowserList::Observer). 58 void OnBrowserWindowReady(const Browser* browser); 59 60 // TabStripModelObserver 61 virtual void TabInsertedAt(TabContentsWrapper* contents, int index, 62 bool foreground); 63 virtual void TabClosingAt(TabStripModel* tab_strip_model, 64 TabContentsWrapper* contents, 65 int index); 66 virtual void TabDetachedAt(TabContentsWrapper* contents, int index); 67 virtual void TabSelectedAt(TabContentsWrapper* old_contents, 68 TabContentsWrapper* new_contents, 69 int index, 70 bool user_gesture); 71 virtual void TabMoved(TabContentsWrapper* contents, int from_index, 72 int to_index); 73 virtual void TabChangedAt(TabContentsWrapper* contents, int index, 74 TabChangeType change_type); 75 virtual void TabReplacedAt(TabStripModel* tab_strip_model, 76 TabContentsWrapper* old_contents, 77 TabContentsWrapper* new_contents, 78 int index); 79 virtual void TabPinnedStateChanged(TabContentsWrapper* contents, int index); 80 virtual void TabStripEmpty(); 81 82 // Page Action execute event. 83 void PageActionExecuted(Profile* profile, 84 const std::string& extension_id, 85 const std::string& page_action_id, 86 int tab_id, 87 const std::string& url, 88 int button); 89 // Browser Actions execute event. 90 void BrowserActionExecuted(Profile* profile, 91 const std::string& extension_id, 92 Browser* browser); 93 94 // NotificationObserver. 95 virtual void Observe(NotificationType type, 96 const NotificationSource& source, 97 const NotificationDetails& details); 98 private: 99 // "Synthetic" event. Called from TabInsertedAt if new tab is detected. 100 void TabCreatedAt(TabContents* contents, int index, bool foreground); 101 102 // Internal processing of tab updated events. Is called by both TabChangedAt 103 // and Observe/NAV_ENTRY_COMMITTED. 104 void TabUpdated(TabContents* contents, bool did_navigate); 105 106 // Packages |changed_properties| as a tab updated event for the tab |contents| 107 // and dispatches the event to the extension. 108 void DispatchTabUpdatedEvent(TabContents* contents, 109 DictionaryValue* changed_properties); 110 111 // Called to dispatch a deprecated style page action click event that was 112 // registered like: 113 // chrome.pageActions["name"].addListener(function(actionId, info){}) 114 void DispatchOldPageActionEvent(Profile* profile, 115 const std::string& extension_id, 116 const std::string& page_action_id, 117 int tab_id, 118 const std::string& url, 119 int button); 120 121 // Register ourselves to receive the various notifications we are interested 122 // in for a browser. 123 void RegisterForBrowserNotifications(const Browser* browser); 124 125 // Register ourselves to receive the various notifications we are interested 126 // in for a tab. 127 void RegisterForTabNotifications(TabContents* contents); 128 129 // Removes notifications added in RegisterForTabNotifications. 130 void UnregisterForTabNotifications(TabContents* contents); 131 132 NotificationRegistrar registrar_; 133 134 bool initialized_; 135 136 // Maintain some information about known tabs, so we can: 137 // 138 // - distinguish between tab creation and tab insertion 139 // - not send tab-detached after tab-removed 140 // - reduce the "noise" of TabChangedAt() when sending events to extensions 141 class TabEntry { 142 public: 143 // Create a new tab entry whose initial state is TAB_COMPLETE. This 144 // constructor is required because TabEntry objects placed inside an 145 // std::map<> by value. 146 TabEntry(); 147 148 // Update the load state of the tab based on its TabContents. Returns true 149 // if the state changed, false otherwise. Whether the state has changed or 150 // not is used to determine if events needs to be sent to extensions during 151 // processing of TabChangedAt(). This method will "hold" a state-change 152 // to "loading", until the DidNavigate() method which should always follow 153 // it. Returns NULL if no updates should be sent. 154 DictionaryValue* UpdateLoadState(const TabContents* contents); 155 156 // Indicates that a tab load has resulted in a navigation and the 157 // destination url is available for inspection. Returns NULL if no updates 158 // should be sent. 159 DictionaryValue* DidNavigate(const TabContents* contents); 160 161 private: 162 // Whether we are waiting to fire the 'complete' status change. This will 163 // occur the first time the TabContents stops loading after the 164 // NAV_ENTRY_COMMITTED was fired. The tab may go back into and out of the 165 // loading state subsequently, but we will ignore those changes. 166 bool complete_waiting_on_load_; 167 168 GURL url_; 169 }; 170 171 // Gets the TabEntry for the given |contents|. Returns TabEntry* if 172 // found, NULL if not. 173 TabEntry* GetTabEntry(const TabContents* contents); 174 175 std::map<int, TabEntry> tab_entries_; 176 177 // The currently focused window. We keep this so as to avoid sending multiple 178 // windows.onFocusChanged events with the same windowId. 179 int focused_window_id_; 180 181 // The main profile (non-OTR) profile which will be used to send events not 182 // associated with any browser. 183 Profile* profile_; 184 185 DISALLOW_COPY_AND_ASSIGN(ExtensionBrowserEventRouter); 186 }; 187 188 #endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_BROWSER_EVENT_ROUTER_H_ 189