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   return kKeys;
125 }
126 
UpdateURLHandler()127 UpdateURLHandler::UpdateURLHandler() {
128 }
129 
~UpdateURLHandler()130 UpdateURLHandler::~UpdateURLHandler() {
131 }
132 
Parse(Extension * extension,base::string16 * error)133 bool UpdateURLHandler::Parse(Extension* extension, base::string16* error) {
134   std::unique_ptr<ManifestURL> manifest_url(new ManifestURL);
135   std::string tmp_update_url;
136 
137   if (!extension->manifest()->GetString(keys::kUpdateURL, &tmp_update_url)) {
138     *error = ErrorUtils::FormatErrorMessageUTF16(errors::kInvalidUpdateURL,
139                                                  std::string());
140     return false;
141   }
142 
143   manifest_url->url_ = GURL(tmp_update_url);
144   if (!manifest_url->url_.is_valid() ||
145       manifest_url->url_.has_ref()) {
146     *error = ErrorUtils::FormatErrorMessageUTF16(
147         errors::kInvalidUpdateURL, tmp_update_url);
148     return false;
149   }
150 
151   extension->SetManifestData(keys::kUpdateURL, std::move(manifest_url));
152   return true;
153 }
154 
Keys() const155 base::span<const char* const> UpdateURLHandler::Keys() const {
156   static constexpr const char* kKeys[] = {keys::kUpdateURL};
157   return kKeys;
158 }
159 
AboutPageHandler()160 AboutPageHandler::AboutPageHandler() {
161 }
162 
~AboutPageHandler()163 AboutPageHandler::~AboutPageHandler() {
164 }
165 
Parse(Extension * extension,base::string16 * error)166 bool AboutPageHandler::Parse(Extension* extension, base::string16* error) {
167   std::unique_ptr<ManifestURL> manifest_url(new ManifestURL);
168   std::string about_str;
169   if (!extension->manifest()->GetString(keys::kAboutPage, &about_str)) {
170     *error = base::ASCIIToUTF16(errors::kInvalidAboutPage);
171     return false;
172   }
173 
174   GURL absolute(about_str);
175   if (absolute.is_valid()) {
176     *error = base::ASCIIToUTF16(errors::kInvalidAboutPageExpectRelativePath);
177     return false;
178   }
179   manifest_url->url_ = extension->GetResourceURL(about_str);
180   if (!manifest_url->url_.is_valid()) {
181     *error = base::ASCIIToUTF16(errors::kInvalidAboutPage);
182     return false;
183   }
184   extension->SetManifestData(keys::kAboutPage, std::move(manifest_url));
185   return true;
186 }
187 
Validate(const Extension * extension,std::string * error,std::vector<InstallWarning> * warnings) const188 bool AboutPageHandler::Validate(const Extension* extension,
189                                 std::string* error,
190                                 std::vector<InstallWarning>* warnings) const {
191   // Validate path to the options page.
192   if (!extensions::ManifestURL::GetAboutPage(extension).is_empty()) {
193     const base::FilePath about_path =
194         extensions::file_util::ExtensionURLToRelativeFilePath(
195             extensions::ManifestURL::GetAboutPage(extension));
196     const base::FilePath path =
197         extension->GetResource(about_path).GetFilePath();
198     if (path.empty() || !base::PathExists(path)) {
199       *error = l10n_util::GetStringFUTF8(IDS_EXTENSION_LOAD_ABOUT_PAGE_FAILED,
200                                          about_path.LossyDisplayName());
201       return false;
202     }
203   }
204   return true;
205 }
206 
Keys() const207 base::span<const char* const> AboutPageHandler::Keys() const {
208   static constexpr const char* kKeys[] = {keys::kAboutPage};
209   return kKeys;
210 }
211 
212 }  // namespace extensions
213