Commit 2e5437f5 authored by Rayan Kanso's avatar Rayan Kanso Committed by Commit Bot

[Background Fetch] Create pipeline for getting upload data.

This CL takes care of the boilerplate to pass upload data along.
The DownloadService will go through the Data Manager and get the request
body if the request is an upload.

Bug: 1329149
Change-Id: I8ae6664f7b0fe2735451cc5ddf14faa3562c00e1
Reviewed-on: https://chromium-review.googlesource.com/c/1329622
Commit-Queue: Rayan Kanso <rayankans@chromium.org>
Reviewed-by: default avatarAvi Drissman <avi@chromium.org>
Reviewed-by: default avatarPeter Beverloo <peter@chromium.org>
Cr-Commit-Position: refs/heads/master@{#609309}
parent 6c53e238
......@@ -251,7 +251,8 @@ void BackgroundFetchDelegateImpl::DownloadUrl(
const std::string& method,
const GURL& url,
const net::NetworkTrafficAnnotationTag& traffic_annotation,
const net::HttpRequestHeaders& headers) {
const net::HttpRequestHeaders& headers,
bool has_request_body) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
DCHECK(job_details_map_.count(job_unique_id));
DCHECK(!download_job_unique_id_map_.count(download_guid));
......@@ -283,9 +284,9 @@ void BackgroundFetchDelegateImpl::DownloadUrl(
if (job_details.job_state == JobDetails::State::kStartedButPaused) {
job_details.on_resume =
base::BindOnce(&BackgroundFetchDelegateImpl::StartDownload,
GetWeakPtr(), job_unique_id, params);
GetWeakPtr(), job_unique_id, params, has_request_body);
} else {
StartDownload(job_unique_id, params);
StartDownload(job_unique_id, params, has_request_body);
}
UpdateOfflineItemAndUpdateObservers(&job_details);
......@@ -293,10 +294,13 @@ void BackgroundFetchDelegateImpl::DownloadUrl(
void BackgroundFetchDelegateImpl::StartDownload(
const std::string& job_unique_id,
const download::DownloadParams& params) {
const download::DownloadParams& params,
bool has_request_body) {
DCHECK(job_details_map_.count(job_unique_id));
JobDetails& job_details = job_details_map_.find(job_unique_id)->second;
job_details.current_download_guids.insert(params.guid);
job_details.current_fetch_guids.emplace(
params.guid, has_request_body ? JobDetails::UploadData::kIncluded
: JobDetails::UploadData::kAbsent);
GetDownloadService()->StartDownload(params);
}
......@@ -310,9 +314,9 @@ void BackgroundFetchDelegateImpl::Abort(const std::string& job_unique_id) {
JobDetails& job_details = job_details_iter->second;
job_details.job_state = JobDetails::State::kCancelled;
for (const auto& download_guid : job_details.current_download_guids) {
GetDownloadService()->CancelDownload(download_guid);
download_job_unique_id_map_.erase(download_guid);
for (const auto& download_guid_pair : job_details.current_fetch_guids) {
GetDownloadService()->CancelDownload(download_guid_pair.first);
download_job_unique_id_map_.erase(download_guid_pair.first);
}
UpdateOfflineItemAndUpdateObservers(&job_details);
}
......@@ -429,7 +433,7 @@ void BackgroundFetchDelegateImpl::OnDownloadFailed(
std::move(result));
}
job_details.current_download_guids.erase(download_guid);
job_details.current_fetch_guids.erase(download_guid);
download_job_unique_id_map_.erase(download_guid);
}
......@@ -459,8 +463,7 @@ void BackgroundFetchDelegateImpl::OnDownloadSucceeded(
std::move(result));
}
job_details.current_download_guids.erase(
job_details.current_download_guids.find(download_guid));
job_details.current_fetch_guids.erase(download_guid);
download_job_unique_id_map_.erase(download_guid);
}
......@@ -557,8 +560,8 @@ void BackgroundFetchDelegateImpl::PauseDownload(
JobDetails& job_details = job_details_iter->second;
job_details.job_state = JobDetails::State::kStartedButPaused;
job_details.UpdateOfflineItem();
for (auto& download_guid : job_details.current_download_guids)
GetDownloadService()->PauseDownload(download_guid);
for (auto& download_guid_pair : job_details.current_fetch_guids)
GetDownloadService()->PauseDownload(download_guid_pair.first);
}
void BackgroundFetchDelegateImpl::ResumeDownload(
......@@ -571,8 +574,8 @@ void BackgroundFetchDelegateImpl::ResumeDownload(
JobDetails& job_details = job_details_iter->second;
job_details.job_state = JobDetails::State::kStartedAndDownloading;
job_details.UpdateOfflineItem();
for (auto& download_guid : job_details.current_download_guids)
GetDownloadService()->ResumeDownload(download_guid);
for (auto& download_guid_pair : job_details.current_fetch_guids)
GetDownloadService()->ResumeDownload(download_guid_pair.first);
if (job_details.on_resume)
std::move(job_details.on_resume).Run();
......@@ -683,3 +686,22 @@ std::set<std::string> BackgroundFetchDelegateImpl::TakeOutstandingGuids() {
}
return outstanding_guids;
}
void BackgroundFetchDelegateImpl::GetUploadData(
const std::string& download_guid,
download::GetUploadDataCallback callback) {
auto job_it = download_job_unique_id_map_.find(download_guid);
DCHECK(job_it != download_job_unique_id_map_.end());
JobDetails& job_details = job_details_map_.find(job_it->second)->second;
if (job_details.current_fetch_guids[download_guid] ==
JobDetails::UploadData::kAbsent) {
base::SequencedTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(std::move(callback), /* request_body= */ nullptr));
return;
}
if (client())
client()->GetUploadData(job_it->second, download_guid, std::move(callback));
}
......@@ -63,7 +63,8 @@ class BackgroundFetchDelegateImpl
const std::string& method,
const GURL& url,
const net::NetworkTrafficAnnotationTag& traffic_annotation,
const net::HttpRequestHeaders& headers) override;
const net::HttpRequestHeaders& headers,
bool has_request_body) override;
void Abort(const std::string& job_unique_id) override;
void MarkJobComplete(const std::string& job_unique_id) override;
void UpdateUI(const std::string& job_unique_id,
......@@ -118,6 +119,10 @@ class BackgroundFetchDelegateImpl
// GUIDs.
std::set<std::string> TakeOutstandingGuids();
// Gets the upload data, if any, associated with the |download_guid|.
void GetUploadData(const std::string& download_guid,
download::GetUploadDataCallback callback);
base::WeakPtr<BackgroundFetchDelegateImpl> GetWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
}
......@@ -147,10 +152,15 @@ class BackgroundFetchDelegateImpl
void UpdateOfflineItem();
void MarkJobAsStarted();
// Set of DownloadService GUIDs that are currently downloading. They are
// added by DownloadUrl and are removed when the download completes, fails
// or is cancelled.
base::flat_set<std::string> current_download_guids;
enum class UploadData {
kAbsent,
kIncluded,
};
// Set of DownloadService GUIDs that are currently processed. They are
// added by DownloadUrl and are removed when the fetch completes, fails,
// or is cancelled. The GUID maps to whether the fetch has upload data.
std::map<std::string, UploadData> current_fetch_guids;
offline_items_collection::OfflineItem offline_item;
State job_state;
......@@ -168,7 +178,8 @@ class BackgroundFetchDelegateImpl
// Starts a download according to |params| belonging to |job_unique_id|.
void StartDownload(const std::string& job_unique_id,
const download::DownloadParams& params);
const download::DownloadParams& params,
bool has_request_body);
// Updates the OfflineItem that controls the contents of download
// notifications and notifies any OfflineContentProvider::Observer that was
......
......@@ -147,8 +147,7 @@ bool BackgroundFetchDownloadClient::CanServiceRemoveDownloadedFile(
void BackgroundFetchDownloadClient::GetUploadData(
const std::string& guid,
download::GetUploadDataCallback callback) {
base::SequencedTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), nullptr));
GetDelegate()->GetUploadData(guid, std::move(callback));
}
BackgroundFetchDelegateImpl* BackgroundFetchDownloadClient::GetDelegate() {
......
......@@ -156,9 +156,12 @@ class BackgroundFetchDelegateProxy::Core
headers.SetHeader("Origin", origin.Serialize());
}
// TODO(crbug.com/774054): Update |has_request_body| after the cache storage
// supports request bodies.
delegate_->DownloadUrl(job_unique_id, request->download_guid(),
fetch_request.method, fetch_request.url,
traffic_annotation, headers);
traffic_annotation, headers,
/* has_request_body= */ false);
}
void Abort(const std::string& job_unique_id) {
......@@ -201,6 +204,10 @@ class BackgroundFetchDelegateProxy::Core
std::unique_ptr<content::BackgroundFetchResponse> response) override;
void OnUIActivated(const std::string& unique_id) override;
void OnDelegateShutdown() override;
void GetUploadData(
const std::string& job_unique_id,
const std::string& download_guid,
BackgroundFetchDelegate::GetUploadDataCallback callback) override;
private:
// Weak reference to the IO thread outer class that owns us.
......@@ -273,6 +280,31 @@ void BackgroundFetchDelegateProxy::Core::OnDelegateShutdown() {
delegate_ = nullptr;
}
void BackgroundFetchDelegateProxy::Core::GetUploadData(
const std::string& job_unique_id,
const std::string& download_guid,
BackgroundFetchDelegate::GetUploadDataCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// Pass this to the IO thread for processing, but wrap |callback|
// to be posted back to the UI thread when executed.
BackgroundFetchDelegate::GetUploadDataCallback wrapped_callback =
base::BindOnce(
[](BackgroundFetchDelegate::GetUploadDataCallback callback,
scoped_refptr<network::ResourceRequestBody> body) {
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::UI},
base::BindOnce(std::move(callback), std::move(body)));
},
std::move(callback));
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::IO},
base::BindOnce(&BackgroundFetchDelegateProxy::GetUploadData, io_parent_,
job_unique_id, download_guid,
std::move(wrapped_callback)));
}
BackgroundFetchDelegateProxy::JobDetails::JobDetails(
base::WeakPtr<Controller> controller,
std::vector<scoped_refptr<BackgroundFetchRequestInfo>>
......@@ -495,4 +527,17 @@ void BackgroundFetchDelegateProxy::OnDownloadComplete(
job_details.controller->DidCompleteRequest(request_info);
}
void BackgroundFetchDelegateProxy::GetUploadData(
const std::string& job_unique_id,
const std::string& download_guid,
BackgroundFetchDelegate::GetUploadDataCallback callback) {
auto& job_details = job_details_map_.find(job_unique_id)->second;
DCHECK(job_details.controller);
const auto& request =
job_details.current_request_map[download_guid]->fetch_request_ptr();
job_details.controller->GetUploadData(
BackgroundFetchSettledFetch::CloneRequest(request), std::move(callback));
}
} // namespace content
......@@ -52,6 +52,12 @@ class CONTENT_EXPORT BackgroundFetchDelegateProxy {
virtual void AbortFromDelegate(
blink::mojom::BackgroundFetchFailureReason) = 0;
// Called by the delegate when the Download Service is requesting the
// upload data.
virtual void GetUploadData(
blink::mojom::FetchAPIRequestPtr request,
BackgroundFetchDelegate::GetUploadDataCallback callback) = 0;
virtual ~Controller() {}
};
......@@ -143,6 +149,11 @@ class CONTENT_EXPORT BackgroundFetchDelegateProxy {
// Should only be called from the BackgroundFetchDelegate (on the IO thread).
void DidActivateUI(const std::string& job_unique_id);
// Should only be called from the BackgroundFetchDelegate (on the IO thread).
void GetUploadData(const std::string& job_unique_id,
const std::string& download_guid,
BackgroundFetchDelegate::GetUploadDataCallback callback);
std::unique_ptr<Core, BrowserThread::DeleteOnUIThread> ui_core_;
base::WeakPtr<Core> ui_core_ptr_;
......
......@@ -49,7 +49,8 @@ class FakeBackgroundFetchDelegate : public BackgroundFetchDelegate {
const std::string& method,
const GURL& url,
const net::NetworkTrafficAnnotationTag& traffic_annotation,
const net::HttpRequestHeaders& headers) override {
const net::HttpRequestHeaders& headers,
bool has_request_body) override {
if (!client())
return;
......@@ -135,6 +136,10 @@ class FakeController : public BackgroundFetchDelegateProxy::Controller {
void AbortFromDelegate(
blink::mojom::BackgroundFetchFailureReason reason_to_abort) override {}
void GetUploadData(
blink::mojom::FetchAPIRequestPtr request,
BackgroundFetchDelegate::GetUploadDataCallback callback) override {}
bool request_started_ = false;
bool request_completed_ = false;
base::WeakPtrFactory<FakeController> weak_ptr_factory_;
......
......@@ -4,8 +4,10 @@
#include "content/browser/background_fetch/background_fetch_job_controller.h"
#include "content/browser/background_fetch/background_fetch_data_manager.h"
#include "content/browser/background_fetch/background_fetch_request_match_params.h"
#include "content/public/common/origin_util.h"
#include "services/network/public/cpp/cors/cors.h"
#include "services/network/public/cpp/resource_request_body.h"
#include "third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom.h"
#include <utility>
......@@ -295,4 +297,39 @@ void BackgroundFetchJobController::DidMarkRequestAsComplete(
Finish(BackgroundFetchFailureReason::NONE, base::DoNothing());
}
void BackgroundFetchJobController::GetUploadData(
blink::mojom::FetchAPIRequestPtr request,
BackgroundFetchDelegate::GetUploadDataCallback callback) {
data_manager_->MatchRequests(
registration_id(),
std::make_unique<BackgroundFetchRequestMatchParams>(
std::move(request), /* match_params= */ nullptr,
/* match_all= */ false),
base::BindOnce(&BackgroundFetchJobController::DidGetUploadData,
GetWeakPtr(), std::move(callback)));
}
void BackgroundFetchJobController::DidGetUploadData(
BackgroundFetchDelegate::GetUploadDataCallback callback,
BackgroundFetchError error,
std::vector<BackgroundFetchSettledFetch> fetches) {
if (error != BackgroundFetchError::NONE) {
Abort(BackgroundFetchFailureReason::SERVICE_WORKER_UNAVAILABLE,
base::DoNothing());
std::move(callback).Run(/* request_body= */ nullptr);
return;
}
DCHECK_EQ(fetches.size(), 1u);
DCHECK(fetches[0].request->blob);
network::mojom::DataPipeGetterPtr data_pipe_getter_ptr;
blink::mojom::BlobPtr blob_ptr(std::move(fetches[0].request->blob->blob));
blob_ptr->AsDataPipeGetter(MakeRequest(&data_pipe_getter_ptr));
auto request_body = base::MakeRefCounted<network::ResourceRequestBody>();
request_body->AppendDataPipe(std::move(data_pipe_getter_ptr));
std::move(callback).Run(std::move(request_body));
}
} // namespace content
......@@ -109,6 +109,9 @@ class CONTENT_EXPORT BackgroundFetchJobController
const scoped_refptr<BackgroundFetchRequestInfo>& request) override;
void AbortFromDelegate(
blink::mojom::BackgroundFetchFailureReason failure_reason) override;
void GetUploadData(
blink::mojom::FetchAPIRequestPtr request,
BackgroundFetchDelegate::GetUploadDataCallback callback) override;
// Aborts the fetch. |callback| will run with the result of marking the
// registration for deletion.
......@@ -137,6 +140,10 @@ class CONTENT_EXPORT BackgroundFetchJobController
void Finish(blink::mojom::BackgroundFetchFailureReason reason_to_abort,
ErrorCallback callback);
void DidGetUploadData(BackgroundFetchDelegate::GetUploadDataCallback callback,
blink::mojom::BackgroundFetchError error,
std::vector<BackgroundFetchSettledFetch> fetches);
// Manager for interacting with the DB. It is owned by the
// BackgroundFetchContext.
BackgroundFetchDataManager* data_manager_;
......
......@@ -68,6 +68,12 @@ class CONTENT_EXPORT BackgroundFetchRequestInfo
return *fetch_request_;
}
// Returns the Fetch API Request Ptr object that details the developer's
// request.
const blink::mojom::FetchAPIRequestPtr& fetch_request_ptr() const {
return fetch_request_;
}
// Returns the response code for the download. Available for both successful
// and failed requests.
int GetResponseCode() const;
......
......@@ -85,7 +85,8 @@ void MockBackgroundFetchDelegate::DownloadUrl(
const std::string& method,
const GURL& url,
const net::NetworkTrafficAnnotationTag& traffic_annotation,
const net::HttpRequestHeaders& headers) {
const net::HttpRequestHeaders& headers,
bool has_request_body) {
// TODO(delphick): Currently we just disallow re-using GUIDs but later when we
// use the DownloadService, we should signal StartResult::UNEXPECTED_GUID.
DCHECK(seen_guids_.find(guid) == seen_guids_.end());
......
......@@ -81,7 +81,8 @@ class MockBackgroundFetchDelegate : public BackgroundFetchDelegate {
const std::string& method,
const GURL& url,
const net::NetworkTrafficAnnotationTag& traffic_annotation,
const net::HttpRequestHeaders& headers) override;
const net::HttpRequestHeaders& headers,
bool has_request_body) override;
void Abort(const std::string& job_unique_id) override;
void MarkJobComplete(const std::string& job_unique_id) override;
void UpdateUI(const std::string& job_unique_id,
......
......@@ -12,10 +12,12 @@
#include "base/callback_forward.h"
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "content/common/content_export.h"
#include "content/public/browser/resource_request_info.h"
#include "services/network/public/cpp/resource_request_body.h"
#include "third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom.h"
#include "third_party/skia/include/core/SkBitmap.h"
......@@ -23,7 +25,7 @@ class GURL;
namespace gfx {
class Size;
}
} // namespace gfx
namespace net {
class HttpRequestHeaders;
......@@ -60,6 +62,8 @@ class CONTENT_EXPORT BackgroundFetchDelegate {
using GetIconDisplaySizeCallback = base::OnceCallback<void(const gfx::Size&)>;
using GetPermissionForOriginCallback =
base::OnceCallback<void(BackgroundFetchPermission)>;
using GetUploadDataCallback =
base::OnceCallback<void(scoped_refptr<network::ResourceRequestBody>)>;
// Client interface that a BackgroundFetchDelegate would use to signal the
// progress of a background fetch.
......@@ -99,6 +103,12 @@ class CONTENT_EXPORT BackgroundFetchDelegate {
// Called by the delegate when it's shutting down to signal that the
// delegate is no longer valid.
virtual void OnDelegateShutdown() = 0;
// Called by the Download Client when it needs the upload data for
// the given |download_guid|.
virtual void GetUploadData(const std::string& job_unique_id,
const std::string& download_guid,
GetUploadDataCallback callback) = 0;
};
BackgroundFetchDelegate();
......@@ -132,7 +142,8 @@ class CONTENT_EXPORT BackgroundFetchDelegate {
const std::string& method,
const GURL& url,
const net::NetworkTrafficAnnotationTag& traffic_annotation,
const net::HttpRequestHeaders& headers) = 0;
const net::HttpRequestHeaders& headers,
bool has_request_body) = 0;
// Aborts any downloads associated with |job_unique_id|.
virtual void Abort(const std::string& job_unique_id) = 0;
......
......@@ -199,7 +199,8 @@ void LayoutTestBackgroundFetchDelegate::DownloadUrl(
const std::string& method,
const GURL& url,
const net::NetworkTrafficAnnotationTag& traffic_annotation,
const net::HttpRequestHeaders& headers) {
const net::HttpRequestHeaders& headers,
bool has_request_body) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// Lazily create the |download_service_| because only very few layout tests
......
......@@ -38,7 +38,8 @@ class LayoutTestBackgroundFetchDelegate : public BackgroundFetchDelegate {
const std::string& method,
const GURL& url,
const net::NetworkTrafficAnnotationTag& traffic_annotation,
const net::HttpRequestHeaders& headers) override;
const net::HttpRequestHeaders& headers,
bool has_request_body) override;
void Abort(const std::string& job_unique_id) override;
void MarkJobComplete(const std::string& job_unique_id) override;
void UpdateUI(const std::string& job_unique_id,
......
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