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

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: Fixed update of webstore_result 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"
11 #include "chrome/browser/extensions/extension_install_ui.h" 11 #include "chrome/browser/extensions/extension_install_ui.h"
12 #include "chrome/browser/extensions/extension_service.h" 12 #include "chrome/browser/extensions/extension_service.h"
13 #include "chrome/browser/extensions/install_tracker.h"
13 #include "chrome/browser/extensions/webstore_data_fetcher.h" 14 #include "chrome/browser/extensions/webstore_data_fetcher.h"
14 #include "chrome/browser/profiles/profile.h" 15 #include "chrome/browser/profiles/profile.h"
15 #include "content/public/browser/web_contents.h" 16 #include "content/public/browser/web_contents.h"
16 #include "extensions/browser/extension_prefs.h" 17 #include "extensions/browser/extension_prefs.h"
17 #include "extensions/browser/extension_registry.h" 18 #include "extensions/browser/extension_registry.h"
18 #include "extensions/browser/extension_system.h" 19 #include "extensions/browser/extension_system.h"
19 #include "extensions/browser/extension_util.h" 20 #include "extensions/browser/extension_util.h"
20 #include "extensions/common/extension.h" 21 #include "extensions/common/extension.h"
21 #include "url/gurl.h" 22 #include "url/gurl.h"
22 23
23 using content::WebContents; 24 using content::WebContents;
24 25
25 namespace extensions { 26 namespace extensions {
26 27
27 const char kInvalidWebstoreItemId[] = "Invalid Chrome Web Store item ID"; 28 const char kInvalidWebstoreItemId[] = "Invalid Chrome Web Store item ID";
28 const char kWebstoreRequestError[] = 29 const char kWebstoreRequestError[] =
29 "Could not fetch data from the Chrome Web Store"; 30 "Could not fetch data from the Chrome Web Store";
30 const char kInvalidWebstoreResponseError[] = "Invalid Chrome Web Store reponse"; 31 const char kInvalidWebstoreResponseError[] = "Invalid Chrome Web Store reponse";
31 const char kInvalidManifestError[] = "Invalid manifest"; 32 const char kInvalidManifestError[] = "Invalid manifest";
32 const char kUserCancelledError[] = "User cancelled install"; 33 const char kUserCancelledError[] = "User cancelled install";
33 const char kExtensionIsBlacklisted[] = "Extension is blacklisted"; 34 const char kExtensionIsBlacklisted[] = "Extension is blacklisted";
35 const char kInstallInProgressError[] = "An install is already in progress";
36 const char kLaunchInProgressError[] = "A launch is already in progress";
34 37
35 WebstoreStandaloneInstaller::WebstoreStandaloneInstaller( 38 WebstoreStandaloneInstaller::WebstoreStandaloneInstaller(
36 const std::string& webstore_item_id, 39 const std::string& webstore_item_id,
37 Profile* profile, 40 Profile* profile,
38 const Callback& callback) 41 const Callback& callback)
39 : id_(webstore_item_id), 42 : id_(webstore_item_id),
40 callback_(callback), 43 callback_(callback),
41 profile_(profile), 44 profile_(profile),
42 install_source_(WebstoreInstaller::INSTALL_SOURCE_INLINE), 45 install_source_(WebstoreInstaller::INSTALL_SOURCE_INLINE),
43 show_user_count_(true), 46 show_user_count_(true),
44 average_rating_(0.0), 47 average_rating_(0.0),
45 rating_count_(0) { 48 rating_count_(0) {
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 scoped_active_install_.reset();
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 ActiveInstallData* 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 ActiveInstallData install_data(id_);
117 InitInstallData(&install_data);
118 scoped_active_install_.reset(new ScopedActiveInstall(tracker, install_data));
119 return true;
120 }
121
86 void WebstoreStandaloneInstaller::CompleteInstall( 122 void WebstoreStandaloneInstaller::CompleteInstall(
87 webstore_install::Result result, 123 webstore_install::Result result,
88 const std::string& error) { 124 const std::string& error) {
125 scoped_active_install_.reset();
89 if (!callback_.is_null()) 126 if (!callback_.is_null())
90 callback_.Run(result == webstore_install::SUCCESS, error); 127 callback_.Run(result == webstore_install::SUCCESS, error);
91 Release(); // Matches the AddRef in BeginInstall. 128 Release(); // Matches the AddRef in BeginInstall.
92 } 129 }
93 130
94 void WebstoreStandaloneInstaller::ProceedWithInstallPrompt() { 131 void WebstoreStandaloneInstaller::ProceedWithInstallPrompt() {
95 install_prompt_ = CreateInstallPrompt(); 132 install_prompt_ = CreateInstallPrompt();
96 if (install_prompt_) { 133 if (install_prompt_) {
97 ShowInstallUI(); 134 ShowInstallUI();
98 // Control flow finishes up in InstallUIProceed or InstallUIAbort. 135 // Control flow finishes up in InstallUIProceed or InstallUIAbort.
(...skipping 15 matching lines...) Expand all
114 manifest_.get(), 151 manifest_.get(),
115 Extension::REQUIRE_KEY | Extension::FROM_WEBSTORE, 152 Extension::REQUIRE_KEY | Extension::FROM_WEBSTORE,
116 id_, 153 id_,
117 localized_name_, 154 localized_name_,
118 localized_description_, 155 localized_description_,
119 &error); 156 &error);
120 } 157 }
121 return localized_extension_for_display_.get(); 158 return localized_extension_for_display_.get();
122 } 159 }
123 160
161 void WebstoreStandaloneInstaller::InitInstallData(
162 ActiveInstallData* install_data) const {
163 // Default implementation sets no properties.
164 }
165
124 void WebstoreStandaloneInstaller::OnManifestParsed() { 166 void WebstoreStandaloneInstaller::OnManifestParsed() {
125 ProceedWithInstallPrompt(); 167 ProceedWithInstallPrompt();
126 } 168 }
127 169
128 scoped_ptr<ExtensionInstallPrompt> 170 scoped_ptr<ExtensionInstallPrompt>
129 WebstoreStandaloneInstaller::CreateInstallUI() { 171 WebstoreStandaloneInstaller::CreateInstallUI() {
130 return make_scoped_ptr(new ExtensionInstallPrompt(GetWebContents())); 172 return make_scoped_ptr(new ExtensionInstallPrompt(GetWebContents()));
131 } 173 }
132 174
133 scoped_ptr<WebstoreInstaller::Approval> 175 scoped_ptr<WebstoreInstaller::Approval>
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
389 void WebstoreStandaloneInstaller::OnWebStoreDataFetcherDone() { 431 void WebstoreStandaloneInstaller::OnWebStoreDataFetcherDone() {
390 // An instance of this class is passed in as a delegate for the 432 // An instance of this class is passed in as a delegate for the
391 // WebstoreInstallHelper, ExtensionInstallPrompt and WebstoreInstaller, and 433 // WebstoreInstallHelper, ExtensionInstallPrompt and WebstoreInstaller, and
392 // therefore needs to remain alive until they are done. Clear the webstore 434 // 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 435 // data fetcher to avoid calling Release in AbortInstall while any of these
394 // operations are in progress. 436 // operations are in progress.
395 webstore_data_fetcher_.reset(); 437 webstore_data_fetcher_.reset();
396 } 438 }
397 439
398 } // namespace extensions 440 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698