1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Use of this source code is governed by a BSD-style license that can be
3ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// found in the LICENSE file.
4ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
5ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "chrome/browser/extensions/webstore_inline_installer.h"
6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "base/strings/stringprintf.h"
8ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "chrome/browser/profiles/profile.h"
9ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "content/public/browser/web_contents.h"
10ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruusing content::WebContents;
12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querunamespace extensions {
14ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst char kInvalidWebstoreResponseError[] = "Invalid Chrome Web Store reponse";
16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst char kNoVerifiedSitesError[] =
17ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "Inline installs can only be initiated for Chrome Web Store items that "
18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "have one or more verified sites";
19ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst char kNotFromVerifiedSitesError[] =
20ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "Installs can only be initiated by one of the Chrome Web Store item's "
21ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "verified sites";
22ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst char kInlineInstallSupportedError[] =
23ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "Inline installation is not supported for this item. The user will be "
24ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "redirected to the Chrome Web Store.";
25ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
26ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruWebstoreInlineInstaller::WebstoreInlineInstaller(
27ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    content::WebContents* web_contents,
28ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const std::string& webstore_item_id,
29ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const GURL& requestor_url,
30ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const Callback& callback)
31ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    : WebstoreStandaloneInstaller(
32ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru          webstore_item_id,
33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru          Profile::FromBrowserContext(web_contents->GetBrowserContext()),
34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru          callback),
35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      content::WebContentsObserver(web_contents),
36ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      requestor_url_(requestor_url) {
37ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
38ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
39ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruWebstoreInlineInstaller::~WebstoreInlineInstaller() {}
40ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
41ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querubool WebstoreInlineInstaller::CheckRequestorAlive() const {
42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  // The tab may have gone away - cancel installation in that case.
43ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  return web_contents() != NULL;
44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
45ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
46ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst GURL& WebstoreInlineInstaller::GetRequestorURL() const {
47ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  return requestor_url_;
48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruscoped_refptr<ExtensionInstallPrompt::Prompt>
51ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruWebstoreInlineInstaller::CreateInstallPrompt() const {
52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  scoped_refptr<ExtensionInstallPrompt::Prompt> prompt(
53ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      new ExtensionInstallPrompt::Prompt(
54ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru          ExtensionInstallPrompt::INLINE_INSTALL_PROMPT));
55ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
56ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  // crbug.com/260742: Don't display the user count if it's zero. The reason
57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  // it's zero is very often that the number isn't actually being counted
58ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  // (intentionally), which means that it's unlikely to be correct.
59ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  prompt->SetWebstoreData(localized_user_count(),
60ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          show_user_count(),
61ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          average_rating(),
62ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          rating_count());
63ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  return prompt;
64ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
65ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
66ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querubool WebstoreInlineInstaller::ShouldShowPostInstallUI() const {
67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  return true;
68ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
69ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
70ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querubool WebstoreInlineInstaller::ShouldShowAppInstalledBubble() const {
71ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  return true;
72ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
73ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
74ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruWebContents* WebstoreInlineInstaller::GetWebContents() const {
75ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  return web_contents();
76ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
77ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
78ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querubool WebstoreInlineInstaller::CheckInlineInstallPermitted(
79ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const base::DictionaryValue& webstore_data,
80ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    std::string* error) const {
81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  // The store may not support inline installs for this item, in which case
82ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  // we open the store-provided redirect URL in a new tab and abort the
83ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  // installation process.
84ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  bool inline_install_not_supported = false;
85ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  if (webstore_data.HasKey(kInlineInstallNotSupportedKey)
86ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      && !webstore_data.GetBoolean(kInlineInstallNotSupportedKey,
87ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                    &inline_install_not_supported)) {
88ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *error = kInvalidWebstoreResponseError;
89ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return false;
90ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  }
91ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  if (inline_install_not_supported) {
92ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    std::string redirect_url;
93ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (!webstore_data.GetString(kRedirectUrlKey, &redirect_url)) {
94ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      *error = kInvalidWebstoreResponseError;
95ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      return false;
96ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
97ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    web_contents()->OpenURL(
98ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        content::OpenURLParams(
99ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            GURL(redirect_url),
100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            content::Referrer(web_contents()->GetURL(),
101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              blink::WebReferrerPolicyDefault),
102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            NEW_FOREGROUND_TAB, ui::PAGE_TRANSITION_AUTO_BOOKMARK, false));
103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *error = kInlineInstallSupportedError;
104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return false;
105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  }
106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  *error = "";
108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  return true;
109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querubool WebstoreInlineInstaller::CheckRequestorPermitted(
112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const base::DictionaryValue& webstore_data,
113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    std::string* error) const {
114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  // Ensure that there is at least one verified site present.
115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  const bool data_has_single_site = webstore_data.HasKey(kVerifiedSiteKey);
116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  const bool data_has_site_list = webstore_data.HasKey(kVerifiedSitesKey);
117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  if (!data_has_single_site && !data_has_site_list) {
118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *error = kNoVerifiedSitesError;
119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return false;
120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  }
121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  bool requestor_is_ok = false;
122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  // Handle the deprecated single-site case.
123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  if (!data_has_site_list) {
124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    std::string verified_site;
125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (!webstore_data.GetString(kVerifiedSiteKey, &verified_site)) {
126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      *error = kInvalidWebstoreResponseError;
127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      return false;
128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    requestor_is_ok = IsRequestorURLInVerifiedSite(requestor_url_,
130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                                   verified_site);
131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  } else {
132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const base::ListValue* verified_sites = NULL;
133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (!webstore_data.GetList(kVerifiedSitesKey, &verified_sites)) {
134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      *error = kInvalidWebstoreResponseError;
135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      return false;
136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (base::ListValue::const_iterator it = verified_sites->begin();
138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         it != verified_sites->end() && !requestor_is_ok; ++it) {
139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      std::string verified_site;
140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      if (!(*it)->GetAsString(&verified_site)) {
141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *error = kInvalidWebstoreResponseError;
142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return false;
143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      }
144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      if (IsRequestorURLInVerifiedSite(requestor_url_, verified_site)) {
145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        requestor_is_ok = true;
146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      }
147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  }
149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  if (!requestor_is_ok) {
150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *error = kNotFromVerifiedSitesError;
151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return false;
152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  }
153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  *error = "";
154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  return true;
155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
157ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//
158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Private implementation.
159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//
160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid WebstoreInlineInstaller::WebContentsDestroyed() {
162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  AbortInstall();
163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// static
166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querubool WebstoreInlineInstaller::IsRequestorURLInVerifiedSite(
167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const GURL& requestor_url,
168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const std::string& verified_site) {
169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  // Turn the verified site into a URL that can be parsed by URLPattern.
170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  // |verified_site| must follow the format:
171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  //
172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  // [scheme://]host[:port][/path/specifier]
173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  //
174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  // If scheme is omitted, URLPattern will match against either an
175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  // HTTP or HTTPS requestor. If scheme is specified, it must be either HTTP
176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  // or HTTPS, and URLPattern will only match the scheme specified.
177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  GURL verified_site_url(verified_site);
178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  int valid_schemes = URLPattern::SCHEME_HTTP | URLPattern::SCHEME_HTTPS;
179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  if (!verified_site_url.is_valid() || !verified_site_url.IsStandard())
180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // If no scheme is specified, GURL will fail to parse the string correctly.
181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // It will either determine that the URL is invalid, or parse a
182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // host:port/path as scheme:host/path.
183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    verified_site_url = GURL("http://" + verified_site);
184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  else if (verified_site_url.SchemeIs("http"))
185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    valid_schemes = URLPattern::SCHEME_HTTP;
186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  else if (verified_site_url.SchemeIs("https"))
187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    valid_schemes = URLPattern::SCHEME_HTTPS;
188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  else
189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return false;
190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  std::string port_spec =
192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      verified_site_url.has_port() ? ":" + verified_site_url.port() : "";
193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  std::string path_spec = verified_site_url.path() + "*";
194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  std::string verified_site_pattern_spec =
195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      base::StringPrintf(
196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru          "%s://*.%s%s%s",
197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru          verified_site_url.scheme().c_str(),
198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru          verified_site_url.host().c_str(),
199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru          port_spec.c_str(),
200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru          path_spec.c_str());
201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  URLPattern verified_site_pattern(valid_schemes);
203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  URLPattern::ParseResult parse_result =
204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      verified_site_pattern.Parse(verified_site_pattern_spec);
205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  if (parse_result != URLPattern::PARSE_SUCCESS) {
206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    DLOG(WARNING) << "Could not parse " << verified_site_pattern_spec <<
207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        " as URL pattern " << parse_result;
208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return false;
209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  }
210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  verified_site_pattern.SetScheme("*");
211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  return verified_site_pattern.MatchesURL(requestor_url);
213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}  // namespace extensions
216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru