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(tab_helper); |
| 95 DCHECK(observe_download_progress || observe_install_stage); |
| 96 InstallTracker* install_tracker = |
| 97 InstallTrackerFactory::GetForBrowserContext(browser_context); |
| 98 if (install_tracker) |
| 99 install_observer_.Add(install_tracker); |
| 100 } |
| 101 ~InlineInstallObserver() override {} |
| 102 |
| 103 private: |
| 104 // InstallObserver: |
| 105 void OnBeginExtensionDownload(const std::string& extension_id) override { |
| 106 SendInstallStageChangedMessage(extension_id, |
| 107 api::webstore::INSTALL_STAGE_DOWNLOADING); |
| 108 } |
| 109 void OnDownloadProgress(const std::string& extension_id, |
| 110 int percent_downloaded) override { |
| 111 if (observe_download_progress_ && extension_id == extension_id_) { |
| 112 tab_helper_->Send(new ExtensionMsg_InlineInstallDownloadProgress( |
| 113 routing_id_, percent_downloaded)); |
| 114 } |
| 115 } |
| 116 void OnBeginCrxInstall(const std::string& extension_id) override { |
| 117 SendInstallStageChangedMessage(extension_id, |
| 118 api::webstore::INSTALL_STAGE_INSTALLING); |
| 119 } |
| 120 void OnShutdown() override { install_observer_.RemoveAll(); } |
| 121 |
| 122 void SendInstallStageChangedMessage(const std::string& extension_id, |
| 123 api::webstore::InstallStage stage) { |
| 124 if (observe_install_stage_ && extension_id == extension_id_) { |
| 125 tab_helper_->Send( |
| 126 new ExtensionMsg_InlineInstallStageChanged(routing_id_, stage)); |
| 127 } |
| 128 } |
| 129 |
| 130 // The owning TabHelper (guaranteed to be valid). |
| 131 TabHelper* const tab_helper_; |
| 132 |
| 133 // The routing id to use in sending IPC updates. |
| 134 int routing_id_; |
| 135 |
| 136 // The id of the extension to observe. |
| 137 std::string extension_id_; |
| 138 |
| 139 // Whether or not to observe download/install progress. |
| 140 const bool observe_download_progress_; |
| 141 const bool observe_install_stage_; |
| 142 |
| 143 ScopedObserver<InstallTracker, InstallObserver> install_observer_; |
| 144 |
| 145 DISALLOW_COPY_AND_ASSIGN(InlineInstallObserver); |
| 146 }; |
| 147 |
75 TabHelper::TabHelper(content::WebContents* web_contents) | 148 TabHelper::TabHelper(content::WebContents* web_contents) |
76 : content::WebContentsObserver(web_contents), | 149 : content::WebContentsObserver(web_contents), |
77 profile_(Profile::FromBrowserContext(web_contents->GetBrowserContext())), | 150 profile_(Profile::FromBrowserContext(web_contents->GetBrowserContext())), |
78 extension_app_(NULL), | 151 extension_app_(NULL), |
79 pending_web_app_action_(NONE), | 152 pending_web_app_action_(NONE), |
80 last_committed_nav_entry_unique_id_(0), | 153 last_committed_nav_entry_unique_id_(0), |
81 update_shortcut_on_load_complete_(false), | 154 update_shortcut_on_load_complete_(false), |
82 script_executor_( | 155 script_executor_( |
83 new ScriptExecutor(web_contents, &script_execution_observers_)), | 156 new ScriptExecutor(web_contents, &script_execution_observers_)), |
84 location_bar_controller_(new LocationBarController(web_contents)), | 157 location_bar_controller_(new LocationBarController(web_contents)), |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
354 const GURL& requestor_url, | 427 const GURL& requestor_url, |
355 int listeners_mask) { | 428 int listeners_mask) { |
356 // Check that the listener is reasonable. We should never get anything other | 429 // Check that the listener is reasonable. We should never get anything other |
357 // than an install stage listener, a download listener, or both. | 430 // than an install stage listener, a download listener, or both. |
358 if ((listeners_mask & ~(api::webstore::INSTALL_STAGE_LISTENER | | 431 if ((listeners_mask & ~(api::webstore::INSTALL_STAGE_LISTENER | |
359 api::webstore::DOWNLOAD_PROGRESS_LISTENER)) != 0 || | 432 api::webstore::DOWNLOAD_PROGRESS_LISTENER)) != 0 || |
360 requestor_url.is_empty()) { | 433 requestor_url.is_empty()) { |
361 NOTREACHED(); | 434 NOTREACHED(); |
362 return; | 435 return; |
363 } | 436 } |
| 437 |
| 438 if (pending_inline_installations_.count(webstore_item_id) != 0) { |
| 439 Send(new ExtensionMsg_InlineWebstoreInstallResponse( |
| 440 return_route_id, install_id, false, |
| 441 webstore_install::kInstallInProgressError, |
| 442 webstore_install::INSTALL_IN_PROGRESS)); |
| 443 return; |
| 444 } |
| 445 |
| 446 pending_inline_installations_.insert(webstore_item_id); |
364 // Inform the Webstore API that an inline install is happening, in case the | 447 // Inform the Webstore API that an inline install is happening, in case the |
365 // page requested status updates. | 448 // page requested status updates. |
366 ExtensionRegistry* registry = ExtensionRegistry::Get(profile_); | 449 ExtensionRegistry* registry = ExtensionRegistry::Get(profile_); |
367 if (registry->disabled_extensions().Contains(webstore_item_id) && | 450 if (registry->disabled_extensions().Contains(webstore_item_id) && |
368 (ExtensionPrefs::Get(profile_)->GetDisableReasons(webstore_item_id) & | 451 (ExtensionPrefs::Get(profile_)->GetDisableReasons(webstore_item_id) & |
369 Extension::DISABLE_PERMISSIONS_INCREASE) != 0) { | 452 Extension::DISABLE_PERMISSIONS_INCREASE) != 0) { |
370 // The extension was disabled due to permissions increase. Prompt for | 453 // The extension was disabled due to permissions increase. Prompt for |
371 // re-enable. | 454 // re-enable. |
372 // TODO(devlin): We should also prompt for re-enable for other reasons, | 455 // TODO(devlin): We should also prompt for re-enable for other reasons, |
373 // like user-disabled. | 456 // like user-disabled. |
374 // For clarity, explicitly end any prior reenable process. | 457 // For clarity, explicitly end any prior reenable process. |
375 extension_reenabler_.reset(); | 458 extension_reenabler_.reset(); |
376 extension_reenabler_ = ExtensionReenabler::PromptForReenable( | 459 extension_reenabler_ = ExtensionReenabler::PromptForReenable( |
377 registry->disabled_extensions().GetByID(webstore_item_id), | 460 registry->disabled_extensions().GetByID(webstore_item_id), profile_, |
378 profile_, | 461 web_contents(), requestor_url, |
379 web_contents(), | |
380 requestor_url, | |
381 base::Bind(&TabHelper::OnReenableComplete, | 462 base::Bind(&TabHelper::OnReenableComplete, |
382 weak_ptr_factory_.GetWeakPtr(), | 463 weak_ptr_factory_.GetWeakPtr(), install_id, |
383 install_id, | 464 return_route_id, webstore_item_id)); |
384 return_route_id)); | |
385 } else { | 465 } else { |
386 // TODO(devlin): We should adddress the case of the extension already | 466 // TODO(devlin): We should adddress the case of the extension already |
387 // being installed and enabled. | 467 // being installed and enabled. |
388 WebstoreAPI::Get(profile_)->OnInlineInstallStart( | 468 bool observe_download_progress = |
389 return_route_id, this, webstore_item_id, listeners_mask); | 469 (listeners_mask & api::webstore::DOWNLOAD_PROGRESS_LISTENER) != 0; |
| 470 bool observe_install_stage = |
| 471 (listeners_mask & api::webstore::INSTALL_STAGE_LISTENER) != 0; |
| 472 if (observe_install_stage || observe_download_progress) { |
| 473 DCHECK_EQ(0u, install_observers_.count(webstore_item_id)); |
| 474 install_observers_[webstore_item_id] = |
| 475 base::MakeUnique<InlineInstallObserver>( |
| 476 this, web_contents()->GetBrowserContext(), return_route_id, |
| 477 webstore_item_id, observe_download_progress, |
| 478 observe_install_stage); |
| 479 } |
390 | 480 |
391 WebstoreStandaloneInstaller::Callback callback = | 481 WebstoreStandaloneInstaller::Callback callback = base::Bind( |
392 base::Bind(&TabHelper::OnInlineInstallComplete, | 482 &TabHelper::OnInlineInstallComplete, weak_ptr_factory_.GetWeakPtr(), |
393 base::Unretained(this), | 483 install_id, return_route_id, webstore_item_id); |
394 install_id, | |
395 return_route_id); | |
396 scoped_refptr<WebstoreInlineInstaller> installer( | 484 scoped_refptr<WebstoreInlineInstaller> installer( |
397 webstore_inline_installer_factory_->CreateInstaller( | 485 webstore_inline_installer_factory_->CreateInstaller( |
398 web_contents(), host, webstore_item_id, requestor_url, callback)); | 486 web_contents(), host, webstore_item_id, requestor_url, callback)); |
399 installer->BeginInstall(); | 487 installer->BeginInstall(); |
400 } | 488 } |
401 } | 489 } |
402 | 490 |
403 void TabHelper::OnGetAppInstallState(content::RenderFrameHost* host, | 491 void TabHelper::OnGetAppInstallState(content::RenderFrameHost* host, |
404 const GURL& requestor_url, | 492 const GURL& requestor_url, |
405 int return_route_id, | 493 int return_route_id, |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
479 web_contents()->NotifyNavigationStateChanged(content::INVALIDATE_TYPE_TAB); | 567 web_contents()->NotifyNavigationStateChanged(content::INVALIDATE_TYPE_TAB); |
480 } | 568 } |
481 } | 569 } |
482 | 570 |
483 WindowController* TabHelper::GetExtensionWindowController() const { | 571 WindowController* TabHelper::GetExtensionWindowController() const { |
484 return ExtensionTabUtil::GetWindowControllerOfTab(web_contents()); | 572 return ExtensionTabUtil::GetWindowControllerOfTab(web_contents()); |
485 } | 573 } |
486 | 574 |
487 void TabHelper::OnReenableComplete(int install_id, | 575 void TabHelper::OnReenableComplete(int install_id, |
488 int return_route_id, | 576 int return_route_id, |
| 577 const std::string& extension_id, |
489 ExtensionReenabler::ReenableResult result) { | 578 ExtensionReenabler::ReenableResult result) { |
490 extension_reenabler_.reset(); | |
491 // Map the re-enable results to webstore-install results. | 579 // Map the re-enable results to webstore-install results. |
492 webstore_install::Result webstore_result = webstore_install::SUCCESS; | 580 webstore_install::Result webstore_result = webstore_install::SUCCESS; |
493 std::string error; | 581 std::string error; |
494 switch (result) { | 582 switch (result) { |
495 case ExtensionReenabler::REENABLE_SUCCESS: | 583 case ExtensionReenabler::REENABLE_SUCCESS: |
496 break; // already set | 584 break; // already set |
497 case ExtensionReenabler::USER_CANCELED: | 585 case ExtensionReenabler::USER_CANCELED: |
498 webstore_result = webstore_install::USER_CANCELLED; | 586 webstore_result = webstore_install::USER_CANCELLED; |
499 error = "User canceled install."; | 587 error = "User canceled install."; |
500 break; | 588 break; |
501 case ExtensionReenabler::NOT_ALLOWED: | 589 case ExtensionReenabler::NOT_ALLOWED: |
502 webstore_result = webstore_install::NOT_PERMITTED; | 590 webstore_result = webstore_install::NOT_PERMITTED; |
503 error = "Install not permitted."; | 591 error = "Install not permitted."; |
504 break; | 592 break; |
505 case ExtensionReenabler::ABORTED: | 593 case ExtensionReenabler::ABORTED: |
506 webstore_result = webstore_install::ABORTED; | 594 webstore_result = webstore_install::ABORTED; |
507 error = "Aborted due to tab closing."; | 595 error = "Aborted due to tab closing."; |
508 break; | 596 break; |
509 } | 597 } |
510 | 598 |
511 OnInlineInstallComplete(install_id, | 599 OnInlineInstallComplete(install_id, return_route_id, extension_id, |
512 return_route_id, | 600 result == ExtensionReenabler::REENABLE_SUCCESS, error, |
513 result == ExtensionReenabler::REENABLE_SUCCESS, | |
514 error, | |
515 webstore_result); | 601 webstore_result); |
| 602 // Note: ExtensionReenabler contained the callback with the curried-in |
| 603 // |extension_id|; delete it last. |
| 604 extension_reenabler_.reset(); |
516 } | 605 } |
517 | 606 |
518 void TabHelper::OnInlineInstallComplete(int install_id, | 607 void TabHelper::OnInlineInstallComplete(int install_id, |
519 int return_route_id, | 608 int return_route_id, |
| 609 const std::string& extension_id, |
520 bool success, | 610 bool success, |
521 const std::string& error, | 611 const std::string& error, |
522 webstore_install::Result result) { | 612 webstore_install::Result result) { |
| 613 DCHECK_EQ(1u, pending_inline_installations_.count(extension_id)); |
| 614 pending_inline_installations_.erase(extension_id); |
| 615 install_observers_.erase(extension_id); |
523 Send(new ExtensionMsg_InlineWebstoreInstallResponse( | 616 Send(new ExtensionMsg_InlineWebstoreInstallResponse( |
524 return_route_id, | 617 return_route_id, |
525 install_id, | 618 install_id, |
526 success, | 619 success, |
527 success ? std::string() : error, | 620 success ? std::string() : error, |
528 result)); | 621 result)); |
529 } | 622 } |
530 | 623 |
531 WebContents* TabHelper::GetAssociatedWebContents() const { | 624 WebContents* TabHelper::GetAssociatedWebContents() const { |
532 return web_contents(); | 625 return web_contents(); |
(...skipping 30 matching lines...) Expand all Loading... |
563 } | 656 } |
564 } | 657 } |
565 | 658 |
566 void TabHelper::SetTabId(content::RenderFrameHost* render_frame_host) { | 659 void TabHelper::SetTabId(content::RenderFrameHost* render_frame_host) { |
567 render_frame_host->Send( | 660 render_frame_host->Send( |
568 new ExtensionMsg_SetTabId(render_frame_host->GetRoutingID(), | 661 new ExtensionMsg_SetTabId(render_frame_host->GetRoutingID(), |
569 SessionTabHelper::IdForTab(web_contents()))); | 662 SessionTabHelper::IdForTab(web_contents()))); |
570 } | 663 } |
571 | 664 |
572 } // namespace extensions | 665 } // namespace extensions |
OLD | NEW |