Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / extensions / webstore_inline_installer.cc
blob99fa7103cfb3dc78cd7126d5aff7c381c242bedf
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 kVerifiedSiteKey[] = "verified_site";
16 const char kVerifiedSitesKey[] = "verified_sites";
17 const char kInlineInstallNotSupportedKey[] = "inline_install_not_supported";
18 const char kRedirectUrlKey[] = "redirect_url";
20 const char kInvalidWebstoreResponseError[] = "Invalid Chrome Web Store reponse";
21 const char kNoVerifiedSitesError[] =
22 "Inline installs can only be initiated for Chrome Web Store items that "
23 "have one or more verified sites";
24 const char kNotFromVerifiedSitesError[] =
25 "Installs can only be initiated by one of the Chrome Web Store item's "
26 "verified sites";
27 const char kInlineInstallSupportedError[] =
28 "Inline installation is not supported for this item. The user will be "
29 "redirected to the Chrome Web Store.";
31 WebstoreInlineInstaller::WebstoreInlineInstaller(
32 content::WebContents* web_contents,
33 const std::string& webstore_item_id,
34 const GURL& requestor_url,
35 const Callback& callback)
36 : WebstoreStandaloneInstaller(
37 webstore_item_id,
38 Profile::FromBrowserContext(web_contents->GetBrowserContext()),
39 callback),
40 content::WebContentsObserver(web_contents),
41 requestor_url_(requestor_url) {
44 WebstoreInlineInstaller::~WebstoreInlineInstaller() {}
46 bool WebstoreInlineInstaller::CheckRequestorAlive() const {
47 // The tab may have gone away - cancel installation in that case.
48 return web_contents() != NULL;
51 const GURL& WebstoreInlineInstaller::GetRequestorURL() const {
52 return requestor_url_;
55 scoped_ptr<ExtensionInstallPrompt::Prompt>
56 WebstoreInlineInstaller::CreateInstallPrompt() const {
57 scoped_ptr<ExtensionInstallPrompt::Prompt> prompt(
58 new ExtensionInstallPrompt::Prompt(
59 ExtensionInstallPrompt::INLINE_INSTALL_PROMPT));
61 // crbug.com/260742: Don't display the user count if it's zero. The reason
62 // it's zero is very often that the number isn't actually being counted
63 // (intentionally), which means that it's unlikely to be correct.
64 prompt->SetInlineInstallWebstoreData(localized_user_count(),
65 show_user_count(),
66 average_rating(),
67 rating_count());
68 return prompt.Pass();
71 bool WebstoreInlineInstaller::ShouldShowPostInstallUI() const {
72 return true;
75 bool WebstoreInlineInstaller::ShouldShowAppInstalledBubble() const {
76 return true;
79 WebContents* WebstoreInlineInstaller::GetWebContents() const {
80 return web_contents();
83 bool WebstoreInlineInstaller::CheckInlineInstallPermitted(
84 const base::DictionaryValue& webstore_data,
85 std::string* error) const {
86 // The store may not support inline installs for this item, in which case
87 // we open the store-provided redirect URL in a new tab and abort the
88 // installation process.
89 bool inline_install_not_supported = false;
90 if (webstore_data.HasKey(kInlineInstallNotSupportedKey)
91 && !webstore_data.GetBoolean(kInlineInstallNotSupportedKey,
92 &inline_install_not_supported)) {
93 *error = kInvalidWebstoreResponseError;
94 return false;
96 if (inline_install_not_supported) {
97 std::string redirect_url;
98 if (!webstore_data.GetString(kRedirectUrlKey, &redirect_url)) {
99 *error = kInvalidWebstoreResponseError;
100 return false;
102 web_contents()->OpenURL(
103 content::OpenURLParams(
104 GURL(redirect_url),
105 content::Referrer(web_contents()->GetURL(),
106 blink::WebReferrerPolicyDefault),
107 NEW_FOREGROUND_TAB, content::PAGE_TRANSITION_AUTO_BOOKMARK, false));
108 *error = kInlineInstallSupportedError;
109 return false;
112 *error = "";
113 return true;
116 bool WebstoreInlineInstaller::CheckRequestorPermitted(
117 const base::DictionaryValue& webstore_data,
118 std::string* error) const {
119 // Ensure that there is at least one verified site present.
120 const bool data_has_single_site = webstore_data.HasKey(kVerifiedSiteKey);
121 const bool data_has_site_list = webstore_data.HasKey(kVerifiedSitesKey);
122 if (!data_has_single_site && !data_has_site_list) {
123 *error = kNoVerifiedSitesError;
124 return false;
126 bool requestor_is_ok = false;
127 // Handle the deprecated single-site case.
128 if (!data_has_site_list) {
129 std::string verified_site;
130 if (!webstore_data.GetString(kVerifiedSiteKey, &verified_site)) {
131 *error = kInvalidWebstoreResponseError;
132 return false;
134 requestor_is_ok = IsRequestorURLInVerifiedSite(requestor_url_,
135 verified_site);
136 } else {
137 const base::ListValue* verified_sites = NULL;
138 if (!webstore_data.GetList(kVerifiedSitesKey, &verified_sites)) {
139 *error = kInvalidWebstoreResponseError;
140 return false;
142 for (base::ListValue::const_iterator it = verified_sites->begin();
143 it != verified_sites->end() && !requestor_is_ok; ++it) {
144 std::string verified_site;
145 if (!(*it)->GetAsString(&verified_site)) {
146 *error = kInvalidWebstoreResponseError;
147 return false;
149 if (IsRequestorURLInVerifiedSite(requestor_url_, verified_site)) {
150 requestor_is_ok = true;
154 if (!requestor_is_ok) {
155 *error = kNotFromVerifiedSitesError;
156 return false;
158 *error = "";
159 return true;
163 // Private implementation.
166 void WebstoreInlineInstaller::WebContentsDestroyed(
167 content::WebContents* web_contents) {
168 AbortInstall();
171 // static
172 bool WebstoreInlineInstaller::IsRequestorURLInVerifiedSite(
173 const GURL& requestor_url,
174 const std::string& verified_site) {
175 // Turn the verified site into a URL that can be parsed by URLPattern.
176 // |verified_site| must follow the format:
178 // [scheme://]host[:port][/path/specifier]
180 // If scheme is omitted, URLPattern will match against either an
181 // HTTP or HTTPS requestor. If scheme is specified, it must be either HTTP
182 // or HTTPS, and URLPattern will only match the scheme specified.
183 GURL verified_site_url(verified_site);
184 int valid_schemes = URLPattern::SCHEME_HTTP | URLPattern::SCHEME_HTTPS;
185 if (!verified_site_url.is_valid() || !verified_site_url.IsStandard())
186 // If no scheme is specified, GURL will fail to parse the string correctly.
187 // It will either determine that the URL is invalid, or parse a
188 // host:port/path as scheme:host/path.
189 verified_site_url = GURL("http://" + verified_site);
190 else if (verified_site_url.SchemeIs("http"))
191 valid_schemes = URLPattern::SCHEME_HTTP;
192 else if (verified_site_url.SchemeIs("https"))
193 valid_schemes = URLPattern::SCHEME_HTTPS;
194 else
195 return false;
197 std::string port_spec =
198 verified_site_url.has_port() ? ":" + verified_site_url.port() : "";
199 std::string path_spec = verified_site_url.path() + "*";
200 std::string verified_site_pattern_spec =
201 base::StringPrintf(
202 "%s://*.%s%s%s",
203 verified_site_url.scheme().c_str(),
204 verified_site_url.host().c_str(),
205 port_spec.c_str(),
206 path_spec.c_str());
208 URLPattern verified_site_pattern(valid_schemes);
209 URLPattern::ParseResult parse_result =
210 verified_site_pattern.Parse(verified_site_pattern_spec);
211 if (parse_result != URLPattern::PARSE_SUCCESS) {
212 DLOG(WARNING) << "Could not parse " << verified_site_pattern_spec <<
213 " as URL pattern " << parse_result;
214 return false;
216 verified_site_pattern.SetScheme("*");
218 return verified_site_pattern.MatchesURL(requestor_url);
221 } // namespace extensions