drive_base_requests.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. // Copyright 2021 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. //
  5. // This file provides base classes used to issue HTTP requests for Google
  6. // APIs.
  7. #ifndef GOOGLE_APIS_DRIVE_DRIVE_BASE_REQUESTS_H_
  8. #define GOOGLE_APIS_DRIVE_DRIVE_BASE_REQUESTS_H_
  9. #include <stdint.h>
  10. #include <memory>
  11. #include <string>
  12. #include <utility>
  13. #include <vector>
  14. #include "base/callback.h"
  15. #include "base/files/file_path.h"
  16. #include "base/memory/weak_ptr.h"
  17. #include "base/task/sequenced_task_runner.h"
  18. #include "base/threading/thread_checker.h"
  19. #include "google_apis/common/api_error_codes.h"
  20. #include "google_apis/common/base_requests.h"
  21. #include "services/network/public/cpp/simple_url_loader.h"
  22. #include "services/network/public/cpp/simple_url_loader_stream_consumer.h"
  23. #include "services/network/public/mojom/url_response_head.mojom-forward.h"
  24. #include "url/gurl.h"
  25. namespace base {
  26. class Value;
  27. } // namespace base
  28. namespace google_apis {
  29. class FileResource;
  30. class RequestSender;
  31. // Content type for multipart body.
  32. enum class MultipartType { kRelated, kMixed };
  33. // Pair of content type and data.
  34. struct ContentTypeAndData {
  35. std::string type;
  36. std::string data;
  37. };
  38. // Callback used for requests that the server returns FileResource data
  39. // formatted into JSON value.
  40. typedef base::OnceCallback<void(ApiErrorCode error,
  41. std::unique_ptr<FileResource> entry)>
  42. FileResourceCallback;
  43. // Generate multipart body. If |predetermined_boundary| is not empty, it uses
  44. // the string as boundary. Otherwise it generates random boundary that does not
  45. // conflict with |parts|. If |data_offset| is not nullptr, it stores the
  46. // index of first byte of each part in multipart body.
  47. void GenerateMultipartBody(MultipartType multipart_type,
  48. const std::string& predetermined_boundary,
  49. const std::vector<ContentTypeAndData>& parts,
  50. ContentTypeAndData* output,
  51. std::vector<uint64_t>* data_offset);
  52. //============================ DriveUrlFetchRequestBase =======================
  53. // Base class for Drive requests that are fetching URLs.
  54. class DriveUrlFetchRequestBase : public UrlFetchRequestBase {
  55. public:
  56. DriveUrlFetchRequestBase(const DriveUrlFetchRequestBase&) = delete;
  57. DriveUrlFetchRequestBase& operator=(const DriveUrlFetchRequestBase&) = delete;
  58. protected:
  59. DriveUrlFetchRequestBase(RequestSender* sender,
  60. ProgressCallback upload_progress_callback,
  61. ProgressCallback download_progress_callback);
  62. ~DriveUrlFetchRequestBase() override;
  63. ApiErrorCode MapReasonToError(ApiErrorCode code,
  64. const std::string& reason) override;
  65. bool IsSuccessfulErrorCode(ApiErrorCode error) override;
  66. };
  67. //============================ BatchableDelegate ============================
  68. // Delegate to be used by |SingleBatchableDelegateRequest| and
  69. // |BatchUploadRequest|.
  70. class BatchableDelegate {
  71. public:
  72. virtual ~BatchableDelegate() = default;
  73. // See UrlFetchRequestBase.
  74. virtual GURL GetURL() const = 0;
  75. virtual std::string GetRequestType() const = 0;
  76. virtual std::vector<std::string> GetExtraRequestHeaders() const = 0;
  77. virtual void Prepare(PrepareCallback callback) = 0;
  78. virtual bool GetContentData(std::string* upload_content_type,
  79. std::string* upload_content) = 0;
  80. // Notifies result of the request. Usually, it parses the |code| and
  81. // |response_body|, then notifies the parsed value to client code of the
  82. // API. |callback| must be called on completion. The instance must not
  83. // do anything after calling |callback| since the instance may be deleted in
  84. // |callback|.
  85. virtual void NotifyResult(ApiErrorCode code,
  86. const std::string& response_body,
  87. base::OnceClosure callback) = 0;
  88. // Notifies error. Unlike |NotifyResult|, it must report error
  89. // synchronously. The instance may be deleted just after calling
  90. // NotifyError.
  91. virtual void NotifyError(ApiErrorCode code) = 0;
  92. // Notifies progress.
  93. virtual void NotifyUploadProgress(int64_t current, int64_t total) = 0;
  94. };
  95. //============================ EntryActionRequest ============================
  96. // Callback type for requests that return only error status, like: Delete/Move.
  97. using EntryActionCallback = base::OnceCallback<void(ApiErrorCode error)>;
  98. // This class performs a simple action over a given entry (document/file).
  99. // It is meant to be used for requests that return no JSON blobs.
  100. class EntryActionRequest : public DriveUrlFetchRequestBase {
  101. public:
  102. // |callback| is called when the request is finished either by success or by
  103. // failure. It must not be null.
  104. EntryActionRequest(RequestSender* sender, EntryActionCallback callback);
  105. EntryActionRequest(const EntryActionRequest&) = delete;
  106. EntryActionRequest& operator=(const EntryActionRequest&) = delete;
  107. ~EntryActionRequest() override;
  108. protected:
  109. // Overridden from UrlFetchRequestBase.
  110. void ProcessURLFetchResults(
  111. const network::mojom::URLResponseHead* response_head,
  112. base::FilePath response_file,
  113. std::string response_body) override;
  114. void RunCallbackOnPrematureFailure(ApiErrorCode code) override;
  115. private:
  116. EntryActionCallback callback_;
  117. };
  118. //=========================== InitiateUploadRequestBase=======================
  119. // Callback type for DriveServiceInterface::InitiateUpload.
  120. typedef base::OnceCallback<void(ApiErrorCode error, const GURL& upload_url)>
  121. InitiateUploadCallback;
  122. // This class provides base implementation for performing the request for
  123. // initiating the upload of a file.
  124. // |callback| will be called with the obtained upload URL. The URL will be
  125. // used with requests for resuming the file uploading.
  126. //
  127. // Here's the flow of uploading:
  128. // 1) Get the upload URL with a class inheriting InitiateUploadRequestBase.
  129. // 2) Upload the first 1GB (see kUploadChunkSize in drive_uploader.cc)
  130. // of the target file to the upload URL
  131. // 3) If there is more data to upload, go to 2).
  132. //
  133. class InitiateUploadRequestBase : public DriveUrlFetchRequestBase {
  134. public:
  135. InitiateUploadRequestBase(const InitiateUploadRequestBase&) = delete;
  136. InitiateUploadRequestBase& operator=(const InitiateUploadRequestBase&) =
  137. delete;
  138. protected:
  139. // |callback| will be called with the upload URL, where upload data is
  140. // uploaded to with ResumeUploadRequestBase. It must not be null.
  141. // |content_type| and |content_length| should be the attributes of the
  142. // uploading file.
  143. InitiateUploadRequestBase(RequestSender* sender,
  144. InitiateUploadCallback callback,
  145. const std::string& content_type,
  146. int64_t content_length);
  147. ~InitiateUploadRequestBase() override;
  148. // UrlFetchRequestBase overrides.
  149. void ProcessURLFetchResults(
  150. const network::mojom::URLResponseHead* response_head,
  151. base::FilePath response_file,
  152. std::string response_body) override;
  153. void RunCallbackOnPrematureFailure(ApiErrorCode code) override;
  154. std::vector<std::string> GetExtraRequestHeaders() const override;
  155. private:
  156. InitiateUploadCallback callback_;
  157. const std::string content_type_;
  158. const int64_t content_length_;
  159. };
  160. //========================== UploadRangeRequestBase ==========================
  161. // Struct for response to ResumeUpload and GetUploadStatus.
  162. struct UploadRangeResponse {
  163. UploadRangeResponse();
  164. UploadRangeResponse(ApiErrorCode code,
  165. int64_t start_position_received,
  166. int64_t end_position_received);
  167. ~UploadRangeResponse();
  168. ApiErrorCode code = HTTP_SUCCESS;
  169. // The values of "Range" header returned from the server. The values are
  170. // used to continue uploading more data. These are set to -1 if an upload
  171. // is complete.
  172. // |start_position_received| is inclusive and |end_position_received| is
  173. // exclusive to follow the common C++ manner, although the response from
  174. // the server has "Range" header in inclusive format at both sides.
  175. int64_t start_position_received = 0;
  176. int64_t end_position_received = 0;
  177. };
  178. // Base class for a URL fetch request expecting the response containing the
  179. // current uploading range. This class processes the response containing
  180. // "Range" header and invoke OnRangeRequestComplete.
  181. class UploadRangeRequestBase : public DriveUrlFetchRequestBase {
  182. public:
  183. UploadRangeRequestBase(const UploadRangeRequestBase&) = delete;
  184. UploadRangeRequestBase& operator=(const UploadRangeRequestBase&) = delete;
  185. protected:
  186. // |upload_url| is the URL of where to upload the file to.
  187. UploadRangeRequestBase(RequestSender* sender,
  188. const GURL& upload_url,
  189. ProgressCallback upload_progress_callback);
  190. ~UploadRangeRequestBase() override;
  191. // UrlFetchRequestBase overrides.
  192. GURL GetURL() const override;
  193. std::string GetRequestType() const override;
  194. void ProcessURLFetchResults(
  195. const network::mojom::URLResponseHead* response_head,
  196. base::FilePath response_file,
  197. std::string response_body) override;
  198. void RunCallbackOnPrematureFailure(ApiErrorCode code) override;
  199. // This method will be called when the request is done, regardless of
  200. // whether it is succeeded or failed.
  201. //
  202. // 1) If there is more data to upload, |code| of |response| is set to
  203. // HTTP_RESUME_INCOMPLETE, and positions are set appropriately. Also, |value|
  204. // will be set to NULL.
  205. // 2) If the upload is complete, |code| is set to HTTP_CREATED for a new file
  206. // or HTTP_SUCCESS for an existing file. Positions are set to -1, and |value|
  207. // is set to a parsed JSON value representing the uploaded file.
  208. // 3) If a premature failure is found, |code| is set to a value representing
  209. // the situation. Positions are set to 0, and |value| is set to NULL.
  210. //
  211. // See also the comments for UploadRangeResponse.
  212. // Note: Subclasses should have responsibility to run some callback
  213. // in this method to notify the finish status to its clients (or ignore it
  214. // under its responsibility).
  215. virtual void OnRangeRequestComplete(const UploadRangeResponse& response,
  216. std::unique_ptr<base::Value> value) = 0;
  217. private:
  218. // Called when ParseJson() is completed.
  219. void OnDataParsed(ApiErrorCode code, std::unique_ptr<base::Value> value);
  220. const GURL upload_url_;
  221. // Note: This should remain the last member so it'll be destroyed and
  222. // invalidate its weak pointers before any other members are destroyed.
  223. base::WeakPtrFactory<UploadRangeRequestBase> weak_ptr_factory_{this};
  224. };
  225. //========================== ResumeUploadRequestBase =========================
  226. // This class performs the request for resuming the upload of a file.
  227. // More specifically, this request uploads a chunk of data carried in |buf|
  228. // of ResumeUploadResponseBase. This class is designed to share the
  229. // implementation of upload resuming between GData WAPI and Drive API v2.
  230. // The subclasses should implement OnRangeRequestComplete inherited by
  231. // UploadRangeRequestBase, because the type of the response should be
  232. // different (although the format in the server response is JSON).
  233. class ResumeUploadRequestBase : public UploadRangeRequestBase {
  234. public:
  235. ResumeUploadRequestBase(const ResumeUploadRequestBase&) = delete;
  236. ResumeUploadRequestBase& operator=(const ResumeUploadRequestBase&) = delete;
  237. protected:
  238. // |start_position| is the start of range of contents currently stored in
  239. // |buf|. |end_position| is the end of range of contents currently stared in
  240. // |buf|. This is exclusive. For instance, if you are to upload the first
  241. // 500 bytes of data, |start_position| is 0 and |end_position| is 500.
  242. // |content_length| and |content_type| are the length and type of the
  243. // file content to be uploaded respectively.
  244. // |buf| holds current content to be uploaded.
  245. // See also UploadRangeRequestBase's comment for remaining parameters
  246. // meaning.
  247. ResumeUploadRequestBase(RequestSender* sender,
  248. const GURL& upload_location,
  249. int64_t start_position,
  250. int64_t end_position,
  251. int64_t content_length,
  252. const std::string& content_type,
  253. const base::FilePath& local_file_path,
  254. ProgressCallback progress_callback);
  255. ~ResumeUploadRequestBase() override;
  256. // UrlFetchRequestBase overrides.
  257. std::vector<std::string> GetExtraRequestHeaders() const override;
  258. bool GetContentFile(base::FilePath* local_file_path,
  259. int64_t* range_offset,
  260. int64_t* range_length,
  261. std::string* upload_content_type) override;
  262. private:
  263. // The parameters for the request. See ResumeUploadParams for the details.
  264. const int64_t start_position_;
  265. const int64_t end_position_;
  266. const int64_t content_length_;
  267. const std::string content_type_;
  268. const base::FilePath local_file_path_;
  269. };
  270. //======================== GetUploadStatusRequestBase ========================
  271. // This class performs the request for getting the current upload status
  272. // of a file.
  273. // This request calls OnRangeRequestComplete() with:
  274. // - HTTP_RESUME_INCOMPLETE and the range of previously uploaded data,
  275. // if a file has been partially uploaded. |value| is not used.
  276. // - HTTP_SUCCESS or HTTP_CREATED (up to the upload mode) and |value|
  277. // for the uploaded data, if a file has been completely uploaded.
  278. // See also UploadRangeRequestBase.
  279. class GetUploadStatusRequestBase : public UploadRangeRequestBase {
  280. public:
  281. // |content_length| is the whole data size to be uploaded.
  282. // See also UploadRangeRequestBase's constructor comment for other
  283. // parameters.
  284. GetUploadStatusRequestBase(RequestSender* sender,
  285. const GURL& upload_url,
  286. int64_t content_length);
  287. GetUploadStatusRequestBase(const GetUploadStatusRequestBase&) = delete;
  288. GetUploadStatusRequestBase& operator=(const GetUploadStatusRequestBase&) =
  289. delete;
  290. ~GetUploadStatusRequestBase() override;
  291. protected:
  292. // UrlFetchRequestBase overrides.
  293. std::vector<std::string> GetExtraRequestHeaders() const override;
  294. private:
  295. const int64_t content_length_;
  296. };
  297. //=========================== MultipartUploadRequestBase=======================
  298. // This class provides base implementation for performing the request for
  299. // uploading a file by multipart body.
  300. class MultipartUploadRequestBase : public BatchableDelegate {
  301. public:
  302. MultipartUploadRequestBase(const MultipartUploadRequestBase&) = delete;
  303. MultipartUploadRequestBase& operator=(const MultipartUploadRequestBase&) =
  304. delete;
  305. // Set boundary. Only tests can use this method.
  306. void SetBoundaryForTesting(const std::string& boundary);
  307. protected:
  308. // |callback| will be called with the file resource.upload URL.
  309. // |content_type| and |content_length| should be the attributes of the
  310. // uploading file. Other parameters are optional and can be empty or null
  311. // depending on Upload URL provided by the subclasses.
  312. MultipartUploadRequestBase(base::SequencedTaskRunner* blocking_task_runner,
  313. const std::string& metadata_json,
  314. const std::string& content_type,
  315. int64_t content_length,
  316. const base::FilePath& local_file_path,
  317. FileResourceCallback callback,
  318. ProgressCallback progress_callback);
  319. ~MultipartUploadRequestBase() override;
  320. // BatchableDelegate.
  321. std::vector<std::string> GetExtraRequestHeaders() const override;
  322. void Prepare(PrepareCallback callback) override;
  323. bool GetContentData(std::string* upload_content_type,
  324. std::string* upload_content) override;
  325. void NotifyResult(ApiErrorCode code,
  326. const std::string& body,
  327. base::OnceClosure callback) override;
  328. void NotifyError(ApiErrorCode code) override;
  329. void NotifyUploadProgress(int64_t current, int64_t total) override;
  330. // Parses the response value and invokes |callback_| with |FileResource|.
  331. void OnDataParsed(ApiErrorCode code,
  332. base::OnceClosure callback,
  333. std::unique_ptr<base::Value> value);
  334. private:
  335. // Continues to rest part of |Start| method after determining boundary string
  336. // of multipart/related.
  337. void OnPrepareUploadContent(PrepareCallback callback,
  338. std::string* upload_content_type,
  339. std::string* upload_content_data,
  340. bool result);
  341. scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
  342. const std::string metadata_json_;
  343. const std::string content_type_;
  344. const base::FilePath local_path_;
  345. FileResourceCallback callback_;
  346. const ProgressCallback progress_callback_;
  347. // Boundary of multipart body.
  348. std::string boundary_;
  349. // Upload content of multipart body.
  350. std::string upload_content_type_;
  351. std::string upload_content_data_;
  352. THREAD_CHECKER(thread_checker_);
  353. // Note: This should remain the last member so it'll be destroyed and
  354. // invalidate its weak pointers before any other members are destroyed.
  355. base::WeakPtrFactory<MultipartUploadRequestBase> weak_ptr_factory_{this};
  356. };
  357. //============================ DownloadFileRequest ===========================
  358. // Callback type for receiving the completion of DownloadFileRequest.
  359. typedef base::OnceCallback<void(ApiErrorCode error,
  360. const base::FilePath& temp_file)>
  361. DownloadActionCallback;
  362. // This is a base class for performing the request for downloading a file.
  363. class DownloadFileRequestBase : public DriveUrlFetchRequestBase {
  364. public:
  365. // download_action_callback:
  366. // This callback is called when the download is complete. Must not be null.
  367. //
  368. // get_content_callback:
  369. // This callback is called when some part of the content is
  370. // read. Used to read the download content progressively. May be null.
  371. //
  372. // progress_callback:
  373. // This callback is called for periodically reporting the number of bytes
  374. // downloaded so far. May be null.
  375. //
  376. // download_url:
  377. // Specifies the target file to download.
  378. //
  379. // output_file_path:
  380. // Specifies the file path to save the downloaded file.
  381. //
  382. DownloadFileRequestBase(RequestSender* sender,
  383. DownloadActionCallback download_action_callback,
  384. const GetContentCallback& get_content_callback,
  385. ProgressCallback progress_callback,
  386. const GURL& download_url,
  387. const base::FilePath& output_file_path);
  388. DownloadFileRequestBase(const DownloadFileRequestBase&) = delete;
  389. DownloadFileRequestBase& operator=(const DownloadFileRequestBase&) = delete;
  390. ~DownloadFileRequestBase() override;
  391. protected:
  392. // UrlFetchRequestBase overrides.
  393. GURL GetURL() const override;
  394. void GetOutputFilePath(base::FilePath* local_file_path,
  395. GetContentCallback* get_content_callback) override;
  396. void ProcessURLFetchResults(
  397. const network::mojom::URLResponseHead* response_head,
  398. base::FilePath response_file,
  399. std::string response_body) override;
  400. void RunCallbackOnPrematureFailure(ApiErrorCode code) override;
  401. private:
  402. DownloadActionCallback download_action_callback_;
  403. const GetContentCallback get_content_callback_;
  404. const GURL download_url_;
  405. const base::FilePath output_file_path_;
  406. };
  407. } // namespace google_apis
  408. #endif // GOOGLE_APIS_DRIVE_DRIVE_BASE_REQUESTS_H_