| 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 |