[email protected] | bdb74a2 | 2012-01-25 20:33:33 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
[email protected] | 8915f34 | 2011-08-29 22:14:37 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
[email protected] | 734bcec | 2012-10-08 20:29:05 | [diff] [blame] | 5 | #include "chrome/browser/extensions/webstore_standalone_installer.h" |
[email protected] | 8915f34 | 2011-08-29 22:14:37 | [diff] [blame] | 6 | |
| 7 | #include <vector> |
| 8 | |
[email protected] | 7b394105 | 2013-02-13 01:21:59 | [diff] [blame] | 9 | #include "base/stringprintf.h" |
[email protected] | 8915f34 | 2011-08-29 22:14:37 | [diff] [blame] | 10 | #include "base/values.h" |
[email protected] | 8915f34 | 2011-08-29 22:14:37 | [diff] [blame] | 11 | #include "chrome/browser/extensions/crx_installer.h" |
[email protected] | 00b3824 | 2012-07-18 18:43:22 | [diff] [blame] | 12 | #include "chrome/browser/extensions/extension_install_ui.h" |
[email protected] | 655b2b1a | 2011-10-13 17:13:06 | [diff] [blame] | 13 | #include "chrome/browser/extensions/extension_service.h" |
[email protected] | 7b394105 | 2013-02-13 01:21:59 | [diff] [blame] | 14 | #include "chrome/browser/extensions/webstore_data_fetcher.h" |
[email protected] | 8915f34 | 2011-08-29 22:14:37 | [diff] [blame] | 15 | #include "chrome/browser/profiles/profile.h" |
[email protected] | 8915f34 | 2011-08-29 22:14:37 | [diff] [blame] | 16 | #include "chrome/common/extensions/extension.h" |
[email protected] | 10c2d69 | 2012-05-11 05:32:23 | [diff] [blame] | 17 | #include "content/public/browser/web_contents.h" |
[email protected] | 3076a223 | 2012-10-15 21:18:04 | [diff] [blame] | 18 | #include "content/public/browser/web_contents_view.h" |
[email protected] | 8915f34 | 2011-08-29 22:14:37 | [diff] [blame] | 19 | |
[email protected] | 631bb74 | 2011-11-02 11:29:39 | [diff] [blame] | 20 | using content::BrowserThread; |
[email protected] | e5d549d | 2011-12-28 01:29:20 | [diff] [blame] | 21 | using content::OpenURLParams; |
[email protected] | 26b5e32 | 2011-12-23 01:36:47 | [diff] [blame] | 22 | using content::WebContents; |
[email protected] | 631bb74 | 2011-11-02 11:29:39 | [diff] [blame] | 23 | |
[email protected] | 3d61a7f | 2012-07-12 19:11:25 | [diff] [blame] | 24 | namespace extensions { |
| 25 | |
[email protected] | 8915f34 | 2011-08-29 22:14:37 | [diff] [blame] | 26 | const char kManifestKey[] = "manifest"; |
| 27 | const char kIconUrlKey[] = "icon_url"; |
| 28 | const char kLocalizedNameKey[] = "localized_name"; |
[email protected] | 5fdbd6f | 2011-09-01 17:33:04 | [diff] [blame] | 29 | const char kLocalizedDescriptionKey[] = "localized_description"; |
| 30 | const char kUsersKey[] = "users"; |
| 31 | const char kAverageRatingKey[] = "average_rating"; |
| 32 | const char kRatingCountKey[] = "rating_count"; |
[email protected] | a221ef09 | 2011-09-07 01:34:10 | [diff] [blame] | 33 | const char kVerifiedSiteKey[] = "verified_site"; |
[email protected] | dd5161a | 2011-09-14 17:40:17 | [diff] [blame] | 34 | const char kInlineInstallNotSupportedKey[] = "inline_install_not_supported"; |
| 35 | const char kRedirectUrlKey[] = "redirect_url"; |
[email protected] | 8915f34 | 2011-08-29 22:14:37 | [diff] [blame] | 36 | |
[email protected] | a221ef09 | 2011-09-07 01:34:10 | [diff] [blame] | 37 | const char kInvalidWebstoreItemId[] = "Invalid Chrome Web Store item ID"; |
| 38 | const char kWebstoreRequestError[] = |
| 39 | "Could not fetch data from the Chrome Web Store"; |
| 40 | const char kInvalidWebstoreResponseError[] = "Invalid Chrome Web Store reponse"; |
[email protected] | 8915f34 | 2011-08-29 22:14:37 | [diff] [blame] | 41 | const char kInvalidManifestError[] = "Invalid manifest"; |
| 42 | const char kUserCancelledError[] = "User cancelled install"; |
[email protected] | 5da311ea | 2011-09-14 20:57:32 | [diff] [blame] | 43 | const char kNoVerifiedSiteError[] = |
| 44 | "Inline installs can only be initiated for Chrome Web Store items that " |
| 45 | "have a verified site"; |
| 46 | const char kNotFromVerifiedSiteError[] = |
[email protected] | a221ef09 | 2011-09-07 01:34:10 | [diff] [blame] | 47 | "Installs can only be initiated by the Chrome Web Store item's verified " |
| 48 | "site"; |
[email protected] | dd5161a | 2011-09-14 17:40:17 | [diff] [blame] | 49 | const char kInlineInstallSupportedError[] = |
| 50 | "Inline installation is not supported for this item. The user will be " |
| 51 | "redirected to the Chrome Web Store."; |
[email protected] | 8915f34 | 2011-08-29 22:14:37 | [diff] [blame] | 52 | |
[email protected] | 734bcec | 2012-10-08 20:29:05 | [diff] [blame] | 53 | WebstoreStandaloneInstaller::WebstoreStandaloneInstaller( |
[email protected] | d2a639e | 2012-09-17 07:41:21 | [diff] [blame] | 54 | std::string webstore_item_id, |
| 55 | VerifiedSiteRequired require_verified_site, |
[email protected] | 734bcec | 2012-10-08 20:29:05 | [diff] [blame] | 56 | PromptType prompt_type, |
[email protected] | d2a639e | 2012-09-17 07:41:21 | [diff] [blame] | 57 | GURL requestor_url, |
[email protected] | c1b2d04 | 2013-02-23 00:31:04 | [diff] [blame^] | 58 | Profile* profile, |
| 59 | WebContents* web_contents, |
| 60 | const Callback& callback) |
| 61 | : content::WebContentsObserver( |
| 62 | prompt_type == INLINE_PROMPT ? |
| 63 | web_contents : |
| 64 | content::WebContents::Create( |
| 65 | content::WebContents::CreateParams(profile))), |
[email protected] | 8915f34 | 2011-08-29 22:14:37 | [diff] [blame] | 66 | id_(webstore_item_id), |
[email protected] | d2a639e | 2012-09-17 07:41:21 | [diff] [blame] | 67 | require_verified_site_(require_verified_site == REQUIRE_VERIFIED_SITE), |
[email protected] | 77e9261d | 2013-02-04 22:01:47 | [diff] [blame] | 68 | prompt_type_(prompt_type), |
[email protected] | a221ef09 | 2011-09-07 01:34:10 | [diff] [blame] | 69 | requestor_url_(requestor_url), |
[email protected] | c1b2d04 | 2013-02-23 00:31:04 | [diff] [blame^] | 70 | profile_(profile), |
[email protected] | d2a639e | 2012-09-17 07:41:21 | [diff] [blame] | 71 | callback_(callback), |
[email protected] | c7bf745 | 2011-09-12 21:31:50 | [diff] [blame] | 72 | average_rating_(0.0), |
[email protected] | 5f2a475 | 2012-04-27 22:18:58 | [diff] [blame] | 73 | rating_count_(0) { |
[email protected] | c1b2d04 | 2013-02-23 00:31:04 | [diff] [blame^] | 74 | DCHECK((prompt_type == SKIP_PROMPT && |
| 75 | profile != NULL && |
| 76 | web_contents == NULL) || |
| 77 | (prompt_type == STANDARD_PROMPT && |
| 78 | profile != NULL && |
| 79 | web_contents == NULL) || |
| 80 | (prompt_type == INLINE_PROMPT && |
| 81 | profile != NULL && |
| 82 | web_contents != NULL && |
| 83 | profile == Profile::FromBrowserContext( |
| 84 | web_contents->GetBrowserContext())) |
| 85 | ) << " prompt_type=" << prompt_type |
| 86 | << " profile=" << profile |
| 87 | << " web_contents=" << web_contents; |
| 88 | DCHECK(this->web_contents() != NULL); |
| 89 | CHECK(!callback_.is_null()); |
| 90 | } |
| 91 | |
| 92 | WebstoreStandaloneInstaller::~WebstoreStandaloneInstaller() { |
| 93 | if (prompt_type_ != INLINE_PROMPT) { |
| 94 | // We create and own the web_contents in this case. |
| 95 | delete web_contents(); |
| 96 | } |
[email protected] | 8915f34 | 2011-08-29 22:14:37 | [diff] [blame] | 97 | } |
| 98 | |
[email protected] | 734bcec | 2012-10-08 20:29:05 | [diff] [blame] | 99 | void WebstoreStandaloneInstaller::BeginInstall() { |
[email protected] | 5db2e88 | 2012-12-20 10:17:26 | [diff] [blame] | 100 | AddRef(); // Balanced in CompleteInstall or WebContentsDestroyed. |
[email protected] | 8915f34 | 2011-08-29 22:14:37 | [diff] [blame] | 101 | |
[email protected] | 3d61a7f | 2012-07-12 19:11:25 | [diff] [blame] | 102 | if (!Extension::IdIsValid(id_)) { |
[email protected] | 8915f34 | 2011-08-29 22:14:37 | [diff] [blame] | 103 | CompleteInstall(kInvalidWebstoreItemId); |
| 104 | return; |
| 105 | } |
| 106 | |
[email protected] | b4574c0 | 2011-11-17 06:19:13 | [diff] [blame] | 107 | // Use the requesting page as the referrer both since that is more correct |
| 108 | // (it is the page that caused this request to happen) and so that we can |
| 109 | // track top sites that trigger inline install requests. |
[email protected] | 7b394105 | 2013-02-13 01:21:59 | [diff] [blame] | 110 | webstore_data_fetcher_.reset(new WebstoreDataFetcher( |
| 111 | this, |
[email protected] | c1b2d04 | 2013-02-23 00:31:04 | [diff] [blame^] | 112 | profile_->GetRequestContext(), |
[email protected] | 7b394105 | 2013-02-13 01:21:59 | [diff] [blame] | 113 | requestor_url_, |
| 114 | id_)); |
| 115 | webstore_data_fetcher_->Start(); |
[email protected] | 8915f34 | 2011-08-29 22:14:37 | [diff] [blame] | 116 | } |
| 117 | |
[email protected] | 7b394105 | 2013-02-13 01:21:59 | [diff] [blame] | 118 | void WebstoreStandaloneInstaller::OnWebstoreRequestFailure() { |
| 119 | CompleteInstall(kWebstoreRequestError); |
[email protected] | 8915f34 | 2011-08-29 22:14:37 | [diff] [blame] | 120 | } |
| 121 | |
[email protected] | 734bcec | 2012-10-08 20:29:05 | [diff] [blame] | 122 | void WebstoreStandaloneInstaller::OnWebstoreResponseParseSuccess( |
[email protected] | 8915f34 | 2011-08-29 22:14:37 | [diff] [blame] | 123 | DictionaryValue* webstore_data) { |
[email protected] | 4693243e | 2011-09-09 23:52:37 | [diff] [blame] | 124 | // Check if the tab has gone away in the meantime. |
[email protected] | c1b2d04 | 2013-02-23 00:31:04 | [diff] [blame^] | 125 | if (prompt_type_ == INLINE_PROMPT && !web_contents()) { |
[email protected] | 4693243e | 2011-09-09 23:52:37 | [diff] [blame] | 126 | CompleteInstall(""); |
| 127 | return; |
| 128 | } |
| 129 | |
[email protected] | 8915f34 | 2011-08-29 22:14:37 | [diff] [blame] | 130 | webstore_data_.reset(webstore_data); |
| 131 | |
[email protected] | dd5161a | 2011-09-14 17:40:17 | [diff] [blame] | 132 | // The store may not support inline installs for this item, in which case |
| 133 | // we open the store-provided redirect URL in a new tab and abort the |
| 134 | // installation process. |
| 135 | bool inline_install_not_supported = false; |
| 136 | if (webstore_data->HasKey(kInlineInstallNotSupportedKey) && |
| 137 | !webstore_data->GetBoolean( |
| 138 | kInlineInstallNotSupportedKey, &inline_install_not_supported)) { |
[email protected] | 8915f34 | 2011-08-29 22:14:37 | [diff] [blame] | 139 | CompleteInstall(kInvalidWebstoreResponseError); |
| 140 | return; |
| 141 | } |
[email protected] | dd5161a | 2011-09-14 17:40:17 | [diff] [blame] | 142 | if (inline_install_not_supported) { |
| 143 | std::string redirect_url; |
| 144 | if (!webstore_data->GetString(kRedirectUrlKey, &redirect_url)) { |
| 145 | CompleteInstall(kInvalidWebstoreResponseError); |
| 146 | return; |
| 147 | } |
[email protected] | 8915f34 | 2011-08-29 22:14:37 | [diff] [blame] | 148 | |
[email protected] | c1b2d04 | 2013-02-23 00:31:04 | [diff] [blame^] | 149 | if (prompt_type_ == INLINE_PROMPT) { |
| 150 | web_contents()->OpenURL(OpenURLParams( |
| 151 | GURL(redirect_url), |
| 152 | content::Referrer(web_contents()->GetURL(), |
| 153 | WebKit::WebReferrerPolicyDefault), |
| 154 | NEW_FOREGROUND_TAB, |
| 155 | content::PAGE_TRANSITION_AUTO_BOOKMARK, |
| 156 | false)); |
| 157 | } |
[email protected] | dd5161a | 2011-09-14 17:40:17 | [diff] [blame] | 158 | CompleteInstall(kInlineInstallSupportedError); |
| 159 | return; |
| 160 | } |
| 161 | |
| 162 | // Manifest, number of users, average rating and rating count are required. |
| 163 | std::string manifest; |
| 164 | if (!webstore_data->GetString(kManifestKey, &manifest) || |
| 165 | !webstore_data->GetString(kUsersKey, &localized_user_count_) || |
[email protected] | 5fdbd6f | 2011-09-01 17:33:04 | [diff] [blame] | 166 | !webstore_data->GetDouble(kAverageRatingKey, &average_rating_) || |
| 167 | !webstore_data->GetInteger(kRatingCountKey, &rating_count_)) { |
| 168 | CompleteInstall(kInvalidWebstoreResponseError); |
| 169 | return; |
| 170 | } |
| 171 | |
[email protected] | c82da8c4 | 2012-06-08 19:49:11 | [diff] [blame] | 172 | if (average_rating_ < ExtensionInstallPrompt::kMinExtensionRating || |
| 173 | average_rating_ > ExtensionInstallPrompt::kMaxExtensionRating) { |
[email protected] | 5fdbd6f | 2011-09-01 17:33:04 | [diff] [blame] | 174 | CompleteInstall(kInvalidWebstoreResponseError); |
| 175 | return; |
| 176 | } |
| 177 | |
| 178 | // Localized name and description are optional. |
| 179 | if ((webstore_data->HasKey(kLocalizedNameKey) && |
| 180 | !webstore_data->GetString(kLocalizedNameKey, &localized_name_)) || |
| 181 | (webstore_data->HasKey(kLocalizedDescriptionKey) && |
| 182 | !webstore_data->GetString( |
| 183 | kLocalizedDescriptionKey, &localized_description_))) { |
[email protected] | 8915f34 | 2011-08-29 22:14:37 | [diff] [blame] | 184 | CompleteInstall(kInvalidWebstoreResponseError); |
| 185 | return; |
| 186 | } |
| 187 | |
| 188 | // Icon URL is optional. |
| 189 | GURL icon_url; |
| 190 | if (webstore_data->HasKey(kIconUrlKey)) { |
| 191 | std::string icon_url_string; |
| 192 | if (!webstore_data->GetString(kIconUrlKey, &icon_url_string)) { |
| 193 | CompleteInstall(kInvalidWebstoreResponseError); |
| 194 | return; |
| 195 | } |
| 196 | icon_url = GURL(extension_urls::GetWebstoreLaunchURL()).Resolve( |
| 197 | icon_url_string); |
| 198 | if (!icon_url.is_valid()) { |
| 199 | CompleteInstall(kInvalidWebstoreResponseError); |
| 200 | return; |
| 201 | } |
| 202 | } |
| 203 | |
[email protected] | d2a639e | 2012-09-17 07:41:21 | [diff] [blame] | 204 | // Check for a verified site if required. |
| 205 | if (require_verified_site_) { |
| 206 | if (!webstore_data->HasKey(kVerifiedSiteKey)) { |
| 207 | CompleteInstall(kNoVerifiedSiteError); |
| 208 | return; |
| 209 | } |
[email protected] | bdb74a2 | 2012-01-25 20:33:33 | [diff] [blame] | 210 | std::string verified_site; |
| 211 | if (!webstore_data->GetString(kVerifiedSiteKey, &verified_site)) { |
[email protected] | a221ef09 | 2011-09-07 01:34:10 | [diff] [blame] | 212 | CompleteInstall(kInvalidWebstoreResponseError); |
| 213 | return; |
| 214 | } |
[email protected] | bdb74a2 | 2012-01-25 20:33:33 | [diff] [blame] | 215 | if (!IsRequestorURLInVerifiedSite(requestor_url_, verified_site)) { |
[email protected] | 5da311ea | 2011-09-14 20:57:32 | [diff] [blame] | 216 | CompleteInstall(kNotFromVerifiedSiteError); |
[email protected] | a221ef09 | 2011-09-07 01:34:10 | [diff] [blame] | 217 | return; |
| 218 | } |
| 219 | } |
| 220 | |
[email protected] | 8915f34 | 2011-08-29 22:14:37 | [diff] [blame] | 221 | scoped_refptr<WebstoreInstallHelper> helper = new WebstoreInstallHelper( |
| 222 | this, |
[email protected] | 98e4e52 | 2011-10-25 13:00:16 | [diff] [blame] | 223 | id_, |
[email protected] | 8915f34 | 2011-08-29 22:14:37 | [diff] [blame] | 224 | manifest, |
[email protected] | 5db2e88 | 2012-12-20 10:17:26 | [diff] [blame] | 225 | "", // We don't have any icon data. |
[email protected] | 8915f34 | 2011-08-29 22:14:37 | [diff] [blame] | 226 | icon_url, |
[email protected] | c1b2d04 | 2013-02-23 00:31:04 | [diff] [blame^] | 227 | profile_->GetRequestContext()); |
[email protected] | 8915f34 | 2011-08-29 22:14:37 | [diff] [blame] | 228 | // The helper will call us back via OnWebstoreParseSucces or |
| 229 | // OnWebstoreParseFailure. |
| 230 | helper->Start(); |
| 231 | } |
| 232 | |
[email protected] | 734bcec | 2012-10-08 20:29:05 | [diff] [blame] | 233 | void WebstoreStandaloneInstaller::OnWebstoreResponseParseFailure( |
[email protected] | 8915f34 | 2011-08-29 22:14:37 | [diff] [blame] | 234 | const std::string& error) { |
| 235 | CompleteInstall(error); |
| 236 | } |
| 237 | |
[email protected] | 734bcec | 2012-10-08 20:29:05 | [diff] [blame] | 238 | void WebstoreStandaloneInstaller::OnWebstoreParseSuccess( |
[email protected] | 98e4e52 | 2011-10-25 13:00:16 | [diff] [blame] | 239 | const std::string& id, |
[email protected] | 8915f34 | 2011-08-29 22:14:37 | [diff] [blame] | 240 | const SkBitmap& icon, |
| 241 | base::DictionaryValue* manifest) { |
[email protected] | 2fd920fb | 2011-09-08 23:33:00 | [diff] [blame] | 242 | // Check if the tab has gone away in the meantime. |
[email protected] | c1b2d04 | 2013-02-23 00:31:04 | [diff] [blame^] | 243 | if (prompt_type_ == INLINE_PROMPT && !web_contents()) { |
[email protected] | 2fd920fb | 2011-09-08 23:33:00 | [diff] [blame] | 244 | CompleteInstall(""); |
| 245 | return; |
| 246 | } |
| 247 | |
[email protected] | 98e4e52 | 2011-10-25 13:00:16 | [diff] [blame] | 248 | CHECK_EQ(id_, id); |
[email protected] | 8915f34 | 2011-08-29 22:14:37 | [diff] [blame] | 249 | manifest_.reset(manifest); |
| 250 | icon_ = icon; |
| 251 | |
[email protected] | 77e9261d | 2013-02-04 22:01:47 | [diff] [blame] | 252 | if (prompt_type_ == SKIP_PROMPT) { |
| 253 | InstallUIProceed(); |
| 254 | return; |
| 255 | } |
| 256 | |
| 257 | ExtensionInstallPrompt::PromptType prompt_type = |
| 258 | prompt_type_ == INLINE_PROMPT ? |
| 259 | ExtensionInstallPrompt::INLINE_INSTALL_PROMPT : |
| 260 | ExtensionInstallPrompt::INSTALL_PROMPT; |
[email protected] | 5db2e88 | 2012-12-20 10:17:26 | [diff] [blame] | 261 | ExtensionInstallPrompt::Prompt prompt(prompt_type); |
[email protected] | 77e9261d | 2013-02-04 22:01:47 | [diff] [blame] | 262 | if (prompt_type_ == INLINE_PROMPT) { |
[email protected] | 734bcec | 2012-10-08 20:29:05 | [diff] [blame] | 263 | prompt.SetInlineInstallWebstoreData(localized_user_count_, |
| 264 | average_rating_, |
| 265 | rating_count_); |
| 266 | } |
[email protected] | 514c547 | 2012-04-20 22:56:36 | [diff] [blame] | 267 | std::string error; |
[email protected] | c82da8c4 | 2012-06-08 19:49:11 | [diff] [blame] | 268 | dummy_extension_ = ExtensionInstallPrompt::GetLocalizedExtensionForDisplay( |
[email protected] | c422a86 | 2012-07-31 15:46:13 | [diff] [blame] | 269 | manifest, |
| 270 | Extension::REQUIRE_KEY | Extension::FROM_WEBSTORE, |
| 271 | id_, |
| 272 | localized_name_, |
| 273 | localized_description_, |
| 274 | &error); |
[email protected] | 514c547 | 2012-04-20 22:56:36 | [diff] [blame] | 275 | if (!dummy_extension_) { |
| 276 | OnWebstoreParseFailure(id_, WebstoreInstallHelper::Delegate::MANIFEST_ERROR, |
| 277 | kInvalidManifestError); |
[email protected] | 8915f34 | 2011-08-29 22:14:37 | [diff] [blame] | 278 | return; |
| 279 | } |
| 280 | |
[email protected] | 91e51d61 | 2012-10-21 23:03:05 | [diff] [blame] | 281 | install_ui_.reset(new ExtensionInstallPrompt(web_contents())); |
[email protected] | 77e9261d | 2013-02-04 22:01:47 | [diff] [blame] | 282 | install_ui_->ConfirmStandaloneInstall(this, |
| 283 | dummy_extension_, |
| 284 | &icon_, |
| 285 | prompt); |
[email protected] | 8915f34 | 2011-08-29 22:14:37 | [diff] [blame] | 286 | // Control flow finishes up in InstallUIProceed or InstallUIAbort. |
| 287 | } |
| 288 | |
[email protected] | 734bcec | 2012-10-08 20:29:05 | [diff] [blame] | 289 | void WebstoreStandaloneInstaller::OnWebstoreParseFailure( |
[email protected] | 98e4e52 | 2011-10-25 13:00:16 | [diff] [blame] | 290 | const std::string& id, |
[email protected] | 8915f34 | 2011-08-29 22:14:37 | [diff] [blame] | 291 | InstallHelperResultCode result_code, |
| 292 | const std::string& error_message) { |
| 293 | CompleteInstall(error_message); |
| 294 | } |
| 295 | |
[email protected] | 734bcec | 2012-10-08 20:29:05 | [diff] [blame] | 296 | void WebstoreStandaloneInstaller::InstallUIProceed() { |
[email protected] | 2fd920fb | 2011-09-08 23:33:00 | [diff] [blame] | 297 | // Check if the tab has gone away in the meantime. |
[email protected] | c1b2d04 | 2013-02-23 00:31:04 | [diff] [blame^] | 298 | if (prompt_type_ == INLINE_PROMPT && !web_contents()) { |
[email protected] | 2fd920fb | 2011-09-08 23:33:00 | [diff] [blame] | 299 | CompleteInstall(""); |
| 300 | return; |
| 301 | } |
| 302 | |
[email protected] | 21a5ad6 | 2012-04-03 04:48:45 | [diff] [blame] | 303 | scoped_ptr<WebstoreInstaller::Approval> approval( |
[email protected] | 89019d6 | 2012-05-17 18:47:09 | [diff] [blame] | 304 | WebstoreInstaller::Approval::CreateWithNoInstallPrompt( |
[email protected] | c1b2d04 | 2013-02-23 00:31:04 | [diff] [blame^] | 305 | profile_, |
[email protected] | 89019d6 | 2012-05-17 18:47:09 | [diff] [blame] | 306 | id_, |
| 307 | scoped_ptr<base::DictionaryValue>(manifest_.get()->DeepCopy()))); |
[email protected] | c1b2d04 | 2013-02-23 00:31:04 | [diff] [blame^] | 308 | approval->skip_post_install_ui = (prompt_type_ != INLINE_PROMPT); |
| 309 | approval->use_app_installed_bubble = (prompt_type_ == INLINE_PROMPT); |
[email protected] | 21a5ad6 | 2012-04-03 04:48:45 | [diff] [blame] | 310 | |
[email protected] | 98e4e52 | 2011-10-25 13:00:16 | [diff] [blame] | 311 | scoped_refptr<WebstoreInstaller> installer = new WebstoreInstaller( |
[email protected] | c1b2d04 | 2013-02-23 00:31:04 | [diff] [blame^] | 312 | profile_, this, &(web_contents()->GetController()), id_, approval.Pass(), |
[email protected] | 98e4e52 | 2011-10-25 13:00:16 | [diff] [blame] | 313 | WebstoreInstaller::FLAG_INLINE_INSTALL); |
| 314 | installer->Start(); |
[email protected] | 8915f34 | 2011-08-29 22:14:37 | [diff] [blame] | 315 | } |
| 316 | |
[email protected] | 734bcec | 2012-10-08 20:29:05 | [diff] [blame] | 317 | void WebstoreStandaloneInstaller::InstallUIAbort(bool user_initiated) { |
[email protected] | 8915f34 | 2011-08-29 22:14:37 | [diff] [blame] | 318 | CompleteInstall(kUserCancelledError); |
| 319 | } |
| 320 | |
[email protected] | 734bcec | 2012-10-08 20:29:05 | [diff] [blame] | 321 | void WebstoreStandaloneInstaller::WebContentsDestroyed( |
| 322 | WebContents* web_contents) { |
[email protected] | d2a639e | 2012-09-17 07:41:21 | [diff] [blame] | 323 | callback_.Reset(); |
[email protected] | 2fd920fb | 2011-09-08 23:33:00 | [diff] [blame] | 324 | // Abort any in-progress fetches. |
[email protected] | 7b394105 | 2013-02-13 01:21:59 | [diff] [blame] | 325 | if (webstore_data_fetcher_.get()) { |
| 326 | webstore_data_fetcher_.reset(); |
[email protected] | 5db2e88 | 2012-12-20 10:17:26 | [diff] [blame] | 327 | Release(); // Matches the AddRef in BeginInstall. |
[email protected] | 8915f34 | 2011-08-29 22:14:37 | [diff] [blame] | 328 | } |
[email protected] | 2fd920fb | 2011-09-08 23:33:00 | [diff] [blame] | 329 | } |
| 330 | |
[email protected] | 734bcec | 2012-10-08 20:29:05 | [diff] [blame] | 331 | void WebstoreStandaloneInstaller::OnExtensionInstallSuccess( |
| 332 | const std::string& id) { |
[email protected] | cb08ba2 | 2011-10-19 21:41:40 | [diff] [blame] | 333 | CHECK_EQ(id_, id); |
| 334 | CompleteInstall(""); |
| 335 | } |
| 336 | |
[email protected] | 734bcec | 2012-10-08 20:29:05 | [diff] [blame] | 337 | void WebstoreStandaloneInstaller::OnExtensionInstallFailure( |
[email protected] | bcd1eaf7 | 2012-10-03 05:42:29 | [diff] [blame] | 338 | const std::string& id, |
| 339 | const std::string& error, |
| 340 | WebstoreInstaller::FailureReason cancelled) { |
[email protected] | cb08ba2 | 2011-10-19 21:41:40 | [diff] [blame] | 341 | CHECK_EQ(id_, id); |
| 342 | CompleteInstall(error); |
| 343 | } |
| 344 | |
[email protected] | 734bcec | 2012-10-08 20:29:05 | [diff] [blame] | 345 | void WebstoreStandaloneInstaller::CompleteInstall(const std::string& error) { |
[email protected] | 0688d8dc | 2013-02-16 04:10:38 | [diff] [blame] | 346 | // Clear webstore_data_fetcher_ so that WebContentsDestroyed will no longer |
| 347 | // call Release in case the WebContents is destroyed before this object. |
| 348 | scoped_ptr<WebstoreDataFetcher> webstore_data_fetcher( |
| 349 | webstore_data_fetcher_.Pass()); |
[email protected] | d2a639e | 2012-09-17 07:41:21 | [diff] [blame] | 350 | if (!callback_.is_null()) |
| 351 | callback_.Run(error.empty(), error); |
[email protected] | 2fd920fb | 2011-09-08 23:33:00 | [diff] [blame] | 352 | |
[email protected] | 5db2e88 | 2012-12-20 10:17:26 | [diff] [blame] | 353 | Release(); // Matches the AddRef in BeginInstall. |
[email protected] | 8915f34 | 2011-08-29 22:14:37 | [diff] [blame] | 354 | } |
[email protected] | 5f2a475 | 2012-04-27 22:18:58 | [diff] [blame] | 355 | |
| 356 | // static |
[email protected] | 734bcec | 2012-10-08 20:29:05 | [diff] [blame] | 357 | bool WebstoreStandaloneInstaller::IsRequestorURLInVerifiedSite( |
[email protected] | 5f2a475 | 2012-04-27 22:18:58 | [diff] [blame] | 358 | const GURL& requestor_url, |
| 359 | const std::string& verified_site) { |
| 360 | // Turn the verified site (which may be a bare domain, or have a port and/or a |
| 361 | // path) into a URL that can be parsed by URLPattern. |
| 362 | std::string verified_site_url = |
| 363 | StringPrintf("http://*.%s%s", |
| 364 | verified_site.c_str(), |
| 365 | verified_site.find('/') == std::string::npos ? "/*" : "*"); |
| 366 | |
| 367 | URLPattern verified_site_pattern( |
| 368 | URLPattern::SCHEME_HTTP | URLPattern::SCHEME_HTTPS); |
| 369 | URLPattern::ParseResult parse_result = |
| 370 | verified_site_pattern.Parse(verified_site_url); |
| 371 | if (parse_result != URLPattern::PARSE_SUCCESS) { |
| 372 | DLOG(WARNING) << "Could not parse " << verified_site_url << |
| 373 | " as URL pattern " << parse_result; |
| 374 | return false; |
| 375 | } |
| 376 | verified_site_pattern.SetScheme("*"); |
| 377 | |
| 378 | return verified_site_pattern.MatchesURL(requestor_url); |
| 379 | } |
[email protected] | 3d61a7f | 2012-07-12 19:11:25 | [diff] [blame] | 380 | |
| 381 | } // namespace extensions |