Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(99)

Unified Diff: chrome/browser/ui/views/extensions/extension_action_view_controller.cc

Issue 670463004: Make a platform-independent ToolbarActionViewController (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/views/extensions/extension_action_view_controller.cc
diff --git a/chrome/browser/ui/views/extensions/extension_action_view_controller.cc b/chrome/browser/ui/views/extensions/extension_action_view_controller.cc
deleted file mode 100644
index cd0410e9b83b5e3171c5b4fbe5506252113567ff..0000000000000000000000000000000000000000
--- a/chrome/browser/ui/views/extensions/extension_action_view_controller.cc
+++ /dev/null
@@ -1,413 +0,0 @@
-// Copyright 2014 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/extensions/extension_action_view_controller.h"
-
-#include "base/logging.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/extensions/api/commands/command_service.h"
-#include "chrome/browser/extensions/api/extension_action/extension_action_api.h"
-#include "chrome/browser/extensions/extension_action.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/extensions/accelerator_priority.h"
-#include "chrome/browser/ui/views/toolbar/toolbar_action_view_delegate.h"
-#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
-#include "chrome/common/extensions/api/extension_action/action_info.h"
-#include "content/public/browser/notification_details.h"
-#include "content/public/browser/notification_source.h"
-#include "extensions/browser/notification_types.h"
-#include "extensions/common/extension.h"
-#include "extensions/common/manifest_constants.h"
-#include "ui/gfx/image/image_skia.h"
-#include "ui/gfx/image/image_skia_operations.h"
-#include "ui/views/controls/menu/menu_controller.h"
-#include "ui/views/controls/menu/menu_runner.h"
-#include "ui/views/view.h"
-#include "ui/views/widget/widget.h"
-
-using extensions::ActionInfo;
-using extensions::CommandService;
-
-namespace {
-
-// The ExtensionActionViewController which is currently showing its context
-// menu, if any.
-// Since only one context menu can be shown (even across browser windows), it's
-// safe to have this be a global singleton.
-ExtensionActionViewController* context_menu_owner = NULL;
-
-} // namespace
-
-ExtensionActionViewController::ExtensionActionViewController(
- const extensions::Extension* extension,
- Browser* browser,
- ExtensionAction* extension_action)
- : extension_(extension),
- browser_(browser),
- extension_action_(extension_action),
- delegate_(nullptr),
- icon_factory_(browser->profile(), extension, extension_action, this),
- icon_observer_(nullptr),
- popup_(nullptr),
- weak_factory_(this) {
- DCHECK(extension_action);
- DCHECK(extension_action->action_type() == ActionInfo::TYPE_PAGE ||
- extension_action->action_type() == ActionInfo::TYPE_BROWSER);
- DCHECK(extension);
-
- content::NotificationSource notification_source =
- content::Source<Profile>(browser->profile()->GetOriginalProfile());
- registrar_.Add(this,
- extensions::NOTIFICATION_EXTENSION_COMMAND_ADDED,
- notification_source);
- registrar_.Add(this,
- extensions::NOTIFICATION_EXTENSION_COMMAND_REMOVED,
- notification_source);
-}
-
-ExtensionActionViewController::~ExtensionActionViewController() {
- if (context_menu_owner == this)
- context_menu_owner = NULL;
- HidePopup();
- UnregisterCommand(false);
-}
-
-const std::string& ExtensionActionViewController::GetId() const {
- return extension_->id();
-}
-
-void ExtensionActionViewController::SetDelegate(
- ToolbarActionViewDelegate* delegate) {
- delegate_ = delegate;
- delegate_->GetAsView()->set_context_menu_controller(this);
-}
-
-gfx::Image ExtensionActionViewController::GetIcon(
- content::WebContents* web_contents) {
- return icon_factory_.GetIcon(SessionTabHelper::IdForTab(web_contents));
-}
-
-gfx::ImageSkia ExtensionActionViewController::GetIconWithBadge() {
- content::WebContents* web_contents = delegate_->GetCurrentWebContents();
- gfx::Size spacing(0, ToolbarView::kVertSpacing);
- gfx::ImageSkia icon = *GetIcon(web_contents).ToImageSkia();
- if (!IsEnabled(web_contents))
- icon = gfx::ImageSkiaOperations::CreateTransparentImage(icon, .25);
- return extension_action_->GetIconWithBadge(
- icon, SessionTabHelper::IdForTab(web_contents), spacing);
-}
-
-base::string16 ExtensionActionViewController::GetAccessibleName(
- content::WebContents* web_contents) const {
- std::string title =
- extension_action()->GetTitle(SessionTabHelper::IdForTab(web_contents));
- return base::UTF8ToUTF16(title.empty() ? extension()->name() : title);
-}
-
-base::string16 ExtensionActionViewController::GetTooltip(
- content::WebContents* web_contents) const {
- return GetAccessibleName(web_contents);
-}
-
-bool ExtensionActionViewController::IsEnabled(
- content::WebContents* web_contents) const {
- return extension_action_->GetIsVisible(
- SessionTabHelper::IdForTab(web_contents));
-}
-
-bool ExtensionActionViewController::HasPopup(
- content::WebContents* web_contents) const {
- int tab_id = SessionTabHelper::IdForTab(web_contents);
- return (tab_id < 0) ? false : extension_action_->HasPopup(tab_id);
-}
-
-void ExtensionActionViewController::HidePopup() {
- if (popup_)
- CleanupPopup(true);
-}
-
-gfx::NativeView ExtensionActionViewController::GetPopupNativeView() {
- return popup_ ? popup_->GetWidget()->GetNativeView() : nullptr;
-}
-
-bool ExtensionActionViewController::IsMenuRunning() const {
- return menu_runner_.get() != NULL;
-}
-
-bool ExtensionActionViewController::CanDrag() const {
- return true;
-}
-
-bool ExtensionActionViewController::ExecuteAction(bool by_user) {
- return ExecuteAction(ExtensionPopup::SHOW, by_user);
-}
-
-void ExtensionActionViewController::PaintExtra(
- gfx::Canvas* canvas,
- const gfx::Rect& bounds,
- content::WebContents* web_contents) const {
- int tab_id = SessionTabHelper::IdForTab(web_contents);
- if (tab_id >= 0)
- extension_action_->PaintBadge(canvas, bounds, tab_id);
-}
-
-void ExtensionActionViewController::RegisterCommand() {
- // If we've already registered, do nothing.
- if (action_keybinding_.get())
- return;
-
- extensions::Command extension_command;
- views::FocusManager* focus_manager =
- delegate_->GetFocusManagerForAccelerator();
- if (focus_manager && GetExtensionCommand(&extension_command)) {
- action_keybinding_.reset(
- new ui::Accelerator(extension_command.accelerator()));
- focus_manager->RegisterAccelerator(
- *action_keybinding_,
- GetAcceleratorPriority(extension_command.accelerator(), extension_),
- this);
- }
-}
-
-void ExtensionActionViewController::InspectPopup() {
- ExecuteAction(ExtensionPopup::SHOW_AND_INSPECT, true);
-}
-
-bool ExtensionActionViewController::ExecuteAction(
- ExtensionPopup::ShowAction show_action, bool grant_tab_permissions) {
- if (extensions::ExtensionActionAPI::Get(browser_->profile())->
- ExecuteExtensionAction(extension_, browser_, grant_tab_permissions) ==
- ExtensionAction::ACTION_SHOW_POPUP) {
- GURL popup_url = extension_action_->GetPopupUrl(
- SessionTabHelper::IdForTab(delegate_->GetCurrentWebContents()));
- return static_cast<ExtensionActionViewController*>(
- delegate_->GetPreferredPopupViewController())->ShowPopupWithUrl(
- show_action, popup_url, grant_tab_permissions);
- }
- return false;
-}
-
-void ExtensionActionViewController::OnIconUpdated() {
- delegate_->OnIconUpdated();
- if (icon_observer_)
- icon_observer_->OnIconUpdated();
-}
-
-bool ExtensionActionViewController::AcceleratorPressed(
- const ui::Accelerator& accelerator) {
- // We shouldn't be handling any accelerators if the view is hidden, unless
- // this is a browser action.
- DCHECK(extension_action_->action_type() == ActionInfo::TYPE_BROWSER ||
- delegate_->GetAsView()->visible());
-
- // Normal priority shortcuts must be handled via standard browser commands to
- // be processed at the proper time.
- if (GetAcceleratorPriority(accelerator, extension()) ==
- ui::AcceleratorManager::kNormalPriority)
- return false;
-
- ExecuteAction(true);
- return true;
-}
-
-bool ExtensionActionViewController::CanHandleAccelerators() const {
- // Page actions can only handle accelerators when they are visible.
- // Browser actions can handle accelerators even when not visible, since they
- // might be hidden in an overflow menu.
- return extension_action_->action_type() == ActionInfo::TYPE_PAGE ?
- delegate_->GetAsView()->visible() : true;
-}
-
-void ExtensionActionViewController::OnWidgetDestroying(views::Widget* widget) {
- DCHECK(popup_);
- DCHECK_EQ(popup_->GetWidget(), widget);
- CleanupPopup(false);
-}
-
-void ExtensionActionViewController::ShowContextMenuForView(
- views::View* source,
- const gfx::Point& point,
- ui::MenuSourceType source_type) {
- // If there's another active menu that won't be dismissed by opening this one,
- // then we can't show this one right away, since we can only show one nested
- // menu at a time.
- // If the other menu is an extension action's context menu, then we'll run
- // this one after that one closes. If it's a different type of menu, then we
- // close it and give up, for want of a better solution. (Luckily, this is
- // rare).
- // TODO(devlin): Update this when views code no longer runs menus in a nested
- // loop.
- if (context_menu_owner) {
- context_menu_owner->followup_context_menu_task_ =
- base::Bind(&ExtensionActionViewController::DoShowContextMenu,
- weak_factory_.GetWeakPtr(),
- source_type);
- }
- if (CloseActiveMenuIfNeeded())
- return;
-
- // Otherwise, no other menu is showing, and we can proceed normally.
- DoShowContextMenu(source_type);
-}
-
-void ExtensionActionViewController::Observe(
- int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) {
- DCHECK(type == extensions::NOTIFICATION_EXTENSION_COMMAND_ADDED ||
- type == extensions::NOTIFICATION_EXTENSION_COMMAND_REMOVED);
- std::pair<const std::string, const std::string>* payload =
- content::Details<std::pair<const std::string, const std::string> >(
- details).ptr();
- if (extension_->id() == payload->first &&
- payload->second ==
- extensions::manifest_values::kBrowserActionCommandEvent) {
- if (type == extensions::NOTIFICATION_EXTENSION_COMMAND_ADDED)
- RegisterCommand();
- else
- UnregisterCommand(true);
- }
-}
-
-void ExtensionActionViewController::DoShowContextMenu(
- ui::MenuSourceType source_type) {
- if (!extension_->ShowConfigureContextMenus())
- return;
-
- DCHECK(!context_menu_owner);
- context_menu_owner = this;
-
- // We shouldn't have both a popup and a context menu showing.
- delegate_->HideActivePopup();
-
- // Reconstructs the menu every time because the menu's contents are dynamic.
- scoped_refptr<ExtensionContextMenuModel> context_menu_model(
- new ExtensionContextMenuModel(extension_, browser_, this));
-
- gfx::Point screen_loc;
- views::View::ConvertPointToScreen(delegate_->GetAsView(), &screen_loc);
-
- int run_types = views::MenuRunner::HAS_MNEMONICS |
- views::MenuRunner::CONTEXT_MENU;
- if (delegate_->IsShownInMenu())
- run_types |= views::MenuRunner::IS_NESTED;
-
- views::Widget* parent = delegate_->GetParentForContextMenu();
-
- menu_runner_.reset(
- new views::MenuRunner(context_menu_model.get(), run_types));
-
- if (menu_runner_->RunMenuAt(
- parent,
- delegate_->GetContextMenuButton(),
- gfx::Rect(screen_loc, delegate_->GetAsView()->size()),
- views::MENU_ANCHOR_TOPLEFT,
- source_type) == views::MenuRunner::MENU_DELETED) {
- return;
- }
-
- context_menu_owner = NULL;
- menu_runner_.reset();
-
- // If another extension action wants to show its context menu, allow it to.
- if (!followup_context_menu_task_.is_null()) {
- base::Closure task = followup_context_menu_task_;
- followup_context_menu_task_ = base::Closure();
- task.Run();
- }
-}
-
-bool ExtensionActionViewController::ShowPopupWithUrl(
- ExtensionPopup::ShowAction show_action,
- const GURL& popup_url,
- bool grant_tab_permissions) {
- // If we're already showing the popup for this browser action, just hide it
- // and return.
- bool already_showing = popup_ != NULL;
-
- // Always hide the current popup, even if it's not the same.
- // Only one popup should be visible at a time.
- delegate_->HideActivePopup();
-
- // Similarly, don't allow a context menu and a popup to be showing
- // simultaneously.
- CloseActiveMenuIfNeeded();
-
- if (already_showing)
- return false;
-
- views::BubbleBorder::Arrow arrow = base::i18n::IsRTL() ?
- views::BubbleBorder::TOP_LEFT : views::BubbleBorder::TOP_RIGHT;
-
- views::View* reference_view = delegate_->GetReferenceViewForPopup();
-
- popup_ = ExtensionPopup::ShowPopup(
- popup_url, browser_, reference_view, arrow, show_action);
- popup_->GetWidget()->AddObserver(this);
-
- delegate_->OnPopupShown(grant_tab_permissions);
-
- return true;
-}
-
-bool ExtensionActionViewController::GetExtensionCommand(
- extensions::Command* command) {
- DCHECK(command);
- CommandService* command_service = CommandService::Get(browser_->profile());
- if (extension_action_->action_type() == ActionInfo::TYPE_PAGE) {
- return command_service->GetPageActionCommand(
- extension_->id(), CommandService::ACTIVE_ONLY, command, NULL);
- }
- return command_service->GetBrowserActionCommand(
- extension_->id(), CommandService::ACTIVE_ONLY, command, NULL);
-}
-
-void ExtensionActionViewController::UnregisterCommand(bool only_if_removed) {
- views::FocusManager* focus_manager =
- delegate_->GetFocusManagerForAccelerator();
- if (!focus_manager || !action_keybinding_.get())
- return;
-
- // If |only_if_removed| is true, it means that we only need to unregister
- // ourselves as an accelerator if the command was removed. Otherwise, we need
- // to unregister ourselves no matter what (likely because we are shutting
- // down).
- extensions::Command extension_command;
- if (!only_if_removed || !GetExtensionCommand(&extension_command)) {
- focus_manager->UnregisterAccelerator(*action_keybinding_, this);
- action_keybinding_.reset();
- }
-}
-
-bool ExtensionActionViewController::CloseActiveMenuIfNeeded() {
- // If this view is shown inside another menu, there's a possibility that there
- // is another context menu showing that we have to close before we can
- // activate a different menu.
- if (delegate_->IsShownInMenu()) {
- views::MenuController* menu_controller =
- views::MenuController::GetActiveInstance();
- // If this is shown inside a menu, then there should always be an active
- // menu controller.
- DCHECK(menu_controller);
- if (menu_controller->in_nested_run()) {
- // There is another menu showing. Close the outermost menu (since we are
- // shown in the same menu, we don't want to close the whole thing).
- menu_controller->Cancel(views::MenuController::EXIT_OUTERMOST);
- return true;
- }
- }
-
- return false;
-}
-
-void ExtensionActionViewController::CleanupPopup(bool close_widget) {
- DCHECK(popup_);
- delegate_->CleanupPopup();
- popup_->GetWidget()->RemoveObserver(this);
- if (close_widget)
- popup_->GetWidget()->Close();
- popup_ = NULL;
-}

Powered by Google App Engine
This is Rietveld 408576698