• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 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_API_TABS_TABS_EVENT_ROUTER_H_
6 #define CHROME_BROWSER_EXTENSIONS_API_TABS_TABS_EVENT_ROUTER_H_
7 
8 #include <map>
9 #include <string>
10 
11 #include "base/basictypes.h"
12 #include "base/compiler_specific.h"
13 #include "chrome/browser/extensions/api/tabs/tabs_api.h"
14 #include "chrome/browser/ui/browser_list_observer.h"
15 #include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
16 #include "chrome/browser/ui/zoom/zoom_observer.h"
17 #include "content/public/browser/notification_registrar.h"
18 #include "extensions/browser/event_router.h"
19 
20 namespace content {
21 class WebContents;
22 }
23 
24 namespace extensions {
25 
26 // The TabsEventRouter listens to tab events and routes them to listeners inside
27 // extension process renderers.
28 // TabsEventRouter will only route events from windows/tabs within a profile to
29 // extension processes in the same profile.
30 class TabsEventRouter : public TabStripModelObserver,
31                         public chrome::BrowserListObserver,
32                         public content::NotificationObserver,
33                         public ZoomObserver {
34  public:
35   explicit TabsEventRouter(Profile* profile);
36   virtual ~TabsEventRouter();
37 
38   // chrome::BrowserListObserver
39   virtual void OnBrowserAdded(Browser* browser) OVERRIDE;
40   virtual void OnBrowserRemoved(Browser* browser) OVERRIDE;
41   virtual void OnBrowserSetLastActive(Browser* browser) OVERRIDE;
42 
43   // TabStripModelObserver
44   virtual void TabInsertedAt(content::WebContents* contents, int index,
45                              bool active) OVERRIDE;
46   virtual void TabClosingAt(TabStripModel* tab_strip_model,
47                             content::WebContents* contents,
48                             int index) OVERRIDE;
49   virtual void TabDetachedAt(content::WebContents* contents,
50                              int index) OVERRIDE;
51   virtual void ActiveTabChanged(content::WebContents* old_contents,
52                                 content::WebContents* new_contents,
53                                 int index,
54                                 int reason) OVERRIDE;
55   virtual void TabSelectionChanged(
56       TabStripModel* tab_strip_model,
57       const ui::ListSelectionModel& old_model) OVERRIDE;
58   virtual void TabMoved(content::WebContents* contents,
59                         int from_index,
60                         int to_index) OVERRIDE;
61   virtual void TabChangedAt(content::WebContents* contents,
62                             int index,
63                             TabChangeType change_type) OVERRIDE;
64   virtual void TabReplacedAt(TabStripModel* tab_strip_model,
65                              content::WebContents* old_contents,
66                              content::WebContents* new_contents,
67                              int index) OVERRIDE;
68   virtual void TabPinnedStateChanged(content::WebContents* contents,
69                                      int index) OVERRIDE;
70 
71   // content::NotificationObserver.
72   virtual void Observe(int type,
73                        const content::NotificationSource& source,
74                        const content::NotificationDetails& details) OVERRIDE;
75 
76   // ZoomObserver.
77   virtual void OnZoomChanged(
78       const ZoomController::ZoomChangedEventData& data) OVERRIDE;
79 
80  private:
81   // "Synthetic" event. Called from TabInsertedAt if new tab is detected.
82   void TabCreatedAt(content::WebContents* contents, int index, bool active);
83 
84   // Internal processing of tab updated events. Is called by both TabChangedAt
85   // and Observe/NAV_ENTRY_COMMITTED.
86   void TabUpdated(content::WebContents* contents, bool did_navigate);
87 
88   // Triggers a tab updated event if the favicon URL changes.
89   void FaviconUrlUpdated(content::WebContents* contents);
90 
91   // The DispatchEvent methods forward events to the |profile|'s event router.
92   // The TabsEventRouter listens to events for all profiles,
93   // so we avoid duplication by dropping events destined for other profiles.
94   void DispatchEvent(Profile* profile,
95                      const std::string& event_name,
96                      scoped_ptr<base::ListValue> args,
97                      EventRouter::UserGestureState user_gesture);
98 
99   void DispatchEventsAcrossIncognito(
100       Profile* profile,
101       const std::string& event_name,
102       scoped_ptr<base::ListValue> event_args,
103       scoped_ptr<base::ListValue> cross_incognito_args);
104 
105   void DispatchSimpleBrowserEvent(Profile* profile,
106                                   const int window_id,
107                                   const std::string& event_name);
108 
109   // Packages |changed_properties| as a tab updated event for the tab |contents|
110   // and dispatches the event to the extension.
111   void DispatchTabUpdatedEvent(
112       content::WebContents* contents,
113       scoped_ptr<base::DictionaryValue> changed_properties);
114 
115   // Register ourselves to receive the various notifications we are interested
116   // in for a browser.
117   void RegisterForBrowserNotifications(Browser* browser);
118 
119   // Register ourselves to receive the various notifications we are interested
120   // in for a tab.
121   void RegisterForTabNotifications(content::WebContents* contents);
122 
123   // Removes notifications added in RegisterForTabNotifications.
124   void UnregisterForTabNotifications(content::WebContents* contents);
125 
126   content::NotificationRegistrar registrar_;
127 
128   // Maintain some information about known tabs, so we can:
129   //
130   //  - distinguish between tab creation and tab insertion
131   //  - not send tab-detached after tab-removed
132   //  - reduce the "noise" of TabChangedAt() when sending events to extensions
133   class TabEntry {
134    public:
135     // Create a new tab entry whose initial state is TAB_COMPLETE.  This
136     // constructor is required because TabEntry objects placed inside an
137     // std::map<> by value.
138     TabEntry();
139 
140     // Update the load state of the tab based on its WebContents.  Returns true
141     // if the state changed, false otherwise.  Whether the state has changed or
142     // not is used to determine if events needs to be sent to extensions during
143     // processing of TabChangedAt(). This method will "hold" a state-change
144     // to "loading", until the DidNavigate() method which should always follow
145     // it. Returns NULL if no updates should be sent.
146     base::DictionaryValue* UpdateLoadState(
147         const content::WebContents* contents);
148 
149     // Indicates that a tab load has resulted in a navigation and the
150     // destination url is available for inspection. Returns NULL if no updates
151     // should be sent.
152     base::DictionaryValue* DidNavigate(const content::WebContents* contents);
153 
154    private:
155     // Whether we are waiting to fire the 'complete' status change. This will
156     // occur the first time the WebContents stops loading after the
157     // NAV_ENTRY_COMMITTED was fired. The tab may go back into and out of the
158     // loading state subsequently, but we will ignore those changes.
159     bool complete_waiting_on_load_;
160 
161     GURL url_;
162   };
163 
164   // Gets the TabEntry for the given |contents|. Returns TabEntry* if
165   // found, NULL if not.
166   TabEntry* GetTabEntry(content::WebContents* contents);
167 
168   std::map<int, TabEntry> tab_entries_;
169 
170   // The main profile that owns this event router.
171   Profile* profile_;
172 
173   DISALLOW_COPY_AND_ASSIGN(TabsEventRouter);
174 };
175 
176 }  // namespace extensions
177 
178 #endif  // CHROME_BROWSER_EXTENSIONS_API_TABS_TABS_EVENT_ROUTER_H_
179