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
20const char PageActionImageView::kViewClassName[] = "PageActionImageView";
21
22PageActionImageView::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
41PageActionImageView::~PageActionImageView() {
42}
43
44const char* PageActionImageView::GetClassName() const {
45  return kViewClassName;
46}
47
48void PageActionImageView::GetAccessibleState(ui::AXViewState* state) {
49  state->role = ui::AX_ROLE_BUTTON;
50  state->name = base::UTF8ToUTF16(tooltip_);
51}
52
53bool 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
60void 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
73bool 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
82void PageActionImageView::OnGestureEvent(ui::GestureEvent* event) {
83  if (event->type() == ui::ET_GESTURE_TAP) {
84    view_controller_->ExecuteActionByUser();
85    event->SetHandled();
86  }
87}
88
89void 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
111void 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
121void PageActionImageView::OnIconUpdated() {
122  UpdateVisibility(GetCurrentWebContents());
123}
124
125views::View* PageActionImageView::GetAsView() {
126  return this;
127}
128
129bool PageActionImageView::IsShownInMenu() {
130  return false;
131}
132
133views::FocusManager* PageActionImageView::GetFocusManagerForAccelerator() {
134  return owner_->GetFocusManager();
135}
136
137views::Widget* PageActionImageView::GetParentForContextMenu() {
138  return GetWidget();
139}
140
141ExtensionActionViewController*
142PageActionImageView::GetPreferredPopupViewController() {
143  return view_controller_.get();
144}
145
146views::View* PageActionImageView::GetReferenceViewForPopup() {
147  return this;
148}
149
150views::MenuButton* PageActionImageView::GetContextMenuButton() {
151  return NULL;  // No menu button for page action views.
152}
153
154content::WebContents* PageActionImageView::GetCurrentWebContents() {
155  return owner_->GetWebContents();
156}
157
158void PageActionImageView::HideActivePopup() {
159  // The only popup that will be active is this popup.
160  view_controller_->HidePopup();
161}
162