Commit ec97aa89 authored by Mugdha Lakhani's avatar Mugdha Lakhani Committed by Commit Bot

[Background Fetch] Respond to service worker database corruption.

This will abort all ongoing fetches, and mark their data for deletion.

Bug: 841385
Change-Id: I19eba7a294dd348c0c0a5324f3b23b438b571c03

Change-Id: I19eba7a294dd348c0c0a5324f3b23b438b571c03
Reviewed-on: https://chromium-review.googlesource.com/1103559
Commit-Queue: Mugdha Lakhani <nator@chromium.org>
Reviewed-by: default avatarPeter Beverloo <peter@chromium.org>
Cr-Commit-Position: refs/heads/master@{#570830}
parent 0e114bd4
...@@ -27,21 +27,21 @@ BackgroundFetchContext::BackgroundFetchContext( ...@@ -27,21 +27,21 @@ BackgroundFetchContext::BackgroundFetchContext(
const scoped_refptr<content::CacheStorageContextImpl>& const scoped_refptr<content::CacheStorageContextImpl>&
cache_storage_context) cache_storage_context)
: browser_context_(browser_context), : browser_context_(browser_context),
data_manager_(
std::make_unique<BackgroundFetchDataManager>(browser_context,
service_worker_context,
cache_storage_context)),
service_worker_context_(service_worker_context), service_worker_context_(service_worker_context),
event_dispatcher_(service_worker_context), event_dispatcher_(service_worker_context),
registration_notifier_( registration_notifier_(
std::make_unique<BackgroundFetchRegistrationNotifier>()), std::make_unique<BackgroundFetchRegistrationNotifier>()),
delegate_proxy_(browser_context_->GetBackgroundFetchDelegate()), delegate_proxy_(browser_context_->GetBackgroundFetchDelegate()),
scheduler_(
std::make_unique<BackgroundFetchScheduler>(data_manager_.get())),
weak_factory_(this) { weak_factory_(this) {
// Although this lives only on the IO thread, it is constructed on UI thread. // Although this lives only on the IO thread, it is constructed on UI thread.
DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(service_worker_context_); DCHECK(service_worker_context_);
data_manager_ = std::make_unique<BackgroundFetchDataManager>(
browser_context, service_worker_context, cache_storage_context,
base::BindRepeating(&BackgroundFetchContext::AbandonFetches,
weak_factory_.GetWeakPtr(),
blink::mojom::kInvalidServiceWorkerRegistrationId));
scheduler_ = std::make_unique<BackgroundFetchScheduler>(data_manager_.get());
} }
BackgroundFetchContext::~BackgroundFetchContext() { BackgroundFetchContext::~BackgroundFetchContext() {
......
...@@ -63,13 +63,16 @@ void GetRegistrationFromMetadata( ...@@ -63,13 +63,16 @@ void GetRegistrationFromMetadata(
BackgroundFetchDataManager::BackgroundFetchDataManager( BackgroundFetchDataManager::BackgroundFetchDataManager(
BrowserContext* browser_context, BrowserContext* browser_context,
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context, scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
scoped_refptr<CacheStorageContextImpl> cache_storage_context) scoped_refptr<CacheStorageContextImpl> cache_storage_context,
const base::RepeatingClosure& abandon_fetches_callback)
: service_worker_context_(std::move(service_worker_context)), : service_worker_context_(std::move(service_worker_context)),
cache_storage_context_(std::move(cache_storage_context)), cache_storage_context_(std::move(cache_storage_context)),
abandon_fetches_callback_(abandon_fetches_callback),
weak_ptr_factory_(this) { weak_ptr_factory_(this) {
// Constructed on the UI thread, then used on the IO thread. // Constructed on the UI thread, then used on the IO thread.
DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(browser_context); DCHECK(browser_context);
DCHECK(abandon_fetches_callback_);
// Store the blob storage context for the given |browser_context|. // Store the blob storage context for the given |browser_context|.
blob_storage_context_ = blob_storage_context_ =
......
...@@ -72,7 +72,8 @@ class CONTENT_EXPORT BackgroundFetchDataManager ...@@ -72,7 +72,8 @@ class CONTENT_EXPORT BackgroundFetchDataManager
BackgroundFetchDataManager( BackgroundFetchDataManager(
BrowserContext* browser_context, BrowserContext* browser_context,
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context, scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
scoped_refptr<CacheStorageContextImpl> cache_storage_context); scoped_refptr<CacheStorageContextImpl> cache_storage_context,
const base::RepeatingClosure& abandon_fetches_callback);
~BackgroundFetchDataManager() override; ~BackgroundFetchDataManager() override;
...@@ -148,6 +149,10 @@ class CONTENT_EXPORT BackgroundFetchDataManager ...@@ -148,6 +149,10 @@ class CONTENT_EXPORT BackgroundFetchDataManager
const BackgroundFetchRegistrationId& registration_id, const BackgroundFetchRegistrationId& registration_id,
NumRequestsCallback callback); NumRequestsCallback callback);
const base::RepeatingClosure& abandon_fetches_callback() {
return abandon_fetches_callback_;
}
// BackgroundFetchScheduler::RequestProvider implementation: // BackgroundFetchScheduler::RequestProvider implementation:
void PopNextRequest(const BackgroundFetchRegistrationId& registration_id, void PopNextRequest(const BackgroundFetchRegistrationId& registration_id,
NextRequestCallback callback) override; NextRequestCallback callback) override;
...@@ -217,6 +222,11 @@ class CONTENT_EXPORT BackgroundFetchDataManager ...@@ -217,6 +222,11 @@ class CONTENT_EXPORT BackgroundFetchDataManager
// the browser is shutdown first. // the browser is shutdown first.
std::set<std::string> ref_counted_unique_ids_; std::set<std::string> ref_counted_unique_ids_;
// This is called to abandon all ongoing fetches. It will also mark these
// fetches for deletion, which will be cleaned up by the Cleanup task
// subsequently.
base::RepeatingClosure abandon_fetches_callback_;
base::WeakPtrFactory<BackgroundFetchDataManager> weak_ptr_factory_; base::WeakPtrFactory<BackgroundFetchDataManager> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(BackgroundFetchDataManager); DISALLOW_COPY_AND_ASSIGN(BackgroundFetchDataManager);
......
...@@ -42,7 +42,8 @@ BackgroundFetchTestDataManager::BackgroundFetchTestDataManager( ...@@ -42,7 +42,8 @@ BackgroundFetchTestDataManager::BackgroundFetchTestDataManager(
bool mock_fill_response) bool mock_fill_response)
: BackgroundFetchDataManager(browser_context, : BackgroundFetchDataManager(browser_context,
service_worker_context, service_worker_context,
nullptr /* cache_storage_context */), nullptr /* cache_storage_context */,
base::DoNothing()),
browser_context_(browser_context), browser_context_(browser_context),
storage_partition_(storage_partition), storage_partition_(storage_partition),
mock_fill_response_(mock_fill_response) {} mock_fill_response_(mock_fill_response) {}
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "base/barrier_closure.h" #include "base/barrier_closure.h"
#include "content/browser/background_fetch/background_fetch.pb.h" #include "content/browser/background_fetch/background_fetch.pb.h"
#include "content/browser/background_fetch/background_fetch_data_manager.h"
#include "content/browser/background_fetch/storage/database_helpers.h" #include "content/browser/background_fetch/storage/database_helpers.h"
#include "content/browser/cache_storage/cache_storage_manager.h" #include "content/browser/cache_storage/cache_storage_manager.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h" #include "content/browser/service_worker/service_worker_context_wrapper.h"
...@@ -91,8 +92,10 @@ void DeleteRegistrationTask::DidGetRegistration( ...@@ -91,8 +92,10 @@ void DeleteRegistrationTask::DidGetRegistration(
metadata_proto.registration().developer_id())}, metadata_proto.registration().developer_id())},
base::BindOnce(&DCheckRegistrationNotActive, unique_id_)); base::BindOnce(&DCheckRegistrationNotActive, unique_id_));
} else { } else {
NOTREACHED() // Service worker database has been corrupted. Abandon all fetches.
<< "Database is corrupt"; // TODO(crbug.com/780027): Nuke it. error_ = blink::mojom::BackgroundFetchError::STORAGE_ERROR;
data_manager()->abandon_fetches_callback().Run();
std::move(done_closure).Run();
} }
} else { } else {
// TODO(crbug.com/780025): Log failure to UMA. // TODO(crbug.com/780025): Log failure to UMA.
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "content/browser/background_fetch/storage/get_settled_fetches_task.h" #include "content/browser/background_fetch/storage/get_settled_fetches_task.h"
#include "base/barrier_closure.h" #include "base/barrier_closure.h"
#include "content/browser/background_fetch/background_fetch_data_manager.h"
#include "content/browser/background_fetch/storage/database_helpers.h" #include "content/browser/background_fetch/storage/database_helpers.h"
#include "content/browser/cache_storage/cache_storage_manager.h" #include "content/browser/cache_storage/cache_storage_manager.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h" #include "content/browser/service_worker/service_worker_context_wrapper.h"
...@@ -78,8 +79,11 @@ void GetSettledFetchesTask::DidGetCompletedRequests( ...@@ -78,8 +79,11 @@ void GetSettledFetchesTask::DidGetCompletedRequests(
completed_requests_.emplace_back(); completed_requests_.emplace_back();
if (!completed_requests_.back().ParseFromString( if (!completed_requests_.back().ParseFromString(
serialized_completed_request)) { serialized_completed_request)) {
NOTREACHED() // Service worker database has been corrupted. Abandon fetches.
<< "Database is corrupt"; // TODO(crbug.com/780027): Nuke it. error_ = blink::mojom::BackgroundFetchError::STORAGE_ERROR;
background_fetch_succeeded_ = false;
data_manager()->abandon_fetches_callback().Run();
break;
} }
if (!completed_requests_.back().succeeded()) if (!completed_requests_.back().succeeded())
background_fetch_succeeded_ = false; background_fetch_succeeded_ = false;
......
...@@ -77,7 +77,11 @@ void MarkRegistrationForDeletionTask::DidGetActiveUniqueId( ...@@ -77,7 +77,11 @@ void MarkRegistrationForDeletionTask::DidGetActiveUniqueId(
base::BindOnce(&MarkRegistrationForDeletionTask::DidDeactivate, base::BindOnce(&MarkRegistrationForDeletionTask::DidDeactivate,
weak_factory_.GetWeakPtr())); weak_factory_.GetWeakPtr()));
} else { } else {
NOTREACHED() << "Database is corrupt"; // TODO(crbug.com/780027): Nuke it. // Service worker database has been corrupted. Abandon fetches.
data_manager()->abandon_fetches_callback().Run();
std::move(callback_).Run(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
Finished(); // Destroys |this|.
return;
} }
} }
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "content/browser/background_fetch/storage/start_next_pending_request_task.h" #include "content/browser/background_fetch/storage/start_next_pending_request_task.h"
#include "base/guid.h" #include "base/guid.h"
#include "content/browser/background_fetch/background_fetch_data_manager.h"
#include "content/browser/background_fetch/storage/database_helpers.h" #include "content/browser/background_fetch/storage/database_helpers.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h" #include "content/browser/service_worker/service_worker_context_wrapper.h"
...@@ -59,7 +60,11 @@ void StartNextPendingRequestTask::DidGetPendingRequests( ...@@ -59,7 +60,11 @@ void StartNextPendingRequestTask::DidGetPendingRequests(
} }
if (!pending_request_.ParseFromString(data.front())) { if (!pending_request_.ParseFromString(data.front())) {
NOTREACHED() << "Database is corrupt"; // TODO(crbug.com/780027): Nuke it. // Service Worker database has been corrupted. Abandon fetches.
data_manager()->abandon_fetches_callback().Run();
std::move(callback_).Run(nullptr /* request */);
Finished(); // Destroys |this|.
return;
} }
// Make sure there isn't already an Active Request. // Make sure there isn't already an Active Request.
...@@ -87,8 +92,11 @@ void StartNextPendingRequestTask::DidFindActiveRequest( ...@@ -87,8 +92,11 @@ void StartNextPendingRequestTask::DidFindActiveRequest(
case DatabaseStatus::kOk: case DatabaseStatus::kOk:
// We already stored the active request. // We already stored the active request.
if (!active_request_.ParseFromString(data.front())) { if (!active_request_.ParseFromString(data.front())) {
NOTREACHED() // Service worker database has been corrupted. Abandon fetches.
<< "Database is corrupt"; // TODO(crbug.com/780027): Nuke it. data_manager()->abandon_fetches_callback().Run();
std::move(callback_).Run(nullptr /* request */);
Finished();
return;
} }
StartDownload(); StartDownload();
return; return;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment