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 #include "google_apis/drive/base_requests.h"
      6 
      7 #include "base/json/json_reader.h"
      8 #include "base/location.h"
      9 #include "base/sequenced_task_runner.h"
     10 #include "base/strings/string_number_conversions.h"
     11 #include "base/strings/stringprintf.h"
     12 #include "base/task_runner_util.h"
     13 #include "base/values.h"
     14 #include "google_apis/drive/request_sender.h"
     15 #include "google_apis/drive/task_util.h"
     16 #include "net/base/io_buffer.h"
     17 #include "net/base/load_flags.h"
     18 #include "net/base/net_errors.h"
     19 #include "net/http/http_byte_range.h"
     20 #include "net/http/http_response_headers.h"
     21 #include "net/http/http_util.h"
     22 #include "net/url_request/url_fetcher.h"
     23 #include "net/url_request/url_request_status.h"
     24 
     25 using net::URLFetcher;
     26 
     27 namespace {
     28 
     29 // Template for optional OAuth2 authorization HTTP header.
     30 const char kAuthorizationHeaderFormat[] = "Authorization: Bearer %s";
     31 // Template for GData API version HTTP header.
     32 const char kGDataVersionHeader[] = "GData-Version: 3.0";
     33 
     34 // Maximum number of attempts for re-authentication per request.
     35 const int kMaxReAuthenticateAttemptsPerRequest = 1;
     36 
     37 // Template for initiate upload of both GData WAPI and Drive API v2.
     38 const char kUploadContentType[] = "X-Upload-Content-Type: ";
     39 const char kUploadContentLength[] = "X-Upload-Content-Length: ";
     40 const char kUploadResponseLocation[] = "location";
     41 
     42 // Template for upload data range of both GData WAPI and Drive API v2.
     43 const char kUploadContentRange[] = "Content-Range: bytes ";
     44 const char kUploadResponseRange[] = "range";
     45 
     46 // Parse JSON string to base::Value object.
     47 scoped_ptr<base::Value> ParseJsonInternal(const std::string& json) {
     48   int error_code = -1;
     49   std::string error_message;
     50   scoped_ptr<base::Value> value(base::JSONReader::ReadAndReturnError(
     51       json, base::JSON_PARSE_RFC, &error_code, &error_message));
     52 
     53   if (!value.get()) {
     54     std::string trimmed_json;
     55     if (json.size() < 80) {
     56       trimmed_json  = json;
     57     } else {
     58       // Take the first 50 and the last 10 bytes.
     59       trimmed_json = base::StringPrintf(
     60           "%s [%s bytes] %s",
     61           json.substr(0, 50).c_str(),
     62           base::Uint64ToString(json.size() - 60).c_str(),
     63           json.substr(json.size() - 10).c_str());
     64     }
     65     LOG(WARNING) << "Error while parsing entry response: " << error_message
     66                  << ", code: " << error_code << ", json:\n" << trimmed_json;
     67   }
     68   return value.Pass();
     69 }
     70 
     71 // Returns response headers as a string. Returns a warning message if
     72 // |url_fetcher| does not contain a valid response. Used only for debugging.
     73 std::string GetResponseHeadersAsString(
     74     const URLFetcher* url_fetcher) {
     75   // net::HttpResponseHeaders::raw_headers(), as the name implies, stores
     76   // all headers in their raw format, i.e each header is null-terminated.
     77   // So logging raw_headers() only shows the first header, which is probably
     78   // the status line.  GetNormalizedHeaders, on the other hand, will show all
     79   // the headers, one per line, which is probably what we want.
     80   std::string headers;
     81   // Check that response code indicates response headers are valid (i.e. not
     82   // malformed) before we retrieve the headers.
     83   if (url_fetcher->GetResponseCode() == URLFetcher::RESPONSE_CODE_INVALID) {
     84     headers.assign("Response headers are malformed!!");
     85   } else {
     86     url_fetcher->GetResponseHeaders()->GetNormalizedHeaders(&headers);
     87   }
     88   return headers;
     89 }
     90 
     91 bool IsSuccessfulResponseCode(int response_code) {
     92   return 200 <= response_code && response_code <= 299;
     93 }
     94 
     95 }  // namespace
     96 
     97 namespace google_apis {
     98 
     99 void ParseJson(base::TaskRunner* blocking_task_runner,
    100                const std::string& json,
    101                const ParseJsonCallback& callback) {
    102   base::PostTaskAndReplyWithResult(
    103       blocking_task_runner,
    104       FROM_HERE,
    105       base::Bind(&ParseJsonInternal, json),
    106       callback);
    107 }
    108 
    109 //=========================== ResponseWriter ==================================
    110 ResponseWriter::ResponseWriter(base::SequencedTaskRunner* file_task_runner,
    111                                const base::FilePath& file_path,
    112                                const GetContentCallback& get_content_callback)
    113     : get_content_callback_(get_content_callback),
    114       weak_ptr_factory_(this) {
    115   if (!file_path.empty()) {
    116     file_writer_.reset(
    117         new net::URLFetcherFileWriter(file_task_runner, file_path));
    118   }
    119 }
    120 
    121 ResponseWriter::~ResponseWriter() {
    122 }
    123 
    124 void ResponseWriter::DisownFile() {
    125   DCHECK(file_writer_);
    126   file_writer_->DisownFile();
    127 }
    128 
    129 int ResponseWriter::Initialize(const net::CompletionCallback& callback) {
    130   if (file_writer_)
    131     return file_writer_->Initialize(callback);
    132 
    133   data_.clear();
    134   return net::OK;
    135 }
    136 
    137 int ResponseWriter::Write(net::IOBuffer* buffer,
    138                           int num_bytes,
    139                           const net::CompletionCallback& callback) {
    140   if (!get_content_callback_.is_null()) {
    141     get_content_callback_.Run(
    142         HTTP_SUCCESS,
    143         make_scoped_ptr(new std::string(buffer->data(), num_bytes)));
    144   }
    145 
    146   if (file_writer_) {
    147     const int result = file_writer_->Write(
    148         buffer, num_bytes,
    149         base::Bind(&ResponseWriter::DidWrite,
    150                    weak_ptr_factory_.GetWeakPtr(),
    151                    make_scoped_refptr(buffer), callback));
    152     if (result != net::ERR_IO_PENDING)
    153       DidWrite(buffer, net::CompletionCallback(), result);
    154     return result;
    155   }
    156 
    157   data_.append(buffer->data(), num_bytes);
    158   return num_bytes;
    159 }
    160 
    161 int ResponseWriter::Finish(const net::CompletionCallback& callback) {
    162   if (file_writer_)
    163     return file_writer_->Finish(callback);
    164 
    165   return net::OK;
    166 }
    167 
    168 void ResponseWriter::DidWrite(scoped_refptr<net::IOBuffer> buffer,
    169                               const net::CompletionCallback& callback,
    170                               int result) {
    171   if (result > 0) {
    172     // Even if file_writer_ is used, append the data to |data_|, so that it can
    173     // be used to get error information in case of server side errors.
    174     // The size limit is to avoid consuming too much redundant memory.
    175     const size_t kMaxStringSize = 1024*1024;
    176     if (data_.size() < kMaxStringSize) {
    177       data_.append(buffer->data(), std::min(static_cast<size_t>(result),
    178                                             kMaxStringSize - data_.size()));
    179     }
    180   }
    181 
    182   if (!callback.is_null())
    183     callback.Run(result);
    184 }
    185 
    186 //============================ UrlFetchRequestBase ===========================
    187 
    188 UrlFetchRequestBase::UrlFetchRequestBase(RequestSender* sender)
    189     : re_authenticate_count_(0),
    190       sender_(sender),
    191       error_code_(GDATA_OTHER_ERROR),
    192       weak_ptr_factory_(this) {
    193 }
    194 
    195 UrlFetchRequestBase::~UrlFetchRequestBase() {}
    196 
    197 void UrlFetchRequestBase::Start(const std::string& access_token,
    198                                 const std::string& custom_user_agent,
    199                                 const ReAuthenticateCallback& callback) {
    200   DCHECK(CalledOnValidThread());
    201   DCHECK(!access_token.empty());
    202   DCHECK(!callback.is_null());
    203   DCHECK(re_authenticate_callback_.is_null());
    204 
    205   re_authenticate_callback_ = callback;
    206 
    207   GURL url = GetURL();
    208   if (url.is_empty()) {
    209     // Error is found on generating the url. Send the error message to the
    210     // callback, and then return immediately without trying to connect
    211     // to the server.
    212     RunCallbackOnPrematureFailure(GDATA_OTHER_ERROR);
    213     return;
    214   }
    215   DVLOG(1) << "URL: " << url.spec();
    216 
    217   URLFetcher::RequestType request_type = GetRequestType();
    218   url_fetcher_.reset(
    219       URLFetcher::Create(url, request_type, this));
    220   url_fetcher_->SetRequestContext(sender_->url_request_context_getter());
    221   // Always set flags to neither send nor save cookies.
    222   url_fetcher_->SetLoadFlags(
    223       net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES |
    224       net::LOAD_DISABLE_CACHE);
    225 
    226   base::FilePath output_file_path;
    227   GetContentCallback get_content_callback;
    228   GetOutputFilePath(&output_file_path, &get_content_callback);
    229   if (!get_content_callback.is_null())
    230     get_content_callback = CreateRelayCallback(get_content_callback);
    231   response_writer_ = new ResponseWriter(blocking_task_runner(),
    232                                         output_file_path,
    233                                         get_content_callback);
    234   url_fetcher_->SaveResponseWithWriter(
    235       scoped_ptr<net::URLFetcherResponseWriter>(response_writer_));
    236 
    237   // Add request headers.
    238   // Note that SetExtraRequestHeaders clears the current headers and sets it
    239   // to the passed-in headers, so calling it for each header will result in
    240   // only the last header being set in request headers.
    241   if (!custom_user_agent.empty())
    242     url_fetcher_->AddExtraRequestHeader("User-Agent: " + custom_user_agent);
    243   url_fetcher_->AddExtraRequestHeader(kGDataVersionHeader);
    244   url_fetcher_->AddExtraRequestHeader(
    245       base::StringPrintf(kAuthorizationHeaderFormat, access_token.data()));
    246   std::vector<std::string> headers = GetExtraRequestHeaders();
    247   for (size_t i = 0; i < headers.size(); ++i) {
    248     url_fetcher_->AddExtraRequestHeader(headers[i]);
    249     DVLOG(1) << "Extra header: " << headers[i];
    250   }
    251 
    252   // Set upload data if available.
    253   std::string upload_content_type;
    254   std::string upload_content;
    255   if (GetContentData(&upload_content_type, &upload_content)) {
    256     url_fetcher_->SetUploadData(upload_content_type, upload_content);
    257   } else {
    258     base::FilePath local_file_path;
    259     int64 range_offset = 0;
    260     int64 range_length = 0;
    261     if (GetContentFile(&local_file_path, &range_offset, &range_length,
    262                        &upload_content_type)) {
    263       url_fetcher_->SetUploadFilePath(
    264           upload_content_type,
    265           local_file_path,
    266           range_offset,
    267           range_length,
    268           blocking_task_runner());
    269     } else {
    270       // Even if there is no content data, UrlFetcher requires to set empty
    271       // upload data string for POST, PUT and PATCH methods, explicitly.
    272       // It is because that most requests of those methods have non-empty
    273       // body, and UrlFetcher checks whether it is actually not forgotten.
    274       if (request_type == URLFetcher::POST ||
    275           request_type == URLFetcher::PUT ||
    276           request_type == URLFetcher::PATCH) {
    277         // Set empty upload content-type and upload content, so that
    278         // the request will have no "Content-type: " header and no content.
    279         url_fetcher_->SetUploadData(std::string(), std::string());
    280       }
    281     }
    282   }
    283 
    284   url_fetcher_->Start();
    285 }
    286 
    287 URLFetcher::RequestType UrlFetchRequestBase::GetRequestType() const {
    288   return URLFetcher::GET;
    289 }
    290 
    291 std::vector<std::string> UrlFetchRequestBase::GetExtraRequestHeaders() const {
    292   return std::vector<std::string>();
    293 }
    294 
    295 bool UrlFetchRequestBase::GetContentData(std::string* upload_content_type,
    296                                          std::string* upload_content) {
    297   return false;
    298 }
    299 
    300 bool UrlFetchRequestBase::GetContentFile(base::FilePath* local_file_path,
    301                                          int64* range_offset,
    302                                          int64* range_length,
    303                                          std::string* upload_content_type) {
    304   return false;
    305 }
    306 
    307 void UrlFetchRequestBase::GetOutputFilePath(
    308     base::FilePath* local_file_path,
    309     GetContentCallback* get_content_callback) {
    310 }
    311 
    312 void UrlFetchRequestBase::Cancel() {
    313   response_writer_ = NULL;
    314   url_fetcher_.reset(NULL);
    315   RunCallbackOnPrematureFailure(GDATA_CANCELLED);
    316   sender_->RequestFinished(this);
    317 }
    318 
    319 GDataErrorCode UrlFetchRequestBase::GetErrorCode() {
    320   return error_code_;
    321 }
    322 
    323 bool UrlFetchRequestBase::CalledOnValidThread() {
    324   return thread_checker_.CalledOnValidThread();
    325 }
    326 
    327 base::SequencedTaskRunner* UrlFetchRequestBase::blocking_task_runner() const {
    328   return sender_->blocking_task_runner();
    329 }
    330 
    331 void UrlFetchRequestBase::OnProcessURLFetchResultsComplete() {
    332   sender_->RequestFinished(this);
    333 }
    334 
    335 void UrlFetchRequestBase::OnURLFetchComplete(const URLFetcher* source) {
    336   DVLOG(1) << "Response headers:\n" << GetResponseHeadersAsString(source);
    337 
    338   // Determine error code.
    339   error_code_ = static_cast<GDataErrorCode>(source->GetResponseCode());
    340   if (!source->GetStatus().is_success()) {
    341     switch (source->GetStatus().error()) {
    342       case net::ERR_NETWORK_CHANGED:
    343         error_code_ = GDATA_NO_CONNECTION;
    344         break;
    345       default:
    346         error_code_ = GDATA_OTHER_ERROR;
    347     }
    348   }
    349 
    350   // The server may return detailed error status in JSON.
    351   // See https://developers.google.com/drive/handle-errors
    352   if (!IsSuccessfulResponseCode(error_code_)) {
    353     DVLOG(1) << response_writer_->data();
    354 
    355     const char kErrorKey[] = "error";
    356     const char kErrorErrorsKey[] = "errors";
    357     const char kErrorReasonKey[] = "reason";
    358     const char kErrorMessageKey[] = "message";
    359     const char kErrorReasonRateLimitExceeded[] = "rateLimitExceeded";
    360     const char kErrorReasonUserRateLimitExceeded[] = "userRateLimitExceeded";
    361     const char kErrorReasonQuotaExceeded[] = "quotaExceeded";
    362 
    363     scoped_ptr<base::Value> value(ParseJsonInternal(response_writer_->data()));
    364     base::DictionaryValue* dictionary = NULL;
    365     base::DictionaryValue* error = NULL;
    366     if (value &&
    367         value->GetAsDictionary(&dictionary) &&
    368         dictionary->GetDictionaryWithoutPathExpansion(kErrorKey, &error)) {
    369       // Get error message.
    370       std::string message;
    371       error->GetStringWithoutPathExpansion(kErrorMessageKey, &message);
    372       DLOG(ERROR) << "code: " << error_code_ << ", message: " << message;
    373 
    374       // Override the error code based on the reason of the first error.
    375       base::ListValue* errors = NULL;
    376       base::DictionaryValue* first_error = NULL;
    377       if (error->GetListWithoutPathExpansion(kErrorErrorsKey, &errors) &&
    378           errors->GetDictionary(0, &first_error)) {
    379         std::string reason;
    380         first_error->GetStringWithoutPathExpansion(kErrorReasonKey, &reason);
    381         if (reason == kErrorReasonRateLimitExceeded ||
    382             reason == kErrorReasonUserRateLimitExceeded)
    383           error_code_ = HTTP_SERVICE_UNAVAILABLE;
    384         if (reason == kErrorReasonQuotaExceeded)
    385           error_code_ = GDATA_NO_SPACE;
    386       }
    387     }
    388   }
    389 
    390   // Handle authentication failure.
    391   if (error_code_ == HTTP_UNAUTHORIZED) {
    392     if (++re_authenticate_count_ <= kMaxReAuthenticateAttemptsPerRequest) {
    393       // Reset re_authenticate_callback_ so Start() can be called again.
    394       ReAuthenticateCallback callback = re_authenticate_callback_;
    395       re_authenticate_callback_.Reset();
    396       callback.Run(this);
    397       return;
    398     }
    399 
    400     OnAuthFailed(error_code_);
    401     return;
    402   }
    403 
    404   // Overridden by each specialization
    405   ProcessURLFetchResults(source);
    406 }
    407 
    408 void UrlFetchRequestBase::OnAuthFailed(GDataErrorCode code) {
    409   RunCallbackOnPrematureFailure(code);
    410   sender_->RequestFinished(this);
    411 }
    412 
    413 base::WeakPtr<AuthenticatedRequestInterface>
    414 UrlFetchRequestBase::GetWeakPtr() {
    415   return weak_ptr_factory_.GetWeakPtr();
    416 }
    417 
    418 //============================ EntryActionRequest ============================
    419 
    420 EntryActionRequest::EntryActionRequest(RequestSender* sender,
    421                                        const EntryActionCallback& callback)
    422     : UrlFetchRequestBase(sender),
    423       callback_(callback) {
    424   DCHECK(!callback_.is_null());
    425 }
    426 
    427 EntryActionRequest::~EntryActionRequest() {}
    428 
    429 void EntryActionRequest::ProcessURLFetchResults(const URLFetcher* source) {
    430   callback_.Run(GetErrorCode());
    431   OnProcessURLFetchResultsComplete();
    432 }
    433 
    434 void EntryActionRequest::RunCallbackOnPrematureFailure(GDataErrorCode code) {
    435   callback_.Run(code);
    436 }
    437 
    438 //============================== GetDataRequest ==============================
    439 
    440 GetDataRequest::GetDataRequest(RequestSender* sender,
    441                                const GetDataCallback& callback)
    442     : UrlFetchRequestBase(sender),
    443       callback_(callback),
    444       weak_ptr_factory_(this) {
    445   DCHECK(!callback_.is_null());
    446 }
    447 
    448 GetDataRequest::~GetDataRequest() {}
    449 
    450 void GetDataRequest::ParseResponse(GDataErrorCode fetch_error_code,
    451                                    const std::string& data) {
    452   DCHECK(CalledOnValidThread());
    453 
    454   VLOG(1) << "JSON received from " << GetURL().spec() << ": "
    455           << data.size() << " bytes";
    456   ParseJson(blocking_task_runner(),
    457             data,
    458             base::Bind(&GetDataRequest::OnDataParsed,
    459                        weak_ptr_factory_.GetWeakPtr(),
    460                        fetch_error_code));
    461 }
    462 
    463 void GetDataRequest::ProcessURLFetchResults(const URLFetcher* source) {
    464   GDataErrorCode fetch_error_code = GetErrorCode();
    465 
    466   switch (fetch_error_code) {
    467     case HTTP_SUCCESS:
    468     case HTTP_CREATED:
    469       ParseResponse(fetch_error_code, response_writer()->data());
    470       break;
    471     default:
    472       RunCallbackOnPrematureFailure(fetch_error_code);
    473       OnProcessURLFetchResultsComplete();
    474       break;
    475   }
    476 }
    477 
    478 void GetDataRequest::RunCallbackOnPrematureFailure(
    479     GDataErrorCode fetch_error_code) {
    480   callback_.Run(fetch_error_code, scoped_ptr<base::Value>());
    481 }
    482 
    483 void GetDataRequest::OnDataParsed(GDataErrorCode fetch_error_code,
    484                                   scoped_ptr<base::Value> value) {
    485   DCHECK(CalledOnValidThread());
    486 
    487   if (!value.get())
    488     fetch_error_code = GDATA_PARSE_ERROR;
    489 
    490   callback_.Run(fetch_error_code, value.Pass());
    491   OnProcessURLFetchResultsComplete();
    492 }
    493 
    494 //========================= InitiateUploadRequestBase ========================
    495 
    496 InitiateUploadRequestBase::InitiateUploadRequestBase(
    497     RequestSender* sender,
    498     const InitiateUploadCallback& callback,
    499     const std::string& content_type,
    500     int64 content_length)
    501     : UrlFetchRequestBase(sender),
    502       callback_(callback),
    503       content_type_(content_type),
    504       content_length_(content_length) {
    505   DCHECK(!callback_.is_null());
    506   DCHECK(!content_type_.empty());
    507   DCHECK_GE(content_length_, 0);
    508 }
    509 
    510 InitiateUploadRequestBase::~InitiateUploadRequestBase() {}
    511 
    512 void InitiateUploadRequestBase::ProcessURLFetchResults(
    513     const URLFetcher* source) {
    514   GDataErrorCode code = GetErrorCode();
    515 
    516   std::string upload_location;
    517   if (code == HTTP_SUCCESS) {
    518     // Retrieve value of the first "Location" header.
    519     source->GetResponseHeaders()->EnumerateHeader(NULL,
    520                                                   kUploadResponseLocation,
    521                                                   &upload_location);
    522   }
    523 
    524   callback_.Run(code, GURL(upload_location));
    525   OnProcessURLFetchResultsComplete();
    526 }
    527 
    528 void InitiateUploadRequestBase::RunCallbackOnPrematureFailure(
    529     GDataErrorCode code) {
    530   callback_.Run(code, GURL());
    531 }
    532 
    533 std::vector<std::string>
    534 InitiateUploadRequestBase::GetExtraRequestHeaders() const {
    535   std::vector<std::string> headers;
    536   headers.push_back(kUploadContentType + content_type_);
    537   headers.push_back(
    538       kUploadContentLength + base::Int64ToString(content_length_));
    539   return headers;
    540 }
    541 
    542 //============================ UploadRangeResponse =============================
    543 
    544 UploadRangeResponse::UploadRangeResponse()
    545     : code(HTTP_SUCCESS),
    546       start_position_received(0),
    547       end_position_received(0) {
    548 }
    549 
    550 UploadRangeResponse::UploadRangeResponse(GDataErrorCode code,
    551                                          int64 start_position_received,
    552                                          int64 end_position_received)
    553     : code(code),
    554       start_position_received(start_position_received),
    555       end_position_received(end_position_received) {
    556 }
    557 
    558 UploadRangeResponse::~UploadRangeResponse() {
    559 }
    560 
    561 //========================== UploadRangeRequestBase ==========================
    562 
    563 UploadRangeRequestBase::UploadRangeRequestBase(RequestSender* sender,
    564                                                const GURL& upload_url)
    565     : UrlFetchRequestBase(sender),
    566       upload_url_(upload_url),
    567       weak_ptr_factory_(this) {
    568 }
    569 
    570 UploadRangeRequestBase::~UploadRangeRequestBase() {}
    571 
    572 GURL UploadRangeRequestBase::GetURL() const {
    573   // This is very tricky to get json from this request. To do that, &alt=json
    574   // has to be appended not here but in InitiateUploadRequestBase::GetURL().
    575   return upload_url_;
    576 }
    577 
    578 URLFetcher::RequestType UploadRangeRequestBase::GetRequestType() const {
    579   return URLFetcher::PUT;
    580 }
    581 
    582 void UploadRangeRequestBase::ProcessURLFetchResults(
    583     const URLFetcher* source) {
    584   GDataErrorCode code = GetErrorCode();
    585   net::HttpResponseHeaders* hdrs = source->GetResponseHeaders();
    586 
    587   if (code == HTTP_RESUME_INCOMPLETE) {
    588     // Retrieve value of the first "Range" header.
    589     // The Range header is appeared only if there is at least one received
    590     // byte. So, initialize the positions by 0 so that the [0,0) will be
    591     // returned via the |callback_| for empty data case.
    592     int64 start_position_received = 0;
    593     int64 end_position_received = 0;
    594     std::string range_received;
    595     hdrs->EnumerateHeader(NULL, kUploadResponseRange, &range_received);
    596     if (!range_received.empty()) {  // Parse the range header.
    597       std::vector<net::HttpByteRange> ranges;
    598       if (net::HttpUtil::ParseRangeHeader(range_received, &ranges) &&
    599           !ranges.empty() ) {
    600         // We only care about the first start-end pair in the range.
    601         //
    602         // Range header represents the range inclusively, while we are treating
    603         // ranges exclusively (i.e., end_position_received should be one passed
    604         // the last valid index). So "+ 1" is added.
    605         start_position_received = ranges[0].first_byte_position();
    606         end_position_received = ranges[0].last_byte_position() + 1;
    607       }
    608     }
    609     // The Range header has the received data range, so the start position
    610     // should be always 0.
    611     DCHECK_EQ(start_position_received, 0);
    612 
    613     OnRangeRequestComplete(UploadRangeResponse(code,
    614                                                start_position_received,
    615                                                end_position_received),
    616                            scoped_ptr<base::Value>());
    617 
    618     OnProcessURLFetchResultsComplete();
    619   } else if (code == HTTP_CREATED || code == HTTP_SUCCESS) {
    620     // The upload is successfully done. Parse the response which should be
    621     // the entry's metadata.
    622     ParseJson(blocking_task_runner(),
    623               response_writer()->data(),
    624               base::Bind(&UploadRangeRequestBase::OnDataParsed,
    625                          weak_ptr_factory_.GetWeakPtr(),
    626                          code));
    627   } else {
    628     // Failed to upload. Run callbacks to notify the error.
    629     OnRangeRequestComplete(
    630         UploadRangeResponse(code, -1, -1), scoped_ptr<base::Value>());
    631     OnProcessURLFetchResultsComplete();
    632   }
    633 }
    634 
    635 void UploadRangeRequestBase::OnDataParsed(GDataErrorCode code,
    636                                           scoped_ptr<base::Value> value) {
    637   DCHECK(CalledOnValidThread());
    638   DCHECK(code == HTTP_CREATED || code == HTTP_SUCCESS);
    639 
    640   OnRangeRequestComplete(UploadRangeResponse(code, -1, -1), value.Pass());
    641   OnProcessURLFetchResultsComplete();
    642 }
    643 
    644 void UploadRangeRequestBase::RunCallbackOnPrematureFailure(
    645     GDataErrorCode code) {
    646   OnRangeRequestComplete(
    647       UploadRangeResponse(code, 0, 0), scoped_ptr<base::Value>());
    648 }
    649 
    650 //========================== ResumeUploadRequestBase =========================
    651 
    652 ResumeUploadRequestBase::ResumeUploadRequestBase(
    653     RequestSender* sender,
    654     const GURL& upload_location,
    655     int64 start_position,
    656     int64 end_position,
    657     int64 content_length,
    658     const std::string& content_type,
    659     const base::FilePath& local_file_path)
    660     : UploadRangeRequestBase(sender, upload_location),
    661       start_position_(start_position),
    662       end_position_(end_position),
    663       content_length_(content_length),
    664       content_type_(content_type),
    665       local_file_path_(local_file_path) {
    666   DCHECK_LE(start_position_, end_position_);
    667 }
    668 
    669 ResumeUploadRequestBase::~ResumeUploadRequestBase() {}
    670 
    671 std::vector<std::string>
    672 ResumeUploadRequestBase::GetExtraRequestHeaders() const {
    673   if (content_length_ == 0) {
    674     // For uploading an empty document, just PUT an empty content.
    675     DCHECK_EQ(start_position_, 0);
    676     DCHECK_EQ(end_position_, 0);
    677     return std::vector<std::string>();
    678   }
    679 
    680   // The header looks like
    681   // Content-Range: bytes <start_position>-<end_position>/<content_length>
    682   // for example:
    683   // Content-Range: bytes 7864320-8388607/13851821
    684   // The header takes inclusive range, so we adjust by "end_position - 1".
    685   DCHECK_GE(start_position_, 0);
    686   DCHECK_GT(end_position_, 0);
    687   DCHECK_GE(content_length_, 0);
    688 
    689   std::vector<std::string> headers;
    690   headers.push_back(
    691       std::string(kUploadContentRange) +
    692       base::Int64ToString(start_position_) + "-" +
    693       base::Int64ToString(end_position_ - 1) + "/" +
    694       base::Int64ToString(content_length_));
    695   return headers;
    696 }
    697 
    698 bool ResumeUploadRequestBase::GetContentFile(
    699     base::FilePath* local_file_path,
    700     int64* range_offset,
    701     int64* range_length,
    702     std::string* upload_content_type) {
    703   if (start_position_ == end_position_) {
    704     // No content data.
    705     return false;
    706   }
    707 
    708   *local_file_path = local_file_path_;
    709   *range_offset = start_position_;
    710   *range_length = end_position_ - start_position_;
    711   *upload_content_type = content_type_;
    712   return true;
    713 }
    714 
    715 //======================== GetUploadStatusRequestBase ========================
    716 
    717 GetUploadStatusRequestBase::GetUploadStatusRequestBase(RequestSender* sender,
    718                                                        const GURL& upload_url,
    719                                                        int64 content_length)
    720     : UploadRangeRequestBase(sender, upload_url),
    721       content_length_(content_length) {}
    722 
    723 GetUploadStatusRequestBase::~GetUploadStatusRequestBase() {}
    724 
    725 std::vector<std::string>
    726 GetUploadStatusRequestBase::GetExtraRequestHeaders() const {
    727   // The header looks like
    728   // Content-Range: bytes */<content_length>
    729   // for example:
    730   // Content-Range: bytes */13851821
    731   DCHECK_GE(content_length_, 0);
    732 
    733   std::vector<std::string> headers;
    734   headers.push_back(
    735       std::string(kUploadContentRange) + "*/" +
    736       base::Int64ToString(content_length_));
    737   return headers;
    738 }
    739 
    740 //============================ DownloadFileRequestBase =========================
    741 
    742 DownloadFileRequestBase::DownloadFileRequestBase(
    743     RequestSender* sender,
    744     const DownloadActionCallback& download_action_callback,
    745     const GetContentCallback& get_content_callback,
    746     const ProgressCallback& progress_callback,
    747     const GURL& download_url,
    748     const base::FilePath& output_file_path)
    749     : UrlFetchRequestBase(sender),
    750       download_action_callback_(download_action_callback),
    751       get_content_callback_(get_content_callback),
    752       progress_callback_(progress_callback),
    753       download_url_(download_url),
    754       output_file_path_(output_file_path) {
    755   DCHECK(!download_action_callback_.is_null());
    756   DCHECK(!output_file_path_.empty());
    757   // get_content_callback may be null.
    758 }
    759 
    760 DownloadFileRequestBase::~DownloadFileRequestBase() {}
    761 
    762 // Overridden from UrlFetchRequestBase.
    763 GURL DownloadFileRequestBase::GetURL() const {
    764   return download_url_;
    765 }
    766 
    767 void DownloadFileRequestBase::GetOutputFilePath(
    768     base::FilePath* local_file_path,
    769     GetContentCallback* get_content_callback) {
    770   // Configure so that the downloaded content is saved to |output_file_path_|.
    771   *local_file_path = output_file_path_;
    772   *get_content_callback = get_content_callback_;
    773 }
    774 
    775 void DownloadFileRequestBase::OnURLFetchDownloadProgress(
    776     const URLFetcher* source,
    777     int64 current,
    778     int64 total) {
    779   if (!progress_callback_.is_null())
    780     progress_callback_.Run(current, total);
    781 }
    782 
    783 void DownloadFileRequestBase::ProcessURLFetchResults(const URLFetcher* source) {
    784   GDataErrorCode code = GetErrorCode();
    785 
    786   // Take over the ownership of the the downloaded temp file.
    787   base::FilePath temp_file;
    788   if (code == HTTP_SUCCESS) {
    789     response_writer()->DisownFile();
    790     temp_file = output_file_path_;
    791   }
    792 
    793   download_action_callback_.Run(code, temp_file);
    794   OnProcessURLFetchResultsComplete();
    795 }
    796 
    797 void DownloadFileRequestBase::RunCallbackOnPrematureFailure(
    798     GDataErrorCode code) {
    799   download_action_callback_.Run(code, base::FilePath());
    800 }
    801 
    802 }  // namespace google_apis
    803