OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |