Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1035)

Unified Diff: content/browser/background_fetch/background_fetch_data_manager.cc

Issue 2786783002: Dispatch a bare Service Worker event for a finished Background Fetch (Closed)
Patch Set: Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/background_fetch/background_fetch_data_manager.cc
diff --git a/content/browser/background_fetch/background_fetch_data_manager.cc b/content/browser/background_fetch/background_fetch_data_manager.cc
index c47840865c19b44d5aa6883492bbc4c82e44e7f5..100e67d4631bf6cf5817fcab7d9e2a7dc105197f 100644
--- a/content/browser/background_fetch/background_fetch_data_manager.cc
+++ b/content/browser/background_fetch/background_fetch_data_manager.cc
@@ -4,12 +4,12 @@
#include "content/browser/background_fetch/background_fetch_data_manager.h"
+#include <algorithm>
#include <queue>
#include "base/memory/ptr_util.h"
#include "content/browser/background_fetch/background_fetch_constants.h"
#include "content/browser/background_fetch/background_fetch_context.h"
-#include "content/browser/background_fetch/background_fetch_job_response_data.h"
#include "content/browser/background_fetch/background_fetch_request_info.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/public/browser/blob_handle.h"
@@ -31,35 +31,92 @@ class BackgroundFetchDataManager::RegistrationData {
// Convert the given |requests| to BackgroundFetchRequestInfo objects.
for (const ServiceWorkerFetchRequest& request : requests)
- requests_.emplace(request_index++, request);
+ pending_requests_.emplace(request_index++, request);
}
~RegistrationData() = default;
// Returns whether there are remaining requests on the request queue.
- bool HasPendingRequests() const { return !requests_.empty(); }
+ bool HasPendingRequests() const { return !pending_requests_.empty(); }
// Consumes a request from the queue that is to be fetched.
- BackgroundFetchRequestInfo ConsumeRequest() {
- DCHECK(!requests_.empty());
+ BackgroundFetchRequestInfo GetPendingRequest() {
+ DCHECK(!pending_requests_.empty());
- BackgroundFetchRequestInfo request = requests_.front();
- requests_.pop();
+ BackgroundFetchRequestInfo request = pending_requests_.front();
+ pending_requests_.pop();
+
+ // The |request| is considered to be active now.
+ active_requests_.push_back(request);
return request;
}
+ // Marks the |request| as having started with the given |download_guid|.
+ // Persistent storage needs to store the association so we can resume fetches
+ // after a browser restart, here we just verify that the |request| is active.
+ void MarkRequestAsStarted(const BackgroundFetchRequestInfo& request,
+ const std::string& download_guid) {
+ const auto iter = std::find_if(
+ active_requests_.begin(), active_requests_.end(),
+ [&request](const BackgroundFetchRequestInfo& active_request) {
+ return active_request.request_index() == request.request_index();
+ });
+
+ // The |request| must have been consumed from this RegistrationData.
+ DCHECK(iter != active_requests_.end());
+ }
+
+ // Marks the |request| as having completed. Verifies that the |request| is
+ // currently active and moves it to the |completed_requests_| vector.
+ void MarkRequestAsComplete(const BackgroundFetchRequestInfo& request) {
harkness 2017/03/29 22:12:33 Maybe add the file_path and received_bytes to this
Peter Beverloo 2017/03/29 22:20:28 We'll need much more information, so I'd like thos
+ const auto iter = std::find_if(
+ active_requests_.begin(), active_requests_.end(),
+ [&request](const BackgroundFetchRequestInfo& active_request) {
+ return active_request.request_index() == request.request_index();
+ });
+
+ // The |request| must have been consumed from this RegistrationData.
+ DCHECK(iter != active_requests_.end());
+
+ active_requests_.erase(iter);
+ completed_requests_.push_back(request);
+ }
+
+ // Returns the vector with all completed requests part of this registration.
+ const std::vector<BackgroundFetchRequestInfo>& GetCompletedRequests() const {
+ return completed_requests_;
+ }
+
private:
- std::queue<BackgroundFetchRequestInfo> requests_;
BackgroundFetchOptions options_;
+ // TODO(peter): BackgroundFetchRequestInfo should be stored in a
+ // unique_ptr, owned by the BackgroundFetchJobController. Right now we
+ // can't do that as we need to hold on to copies here.
+ std::queue<BackgroundFetchRequestInfo> pending_requests_;
+ std::vector<BackgroundFetchRequestInfo> active_requests_;
+
+ // TODO(peter): Right now it's safe for this to be a vector because we only
+ // allow a single parallel request. That stops when we start allowing more.
+ static_assert(kMaximumBackgroundFetchParallelRequests == 1,
+ "RegistrationData::completed_requests_ assumes no parallelism");
+
+ std::vector<BackgroundFetchRequestInfo> completed_requests_;
+
DISALLOW_COPY_AND_ASSIGN(RegistrationData);
};
BackgroundFetchDataManager::BackgroundFetchDataManager(
BrowserContext* browser_context)
- : browser_context_(browser_context), weak_ptr_factory_(this) {
- DCHECK(browser_context_);
+ : weak_ptr_factory_(this) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(browser_context);
+
+ // Store the blob storage context for the given |browser_context|.
+ blob_storage_context_ =
+ make_scoped_refptr(ChromeBlobStorageContext::GetFor(browser_context));
+ DCHECK(blob_storage_context_);
}
BackgroundFetchDataManager::~BackgroundFetchDataManager() = default;
@@ -84,7 +141,7 @@ void BackgroundFetchDataManager::CreateRegistration(
if (!registration_data->HasPendingRequests())
break;
- initial_requests.push_back(registration_data->ConsumeRequest());
+ initial_requests.push_back(registration_data->GetPendingRequest());
}
// Store the created |registration_data| so that we can easily access it.
@@ -103,7 +160,8 @@ void BackgroundFetchDataManager::MarkRequestAsStarted(
auto iter = registrations_.find(registration_id);
DCHECK(iter != registrations_.end());
- // TODO(peter): Associate the |download_guid| with the |request|.
+ RegistrationData* registration_data = iter->second.get();
+ registration_data->MarkRequestAsStarted(request, download_guid);
}
void BackgroundFetchDataManager::MarkRequestAsCompleteAndGetNextRequest(
@@ -114,204 +172,82 @@ void BackgroundFetchDataManager::MarkRequestAsCompleteAndGetNextRequest(
DCHECK(iter != registrations_.end());
RegistrationData* registration_data = iter->second.get();
-
- // TODO(peter): Store the |request| with the |registration_data|.
+ registration_data->MarkRequestAsComplete(request);
base::Optional<BackgroundFetchRequestInfo> next_request;
if (registration_data->HasPendingRequests())
- next_request = registration_data->ConsumeRequest();
+ next_request = registration_data->GetPendingRequest();
std::move(callback).Run(next_request);
}
-void BackgroundFetchDataManager::DeleteRegistration(
+void BackgroundFetchDataManager::GetSettledFetchesForRegistration(
const BackgroundFetchRegistrationId& registration_id,
- DeleteRegistrationCallback callback) {
+ SettledFetchesCallback callback) {
auto iter = registrations_.find(registration_id);
- if (iter == registrations_.end()) {
- std::move(callback).Run(blink::mojom::BackgroundFetchError::INVALID_TAG);
- return;
- }
+ DCHECK(iter != registrations_.end());
- registrations_.erase(iter);
+ RegistrationData* registration_data = iter->second.get();
+ DCHECK(!registration_data->HasPendingRequests());
- std::move(callback).Run(blink::mojom::BackgroundFetchError::NONE);
-}
+ const std::vector<BackgroundFetchRequestInfo>& requests =
+ registration_data->GetCompletedRequests();
-void BackgroundFetchDataManager::WriteJobToStorage(
- std::unique_ptr<BackgroundFetchJobInfo> job_info,
- std::vector<std::unique_ptr<BackgroundFetchRequestInfo>> request_infos) {
- // TODO(harkness): Check for job_guid clash.
- const std::string job_guid = job_info->guid();
- job_map_[job_guid] = std::move(job_info);
-
- // Make an explicit copy of the original requests
- // TODO(harkness): Replace this with actually writing to storage.
- std::vector<BackgroundFetchRequestInfo> requests;
- for (const auto& request_info : request_infos) {
- requests.emplace_back(*(request_info.get()));
- }
- request_map_[job_guid] = std::move(requests);
+ std::vector<BackgroundFetchSettledFetch> settled_fetches;
+ settled_fetches.reserve(requests.size());
- // |request_infos| will be destroyed when it leaves scope here.
-}
+ std::vector<std::unique_ptr<BlobHandle>> blob_handles;
-void BackgroundFetchDataManager::WriteRequestToStorage(
- const std::string& job_guid,
- BackgroundFetchRequestInfo* request_info) {
- std::vector<BackgroundFetchRequestInfo>& request_infos =
- request_map_[job_guid];
+ for (const auto& request : requests) {
+ BackgroundFetchSettledFetch settled_fetch;
+ settled_fetch.request = request.fetch_request();
- // Copy the updated |request_info| over the in-memory version.
- for (size_t i = 0; i < request_infos.size(); i++) {
- if (request_infos[i].guid() == request_info->guid())
- request_infos[i] = *request_info;
- }
-}
+ settled_fetch.response.url_list.push_back(request.GetURL());
+ // TODO: settled_fetch.response.status_code
+ // TODO: settled_fetch.response.status_text
+ // TODO: settled_fetch.response.response_type
+ // TODO: settled_fetch.response.headers
-std::unique_ptr<BackgroundFetchRequestInfo>
-BackgroundFetchDataManager::GetRequestInfo(const std::string& job_guid,
- size_t request_index) {
- // Explicitly create a copy. When this is persisted to StorageWorkerStorage,
- // the request_map_ will not exist.
- auto iter = request_map_.find(job_guid);
- DCHECK(iter != request_map_.end());
- const std::vector<BackgroundFetchRequestInfo>& request_infos = iter->second;
-
- DCHECK(request_index <= request_infos.size());
- return base::MakeUnique<BackgroundFetchRequestInfo>(
- request_infos[request_index]);
-}
+ if (request.received_bytes() > 0) {
+ DCHECK(!request.file_path().empty());
-void BackgroundFetchDataManager::GetJobResponse(
- const std::string& job_guid,
- const BackgroundFetchResponseCompleteCallback& callback) {
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&ChromeBlobStorageContext::GetFor, browser_context_),
- base::Bind(&BackgroundFetchDataManager::DidGetBlobStorageContext,
- weak_ptr_factory_.GetWeakPtr(), job_guid, callback));
-}
+ std::unique_ptr<BlobHandle> blob_handle =
+ blob_storage_context_->CreateFileBackedBlob(
+ request.file_path(), 0 /* offset */, request.received_bytes(),
+ base::Time() /* expected_modification_time */);
-void BackgroundFetchDataManager::DidGetBlobStorageContext(
- const std::string& job_guid,
- const BackgroundFetchResponseCompleteCallback& callback,
- ChromeBlobStorageContext* blob_context) {
- DCHECK(blob_context);
- BackgroundFetchJobInfo* job_info = job_map_[job_guid].get();
- DCHECK(job_info);
-
- // Create a BackgroundFetchJobResponseData object which will aggregate
- // together the response blobs.
- job_info->set_job_response_data(
- base::MakeUnique<BackgroundFetchJobResponseData>(job_info->num_requests(),
- callback));
- BackgroundFetchJobResponseData* job_response_data =
- job_info->job_response_data();
- DCHECK(job_response_data);
-
- // Iterate over the requests and create blobs for each response.
- for (size_t request_index = 0; request_index < job_info->num_requests();
- request_index++) {
- // TODO(harkness): This will need to be asynchronous.
- std::unique_ptr<BackgroundFetchRequestInfo> request_info =
- GetRequestInfo(job_guid, request_index);
-
- // TODO(harkness): Only create a blob response if the request was
- // successful. Otherwise create an error response.
- std::unique_ptr<BlobHandle> blob_handle =
- blob_context->CreateFileBackedBlob(
- request_info->file_path(), 0 /* offset */,
- request_info->received_bytes(),
- base::Time() /* expected_modification_time */);
-
- job_response_data->AddResponse(*request_info.get(), std::move(blob_handle));
- }
-}
+ // TODO(peter): Appropriately handle !blob_handle
+ if (blob_handle) {
+ settled_fetch.response.blob_uuid = blob_handle->GetUUID();
+ settled_fetch.response.blob_size = request.received_bytes();
-bool BackgroundFetchDataManager::UpdateRequestState(
- const std::string& job_guid,
- const std::string& request_guid,
- DownloadItem::DownloadState state,
- DownloadInterruptReason interrupt_reason) {
- // Find the request and set the state and the interrupt reason.
- BackgroundFetchJobInfo* job_info = job_map_[job_guid].get();
- DCHECK(job_info);
- BackgroundFetchRequestInfo* request =
- job_info->GetActiveRequest(request_guid);
- DCHECK(request);
- request->set_state(state);
- request->set_interrupt_reason(interrupt_reason);
-
- // If the request is now finished, remove it from the active requests.
- switch (state) {
- case DownloadItem::DownloadState::COMPLETE:
- case DownloadItem::DownloadState::CANCELLED:
- WriteRequestToStorage(job_guid, request);
- job_info->RemoveActiveRequest(request_guid);
- break;
- case DownloadItem::DownloadState::IN_PROGRESS:
- case DownloadItem::DownloadState::INTERRUPTED:
- case DownloadItem::DownloadState::MAX_DOWNLOAD_STATE:
- break;
- }
+ blob_handles.push_back(std::move(blob_handle));
+ }
+ }
- // Return a boolean indicating whether there are more requests to be
- // processed.
- return job_info->HasRequestsRemaining();
-}
+ // TODO: settled_fetch.response.error
+ // TODO: settled_fetch.response.response_time
+ // TODO: settled_fetch.response.cors_exposed_header_names
-void BackgroundFetchDataManager::UpdateRequestStorageState(
- const std::string& job_guid,
- const std::string& request_guid,
- const base::FilePath& file_path,
- int64_t received_bytes) {
- BackgroundFetchJobInfo* job_info = job_map_[job_guid].get();
- DCHECK(job_info);
- BackgroundFetchRequestInfo* request =
- job_info->GetActiveRequest(request_guid);
- DCHECK(request);
- request->set_file_path(file_path);
- request->set_received_bytes(received_bytes);
-}
+ settled_fetches.push_back(settled_fetch);
+ }
-const BackgroundFetchRequestInfo&
-BackgroundFetchDataManager::GetNextBackgroundFetchRequestInfo(
- const std::string& job_guid) {
- BackgroundFetchJobInfo* job_info = job_map_[job_guid].get();
- DCHECK(job_info);
-
- // TODO(harkness): This needs to be async when it queries real storage.
- std::unique_ptr<BackgroundFetchRequestInfo> request_info =
- GetRequestInfo(job_guid, job_info->next_request_index());
- const std::string request_guid = request_info->guid();
- job_info->AddActiveRequest(std::move(request_info));
- return *job_info->GetActiveRequest(request_guid);
+ std::move(callback).Run(blink::mojom::BackgroundFetchError::NONE,
+ std::move(settled_fetches), std::move(blob_handles));
}
-bool BackgroundFetchDataManager::IsComplete(const std::string& job_guid) const {
- auto iter = job_map_.find(job_guid);
- DCHECK(iter != job_map_.end());
- return iter->second->IsComplete();
-}
+void BackgroundFetchDataManager::DeleteRegistration(
+ const BackgroundFetchRegistrationId& registration_id,
+ DeleteRegistrationCallback callback) {
+ auto iter = registrations_.find(registration_id);
+ if (iter == registrations_.end()) {
+ std::move(callback).Run(blink::mojom::BackgroundFetchError::INVALID_TAG);
+ return;
+ }
-bool BackgroundFetchDataManager::HasRequestsRemaining(
- const std::string& job_guid) const {
- auto iter = job_map_.find(job_guid);
- DCHECK(iter != job_map_.end());
- return iter->second->HasRequestsRemaining();
-}
+ registrations_.erase(iter);
-void BackgroundFetchDataManager::UpdateRequestDownloadGuid(
- const std::string& job_guid,
- const std::string& request_guid,
- const std::string& download_guid) {
- BackgroundFetchJobInfo* job_info = job_map_[job_guid].get();
- DCHECK(job_info);
- BackgroundFetchRequestInfo* request =
- job_info->GetActiveRequest(request_guid);
- DCHECK(request);
- request->set_download_guid(download_guid);
+ std::move(callback).Run(blink::mojom::BackgroundFetchError::NONE);
}
} // namespace content

Powered by Google App Engine
This is Rietveld 408576698