Home | History | Annotate | Download | only in drive
      1 // Copyright (c) 2012 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 
      8 #ifndef GOOGLE_APIS_DRIVE_BASE_REQUESTS_H_
      9 #define GOOGLE_APIS_DRIVE_BASE_REQUESTS_H_
     10 
     11 #include <string>
     12 #include <vector>
     13 
     14 #include "base/callback.h"
     15 #include "base/files/file_path.h"
     16 #include "base/memory/weak_ptr.h"
     17 #include "base/threading/thread_checker.h"
     18 #include "google_apis/drive/gdata_errorcode.h"
     19 #include "net/url_request/url_fetcher.h"
     20 #include "net/url_request/url_fetcher_delegate.h"
     21 #include "net/url_request/url_fetcher_response_writer.h"
     22 #include "url/gurl.h"
     23 
     24 namespace base {
     25 class Value;
     26 }  // namespace base
     27 
     28 namespace google_apis {
     29 
     30 class RequestSender;
     31 
     32 // Callback used for DownloadFileRequest and ResumeUploadRequestBase.
     33 typedef base::Callback<void(int64 progress, int64 total)> ProgressCallback;
     34 
     35 // Callback used to get the content from DownloadFileRequest.
     36 typedef base::Callback<void(
     37     GDataErrorCode error,
     38     scoped_ptr<std::string> content)> GetContentCallback;
     39 
     40 // Parses JSON passed in |json|. Returns NULL on failure.
     41 scoped_ptr<base::Value> ParseJson(const std::string& json);
     42 
     43 //======================= AuthenticatedRequestInterface ======================
     44 
     45 // An interface class for implementing a request which requires OAuth2
     46 // authentication.
     47 class AuthenticatedRequestInterface {
     48  public:
     49   // Called when re-authentication is required. See Start() for details.
     50   typedef base::Callback<void(AuthenticatedRequestInterface* request)>
     51       ReAuthenticateCallback;
     52 
     53   virtual ~AuthenticatedRequestInterface() {}
     54 
     55   // Starts the request with |access_token|. User-Agent header will be set
     56   // to |custom_user_agent| if the value is not empty.
     57   //
     58   // |callback| is called when re-authentication is needed for a certain
     59   // number of times (see kMaxReAuthenticateAttemptsPerRequest in .cc).
     60   // The callback should retry by calling Start() again with a new access
     61   // token, or just call OnAuthFailed() if a retry is not attempted.
     62   // |callback| must not be null.
     63   virtual void Start(const std::string& access_token,
     64                      const std::string& custom_user_agent,
     65                      const ReAuthenticateCallback& callback) = 0;
     66 
     67   // Invoked when the authentication failed with an error code |code|.
     68   virtual void OnAuthFailed(GDataErrorCode code) = 0;
     69 
     70   // Gets a weak pointer to this request object. Since requests may be
     71   // deleted when it is canceled by user action, for posting asynchronous tasks
     72   // on the authentication request object, weak pointers have to be used.
     73   // TODO(kinaba): crbug.com/134814 use more clean life time management than
     74   // using weak pointers.
     75   virtual base::WeakPtr<AuthenticatedRequestInterface> GetWeakPtr() = 0;
     76 
     77   // Cancels the request. It will invoke the callback object passed in
     78   // each request's constructor with error code GDATA_CANCELLED.
     79   virtual void Cancel() = 0;
     80 };
     81 
     82 //=========================== ResponseWriter ==================================
     83 
     84 // Saves the response for the request to a file or string.
     85 class ResponseWriter : public net::URLFetcherResponseWriter {
     86  public:
     87   // If file_path is not empty, the response will be saved with file_writer_,
     88   // otherwise it will be saved to data_.
     89   ResponseWriter(base::SequencedTaskRunner* file_task_runner,
     90                  const base::FilePath& file_path,
     91                  const GetContentCallback& get_content_callback);
     92   virtual ~ResponseWriter();
     93 
     94   const std::string& data() const { return data_; }
     95 
     96   // Disowns the output file.
     97   void DisownFile();
     98 
     99   // URLFetcherResponseWriter overrides:
    100   virtual int Initialize(const net::CompletionCallback& callback) OVERRIDE;
    101   virtual int Write(net::IOBuffer* buffer,
    102                     int num_bytes,
    103                     const net::CompletionCallback& callback) OVERRIDE;
    104   virtual int Finish(const net::CompletionCallback& callback) OVERRIDE;
    105 
    106  private:
    107   void DidWrite(scoped_refptr<net::IOBuffer> buffer,
    108                 const net::CompletionCallback& callback,
    109                 int result);
    110 
    111   const GetContentCallback get_content_callback_;
    112   std::string data_;
    113   scoped_ptr<net::URLFetcherFileWriter> file_writer_;
    114   base::WeakPtrFactory<ResponseWriter> weak_ptr_factory_;
    115 
    116   DISALLOW_COPY_AND_ASSIGN(ResponseWriter);
    117 };
    118 
    119 //============================ UrlFetchRequestBase ===========================
    120 
    121 // Base class for requests that are fetching URLs.
    122 class UrlFetchRequestBase : public AuthenticatedRequestInterface,
    123                             public net::URLFetcherDelegate {
    124  public:
    125   // AuthenticatedRequestInterface overrides.
    126   virtual void Start(const std::string& access_token,
    127                      const std::string& custom_user_agent,
    128                      const ReAuthenticateCallback& callback) OVERRIDE;
    129   virtual base::WeakPtr<AuthenticatedRequestInterface> GetWeakPtr() OVERRIDE;
    130   virtual void Cancel() OVERRIDE;
    131 
    132  protected:
    133   explicit UrlFetchRequestBase(RequestSender* sender);
    134   virtual ~UrlFetchRequestBase();
    135 
    136   // Gets URL for the request.
    137   virtual GURL GetURL() const = 0;
    138 
    139   // Returns the request type. A derived class should override this method
    140   // for a request type other than HTTP GET.
    141   virtual net::URLFetcher::RequestType GetRequestType() const;
    142 
    143   // Returns the extra HTTP headers for the request. A derived class should
    144   // override this method to specify any extra headers needed for the request.
    145   virtual std::vector<std::string> GetExtraRequestHeaders() const;
    146 
    147   // Used by a derived class to add any content data to the request.
    148   // Returns true if |upload_content_type| and |upload_content| are updated
    149   // with the content type and data for the request.
    150   // Note that this and GetContentFile() cannot be used together.
    151   virtual bool GetContentData(std::string* upload_content_type,
    152                               std::string* upload_content);
    153 
    154   // Used by a derived class to add content data which is the whole file or
    155   // a part of the file at |local_file_path|.
    156   // Returns true if all the arguments are updated for the content being
    157   // uploaded.
    158   // Note that this and GetContentData() cannot be used together.
    159   virtual bool GetContentFile(base::FilePath* local_file_path,
    160                               int64* range_offset,
    161                               int64* range_length,
    162                               std::string* upload_content_type);
    163 
    164   // Used by a derived class to set an output file path if they want to save
    165   // the downloaded content to a file at a specific path.
    166   // Sets |get_content_callback|, which is called when some part of the response
    167   // is read.
    168   virtual void GetOutputFilePath(base::FilePath* local_file_path,
    169                                  GetContentCallback* get_content_callback);
    170 
    171   // Invoked by OnURLFetchComplete when the request completes without an
    172   // authentication error. Must be implemented by a derived class.
    173   virtual void ProcessURLFetchResults(const net::URLFetcher* source) = 0;
    174 
    175   // Invoked by this base class upon an authentication error or cancel by
    176   // a user request. Must be implemented by a derived class.
    177   virtual void RunCallbackOnPrematureFailure(GDataErrorCode code) = 0;
    178 
    179   // Invoked from derived classes when ProcessURLFetchResults() is completed.
    180   void OnProcessURLFetchResultsComplete();
    181 
    182   // Returns an appropriate GDataErrorCode based on the HTTP response code and
    183   // the status of the URLFetcher.
    184   GDataErrorCode GetErrorCode();
    185 
    186   // Returns true if called on the thread where the constructor was called.
    187   bool CalledOnValidThread();
    188 
    189   // Returns the writer which is used to save the response for the request.
    190   ResponseWriter* response_writer() const { return response_writer_; }
    191 
    192   // Returns the task runner that should be used for blocking tasks.
    193   base::SequencedTaskRunner* blocking_task_runner() const;
    194 
    195  private:
    196   // URLFetcherDelegate overrides.
    197   virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
    198 
    199   // AuthenticatedRequestInterface overrides.
    200   virtual void OnAuthFailed(GDataErrorCode code) OVERRIDE;
    201 
    202   ReAuthenticateCallback re_authenticate_callback_;
    203   int re_authenticate_count_;
    204   scoped_ptr<net::URLFetcher> url_fetcher_;
    205   ResponseWriter* response_writer_;  // Owned by |url_fetcher_|.
    206   RequestSender* sender_;
    207   GDataErrorCode error_code_;
    208 
    209   base::ThreadChecker thread_checker_;
    210 
    211   // Note: This should remain the last member so it'll be destroyed and
    212   // invalidate its weak pointers before any other members are destroyed.
    213   base::WeakPtrFactory<UrlFetchRequestBase> weak_ptr_factory_;
    214 
    215   DISALLOW_COPY_AND_ASSIGN(UrlFetchRequestBase);
    216 };
    217 
    218 //============================ EntryActionRequest ============================
    219 
    220 // Callback type for requests that return only error status, like: Delete/Move.
    221 typedef base::Callback<void(GDataErrorCode error)> EntryActionCallback;
    222 
    223 // This class performs a simple action over a given entry (document/file).
    224 // It is meant to be used for requests that return no JSON blobs.
    225 class EntryActionRequest : public UrlFetchRequestBase {
    226  public:
    227   // |callback| is called when the request is finished either by success or by
    228   // failure. It must not be null.
    229   EntryActionRequest(RequestSender* sender,
    230                      const EntryActionCallback& callback);
    231   virtual ~EntryActionRequest();
    232 
    233  protected:
    234   // Overridden from UrlFetchRequestBase.
    235   virtual void ProcessURLFetchResults(const net::URLFetcher* source) OVERRIDE;
    236   virtual void RunCallbackOnPrematureFailure(GDataErrorCode code) OVERRIDE;
    237 
    238  private:
    239   const EntryActionCallback callback_;
    240 
    241   DISALLOW_COPY_AND_ASSIGN(EntryActionRequest);
    242 };
    243 
    244 //=========================== InitiateUploadRequestBase=======================
    245 
    246 // Callback type for DriveServiceInterface::InitiateUpload.
    247 typedef base::Callback<void(GDataErrorCode error,
    248                             const GURL& upload_url)> InitiateUploadCallback;
    249 
    250 // This class provides base implementation for performing the request for
    251 // initiating the upload of a file.
    252 // |callback| will be called with the obtained upload URL. The URL will be
    253 // used with requests for resuming the file uploading.
    254 //
    255 // Here's the flow of uploading:
    256 // 1) Get the upload URL with a class inheriting InitiateUploadRequestBase.
    257 // 2) Upload the first 1GB (see kUploadChunkSize in drive_uploader.cc)
    258 //    of the target file to the upload URL
    259 // 3) If there is more data to upload, go to 2).
    260 //
    261 class InitiateUploadRequestBase : public UrlFetchRequestBase {
    262  protected:
    263   // |callback| will be called with the upload URL, where upload data is
    264   // uploaded to with ResumeUploadRequestBase. It must not be null.
    265   // |content_type| and |content_length| should be the attributes of the
    266   // uploading file.
    267   InitiateUploadRequestBase(RequestSender* sender,
    268                             const InitiateUploadCallback& callback,
    269                             const std::string& content_type,
    270                             int64 content_length);
    271   virtual ~InitiateUploadRequestBase();
    272 
    273   // UrlFetchRequestBase overrides.
    274   virtual void ProcessURLFetchResults(const net::URLFetcher* source) OVERRIDE;
    275   virtual void RunCallbackOnPrematureFailure(GDataErrorCode code) OVERRIDE;
    276   virtual std::vector<std::string> GetExtraRequestHeaders() const OVERRIDE;
    277 
    278  private:
    279   const InitiateUploadCallback callback_;
    280   const std::string content_type_;
    281   const int64 content_length_;
    282 
    283   DISALLOW_COPY_AND_ASSIGN(InitiateUploadRequestBase);
    284 };
    285 
    286 //========================== UploadRangeRequestBase ==========================
    287 
    288 // Struct for response to ResumeUpload and GetUploadStatus.
    289 struct UploadRangeResponse {
    290   UploadRangeResponse();
    291   UploadRangeResponse(GDataErrorCode code,
    292                       int64 start_position_received,
    293                       int64 end_position_received);
    294   ~UploadRangeResponse();
    295 
    296   GDataErrorCode code;
    297   // The values of "Range" header returned from the server. The values are
    298   // used to continue uploading more data. These are set to -1 if an upload
    299   // is complete.
    300   // |start_position_received| is inclusive and |end_position_received| is
    301   // exclusive to follow the common C++ manner, although the response from
    302   // the server has "Range" header in inclusive format at both sides.
    303   int64 start_position_received;
    304   int64 end_position_received;
    305 };
    306 
    307 // Base class for a URL fetch request expecting the response containing the
    308 // current uploading range. This class processes the response containing
    309 // "Range" header and invoke OnRangeRequestComplete.
    310 class UploadRangeRequestBase : public UrlFetchRequestBase {
    311  protected:
    312   // |upload_url| is the URL of where to upload the file to.
    313   UploadRangeRequestBase(RequestSender* sender, const GURL& upload_url);
    314   virtual ~UploadRangeRequestBase();
    315 
    316   // UrlFetchRequestBase overrides.
    317   virtual GURL GetURL() const OVERRIDE;
    318   virtual net::URLFetcher::RequestType GetRequestType() const OVERRIDE;
    319   virtual void ProcessURLFetchResults(const net::URLFetcher* source) OVERRIDE;
    320   virtual void RunCallbackOnPrematureFailure(GDataErrorCode code) OVERRIDE;
    321 
    322   // This method will be called when the request is done, regardless of
    323   // whether it is succeeded or failed.
    324   //
    325   // 1) If there is more data to upload, |code| of |response| is set to
    326   // HTTP_RESUME_INCOMPLETE, and positions are set appropriately. Also, |value|
    327   // will be set to NULL.
    328   // 2) If the upload is complete, |code| is set to HTTP_CREATED for a new file
    329   // or HTTP_SUCCESS for an existing file. Positions are set to -1, and |value|
    330   // is set to a parsed JSON value representing the uploaded file.
    331   // 3) If a premature failure is found, |code| is set to a value representing
    332   // the situation. Positions are set to 0, and |value| is set to NULL.
    333   //
    334   // See also the comments for UploadRangeResponse.
    335   // Note: Subclasses should have responsibility to run some callback
    336   // in this method to notify the finish status to its clients (or ignore it
    337   // under its responsibility).
    338   virtual void OnRangeRequestComplete(
    339       const UploadRangeResponse& response, scoped_ptr<base::Value> value) = 0;
    340 
    341  private:
    342   // Called when ParseJson() is completed.
    343   void OnDataParsed(GDataErrorCode code, scoped_ptr<base::Value> value);
    344 
    345   const GURL upload_url_;
    346 
    347   // Note: This should remain the last member so it'll be destroyed and
    348   // invalidate its weak pointers before any other members are destroyed.
    349   base::WeakPtrFactory<UploadRangeRequestBase> weak_ptr_factory_;
    350 
    351   DISALLOW_COPY_AND_ASSIGN(UploadRangeRequestBase);
    352 };
    353 
    354 //========================== ResumeUploadRequestBase =========================
    355 
    356 // This class performs the request for resuming the upload of a file.
    357 // More specifically, this request uploads a chunk of data carried in |buf|
    358 // of ResumeUploadResponseBase. This class is designed to share the
    359 // implementation of upload resuming between GData WAPI and Drive API v2.
    360 // The subclasses should implement OnRangeRequestComplete inherited by
    361 // UploadRangeRequestBase, because the type of the response should be
    362 // different (although the format in the server response is JSON).
    363 class ResumeUploadRequestBase : public UploadRangeRequestBase {
    364  protected:
    365   // |start_position| is the start of range of contents currently stored in
    366   // |buf|. |end_position| is the end of range of contents currently stared in
    367   // |buf|. This is exclusive. For instance, if you are to upload the first
    368   // 500 bytes of data, |start_position| is 0 and |end_position| is 500.
    369   // |content_length| and |content_type| are the length and type of the
    370   // file content to be uploaded respectively.
    371   // |buf| holds current content to be uploaded.
    372   // See also UploadRangeRequestBase's comment for remaining parameters
    373   // meaning.
    374   ResumeUploadRequestBase(RequestSender* sender,
    375                           const GURL& upload_location,
    376                           int64 start_position,
    377                           int64 end_position,
    378                           int64 content_length,
    379                           const std::string& content_type,
    380                           const base::FilePath& local_file_path);
    381   virtual ~ResumeUploadRequestBase();
    382 
    383   // UrlFetchRequestBase overrides.
    384   virtual std::vector<std::string> GetExtraRequestHeaders() const OVERRIDE;
    385   virtual bool GetContentFile(base::FilePath* local_file_path,
    386                               int64* range_offset,
    387                               int64* range_length,
    388                               std::string* upload_content_type) OVERRIDE;
    389 
    390  private:
    391   // The parameters for the request. See ResumeUploadParams for the details.
    392   const int64 start_position_;
    393   const int64 end_position_;
    394   const int64 content_length_;
    395   const std::string content_type_;
    396   const base::FilePath local_file_path_;
    397 
    398   DISALLOW_COPY_AND_ASSIGN(ResumeUploadRequestBase);
    399 };
    400 
    401 //======================== GetUploadStatusRequestBase ========================
    402 
    403 // This class performs the request for getting the current upload status
    404 // of a file.
    405 // This request calls OnRangeRequestComplete() with:
    406 // - HTTP_RESUME_INCOMPLETE and the range of previously uploaded data,
    407 //   if a file has been partially uploaded. |value| is not used.
    408 // - HTTP_SUCCESS or HTTP_CREATED (up to the upload mode) and |value|
    409 //   for the uploaded data, if a file has been completely uploaded.
    410 // See also UploadRangeRequestBase.
    411 class GetUploadStatusRequestBase : public UploadRangeRequestBase {
    412  public:
    413   // |content_length| is the whole data size to be uploaded.
    414   // See also UploadRangeRequestBase's constructor comment for other
    415   // parameters.
    416   GetUploadStatusRequestBase(RequestSender* sender,
    417                              const GURL& upload_url,
    418                              int64 content_length);
    419   virtual ~GetUploadStatusRequestBase();
    420 
    421  protected:
    422   // UrlFetchRequestBase overrides.
    423   virtual std::vector<std::string> GetExtraRequestHeaders() const OVERRIDE;
    424 
    425  private:
    426   const int64 content_length_;
    427 
    428   DISALLOW_COPY_AND_ASSIGN(GetUploadStatusRequestBase);
    429 };
    430 
    431 //============================ DownloadFileRequest ===========================
    432 
    433 // Callback type for receiving the completion of DownloadFileRequest.
    434 typedef base::Callback<void(GDataErrorCode error,
    435                             const base::FilePath& temp_file)>
    436     DownloadActionCallback;
    437 
    438 // This is a base class for performing the request for downloading a file.
    439 class DownloadFileRequestBase : public UrlFetchRequestBase {
    440  public:
    441   // download_action_callback:
    442   //   This callback is called when the download is complete. Must not be null.
    443   //
    444   // get_content_callback:
    445   //   This callback is called when some part of the content is
    446   //   read. Used to read the download content progressively. May be null.
    447   //
    448   // progress_callback:
    449   //   This callback is called for periodically reporting the number of bytes
    450   //   downloaded so far. May be null.
    451   //
    452   // download_url:
    453   //   Specifies the target file to download.
    454   //
    455   // output_file_path:
    456   //   Specifies the file path to save the downloaded file.
    457   //
    458   DownloadFileRequestBase(
    459       RequestSender* sender,
    460       const DownloadActionCallback& download_action_callback,
    461       const GetContentCallback& get_content_callback,
    462       const ProgressCallback& progress_callback,
    463       const GURL& download_url,
    464       const base::FilePath& output_file_path);
    465   virtual ~DownloadFileRequestBase();
    466 
    467  protected:
    468   // UrlFetchRequestBase overrides.
    469   virtual GURL GetURL() const OVERRIDE;
    470   virtual void GetOutputFilePath(
    471       base::FilePath* local_file_path,
    472       GetContentCallback* get_content_callback) OVERRIDE;
    473   virtual void ProcessURLFetchResults(const net::URLFetcher* source) OVERRIDE;
    474   virtual void RunCallbackOnPrematureFailure(GDataErrorCode code) OVERRIDE;
    475 
    476   // net::URLFetcherDelegate overrides.
    477   virtual void OnURLFetchDownloadProgress(const net::URLFetcher* source,
    478                                           int64 current, int64 total) OVERRIDE;
    479 
    480  private:
    481   const DownloadActionCallback download_action_callback_;
    482   const GetContentCallback get_content_callback_;
    483   const ProgressCallback progress_callback_;
    484   const GURL download_url_;
    485   const base::FilePath output_file_path_;
    486 
    487   DISALLOW_COPY_AND_ASSIGN(DownloadFileRequestBase);
    488 };
    489 
    490 }  // namespace google_apis
    491 
    492 #endif  // GOOGLE_APIS_DRIVE_BASE_REQUESTS_H_
    493