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