1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/ui/views/extensions/extension_action_platform_delegate_views.h"
7 #include "base/logging.h"
8 #include "chrome/browser/extensions/extension_action.h"
9 #include "chrome/browser/extensions/extension_view_host.h"
10 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/browser/ui/browser.h"
12 #include "chrome/browser/ui/extensions/accelerator_priority.h"
13 #include "chrome/browser/ui/views/frame/browser_view.h"
14 #include "chrome/browser/ui/views/toolbar/browser_actions_container.h"
15 #include "chrome/browser/ui/views/toolbar/toolbar_action_view_delegate_views.h"
16 #include "chrome/browser/ui/views/toolbar/toolbar_view.h"
17 #include "chrome/common/extensions/api/extension_action/action_info.h"
18 #include "chrome/common/extensions/command.h"
19 #include "content/public/browser/notification_details.h"
20 #include "content/public/browser/notification_source.h"
21 #include "extensions/browser/notification_types.h"
22 #include "extensions/common/extension.h"
23 #include "extensions/common/manifest_constants.h"
24 #include "ui/views/view.h"
26 using extensions::ActionInfo
;
29 scoped_ptr
<ExtensionActionPlatformDelegate
>
30 ExtensionActionPlatformDelegate::Create(
31 ExtensionActionViewController
* controller
) {
32 return make_scoped_ptr(new ExtensionActionPlatformDelegateViews(controller
));
35 ExtensionActionPlatformDelegateViews::ExtensionActionPlatformDelegateViews(
36 ExtensionActionViewController
* controller
)
37 : controller_(controller
) {
38 content::NotificationSource notification_source
= content::Source
<Profile
>(
39 controller_
->browser()->profile()->GetOriginalProfile());
41 extensions::NOTIFICATION_EXTENSION_COMMAND_ADDED
,
44 extensions::NOTIFICATION_EXTENSION_COMMAND_REMOVED
,
48 ExtensionActionPlatformDelegateViews::~ExtensionActionPlatformDelegateViews() {
49 UnregisterCommand(false);
52 void ExtensionActionPlatformDelegateViews::RegisterCommand() {
53 // If we've already registered, do nothing.
54 if (action_keybinding_
.get())
57 extensions::Command extension_command
;
58 views::FocusManager
* focus_manager
=
59 GetDelegateViews()->GetFocusManagerForAccelerator();
60 if (focus_manager
&& controller_
->GetExtensionCommand(&extension_command
)) {
61 action_keybinding_
.reset(
62 new ui::Accelerator(extension_command
.accelerator()));
63 focus_manager
->RegisterAccelerator(
65 GetAcceleratorPriority(extension_command
.accelerator(),
66 controller_
->extension()),
71 void ExtensionActionPlatformDelegateViews::ShowPopup(
72 scoped_ptr
<extensions::ExtensionViewHost
> host
,
73 bool grant_tab_permissions
,
74 ExtensionActionViewController::PopupShowAction show_action
) {
75 // TOP_RIGHT is correct for both RTL and LTR, because the views platform
76 // performs the flipping in RTL cases.
77 views::BubbleBorder::Arrow arrow
= views::BubbleBorder::TOP_RIGHT
;
79 views::View
* reference_view
= GetDelegateViews()->GetReferenceViewForPopup();
81 ExtensionPopup::ShowAction popup_show_action
=
82 show_action
== ExtensionActionViewController::SHOW_POPUP
?
83 ExtensionPopup::SHOW
: ExtensionPopup::SHOW_AND_INSPECT
;
84 ExtensionPopup::ShowPopup(host
.Pass(),
90 void ExtensionActionPlatformDelegateViews::CloseOverflowMenu() {
91 ToolbarView
* toolbar
=
92 BrowserView::GetBrowserViewForBrowser(controller_
->browser())->toolbar();
93 if (toolbar
->IsWrenchMenuShowing())
94 toolbar
->CloseAppMenu();
97 void ExtensionActionPlatformDelegateViews::Observe(
99 const content::NotificationSource
& source
,
100 const content::NotificationDetails
& details
) {
101 DCHECK(type
== extensions::NOTIFICATION_EXTENSION_COMMAND_ADDED
||
102 type
== extensions::NOTIFICATION_EXTENSION_COMMAND_REMOVED
);
103 extensions::ExtensionCommandRemovedDetails
* payload
=
104 content::Details
<extensions::ExtensionCommandRemovedDetails
>(details
)
106 if (controller_
->extension()->id() == payload
->extension_id
&&
107 (payload
->command_name
==
108 extensions::manifest_values::kBrowserActionCommandEvent
||
109 payload
->command_name
==
110 extensions::manifest_values::kPageActionCommandEvent
)) {
111 if (type
== extensions::NOTIFICATION_EXTENSION_COMMAND_ADDED
)
114 UnregisterCommand(true);
118 bool ExtensionActionPlatformDelegateViews::AcceleratorPressed(
119 const ui::Accelerator
& accelerator
) {
120 // We shouldn't be handling any accelerators if the view is hidden, unless
121 // this is a browser action.
122 DCHECK(controller_
->extension_action()->action_type() ==
123 ActionInfo::TYPE_BROWSER
||
124 GetDelegateViews()->GetAsView()->visible());
126 // Normal priority shortcuts must be handled via standard browser commands to
127 // be processed at the proper time.
128 if (GetAcceleratorPriority(accelerator
, controller_
->extension()) ==
129 ui::AcceleratorManager::kNormalPriority
)
132 controller_
->ExecuteAction(true);
136 bool ExtensionActionPlatformDelegateViews::CanHandleAccelerators() const {
137 // Page actions can only handle accelerators when they are visible.
138 // Browser actions can handle accelerators even when not visible, since they
139 // might be hidden in an overflow menu.
140 return controller_
->extension_action()->action_type() ==
141 ActionInfo::TYPE_PAGE
? GetDelegateViews()->GetAsView()->visible() :
145 void ExtensionActionPlatformDelegateViews::UnregisterCommand(
146 bool only_if_removed
) {
147 views::FocusManager
* focus_manager
=
148 GetDelegateViews()->GetFocusManagerForAccelerator();
149 if (!focus_manager
|| !action_keybinding_
.get())
152 // If |only_if_removed| is true, it means that we only need to unregister
153 // ourselves as an accelerator if the command was removed. Otherwise, we need
154 // to unregister ourselves no matter what (likely because we are shutting
156 extensions::Command extension_command
;
157 if (!only_if_removed
||
158 !controller_
->GetExtensionCommand(&extension_command
)) {
159 focus_manager
->UnregisterAccelerator(*action_keybinding_
, this);
160 action_keybinding_
.reset();
164 ToolbarActionViewDelegateViews
*
165 ExtensionActionPlatformDelegateViews::GetDelegateViews() const {
166 return static_cast<ToolbarActionViewDelegateViews
*>(
167 controller_
->view_delegate());