| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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/gfx/point.h" | 7 #include "base/gfx/point.h" |
| 8 #include "base/json/json_writer.h" | 8 #include "base/json/json_writer.h" |
| 9 #include "base/string_util.h" | 9 #include "base/string_util.h" |
| 10 #include "chrome/common/extensions/extension.h" | 10 #include "chrome/common/extensions/extension.h" |
| 11 #include "chrome/common/notification_details.h" | 11 #include "chrome/common/notification_details.h" |
| 12 #include "chrome/common/notification_service.h" | 12 #include "chrome/common/notification_service.h" |
| 13 #include "chrome/common/notification_source.h" | 13 #include "chrome/common/notification_source.h" |
| 14 #include "chrome/common/notification_type.h" | 14 #include "chrome/common/notification_type.h" |
| 15 #include "chrome/browser/extensions/extension_dom_ui.h" |
| 15 #include "chrome/browser/extensions/extension_host.h" | 16 #include "chrome/browser/extensions/extension_host.h" |
| 16 #include "chrome/browser/extensions/extension_message_service.h" | 17 #include "chrome/browser/extensions/extension_message_service.h" |
| 17 #include "chrome/browser/browser.h" | 18 #include "chrome/browser/browser.h" |
| 18 #include "chrome/browser/profile.h" | 19 #include "chrome/browser/profile.h" |
| 20 #include "chrome/browser/tab_contents/tab_contents.h" |
| 19 #if defined(TOOLKIT_VIEWS) | 21 #if defined(TOOLKIT_VIEWS) |
| 20 #include "chrome/browser/views/extensions/extension_popup.h" | 22 #include "chrome/browser/views/extensions/extension_popup.h" |
| 21 #include "views/view.h" | 23 #include "views/view.h" |
| 22 #endif | 24 #endif |
| 23 | 25 |
| 24 namespace extension_popup_module_events { | 26 namespace extension_popup_module_events { |
| 25 | 27 |
| 26 const char kOnPopupClosed[] = "experimental.popup.onClosed.%d"; | 28 const char kOnPopupClosed[] = "experimental.popup.onClosed.%d"; |
| 27 | 29 |
| 28 } // namespace extension_popup_module_events | 30 } // namespace extension_popup_module_events |
| 29 | 31 |
| 30 namespace { | 32 namespace { |
| 31 | 33 |
| 32 // Errors. | 34 // Errors. |
| 33 const char kBadAnchorArgument[] = "Invalid anchor argument."; | 35 const char kBadAnchorArgument[] = "Invalid anchor argument."; |
| 34 const char kInvalidURLError[] = "Invalid URL."; | 36 const char kInvalidURLError[] = "Invalid URL."; |
| 37 const char kNotAnExtension[] = "Not an extension view."; |
| 35 | 38 |
| 36 // Keys. | 39 // Keys. |
| 37 const wchar_t kUrlKey[] = L"url"; | 40 const wchar_t kUrlKey[] = L"url"; |
| 38 const wchar_t kWidthKey[] = L"width"; | 41 const wchar_t kWidthKey[] = L"width"; |
| 39 const wchar_t kHeightKey[] = L"height"; | 42 const wchar_t kHeightKey[] = L"height"; |
| 40 const wchar_t kTopKey[] = L"top"; | 43 const wchar_t kTopKey[] = L"top"; |
| 41 const wchar_t kLeftKey[] = L"left"; | 44 const wchar_t kLeftKey[] = L"left"; |
| 42 | 45 |
| 43 }; // namespace | 46 }; // namespace |
| 44 | 47 |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 // Disallow non-extension requests, or requests outside of the requesting | 107 // Disallow non-extension requests, or requests outside of the requesting |
| 105 // extension view's extension. | 108 // extension view's extension. |
| 106 const std::string& extension_id = url.host(); | 109 const std::string& extension_id = url.host(); |
| 107 if (extension_id != dispatcher()->GetExtension()->id() || | 110 if (extension_id != dispatcher()->GetExtension()->id() || |
| 108 !url.SchemeIs("chrome-extension")) { | 111 !url.SchemeIs("chrome-extension")) { |
| 109 error_ = kInvalidURLError; | 112 error_ = kInvalidURLError; |
| 110 return false; | 113 return false; |
| 111 } | 114 } |
| 112 | 115 |
| 113 #if defined(TOOLKIT_VIEWS) | 116 #if defined(TOOLKIT_VIEWS) |
| 114 views::View* extension_view = dispatcher()->GetExtensionHost()->view(); | |
| 115 gfx::Point origin(dom_left, dom_top); | 117 gfx::Point origin(dom_left, dom_top); |
| 116 views::View::ConvertPointToScreen(extension_view, &origin); | 118 if (!ConvertHostPointToScreen(&origin)) { |
| 119 error_ = kNotAnExtension; |
| 120 return false; |
| 121 } |
| 117 gfx::Rect rect(origin.x(), origin.y(), dom_width, dom_height); | 122 gfx::Rect rect(origin.x(), origin.y(), dom_width, dom_height); |
| 118 | 123 |
| 124 // Pop-up from extension views (ExtensionShelf, etc.), and drop-down when |
| 125 // in a TabContents view. |
| 126 BubbleBorder::ArrowLocation arrow_location = |
| 127 (NULL != dispatcher()->GetExtensionHost()) ? BubbleBorder::BOTTOM_LEFT : |
| 128 BubbleBorder::TOP_LEFT; |
| 119 popup_ = ExtensionPopup::Show(url, dispatcher()->GetBrowser(), rect, | 129 popup_ = ExtensionPopup::Show(url, dispatcher()->GetBrowser(), rect, |
| 120 BubbleBorder::BOTTOM_LEFT); | 130 arrow_location); |
| 121 | 131 |
| 122 dispatcher()->GetExtensionHost()->set_child_popup(popup_); | 132 ExtensionPopupHost* popup_host = dispatcher()->GetPopupHost(); |
| 123 popup_->set_delegate(dispatcher()->GetExtensionHost()); | 133 DCHECK(popup_host); |
| 124 #endif | 134 |
| 135 popup_host->set_child_popup(popup_); |
| 136 popup_->set_delegate(popup_host); |
| 137 #endif // defined(TOOLKIT_VIEWS) |
| 138 return true; |
| 139 } |
| 140 |
| 141 bool PopupShowFunction::ConvertHostPointToScreen(gfx::Point* point) { |
| 142 DCHECK(point); |
| 143 |
| 144 // If the popup is being requested from an ExtensionHost, then compute |
| 145 // the sreen coordinates based on the views::View object of the ExtensionHost. |
| 146 if (dispatcher()->GetExtensionHost()) { |
| 147 // A dispatcher cannot have both an ExtensionHost, and an ExtensionDOMUI. |
| 148 DCHECK(!dispatcher()->GetExtensionDOMUI()); |
| 149 |
| 150 #if defined(TOOLKIT_VIEWS) |
| 151 views::View* extension_view = dispatcher()->GetExtensionHost()->view(); |
| 152 if (!extension_view) |
| 153 return false; |
| 154 |
| 155 views::View::ConvertPointToScreen(extension_view, point); |
| 156 #else |
| 157 // TODO(port) |
| 158 NOTIMPLEMENTED(); |
| 159 #endif // defined(TOOLKIT_VIEWS) |
| 160 } else if (dispatcher()->GetExtensionDOMUI()) { |
| 161 // Otherwise, the popup is being requested from a TabContents, so determine |
| 162 // the screen-space position through the TabContentsView. |
| 163 ExtensionDOMUI* dom_ui = dispatcher()->GetExtensionDOMUI(); |
| 164 TabContents* tab_contents = dom_ui->tab_contents(); |
| 165 if (!tab_contents) |
| 166 return false; |
| 167 |
| 168 gfx::Rect content_bounds; |
| 169 tab_contents->GetContainerBounds(&content_bounds); |
| 170 point->Offset(content_bounds.x(), content_bounds.y()); |
| 171 } |
| 172 |
| 125 return true; | 173 return true; |
| 126 } | 174 } |
| 127 | 175 |
| 128 void PopupShowFunction::Observe(NotificationType type, | 176 void PopupShowFunction::Observe(NotificationType type, |
| 129 const NotificationSource& source, | 177 const NotificationSource& source, |
| 130 const NotificationDetails& details) { | 178 const NotificationDetails& details) { |
| 131 #if defined(TOOLKIT_VIEWS) | 179 #if defined(TOOLKIT_VIEWS) |
| 132 DCHECK(type == NotificationType::EXTENSION_POPUP_VIEW_READY || | 180 DCHECK(type == NotificationType::EXTENSION_POPUP_VIEW_READY || |
| 133 type == NotificationType::EXTENSION_HOST_DESTROYED); | 181 type == NotificationType::EXTENSION_HOST_DESTROYED); |
| 134 DCHECK(popup_ != NULL); | 182 DCHECK(popup_ != NULL); |
| 135 | 183 |
| 136 if (popup_ && type == NotificationType::EXTENSION_POPUP_VIEW_READY && | 184 if (popup_ && type == NotificationType::EXTENSION_POPUP_VIEW_READY && |
| 137 Details<ExtensionHost>(popup_->host()) == details) { | 185 Details<ExtensionHost>(popup_->host()) == details) { |
| 138 SendResponse(true); | 186 SendResponse(true); |
| 139 Release(); // Balanced in Run(). | 187 Release(); // Balanced in Run(). |
| 140 } else if (popup_ && type == NotificationType::EXTENSION_HOST_DESTROYED && | 188 } else if (popup_ && type == NotificationType::EXTENSION_HOST_DESTROYED && |
| 141 Details<ExtensionHost>(popup_->host()) == details) { | 189 Details<ExtensionHost>(popup_->host()) == details) { |
| 142 // If the host was destroyed, then report failure, and release the remaining | 190 // If the host was destroyed, then report failure, and release the remaining |
| 143 // reference. | 191 // reference. |
| 144 SendResponse(false); | 192 SendResponse(false); |
| 145 Release(); // Balanced in Run(). | 193 Release(); // Balanced in Run(). |
| 146 } | 194 } |
| 147 #endif | 195 #endif // defined(TOOLKIT_VIEWS) |
| 148 } | 196 } |
| 149 | 197 |
| 150 // static | 198 // static |
| 151 void PopupEventRouter::OnPopupClosed(Profile* profile, | 199 void PopupEventRouter::OnPopupClosed(Profile* profile, |
| 152 int routing_id) { | 200 int routing_id) { |
| 153 std::string full_event_name = StringPrintf( | 201 std::string full_event_name = StringPrintf( |
| 154 extension_popup_module_events::kOnPopupClosed, | 202 extension_popup_module_events::kOnPopupClosed, |
| 155 routing_id); | 203 routing_id); |
| 156 | 204 |
| 157 profile->GetExtensionMessageService()->DispatchEventToRenderers( | 205 profile->GetExtensionMessageService()->DispatchEventToRenderers( |
| 158 full_event_name, | 206 full_event_name, |
| 159 base::JSONWriter::kEmptyArray); | 207 base::JSONWriter::kEmptyArray); |
| 160 } | 208 } |
| OLD | NEW |