| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 "chrome/common/extensions/extension.h" | 5 #include "chrome/common/extensions/extension.h" |
| 6 | 6 |
| 7 #include "app/resource_bundle.h" | 7 #include "app/resource_bundle.h" |
| 8 #include "base/file_path.h" | 8 #include "base/file_path.h" |
| 9 #include "base/file_util.h" | 9 #include "base/file_util.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "base/string_util.h" | 11 #include "base/string_util.h" |
| 12 #include "net/base/net_util.h" | 12 #include "net/base/net_util.h" |
| 13 #include "chrome/common/extensions/extension_error_reporter.h" | 13 #include "chrome/common/extensions/extension_error_reporter.h" |
| 14 #include "chrome/common/extensions/extension_error_utils.h" | 14 #include "chrome/common/extensions/extension_error_utils.h" |
| 15 #include "chrome/common/extensions/user_script.h" | 15 #include "chrome/common/extensions/user_script.h" |
| 16 #include "chrome/common/url_constants.h" | 16 #include "chrome/common/url_constants.h" |
| 17 #include "net/base/base64.h" |
| 17 | 18 |
| 18 #if defined(OS_WIN) | 19 #if defined(OS_WIN) |
| 19 #include "base/registry.h" | 20 #include "base/registry.h" |
| 20 #endif | 21 #endif |
| 21 | 22 |
| 23 namespace { |
| 24 const int kPEMOutputColumns = 65; |
| 25 |
| 26 // KEY MARKERS |
| 27 const char kKeyBeginHeaderMarker[] = "-----BEGIN"; |
| 28 const char kKeyBeginFooterMarker[] = "-----END"; |
| 29 const char kKeyInfoEndMarker[] = "KEY-----"; |
| 30 const char kPublic[] = "PUBLIC"; |
| 31 const char kPrivate[] = "PRIVATE"; |
| 32 |
| 33 const int kRSAKeySize = 1024; |
| 34 }; |
| 35 |
| 22 const char Extension::kManifestFilename[] = "manifest.json"; | 36 const char Extension::kManifestFilename[] = "manifest.json"; |
| 23 | 37 |
| 38 const wchar_t* Extension::kBackgroundKey = L"background_page"; |
| 24 const wchar_t* Extension::kContentScriptsKey = L"content_scripts"; | 39 const wchar_t* Extension::kContentScriptsKey = L"content_scripts"; |
| 25 const wchar_t* Extension::kCssKey = L"css"; | 40 const wchar_t* Extension::kCssKey = L"css"; |
| 26 const wchar_t* Extension::kDescriptionKey = L"description"; | 41 const wchar_t* Extension::kDescriptionKey = L"description"; |
| 27 const wchar_t* Extension::kIconPathKey = L"icon"; | 42 const wchar_t* Extension::kIconPathKey = L"icon"; |
| 28 const wchar_t* Extension::kIdKey = L"id"; | 43 const wchar_t* Extension::kIdKey = L"id"; |
| 29 const wchar_t* Extension::kJsKey = L"js"; | 44 const wchar_t* Extension::kJsKey = L"js"; |
| 30 const wchar_t* Extension::kMatchesKey = L"matches"; | 45 const wchar_t* Extension::kMatchesKey = L"matches"; |
| 31 const wchar_t* Extension::kNameKey = L"name"; | 46 const wchar_t* Extension::kNameKey = L"name"; |
| 32 const wchar_t* Extension::kPageActionsKey = L"page_actions"; | 47 const wchar_t* Extension::kPageActionsKey = L"page_actions"; |
| 33 const wchar_t* Extension::kPermissionsKey = L"permissions"; | 48 const wchar_t* Extension::kPermissionsKey = L"permissions"; |
| 34 const wchar_t* Extension::kPluginsKey = L"plugins"; | 49 const wchar_t* Extension::kPluginsKey = L"plugins"; |
| 35 const wchar_t* Extension::kPluginsPathKey = L"path"; | 50 const wchar_t* Extension::kPluginsPathKey = L"path"; |
| 36 const wchar_t* Extension::kPluginsPublicKey = L"public"; | 51 const wchar_t* Extension::kPluginsPublicKey = L"public"; |
| 37 const wchar_t* Extension::kBackgroundKey = L"background_page"; | 52 const wchar_t* Extension::kPublicKeyKey = L"key"; |
| 38 const wchar_t* Extension::kRunAtKey = L"run_at"; | 53 const wchar_t* Extension::kRunAtKey = L"run_at"; |
| 54 const wchar_t* Extension::kSignatureKey = L"signature"; |
| 39 const wchar_t* Extension::kThemeKey = L"theme"; | 55 const wchar_t* Extension::kThemeKey = L"theme"; |
| 40 const wchar_t* Extension::kThemeImagesKey = L"images"; | 56 const wchar_t* Extension::kThemeImagesKey = L"images"; |
| 41 const wchar_t* Extension::kThemeColorsKey = L"colors"; | 57 const wchar_t* Extension::kThemeColorsKey = L"colors"; |
| 42 const wchar_t* Extension::kThemeTintsKey = L"tints"; | 58 const wchar_t* Extension::kThemeTintsKey = L"tints"; |
| 43 const wchar_t* Extension::kThemeDisplayPropertiesKey = L"properties"; | 59 const wchar_t* Extension::kThemeDisplayPropertiesKey = L"properties"; |
| 44 const wchar_t* Extension::kToolstripsKey = L"toolstrips"; | 60 const wchar_t* Extension::kToolstripsKey = L"toolstrips"; |
| 45 const wchar_t* Extension::kTooltipKey = L"tooltip"; | 61 const wchar_t* Extension::kTooltipKey = L"tooltip"; |
| 46 const wchar_t* Extension::kTypeKey = L"type"; | 62 const wchar_t* Extension::kTypeKey = L"type"; |
| 47 const wchar_t* Extension::kVersionKey = L"version"; | 63 const wchar_t* Extension::kVersionKey = L"version"; |
| 48 const wchar_t* Extension::kZipHashKey = L"zip_hash"; | |
| 49 | 64 |
| 50 const char* Extension::kRunAtDocumentStartValue = "document_start"; | 65 const char* Extension::kRunAtDocumentStartValue = "document_start"; |
| 51 const char* Extension::kRunAtDocumentEndValue = "document_end"; | 66 const char* Extension::kRunAtDocumentEndValue = "document_end"; |
| 52 const char* Extension::kPageActionTypeTab = "tab"; | 67 const char* Extension::kPageActionTypeTab = "tab"; |
| 53 const char* Extension::kPageActionTypePermanent = "permanent"; | 68 const char* Extension::kPageActionTypePermanent = "permanent"; |
| 54 | 69 |
| 55 // A list of all the keys allowed by themes. | 70 // A list of all the keys allowed by themes. |
| 56 static const wchar_t* kValidThemeKeys[] = { | 71 static const wchar_t* kValidThemeKeys[] = { |
| 57 Extension::kDescriptionKey, | 72 Extension::kDescriptionKey, |
| 58 Extension::kIconPathKey, | 73 Extension::kIconPathKey, |
| 59 Extension::kIdKey, | 74 Extension::kIdKey, |
| 60 Extension::kNameKey, | 75 Extension::kNameKey, |
| 76 Extension::kPublicKeyKey, |
| 77 Extension::kSignatureKey, |
| 61 Extension::kThemeKey, | 78 Extension::kThemeKey, |
| 62 Extension::kVersionKey, | 79 Extension::kVersionKey |
| 63 Extension::kZipHashKey | |
| 64 }; | 80 }; |
| 65 | 81 |
| 66 // Extension-related error messages. Some of these are simple patterns, where a | 82 // Extension-related error messages. Some of these are simple patterns, where a |
| 67 // '*' is replaced at runtime with a specific value. This is used instead of | 83 // '*' is replaced at runtime with a specific value. This is used instead of |
| 68 // printf because we want to unit test them and scanf is hard to make | 84 // printf because we want to unit test them and scanf is hard to make |
| 69 // cross-platform. | 85 // cross-platform. |
| 70 const char* Extension::kInvalidContentScriptError = | 86 const char* Extension::kInvalidContentScriptError = |
| 71 "Invalid value for 'content_scripts[*]'."; | 87 "Invalid value for 'content_scripts[*]'."; |
| 72 const char* Extension::kInvalidContentScriptsListError = | 88 const char* Extension::kInvalidContentScriptsListError = |
| 73 "Invalid value for 'content_scripts'."; | 89 "Invalid value for 'content_scripts'."; |
| (...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 469 if (path_str.size() >= 2 && path_str[0] >= L'a' && path_str[0] <= L'z' && | 485 if (path_str.size() >= 2 && path_str[0] >= L'a' && path_str[0] <= L'z' && |
| 470 path_str[1] == ':') | 486 path_str[1] == ':') |
| 471 path_str[0] += ('A' - 'a'); | 487 path_str[0] += ('A' - 'a'); |
| 472 | 488 |
| 473 path_ = FilePath(path_str); | 489 path_ = FilePath(path_str); |
| 474 #else | 490 #else |
| 475 path_ = path; | 491 path_ = path; |
| 476 #endif | 492 #endif |
| 477 } | 493 } |
| 478 | 494 |
| 495 |
| 496 // TODO(rafaelw): Move ParsePEMKeyBytes, ProducePEM & FormatPEMForOutput to a |
| 497 // util class in base: |
| 498 // http://code.google.com/p/chromium/issues/detail?id=13572 |
| 499 bool Extension::ParsePEMKeyBytes(const std::string& input, |
| 500 std::string* output) { |
| 501 CHECK(output); |
| 502 if (input.length() == 0) |
| 503 return false; |
| 504 |
| 505 std::string working = input; |
| 506 if (StartsWithASCII(working, kKeyBeginHeaderMarker, true)) { |
| 507 working = CollapseWhitespaceASCII(working, true); |
| 508 size_t header_pos = working.find(kKeyInfoEndMarker, |
| 509 sizeof(kKeyBeginHeaderMarker) - 1); |
| 510 if (header_pos == std::string::npos) |
| 511 return false; |
| 512 size_t start_pos = header_pos + sizeof(kKeyInfoEndMarker) - 1; |
| 513 size_t end_pos = working.rfind(kKeyBeginFooterMarker); |
| 514 if (end_pos == std::string::npos) |
| 515 return false; |
| 516 if (start_pos >= end_pos) |
| 517 return false; |
| 518 |
| 519 working = working.substr(start_pos, end_pos - start_pos); |
| 520 if (working.length() == 0) |
| 521 return false; |
| 522 } |
| 523 |
| 524 return net::Base64Decode(working, output); |
| 525 } |
| 526 |
| 527 bool Extension::ProducePEM(const std::string& input, |
| 528 std::string* output) { |
| 529 CHECK(output); |
| 530 if (input.length() == 0) |
| 531 return false; |
| 532 |
| 533 return net::Base64Encode(input, output); |
| 534 } |
| 535 |
| 536 bool Extension::FormatPEMForFileOutput(const std::string input, |
| 537 std::string* output, |
| 538 bool is_public) { |
| 539 CHECK(output); |
| 540 if (input.length() == 0) |
| 541 return false; |
| 542 *output = ""; |
| 543 output->append(kKeyBeginHeaderMarker); |
| 544 output->append(" "); |
| 545 output->append(is_public ? kPublic : kPrivate); |
| 546 output->append(" "); |
| 547 output->append(kKeyInfoEndMarker); |
| 548 output->append("\n"); |
| 549 for (size_t i = 0; i < input.length(); ) { |
| 550 int slice = std::min<int>(input.length() - i, kPEMOutputColumns); |
| 551 output->append(input.substr(i, slice)); |
| 552 output->append("\n"); |
| 553 i += slice; |
| 554 } |
| 555 output->append(kKeyBeginFooterMarker); |
| 556 output->append(" "); |
| 557 output->append(is_public ? kPublic : kPrivate); |
| 558 output->append(" "); |
| 559 output->append(kKeyInfoEndMarker); |
| 560 output->append("\n"); |
| 561 |
| 562 return true; |
| 563 } |
| 564 |
| 479 bool Extension::InitFromValue(const DictionaryValue& source, bool require_id, | 565 bool Extension::InitFromValue(const DictionaryValue& source, bool require_id, |
| 480 std::string* error) { | 566 std::string* error) { |
| 481 // Initialize id. | 567 // Initialize id. |
| 482 if (source.HasKey(kIdKey)) { | 568 if (source.HasKey(kIdKey)) { |
| 483 if (!source.GetString(kIdKey, &id_)) { | 569 if (!source.GetString(kIdKey, &id_)) { |
| 484 *error = kInvalidIdError; | 570 *error = kInvalidIdError; |
| 485 return false; | 571 return false; |
| 486 } | 572 } |
| 487 | 573 |
| 488 // Normalize the string to lowercase, so it can be used as an URL component | 574 // Normalize the string to lowercase, so it can be used as an URL component |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 530 } | 616 } |
| 531 | 617 |
| 532 // Initialize description (optional). | 618 // Initialize description (optional). |
| 533 if (source.HasKey(kDescriptionKey)) { | 619 if (source.HasKey(kDescriptionKey)) { |
| 534 if (!source.GetString(kDescriptionKey, &description_)) { | 620 if (!source.GetString(kDescriptionKey, &description_)) { |
| 535 *error = kInvalidDescriptionError; | 621 *error = kInvalidDescriptionError; |
| 536 return false; | 622 return false; |
| 537 } | 623 } |
| 538 } | 624 } |
| 539 | 625 |
| 540 // Initialize zip hash (only present in zip) | |
| 541 // There's no need to verify it at this point. If it's in a bogus format | |
| 542 // it won't pass the hash verify step. | |
| 543 if (source.HasKey(kZipHashKey)) { | |
| 544 if (!source.GetString(kZipHashKey, &zip_hash_)) { | |
| 545 *error = kInvalidZipHashError; | |
| 546 return false; | |
| 547 } | |
| 548 } | |
| 549 | |
| 550 // Initialize themes. | 626 // Initialize themes. |
| 551 is_theme_ = false; | 627 is_theme_ = false; |
| 552 if (source.HasKey(kThemeKey)) { | 628 if (source.HasKey(kThemeKey)) { |
| 553 // Themes cannot contain extension keys. | 629 // Themes cannot contain extension keys. |
| 554 if (ContainsNonThemeKeys(source)) { | 630 if (ContainsNonThemeKeys(source)) { |
| 555 *error = kThemesCannotContainExtensionsError; | 631 *error = kThemesCannotContainExtensionsError; |
| 556 return false; | 632 return false; |
| 557 } | 633 } |
| 558 | 634 |
| 559 DictionaryValue* theme_value; | 635 DictionaryValue* theme_value; |
| (...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 820 } | 896 } |
| 821 } | 897 } |
| 822 | 898 |
| 823 for (PageActionMap::const_iterator it = page_actions().begin(); | 899 for (PageActionMap::const_iterator it = page_actions().begin(); |
| 824 it != page_actions().end(); ++it) { | 900 it != page_actions().end(); ++it) { |
| 825 image_paths.insert(it->second->icon_path()); | 901 image_paths.insert(it->second->icon_path()); |
| 826 } | 902 } |
| 827 | 903 |
| 828 return image_paths; | 904 return image_paths; |
| 829 } | 905 } |
| OLD | NEW |