OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "extensions/common/file_util.h" | 5 #include "extensions/common/file_util.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include <map> | 10 #include <map> |
11 #include <memory> | 11 #include <memory> |
12 #include <set> | 12 #include <set> |
13 #include <string> | 13 #include <string> |
14 #include <utility> | 14 #include <utility> |
15 #include <vector> | 15 #include <vector> |
16 | 16 |
17 #include "base/files/file_enumerator.h" | 17 #include "base/files/file_enumerator.h" |
18 #include "base/files/file_path.h" | 18 #include "base/files/file_path.h" |
19 #include "base/files/file_util.h" | 19 #include "base/files/file_util.h" |
20 #include "base/files/scoped_temp_dir.h" | 20 #include "base/files/scoped_temp_dir.h" |
21 #include "base/json/json_file_value_serializer.h" | 21 #include "base/json/json_file_value_serializer.h" |
22 #include "base/logging.h" | 22 #include "base/logging.h" |
23 #include "base/macros.h" | 23 #include "base/macros.h" |
24 #include "base/metrics/field_trial.h" | 24 #include "base/metrics/field_trial.h" |
25 #include "base/metrics/histogram_macros.h" | 25 #include "base/metrics/histogram_macros.h" |
26 #include "base/strings/stringprintf.h" | 26 #include "base/strings/stringprintf.h" |
27 #include "base/strings/utf_string_conversions.h" | 27 #include "base/strings/utf_string_conversions.h" |
28 #include "base/threading/thread_restrictions.h" | 28 #include "base/threading/thread_restrictions.h" |
29 #include "base/time/time.h" | 29 #include "base/time/time.h" |
| 30 #include "extensions/common/api/declarative_net_request/rules_indexer_util.h" |
| 31 #include "extensions/common/api/declarative_net_request/rules_manifest_info.h" |
30 #include "extensions/common/constants.h" | 32 #include "extensions/common/constants.h" |
31 #include "extensions/common/extension.h" | 33 #include "extensions/common/extension.h" |
32 #include "extensions/common/extension_icon_set.h" | 34 #include "extensions/common/extension_icon_set.h" |
33 #include "extensions/common/extension_l10n_util.h" | 35 #include "extensions/common/extension_l10n_util.h" |
34 #include "extensions/common/extension_set.h" | 36 #include "extensions/common/extension_set.h" |
35 #include "extensions/common/install_warning.h" | 37 #include "extensions/common/install_warning.h" |
36 #include "extensions/common/manifest.h" | 38 #include "extensions/common/manifest.h" |
37 #include "extensions/common/manifest_constants.h" | 39 #include "extensions/common/manifest_constants.h" |
38 #include "extensions/common/manifest_handler.h" | 40 #include "extensions/common/manifest_handler.h" |
39 #include "extensions/common/manifest_handlers/default_locale_handler.h" | 41 #include "extensions/common/manifest_handlers/default_locale_handler.h" |
40 #include "extensions/common/manifest_handlers/icons_handler.h" | 42 #include "extensions/common/manifest_handlers/icons_handler.h" |
| 43 #include "extensions/common/permissions/api_permission.h" |
| 44 #include "extensions/common/permissions/permissions_data.h" |
41 #include "extensions/strings/grit/extensions_strings.h" | 45 #include "extensions/strings/grit/extensions_strings.h" |
42 #include "net/base/escape.h" | 46 #include "net/base/escape.h" |
43 #include "net/base/filename_util.h" | 47 #include "net/base/filename_util.h" |
44 #include "ui/base/l10n/l10n_util.h" | 48 #include "ui/base/l10n/l10n_util.h" |
45 #include "url/gurl.h" | 49 #include "url/gurl.h" |
46 | 50 |
47 namespace extensions { | 51 namespace extensions { |
48 namespace file_util { | 52 namespace file_util { |
49 namespace { | 53 namespace { |
50 | 54 |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
202 } | 206 } |
203 | 207 |
204 scoped_refptr<Extension> LoadExtension(const base::FilePath& extension_path, | 208 scoped_refptr<Extension> LoadExtension(const base::FilePath& extension_path, |
205 const std::string& extension_id, | 209 const std::string& extension_id, |
206 Manifest::Location location, | 210 Manifest::Location location, |
207 int flags, | 211 int flags, |
208 std::string* error) { | 212 std::string* error) { |
209 std::unique_ptr<base::DictionaryValue> manifest = | 213 std::unique_ptr<base::DictionaryValue> manifest = |
210 LoadManifest(extension_path, error); | 214 LoadManifest(extension_path, error); |
211 if (!manifest.get()) | 215 if (!manifest.get()) |
212 return NULL; | 216 return nullptr; |
213 if (!extension_l10n_util::LocalizeExtension( | 217 if (!extension_l10n_util::LocalizeExtension( |
214 extension_path, manifest.get(), error)) { | 218 extension_path, manifest.get(), error)) { |
215 return NULL; | 219 return nullptr; |
216 } | 220 } |
217 | 221 |
218 scoped_refptr<Extension> extension(Extension::Create( | 222 scoped_refptr<Extension> extension(Extension::Create( |
219 extension_path, location, *manifest, flags, extension_id, error)); | 223 extension_path, location, *manifest, flags, extension_id, error)); |
220 if (!extension.get()) | 224 if (!extension.get()) |
221 return NULL; | 225 return nullptr; |
222 | 226 |
223 std::vector<InstallWarning> warnings; | 227 std::vector<InstallWarning> warnings; |
224 if (!ValidateExtension(extension.get(), error, &warnings)) | 228 if (!ValidateExtension(extension.get(), error, &warnings)) |
225 return NULL; | 229 return nullptr; |
| 230 |
| 231 // Rulesets for unpacked extensions need to be indexed and persisted, since |
| 232 // they don't go through the CrxInstaller. |
| 233 if (Manifest::IsUnpackedLocation(extension->location()) && |
| 234 !IndexAndPersistRulesetIfNeeded( |
| 235 extension.get(), GetIndexedRulesetPath(extension_path), error)) { |
| 236 return nullptr; |
| 237 } |
| 238 |
226 extension->AddInstallWarnings(warnings); | 239 extension->AddInstallWarnings(warnings); |
227 | 240 |
228 return extension; | 241 return extension; |
229 } | 242 } |
230 | 243 |
231 std::unique_ptr<base::DictionaryValue> LoadManifest( | 244 std::unique_ptr<base::DictionaryValue> LoadManifest( |
232 const base::FilePath& extension_path, | 245 const base::FilePath& extension_path, |
233 std::string* error) { | 246 std::string* error) { |
234 return LoadManifest(extension_path, kManifestFilename, error); | 247 return LoadManifest(extension_path, kManifestFilename, error); |
235 } | 248 } |
236 | 249 |
237 std::unique_ptr<base::DictionaryValue> LoadManifest( | 250 std::unique_ptr<base::DictionaryValue> LoadManifest( |
238 const base::FilePath& extension_path, | 251 const base::FilePath& extension_path, |
239 const base::FilePath::CharType* manifest_filename, | 252 const base::FilePath::CharType* manifest_filename, |
240 std::string* error) { | 253 std::string* error) { |
241 base::FilePath manifest_path = extension_path.Append(manifest_filename); | 254 base::FilePath manifest_path = extension_path.Append(manifest_filename); |
242 if (!base::PathExists(manifest_path)) { | 255 if (!base::PathExists(manifest_path)) { |
243 *error = l10n_util::GetStringUTF8(IDS_EXTENSION_MANIFEST_UNREADABLE); | 256 *error = l10n_util::GetStringUTF8(IDS_EXTENSION_MANIFEST_UNREADABLE); |
244 return NULL; | 257 return nullptr; |
245 } | 258 } |
246 | 259 |
247 JSONFileValueDeserializer deserializer(manifest_path); | 260 JSONFileValueDeserializer deserializer(manifest_path); |
248 std::unique_ptr<base::Value> root(deserializer.Deserialize(NULL, error)); | 261 std::unique_ptr<base::Value> root(deserializer.Deserialize(nullptr, error)); |
249 if (!root.get()) { | 262 if (!root.get()) { |
250 if (error->empty()) { | 263 if (error->empty()) { |
251 // If |error| is empty, than the file could not be read. | 264 // If |error| is empty, than the file could not be read. |
252 // It would be cleaner to have the JSON reader give a specific error | 265 // It would be cleaner to have the JSON reader give a specific error |
253 // in this case, but other code tests for a file error with | 266 // in this case, but other code tests for a file error with |
254 // error->empty(). For now, be consistent. | 267 // error->empty(). For now, be consistent. |
255 *error = l10n_util::GetStringUTF8(IDS_EXTENSION_MANIFEST_UNREADABLE); | 268 *error = l10n_util::GetStringUTF8(IDS_EXTENSION_MANIFEST_UNREADABLE); |
256 } else { | 269 } else { |
257 *error = base::StringPrintf( | 270 *error = base::StringPrintf( |
258 "%s %s", manifest_errors::kManifestParseError, error->c_str()); | 271 "%s %s", manifest_errors::kManifestParseError, error->c_str()); |
259 } | 272 } |
260 return NULL; | 273 return nullptr; |
261 } | 274 } |
262 | 275 |
263 if (!root->IsType(base::Value::Type::DICTIONARY)) { | 276 if (!root->IsType(base::Value::Type::DICTIONARY)) { |
264 *error = l10n_util::GetStringUTF8(IDS_EXTENSION_MANIFEST_INVALID); | 277 *error = l10n_util::GetStringUTF8(IDS_EXTENSION_MANIFEST_INVALID); |
265 return NULL; | 278 return nullptr; |
266 } | 279 } |
267 | 280 |
268 return base::DictionaryValue::From(std::move(root)); | 281 return base::DictionaryValue::From(std::move(root)); |
269 } | 282 } |
270 | 283 |
| 284 bool IndexAndPersistRulesetIfNeeded(const Extension* extension, |
| 285 const base::FilePath& indexed_ruleset_path, |
| 286 std::string* error) { |
| 287 const base::FilePath* json_ruleset_path = |
| 288 declarative_net_request::RulesManifestData::GetJSONRulesetPath(extension); |
| 289 if (!json_ruleset_path) |
| 290 return true; |
| 291 |
| 292 DCHECK(extension->permissions_data()->HasAPIPermission( |
| 293 APIPermission::kDeclarativeNetRequest)); |
| 294 return declarative_net_request::IndexAndPersistRuleset( |
| 295 *json_ruleset_path, indexed_ruleset_path, error); |
| 296 } |
| 297 |
271 bool ValidateExtension(const Extension* extension, | 298 bool ValidateExtension(const Extension* extension, |
272 std::string* error, | 299 std::string* error, |
273 std::vector<InstallWarning>* warnings) { | 300 std::vector<InstallWarning>* warnings) { |
274 // Ask registered manifest handlers to validate their paths. | 301 // Ask registered manifest handlers to validate their paths. |
275 if (!ManifestHandler::ValidateExtension(extension, error, warnings)) | 302 if (!ManifestHandler::ValidateExtension(extension, error, warnings)) |
276 return false; | 303 return false; |
277 | 304 |
278 // Check children of extension root to see if any of them start with _ and is | 305 // Check children of extension root to see if any of them start with _ and is |
279 // not on the reserved list. We only warn, and do not block the loading of the | 306 // not on the reserved list. We only warn, and do not block the loading of the |
280 // extension. | 307 // extension. |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
335 } | 362 } |
336 | 363 |
337 result.push_back(current); | 364 result.push_back(current); |
338 } | 365 } |
339 return result; | 366 return result; |
340 } | 367 } |
341 | 368 |
342 bool CheckForIllegalFilenames(const base::FilePath& extension_path, | 369 bool CheckForIllegalFilenames(const base::FilePath& extension_path, |
343 std::string* error) { | 370 std::string* error) { |
344 // Reserved underscore names. | 371 // Reserved underscore names. |
| 372 // TODO add kIndexedRulesetFilename, kMetadata and other? |
345 static const base::FilePath::CharType* reserved_names[] = { | 373 static const base::FilePath::CharType* reserved_names[] = { |
346 kLocaleFolder, kPlatformSpecificFolder, FILE_PATH_LITERAL("__MACOSX"), }; | 374 kLocaleFolder, kPlatformSpecificFolder, FILE_PATH_LITERAL("__MACOSX"), |
| 375 kIndexedRulesetFilename}; |
347 CR_DEFINE_STATIC_LOCAL( | 376 CR_DEFINE_STATIC_LOCAL( |
348 std::set<base::FilePath::StringType>, | 377 std::set<base::FilePath::StringType>, |
349 reserved_underscore_names, | 378 reserved_underscore_names, |
350 (reserved_names, reserved_names + arraysize(reserved_names))); | 379 (reserved_names, reserved_names + arraysize(reserved_names))); |
351 | 380 |
352 // Enumerate all files and directories in the extension root. | 381 // Enumerate all files and directories in the extension root. |
353 // There is a problem when using pattern "_*" with FileEnumerator, so we have | 382 // There is a problem when using pattern "_*" with FileEnumerator, so we have |
354 // to cheat with find_first_of and match all. | 383 // to cheat with find_first_of and match all. |
355 const int kFilesAndDirectories = | 384 const int kFilesAndDirectories = |
356 base::FileEnumerator::DIRECTORIES | base::FileEnumerator::FILES; | 385 base::FileEnumerator::DIRECTORIES | base::FileEnumerator::FILES; |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
478 } | 507 } |
479 | 508 |
480 MessageBundle* LoadMessageBundle( | 509 MessageBundle* LoadMessageBundle( |
481 const base::FilePath& extension_path, | 510 const base::FilePath& extension_path, |
482 const std::string& default_locale, | 511 const std::string& default_locale, |
483 std::string* error) { | 512 std::string* error) { |
484 error->clear(); | 513 error->clear(); |
485 // Load locale information if available. | 514 // Load locale information if available. |
486 base::FilePath locale_path = extension_path.Append(kLocaleFolder); | 515 base::FilePath locale_path = extension_path.Append(kLocaleFolder); |
487 if (!base::PathExists(locale_path)) | 516 if (!base::PathExists(locale_path)) |
488 return NULL; | 517 return nullptr; |
489 | 518 |
490 std::set<std::string> chrome_locales; | 519 std::set<std::string> chrome_locales; |
491 extension_l10n_util::GetAllLocales(&chrome_locales); | 520 extension_l10n_util::GetAllLocales(&chrome_locales); |
492 | 521 |
493 base::FilePath default_locale_path = locale_path.AppendASCII(default_locale); | 522 base::FilePath default_locale_path = locale_path.AppendASCII(default_locale); |
494 if (default_locale.empty() || | 523 if (default_locale.empty() || |
495 chrome_locales.find(default_locale) == chrome_locales.end() || | 524 chrome_locales.find(default_locale) == chrome_locales.end() || |
496 !base::PathExists(default_locale_path)) { | 525 !base::PathExists(default_locale_path)) { |
497 *error = l10n_util::GetStringUTF8( | 526 *error = l10n_util::GetStringUTF8( |
498 IDS_EXTENSION_LOCALES_NO_DEFAULT_LOCALE_SPECIFIED); | 527 IDS_EXTENSION_LOCALES_NO_DEFAULT_LOCALE_SPECIFIED); |
499 return NULL; | 528 return nullptr; |
500 } | 529 } |
501 | 530 |
502 MessageBundle* message_bundle = | 531 MessageBundle* message_bundle = |
503 extension_l10n_util::LoadMessageCatalogs( | 532 extension_l10n_util::LoadMessageCatalogs( |
504 locale_path, | 533 locale_path, |
505 default_locale, | 534 default_locale, |
506 extension_l10n_util::CurrentLocaleOrDefault(), | 535 extension_l10n_util::CurrentLocaleOrDefault(), |
507 error); | 536 error); |
508 | 537 |
509 return message_bundle; | 538 return message_bundle; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
558 } | 587 } |
559 | 588 |
560 base::FilePath GetVerifiedContentsPath(const base::FilePath& extension_path) { | 589 base::FilePath GetVerifiedContentsPath(const base::FilePath& extension_path) { |
561 return extension_path.Append(kMetadataFolder) | 590 return extension_path.Append(kMetadataFolder) |
562 .Append(kVerifiedContentsFilename); | 591 .Append(kVerifiedContentsFilename); |
563 } | 592 } |
564 base::FilePath GetComputedHashesPath(const base::FilePath& extension_path) { | 593 base::FilePath GetComputedHashesPath(const base::FilePath& extension_path) { |
565 return extension_path.Append(kMetadataFolder).Append(kComputedHashesFilename); | 594 return extension_path.Append(kMetadataFolder).Append(kComputedHashesFilename); |
566 } | 595 } |
567 | 596 |
| 597 base::FilePath GetIndexedRulesetPath(const base::FilePath& extension_path) { |
| 598 return extension_path.Append(kIndexedRulesetFilename); |
| 599 } |
| 600 |
568 } // namespace file_util | 601 } // namespace file_util |
569 } // namespace extensions | 602 } // namespace extensions |
OLD | NEW |