blob: 4a5642010b8956cd40a21a3b92b4fac5a89a200d [file] [log] [blame]
[email protected]bdb74a22012-01-25 20:33:331// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]8915f342011-08-29 22:14:372// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/extensions/webstore_inline_installer.h"
6
7#include <vector>
8
[email protected]8e6ac4b2011-10-17 19:04:319#include "base/bind.h"
[email protected]8915f342011-08-29 22:14:3710#include "base/string_util.h"
11#include "base/values.h"
12#include "chrome/browser/browser_process.h"
13#include "chrome/browser/extensions/crx_installer.h"
14#include "chrome/browser/extensions/extension_install_dialog.h"
[email protected]655b2b1a2011-10-13 17:13:0615#include "chrome/browser/extensions/extension_service.h"
[email protected]8915f342011-08-29 22:14:3716#include "chrome/browser/profiles/profile.h"
17#include "chrome/common/chrome_utility_messages.h"
18#include "chrome/common/extensions/extension.h"
19#include "chrome/common/extensions/extension_constants.h"
[email protected]a221ef092011-09-07 01:34:1020#include "chrome/common/extensions/url_pattern.h"
[email protected]bdb74a22012-01-25 20:33:3321#include "chrome/common/url_constants.h"
[email protected]ea049a02011-12-25 21:37:0922#include "content/public/browser/web_contents.h"
[email protected]c4f883a2012-02-03 17:02:0723#include "content/public/browser/utility_process_host.h"
24#include "content/public/browser/utility_process_host_client.h"
[email protected]7b419b82011-10-27 04:23:4625#include "content/public/common/url_fetcher.h"
[email protected]8915f342011-08-29 22:14:3726#include "net/base/escape.h"
[email protected]41e9a0de2011-09-14 17:24:5127#include "net/base/load_flags.h"
[email protected]8915f342011-08-29 22:14:3728#include "net/url_request/url_request_status.h"
29
[email protected]631bb742011-11-02 11:29:3930using content::BrowserThread;
[email protected]e5d549d2011-12-28 01:29:2031using content::OpenURLParams;
[email protected]c4f883a2012-02-03 17:02:0732using content::UtilityProcessHost;
33using content::UtilityProcessHostClient;
[email protected]26b5e322011-12-23 01:36:4734using content::WebContents;
[email protected]631bb742011-11-02 11:29:3935
[email protected]8915f342011-08-29 22:14:3736const char kManifestKey[] = "manifest";
37const char kIconUrlKey[] = "icon_url";
38const char kLocalizedNameKey[] = "localized_name";
[email protected]5fdbd6f2011-09-01 17:33:0439const char kLocalizedDescriptionKey[] = "localized_description";
40const char kUsersKey[] = "users";
41const char kAverageRatingKey[] = "average_rating";
42const char kRatingCountKey[] = "rating_count";
[email protected]a221ef092011-09-07 01:34:1043const char kVerifiedSiteKey[] = "verified_site";
[email protected]dd5161a2011-09-14 17:40:1744const char kInlineInstallNotSupportedKey[] = "inline_install_not_supported";
45const char kRedirectUrlKey[] = "redirect_url";
[email protected]8915f342011-08-29 22:14:3746
[email protected]a221ef092011-09-07 01:34:1047const char kInvalidWebstoreItemId[] = "Invalid Chrome Web Store item ID";
48const char kWebstoreRequestError[] =
49 "Could not fetch data from the Chrome Web Store";
50const char kInvalidWebstoreResponseError[] = "Invalid Chrome Web Store reponse";
[email protected]8915f342011-08-29 22:14:3751const char kInvalidManifestError[] = "Invalid manifest";
52const char kUserCancelledError[] = "User cancelled install";
[email protected]5da311ea2011-09-14 20:57:3253const char kNoVerifiedSiteError[] =
54 "Inline installs can only be initiated for Chrome Web Store items that "
55 "have a verified site";
56const char kNotFromVerifiedSiteError[] =
[email protected]a221ef092011-09-07 01:34:1057 "Installs can only be initiated by the Chrome Web Store item's verified "
58 "site";
[email protected]dd5161a2011-09-14 17:40:1759const char kInlineInstallSupportedError[] =
60 "Inline installation is not supported for this item. The user will be "
61 "redirected to the Chrome Web Store.";
[email protected]8915f342011-08-29 22:14:3762
[email protected]c4f883a2012-02-03 17:02:0763class SafeWebstoreResponseParser : public UtilityProcessHostClient {
[email protected]8915f342011-08-29 22:14:3764 public:
65 SafeWebstoreResponseParser(WebstoreInlineInstaller *client,
66 const std::string& webstore_data)
67 : client_(client),
[email protected]c4f883a2012-02-03 17:02:0768 webstore_data_(webstore_data) {}
[email protected]8915f342011-08-29 22:14:3769
70 void Start() {
71 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
72 BrowserThread::PostTask(
73 BrowserThread::IO,
74 FROM_HERE,
[email protected]8e6ac4b2011-10-17 19:04:3175 base::Bind(&SafeWebstoreResponseParser::StartWorkOnIOThread, this));
[email protected]8915f342011-08-29 22:14:3776 }
77
78 void StartWorkOnIOThread() {
79 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
[email protected]c4f883a2012-02-03 17:02:0780 UtilityProcessHost* host =
81 UtilityProcessHost::Create(this, BrowserThread::IO);
82 host->EnableZygote();
83 host->Send(new ChromeUtilityMsg_ParseJSON(webstore_data_));
[email protected]8915f342011-08-29 22:14:3784 }
85
[email protected]c4f883a2012-02-03 17:02:0786 // Implementing pieces of the UtilityProcessHostClient interface.
[email protected]8915f342011-08-29 22:14:3787 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
88 bool handled = true;
89 IPC_BEGIN_MESSAGE_MAP(SafeWebstoreResponseParser, message)
90 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ParseJSON_Succeeded,
91 OnJSONParseSucceeded)
92 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ParseJSON_Failed,
93 OnJSONParseFailed)
94 IPC_MESSAGE_UNHANDLED(handled = false)
95 IPC_END_MESSAGE_MAP()
96 return handled;
97 }
98
99 void OnJSONParseSucceeded(const ListValue& wrapper) {
100 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
101 Value* value = NULL;
102 CHECK(wrapper.Get(0, &value));
103 if (value->IsType(Value::TYPE_DICTIONARY)) {
104 parsed_webstore_data_.reset(
105 static_cast<DictionaryValue*>(value)->DeepCopy());
106 } else {
107 error_ = kInvalidWebstoreResponseError;
108 }
109
110 ReportResults();
111 }
112
113 virtual void OnJSONParseFailed(const std::string& error_message) {
114 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
115 error_ = error_message;
116 ReportResults();
117 }
118
119 void ReportResults() {
120 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
121
[email protected]8915f342011-08-29 22:14:37122 BrowserThread::PostTask(
123 BrowserThread::UI,
124 FROM_HERE,
[email protected]8e6ac4b2011-10-17 19:04:31125 base::Bind(&SafeWebstoreResponseParser::ReportResultOnUIThread, this));
[email protected]8915f342011-08-29 22:14:37126 }
127
128 void ReportResultOnUIThread() {
129 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
130 if (error_.empty() && parsed_webstore_data_.get()) {
131 client_->OnWebstoreResponseParseSuccess(parsed_webstore_data_.release());
132 } else {
133 client_->OnWebstoreResponseParseFailure(error_);
134 }
135 }
136
137 private:
138 virtual ~SafeWebstoreResponseParser() {}
139
140 WebstoreInlineInstaller* client_;
141
142 std::string webstore_data_;
[email protected]8915f342011-08-29 22:14:37143 std::string error_;
144 scoped_ptr<DictionaryValue> parsed_webstore_data_;
145};
146
[email protected]26b5e322011-12-23 01:36:47147WebstoreInlineInstaller::WebstoreInlineInstaller(WebContents* web_contents,
[email protected]a221ef092011-09-07 01:34:10148 int install_id,
[email protected]7b921042012-02-11 01:41:27149 int return_route_id,
[email protected]8915f342011-08-29 22:14:37150 std::string webstore_item_id,
[email protected]a221ef092011-09-07 01:34:10151 GURL requestor_url,
[email protected]8915f342011-08-29 22:14:37152 Delegate* delegate)
[email protected]26b5e322011-12-23 01:36:47153 : content::WebContentsObserver(web_contents),
[email protected]a221ef092011-09-07 01:34:10154 install_id_(install_id),
[email protected]7b921042012-02-11 01:41:27155 return_route_id_(return_route_id),
[email protected]8915f342011-08-29 22:14:37156 id_(webstore_item_id),
[email protected]a221ef092011-09-07 01:34:10157 requestor_url_(requestor_url),
[email protected]c7bf7452011-09-12 21:31:50158 delegate_(delegate),
159 average_rating_(0.0),
[email protected]5f2a4752012-04-27 22:18:58160 rating_count_(0) {
[email protected]8915f342011-08-29 22:14:37161}
162
163void WebstoreInlineInstaller::BeginInstall() {
[email protected]26b5e322011-12-23 01:36:47164 AddRef(); // Balanced in CompleteInstall or WebContentsDestroyed.
[email protected]8915f342011-08-29 22:14:37165
166 if (!Extension::IdIsValid(id_)) {
167 CompleteInstall(kInvalidWebstoreItemId);
168 return;
169 }
170
171 GURL webstore_data_url(extension_urls::GetWebstoreItemJsonDataURL(id_));
172
[email protected]36aea2702011-10-26 01:12:22173 webstore_data_url_fetcher_.reset(content::URLFetcher::Create(
174 webstore_data_url, content::URLFetcher::GET, this));
[email protected]8915f342011-08-29 22:14:37175 Profile* profile = Profile::FromBrowserContext(
[email protected]ea049a02011-12-25 21:37:09176 web_contents()->GetBrowserContext());
[email protected]7cc6e5632011-10-25 17:56:12177 webstore_data_url_fetcher_->SetRequestContext(
[email protected]8915f342011-08-29 22:14:37178 profile->GetRequestContext());
[email protected]b4574c02011-11-17 06:19:13179 // Use the requesting page as the referrer both since that is more correct
180 // (it is the page that caused this request to happen) and so that we can
181 // track top sites that trigger inline install requests.
182 webstore_data_url_fetcher_->SetReferrer(requestor_url_.spec());
[email protected]7cc6e5632011-10-25 17:56:12183 webstore_data_url_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
184 net::LOAD_DO_NOT_SAVE_COOKIES |
185 net::LOAD_DISABLE_CACHE);
[email protected]8915f342011-08-29 22:14:37186 webstore_data_url_fetcher_->Start();
187}
188
[email protected]5f2a4752012-04-27 22:18:58189WebstoreInlineInstaller::~WebstoreInlineInstaller() {}
190
[email protected]7cc6e5632011-10-25 17:56:12191void WebstoreInlineInstaller::OnURLFetchComplete(
192 const content::URLFetcher* source) {
[email protected]8915f342011-08-29 22:14:37193 CHECK_EQ(webstore_data_url_fetcher_.get(), source);
[email protected]26b5e322011-12-23 01:36:47194 // We shouldn't be getting UrlFetcher callbacks if the WebContents has gone
195 // away; we stop any in in-progress fetches in WebContentsDestroyed.
[email protected]ea049a02011-12-25 21:37:09196 CHECK(web_contents());
[email protected]8915f342011-08-29 22:14:37197
[email protected]7cc6e5632011-10-25 17:56:12198 if (!webstore_data_url_fetcher_->GetStatus().is_success() ||
199 webstore_data_url_fetcher_->GetResponseCode() != 200) {
[email protected]8915f342011-08-29 22:14:37200 CompleteInstall(kWebstoreRequestError);
201 return;
202 }
203
204 std::string webstore_json_data;
205 webstore_data_url_fetcher_->GetResponseAsString(&webstore_json_data);
206 webstore_data_url_fetcher_.reset();
207
208 scoped_refptr<SafeWebstoreResponseParser> parser =
209 new SafeWebstoreResponseParser(this, webstore_json_data);
210 // The parser will call us back via OnWebstoreResponseParseSucces or
211 // OnWebstoreResponseParseFailure.
212 parser->Start();
213}
214
215void WebstoreInlineInstaller::OnWebstoreResponseParseSuccess(
216 DictionaryValue* webstore_data) {
[email protected]4693243e2011-09-09 23:52:37217 // Check if the tab has gone away in the meantime.
[email protected]ea049a02011-12-25 21:37:09218 if (!web_contents()) {
[email protected]4693243e2011-09-09 23:52:37219 CompleteInstall("");
220 return;
221 }
222
[email protected]8915f342011-08-29 22:14:37223 webstore_data_.reset(webstore_data);
224
[email protected]dd5161a2011-09-14 17:40:17225 // The store may not support inline installs for this item, in which case
226 // we open the store-provided redirect URL in a new tab and abort the
227 // installation process.
228 bool inline_install_not_supported = false;
229 if (webstore_data->HasKey(kInlineInstallNotSupportedKey) &&
230 !webstore_data->GetBoolean(
231 kInlineInstallNotSupportedKey, &inline_install_not_supported)) {
[email protected]8915f342011-08-29 22:14:37232 CompleteInstall(kInvalidWebstoreResponseError);
233 return;
234 }
[email protected]dd5161a2011-09-14 17:40:17235 if (inline_install_not_supported) {
236 std::string redirect_url;
237 if (!webstore_data->GetString(kRedirectUrlKey, &redirect_url)) {
238 CompleteInstall(kInvalidWebstoreResponseError);
239 return;
240 }
[email protected]8915f342011-08-29 22:14:37241
[email protected]ea049a02011-12-25 21:37:09242 web_contents()->OpenURL(OpenURLParams(
[email protected]dd5161a2011-09-14 17:40:17243 GURL(redirect_url),
[email protected]ea049a02011-12-25 21:37:09244 content::Referrer(web_contents()->GetURL(),
[email protected]bce1f1c2011-12-05 15:11:58245 WebKit::WebReferrerPolicyDefault),
[email protected]dd5161a2011-09-14 17:40:17246 NEW_FOREGROUND_TAB,
[email protected]e47ae9472011-10-13 19:48:34247 content::PAGE_TRANSITION_AUTO_BOOKMARK,
248 false));
[email protected]dd5161a2011-09-14 17:40:17249 CompleteInstall(kInlineInstallSupportedError);
250 return;
251 }
252
253 // Manifest, number of users, average rating and rating count are required.
254 std::string manifest;
255 if (!webstore_data->GetString(kManifestKey, &manifest) ||
256 !webstore_data->GetString(kUsersKey, &localized_user_count_) ||
[email protected]5fdbd6f2011-09-01 17:33:04257 !webstore_data->GetDouble(kAverageRatingKey, &average_rating_) ||
258 !webstore_data->GetInteger(kRatingCountKey, &rating_count_)) {
259 CompleteInstall(kInvalidWebstoreResponseError);
260 return;
261 }
262
263 if (average_rating_ < ExtensionInstallUI::kMinExtensionRating ||
264 average_rating_ >ExtensionInstallUI::kMaxExtensionRating) {
265 CompleteInstall(kInvalidWebstoreResponseError);
266 return;
267 }
268
269 // Localized name and description are optional.
270 if ((webstore_data->HasKey(kLocalizedNameKey) &&
271 !webstore_data->GetString(kLocalizedNameKey, &localized_name_)) ||
272 (webstore_data->HasKey(kLocalizedDescriptionKey) &&
273 !webstore_data->GetString(
274 kLocalizedDescriptionKey, &localized_description_))) {
[email protected]8915f342011-08-29 22:14:37275 CompleteInstall(kInvalidWebstoreResponseError);
276 return;
277 }
278
279 // Icon URL is optional.
280 GURL icon_url;
281 if (webstore_data->HasKey(kIconUrlKey)) {
282 std::string icon_url_string;
283 if (!webstore_data->GetString(kIconUrlKey, &icon_url_string)) {
284 CompleteInstall(kInvalidWebstoreResponseError);
285 return;
286 }
287 icon_url = GURL(extension_urls::GetWebstoreLaunchURL()).Resolve(
288 icon_url_string);
289 if (!icon_url.is_valid()) {
290 CompleteInstall(kInvalidWebstoreResponseError);
291 return;
292 }
293 }
294
[email protected]5da311ea2011-09-14 20:57:32295 // Verified site is required
[email protected]a221ef092011-09-07 01:34:10296 if (webstore_data->HasKey(kVerifiedSiteKey)) {
[email protected]bdb74a22012-01-25 20:33:33297 std::string verified_site;
298 if (!webstore_data->GetString(kVerifiedSiteKey, &verified_site)) {
[email protected]a221ef092011-09-07 01:34:10299 CompleteInstall(kInvalidWebstoreResponseError);
300 return;
301 }
302
[email protected]bdb74a22012-01-25 20:33:33303 if (!IsRequestorURLInVerifiedSite(requestor_url_, verified_site)) {
[email protected]5da311ea2011-09-14 20:57:32304 CompleteInstall(kNotFromVerifiedSiteError);
[email protected]a221ef092011-09-07 01:34:10305 return;
306 }
[email protected]5da311ea2011-09-14 20:57:32307 } else {
308 CompleteInstall(kNoVerifiedSiteError);
309 return;
[email protected]a221ef092011-09-07 01:34:10310 }
311
[email protected]8915f342011-08-29 22:14:37312 scoped_refptr<WebstoreInstallHelper> helper = new WebstoreInstallHelper(
313 this,
[email protected]98e4e522011-10-25 13:00:16314 id_,
[email protected]8915f342011-08-29 22:14:37315 manifest,
316 "", // We don't have any icon data.
317 icon_url,
[email protected]ea049a02011-12-25 21:37:09318 Profile::FromBrowserContext(web_contents()->GetBrowserContext())->
[email protected]8915f342011-08-29 22:14:37319 GetRequestContext());
320 // The helper will call us back via OnWebstoreParseSucces or
321 // OnWebstoreParseFailure.
322 helper->Start();
323}
324
[email protected]8915f342011-08-29 22:14:37325void WebstoreInlineInstaller::OnWebstoreResponseParseFailure(
326 const std::string& error) {
327 CompleteInstall(error);
328}
329
330void WebstoreInlineInstaller::OnWebstoreParseSuccess(
[email protected]98e4e522011-10-25 13:00:16331 const std::string& id,
[email protected]8915f342011-08-29 22:14:37332 const SkBitmap& icon,
333 base::DictionaryValue* manifest) {
[email protected]2fd920fb2011-09-08 23:33:00334 // Check if the tab has gone away in the meantime.
[email protected]ea049a02011-12-25 21:37:09335 if (!web_contents()) {
[email protected]2fd920fb2011-09-08 23:33:00336 CompleteInstall("");
337 return;
338 }
339
[email protected]98e4e522011-10-25 13:00:16340 CHECK_EQ(id_, id);
[email protected]8915f342011-08-29 22:14:37341 manifest_.reset(manifest);
342 icon_ = icon;
343
344 Profile* profile = Profile::FromBrowserContext(
[email protected]ea049a02011-12-25 21:37:09345 web_contents()->GetBrowserContext());
[email protected]5fdbd6f2011-09-01 17:33:04346
347 ExtensionInstallUI::Prompt prompt(ExtensionInstallUI::INLINE_INSTALL_PROMPT);
[email protected]122e8df2011-09-02 18:20:24348 prompt.SetInlineInstallWebstoreData(localized_user_count_,
349 average_rating_,
350 rating_count_);
[email protected]514c5472012-04-20 22:56:36351 std::string error;
352 dummy_extension_ = ExtensionInstallUI::GetLocalizedExtensionForDisplay(
353 manifest, id_, localized_name_, localized_description_, &error);
354 if (!dummy_extension_) {
355 OnWebstoreParseFailure(id_, WebstoreInstallHelper::Delegate::MANIFEST_ERROR,
356 kInvalidManifestError);
[email protected]8915f342011-08-29 22:14:37357 return;
358 }
359
[email protected]514c5472012-04-20 22:56:36360 install_ui_.reset(new ExtensionInstallUI(profile));
361 install_ui_->ConfirmInlineInstall(this, dummy_extension_, &icon_, prompt);
[email protected]8915f342011-08-29 22:14:37362 // Control flow finishes up in InstallUIProceed or InstallUIAbort.
363}
364
365void WebstoreInlineInstaller::OnWebstoreParseFailure(
[email protected]98e4e522011-10-25 13:00:16366 const std::string& id,
[email protected]8915f342011-08-29 22:14:37367 InstallHelperResultCode result_code,
368 const std::string& error_message) {
369 CompleteInstall(error_message);
370}
371
372void WebstoreInlineInstaller::InstallUIProceed() {
[email protected]2fd920fb2011-09-08 23:33:00373 // Check if the tab has gone away in the meantime.
[email protected]ea049a02011-12-25 21:37:09374 if (!web_contents()) {
[email protected]2fd920fb2011-09-08 23:33:00375 CompleteInstall("");
376 return;
377 }
378
[email protected]655b2b1a2011-10-13 17:13:06379 Profile* profile = Profile::FromBrowserContext(
[email protected]ea049a02011-12-25 21:37:09380 web_contents()->GetBrowserContext());
[email protected]8915f342011-08-29 22:14:37381
[email protected]21a5ad62012-04-03 04:48:45382 scoped_ptr<WebstoreInstaller::Approval> approval(
383 new WebstoreInstaller::Approval);
384 approval->extension_id = id_;
385 approval->profile = profile;
386 approval->parsed_manifest.reset(manifest_.get()->DeepCopy());
387 approval->use_app_installed_bubble = true;
388
[email protected]98e4e522011-10-25 13:00:16389 scoped_refptr<WebstoreInstaller> installer = new WebstoreInstaller(
[email protected]21a5ad62012-04-03 04:48:45390 profile, this, &(web_contents()->GetController()), id_, approval.Pass(),
[email protected]98e4e522011-10-25 13:00:16391 WebstoreInstaller::FLAG_INLINE_INSTALL);
392 installer->Start();
[email protected]8915f342011-08-29 22:14:37393}
394
395void WebstoreInlineInstaller::InstallUIAbort(bool user_initiated) {
396 CompleteInstall(kUserCancelledError);
397}
398
[email protected]26b5e322011-12-23 01:36:47399void WebstoreInlineInstaller::WebContentsDestroyed(WebContents* web_contents) {
[email protected]2fd920fb2011-09-08 23:33:00400 // Abort any in-progress fetches.
401 if (webstore_data_url_fetcher_.get()) {
402 webstore_data_url_fetcher_.reset();
403 Release(); // Matches the AddRef in BeginInstall.
[email protected]8915f342011-08-29 22:14:37404 }
[email protected]2fd920fb2011-09-08 23:33:00405}
406
[email protected]cb08ba22011-10-19 21:41:40407void WebstoreInlineInstaller::OnExtensionInstallSuccess(const std::string& id) {
408 CHECK_EQ(id_, id);
409 CompleteInstall("");
410}
411
412void WebstoreInlineInstaller::OnExtensionInstallFailure(
413 const std::string& id, const std::string& error) {
414 CHECK_EQ(id_, id);
415 CompleteInstall(error);
416}
417
[email protected]2fd920fb2011-09-08 23:33:00418void WebstoreInlineInstaller::CompleteInstall(const std::string& error) {
419 // Only bother responding if there's still a tab contents to send back the
420 // response to.
[email protected]ea049a02011-12-25 21:37:09421 if (web_contents()) {
[email protected]2fd920fb2011-09-08 23:33:00422 if (error.empty()) {
[email protected]7b921042012-02-11 01:41:27423 delegate_->OnInlineInstallSuccess(install_id_, return_route_id_);
[email protected]2fd920fb2011-09-08 23:33:00424 } else {
[email protected]7b921042012-02-11 01:41:27425 delegate_->OnInlineInstallFailure(install_id_, return_route_id_, error);
[email protected]2fd920fb2011-09-08 23:33:00426 }
427 }
428
[email protected]8915f342011-08-29 22:14:37429 Release(); // Matches the AddRef in BeginInstall.
430}
[email protected]5f2a4752012-04-27 22:18:58431
432// static
433bool WebstoreInlineInstaller::IsRequestorURLInVerifiedSite(
434 const GURL& requestor_url,
435 const std::string& verified_site) {
436 // Turn the verified site (which may be a bare domain, or have a port and/or a
437 // path) into a URL that can be parsed by URLPattern.
438 std::string verified_site_url =
439 StringPrintf("http://*.%s%s",
440 verified_site.c_str(),
441 verified_site.find('/') == std::string::npos ? "/*" : "*");
442
443 URLPattern verified_site_pattern(
444 URLPattern::SCHEME_HTTP | URLPattern::SCHEME_HTTPS);
445 URLPattern::ParseResult parse_result =
446 verified_site_pattern.Parse(verified_site_url);
447 if (parse_result != URLPattern::PARSE_SUCCESS) {
448 DLOG(WARNING) << "Could not parse " << verified_site_url <<
449 " as URL pattern " << parse_result;
450 return false;
451 }
452 verified_site_pattern.SetScheme("*");
453
454 return verified_site_pattern.MatchesURL(requestor_url);
455}