[Metrics] Make MetricsStateManager take a callback param to check if UMA is enabled.
[chromium-blink-merge.git] / chrome / browser / ui / views / location_bar / page_action_image_view.cc
blob6302fb4c9e5e6d1bbb6f7d44eb7b06cd559debee
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/api/commands/command_service.h"
9 #include "chrome/browser/extensions/extension_action.h"
10 #include "chrome/browser/extensions/extension_action_icon_factory.h"
11 #include "chrome/browser/extensions/extension_action_manager.h"
12 #include "chrome/browser/extensions/extension_context_menu_model.h"
13 #include "chrome/browser/extensions/extension_service.h"
14 #include "chrome/browser/extensions/extension_tab_util.h"
15 #include "chrome/browser/extensions/location_bar_controller.h"
16 #include "chrome/browser/extensions/tab_helper.h"
17 #include "chrome/browser/platform_util.h"
18 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/browser/sessions/session_id.h"
20 #include "chrome/browser/ui/browser_list.h"
21 #include "chrome/browser/ui/views/frame/browser_view.h"
22 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
23 #include "chrome/browser/ui/webui/extensions/extension_info_ui.h"
24 #include "extensions/common/extension.h"
25 #include "ui/accessibility/ax_view_state.h"
26 #include "ui/events/event.h"
27 #include "ui/gfx/canvas.h"
28 #include "ui/gfx/image/image.h"
29 #include "ui/views/controls/menu/menu_runner.h"
31 using content::WebContents;
32 using extensions::LocationBarController;
33 using extensions::Extension;
35 PageActionImageView::PageActionImageView(LocationBarView* owner,
36 ExtensionAction* page_action,
37 Browser* browser)
38 : owner_(owner),
39 page_action_(page_action),
40 browser_(browser),
41 current_tab_id_(-1),
42 preview_enabled_(false),
43 popup_(NULL) {
44 const Extension* extension = owner_->profile()->GetExtensionService()->
45 GetExtensionById(page_action->extension_id(), false);
46 DCHECK(extension);
48 icon_factory_.reset(
49 new ExtensionActionIconFactory(
50 owner_->profile(), extension, page_action, this));
52 SetAccessibilityFocusable(true);
53 set_context_menu_controller(this);
55 extensions::CommandService* command_service =
56 extensions::CommandService::Get(browser_->profile());
57 extensions::Command page_action_command;
58 if (command_service->GetPageActionCommand(
59 extension->id(),
60 extensions::CommandService::ACTIVE_ONLY,
61 &page_action_command,
62 NULL)) {
63 page_action_keybinding_.reset(
64 new ui::Accelerator(page_action_command.accelerator()));
65 owner_->GetFocusManager()->RegisterAccelerator(
66 *page_action_keybinding_.get(),
67 ui::AcceleratorManager::kHighPriority,
68 this);
72 PageActionImageView::~PageActionImageView() {
73 if (owner_->GetFocusManager()) {
74 if (page_action_keybinding_.get()) {
75 owner_->GetFocusManager()->UnregisterAccelerator(
76 *page_action_keybinding_.get(), this);
80 if (popup_)
81 popup_->GetWidget()->RemoveObserver(this);
82 HidePopup();
85 void PageActionImageView::ExecuteAction(
86 ExtensionPopup::ShowAction show_action) {
87 WebContents* web_contents = owner_->GetWebContents();
88 if (!web_contents)
89 return;
91 extensions::TabHelper* extensions_tab_helper =
92 extensions::TabHelper::FromWebContents(web_contents);
93 LocationBarController* controller =
94 extensions_tab_helper->location_bar_controller();
96 switch (controller->OnClicked(page_action_)) {
97 case LocationBarController::ACTION_NONE:
98 break;
100 case LocationBarController::ACTION_SHOW_POPUP:
101 ShowPopupWithURL(page_action_->GetPopupUrl(current_tab_id_), show_action);
102 break;
104 case LocationBarController::ACTION_SHOW_CONTEXT_MENU:
105 // We are never passing OnClicked a right-click button, so assume that
106 // we're never going to be asked to show a context menu.
107 // TODO(kalman): if this changes, update this class to pass the real
108 // mouse button through to the LocationBarController.
109 NOTREACHED();
110 break;
114 void PageActionImageView::GetAccessibleState(ui::AXViewState* state) {
115 state->role = ui::AX_ROLE_BUTTON;
116 state->name = base::UTF8ToUTF16(tooltip_);
119 bool PageActionImageView::OnMousePressed(const ui::MouseEvent& event) {
120 // We want to show the bubble on mouse release; that is the standard behavior
121 // for buttons. (Also, triggering on mouse press causes bugs like
122 // http://crbug.com/33155.)
123 return true;
126 void PageActionImageView::OnMouseReleased(const ui::MouseEvent& event) {
127 if (!HitTestPoint(event.location()))
128 return;
130 if (event.IsRightMouseButton()) {
131 // Don't show a menu here, its handled in View::ProcessMouseReleased. We
132 // show the context menu by way of being the ContextMenuController.
133 return;
136 ExecuteAction(ExtensionPopup::SHOW);
139 bool PageActionImageView::OnKeyPressed(const ui::KeyEvent& event) {
140 if (event.key_code() == ui::VKEY_SPACE ||
141 event.key_code() == ui::VKEY_RETURN) {
142 ExecuteAction(ExtensionPopup::SHOW);
143 return true;
145 return false;
148 void PageActionImageView::ShowContextMenuForView(
149 View* source,
150 const gfx::Point& point,
151 ui::MenuSourceType source_type) {
152 const Extension* extension = owner_->profile()->GetExtensionService()->
153 GetExtensionById(page_action()->extension_id(), false);
154 if (!extension->ShowConfigureContextMenus())
155 return;
157 scoped_refptr<ExtensionContextMenuModel> context_menu_model(
158 new ExtensionContextMenuModel(extension, browser_, this));
159 menu_runner_.reset(new views::MenuRunner(context_menu_model.get()));
160 gfx::Point screen_loc;
161 views::View::ConvertPointToScreen(this, &screen_loc);
162 if (menu_runner_->RunMenuAt(
163 GetWidget(),
164 NULL,
165 gfx::Rect(screen_loc, size()),
166 views::MENU_ANCHOR_TOPLEFT,
167 source_type,
168 views::MenuRunner::HAS_MNEMONICS | views::MenuRunner::CONTEXT_MENU) ==
169 views::MenuRunner::MENU_DELETED) {
170 return;
174 bool PageActionImageView::AcceleratorPressed(
175 const ui::Accelerator& accelerator) {
176 DCHECK(visible()); // Should not have happened due to CanHandleAccelerator.
178 ExecuteAction(ExtensionPopup::SHOW);
179 return true;
182 bool PageActionImageView::CanHandleAccelerators() const {
183 // While visible, we don't handle accelerators and while so we also don't
184 // count as a priority accelerator handler.
185 return visible();
188 void PageActionImageView::UpdateVisibility(WebContents* contents,
189 const GURL& url) {
190 // Save this off so we can pass it back to the extension when the action gets
191 // executed. See PageActionImageView::OnMousePressed.
192 current_tab_id_ =
193 contents ? extensions::ExtensionTabUtil::GetTabId(contents) : -1;
194 current_url_ = url;
196 if (!contents ||
197 (!preview_enabled_ && !page_action_->GetIsVisible(current_tab_id_))) {
198 SetVisible(false);
199 return;
202 // Set the tooltip.
203 tooltip_ = page_action_->GetTitle(current_tab_id_);
204 SetTooltipText(base::UTF8ToUTF16(tooltip_));
206 // Set the image.
207 gfx::Image icon = icon_factory_->GetIcon(current_tab_id_);
208 if (!icon.IsEmpty())
209 SetImage(*icon.ToImageSkia());
211 SetVisible(true);
214 void PageActionImageView::InspectPopup(ExtensionAction* action) {
215 ExecuteAction(ExtensionPopup::SHOW_AND_INSPECT);
218 void PageActionImageView::OnWidgetDestroying(views::Widget* widget) {
219 DCHECK_EQ(popup_->GetWidget(), widget);
220 popup_->GetWidget()->RemoveObserver(this);
221 popup_ = NULL;
224 void PageActionImageView::OnIconUpdated() {
225 WebContents* web_contents = owner_->GetWebContents();
226 if (web_contents)
227 UpdateVisibility(web_contents, current_url_);
230 void PageActionImageView::PaintChildren(gfx::Canvas* canvas,
231 const views::CullSet& cull_set) {
232 View::PaintChildren(canvas, cull_set);
233 if (current_tab_id_ >= 0)
234 page_action_->PaintBadge(canvas, GetLocalBounds(), current_tab_id_);
237 void PageActionImageView::ShowPopupWithURL(
238 const GURL& popup_url,
239 ExtensionPopup::ShowAction show_action) {
240 bool popup_showing = popup_ != NULL;
242 // Always hide the current popup. Only one popup at a time.
243 HidePopup();
245 // If we were already showing, then treat this click as a dismiss.
246 if (popup_showing)
247 return;
249 views::BubbleBorder::Arrow arrow = base::i18n::IsRTL() ?
250 views::BubbleBorder::TOP_LEFT : views::BubbleBorder::TOP_RIGHT;
252 popup_ = ExtensionPopup::ShowPopup(popup_url, browser_, this, arrow,
253 show_action);
254 popup_->GetWidget()->AddObserver(this);
257 void PageActionImageView::HidePopup() {
258 if (popup_)
259 popup_->GetWidget()->Close();