Check USB device path access when prompting users to select a device.
[chromium-blink-merge.git] / chrome / browser / ui / extensions / extension_action_view_controller.cc
blob1b75901235107162603fadff3131eec4b3cbd577
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/extensions/extension_action_view_controller.h"
7 #include "base/logging.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/browser/extensions/api/commands/command_service.h"
10 #include "chrome/browser/extensions/api/extension_action/extension_action_api.h"
11 #include "chrome/browser/extensions/extension_action.h"
12 #include "chrome/browser/extensions/extension_view.h"
13 #include "chrome/browser/extensions/extension_view_host.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/sessions/session_tab_helper.h"
16 #include "chrome/browser/ui/browser.h"
17 #include "chrome/browser/ui/extensions/accelerator_priority.h"
18 #include "chrome/browser/ui/extensions/extension_action_platform_delegate.h"
19 #include "chrome/browser/ui/toolbar/toolbar_action_view_delegate.h"
20 #include "chrome/common/extensions/api/extension_action/action_info.h"
21 #include "extensions/browser/extension_host.h"
22 #include "extensions/browser/extension_registry.h"
23 #include "extensions/common/extension.h"
24 #include "extensions/common/manifest_constants.h"
25 #include "ui/gfx/image/image_skia.h"
26 #include "ui/gfx/image/image_skia_operations.h"
28 using extensions::ActionInfo;
29 using extensions::CommandService;
31 ExtensionActionViewController::ExtensionActionViewController(
32 const extensions::Extension* extension,
33 Browser* browser,
34 ExtensionAction* extension_action)
35 : extension_(extension),
36 browser_(browser),
37 extension_action_(extension_action),
38 popup_host_(nullptr),
39 view_delegate_(nullptr),
40 platform_delegate_(ExtensionActionPlatformDelegate::Create(this)),
41 icon_factory_(browser->profile(), extension, extension_action, this),
42 icon_observer_(nullptr),
43 extension_registry_(
44 extensions::ExtensionRegistry::Get(browser_->profile())),
45 popup_host_observer_(this) {
46 DCHECK(extension_action);
47 DCHECK(extension_action->action_type() == ActionInfo::TYPE_PAGE ||
48 extension_action->action_type() == ActionInfo::TYPE_BROWSER);
49 DCHECK(extension);
52 ExtensionActionViewController::~ExtensionActionViewController() {
53 DCHECK(!is_showing_popup());
56 const std::string& ExtensionActionViewController::GetId() const {
57 return extension_->id();
60 void ExtensionActionViewController::SetDelegate(
61 ToolbarActionViewDelegate* delegate) {
62 DCHECK((delegate == nullptr) ^ (view_delegate_ == nullptr));
63 if (delegate) {
64 view_delegate_ = delegate;
65 platform_delegate_->OnDelegateSet();
66 } else {
67 if (is_showing_popup())
68 HidePopup();
69 platform_delegate_.reset();
70 view_delegate_ = nullptr;
74 gfx::Image ExtensionActionViewController::GetIcon(
75 content::WebContents* web_contents) {
76 if (!ExtensionIsValid())
77 return gfx::Image();
79 return icon_factory_.GetIcon(SessionTabHelper::IdForTab(web_contents));
82 gfx::ImageSkia ExtensionActionViewController::GetIconWithBadge() {
83 if (!ExtensionIsValid())
84 return gfx::ImageSkia();
86 content::WebContents* web_contents = view_delegate_->GetCurrentWebContents();
87 gfx::Size spacing(0, 3);
88 gfx::ImageSkia icon = *GetIcon(web_contents).ToImageSkia();
89 if (!IsEnabled(web_contents))
90 icon = gfx::ImageSkiaOperations::CreateTransparentImage(icon, .25);
91 return extension_action_->GetIconWithBadge(
92 icon, SessionTabHelper::IdForTab(web_contents), spacing);
95 base::string16 ExtensionActionViewController::GetActionName() const {
96 if (!ExtensionIsValid())
97 return base::string16();
99 return base::UTF8ToUTF16(extension_->name());
102 base::string16 ExtensionActionViewController::GetAccessibleName(
103 content::WebContents* web_contents) const {
104 if (!ExtensionIsValid())
105 return base::string16();
107 std::string title =
108 extension_action()->GetTitle(SessionTabHelper::IdForTab(web_contents));
109 return base::UTF8ToUTF16(title.empty() ? extension()->name() : title);
112 base::string16 ExtensionActionViewController::GetTooltip(
113 content::WebContents* web_contents) const {
114 return GetAccessibleName(web_contents);
117 bool ExtensionActionViewController::IsEnabled(
118 content::WebContents* web_contents) const {
119 if (!ExtensionIsValid())
120 return false;
122 return extension_action_->GetIsVisible(
123 SessionTabHelper::IdForTab(web_contents)) ||
124 extensions::ExtensionActionAPI::Get(browser_->profile())->
125 ExtensionWantsToRun(extension(), web_contents);
128 bool ExtensionActionViewController::WantsToRun(
129 content::WebContents* web_contents) const {
130 return extensions::ExtensionActionAPI::Get(browser_->profile())->
131 ExtensionWantsToRun(extension(), web_contents);
134 bool ExtensionActionViewController::HasPopup(
135 content::WebContents* web_contents) const {
136 if (!ExtensionIsValid())
137 return false;
139 int tab_id = SessionTabHelper::IdForTab(web_contents);
140 return (tab_id < 0) ? false : extension_action_->HasPopup(tab_id);
143 void ExtensionActionViewController::HidePopup() {
144 if (is_showing_popup()) {
145 popup_host_->Close();
146 // We need to do these actions synchronously (instead of closing and then
147 // performing the rest of the cleanup in OnExtensionHostDestroyed()) because
148 // the extension host can close asynchronously, and we need to keep the view
149 // delegate up-to-date.
150 OnPopupClosed();
154 gfx::NativeView ExtensionActionViewController::GetPopupNativeView() {
155 return popup_host_ ? popup_host_->view()->GetNativeView() : nullptr;
158 ui::MenuModel* ExtensionActionViewController::GetContextMenu() {
159 if (!ExtensionIsValid() || !extension()->ShowConfigureContextMenus())
160 return nullptr;
162 // Reconstruct the menu every time because the menu's contents are dynamic.
163 context_menu_model_ = make_scoped_refptr(new ExtensionContextMenuModel(
164 extension(), browser_, this));
165 return context_menu_model_.get();
168 bool ExtensionActionViewController::IsMenuRunning() const {
169 return platform_delegate_->IsMenuRunning();
172 bool ExtensionActionViewController::CanDrag() const {
173 return true;
176 bool ExtensionActionViewController::ExecuteAction(bool by_user) {
177 return ExecuteAction(SHOW_POPUP, by_user);
180 void ExtensionActionViewController::UpdateState() {
181 if (!ExtensionIsValid())
182 return;
184 view_delegate_->UpdateState();
187 bool ExtensionActionViewController::ExecuteAction(PopupShowAction show_action,
188 bool grant_tab_permissions) {
189 if (!ExtensionIsValid())
190 return false;
192 if (extensions::ExtensionActionAPI::Get(browser_->profile())
193 ->ExecuteExtensionAction(
194 extension_, browser_, grant_tab_permissions) ==
195 ExtensionAction::ACTION_SHOW_POPUP) {
196 GURL popup_url = extension_action_->GetPopupUrl(
197 SessionTabHelper::IdForTab(view_delegate_->GetCurrentWebContents()));
198 return static_cast<ExtensionActionViewController*>(
199 view_delegate_->GetPreferredPopupViewController())
200 ->ShowPopupWithUrl(show_action, popup_url, grant_tab_permissions);
202 return false;
205 void ExtensionActionViewController::PaintExtra(
206 gfx::Canvas* canvas,
207 const gfx::Rect& bounds,
208 content::WebContents* web_contents) const {
209 if (!ExtensionIsValid())
210 return;
212 int tab_id = SessionTabHelper::IdForTab(web_contents);
213 if (tab_id >= 0)
214 extension_action_->PaintBadge(canvas, bounds, tab_id);
217 void ExtensionActionViewController::RegisterCommand() {
218 if (!ExtensionIsValid())
219 return;
221 platform_delegate_->RegisterCommand();
224 void ExtensionActionViewController::InspectPopup() {
225 ExecuteAction(SHOW_POPUP_AND_INSPECT, true);
228 void ExtensionActionViewController::OnIconUpdated() {
229 if (icon_observer_)
230 icon_observer_->OnIconUpdated();
231 if (view_delegate_)
232 view_delegate_->UpdateState();
235 void ExtensionActionViewController::OnExtensionHostDestroyed(
236 const extensions::ExtensionHost* host) {
237 OnPopupClosed();
240 bool ExtensionActionViewController::ExtensionIsValid() const {
241 return extension_registry_->enabled_extensions().Contains(extension_->id());
244 bool ExtensionActionViewController::GetExtensionCommand(
245 extensions::Command* command) {
246 DCHECK(command);
247 if (!ExtensionIsValid())
248 return false;
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, command, NULL);
255 return command_service->GetBrowserActionCommand(
256 extension_->id(), CommandService::ACTIVE, command, NULL);
259 bool ExtensionActionViewController::ShowPopupWithUrl(
260 PopupShowAction show_action,
261 const GURL& popup_url,
262 bool grant_tab_permissions) {
263 if (!ExtensionIsValid())
264 return false;
266 bool already_showing = is_showing_popup();
268 // Always hide the current popup, even if it's not owned by this extension.
269 // Only one popup should be visible at a time.
270 platform_delegate_->CloseActivePopup();
272 // If we were showing a popup already, then we treat the action to open the
273 // same one as a desire to close it (like clicking a menu button that was
274 // already open).
275 if (already_showing)
276 return false;
278 popup_host_ = platform_delegate_->ShowPopupWithUrl(
279 show_action, popup_url, grant_tab_permissions);
280 if (popup_host_) {
281 popup_host_observer_.Add(popup_host_);
282 view_delegate_->OnPopupShown(grant_tab_permissions);
284 return is_showing_popup();
287 void ExtensionActionViewController::OnPopupClosed() {
288 popup_host_observer_.Remove(popup_host_);
289 popup_host_ = nullptr;
290 view_delegate_->OnPopupClosed();