12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "google_apis/drive/base_requests.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/json/json_reader.h"
87dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/location.h"
9f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/sequenced_task_runner.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/task_runner_util.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/values.h"
14a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "google_apis/drive/request_sender.h"
15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "google_apis/drive/task_util.h"
161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "net/base/io_buffer.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/load_flags.h"
18a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "net/base/net_errors.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/http/http_byte_range.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/http/http_response_headers.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/http/http_util.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/url_request/url_fetcher.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/url_request/url_request_status.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using net::URLFetcher;
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Template for optional OAuth2 authorization HTTP header.
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kAuthorizationHeaderFormat[] = "Authorization: Bearer %s";
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Template for GData API version HTTP header.
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kGDataVersionHeader[] = "GData-Version: 3.0";
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
34868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Maximum number of attempts for re-authentication per request.
35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const int kMaxReAuthenticateAttemptsPerRequest = 1;
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Template for initiate upload of both GData WAPI and Drive API v2.
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kUploadContentType[] = "X-Upload-Content-Type: ";
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kUploadContentLength[] = "X-Upload-Content-Length: ";
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kUploadResponseLocation[] = "location";
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Template for upload data range of both GData WAPI and Drive API v2.
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kUploadContentRange[] = "Content-Range: bytes ";
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kUploadResponseRange[] = "range";
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Parses JSON passed in |json| on |blocking_task_runner|. Runs |callback| on
475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// the calling thread when finished with either success or failure.
485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// The callback must not be null.
495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ParseJsonOnBlockingPool(
505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    base::TaskRunner* blocking_task_runner,
515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const std::string& json,
525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const base::Callback<void(scoped_ptr<base::Value> value)>& callback) {
535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::PostTaskAndReplyWithResult(
545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      blocking_task_runner,
555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      FROM_HERE,
565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      base::Bind(&google_apis::ParseJson, json),
575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      callback);
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns response headers as a string. Returns a warning message if
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |url_fetcher| does not contain a valid response. Used only for debugging.
626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)std::string GetResponseHeadersAsString(const URLFetcher* url_fetcher) {
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // net::HttpResponseHeaders::raw_headers(), as the name implies, stores
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // all headers in their raw format, i.e each header is null-terminated.
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // So logging raw_headers() only shows the first header, which is probably
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the status line.  GetNormalizedHeaders, on the other hand, will show all
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the headers, one per line, which is probably what we want.
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string headers;
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Check that response code indicates response headers are valid (i.e. not
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // malformed) before we retrieve the headers.
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (url_fetcher->GetResponseCode() == URLFetcher::RESPONSE_CODE_INVALID) {
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    headers.assign("Response headers are malformed!!");
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    url_fetcher->GetResponseHeaders()->GetNormalizedHeaders(&headers);
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return headers;
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
79f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool IsSuccessfulResponseCode(int response_code) {
80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return 200 <= response_code && response_code <= 299;
81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace google_apis {
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)scoped_ptr<base::Value> ParseJson(const std::string& json) {
885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  int error_code = -1;
895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::string error_message;
905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_ptr<base::Value> value(base::JSONReader::ReadAndReturnError(
915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      json, base::JSON_PARSE_RFC, &error_code, &error_message));
925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!value.get()) {
945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    std::string trimmed_json;
955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (json.size() < 80) {
965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      trimmed_json  = json;
975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    } else {
985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      // Take the first 50 and the last 10 bytes.
995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      trimmed_json = base::StringPrintf(
1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          "%s [%s bytes] %s",
1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          json.substr(0, 50).c_str(),
1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          base::Uint64ToString(json.size() - 60).c_str(),
1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          json.substr(json.size() - 10).c_str());
1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(WARNING) << "Error while parsing entry response: " << error_message
1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                 << ", code: " << error_code << ", json:\n" << trimmed_json;
1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return value.Pass();
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)//=========================== ResponseWriter ==================================
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ResponseWriter::ResponseWriter(base::SequencedTaskRunner* file_task_runner,
1131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                               const base::FilePath& file_path,
1141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                               const GetContentCallback& get_content_callback)
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : get_content_callback_(get_content_callback),
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      weak_ptr_factory_(this) {
1171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (!file_path.empty()) {
1181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    file_writer_.reset(
1191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        new net::URLFetcherFileWriter(file_task_runner, file_path));
1201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
1211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)ResponseWriter::~ResponseWriter() {
1241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void ResponseWriter::DisownFile() {
1271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK(file_writer_);
1281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  file_writer_->DisownFile();
1291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)int ResponseWriter::Initialize(const net::CompletionCallback& callback) {
1321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (file_writer_)
1331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return file_writer_->Initialize(callback);
1341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  data_.clear();
1361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return net::OK;
1371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)int ResponseWriter::Write(net::IOBuffer* buffer,
1401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                          int num_bytes,
1411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                          const net::CompletionCallback& callback) {
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!get_content_callback_.is_null()) {
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    get_content_callback_.Run(
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        HTTP_SUCCESS,
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        make_scoped_ptr(new std::string(buffer->data(), num_bytes)));
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (file_writer_) {
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const int result = file_writer_->Write(
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        buffer, num_bytes,
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        base::Bind(&ResponseWriter::DidWrite,
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr(),
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                   make_scoped_refptr(buffer), callback));
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (result != net::ERR_IO_PENDING)
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      DidWrite(buffer, net::CompletionCallback(), result);
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return result;
157f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
1581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  data_.append(buffer->data(), num_bytes);
1601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return num_bytes;
1611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)int ResponseWriter::Finish(const net::CompletionCallback& callback) {
1641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (file_writer_)
1651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return file_writer_->Finish(callback);
1661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return net::OK;
1681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ResponseWriter::DidWrite(scoped_refptr<net::IOBuffer> buffer,
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              const net::CompletionCallback& callback,
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              int result) {
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (result > 0) {
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Even if file_writer_ is used, append the data to |data_|, so that it can
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // be used to get error information in case of server side errors.
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // The size limit is to avoid consuming too much redundant memory.
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const size_t kMaxStringSize = 1024*1024;
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (data_.size() < kMaxStringSize) {
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      data_.append(buffer->data(), std::min(static_cast<size_t>(result),
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                            kMaxStringSize - data_.size()));
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!callback.is_null())
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    callback.Run(result);
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
188868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)//============================ UrlFetchRequestBase ===========================
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
190eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochUrlFetchRequestBase::UrlFetchRequestBase(RequestSender* sender)
191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    : re_authenticate_count_(0),
1926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      response_writer_(NULL),
193eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      sender_(sender),
194f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      error_code_(GDATA_OTHER_ERROR),
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      weak_ptr_factory_(this) {
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
198868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)UrlFetchRequestBase::~UrlFetchRequestBase() {}
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
200868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void UrlFetchRequestBase::Start(const std::string& access_token,
201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                const std::string& custom_user_agent,
202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                const ReAuthenticateCallback& callback) {
203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(CalledOnValidThread());
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!access_token.empty());
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!callback.is_null());
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(re_authenticate_callback_.is_null());
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  re_authenticate_callback_ = callback;
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL url = GetURL();
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (url.is_empty()) {
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Error is found on generating the url. Send the error message to the
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // callback, and then return immediately without trying to connect
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // to the server.
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    RunCallbackOnPrematureFailure(GDATA_OTHER_ERROR);
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "URL: " << url.spec();
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  URLFetcher::RequestType request_type = GetRequestType();
2216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  url_fetcher_.reset(URLFetcher::Create(url, request_type, this));
222eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  url_fetcher_->SetRequestContext(sender_->url_request_context_getter());
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Always set flags to neither send nor save cookies.
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher_->SetLoadFlags(
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES |
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      net::LOAD_DISABLE_CACHE);
227eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
228eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::FilePath output_file_path;
2291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  GetContentCallback get_content_callback;
2301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  GetOutputFilePath(&output_file_path, &get_content_callback);
2311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (!get_content_callback.is_null())
2321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    get_content_callback = CreateRelayCallback(get_content_callback);
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  response_writer_ = new ResponseWriter(blocking_task_runner(),
2341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                        output_file_path,
2351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                        get_content_callback);
2361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  url_fetcher_->SaveResponseWithWriter(
2371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      scoped_ptr<net::URLFetcherResponseWriter>(response_writer_));
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Add request headers.
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Note that SetExtraRequestHeaders clears the current headers and sets it
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // to the passed-in headers, so calling it for each header will result in
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // only the last header being set in request headers.
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!custom_user_agent.empty())
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    url_fetcher_->AddExtraRequestHeader("User-Agent: " + custom_user_agent);
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher_->AddExtraRequestHeader(kGDataVersionHeader);
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher_->AddExtraRequestHeader(
247868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      base::StringPrintf(kAuthorizationHeaderFormat, access_token.data()));
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::string> headers = GetExtraRequestHeaders();
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < headers.size(); ++i) {
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    url_fetcher_->AddExtraRequestHeader(headers[i]);
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DVLOG(1) << "Extra header: " << headers[i];
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Set upload data if available.
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string upload_content_type;
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string upload_content;
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (GetContentData(&upload_content_type, &upload_content)) {
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    url_fetcher_->SetUploadData(upload_content_type, upload_content);
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
260a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    base::FilePath local_file_path;
261a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    int64 range_offset = 0;
262a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    int64 range_length = 0;
263a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    if (GetContentFile(&local_file_path, &range_offset, &range_length,
264a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                       &upload_content_type)) {
265a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      url_fetcher_->SetUploadFilePath(
266a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)          upload_content_type,
267a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)          local_file_path,
268a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)          range_offset,
269a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)          range_length,
2707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          blocking_task_runner());
271a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    } else {
272a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      // Even if there is no content data, UrlFetcher requires to set empty
273a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      // upload data string for POST, PUT and PATCH methods, explicitly.
274a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      // It is because that most requests of those methods have non-empty
275a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      // body, and UrlFetcher checks whether it is actually not forgotten.
276a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      if (request_type == URLFetcher::POST ||
277a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)          request_type == URLFetcher::PUT ||
278a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)          request_type == URLFetcher::PATCH) {
279a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        // Set empty upload content-type and upload content, so that
280a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        // the request will have no "Content-type: " header and no content.
281a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        url_fetcher_->SetUploadData(std::string(), std::string());
282a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      }
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher_->Start();
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
289868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)URLFetcher::RequestType UrlFetchRequestBase::GetRequestType() const {
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return URLFetcher::GET;
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
293868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)std::vector<std::string> UrlFetchRequestBase::GetExtraRequestHeaders() const {
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return std::vector<std::string>();
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
297868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool UrlFetchRequestBase::GetContentData(std::string* upload_content_type,
298868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                         std::string* upload_content) {
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return false;
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
302868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool UrlFetchRequestBase::GetContentFile(base::FilePath* local_file_path,
303868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                         int64* range_offset,
304868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                         int64* range_length,
305868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                         std::string* upload_content_type) {
306a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  return false;
307a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
308a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
3091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void UrlFetchRequestBase::GetOutputFilePath(
3101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    base::FilePath* local_file_path,
3111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    GetContentCallback* get_content_callback) {
312eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
313eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
314eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid UrlFetchRequestBase::Cancel() {
3151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  response_writer_ = NULL;
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_fetcher_.reset(NULL);
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RunCallbackOnPrematureFailure(GDATA_CANCELLED);
318eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  sender_->RequestFinished(this);
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
321f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)GDataErrorCode UrlFetchRequestBase::GetErrorCode() {
322f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return error_code_;
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
325eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool UrlFetchRequestBase::CalledOnValidThread() {
326eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return thread_checker_.CalledOnValidThread();
327eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
328eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
329f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)base::SequencedTaskRunner* UrlFetchRequestBase::blocking_task_runner() const {
3307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return sender_->blocking_task_runner();
3317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
3327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
333d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void UrlFetchRequestBase::OnProcessURLFetchResultsComplete() {
334eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  sender_->RequestFinished(this);
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
337868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void UrlFetchRequestBase::OnURLFetchComplete(const URLFetcher* source) {
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "Response headers:\n" << GetResponseHeadersAsString(source);
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
340f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Determine error code.
341f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  error_code_ = static_cast<GDataErrorCode>(source->GetResponseCode());
342f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!source->GetStatus().is_success()) {
343f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    switch (source->GetStatus().error()) {
344f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      case net::ERR_NETWORK_CHANGED:
345f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        error_code_ = GDATA_NO_CONNECTION;
346f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        break;
347f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      default:
348f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        error_code_ = GDATA_OTHER_ERROR;
349f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
350f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
351f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
352f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // The server may return detailed error status in JSON.
353f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // See https://developers.google.com/drive/handle-errors
354f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!IsSuccessfulResponseCode(error_code_)) {
355f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DVLOG(1) << response_writer_->data();
356f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
357f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const char kErrorKey[] = "error";
358f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const char kErrorErrorsKey[] = "errors";
359f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const char kErrorReasonKey[] = "reason";
360f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const char kErrorMessageKey[] = "message";
361f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const char kErrorReasonRateLimitExceeded[] = "rateLimitExceeded";
362f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const char kErrorReasonUserRateLimitExceeded[] = "userRateLimitExceeded";
3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const char kErrorReasonQuotaExceeded[] = "quotaExceeded";
364f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
3655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    scoped_ptr<base::Value> value(ParseJson(response_writer_->data()));
366f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    base::DictionaryValue* dictionary = NULL;
367f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    base::DictionaryValue* error = NULL;
368f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (value &&
369f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        value->GetAsDictionary(&dictionary) &&
370f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        dictionary->GetDictionaryWithoutPathExpansion(kErrorKey, &error)) {
371f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      // Get error message.
372f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      std::string message;
373f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      error->GetStringWithoutPathExpansion(kErrorMessageKey, &message);
374f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      DLOG(ERROR) << "code: " << error_code_ << ", message: " << message;
375f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
376f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      // Override the error code based on the reason of the first error.
377f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      base::ListValue* errors = NULL;
378f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      base::DictionaryValue* first_error = NULL;
379f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (error->GetListWithoutPathExpansion(kErrorErrorsKey, &errors) &&
380f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          errors->GetDictionary(0, &first_error)) {
381f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        std::string reason;
382f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        first_error->GetStringWithoutPathExpansion(kErrorReasonKey, &reason);
383f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        if (reason == kErrorReasonRateLimitExceeded ||
384f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            reason == kErrorReasonUserRateLimitExceeded)
385f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          error_code_ = HTTP_SERVICE_UNAVAILABLE;
3865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (reason == kErrorReasonQuotaExceeded)
3875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          error_code_ = GDATA_NO_SPACE;
388f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
389f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
390f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
391f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
392f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Handle authentication failure.
393f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (error_code_ == HTTP_UNAUTHORIZED) {
394868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (++re_authenticate_count_ <= kMaxReAuthenticateAttemptsPerRequest) {
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Reset re_authenticate_callback_ so Start() can be called again.
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ReAuthenticateCallback callback = re_authenticate_callback_;
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      re_authenticate_callback_.Reset();
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      callback.Run(this);
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
402f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    OnAuthFailed(error_code_);
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Overridden by each specialization
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ProcessURLFetchResults(source);
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
410868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void UrlFetchRequestBase::OnAuthFailed(GDataErrorCode code) {
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RunCallbackOnPrematureFailure(code);
412eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  sender_->RequestFinished(this);
4137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
4147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
415868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)base::WeakPtr<AuthenticatedRequestInterface>
416868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)UrlFetchRequestBase::GetWeakPtr() {
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return weak_ptr_factory_.GetWeakPtr();
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
420868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)//============================ EntryActionRequest ============================
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
422eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochEntryActionRequest::EntryActionRequest(RequestSender* sender,
423eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                       const EntryActionCallback& callback)
424eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    : UrlFetchRequestBase(sender),
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      callback_(callback) {
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!callback_.is_null());
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
429868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)EntryActionRequest::~EntryActionRequest() {}
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
431868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void EntryActionRequest::ProcessURLFetchResults(const URLFetcher* source) {
432f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  callback_.Run(GetErrorCode());
433d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  OnProcessURLFetchResultsComplete();
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
436868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void EntryActionRequest::RunCallbackOnPrematureFailure(GDataErrorCode code) {
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback_.Run(code);
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
440868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)//========================= InitiateUploadRequestBase ========================
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
442868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)InitiateUploadRequestBase::InitiateUploadRequestBase(
443eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    RequestSender* sender,
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const InitiateUploadCallback& callback,
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& content_type,
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int64 content_length)
447eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    : UrlFetchRequestBase(sender),
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      callback_(callback),
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      content_type_(content_type),
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      content_length_(content_length) {
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!callback_.is_null());
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!content_type_.empty());
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_GE(content_length_, 0);
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
456868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)InitiateUploadRequestBase::~InitiateUploadRequestBase() {}
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
458868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void InitiateUploadRequestBase::ProcessURLFetchResults(
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const URLFetcher* source) {
460f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  GDataErrorCode code = GetErrorCode();
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string upload_location;
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (code == HTTP_SUCCESS) {
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Retrieve value of the first "Location" header.
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    source->GetResponseHeaders()->EnumerateHeader(NULL,
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                  kUploadResponseLocation,
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                  &upload_location);
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback_.Run(code, GURL(upload_location));
471d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  OnProcessURLFetchResultsComplete();
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
474868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void InitiateUploadRequestBase::RunCallbackOnPrematureFailure(
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GDataErrorCode code) {
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback_.Run(code, GURL());
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::vector<std::string>
480868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)InitiateUploadRequestBase::GetExtraRequestHeaders() const {
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::string> headers;
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  headers.push_back(kUploadContentType + content_type_);
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  headers.push_back(
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kUploadContentLength + base::Int64ToString(content_length_));
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return headers;
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//============================ UploadRangeResponse =============================
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)UploadRangeResponse::UploadRangeResponse()
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : code(HTTP_SUCCESS),
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      start_position_received(0),
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      end_position_received(0) {
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)UploadRangeResponse::UploadRangeResponse(GDataErrorCode code,
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         int64 start_position_received,
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         int64 end_position_received)
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : code(code),
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      start_position_received(start_position_received),
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      end_position_received(end_position_received) {
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)UploadRangeResponse::~UploadRangeResponse() {
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
507868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)//========================== UploadRangeRequestBase ==========================
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
509eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochUploadRangeRequestBase::UploadRangeRequestBase(RequestSender* sender,
510eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                               const GURL& upload_url)
511eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    : UrlFetchRequestBase(sender),
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      upload_url_(upload_url),
513c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      weak_ptr_factory_(this) {
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
516868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)UploadRangeRequestBase::~UploadRangeRequestBase() {}
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
518868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)GURL UploadRangeRequestBase::GetURL() const {
519868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // This is very tricky to get json from this request. To do that, &alt=json
520868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // has to be appended not here but in InitiateUploadRequestBase::GetURL().
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return upload_url_;
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
524868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)URLFetcher::RequestType UploadRangeRequestBase::GetRequestType() const {
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return URLFetcher::PUT;
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
528868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void UploadRangeRequestBase::ProcessURLFetchResults(
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const URLFetcher* source) {
530f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  GDataErrorCode code = GetErrorCode();
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::HttpResponseHeaders* hdrs = source->GetResponseHeaders();
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (code == HTTP_RESUME_INCOMPLETE) {
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Retrieve value of the first "Range" header.
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // The Range header is appeared only if there is at least one received
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // byte. So, initialize the positions by 0 so that the [0,0) will be
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // returned via the |callback_| for empty data case.
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int64 start_position_received = 0;
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int64 end_position_received = 0;
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string range_received;
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    hdrs->EnumerateHeader(NULL, kUploadResponseRange, &range_received);
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!range_received.empty()) {  // Parse the range header.
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      std::vector<net::HttpByteRange> ranges;
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (net::HttpUtil::ParseRangeHeader(range_received, &ranges) &&
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          !ranges.empty() ) {
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // We only care about the first start-end pair in the range.
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        //
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // Range header represents the range inclusively, while we are treating
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // ranges exclusively (i.e., end_position_received should be one passed
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // the last valid index). So "+ 1" is added.
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        start_position_received = ranges[0].first_byte_position();
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        end_position_received = ranges[0].last_byte_position() + 1;
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // The Range header has the received data range, so the start position
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // should be always 0.
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK_EQ(start_position_received, 0);
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
559868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    OnRangeRequestComplete(UploadRangeResponse(code,
560868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                               start_position_received,
561868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                               end_position_received),
562868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                           scoped_ptr<base::Value>());
5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
564d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    OnProcessURLFetchResultsComplete();
565bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  } else if (code == HTTP_CREATED || code == HTTP_SUCCESS) {
566bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    // The upload is successfully done. Parse the response which should be
567bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    // the entry's metadata.
5685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ParseJsonOnBlockingPool(blocking_task_runner(),
5695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            response_writer()->data(),
5705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            base::Bind(&UploadRangeRequestBase::OnDataParsed,
5715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                       weak_ptr_factory_.GetWeakPtr(),
5725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                       code));
573bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  } else {
574bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    // Failed to upload. Run callbacks to notify the error.
575bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    OnRangeRequestComplete(
576bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch        UploadRangeResponse(code, -1, -1), scoped_ptr<base::Value>());
577d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    OnProcessURLFetchResultsComplete();
5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
581868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void UploadRangeRequestBase::OnDataParsed(GDataErrorCode code,
582868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          scoped_ptr<base::Value> value) {
583eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(CalledOnValidThread());
584bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  DCHECK(code == HTTP_CREATED || code == HTTP_SUCCESS);
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
586868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  OnRangeRequestComplete(UploadRangeResponse(code, -1, -1), value.Pass());
587d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  OnProcessURLFetchResultsComplete();
5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
590868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void UploadRangeRequestBase::RunCallbackOnPrematureFailure(
5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GDataErrorCode code) {
592868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  OnRangeRequestComplete(
5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      UploadRangeResponse(code, 0, 0), scoped_ptr<base::Value>());
5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
596868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)//========================== ResumeUploadRequestBase =========================
5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
598868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)ResumeUploadRequestBase::ResumeUploadRequestBase(
599eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    RequestSender* sender,
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GURL& upload_location,
6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int64 start_position,
6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int64 end_position,
6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int64 content_length,
6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& content_type,
605a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    const base::FilePath& local_file_path)
606eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    : UploadRangeRequestBase(sender, upload_location),
6072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      start_position_(start_position),
6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      end_position_(end_position),
6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      content_length_(content_length),
6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      content_type_(content_type),
611a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      local_file_path_(local_file_path) {
6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_LE(start_position_, end_position_);
6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
615868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)ResumeUploadRequestBase::~ResumeUploadRequestBase() {}
6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::vector<std::string>
618868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)ResumeUploadRequestBase::GetExtraRequestHeaders() const {
6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (content_length_ == 0) {
6202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // For uploading an empty document, just PUT an empty content.
6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK_EQ(start_position_, 0);
6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK_EQ(end_position_, 0);
6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return std::vector<std::string>();
6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The header looks like
6272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Content-Range: bytes <start_position>-<end_position>/<content_length>
6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // for example:
6292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Content-Range: bytes 7864320-8388607/13851821
6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The header takes inclusive range, so we adjust by "end_position - 1".
6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_GE(start_position_, 0);
6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_GT(end_position_, 0);
6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_GE(content_length_, 0);
6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::string> headers;
6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  headers.push_back(
6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      std::string(kUploadContentRange) +
6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Int64ToString(start_position_) + "-" +
6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Int64ToString(end_position_ - 1) + "/" +
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Int64ToString(content_length_));
6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return headers;
6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
644868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool ResumeUploadRequestBase::GetContentFile(
645a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    base::FilePath* local_file_path,
646a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    int64* range_offset,
647a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    int64* range_length,
648a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    std::string* upload_content_type) {
649a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (start_position_ == end_position_) {
650a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // No content data.
651a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return false;
652a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
653a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
654a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  *local_file_path = local_file_path_;
655a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  *range_offset = start_position_;
656a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  *range_length = end_position_ - start_position_;
6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *upload_content_type = content_type_;
6582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
6592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
661868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)//======================== GetUploadStatusRequestBase ========================
662a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
663eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochGetUploadStatusRequestBase::GetUploadStatusRequestBase(RequestSender* sender,
664eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                       const GURL& upload_url,
665eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                       int64 content_length)
666eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    : UploadRangeRequestBase(sender, upload_url),
667868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      content_length_(content_length) {}
668a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
669868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)GetUploadStatusRequestBase::~GetUploadStatusRequestBase() {}
670a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
671a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)std::vector<std::string>
672868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)GetUploadStatusRequestBase::GetExtraRequestHeaders() const {
673a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // The header looks like
674a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Content-Range: bytes */<content_length>
675a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // for example:
676a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Content-Range: bytes */13851821
677a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DCHECK_GE(content_length_, 0);
678a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
679a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  std::vector<std::string> headers;
680a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  headers.push_back(
681a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      std::string(kUploadContentRange) + "*/" +
682a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      base::Int64ToString(content_length_));
683a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  return headers;
684a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
685a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
686eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch//============================ DownloadFileRequestBase =========================
6872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
688eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochDownloadFileRequestBase::DownloadFileRequestBase(
689eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    RequestSender* sender,
6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const DownloadActionCallback& download_action_callback,
6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GetContentCallback& get_content_callback,
692c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ProgressCallback& progress_callback,
6932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GURL& download_url,
6942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& output_file_path)
695eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    : UrlFetchRequestBase(sender),
6962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      download_action_callback_(download_action_callback),
6972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      get_content_callback_(get_content_callback),
698c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      progress_callback_(progress_callback),
699eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      download_url_(download_url),
700eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      output_file_path_(output_file_path) {
7012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!download_action_callback_.is_null());
702eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(!output_file_path_.empty());
7032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // get_content_callback may be null.
7042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
706eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochDownloadFileRequestBase::~DownloadFileRequestBase() {}
7072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
708868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Overridden from UrlFetchRequestBase.
709eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochGURL DownloadFileRequestBase::GetURL() const {
7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return download_url_;
7112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void DownloadFileRequestBase::GetOutputFilePath(
7141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    base::FilePath* local_file_path,
7151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    GetContentCallback* get_content_callback) {
716eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Configure so that the downloaded content is saved to |output_file_path_|.
717eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  *local_file_path = output_file_path_;
7181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  *get_content_callback = get_content_callback_;
719eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
720eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
721eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid DownloadFileRequestBase::OnURLFetchDownloadProgress(
722eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const URLFetcher* source,
723eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    int64 current,
724eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    int64 total) {
725c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!progress_callback_.is_null())
726c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    progress_callback_.Run(current, total);
7272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
729eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid DownloadFileRequestBase::ProcessURLFetchResults(const URLFetcher* source) {
730f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  GDataErrorCode code = GetErrorCode();
7312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Take over the ownership of the the downloaded temp file.
7332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath temp_file;
7341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (code == HTTP_SUCCESS) {
7351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    response_writer()->DisownFile();
7361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    temp_file = output_file_path_;
7372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  download_action_callback_.Run(code, temp_file);
740d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  OnProcessURLFetchResultsComplete();
7412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
743eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid DownloadFileRequestBase::RunCallbackOnPrematureFailure(
744eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    GDataErrorCode code) {
7452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  download_action_callback_.Run(code, base::FilePath());
7462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace google_apis
749