OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/ui/extensions/extension_action_view_controller.h" | 5 #include "chrome/browser/ui/extensions/extension_action_view_controller.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/strings/utf_string_conversions.h" | 8 #include "base/strings/utf_string_conversions.h" |
9 #include "chrome/browser/extensions/api/commands/command_service.h" | 9 #include "chrome/browser/extensions/api/commands/command_service.h" |
10 #include "chrome/browser/extensions/api/extension_action/extension_action_api.h" | 10 #include "chrome/browser/extensions/api/extension_action/extension_action_api.h" |
11 #include "chrome/browser/extensions/extension_action.h" | 11 #include "chrome/browser/extensions/extension_action.h" |
12 #include "chrome/browser/extensions/extension_view.h" | 12 #include "chrome/browser/extensions/extension_view.h" |
13 #include "chrome/browser/extensions/extension_view_host.h" | 13 #include "chrome/browser/extensions/extension_view_host.h" |
14 #include "chrome/browser/extensions/extension_view_host_factory.h" | 14 #include "chrome/browser/extensions/extension_view_host_factory.h" |
15 #include "chrome/browser/profiles/profile.h" | 15 #include "chrome/browser/profiles/profile.h" |
16 #include "chrome/browser/sessions/session_tab_helper.h" | 16 #include "chrome/browser/sessions/session_tab_helper.h" |
17 #include "chrome/browser/ui/browser.h" | 17 #include "chrome/browser/ui/browser.h" |
18 #include "chrome/browser/ui/extensions/accelerator_priority.h" | 18 #include "chrome/browser/ui/extensions/accelerator_priority.h" |
19 #include "chrome/browser/ui/extensions/extension_action_platform_delegate.h" | 19 #include "chrome/browser/ui/extensions/extension_action_platform_delegate.h" |
| 20 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
20 #include "chrome/browser/ui/toolbar/toolbar_action_view_delegate.h" | 21 #include "chrome/browser/ui/toolbar/toolbar_action_view_delegate.h" |
21 #include "chrome/browser/ui/toolbar/toolbar_actions_bar.h" | 22 #include "chrome/browser/ui/toolbar/toolbar_actions_bar.h" |
22 #include "chrome/browser/ui/toolbar/toolbar_actions_bar.h" | |
23 #include "chrome/common/extensions/api/extension_action/action_info.h" | 23 #include "chrome/common/extensions/api/extension_action/action_info.h" |
24 #include "chrome/common/icon_with_badge_image_source.h" | 24 #include "chrome/common/icon_with_badge_image_source.h" |
| 25 #include "chrome/common/pref_names.h" |
25 #include "extensions/browser/extension_host.h" | 26 #include "extensions/browser/extension_host.h" |
26 #include "extensions/browser/extension_registry.h" | 27 #include "extensions/browser/extension_registry.h" |
27 #include "extensions/common/extension.h" | 28 #include "extensions/common/extension.h" |
28 #include "extensions/common/feature_switch.h" | 29 #include "extensions/common/feature_switch.h" |
29 #include "extensions/common/manifest_constants.h" | 30 #include "extensions/common/manifest_constants.h" |
30 #include "ui/gfx/image/image_skia.h" | 31 #include "ui/gfx/image/image_skia.h" |
31 #include "ui/gfx/image/image_skia_operations.h" | 32 #include "ui/gfx/image/image_skia_operations.h" |
32 | 33 |
33 using extensions::ActionInfo; | 34 using extensions::ActionInfo; |
34 using extensions::CommandService; | 35 using extensions::CommandService; |
(...skipping 30 matching lines...) Expand all Loading... |
65 return extension_->id(); | 66 return extension_->id(); |
66 } | 67 } |
67 | 68 |
68 void ExtensionActionViewController::SetDelegate( | 69 void ExtensionActionViewController::SetDelegate( |
69 ToolbarActionViewDelegate* delegate) { | 70 ToolbarActionViewDelegate* delegate) { |
70 DCHECK((delegate == nullptr) ^ (view_delegate_ == nullptr)); | 71 DCHECK((delegate == nullptr) ^ (view_delegate_ == nullptr)); |
71 if (delegate) { | 72 if (delegate) { |
72 view_delegate_ = delegate; | 73 view_delegate_ = delegate; |
73 platform_delegate_->OnDelegateSet(); | 74 platform_delegate_->OnDelegateSet(); |
74 } else { | 75 } else { |
75 if (is_showing_popup()) | 76 if (popup_host_) |
76 HidePopup(); | 77 HidePopup(); |
77 platform_delegate_.reset(); | 78 platform_delegate_.reset(); |
78 view_delegate_ = nullptr; | 79 view_delegate_ = nullptr; |
79 } | 80 } |
80 } | 81 } |
81 | 82 |
82 gfx::Image ExtensionActionViewController::GetIcon( | 83 gfx::Image ExtensionActionViewController::GetIcon( |
83 content::WebContents* web_contents, | 84 content::WebContents* web_contents, |
84 const gfx::Size& size) { | 85 const gfx::Size& size) { |
85 if (!ExtensionIsValid()) | 86 if (!ExtensionIsValid()) |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
131 bool ExtensionActionViewController::HasPopup( | 132 bool ExtensionActionViewController::HasPopup( |
132 content::WebContents* web_contents) const { | 133 content::WebContents* web_contents) const { |
133 if (!ExtensionIsValid()) | 134 if (!ExtensionIsValid()) |
134 return false; | 135 return false; |
135 | 136 |
136 int tab_id = SessionTabHelper::IdForTab(web_contents); | 137 int tab_id = SessionTabHelper::IdForTab(web_contents); |
137 return (tab_id < 0) ? false : extension_action_->HasPopup(tab_id); | 138 return (tab_id < 0) ? false : extension_action_->HasPopup(tab_id); |
138 } | 139 } |
139 | 140 |
140 void ExtensionActionViewController::HidePopup() { | 141 void ExtensionActionViewController::HidePopup() { |
141 if (is_showing_popup()) { | 142 if (!is_showing_popup()) |
142 popup_host_->Close(); | 143 return; |
143 // We need to do these actions synchronously (instead of closing and then | 144 |
144 // performing the rest of the cleanup in OnExtensionHostDestroyed()) because | 145 popup_host_->Close(); |
145 // the extension host may close asynchronously, and we need to keep the view | 146 // We need to do these actions synchronously (instead of closing and then |
146 // delegate up-to-date. | 147 // performing the rest of the cleanup in OnExtensionHostDestroyed()) because |
147 if (popup_host_) | 148 // the extension host may close asynchronously, and we need to keep the view |
148 OnPopupClosed(); | 149 // delegate up-to-date. |
149 } | 150 if (popup_host_) |
| 151 OnPopupClosed(); |
150 } | 152 } |
151 | 153 |
152 gfx::NativeView ExtensionActionViewController::GetPopupNativeView() { | 154 gfx::NativeView ExtensionActionViewController::GetPopupNativeView() { |
153 return popup_host_ ? popup_host_->view()->GetNativeView() : nullptr; | 155 return popup_host_ ? popup_host_->view()->GetNativeView() : nullptr; |
154 } | 156 } |
155 | 157 |
156 ui::MenuModel* ExtensionActionViewController::GetContextMenu() { | 158 ui::MenuModel* ExtensionActionViewController::GetContextMenu() { |
157 if (!ExtensionIsValid() || !extension()->ShowConfigureContextMenus()) | 159 if (!ExtensionIsValid() || !extension()->ShowConfigureContextMenus()) |
158 return nullptr; | 160 return nullptr; |
159 | 161 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
195 bool grant_tab_permissions) { | 197 bool grant_tab_permissions) { |
196 if (!ExtensionIsValid()) | 198 if (!ExtensionIsValid()) |
197 return false; | 199 return false; |
198 | 200 |
199 if (extensions::ExtensionActionAPI::Get(browser_->profile()) | 201 if (extensions::ExtensionActionAPI::Get(browser_->profile()) |
200 ->ExecuteExtensionAction( | 202 ->ExecuteExtensionAction( |
201 extension_.get(), browser_, grant_tab_permissions) == | 203 extension_.get(), browser_, grant_tab_permissions) == |
202 ExtensionAction::ACTION_SHOW_POPUP) { | 204 ExtensionAction::ACTION_SHOW_POPUP) { |
203 GURL popup_url = extension_action_->GetPopupUrl( | 205 GURL popup_url = extension_action_->GetPopupUrl( |
204 SessionTabHelper::IdForTab(view_delegate_->GetCurrentWebContents())); | 206 SessionTabHelper::IdForTab(view_delegate_->GetCurrentWebContents())); |
205 return GetPreferredPopupViewController() | 207 |
206 ->TriggerPopupWithUrl(show_action, popup_url, grant_tab_permissions); | 208 if (extension_action_->open_in_sidebar()) |
| 209 return GetPreferredPopupViewController()->TriggerSidebarWithUrl( |
| 210 popup_url); |
| 211 else |
| 212 return GetPreferredPopupViewController()->TriggerPopupWithUrl( |
| 213 show_action, popup_url, grant_tab_permissions); |
207 } | 214 } |
208 return false; | 215 return false; |
209 } | 216 } |
210 | 217 |
211 void ExtensionActionViewController::RegisterCommand() { | 218 void ExtensionActionViewController::RegisterCommand() { |
212 if (!ExtensionIsValid()) | 219 if (!ExtensionIsValid()) |
213 return; | 220 return; |
214 | 221 |
215 platform_delegate_->RegisterCommand(); | 222 platform_delegate_->RegisterCommand(); |
216 } | 223 } |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
281 toolbar_actions_bar_->GetMainControllerForAction(this)); | 288 toolbar_actions_bar_->GetMainControllerForAction(this)); |
282 } | 289 } |
283 | 290 |
284 return this; | 291 return this; |
285 } | 292 } |
286 | 293 |
287 bool ExtensionActionViewController::TriggerPopupWithUrl( | 294 bool ExtensionActionViewController::TriggerPopupWithUrl( |
288 PopupShowAction show_action, | 295 PopupShowAction show_action, |
289 const GURL& popup_url, | 296 const GURL& popup_url, |
290 bool grant_tab_permissions) { | 297 bool grant_tab_permissions) { |
291 if (!ExtensionIsValid()) | 298 |
| 299 // If we were showing a popup already, then we treat the action to open the |
| 300 // same one as a desire to close it (like clicking a menu button that was |
| 301 // already open). |
| 302 if (is_showing_popup()) { |
| 303 HideActivePopup(); |
292 return false; | 304 return false; |
293 | 305 } |
294 bool already_showing = is_showing_popup(); | |
295 | 306 |
296 // Always hide the current popup, even if it's not owned by this extension. | 307 // Always hide the current popup, even if it's not owned by this extension. |
297 // Only one popup should be visible at a time. | 308 // Only one popup should be visible at a time. |
298 HideActivePopup(); | 309 HideActivePopup(); |
299 | 310 |
300 // If we were showing a popup already, then we treat the action to open the | |
301 // same one as a desire to close it (like clicking a menu button that was | |
302 // already open). | |
303 if (already_showing) | |
304 return false; | |
305 | |
306 scoped_ptr<extensions::ExtensionViewHost> host( | 311 scoped_ptr<extensions::ExtensionViewHost> host( |
307 extensions::ExtensionViewHostFactory::CreatePopupHost(popup_url, | 312 extensions::ExtensionViewHostFactory::CreatePopupHost(popup_url, |
308 browser_)); | 313 browser_)); |
309 if (!host) | 314 if (!host) |
310 return false; | 315 return false; |
311 | 316 |
312 popup_host_ = host.get(); | 317 popup_host_ = host.get(); |
313 popup_host_observer_.Add(popup_host_); | 318 popup_host_observer_.Add(popup_host_); |
314 if (toolbar_actions_bar_) | 319 if (toolbar_actions_bar_) |
315 toolbar_actions_bar_->SetPopupOwner(this); | 320 toolbar_actions_bar_->SetPopupOwner(this); |
316 | 321 |
317 if (toolbar_actions_bar_ && | 322 PressButtonWithSlideOutIfEnabled(base::Bind( |
318 !toolbar_actions_bar_->IsActionVisibleOnMainBar(this) && | 323 &ExtensionActionViewController::ShowPopup, weak_factory_.GetWeakPtr(), |
319 extensions::FeatureSwitch::extension_action_redesign()->IsEnabled()) { | 324 base::Passed(host.Pass()), grant_tab_permissions, show_action)); |
320 platform_delegate_->CloseOverflowMenu(); | |
321 toolbar_actions_bar_->PopOutAction( | |
322 this, | |
323 base::Bind(&ExtensionActionViewController::ShowPopup, | |
324 weak_factory_.GetWeakPtr(), | |
325 base::Passed(host.Pass()), | |
326 grant_tab_permissions, | |
327 show_action)); | |
328 } else { | |
329 ShowPopup(host.Pass(), grant_tab_permissions, show_action); | |
330 } | |
331 | 325 |
332 return true; | 326 return true; |
333 } | 327 } |
334 | 328 |
| 329 bool ExtensionActionViewController::TriggerSidebarWithUrl( |
| 330 const GURL& sidebar_url) { |
| 331 // Sidebar is only allowed via browser action |
| 332 if (ActionInfo::TYPE_BROWSER != extension_action_->action_type()) |
| 333 return false; |
| 334 |
| 335 DCHECK(toolbar_actions_bar_); |
| 336 |
| 337 if (sidebar_host_) { |
| 338 HideActiveSidebar(); |
| 339 return false; |
| 340 } |
| 341 |
| 342 HideActiveSidebar(); |
| 343 |
| 344 sidebar_host_.reset(extensions::ExtensionViewHostFactory::CreateSidebarHost( |
| 345 sidebar_url, browser_)); |
| 346 |
| 347 sidebar_host_->CreateRenderViewSoon(); |
| 348 sidebar_host_->host_contents()->SetInitialFocus(); |
| 349 |
| 350 DCHECK(toolbar_actions_bar_); |
| 351 toolbar_actions_bar_->SetSidebarOwner(this); |
| 352 |
| 353 PressButtonWithSlideOutIfEnabled( |
| 354 base::Bind(&ExtensionActionViewController::PressButton, |
| 355 weak_factory_.GetWeakPtr(), true)); |
| 356 return true; |
| 357 } |
| 358 |
335 void ExtensionActionViewController::ShowPopup( | 359 void ExtensionActionViewController::ShowPopup( |
336 scoped_ptr<extensions::ExtensionViewHost> popup_host, | 360 scoped_ptr<extensions::ExtensionViewHost> popup_host, |
337 bool grant_tab_permissions, | 361 bool grant_tab_permissions, |
338 PopupShowAction show_action) { | 362 PopupShowAction show_action) { |
339 // It's possible that the popup should be closed before it finishes opening | 363 // It's possible that the popup should be closed before it finishes opening |
340 // (since it can open asynchronously). Check before proceeding. | 364 // (since it can open asynchronously). Check before proceeding. |
341 if (!popup_host_) | 365 if (!popup_host_) |
342 return; | 366 return; |
343 platform_delegate_->ShowPopup( | 367 platform_delegate_->ShowPopup( |
344 popup_host.Pass(), grant_tab_permissions, show_action); | 368 popup_host.Pass(), grant_tab_permissions, show_action); |
345 view_delegate_->OnPopupShown(grant_tab_permissions); | 369 PressButton(grant_tab_permissions); |
346 } | 370 } |
347 | 371 |
348 void ExtensionActionViewController::OnPopupClosed() { | 372 void ExtensionActionViewController::OnPopupClosed() { |
349 popup_host_observer_.Remove(popup_host_); | 373 if (popup_host_) { |
350 popup_host_ = nullptr; | 374 popup_host_observer_.Remove(popup_host_); |
| 375 popup_host_ = nullptr; |
| 376 } |
| 377 if (toolbar_actions_bar_) |
| 378 toolbar_actions_bar_->SetPopupOwner(nullptr); |
| 379 |
| 380 RaiseButton(); |
| 381 } |
| 382 |
| 383 void ExtensionActionViewController::HideActiveSidebar() { |
| 384 DCHECK(toolbar_actions_bar_); |
| 385 DCHECK_EQ(ActionInfo::TYPE_BROWSER, extension_action_->action_type()); |
| 386 toolbar_actions_bar_->HideActiveSidebar(); |
| 387 } |
| 388 |
| 389 void ExtensionActionViewController::HideSidebar() { |
| 390 if (!sidebar_host_) |
| 391 return; |
| 392 |
| 393 sidebar_host_.reset(); |
| 394 if (toolbar_actions_bar_) |
| 395 toolbar_actions_bar_->SetSidebarOwner(nullptr); |
| 396 |
| 397 RaiseButton(); |
| 398 } |
| 399 |
| 400 void ExtensionActionViewController::RaiseButton() { |
| 401 // Reset button state |
351 if (toolbar_actions_bar_) { | 402 if (toolbar_actions_bar_) { |
352 toolbar_actions_bar_->SetPopupOwner(nullptr); | |
353 if (toolbar_actions_bar_->popped_out_action() == this && | 403 if (toolbar_actions_bar_->popped_out_action() == this && |
354 !view_delegate_->IsMenuRunning()) | 404 !view_delegate_->IsMenuRunning()) { |
355 toolbar_actions_bar_->UndoPopOut(); | 405 toolbar_actions_bar_->UndoPopOut(); |
| 406 } |
356 } | 407 } |
357 view_delegate_->OnPopupClosed(); | 408 view_delegate_->OnPopupClosed(); |
358 } | 409 } |
359 | 410 |
| 411 void ExtensionActionViewController::PressButtonWithSlideOutIfEnabled( |
| 412 const base::Closure& closure) { |
| 413 if (!toolbar_actions_bar_ || |
| 414 toolbar_actions_bar_->IsActionVisibleOnMainBar(this) || |
| 415 !extensions::FeatureSwitch::extension_action_redesign()->IsEnabled()) { |
| 416 closure.Run(); |
| 417 return; |
| 418 } |
| 419 |
| 420 // We disabled PopOutAction for sidebar |
| 421 if (extension_action_->open_in_sidebar()) { |
| 422 closure.Run(); |
| 423 return; |
| 424 } |
| 425 |
| 426 platform_delegate_->CloseOverflowMenu(); |
| 427 toolbar_actions_bar_->PopOutAction(this, closure); |
| 428 } |
| 429 |
| 430 void ExtensionActionViewController::PressButton(bool grant_tab_permissions) { |
| 431 view_delegate_->OnPopupShown(grant_tab_permissions); |
| 432 } |
| 433 |
360 scoped_ptr<IconWithBadgeImageSource> | 434 scoped_ptr<IconWithBadgeImageSource> |
361 ExtensionActionViewController::GetIconImageSource( | 435 ExtensionActionViewController::GetIconImageSource( |
362 content::WebContents* web_contents, | 436 content::WebContents* web_contents, |
363 const gfx::Size& size) { | 437 const gfx::Size& size) { |
364 int tab_id = SessionTabHelper::IdForTab(web_contents); | 438 int tab_id = SessionTabHelper::IdForTab(web_contents); |
365 scoped_ptr<IconWithBadgeImageSource> image_source( | 439 scoped_ptr<IconWithBadgeImageSource> image_source( |
366 new IconWithBadgeImageSource(size)); | 440 new IconWithBadgeImageSource(size)); |
367 image_source->SetIcon(icon_factory_.GetIcon(tab_id)); | 441 image_source->SetIcon(icon_factory_.GetIcon(tab_id)); |
368 scoped_ptr<IconWithBadgeImageSource::Badge> badge; | 442 scoped_ptr<IconWithBadgeImageSource::Badge> badge; |
369 std::string badge_text = extension_action_->GetBadgeText(tab_id); | 443 std::string badge_text = extension_action_->GetBadgeText(tab_id); |
(...skipping 15 matching lines...) Expand all Loading... |
385 // overflowed, we add a decoration so that the user can see which overflowed | 459 // overflowed, we add a decoration so that the user can see which overflowed |
386 // action wants to run (since they wouldn't be able to see the change from | 460 // action wants to run (since they wouldn't be able to see the change from |
387 // grayscale to color). | 461 // grayscale to color). |
388 bool is_overflow = | 462 bool is_overflow = |
389 toolbar_actions_bar_ && toolbar_actions_bar_->in_overflow_mode(); | 463 toolbar_actions_bar_ && toolbar_actions_bar_->in_overflow_mode(); |
390 image_source->set_paint_decoration(WantsToRun(web_contents) && is_overflow); | 464 image_source->set_paint_decoration(WantsToRun(web_contents) && is_overflow); |
391 } | 465 } |
392 | 466 |
393 return image_source.Pass(); | 467 return image_source.Pass(); |
394 } | 468 } |
OLD | NEW |