15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/location_bar/page_action_image_view.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_action.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/platform_util.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "chrome/browser/ui/browser.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
13116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "extensions/browser/extension_registry.h"
14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/accessibility/ax_view_state.h"
15d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/events/event.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/canvas.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/image/image.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// static
205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const char PageActionImageView::kViewClassName[] = "PageActionImageView";
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PageActionImageView::PageActionImageView(LocationBarView* owner,
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         ExtensionAction* page_action,
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         Browser* browser)
255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    : view_controller_(new ExtensionActionViewController(
265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          extensions::ExtensionRegistry::Get(browser->profile())->
275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              enabled_extensions().GetByID(page_action->extension_id()),
285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          browser,
295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          page_action,
305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          this)),
315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      owner_(owner),
325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      preview_enabled_(false) {
335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // There should be an associated focus manager so that we can safely register
345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // accelerators for commands.
355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(GetFocusManagerForAccelerator());
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetAccessibilityFocusable(true);
375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  view_controller_->RegisterCommand();
385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  set_context_menu_controller(view_controller_.get());
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PageActionImageView::~PageActionImageView() {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const char* PageActionImageView::GetClassName() const {
455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return kViewClassName;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void PageActionImageView::GetAccessibleState(ui::AXViewState* state) {
49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  state->role = ui::AX_ROLE_BUTTON;
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  state->name = base::UTF8ToUTF16(tooltip_);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PageActionImageView::OnMousePressed(const ui::MouseEvent& event) {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We want to show the bubble on mouse release; that is the standard behavior
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for buttons.  (Also, triggering on mouse press causes bugs like
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // http://crbug.com/33155.)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PageActionImageView::OnMouseReleased(const ui::MouseEvent& event) {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!HitTestPoint(event.location()))
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (event.IsRightMouseButton()) {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Don't show a menu here, its handled in View::ProcessMouseReleased. We
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // show the context menu by way of being the ContextMenuController.
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  view_controller_->ExecuteActionByUser();
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PageActionImageView::OnKeyPressed(const ui::KeyEvent& event) {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (event.key_code() == ui::VKEY_SPACE ||
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      event.key_code() == ui::VKEY_RETURN) {
765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    view_controller_->ExecuteActionByUser();
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void PageActionImageView::OnGestureEvent(ui::GestureEvent* event) {
835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (event->type() == ui::ET_GESTURE_TAP) {
845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    view_controller_->ExecuteActionByUser();
855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    event->SetHandled();
865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void PageActionImageView::UpdateVisibility(content::WebContents* contents) {
905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  int tab_id = view_controller_->GetCurrentTabId();
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!contents ||
935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      tab_id == -1 ||
945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      (!preview_enabled_ && !extension_action()->GetIsVisible(tab_id))) {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetVisible(false);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set the tooltip.
1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  tooltip_ = extension_action()->GetTitle(tab_id);
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetTooltipText(base::UTF8ToUTF16(tooltip_));
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set the image.
1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  gfx::Image icon = view_controller_->GetIcon(tab_id);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!icon.IsEmpty())
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetImage(*icon.ToImageSkia());
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetVisible(true);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void PageActionImageView::PaintChildren(gfx::Canvas* canvas,
1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                        const views::CullSet& cull_set) {
1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  View::PaintChildren(canvas, cull_set);
1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  int tab_id = view_controller_->GetCurrentTabId();
1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (tab_id >= 0) {
1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    view_controller_->extension_action()->PaintBadge(
1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        canvas, GetLocalBounds(), tab_id);
1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PageActionImageView::OnIconUpdated() {
1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  UpdateVisibility(GetCurrentWebContents());
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)views::View* PageActionImageView::GetAsView() {
1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return this;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool PageActionImageView::IsShownInMenu() {
1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return false;
1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)views::FocusManager* PageActionImageView::GetFocusManagerForAccelerator() {
1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return owner_->GetFocusManager();
1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)views::Widget* PageActionImageView::GetParentForContextMenu() {
1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return GetWidget();
1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciExtensionActionViewController*
1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciPageActionImageView::GetPreferredPopupViewController() {
1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return view_controller_.get();
1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)views::View* PageActionImageView::GetReferenceViewForPopup() {
1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return this;
1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciviews::MenuButton* PageActionImageView::GetContextMenuButton() {
1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return NULL;  // No menu button for page action views.
1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)content::WebContents* PageActionImageView::GetCurrentWebContents() {
1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return owner_->GetWebContents();
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void PageActionImageView::HideActivePopup() {
1595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // The only popup that will be active is this popup.
1605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  view_controller_->HidePopup();
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
162