summaryrefslogtreecommitdiff
path: root/chromium/extensions/browser/updater
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/extensions/browser/updater')
-rw-r--r--chromium/extensions/browser/updater/extension_cache_fake.cc9
-rw-r--r--chromium/extensions/browser/updater/extension_downloader.cc295
-rw-r--r--chromium/extensions/browser/updater/extension_downloader.h80
-rw-r--r--chromium/extensions/browser/updater/extension_downloader_delegate.cc4
-rw-r--r--chromium/extensions/browser/updater/extension_downloader_delegate.h16
-rw-r--r--chromium/extensions/browser/updater/extension_installer.cc4
-rw-r--r--chromium/extensions/browser/updater/manifest_fetch_data.cc82
-rw-r--r--chromium/extensions/browser/updater/manifest_fetch_data.h46
-rw-r--r--chromium/extensions/browser/updater/update_data_provider.cc26
-rw-r--r--chromium/extensions/browser/updater/update_service.cc15
-rw-r--r--chromium/extensions/browser/updater/update_service_unittest.cc30
11 files changed, 467 insertions, 140 deletions
diff --git a/chromium/extensions/browser/updater/extension_cache_fake.cc b/chromium/extensions/browser/updater/extension_cache_fake.cc
index 5425a994477..3275bb13ff7 100644
--- a/chromium/extensions/browser/updater/extension_cache_fake.cc
+++ b/chromium/extensions/browser/updater/extension_cache_fake.cc
@@ -6,7 +6,6 @@
#include "base/bind.h"
#include "base/stl_util.h"
-#include "base/task/post_task.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
@@ -17,11 +16,11 @@ ExtensionCacheFake::ExtensionCacheFake() = default;
ExtensionCacheFake::~ExtensionCacheFake() = default;
void ExtensionCacheFake::Start(const base::Closure& callback) {
- base::PostTask(FROM_HERE, {content::BrowserThread::UI}, callback);
+ content::GetUIThreadTaskRunner({})->PostTask(FROM_HERE, callback);
}
void ExtensionCacheFake::Shutdown(const base::Closure& callback) {
- base::PostTask(FROM_HERE, {content::BrowserThread::UI}, callback);
+ content::GetUIThreadTaskRunner({})->PostTask(FROM_HERE, callback);
}
void ExtensionCacheFake::AllowCaching(const std::string& id) {
@@ -52,8 +51,8 @@ void ExtensionCacheFake::PutExtension(const std::string& id,
if (base::Contains(allowed_extensions_, id)) {
cache_[id].first = version;
cache_[id].second = file_path;
- base::PostTask(FROM_HERE, {content::BrowserThread::UI},
- base::BindOnce(callback, file_path, false));
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(callback, file_path, false));
} else {
callback.Run(file_path, true);
}
diff --git a/chromium/extensions/browser/updater/extension_downloader.cc b/chromium/extensions/browser/updater/extension_downloader.cc
index 2806def0117..a8c378d4d6b 100644
--- a/chromium/extensions/browser/updater/extension_downloader.cc
+++ b/chromium/extensions/browser/updater/extension_downloader.cc
@@ -134,6 +134,10 @@ bool ShouldRetryRequest(const network::SimpleURLLoader* loader) {
return response_code >= 500 && response_code < 600;
}
+bool ShouldRetryRequestForExtensionNotFoundInCache(const int net_error_code) {
+ return net_error_code == net::ERR_INTERNET_DISCONNECTED;
+}
+
// This parses and updates a URL query such that the value of the |authuser|
// query parameter is incremented by 1. If parameter was not present in the URL,
// it will be added with a value of 1. All other query keys and values are
@@ -203,6 +207,27 @@ ExtensionDownloader::ExtensionFetch::ExtensionFetch(
ExtensionDownloader::ExtensionFetch::~ExtensionFetch() = default;
+ExtensionDownloader::FetchDataGroupKey::FetchDataGroupKey() = default;
+
+ExtensionDownloader::FetchDataGroupKey::FetchDataGroupKey(
+ const FetchDataGroupKey& other) = default;
+
+ExtensionDownloader::FetchDataGroupKey::FetchDataGroupKey(
+ const int request_id,
+ const GURL& update_url,
+ const bool is_force_installed)
+ : request_id(request_id),
+ update_url(update_url),
+ is_force_installed(is_force_installed) {}
+
+ExtensionDownloader::FetchDataGroupKey::~FetchDataGroupKey() = default;
+
+bool ExtensionDownloader::FetchDataGroupKey::operator<(
+ const FetchDataGroupKey& other) const {
+ return std::tie(request_id, update_url, is_force_installed) <
+ std::tie(other.request_id, other.update_url, other.is_force_installed);
+}
+
ExtensionDownloader::ExtraParams::ExtraParams() : is_corrupt_reinstall(false) {}
ExtensionDownloader::ExtensionDownloader(
@@ -324,6 +349,11 @@ void ExtensionDownloader::set_test_delegate(
g_test_delegate = delegate;
}
+void ExtensionDownloader::SetBackoffPolicyForTesting(
+ const net::BackoffEntry::Policy* backoff_policy) {
+ manifests_queue_.set_backoff_policy(backoff_policy);
+}
+
bool ExtensionDownloader::AddExtensionData(
const std::string& id,
const base::Version& version,
@@ -403,8 +433,11 @@ bool ExtensionDownloader::AddExtensionData(
// Find or create a ManifestFetchData to add this extension to.
bool added = false;
- auto existing_iter =
- fetches_preparing_.find(std::make_pair(request_id, update_url));
+ bool is_new_extension_force_installed =
+ extension_location == Manifest::Location::EXTERNAL_POLICY_DOWNLOAD;
+ FetchDataGroupKey key(request_id, update_url,
+ is_new_extension_force_installed);
+ auto existing_iter = fetches_preparing_.find(key);
if (existing_iter != fetches_preparing_.end() &&
!existing_iter->second.empty()) {
// Try to add to the ManifestFetchData at the end of the list.
@@ -421,8 +454,9 @@ bool ExtensionDownloader::AddExtensionData(
std::unique_ptr<ManifestFetchData> fetch(
CreateManifestFetchData(update_url, request_id, fetch_priority));
ManifestFetchData* fetch_ptr = fetch.get();
- fetches_preparing_[std::make_pair(request_id, update_url)].push_back(
- std::move(fetch));
+ if (is_new_extension_force_installed)
+ fetch_ptr->set_is_all_external_policy_download();
+ fetches_preparing_[key].push_back(std::move(fetch));
added = fetch_ptr->AddExtension(id, version.GetString(), optional_ping_data,
extra.update_url_data, install_source,
extension_location, fetch_priority);
@@ -456,13 +490,12 @@ void ExtensionDownloader::StartUpdateCheck(
g_test_delegate->StartUpdateCheck(this, delegate_, std::move(fetch_data));
return;
}
-
+ const ExtensionIdSet extension_ids = fetch_data->GetExtensionIds();
if (!ExtensionsBrowserClient::Get()->IsBackgroundUpdateAllowed()) {
NotifyExtensionsDownloadStageChanged(
- fetch_data->extension_ids(),
- ExtensionDownloaderDelegate::Stage::FINISHED);
+ extension_ids, ExtensionDownloaderDelegate::Stage::FINISHED);
NotifyExtensionsDownloadFailed(
- fetch_data->extension_ids(), fetch_data->request_ids(),
+ extension_ids, fetch_data->request_ids(),
ExtensionDownloaderDelegate::Error::DISABLED);
return;
}
@@ -472,7 +505,7 @@ void ExtensionDownloader::StartUpdateCheck(
if (fetch_data->full_url() == i->full_url()) {
// This url is already scheduled to be fetched.
NotifyExtensionsDownloadStageChanged(
- fetch_data->extension_ids(),
+ extension_ids,
ExtensionDownloaderDelegate::Stage::QUEUED_FOR_MANIFEST);
i->Merge(*fetch_data);
return;
@@ -482,7 +515,7 @@ void ExtensionDownloader::StartUpdateCheck(
if (manifests_queue_.active_request() &&
manifests_queue_.active_request()->full_url() == fetch_data->full_url()) {
NotifyExtensionsDownloadStageChanged(
- fetch_data->extension_ids(),
+ extension_ids,
ExtensionDownloaderDelegate::Stage::DOWNLOADING_MANIFEST);
manifests_queue_.active_request()->Merge(*fetch_data);
} else {
@@ -491,8 +524,7 @@ void ExtensionDownloader::StartUpdateCheck(
fetch_data->full_url().possibly_invalid_spec().length());
NotifyExtensionsDownloadStageChanged(
- fetch_data->extension_ids(),
- ExtensionDownloaderDelegate::Stage::QUEUED_FOR_MANIFEST);
+ extension_ids, ExtensionDownloaderDelegate::Stage::QUEUED_FOR_MANIFEST);
manifests_queue_.ScheduleRequest(std::move(fetch_data));
}
}
@@ -515,12 +547,11 @@ network::mojom::URLLoaderFactory* ExtensionDownloader::GetURLLoaderFactoryToUse(
void ExtensionDownloader::CreateManifestLoader() {
const ManifestFetchData* active_request = manifests_queue_.active_request();
+ const ExtensionIdSet extension_ids = active_request->GetExtensionIds();
NotifyExtensionsDownloadStageChanged(
- active_request->extension_ids(),
- ExtensionDownloaderDelegate::Stage::DOWNLOADING_MANIFEST);
- std::vector<base::StringPiece> id_vector(
- active_request->extension_ids().begin(),
- active_request->extension_ids().end());
+ extension_ids, ExtensionDownloaderDelegate::Stage::DOWNLOADING_MANIFEST);
+ std::vector<base::StringPiece> id_vector(extension_ids.begin(),
+ extension_ids.end());
std::string id_list = base::JoinString(id_vector, ",");
VLOG(2) << "Fetching " << active_request->full_url() << " for " << id_list;
VLOG(2) << "Update interactivity: "
@@ -605,10 +636,132 @@ void ExtensionDownloader::CreateManifestLoader() {
base::Unretained(this)));
}
+void ExtensionDownloader::RetryManifestFetchRequest() {
+ constexpr base::TimeDelta backoff_delay;
+ NotifyExtensionsDownloadStageChanged(
+ manifests_queue_.active_request()->GetExtensionIds(),
+ ExtensionDownloaderDelegate::Stage::DOWNLOADING_MANIFEST_RETRY);
+ manifests_queue_.RetryRequest(backoff_delay);
+}
+
+void ExtensionDownloader::ReportManifestFetchFailure(
+ ManifestFetchData* fetch_data,
+ ExtensionDownloaderDelegate::Error error,
+ const ExtensionDownloaderDelegate::FailureData& data) {
+ const ExtensionIdSet extension_ids = fetch_data->GetExtensionIds();
+ NotifyExtensionsDownloadStageChanged(
+ extension_ids, ExtensionDownloaderDelegate::Stage::FINISHED);
+ NotifyExtensionsDownloadFailedWithFailureData(
+ extension_ids, fetch_data->request_ids(), error, data);
+}
+
+void ExtensionDownloader::TryFetchingExtensionsFromCache(
+ ManifestFetchData* fetch_data,
+ ExtensionDownloaderDelegate::Error error,
+ const int net_error,
+ const int response_code,
+ const base::Optional<ManifestInvalidErrorList>& manifest_invalid_errors) {
+ const ExtensionIdSet extension_ids = fetch_data->GetExtensionIds();
+ ExtensionIdSet extensions_fetched_from_cache;
+ for (const auto& extension_id : extension_ids) {
+ // Extension is fetched here only in cases when we fail to fetch the update
+ // manifest or parsing of update manifest failed. In such cases, we don't
+ // have expected version and expected hash. Thus, passing empty hash and
+ // version would not be a problem as we only check for the expected hash and
+ // version if we have them.
+ auto extension_fetch_data(std::make_unique<ExtensionFetch>(
+ extension_id, fetch_data->base_url(), /*hash not fetched*/ "",
+ /*version not fetched*/ "", fetch_data->request_ids()));
+ base::Optional<base::FilePath> cached_crx_path = GetCachedExtension(
+ *extension_fetch_data, /*manifest_fetch_failed*/ true);
+ if (cached_crx_path) {
+ delegate_->OnExtensionDownloadStageChanged(
+ extension_id, ExtensionDownloaderDelegate::Stage::FINISHED);
+ NotifyDelegateDownloadFinished(std::move(extension_fetch_data), true,
+ cached_crx_path.value(), false);
+ extensions_fetched_from_cache.insert(extension_id);
+ }
+ }
+ // All the extensions were found in the cache, no need to retry any request or
+ // report failure.
+ if (extensions_fetched_from_cache.size() == extension_ids.size())
+ return;
+ fetch_data->RemoveExtensions(extensions_fetched_from_cache,
+ manifest_query_params_);
+
+ if (ShouldRetryRequestForExtensionNotFoundInCache(net_error)) {
+ RetryManifestFetchRequest();
+ return;
+ }
+ if (error == ExtensionDownloaderDelegate::Error::MANIFEST_FETCH_FAILED) {
+ ExtensionDownloaderDelegate::FailureData failure_data(
+ -net_error,
+ response_code > 0 ? base::Optional<int>(response_code) : base::nullopt,
+ manifests_queue_.active_request_failure_count());
+ ReportManifestFetchFailure(fetch_data, error, failure_data);
+ return;
+ }
+ DCHECK(manifest_invalid_errors);
+ ManifestInvalidErrorList errors_for_remaining_extensions;
+ for (const auto& manifest_invalid_error : manifest_invalid_errors.value()) {
+ if (!extensions_fetched_from_cache.count(manifest_invalid_error.first))
+ errors_for_remaining_extensions.push_back(manifest_invalid_error);
+ }
+ NotifyExtensionsDownloadStageChanged(
+ fetch_data->GetExtensionIds(),
+ ExtensionDownloaderDelegate::Stage::FINISHED);
+ NotifyExtensionsManifestInvalidFailure(errors_for_remaining_extensions,
+ fetch_data->request_ids());
+}
+
+void ExtensionDownloader::RetryRequestOrHandleFailureOnManifestFetchFailure(
+ const network::SimpleURLLoader* loader,
+ const int response_code) {
+ bool all_force_installed_extensions =
+ manifests_queue_.active_request()->is_all_external_policy_download();
+
+ const int net_error = manifest_loader_->NetError();
+ const int request_failure_count =
+ manifests_queue_.active_request_failure_count();
+ // If the device is offline, do not retry for force installed extensions,
+ // try installing it from cache. Try fetching from cache only on first attempt
+ // in this case, because we will retry the request only if there was no entry
+ // in cache corresponding to this extension and there is no point in trying to
+ // fetch extension from cache again.
+ if (net_error == net::ERR_INTERNET_DISCONNECTED &&
+ all_force_installed_extensions && request_failure_count == 0) {
+ TryFetchingExtensionsFromCache(
+ manifests_queue_.active_request(),
+ ExtensionDownloaderDelegate::Error::MANIFEST_FETCH_FAILED, net_error,
+ response_code, base::nullopt /*manifest_invalid_errors*/);
+ return;
+ }
+ if (ShouldRetryRequest(loader) && request_failure_count < kMaxRetries) {
+ RetryManifestFetchRequest();
+ return;
+ }
+ const GURL url = loader->GetFinalURL();
+ RETRY_HISTOGRAM("ManifestFetchFailure", request_failure_count, url);
+ if (all_force_installed_extensions) {
+ TryFetchingExtensionsFromCache(
+ manifests_queue_.active_request(),
+ ExtensionDownloaderDelegate::Error::MANIFEST_FETCH_FAILED, net_error,
+ response_code, base::nullopt /*manifest_invalid_errors*/);
+ } else {
+ ExtensionDownloaderDelegate::FailureData failure_data(
+ -net_error,
+ response_code > 0 ? base::Optional<int>(response_code) : base::nullopt,
+ request_failure_count);
+ ReportManifestFetchFailure(
+ manifests_queue_.active_request(),
+ ExtensionDownloaderDelegate::Error::MANIFEST_FETCH_FAILED,
+ failure_data);
+ }
+}
+
void ExtensionDownloader::OnManifestLoadComplete(
std::unique_ptr<std::string> response_body) {
const GURL url = manifest_loader_->GetFinalURL();
- int net_error = manifest_loader_->NetError();
DCHECK(manifests_queue_.active_request());
int response_code = -1;
@@ -618,7 +771,6 @@ void ExtensionDownloader::OnManifestLoadComplete(
VLOG(2) << response_code << " " << url;
- const base::TimeDelta& backoff_delay = base::TimeDelta::FromMilliseconds(0);
const int request_failure_count =
manifests_queue_.active_request_failure_count();
@@ -628,7 +780,7 @@ void ExtensionDownloader::OnManifestLoadComplete(
RETRY_HISTOGRAM("ManifestFetchSuccess", request_failure_count, url);
VLOG(2) << "beginning manifest parse for " << url;
NotifyExtensionsDownloadStageChanged(
- manifests_queue_.active_request()->extension_ids(),
+ manifests_queue_.active_request()->GetExtensionIds(),
ExtensionDownloaderDelegate::Stage::PARSING_MANIFEST);
auto callback = base::BindOnce(&ExtensionDownloader::HandleManifestResults,
weak_ptr_factory_.GetWeakPtr(),
@@ -637,30 +789,8 @@ void ExtensionDownloader::OnManifestLoadComplete(
} else {
VLOG(1) << "Failed to fetch manifest '" << url.possibly_invalid_spec()
<< "' response code:" << response_code;
- const auto* loader = manifest_loader_.get();
- if (ShouldRetryRequest(loader) && request_failure_count < kMaxRetries) {
- NotifyExtensionsDownloadStageChanged(
- manifests_queue_.active_request()->extension_ids(),
- ExtensionDownloaderDelegate::Stage::DOWNLOADING_MANIFEST_RETRY);
- manifests_queue_.RetryRequest(backoff_delay);
- } else {
- RETRY_HISTOGRAM("ManifestFetchFailure",
- manifests_queue_.active_request_failure_count(),
- url);
- NotifyExtensionsDownloadStageChanged(
- manifests_queue_.active_request()->extension_ids(),
- ExtensionDownloaderDelegate::Stage::FINISHED);
- ExtensionDownloaderDelegate::FailureData failure_data(
- -net_error,
- response_code > 0 ? base::Optional<int>(response_code)
- : base::nullopt,
- manifests_queue_.active_request_failure_count());
- NotifyExtensionsDownloadFailedWithFailureData(
- manifests_queue_.active_request()->extension_ids(),
- manifests_queue_.active_request()->request_ids(),
- ExtensionDownloaderDelegate::Error::MANIFEST_FETCH_FAILED,
- failure_data);
- }
+ RetryRequestOrHandleFailureOnManifestFetchFailure(manifest_loader_.get(),
+ response_code);
}
manifest_loader_.reset();
file_url_loader_factory_.reset();
@@ -678,18 +808,17 @@ void ExtensionDownloader::HandleManifestResults(
VLOG(2) << "parsing manifest failed (" << fetch_data->full_url() << ")";
DCHECK(error.has_value());
ManifestInvalidErrorList manifest_invalid_errors;
- manifest_invalid_errors.reserve(fetch_data->extension_ids().size());
+ const ExtensionIdSet extension_ids = fetch_data->GetExtensionIds();
+ manifest_invalid_errors.reserve(extension_ids.size());
// If the manifest parsing failed for all the extensions with a common
// error, add all extensions in the list with that error.
- for (const auto& extension_id : fetch_data->extension_ids()) {
+ for (const auto& extension_id : extension_ids) {
manifest_invalid_errors.push_back(
std::make_pair(extension_id, error.value().error));
}
- NotifyExtensionsDownloadStageChanged(
- fetch_data->extension_ids(),
- ExtensionDownloaderDelegate::Stage::FINISHED);
- NotifyExtensionsManifestInvalidFailure(manifest_invalid_errors,
- fetch_data->request_ids());
+ TryFetchingExtensionsFromCache(
+ fetch_data.get(), ExtensionDownloaderDelegate::Error::MANIFEST_INVALID,
+ 0 /*net_error_code*/, 0 /*response_code*/, manifest_invalid_errors);
return;
} else {
VLOG(2) << "parsing manifest succeeded (" << fetch_data->full_url() << ")";
@@ -698,9 +827,9 @@ void ExtensionDownloader::HandleManifestResults(
// Report manifest update check status.
NotifyExtensionManifestUpdateCheckStatus(results->update_list);
+ const ExtensionIdSet extension_ids = fetch_data->GetExtensionIds();
NotifyExtensionsDownloadStageChanged(
- fetch_data->extension_ids(),
- ExtensionDownloaderDelegate::Stage::MANIFEST_LOADED);
+ extension_ids, ExtensionDownloaderDelegate::Stage::MANIFEST_LOADED);
std::vector<UpdateManifestResult*> to_update;
std::set<std::string> no_updates;
@@ -713,9 +842,14 @@ void ExtensionDownloader::HandleManifestResults(
GURL crx_url = update->crx_url;
NotifyUpdateFound(extension_id, update->version);
+ if (fetch_data->is_all_external_policy_download() && crx_url.is_empty()) {
+ DCHECK_EQ(fetch_data->fetch_priority(),
+ ManifestFetchData::FetchPriority::FOREGROUND);
+ }
FetchUpdatedExtension(std::make_unique<ExtensionFetch>(
- update->extension_id, crx_url, update->package_hash, update->version,
- fetch_data->request_ids()));
+ extension_id, crx_url, update->package_hash,
+ update->version, fetch_data->request_ids()),
+ update->info);
}
// If the manifest response included a <daystart> element, we want to save
@@ -725,7 +859,7 @@ void ExtensionDownloader::HandleManifestResults(
Time day_start =
Time::Now() - TimeDelta::FromSeconds(results->daystart_elapsed_seconds);
- for (const std::string& id : fetch_data->extension_ids()) {
+ for (const ExtensionId& id : extension_ids) {
ExtensionDownloaderDelegate::PingResult& result = ping_results_[id];
result.did_ping = fetch_data->DidPing(id, ManifestFetchData::ROLLCALL);
result.day_start = day_start;
@@ -843,9 +977,10 @@ void ExtensionDownloader::DetermineUpdates(
// are already inserted into |errors|.
ExtensionIdSet extension_errors;
+ const ExtensionIdSet extension_ids = fetch_data.GetExtensionIds();
// For each extensions in the current batch, greedily find an update from
// |possible_updates|.
- for (const std::string& extension_id : fetch_data.extension_ids()) {
+ for (const auto& extension_id : extension_ids) {
const auto it = update_groups.find(extension_id);
if (it == update_groups.end()) {
VLOG(2) << "Manifest doesn't have an update entry for " << extension_id;
@@ -893,7 +1028,8 @@ void ExtensionDownloader::DetermineUpdates(
}
base::Optional<base::FilePath> ExtensionDownloader::GetCachedExtension(
- const ExtensionFetch& fetch_data) {
+ const ExtensionFetch& fetch_data,
+ bool manifest_fetch_failed) {
if (!extension_cache_) {
delegate_->OnExtensionDownloadCacheStatusRetrieved(
fetch_data.id,
@@ -908,8 +1044,9 @@ base::Optional<base::FilePath> ExtensionDownloader::GetCachedExtension(
fetch_data.id, ExtensionDownloaderDelegate::CacheStatus::CACHE_MISS);
return base::nullopt;
}
-
- if (version != fetch_data.version) {
+ // If manifest fetch is failed, we need not verify the version of the cache as
+ // we will try to install the version present in the cache.
+ if (!manifest_fetch_failed && version != fetch_data.version) {
delegate_->OnExtensionDownloadCacheStatusRetrieved(
fetch_data.id,
ExtensionDownloaderDelegate::CacheStatus::CACHE_OUTDATED);
@@ -917,7 +1054,10 @@ base::Optional<base::FilePath> ExtensionDownloader::GetCachedExtension(
}
delegate_->OnExtensionDownloadCacheStatusRetrieved(
- fetch_data.id, ExtensionDownloaderDelegate::CacheStatus::CACHE_HIT);
+ fetch_data.id, manifest_fetch_failed
+ ? ExtensionDownloaderDelegate::CacheStatus::
+ CACHE_HIT_ON_MANIFEST_FETCH_FAILURE
+ : ExtensionDownloaderDelegate::CacheStatus::CACHE_HIT);
base::FilePath crx_path;
// Now get .crx file path.
@@ -931,7 +1071,8 @@ base::Optional<base::FilePath> ExtensionDownloader::GetCachedExtension(
// Begins (or queues up) download of an updated extension.
void ExtensionDownloader::FetchUpdatedExtension(
- std::unique_ptr<ExtensionFetch> fetch_data) {
+ std::unique_ptr<ExtensionFetch> fetch_data,
+ base::Optional<std::string> info) {
if (!fetch_data->url.is_valid()) {
// TODO(asargent): This can sometimes be invalid. See crbug.com/130881.
DLOG(WARNING) << "Invalid URL: '" << fetch_data->url.possibly_invalid_spec()
@@ -939,9 +1080,12 @@ void ExtensionDownloader::FetchUpdatedExtension(
delegate_->OnExtensionDownloadStageChanged(
fetch_data->id, ExtensionDownloaderDelegate::Stage::FINISHED);
if (fetch_data->url.is_empty()) {
- NotifyExtensionsDownloadFailed(
+ // We expect to receive initialised |info| from the manifest parser in
+ // case of no updates status in the update manifest.
+ ExtensionDownloaderDelegate::FailureData data(info.value_or(""));
+ NotifyExtensionsDownloadFailedWithFailureData(
{fetch_data->id}, fetch_data->request_ids,
- ExtensionDownloaderDelegate::Error::CRX_FETCH_URL_EMPTY);
+ ExtensionDownloaderDelegate::Error::CRX_FETCH_URL_EMPTY, data);
} else {
NotifyExtensionsDownloadFailed(
{fetch_data->id}, fetch_data->request_ids,
@@ -971,7 +1115,7 @@ void ExtensionDownloader::FetchUpdatedExtension(
return;
}
base::Optional<base::FilePath> cached_crx_path =
- GetCachedExtension(*fetch_data);
+ GetCachedExtension(*fetch_data, /*manifest_fetch_failed*/ false);
if (cached_crx_path) {
delegate_->OnExtensionDownloadStageChanged(
fetch_data->id, ExtensionDownloaderDelegate::Stage::FINISHED);
@@ -1002,7 +1146,9 @@ void ExtensionDownloader::NotifyDelegateDownloadFinished(
CRXFileInfo crx_info(crx_path, required_format);
crx_info.expected_hash = package_hash;
crx_info.extension_id = id;
- crx_info.expected_version = version;
+ // TODO(https://crbug.com/1076376): Change |version| in ExtensionFetch from
+ // std::string to base::Version.
+ crx_info.expected_version = base::Version(version);
delegate_->OnExtensionDownloadFinished(
crx_info, file_ownership_passed, url, ping_results_[id], request_ids,
from_cache ? base::BindRepeating(&ExtensionDownloader::CacheInstallDone,
@@ -1140,19 +1286,8 @@ void ExtensionDownloader::OnExtensionLoadComplete(base::FilePath crx_path) {
extensions_queue_.reset_active_request();
delegate_->OnExtensionDownloadStageChanged(
id, ExtensionDownloaderDelegate::Stage::FINISHED);
- if (extension_cache_) {
- const std::string& version = fetch_data->version;
- const std::string& expected_hash = fetch_data->package_hash;
- extension_cache_->PutExtension(
- id, expected_hash, crx_path, version,
- base::BindRepeating(
- &ExtensionDownloader::NotifyDelegateDownloadFinished,
- weak_ptr_factory_.GetWeakPtr(), base::Passed(&fetch_data),
- false));
- } else {
- NotifyDelegateDownloadFinished(std::move(fetch_data), false, crx_path,
- true);
- }
+ NotifyDelegateDownloadFinished(std::move(fetch_data), false, crx_path,
+ true);
} else if (IterateFetchCredentialsAfterFailure(&active_request,
response_code)) {
delegate_->OnExtensionDownloadStageChanged(
@@ -1174,8 +1309,6 @@ void ExtensionDownloader::OnExtensionLoadComplete(base::FilePath crx_path) {
RETRY_HISTOGRAM("CrxFetchFailure",
extensions_queue_.active_request_failure_count(),
url);
- // net_error is 0 (net::OK) or negative. (See net/base/net_errors.h)
- base::UmaHistogramSparse("Extensions.CrxFetchError", -net_error);
delegate_->OnExtensionDownloadStageChanged(
id, ExtensionDownloaderDelegate::Stage::FINISHED);
ExtensionDownloaderDelegate::FailureData failure_data(
diff --git a/chromium/extensions/browser/updater/extension_downloader.h b/chromium/extensions/browser/updater/extension_downloader.h
index e2059b9a3ad..56ac50ddcab 100644
--- a/chromium/extensions/browser/updater/extension_downloader.h
+++ b/chromium/extensions/browser/updater/extension_downloader.h
@@ -144,6 +144,11 @@ class ExtensionDownloader {
ping_enabled_domain_ = domain;
}
+ // Set backoff policy for manifest queue for testing with less initial delay
+ // so the tests do not timeout on retries.
+ void SetBackoffPolicyForTesting(
+ const net::BackoffEntry::Policy* backoff_policy);
+
// Sets a test delegate to use by any instances of this class. The |delegate|
// should outlive all instances.
static void set_test_delegate(ExtensionDownloaderTestDelegate* delegate);
@@ -229,6 +234,28 @@ class ExtensionDownloader {
ExtraParams();
};
+ // We limit the number of extensions grouped together in one batch to avoid
+ // running into the limits on the length of http GET requests, this represents
+ // the key for grouping these extensions.
+ struct FetchDataGroupKey {
+ FetchDataGroupKey();
+ FetchDataGroupKey(const FetchDataGroupKey& other);
+ FetchDataGroupKey(const int request_id,
+ const GURL& update_url,
+ const bool is_force_installed);
+ ~FetchDataGroupKey();
+
+ bool operator<(const FetchDataGroupKey& other) const;
+
+ int request_id{0};
+ GURL update_url;
+ // The extensions in current ManifestFetchData are all force installed
+ // (Manifest::Location::EXTERNAL_POLICY_DOWNLOAD) or not. In a
+ // ManifestFetchData we would have either all the extensions as force
+ // installed or we would none extensions as force installed.
+ bool is_force_installed{false};
+ };
+
enum class UpdateAvailability {
kAvailable,
kNoUpdate,
@@ -258,6 +285,33 @@ class ExtensionDownloader {
// Called by RequestQueue when a new manifest load request is started.
void CreateManifestLoader();
+ // Retries the active request with some backoff delay.
+ void RetryManifestFetchRequest();
+
+ // Reports failures if we failed to fetch the manifest or the fetched manifest
+ // was invalid.
+ void ReportManifestFetchFailure(
+ ManifestFetchData* fetch_data,
+ ExtensionDownloaderDelegate::Error error,
+ const ExtensionDownloaderDelegate::FailureData& data);
+
+ // Tries fetching the extension from cache if manifest fetch is failed for
+ // force installed extensions, and notifies the failure reason for remaining
+ // extensions.
+ void TryFetchingExtensionsFromCache(
+ ManifestFetchData* fetch_data,
+ ExtensionDownloaderDelegate::Error error,
+ const int net_error,
+ const int response_code,
+ const base::Optional<ManifestInvalidErrorList>& manifest_invalid_errors);
+
+ // Makes a retry attempt, reports failure by calling
+ // AddFailureDataOnManifestFetchFailed when fetching of update manifest
+ // failed.
+ void RetryRequestOrHandleFailureOnManifestFetchFailure(
+ const network::SimpleURLLoader* loader,
+ const int response_code);
+
// Handles the result of a manifest fetch.
void OnManifestLoadComplete(std::unique_ptr<std::string> response_body);
@@ -283,12 +337,18 @@ class ExtensionDownloader {
ManifestInvalidErrorList* errors);
// Checks whether extension is presented in cache. If yes, return path to its
- // cached CRX, base::nullopt otherwise.
+ // cached CRX, base::nullopt otherwise. |manifest_fetch_failed| flag indicates
+ // whether the lookup in cache is performed after the manifest is fetched or
+ // due to failure while fetching or parsing manifest.
base::Optional<base::FilePath> GetCachedExtension(
- const ExtensionFetch& fetch_data);
+ const ExtensionFetch& fetch_data,
+ bool manifest_fetch_failed);
- // Begins (or queues up) download of an updated extension.
- void FetchUpdatedExtension(std::unique_ptr<ExtensionFetch> fetch_data);
+ // Begins (or queues up) download of an updated extension. |info| represents
+ // additional information about the extension update from the info field in
+ // the update manifest.
+ void FetchUpdatedExtension(std::unique_ptr<ExtensionFetch> fetch_data,
+ base::Optional<std::string> info);
// Called by RequestQueue when a new extension load request is started.
void CreateExtensionLoader();
@@ -388,13 +448,11 @@ class ExtensionDownloader {
// Collects UMA samples that are reported when ReportStats() is called.
URLStats url_stats_;
- // List of data on fetches we're going to do. We limit the number of
- // extensions grouped together in one batch to avoid running into the limits
- // on the length of http GET requests, so there might be multiple
- // ManifestFetchData* objects with the same base_url.
- using FetchMap = std::map<std::pair<int, GURL>,
- std::vector<std::unique_ptr<ManifestFetchData>>>;
- FetchMap fetches_preparing_;
+ // We limit the number of extensions grouped together in one batch to avoid
+ // running into the limits on the length of http GET requests, so there might
+ // be multiple ManifestFetchData* objects with the same update_url.
+ std::map<FetchDataGroupKey, std::vector<std::unique_ptr<ManifestFetchData>>>
+ fetches_preparing_;
// Outstanding url loader requests for manifests and updates.
std::unique_ptr<network::SimpleURLLoader> manifest_loader_;
diff --git a/chromium/extensions/browser/updater/extension_downloader_delegate.cc b/chromium/extensions/browser/updater/extension_downloader_delegate.cc
index dc7dd473ca8..02d98fe0a38 100644
--- a/chromium/extensions/browser/updater/extension_downloader_delegate.cc
+++ b/chromium/extensions/browser/updater/extension_downloader_delegate.cc
@@ -32,6 +32,10 @@ ExtensionDownloaderDelegate::FailureData::FailureData(
ManifestInvalidError manifest_invalid_error)
: manifest_invalid_error(manifest_invalid_error) {}
+ExtensionDownloaderDelegate::FailureData::FailureData(
+ const std::string& additional_info)
+ : additional_info(additional_info) {}
+
ExtensionDownloaderDelegate::FailureData::~FailureData() = default;
ExtensionDownloaderDelegate::~ExtensionDownloaderDelegate() = default;
diff --git a/chromium/extensions/browser/updater/extension_downloader_delegate.h b/chromium/extensions/browser/updater/extension_downloader_delegate.h
index 84d7803b7a0..0ba28d76a3b 100644
--- a/chromium/extensions/browser/updater/extension_downloader_delegate.h
+++ b/chromium/extensions/browser/updater/extension_downloader_delegate.h
@@ -124,9 +124,13 @@ class ExtensionDownloaderDelegate {
// Cache entry is good and will be used.
CACHE_HIT = 4,
+ // Cache entry will be used in case we fail to fetch the manifest for the
+ // extension.
+ CACHE_HIT_ON_MANIFEST_FETCH_FAILURE = 5,
+
// Magic constant used by the histogram macros.
// Always update it to the max value.
- kMaxValue = CACHE_HIT,
+ kMaxValue = CACHE_HIT_ON_MANIFEST_FETCH_FAILURE,
};
// Passed as an argument to the completion callbacks to signal whether
@@ -143,8 +147,9 @@ class ExtensionDownloaderDelegate {
base::Time day_start;
};
- // Contains the error codes when Force installed extension fail to install
- // with error CRX_FETCH_FAILED, MANIFEST_FETCH_FAILED or MANIFEST_INVALID.
+ // Additional information in case of force installed extension install failure
+ // due to CRX_FETCH_FAILED, MANIFEST_FETCH_FAILED, MANIFEST_INVALID,
+ // CRX_FETCH_URL_EMPTY.
struct FailureData {
FailureData();
FailureData(const FailureData& other);
@@ -153,6 +158,7 @@ class ExtensionDownloaderDelegate {
const base::Optional<int> response,
const int fetch_attempts);
explicit FailureData(ManifestInvalidError manifest_invalid_error);
+ explicit FailureData(const std::string& additional_info);
~FailureData();
// Network error code in case of CRX_FETCH_FAILED or MANIFEST_FETCH_FAILED.
@@ -166,6 +172,10 @@ class ExtensionDownloaderDelegate {
// errors occurred while parsing the update manifest and the errors in the
// internal details of the parsed manifest.
const base::Optional<ManifestInvalidError> manifest_invalid_error;
+ // Info field in the update manifest returned by the server. Currently it is
+ // only set when no update is available and install fails with the error
+ // CRX_FETCH_URL_EMPTY.
+ const base::Optional<std::string> additional_info;
};
// A callback that is called to indicate if ExtensionDownloader should ignore
diff --git a/chromium/extensions/browser/updater/extension_installer.cc b/chromium/extensions/browser/updater/extension_installer.cc
index ce88e3aeb23..60a074809fa 100644
--- a/chromium/extensions/browser/updater/extension_installer.cc
+++ b/chromium/extensions/browser/updater/extension_installer.cc
@@ -12,7 +12,6 @@
#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
-#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/update_client/update_client_errors.h"
#include "content/public/browser/browser_task_traits.h"
@@ -45,8 +44,7 @@ void ExtensionInstaller::Install(
std::unique_ptr<InstallParams> /*install_params*/,
ProgressCallback /*progress_callback*/,
UpdateClientCallback update_client_callback) {
- auto ui_thread =
- base::CreateSingleThreadTaskRunner({content::BrowserThread::UI});
+ auto ui_thread = content::GetUIThreadTaskRunner({});
DCHECK(ui_thread);
DCHECK(!extension_installer_callback_.is_null());
if (base::PathExists(unpack_path)) {
diff --git a/chromium/extensions/browser/updater/manifest_fetch_data.cc b/chromium/extensions/browser/updater/manifest_fetch_data.cc
index 1246974885a..afb8318e619 100644
--- a/chromium/extensions/browser/updater/manifest_fetch_data.cc
+++ b/chromium/extensions/browser/updater/manifest_fetch_data.cc
@@ -46,6 +46,23 @@ void AddEnabledStateToPing(std::string* ping_value,
} // namespace
+ManifestFetchData::ExtensionData::ExtensionData() : version(base::Version()) {}
+
+ManifestFetchData::ExtensionData::ExtensionData(const ExtensionData& other) =
+ default;
+
+ManifestFetchData::ExtensionData::ExtensionData(
+ const base::Version& version,
+ const std::string& update_url_data,
+ const std::string& install_source,
+ Manifest::Location extension_location)
+ : version(version),
+ update_url_data(update_url_data),
+ install_source(install_source),
+ extension_location(extension_location) {}
+
+ManifestFetchData::ExtensionData::~ExtensionData() = default;
+
// static
std::string ManifestFetchData::GetSimpleLocationString(Manifest::Location loc) {
std::string result = kInvalidLocation;
@@ -87,14 +104,9 @@ ManifestFetchData::ManifestFetchData(const GURL& update_url,
full_url_(update_url),
brand_code_(brand_code),
ping_mode_(ping_mode),
- fetch_priority_(fetch_priority) {
- std::string query =
- full_url_.has_query() ? full_url_.query() + "&" : std::string();
- query += base_query_params;
- GURL::Replacements replacements;
- replacements.SetQueryStr(query);
- full_url_ = full_url_.ReplaceComponents(replacements);
-
+ fetch_priority_(fetch_priority),
+ is_all_external_policy_download_(false) {
+ UpdateFullUrl(base_query_params);
request_ids_.insert(request_id);
}
@@ -129,7 +141,9 @@ bool ManifestFetchData::AddExtension(const std::string& id,
const std::string& install_source,
Manifest::Location extension_location,
FetchPriority fetch_priority) {
- if (extension_ids_.find(id) != extension_ids_.end()) {
+ DCHECK(!is_all_external_policy_download_ ||
+ extension_location == Manifest::Location::EXTERNAL_POLICY_DOWNLOAD);
+ if (extensions_data_.find(id) != extensions_data_.end()) {
NOTREACHED() << "Duplicate extension id " << id;
return false;
}
@@ -192,20 +206,60 @@ bool ManifestFetchData::AddExtension(const std::string& id,
// Check against our max url size, exempting the first extension added.
int new_size = full_url_.possibly_invalid_spec().size() + extra.size();
- if (!extension_ids_.empty() && new_size > kExtensionsManifestMaxURLSize) {
+ if (!extensions_data_.empty() && new_size > kExtensionsManifestMaxURLSize) {
UMA_HISTOGRAM_PERCENTAGE("Extensions.UpdateCheckHitUrlSizeLimit", 1);
return false;
}
UMA_HISTOGRAM_PERCENTAGE("Extensions.UpdateCheckHitUrlSizeLimit", 0);
// We have room so go ahead and add the extension.
- extension_ids_.insert(id);
+ extensions_data_[id] = ExtensionData(base::Version(version), update_url_data,
+ install_source, extension_location);
full_url_ = GURL(full_url_.possibly_invalid_spec() + extra);
return true;
}
+void ManifestFetchData::UpdateFullUrl(const std::string& base_query_params) {
+ std::string query =
+ full_url_.has_query() ? full_url_.query() + "&" : std::string();
+ query += base_query_params;
+ GURL::Replacements replacements;
+ replacements.SetQueryStr(query);
+ full_url_ = full_url_.ReplaceComponents(replacements);
+}
+
+void ManifestFetchData::RemoveExtensions(const ExtensionIdSet& id_to_remove,
+ const std::string& base_query_params) {
+ const std::map<ExtensionId, ExtensionData> extensions_data =
+ std::move(extensions_data_);
+ extensions_data_.clear();
+ full_url_ = base_url_;
+ UpdateFullUrl(base_query_params);
+
+ for (const auto& data : extensions_data) {
+ const ExtensionId& extension_id = data.first;
+ if (id_to_remove.count(extension_id))
+ continue;
+ const ExtensionData& extension_data = data.second;
+ auto it = pings_.find(extension_id);
+ const PingData* optional_ping_data =
+ it != pings_.end() ? &(it->second) : nullptr;
+ AddExtension(extension_id, extension_data.version.GetString(),
+ optional_ping_data, extension_data.update_url_data,
+ extension_data.install_source,
+ extension_data.extension_location, fetch_priority_);
+ }
+}
+
+ExtensionIdSet ManifestFetchData::GetExtensionIds() const {
+ ExtensionIdSet extension_ids;
+ for (const auto& extension_data : extensions_data_)
+ extension_ids.insert(extension_data.first);
+ return extension_ids;
+}
+
bool ManifestFetchData::Includes(const std::string& extension_id) const {
- return extension_ids_.find(extension_id) != extension_ids_.end();
+ return extensions_data_.find(extension_id) != extensions_data_.end();
}
bool ManifestFetchData::DidPing(const std::string& extension_id,
@@ -231,4 +285,8 @@ void ManifestFetchData::Merge(const ManifestFetchData& other) {
request_ids_.insert(other.request_ids_.begin(), other.request_ids_.end());
}
+void ManifestFetchData::set_is_all_external_policy_download() {
+ is_all_external_policy_download_ = true;
+}
+
} // namespace extensions
diff --git a/chromium/extensions/browser/updater/manifest_fetch_data.h b/chromium/extensions/browser/updater/manifest_fetch_data.h
index b183e2e5833..0bbb0132f0b 100644
--- a/chromium/extensions/browser/updater/manifest_fetch_data.h
+++ b/chromium/extensions/browser/updater/manifest_fetch_data.h
@@ -10,6 +10,7 @@
#include <string>
#include "base/macros.h"
+#include "base/version.h"
#include "extensions/common/manifest.h"
#include "url/gurl.h"
@@ -108,14 +109,22 @@ class ManifestFetchData {
const GURL& base_url() const { return base_url_; }
const GURL& full_url() const { return full_url_; }
- const std::set<std::string>& extension_ids() const { return extension_ids_; }
+ ExtensionIdSet GetExtensionIds() const;
const std::set<int>& request_ids() const { return request_ids_; }
bool foreground_check() const { return fetch_priority_ == FOREGROUND; }
FetchPriority fetch_priority() const { return fetch_priority_; }
+ bool is_all_external_policy_download() const {
+ return is_all_external_policy_download_;
+ }
// Returns true if the given id is included in this manifest fetch.
bool Includes(const std::string& extension_id) const;
+ // Resets the full url to base url and removes |id_to_remove| from
+ // the ManifestFetchData.
+ void RemoveExtensions(const ExtensionIdSet& id_to_remove,
+ const std::string& base_query_params);
+
// Returns true if a ping parameter for |type| was added to full_url for this
// extension id.
bool DidPing(const std::string& extension_id, PingType type) const;
@@ -126,9 +135,36 @@ class ManifestFetchData {
// to this ManifestFetchData).
void Merge(const ManifestFetchData& other);
+ // Assigns true if all the extensions are force installed.
+ void set_is_all_external_policy_download();
+
private:
- // The set of extension id's for this ManifestFetchData.
- std::set<std::string> extension_ids_;
+ // Contains supplementary data needed to construct update manifest fetch
+ // query.
+ struct ExtensionData {
+ ExtensionData();
+ ExtensionData(const ExtensionData& other);
+ ExtensionData(const base::Version& version,
+ const std::string& update_url_data,
+ const std::string& install_source,
+ Manifest::Location extension_location);
+
+ ~ExtensionData();
+ base::Version version;
+ std::string update_url_data;
+ std::string install_source;
+ Manifest::Location extension_location{Manifest::Location::INTERNAL};
+ };
+
+ const std::map<ExtensionId, ExtensionData>& extensions_data() const {
+ return extensions_data_;
+ }
+
+ // Appends query parameters to the full url if any.
+ void UpdateFullUrl(const std::string& base_query_params);
+
+ // The set of extension data for each extension.
+ std::map<std::string, ExtensionData> extensions_data_;
// The set of ping data we actually sent.
std::map<std::string, PingData> pings_;
@@ -157,6 +193,10 @@ class ManifestFetchData {
// The priority of the update.
FetchPriority fetch_priority_;
+ // The flag is set to true if all the extensions are force installed
+ // extensions.
+ bool is_all_external_policy_download_;
+
DISALLOW_COPY_AND_ASSIGN(ManifestFetchData);
};
diff --git a/chromium/extensions/browser/updater/update_data_provider.cc b/chromium/extensions/browser/updater/update_data_provider.cc
index ee6f6b221bd..ead0cac88c5 100644
--- a/chromium/extensions/browser/updater/update_data_provider.cc
+++ b/chromium/extensions/browser/updater/update_data_provider.cc
@@ -12,7 +12,6 @@
#include "base/files/file_util.h"
#include "base/optional.h"
#include "base/strings/string_util.h"
-#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
#include "components/crx_file/crx_verifier.h"
#include "components/update_client/utils.h"
@@ -154,23 +153,20 @@ void UpdateDataProvider::RunInstallCallback(
if (!browser_context_) {
base::ThreadPool::PostTask(
FROM_HERE, {base::TaskPriority::BEST_EFFORT, base::MayBlock()},
- base::BindOnce(base::IgnoreResult(&base::DeleteFile), unpacked_dir,
- true));
- base::CreateSingleThreadTaskRunner({content::BrowserThread::UI})
- ->PostTask(
- FROM_HERE,
- base::BindOnce(std::move(update_client_callback),
- update_client::CrxInstaller::Result(
- update_client::InstallError::GENERIC_ERROR)));
+ base::BindOnce(base::GetDeletePathRecursivelyCallback(), unpacked_dir));
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
+ base::BindOnce(std::move(update_client_callback),
+ update_client::CrxInstaller::Result(
+ update_client::InstallError::GENERIC_ERROR)));
return;
}
- base::CreateSingleThreadTaskRunner({content::BrowserThread::UI})
- ->PostTask(
- FROM_HERE,
- base::BindOnce(InstallUpdateCallback, browser_context_, extension_id,
- public_key, unpacked_dir, install_immediately,
- std::move(update_client_callback)));
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
+ base::BindOnce(InstallUpdateCallback, browser_context_, extension_id,
+ public_key, unpacked_dir, install_immediately,
+ std::move(update_client_callback)));
}
} // namespace extensions
diff --git a/chromium/extensions/browser/updater/update_service.cc b/chromium/extensions/browser/updater/update_service.cc
index 2c57317abe9..2b62acd4ae9 100644
--- a/chromium/extensions/browser/updater/update_service.cc
+++ b/chromium/extensions/browser/updater/update_service.cc
@@ -135,14 +135,15 @@ void UpdateService::OnEvent(Events event, const std::string& extension_id) {
break;
}
- base::Value attributes(base::Value::Type::DICTIONARY);
- if (should_perform_action_on_omaha_attributes &&
- base::FeatureList::IsEnabled(
- extensions_features::kDisableMalwareExtensionsRemotely)) {
- attributes = GetExtensionOmahaAttributes(extension_id);
+ if (should_perform_action_on_omaha_attributes) {
+ base::Value attributes(base::Value::Type::DICTIONARY);
+ if (base::FeatureList::IsEnabled(
+ extensions_features::kDisableMalwareExtensionsRemotely)) {
+ attributes = GetExtensionOmahaAttributes(extension_id);
+ }
+ ExtensionSystem::Get(browser_context_)
+ ->PerformActionBasedOnOmahaAttributes(extension_id, attributes);
}
- ExtensionSystem::Get(browser_context_)
- ->PerformActionBasedOnOmahaAttributes(extension_id, attributes);
}
UpdateService::UpdateService(
diff --git a/chromium/extensions/browser/updater/update_service_unittest.cc b/chromium/extensions/browser/updater/update_service_unittest.cc
index 8b17ff6a9d8..1dd9e3cc094 100644
--- a/chromium/extensions/browser/updater/update_service_unittest.cc
+++ b/chromium/extensions/browser/updater/update_service_unittest.cc
@@ -497,6 +497,36 @@ TEST_F(UpdateServiceTest, UninstallPings) {
}
}
+TEST_F(UpdateServiceTest, NoPerformAction) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(
+ extensions_features::kDisableMalwareExtensionsRemotely);
+ std::string extension_id = "lpcaedmchfhocbbapmcbpinfpgnhiddi";
+ ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context());
+ scoped_refptr<const Extension> extension1 =
+ ExtensionBuilder("1").SetVersion("1.2").SetID(extension_id).Build();
+ EXPECT_TRUE(registry->AddEnabled(extension1));
+
+ update_client()->set_is_malware_update_item();
+ update_client()->set_delay_update();
+
+ ExtensionUpdateCheckParams update_check_params;
+ update_check_params.update_info[extension_id] = ExtensionUpdateData();
+
+ bool executed = false;
+ update_service()->StartUpdateCheck(
+ update_check_params,
+ base::BindOnce([](bool* executed) { *executed = true; }, &executed));
+ EXPECT_FALSE(executed);
+
+ const auto& request = update_client()->update_request(0);
+ EXPECT_THAT(request.extension_ids, testing::ElementsAre(extension_id));
+
+ update_client()->RunDelayedUpdate(
+ 0, UpdateClientEvents::COMPONENT_CHECKING_FOR_UPDATES);
+ EXPECT_FALSE(registry->disabled_extensions().GetByID(extension_id));
+}
+
TEST_F(UpdateServiceTest, CheckOmahaAttributes) {
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(