• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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