1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284
|
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_IN_MEMORY_DOWNLOAD_H_
#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_IN_MEMORY_DOWNLOAD_H_
#include <memory>
#include <string>
#include <string_view>
#include <vector>
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/task/single_thread_task_runner.h"
#include "base/time/time.h"
#include "components/download/internal/background_service/blob_task_proxy.h"
#include "components/download/public/background_service/blob_context_getter_factory.h"
#include "components/download/public/background_service/download_params.h"
#include "components/download/public/background_service/url_loader_factory_getter.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "services/network/public/cpp/simple_url_loader_stream_consumer.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "services/network/public/mojom/url_response_head.mojom-forward.h"
class GURL;
namespace net {
struct NetworkTrafficAnnotationTag;
} // namespace net
namespace storage {
class BlobDataHandle;
} // namespace storage
namespace download {
struct RequestParams;
// Class to start a single download and hold in-memory download data.
// Used by download service in Incognito mode, where download files shouldn't
// be persisted to disk.
//
// Life cycle: The object is created before sending the network request.
// Call Start() to retrieve the blob storage context and send the network
// request.
class InMemoryDownload {
public:
class Delegate {
public:
// Report download progress with in-memory download backend.
virtual void OnDownloadStarted(InMemoryDownload* download) = 0;
virtual void OnDownloadProgress(InMemoryDownload* download) = 0;
virtual void OnDownloadComplete(InMemoryDownload* download) = 0;
virtual void OnUploadProgress(InMemoryDownload* download) = 0;
// Retrieves the blob storage context getter.
virtual void RetrieveBlobContextGetter(
BlobContextGetterCallback callback) = 0;
// Retrieves browser context specific URLLoaderFactory
virtual void RetrievedURLLoaderFactory(
URLLoaderFactoryGetterCallback callback) = 0;
protected:
virtual ~Delegate() = default;
};
// Factory to create in memory download.
class Factory {
public:
virtual std::unique_ptr<InMemoryDownload> Create(
const std::string& guid,
const RequestParams& request_params,
scoped_refptr<network::ResourceRequestBody> request_body,
const net::NetworkTrafficAnnotationTag& traffic_annotation,
Delegate* delegate) = 0;
virtual ~Factory() = default;
};
// States of the download.
enum class State {
// The object is just created.
INITIAL,
// Waiting to retrieve URLLoaderFactory.
RETRIEVE_URL_LOADER_FACTIORY,
// Waiting to retrieve BlobStorageContextGetter.
RETRIEVE_BLOB_CONTEXT,
// Download is in progress, including the following procedures.
// 1. Send the network request and transfer data from network.
// 2. Save the data to blob storage.
IN_PROGRESS,
// The download can fail due to:
// 1. network layer failure or unsuccessful HTTP server response code.
// 2. Blob system failures after blob construction is done.
FAILED,
// Download is completed, and data is successfully saved as a blob.
// Guarantee the blob is fully constructed.
COMPLETE,
};
InMemoryDownload(const InMemoryDownload&) = delete;
InMemoryDownload& operator=(const InMemoryDownload&) = delete;
virtual ~InMemoryDownload();
// Send the download request.
virtual void Start() = 0;
// Pause the download request.
virtual void Pause() = 0;
// Resume the download request.
virtual void Resume() = 0;
// Get a copy of blob data handle.
virtual std::unique_ptr<storage::BlobDataHandle> ResultAsBlob() const = 0;
// Returns the estimate of dynamically allocated memory in bytes.
virtual size_t EstimateMemoryUsage() const = 0;
const std::string& guid() const { return guid_; }
uint64_t bytes_downloaded() const { return bytes_downloaded_; }
State state() const { return state_; }
bool paused() const { return paused_; }
const base::Time& completion_time() const { return completion_time_; }
const std::vector<GURL>& url_chain() const { return url_chain_; }
scoped_refptr<const net::HttpResponseHeaders> response_headers() const {
return response_headers_;
}
uint64_t bytes_uploaded() const { return bytes_uploaded_; }
protected:
InMemoryDownload(const std::string& guid);
// GUID of the download.
const std::string guid_;
State state_;
// If the download is paused.
bool paused_;
// Completion time of download when data is saved as blob.
base::Time completion_time_;
// The URL request chain of this download.
std::vector<GURL> url_chain_;
// HTTP response headers.
scoped_refptr<const net::HttpResponseHeaders> response_headers_;
uint64_t bytes_downloaded_;
uint64_t bytes_uploaded_;
};
// Implementation of InMemoryDownload and uses SimpleURLLoader as network
// backend.
// Threading contract:
// 1. This object lives on the main thread.
// 2. Reading/writing IO buffer from network is done on another thread,
// based on |request_context_getter_|. When complete, main thread is notified.
// 3. After network IO is done, Blob related work is done on IO thread with
// |blob_task_proxy_|, then notify the result to main thread.
class InMemoryDownloadImpl : public network::SimpleURLLoaderStreamConsumer,
public InMemoryDownload {
public:
InMemoryDownloadImpl(
const std::string& guid,
const RequestParams& request_params,
scoped_refptr<network::ResourceRequestBody> request_body,
const net::NetworkTrafficAnnotationTag& traffic_annotation,
Delegate* delegate,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
InMemoryDownloadImpl(const InMemoryDownloadImpl&) = delete;
InMemoryDownloadImpl& operator=(const InMemoryDownloadImpl&) = delete;
~InMemoryDownloadImpl() override;
private:
// InMemoryDownload implementation.
void Start() override;
void Pause() override;
void Resume() override;
// Called when browser context specific URLLoaderFactory is ready to use.
void OnRetrievedURLLoaderFactory(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
// Called when the BlobStorageContextGetter is ready to use.
void OnRetrievedBlobContextGetter(BlobContextGetter blob_context_getter);
std::unique_ptr<storage::BlobDataHandle> ResultAsBlob() const override;
size_t EstimateMemoryUsage() const override;
// network::SimpleURLLoaderStreamConsumer implementation.
void OnDataReceived(std::string_view string_piece,
base::OnceClosure resume) override;
void OnComplete(bool success) override;
void OnRetry(base::OnceClosure start_retry) override;
// Saves the download data into blob storage.
void SaveAsBlob();
void OnSaveBlobDone(std::unique_ptr<storage::BlobDataHandle> blob_handle,
storage::BlobStatus status);
// Notifies the delegate about completion. Can be called multiple times and
// |completion_notified_| will ensure the delegate only receive one completion
// call.
void NotifyDelegateDownloadComplete();
// Sends a new network request.
void SendRequest();
// Called when the server redirects to another URL.
void OnRedirect(const GURL& url_before_redirect,
const net::RedirectInfo& redirect_info,
const network::mojom::URLResponseHead& response_head,
std::vector<std::string>* to_be_removed_headers);
// Called when the response of the final URL is received.
void OnResponseStarted(const GURL& final_url,
const network::mojom::URLResponseHead& response_head);
void OnUploadProgress(uint64_t position, uint64_t total);
// Resets local states.
void Reset();
// Request parameters of the download.
const RequestParams request_params_;
// The request body to upload (if any).
scoped_refptr<network::ResourceRequestBody> request_body_;
// Traffic annotation of the request.
const net::NetworkTrafficAnnotationTag traffic_annotation_;
// Used to send requests to servers.
std::unique_ptr<network::SimpleURLLoader> loader_;
// Used to handle network response.
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
// Worker that does blob related task on IO thread.
std::unique_ptr<BlobTaskProxy> blob_task_proxy_;
// Owned blob data handle, so that blob system keeps at least one reference
// count of the underlying data.
std::unique_ptr<storage::BlobDataHandle> blob_data_handle_;
// Used to access blob storage context.
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
raw_ptr<Delegate, DanglingUntriaged> delegate_;
// Data downloaded from network, should be moved to avoid extra copy.
std::string data_;
// Cached callback to let network backend continue to pull data.
base::OnceClosure resume_callback_;
// Ensures Delegate::OnDownloadComplete is only called once.
bool completion_notified_;
// If |OnResponseStarted| is called.
bool started_;
// Bounded to main thread task runner.
base::WeakPtrFactory<InMemoryDownloadImpl> weak_ptr_factory_{this};
};
} // namespace download
#endif // COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_IN_MEMORY_DOWNLOAD_H_
|