Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/extensions/tab_helper.h" | 5 #include "chrome/browser/extensions/tab_helper.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/strings/string_util.h" | 8 #include "base/strings/string_util.h" |
| 9 #include "base/strings/utf_string_conversions.h" | 9 #include "base/strings/utf_string_conversions.h" |
| 10 #include "build/build_config.h" | 10 #include "build/build_config.h" |
| 11 #include "chrome/browser/chrome_notification_types.h" | 11 #include "chrome/browser/chrome_notification_types.h" |
| 12 #include "chrome/browser/extensions/activity_log/activity_log.h" | 12 #include "chrome/browser/extensions/activity_log/activity_log.h" |
| 13 #include "chrome/browser/extensions/api/declarative_content/chrome_content_rules _registry.h" | 13 #include "chrome/browser/extensions/api/declarative_content/chrome_content_rules _registry.h" |
| 14 #include "chrome/browser/extensions/api/extension_action/extension_action_api.h" | 14 #include "chrome/browser/extensions/api/extension_action/extension_action_api.h" |
| 15 #include "chrome/browser/extensions/api/webstore/webstore_api.h" | |
| 16 #include "chrome/browser/extensions/bookmark_app_helper.h" | 15 #include "chrome/browser/extensions/bookmark_app_helper.h" |
| 17 #include "chrome/browser/extensions/chrome_extension_web_contents_observer.h" | 16 #include "chrome/browser/extensions/chrome_extension_web_contents_observer.h" |
| 18 #include "chrome/browser/extensions/extension_action_runner.h" | 17 #include "chrome/browser/extensions/extension_action_runner.h" |
| 19 #include "chrome/browser/extensions/extension_tab_util.h" | 18 #include "chrome/browser/extensions/extension_tab_util.h" |
| 20 #include "chrome/browser/extensions/extension_util.h" | 19 #include "chrome/browser/extensions/extension_util.h" |
| 20 #include "chrome/browser/extensions/install_observer.h" | |
| 21 #include "chrome/browser/extensions/install_tracker.h" | |
| 22 #include "chrome/browser/extensions/install_tracker_factory.h" | |
| 21 #include "chrome/browser/extensions/location_bar_controller.h" | 23 #include "chrome/browser/extensions/location_bar_controller.h" |
| 22 #include "chrome/browser/extensions/webstore_inline_installer.h" | 24 #include "chrome/browser/extensions/webstore_inline_installer.h" |
| 23 #include "chrome/browser/extensions/webstore_inline_installer_factory.h" | 25 #include "chrome/browser/extensions/webstore_inline_installer_factory.h" |
| 24 #include "chrome/browser/profiles/profile.h" | 26 #include "chrome/browser/profiles/profile.h" |
| 25 #include "chrome/browser/sessions/session_tab_helper.h" | 27 #include "chrome/browser/sessions/session_tab_helper.h" |
| 26 #include "chrome/browser/shell_integration.h" | 28 #include "chrome/browser/shell_integration.h" |
| 27 #include "chrome/browser/ui/browser_commands.h" | 29 #include "chrome/browser/ui/browser_commands.h" |
| 28 #include "chrome/browser/ui/browser_dialogs.h" | 30 #include "chrome/browser/ui/browser_dialogs.h" |
| 29 #include "chrome/browser/ui/browser_finder.h" | 31 #include "chrome/browser/ui/browser_finder.h" |
| 30 #include "chrome/browser/web_applications/web_app.h" | 32 #include "chrome/browser/web_applications/web_app.h" |
| 33 #include "chrome/common/extensions/api/webstore/webstore_api_constants.h" | |
| 31 #include "chrome/common/extensions/chrome_extension_messages.h" | 34 #include "chrome/common/extensions/chrome_extension_messages.h" |
| 32 #include "chrome/common/extensions/extension_constants.h" | 35 #include "chrome/common/extensions/extension_constants.h" |
| 33 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" | 36 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" |
| 34 #include "chrome/common/render_messages.h" | 37 #include "chrome/common/render_messages.h" |
| 35 #include "chrome/common/url_constants.h" | 38 #include "chrome/common/url_constants.h" |
| 36 #include "content/public/browser/invalidate_type.h" | 39 #include "content/public/browser/invalidate_type.h" |
| 37 #include "content/public/browser/navigation_controller.h" | 40 #include "content/public/browser/navigation_controller.h" |
| 38 #include "content/public/browser/navigation_details.h" | 41 #include "content/public/browser/navigation_details.h" |
| 39 #include "content/public/browser/navigation_entry.h" | 42 #include "content/public/browser/navigation_entry.h" |
| 40 #include "content/public/browser/notification_service.h" | 43 #include "content/public/browser/notification_service.h" |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 65 #endif | 68 #endif |
| 66 | 69 |
| 67 using content::NavigationController; | 70 using content::NavigationController; |
| 68 using content::NavigationEntry; | 71 using content::NavigationEntry; |
| 69 using content::WebContents; | 72 using content::WebContents; |
| 70 | 73 |
| 71 DEFINE_WEB_CONTENTS_USER_DATA_KEY(extensions::TabHelper); | 74 DEFINE_WEB_CONTENTS_USER_DATA_KEY(extensions::TabHelper); |
| 72 | 75 |
| 73 namespace extensions { | 76 namespace extensions { |
| 74 | 77 |
| 78 // A helper class to watch the progress of inline installation and update the | |
| 79 // renderer. Owned by the TabHelper. | |
| 80 class TabHelper::InlineInstallObserver : public InstallObserver { | |
| 81 public: | |
| 82 InlineInstallObserver(TabHelper* tab_helper, | |
| 83 content::BrowserContext* browser_context, | |
| 84 int routing_id, | |
| 85 const std::string& extension_id, | |
| 86 bool observe_download_progress, | |
| 87 bool observe_install_stage) | |
| 88 : tab_helper_(tab_helper), | |
| 89 routing_id_(routing_id), | |
| 90 extension_id_(extension_id), | |
| 91 observe_download_progress_(observe_download_progress), | |
| 92 observe_install_stage_(observe_install_stage), | |
| 93 install_observer_(this) { | |
| 94 DCHECK(observe_download_progress || observe_install_stage); | |
|
lazyboy
2016/06/29 21:03:03
DCHECK(tab_helper_)
Devlin
2016/06/29 22:32:09
Sure, can't hurt.
| |
| 95 InstallTracker* install_tracker = | |
| 96 InstallTrackerFactory::GetForBrowserContext(browser_context); | |
| 97 if (install_tracker) | |
| 98 install_observer_.Add(install_tracker); | |
| 99 } | |
| 100 ~InlineInstallObserver() override {} | |
| 101 | |
| 102 private: | |
| 103 // InstallObserver: | |
| 104 void OnBeginExtensionDownload(const std::string& extension_id) override { | |
| 105 SendInstallStageChangedMessage(extension_id, | |
| 106 api::webstore::INSTALL_STAGE_DOWNLOADING); | |
| 107 } | |
| 108 void OnDownloadProgress(const std::string& extension_id, | |
| 109 int percent_downloaded) override { | |
| 110 if (observe_download_progress_ && extension_id == extension_id_) { | |
| 111 tab_helper_->Send(new ExtensionMsg_InlineInstallDownloadProgress( | |
| 112 routing_id_, percent_downloaded)); | |
| 113 } | |
| 114 } | |
| 115 void OnBeginCrxInstall(const std::string& extension_id) override { | |
| 116 SendInstallStageChangedMessage(extension_id, | |
| 117 api::webstore::INSTALL_STAGE_INSTALLING); | |
| 118 } | |
| 119 void OnShutdown() override { | |
| 120 install_observer_.RemoveAll(); | |
| 121 } | |
| 122 | |
| 123 void SendInstallStageChangedMessage(const std::string& extension_id, | |
| 124 api::webstore::InstallStage stage) { | |
| 125 if (observe_install_stage_ && extension_id == extension_id_) { | |
| 126 tab_helper_->Send(new ExtensionMsg_InlineInstallStageChanged( | |
| 127 routing_id_, stage)); | |
| 128 } | |
| 129 } | |
| 130 | |
| 131 // The owning TabHelper (guaranteed to be valid). | |
| 132 TabHelper* tab_helper_; | |
|
lazyboy
2016/06/29 21:03:04
Mark this and last two bool members const.
Devlin
2016/06/29 22:32:09
Done (assuming you mean TabHelper* const tab_helpe
lazyboy
2016/06/29 23:10:27
Yes that's what I meant.
, and not const TabHelper
| |
| 133 | |
| 134 // The routing id to use in sending IPC updates. | |
| 135 int routing_id_; | |
| 136 | |
| 137 // The id of the extension to observe. | |
| 138 std::string extension_id_; | |
| 139 | |
| 140 // Whether or not to observe download/install progress. | |
| 141 bool observe_download_progress_; | |
| 142 bool observe_install_stage_; | |
| 143 | |
| 144 ScopedObserver<InstallTracker, InstallObserver> install_observer_; | |
| 145 | |
| 146 DISALLOW_COPY_AND_ASSIGN(InlineInstallObserver); | |
| 147 }; | |
| 148 | |
| 75 TabHelper::TabHelper(content::WebContents* web_contents) | 149 TabHelper::TabHelper(content::WebContents* web_contents) |
| 76 : content::WebContentsObserver(web_contents), | 150 : content::WebContentsObserver(web_contents), |
| 77 profile_(Profile::FromBrowserContext(web_contents->GetBrowserContext())), | 151 profile_(Profile::FromBrowserContext(web_contents->GetBrowserContext())), |
| 78 extension_app_(NULL), | 152 extension_app_(NULL), |
| 79 pending_web_app_action_(NONE), | 153 pending_web_app_action_(NONE), |
| 80 last_committed_nav_entry_unique_id_(0), | 154 last_committed_nav_entry_unique_id_(0), |
| 81 update_shortcut_on_load_complete_(false), | 155 update_shortcut_on_load_complete_(false), |
| 82 script_executor_( | 156 script_executor_( |
| 83 new ScriptExecutor(web_contents, &script_execution_observers_)), | 157 new ScriptExecutor(web_contents, &script_execution_observers_)), |
| 84 location_bar_controller_(new LocationBarController(web_contents)), | 158 location_bar_controller_(new LocationBarController(web_contents)), |
| (...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 362 const GURL& requestor_url, | 436 const GURL& requestor_url, |
| 363 int listeners_mask) { | 437 int listeners_mask) { |
| 364 // Check that the listener is reasonable. We should never get anything other | 438 // Check that the listener is reasonable. We should never get anything other |
| 365 // than an install stage listener, a download listener, or both. | 439 // than an install stage listener, a download listener, or both. |
| 366 if ((listeners_mask & ~(api::webstore::INSTALL_STAGE_LISTENER | | 440 if ((listeners_mask & ~(api::webstore::INSTALL_STAGE_LISTENER | |
| 367 api::webstore::DOWNLOAD_PROGRESS_LISTENER)) != 0 || | 441 api::webstore::DOWNLOAD_PROGRESS_LISTENER)) != 0 || |
| 368 requestor_url.is_empty()) { | 442 requestor_url.is_empty()) { |
| 369 NOTREACHED(); | 443 NOTREACHED(); |
| 370 return; | 444 return; |
| 371 } | 445 } |
| 446 | |
| 447 if (pending_inline_installations_.count(webstore_item_id) != 0) { | |
|
lazyboy
2016/06/29 21:03:03
This seems like a new behavior? Test would be help
Devlin
2016/06/29 22:32:09
D'oh, I knew you would say that! ;)
So, looking i
lazyboy
2016/06/29 23:10:27
Thanks!
Devlin
2016/06/30 14:46:55
Filed a bug: 624614
| |
| 448 Send(new ExtensionMsg_InlineWebstoreInstallResponse( | |
| 449 return_route_id, | |
| 450 install_id, | |
| 451 false, | |
| 452 "An install is already in progress", | |
|
lazyboy
2016/06/29 21:03:03
This needs to be in a constant, pull out the const
Devlin
2016/06/29 22:32:09
Done.
| |
| 453 webstore_install::INSTALL_IN_PROGRESS)); | |
| 454 return; | |
| 455 } | |
| 456 | |
| 457 pending_inline_installations_.insert(webstore_item_id); | |
| 372 // Inform the Webstore API that an inline install is happening, in case the | 458 // Inform the Webstore API that an inline install is happening, in case the |
| 373 // page requested status updates. | 459 // page requested status updates. |
| 374 ExtensionRegistry* registry = ExtensionRegistry::Get(profile_); | 460 ExtensionRegistry* registry = ExtensionRegistry::Get(profile_); |
| 375 if (registry->disabled_extensions().Contains(webstore_item_id) && | 461 if (registry->disabled_extensions().Contains(webstore_item_id) && |
| 376 (ExtensionPrefs::Get(profile_)->GetDisableReasons(webstore_item_id) & | 462 (ExtensionPrefs::Get(profile_)->GetDisableReasons(webstore_item_id) & |
| 377 Extension::DISABLE_PERMISSIONS_INCREASE) != 0) { | 463 Extension::DISABLE_PERMISSIONS_INCREASE) != 0) { |
| 378 // The extension was disabled due to permissions increase. Prompt for | 464 // The extension was disabled due to permissions increase. Prompt for |
| 379 // re-enable. | 465 // re-enable. |
| 380 // TODO(devlin): We should also prompt for re-enable for other reasons, | 466 // TODO(devlin): We should also prompt for re-enable for other reasons, |
| 381 // like user-disabled. | 467 // like user-disabled. |
| 382 // For clarity, explicitly end any prior reenable process. | 468 // For clarity, explicitly end any prior reenable process. |
| 383 extension_reenabler_.reset(); | 469 extension_reenabler_.reset(); |
| 384 extension_reenabler_ = ExtensionReenabler::PromptForReenable( | 470 extension_reenabler_ = ExtensionReenabler::PromptForReenable( |
|
lazyboy
2016/06/29 21:03:03
It's not obvious to me how this will end up cleari
Devlin
2016/06/29 22:32:09
Acknowledged.
| |
| 385 registry->disabled_extensions().GetByID(webstore_item_id), | 471 registry->disabled_extensions().GetByID(webstore_item_id), |
| 386 profile_, | 472 profile_, |
| 387 web_contents(), | 473 web_contents(), |
| 388 requestor_url, | 474 requestor_url, |
| 389 base::Bind(&TabHelper::OnReenableComplete, | 475 base::Bind(&TabHelper::OnReenableComplete, |
| 390 weak_ptr_factory_.GetWeakPtr(), | 476 weak_ptr_factory_.GetWeakPtr(), |
| 391 install_id, | 477 install_id, |
| 392 return_route_id)); | 478 return_route_id, |
| 479 webstore_item_id)); | |
| 393 } else { | 480 } else { |
| 394 // TODO(devlin): We should adddress the case of the extension already | 481 // TODO(devlin): We should adddress the case of the extension already |
|
lazyboy
2016/06/29 21:03:04
Doesn't the beginning of the function prevent this
Devlin
2016/06/29 22:32:09
Nope. The beginning prevents two inline installat
lazyboy
2016/06/29 23:10:27
Acknowledged.
| |
| 395 // being installed and enabled. | 482 // being installed and enabled. |
| 396 WebstoreAPI::Get(profile_)->OnInlineInstallStart( | 483 bool observe_download_progress = |
| 397 return_route_id, this, webstore_item_id, listeners_mask); | 484 (listeners_mask & api::webstore::DOWNLOAD_PROGRESS_LISTENER) != 0; |
| 485 bool observe_install_stage = | |
| 486 (listeners_mask & api::webstore::INSTALL_STAGE_LISTENER) != 0; | |
| 487 if (observe_install_stage || observe_download_progress) { | |
| 488 DCHECK(install_observers_.find(webstore_item_id) == | |
|
lazyboy
2016/06/29 21:03:03
can use install_observers_.count(webstore_item_id)
Devlin
2016/06/29 22:32:09
Done.
| |
| 489 install_observers_.end()); | |
| 490 install_observers_[webstore_item_id] = | |
| 491 base::MakeUnique<InlineInstallObserver>( | |
| 492 this, web_contents()->GetBrowserContext(), return_route_id, | |
| 493 webstore_item_id, observe_download_progress, | |
| 494 observe_install_stage); | |
| 495 } | |
| 398 | 496 |
| 399 WebstoreStandaloneInstaller::Callback callback = | 497 WebstoreStandaloneInstaller::Callback callback = |
| 400 base::Bind(&TabHelper::OnInlineInstallComplete, | 498 base::Bind(&TabHelper::OnInlineInstallComplete, |
| 401 base::Unretained(this), | 499 weak_ptr_factory_.GetWeakPtr(), |
| 402 install_id, | 500 install_id, |
| 403 return_route_id); | 501 return_route_id, |
| 502 webstore_item_id); | |
| 404 scoped_refptr<WebstoreInlineInstaller> installer( | 503 scoped_refptr<WebstoreInlineInstaller> installer( |
| 405 webstore_inline_installer_factory_->CreateInstaller( | 504 webstore_inline_installer_factory_->CreateInstaller( |
| 406 web_contents(), host, webstore_item_id, requestor_url, callback)); | 505 web_contents(), host, webstore_item_id, requestor_url, callback)); |
| 407 installer->BeginInstall(); | 506 installer->BeginInstall(); |
| 408 } | 507 } |
| 409 } | 508 } |
| 410 | 509 |
| 411 void TabHelper::OnGetAppInstallState(content::RenderFrameHost* host, | 510 void TabHelper::OnGetAppInstallState(content::RenderFrameHost* host, |
| 412 const GURL& requestor_url, | 511 const GURL& requestor_url, |
| 413 int return_route_id, | 512 int return_route_id, |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 487 web_contents()->NotifyNavigationStateChanged(content::INVALIDATE_TYPE_TAB); | 586 web_contents()->NotifyNavigationStateChanged(content::INVALIDATE_TYPE_TAB); |
| 488 } | 587 } |
| 489 } | 588 } |
| 490 | 589 |
| 491 WindowController* TabHelper::GetExtensionWindowController() const { | 590 WindowController* TabHelper::GetExtensionWindowController() const { |
| 492 return ExtensionTabUtil::GetWindowControllerOfTab(web_contents()); | 591 return ExtensionTabUtil::GetWindowControllerOfTab(web_contents()); |
| 493 } | 592 } |
| 494 | 593 |
| 495 void TabHelper::OnReenableComplete(int install_id, | 594 void TabHelper::OnReenableComplete(int install_id, |
| 496 int return_route_id, | 595 int return_route_id, |
| 596 const std::string& extension_id, | |
| 497 ExtensionReenabler::ReenableResult result) { | 597 ExtensionReenabler::ReenableResult result) { |
| 498 extension_reenabler_.reset(); | |
| 499 // Map the re-enable results to webstore-install results. | 598 // Map the re-enable results to webstore-install results. |
| 500 webstore_install::Result webstore_result = webstore_install::SUCCESS; | 599 webstore_install::Result webstore_result = webstore_install::SUCCESS; |
| 501 std::string error; | 600 std::string error; |
| 502 switch (result) { | 601 switch (result) { |
| 503 case ExtensionReenabler::REENABLE_SUCCESS: | 602 case ExtensionReenabler::REENABLE_SUCCESS: |
| 504 break; // already set | 603 break; // already set |
| 505 case ExtensionReenabler::USER_CANCELED: | 604 case ExtensionReenabler::USER_CANCELED: |
| 506 webstore_result = webstore_install::USER_CANCELLED; | 605 webstore_result = webstore_install::USER_CANCELLED; |
| 507 error = "User canceled install."; | 606 error = "User canceled install."; |
| 508 break; | 607 break; |
| 509 case ExtensionReenabler::NOT_ALLOWED: | 608 case ExtensionReenabler::NOT_ALLOWED: |
| 510 webstore_result = webstore_install::NOT_PERMITTED; | 609 webstore_result = webstore_install::NOT_PERMITTED; |
| 511 error = "Install not permitted."; | 610 error = "Install not permitted."; |
| 512 break; | 611 break; |
| 513 case ExtensionReenabler::ABORTED: | 612 case ExtensionReenabler::ABORTED: |
| 514 webstore_result = webstore_install::ABORTED; | 613 webstore_result = webstore_install::ABORTED; |
| 515 error = "Aborted due to tab closing."; | 614 error = "Aborted due to tab closing."; |
| 516 break; | 615 break; |
| 517 } | 616 } |
| 518 | 617 |
| 519 OnInlineInstallComplete(install_id, | 618 OnInlineInstallComplete(install_id, |
| 520 return_route_id, | 619 return_route_id, |
| 620 extension_id, | |
| 521 result == ExtensionReenabler::REENABLE_SUCCESS, | 621 result == ExtensionReenabler::REENABLE_SUCCESS, |
| 522 error, | 622 error, |
| 523 webstore_result); | 623 webstore_result); |
| 624 // Note: ExtensionReenabler contained the callback with the curried-in | |
| 625 // extension id; delete it last. | |
|
lazyboy
2016/06/29 21:03:03
|extension_id|?
Devlin
2016/06/29 22:32:09
Done.
| |
| 626 extension_reenabler_.reset(); | |
| 524 } | 627 } |
| 525 | 628 |
| 526 void TabHelper::OnInlineInstallComplete(int install_id, | 629 void TabHelper::OnInlineInstallComplete(int install_id, |
| 527 int return_route_id, | 630 int return_route_id, |
| 631 const std::string& extension_id, | |
| 528 bool success, | 632 bool success, |
| 529 const std::string& error, | 633 const std::string& error, |
| 530 webstore_install::Result result) { | 634 webstore_install::Result result) { |
| 635 DCHECK_EQ(1u, pending_inline_installations_.count(extension_id)); | |
| 636 pending_inline_installations_.erase(extension_id); | |
| 637 install_observers_.erase(extension_id); | |
| 531 Send(new ExtensionMsg_InlineWebstoreInstallResponse( | 638 Send(new ExtensionMsg_InlineWebstoreInstallResponse( |
| 532 return_route_id, | 639 return_route_id, |
| 533 install_id, | 640 install_id, |
| 534 success, | 641 success, |
| 535 success ? std::string() : error, | 642 success ? std::string() : error, |
| 536 result)); | 643 result)); |
| 537 } | 644 } |
| 538 | 645 |
| 539 WebContents* TabHelper::GetAssociatedWebContents() const { | 646 WebContents* TabHelper::GetAssociatedWebContents() const { |
| 540 return web_contents(); | 647 return web_contents(); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 580 } | 687 } |
| 581 } | 688 } |
| 582 | 689 |
| 583 void TabHelper::SetTabId(content::RenderFrameHost* render_frame_host) { | 690 void TabHelper::SetTabId(content::RenderFrameHost* render_frame_host) { |
| 584 render_frame_host->Send( | 691 render_frame_host->Send( |
| 585 new ExtensionMsg_SetTabId(render_frame_host->GetRoutingID(), | 692 new ExtensionMsg_SetTabId(render_frame_host->GetRoutingID(), |
| 586 SessionTabHelper::IdForTab(web_contents()))); | 693 SessionTabHelper::IdForTab(web_contents()))); |
| 587 } | 694 } |
| 588 | 695 |
| 589 } // namespace extensions | 696 } // namespace extensions |
| OLD | NEW |