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 |