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