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 "extensions/common/manifest_url_handlers.h"
6 
7 #include <memory>
8 #include <utility>
9 
10 #include "base/files/file_util.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/stringprintf.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "base/values.h"
15 #include "extensions/common/error_utils.h"
16 #include "extensions/common/extension_urls.h"
17 #include "extensions/common/file_util.h"
18 #include "extensions/common/manifest.h"
19 #include "extensions/common/manifest_constants.h"
20 #include "extensions/common/manifest_handlers/shared_module_info.h"
21 #include "extensions/strings/grit/extensions_strings.h"
22 #include "ui/base/l10n/l10n_util.h"
23 
24 namespace extensions {
25 
26 namespace keys = manifest_keys;
27 namespace errors = manifest_errors;
28 
29 // static
Get(const Extension * extension,const std::string & key)30 const GURL& ManifestURL::Get(const Extension* extension,
31                              const std::string& key) {
32   ManifestURL* manifest_url =
33       static_cast<ManifestURL*>(extension->GetManifestData(key));
34   return manifest_url ? manifest_url->url_ : GURL::EmptyGURL();
35 }
36 
37 // static
GetHomepageURL(const Extension * extension)38 const GURL ManifestURL::GetHomepageURL(const Extension* extension) {
39   const GURL& homepage_url = Get(extension, keys::kHomepageURL);
40   if (homepage_url.is_valid())
41     return homepage_url;
42   return GetWebStoreURL(extension);
43 }
44 
45 // static
SpecifiedHomepageURL(const Extension * extension)46 bool ManifestURL::SpecifiedHomepageURL(const Extension* extension) {
47   return Get(extension, keys::kHomepageURL).is_valid();
48 }
49 
50 // static
GetManifestHomePageURL(const Extension * extension)51 const GURL ManifestURL::GetManifestHomePageURL(const Extension* extension) {
52   const GURL& homepage_url = Get(extension, keys::kHomepageURL);
53   return homepage_url.is_valid() ? homepage_url : GURL::EmptyGURL();
54 }
55 
56 // static
GetWebStoreURL(const Extension * extension)57 const GURL ManifestURL::GetWebStoreURL(const Extension* extension) {
58   bool use_webstore_url = UpdatesFromGallery(extension) &&
59                           !SharedModuleInfo::IsSharedModule(extension);
60   return use_webstore_url
61              ? GURL(extension_urls::GetWebstoreItemDetailURLPrefix() +
62                     extension->id())
63              : GURL::EmptyGURL();
64 }
65 
66 // static
GetUpdateURL(const Extension * extension)67 const GURL& ManifestURL::GetUpdateURL(const Extension* extension) {
68   return Get(extension, keys::kUpdateURL);
69 }
70 
71 // static
UpdatesFromGallery(const Extension * extension)72 bool ManifestURL::UpdatesFromGallery(const Extension* extension) {
73   return extension_urls::IsWebstoreUpdateUrl(GetUpdateURL(extension));
74 }
75 
76 // static
UpdatesFromGallery(const base::DictionaryValue * manifest)77 bool  ManifestURL::UpdatesFromGallery(const base::DictionaryValue* manifest) {
78   std::string url;
79   if (!manifest->GetString(keys::kUpdateURL, &url))
80     return false;
81   return extension_urls::IsWebstoreUpdateUrl(GURL(url));
82 }
83 
84 // static
GetAboutPage(const Extension * extension)85 const GURL& ManifestURL::GetAboutPage(const Extension* extension) {
86   return Get(extension, keys::kAboutPage);
87 }
88 
89 // static
GetDetailsURL(const Extension * extension)90 const GURL ManifestURL::GetDetailsURL(const Extension* extension) {
91   return extension->from_webstore() ?
92       GURL(extension_urls::GetWebstoreItemDetailURLPrefix() + extension->id()) :
93       GURL::EmptyGURL();
94 }
95 
HomepageURLHandler()96 HomepageURLHandler::HomepageURLHandler() {
97 }
98 
~HomepageURLHandler()99 HomepageURLHandler::~HomepageURLHandler() {
100 }
101 
Parse(Extension * extension,base::string16 * error)102 bool HomepageURLHandler::Parse(Extension* extension, base::string16* error) {
103   std::unique_ptr<ManifestURL> manifest_url(new ManifestURL);
104   std::string homepage_url_str;
105   if (!extension->manifest()->GetString(keys::kHomepageURL,
106                                         &homepage_url_str)) {
107     *error = ErrorUtils::FormatErrorMessageUTF16(errors::kInvalidHomepageURL,
108                                                  std::string());
109     return false;
110   }
111   manifest_url->url_ = GURL(homepage_url_str);
112   if (!manifest_url->url_.is_valid() ||
113       !manifest_url->url_.SchemeIsHTTPOrHTTPS()) {
114     *error = ErrorUtils::FormatErrorMessageUTF16(
115         errors::kInvalidHomepageURL, homepage_url_str);
116     return false;
117   }
118   extension->SetManifestData(keys::kHomepageURL, std::move(manifest_url));
119   return true;
120 }
121 
Keys() const122 base::span<const char* const> HomepageURLHandler::Keys() const {
123   static constexpr const char* kKeys[] = {keys::kHomepageURL};
124 #if !defined(__GNUC__) || __GNUC__ > 5
125   return kKeys;
126 #else
127   return base::make_span(kKeys, 1);
128 #endif
129 }
130 
UpdateURLHandler()131 UpdateURLHandler::UpdateURLHandler() {
132 }
133 
~UpdateURLHandler()134 UpdateURLHandler::~UpdateURLHandler() {
135 }
136 
Parse(Extension * extension,base::string16 * error)137 bool UpdateURLHandler::Parse(Extension* extension, base::string16* error) {
138   std::unique_ptr<ManifestURL> manifest_url(new ManifestURL);
139   std::string tmp_update_url;
140 
141   if (!extension->manifest()->GetString(keys::kUpdateURL, &tmp_update_url)) {
142     *error = ErrorUtils::FormatErrorMessageUTF16(errors::kInvalidUpdateURL,
143                                                  std::string());
144     return false;
145   }
146 
147   manifest_url->url_ = GURL(tmp_update_url);
148   if (!manifest_url->url_.is_valid() ||
149       manifest_url->url_.has_ref()) {
150     *error = ErrorUtils::FormatErrorMessageUTF16(
151         errors::kInvalidUpdateURL, tmp_update_url);
152     return false;
153   }
154 
155   extension->SetManifestData(keys::kUpdateURL, std::move(manifest_url));
156   return true;
157 }
158 
Keys() const159 base::span<const char* const> UpdateURLHandler::Keys() const {
160   static constexpr const char* kKeys[] = {keys::kUpdateURL};
161 #if !defined(__GNUC__) || __GNUC__ > 5
162   return kKeys;
163 #else
164   return base::make_span(kKeys, 1);
165 #endif
166 }
167 
AboutPageHandler()168 AboutPageHandler::AboutPageHandler() {
169 }
170 
~AboutPageHandler()171 AboutPageHandler::~AboutPageHandler() {
172 }
173 
Parse(Extension * extension,base::string16 * error)174 bool AboutPageHandler::Parse(Extension* extension, base::string16* error) {
175   std::unique_ptr<ManifestURL> manifest_url(new ManifestURL);
176   std::string about_str;
177   if (!extension->manifest()->GetString(keys::kAboutPage, &about_str)) {
178     *error = base::ASCIIToUTF16(errors::kInvalidAboutPage);
179     return false;
180   }
181 
182   GURL absolute(about_str);
183   if (absolute.is_valid()) {
184     *error = base::ASCIIToUTF16(errors::kInvalidAboutPageExpectRelativePath);
185     return false;
186   }
187   manifest_url->url_ = extension->GetResourceURL(about_str);
188   if (!manifest_url->url_.is_valid()) {
189     *error = base::ASCIIToUTF16(errors::kInvalidAboutPage);
190     return false;
191   }
192   extension->SetManifestData(keys::kAboutPage, std::move(manifest_url));
193   return true;
194 }
195 
Validate(const Extension * extension,std::string * error,std::vector<InstallWarning> * warnings) const196 bool AboutPageHandler::Validate(const Extension* extension,
197                                 std::string* error,
198                                 std::vector<InstallWarning>* warnings) const {
199   // Validate path to the options page.
200   if (!extensions::ManifestURL::GetAboutPage(extension).is_empty()) {
201     const base::FilePath about_path =
202         extensions::file_util::ExtensionURLToRelativeFilePath(
203             extensions::ManifestURL::GetAboutPage(extension));
204     const base::FilePath path =
205         extension->GetResource(about_path).GetFilePath();
206     if (path.empty() || !base::PathExists(path)) {
207       *error = l10n_util::GetStringFUTF8(IDS_EXTENSION_LOAD_ABOUT_PAGE_FAILED,
208                                          about_path.LossyDisplayName());
209       return false;
210     }
211   }
212   return true;
213 }
214 
Keys() const215 base::span<const char* const> AboutPageHandler::Keys() const {
216   static constexpr const char* kKeys[] = {keys::kAboutPage};
217 #if !defined(__GNUC__) || __GNUC__ > 5
218   return kKeys;
219 #else
220   return base::make_span(kKeys, 1);
221 #endif
222 }
223 
224 }  // namespace extensions
225