Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(306)

Side by Side Diff: chrome/browser/extensions/extension_browser_event_router.cc

Issue 10777004: Support chrome.windows extension API events for browserless Panels. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix non-mac compiles Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/extension_browser_event_router.h" 5 #include "chrome/browser/extensions/extension_browser_event_router.h"
6 6
7 #include "base/json/json_writer.h" 7 #include "base/json/json_writer.h"
8 #include "base/values.h" 8 #include "base/values.h"
9 #include "chrome/browser/extensions/api/extension_action/extension_page_actions_ api_constants.h" 9 #include "chrome/browser/extensions/api/extension_action/extension_page_actions_ api_constants.h"
10 #include "chrome/browser/extensions/api/tabs/tabs_constants.h" 10 #include "chrome/browser/extensions/api/tabs/tabs_constants.h"
11 #include "chrome/browser/extensions/extension_event_names.h" 11 #include "chrome/browser/extensions/extension_event_names.h"
12 #include "chrome/browser/extensions/extension_event_router.h" 12 #include "chrome/browser/extensions/extension_event_router.h"
13 #include "chrome/browser/extensions/extension_service.h" 13 #include "chrome/browser/extensions/extension_service.h"
14 #include "chrome/browser/extensions/extension_system.h"
14 #include "chrome/browser/extensions/extension_tab_util.h" 15 #include "chrome/browser/extensions/extension_tab_util.h"
15 #include "chrome/browser/extensions/window_controller.h" 16 #include "chrome/browser/extensions/window_controller.h"
17 #include "chrome/browser/extensions/window_event_router.h"
16 #include "chrome/browser/profiles/profile.h" 18 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/browser/ui/browser.h" 19 #include "chrome/browser/ui/browser.h"
18 #include "chrome/browser/ui/browser_list.h" 20 #include "chrome/browser/ui/browser_list.h"
19 #include "chrome/browser/ui/browser_tabstrip.h" 21 #include "chrome/browser/ui/browser_tabstrip.h"
20 #include "chrome/browser/ui/tab_contents/tab_contents.h" 22 #include "chrome/browser/ui/tab_contents/tab_contents.h"
21 #include "chrome/browser/ui/tabs/tab_strip_model.h" 23 #include "chrome/browser/ui/tabs/tab_strip_model.h"
22 #include "chrome/common/chrome_notification_types.h"
23 #include "chrome/common/extensions/extension.h" 24 #include "chrome/common/extensions/extension.h"
24 #include "chrome/common/extensions/extension_constants.h" 25 #include "chrome/common/extensions/extension_constants.h"
25 #include "content/public/browser/navigation_controller.h" 26 #include "content/public/browser/navigation_controller.h"
26 #include "content/public/browser/notification_service.h" 27 #include "content/public/browser/notification_service.h"
28 #include "content/public/browser/notification_types.h"
27 #include "content/public/browser/web_contents.h" 29 #include "content/public/browser/web_contents.h"
28 30
29 #if defined(TOOLKIT_GTK)
30 #include "ui/base/x/active_window_watcher_x.h"
31 #endif
32
33 namespace events = extension_event_names; 31 namespace events = extension_event_names;
34 namespace tab_keys = extensions::tabs_constants; 32 namespace tab_keys = extensions::tabs_constants;
35 namespace page_action_keys = extension_page_actions_api_constants; 33 namespace page_action_keys = extension_page_actions_api_constants;
36 34
37 using content::NavigationController; 35 using content::NavigationController;
38 using content::WebContents; 36 using content::WebContents;
39 37
40 ExtensionBrowserEventRouter::TabEntry::TabEntry() 38 ExtensionBrowserEventRouter::TabEntry::TabEntry()
41 : complete_waiting_on_load_(false), 39 : complete_waiting_on_load_(false),
42 url_() { 40 url_() {
(...skipping 28 matching lines...) Expand all
71 changed_properties->SetString(tab_keys::kUrlKey, url_.spec()); 69 changed_properties->SetString(tab_keys::kUrlKey, url_.spec());
72 } 70 }
73 71
74 return changed_properties; 72 return changed_properties;
75 } 73 }
76 74
77 void ExtensionBrowserEventRouter::Init() { 75 void ExtensionBrowserEventRouter::Init() {
78 if (initialized_) 76 if (initialized_)
79 return; 77 return;
80 BrowserList::AddObserver(this); 78 BrowserList::AddObserver(this);
81 #if defined(TOOLKIT_VIEWS)
82 views::WidgetFocusManager::GetInstance()->AddFocusChangeListener(this);
83 #elif defined(TOOLKIT_GTK)
84 ui::ActiveWindowWatcherX::AddObserver(this);
85 #elif defined(OS_MACOSX)
86 // Needed for when no suitable window can be passed to an extension as the
87 // currently focused window.
88 registrar_.Add(this, chrome::NOTIFICATION_NO_KEY_WINDOW,
89 content::NotificationService::AllSources());
90 #endif
91 79
92 // Init() can happen after the browser is running, so catch up with any 80 // Init() can happen after the browser is running, so catch up with any
93 // windows that already exist. 81 // windows that already exist.
94 for (BrowserList::const_iterator iter = BrowserList::begin(); 82 for (BrowserList::const_iterator iter = BrowserList::begin();
95 iter != BrowserList::end(); ++iter) { 83 iter != BrowserList::end(); ++iter) {
96 RegisterForBrowserNotifications(*iter); 84 RegisterForBrowserNotifications(*iter);
97 85
98 // Also catch up our internal bookkeeping of tab entries. 86 // Also catch up our internal bookkeeping of tab entries.
99 Browser* browser = *iter; 87 Browser* browser = *iter;
100 if (browser->tab_strip_model()) { 88 if (browser->tab_strip_model()) {
101 for (int i = 0; i < browser->tab_strip_model()->count(); ++i) { 89 for (int i = 0; i < browser->tab_strip_model()->count(); ++i) {
102 WebContents* contents = 90 WebContents* contents =
103 chrome::GetTabContentsAt(browser, i)->web_contents(); 91 chrome::GetTabContentsAt(browser, i)->web_contents();
104 int tab_id = ExtensionTabUtil::GetTabId(contents); 92 int tab_id = ExtensionTabUtil::GetTabId(contents);
105 tab_entries_[tab_id] = TabEntry(); 93 tab_entries_[tab_id] = TabEntry();
106 } 94 }
107 } 95 }
108 } 96 }
109 97
110 initialized_ = true; 98 initialized_ = true;
111 } 99 }
112 100
113 ExtensionBrowserEventRouter::ExtensionBrowserEventRouter(Profile* profile) 101 ExtensionBrowserEventRouter::ExtensionBrowserEventRouter(Profile* profile)
114 : initialized_(false), 102 : initialized_(false),
115 profile_(profile), 103 profile_(profile) {
116 focused_profile_(NULL),
117 focused_window_id_(extension_misc::kUnknownWindowId) {
118 DCHECK(!profile->IsOffTheRecord()); 104 DCHECK(!profile->IsOffTheRecord());
119 } 105 }
120 106
121 ExtensionBrowserEventRouter::~ExtensionBrowserEventRouter() { 107 ExtensionBrowserEventRouter::~ExtensionBrowserEventRouter() {
122 BrowserList::RemoveObserver(this); 108 BrowserList::RemoveObserver(this);
123 #if defined(TOOLKIT_VIEWS)
124 views::WidgetFocusManager::GetInstance()->RemoveFocusChangeListener(this);
125 #elif defined(TOOLKIT_GTK)
126 ui::ActiveWindowWatcherX::RemoveObserver(this);
127 #endif
128 } 109 }
129 110
130 void ExtensionBrowserEventRouter::OnBrowserAdded(Browser* browser) { 111 void ExtensionBrowserEventRouter::OnBrowserAdded(Browser* browser) {
131 RegisterForBrowserNotifications(browser); 112 RegisterForBrowserNotifications(browser);
132 } 113 }
133 114
134 void ExtensionBrowserEventRouter::RegisterForBrowserNotifications( 115 void ExtensionBrowserEventRouter::RegisterForBrowserNotifications(
135 Browser* browser) { 116 Browser* browser) {
136 if (!profile_->IsSameProfile(browser->profile())) 117 if (!profile_->IsSameProfile(browser->profile()))
137 return; 118 return;
138 // Start listening to TabStripModel events for this browser. 119 // Start listening to TabStripModel events for this browser.
139 browser->tab_strip_model()->AddObserver(this); 120 browser->tab_strip_model()->AddObserver(this);
140 121
141 // If this is a new window, it isn't ready at this point, so we register to be
142 // notified when it is. If this is an existing window, this is a no-op that we
143 // just do to reduce code complexity.
144 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_WINDOW_READY,
145 content::Source<Browser>(browser));
146
147 for (int i = 0; i < browser->tab_strip_model()->count(); ++i) { 122 for (int i = 0; i < browser->tab_strip_model()->count(); ++i) {
148 RegisterForTabNotifications( 123 RegisterForTabNotifications(
149 chrome::GetTabContentsAt(browser, i)->web_contents()); 124 chrome::GetTabContentsAt(browser, i)->web_contents());
150 } 125 }
151 } 126 }
152 127
153 void ExtensionBrowserEventRouter::RegisterForTabNotifications( 128 void ExtensionBrowserEventRouter::RegisterForTabNotifications(
154 WebContents* contents) { 129 WebContents* contents) {
155 registrar_.Add( 130 registrar_.Add(
156 this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, 131 this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
157 content::Source<NavigationController>(&contents->GetController())); 132 content::Source<NavigationController>(&contents->GetController()));
158 133
159 // Observing NOTIFICATION_WEB_CONTENTS_DESTROYED is necessary because it's 134 // Observing NOTIFICATION_WEB_CONTENTS_DESTROYED is necessary because it's
160 // possible for tabs to be created, detached and then destroyed without 135 // possible for tabs to be created, detached and then destroyed without
161 // ever having been re-attached and closed. This happens in the case of 136 // ever having been re-attached and closed. This happens in the case of
162 // a devtools WebContents that is opened in window, docked, then closed. 137 // a devtools WebContents that is opened in window, docked, then closed.
163 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, 138 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
164 content::Source<WebContents>(contents)); 139 content::Source<WebContents>(contents));
165 } 140 }
166 141
167 void ExtensionBrowserEventRouter::UnregisterForTabNotifications( 142 void ExtensionBrowserEventRouter::UnregisterForTabNotifications(
168 WebContents* contents) { 143 WebContents* contents) {
169 registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, 144 registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
170 content::Source<NavigationController>(&contents->GetController())); 145 content::Source<NavigationController>(&contents->GetController()));
171 registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, 146 registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
172 content::Source<WebContents>(contents)); 147 content::Source<WebContents>(contents));
173 } 148 }
174 149
175 void ExtensionBrowserEventRouter::OnBrowserWindowReady(Browser* browser) {
176 ListValue args;
177
178 DCHECK(browser->extension_window_controller());
179 DictionaryValue* window_dictionary =
180 browser->extension_window_controller()->CreateWindowValue();
181 args.Append(window_dictionary);
182
183 std::string json_args;
184 base::JSONWriter::Write(&args, &json_args);
185
186 DispatchEvent(browser->profile(), events::kOnWindowCreated, json_args);
187 }
188
189 void ExtensionBrowserEventRouter::OnBrowserRemoved(Browser* browser) { 150 void ExtensionBrowserEventRouter::OnBrowserRemoved(Browser* browser) {
190 if (!profile_->IsSameProfile(browser->profile())) 151 if (!profile_->IsSameProfile(browser->profile()))
191 return; 152 return;
192 153
193 // Stop listening to TabStripModel events for this browser. 154 // Stop listening to TabStripModel events for this browser.
194 browser->tab_strip_model()->RemoveObserver(this); 155 browser->tab_strip_model()->RemoveObserver(this);
195
196 registrar_.Remove(this, chrome::NOTIFICATION_BROWSER_WINDOW_READY,
197 content::Source<Browser>(browser));
198
199 DispatchSimpleBrowserEvent(browser->profile(),
200 ExtensionTabUtil::GetWindowId(browser),
201 events::kOnWindowRemoved);
202 } 156 }
203 157
204 #if defined(TOOLKIT_VIEWS)
205 void ExtensionBrowserEventRouter::OnNativeFocusChange(
206 gfx::NativeView focused_before,
207 gfx::NativeView focused_now) {
208 if (!focused_now)
209 OnBrowserSetLastActive(NULL);
210 }
211 #elif defined(TOOLKIT_GTK)
212 void ExtensionBrowserEventRouter::ActiveWindowChanged(
213 GdkWindow* active_window) {
214 if (!active_window)
215 OnBrowserSetLastActive(NULL);
216 }
217 #endif
218
219 void ExtensionBrowserEventRouter::OnBrowserSetLastActive( 158 void ExtensionBrowserEventRouter::OnBrowserSetLastActive(
220 Browser* browser) { 159 Browser* browser) {
221 Profile* window_profile = NULL; 160 ExtensionService* service =
222 int window_id = extension_misc::kUnknownWindowId; 161 extensions::ExtensionSystem::Get(profile_)->extension_service();
223 if (browser && profile_->IsSameProfile(browser->profile())) { 162 if (service) {
224 window_profile = browser->profile(); 163 service->window_event_router()->OnActiveWindowChanged(
225 window_id = ExtensionTabUtil::GetWindowId(browser); 164 browser ? browser->extension_window_controller() : NULL);
226 } 165 }
227
228 if (focused_window_id_ == window_id)
229 return;
230
231 // window_profile is either this profile's default profile, its
232 // incognito profile, or NULL iff this profile is losing focus.
233 Profile* previous_focused_profile = focused_profile_;
234 focused_profile_ = window_profile;
235 focused_window_id_ = window_id;
236
237 ListValue real_args;
238 real_args.Append(Value::CreateIntegerValue(window_id));
239 std::string real_json_args;
240 base::JSONWriter::Write(&real_args, &real_json_args);
241
242 // When switching between windows in the default and incognitoi profiles,
243 // dispatch WINDOW_ID_NONE to extensions whose profile lost focus that
244 // can't see the new focused window across the incognito boundary.
245 // See crbug.com/46610.
246 std::string none_json_args;
247 if (focused_profile_ != NULL && previous_focused_profile != NULL &&
248 focused_profile_ != previous_focused_profile) {
249 ListValue none_args;
250 none_args.Append(
251 Value::CreateIntegerValue(extension_misc::kUnknownWindowId));
252 base::JSONWriter::Write(&none_args, &none_json_args);
253 }
254
255 DispatchEventsAcrossIncognito((focused_profile_ ? focused_profile_ :
256 previous_focused_profile),
257 events::kOnWindowFocusedChanged,
258 real_json_args,
259 none_json_args);
260 } 166 }
261 167
262 void ExtensionBrowserEventRouter::TabCreatedAt(WebContents* contents, 168 void ExtensionBrowserEventRouter::TabCreatedAt(WebContents* contents,
263 int index, 169 int index,
264 bool active) { 170 bool active) {
265 Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext()); 171 Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext());
266 DispatchEventWithTab(profile, "", events::kOnTabCreated, contents, active); 172 DispatchEventWithTab(profile, "", events::kOnTabCreated, contents, active);
267 173
268 RegisterForTabNotifications(contents); 174 RegisterForTabNotifications(contents);
269 } 175 }
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after
558 NavigationController* source_controller = 464 NavigationController* source_controller =
559 content::Source<NavigationController>(source).ptr(); 465 content::Source<NavigationController>(source).ptr();
560 TabUpdated(source_controller->GetWebContents(), true); 466 TabUpdated(source_controller->GetWebContents(), true);
561 } else if (type == content::NOTIFICATION_WEB_CONTENTS_DESTROYED) { 467 } else if (type == content::NOTIFICATION_WEB_CONTENTS_DESTROYED) {
562 // Tab was destroyed after being detached (without being re-attached). 468 // Tab was destroyed after being detached (without being re-attached).
563 WebContents* contents = content::Source<WebContents>(source).ptr(); 469 WebContents* contents = content::Source<WebContents>(source).ptr();
564 registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, 470 registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
565 content::Source<NavigationController>(&contents->GetController())); 471 content::Source<NavigationController>(&contents->GetController()));
566 registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, 472 registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
567 content::Source<WebContents>(contents)); 473 content::Source<WebContents>(contents));
568 } else if (type == chrome::NOTIFICATION_BROWSER_WINDOW_READY) {
569 Browser* browser = content::Source<Browser>(source).ptr();
570 OnBrowserWindowReady(browser);
571 #if defined(OS_MACOSX)
572 } else if (type == chrome::NOTIFICATION_NO_KEY_WINDOW) {
573 OnBrowserSetLastActive(NULL);
574 #endif
575 } else { 474 } else {
576 NOTREACHED(); 475 NOTREACHED();
577 } 476 }
578 } 477 }
579 478
580 void ExtensionBrowserEventRouter::TabChangedAt(TabContents* contents, 479 void ExtensionBrowserEventRouter::TabChangedAt(TabContents* contents,
581 int index, 480 int index,
582 TabChangeType change_type) { 481 TabChangeType change_type) {
583 TabUpdated(contents->web_contents(), false); 482 TabUpdated(contents->web_contents(), false);
584 } 483 }
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
703 } 602 }
704 603
705 if (event_name) { 604 if (event_name) {
706 DispatchEventWithTab(profile, 605 DispatchEventWithTab(profile,
707 extension_action.extension_id(), 606 extension_action.extension_id(),
708 event_name, 607 event_name,
709 tab_contents->web_contents(), 608 tab_contents->web_contents(),
710 true); 609 true);
711 } 610 }
712 } 611 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698