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

Side by Side Diff: chrome/browser/extensions/webstore_standalone_installer.cc

Issue 389613006: Prevent duplicate concurrent installs of the same extension (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 5 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/webstore_standalone_installer.h" 5 #include "chrome/browser/extensions/webstore_standalone_installer.h"
6 6
7 #include "base/values.h" 7 #include "base/values.h"
8 #include "base/version.h" 8 #include "base/version.h"
9 #include "chrome/browser/extensions/crx_installer.h" 9 #include "chrome/browser/extensions/crx_installer.h"
10 #include "chrome/browser/extensions/extension_install_prompt.h" 10 #include "chrome/browser/extensions/extension_install_prompt.h"
(...skipping 13 matching lines...) Expand all
24 24
25 namespace extensions { 25 namespace extensions {
26 26
27 const char kInvalidWebstoreItemId[] = "Invalid Chrome Web Store item ID"; 27 const char kInvalidWebstoreItemId[] = "Invalid Chrome Web Store item ID";
28 const char kWebstoreRequestError[] = 28 const char kWebstoreRequestError[] =
29 "Could not fetch data from the Chrome Web Store"; 29 "Could not fetch data from the Chrome Web Store";
30 const char kInvalidWebstoreResponseError[] = "Invalid Chrome Web Store reponse"; 30 const char kInvalidWebstoreResponseError[] = "Invalid Chrome Web Store reponse";
31 const char kInvalidManifestError[] = "Invalid manifest"; 31 const char kInvalidManifestError[] = "Invalid manifest";
32 const char kUserCancelledError[] = "User cancelled install"; 32 const char kUserCancelledError[] = "User cancelled install";
33 const char kExtensionIsBlacklisted[] = "Extension is blacklisted"; 33 const char kExtensionIsBlacklisted[] = "Extension is blacklisted";
34 const char kInstallInProgressError[] = "An install is already in progress";
35 const char kLaunchInProgressError[] = "A launch is already in progress";
34 36
35 WebstoreStandaloneInstaller::WebstoreStandaloneInstaller( 37 WebstoreStandaloneInstaller::WebstoreStandaloneInstaller(
36 const std::string& webstore_item_id, 38 const std::string& webstore_item_id,
37 Profile* profile, 39 Profile* profile,
38 const Callback& callback) 40 const Callback& callback)
39 : id_(webstore_item_id), 41 : id_(webstore_item_id),
40 callback_(callback), 42 callback_(callback),
41 profile_(profile), 43 profile_(profile),
42 install_source_(WebstoreInstaller::INSTALL_SOURCE_INLINE), 44 install_source_(WebstoreInstaller::INSTALL_SOURCE_INLINE),
43 show_user_count_(true), 45 show_user_count_(true),
44 average_rating_(0.0), 46 average_rating_(0.0),
45 rating_count_(0) { 47 rating_count_(0),
48 install_registered_(false) {
46 } 49 }
47 50
48 void WebstoreStandaloneInstaller::BeginInstall() { 51 void WebstoreStandaloneInstaller::BeginInstall() {
49 // Add a ref to keep this alive for WebstoreDataFetcher. 52 // Add a ref to keep this alive for WebstoreDataFetcher.
50 // All code paths from here eventually lead to either CompleteInstall or 53 // All code paths from here eventually lead to either CompleteInstall or
51 // AbortInstall, which both release this ref. 54 // AbortInstall, which both release this ref.
52 AddRef(); 55 AddRef();
53 56
54 if (!Extension::IdIsValid(id_)) { 57 if (!Extension::IdIsValid(id_)) {
55 CompleteInstall(webstore_install::INVALID_ID, kInvalidWebstoreItemId); 58 CompleteInstall(webstore_install::INVALID_ID, kInvalidWebstoreItemId);
56 return; 59 return;
57 } 60 }
58 61
62 webstore_install::Result result = webstore_install::UNKNOWN_ERROR;
63 std::string error;
64 if (!EnsureUniqueInstall(&result, &error)) {
65 CompleteInstall(result, error);
66 return;
67 }
68
59 // Use the requesting page as the referrer both since that is more correct 69 // Use the requesting page as the referrer both since that is more correct
60 // (it is the page that caused this request to happen) and so that we can 70 // (it is the page that caused this request to happen) and so that we can
61 // track top sites that trigger inline install requests. 71 // track top sites that trigger inline install requests.
62 webstore_data_fetcher_.reset(new WebstoreDataFetcher( 72 webstore_data_fetcher_.reset(new WebstoreDataFetcher(
63 this, 73 this,
64 profile_->GetRequestContext(), 74 profile_->GetRequestContext(),
65 GetRequestorURL(), 75 GetRequestorURL(),
66 id_)); 76 id_));
67 webstore_data_fetcher_->Start(); 77 webstore_data_fetcher_->Start();
68 } 78 }
69 79
70 // 80 //
71 // Private interface implementation. 81 // Private interface implementation.
72 // 82 //
73 83
74 WebstoreStandaloneInstaller::~WebstoreStandaloneInstaller() { 84 WebstoreStandaloneInstaller::~WebstoreStandaloneInstaller() {
75 } 85 }
76 86
77 void WebstoreStandaloneInstaller::AbortInstall() { 87 void WebstoreStandaloneInstaller::AbortInstall() {
78 callback_.Reset(); 88 callback_.Reset();
79 // Abort any in-progress fetches. 89 // Abort any in-progress fetches.
80 if (webstore_data_fetcher_) { 90 if (webstore_data_fetcher_) {
81 webstore_data_fetcher_.reset(); 91 webstore_data_fetcher_.reset();
92 DeregisterActiveInstall();
82 Release(); // Matches the AddRef in BeginInstall. 93 Release(); // Matches the AddRef in BeginInstall.
83 } 94 }
84 } 95 }
85 96
97 bool WebstoreStandaloneInstaller::EnsureUniqueInstall(
98 webstore_install::Result* reason,
99 std::string* error) {
100 InstallTracker* tracker = InstallTracker::Get(profile_);
101 DCHECK(tracker);
102
103 const InstallTracker::InstallProgressData* existing_install_data =
104 tracker->GetActiveInstall(id_);
105 if (existing_install_data) {
106 if (existing_install_data->is_ephemeral) {
107 *reason = webstore_install::LAUNCH_IN_PROGRESS;
108 *error = kLaunchInProgressError;
109 } else {
110 *reason = webstore_install::INSTALL_IN_PROGRESS;
111 *error = kInstallInProgressError;
112 }
113 return false;
114 }
115
116 InstallTracker::InstallProgressData install_data(id_);
117 InitInstallData(&install_data);
118 tracker->AddActiveInstall(install_data);
119 install_registered_ = true;
120 return true;
121 }
122
86 void WebstoreStandaloneInstaller::CompleteInstall( 123 void WebstoreStandaloneInstaller::CompleteInstall(
87 webstore_install::Result result, 124 webstore_install::Result result,
88 const std::string& error) { 125 const std::string& error) {
126 DeregisterActiveInstall();
89 if (!callback_.is_null()) 127 if (!callback_.is_null())
90 callback_.Run(result == webstore_install::SUCCESS, error); 128 callback_.Run(result == webstore_install::SUCCESS, error);
91 Release(); // Matches the AddRef in BeginInstall. 129 Release(); // Matches the AddRef in BeginInstall.
92 } 130 }
93 131
94 void WebstoreStandaloneInstaller::ProceedWithInstallPrompt() { 132 void WebstoreStandaloneInstaller::ProceedWithInstallPrompt() {
95 install_prompt_ = CreateInstallPrompt(); 133 install_prompt_ = CreateInstallPrompt();
96 if (install_prompt_) { 134 if (install_prompt_) {
97 ShowInstallUI(); 135 ShowInstallUI();
98 // Control flow finishes up in InstallUIProceed or InstallUIAbort. 136 // Control flow finishes up in InstallUIProceed or InstallUIAbort.
(...skipping 15 matching lines...) Expand all
114 manifest_.get(), 152 manifest_.get(),
115 Extension::REQUIRE_KEY | Extension::FROM_WEBSTORE, 153 Extension::REQUIRE_KEY | Extension::FROM_WEBSTORE,
116 id_, 154 id_,
117 localized_name_, 155 localized_name_,
118 localized_description_, 156 localized_description_,
119 &error); 157 &error);
120 } 158 }
121 return localized_extension_for_display_.get(); 159 return localized_extension_for_display_.get();
122 } 160 }
123 161
162 void WebstoreStandaloneInstaller::InitInstallData(
163 InstallTracker::InstallProgressData* install_data) const {
164 // Default implementation sets no properties.
165 }
166
124 void WebstoreStandaloneInstaller::OnManifestParsed() { 167 void WebstoreStandaloneInstaller::OnManifestParsed() {
125 ProceedWithInstallPrompt(); 168 ProceedWithInstallPrompt();
126 } 169 }
127 170
128 scoped_ptr<ExtensionInstallPrompt> 171 scoped_ptr<ExtensionInstallPrompt>
129 WebstoreStandaloneInstaller::CreateInstallUI() { 172 WebstoreStandaloneInstaller::CreateInstallUI() {
130 return make_scoped_ptr(new ExtensionInstallPrompt(GetWebContents())); 173 return make_scoped_ptr(new ExtensionInstallPrompt(GetWebContents()));
131 } 174 }
132 175
133 scoped_ptr<WebstoreInstaller::Approval> 176 scoped_ptr<WebstoreInstaller::Approval>
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after
388 431
389 void WebstoreStandaloneInstaller::OnWebStoreDataFetcherDone() { 432 void WebstoreStandaloneInstaller::OnWebStoreDataFetcherDone() {
390 // An instance of this class is passed in as a delegate for the 433 // An instance of this class is passed in as a delegate for the
391 // WebstoreInstallHelper, ExtensionInstallPrompt and WebstoreInstaller, and 434 // WebstoreInstallHelper, ExtensionInstallPrompt and WebstoreInstaller, and
392 // therefore needs to remain alive until they are done. Clear the webstore 435 // therefore needs to remain alive until they are done. Clear the webstore
393 // data fetcher to avoid calling Release in AbortInstall while any of these 436 // data fetcher to avoid calling Release in AbortInstall while any of these
394 // operations are in progress. 437 // operations are in progress.
395 webstore_data_fetcher_.reset(); 438 webstore_data_fetcher_.reset();
396 } 439 }
397 440
441 void WebstoreStandaloneInstaller::DeregisterActiveInstall() {
442 if (!install_registered_)
443 return;
444
445 InstallTracker* tracker = InstallTracker::Get(profile_);
446 DCHECK(tracker);
447 tracker->RemoveActiveInstall(id_);
448 }
449
398 } // namespace extensions 450 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698