Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(78)

Side by Side Diff: chrome/browser/extensions/extension_popup_api.cc

Issue 1001002: Initial support for inspecting extension popups. (Closed)
Patch Set: pre submit Created 10 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/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/common/extensions/extension.h" 9 #include "chrome/common/extensions/extension.h"
10 #include "chrome/common/notification_details.h" 10 #include "chrome/common/notification_details.h"
11 #include "chrome/common/notification_service.h" 11 #include "chrome/common/notification_service.h"
12 #include "chrome/common/notification_source.h" 12 #include "chrome/common/notification_source.h"
13 #include "chrome/common/notification_type.h" 13 #include "chrome/common/notification_type.h"
14 #include "chrome/common/url_constants.h" 14 #include "chrome/common/url_constants.h"
15 #include "chrome/browser/extensions/extension_dom_ui.h" 15 #include "chrome/browser/extensions/extension_dom_ui.h"
16 #include "chrome/browser/extensions/extension_host.h" 16 #include "chrome/browser/extensions/extension_host.h"
17 #include "chrome/browser/extensions/extension_message_service.h" 17 #include "chrome/browser/extensions/extension_message_service.h"
18 #include "chrome/browser/browser.h" 18 #include "chrome/browser/browser.h"
19 #include "chrome/browser/profile.h" 19 #include "chrome/browser/profile.h"
20 #include "chrome/browser/tab_contents/tab_contents.h" 20 #include "chrome/browser/tab_contents/tab_contents.h"
21 #include "gfx/point.h" 21 #include "gfx/point.h"
22 22
23 #if defined(TOOLKIT_VIEWS) 23 #if defined(TOOLKIT_VIEWS)
24 #include "chrome/browser/renderer_host/render_view_host.h"
25 #include "chrome/browser/renderer_host/render_widget_host_view.h"
24 #include "chrome/browser/views/extensions/extension_popup.h" 26 #include "chrome/browser/views/extensions/extension_popup.h"
25 #include "views/view.h" 27 #include "views/view.h"
26 #endif 28 #include "views/focus/focus_manager.h"
29 #endif // TOOLKIT_VIEWS
27 30
28 namespace extension_popup_module_events { 31 namespace extension_popup_module_events {
29 32
30 const char kOnPopupClosed[] = "experimental.popup.onClosed.%d"; 33 const char kOnPopupClosed[] = "experimental.popup.onClosed.%d";
31 34
32 } // namespace extension_popup_module_events 35 } // namespace extension_popup_module_events
33 36
34 namespace { 37 namespace {
35 38
36 // Errors. 39 // Errors.
37 const char kBadAnchorArgument[] = "Invalid anchor argument."; 40 const char kBadAnchorArgument[] = "Invalid anchor argument.";
38 const char kInvalidURLError[] = "Invalid URL."; 41 const char kInvalidURLError[] = "Invalid URL.";
39 const char kNotAnExtension[] = "Not an extension view."; 42 const char kNotAnExtension[] = "Not an extension view.";
40 43
41 // Keys. 44 // Keys.
42 const wchar_t kUrlKey[] = L"url"; 45 const wchar_t kUrlKey[] = L"url";
43 const wchar_t kWidthKey[] = L"width"; 46 const wchar_t kWidthKey[] = L"width";
44 const wchar_t kHeightKey[] = L"height"; 47 const wchar_t kHeightKey[] = L"height";
45 const wchar_t kTopKey[] = L"top"; 48 const wchar_t kTopKey[] = L"top";
46 const wchar_t kLeftKey[] = L"left"; 49 const wchar_t kLeftKey[] = L"left";
47 const wchar_t kGiveFocusKey[] = L"giveFocus"; 50 const wchar_t kGiveFocusKey[] = L"giveFocus";
48 const wchar_t kDomAnchorKey[] = L"domAnchor"; 51 const wchar_t kDomAnchorKey[] = L"domAnchor";
49 const wchar_t kBorderStyleKey[] = L"borderStyle"; 52 const wchar_t kBorderStyleKey[] = L"borderStyle";
50 53
51 // chrome enumeration values 54 // chrome enumeration values
52 const char kRectangleChrome[] = "rectangle"; 55 const char kRectangleChrome[] = "rectangle";
53 56
54 }; // namespace 57 }; // namespace
55 58
59 #if defined(TOOLKIT_VIEWS)
60 // ExtensionPopupHost objects implement the environment necessary to host
61 // an ExtensionPopup views for the popup api. Its main job is to handle
62 // its lifetime and to fire the popup-closed event when the popup is closed.
63 // Because the close-on-focus-lost behavior is different from page action
64 // and browser action, it also manages its own focus change listening. The
65 // difference in close-on-focus-lost is that in the page action and browser
66 // action cases, the popup closes when the focus leaves the popup or any of its
67 // children. In this case, the popup closes when the focus leaves the popups
68 // containing view or any of *its* children.
69 class ExtensionPopupHost : public ExtensionPopup::Observer,
70 public views::WidgetFocusChangeListener,
71 public base::RefCounted<ExtensionPopupHost> {
72 public:
73 explicit ExtensionPopupHost(ExtensionFunctionDispatcher* dispatcher)
74 : dispatcher_(dispatcher), popup_(NULL) {
75 AddRef(); // Balanced in ExtensionPopupClosed().
76 views::FocusManager::GetWidgetFocusManager()->AddFocusChangeListener(this);
77 }
78
79 ~ExtensionPopupHost() {
80 views::FocusManager::GetWidgetFocusManager()->
81 RemoveFocusChangeListener(this);
82 }
83
84 void set_popup(ExtensionPopup* popup) {
85 popup_ = popup;
86 }
87
88 // Overriden from ExtensionPopup::Observer
89 virtual void ExtensionPopupClosed(ExtensionPopup* popup) {
90 RenderViewHost* render_view_host = dispatcher_->GetExtensionHost() ?
91 dispatcher_->GetExtensionHost()->render_view_host() :
92 dispatcher_->GetExtensionDOMUI()->GetRenderViewHost();
93
94 PopupEventRouter::OnPopupClosed(dispatcher_->profile(),
95 render_view_host->routing_id());
96 dispatcher_ = NULL;
97 Release(); // Balanced in ctor.
98 }
99
100 // Overriden from views::WidgetFocusChangeListener
101 virtual void NativeFocusWillChange(gfx::NativeView focused_before,
102 gfx::NativeView focused_now) {
103 // If no view is to be focused, then Chrome was deactivated, so hide the
104 // popup.
105 if (focused_now) {
106 gfx::NativeView host_view = dispatcher_->GetExtensionHost() ?
107 dispatcher_->GetExtensionHost()->GetNativeViewOfHost() :
108 dispatcher_->GetExtensionDOMUI()->GetNativeViewOfHost();
109
110 // If the widget hosting the popup contains the newly focused view, then
111 // don't dismiss the pop-up.
112 views::Widget* popup_root_widget = popup_->host()->view()->GetWidget();
113 if (popup_root_widget &&
114 popup_root_widget->ContainsNativeView(focused_now))
115 return;
116
117 // If the widget or RenderWidgetHostView hosting the extension that
118 // launched the pop-up is receiving focus, then don't dismiss the popup.
119 views::Widget* host_widget =
120 views::Widget::GetWidgetFromNativeView(host_view);
121 if (host_widget && host_widget->ContainsNativeView(focused_now))
122 return;
123
124 RenderWidgetHostView* render_host_view =
125 RenderWidgetHostView::GetRenderWidgetHostViewFromNativeView(
126 host_view);
127 if (render_host_view &&
128 render_host_view->ContainsNativeView(focused_now))
129 return;
130 }
131
132 // We are careful here to let the current event loop unwind before
133 // causing the popup to be closed.
134 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(popup_,
135 &ExtensionPopup::Close));
136 }
137
138 private:
139 // A pointer to the dispatcher that handled the request that opened this
140 // popup view.
141 ExtensionFunctionDispatcher* dispatcher_;
142
143 // A pointer to the popup.
144 ExtensionPopup* popup_;
145
146 DISALLOW_COPY_AND_ASSIGN(ExtensionPopupHost);
147 };
148 #endif // TOOLKIT_VIEWS
149
56 PopupShowFunction::PopupShowFunction() 150 PopupShowFunction::PopupShowFunction()
57 #if defined (TOOLKIT_VIEWS) 151 #if defined (TOOLKIT_VIEWS)
58 : popup_(NULL) 152 : popup_(NULL)
59 #endif 153 #endif
60 {} 154 {}
61 155
62 void PopupShowFunction::Run() { 156 void PopupShowFunction::Run() {
63 #if defined(TOOLKIT_VIEWS) 157 #if defined(TOOLKIT_VIEWS)
64 if (!RunImpl()) { 158 if (!RunImpl()) {
65 SendResponse(false); 159 SendResponse(false);
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
150 error_ = kNotAnExtension; 244 error_ = kNotAnExtension;
151 return false; 245 return false;
152 } 246 }
153 gfx::Rect rect(origin.x(), origin.y(), dom_width, dom_height); 247 gfx::Rect rect(origin.x(), origin.y(), dom_width, dom_height);
154 248
155 // Pop-up from extension views (ExtensionShelf, etc.), and drop-down when 249 // Pop-up from extension views (ExtensionShelf, etc.), and drop-down when
156 // in a TabContents view. 250 // in a TabContents view.
157 BubbleBorder::ArrowLocation arrow_location = 251 BubbleBorder::ArrowLocation arrow_location =
158 (NULL != dispatcher()->GetExtensionHost()) ? BubbleBorder::BOTTOM_LEFT : 252 (NULL != dispatcher()->GetExtensionHost()) ? BubbleBorder::BOTTOM_LEFT :
159 BubbleBorder::TOP_LEFT; 253 BubbleBorder::TOP_LEFT;
160 popup_ = ExtensionPopup::Show(url, GetBrowser(), 254
255 // ExtensionPopupHost manages it's own lifetime.
256 ExtensionPopupHost* popup_host = new ExtensionPopupHost(dispatcher());
257 popup_ = ExtensionPopup::Show(url,
258 GetBrowser(),
161 dispatcher()->profile(), 259 dispatcher()->profile(),
162 dispatcher()->GetFrameNativeWindow(), 260 dispatcher()->GetFrameNativeWindow(),
163 rect, 261 rect,
164 arrow_location, 262 arrow_location,
165 give_focus, 263 give_focus,
166 chrome); 264 false, // inspect_with_devtools
265 chrome,
266 popup_host); // ExtensionPopup::Observer
167 267
168 ExtensionPopupHost* popup_host = dispatcher()->GetPopupHost(); 268 // popup_host will handle focus change listening and close the popup when
169 DCHECK(popup_host); 269 // focus leaves the containing views hierarchy.
170 270 popup_->set_close_on_lost_focus(false);
171 popup_host->set_child_popup(popup_); 271 popup_host->set_popup(popup_);
172 popup_->set_delegate(popup_host);
173 #endif // defined(TOOLKIT_VIEWS) 272 #endif // defined(TOOLKIT_VIEWS)
174 return true; 273 return true;
175 } 274 }
176 275
177 bool PopupShowFunction::ConvertHostPointToScreen(gfx::Point* point) { 276 bool PopupShowFunction::ConvertHostPointToScreen(gfx::Point* point) {
178 DCHECK(point); 277 DCHECK(point);
179 278
180 // If the popup is being requested from an ExtensionHost, then compute 279 // If the popup is being requested from an ExtensionHost, then compute
181 // the sreen coordinates based on the views::View object of the ExtensionHost. 280 // the sreen coordinates based on the views::View object of the ExtensionHost.
182 if (dispatcher()->GetExtensionHost()) { 281 if (dispatcher()->GetExtensionHost()) {
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
236 int routing_id) { 335 int routing_id) {
237 std::string full_event_name = StringPrintf( 336 std::string full_event_name = StringPrintf(
238 extension_popup_module_events::kOnPopupClosed, 337 extension_popup_module_events::kOnPopupClosed,
239 routing_id); 338 routing_id);
240 339
241 profile->GetExtensionMessageService()->DispatchEventToRenderers( 340 profile->GetExtensionMessageService()->DispatchEventToRenderers(
242 full_event_name, 341 full_event_name,
243 base::JSONWriter::kEmptyArray, 342 base::JSONWriter::kEmptyArray,
244 profile->IsOffTheRecord()); 343 profile->IsOffTheRecord());
245 } 344 }
OLDNEW
« no previous file with comments | « chrome/browser/extensions/extension_host.h ('k') | chrome/browser/extensions/extension_popup_host.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698