1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/ui/views/location_bar/page_action_image_view.h" 6 7 #include "base/strings/utf_string_conversions.h" 8 #include "chrome/browser/extensions/extension_action.h" 9 #include "chrome/browser/platform_util.h" 10 #include "chrome/browser/profiles/profile.h" 11 #include "chrome/browser/ui/browser.h" 12 #include "chrome/browser/ui/views/location_bar/location_bar_view.h" 13 #include "extensions/browser/extension_registry.h" 14 #include "ui/accessibility/ax_view_state.h" 15 #include "ui/events/event.h" 16 #include "ui/gfx/canvas.h" 17 #include "ui/gfx/image/image.h" 18 19 // static 20 const char PageActionImageView::kViewClassName[] = "PageActionImageView"; 21 22 PageActionImageView::PageActionImageView(LocationBarView* owner, 23 ExtensionAction* page_action, 24 Browser* browser) 25 : view_controller_(new ExtensionActionViewController( 26 extensions::ExtensionRegistry::Get(browser->profile())-> 27 enabled_extensions().GetByID(page_action->extension_id()), 28 browser, 29 page_action, 30 this)), 31 owner_(owner), 32 preview_enabled_(false) { 33 // There should be an associated focus manager so that we can safely register 34 // accelerators for commands. 35 DCHECK(GetFocusManagerForAccelerator()); 36 SetAccessibilityFocusable(true); 37 view_controller_->RegisterCommand(); 38 set_context_menu_controller(view_controller_.get()); 39 } 40 41 PageActionImageView::~PageActionImageView() { 42 } 43 44 const char* PageActionImageView::GetClassName() const { 45 return kViewClassName; 46 } 47 48 void PageActionImageView::GetAccessibleState(ui::AXViewState* state) { 49 state->role = ui::AX_ROLE_BUTTON; 50 state->name = base::UTF8ToUTF16(tooltip_); 51 } 52 53 bool PageActionImageView::OnMousePressed(const ui::MouseEvent& event) { 54 // We want to show the bubble on mouse release; that is the standard behavior 55 // for buttons. (Also, triggering on mouse press causes bugs like 56 // http://crbug.com/33155.) 57 return true; 58 } 59 60 void PageActionImageView::OnMouseReleased(const ui::MouseEvent& event) { 61 if (!HitTestPoint(event.location())) 62 return; 63 64 if (event.IsRightMouseButton()) { 65 // Don't show a menu here, its handled in View::ProcessMouseReleased. We 66 // show the context menu by way of being the ContextMenuController. 67 return; 68 } 69 70 view_controller_->ExecuteActionByUser(); 71 } 72 73 bool PageActionImageView::OnKeyPressed(const ui::KeyEvent& event) { 74 if (event.key_code() == ui::VKEY_SPACE || 75 event.key_code() == ui::VKEY_RETURN) { 76 view_controller_->ExecuteActionByUser(); 77 return true; 78 } 79 return false; 80 } 81 82 void PageActionImageView::OnGestureEvent(ui::GestureEvent* event) { 83 if (event->type() == ui::ET_GESTURE_TAP) { 84 view_controller_->ExecuteActionByUser(); 85 event->SetHandled(); 86 } 87 } 88 89 void PageActionImageView::UpdateVisibility(content::WebContents* contents) { 90 int tab_id = view_controller_->GetCurrentTabId(); 91 92 if (!contents || 93 tab_id == -1 || 94 (!preview_enabled_ && !extension_action()->GetIsVisible(tab_id))) { 95 SetVisible(false); 96 return; 97 } 98 99 // Set the tooltip. 100 tooltip_ = extension_action()->GetTitle(tab_id); 101 SetTooltipText(base::UTF8ToUTF16(tooltip_)); 102 103 // Set the image. 104 gfx::Image icon = view_controller_->GetIcon(tab_id); 105 if (!icon.IsEmpty()) 106 SetImage(*icon.ToImageSkia()); 107 108 SetVisible(true); 109 } 110 111 void PageActionImageView::PaintChildren(gfx::Canvas* canvas, 112 const views::CullSet& cull_set) { 113 View::PaintChildren(canvas, cull_set); 114 int tab_id = view_controller_->GetCurrentTabId(); 115 if (tab_id >= 0) { 116 view_controller_->extension_action()->PaintBadge( 117 canvas, GetLocalBounds(), tab_id); 118 } 119 } 120 121 void PageActionImageView::OnIconUpdated() { 122 UpdateVisibility(GetCurrentWebContents()); 123 } 124 125 views::View* PageActionImageView::GetAsView() { 126 return this; 127 } 128 129 bool PageActionImageView::IsShownInMenu() { 130 return false; 131 } 132 133 views::FocusManager* PageActionImageView::GetFocusManagerForAccelerator() { 134 return owner_->GetFocusManager(); 135 } 136 137 views::Widget* PageActionImageView::GetParentForContextMenu() { 138 return GetWidget(); 139 } 140 141 ExtensionActionViewController* 142 PageActionImageView::GetPreferredPopupViewController() { 143 return view_controller_.get(); 144 } 145 146 views::View* PageActionImageView::GetReferenceViewForPopup() { 147 return this; 148 } 149 150 views::MenuButton* PageActionImageView::GetContextMenuButton() { 151 return NULL; // No menu button for page action views. 152 } 153 154 content::WebContents* PageActionImageView::GetCurrentWebContents() { 155 return owner_->GetWebContents(); 156 } 157 158 void PageActionImageView::HideActivePopup() { 159 // The only popup that will be active is this popup. 160 view_controller_->HidePopup(); 161 } 162