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
24namespace base {
25class Value;
26}  // namespace base
27
28namespace google_apis {
29
30class RequestSender;
31
32// Callback used to pass parsed JSON from ParseJson(). If parsing error occurs,
33// then the passed argument is null.
34typedef base::Callback<void(scoped_ptr<base::Value> value)> ParseJsonCallback;
35
36// Callback used for DownloadFileRequest and ResumeUploadRequestBase.
37typedef base::Callback<void(int64 progress, int64 total)> ProgressCallback;
38
39// Callback used to get the content from DownloadFileRequest.
40typedef 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.
47void 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.
55class 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.
93class 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.
130class 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.
229typedef 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.
233class 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.
255typedef 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.
260class 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.
294typedef 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//
308class 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.
336struct 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.
357class 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).
410class 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.
458class 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.
481typedef 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.
486class 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