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