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

Side by Side Diff: chrome/browser/views/extensions/extension_popup.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/views/extensions/extension_popup.h" 5 #include "chrome/browser/views/extensions/extension_popup.h"
6 6
7 #include "chrome/browser/browser.h" 7 #include "chrome/browser/browser.h"
8 #include "chrome/browser/browser_list.h" 8 #include "chrome/browser/browser_list.h"
9 #include "chrome/browser/browser_window.h" 9 #include "chrome/browser/browser_window.h"
10 #include "chrome/browser/debugger/devtools_manager.h"
11 #include "chrome/browser/extensions/extension_host.h"
12 #include "chrome/browser/extensions/extension_process_manager.h"
10 #include "chrome/browser/profile.h" 13 #include "chrome/browser/profile.h"
11 #include "chrome/browser/extensions/extension_process_manager.h" 14 #include "chrome/browser/renderer_host/render_widget_host_view.h"
15 #include "chrome/browser/renderer_host/render_view_host.h"
12 #include "chrome/browser/views/frame/browser_view.h" 16 #include "chrome/browser/views/frame/browser_view.h"
13 #include "chrome/common/extensions/extension.h" 17 #include "chrome/common/extensions/extension.h"
14 #include "chrome/common/notification_details.h" 18 #include "chrome/common/notification_details.h"
15 #include "chrome/common/notification_source.h" 19 #include "chrome/common/notification_source.h"
16 #include "chrome/common/notification_type.h" 20 #include "chrome/common/notification_type.h"
17 #include "third_party/skia/include/core/SkColor.h" 21 #include "third_party/skia/include/core/SkColor.h"
18 #include "views/widget/root_view.h" 22 #include "views/widget/root_view.h"
19 #include "views/window/window.h" 23 #include "views/window/window.h"
20 24
21 #if defined(OS_LINUX) 25 #if defined(OS_LINUX)
(...skipping 17 matching lines...) Expand all
39 // The width, in pixels, of the black-border on a popup. 43 // The width, in pixels, of the black-border on a popup.
40 const int kPopupBorderWidth = 1; 44 const int kPopupBorderWidth = 1;
41 45
42 const int kPopupBubbleCornerRadius = BubbleBorder::GetCornerRadius() / 2; 46 const int kPopupBubbleCornerRadius = BubbleBorder::GetCornerRadius() / 2;
43 47
44 ExtensionPopup::ExtensionPopup(ExtensionHost* host, 48 ExtensionPopup::ExtensionPopup(ExtensionHost* host,
45 views::Widget* frame, 49 views::Widget* frame,
46 const gfx::Rect& relative_to, 50 const gfx::Rect& relative_to,
47 BubbleBorder::ArrowLocation arrow_location, 51 BubbleBorder::ArrowLocation arrow_location,
48 bool activate_on_show, 52 bool activate_on_show,
49 PopupChrome chrome) 53 bool inspect_with_devtools,
54 PopupChrome chrome,
55 Observer* observer)
50 : BrowserBubble(host->view(), 56 : BrowserBubble(host->view(),
51 frame, 57 frame,
52 gfx::Point(), 58 gfx::Point(),
53 RECTANGLE_CHROME == chrome), // If no bubble chrome is to 59 RECTANGLE_CHROME == chrome), // If no bubble chrome is to
54 // be displayed, then enable a 60 // be displayed, then enable a
55 // drop-shadow on the bubble 61 // drop-shadow on the bubble
56 // widget. 62 // widget.
57 relative_to_(relative_to), 63 relative_to_(relative_to),
58 extension_host_(host), 64 extension_host_(host),
59 activate_on_show_(activate_on_show), 65 activate_on_show_(activate_on_show),
66 inspect_with_devtools_(inspect_with_devtools),
67 close_on_lost_focus_(true),
68 closing_(false),
60 border_widget_(NULL), 69 border_widget_(NULL),
61 border_(NULL), 70 border_(NULL),
62 border_view_(NULL), 71 border_view_(NULL),
63 popup_chrome_(chrome), 72 popup_chrome_(chrome),
73 observer_(observer),
64 anchor_position_(arrow_location) { 74 anchor_position_(arrow_location) {
75 AddRef(); // Balanced in Close();
76 set_delegate(this);
65 host->view()->SetContainer(this); 77 host->view()->SetContainer(this);
78
79 // We wait to show the popup until the contained host finishes loading.
66 registrar_.Add(this, 80 registrar_.Add(this,
67 NotificationType::EXTENSION_HOST_DID_STOP_LOADING, 81 NotificationType::EXTENSION_HOST_DID_STOP_LOADING,
68 Source<Profile>(host->profile())); 82 Source<Profile>(host->profile()));
69 83
84 // Listen for the containing view calling window.close();
85 registrar_.Add(this, NotificationType::EXTENSION_HOST_VIEW_SHOULD_CLOSE,
86 Source<Profile>(host->profile()));
87
70 // TODO(erikkay) Some of this border code is derived from InfoBubble. 88 // TODO(erikkay) Some of this border code is derived from InfoBubble.
71 // We should see if we can unify these classes. 89 // We should see if we can unify these classes.
72 90
73 // The bubble chrome requires a separate window, so construct it here. 91 // The bubble chrome requires a separate window, so construct it here.
74 if (BUBBLE_CHROME == popup_chrome_) { 92 if (BUBBLE_CHROME == popup_chrome_) {
75 gfx::NativeView native_window = frame->GetNativeView(); 93 gfx::NativeView native_window = frame->GetNativeView();
76 #if defined(OS_LINUX) 94 #if defined(OS_LINUX)
77 border_widget_ = new views::WidgetGtk(views::WidgetGtk::TYPE_WINDOW); 95 border_widget_ = new views::WidgetGtk(views::WidgetGtk::TYPE_WINDOW);
78 static_cast<views::WidgetGtk*>(border_widget_)->MakeTransparent(); 96 static_cast<views::WidgetGtk*>(border_widget_)->MakeTransparent();
79 static_cast<views::WidgetGtk*>(border_widget_)->make_transient_to_parent(); 97 static_cast<views::WidgetGtk*>(border_widget_)->make_transient_to_parent();
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 178
161 origin.set_x(origin.x() + border_insets.left() + kPopupBubbleCornerRadius); 179 origin.set_x(origin.x() + border_insets.left() + kPopupBubbleCornerRadius);
162 origin.set_y(origin.y() + border_insets.top() + kPopupBubbleCornerRadius); 180 origin.set_y(origin.y() + border_insets.top() + kPopupBubbleCornerRadius);
163 181
164 SetBounds(origin.x(), origin.y(), new_size.width(), new_size.height()); 182 SetBounds(origin.x(), origin.y(), new_size.width(), new_size.height());
165 } else { 183 } else {
166 SetBounds(origin.x(), origin.y(), rect.width(), rect.height()); 184 SetBounds(origin.x(), origin.y(), rect.width(), rect.height());
167 } 185 }
168 } 186 }
169 187
188 void ExtensionPopup::BubbleBrowserWindowMoved(BrowserBubble* bubble) {
189 if (!closing_)
190 Close();
191 // TODO(rafaelw) -- the border must move as well.
192 }
193
194 void ExtensionPopup::BubbleBrowserWindowClosing(BrowserBubble* bubble) {
195 if (!closing_)
196 Close();
197 }
198
199 void ExtensionPopup::BubbleGotFocus(BrowserBubble* bubble) {
200 // Forward the focus to the renderer.
201 host()->render_view_host()->view()->Focus();
202 }
203
204 void ExtensionPopup::BubbleLostFocus(BrowserBubble* bubble,
205 bool lost_focus_to_child) {
206 if (closing_ || // We are already closing.
207 inspect_with_devtools_ || // The popup is being inspected.
208 !close_on_lost_focus_ || // Our client is handling focus listening.
209 lost_focus_to_child) // A child of this view got focus.
210 return;
211
212 // When we do close on BubbleLostFocus, we do it in the next event loop
213 // because a subsequent event in this loop may also want to close this popup
214 // and if so, we want to allow that. Example: Clicking the same browser
215 // action button that opened the popup. If we closed immediately, the
216 // browser action container would fail to discover that the same button
217 // was pressed.
218 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(this,
219 &ExtensionPopup::Close));
220 }
221
222
170 void ExtensionPopup::Observe(NotificationType type, 223 void ExtensionPopup::Observe(NotificationType type,
171 const NotificationSource& source, 224 const NotificationSource& source,
172 const NotificationDetails& details) { 225 const NotificationDetails& details) {
173 if (type == NotificationType::EXTENSION_HOST_DID_STOP_LOADING) { 226 switch (type.value) {
174 // Once we receive did stop loading, the content will be complete and 227 case NotificationType::EXTENSION_HOST_DID_STOP_LOADING:
175 // the width will have been computed. Now it's safe to show. 228 // Once we receive did stop loading, the content will be complete and
176 if (extension_host_.get() == Details<ExtensionHost>(details).ptr()) 229 // the width will have been computed. Now it's safe to show.
177 Show(activate_on_show_); 230 if (extension_host_.get() == Details<ExtensionHost>(details).ptr()) {
178 } else { 231 Show(activate_on_show_);
179 NOTREACHED() << L"Received unexpected notification"; 232
233 if (inspect_with_devtools_) {
234 // Listen for the the devtools window closing.
235 registrar_.Add(this, NotificationType::DEVTOOLS_WINDOW_CLOSING,
236 Source<Profile>(extension_host_->profile()));
237 DevToolsManager::GetInstance()->ToggleDevToolsWindow(
238 extension_host_->render_view_host(), true);
239 }
240 }
241 break;
242 case NotificationType::EXTENSION_HOST_VIEW_SHOULD_CLOSE:
243 // If we aren't the host of the popup, then disregard the notification.
244 if (Details<ExtensionHost>(host()) != details)
245 return;
246 Close();
247
248 break;
249 case NotificationType::DEVTOOLS_WINDOW_CLOSING:
250 // Make sure its the devtools window that inspecting our popup.
251 if (Details<RenderViewHost>(extension_host_->render_view_host()) != detail s)
252 return;
253
254 // If the devtools window is closing, we post a task to ourselves to
255 // close the popup. This gives the devtools window a chance to finish
256 // detaching from the inspected RenderViewHost.
257 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(this,
258 &ExtensionPopup::Close));
259
260 break;
261 default:
262 NOTREACHED() << L"Received unexpected notification";
180 } 263 }
181 } 264 }
182 265
183 void ExtensionPopup::OnExtensionPreferredSizeChanged(ExtensionView* view) { 266 void ExtensionPopup::OnExtensionPreferredSizeChanged(ExtensionView* view) {
184 // Constrain the size to popup min/max. 267 // Constrain the size to popup min/max.
185 gfx::Size sz = view->GetPreferredSize(); 268 gfx::Size sz = view->GetPreferredSize();
186 view->SetBounds(view->x(), view->y(), 269 view->SetBounds(view->x(), view->y(),
187 std::max(kMinWidth, std::min(kMaxWidth, sz.width())), 270 std::max(kMinWidth, std::min(kMaxWidth, sz.width())),
188 std::max(kMinHeight, std::min(kMaxHeight, sz.height()))); 271 std::max(kMinHeight, std::min(kMaxHeight, sz.height())));
189 272
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
225 308
226 // static 309 // static
227 ExtensionPopup* ExtensionPopup::Show( 310 ExtensionPopup* ExtensionPopup::Show(
228 const GURL& url, 311 const GURL& url,
229 Browser* browser, 312 Browser* browser,
230 Profile* profile, 313 Profile* profile,
231 gfx::NativeWindow frame_window, 314 gfx::NativeWindow frame_window,
232 const gfx::Rect& relative_to, 315 const gfx::Rect& relative_to,
233 BubbleBorder::ArrowLocation arrow_location, 316 BubbleBorder::ArrowLocation arrow_location,
234 bool activate_on_show, 317 bool activate_on_show,
235 PopupChrome chrome) { 318 bool inspect_with_devtools,
319 PopupChrome chrome,
320 Observer* observer) {
236 DCHECK(profile); 321 DCHECK(profile);
237 DCHECK(frame_window); 322 DCHECK(frame_window);
238 ExtensionProcessManager* manager = profile->GetExtensionProcessManager(); 323 ExtensionProcessManager* manager = profile->GetExtensionProcessManager();
239 DCHECK(manager); 324 DCHECK(manager);
240 if (!manager) 325 if (!manager)
241 return NULL; 326 return NULL;
242 327
243 // If no Browser instance was given, attempt to look up one matching the given 328 // If no Browser instance was given, attempt to look up one matching the given
244 // profile. 329 // profile.
245 if (!browser) 330 if (!browser)
246 browser = BrowserList::FindBrowserWithProfile(profile); 331 browser = BrowserList::FindBrowserWithProfile(profile);
247 332
248 Widget* frame_widget = Widget::GetWidgetFromNativeWindow(frame_window); 333 Widget* frame_widget = Widget::GetWidgetFromNativeWindow(frame_window);
249 DCHECK(frame_widget); 334 DCHECK(frame_widget);
250 if (!frame_widget) 335 if (!frame_widget)
251 return NULL; 336 return NULL;
252 337
253 ExtensionHost* host = manager->CreatePopup(url, browser); 338 ExtensionHost* host = manager->CreatePopup(url, browser);
254 ExtensionPopup* popup = new ExtensionPopup(host, frame_widget, relative_to, 339 ExtensionPopup* popup = new ExtensionPopup(host, frame_widget, relative_to,
255 arrow_location, activate_on_show, 340 arrow_location, activate_on_show,
256 chrome); 341 inspect_with_devtools, chrome,
342 observer);
257 343
258 // If the host had somehow finished loading, then we'd miss the notification 344 // If the host had somehow finished loading, then we'd miss the notification
259 // and not show. This seems to happen in single-process mode. 345 // and not show. This seems to happen in single-process mode.
260 if (host->did_stop_loading()) 346 if (host->did_stop_loading())
261 popup->Show(activate_on_show); 347 popup->Show(activate_on_show);
262 348
263 return popup; 349 return popup;
264 } 350 }
351
352 void ExtensionPopup::Close() {
353 if (closing_)
354 return;
355 closing_ = true;
356 DetachFromBrowser();
357 if (observer_)
358 observer_->ExtensionPopupClosed(this);
359 Release(); // Balanced in ctor.
360 }
OLDNEW
« no previous file with comments | « chrome/browser/views/extensions/extension_popup.h ('k') | chrome/browser/views/infobars/extension_infobar.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698