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 ~AuthenticatedRequestInterface()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 data()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. response_writer()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