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

Side by Side Diff: chrome/browser/views/browser_actions_container.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) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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/browser_actions_container.h" 5 #include "chrome/browser/views/browser_actions_container.h"
6 6
7 #include "app/gfx/canvas.h" 7 #include "app/gfx/canvas.h"
8 #include "app/resource_bundle.h" 8 #include "app/resource_bundle.h"
9 #include "app/slide_animation.h" 9 #include "app/slide_animation.h"
10 #include "base/stl_util-inl.h" 10 #include "base/stl_util-inl.h"
11 #include "base/string_util.h" 11 #include "base/string_util.h"
12 #include "chrome/browser/browser.h" 12 #include "chrome/browser/browser.h"
13 #include "chrome/browser/browser_theme_provider.h" 13 #include "chrome/browser/browser_theme_provider.h"
14 #include "chrome/browser/browser_window.h" 14 #include "chrome/browser/browser_window.h"
15 #include "chrome/browser/extensions/extension_browser_event_router.h" 15 #include "chrome/browser/extensions/extension_browser_event_router.h"
16 #include "chrome/browser/extensions/extension_host.h"
16 #include "chrome/browser/extensions/extensions_service.h" 17 #include "chrome/browser/extensions/extensions_service.h"
17 #include "chrome/browser/extensions/extension_tabs_module.h" 18 #include "chrome/browser/extensions/extension_tabs_module.h"
18 #include "chrome/browser/renderer_host/render_widget_host_view.h" 19 #include "chrome/browser/renderer_host/render_widget_host_view.h"
19 #include "chrome/browser/renderer_host/render_view_host.h" 20 #include "chrome/browser/renderer_host/render_view_host.h"
20 #include "chrome/browser/profile.h" 21 #include "chrome/browser/profile.h"
21 #include "chrome/browser/tab_contents/tab_contents.h" 22 #include "chrome/browser/tab_contents/tab_contents.h"
22 #include "chrome/browser/view_ids.h" 23 #include "chrome/browser/view_ids.h"
23 #include "chrome/browser/views/detachable_toolbar_view.h" 24 #include "chrome/browser/views/detachable_toolbar_view.h"
24 #include "chrome/browser/views/extensions/browser_action_drag_data.h" 25 #include "chrome/browser/views/extensions/browser_action_drag_data.h"
25 #include "chrome/browser/views/extensions/extension_popup.h" 26 #include "chrome/browser/views/extensions/extension_popup.h"
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 BrowserActionButton::~BrowserActionButton() { 127 BrowserActionButton::~BrowserActionButton() {
127 if (tracker_) 128 if (tracker_)
128 tracker_->StopTrackingImageLoad(); 129 tracker_->StopTrackingImageLoad();
129 } 130 }
130 131
131 gfx::Insets BrowserActionButton::GetInsets() const { 132 gfx::Insets BrowserActionButton::GetInsets() const {
132 static gfx::Insets zero_inset; 133 static gfx::Insets zero_inset;
133 return zero_inset; 134 return zero_inset;
134 } 135 }
135 136
136 void BrowserActionButton::ButtonPressed( 137 void BrowserActionButton::ButtonPressed(views::Button* sender,
137 views::Button* sender, const views::Event& event) { 138 const views::Event& event) {
138 panel_->OnBrowserActionExecuted(this); 139 panel_->OnBrowserActionExecuted(this, false); // inspect_with_devtools
139 } 140 }
140 141
141 void BrowserActionButton::OnImageLoaded(SkBitmap* image, size_t index) { 142 void BrowserActionButton::OnImageLoaded(SkBitmap* image, size_t index) {
142 if (image) 143 if (image)
143 default_icon_ = *image; 144 default_icon_ = *image;
144 145
145 tracker_ = NULL; // The tracker object will delete itself when we return. 146 tracker_ = NULL; // The tracker object will delete itself when we return.
146 147
147 // Call back to UpdateState() because a more specific icon might have been set 148 // Call back to UpdateState() because a more specific icon might have been set
148 // while the load was outstanding. 149 // while the load was outstanding.
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
191 if (tab_id < 0) { 192 if (tab_id < 0) {
192 NOTREACHED() << "Button is not on a specific tab."; 193 NOTREACHED() << "Button is not on a specific tab.";
193 GURL empty_url; 194 GURL empty_url;
194 return empty_url; 195 return empty_url;
195 } 196 }
196 return browser_action_->GetPopupUrl(tab_id); 197 return browser_action_->GetPopupUrl(tab_id);
197 } 198 }
198 199
199 bool BrowserActionButton::Activate() { 200 bool BrowserActionButton::Activate() {
200 if (IsPopup()) { 201 if (IsPopup()) {
201 panel_->OnBrowserActionExecuted(this); 202 panel_->OnBrowserActionExecuted(this, false); // inspect_with_devtools
202 203
203 // TODO(erikkay): Run a nested modal loop while the mouse is down to 204 // TODO(erikkay): Run a nested modal loop while the mouse is down to
204 // enable menu-like drag-select behavior. 205 // enable menu-like drag-select behavior.
205 206
206 // The return value of this method is returned via OnMousePressed. 207 // The return value of this method is returned via OnMousePressed.
207 // We need to return false here since we're handing off focus to another 208 // We need to return false here since we're handing off focus to another
208 // widget/view, and true will grab it right back and try to send events 209 // widget/view, and true will grab it right back and try to send events
209 // to us. 210 // to us.
210 return false; 211 return false;
211 } 212 }
212 return true; 213 return true;
213 } 214 }
214 215
215 bool BrowserActionButton::OnMousePressed(const views::MouseEvent& e) { 216 bool BrowserActionButton::OnMousePressed(const views::MouseEvent& e) {
216 showing_context_menu_ = e.IsRightMouseButton(); 217 showing_context_menu_ = e.IsRightMouseButton();
217 if (showing_context_menu_) { 218 if (showing_context_menu_) {
218 SetButtonPushed(); 219 SetButtonPushed();
219 220
220 // Get the top left point of this button in screen coordinates. 221 // Get the top left point of this button in screen coordinates.
221 gfx::Point point = gfx::Point(0, 0); 222 gfx::Point point = gfx::Point(0, 0);
222 ConvertPointToScreen(this, &point); 223 ConvertPointToScreen(this, &point);
223 224
224 // Make the menu appear below the button. 225 // Make the menu appear below the button.
225 point.Offset(0, height()); 226 point.Offset(0, height());
226 227
227 panel_->GetContextMenu()->Run(extension(), point); 228 panel_->GetContextMenu()->Run(extension(), extension()->browser_action(),
229 panel_, panel_->profile()->GetPrefs(), point);
228 230
229 SetButtonNotPushed(); 231 SetButtonNotPushed();
230 return false; 232 return false;
231 } else if (IsPopup()) { 233 } else if (IsPopup()) {
232 return MenuButton::OnMousePressed(e); 234 return MenuButton::OnMousePressed(e);
233 } 235 }
234 return TextButton::OnMousePressed(e); 236 return TextButton::OnMousePressed(e);
235 } 237 }
236 238
237 void BrowserActionButton::OnMouseReleased(const views::MouseEvent& e, 239 void BrowserActionButton::OnMouseReleased(const views::MouseEvent& e,
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 animation_target_size_(0), 335 animation_target_size_(0),
334 drop_indicator_position_(-1), 336 drop_indicator_position_(-1),
335 ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)), 337 ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)),
336 ALLOW_THIS_IN_INITIALIZER_LIST(show_menu_task_factory_(this)) { 338 ALLOW_THIS_IN_INITIALIZER_LIST(show_menu_task_factory_(this)) {
337 SetID(VIEW_ID_BROWSER_ACTION_TOOLBAR); 339 SetID(VIEW_ID_BROWSER_ACTION_TOOLBAR);
338 340
339 ExtensionsService* extension_service = profile_->GetExtensionsService(); 341 ExtensionsService* extension_service = profile_->GetExtensionsService();
340 if (!extension_service) // The |extension_service| can be NULL in Incognito. 342 if (!extension_service) // The |extension_service| can be NULL in Incognito.
341 return; 343 return;
342 344
343 registrar_.Add(this, NotificationType::EXTENSION_HOST_VIEW_SHOULD_CLOSE,
344 Source<Profile>(profile_));
345
346 model_ = extension_service->toolbar_model(); 345 model_ = extension_service->toolbar_model();
347 model_->AddObserver(this); 346 model_->AddObserver(this);
348 347
349 resize_animation_.reset(new SlideAnimation(this)); 348 resize_animation_.reset(new SlideAnimation(this));
350 resize_gripper_ = new views::ResizeGripper(this); 349 resize_gripper_ = new views::ResizeGripper(this);
351 resize_gripper_->SetVisible(false); 350 resize_gripper_->SetVisible(false);
352 AddChildView(resize_gripper_); 351 AddChildView(resize_gripper_);
353 352
354 // TODO(glen): Come up with a new bitmap for the chevron. 353 // TODO(glen): Come up with a new bitmap for the chevron.
355 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 354 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
477 } 476 }
478 477
479 void BrowserActionsContainer::OnBrowserActionVisibilityChanged() { 478 void BrowserActionsContainer::OnBrowserActionVisibilityChanged() {
480 resize_gripper_->SetVisible(browser_action_views_.size() > 0); 479 resize_gripper_->SetVisible(browser_action_views_.size() > 0);
481 480
482 owner_view_->Layout(); 481 owner_view_->Layout();
483 owner_view_->SchedulePaint(); 482 owner_view_->SchedulePaint();
484 } 483 }
485 484
486 void BrowserActionsContainer::HidePopup() { 485 void BrowserActionsContainer::HidePopup() {
487 if (popup_) { 486 if (popup_)
488 // This sometimes gets called via a timer (See BubbleLostFocus), so clear 487 popup_->Close();
489 // the task factory in case one is pending.
490 task_factory_.RevokeAll();
491
492 // Save these variables in local temporaries since destroying the popup
493 // calls BubbleLostFocus to be called, which will try to call HidePopup()
494 // again if popup_ is non-null.
495 ExtensionPopup* closing_popup = popup_;
496 BrowserActionButton* closing_button = popup_button_;
497 popup_ = NULL;
498 popup_button_ = NULL;
499
500 closing_popup->DetachFromBrowser();
501 delete closing_popup;
502 closing_button->SetButtonNotPushed();
503 return;
504 }
505 } 488 }
506 489
507 void BrowserActionsContainer::TestExecuteBrowserAction(int index) { 490 void BrowserActionsContainer::TestExecuteBrowserAction(int index) {
508 BrowserActionButton* button = browser_action_views_[index]->button(); 491 BrowserActionButton* button = browser_action_views_[index]->button();
509 OnBrowserActionExecuted(button); 492 OnBrowserActionExecuted(button, false); // inspect_with_devtools
510 } 493 }
511 494
512 void BrowserActionsContainer::TestSetIconVisibilityCount(size_t icons) { 495 void BrowserActionsContainer::TestSetIconVisibilityCount(size_t icons) {
513 chevron_->SetVisible(icons < browser_action_views_.size()); 496 chevron_->SetVisible(icons < browser_action_views_.size());
514 container_size_.set_width(IconCountToWidth(icons)); 497 container_size_.set_width(IconCountToWidth(icons));
515 Layout(); 498 Layout();
516 SchedulePaint(); 499 SchedulePaint();
517 } 500 }
518 501
519 void BrowserActionsContainer::OnBrowserActionExecuted( 502 void BrowserActionsContainer::OnBrowserActionExecuted(
520 BrowserActionButton* button) { 503 BrowserActionButton* button, bool inspect_with_devtools) {
521 ExtensionAction* browser_action = button->browser_action(); 504 ExtensionAction* browser_action = button->browser_action();
522 505
523 // Popups just display. No notification to the extension. 506 // Popups just display. No notification to the extension.
524 // TODO(erikkay): should there be? 507 // TODO(erikkay): should there be?
525 if (button->IsPopup()) { 508 if (button->IsPopup()) {
526 // If we're showing the same popup, just hide it and return. 509 // If we're showing the same popup, just hide it and return.
527 bool same_showing = popup_ && button == popup_button_; 510 bool same_showing = popup_ && button == popup_button_;
528 511
529 // Always hide the current popup, even if it's not the same. 512 // Always hide the current popup, even if it's not the same.
530 // Only one popup should be visible at a time. 513 // Only one popup should be visible at a time.
(...skipping 10 matching lines...) Expand all
541 View::ConvertPointToScreen(reference_view, &origin); 524 View::ConvertPointToScreen(reference_view, &origin);
542 gfx::Rect rect = reference_view->bounds(); 525 gfx::Rect rect = reference_view->bounds();
543 rect.set_x(origin.x()); 526 rect.set_x(origin.x());
544 rect.set_y(origin.y()); 527 rect.set_y(origin.y());
545 528
546 gfx::NativeWindow frame_window = 529 gfx::NativeWindow frame_window =
547 browser_->window()->GetNativeHandle(); 530 browser_->window()->GetNativeHandle();
548 BubbleBorder::ArrowLocation arrow_location = UILayoutIsRightToLeft() ? 531 BubbleBorder::ArrowLocation arrow_location = UILayoutIsRightToLeft() ?
549 BubbleBorder::TOP_LEFT : BubbleBorder::TOP_RIGHT; 532 BubbleBorder::TOP_LEFT : BubbleBorder::TOP_RIGHT;
550 533
551 popup_ = ExtensionPopup::Show( 534 popup_ = ExtensionPopup::Show(button->GetPopupUrl(), browser_,
552 button->GetPopupUrl(), 535 browser_->profile(), frame_window, rect, arrow_location,
553 browser_,
554 browser_->profile(),
555 frame_window,
556 rect,
557 arrow_location,
558 true, // Activate the popup window. 536 true, // Activate the popup window.
559 ExtensionPopup::BUBBLE_CHROME); 537 inspect_with_devtools,
560 popup_->set_delegate(this); 538 ExtensionPopup::BUBBLE_CHROME,
539 this); // ExtensionPopupDelegate
561 popup_button_ = button; 540 popup_button_ = button;
562 popup_button_->SetButtonPushed(); 541 popup_button_->SetButtonPushed();
542
563 return; 543 return;
564 } 544 }
565 545
566 // Otherwise, we send the action to the extension. 546 // Otherwise, we send the action to the extension.
567 ExtensionBrowserEventRouter::GetInstance()->BrowserActionExecuted( 547 ExtensionBrowserEventRouter::GetInstance()->BrowserActionExecuted(
568 profile_, browser_action->extension_id(), browser_); 548 profile_, browser_action->extension_id(), browser_);
569 } 549 }
570 550
571 gfx::Size BrowserActionsContainer::GetPreferredSize() { 551 gfx::Size BrowserActionsContainer::GetPreferredSize() {
572 if (browser_action_views_.empty()) 552 if (browser_action_views_.empty())
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after
802 } 782 }
803 783
804 void BrowserActionsContainer::MoveBrowserAction( 784 void BrowserActionsContainer::MoveBrowserAction(
805 const std::string& extension_id, size_t new_index) { 785 const std::string& extension_id, size_t new_index) {
806 ExtensionsService* service = profile_->GetExtensionsService(); 786 ExtensionsService* service = profile_->GetExtensionsService();
807 Extension* extension = service->GetExtensionById(extension_id, false); 787 Extension* extension = service->GetExtensionById(extension_id, false);
808 model_->MoveBrowserAction(extension, new_index); 788 model_->MoveBrowserAction(extension, new_index);
809 SchedulePaint(); 789 SchedulePaint();
810 } 790 }
811 791
812 void BrowserActionsContainer::Observe(NotificationType type,
813 const NotificationSource& source,
814 const NotificationDetails& details) {
815 switch (type.value) {
816 case NotificationType::EXTENSION_HOST_VIEW_SHOULD_CLOSE:
817 // If we aren't the host of the popup, then disregard the notification.
818 if (!popup_ || Details<ExtensionHost>(popup_->host()) != details)
819 return;
820
821 HidePopup();
822 break;
823
824 default:
825 NOTREACHED() << "Unexpected notification";
826 }
827 }
828
829 void BrowserActionsContainer::BubbleBrowserWindowMoved(BrowserBubble* bubble) {
830 }
831
832 void BrowserActionsContainer::BubbleBrowserWindowClosing(
833 BrowserBubble* bubble) {
834 HidePopup();
835 }
836
837 void BrowserActionsContainer::BubbleGotFocus(BrowserBubble* bubble) {
838 if (!popup_)
839 return;
840
841 // Forward the focus to the renderer.
842 popup_->host()->render_view_host()->view()->Focus();
843 }
844
845 void BrowserActionsContainer::BubbleLostFocus(BrowserBubble* bubble,
846 bool lost_focus_to_child) {
847 // Don't close when we are losing focus to a child window, this is the case
848 // for select popups and alert for example.
849 if (!popup_ || lost_focus_to_child)
850 return;
851
852 // This is a bit annoying. If you click on the button that generated the
853 // current popup, then we first get this lost focus message, and then
854 // we get the click action. This results in the popup being immediately
855 // shown again. To workaround this, we put in a delay.
856 MessageLoop::current()->PostTask(FROM_HERE,
857 task_factory_.NewRunnableMethod(&BrowserActionsContainer::HidePopup));
858 }
859
860 void BrowserActionsContainer::RunMenu(View* source, const gfx::Point& pt) { 792 void BrowserActionsContainer::RunMenu(View* source, const gfx::Point& pt) {
861 if (source == chevron_) { 793 if (source == chevron_) {
862 overflow_menu_ = new BrowserActionOverflowMenuController( 794 overflow_menu_ = new BrowserActionOverflowMenuController(
863 this, chevron_, browser_action_views_, VisibleBrowserActions()); 795 this, chevron_, browser_action_views_, VisibleBrowserActions());
864 overflow_menu_->set_observer(this); 796 overflow_menu_->set_observer(this);
865 overflow_menu_->RunMenu(GetWindow()->GetNativeWindow(), false); 797 overflow_menu_->RunMenu(GetWindow()->GetNativeWindow(), false);
866 } 798 }
867 } 799 }
868 800
869 void BrowserActionsContainer::WriteDragData(View* sender, 801 void BrowserActionsContainer::WriteDragData(View* sender,
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
1135 profile_->GetPrefs()->SetInteger(prefs::kBrowserActionContainerWidth, 1067 profile_->GetPrefs()->SetInteger(prefs::kBrowserActionContainerWidth,
1136 container_size_.width()); 1068 container_size_.width());
1137 } 1069 }
1138 1070
1139 void BrowserActionsContainer::NotifyMenuDeleted( 1071 void BrowserActionsContainer::NotifyMenuDeleted(
1140 BrowserActionOverflowMenuController* controller) { 1072 BrowserActionOverflowMenuController* controller) {
1141 DCHECK(controller == overflow_menu_); 1073 DCHECK(controller == overflow_menu_);
1142 overflow_menu_ = NULL; 1074 overflow_menu_ = NULL;
1143 } 1075 }
1144 1076
1077 void BrowserActionsContainer::ShowPopupForDevToolsWindow(Extension* extension,
1078 ExtensionAction* extension_action) {
1079 OnBrowserActionExecuted(GetBrowserActionView(extension)->button(),
1080 true); // inspect_with_devtools
1081 }
1082
1083 void BrowserActionsContainer::ExtensionPopupClosed(ExtensionPopup* popup) {
1084 // ExtensionPopup is ref-counted, so we don't need to delete it.
1085 DCHECK_EQ(popup_, popup);
1086 popup_ = NULL;
1087 popup_button_->SetButtonNotPushed();
1088 popup_button_ = NULL;
1089 }
1090
1145 bool BrowserActionsContainer::ShouldDisplayBrowserAction(Extension* extension) { 1091 bool BrowserActionsContainer::ShouldDisplayBrowserAction(Extension* extension) {
1146 // Only display incognito-enabled extensions while in incognito mode. 1092 // Only display incognito-enabled extensions while in incognito mode.
1147 return (!profile_->IsOffTheRecord() || 1093 return (!profile_->IsOffTheRecord() ||
1148 profile_->GetExtensionsService()->IsIncognitoEnabled(extension)); 1094 profile_->GetExtensionsService()->IsIncognitoEnabled(extension));
1149 } 1095 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698