File: in_memory_download.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (284 lines) | stat: -rw-r--r-- 9,770 bytes parent folder | download | duplicates (6)
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_