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