15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
57d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "chrome/browser/drive/drive_uploader.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h"
111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
13a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "base/task_runner_util.h"
147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "chrome/browser/drive/drive_service_interface.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/power_save_blocker.h"
1746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "google_apis/drive/drive_api_parser.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
20eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochusing google_apis::CancelCallback;
2146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)using google_apis::FileResource;
22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochusing google_apis::GDATA_CANCELLED;
23eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochusing google_apis::GDataErrorCode;
24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochusing google_apis::GDATA_NO_SPACE;
25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochusing google_apis::HTTP_CONFLICT;
26eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochusing google_apis::HTTP_CREATED;
27eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochusing google_apis::HTTP_FORBIDDEN;
28eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochusing google_apis::HTTP_NOT_FOUND;
29eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochusing google_apis::HTTP_PRECONDITION;
30eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochusing google_apis::HTTP_RESUME_INCOMPLETE;
31eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochusing google_apis::HTTP_SUCCESS;
32eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochusing google_apis::ProgressCallback;
33eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochusing google_apis::UploadRangeResponse;
34eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
35eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace drive {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3758e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdochnamespace {
3858e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch// Upload data is split to multiple HTTP request each conveying kUploadChunkSize
3958e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch// bytes (except the request for uploading the last chunk of data).
4058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch// The value must be a multiple of 512KB according to the spec of GData WAPI and
4158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch// Drive API v2. It is set to a smaller value than 2^31 for working around
4258e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch// server side error (crbug.com/264089).
4358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdochconst int64 kUploadChunkSize = (1LL << 30);  // 1GB
4458e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch}  // namespace
4558e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Structure containing current upload information of file, passed between
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// DriveServiceInterface methods and callbacks.
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct DriveUploader::UploadFileInfo {
49eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  UploadFileInfo(const base::FilePath& local_path,
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 const std::string& content_type,
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 const UploadCompletionCallback& callback,
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 const ProgressCallback& progress_callback)
53eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      : file_path(local_path),
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        content_type(content_type),
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        completion_callback(callback),
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        progress_callback(progress_callback),
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        content_length(0),
582385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch        next_start_position(-1),
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        power_save_blocker(content::PowerSaveBlocker::Create(
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            content::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)            "Upload in progress")),
627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        cancelled(false),
637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        weak_ptr_factory_(this) {
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ~UploadFileInfo() {
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Useful for printf debugging.
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string DebugString() const {
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return "file_path=[" + file_path.AsUTF8Unsafe() +
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           "], content_type=[" + content_type +
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           "], content_length=[" + base::UintToString(content_length) +
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           "]";
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Returns the callback to cancel the upload represented by this struct.
787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  CancelCallback GetCancelCallback() {
797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return base::Bind(&UploadFileInfo::Cancel, weak_ptr_factory_.GetWeakPtr());
807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The local file path of the file to be uploaded.
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::FilePath file_path;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Content-Type of file.
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string content_type;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Callback to be invoked once the upload has finished.
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const UploadCompletionCallback completion_callback;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Callback to periodically notify the upload progress.
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const ProgressCallback progress_callback;
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Location URL where file is to be uploaded to, returned from
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // InitiateUpload. Used for the subsequent ResumeUpload requests.
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL upload_location;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Header content-Length.
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int64 content_length;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1012385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  int64 next_start_position;
1022385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Blocks system suspend while upload is in progress.
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<content::PowerSaveBlocker> power_save_blocker;
1057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Fields for implementing cancellation. |cancel_callback| is non-null if
1077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // there is an in-flight HTTP request. In that case, |cancell_callback| will
1087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // cancel the operation. |cancelled| is initially false and turns to true
1097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // once Cancel() is called. DriveUploader will check this field before after
1107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // an async task other than HTTP requests and cancels the subsequent requests
1117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // if this is flagged to true.
1127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  CancelCallback cancel_callback;
1137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  bool cancelled;
1147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) private:
1167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Cancels the upload represented by this struct.
1177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  void Cancel() {
1187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    cancelled = true;
1197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (!cancel_callback.is_null())
1207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      cancel_callback.Run();
1217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
1227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  base::WeakPtrFactory<UploadFileInfo> weak_ptr_factory_;
1247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(UploadFileInfo);
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciDriveUploader::DriveUploader(
1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DriveServiceInterface* drive_service,
1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const scoped_refptr<base::TaskRunner>& blocking_task_runner)
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : drive_service_(drive_service),
131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      blocking_task_runner_(blocking_task_runner),
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      weak_ptr_factory_(this) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DriveUploader::~DriveUploader() {}
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)CancelCallback DriveUploader::UploadNewFile(
1387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const std::string& parent_resource_id,
1397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const base::FilePath& local_file_path,
1407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const std::string& title,
1417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const std::string& content_type,
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const UploadNewFileOptions& options,
1437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const UploadCompletionCallback& callback,
1447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const ProgressCallback& progress_callback) {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!parent_resource_id.empty());
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!local_file_path.empty());
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!title.empty());
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!content_type.empty());
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!callback.is_null());
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return StartUploadFile(
153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      scoped_ptr<UploadFileInfo>(new UploadFileInfo(local_file_path,
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                    content_type,
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                    callback,
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                    progress_callback)),
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&DriveUploader::StartInitiateUploadNewFile,
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr(),
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 parent_resource_id,
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 title,
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 options));
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)CancelCallback DriveUploader::UploadExistingFile(
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& resource_id,
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& local_file_path,
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& content_type,
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const UploadExistingFileOptions& options,
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const UploadCompletionCallback& callback,
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ProgressCallback& progress_callback) {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!resource_id.empty());
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!local_file_path.empty());
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!content_type.empty());
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!callback.is_null());
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return StartUploadFile(
178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      scoped_ptr<UploadFileInfo>(new UploadFileInfo(local_file_path,
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                    content_type,
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                    callback,
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                    progress_callback)),
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&DriveUploader::StartInitiateUploadExistingFile,
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr(),
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 resource_id,
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 options));
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)CancelCallback DriveUploader::ResumeUploadFile(
18990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const GURL& upload_location,
19090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const base::FilePath& local_file_path,
19190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const std::string& content_type,
19290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const UploadCompletionCallback& callback,
19390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const ProgressCallback& progress_callback) {
19490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
19590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(!local_file_path.empty());
19690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(!content_type.empty());
19790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(!callback.is_null());
19890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
19990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<UploadFileInfo> upload_file_info(new UploadFileInfo(
200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      local_file_path, content_type,
20190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      callback, progress_callback));
20290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  upload_file_info->upload_location = upload_location;
20390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return StartUploadFile(
20590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      upload_file_info.Pass(),
20690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::Bind(&DriveUploader::StartGetUploadStatus,
20790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr()));
20890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
20990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)CancelCallback DriveUploader::StartUploadFile(
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<UploadFileInfo> upload_file_info,
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const StartInitiateUploadCallback& start_initiate_upload_callback) {
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "Uploading file: " << upload_file_info->DebugString();
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UploadFileInfo* info_ptr = upload_file_info.get();
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::PostTaskAndReplyWithResult(
218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      blocking_task_runner_.get(),
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
220a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      base::Bind(&base::GetFileSize,
221eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                 info_ptr->file_path,
222a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                 &info_ptr->content_length),
223a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      base::Bind(&DriveUploader::StartUploadFileAfterGetFileSize,
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr(),
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 base::Passed(&upload_file_info),
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 start_initiate_upload_callback));
2277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return info_ptr->GetCancelCallback();
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
230a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void DriveUploader::StartUploadFileAfterGetFileSize(
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<UploadFileInfo> upload_file_info,
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const StartInitiateUploadCallback& start_initiate_upload_callback,
233a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    bool get_file_size_result) {
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
236a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (!get_file_size_result) {
237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    UploadFailed(upload_file_info.Pass(), HTTP_NOT_FOUND);
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
240a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DCHECK_GE(upload_file_info->content_length, 0);
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (upload_file_info->cancelled) {
2437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    UploadFailed(upload_file_info.Pass(), GDATA_CANCELLED);
2447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
2457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  start_initiate_upload_callback.Run(upload_file_info.Pass());
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DriveUploader::StartInitiateUploadNewFile(
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& parent_resource_id,
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& title,
2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const UploadNewFileOptions& options,
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<UploadFileInfo> upload_file_info) {
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UploadFileInfo* info_ptr = upload_file_info.get();
2577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  info_ptr->cancel_callback = drive_service_->InitiateUploadNewFile(
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      info_ptr->content_type,
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      info_ptr->content_length,
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      parent_resource_id,
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      title,
2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      options,
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&DriveUploader::OnUploadLocationReceived,
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr(),
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 base::Passed(&upload_file_info)));
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DriveUploader::StartInitiateUploadExistingFile(
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& resource_id,
2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const UploadExistingFileOptions& options,
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<UploadFileInfo> upload_file_info) {
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UploadFileInfo* info_ptr = upload_file_info.get();
2757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  info_ptr->cancel_callback = drive_service_->InitiateUploadExistingFile(
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      info_ptr->content_type,
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      info_ptr->content_length,
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      resource_id,
2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      options,
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&DriveUploader::OnUploadLocationReceived,
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr(),
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 base::Passed(&upload_file_info)));
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DriveUploader::OnUploadLocationReceived(
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<UploadFileInfo> upload_file_info,
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GDataErrorCode code,
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GURL& upload_location) {
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "Got upload location [" << upload_location.spec()
292eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch           << "] for [" << upload_file_info->file_path.value() << "]";
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (code != HTTP_SUCCESS) {
2958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (code == HTTP_PRECONDITION)
2968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      code = HTTP_CONFLICT;  // ETag mismatch.
297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    UploadFailed(upload_file_info.Pass(), code);
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  upload_file_info->upload_location = upload_location;
3022385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  upload_file_info->next_start_position = 0;
3032385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  UploadNextChunk(upload_file_info.Pass());
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void DriveUploader::StartGetUploadStatus(
30790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    scoped_ptr<UploadFileInfo> upload_file_info) {
30890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
30990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(upload_file_info);
31090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
31190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  UploadFileInfo* info_ptr = upload_file_info.get();
3127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  info_ptr->cancel_callback = drive_service_->GetUploadStatus(
31390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      info_ptr->upload_location,
31490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      info_ptr->content_length,
31590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::Bind(&DriveUploader::OnUploadRangeResponseReceived,
31690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr(),
31790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 base::Passed(&upload_file_info)));
31890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
31990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
320a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void DriveUploader::UploadNextChunk(
3212385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    scoped_ptr<UploadFileInfo> upload_file_info) {
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
323a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DCHECK(upload_file_info);
3242385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  DCHECK_GE(upload_file_info->next_start_position, 0);
3252385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  DCHECK_LE(upload_file_info->next_start_position,
3262385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch            upload_file_info->content_length);
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (upload_file_info->cancelled) {
3297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    UploadFailed(upload_file_info.Pass(), GDATA_CANCELLED);
3307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
3317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
3327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
33358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  // Limit the size of data uploaded per each request by kUploadChunkSize.
3342385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  const int64 end_position = std::min(
3352385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      upload_file_info->content_length,
3362385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      upload_file_info->next_start_position + kUploadChunkSize);
33758e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UploadFileInfo* info_ptr = upload_file_info.get();
3397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  info_ptr->cancel_callback = drive_service_->ResumeUpload(
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      info_ptr->upload_location,
3412385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      info_ptr->next_start_position,
34258e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch      end_position,
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      info_ptr->content_length,
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      info_ptr->content_type,
345a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      info_ptr->file_path,
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&DriveUploader::OnUploadRangeResponseReceived,
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr(),
348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Passed(&upload_file_info)),
349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&DriveUploader::OnUploadProgress,
350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr(),
351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 info_ptr->progress_callback,
3522385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                 info_ptr->next_start_position,
353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 info_ptr->content_length));
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DriveUploader::OnUploadRangeResponseReceived(
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<UploadFileInfo> upload_file_info,
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const UploadRangeResponse& response,
35946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    scoped_ptr<FileResource> entry) {
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (response.code == HTTP_CREATED || response.code == HTTP_SUCCESS) {
36390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // When uploading a new file, we expect HTTP_CREATED, and when uploading
36490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // an existing file (to overwrite), we expect HTTP_SUCCESS.
36590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // There is an exception: if we uploading an empty file, uploading a new
36690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // file also returns HTTP_SUCCESS on Drive API v2. The correct way of the
36790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // fix should be uploading the metadata only. However, to keep the
368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // compatibility with GData WAPI during the migration period, we just
369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // relax the condition here.
370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // TODO(hidehiko): Upload metadata only for empty files, after GData WAPI
371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // code is gone.
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "Successfully created uploaded file=["
373eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch             << upload_file_info->file_path.value() << "]";
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Done uploading.
37690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    upload_file_info->completion_callback.Run(
37790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        HTTP_SUCCESS, GURL(), entry.Pass());
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // ETag mismatch.
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (response.code == HTTP_PRECONDITION) {
383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    UploadFailed(upload_file_info.Pass(), HTTP_CONFLICT);
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
387a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // If code is 308 (RESUME_INCOMPLETE) and |range_received| starts with 0
388a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // (meaning that the data is uploaded from the beginning of the file),
389a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // proceed to upload the next chunk.
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (response.code != HTTP_RESUME_INCOMPLETE ||
391a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      response.start_position_received != 0) {
39258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    DVLOG(1)
393a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        << "UploadNextChunk http code=" << response.code
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        << ", start_position_received=" << response.start_position_received
395a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        << ", end_position_received=" << response.end_position_received;
396a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    UploadFailed(
397a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        upload_file_info.Pass(),
398a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        response.code == HTTP_FORBIDDEN ? GDATA_NO_SPACE : response.code);
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "Received range " << response.start_position_received
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           << "-" << response.end_position_received
404eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch           << " for [" << upload_file_info->file_path.value() << "]";
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4062385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  upload_file_info->next_start_position = response.end_position_received;
4072385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  UploadNextChunk(upload_file_info.Pass());
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void DriveUploader::OnUploadProgress(const ProgressCallback& callback,
411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                     int64 start_position,
412c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                     int64 total_size,
413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                     int64 progress_of_chunk,
414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                     int64 total_of_chunk) {
415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!callback.is_null())
416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    callback.Run(start_position + progress_of_chunk, total_size);
417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
418c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DriveUploader::UploadFailed(scoped_ptr<UploadFileInfo> upload_file_info,
420c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 GDataErrorCode error) {
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DVLOG(1) << "Upload failed " << upload_file_info->DebugString();
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4252385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  if (upload_file_info->next_start_position < 0) {
4262385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    // Discard the upload location because no request could succeed with it.
4272385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    // Maybe it's obsolete.
4282385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    upload_file_info->upload_location = GURL();
4292385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  }
4302385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
43190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  upload_file_info->completion_callback.Run(
43246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      error, upload_file_info->upload_location, scoped_ptr<FileResource>());
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}  // namespace drive
436