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