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

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

Issue 431173002: Create ExtensionActionView class (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: merge conflict Created 6 years, 4 months 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
new file mode 100644
index 0000000000000000000000000000000000000000..52c15ef148a2af2d72d64857359feb1675f26d0d
--- /dev/null
+++ b/chrome/browser/ui/views/extensions/extension_action_view_controller.cc
@@ -0,0 +1,266 @@
+// 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 "chrome/browser/extensions/api/commands/command_service.h"
+#include "chrome/browser/extensions/extension_action.h"
+#include "chrome/browser/extensions/extension_toolbar_model.h"
+#include "chrome/browser/extensions/location_bar_controller.h"
+#include "chrome/browser/extensions/tab_helper.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/sessions/session_id.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/extensions/accelerator_priority.h"
+#include "chrome/browser/ui/views/extensions/extension_action_view_delegate.h"
+#include "chrome/common/extensions/api/extension_action/action_info.h"
+#include "extensions/common/extension.h"
+#include "extensions/common/manifest_constants.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;
+
+ExtensionActionViewController::ExtensionActionViewController(
+ const extensions::Extension* extension,
+ Browser* browser,
+ ExtensionAction* extension_action,
+ ExtensionActionViewDelegate* delegate)
+ : extension_(extension),
+ browser_(browser),
+ extension_action_(extension_action),
+ delegate_(delegate),
+ icon_factory_(browser->profile(), extension, extension_action, this),
+ popup_(NULL) {
+ DCHECK(extension_action->action_type() == ActionInfo::TYPE_PAGE ||
+ extension_action->action_type() == ActionInfo::TYPE_BROWSER);
+ DCHECK(extension);
+
+}
+
+ExtensionActionViewController::~ExtensionActionViewController() {
+ HidePopup();
+ UnregisterCommand(false);
+}
+
+void ExtensionActionViewController::InspectPopup() {
+ ExecuteAction(ExtensionPopup::SHOW_AND_INSPECT, true);
+}
+
+void ExtensionActionViewController::ExecuteActionByUser() {
+ ExecuteAction(ExtensionPopup::SHOW, true);
+}
+
+bool ExtensionActionViewController::ExecuteAction(
+ ExtensionPopup::ShowAction show_action, bool grant_tab_permissions) {
+ GURL popup_url;
+ bool show_popup = false;
+ if (extension_action_->action_type() == ActionInfo::TYPE_BROWSER) {
+ extensions::ExtensionToolbarModel* toolbar_model =
+ extensions::ExtensionToolbarModel::Get(browser_->profile());
+ show_popup = toolbar_model->ExecuteBrowserAction(
+ extension_, browser_, &popup_url, grant_tab_permissions) ==
+ extensions::ExtensionToolbarModel::ACTION_SHOW_POPUP;
+ } else { // PageAction
+ content::WebContents* web_contents = delegate_->GetCurrentWebContents();
+ if (!web_contents)
+ return false;
+ extensions::LocationBarController* controller =
+ extensions::TabHelper::FromWebContents(web_contents)->
+ location_bar_controller();
+ switch (controller->OnClicked(extension_action_)) {
+ case extensions::LocationBarController::ACTION_NONE:
+ break;
+ case extensions::LocationBarController::ACTION_SHOW_POPUP:
+ popup_url = extension_action_->GetPopupUrl(GetCurrentTabId());
+ show_popup = true;
+ break;
+ case extensions::LocationBarController::ACTION_SHOW_CONTEXT_MENU:
+ // We are never passing OnClicked a right-click button, so assume that
+ // we're never going to be asked to show a context menu.
+ // TODO(kalman): if this changes, update this class to pass the real
+ // mouse button through to the LocationBarController.
+ NOTREACHED();
+ break;
+ }
+ }
+
+ if (show_popup && ShowPopupWithUrl(show_action, popup_url)) {
+ delegate_->OnPopupShown(grant_tab_permissions);
+ return true;
+ }
+
+ return false;
+}
+
+void ExtensionActionViewController::HidePopup() {
+ if (popup_)
+ CleanupPopup(true);
+}
+
+gfx::Image ExtensionActionViewController::GetIcon(int tab_id) {
+ return icon_factory_.GetIcon(tab_id);
+}
+
+int ExtensionActionViewController::GetCurrentTabId() const {
+ content::WebContents* web_contents = delegate_->GetCurrentWebContents();
+ return web_contents ? SessionID::IdForTab(web_contents) : -1;
+}
+
+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::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();
+ }
+}
+
+void ExtensionActionViewController::OnIconUpdated() {
+ delegate_->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;
+
+ ExecuteActionByUser();
+ 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 (!extension_->ShowConfigureContextMenus())
+ return;
+
+ delegate_->OnWillShowContextMenus();
+
+ // 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,
+ NULL,
+ gfx::Rect(screen_loc, delegate_->GetAsView()->size()),
+ views::MENU_ANCHOR_TOPLEFT,
+ source_type) == views::MenuRunner::MENU_DELETED) {
+ return;
+ }
+
+ menu_runner_.reset();
+ delegate_->OnContextMenuDone();
+}
+
+bool ExtensionActionViewController::ShowPopupWithUrl(
+ ExtensionPopup::ShowAction show_action, const GURL& popup_url) {
+ // 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();
+ 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);
+
+ 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::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