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