| 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 |