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