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/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 Loading... |
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 Loading... |
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 |
OLD | NEW |