Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(232)

Side by Side Diff: chrome/browser/extensions/api/webstore_private/webstore_private_api.cc

Issue 15292011: Prevent duplicate webstore install requests being serviced. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
79 WebstoreInstaller::Approval* approval = approvals[i]; 79 WebstoreInstaller::Approval* approval = approvals[i];
80 if (approval->extension_id == id && 80 if (approval->extension_id == id &&
81 profile->IsSameProfile(approval->profile)) { 81 profile->IsSameProfile(approval->profile)) {
82 approvals.weak_erase(approvals.begin() + i); 82 approvals.weak_erase(approvals.begin() + i);
83 return scoped_ptr<WebstoreInstaller::Approval>(approval); 83 return scoped_ptr<WebstoreInstaller::Approval>(approval);
84 } 84 }
85 } 85 }
86 return scoped_ptr<WebstoreInstaller::Approval>(NULL); 86 return scoped_ptr<WebstoreInstaller::Approval>(NULL);
87 } 87 }
88 88
89 // Uniquely holds the profile and extension id of an install between the time we
90 // prompt and complete the installs.
91 struct PendingInstalls {
koz (OOO until 15th September) 2013/05/20 23:57:12 Make this a class with |installs_| and related typ
calamity 2013/05/21 00:49:41 Done.
92 typedef std::pair<Profile*, std::string> ProfileAndExtensionId;
93 typedef std::vector<ProfileAndExtensionId> InstallList;
94
95 bool InsertInstall(Profile* profile, const std::string& id);
96 void EraseInstall(Profile* profile, const std::string& id);
97 InstallList::iterator FindInstall(Profile* profile, const std::string& id);
98
99 InstallList installs_;
100 };
101
102 // Returns true and inserts the profile/id pair if it is not present. Otherwise
103 // returns false.
104 bool PendingInstalls::InsertInstall(Profile* profile, const std::string& id) {
105 if (FindInstall(profile, id) != installs_.end()) {
koz (OOO until 15th September) 2013/05/20 23:57:12 nit: no curlies
calamity 2013/05/21 00:49:41 Done.
106 return false;
107 }
108 installs_.push_back(make_pair(profile, id));
109 return true;
110 }
111
112 // Removes the given profile/id pair.
113 void PendingInstalls::EraseInstall(Profile* profile, const std::string& id) {
114 InstallList::iterator it = FindInstall(profile, id);
115 if (it != installs_.end()) {
koz (OOO until 15th September) 2013/05/20 23:57:12 nit: no curlies
calamity 2013/05/21 00:49:41 Done.
116 installs_.erase(it);
117 }
118 }
119
120 PendingInstalls::InstallList::iterator PendingInstalls::FindInstall(
121 Profile* profile,
122 const std::string& id) {
123 for (size_t i = 0; i < installs_.size(); ++i) {
124 ProfileAndExtensionId install = installs_[i];
125 if (install.second == id &&
126 profile->IsSameProfile(install.first)) {
127 return (installs_.begin() + i);
128 }
129 }
130 return installs_.end();
131 }
132
89 static base::LazyInstance<PendingApprovals> g_pending_approvals = 133 static base::LazyInstance<PendingApprovals> g_pending_approvals =
90 LAZY_INSTANCE_INITIALIZER; 134 LAZY_INSTANCE_INITIALIZER;
135 static base::LazyInstance<PendingInstalls> g_pending_installs =
136 LAZY_INSTANCE_INITIALIZER;
91 137
92 const char kAppInstallBubbleKey[] = "appInstallBubble"; 138 const char kAppInstallBubbleKey[] = "appInstallBubble";
93 const char kEnableLauncherKey[] = "enableLauncher"; 139 const char kEnableLauncherKey[] = "enableLauncher";
94 const char kIconDataKey[] = "iconData"; 140 const char kIconDataKey[] = "iconData";
95 const char kIconUrlKey[] = "iconUrl"; 141 const char kIconUrlKey[] = "iconUrl";
96 const char kIdKey[] = "id"; 142 const char kIdKey[] = "id";
97 const char kLocalizedNameKey[] = "localizedName"; 143 const char kLocalizedNameKey[] = "localizedName";
98 const char kLoginKey[] = "login"; 144 const char kLoginKey[] = "login";
99 const char kManifestKey[] = "manifest"; 145 const char kManifestKey[] = "manifest";
100 146
147 const char kAlreadyInstalledError[] = "This item is already installed";
101 const char kCannotSpecifyIconDataAndUrlError[] = 148 const char kCannotSpecifyIconDataAndUrlError[] =
102 "You cannot specify both icon data and an icon url"; 149 "You cannot specify both icon data and an icon url";
103 const char kInvalidIconUrlError[] = "Invalid icon url"; 150 const char kInvalidIconUrlError[] = "Invalid icon url";
104 const char kInvalidIdError[] = "Invalid id"; 151 const char kInvalidIdError[] = "Invalid id";
105 const char kInvalidManifestError[] = "Invalid manifest"; 152 const char kInvalidManifestError[] = "Invalid manifest";
106 const char kNoPreviousBeginInstallWithManifestError[] = 153 const char kNoPreviousBeginInstallWithManifestError[] =
107 "* does not match a previous call to beginInstallWithManifest3"; 154 "* does not match a previous call to beginInstallWithManifest3";
108 const char kUserCancelledError[] = "User cancelled install"; 155 const char kUserCancelledError[] = "User cancelled install";
109 156
110 // Helper to create a dictionary with login properties set from the appropriate 157 // Helper to create a dictionary with login properties set from the appropriate
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
216 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &details)); 263 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &details));
217 CHECK(details); 264 CHECK(details);
218 265
219 EXTENSION_FUNCTION_VALIDATE(details->GetString(kIdKey, &id_)); 266 EXTENSION_FUNCTION_VALIDATE(details->GetString(kIdKey, &id_));
220 if (!extensions::Extension::IdIsValid(id_)) { 267 if (!extensions::Extension::IdIsValid(id_)) {
221 SetResultCode(INVALID_ID); 268 SetResultCode(INVALID_ID);
222 error_ = kInvalidIdError; 269 error_ = kInvalidIdError;
223 return false; 270 return false;
224 } 271 }
225 272
273 ExtensionService* service =
274 extensions::ExtensionSystem::Get(profile_)->extension_service();
275 if (service->GetInstalledExtension(id_) ||
276 !g_pending_installs.Get().InsertInstall(profile_, id_)) {
277 SetResultCode(ALREADY_INSTALLED);
278 error_ = kAlreadyInstalledError;
279 return false;
280 }
281
226 EXTENSION_FUNCTION_VALIDATE(details->GetString(kManifestKey, &manifest_)); 282 EXTENSION_FUNCTION_VALIDATE(details->GetString(kManifestKey, &manifest_));
227 283
228 if (details->HasKey(kIconDataKey) && details->HasKey(kIconUrlKey)) { 284 if (details->HasKey(kIconDataKey) && details->HasKey(kIconUrlKey)) {
229 SetResultCode(ICON_ERROR); 285 SetResultCode(ICON_ERROR);
230 error_ = kCannotSpecifyIconDataAndUrlError; 286 error_ = kCannotSpecifyIconDataAndUrlError;
231 return false; 287 return false;
232 } 288 }
233 289
234 if (details->HasKey(kIconDataKey)) 290 if (details->HasKey(kIconDataKey))
235 EXTENSION_FUNCTION_VALIDATE(details->GetString(kIconDataKey, &icon_data_)); 291 EXTENSION_FUNCTION_VALIDATE(details->GetString(kIconDataKey, &icon_data_));
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
300 break; 356 break;
301 case PERMISSION_DENIED: 357 case PERMISSION_DENIED:
302 SetResult(Value::CreateStringValue("permission_denied")); 358 SetResult(Value::CreateStringValue("permission_denied"));
303 break; 359 break;
304 case INVALID_ICON_URL: 360 case INVALID_ICON_URL:
305 SetResult(Value::CreateStringValue("invalid_icon_url")); 361 SetResult(Value::CreateStringValue("invalid_icon_url"));
306 break; 362 break;
307 case SIGNIN_FAILED: 363 case SIGNIN_FAILED:
308 SetResult(Value::CreateStringValue("signin_failed")); 364 SetResult(Value::CreateStringValue("signin_failed"));
309 break; 365 break;
366 case ALREADY_INSTALLED:
367 SetResult(Value::CreateStringValue("already_installed"));
368 break;
310 default: 369 default:
311 CHECK(false); 370 CHECK(false);
312 } 371 }
313 } 372 }
314 373
315 void BeginInstallWithManifestFunction::OnWebstoreParseSuccess( 374 void BeginInstallWithManifestFunction::OnWebstoreParseSuccess(
316 const std::string& id, 375 const std::string& id,
317 const SkBitmap& icon, 376 const SkBitmap& icon,
318 DictionaryValue* parsed_manifest) { 377 DictionaryValue* parsed_manifest) {
319 CHECK_EQ(id_, id); 378 CHECK_EQ(id_, id);
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
525 &(dispatcher()->delegate()->GetAssociatedWebContents()->GetController()), 584 &(dispatcher()->delegate()->GetAssociatedWebContents()->GetController()),
526 id, approval_.Pass(), WebstoreInstaller::FLAG_NONE); 585 id, approval_.Pass(), WebstoreInstaller::FLAG_NONE);
527 installer->Start(); 586 installer->Start();
528 } 587 }
529 588
530 void CompleteInstallFunction::OnExtensionInstallSuccess( 589 void CompleteInstallFunction::OnExtensionInstallSuccess(
531 const std::string& id) { 590 const std::string& id) {
532 if (test_webstore_installer_delegate) 591 if (test_webstore_installer_delegate)
533 test_webstore_installer_delegate->OnExtensionInstallSuccess(id); 592 test_webstore_installer_delegate->OnExtensionInstallSuccess(id);
534 593
594 g_pending_installs.Get().EraseInstall(profile_, id);
595
535 LOG(INFO) << "Install success, sending response"; 596 LOG(INFO) << "Install success, sending response";
536 SendResponse(true); 597 SendResponse(true);
537 598
538 // Matches the AddRef in RunImpl(). 599 // Matches the AddRef in RunImpl().
539 Release(); 600 Release();
540 } 601 }
541 602
542 void CompleteInstallFunction::OnExtensionInstallFailure( 603 void CompleteInstallFunction::OnExtensionInstallFailure(
543 const std::string& id, 604 const std::string& id,
544 const std::string& error, 605 const std::string& error,
545 WebstoreInstaller::FailureReason reason) { 606 WebstoreInstaller::FailureReason reason) {
546 extensions::InstallTracker* tracker = 607 extensions::InstallTracker* tracker =
547 extensions::InstallTrackerFactory::GetForProfile(profile()); 608 extensions::InstallTrackerFactory::GetForProfile(profile());
548 tracker->OnInstallFailure(id); 609 tracker->OnInstallFailure(id);
549 if (test_webstore_installer_delegate) { 610 if (test_webstore_installer_delegate) {
550 test_webstore_installer_delegate->OnExtensionInstallFailure( 611 test_webstore_installer_delegate->OnExtensionInstallFailure(
551 id, error, reason); 612 id, error, reason);
552 } 613 }
553 614
615 g_pending_installs.Get().EraseInstall(profile_, id);
616
554 error_ = error; 617 error_ = error;
555 LOG(INFO) << "Install failed, sending response"; 618 LOG(INFO) << "Install failed, sending response";
556 SendResponse(false); 619 SendResponse(false);
557 620
558 // Matches the AddRef in RunImpl(). 621 // Matches the AddRef in RunImpl().
559 Release(); 622 Release();
560 } 623 }
561 624
562 void CompleteInstallFunction::OnExtensionDownloadProgress( 625 void CompleteInstallFunction::OnExtensionDownloadProgress(
563 const std::string& id, 626 const std::string& id,
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
640 &GetIsLauncherEnabledFunction::OnIsLauncherCheckCompleted, this)); 703 &GetIsLauncherEnabledFunction::OnIsLauncherCheckCompleted, this));
641 return true; 704 return true;
642 } 705 }
643 706
644 void GetIsLauncherEnabledFunction::OnIsLauncherCheckCompleted(bool is_enabled) { 707 void GetIsLauncherEnabledFunction::OnIsLauncherCheckCompleted(bool is_enabled) {
645 SetResult(Value::CreateBooleanValue(is_enabled)); 708 SetResult(Value::CreateBooleanValue(is_enabled));
646 SendResponse(true); 709 SendResponse(true);
647 } 710 }
648 711
649 } // namespace extensions 712 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698