OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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_popup_api.h" | 5 #include "chrome/browser/extensions/extension_popup_api.h" |
6 | 6 |
7 #include "base/json/json_writer.h" | 7 #include "base/json/json_writer.h" |
8 #include "base/string_util.h" | 8 #include "base/string_util.h" |
9 #include "chrome/browser/extensions/extension_dom_ui.h" | 9 #include "chrome/browser/extensions/extension_dom_ui.h" |
10 #include "chrome/browser/extensions/extension_host.h" | 10 #include "chrome/browser/extensions/extension_host.h" |
11 #include "chrome/browser/extensions/extension_message_service.h" | 11 #include "chrome/browser/extensions/extension_message_service.h" |
12 #include "chrome/browser/browser.h" | 12 #include "chrome/browser/browser.h" |
13 #include "chrome/browser/browser_window.h" | 13 #include "chrome/browser/browser_window.h" |
14 #include "chrome/browser/profile.h" | 14 #include "chrome/browser/profile.h" |
| 15 #include "chrome/browser/renderer_host/render_view_host.h" |
| 16 #include "chrome/browser/renderer_host/render_view_host_delegate.h" |
| 17 #include "chrome/browser/renderer_host/render_widget_host_view.h" |
15 #include "chrome/browser/tab_contents/tab_contents.h" | 18 #include "chrome/browser/tab_contents/tab_contents.h" |
16 #include "chrome/common/extensions/extension.h" | 19 #include "chrome/common/extensions/extension.h" |
17 #include "chrome/common/notification_details.h" | 20 #include "chrome/common/notification_details.h" |
18 #include "chrome/common/notification_service.h" | 21 #include "chrome/common/notification_service.h" |
19 #include "chrome/common/notification_source.h" | 22 #include "chrome/common/notification_source.h" |
20 #include "chrome/common/notification_type.h" | 23 #include "chrome/common/notification_type.h" |
21 #include "chrome/common/url_constants.h" | 24 #include "chrome/common/url_constants.h" |
22 #include "gfx/point.h" | 25 #include "gfx/point.h" |
23 | 26 |
24 #if defined(TOOLKIT_VIEWS) | 27 #if defined(TOOLKIT_VIEWS) |
25 #include "chrome/browser/renderer_host/render_view_host.h" | |
26 #include "chrome/browser/renderer_host/render_view_host_delegate.h" | |
27 #include "chrome/browser/renderer_host/render_widget_host_view.h" | |
28 #include "chrome/browser/views/extensions/extension_popup.h" | 28 #include "chrome/browser/views/extensions/extension_popup.h" |
29 #include "views/view.h" | 29 #include "views/view.h" |
30 #include "views/focus/focus_manager.h" | 30 #include "views/focus/focus_manager.h" |
31 #endif // TOOLKIT_VIEWS | 31 #endif // TOOLKIT_VIEWS |
32 | 32 |
33 namespace extension_popup_module_events { | 33 namespace extension_popup_module_events { |
34 | 34 |
35 const char kOnPopupClosed[] = "experimental.popup.onClosed.%d"; | 35 const char kOnPopupClosed[] = "experimental.popup.onClosed.%d"; |
36 | 36 |
37 } // namespace extension_popup_module_events | 37 } // namespace extension_popup_module_events |
38 | 38 |
39 namespace { | 39 namespace { |
40 | 40 |
41 // Errors. | 41 // Errors. |
42 const char kBadAnchorArgument[] = "Invalid anchor argument."; | 42 const char kBadAnchorArgument[] = "Invalid anchor argument."; |
43 const char kInvalidURLError[] = "Invalid URL."; | 43 const char kInvalidURLError[] = "Invalid URL."; |
44 const char kNotAnExtension[] = "Not an extension view."; | 44 const char kNotAnExtension[] = "Not an extension view."; |
| 45 const char kPopupsDisallowed[] = |
| 46 "Popups are only supported from toolstrip or tab-contents views."; |
45 | 47 |
46 // Keys. | 48 // Keys. |
47 const wchar_t kUrlKey[] = L"url"; | 49 const wchar_t kUrlKey[] = L"url"; |
48 const wchar_t kWidthKey[] = L"width"; | 50 const wchar_t kWidthKey[] = L"width"; |
49 const wchar_t kHeightKey[] = L"height"; | 51 const wchar_t kHeightKey[] = L"height"; |
50 const wchar_t kTopKey[] = L"top"; | 52 const wchar_t kTopKey[] = L"top"; |
51 const wchar_t kLeftKey[] = L"left"; | 53 const wchar_t kLeftKey[] = L"left"; |
52 const wchar_t kGiveFocusKey[] = L"giveFocus"; | 54 const wchar_t kGiveFocusKey[] = L"giveFocus"; |
53 const wchar_t kDomAnchorKey[] = L"domAnchor"; | 55 const wchar_t kDomAnchorKey[] = L"domAnchor"; |
54 const wchar_t kBorderStyleKey[] = L"borderStyle"; | 56 const wchar_t kBorderStyleKey[] = L"borderStyle"; |
55 | 57 |
56 // chrome enumeration values | 58 // chrome enumeration values |
57 const char kRectangleChrome[] = "rectangle"; | 59 const char kRectangleChrome[] = "rectangle"; |
58 | 60 |
59 }; // namespace | 61 }; // namespace |
60 | 62 |
61 #if defined(TOOLKIT_VIEWS) | 63 #if defined(TOOLKIT_VIEWS) |
62 // ExtensionPopupHost objects implement the environment necessary to host | 64 // ExtensionPopupHost objects implement the environment necessary to host |
63 // an ExtensionPopup views for the popup api. Its main job is to handle | 65 // an ExtensionPopup views for the popup api. Its main job is to handle |
64 // its lifetime and to fire the popup-closed event when the popup is closed. | 66 // its lifetime and to fire the popup-closed event when the popup is closed. |
65 // Because the close-on-focus-lost behavior is different from page action | 67 // Because the close-on-focus-lost behavior is different from page action |
66 // and browser action, it also manages its own focus change listening. The | 68 // and browser action, it also manages its own focus change listening. The |
67 // difference in close-on-focus-lost is that in the page action and browser | 69 // difference in close-on-focus-lost is that in the page action and browser |
68 // action cases, the popup closes when the focus leaves the popup or any of its | 70 // action cases, the popup closes when the focus leaves the popup or any of its |
69 // children. In this case, the popup closes when the focus leaves the popups | 71 // children. In this case, the popup closes when the focus leaves the popups |
70 // containing view or any of *its* children. | 72 // containing view or any of *its* children. |
71 class ExtensionPopupHost : public ExtensionPopup::Observer, | 73 class ExtensionPopupHost : public ExtensionPopup::Observer, |
72 public views::WidgetFocusChangeListener, | 74 public views::WidgetFocusChangeListener, |
73 public base::RefCounted<ExtensionPopupHost> { | 75 public base::RefCounted<ExtensionPopupHost>, |
| 76 public NotificationObserver { |
74 public: | 77 public: |
75 explicit ExtensionPopupHost(ExtensionFunctionDispatcher* dispatcher) | 78 explicit ExtensionPopupHost(ExtensionFunctionDispatcher* dispatcher) |
76 : dispatcher_(dispatcher), popup_(NULL) { | 79 : dispatcher_(dispatcher), popup_(NULL) { |
77 AddRef(); // Balanced in DispatchPopupClosedEvent(). | 80 AddRef(); // Balanced in DispatchPopupClosedEvent(). |
78 views::FocusManager::GetWidgetFocusManager()->AddFocusChangeListener(this); | 81 views::FocusManager::GetWidgetFocusManager()->AddFocusChangeListener(this); |
79 } | 82 } |
80 | 83 |
81 ~ExtensionPopupHost() { | 84 ~ExtensionPopupHost() { |
82 views::FocusManager::GetWidgetFocusManager()-> | 85 views::FocusManager::GetWidgetFocusManager()-> |
83 RemoveFocusChangeListener(this); | 86 RemoveFocusChangeListener(this); |
84 } | 87 } |
85 | 88 |
86 void set_popup(ExtensionPopup* popup) { | 89 void set_popup(ExtensionPopup* popup) { |
87 popup_ = popup; | 90 popup_ = popup; |
| 91 |
| 92 // Now that a popup has been assigned, listen for subsequent popups being |
| 93 // created in the same extension - we want to disallow more than one |
| 94 // concurrently displayed popup windows. |
| 95 registrar_.Add( |
| 96 this, |
| 97 NotificationType::EXTENSION_HOST_CREATED, |
| 98 Source<ExtensionProcessManager>( |
| 99 dispatcher_->profile()->GetExtensionProcessManager())); |
88 } | 100 } |
89 | 101 |
90 // Overriden from ExtensionPopup::Observer | 102 // Overridden from ExtensionPopup::Observer |
91 virtual void ExtensionPopupClosed(ExtensionPopup* popup) { | 103 virtual void ExtensionPopupClosed(ExtensionPopup* popup) { |
92 // Unregister the automation resource routing registered upon host | 104 // Unregister the automation resource routing registered upon host |
93 // creation. | 105 // creation. |
94 AutomationResourceRoutingDelegate* router = | 106 AutomationResourceRoutingDelegate* router = |
95 GetRoutingFromDispatcher(dispatcher_); | 107 GetRoutingFromDispatcher(dispatcher_); |
96 if (router) | 108 if (router) |
97 router->UnregisterRenderViewHost(popup_->host()->render_view_host()); | 109 router->UnregisterRenderViewHost(popup_->host()->render_view_host()); |
98 | 110 |
99 // The OnPopupClosed event should be sent later to give the popup time to | 111 // The OnPopupClosed event should be sent later to give the popup time to |
100 // complete closing. | 112 // complete closing. |
(...skipping 11 matching lines...) Expand all Loading... |
112 router->RegisterRenderViewHost(host->render_view_host()); | 124 router->RegisterRenderViewHost(host->render_view_host()); |
113 } | 125 } |
114 | 126 |
115 virtual void DispatchPopupClosedEvent() { | 127 virtual void DispatchPopupClosedEvent() { |
116 PopupEventRouter::OnPopupClosed( | 128 PopupEventRouter::OnPopupClosed( |
117 dispatcher_->profile(), dispatcher_->render_view_host()->routing_id()); | 129 dispatcher_->profile(), dispatcher_->render_view_host()->routing_id()); |
118 dispatcher_ = NULL; | 130 dispatcher_ = NULL; |
119 Release(); // Balanced in ctor. | 131 Release(); // Balanced in ctor. |
120 } | 132 } |
121 | 133 |
122 // Overriden from views::WidgetFocusChangeListener | 134 // Overridden from views::WidgetFocusChangeListener |
123 virtual void NativeFocusWillChange(gfx::NativeView focused_before, | 135 virtual void NativeFocusWillChange(gfx::NativeView focused_before, |
124 gfx::NativeView focused_now) { | 136 gfx::NativeView focused_now) { |
| 137 // If the popup doesn't exist, then do nothing. |
| 138 if (!popup_) |
| 139 return; |
| 140 |
125 // If no view is to be focused, then Chrome was deactivated, so hide the | 141 // If no view is to be focused, then Chrome was deactivated, so hide the |
126 // popup. | 142 // popup. |
127 if (focused_now) { | 143 if (focused_now) { |
128 gfx::NativeView host_view = | 144 gfx::NativeView host_view = |
129 dispatcher_->delegate()->GetNativeViewOfHost(); | 145 dispatcher_->delegate()->GetNativeViewOfHost(); |
130 | 146 |
131 // If the widget hosting the popup contains the newly focused view, then | 147 // If the widget hosting the popup contains the newly focused view, then |
132 // don't dismiss the pop-up. | 148 // don't dismiss the pop-up. |
133 views::Widget* popup_root_widget = popup_->host()->view()->GetWidget(); | 149 ExtensionView* view = popup_->host()->view(); |
134 if (popup_root_widget && | 150 if (view) { |
135 popup_root_widget->ContainsNativeView(focused_now)) | 151 views::Widget* popup_root_widget = view->GetWidget(); |
136 return; | 152 if (popup_root_widget && |
| 153 popup_root_widget->ContainsNativeView(focused_now)) |
| 154 return; |
| 155 } |
137 | 156 |
138 // If the widget or RenderWidgetHostView hosting the extension that | 157 // If the widget or RenderWidgetHostView hosting the extension that |
139 // launched the pop-up is receiving focus, then don't dismiss the popup. | 158 // launched the pop-up is receiving focus, then don't dismiss the popup. |
140 views::Widget* host_widget = | 159 views::Widget* host_widget = |
141 views::Widget::GetWidgetFromNativeView(host_view); | 160 views::Widget::GetWidgetFromNativeView(host_view); |
142 if (host_widget && host_widget->ContainsNativeView(focused_now)) | 161 if (host_widget && host_widget->ContainsNativeView(focused_now)) |
143 return; | 162 return; |
144 | 163 |
145 RenderWidgetHostView* render_host_view = | 164 RenderWidgetHostView* render_host_view = |
146 RenderWidgetHostView::GetRenderWidgetHostViewFromNativeView( | 165 RenderWidgetHostView::GetRenderWidgetHostViewFromNativeView( |
147 host_view); | 166 host_view); |
148 if (render_host_view && | 167 if (render_host_view && |
149 render_host_view->ContainsNativeView(focused_now)) | 168 render_host_view->ContainsNativeView(focused_now)) |
150 return; | 169 return; |
151 } | 170 } |
152 | 171 |
153 // We are careful here to let the current event loop unwind before | 172 // We are careful here to let the current event loop unwind before |
154 // causing the popup to be closed. | 173 // causing the popup to be closed. |
155 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(popup_, | 174 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(popup_, |
156 &ExtensionPopup::Close)); | 175 &ExtensionPopup::Close)); |
157 } | 176 } |
158 | 177 |
| 178 // Overridden from NotificationObserver |
| 179 virtual void Observe(NotificationType type, |
| 180 const NotificationSource& source, |
| 181 const NotificationDetails& details) { |
| 182 DCHECK(NotificationType::EXTENSION_HOST_CREATED == type); |
| 183 if (NotificationType::EXTENSION_HOST_CREATED == type) { |
| 184 Details<ExtensionHost> details_host(details); |
| 185 // Disallow multiple pop-ups from the same extension, by closing |
| 186 // the presently opened popup during construction of any new popups. |
| 187 if (ViewType::EXTENSION_POPUP == details_host->GetRenderViewType() && |
| 188 popup_->host()->extension() == details_host->extension() && |
| 189 Details<ExtensionHost>(popup_->host()) != details) { |
| 190 popup_->Close(); |
| 191 } |
| 192 } |
| 193 } |
| 194 |
159 private: | 195 private: |
160 // Returns the AutomationResourceRoutingDelegate interface for |dispatcher|. | 196 // Returns the AutomationResourceRoutingDelegate interface for |dispatcher|. |
161 static AutomationResourceRoutingDelegate* | 197 static AutomationResourceRoutingDelegate* |
162 GetRoutingFromDispatcher(ExtensionFunctionDispatcher* dispatcher) { | 198 GetRoutingFromDispatcher(ExtensionFunctionDispatcher* dispatcher) { |
163 if (!dispatcher) | 199 if (!dispatcher) |
164 return NULL; | 200 return NULL; |
165 | 201 |
166 RenderViewHost* render_view_host = dispatcher->render_view_host(); | 202 RenderViewHost* render_view_host = dispatcher->render_view_host(); |
167 RenderViewHostDelegate* delegate = | 203 RenderViewHostDelegate* delegate = |
168 render_view_host ? render_view_host->delegate() : NULL; | 204 render_view_host ? render_view_host->delegate() : NULL; |
169 | 205 |
170 return delegate ? delegate->GetAutomationResourceRoutingDelegate() : NULL; | 206 return delegate ? delegate->GetAutomationResourceRoutingDelegate() : NULL; |
171 } | 207 } |
172 | 208 |
173 // A pointer to the dispatcher that handled the request that opened this | 209 // A pointer to the dispatcher that handled the request that opened this |
174 // popup view. | 210 // popup view. |
175 ExtensionFunctionDispatcher* dispatcher_; | 211 ExtensionFunctionDispatcher* dispatcher_; |
176 | 212 |
177 // A pointer to the popup. | 213 // A pointer to the popup. |
178 ExtensionPopup* popup_; | 214 ExtensionPopup* popup_; |
179 | 215 |
| 216 NotificationRegistrar registrar_; |
| 217 |
180 DISALLOW_COPY_AND_ASSIGN(ExtensionPopupHost); | 218 DISALLOW_COPY_AND_ASSIGN(ExtensionPopupHost); |
181 }; | 219 }; |
182 #endif // TOOLKIT_VIEWS | 220 #endif // TOOLKIT_VIEWS |
183 | 221 |
184 PopupShowFunction::PopupShowFunction() | 222 PopupShowFunction::PopupShowFunction() |
185 #if defined (TOOLKIT_VIEWS) | 223 #if defined (TOOLKIT_VIEWS) |
186 : popup_(NULL) | 224 : popup_(NULL) |
187 #endif | 225 #endif |
188 {} | 226 {} |
189 | 227 |
(...skipping 14 matching lines...) Expand all Loading... |
204 registrar_.Add(this, NotificationType::EXTENSION_HOST_DESTROYED, | 242 registrar_.Add(this, NotificationType::EXTENSION_HOST_DESTROYED, |
205 NotificationService::AllSources()); | 243 NotificationService::AllSources()); |
206 } | 244 } |
207 } | 245 } |
208 #else | 246 #else |
209 SendResponse(false); | 247 SendResponse(false); |
210 #endif | 248 #endif |
211 } | 249 } |
212 | 250 |
213 bool PopupShowFunction::RunImpl() { | 251 bool PopupShowFunction::RunImpl() { |
| 252 // Popups may only be displayed from TAB_CONTENTS and EXTENSION_TOOLSTRIP |
| 253 // views. |
| 254 ViewType::Type view_type = |
| 255 dispatcher()->render_view_host()->delegate()->GetRenderViewType(); |
| 256 if (ViewType::EXTENSION_TOOLSTRIP != view_type && |
| 257 ViewType::TAB_CONTENTS != view_type) { |
| 258 error_ = kPopupsDisallowed; |
| 259 return false; |
| 260 } |
| 261 |
214 EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_LIST)); | 262 EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_LIST)); |
215 const ListValue* args = args_as_list(); | 263 const ListValue* args = args_as_list(); |
216 | 264 |
217 std::string url_string; | 265 std::string url_string; |
218 EXTENSION_FUNCTION_VALIDATE(args->GetString(0, &url_string)); | 266 EXTENSION_FUNCTION_VALIDATE(args->GetString(0, &url_string)); |
219 | 267 |
220 DictionaryValue* show_details = NULL; | 268 DictionaryValue* show_details = NULL; |
221 EXTENSION_FUNCTION_VALIDATE(args->GetDictionary(1, &show_details)); | 269 EXTENSION_FUNCTION_VALIDATE(args->GetDictionary(1, &show_details)); |
222 | 270 |
223 DictionaryValue* dom_anchor = NULL; | 271 DictionaryValue* dom_anchor = NULL; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
265 | 313 |
266 // Disallow non-extension requests, or requests outside of the requesting | 314 // Disallow non-extension requests, or requests outside of the requesting |
267 // extension view's extension. | 315 // extension view's extension. |
268 const std::string& extension_id = url.host(); | 316 const std::string& extension_id = url.host(); |
269 if (extension_id != GetExtension()->id() || | 317 if (extension_id != GetExtension()->id() || |
270 !url.SchemeIs(chrome::kExtensionScheme)) { | 318 !url.SchemeIs(chrome::kExtensionScheme)) { |
271 error_ = kInvalidURLError; | 319 error_ = kInvalidURLError; |
272 return false; | 320 return false; |
273 } | 321 } |
274 | 322 |
275 #if defined(TOOLKIT_VIEWS) | |
276 gfx::Point origin(dom_left, dom_top); | 323 gfx::Point origin(dom_left, dom_top); |
277 if (!dispatcher()->render_view_host()->view()) { | 324 if (!dispatcher()->render_view_host()->view()) { |
278 error_ = kNotAnExtension; | 325 error_ = kNotAnExtension; |
279 return false; | 326 return false; |
280 } | 327 } |
281 | 328 |
282 gfx::Rect content_bounds = | 329 gfx::Rect content_bounds = |
283 dispatcher()->render_view_host()->view()->GetViewBounds(); | 330 dispatcher()->render_view_host()->view()->GetViewBounds(); |
284 origin.Offset(content_bounds.x(), content_bounds.y()); | 331 origin.Offset(content_bounds.x(), content_bounds.y()); |
285 gfx::Rect rect(origin.x(), origin.y(), dom_width, dom_height); | 332 gfx::Rect rect(origin.x(), origin.y(), dom_width, dom_height); |
286 | 333 |
287 // Pop-up from extension views (ExtensionShelf, etc.), and drop-down when | |
288 // in a TabContents view. | |
289 ViewType::Type view_type = | |
290 dispatcher()->render_view_host()->delegate()->GetRenderViewType(); | |
291 BubbleBorder::ArrowLocation arrow_location = | |
292 view_type == ViewType::TAB_CONTENTS ? | |
293 BubbleBorder::TOP_LEFT : BubbleBorder::BOTTOM_LEFT; | |
294 | |
295 // Get the correct native window to pass to ExtensionPopup. | 334 // Get the correct native window to pass to ExtensionPopup. |
296 // ExtensionFunctionDispatcher::Delegate may provide a custom implementation | 335 // ExtensionFunctionDispatcher::Delegate may provide a custom implementation |
297 // of this. | 336 // of this. |
298 gfx::NativeWindow window = | 337 gfx::NativeWindow window = |
299 dispatcher()->delegate()->GetCustomFrameNativeWindow(); | 338 dispatcher()->delegate()->GetCustomFrameNativeWindow(); |
300 if (!window) | 339 if (!window) |
301 window = GetCurrentBrowser()->window()->GetNativeHandle(); | 340 window = GetCurrentBrowser()->window()->GetNativeHandle(); |
302 | 341 |
| 342 #if defined(TOOLKIT_VIEWS) |
| 343 // Pop-up from extension views (ExtensionShelf, etc.), and drop-down when |
| 344 // in a TabContents view. |
| 345 BubbleBorder::ArrowLocation arrow_location = |
| 346 view_type == ViewType::TAB_CONTENTS ? |
| 347 BubbleBorder::TOP_LEFT : BubbleBorder::BOTTOM_LEFT; |
| 348 |
303 // ExtensionPopupHost manages it's own lifetime. | 349 // ExtensionPopupHost manages it's own lifetime. |
304 ExtensionPopupHost* popup_host = new ExtensionPopupHost(dispatcher()); | 350 ExtensionPopupHost* popup_host = new ExtensionPopupHost(dispatcher()); |
305 popup_ = ExtensionPopup::Show(url, | 351 popup_ = ExtensionPopup::Show(url, |
306 GetCurrentBrowser(), | 352 GetCurrentBrowser(), |
307 dispatcher()->profile(), | 353 dispatcher()->profile(), |
308 window, | 354 window, |
309 rect, | 355 rect, |
310 arrow_location, | 356 arrow_location, |
311 give_focus, | 357 give_focus, |
312 false, // inspect_with_devtools | 358 false, // inspect_with_devtools |
313 chrome, | 359 chrome, |
314 popup_host); // ExtensionPopup::Observer | 360 popup_host); // ExtensionPopup::Observer |
315 | 361 |
316 // popup_host will handle focus change listening and close the popup when | 362 // popup_host will handle focus change listening and close the popup when |
317 // focus leaves the containing views hierarchy. | 363 // focus leaves the containing views hierarchy. |
318 popup_->set_close_on_lost_focus(false); | 364 popup_->set_close_on_lost_focus(false); |
319 popup_host->set_popup(popup_); | 365 popup_host->set_popup(popup_); |
320 #endif // defined(TOOLKIT_VIEWS) | 366 #endif // defined(TOOLKIT_VIEWS) |
321 return true; | 367 return true; |
322 } | 368 } |
323 | 369 |
324 void PopupShowFunction::Observe(NotificationType type, | 370 void PopupShowFunction::Observe(NotificationType type, |
325 const NotificationSource& source, | 371 const NotificationSource& source, |
326 const NotificationDetails& details) { | 372 const NotificationDetails& details) { |
327 #if defined(TOOLKIT_VIEWS) | 373 #if defined(TOOLKIT_VIEWS) |
328 DCHECK(type == NotificationType::EXTENSION_POPUP_VIEW_READY || | 374 DCHECK(type == NotificationType::EXTENSION_POPUP_VIEW_READY || |
329 type == NotificationType::EXTENSION_HOST_DESTROYED); | 375 type == NotificationType::EXTENSION_HOST_DESTROYED); |
330 DCHECK(popup_ != NULL); | 376 DCHECK(popup_ != NULL); |
331 | 377 |
| 378 // Wait for notification that the popup view is ready (and onload has been |
| 379 // called), before completing the API call. |
332 if (popup_ && type == NotificationType::EXTENSION_POPUP_VIEW_READY && | 380 if (popup_ && type == NotificationType::EXTENSION_POPUP_VIEW_READY && |
333 Details<ExtensionHost>(popup_->host()) == details) { | 381 Details<ExtensionHost>(popup_->host()) == details) { |
334 SendResponse(true); | 382 SendResponse(true); |
335 Release(); // Balanced in Run(). | 383 Release(); // Balanced in Run(). |
336 } else if (popup_ && type == NotificationType::EXTENSION_HOST_DESTROYED && | 384 } else if (popup_ && type == NotificationType::EXTENSION_HOST_DESTROYED && |
337 Details<ExtensionHost>(popup_->host()) == details) { | 385 Details<ExtensionHost>(popup_->host()) == details) { |
338 // If the host was destroyed, then report failure, and release the remaining | 386 // If the host was destroyed, then report failure, and release the remaining |
339 // reference. | 387 // reference. |
340 SendResponse(false); | 388 SendResponse(false); |
341 Release(); // Balanced in Run(). | 389 Release(); // Balanced in Run(). |
342 } | 390 } |
343 #endif // defined(TOOLKIT_VIEWS) | 391 #endif // defined(TOOLKIT_VIEWS) |
344 } | 392 } |
345 | 393 |
346 // static | 394 // static |
347 void PopupEventRouter::OnPopupClosed(Profile* profile, | 395 void PopupEventRouter::OnPopupClosed(Profile* profile, |
348 int routing_id) { | 396 int routing_id) { |
349 std::string full_event_name = StringPrintf( | 397 std::string full_event_name = StringPrintf( |
350 extension_popup_module_events::kOnPopupClosed, | 398 extension_popup_module_events::kOnPopupClosed, |
351 routing_id); | 399 routing_id); |
352 | 400 |
353 profile->GetExtensionMessageService()->DispatchEventToRenderers( | 401 profile->GetExtensionMessageService()->DispatchEventToRenderers( |
354 full_event_name, | 402 full_event_name, |
355 base::JSONWriter::kEmptyArray, | 403 base::JSONWriter::kEmptyArray, |
356 profile->IsOffTheRecord(), | 404 profile->IsOffTheRecord(), |
357 GURL()); | 405 GURL()); |
358 } | 406 } |
OLD | NEW |