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.
5 #include "chrome/browser/ui/views/location_bar/page_action_image_view.h"
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/sessions/session_tab_helper.h"
12 #include "chrome/browser/ui/browser.h"
13 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
14 #include "extensions/browser/extension_registry.h"
15 #include "extensions/common/constants.h"
16 #include "ui/accessibility/ax_view_state.h"
17 #include "ui/compositor/paint_recorder.h"
18 #include "ui/events/event.h"
19 #include "ui/gfx/canvas.h"
20 #include "ui/gfx/image/image.h"
21 #include "ui/views/controls/menu/menu_runner.h"
24 const char PageActionImageView::kViewClassName
[] = "PageActionImageView";
26 PageActionImageView::PageActionImageView(LocationBarView
* owner
,
27 ExtensionAction
* page_action
,
29 : view_controller_(new ExtensionActionViewController(
30 extensions::ExtensionRegistry::Get(browser
->profile())->
31 enabled_extensions().GetByID(page_action
->extension_id()),
36 preview_enabled_(false) {
37 // There should be an associated focus manager so that we can safely register
38 // accelerators for commands.
39 DCHECK(GetFocusManagerForAccelerator());
40 SetAccessibilityFocusable(true);
41 view_controller_
->SetDelegate(this);
42 view_controller_
->RegisterCommand();
43 set_context_menu_controller(this);
46 PageActionImageView::~PageActionImageView() {
49 const char* PageActionImageView::GetClassName() const {
50 return kViewClassName
;
53 void PageActionImageView::GetAccessibleState(ui::AXViewState
* state
) {
54 state
->role
= ui::AX_ROLE_BUTTON
;
55 state
->name
= base::UTF8ToUTF16(tooltip_
);
58 bool PageActionImageView::OnMousePressed(const ui::MouseEvent
& event
) {
59 // We want to show the bubble on mouse release; that is the standard behavior
60 // for buttons. (Also, triggering on mouse press causes bugs like
61 // http://crbug.com/33155.)
65 void PageActionImageView::OnMouseReleased(const ui::MouseEvent
& event
) {
66 if (!HitTestPoint(event
.location()))
69 if (event
.IsRightMouseButton()) {
70 // Don't show a menu here, its handled in View::ProcessMouseReleased. We
71 // show the context menu by way of being the ContextMenuController.
75 view_controller_
->ExecuteAction(true);
78 bool PageActionImageView::OnKeyPressed(const ui::KeyEvent
& event
) {
79 if (event
.key_code() == ui::VKEY_SPACE
||
80 event
.key_code() == ui::VKEY_RETURN
) {
81 view_controller_
->ExecuteAction(true);
87 void PageActionImageView::OnGestureEvent(ui::GestureEvent
* event
) {
88 if (event
->type() == ui::ET_GESTURE_TAP
) {
89 view_controller_
->ExecuteAction(true);
94 void PageActionImageView::UpdateVisibility(content::WebContents
* contents
) {
95 int tab_id
= SessionTabHelper::IdForTab(contents
);
98 (!preview_enabled_
&& !extension_action()->GetIsVisible(tab_id
))) {
104 tooltip_
= extension_action()->GetTitle(tab_id
);
105 SetTooltipText(base::UTF8ToUTF16(tooltip_
));
108 gfx::Size
size(extension_misc::EXTENSION_ICON_ACTION
,
109 extension_misc::EXTENSION_ICON_ACTION
);
110 gfx::Image icon
= view_controller_
->GetIcon(contents
, size
);
112 SetImage(*icon
.ToImageSkia());
117 void PageActionImageView::UpdateState() {
118 UpdateVisibility(GetCurrentWebContents());
121 views::View
* PageActionImageView::GetAsView() {
125 bool PageActionImageView::IsMenuRunning() const {
126 return menu_runner_
.get() != nullptr;
129 views::FocusManager
* PageActionImageView::GetFocusManagerForAccelerator() {
130 return owner_
->GetFocusManager();
133 views::View
* PageActionImageView::GetReferenceViewForPopup() {
137 content::WebContents
* PageActionImageView::GetCurrentWebContents() const {
138 return owner_
->GetWebContents();
141 void PageActionImageView::ShowContextMenuForView(
143 const gfx::Point
& point
,
144 ui::MenuSourceType source_type
) {
145 ui::MenuModel
* context_menu_model
= view_controller_
->GetContextMenu();
146 // It's possible the action doesn't have a context menu.
147 if (!context_menu_model
)
150 gfx::Point screen_loc
;
151 ConvertPointToScreen(this, &screen_loc
);
153 views::MenuRunner::HAS_MNEMONICS
| views::MenuRunner::CONTEXT_MENU
;
154 menu_runner_
.reset(new views::MenuRunner(context_menu_model
, run_types
));
156 if (menu_runner_
->RunMenuAt(GetWidget(),
157 nullptr, // No menu button for page action views.
158 gfx::Rect(screen_loc
, size()),
159 views::MENU_ANCHOR_TOPLEFT
,
160 source_type
) == views::MenuRunner::MENU_DELETED
) {
164 menu_runner_
.reset();
165 view_controller_
->OnContextMenuClosed();