diff options
author | twiz@google.com <twiz@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-11-16 23:28:26 +0000 |
---|---|---|
committer | twiz@google.com <twiz@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-11-16 23:28:26 +0000 |
commit | b2725756d6f40456048f052427746f347dcd8219 (patch) | |
tree | cf02ff046b428d9418291f0f7c6376ac71bbb1ea /chrome/browser/extensions/extension_popup_api.cc | |
parent | ba1d6b0893d6d07cf1fb924f4212446d4e6136d4 (diff) | |
download | chromium_src-b2725756d6f40456048f052427746f347dcd8219.zip chromium_src-b2725756d6f40456048f052427746f347dcd8219.tar.gz chromium_src-b2725756d6f40456048f052427746f347dcd8219.tar.bz2 |
Refactoring of the chrome.experimental.popup API implementation to allow display of pop-ups for extensions viewed through a tab-contents view.I added a new class, ExtensionPopupHost. This class implements the necessary environment for managing child popup windows from either an ExtensionHost, or an ExtensionDOMUI. Note that this class is added as a member to ExtensionHost and ExtensionDOMUI.
I decided to take this approach to prevent multiple inheritance of the NotificationObserver class: Both ExtensionPopupHost and ExtensionHost must inherit from this class, and I was uncertain of how the system would behave wrt virtual inheritance. Please comment on if I should have used the inheritance approach.
I also removed the customHandler tag (in extension_api.json) that I had added in the initial submission. The arguments in the schema are now those that users of the API see. The nodocs tags were also removed.
The api experimental.popup.getAnchorWindow() has been renamed to popup.getParentWindow, as per a suggestion from Erik K.
BUG=none
TEST=extension_popup_apitest.cc
Review URL: http://codereview.chromium.org/385061
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@32120 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/extensions/extension_popup_api.cc')
-rw-r--r-- | chrome/browser/extensions/extension_popup_api.cc | 62 |
1 files changed, 55 insertions, 7 deletions
diff --git a/chrome/browser/extensions/extension_popup_api.cc b/chrome/browser/extensions/extension_popup_api.cc index 26db2e1..f778e0e 100644 --- a/chrome/browser/extensions/extension_popup_api.cc +++ b/chrome/browser/extensions/extension_popup_api.cc @@ -12,10 +12,12 @@ #include "chrome/common/notification_service.h" #include "chrome/common/notification_source.h" #include "chrome/common/notification_type.h" +#include "chrome/browser/extensions/extension_dom_ui.h" #include "chrome/browser/extensions/extension_host.h" #include "chrome/browser/extensions/extension_message_service.h" #include "chrome/browser/browser.h" #include "chrome/browser/profile.h" +#include "chrome/browser/tab_contents/tab_contents.h" #if defined(TOOLKIT_VIEWS) #include "chrome/browser/views/extensions/extension_popup.h" #include "views/view.h" @@ -32,6 +34,7 @@ namespace { // Errors. const char kBadAnchorArgument[] = "Invalid anchor argument."; const char kInvalidURLError[] = "Invalid URL."; +const char kNotAnExtension[] = "Not an extension view."; // Keys. const wchar_t kUrlKey[] = L"url"; @@ -111,17 +114,62 @@ bool PopupShowFunction::RunImpl() { } #if defined(TOOLKIT_VIEWS) - views::View* extension_view = dispatcher()->GetExtensionHost()->view(); gfx::Point origin(dom_left, dom_top); - views::View::ConvertPointToScreen(extension_view, &origin); + if (!ConvertHostPointToScreen(&origin)) { + error_ = kNotAnExtension; + return false; + } gfx::Rect rect(origin.x(), origin.y(), dom_width, dom_height); + // Pop-up from extension views (ExtensionShelf, etc.), and drop-down when + // in a TabContents view. + BubbleBorder::ArrowLocation arrow_location = + (NULL != dispatcher()->GetExtensionHost()) ? BubbleBorder::BOTTOM_LEFT : + BubbleBorder::TOP_LEFT; popup_ = ExtensionPopup::Show(url, dispatcher()->GetBrowser(), rect, - BubbleBorder::BOTTOM_LEFT); + arrow_location); + + ExtensionPopupHost* popup_host = dispatcher()->GetPopupHost(); + DCHECK(popup_host); + + popup_host->set_child_popup(popup_); + popup_->set_delegate(popup_host); +#endif // defined(TOOLKIT_VIEWS) + return true; +} + +bool PopupShowFunction::ConvertHostPointToScreen(gfx::Point* point) { + DCHECK(point); + + // If the popup is being requested from an ExtensionHost, then compute + // the sreen coordinates based on the views::View object of the ExtensionHost. + if (dispatcher()->GetExtensionHost()) { + // A dispatcher cannot have both an ExtensionHost, and an ExtensionDOMUI. + DCHECK(!dispatcher()->GetExtensionDOMUI()); + +#if defined(TOOLKIT_VIEWS) + views::View* extension_view = dispatcher()->GetExtensionHost()->view(); + if (!extension_view) + return false; + + views::View::ConvertPointToScreen(extension_view, point); +#else + // TODO(port) + NOTIMPLEMENTED(); +#endif // defined(TOOLKIT_VIEWS) + } else if (dispatcher()->GetExtensionDOMUI()) { + // Otherwise, the popup is being requested from a TabContents, so determine + // the screen-space position through the TabContentsView. + ExtensionDOMUI* dom_ui = dispatcher()->GetExtensionDOMUI(); + TabContents* tab_contents = dom_ui->tab_contents(); + if (!tab_contents) + return false; + + gfx::Rect content_bounds; + tab_contents->GetContainerBounds(&content_bounds); + point->Offset(content_bounds.x(), content_bounds.y()); + } - dispatcher()->GetExtensionHost()->set_child_popup(popup_); - popup_->set_delegate(dispatcher()->GetExtensionHost()); -#endif return true; } @@ -144,7 +192,7 @@ void PopupShowFunction::Observe(NotificationType type, SendResponse(false); Release(); // Balanced in Run(). } -#endif +#endif // defined(TOOLKIT_VIEWS) } // static |