| 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/api/webstore_private/webstore_private_api.h" | 5 #include "chrome/browser/extensions/api/webstore_private/webstore_private_api.h" |
| 6 | 6 |
| 7 #include "apps/app_launcher.h" | 7 #include "apps/app_launcher.h" |
| 8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 45 #include "grit/generated_resources.h" | 45 #include "grit/generated_resources.h" |
| 46 #include "ui/base/l10n/l10n_util.h" | 46 #include "ui/base/l10n/l10n_util.h" |
| 47 | 47 |
| 48 using content::GpuDataManager; | 48 using content::GpuDataManager; |
| 49 | 49 |
| 50 namespace extensions { | 50 namespace extensions { |
| 51 | 51 |
| 52 namespace { | 52 namespace { |
| 53 | 53 |
| 54 // Holds the Approvals between the time we prompt and start the installs. | 54 // Holds the Approvals between the time we prompt and start the installs. |
| 55 struct PendingApprovals { | 55 class PendingApprovals { |
| 56 typedef ScopedVector<WebstoreInstaller::Approval> ApprovalList; | 56 public: |
| 57 | |
| 58 PendingApprovals(); | 57 PendingApprovals(); |
| 59 ~PendingApprovals(); | 58 ~PendingApprovals(); |
| 60 | 59 |
| 61 void PushApproval(scoped_ptr<WebstoreInstaller::Approval> approval); | 60 void PushApproval(scoped_ptr<WebstoreInstaller::Approval> approval); |
| 62 scoped_ptr<WebstoreInstaller::Approval> PopApproval( | 61 scoped_ptr<WebstoreInstaller::Approval> PopApproval( |
| 63 Profile* profile, const std::string& id); | 62 Profile* profile, const std::string& id); |
| 63 private: |
| 64 typedef ScopedVector<WebstoreInstaller::Approval> ApprovalList; |
| 64 | 65 |
| 65 ApprovalList approvals; | 66 ApprovalList approvals_; |
| 67 |
| 68 DISALLOW_COPY_AND_ASSIGN(PendingApprovals); |
| 66 }; | 69 }; |
| 67 | 70 |
| 68 PendingApprovals::PendingApprovals() {} | 71 PendingApprovals::PendingApprovals() {} |
| 69 PendingApprovals::~PendingApprovals() {} | 72 PendingApprovals::~PendingApprovals() {} |
| 70 | 73 |
| 71 void PendingApprovals::PushApproval( | 74 void PendingApprovals::PushApproval( |
| 72 scoped_ptr<WebstoreInstaller::Approval> approval) { | 75 scoped_ptr<WebstoreInstaller::Approval> approval) { |
| 73 approvals.push_back(approval.release()); | 76 approvals_.push_back(approval.release()); |
| 74 } | 77 } |
| 75 | 78 |
| 76 scoped_ptr<WebstoreInstaller::Approval> PendingApprovals::PopApproval( | 79 scoped_ptr<WebstoreInstaller::Approval> PendingApprovals::PopApproval( |
| 77 Profile* profile, const std::string& id) { | 80 Profile* profile, const std::string& id) { |
| 78 for (size_t i = 0; i < approvals.size(); ++i) { | 81 for (size_t i = 0; i < approvals_.size(); ++i) { |
| 79 WebstoreInstaller::Approval* approval = approvals[i]; | 82 WebstoreInstaller::Approval* approval = approvals_[i]; |
| 80 if (approval->extension_id == id && | 83 if (approval->extension_id == id && |
| 81 profile->IsSameProfile(approval->profile)) { | 84 profile->IsSameProfile(approval->profile)) { |
| 82 approvals.weak_erase(approvals.begin() + i); | 85 approvals_.weak_erase(approvals_.begin() + i); |
| 83 return scoped_ptr<WebstoreInstaller::Approval>(approval); | 86 return scoped_ptr<WebstoreInstaller::Approval>(approval); |
| 84 } | 87 } |
| 85 } | 88 } |
| 86 return scoped_ptr<WebstoreInstaller::Approval>(NULL); | 89 return scoped_ptr<WebstoreInstaller::Approval>(NULL); |
| 87 } | 90 } |
| 88 | 91 |
| 92 // Uniquely holds the profile and extension id of an install between the time we |
| 93 // prompt and complete the installs. |
| 94 class PendingInstalls { |
| 95 public: |
| 96 PendingInstalls(); |
| 97 ~PendingInstalls(); |
| 98 |
| 99 bool InsertInstall(Profile* profile, const std::string& id); |
| 100 void EraseInstall(Profile* profile, const std::string& id); |
| 101 private: |
| 102 typedef std::pair<Profile*, std::string> ProfileAndExtensionId; |
| 103 typedef std::vector<ProfileAndExtensionId> InstallList; |
| 104 |
| 105 InstallList::iterator FindInstall(Profile* profile, const std::string& id); |
| 106 |
| 107 InstallList installs_; |
| 108 |
| 109 DISALLOW_COPY_AND_ASSIGN(PendingInstalls); |
| 110 }; |
| 111 |
| 112 PendingInstalls::PendingInstalls() {} |
| 113 PendingInstalls::~PendingInstalls() {} |
| 114 |
| 115 // Returns true and inserts the profile/id pair if it is not present. Otherwise |
| 116 // returns false. |
| 117 bool PendingInstalls::InsertInstall(Profile* profile, const std::string& id) { |
| 118 if (FindInstall(profile, id) != installs_.end()) |
| 119 return false; |
| 120 installs_.push_back(make_pair(profile, id)); |
| 121 return true; |
| 122 } |
| 123 |
| 124 // Removes the given profile/id pair. |
| 125 void PendingInstalls::EraseInstall(Profile* profile, const std::string& id) { |
| 126 InstallList::iterator it = FindInstall(profile, id); |
| 127 if (it != installs_.end()) |
| 128 installs_.erase(it); |
| 129 } |
| 130 |
| 131 PendingInstalls::InstallList::iterator PendingInstalls::FindInstall( |
| 132 Profile* profile, |
| 133 const std::string& id) { |
| 134 for (size_t i = 0; i < installs_.size(); ++i) { |
| 135 ProfileAndExtensionId install = installs_[i]; |
| 136 if (install.second == id && profile->IsSameProfile(install.first)) |
| 137 return (installs_.begin() + i); |
| 138 } |
| 139 return installs_.end(); |
| 140 } |
| 141 |
| 89 static base::LazyInstance<PendingApprovals> g_pending_approvals = | 142 static base::LazyInstance<PendingApprovals> g_pending_approvals = |
| 90 LAZY_INSTANCE_INITIALIZER; | 143 LAZY_INSTANCE_INITIALIZER; |
| 144 static base::LazyInstance<PendingInstalls> g_pending_installs = |
| 145 LAZY_INSTANCE_INITIALIZER; |
| 91 | 146 |
| 92 const char kAppInstallBubbleKey[] = "appInstallBubble"; | 147 const char kAppInstallBubbleKey[] = "appInstallBubble"; |
| 93 const char kEnableLauncherKey[] = "enableLauncher"; | 148 const char kEnableLauncherKey[] = "enableLauncher"; |
| 94 const char kIconDataKey[] = "iconData"; | 149 const char kIconDataKey[] = "iconData"; |
| 95 const char kIconUrlKey[] = "iconUrl"; | 150 const char kIconUrlKey[] = "iconUrl"; |
| 96 const char kIdKey[] = "id"; | 151 const char kIdKey[] = "id"; |
| 97 const char kLocalizedNameKey[] = "localizedName"; | 152 const char kLocalizedNameKey[] = "localizedName"; |
| 98 const char kLoginKey[] = "login"; | 153 const char kLoginKey[] = "login"; |
| 99 const char kManifestKey[] = "manifest"; | 154 const char kManifestKey[] = "manifest"; |
| 100 | 155 |
| 101 // A preference set by the web store to indicate login information for | 156 // A preference set by the web store to indicate login information for |
| 102 // purchased apps. | 157 // purchased apps. |
| 103 const char kWebstoreLogin[] = "extensions.webstore_login"; | 158 const char kWebstoreLogin[] = "extensions.webstore_login"; |
| 104 | 159 const char kAlreadyInstalledError[] = "This item is already installed"; |
| 105 const char kCannotSpecifyIconDataAndUrlError[] = | 160 const char kCannotSpecifyIconDataAndUrlError[] = |
| 106 "You cannot specify both icon data and an icon url"; | 161 "You cannot specify both icon data and an icon url"; |
| 107 const char kInvalidIconUrlError[] = "Invalid icon url"; | 162 const char kInvalidIconUrlError[] = "Invalid icon url"; |
| 108 const char kInvalidIdError[] = "Invalid id"; | 163 const char kInvalidIdError[] = "Invalid id"; |
| 109 const char kInvalidManifestError[] = "Invalid manifest"; | 164 const char kInvalidManifestError[] = "Invalid manifest"; |
| 110 const char kNoPreviousBeginInstallWithManifestError[] = | 165 const char kNoPreviousBeginInstallWithManifestError[] = |
| 111 "* does not match a previous call to beginInstallWithManifest3"; | 166 "* does not match a previous call to beginInstallWithManifest3"; |
| 112 const char kUserCancelledError[] = "User cancelled install"; | 167 const char kUserCancelledError[] = "User cancelled install"; |
| 113 | 168 |
| 114 // Helper to create a dictionary with login properties set from the appropriate | 169 // Helper to create a dictionary with login properties set from the appropriate |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 270 &localized_name_)); | 325 &localized_name_)); |
| 271 | 326 |
| 272 if (details->HasKey(kAppInstallBubbleKey)) | 327 if (details->HasKey(kAppInstallBubbleKey)) |
| 273 EXTENSION_FUNCTION_VALIDATE(details->GetBoolean( | 328 EXTENSION_FUNCTION_VALIDATE(details->GetBoolean( |
| 274 kAppInstallBubbleKey, &use_app_installed_bubble_)); | 329 kAppInstallBubbleKey, &use_app_installed_bubble_)); |
| 275 | 330 |
| 276 if (details->HasKey(kEnableLauncherKey)) | 331 if (details->HasKey(kEnableLauncherKey)) |
| 277 EXTENSION_FUNCTION_VALIDATE(details->GetBoolean( | 332 EXTENSION_FUNCTION_VALIDATE(details->GetBoolean( |
| 278 kEnableLauncherKey, &enable_launcher_)); | 333 kEnableLauncherKey, &enable_launcher_)); |
| 279 | 334 |
| 335 ExtensionService* service = |
| 336 extensions::ExtensionSystem::Get(profile_)->extension_service(); |
| 337 if (service->GetInstalledExtension(id_) || |
| 338 !g_pending_installs.Get().InsertInstall(profile_, id_)) { |
| 339 SetResultCode(ALREADY_INSTALLED); |
| 340 error_ = kAlreadyInstalledError; |
| 341 return false; |
| 342 } |
| 343 |
| 280 net::URLRequestContextGetter* context_getter = NULL; | 344 net::URLRequestContextGetter* context_getter = NULL; |
| 281 if (!icon_url.is_empty()) | 345 if (!icon_url.is_empty()) |
| 282 context_getter = profile()->GetRequestContext(); | 346 context_getter = profile()->GetRequestContext(); |
| 283 | 347 |
| 284 scoped_refptr<WebstoreInstallHelper> helper = new WebstoreInstallHelper( | 348 scoped_refptr<WebstoreInstallHelper> helper = new WebstoreInstallHelper( |
| 285 this, id_, manifest_, icon_data_, icon_url, context_getter); | 349 this, id_, manifest_, icon_data_, icon_url, context_getter); |
| 286 | 350 |
| 287 // The helper will call us back via OnWebstoreParseSuccess or | 351 // The helper will call us back via OnWebstoreParseSuccess or |
| 288 // OnWebstoreParseFailure. | 352 // OnWebstoreParseFailure. |
| 289 helper->Start(); | 353 helper->Start(); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 319 break; | 383 break; |
| 320 case PERMISSION_DENIED: | 384 case PERMISSION_DENIED: |
| 321 SetResult(Value::CreateStringValue("permission_denied")); | 385 SetResult(Value::CreateStringValue("permission_denied")); |
| 322 break; | 386 break; |
| 323 case INVALID_ICON_URL: | 387 case INVALID_ICON_URL: |
| 324 SetResult(Value::CreateStringValue("invalid_icon_url")); | 388 SetResult(Value::CreateStringValue("invalid_icon_url")); |
| 325 break; | 389 break; |
| 326 case SIGNIN_FAILED: | 390 case SIGNIN_FAILED: |
| 327 SetResult(Value::CreateStringValue("signin_failed")); | 391 SetResult(Value::CreateStringValue("signin_failed")); |
| 328 break; | 392 break; |
| 393 case ALREADY_INSTALLED: |
| 394 SetResult(Value::CreateStringValue("already_installed")); |
| 395 break; |
| 329 default: | 396 default: |
| 330 CHECK(false); | 397 CHECK(false); |
| 331 } | 398 } |
| 332 } | 399 } |
| 333 | 400 |
| 334 void BeginInstallWithManifestFunction::OnWebstoreParseSuccess( | 401 void BeginInstallWithManifestFunction::OnWebstoreParseSuccess( |
| 335 const std::string& id, | 402 const std::string& id, |
| 336 const SkBitmap& icon, | 403 const SkBitmap& icon, |
| 337 DictionaryValue* parsed_manifest) { | 404 DictionaryValue* parsed_manifest) { |
| 338 CHECK_EQ(id_, id); | 405 CHECK_EQ(id_, id); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 381 case WebstoreInstallHelper::Delegate::ICON_ERROR: | 448 case WebstoreInstallHelper::Delegate::ICON_ERROR: |
| 382 SetResultCode(ICON_ERROR); | 449 SetResultCode(ICON_ERROR); |
| 383 break; | 450 break; |
| 384 case WebstoreInstallHelper::Delegate::MANIFEST_ERROR: | 451 case WebstoreInstallHelper::Delegate::MANIFEST_ERROR: |
| 385 SetResultCode(MANIFEST_ERROR); | 452 SetResultCode(MANIFEST_ERROR); |
| 386 break; | 453 break; |
| 387 default: | 454 default: |
| 388 CHECK(false); | 455 CHECK(false); |
| 389 } | 456 } |
| 390 error_ = error_message; | 457 error_ = error_message; |
| 458 g_pending_installs.Get().EraseInstall(profile_, id); |
| 391 SendResponse(false); | 459 SendResponse(false); |
| 392 | 460 |
| 393 // Matches the AddRef in RunImpl(). | 461 // Matches the AddRef in RunImpl(). |
| 394 Release(); | 462 Release(); |
| 395 } | 463 } |
| 396 | 464 |
| 397 void BeginInstallWithManifestFunction::GaiaCredentialsValid() {} | 465 void BeginInstallWithManifestFunction::GaiaCredentialsValid() {} |
| 398 | 466 |
| 399 void BeginInstallWithManifestFunction::SigninFailed( | 467 void BeginInstallWithManifestFunction::SigninFailed( |
| 400 const GoogleServiceAuthError& error) { | 468 const GoogleServiceAuthError& error) { |
| 401 signin_tracker_.reset(); | 469 signin_tracker_.reset(); |
| 402 | 470 |
| 403 SetResultCode(SIGNIN_FAILED); | 471 SetResultCode(SIGNIN_FAILED); |
| 404 error_ = error.ToString(); | 472 error_ = error.ToString(); |
| 473 g_pending_installs.Get().EraseInstall(profile_, id_); |
| 405 SendResponse(false); | 474 SendResponse(false); |
| 406 | 475 |
| 407 // Matches the AddRef in RunImpl(). | 476 // Matches the AddRef in RunImpl(). |
| 408 Release(); | 477 Release(); |
| 409 } | 478 } |
| 410 | 479 |
| 411 void BeginInstallWithManifestFunction::SigninSuccess() { | 480 void BeginInstallWithManifestFunction::SigninSuccess() { |
| 412 signin_tracker_.reset(); | 481 signin_tracker_.reset(); |
| 413 | 482 |
| 414 SigninCompletedOrNotNeeded(); | 483 SigninCompletedOrNotNeeded(); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 448 ExtensionService::RecordPermissionMessagesHistogram( | 517 ExtensionService::RecordPermissionMessagesHistogram( |
| 449 dummy_extension_, "Extensions.Permissions_WebStoreInstall"); | 518 dummy_extension_, "Extensions.Permissions_WebStoreInstall"); |
| 450 | 519 |
| 451 // Matches the AddRef in RunImpl(). | 520 // Matches the AddRef in RunImpl(). |
| 452 Release(); | 521 Release(); |
| 453 } | 522 } |
| 454 | 523 |
| 455 void BeginInstallWithManifestFunction::InstallUIAbort(bool user_initiated) { | 524 void BeginInstallWithManifestFunction::InstallUIAbort(bool user_initiated) { |
| 456 error_ = kUserCancelledError; | 525 error_ = kUserCancelledError; |
| 457 SetResultCode(USER_CANCELLED); | 526 SetResultCode(USER_CANCELLED); |
| 527 g_pending_installs.Get().EraseInstall(profile_, id_); |
| 458 SendResponse(false); | 528 SendResponse(false); |
| 459 | 529 |
| 460 // The web store install histograms are a subset of the install histograms. | 530 // The web store install histograms are a subset of the install histograms. |
| 461 // We need to record both histograms here since CrxInstaller::InstallUIAbort | 531 // We need to record both histograms here since CrxInstaller::InstallUIAbort |
| 462 // is never called for web store install cancellations. | 532 // is never called for web store install cancellations. |
| 463 std::string histogram_name = user_initiated ? | 533 std::string histogram_name = user_initiated ? |
| 464 "Extensions.Permissions_WebStoreInstallCancel" : | 534 "Extensions.Permissions_WebStoreInstallCancel" : |
| 465 "Extensions.Permissions_WebStoreInstallAbort"; | 535 "Extensions.Permissions_WebStoreInstallAbort"; |
| 466 ExtensionService::RecordPermissionMessagesHistogram( | 536 ExtensionService::RecordPermissionMessagesHistogram( |
| 467 dummy_extension_, histogram_name.c_str()); | 537 dummy_extension_, histogram_name.c_str()); |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 545 id, approval_.Pass(), WebstoreInstaller::FLAG_NONE); | 615 id, approval_.Pass(), WebstoreInstaller::FLAG_NONE); |
| 546 installer->Start(); | 616 installer->Start(); |
| 547 } | 617 } |
| 548 | 618 |
| 549 void CompleteInstallFunction::OnExtensionInstallSuccess( | 619 void CompleteInstallFunction::OnExtensionInstallSuccess( |
| 550 const std::string& id) { | 620 const std::string& id) { |
| 551 if (test_webstore_installer_delegate) | 621 if (test_webstore_installer_delegate) |
| 552 test_webstore_installer_delegate->OnExtensionInstallSuccess(id); | 622 test_webstore_installer_delegate->OnExtensionInstallSuccess(id); |
| 553 | 623 |
| 554 LOG(INFO) << "Install success, sending response"; | 624 LOG(INFO) << "Install success, sending response"; |
| 625 g_pending_installs.Get().EraseInstall(profile_, id); |
| 555 SendResponse(true); | 626 SendResponse(true); |
| 556 | 627 |
| 557 // Matches the AddRef in RunImpl(). | 628 // Matches the AddRef in RunImpl(). |
| 558 Release(); | 629 Release(); |
| 559 } | 630 } |
| 560 | 631 |
| 561 void CompleteInstallFunction::OnExtensionInstallFailure( | 632 void CompleteInstallFunction::OnExtensionInstallFailure( |
| 562 const std::string& id, | 633 const std::string& id, |
| 563 const std::string& error, | 634 const std::string& error, |
| 564 WebstoreInstaller::FailureReason reason) { | 635 WebstoreInstaller::FailureReason reason) { |
| 565 extensions::InstallTracker* tracker = | 636 extensions::InstallTracker* tracker = |
| 566 extensions::InstallTrackerFactory::GetForProfile(profile()); | 637 extensions::InstallTrackerFactory::GetForProfile(profile()); |
| 567 tracker->OnInstallFailure(id); | 638 tracker->OnInstallFailure(id); |
| 568 if (test_webstore_installer_delegate) { | 639 if (test_webstore_installer_delegate) { |
| 569 test_webstore_installer_delegate->OnExtensionInstallFailure( | 640 test_webstore_installer_delegate->OnExtensionInstallFailure( |
| 570 id, error, reason); | 641 id, error, reason); |
| 571 } | 642 } |
| 572 | 643 |
| 573 error_ = error; | 644 error_ = error; |
| 574 LOG(INFO) << "Install failed, sending response"; | 645 LOG(INFO) << "Install failed, sending response"; |
| 646 g_pending_installs.Get().EraseInstall(profile_, id); |
| 575 SendResponse(false); | 647 SendResponse(false); |
| 576 | 648 |
| 577 // Matches the AddRef in RunImpl(). | 649 // Matches the AddRef in RunImpl(). |
| 578 Release(); | 650 Release(); |
| 579 } | 651 } |
| 580 | 652 |
| 581 void CompleteInstallFunction::OnExtensionDownloadProgress( | 653 void CompleteInstallFunction::OnExtensionDownloadProgress( |
| 582 const std::string& id, | 654 const std::string& id, |
| 583 content::DownloadItem* item) { | 655 content::DownloadItem* item) { |
| 584 extensions::InstallTracker* tracker = | 656 extensions::InstallTracker* tracker = |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 648 &GetIsLauncherEnabledFunction::OnIsLauncherCheckCompleted, this)); | 720 &GetIsLauncherEnabledFunction::OnIsLauncherCheckCompleted, this)); |
| 649 return true; | 721 return true; |
| 650 } | 722 } |
| 651 | 723 |
| 652 void GetIsLauncherEnabledFunction::OnIsLauncherCheckCompleted(bool is_enabled) { | 724 void GetIsLauncherEnabledFunction::OnIsLauncherCheckCompleted(bool is_enabled) { |
| 653 SetResult(Value::CreateBooleanValue(is_enabled)); | 725 SetResult(Value::CreateBooleanValue(is_enabled)); |
| 654 SendResponse(true); | 726 SendResponse(true); |
| 655 } | 727 } |
| 656 | 728 |
| 657 } // namespace extensions | 729 } // namespace extensions |
| OLD | NEW |