blob: e3abc4c3ac1144f5304ca611e8ba50dff65acf84 [file] [log] [blame]
// 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.
#import "chrome/browser/ui/cocoa/extensions/extension_action_platform_delegate_cocoa.h"
#include <string>
#include <utility>
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "chrome/browser/extensions/extension_action.h"
#include "chrome/browser/extensions/extension_view_host.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_window.h"
#import "chrome/browser/ui/cocoa/app_menu/app_menu_controller.h"
#import "chrome/browser/ui/cocoa/browser_window_controller.h"
#import "chrome/browser/ui/cocoa/extensions/browser_action_button.h"
#import "chrome/browser/ui/cocoa/extensions/browser_actions_controller.h"
#import "chrome/browser/ui/cocoa/extensions/extension_popup_controller.h"
#import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
#import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h"
#include "chrome/browser/ui/toolbar/toolbar_action_view_delegate.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"
namespace {
// Returns the notification to listen to for activation for a particular
// |extension_action|.
int GetNotificationTypeForAction(const ExtensionAction& extension_action) {
if (extension_action.action_type() == extensions::ActionInfo::TYPE_BROWSER)
return extensions::NOTIFICATION_EXTENSION_COMMAND_BROWSER_ACTION_MAC;
// We should only have page and browser action types.
DCHECK_EQ(extensions::ActionInfo::TYPE_PAGE, extension_action.action_type());
return extensions::NOTIFICATION_EXTENSION_COMMAND_PAGE_ACTION_MAC;
}
} // namespace
// static
std::unique_ptr<ExtensionActionPlatformDelegate>
ExtensionActionPlatformDelegate::Create(
ExtensionActionViewController* controller) {
return base::WrapUnique(new ExtensionActionPlatformDelegateCocoa(controller));
}
ExtensionActionPlatformDelegateCocoa::ExtensionActionPlatformDelegateCocoa(
ExtensionActionViewController* controller)
: controller_(controller) {
}
ExtensionActionPlatformDelegateCocoa::~ExtensionActionPlatformDelegateCocoa() {
}
void ExtensionActionPlatformDelegateCocoa::RegisterCommand() {
// Commands are handled elsewhere for Cocoa.
}
void ExtensionActionPlatformDelegateCocoa::OnDelegateSet() {
registrar_.Add(
this,
GetNotificationTypeForAction(*controller_->extension_action()),
content::Source<Profile>(controller_->browser()->profile()));
}
void ExtensionActionPlatformDelegateCocoa::ShowPopup(
std::unique_ptr<extensions::ExtensionViewHost> host,
bool grant_tab_permissions,
ExtensionActionViewController::PopupShowAction show_action) {
BOOL devMode =
show_action == ExtensionActionViewController::SHOW_POPUP_AND_INSPECT;
[ExtensionPopupController host:std::move(host)
inBrowser:controller_->browser()
anchoredAt:GetPopupPoint()
arrowLocation:info_bubble::kTopTrailing
devMode:devMode];
}
void ExtensionActionPlatformDelegateCocoa::CloseOverflowMenu() {
// If this was triggered by an action overflowed to the app menu, then the app
// menu will be open. Close it before opening the popup.
AppMenuController* appMenuController =
[[[BrowserWindowController
browserWindowControllerForWindow:
controller_->browser()->window()->GetNativeWindow()]
toolbarController] appMenuController];
if ([appMenuController isMenuOpen])
[appMenuController cancel];
}
void ExtensionActionPlatformDelegateCocoa::ShowContextMenu() {
// We should only use this code path for extensions shown in the toolbar.
BrowserWindowController* windowController = [BrowserWindowController
browserWindowControllerForWindow:controller_->browser()
->window()
->GetNativeWindow()];
BrowserActionsController* actionsController =
[[windowController toolbarController] browserActionsController];
[[actionsController mainButtonForId:controller_->GetId()] showContextMenu];
}
NSPoint ExtensionActionPlatformDelegateCocoa::GetPopupPoint() const {
BrowserWindowController* windowController =
[BrowserWindowController browserWindowControllerForWindow:
controller_->browser()->window()->GetNativeWindow()];
BrowserActionsController* actionsController =
[[windowController toolbarController] browserActionsController];
return [actionsController popupPointForId:controller_->GetId()];
}
void ExtensionActionPlatformDelegateCocoa::Observe(
int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
switch (type) {
case extensions::NOTIFICATION_EXTENSION_COMMAND_BROWSER_ACTION_MAC:
case extensions::NOTIFICATION_EXTENSION_COMMAND_PAGE_ACTION_MAC: {
DCHECK_EQ(type,
GetNotificationTypeForAction(*controller_->extension_action()));
std::pair<const std::string, gfx::NativeWindow>* payload =
content::Details<std::pair<const std::string, gfx::NativeWindow> >(
details).ptr();
const std::string& extension_id = payload->first;
gfx::NativeWindow window = payload->second;
if (window == controller_->browser()->window()->GetNativeWindow() &&
extension_id == controller_->extension()->id() &&
controller_->IsEnabled(
controller_->view_delegate()->GetCurrentWebContents())) {
controller_->ExecuteAction(true);
}
break;
}
default:
NOTREACHED() << "Unexpected notification";
}
}