summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrockot <rockot@chromium.org>2014-09-02 16:14:15 -0700
committerCommit bot <commit-bot@chromium.org>2014-09-02 23:17:04 +0000
commit43ae1fb32df63bfd42c13914feb6a71f111fccb3 (patch)
tree745ae3ec372d3d572668e27d9883b016409a4b31
parentb0b8648dc4298ee5cd46259bae0da66d04a631f9 (diff)
downloadchromium_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.cc66
-rw-r--r--chrome/browser/extensions/updater/extension_downloader.h4
-rw-r--r--chrome/browser/extensions/updater/extension_updater_unittest.cc32
-rw-r--r--chrome/browser/extensions/updater/manifest_fetch_data.cc16
-rw-r--r--chrome/browser/extensions/updater/manifest_fetch_data.h9
-rw-r--r--extensions/common/extension.cc36
-rw-r--r--extensions/common/extension.h7
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(), &params);
@@ -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(), &params);
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(), &params);
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(), &params);
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);
};