diff options
author | twiz@google.com <twiz@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-12-10 01:59:11 +0000 |
---|---|---|
committer | twiz@google.com <twiz@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-12-10 01:59:11 +0000 |
commit | a95631cb9427e4d20c243dcd0f36da3fd3e7cb55 (patch) | |
tree | 09da2c4493a7303671961051b32718830c451ad7 /chrome/browser | |
parent | 2007ad49132097b2a2eb10d0025361d1bf7a9340 (diff) | |
download | chromium_src-a95631cb9427e4d20c243dcd0f36da3fd3e7cb55.zip chromium_src-a95631cb9427e4d20c243dcd0f36da3fd3e7cb55.tar.gz chromium_src-a95631cb9427e4d20c243dcd0f36da3fd3e7cb55.tar.bz2 |
A collection of fixes allowing the chrome.experimental.popup.* set of APIs to function in circumstances where there is no Browser instance present. This is a symptom of a tab-contents view hosted in an ExternalTabContainer.The major change here is the removal of the explicit dependency on a Browser instance across all of the delegates involved when showing a pop-up API. I modified the following delegates:- ExtensionPopupHost::Delegate- TabContentsDelegate- ExtensionFunctionDispatcher::DelegateBecause the pop-up requires a Profile, and a gfx::NativeWindow, I added methods to the above interfaces to provide them.BUG=noneTEST=ExtensionApiTest.FLAKY_Popup
Review URL: http://codereview.chromium.org/434046
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@34219 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
21 files changed, 215 insertions, 40 deletions
diff --git a/chrome/browser/browser.h b/chrome/browser/browser.h index fd7c63d..5192bf0 100644 --- a/chrome/browser/browser.h +++ b/chrome/browser/browser.h @@ -575,6 +575,7 @@ class Browser : public TabStripModelDelegate, virtual bool ShouldAddNavigationsToHistory() const; virtual void OnDidGetApplicationInfo(TabContents* tab_contents, int32 page_id); + virtual Browser* GetBrowser() { return this; } // Overridden from SelectFileDialog::Listener: virtual void FileSelected(const FilePath& path, int index, void* params); diff --git a/chrome/browser/dom_ui/dom_ui.h b/chrome/browser/dom_ui/dom_ui.h index ad4c2dc..2156b30 100644 --- a/chrome/browser/dom_ui/dom_ui.h +++ b/chrome/browser/dom_ui/dom_ui.h @@ -111,7 +111,7 @@ class DOMUI { ThemeProvider* GetThemeProvider() const; - TabContents* tab_contents() { return tab_contents_; } + TabContents* tab_contents() const { return tab_contents_; } Profile* GetProfile(); diff --git a/chrome/browser/extensions/extension_dom_ui.cc b/chrome/browser/extensions/extension_dom_ui.cc index fb95005..e9f1996 100644 --- a/chrome/browser/extensions/extension_dom_ui.cc +++ b/chrome/browser/extensions/extension_dom_ui.cc @@ -63,8 +63,31 @@ void ExtensionDOMUI::ProcessDOMUIMessage(const std::string& message, has_callback); } -Browser* ExtensionDOMUI::GetBrowser() { - return static_cast<Browser*>(tab_contents()->delegate()); +Browser* ExtensionDOMUI::GetBrowser() const { + TabContentsDelegate* tab_contents_delegate = tab_contents()->delegate(); + if (tab_contents_delegate) + return tab_contents_delegate->GetBrowser(); + return NULL; +} + +Profile* ExtensionDOMUI::GetProfile() { + return DOMUI::GetProfile(); +} + +gfx::NativeWindow ExtensionDOMUI::GetFrameNativeWindow() { + gfx::NativeWindow native_window = + ExtensionFunctionDispatcher::Delegate::GetFrameNativeWindow(); + + // If there was no window associated with the function dispatcher delegate, + // then this DOMUI may be hosted in an ExternalTabContainer, and a framing + // window will be accessible through the tab_contents. + if (!native_window) { + TabContentsDelegate* tab_contents_delegate = tab_contents()->delegate(); + if (tab_contents_delegate) + native_window = tab_contents_delegate->GetFrameNativeWindow(); + } + + return native_window; } //////////////////////////////////////////////////////////////////////////////// diff --git a/chrome/browser/extensions/extension_dom_ui.h b/chrome/browser/extensions/extension_dom_ui.h index 0a53607..bd7a0ac 100644 --- a/chrome/browser/extensions/extension_dom_ui.h +++ b/chrome/browser/extensions/extension_dom_ui.h @@ -40,11 +40,13 @@ class ExtensionDOMUI bool has_callback); // ExtensionFunctionDispatcher::Delegate - virtual Browser* GetBrowser(); + virtual Browser* GetBrowser() const; virtual ExtensionDOMUI* GetExtensionDOMUI() { return this; } + virtual gfx::NativeWindow GetFrameNativeWindow(); // ExtensionPopupHost::Delegate virtual RenderViewHost* GetRenderViewHost(); + virtual Profile* GetProfile(); // BrowserURLHandler static bool HandleChromeURLOverride(GURL* url, Profile* profile); diff --git a/chrome/browser/extensions/extension_function_dispatcher.cc b/chrome/browser/extensions/extension_function_dispatcher.cc index 071c6f1..c1cb333 100644 --- a/chrome/browser/extensions/extension_function_dispatcher.cc +++ b/chrome/browser/extensions/extension_function_dispatcher.cc @@ -7,6 +7,8 @@ #include "base/process_util.h" #include "base/singleton.h" #include "base/values.h" +#include "chrome/browser/browser.h" +#include "chrome/browser/browser_window.h" #include "chrome/browser/extensions/execute_code_in_tab_function.h" #include "chrome/browser/extensions/extension_bookmarks_module.h" #include "chrome/browser/extensions/extension_bookmarks_module_constants.h" @@ -181,6 +183,20 @@ ExtensionFunction* FactoryRegistry::NewFunction(const std::string& name) { }; // namespace +// ExtensionFunctionDispatcher::Delegate --------------------------------------- + +gfx::NativeWindow ExtensionFunctionDispatcher::Delegate:: + GetFrameNativeWindow() { + Browser* browser = GetBrowser(); + // If a browser is bound to this dispatcher, then return the widget hosting + // the window. Extensions hosted in ExternalTabContainer objects may not + // have a running browser instance. + if (browser) + return browser->window()->GetNativeHandle(); + + return NULL; +} + // ExtensionFunctionDispatcher ------------------------------------------------- void ExtensionFunctionDispatcher::GetAllFunctionNames( @@ -318,3 +334,7 @@ void ExtensionFunctionDispatcher::HandleBadMessage(ExtensionFunction* api) { Profile* ExtensionFunctionDispatcher::profile() { return render_view_host_->process()->profile(); } + +gfx::NativeWindow ExtensionFunctionDispatcher::GetFrameNativeWindow() { + return delegate_ ? delegate_->GetFrameNativeWindow() : NULL; +} diff --git a/chrome/browser/extensions/extension_function_dispatcher.h b/chrome/browser/extensions/extension_function_dispatcher.h index df50ceb..b35c069 100644 --- a/chrome/browser/extensions/extension_function_dispatcher.h +++ b/chrome/browser/extensions/extension_function_dispatcher.h @@ -9,6 +9,7 @@ #include <set> #include <vector> +#include "app/gfx/native_widget_types.h" #include "base/ref_counted.h" #include "googleurl/src/gurl.h" @@ -33,7 +34,12 @@ class ExtensionFunctionDispatcher { public: class Delegate { public: - virtual Browser* GetBrowser() = 0; + virtual Browser* GetBrowser() const = 0; + + // Returns the gfx::NativeWindow that contains the view hosting the + // environment in which the function dispatcher resides. + virtual gfx::NativeWindow GetFrameNativeWindow(); + virtual ExtensionHost* GetExtensionHost() { return NULL; } virtual ExtensionDOMUI* GetExtensionDOMUI() { return NULL; } }; @@ -94,6 +100,12 @@ class ExtensionFunctionDispatcher { // non-tab-hosted extension pages, this will return NULL. ExtensionDOMUI* GetExtensionDOMUI(); + // Returns the gfx::NativeWindow that frames the view of the extension + // containing the function dispatcher. This may return NULL. Refer to the + // ExtensionFunctionDispatcher::Delegate::GetFrameNativeWindow() + // implementation for an explanation. + gfx::NativeWindow GetFrameNativeWindow(); + // Gets the extension the function is being invoked by. This should not ever // return NULL. Extension* GetExtension(); diff --git a/chrome/browser/extensions/extension_host.cc b/chrome/browser/extensions/extension_host.cc index 0ad3a9e..77bee6c 100644 --- a/chrome/browser/extensions/extension_host.cc +++ b/chrome/browser/extensions/extension_host.cc @@ -549,7 +549,7 @@ void ExtensionHost::HandleMouseLeave() { #endif } -Browser* ExtensionHost::GetBrowser() { +Browser* ExtensionHost::GetBrowser() const { if (view_.get()) return view_->browser(); @@ -604,16 +604,19 @@ void ExtensionHost::RenderViewCreated(RenderViewHost* render_view_host) { } int ExtensionHost::GetBrowserWindowID() const { + // Hosts not attached to any browser window have an id of -1. This includes + // those mentioned below, and background pages. int window_id = -1; if (extension_host_type_ == ViewType::EXTENSION_TOOLSTRIP || extension_host_type_ == ViewType::EXTENSION_MOLE || extension_host_type_ == ViewType::EXTENSION_POPUP) { - window_id = ExtensionTabUtil::GetWindowId( - const_cast<ExtensionHost* >(this)->GetBrowser()); - } else if (extension_host_type_ == ViewType::EXTENSION_BACKGROUND_PAGE) { - // Background page is not attached to any browser window, so pass -1. - window_id = -1; - } else { + // If the host is bound to a browser, then extract its window id. + // Extensions hosted in ExternalTabContainer objects may not have + // an associated browser. + Browser* browser = GetBrowser(); + if (browser) + window_id = ExtensionTabUtil::GetWindowId(browser); + } else if (extension_host_type_ != ViewType::EXTENSION_BACKGROUND_PAGE) { NOTREACHED(); } return window_id; diff --git a/chrome/browser/extensions/extension_host.h b/chrome/browser/extensions/extension_host.h index 76f20d2..5a27030 100644 --- a/chrome/browser/extensions/extension_host.h +++ b/chrome/browser/extensions/extension_host.h @@ -65,7 +65,10 @@ class ExtensionHost : public ExtensionPopupHost::PopupDelegate, void* view() const { return NULL; } #endif - // Create an ExtensionView and tie it to this host and |browser|. + // Create an ExtensionView and tie it to this host and |browser|. Note NULL + // is a valid argument for |browser|. Extension views may be bound to + // tab-contents hosted in ExternalTabContainer objects, which do not + // instantiate Browser objects. void CreateView(Browser* browser); Extension* extension() { return extension_; } @@ -187,7 +190,7 @@ class ExtensionHost : public ExtensionPopupHost::PopupDelegate, // If this ExtensionHost has a view, this returns the Browser that view is a // part of. If this is a global background page, we use the active Browser // instead. - virtual Browser* GetBrowser(); + virtual Browser* GetBrowser() const; virtual ExtensionHost* GetExtensionHost() { return this; } // ExtensionPopupHost::Delegate diff --git a/chrome/browser/extensions/extension_popup_api.cc b/chrome/browser/extensions/extension_popup_api.cc index 091fa71..f68553c 100644 --- a/chrome/browser/extensions/extension_popup_api.cc +++ b/chrome/browser/extensions/extension_popup_api.cc @@ -139,8 +139,12 @@ bool PopupShowFunction::RunImpl() { BubbleBorder::ArrowLocation arrow_location = (NULL != dispatcher()->GetExtensionHost()) ? BubbleBorder::BOTTOM_LEFT : BubbleBorder::TOP_LEFT; - popup_ = ExtensionPopup::Show(url, dispatcher()->GetBrowser(), rect, - arrow_location, give_focus); + popup_ = ExtensionPopup::Show(url, dispatcher()->GetBrowser(), + dispatcher()->profile(), + dispatcher()->GetFrameNativeWindow(), + rect, + arrow_location, + give_focus); ExtensionPopupHost* popup_host = dispatcher()->GetPopupHost(); DCHECK(popup_host); diff --git a/chrome/browser/extensions/extension_popup_apitest.cc b/chrome/browser/extensions/extension_popup_apitest.cc index 16c5374..6095d5d 100644 --- a/chrome/browser/extensions/extension_popup_apitest.cc +++ b/chrome/browser/extensions/extension_popup_apitest.cc @@ -12,5 +12,6 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest, FLAKY_Popup) { switches::kEnableExperimentalExtensionApis); CommandLine::ForCurrentProcess()->AppendSwitch( switches::kEnableExtensionToolstrips); + ASSERT_TRUE(RunExtensionTest("popup_api")) << message_; } diff --git a/chrome/browser/extensions/extension_popup_host.cc b/chrome/browser/extensions/extension_popup_host.cc index f263494..1a964da 100644 --- a/chrome/browser/extensions/extension_popup_host.cc +++ b/chrome/browser/extensions/extension_popup_host.cc @@ -18,6 +18,13 @@ #include "chrome/common/notification_type.h" +ExtensionPopupHost::PopupDelegate::~PopupDelegate() { + // If the PopupDelegate is being torn down, then make sure to reset the + // cached pointer in the host to prevent access to a stale pointer. + if (popup_host_.get()) + popup_host_->RevokeDelegate(); +} + ExtensionPopupHost* ExtensionPopupHost::PopupDelegate::popup_host() { if (!popup_host_.get()) popup_host_.reset(new ExtensionPopupHost(this)); @@ -25,6 +32,18 @@ ExtensionPopupHost* ExtensionPopupHost::PopupDelegate::popup_host() { return popup_host_.get(); } +Profile* ExtensionPopupHost::PopupDelegate::GetProfile() { + // If there is a browser present, return the profile associated with it. + // When hosting a view in an ExternalTabContainer, it is possible to have + // no Browser instance. + Browser* browser = GetBrowser(); + if (browser) { + return browser->profile(); + } + + return NULL; +} + ExtensionPopupHost::ExtensionPopupHost(PopupDelegate* delegate) : // NO LINT #if defined(TOOLKIT_VIEWS) @@ -35,8 +54,10 @@ ExtensionPopupHost::ExtensionPopupHost(PopupDelegate* delegate) // Listen for view close requests, so that we can dismiss a hosted pop-up // view, if necessary. + Profile* profile = delegate_->GetProfile(); + DCHECK(profile); registrar_.Add(this, NotificationType::EXTENSION_HOST_VIEW_SHOULD_CLOSE, - Source<Profile>(delegate_->GetBrowser()->profile())); + Source<Profile>(profile)); } ExtensionPopupHost::~ExtensionPopupHost() { @@ -88,9 +109,11 @@ void ExtensionPopupHost::DismissPopup() { delete child_popup_; child_popup_ = NULL; - PopupEventRouter::OnPopupClosed( - delegate_->GetBrowser()->profile(), - delegate_->GetRenderViewHost()->routing_id()); + if (delegate_) { + PopupEventRouter::OnPopupClosed( + delegate_->GetProfile(), + delegate_->GetRenderViewHost()->routing_id()); + } } #endif // defined(TOOLKIT_VIEWS) } diff --git a/chrome/browser/extensions/extension_popup_host.h b/chrome/browser/extensions/extension_popup_host.h index f8e97a0..102c4ad 100644 --- a/chrome/browser/extensions/extension_popup_host.h +++ b/chrome/browser/extensions/extension_popup_host.h @@ -36,12 +36,14 @@ class ExtensionPopupHost : // NOLINT class PopupDelegate { public: PopupDelegate() {} - virtual ~PopupDelegate() {} - virtual Browser* GetBrowser() = 0; + virtual ~PopupDelegate(); + virtual Browser* GetBrowser() const = 0; virtual RenderViewHost* GetRenderViewHost() = 0; + virtual Profile* GetProfile(); // Constructs, or returns the existing ExtensionPopupHost instance. ExtensionPopupHost* popup_host(); + private: scoped_ptr<ExtensionPopupHost> popup_host_; @@ -51,6 +53,8 @@ class ExtensionPopupHost : // NOLINT explicit ExtensionPopupHost(PopupDelegate* delegate); virtual ~ExtensionPopupHost(); + void RevokeDelegate() { delegate_ = NULL; } + // Dismiss the hosted pop-up, if one is present. void DismissPopup(); diff --git a/chrome/browser/extensions/extension_process_manager.cc b/chrome/browser/extensions/extension_process_manager.cc index 7d6ca0b..78cd214 100644 --- a/chrome/browser/extensions/extension_process_manager.cc +++ b/chrome/browser/extensions/extension_process_manager.cc @@ -52,6 +52,7 @@ ExtensionProcessManager::ExtensionProcessManager(Profile* profile) } ExtensionProcessManager::~ExtensionProcessManager() { + CloseBackgroundHosts(); DCHECK(background_hosts_.empty()); } @@ -60,7 +61,8 @@ ExtensionHost* ExtensionProcessManager::CreateView(Extension* extension, Browser* browser, ViewType::Type view_type) { DCHECK(extension); - DCHECK(browser); + // A NULL browser may only be given for pop-up views. + DCHECK(browser || (!browser && view_type == ViewType::EXTENSION_POPUP)); ExtensionHost* host = #if defined(OS_MACOSX) new ExtensionHostMac(extension, GetSiteInstanceForURL(url), url, @@ -76,7 +78,8 @@ ExtensionHost* ExtensionProcessManager::CreateView(Extension* extension, ExtensionHost* ExtensionProcessManager::CreateView(const GURL& url, Browser* browser, ViewType::Type view_type) { - DCHECK(browser); + // A NULL browser may only be given for pop-up views. + DCHECK(browser || (!browser && view_type == ViewType::EXTENSION_POPUP)); ExtensionsService* service = browsing_instance_->profile()->GetExtensionsService(); if (service) { diff --git a/chrome/browser/external_tab_container.cc b/chrome/browser/external_tab_container.cc index 141a76b..d43df00 100644 --- a/chrome/browser/external_tab_container.cc +++ b/chrome/browser/external_tab_container.cc @@ -385,6 +385,10 @@ void ExternalTabContainer::ForwardMessageToExternalHost( } } +gfx::NativeWindow ExternalTabContainer::GetFrameNativeWindow() { + return hwnd(); +} + bool ExternalTabContainer::TakeFocus(bool reverse) { if (automation_) { automation_->Send(new AutomationMsg_TabbedOut(0, tab_handle_, @@ -677,6 +681,11 @@ void ExternalTabContainer::SetEnableExtensionAutomation( } } +// ExternalTabContainer instances do not have a window. +views::Window* ExternalTabContainer::GetWindow() { + return NULL; +} + void ExternalTabContainer::Navigate(const GURL& url, const GURL& referrer) { if (!tab_contents_) { NOTREACHED(); diff --git a/chrome/browser/external_tab_container.h b/chrome/browser/external_tab_container.h index 4461f7e..0d47d96 100644 --- a/chrome/browser/external_tab_container.h +++ b/chrome/browser/external_tab_container.h @@ -115,6 +115,7 @@ class ExternalTabContainer : public TabContentsDelegate, virtual bool IsExternalTabContainer() const { return true; }; + virtual gfx::NativeWindow GetFrameNativeWindow(); virtual bool HandleKeyboardEvent(const NativeWebKeyboardEvent& event); @@ -129,6 +130,8 @@ class ExternalTabContainer : public TabContentsDelegate, const NavigationEntry::SSLStatus& ssl, bool show_history); + virtual Browser* GetBrowser() { return browser_.get(); } + // Overridden from NotificationObserver: virtual void Observe(NotificationType type, const NotificationSource& source, @@ -160,6 +163,9 @@ class ExternalTabContainer : public TabContentsDelegate, void SetEnableExtensionAutomation( const std::vector<std::string>& functions_enabled); + // Overridden from views::WidgetWin: + virtual views::Window* GetWindow(); + protected: // Overridden from views::WidgetWin: virtual LRESULT OnCreate(LPCREATESTRUCT create_struct); diff --git a/chrome/browser/tab_contents/tab_contents_delegate.h b/chrome/browser/tab_contents/tab_contents_delegate.h index 633910c..8e1379d 100644 --- a/chrome/browser/tab_contents/tab_contents_delegate.h +++ b/chrome/browser/tab_contents/tab_contents_delegate.h @@ -16,6 +16,7 @@ #include "webkit/glue/context_menu.h" #include "webkit/glue/window_open_disposition.h" +class Browser; class DownloadItem; class ExtensionFunctionDispatcher; class GURL; @@ -251,6 +252,12 @@ class TabContentsDelegate { int32 page_id) { } + // Returns the browser in which the tab contents is being displayed. + virtual Browser* GetBrowser() { return NULL; } + + // Returns the widget framing the view containing the tab contents. + virtual gfx::NativeWindow GetFrameNativeWindow() { return NULL; } + protected: ~TabContentsDelegate() {} }; diff --git a/chrome/browser/views/browser_actions_container.cc b/chrome/browser/views/browser_actions_container.cc index 999f3d3..6cc71e4 100644 --- a/chrome/browser/views/browser_actions_container.cc +++ b/chrome/browser/views/browser_actions_container.cc @@ -8,6 +8,8 @@ #include "app/resource_bundle.h" #include "base/stl_util-inl.h" #include "base/string_util.h" +#include "chrome/browser/browser.h" +#include "chrome/browser/browser_window.h" #include "chrome/browser/extensions/extension_browser_event_router.h" #include "chrome/browser/extensions/extensions_service.h" #include "chrome/browser/extensions/extension_tabs_module.h" @@ -376,8 +378,13 @@ void BrowserActionsContainer::OnBrowserActionExecuted( gfx::Rect rect = button->bounds(); rect.set_x(origin.x()); rect.set_y(origin.y()); + + gfx::NativeWindow frame_window = + toolbar_->browser()->window()->GetNativeHandle(); popup_ = ExtensionPopup::Show(browser_action->popup_url(), toolbar_->browser(), + toolbar_->browser()->profile(), + frame_window, rect, BubbleBorder::TOP_RIGHT, true); // Activate the popup window. diff --git a/chrome/browser/views/browser_bubble.cc b/chrome/browser/views/browser_bubble.cc index 087b3b5..6712082 100644 --- a/chrome/browser/views/browser_bubble.cc +++ b/chrome/browser/views/browser_bubble.cc @@ -9,6 +9,21 @@ #include "views/widget/root_view.h" #include "views/window/window.h" +namespace { + +BrowserView* GetBrowserViewFromFrame(views::Widget* frame) { + BrowserView* browser_view = NULL; + views::Window* window = frame->GetWindow(); + if (window) { + browser_view = BrowserView::GetBrowserViewForNativeWindow( + window->GetNativeWindow()); + DCHECK(browser_view); + } + return browser_view; +} + +} // namespace + BrowserBubble::BrowserBubble(views::View* view, views::Widget* frame, const gfx::Point& origin) : frame_(frame), @@ -39,8 +54,8 @@ void BrowserBubble::DetachFromBrowser() { if (!attached_) return; attached_ = false; - BrowserView* browser_view = BrowserView::GetBrowserViewForNativeWindow( - frame_->GetWindow()->GetNativeWindow()); + + BrowserView* browser_view = GetBrowserViewFromFrame(frame_); if (browser_view) browser_view->DetachBrowserBubble(this); } @@ -49,13 +64,12 @@ void BrowserBubble::AttachToBrowser() { DCHECK(!attached_); if (attached_) return; - BrowserView* browser_view = BrowserView::GetBrowserViewForNativeWindow( - frame_->GetWindow()->GetNativeWindow()); - DCHECK(browser_view); - if (browser_view) { + + BrowserView* browser_view = GetBrowserViewFromFrame(frame_); + if (browser_view) browser_view->AttachBrowserBubble(this); - attached_ = true; - } + + attached_ = true; } void BrowserBubble::BrowserWindowMoved() { diff --git a/chrome/browser/views/extensions/extension_popup.cc b/chrome/browser/views/extensions/extension_popup.cc index c9c7ae6..6d8e4d6 100644 --- a/chrome/browser/views/extensions/extension_popup.cc +++ b/chrome/browser/views/extensions/extension_popup.cc @@ -5,6 +5,7 @@ #include "chrome/browser/views/extensions/extension_popup.h" #include "chrome/browser/browser.h" +#include "chrome/browser/browser_list.h" #include "chrome/browser/browser_window.h" #include "chrome/browser/profile.h" #include "chrome/browser/extensions/extension_process_manager.h" @@ -27,7 +28,7 @@ const int ExtensionPopup::kMaxWidth = 800; const int ExtensionPopup::kMaxHeight = 600; ExtensionPopup::ExtensionPopup(ExtensionHost* host, - Widget* frame, + views::Widget* frame, const gfx::Rect& relative_to, BubbleBorder::ArrowLocation arrow_location, bool activate_on_show) @@ -79,7 +80,8 @@ void ExtensionPopup::Show(bool activate) { return; #if defined(OS_WIN) - frame_->GetWindow()->DisableInactiveRendering(); + if (frame_->GetWindow()) + frame_->GetWindow()->DisableInactiveRendering(); #endif ResizeToView(); @@ -142,20 +144,32 @@ void ExtensionPopup::OnExtensionPreferredSizeChanged(ExtensionView* view) { // static ExtensionPopup* ExtensionPopup::Show( - const GURL& url, Browser* browser, + const GURL& url, + Browser* browser, + Profile* profile, + gfx::NativeWindow frame_window, const gfx::Rect& relative_to, BubbleBorder::ArrowLocation arrow_location, bool activate_on_show) { - ExtensionProcessManager* manager = - browser->profile()->GetExtensionProcessManager(); + DCHECK(profile); + DCHECK(frame_window); + ExtensionProcessManager* manager = profile->GetExtensionProcessManager(); DCHECK(manager); if (!manager) return NULL; + // If no Browser instance was given, attempt to look up one matching the given + // profile. + if (!browser) + browser = BrowserList::FindBrowserWithProfile(profile); + + Widget* frame_widget = Widget::GetWidgetFromNativeWindow(frame_window); + DCHECK(frame_widget); + if (!frame_widget) + return NULL; + ExtensionHost* host = manager->CreatePopup(url, browser); - views::Widget* frame = BrowserView::GetBrowserViewForNativeWindow( - browser->window()->GetNativeHandle())->GetWidget(); - ExtensionPopup* popup = new ExtensionPopup(host, frame, relative_to, + ExtensionPopup* popup = new ExtensionPopup(host, frame_widget, relative_to, arrow_location, activate_on_show); // If the host had somehow finished loading, then we'd miss the notification diff --git a/chrome/browser/views/extensions/extension_popup.h b/chrome/browser/views/extensions/extension_popup.h index 4c3ca11..92eab93 100644 --- a/chrome/browser/views/extensions/extension_popup.h +++ b/chrome/browser/views/extensions/extension_popup.h @@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_VIEWS_EXTENSIONS_EXTENSION_POPUP_H_ #define CHROME_BROWSER_VIEWS_EXTENSIONS_EXTENSION_POPUP_H_ +#include "app/gfx/native_widget_types.h" #include "chrome/browser/extensions/extension_host.h" #include "chrome/browser/views/browser_bubble.h" #include "chrome/browser/views/extensions/extension_view.h" @@ -15,6 +16,11 @@ class Browser; class ExtensionHost; +class Profile; + +namespace views { +class Widget; +} class ExtensionPopup : public BrowserBubble, public NotificationObserver, @@ -24,6 +30,12 @@ class ExtensionPopup : public BrowserBubble, // Create and show a popup with |url| positioned adjacent to |relative_to| in // screen coordinates. + // |browser| is the browser to which the pop-up will be attached. NULL is a + // valid parameter for pop-ups not associated with a browser. + // |profile| is the user profile instance associated with the popup. A + // non NULL value must be given. + // |frame_window| is the native window that hosts the view inside which the + // popup will be anchored. // The positioning of the pop-up is determined by |arrow_location| according // to the following logic: The popup is anchored so that the corner indicated // by value of |arrow_location| remains fixed during popup resizes. @@ -34,6 +46,8 @@ class ExtensionPopup : public BrowserBubble, // The actual display of the popup is delayed until the page contents // finish loading in order to minimize UI flashing and resizing. static ExtensionPopup* Show(const GURL& url, Browser* browser, + Profile* profile, + gfx::NativeWindow frame_window, const gfx::Rect& relative_to, BubbleBorder::ArrowLocation arrow_location, bool activate_on_show); diff --git a/chrome/browser/views/location_bar_view.cc b/chrome/browser/views/location_bar_view.cc index 03f8437..d8c41e0 100644 --- a/chrome/browser/views/location_bar_view.cc +++ b/chrome/browser/views/location_bar_view.cc @@ -17,6 +17,7 @@ #include "chrome/app/chrome_dll_resource.h" #include "chrome/browser/alternate_nav_url_fetcher.h" #include "chrome/browser/browser_list.h" +#include "chrome/browser/browser_window.h" #include "chrome/browser/bubble_positioner.h" #include "chrome/browser/command_updater.h" #include "chrome/browser/extensions/extension_browser_event_router.h" @@ -1335,6 +1336,7 @@ void LocationBarView::PageActionImageView::ExecuteAction(int button) { Browser* browser = BrowserList::GetLastActiveWithProfile(profile_); if (!browser) browser = BrowserList::FindBrowserWithProfile(profile_); + DCHECK(browser); bool popup_showing = popup_ != NULL; @@ -1351,8 +1353,11 @@ void LocationBarView::PageActionImageView::ExecuteAction(int button) { gfx::Rect rect = parent->bounds(); rect.set_x(origin.x()); rect.set_y(origin.y()); + popup_ = ExtensionPopup::Show(page_action_->popup_url(), browser, + browser->profile(), + browser->window()->GetNativeHandle(), rect, BubbleBorder::TOP_RIGHT, true); // Activate the popup window. |