diff options
Diffstat (limited to 'chrome/browser')
-rwxr-xr-x | chrome/browser/extensions/extension_creator.cc | 13 | ||||
-rwxr-xr-x | chrome/browser/extensions/extension_creator.h | 22 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_shelf_model_unittest.cc | 2 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_uitest.cc | 4 | ||||
-rw-r--r-- | chrome/browser/extensions/extensions_service.cc | 252 | ||||
-rw-r--r-- | chrome/browser/extensions/extensions_service.h | 68 | ||||
-rw-r--r-- | chrome/browser/extensions/extensions_service_unittest.cc | 88 |
7 files changed, 112 insertions, 337 deletions
diff --git a/chrome/browser/extensions/extension_creator.cc b/chrome/browser/extensions/extension_creator.cc index 9abd030..8c38e17 100755 --- a/chrome/browser/extensions/extension_creator.cc +++ b/chrome/browser/extensions/extension_creator.cc @@ -12,7 +12,6 @@ #include "base/file_util.h" #include "base/scoped_handle.h" #include "base/string_util.h" -#include "chrome/browser/extensions/extensions_service.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/zip.h" #include "net/base/base64.h" @@ -21,6 +20,8 @@ namespace { const int kRSAKeySize = 1024; }; +const char ExtensionCreator::kExtensionHeaderMagic[] = "Cr24"; + bool ExtensionCreator::InitializeInput( const FilePath& extension_dir, const FilePath& private_key_path, @@ -166,14 +167,14 @@ bool ExtensionCreator::WriteCRX(const FilePath& zip_path, return false; } - ExtensionsService::ExtensionHeader header; - memcpy(&header.magic, ExtensionsService::kExtensionHeaderMagic, - ExtensionsService::kExtensionHeaderMagicSize); - header.version = ExtensionsService::kCurrentVersion; + ExtensionCreator::ExtensionHeader header; + memcpy(&header.magic, ExtensionCreator::kExtensionHeaderMagic, + ExtensionCreator::kExtensionHeaderMagicSize); + header.version = kCurrentVersion; header.key_size = public_key.size(); header.signature_size = signature.size(); - fwrite(&header, sizeof(ExtensionsService::ExtensionHeader), 1, + fwrite(&header, sizeof(ExtensionCreator::ExtensionHeader), 1, crx_handle.get()); fwrite(&public_key.front(), sizeof(uint8), public_key.size(), crx_handle.get()); diff --git a/chrome/browser/extensions/extension_creator.h b/chrome/browser/extensions/extension_creator.h index 129e152..febcecd 100755 --- a/chrome/browser/extensions/extension_creator.h +++ b/chrome/browser/extensions/extension_creator.h @@ -17,6 +17,28 @@ // generated randomly (and optionally written to |output_private_key_path|. class ExtensionCreator { public: + // The size of the magic character sequence at the beginning of each crx file, + // in bytes. This should be a multiple of 4. + static const size_t kExtensionHeaderMagicSize = 4; + + // The magic character sequence at the beginning of each crx file. + static const char kExtensionHeaderMagic[]; + + // The current version of the crx format. + static const uint32 kCurrentVersion = 2; + + // This header is the first data at the beginning of an extension. Its + // contents are purposely 32-bit aligned so that it can just be slurped into + // a struct without manual parsing. + struct ExtensionHeader { + char magic[kExtensionHeaderMagicSize]; + uint32 version; + size_t key_size; // The size of the public key, in bytes. + size_t signature_size; // The size of the signature, in bytes. + // An ASN.1-encoded PublicKeyInfo structure follows. + // The signature follows. + }; + ExtensionCreator() {} bool Run(const FilePath& extension_dir, diff --git a/chrome/browser/extensions/extension_shelf_model_unittest.cc b/chrome/browser/extensions/extension_shelf_model_unittest.cc index 82ce02e..230e2cc 100644 --- a/chrome/browser/extensions/extension_shelf_model_unittest.cc +++ b/chrome/browser/extensions/extension_shelf_model_unittest.cc @@ -15,7 +15,7 @@ namespace { // The extension we're using as our test case. -const char* kExtensionId = "fc6f6ba6693faf6773c13701019f2e7a12f0febe"; +const char* kExtensionId = "00123456789abcdef0123456789abcdef0123456"; }; // namespace diff --git a/chrome/browser/extensions/extension_uitest.cc b/chrome/browser/extensions/extension_uitest.cc index 12cac46..38a5bb6 100644 --- a/chrome/browser/extensions/extension_uitest.cc +++ b/chrome/browser/extensions/extension_uitest.cc @@ -103,7 +103,7 @@ TEST_F(SimpleApiCallExtensionTest, RunTest) { namespace keys = extension_automation_constants; TestWithURL(GURL( - "chrome-extension://fc6f6ba6693faf6773c13701019f2e7a12f0febe/test.html")); + "chrome-extension://77774444789ABCDEF0123456789ABCDEF0123456/test.html")); AutomationProxyForExternalTab* proxy = static_cast<AutomationProxyForExternalTab*>(automation()); ASSERT_GT(proxy->messages_received(), 0); @@ -270,7 +270,7 @@ class RoundtripApiCallExtensionTest #if defined(OS_WIN) TEST_F(RoundtripApiCallExtensionTest, RunTest) { TestWithURL(GURL( - "chrome-extension://e5ead92b2c6795c1d2b92df9c5cb37de5582471a/test.html")); + "chrome-extension://66664444789ABCDEF0123456789ABCDEF0123456/test.html")); RoundtripAutomationProxy* proxy = static_cast<RoundtripAutomationProxy*>(automation()); diff --git a/chrome/browser/extensions/extensions_service.cc b/chrome/browser/extensions/extensions_service.cc index b6346b0..94c1dd5 100644 --- a/chrome/browser/extensions/extensions_service.cc +++ b/chrome/browser/extensions/extensions_service.cc @@ -6,7 +6,6 @@ #include "app/l10n_util.h" #include "base/command_line.h" -#include "base/crypto/signature_verifier.h" #include "base/file_util.h" #include "base/gfx/png_encoder.h" #include "base/scoped_handle.h" @@ -21,7 +20,6 @@ #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_thread.h" -#include "chrome/browser/extensions/extension_creator.h" #include "chrome/browser/extensions/extension_browser_event_router.h" #include "chrome/browser/extensions/extension_process_manager.h" #include "chrome/browser/profile.h" @@ -38,7 +36,6 @@ #include "chrome/common/url_constants.h" #include "grit/chromium_strings.h" #include "grit/generated_resources.h" -#include "net/base/base64.h" #include "third_party/skia/include/core/SkBitmap.h" #if defined(OS_WIN) @@ -49,8 +46,6 @@ // ExtensionsService. -const char ExtensionsService::kExtensionHeaderMagic[] = "Cr24"; - const char* ExtensionsService::kInstallDirectoryName = "Extensions"; const char* ExtensionsService::kCurrentVersionFileName = "Current Version"; const char* ExtensionsServiceBackend::kTempExtensionName = "TEMP_INSTALL"; @@ -87,17 +82,8 @@ const char kExternalInstallFile[] = "EXTERNAL_INSTALL"; // A temporary subdirectory where we unpack extensions. const char* kUnpackExtensionDir = "TEMP_UNPACK"; -// Unpacking errors -const char* kBadMagicNumberError = "Bad magic number"; -const char* kBadHeaderSizeError = "Excessively large key or signature"; -const char* kBadVersionNumberError = "Bad version number"; -const char* kInvalidExtensionHeaderError = "Invalid extension header"; -const char* kInvalidPublicKeyError = "Invalid public key"; -const char* kInvalidSignatureError = "Invalid signature"; -const char* kSignatureVerificationFailed = "Signature verification failed"; -const char* kSignatureVerificationInitFailed = - "Signature verification initialization failed. This is most likely " - "caused by a public key in the wrong format (should encode algorithm)."; +// The version of the extension package that this code understands. +const uint32 kExpectedVersion = 1; } // This class coordinates an extension unpack task which is run in a separate @@ -108,12 +94,11 @@ class ExtensionsServiceBackend::UnpackerClient public: UnpackerClient(ExtensionsServiceBackend* backend, const FilePath& extension_path, - const std::string& public_key, const std::string& expected_id, bool from_external) : backend_(backend), extension_path_(extension_path), - public_key_(public_key), expected_id_(expected_id), - from_external_(from_external), got_response_(false) { + expected_id_(expected_id), from_external_(from_external), + got_response_(false) { } // Starts the unpack task. We call back to the backend when the task is done, @@ -178,14 +163,6 @@ class ExtensionsServiceBackend::UnpackerClient void OnUnpackExtensionSucceededImpl( const DictionaryValue& manifest, const ExtensionUnpacker::DecodedImages& images) { - // Add our public key into the parsed manifest. We want it to be saved so - // that we can later refer to it (eg for generating ids, validating - // signatures, etc). - // The const_cast is hacky, but seems like the right thing here, rather than - // making a full copy just to make this change. - const_cast<DictionaryValue*>(&manifest)->SetString( - Extension::kPublicKeyKey, public_key_); - // The extension was unpacked to the temp dir inside our unpacking dir. FilePath extension_dir = temp_extension_path_.DirName().AppendASCII( ExtensionsServiceBackend::kTempExtensionName); @@ -222,9 +199,6 @@ class ExtensionsServiceBackend::UnpackerClient // The path to the crx file that we're installing. FilePath extension_path_; - // The public key of the extension we're installing. - std::string public_key_; - // The path to the copy of the crx file in the temporary directory where we're // unpacking it. FilePath temp_extension_path_; @@ -397,7 +371,7 @@ void ExtensionsService::OnExtensionsLoaded(ExtensionList* new_extensions) { } void ExtensionsService::OnExtensionInstalled(Extension* extension, - Extension::InstallType install_type) { + bool update) { UpdateExtensionPref(ASCIIToWide(extension->id()), kState, Value::CreateIntegerValue(Extension::ENABLED), false); UpdateExtensionPref(ASCIIToWide(extension->id()), kLocation, @@ -427,7 +401,7 @@ void ExtensionsService::OnExternalExtensionInstalled( Value::CreateIntegerValue(location), true); } -void ExtensionsService::OnExtensionOverinstallAttempted(const std::string& id) { +void ExtensionsService::OnExtensionVersionReinstalled(const std::string& id) { Extension* extension = GetExtensionByID(id); if (extension && extension->IsTheme()) { NotificationService::current()->Notify( @@ -648,21 +622,6 @@ void ExtensionsServiceBackend::LoadSingleExtension( } } -DictionaryValue* ExtensionsServiceBackend::ReadManifest(FilePath manifest_path, - std::string* error) { - JSONFileValueSerializer serializer(manifest_path); - scoped_ptr<Value> root(serializer.Deserialize(error)); - if (!root.get()) - return NULL; - - if (!root->IsType(Value::TYPE_DICTIONARY)) { - *error = Extension::kInvalidManifestError; - return NULL; - } - - return static_cast<DictionaryValue*>(root.release()); -} - Extension* ExtensionsServiceBackend::LoadExtension( const FilePath& extension_path, bool require_id) { FilePath manifest_path = @@ -672,15 +631,22 @@ Extension* ExtensionsServiceBackend::LoadExtension( return NULL; } + JSONFileValueSerializer serializer(manifest_path); std::string error; - scoped_ptr<DictionaryValue> root(ReadManifest(manifest_path, &error)); + scoped_ptr<Value> root(serializer.Deserialize(&error)); if (!root.get()) { ReportExtensionLoadError(extension_path, error); return NULL; } + if (!root->IsType(Value::TYPE_DICTIONARY)) { + ReportExtensionLoadError(extension_path, Extension::kInvalidManifestError); + return NULL; + } + scoped_ptr<Extension> extension(new Extension(extension_path)); - if (!extension->InitFromValue(*root.get(), require_id, &error)) { + if (!extension->InitFromValue(*static_cast<DictionaryValue*>(root.get()), + require_id, &error)) { ReportExtensionLoadError(extension_path, error); return NULL; } @@ -795,36 +761,28 @@ bool ExtensionsServiceBackend::ReadCurrentVersion(const FilePath& dir, return false; } -Extension::InstallType ExtensionsServiceBackend::CompareToInstalledVersion( - const std::string& id, +bool ExtensionsServiceBackend::CheckCurrentVersion( const std::string& new_version_str, - std::string *current_version_str) { - CHECK(current_version_str); - FilePath dir(install_directory_.AppendASCII(id.c_str())); - if (!ReadCurrentVersion(dir, current_version_str)) - return Extension::NEW_INSTALL; - + const std::string& current_version_str, + const FilePath& dest_dir) { scoped_ptr<Version> current_version( - Version::GetVersionFromString(*current_version_str)); + Version::GetVersionFromString(current_version_str)); scoped_ptr<Version> new_version( - Version::GetVersionFromString(new_version_str)); - int comp = new_version->CompareTo(*current_version); - if (comp > 0) - return Extension::UPGRADE; - else if (comp == 0) - return Extension::REINSTALL; - else - return Extension::DOWNGRADE; -} - -bool ExtensionsServiceBackend::NeedsReinstall(const std::string& id, - const std::string& current_version) { - // Verify that the directory actually exists. - // TODO(erikkay): A further step would be to verify that the extension - // has actually loaded successfully. - FilePath dir(install_directory_.AppendASCII(id.c_str())); - FilePath version_dir(dir.AppendASCII(current_version)); - return !file_util::PathExists(version_dir); + Version::GetVersionFromString(new_version_str)); + if (current_version->CompareTo(*new_version) >= 0) { + // Verify that the directory actually exists. If it doesn't we'll return + // true so that the install code will repair the broken installation. + // TODO(erikkay): A further step would be to verify that the extension + // has actually loaded successfully. + FilePath version_dir = dest_dir.AppendASCII(current_version_str); + if (file_util::PathExists(version_dir)) { + std::string id = WideToASCII(dest_dir.BaseName().ToWStringHack()); + StringToLowerASCII(&id); + ReportExtensionVersionReinstalled(id); + return false; + } + } + return true; } bool ExtensionsServiceBackend::InstallDirSafely(const FilePath& source_dir, @@ -911,107 +869,13 @@ void ExtensionsServiceBackend::InstallExtension( } void ExtensionsServiceBackend::InstallOrUpdateExtension( - const FilePath& extension_path, - const std::string& expected_id, + const FilePath& extension_path, const std::string& expected_id, bool from_external) { - std::string actual_public_key; - if (!ValidateSignature(extension_path, &actual_public_key)) - return; // Failures reported within ValidateSignature(). - - UnpackerClient* client = new UnpackerClient( - this, extension_path, actual_public_key, expected_id, from_external); + UnpackerClient* client = + new UnpackerClient(this, extension_path, expected_id, from_external); client->Start(); } -bool ExtensionsServiceBackend::ValidateSignature(const FilePath& extension_path, - std::string* key_out) { - ScopedStdioHandle file(file_util::OpenFile(extension_path, "rb")); - if (!file.get()) { - ReportExtensionInstallError(extension_path, "Could not open file."); - return NULL; - } - - // Read and verify the header. - ExtensionsService::ExtensionHeader header; - size_t len; - - // TODO(erikkay): Yuck. I'm not a big fan of this kind of code, but it - // appears that we don't have any endian/alignment aware serialization - // code in the code base. So for now, this assumes that we're running - // on a little endian machine with 4 byte alignment. - len = fread(&header, 1, sizeof(ExtensionsService::ExtensionHeader), - file.get()); - if (len < sizeof(ExtensionsService::ExtensionHeader)) { - ReportExtensionInstallError(extension_path, kInvalidExtensionHeaderError); - return false; - } - if (strncmp(ExtensionsService::kExtensionHeaderMagic, header.magic, - sizeof(header.magic))) { - ReportExtensionInstallError(extension_path, kBadMagicNumberError); - return false; - } - if (header.version != ExtensionsService::kCurrentVersion) { - ReportExtensionInstallError(extension_path, kBadVersionNumberError); - return false; - } - if (header.key_size > ExtensionsService::kMaxPublicKeySize || - header.signature_size > ExtensionsService::kMaxSignatureSize) { - ReportExtensionInstallError(extension_path, kBadHeaderSizeError); - return false; - } - - std::vector<uint8> key; - key.resize(header.key_size); - len = fread(&key.front(), sizeof(uint8), header.key_size, file.get()); - if (len < header.key_size) { - ReportExtensionInstallError(extension_path, kInvalidPublicKeyError); - return false; - } - - std::vector<uint8> signature; - signature.resize(header.signature_size); - len = fread(&signature.front(), sizeof(uint8), header.signature_size, - file.get()); - if (len < header.signature_size) { - ReportExtensionInstallError(extension_path, kInvalidSignatureError); - return false; - } - - // Note: this structure is an ASN.1 which encodes the algorithm used - // with its parameters. This is defined in PKCS #1 v2.1 (RFC 3447). - // It is encoding: { OID sha1WithRSAEncryption PARAMETERS NULL } - // TODO(aa): This needs to be factored away someplace common. - const uint8 signature_algorithm[15] = { - 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, - 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00 - }; - - base::SignatureVerifier verifier; - if (!verifier.VerifyInit(signature_algorithm, - sizeof(signature_algorithm), - &signature.front(), - signature.size(), - &key.front(), - key.size())) { - ReportExtensionInstallError(extension_path, - kSignatureVerificationInitFailed); - return false; - } - - unsigned char buf[1 << 12]; - while ((len = fread(buf, 1, sizeof(buf), file.get())) > 0) - verifier.VerifyUpdate(buf, len); - - if (!verifier.VerifyFinal()) { - ReportExtensionInstallError(extension_path, kSignatureVerificationFailed); - return false; - } - - net::Base64Encode(std::string(reinterpret_cast<char*>(&key.front()), - key.size()), key_out); - return true; -} - void ExtensionsServiceBackend::OnExtensionUnpacked( const FilePath& extension_path, const FilePath& temp_extension_dir, @@ -1074,25 +938,11 @@ void ExtensionsServiceBackend::OnExtensionUnpacked( FilePath dest_dir = install_directory_.AppendASCII(extension.id()); std::string version = extension.VersionString(); std::string current_version; - Extension::InstallType install_type = - CompareToInstalledVersion(extension.id(), version, ¤t_version); - - // Do not allow downgrade. - if (install_type == Extension::DOWNGRADE) { - ReportExtensionInstallError(extension_path, - "Error: Attempt to downgrade extension from more recent version."); - return; - } - - if (install_type == Extension::REINSTALL) { - if (NeedsReinstall(extension.id(), current_version)) { - // Treat corrupted existing installation as new install case. - install_type = Extension::NEW_INSTALL; - } else { - // The client may use this as a signal (to switch themes, for instance). - ReportExtensionOverinstallAttempted(extension.id()); + bool was_update = false; + if (ReadCurrentVersion(dest_dir, ¤t_version)) { + if (!CheckCurrentVersion(version, current_version, dest_dir)) return; - } + was_update = true; } // Write our parsed manifest back to disk, to ensure it doesn't contain an @@ -1191,7 +1041,7 @@ void ExtensionsServiceBackend::OnExtensionUnpacked( frontend_loop_->PostTask(FROM_HERE, NewRunnableMethod( frontend_, &ExtensionsService::OnExtensionInstalled, extension, - install_type)); + was_update)); // Only one extension, but ReportExtensionsLoaded can handle multiple, // so we need to construct a list. @@ -1221,10 +1071,10 @@ void ExtensionsServiceBackend::ReportExtensionInstallError( ExtensionErrorReporter::GetInstance()->ReportError(message, alert_on_error_); } -void ExtensionsServiceBackend::ReportExtensionOverinstallAttempted( +void ExtensionsServiceBackend::ReportExtensionVersionReinstalled( const std::string& id) { frontend_loop_->PostTask(FROM_HERE, NewRunnableMethod( - frontend_, &ExtensionsService::OnExtensionOverinstallAttempted, id)); + frontend_, &ExtensionsService::OnExtensionVersionReinstalled, id)); } bool ExtensionsServiceBackend::ShouldSkipInstallingExtension( @@ -1410,14 +1260,10 @@ void ExtensionsServiceBackend::UninstallExtension( bool ExtensionsServiceBackend::ShouldInstall(const std::string& id, const std::string& version) { + FilePath dir(install_directory_.AppendASCII(id.c_str())); std::string current_version; - Extension::InstallType install_type = CompareToInstalledVersion(id, version, - ¤t_version); - - if (install_type == Extension::DOWNGRADE) - return false; - - return (install_type == Extension::UPGRADE || - install_type == Extension::NEW_INSTALL || - NeedsReinstall(id, current_version)); + if (ReadCurrentVersion(dir, ¤t_version)) { + return CheckCurrentVersion(version, current_version, dir); + } + return true; } diff --git a/chrome/browser/extensions/extensions_service.h b/chrome/browser/extensions/extensions_service.h index f22b15d..f72a63a 100644 --- a/chrome/browser/extensions/extensions_service.h +++ b/chrome/browser/extensions/extensions_service.h @@ -32,43 +32,10 @@ class UserScriptMaster; typedef std::vector<Extension*> ExtensionList; - // Manages installed and running Chromium extensions. class ExtensionsService : public base::RefCountedThreadSafe<ExtensionsService> { public: - - // TODO(port): Move Crx package definitions to ExtentionCreator. They are - // currently here because ExtensionCreator is excluded on linux & mac. - - // The size of the magic character sequence at the beginning of each crx - // file, in bytes. This should be a multiple of 4. - static const size_t kExtensionHeaderMagicSize = 4; - - // The maximum size the crx parser will tolerate for a public key. - static const size_t kMaxPublicKeySize = 1 << 16; - - // The maximum size the crx parser will tolerate for a signature. - static const size_t kMaxSignatureSize = 1 << 16; - - // The magic character sequence at the beginning of each crx file. - static const char kExtensionHeaderMagic[]; - - // The current version of the crx format. - static const uint32 kCurrentVersion = 2; - - // This header is the first data at the beginning of an extension. Its - // contents are purposely 32-bit aligned so that it can just be slurped into - // a struct without manual parsing. - struct ExtensionHeader { - char magic[kExtensionHeaderMagicSize]; - uint32 version; - size_t key_size; // The size of the public key, in bytes. - size_t signature_size; // The size of the signature, in bytes. - // An ASN.1-encoded PublicKeyInfo structure follows. - // The signature follows. - }; - ExtensionsService(Profile* profile, MessageLoop* frontend_loop, MessageLoop* backend_loop, @@ -141,16 +108,14 @@ class ExtensionsService void OnExtensionsLoaded(ExtensionList* extensions); // Called by the backend when an extensoin hsa been installed. - void OnExtensionInstalled(Extension* extension, - Extension::InstallType install_type); + void OnExtensionInstalled(Extension* extension, bool is_update); // Called by the backend when an external extension has been installed. void OnExternalExtensionInstalled( const std::string& id, Extension::Location location); - // Called by the backend when an attempt was made to reinstall the same - // version of an existing extension. - void OnExtensionOverinstallAttempted(const std::string& id); + // Called by the backend when an extension has been reinstalled. + void OnExtensionVersionReinstalled(const std::string& id); // The name of the directory inside the profile where extensions are // installed to. @@ -233,11 +198,6 @@ class ExtensionsServiceBackend class UnpackerClient; friend class UnpackerClient; - // Utility function to read an extension manifest and return it as a - // DictionaryValue. If it fails, NULL is returned and |error| contains an - // appropriate message. - DictionaryValue* ReadManifest(FilePath manifest_path, std::string* error); - // Load a single extension from |extension_path|, the top directory of // a specific extension where its manifest file lives. Extension* LoadExtension(const FilePath& extension_path, bool require_id); @@ -256,10 +216,6 @@ class ExtensionsServiceBackend const std::string& expected_id, bool from_external); - // Validates the signature of the extension in |extension_path|. Returns true - // and the public key (in |key|) if the signature validates, false otherwise. - bool ValidateSignature(const FilePath& extension_path, std::string* key_out); - // Finish installing an extension after it has been unpacked to // |temp_extension_dir| by our utility process. If |expected_id| is not // empty, it's verified against the extension's manifest before installation. @@ -284,9 +240,8 @@ class ExtensionsServiceBackend void ReportExtensionInstallError(const FilePath& extension_path, const std::string& error); - // Notify the frontend that an attempt was made (but not carried out) to - // install the same version of an existing extension. - void ReportExtensionOverinstallAttempted(const std::string& id); + // Notify the frontend that the extension had already been installed. + void ReportExtensionVersionReinstalled(const std::string& id); // Checks a set of strings (containing id's to ignore) in order to determine // if the extension should be installed. @@ -307,14 +262,11 @@ class ExtensionsServiceBackend // Reads the Current Version file from |dir| into |version_string|. bool ReadCurrentVersion(const FilePath& dir, std::string* version_string); - // Look for an existing installation of the extension |id| & return - // an InstallType that would result from installing |new_version_str|. - Extension::InstallType CompareToInstalledVersion(const std::string& id, - const std::string& new_version_str, std::string* current_version_str); - - // Does an existing installed extension need to be reinstalled. - bool NeedsReinstall(const std::string& id, - const std::string& current_version); + // Check that the version to be installed is greater than the current + // installed extension. + bool CheckCurrentVersion(const std::string& version, + const std::string& current_version, + const FilePath& dest_dir); // Install the extension dir by moving it from |source| to |dest| safely. bool InstallDirSafely(const FilePath& source, diff --git a/chrome/browser/extensions/extensions_service_unittest.cc b/chrome/browser/extensions/extensions_service_unittest.cc index 99999fb..ef41940 100644 --- a/chrome/browser/extensions/extensions_service_unittest.cc +++ b/chrome/browser/extensions/extensions_service_unittest.cc @@ -36,13 +36,13 @@ namespace { // Extension ids used during testing. const char* const all_zero = "0000000000000000000000000000000000000000"; const char* const zero_n_one = "0000000000000000000000000000000000000001"; -const char* const good0 = "fc6f6ba6693faf6773c13701019f2e7a12f0febe"; -const char* const good1 = "e5ead92b2c6795c1d2b92df9c5cb37de5582471a"; -const char* const good2 = "a37fed892f622823f4daaec4426a32fc7f6147dc"; -const char* const good_crx = "b3dd733cd71a98fa83f387455e12f5c5501c519e"; -const char* const page_action = "a4ca7d01469a010acb200568a0b8f4d9b3ac1f91"; -const char* const theme_crx = "80c45f5ae9e0f839d105c6a6d2461a036bc40a04"; -const char* const theme2_crx = "f9f6c52c01efdd5edd7c396b5f995a15fc7ad6d1"; +const char* const good0 = "00123456789abcdef0123456789abcdef0123456"; +const char* const good1 = "10123456789abcdef0123456789abcdef0123456"; +const char* const good2 = "20123456789abcdef0123456789abcdef0123456"; +const char* const good_crx = "00123456789abcdef0123456789abcdef0123456"; +const char* const page_action = "8a5e4cb023c61b431e9b603a97c293429ce057c8"; +const char* const theme_crx = "f0123456789abcdef0123456789abcdef0126456"; +const char* const theme2_crx = "f0123456789adddef0123456789abcdef0126456"; struct ExtensionsOrder { bool operator()(const Extension* a, const Extension* b) { @@ -235,7 +235,7 @@ TEST_F(ExtensionsServiceTest, LoadAllExtensionsFromDirectorySuccess) { } ASSERT_EQ(3u, loaded_.size()); - EXPECT_EQ(std::string(good0), loaded_[0]->id()); + EXPECT_EQ(std::string(good_crx), loaded_[0]->id()); EXPECT_EQ(std::string("My extension 1"), loaded_[0]->name()); EXPECT_EQ(std::string("The first extension that I made."), @@ -245,8 +245,8 @@ TEST_F(ExtensionsServiceTest, LoadAllExtensionsFromDirectorySuccess) { EXPECT_EQ(3u, service_->extensions()->size()); ValidatePrefKeyCount(3); - ValidatePref(good0, L"state", Extension::ENABLED); - ValidatePref(good0, L"location", Extension::INTERNAL); + ValidatePref(good_crx, L"state", Extension::ENABLED); + ValidatePref(good_crx, L"location", Extension::INTERNAL); ValidatePref(good1, L"state", Extension::ENABLED); ValidatePref(good1, L"location", Extension::INTERNAL); ValidatePref(good2, L"state", Extension::ENABLED); @@ -398,10 +398,6 @@ TEST_F(ExtensionsServiceTest, InstallExtension) { ValidatePref(page_action, L"state", Extension::ENABLED); ValidatePref(page_action, L"location", Extension::INTERNAL); - // Bad signature. - path = extensions_path.AppendASCII("bad_signature.crx"); - InstallExtension(path, false); - // 0-length extension file. path = extensions_path.AppendASCII("not_an_extension.crx"); InstallExtension(path, false); @@ -412,6 +408,16 @@ TEST_F(ExtensionsServiceTest, InstallExtension) { InstallExtension(path, false); ValidatePrefKeyCount(pref_count); + // Poorly formed JSON. + path = extensions_path.AppendASCII("bad_json.crx"); + InstallExtension(path, false); + ValidatePrefKeyCount(pref_count); + + // Incorrect zip hash. + path = extensions_path.AppendASCII("bad_hash.crx"); + InstallExtension(path, false); + ValidatePrefKeyCount(pref_count); + // TODO(erikkay): add more tests for many of the failure cases. // TODO(erikkay): add tests for upgrade cases. } @@ -553,56 +559,6 @@ TEST_F(ExtensionsServiceTest, Reinstall) { ValidatePref(good_crx, L"location", Extension::INTERNAL); } -// Test upgrading a signed extension. -TEST_F(ExtensionsServiceTest, UpgradeSignedGood) { - FilePath extensions_path; - ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); - extensions_path = extensions_path.AppendASCII("extensions"); - - FilePath path = extensions_path.AppendASCII("good.crx"); - service_->InstallExtension(path); - loop_.RunAllPending(); - - ASSERT_TRUE(installed_); - ASSERT_EQ(1u, loaded_.size()); - ASSERT_EQ(0u, GetErrors().size()); - - // Upgrade to version 2.0 - path = extensions_path.AppendASCII("good2.crx"); - service_->InstallExtension(path); - loop_.RunAllPending(); - - ASSERT_TRUE(installed_); - ASSERT_EQ(2u, loaded_.size()); - ASSERT_EQ(0u, GetErrors().size()); -} - -// Test upgrading a signed extension with a bad signature. -TEST_F(ExtensionsServiceTest, UpgradeSignedBad) { - FilePath extensions_path; - ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); - extensions_path = extensions_path.AppendASCII("extensions"); - - FilePath path = extensions_path.AppendASCII("good.crx"); - service_->InstallExtension(path); - loop_.RunAllPending(); - - ASSERT_TRUE(installed_); - ASSERT_EQ(1u, loaded_.size()); - ASSERT_EQ(0u, GetErrors().size()); - installed_ = NULL; - - // Try upgrading with a bad signature. This should fail during the unpack, - // because the key will not match the signature. - path = extensions_path.AppendASCII("good2_bad_signature.crx"); - service_->InstallExtension(path); - loop_.RunAllPending(); - - ASSERT_FALSE(installed_); - ASSERT_EQ(1u, loaded_.size()); - ASSERT_EQ(1u, GetErrors().size()); -} - // Tests uninstalling normal extensions TEST_F(ExtensionsServiceTest, UninstallExtension) { FilePath extensions_path; @@ -700,8 +656,6 @@ TEST_F(ExtensionsServiceTest, LoadExtension) { // Tests that we generate IDs when they are not specified in the manifest for // --load-extension. TEST_F(ExtensionsServiceTest, GenerateID) { - Extension::ResetGeneratedIdCounter(); - FilePath extensions_path; ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); extensions_path = extensions_path.AppendASCII("extensions"); @@ -743,7 +697,7 @@ TEST_F(ExtensionsServiceTest, ExternalInstallRegistry) { RegKey key; std::wstring reg_path = ASCIIToWide(registry_path_); - reg_path += L"\\b3dd733cd71a98fa83f387455e12f5c5501c519e"; + reg_path += L"\\00123456789ABCDEF0123456789ABCDEF0123456"; ASSERT_TRUE(key.Create(HKEY_LOCAL_MACHINE, reg_path.c_str(), KEY_WRITE)); ASSERT_TRUE(key.WriteValue(L"path", source_path.ToWStringHack().c_str())); ASSERT_TRUE(key.WriteValue(L"version", L"1.0.0.0")); |