Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / ui / views / location_bar / page_action_image_view.cc
blob96fb5e8a7602caf75e580dad52cbeff26c743629
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 scoped_icon_animation_observer_(
46 page_action->GetIconAnimation(
47 SessionID::IdForTab(owner->GetWebContents())),
48 this) {
49 const Extension* extension = owner_->profile()->GetExtensionService()->
50 GetExtensionById(page_action->extension_id(), false);
51 DCHECK(extension);
53 icon_factory_.reset(
54 new ExtensionActionIconFactory(
55 owner_->profile(), extension, page_action, this));
57 SetAccessibilityFocusable(true);
58 set_context_menu_controller(this);
60 extensions::CommandService* command_service =
61 extensions::CommandService::Get(browser_->profile());
62 extensions::Command page_action_command;
63 if (command_service->GetPageActionCommand(
64 extension->id(),
65 extensions::CommandService::ACTIVE_ONLY,
66 &page_action_command,
67 NULL)) {
68 page_action_keybinding_.reset(
69 new ui::Accelerator(page_action_command.accelerator()));
70 owner_->GetFocusManager()->RegisterAccelerator(
71 *page_action_keybinding_.get(),
72 ui::AcceleratorManager::kHighPriority,
73 this);
76 extensions::Command script_badge_command;
77 if (command_service->GetScriptBadgeCommand(
78 extension->id(),
79 extensions::CommandService::ACTIVE_ONLY,
80 &script_badge_command,
81 NULL)) {
82 script_badge_keybinding_.reset(
83 new ui::Accelerator(script_badge_command.accelerator()));
84 owner_->GetFocusManager()->RegisterAccelerator(
85 *script_badge_keybinding_.get(),
86 ui::AcceleratorManager::kHighPriority,
87 this);
91 PageActionImageView::~PageActionImageView() {
92 if (owner_->GetFocusManager()) {
93 if (page_action_keybinding_.get()) {
94 owner_->GetFocusManager()->UnregisterAccelerator(
95 *page_action_keybinding_.get(), this);
98 if (script_badge_keybinding_.get()) {
99 owner_->GetFocusManager()->UnregisterAccelerator(
100 *script_badge_keybinding_.get(), this);
104 if (popup_)
105 popup_->GetWidget()->RemoveObserver(this);
106 HidePopup();
109 void PageActionImageView::ExecuteAction(
110 ExtensionPopup::ShowAction show_action) {
111 WebContents* web_contents = owner_->GetWebContents();
112 if (!web_contents)
113 return;
115 extensions::TabHelper* extensions_tab_helper =
116 extensions::TabHelper::FromWebContents(web_contents);
117 LocationBarController* controller =
118 extensions_tab_helper->location_bar_controller();
120 switch (controller->OnClicked(page_action_->extension_id(), 1)) {
121 case LocationBarController::ACTION_NONE:
122 break;
124 case LocationBarController::ACTION_SHOW_POPUP:
125 ShowPopupWithURL(page_action_->GetPopupUrl(current_tab_id_), show_action);
126 break;
128 case LocationBarController::ACTION_SHOW_CONTEXT_MENU:
129 // We are never passing OnClicked a right-click button, so assume that
130 // we're never going to be asked to show a context menu.
131 // TODO(kalman): if this changes, update this class to pass the real
132 // mouse button through to the LocationBarController.
133 NOTREACHED();
134 break;
136 case LocationBarController::ACTION_SHOW_SCRIPT_POPUP:
137 ShowPopupWithURL(
138 extensions::ExtensionInfoUI::GetURL(page_action_->extension_id()),
139 show_action);
140 break;
144 void PageActionImageView::GetAccessibleState(ui::AccessibleViewState* state) {
145 state->role = ui::AccessibilityTypes::ROLE_PUSHBUTTON;
146 state->name = base::UTF8ToUTF16(tooltip_);
149 bool PageActionImageView::OnMousePressed(const ui::MouseEvent& event) {
150 // We want to show the bubble on mouse release; that is the standard behavior
151 // for buttons. (Also, triggering on mouse press causes bugs like
152 // http://crbug.com/33155.)
153 return true;
156 void PageActionImageView::OnMouseReleased(const ui::MouseEvent& event) {
157 if (!HitTestPoint(event.location()))
158 return;
160 if (event.IsRightMouseButton()) {
161 // Don't show a menu here, its handled in View::ProcessMouseReleased. We
162 // show the context menu by way of being the ContextMenuController.
163 return;
166 ExecuteAction(ExtensionPopup::SHOW);
169 bool PageActionImageView::OnKeyPressed(const ui::KeyEvent& event) {
170 if (event.key_code() == ui::VKEY_SPACE ||
171 event.key_code() == ui::VKEY_RETURN) {
172 ExecuteAction(ExtensionPopup::SHOW);
173 return true;
175 return false;
178 void PageActionImageView::ShowContextMenuForView(
179 View* source,
180 const gfx::Point& point,
181 ui::MenuSourceType source_type) {
182 const Extension* extension = owner_->profile()->GetExtensionService()->
183 GetExtensionById(page_action()->extension_id(), false);
184 if (!extension->ShowConfigureContextMenus())
185 return;
187 scoped_refptr<ExtensionContextMenuModel> context_menu_model(
188 new ExtensionContextMenuModel(extension, browser_, this));
189 menu_runner_.reset(new views::MenuRunner(context_menu_model.get()));
190 gfx::Point screen_loc;
191 views::View::ConvertPointToScreen(this, &screen_loc);
192 if (menu_runner_->RunMenuAt(GetWidget(), NULL, gfx::Rect(screen_loc, size()),
193 views::MenuItemView::TOPLEFT, source_type,
194 views::MenuRunner::HAS_MNEMONICS | views::MenuRunner::CONTEXT_MENU) ==
195 views::MenuRunner::MENU_DELETED)
196 return;
199 bool PageActionImageView::AcceleratorPressed(
200 const ui::Accelerator& accelerator) {
201 DCHECK(visible()); // Should not have happened due to CanHandleAccelerator.
203 ExecuteAction(ExtensionPopup::SHOW);
204 return true;
207 bool PageActionImageView::CanHandleAccelerators() const {
208 // While visible, we don't handle accelerators and while so we also don't
209 // count as a priority accelerator handler.
210 return visible();
213 void PageActionImageView::UpdateVisibility(WebContents* contents,
214 const GURL& url) {
215 // Save this off so we can pass it back to the extension when the action gets
216 // executed. See PageActionImageView::OnMousePressed.
217 current_tab_id_ =
218 contents ? extensions::ExtensionTabUtil::GetTabId(contents) : -1;
219 current_url_ = url;
221 if (!contents ||
222 (!preview_enabled_ && !page_action_->GetIsVisible(current_tab_id_))) {
223 SetVisible(false);
224 return;
227 // Set the tooltip.
228 tooltip_ = page_action_->GetTitle(current_tab_id_);
229 SetTooltipText(base::UTF8ToUTF16(tooltip_));
231 // Set the image.
232 gfx::Image icon = icon_factory_->GetIcon(current_tab_id_);
233 if (!icon.IsEmpty())
234 SetImage(*icon.ToImageSkia());
236 SetVisible(true);
239 void PageActionImageView::InspectPopup(ExtensionAction* action) {
240 ExecuteAction(ExtensionPopup::SHOW_AND_INSPECT);
243 void PageActionImageView::OnWidgetDestroying(views::Widget* widget) {
244 DCHECK_EQ(popup_->GetWidget(), widget);
245 popup_->GetWidget()->RemoveObserver(this);
246 popup_ = NULL;
249 void PageActionImageView::OnIconUpdated() {
250 WebContents* web_contents = owner_->GetWebContents();
251 if (web_contents)
252 UpdateVisibility(web_contents, current_url_);
255 void PageActionImageView::OnIconChanged() {
256 OnIconUpdated();
259 void PageActionImageView::PaintChildren(gfx::Canvas* canvas) {
260 View::PaintChildren(canvas);
261 if (current_tab_id_ >= 0)
262 page_action_->PaintBadge(canvas, GetLocalBounds(), current_tab_id_);
265 void PageActionImageView::ShowPopupWithURL(
266 const GURL& popup_url,
267 ExtensionPopup::ShowAction show_action) {
268 bool popup_showing = popup_ != NULL;
270 // Always hide the current popup. Only one popup at a time.
271 HidePopup();
273 // If we were already showing, then treat this click as a dismiss.
274 if (popup_showing)
275 return;
277 views::BubbleBorder::Arrow arrow = base::i18n::IsRTL() ?
278 views::BubbleBorder::TOP_LEFT : views::BubbleBorder::TOP_RIGHT;
280 popup_ = ExtensionPopup::ShowPopup(popup_url, browser_, this, arrow,
281 show_action);
282 popup_->GetWidget()->AddObserver(this);
285 void PageActionImageView::HidePopup() {
286 if (popup_)
287 popup_->GetWidget()->Close();