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

Side by Side 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 unified diff | Download patch
OLDNEW
(Empty)
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.
4
5 #include "chrome/browser/ui/views/extensions/extension_action_view_controller.h"
6
7 #include "base/logging.h"
8 #include "chrome/browser/extensions/api/commands/command_service.h"
9 #include "chrome/browser/extensions/extension_action.h"
10 #include "chrome/browser/extensions/extension_toolbar_model.h"
11 #include "chrome/browser/extensions/location_bar_controller.h"
12 #include "chrome/browser/extensions/tab_helper.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/sessions/session_id.h"
15 #include "chrome/browser/ui/browser.h"
16 #include "chrome/browser/ui/extensions/accelerator_priority.h"
17 #include "chrome/browser/ui/views/extensions/extension_action_view_delegate.h"
18 #include "chrome/common/extensions/api/extension_action/action_info.h"
19 #include "extensions/common/extension.h"
20 #include "extensions/common/manifest_constants.h"
21 #include "ui/views/controls/menu/menu_runner.h"
22 #include "ui/views/view.h"
23 #include "ui/views/widget/widget.h"
24
25 using extensions::ActionInfo;
26 using extensions::CommandService;
27
28 ExtensionActionViewController::ExtensionActionViewController(
29 const extensions::Extension* extension,
30 Browser* browser,
31 ExtensionAction* extension_action,
32 ExtensionActionViewDelegate* delegate)
33 : extension_(extension),
34 browser_(browser),
35 extension_action_(extension_action),
36 delegate_(delegate),
37 icon_factory_(browser->profile(), extension, extension_action, this),
38 popup_(NULL) {
39 DCHECK(extension_action->action_type() == ActionInfo::TYPE_PAGE ||
40 extension_action->action_type() == ActionInfo::TYPE_BROWSER);
41 DCHECK(extension);
42
43 }
44
45 ExtensionActionViewController::~ExtensionActionViewController() {
46 HidePopup();
47 UnregisterCommand(false);
48 }
49
50 void ExtensionActionViewController::InspectPopup() {
51 ExecuteAction(ExtensionPopup::SHOW_AND_INSPECT, true);
52 }
53
54 void ExtensionActionViewController::ExecuteActionByUser() {
55 ExecuteAction(ExtensionPopup::SHOW, true);
56 }
57
58 bool ExtensionActionViewController::ExecuteAction(
59 ExtensionPopup::ShowAction show_action, bool grant_tab_permissions) {
60 GURL popup_url;
61 bool show_popup = false;
62 if (extension_action_->action_type() == ActionInfo::TYPE_BROWSER) {
63 extensions::ExtensionToolbarModel* toolbar_model =
64 extensions::ExtensionToolbarModel::Get(browser_->profile());
65 show_popup = toolbar_model->ExecuteBrowserAction(
66 extension_, browser_, &popup_url, grant_tab_permissions) ==
67 extensions::ExtensionToolbarModel::ACTION_SHOW_POPUP;
68 } else { // PageAction
69 content::WebContents* web_contents = delegate_->GetCurrentWebContents();
70 if (!web_contents)
71 return false;
72 extensions::LocationBarController* controller =
73 extensions::TabHelper::FromWebContents(web_contents)->
74 location_bar_controller();
75 switch (controller->OnClicked(extension_action_)) {
76 case extensions::LocationBarController::ACTION_NONE:
77 break;
78 case extensions::LocationBarController::ACTION_SHOW_POPUP:
79 popup_url = extension_action_->GetPopupUrl(GetCurrentTabId());
80 show_popup = true;
81 break;
82 case extensions::LocationBarController::ACTION_SHOW_CONTEXT_MENU:
83 // We are never passing OnClicked a right-click button, so assume that
84 // we're never going to be asked to show a context menu.
85 // TODO(kalman): if this changes, update this class to pass the real
86 // mouse button through to the LocationBarController.
87 NOTREACHED();
88 break;
89 }
90 }
91
92 if (show_popup && ShowPopupWithUrl(show_action, popup_url)) {
93 delegate_->OnPopupShown(grant_tab_permissions);
94 return true;
95 }
96
97 return false;
98 }
99
100 void ExtensionActionViewController::HidePopup() {
101 if (popup_)
102 CleanupPopup(true);
103 }
104
105 gfx::Image ExtensionActionViewController::GetIcon(int tab_id) {
106 return icon_factory_.GetIcon(tab_id);
107 }
108
109 int ExtensionActionViewController::GetCurrentTabId() const {
110 content::WebContents* web_contents = delegate_->GetCurrentWebContents();
111 return web_contents ? SessionID::IdForTab(web_contents) : -1;
112 }
113
114 void ExtensionActionViewController::RegisterCommand() {
115 // If we've already registered, do nothing.
116 if (action_keybinding_.get())
117 return;
118
119 extensions::Command extension_command;
120 views::FocusManager* focus_manager =
121 delegate_->GetFocusManagerForAccelerator();
122 if (focus_manager && GetExtensionCommand(&extension_command)) {
123 action_keybinding_.reset(
124 new ui::Accelerator(extension_command.accelerator()));
125 focus_manager->RegisterAccelerator(
126 *action_keybinding_,
127 GetAcceleratorPriority(extension_command.accelerator(), extension_),
128 this);
129 }
130 }
131
132 void ExtensionActionViewController::UnregisterCommand(bool only_if_removed) {
133 views::FocusManager* focus_manager =
134 delegate_->GetFocusManagerForAccelerator();
135 if (!focus_manager || !action_keybinding_.get())
136 return;
137
138 // If |only_if_removed| is true, it means that we only need to unregister
139 // ourselves as an accelerator if the command was removed. Otherwise, we need
140 // to unregister ourselves no matter what (likely because we are shutting
141 // down).
142 extensions::Command extension_command;
143 if (!only_if_removed || !GetExtensionCommand(&extension_command)) {
144 focus_manager->UnregisterAccelerator(*action_keybinding_, this);
145 action_keybinding_.reset();
146 }
147 }
148
149 void ExtensionActionViewController::OnIconUpdated() {
150 delegate_->OnIconUpdated();
151 }
152
153 bool ExtensionActionViewController::AcceleratorPressed(
154 const ui::Accelerator& accelerator) {
155 // We shouldn't be handling any accelerators if the view is hidden, unless
156 // this is a browser action.
157 DCHECK(extension_action_->action_type() == ActionInfo::TYPE_BROWSER ||
158 delegate_->GetAsView()->visible());
159
160 // Normal priority shortcuts must be handled via standard browser commands to
161 // be processed at the proper time.
162 if (GetAcceleratorPriority(accelerator, extension()) ==
163 ui::AcceleratorManager::kNormalPriority)
164 return false;
165
166 ExecuteActionByUser();
167 return true;
168 }
169
170 bool ExtensionActionViewController::CanHandleAccelerators() const {
171 // Page actions can only handle accelerators when they are visible.
172 // Browser actions can handle accelerators even when not visible, since they
173 // might be hidden in an overflow menu.
174 return extension_action_->action_type() == ActionInfo::TYPE_PAGE ?
175 delegate_->GetAsView()->visible() : true;
176 }
177
178 void ExtensionActionViewController::OnWidgetDestroying(views::Widget* widget) {
179 DCHECK(popup_);
180 DCHECK_EQ(popup_->GetWidget(), widget);
181 CleanupPopup(false);
182 }
183
184 void ExtensionActionViewController::ShowContextMenuForView(
185 views::View* source,
186 const gfx::Point& point,
187 ui::MenuSourceType source_type) {
188 if (!extension_->ShowConfigureContextMenus())
189 return;
190
191 delegate_->OnWillShowContextMenus();
192
193 // Reconstructs the menu every time because the menu's contents are dynamic.
194 scoped_refptr<ExtensionContextMenuModel> context_menu_model(
195 new ExtensionContextMenuModel(extension_, browser_, this));
196
197 gfx::Point screen_loc;
198 views::View::ConvertPointToScreen(delegate_->GetAsView(), &screen_loc);
199
200 int run_types = views::MenuRunner::HAS_MNEMONICS |
201 views::MenuRunner::CONTEXT_MENU;
202 if (delegate_->IsShownInMenu())
203 run_types |= views::MenuRunner::IS_NESTED;
204
205 views::Widget* parent = delegate_->GetParentForContextMenu();
206
207 menu_runner_.reset(
208 new views::MenuRunner(context_menu_model.get(), run_types));
209
210 if (menu_runner_->RunMenuAt(
211 parent,
212 NULL,
213 gfx::Rect(screen_loc, delegate_->GetAsView()->size()),
214 views::MENU_ANCHOR_TOPLEFT,
215 source_type) == views::MenuRunner::MENU_DELETED) {
216 return;
217 }
218
219 menu_runner_.reset();
220 delegate_->OnContextMenuDone();
221 }
222
223 bool ExtensionActionViewController::ShowPopupWithUrl(
224 ExtensionPopup::ShowAction show_action, const GURL& popup_url) {
225 // If we're already showing the popup for this browser action, just hide it
226 // and return.
227 bool already_showing = popup_ != NULL;
228
229 // Always hide the current popup, even if it's not the same.
230 // Only one popup should be visible at a time.
231 delegate_->HideActivePopup();
232 if (already_showing)
233 return false;
234
235 views::BubbleBorder::Arrow arrow = base::i18n::IsRTL() ?
236 views::BubbleBorder::TOP_LEFT : views::BubbleBorder::TOP_RIGHT;
237
238 views::View* reference_view = delegate_->GetReferenceViewForPopup();
239
240 popup_ = ExtensionPopup::ShowPopup(
241 popup_url, browser_, reference_view, arrow, show_action);
242 popup_->GetWidget()->AddObserver(this);
243
244 return true;
245 }
246
247 bool ExtensionActionViewController::GetExtensionCommand(
248 extensions::Command* command) {
249 DCHECK(command);
250 CommandService* command_service = CommandService::Get(browser_->profile());
251 if (extension_action_->action_type() == ActionInfo::TYPE_PAGE) {
252 return command_service->GetPageActionCommand(
253 extension_->id(), CommandService::ACTIVE_ONLY, command, NULL);
254 }
255 return command_service->GetBrowserActionCommand(
256 extension_->id(), CommandService::ACTIVE_ONLY, command, NULL);
257 }
258
259 void ExtensionActionViewController::CleanupPopup(bool close_widget) {
260 DCHECK(popup_);
261 delegate_->CleanupPopup();
262 popup_->GetWidget()->RemoveObserver(this);
263 if (close_widget)
264 popup_->GetWidget()->Close();
265 popup_ = NULL;
266 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698