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