123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478 |
- // Copyright 2021 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- //
- // This file provides base classes used to issue HTTP requests for Google
- // APIs.
- #ifndef GOOGLE_APIS_DRIVE_DRIVE_BASE_REQUESTS_H_
- #define GOOGLE_APIS_DRIVE_DRIVE_BASE_REQUESTS_H_
- #include <stdint.h>
- #include <memory>
- #include <string>
- #include <utility>
- #include <vector>
- #include "base/callback.h"
- #include "base/files/file_path.h"
- #include "base/memory/weak_ptr.h"
- #include "base/task/sequenced_task_runner.h"
- #include "base/threading/thread_checker.h"
- #include "google_apis/common/api_error_codes.h"
- #include "google_apis/common/base_requests.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_response_head.mojom-forward.h"
- #include "url/gurl.h"
- namespace base {
- class Value;
- } // namespace base
- namespace google_apis {
- class FileResource;
- class RequestSender;
- // Content type for multipart body.
- enum class MultipartType { kRelated, kMixed };
- // Pair of content type and data.
- struct ContentTypeAndData {
- std::string type;
- std::string data;
- };
- // Callback used for requests that the server returns FileResource data
- // formatted into JSON value.
- typedef base::OnceCallback<void(ApiErrorCode error,
- std::unique_ptr<FileResource> entry)>
- FileResourceCallback;
- // Generate multipart body. If |predetermined_boundary| is not empty, it uses
- // the string as boundary. Otherwise it generates random boundary that does not
- // conflict with |parts|. If |data_offset| is not nullptr, it stores the
- // index of first byte of each part in multipart body.
- void GenerateMultipartBody(MultipartType multipart_type,
- const std::string& predetermined_boundary,
- const std::vector<ContentTypeAndData>& parts,
- ContentTypeAndData* output,
- std::vector<uint64_t>* data_offset);
- //============================ DriveUrlFetchRequestBase =======================
- // Base class for Drive requests that are fetching URLs.
- class DriveUrlFetchRequestBase : public UrlFetchRequestBase {
- public:
- DriveUrlFetchRequestBase(const DriveUrlFetchRequestBase&) = delete;
- DriveUrlFetchRequestBase& operator=(const DriveUrlFetchRequestBase&) = delete;
- protected:
- DriveUrlFetchRequestBase(RequestSender* sender,
- ProgressCallback upload_progress_callback,
- ProgressCallback download_progress_callback);
- ~DriveUrlFetchRequestBase() override;
- ApiErrorCode MapReasonToError(ApiErrorCode code,
- const std::string& reason) override;
- bool IsSuccessfulErrorCode(ApiErrorCode error) override;
- };
- //============================ BatchableDelegate ============================
- // Delegate to be used by |SingleBatchableDelegateRequest| and
- // |BatchUploadRequest|.
- class BatchableDelegate {
- public:
- virtual ~BatchableDelegate() = default;
- // See UrlFetchRequestBase.
- virtual GURL GetURL() const = 0;
- virtual std::string GetRequestType() const = 0;
- virtual std::vector<std::string> GetExtraRequestHeaders() const = 0;
- virtual void Prepare(PrepareCallback callback) = 0;
- virtual bool GetContentData(std::string* upload_content_type,
- std::string* upload_content) = 0;
- // Notifies result of the request. Usually, it parses the |code| and
- // |response_body|, then notifies the parsed value to client code of the
- // API. |callback| must be called on completion. The instance must not
- // do anything after calling |callback| since the instance may be deleted in
- // |callback|.
- virtual void NotifyResult(ApiErrorCode code,
- const std::string& response_body,
- base::OnceClosure callback) = 0;
- // Notifies error. Unlike |NotifyResult|, it must report error
- // synchronously. The instance may be deleted just after calling
- // NotifyError.
- virtual void NotifyError(ApiErrorCode code) = 0;
- // Notifies progress.
- virtual void NotifyUploadProgress(int64_t current, int64_t total) = 0;
- };
- //============================ EntryActionRequest ============================
- // Callback type for requests that return only error status, like: Delete/Move.
- using EntryActionCallback = base::OnceCallback<void(ApiErrorCode error)>;
- // This class performs a simple action over a given entry (document/file).
- // It is meant to be used for requests that return no JSON blobs.
- class EntryActionRequest : public DriveUrlFetchRequestBase {
- public:
- // |callback| is called when the request is finished either by success or by
- // failure. It must not be null.
- EntryActionRequest(RequestSender* sender, EntryActionCallback callback);
- EntryActionRequest(const EntryActionRequest&) = delete;
- EntryActionRequest& operator=(const EntryActionRequest&) = delete;
- ~EntryActionRequest() override;
- protected:
- // Overridden from UrlFetchRequestBase.
- void ProcessURLFetchResults(
- const network::mojom::URLResponseHead* response_head,
- base::FilePath response_file,
- std::string response_body) override;
- void RunCallbackOnPrematureFailure(ApiErrorCode code) override;
- private:
- EntryActionCallback callback_;
- };
- //=========================== InitiateUploadRequestBase=======================
- // Callback type for DriveServiceInterface::InitiateUpload.
- typedef base::OnceCallback<void(ApiErrorCode error, const GURL& upload_url)>
- InitiateUploadCallback;
- // This class provides base implementation for performing the request for
- // initiating the upload of a file.
- // |callback| will be called with the obtained upload URL. The URL will be
- // used with requests for resuming the file uploading.
- //
- // Here's the flow of uploading:
- // 1) Get the upload URL with a class inheriting InitiateUploadRequestBase.
- // 2) Upload the first 1GB (see kUploadChunkSize in drive_uploader.cc)
- // of the target file to the upload URL
- // 3) If there is more data to upload, go to 2).
- //
- class InitiateUploadRequestBase : public DriveUrlFetchRequestBase {
- public:
- InitiateUploadRequestBase(const InitiateUploadRequestBase&) = delete;
- InitiateUploadRequestBase& operator=(const InitiateUploadRequestBase&) =
- delete;
- protected:
- // |callback| will be called with the upload URL, where upload data is
- // uploaded to with ResumeUploadRequestBase. It must not be null.
- // |content_type| and |content_length| should be the attributes of the
- // uploading file.
- InitiateUploadRequestBase(RequestSender* sender,
- InitiateUploadCallback callback,
- const std::string& content_type,
- int64_t content_length);
- ~InitiateUploadRequestBase() override;
- // UrlFetchRequestBase overrides.
- void ProcessURLFetchResults(
- const network::mojom::URLResponseHead* response_head,
- base::FilePath response_file,
- std::string response_body) override;
- void RunCallbackOnPrematureFailure(ApiErrorCode code) override;
- std::vector<std::string> GetExtraRequestHeaders() const override;
- private:
- InitiateUploadCallback callback_;
- const std::string content_type_;
- const int64_t content_length_;
- };
- //========================== UploadRangeRequestBase ==========================
- // Struct for response to ResumeUpload and GetUploadStatus.
- struct UploadRangeResponse {
- UploadRangeResponse();
- UploadRangeResponse(ApiErrorCode code,
- int64_t start_position_received,
- int64_t end_position_received);
- ~UploadRangeResponse();
- ApiErrorCode code = HTTP_SUCCESS;
- // The values of "Range" header returned from the server. The values are
- // used to continue uploading more data. These are set to -1 if an upload
- // is complete.
- // |start_position_received| is inclusive and |end_position_received| is
- // exclusive to follow the common C++ manner, although the response from
- // the server has "Range" header in inclusive format at both sides.
- int64_t start_position_received = 0;
- int64_t end_position_received = 0;
- };
- // Base class for a URL fetch request expecting the response containing the
- // current uploading range. This class processes the response containing
- // "Range" header and invoke OnRangeRequestComplete.
- class UploadRangeRequestBase : public DriveUrlFetchRequestBase {
- public:
- UploadRangeRequestBase(const UploadRangeRequestBase&) = delete;
- UploadRangeRequestBase& operator=(const UploadRangeRequestBase&) = delete;
- protected:
- // |upload_url| is the URL of where to upload the file to.
- UploadRangeRequestBase(RequestSender* sender,
- const GURL& upload_url,
- ProgressCallback upload_progress_callback);
- ~UploadRangeRequestBase() override;
- // UrlFetchRequestBase overrides.
- GURL GetURL() const override;
- std::string GetRequestType() const override;
- void ProcessURLFetchResults(
- const network::mojom::URLResponseHead* response_head,
- base::FilePath response_file,
- std::string response_body) override;
- void RunCallbackOnPrematureFailure(ApiErrorCode code) override;
- // This method will be called when the request is done, regardless of
- // whether it is succeeded or failed.
- //
- // 1) If there is more data to upload, |code| of |response| is set to
- // HTTP_RESUME_INCOMPLETE, and positions are set appropriately. Also, |value|
- // will be set to NULL.
- // 2) If the upload is complete, |code| is set to HTTP_CREATED for a new file
- // or HTTP_SUCCESS for an existing file. Positions are set to -1, and |value|
- // is set to a parsed JSON value representing the uploaded file.
- // 3) If a premature failure is found, |code| is set to a value representing
- // the situation. Positions are set to 0, and |value| is set to NULL.
- //
- // See also the comments for UploadRangeResponse.
- // Note: Subclasses should have responsibility to run some callback
- // in this method to notify the finish status to its clients (or ignore it
- // under its responsibility).
- virtual void OnRangeRequestComplete(const UploadRangeResponse& response,
- std::unique_ptr<base::Value> value) = 0;
- private:
- // Called when ParseJson() is completed.
- void OnDataParsed(ApiErrorCode code, std::unique_ptr<base::Value> value);
- const GURL upload_url_;
- // Note: This should remain the last member so it'll be destroyed and
- // invalidate its weak pointers before any other members are destroyed.
- base::WeakPtrFactory<UploadRangeRequestBase> weak_ptr_factory_{this};
- };
- //========================== ResumeUploadRequestBase =========================
- // This class performs the request for resuming the upload of a file.
- // More specifically, this request uploads a chunk of data carried in |buf|
- // of ResumeUploadResponseBase. This class is designed to share the
- // implementation of upload resuming between GData WAPI and Drive API v2.
- // The subclasses should implement OnRangeRequestComplete inherited by
- // UploadRangeRequestBase, because the type of the response should be
- // different (although the format in the server response is JSON).
- class ResumeUploadRequestBase : public UploadRangeRequestBase {
- public:
- ResumeUploadRequestBase(const ResumeUploadRequestBase&) = delete;
- ResumeUploadRequestBase& operator=(const ResumeUploadRequestBase&) = delete;
- protected:
- // |start_position| is the start of range of contents currently stored in
- // |buf|. |end_position| is the end of range of contents currently stared in
- // |buf|. This is exclusive. For instance, if you are to upload the first
- // 500 bytes of data, |start_position| is 0 and |end_position| is 500.
- // |content_length| and |content_type| are the length and type of the
- // file content to be uploaded respectively.
- // |buf| holds current content to be uploaded.
- // See also UploadRangeRequestBase's comment for remaining parameters
- // meaning.
- ResumeUploadRequestBase(RequestSender* sender,
- const GURL& upload_location,
- int64_t start_position,
- int64_t end_position,
- int64_t content_length,
- const std::string& content_type,
- const base::FilePath& local_file_path,
- ProgressCallback progress_callback);
- ~ResumeUploadRequestBase() override;
- // UrlFetchRequestBase overrides.
- std::vector<std::string> GetExtraRequestHeaders() const override;
- bool GetContentFile(base::FilePath* local_file_path,
- int64_t* range_offset,
- int64_t* range_length,
- std::string* upload_content_type) override;
- private:
- // The parameters for the request. See ResumeUploadParams for the details.
- const int64_t start_position_;
- const int64_t end_position_;
- const int64_t content_length_;
- const std::string content_type_;
- const base::FilePath local_file_path_;
- };
- //======================== GetUploadStatusRequestBase ========================
- // This class performs the request for getting the current upload status
- // of a file.
- // This request calls OnRangeRequestComplete() with:
- // - HTTP_RESUME_INCOMPLETE and the range of previously uploaded data,
- // if a file has been partially uploaded. |value| is not used.
- // - HTTP_SUCCESS or HTTP_CREATED (up to the upload mode) and |value|
- // for the uploaded data, if a file has been completely uploaded.
- // See also UploadRangeRequestBase.
- class GetUploadStatusRequestBase : public UploadRangeRequestBase {
- public:
- // |content_length| is the whole data size to be uploaded.
- // See also UploadRangeRequestBase's constructor comment for other
- // parameters.
- GetUploadStatusRequestBase(RequestSender* sender,
- const GURL& upload_url,
- int64_t content_length);
- GetUploadStatusRequestBase(const GetUploadStatusRequestBase&) = delete;
- GetUploadStatusRequestBase& operator=(const GetUploadStatusRequestBase&) =
- delete;
- ~GetUploadStatusRequestBase() override;
- protected:
- // UrlFetchRequestBase overrides.
- std::vector<std::string> GetExtraRequestHeaders() const override;
- private:
- const int64_t content_length_;
- };
- //=========================== MultipartUploadRequestBase=======================
- // This class provides base implementation for performing the request for
- // uploading a file by multipart body.
- class MultipartUploadRequestBase : public BatchableDelegate {
- public:
- MultipartUploadRequestBase(const MultipartUploadRequestBase&) = delete;
- MultipartUploadRequestBase& operator=(const MultipartUploadRequestBase&) =
- delete;
- // Set boundary. Only tests can use this method.
- void SetBoundaryForTesting(const std::string& boundary);
- protected:
- // |callback| will be called with the file resource.upload URL.
- // |content_type| and |content_length| should be the attributes of the
- // uploading file. Other parameters are optional and can be empty or null
- // depending on Upload URL provided by the subclasses.
- MultipartUploadRequestBase(base::SequencedTaskRunner* blocking_task_runner,
- const std::string& metadata_json,
- const std::string& content_type,
- int64_t content_length,
- const base::FilePath& local_file_path,
- FileResourceCallback callback,
- ProgressCallback progress_callback);
- ~MultipartUploadRequestBase() override;
- // BatchableDelegate.
- std::vector<std::string> GetExtraRequestHeaders() const override;
- void Prepare(PrepareCallback callback) override;
- bool GetContentData(std::string* upload_content_type,
- std::string* upload_content) override;
- void NotifyResult(ApiErrorCode code,
- const std::string& body,
- base::OnceClosure callback) override;
- void NotifyError(ApiErrorCode code) override;
- void NotifyUploadProgress(int64_t current, int64_t total) override;
- // Parses the response value and invokes |callback_| with |FileResource|.
- void OnDataParsed(ApiErrorCode code,
- base::OnceClosure callback,
- std::unique_ptr<base::Value> value);
- private:
- // Continues to rest part of |Start| method after determining boundary string
- // of multipart/related.
- void OnPrepareUploadContent(PrepareCallback callback,
- std::string* upload_content_type,
- std::string* upload_content_data,
- bool result);
- scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
- const std::string metadata_json_;
- const std::string content_type_;
- const base::FilePath local_path_;
- FileResourceCallback callback_;
- const ProgressCallback progress_callback_;
- // Boundary of multipart body.
- std::string boundary_;
- // Upload content of multipart body.
- std::string upload_content_type_;
- std::string upload_content_data_;
- THREAD_CHECKER(thread_checker_);
- // Note: This should remain the last member so it'll be destroyed and
- // invalidate its weak pointers before any other members are destroyed.
- base::WeakPtrFactory<MultipartUploadRequestBase> weak_ptr_factory_{this};
- };
- //============================ DownloadFileRequest ===========================
- // Callback type for receiving the completion of DownloadFileRequest.
- typedef base::OnceCallback<void(ApiErrorCode error,
- const base::FilePath& temp_file)>
- DownloadActionCallback;
- // This is a base class for performing the request for downloading a file.
- class DownloadFileRequestBase : public DriveUrlFetchRequestBase {
- public:
- // download_action_callback:
- // This callback is called when the download is complete. Must not be null.
- //
- // get_content_callback:
- // This callback is called when some part of the content is
- // read. Used to read the download content progressively. May be null.
- //
- // progress_callback:
- // This callback is called for periodically reporting the number of bytes
- // downloaded so far. May be null.
- //
- // download_url:
- // Specifies the target file to download.
- //
- // output_file_path:
- // Specifies the file path to save the downloaded file.
- //
- DownloadFileRequestBase(RequestSender* sender,
- DownloadActionCallback download_action_callback,
- const GetContentCallback& get_content_callback,
- ProgressCallback progress_callback,
- const GURL& download_url,
- const base::FilePath& output_file_path);
- DownloadFileRequestBase(const DownloadFileRequestBase&) = delete;
- DownloadFileRequestBase& operator=(const DownloadFileRequestBase&) = delete;
- ~DownloadFileRequestBase() override;
- protected:
- // UrlFetchRequestBase overrides.
- GURL GetURL() const override;
- void GetOutputFilePath(base::FilePath* local_file_path,
- GetContentCallback* get_content_callback) override;
- void ProcessURLFetchResults(
- const network::mojom::URLResponseHead* response_head,
- base::FilePath response_file,
- std::string response_body) override;
- void RunCallbackOnPrematureFailure(ApiErrorCode code) override;
- private:
- DownloadActionCallback download_action_callback_;
- const GetContentCallback get_content_callback_;
- const GURL download_url_;
- const base::FilePath output_file_path_;
- };
- } // namespace google_apis
- #endif // GOOGLE_APIS_DRIVE_DRIVE_BASE_REQUESTS_H_
|