| 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 |