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.
5 #ifndef CHROME_BROWSER_EXTENSIONS_API_TABS_TABS_EVENT_ROUTER_H_
6 #define CHROME_BROWSER_EXTENSIONS_API_TABS_TABS_EVENT_ROUTER_H_
11 #include "base/basictypes.h"
12 #include "base/compiler_specific.h"
13 #include "base/memory/linked_ptr.h"
14 #include "base/scoped_observer.h"
15 #include "chrome/browser/extensions/api/tabs/tabs_api.h"
16 #include "chrome/browser/ui/browser_list_observer.h"
17 #include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
18 #include "components/favicon/core/favicon_driver_observer.h"
19 #include "components/ui/zoom/zoom_observer.h"
20 #include "content/public/browser/notification_registrar.h"
21 #include "extensions/browser/event_router.h"
31 namespace extensions
{
33 // The TabsEventRouter listens to tab events and routes them to listeners inside
34 // extension process renderers.
35 // TabsEventRouter will only route events from windows/tabs within a profile to
36 // extension processes in the same profile.
37 class TabsEventRouter
: public TabStripModelObserver
,
38 public chrome::BrowserListObserver
,
39 public content::NotificationObserver
,
40 public favicon::FaviconDriverObserver
,
41 public ui_zoom::ZoomObserver
{
43 explicit TabsEventRouter(Profile
* profile
);
44 ~TabsEventRouter() override
;
46 // chrome::BrowserListObserver
47 void OnBrowserAdded(Browser
* browser
) override
;
48 void OnBrowserRemoved(Browser
* browser
) override
;
49 void OnBrowserSetLastActive(Browser
* browser
) override
;
51 // TabStripModelObserver
52 void TabInsertedAt(content::WebContents
* contents
,
54 bool active
) override
;
55 void TabClosingAt(TabStripModel
* tab_strip_model
,
56 content::WebContents
* contents
,
58 void TabDetachedAt(content::WebContents
* contents
, int index
) override
;
59 void ActiveTabChanged(content::WebContents
* old_contents
,
60 content::WebContents
* new_contents
,
63 void TabSelectionChanged(TabStripModel
* tab_strip_model
,
64 const ui::ListSelectionModel
& old_model
) override
;
65 void TabMoved(content::WebContents
* contents
,
67 int to_index
) override
;
68 void TabChangedAt(content::WebContents
* contents
,
70 TabChangeType change_type
) override
;
71 void TabReplacedAt(TabStripModel
* tab_strip_model
,
72 content::WebContents
* old_contents
,
73 content::WebContents
* new_contents
,
75 void TabPinnedStateChanged(content::WebContents
* contents
,
78 // content::NotificationObserver.
79 void Observe(int type
,
80 const content::NotificationSource
& source
,
81 const content::NotificationDetails
& details
) override
;
85 const ui_zoom::ZoomController::ZoomChangedEventData
& data
) override
;
87 // favicon::FaviconDriverObserver.
88 void OnFaviconAvailable(const gfx::Image
& image
) override
;
89 void OnFaviconUpdated(favicon::FaviconDriver
* favicon_driver
,
90 bool icon_url_changed
) override
;
93 // "Synthetic" event. Called from TabInsertedAt if new tab is detected.
94 void TabCreatedAt(content::WebContents
* contents
, int index
, bool active
);
96 // Internal processing of tab updated events. Is called by both TabChangedAt
97 // and Observe/NAV_ENTRY_COMMITTED.
99 void TabUpdated(linked_ptr
<TabEntry
> entry
,
100 scoped_ptr
<base::DictionaryValue
> changed_properties
);
102 // Triggers a tab updated event if the favicon URL changes.
103 void FaviconUrlUpdated(content::WebContents
* contents
);
105 // The DispatchEvent methods forward events to the |profile|'s event router.
106 // The TabsEventRouter listens to events for all profiles,
107 // so we avoid duplication by dropping events destined for other profiles.
108 void DispatchEvent(Profile
* profile
,
109 events::HistogramValue histogram_value
,
110 const std::string
& event_name
,
111 scoped_ptr
<base::ListValue
> args
,
112 EventRouter::UserGestureState user_gesture
);
114 void DispatchEventsAcrossIncognito(
116 const std::string
& event_name
,
117 scoped_ptr
<base::ListValue
> event_args
,
118 scoped_ptr
<base::ListValue
> cross_incognito_args
);
120 // Packages |changed_properties| as a tab updated event for the tab |contents|
121 // and dispatches the event to the extension.
122 void DispatchTabUpdatedEvent(
123 content::WebContents
* contents
,
124 scoped_ptr
<base::DictionaryValue
> changed_properties
);
126 // Register ourselves to receive the various notifications we are interested
128 void RegisterForBrowserNotifications(Browser
* browser
);
130 // Register ourselves to receive the various notifications we are interested
132 void RegisterForTabNotifications(content::WebContents
* contents
);
134 // Removes notifications added in RegisterForTabNotifications.
135 void UnregisterForTabNotifications(content::WebContents
* contents
);
137 content::NotificationRegistrar registrar_
;
139 // Maintain some information about known tabs, so we can:
141 // - distinguish between tab creation and tab insertion
142 // - not send tab-detached after tab-removed
143 // - reduce the "noise" of TabChangedAt() when sending events to extensions
144 // - remember last muted and audible states to know if there was a change
147 // Create a TabEntry associated with, and tracking state changes to,
149 explicit TabEntry(content::WebContents
* contents
);
151 // Indicate via a list of key/value pairs if a tab is loading based on its
152 // WebContents. Whether the state has changed or not is used to determine
153 // if events needs to be sent to extensions during processing of
154 // TabChangedAt(). If this method indicates that a tab should "hold" a
155 // state-change to "loading", the DidNavigate() method should eventually
156 // send a similar message to undo it. If false, the returned key/value
157 // pairs list is empty.
158 scoped_ptr
<base::DictionaryValue
> UpdateLoadState();
160 // Indicate via a list of key/value pairs that a tab load has resulted in a
161 // navigation and the destination url is available for inspection. The list
162 // is empty if no updates should be sent.
163 scoped_ptr
<base::DictionaryValue
> DidNavigate();
165 // Update the audible and muted states and return whether they were changed
166 bool SetAudible(bool new_val
);
167 bool SetMuted(bool new_val
);
169 content::WebContents
* web_contents() { return contents_
; }
172 content::WebContents
* contents_
;
174 // Whether we are waiting to fire the 'complete' status change. This will
175 // occur the first time the WebContents stops loading after the
176 // NAV_ENTRY_COMMITTED was fired. The tab may go back into and out of the
177 // loading state subsequently, but we will ignore those changes.
178 bool complete_waiting_on_load_
;
180 // Previous audible and muted states
187 // Gets the TabEntry for the given |contents|. Returns linked_ptr<TabEntry>
188 // if found, NULL if not.
189 linked_ptr
<TabEntry
> GetTabEntry(content::WebContents
* contents
);
191 using TabEntryMap
= std::map
<int, linked_ptr
<TabEntry
>>;
192 TabEntryMap tab_entries_
;
194 // The main profile that owns this event router.
197 ScopedObserver
<favicon::FaviconDriver
, TabsEventRouter
>
198 favicon_scoped_observer_
;
200 DISALLOW_COPY_AND_ASSIGN(TabsEventRouter
);
203 } // namespace extensions
205 #endif // CHROME_BROWSER_EXTENSIONS_API_TABS_TABS_EVENT_ROUTER_H_