NaCl: Update revision in DEPS, r12770 -> r12773
[chromium-blink-merge.git] / chrome / browser / ui / views / location_bar / page_action_image_view.cc
blob433cd438eabdc0d1fe11bcfaaf36641444a67b39
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/base/accessibility/accessible_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_item_view.h"
30 #include "ui/views/controls/menu/menu_runner.h"
32 using content::WebContents;
33 using extensions::LocationBarController;
34 using extensions::Extension;
36 PageActionImageView::PageActionImageView(LocationBarView* owner,
37 ExtensionAction* page_action,
38 Browser* browser)
39 : owner_(owner),
40 page_action_(page_action),
41 browser_(browser),
42 current_tab_id_(-1),
43 preview_enabled_(false),
44 popup_(NULL) {
45 const Extension* extension = owner_->profile()->GetExtensionService()->
46 GetExtensionById(page_action->extension_id(), false);
47 DCHECK(extension);
49 icon_factory_.reset(
50 new ExtensionActionIconFactory(
51 owner_->profile(), extension, page_action, this));
53 SetAccessibilityFocusable(true);
54 set_context_menu_controller(this);
56 extensions::CommandService* command_service =
57 extensions::CommandService::Get(browser_->profile());
58 extensions::Command page_action_command;
59 if (command_service->GetPageActionCommand(
60 extension->id(),
61 extensions::CommandService::ACTIVE_ONLY,
62 &page_action_command,
63 NULL)) {
64 page_action_keybinding_.reset(
65 new ui::Accelerator(page_action_command.accelerator()));
66 owner_->GetFocusManager()->RegisterAccelerator(
67 *page_action_keybinding_.get(),
68 ui::AcceleratorManager::kHighPriority,
69 this);
73 PageActionImageView::~PageActionImageView() {
74 if (owner_->GetFocusManager()) {
75 if (page_action_keybinding_.get()) {
76 owner_->GetFocusManager()->UnregisterAccelerator(
77 *page_action_keybinding_.get(), this);
81 if (popup_)
82 popup_->GetWidget()->RemoveObserver(this);
83 HidePopup();
86 void PageActionImageView::ExecuteAction(
87 ExtensionPopup::ShowAction show_action) {
88 WebContents* web_contents = owner_->GetWebContents();
89 if (!web_contents)
90 return;
92 extensions::TabHelper* extensions_tab_helper =
93 extensions::TabHelper::FromWebContents(web_contents);
94 LocationBarController* controller =
95 extensions_tab_helper->location_bar_controller();
97 switch (controller->OnClicked(page_action_->extension_id(), 1)) {
98 case LocationBarController::ACTION_NONE:
99 break;
101 case LocationBarController::ACTION_SHOW_POPUP:
102 ShowPopupWithURL(page_action_->GetPopupUrl(current_tab_id_), show_action);
103 break;
105 case LocationBarController::ACTION_SHOW_CONTEXT_MENU:
106 // We are never passing OnClicked a right-click button, so assume that
107 // we're never going to be asked to show a context menu.
108 // TODO(kalman): if this changes, update this class to pass the real
109 // mouse button through to the LocationBarController.
110 NOTREACHED();
111 break;
115 void PageActionImageView::GetAccessibleState(ui::AccessibleViewState* state) {
116 state->role = ui::AccessibilityTypes::ROLE_PUSHBUTTON;
117 state->name = base::UTF8ToUTF16(tooltip_);
120 bool PageActionImageView::OnMousePressed(const ui::MouseEvent& event) {
121 // We want to show the bubble on mouse release; that is the standard behavior
122 // for buttons. (Also, triggering on mouse press causes bugs like
123 // http://crbug.com/33155.)
124 return true;
127 void PageActionImageView::OnMouseReleased(const ui::MouseEvent& event) {
128 if (!HitTestPoint(event.location()))
129 return;
131 if (event.IsRightMouseButton()) {
132 // Don't show a menu here, its handled in View::ProcessMouseReleased. We
133 // show the context menu by way of being the ContextMenuController.
134 return;
137 ExecuteAction(ExtensionPopup::SHOW);
140 bool PageActionImageView::OnKeyPressed(const ui::KeyEvent& event) {
141 if (event.key_code() == ui::VKEY_SPACE ||
142 event.key_code() == ui::VKEY_RETURN) {
143 ExecuteAction(ExtensionPopup::SHOW);
144 return true;
146 return false;
149 void PageActionImageView::ShowContextMenuForView(
150 View* source,
151 const gfx::Point& point,
152 ui::MenuSourceType source_type) {
153 const Extension* extension = owner_->profile()->GetExtensionService()->
154 GetExtensionById(page_action()->extension_id(), false);
155 if (!extension->ShowConfigureContextMenus())
156 return;
158 scoped_refptr<ExtensionContextMenuModel> context_menu_model(
159 new ExtensionContextMenuModel(extension, browser_, this));
160 menu_runner_.reset(new views::MenuRunner(context_menu_model.get()));
161 gfx::Point screen_loc;
162 views::View::ConvertPointToScreen(this, &screen_loc);
163 if (menu_runner_->RunMenuAt(GetWidget(), NULL, gfx::Rect(screen_loc, size()),
164 views::MenuItemView::TOPLEFT, source_type,
165 views::MenuRunner::HAS_MNEMONICS | views::MenuRunner::CONTEXT_MENU) ==
166 views::MenuRunner::MENU_DELETED)
167 return;
170 bool PageActionImageView::AcceleratorPressed(
171 const ui::Accelerator& accelerator) {
172 DCHECK(visible()); // Should not have happened due to CanHandleAccelerator.
174 ExecuteAction(ExtensionPopup::SHOW);
175 return true;
178 bool PageActionImageView::CanHandleAccelerators() const {
179 // While visible, we don't handle accelerators and while so we also don't
180 // count as a priority accelerator handler.
181 return visible();
184 void PageActionImageView::UpdateVisibility(WebContents* contents,
185 const GURL& url) {
186 // Save this off so we can pass it back to the extension when the action gets
187 // executed. See PageActionImageView::OnMousePressed.
188 current_tab_id_ =
189 contents ? extensions::ExtensionTabUtil::GetTabId(contents) : -1;
190 current_url_ = url;
192 if (!contents ||
193 (!preview_enabled_ && !page_action_->GetIsVisible(current_tab_id_))) {
194 SetVisible(false);
195 return;
198 // Set the tooltip.
199 tooltip_ = page_action_->GetTitle(current_tab_id_);
200 SetTooltipText(base::UTF8ToUTF16(tooltip_));
202 // Set the image.
203 gfx::Image icon = icon_factory_->GetIcon(current_tab_id_);
204 if (!icon.IsEmpty())
205 SetImage(*icon.ToImageSkia());
207 SetVisible(true);
210 void PageActionImageView::InspectPopup(ExtensionAction* action) {
211 ExecuteAction(ExtensionPopup::SHOW_AND_INSPECT);
214 void PageActionImageView::OnWidgetDestroying(views::Widget* widget) {
215 DCHECK_EQ(popup_->GetWidget(), widget);
216 popup_->GetWidget()->RemoveObserver(this);
217 popup_ = NULL;
220 void PageActionImageView::OnIconUpdated() {
221 WebContents* web_contents = owner_->GetWebContents();
222 if (web_contents)
223 UpdateVisibility(web_contents, current_url_);
226 void PageActionImageView::PaintChildren(gfx::Canvas* canvas) {
227 View::PaintChildren(canvas);
228 if (current_tab_id_ >= 0)
229 page_action_->PaintBadge(canvas, GetLocalBounds(), current_tab_id_);
232 void PageActionImageView::ShowPopupWithURL(
233 const GURL& popup_url,
234 ExtensionPopup::ShowAction show_action) {
235 bool popup_showing = popup_ != NULL;
237 // Always hide the current popup. Only one popup at a time.
238 HidePopup();
240 // If we were already showing, then treat this click as a dismiss.
241 if (popup_showing)
242 return;
244 views::BubbleBorder::Arrow arrow = base::i18n::IsRTL() ?
245 views::BubbleBorder::TOP_LEFT : views::BubbleBorder::TOP_RIGHT;
247 popup_ = ExtensionPopup::ShowPopup(popup_url, browser_, this, arrow,
248 show_action);
249 popup_->GetWidget()->AddObserver(this);
252 void PageActionImageView::HidePopup() {
253 if (popup_)
254 popup_->GetWidget()->Close();