| Index: chrome/common/extensions/extension.cc
|
| diff --git a/chrome/common/extensions/extension.cc b/chrome/common/extensions/extension.cc
|
| index bf7d3a5ddcde3787021f85eae442d1d5c3ec1334..73eb417cc9e49547bc8ead23be9fd68016bd9a03 100644
|
| --- a/chrome/common/extensions/extension.cc
|
| +++ b/chrome/common/extensions/extension.cc
|
| @@ -5,10 +5,14 @@
|
| #include "chrome/common/extensions/extension.h"
|
|
|
| #include "app/resource_bundle.h"
|
| +#include "base/basictypes.h"
|
| #include "base/file_path.h"
|
| #include "base/file_util.h"
|
| #include "base/logging.h"
|
| #include "base/string_util.h"
|
| +#include "base/third_party/nss/blapi.h"
|
| +#include "base/third_party/nss/sha256.h"
|
| +#include "net/base/base64.h"
|
| #include "net/base/net_util.h"
|
| #include "chrome/common/extensions/extension_error_reporter.h"
|
| #include "chrome/common/extensions/extension_error_utils.h"
|
| @@ -33,6 +37,8 @@ namespace {
|
| const int kRSAKeySize = 1024;
|
| };
|
|
|
| +int Extension::id_counter_ = 0;
|
| +
|
| const char Extension::kManifestFilename[] = "manifest.json";
|
|
|
| const wchar_t* Extension::kBackgroundKey = L"background_page";
|
| @@ -40,10 +46,10 @@ const wchar_t* Extension::kContentScriptsKey = L"content_scripts";
|
| const wchar_t* Extension::kCssKey = L"css";
|
| const wchar_t* Extension::kDescriptionKey = L"description";
|
| const wchar_t* Extension::kIconPathKey = L"icon";
|
| -const wchar_t* Extension::kIdKey = L"id";
|
| const wchar_t* Extension::kJsKey = L"js";
|
| const wchar_t* Extension::kMatchesKey = L"matches";
|
| const wchar_t* Extension::kNameKey = L"name";
|
| +const wchar_t* Extension::kPageActionIdKey = L"id";
|
| const wchar_t* Extension::kPageActionsKey = L"page_actions";
|
| const wchar_t* Extension::kPermissionsKey = L"permissions";
|
| const wchar_t* Extension::kPluginsKey = L"plugins";
|
| @@ -71,7 +77,6 @@ const char* Extension::kPageActionTypePermanent = "permanent";
|
| static const wchar_t* kValidThemeKeys[] = {
|
| Extension::kDescriptionKey,
|
| Extension::kIconPathKey,
|
| - Extension::kIdKey,
|
| Extension::kNameKey,
|
| Extension::kPublicKeyKey,
|
| Extension::kSignatureKey,
|
| @@ -93,12 +98,12 @@ const char* Extension::kInvalidCssListError =
|
| "Required value 'content_scripts[*].css is invalid.";
|
| const char* Extension::kInvalidDescriptionError =
|
| "Invalid value for 'description'.";
|
| -const char* Extension::kInvalidIdError =
|
| - "Required value 'id' is missing or invalid.";
|
| const char* Extension::kInvalidJsError =
|
| "Invalid value for 'content_scripts[*].js[*]'.";
|
| const char* Extension::kInvalidJsListError =
|
| "Required value 'content_scripts[*].js is invalid.";
|
| +const char* Extension::kInvalidKeyError =
|
| + "Value 'key' is missing or invalid.";
|
| const char* Extension::kInvalidManifestError =
|
| "Manifest is missing or invalid.";
|
| const char* Extension::kInvalidMatchCountError =
|
| @@ -116,6 +121,8 @@ const char* Extension::kInvalidPageActionsListError =
|
| "Invalid value for 'page_actions'.";
|
| const char* Extension::kInvalidPageActionIconPathError =
|
| "Invalid value for 'page_actions[*].icon'.";
|
| +const char* Extension::kInvalidPageActionIdError =
|
| + "Required value 'id' is missing or invalid.";
|
| const char* Extension::kInvalidPageActionTooltipError =
|
| "Invalid value for 'page_actions[*].tooltip'.";
|
| const char* Extension::kInvalidPageActionTypeValueError =
|
| @@ -139,6 +146,8 @@ const char* Extension::kInvalidBackgroundError =
|
| "Invalid value for 'background'.";
|
| const char* Extension::kInvalidRunAtError =
|
| "Invalid value for 'content_scripts[*].run_at'.";
|
| +const char* Extension::kInvalidSignatureError =
|
| + "Value 'signature' is missing or invalid.";
|
| const char* Extension::kInvalidToolstripError =
|
| "Invalid value for 'toolstrips[*]'";
|
| const char* Extension::kInvalidToolstripsError =
|
| @@ -167,7 +176,8 @@ const char* Extension::kExtensionRegistryPath =
|
| "Software\\Google\\Chrome\\Extensions";
|
| #endif
|
|
|
| -const size_t Extension::kIdSize = 20; // SHA1 (160 bits) == 20 bytes
|
| +// first 20 bytes of SHA256 hashed public key.
|
| +const size_t Extension::kIdSize = 20;
|
|
|
| Extension::~Extension() {
|
| for (PageActionMap::iterator i = page_actions_.begin();
|
| @@ -230,6 +240,23 @@ Extension::Location Extension::ExternalExtensionInstallType(
|
| return Extension::EXTERNAL_PREF;
|
| }
|
|
|
| +bool Extension::GenerateIdFromPublicKey(const std::string& input,
|
| + std::string* output) {
|
| + CHECK(output);
|
| + if (input.length() == 0)
|
| + return false;
|
| +
|
| + const uint8* ubuf = reinterpret_cast<const unsigned char*>(input.data());
|
| + SHA256Context ctx;
|
| + SHA256_Begin(&ctx);
|
| + SHA256_Update(&ctx, ubuf, input.length());
|
| + uint8 hash[Extension::kIdSize];
|
| + SHA256_End(&ctx, hash, NULL, sizeof(hash));
|
| + *output = StringToLowerASCII(HexEncode(hash, sizeof(hash)));
|
| +
|
| + return true;
|
| +}
|
| +
|
| // Helper method that loads a UserScript object from a dictionary in the
|
| // content_script list of the manifest.
|
| bool Extension::LoadUserScriptHelper(const DictionaryValue* content_script,
|
| @@ -367,8 +394,8 @@ PageAction* Extension::LoadPageActionHelper(
|
|
|
| // Read the page action |id|.
|
| std::string id;
|
| - if (!page_action->GetString(kIdKey, &id)) {
|
| - *error = ExtensionErrorUtils::FormatErrorMessage(kInvalidIdError,
|
| + if (!page_action->GetString(kPageActionIdKey, &id)) {
|
| + *error = ExtensionErrorUtils::FormatErrorMessage(kInvalidPageActionIdError,
|
| IntToString(definition_index));
|
| return NULL;
|
| }
|
| @@ -492,13 +519,14 @@ Extension::Extension(const FilePath& path) {
|
| #endif
|
| }
|
|
|
| -
|
| // TODO(rafaelw): Move ParsePEMKeyBytes, ProducePEM & FormatPEMForOutput to a
|
| // util class in base:
|
| // http://code.google.com/p/chromium/issues/detail?id=13572
|
| bool Extension::ParsePEMKeyBytes(const std::string& input,
|
| std::string* output) {
|
| - CHECK(output);
|
| + DCHECK(output);
|
| + if (!output)
|
| + return false;
|
| if (input.length() == 0)
|
| return false;
|
|
|
| @@ -564,33 +592,23 @@ bool Extension::FormatPEMForFileOutput(const std::string input,
|
|
|
| bool Extension::InitFromValue(const DictionaryValue& source, bool require_id,
|
| std::string* error) {
|
| - // Initialize id.
|
| - if (source.HasKey(kIdKey)) {
|
| - if (!source.GetString(kIdKey, &id_)) {
|
| - *error = kInvalidIdError;
|
| - return false;
|
| - }
|
| -
|
| - // Normalize the string to lowercase, so it can be used as an URL component
|
| - // (where GURL will lowercase it).
|
| - StringToLowerASCII(&id_);
|
| -
|
| - // Verify that the id is legal.
|
| - if (!IdIsValid(id_)) {
|
| - *error = kInvalidIdError;
|
| - return false;
|
| + if (source.HasKey(kPublicKeyKey)) {
|
| + std::string public_key_bytes;
|
| + if (!source.GetString(kPublicKeyKey, &public_key_) ||
|
| + !ParsePEMKeyBytes(public_key_, &public_key_bytes) ||
|
| + !GenerateIdFromPublicKey(public_key_bytes, &id_)) {
|
| + *error = kInvalidKeyError;
|
| + return false;
|
| }
|
| } else if (require_id) {
|
| - *error = kInvalidIdError;
|
| + *error = kInvalidKeyError;
|
| return false;
|
| } else {
|
| // Generate a random ID
|
| - static int counter = 0;
|
| - id_ = StringPrintf("%x", counter);
|
| - ++counter;
|
| + id_ = StringPrintf("%x", NextGeneratedId());
|
|
|
| - // pad the string out to 40 chars with zeroes.
|
| - id_.insert(0, 40 - id_.length(), '0');
|
| + // pad the string out to kIdSize*2 chars with zeroes.
|
| + id_.insert(0, Extension::kIdSize*2 - id_.length(), '0');
|
| }
|
|
|
| // Initialize the URL.
|
|
|