diff options
author | rockot <rockot@chromium.org> | 2014-09-02 16:14:15 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-09-02 23:17:04 +0000 |
commit | 43ae1fb32df63bfd42c13914feb6a71f111fccb3 (patch) | |
tree | 745ae3ec372d3d572668e27d9883b016409a4b31 | |
parent | b0b8648dc4298ee5cd46259bae0da66d04a631f9 (diff) | |
download | chromium_src-43ae1fb32df63bfd42c13914feb6a71f111fccb3.zip chromium_src-43ae1fb32df63bfd42c13914feb6a71f111fccb3.tar.gz chromium_src-43ae1fb32df63bfd42c13914feb6a71f111fccb3.tar.bz2 |
Enable forced extension updates on NaCl arch mismatch
This makes extensions aware of the platforms for which
they have platform-specific resources installed, if any.
This also hooks up the extension update code with some
additional logic to place an extension in forced-update
mode if it has platform-specific resources which don't
match the current NaCl architecture.
BUG=409948
TEST=install an extension which uses NaCl (QuickOffice for example). Rename the _platform-specific/<your-nacl-arch> directory some something else and force an update (e.g. via chrome://extensions button). Observe that a new CRX is downloaded and installed.
Review URL: https://codereview.chromium.org/516293007
Cr-Commit-Position: refs/heads/master@{#293018}
-rw-r--r-- | chrome/browser/extensions/updater/extension_downloader.cc | 66 | ||||
-rw-r--r-- | chrome/browser/extensions/updater/extension_downloader.h | 4 | ||||
-rw-r--r-- | chrome/browser/extensions/updater/extension_updater_unittest.cc | 32 | ||||
-rw-r--r-- | chrome/browser/extensions/updater/manifest_fetch_data.cc | 16 | ||||
-rw-r--r-- | chrome/browser/extensions/updater/manifest_fetch_data.h | 9 | ||||
-rw-r--r-- | extensions/common/extension.cc | 36 | ||||
-rw-r--r-- | extensions/common/extension.h | 7 |
7 files changed, 134 insertions, 36 deletions
diff --git a/chrome/browser/extensions/updater/extension_downloader.cc b/chrome/browser/extensions/updater/extension_downloader.cc index 264e461..d8f183c 100644 --- a/chrome/browser/extensions/updater/extension_downloader.cc +++ b/chrome/browser/extensions/updater/extension_downloader.cc @@ -28,6 +28,7 @@ #include "chrome/common/chrome_version_info.h" #include "chrome/common/extensions/extension_constants.h" #include "chrome/common/extensions/manifest_url_handler.h" +#include "components/omaha_query_params/omaha_query_params.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/notification_details.h" #include "content/public/browser/notification_service.h" @@ -44,6 +45,7 @@ using base::Time; using base::TimeDelta; using content::BrowserThread; +using omaha_query_params::OmahaQueryParams; namespace extensions { @@ -84,6 +86,7 @@ const int kMaxOAuth2Attempts = 3; const char kNotFromWebstoreInstallSource[] = "notfromwebstore"; const char kDefaultInstallSource[] = ""; +const char kWrongMultiCrxInstallSource[] = "wrong_multi_crx"; const char kGoogleDotCom[] = "google.com"; const char kTokenServiceConsumerId[] = "extension_downloader"; @@ -210,10 +213,24 @@ bool ExtensionDownloader::AddExtension(const Extension& extension, if (!ManifestURL::UpdatesFromGallery(&extension)) update_url_data = delegate_->GetUpdateUrlData(extension.id()); - return AddExtensionData(extension.id(), *extension.version(), + // If the browser's native architecture has changed since this extension was + // installed, we need to force an update. + bool force_update = false; + std::string install_source; + if (extension.HasPlatformSpecificResources() && + !extension.HasResourcesForPlatform(OmahaQueryParams::GetNaclArch())) { + force_update = true; + install_source = kWrongMultiCrxInstallSource; + } + + return AddExtensionData(extension.id(), + *extension.version(), extension.GetType(), ManifestURL::GetUpdateURL(&extension), - update_url_data, request_id); + update_url_data, + request_id, + force_update, + install_source); } bool ExtensionDownloader::AddPendingExtension(const std::string& id, @@ -230,7 +247,9 @@ bool ExtensionDownloader::AddPendingExtension(const std::string& id, Manifest::TYPE_UNKNOWN, update_url, std::string(), - request_id); + request_id, + false, + std::string()); } void ExtensionDownloader::StartAllPending(ExtensionCache* cache) { @@ -273,7 +292,8 @@ void ExtensionDownloader::StartBlacklistUpdate( version, &ping_data, std::string(), - kDefaultInstallSource); + kDefaultInstallSource, + false); StartUpdateCheck(blacklist_fetch.Pass()); } @@ -282,12 +302,15 @@ void ExtensionDownloader::SetWebstoreIdentityProvider( identity_provider_.swap(identity_provider); } -bool ExtensionDownloader::AddExtensionData(const std::string& id, - const Version& version, - Manifest::Type extension_type, - const GURL& extension_update_url, - const std::string& update_url_data, - int request_id) { +bool ExtensionDownloader::AddExtensionData( + const std::string& id, + const Version& version, + Manifest::Type extension_type, + const GURL& extension_update_url, + const std::string& update_url_data, + int request_id, + bool force_update, + const std::string& install_source_override) { GURL update_url(extension_update_url); // Skip extensions with non-empty invalid update URLs. if (!update_url.is_empty() && !update_url.is_valid()) { @@ -353,6 +376,9 @@ bool ExtensionDownloader::AddExtensionData(const std::string& id, std::string install_source = i == 0 ? kDefaultInstallSource : kNotFromWebstoreInstallSource; + if (!install_source_override.empty()) { + install_source = install_source_override; + } ManifestFetchData::PingData ping_data; ManifestFetchData::PingData* optional_ping_data = NULL; @@ -369,7 +395,8 @@ bool ExtensionDownloader::AddExtensionData(const std::string& id, ManifestFetchData* existing_fetch = existing_iter->second.back().get(); if (existing_fetch->AddExtension(id, version.GetString(), optional_ping_data, update_url_data, - install_source)) { + install_source, + force_update)) { added = true; } } @@ -383,7 +410,8 @@ bool ExtensionDownloader::AddExtensionData(const std::string& id, added = fetch->AddExtension(id, version.GetString(), optional_ping_data, update_url_data, - install_source); + install_source, + force_update); DCHECK(added); } } @@ -639,12 +667,14 @@ void ExtensionDownloader::DetermineUpdates( VLOG(2) << id << " is at '" << version << "'"; - Version existing_version(version); - Version update_version(update->version); - - if (!update_version.IsValid() || - update_version.CompareTo(existing_version) <= 0) { - continue; + // We should skip the version check if update was forced. + if (!fetch_data.DidForceUpdate(id)) { + Version existing_version(version); + Version update_version(update->version); + if (!update_version.IsValid() || + update_version.CompareTo(existing_version) <= 0) { + continue; + } } } diff --git a/chrome/browser/extensions/updater/extension_downloader.h b/chrome/browser/extensions/updater/extension_downloader.h index a040986..813a400 100644 --- a/chrome/browser/extensions/updater/extension_downloader.h +++ b/chrome/browser/extensions/updater/extension_downloader.h @@ -166,7 +166,9 @@ class ExtensionDownloader Manifest::Type extension_type, const GURL& extension_update_url, const std::string& update_url_data, - int request_id); + int request_id, + bool force_update, + const std::string& install_source_override); // Adds all recorded stats taken so far to histogram counts. void ReportStats() const; diff --git a/chrome/browser/extensions/updater/extension_updater_unittest.cc b/chrome/browser/extensions/updater/extension_updater_unittest.cc index 4a7375f..526b5a8 100644 --- a/chrome/browser/extensions/updater/extension_updater_unittest.cc +++ b/chrome/browser/extensions/updater/extension_updater_unittest.cc @@ -703,7 +703,7 @@ class ExtensionUpdaterTest : public testing::Test { // option to appear in the x= parameter. ManifestFetchData fetch_data(GURL("http://localhost/foo"), 0); fetch_data.AddExtension( - id, version, &kNeverPingedData, std::string(), std::string()); + id, version, &kNeverPingedData, std::string(), std::string(), false); std::map<std::string, std::string> params; VerifyQueryAndExtractParameters(fetch_data.full_url().query(), ¶ms); @@ -720,7 +720,7 @@ class ExtensionUpdaterTest : public testing::Test { // option to appear in the x= parameter. ManifestFetchData fetch_data(GURL("http://localhost/foo"), 0); fetch_data.AddExtension( - id, version, &kNeverPingedData, "bar", std::string()); + id, version, &kNeverPingedData, "bar", std::string(), false); std::map<std::string, std::string> params; VerifyQueryAndExtractParameters(fetch_data.full_url().query(), ¶ms); EXPECT_EQ(id, params["id"]); @@ -736,7 +736,7 @@ class ExtensionUpdaterTest : public testing::Test { // option to appear in the x= parameter. ManifestFetchData fetch_data(GURL("http://localhost/foo"), 0); fetch_data.AddExtension( - id, version, &kNeverPingedData, "a=1&b=2&c", std::string()); + id, version, &kNeverPingedData, "a=1&b=2&c", std::string(), false); std::map<std::string, std::string> params; VerifyQueryAndExtractParameters(fetch_data.full_url().query(), ¶ms); EXPECT_EQ(id, params["id"]); @@ -780,7 +780,7 @@ class ExtensionUpdaterTest : public testing::Test { // Make sure that an installsource= appears in the x= parameter. ManifestFetchData fetch_data(GURL("http://localhost/foo"), 0); fetch_data.AddExtension(id, version, &kNeverPingedData, - kEmptyUpdateUrlData, install_source); + kEmptyUpdateUrlData, install_source, false); std::map<std::string, std::string> params; VerifyQueryAndExtractParameters(fetch_data.full_url().query(), ¶ms); EXPECT_EQ(id, params["id"]); @@ -806,10 +806,12 @@ class ExtensionUpdaterTest : public testing::Test { const std::string id1 = crx_file::id_util::GenerateId("1"); const std::string id2 = crx_file::id_util::GenerateId("2"); fetch_data.AddExtension( - id1, "1.0.0.0", &kNeverPingedData, kEmptyUpdateUrlData, std::string()); + id1, "1.0.0.0", &kNeverPingedData, kEmptyUpdateUrlData, std::string(), + false); AddParseResult(id1, "1.1", "http://localhost/e1_1.1.crx", &updates); fetch_data.AddExtension( - id2, "2.0.0.0", &kNeverPingedData, kEmptyUpdateUrlData, std::string()); + id2, "2.0.0.0", &kNeverPingedData, kEmptyUpdateUrlData, std::string(), + false); AddParseResult(id2, "2.0.0.0", "http://localhost/e2_2.0.crx", &updates); EXPECT_CALL(delegate, IsExtensionPending(_)).WillRepeatedly(Return(false)); @@ -850,7 +852,8 @@ class ExtensionUpdaterTest : public testing::Test { "1.0.0.0", &kNeverPingedData, kEmptyUpdateUrlData, - std::string()); + std::string(), + false); AddParseResult(*it, "1.1", "http://localhost/e1_1.1.crx", &updates); } @@ -884,13 +887,13 @@ class ExtensionUpdaterTest : public testing::Test { scoped_ptr<ManifestFetchData> fetch4(new ManifestFetchData(kUpdateUrl, 0)); ManifestFetchData::PingData zeroDays(0, 0, true); fetch1->AddExtension( - "1111", "1.0", &zeroDays, kEmptyUpdateUrlData, std::string()); + "1111", "1.0", &zeroDays, kEmptyUpdateUrlData, std::string(), false); fetch2->AddExtension( - "2222", "2.0", &zeroDays, kEmptyUpdateUrlData, std::string()); + "2222", "2.0", &zeroDays, kEmptyUpdateUrlData, std::string(), false); fetch3->AddExtension( - "3333", "3.0", &zeroDays, kEmptyUpdateUrlData, std::string()); + "3333", "3.0", &zeroDays, kEmptyUpdateUrlData, std::string(), false); fetch4->AddExtension( - "4444", "4.0", &zeroDays, kEmptyUpdateUrlData, std::string()); + "4444", "4.0", &zeroDays, kEmptyUpdateUrlData, std::string(), false); // This will start the first fetcher and queue the others. The next in queue // is started as each fetcher receives its response. Note that the fetchers @@ -1021,7 +1024,7 @@ class ExtensionUpdaterTest : public testing::Test { scoped_ptr<ManifestFetchData> fetch(new ManifestFetchData(kUpdateUrl, 0)); ManifestFetchData::PingData zeroDays(0, 0, true); fetch->AddExtension( - "1111", "1.0", &zeroDays, kEmptyUpdateUrlData, std::string()); + "1111", "1.0", &zeroDays, kEmptyUpdateUrlData, std::string(), false); // This will start the first fetcher. downloader.StartUpdateCheck(fetch.Pass()); @@ -1049,7 +1052,7 @@ class ExtensionUpdaterTest : public testing::Test { // should not retry. fetch.reset(new ManifestFetchData(kUpdateUrl, 0)); fetch->AddExtension( - "1111", "1.0", &zeroDays, kEmptyUpdateUrlData, std::string()); + "1111", "1.0", &zeroDays, kEmptyUpdateUrlData, std::string(), false); // This will start the first fetcher. downloader.StartUpdateCheck(fetch.Pass()); @@ -1707,7 +1710,8 @@ class ExtensionUpdaterTest : public testing::Test { extension->VersionString(), &kNeverPingedData, kEmptyUpdateUrlData, - std::string()); + std::string(), + false); UpdateManifest::Results results; results.daystart_elapsed_seconds = 750; diff --git a/chrome/browser/extensions/updater/manifest_fetch_data.cc b/chrome/browser/extensions/updater/manifest_fetch_data.cc index 8ed4fe0..dafbdf8 100644 --- a/chrome/browser/extensions/updater/manifest_fetch_data.cc +++ b/chrome/browser/extensions/updater/manifest_fetch_data.cc @@ -67,16 +67,24 @@ bool ManifestFetchData::AddExtension(const std::string& id, const std::string& version, const PingData* ping_data, const std::string& update_url_data, - const std::string& install_source) { + const std::string& install_source, + bool force_update) { if (extension_ids_.find(id) != extension_ids_.end()) { NOTREACHED() << "Duplicate extension id " << id; return false; } + if (force_update) + forced_updates_.insert(id); + + // If we want to force an update, we send 0.0.0.0 as the installed version + // number. + const std::string installed_version = force_update ? "0.0.0.0" : version; + // Compute the string we'd append onto the full_url_, and see if it fits. std::vector<std::string> parts; parts.push_back("id=" + id); - parts.push_back("v=" + version); + parts.push_back("v=" + installed_version); if (!install_source.empty()) parts.push_back("installsource=" + install_source); parts.push_back("uc"); @@ -163,4 +171,8 @@ void ManifestFetchData::Merge(const ManifestFetchData& other) { request_ids_.insert(other.request_ids_.begin(), other.request_ids_.end()); } +bool ManifestFetchData::DidForceUpdate(const std::string& extension_id) const { + return forced_updates_.find(extension_id) != forced_updates_.end(); +} + } // namespace extensions diff --git a/chrome/browser/extensions/updater/manifest_fetch_data.h b/chrome/browser/extensions/updater/manifest_fetch_data.h index a7eab99..36a77c8 100644 --- a/chrome/browser/extensions/updater/manifest_fetch_data.h +++ b/chrome/browser/extensions/updater/manifest_fetch_data.h @@ -56,7 +56,8 @@ class ManifestFetchData { const std::string& version, const PingData* ping_data, const std::string& update_url_data, - const std::string& install_source); + const std::string& install_source, + bool force_update); const GURL& base_url() const { return base_url_; } const GURL& full_url() const { return full_url_; } @@ -76,6 +77,9 @@ class ManifestFetchData { // to this ManifestFetchData). void Merge(const ManifestFetchData& other); + // Returns |true| if a given extension was forced to update. + bool DidForceUpdate(const std::string& extension_id) const; + private: // The set of extension id's for this ManifestFetchData. std::set<std::string> extension_ids_; @@ -96,6 +100,9 @@ class ManifestFetchData { // one ManifestFetchData. std::set<int> request_ids_; + // The set of extension IDs for which this fetch forced a CRX update. + std::set<std::string> forced_updates_; + DISALLOW_COPY_AND_ASSIGN(ManifestFetchData); }; diff --git a/extensions/common/extension.cc b/extensions/common/extension.cc index d8e798e..a671cd1 100644 --- a/extensions/common/extension.cc +++ b/extensions/common/extension.cc @@ -4,10 +4,14 @@ #include "extensions/common/extension.h" +#include <algorithm> + #include "base/base64.h" #include "base/basictypes.h" #include "base/command_line.h" +#include "base/files/file_enumerator.h" #include "base/files/file_path.h" +#include "base/files/file_util.h" #include "base/i18n/rtl.h" #include "base/logging.h" #include "base/memory/singleton.h" @@ -65,6 +69,26 @@ bool ContainsReservedCharacters(const base::FilePath& path) { return !net::IsSafePortableRelativePath(path); } +void CollectPlatformSpecificResourceArchs(const base::FilePath& extension_path, + std::set<std::string>* archs) { + archs->clear(); + base::FilePath platform_specific_path = extension_path.Append( + kPlatformSpecificFolder); + if (!base::PathExists(platform_specific_path)) { + return; + } + + base::FileEnumerator all_archs(platform_specific_path, + false, + base::FileEnumerator::DIRECTORIES); + base::FilePath arch; + while (!(arch = all_archs.Next()).empty()) { + std::string arch_name = arch.BaseName().AsUTF8Unsafe(); + std::replace(arch_name.begin(), arch_name.end(), '_', '-'); + archs->insert(arch_name); + } +} + } // namespace const int Extension::kInitFromValueFlagBits = 13; @@ -435,6 +459,15 @@ void Extension::AddWebExtentPattern(const URLPattern& pattern) { extent_.AddPattern(pattern); } +bool Extension::HasPlatformSpecificResources() const { + return !platform_specific_resource_archs_.empty(); +} + +bool Extension::HasResourcesForPlatform(const std::string& arch) const { + return platform_specific_resource_archs_.find(arch) != + platform_specific_resource_archs_.end(); +} + // static bool Extension::InitExtensionID(extensions::Manifest* manifest, const base::FilePath& path, @@ -536,6 +569,9 @@ bool Extension::InitFromValue(int flags, base::string16* error) { permissions_data_.reset(new PermissionsData(this)); + CollectPlatformSpecificResourceArchs(path_, + &platform_specific_resource_archs_); + return true; } diff --git a/extensions/common/extension.h b/extensions/common/extension.h index 668f52f..9312c62 100644 --- a/extensions/common/extension.h +++ b/extensions/common/extension.h @@ -351,6 +351,9 @@ class Extension : public base::RefCountedThreadSafe<Extension> { void AddWebExtentPattern(const URLPattern& pattern); const URLPatternSet& web_extent() const { return extent_; } + bool HasPlatformSpecificResources() const; + bool HasResourcesForPlatform(const std::string& arch) const; + private: friend class base::RefCountedThreadSafe<Extension>; @@ -480,6 +483,10 @@ class Extension : public base::RefCountedThreadSafe<Extension> { // The flags that were passed to InitFromValue. int creation_flags_; + // The set of archs for which platform-specific resources are present in + // this extension installation. + std::set<std::string> platform_specific_resource_archs_; + DISALLOW_COPY_AND_ASSIGN(Extension); }; |