// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/ui/views/location_bar/page_action_image_view.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/extensions/extension_action.h" #include "chrome/browser/platform_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sessions/session_tab_helper.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/views/location_bar/location_bar_view.h" #include "extensions/browser/extension_registry.h" #include "extensions/common/constants.h" #include "ui/accessibility/ax_view_state.h" #include "ui/compositor/paint_recorder.h" #include "ui/events/event.h" #include "ui/gfx/canvas.h" #include "ui/gfx/image/image.h" #include "ui/views/controls/menu/menu_runner.h" // static const char PageActionImageView::kViewClassName[] = "PageActionImageView"; PageActionImageView::PageActionImageView(LocationBarView* owner, ExtensionAction* page_action, Browser* browser) : view_controller_(new ExtensionActionViewController( extensions::ExtensionRegistry::Get(browser->profile())-> enabled_extensions().GetByID(page_action->extension_id()), browser, page_action, nullptr)), owner_(owner), preview_enabled_(false) { // There should be an associated focus manager so that we can safely register // accelerators for commands. DCHECK(GetFocusManagerForAccelerator()); SetAccessibilityFocusable(true); view_controller_->SetDelegate(this); view_controller_->RegisterCommand(); set_context_menu_controller(this); } PageActionImageView::~PageActionImageView() { } const char* PageActionImageView::GetClassName() const { return kViewClassName; } void PageActionImageView::GetAccessibleState(ui::AXViewState* state) { state->role = ui::AX_ROLE_BUTTON; state->name = base::UTF8ToUTF16(tooltip_); } bool PageActionImageView::OnMousePressed(const ui::MouseEvent& event) { // We want to show the bubble on mouse release; that is the standard behavior // for buttons. (Also, triggering on mouse press causes bugs like // http://crbug.com/33155.) return true; } void PageActionImageView::OnMouseReleased(const ui::MouseEvent& event) { if (!HitTestPoint(event.location())) return; if (event.IsRightMouseButton()) { // Don't show a menu here, its handled in View::ProcessMouseReleased. We // show the context menu by way of being the ContextMenuController. return; } view_controller_->ExecuteAction(true); } bool PageActionImageView::OnKeyPressed(const ui::KeyEvent& event) { if (event.key_code() == ui::VKEY_SPACE || event.key_code() == ui::VKEY_RETURN) { view_controller_->ExecuteAction(true); return true; } return false; } void PageActionImageView::OnGestureEvent(ui::GestureEvent* event) { if (event->type() == ui::ET_GESTURE_TAP) { view_controller_->ExecuteAction(true); event->SetHandled(); } } void PageActionImageView::UpdateVisibility(content::WebContents* contents) { int tab_id = SessionTabHelper::IdForTab(contents); if (!contents || tab_id == -1 || (!preview_enabled_ && !extension_action()->GetIsVisible(tab_id))) { SetVisible(false); return; } // Set the tooltip. tooltip_ = extension_action()->GetTitle(tab_id); SetTooltipText(base::UTF8ToUTF16(tooltip_)); // Set the image. gfx::Size size(extension_misc::EXTENSION_ICON_ACTION, extension_misc::EXTENSION_ICON_ACTION); gfx::Image icon = view_controller_->GetIcon(contents, size); if (!icon.IsEmpty()) SetImage(*icon.ToImageSkia()); SetVisible(true); } void PageActionImageView::UpdateState() { UpdateVisibility(GetCurrentWebContents()); } views::View* PageActionImageView::GetAsView() { return this; } bool PageActionImageView::IsMenuRunning() const { return menu_runner_.get() != nullptr; } views::FocusManager* PageActionImageView::GetFocusManagerForAccelerator() { return owner_->GetFocusManager(); } views::View* PageActionImageView::GetReferenceViewForPopup() { return this; } content::WebContents* PageActionImageView::GetCurrentWebContents() const { return owner_->GetWebContents(); } void PageActionImageView::ShowContextMenuForView( views::View* source, const gfx::Point& point, ui::MenuSourceType source_type) { ui::MenuModel* context_menu_model = view_controller_->GetContextMenu(); // It's possible the action doesn't have a context menu. if (!context_menu_model) return; gfx::Point screen_loc; ConvertPointToScreen(this, &screen_loc); int run_types = views::MenuRunner::HAS_MNEMONICS | views::MenuRunner::CONTEXT_MENU; menu_runner_.reset(new views::MenuRunner(context_menu_model, run_types)); if (menu_runner_->RunMenuAt(GetWidget(), nullptr, // No menu button for page action views. gfx::Rect(screen_loc, size()), views::MENU_ANCHOR_TOPLEFT, source_type) == views::MenuRunner::MENU_DELETED) { return; } menu_runner_.reset(); view_controller_->OnContextMenuClosed(); }