Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(797)

Unified Diff: chrome/browser/drive/drive_uploader.cc

Issue 1190203002: Move (most of) chrome/browser/drive into components/drive/service. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebasing... Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/drive/drive_uploader.h ('k') | chrome/browser/drive/drive_uploader_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/drive/drive_uploader.cc
diff --git a/chrome/browser/drive/drive_uploader.cc b/chrome/browser/drive/drive_uploader.cc
deleted file mode 100644
index e267d24da00b47e9af01a9e532d3ae82e27185bd..0000000000000000000000000000000000000000
--- a/chrome/browser/drive/drive_uploader.cc
+++ /dev/null
@@ -1,533 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/drive/drive_uploader.h"
-
-#include <algorithm>
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/files/file_util.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/task_runner_util.h"
-#include "chrome/browser/drive/drive_service_interface.h"
-#include "content/public/browser/power_save_blocker.h"
-#include "google_apis/drive/drive_api_parser.h"
-
-using google_apis::CancelCallback;
-using google_apis::FileResource;
-using google_apis::DRIVE_CANCELLED;
-using google_apis::DriveApiErrorCode;
-using google_apis::DRIVE_NO_SPACE;
-using google_apis::HTTP_CONFLICT;
-using google_apis::HTTP_CREATED;
-using google_apis::HTTP_FORBIDDEN;
-using google_apis::HTTP_NOT_FOUND;
-using google_apis::HTTP_PRECONDITION;
-using google_apis::HTTP_RESUME_INCOMPLETE;
-using google_apis::HTTP_SUCCESS;
-using google_apis::ProgressCallback;
-using google_apis::UploadRangeResponse;
-
-namespace drive {
-
-namespace {
-// Upload data is split to multiple HTTP request each conveying kUploadChunkSize
-// bytes (except the request for uploading the last chunk of data).
-// The value must be a multiple of 512KB according to the spec of GData WAPI and
-// Drive API v2. It is set to a smaller value than 2^31 for working around
-// server side error (crbug.com/264089).
-const int64 kUploadChunkSize = (1LL << 30); // 1GB
-// Maximum file size to be uploaded by multipart requests. The file that is
-// larger than the size is processed by resumable upload.
-const int64 kMaxMultipartUploadSize = (1LL << 20); // 1MB
-
-// Drive upload protocol. This is used to back a histogram. Sync this with UMA
-// enum "DriveUploadProtocol" and treat this as append-only.
-enum DriveUploadProtocol {
- UPLOAD_METHOD_RESUMABLE,
- UPLOAD_METHOD_MULTIPART,
- UPLOAD_METHOD_BATCH,
- UPLOAD_METHOD_MAX_VALUE
-};
-
-void RecordDriveUploadProtocol(DriveUploadProtocol protocol) {
- UMA_HISTOGRAM_ENUMERATION(
- "Drive.UploadProtocol", protocol, UPLOAD_METHOD_MAX_VALUE);
-}
-} // namespace
-
-// Refcounted helper class to manage batch request. DriveUploader uses the class
-// for keeping the BatchRequestConfigurator instance while it prepares upload
-// file information asynchronously. DriveUploader discard the reference after
-// getting file information and the instance will be destroyed after all
-// preparations complete. At that time, the helper instance commits owned batch
-// request at the destrutor.
-class DriveUploader::RefCountedBatchRequest
- : public base::RefCounted<RefCountedBatchRequest> {
- public:
- RefCountedBatchRequest(
- scoped_ptr<BatchRequestConfiguratorInterface> configurator)
- : configurator_(configurator.Pass()) {}
-
- // Gets pointer of BatchRequestConfiguratorInterface owned by the instance.
- BatchRequestConfiguratorInterface* configurator() const {
- return configurator_.get();
- }
-
- private:
- friend class base::RefCounted<RefCountedBatchRequest>;
- ~RefCountedBatchRequest() { configurator_->Commit(); }
- scoped_ptr<BatchRequestConfiguratorInterface> configurator_;
-};
-
-// Structure containing current upload information of file, passed between
-// DriveServiceInterface methods and callbacks.
-struct DriveUploader::UploadFileInfo {
- UploadFileInfo(const base::FilePath& local_path,
- const std::string& content_type,
- const UploadCompletionCallback& callback,
- const ProgressCallback& progress_callback)
- : file_path(local_path),
- content_type(content_type),
- completion_callback(callback),
- progress_callback(progress_callback),
- content_length(0),
- next_start_position(-1),
- power_save_blocker(content::PowerSaveBlocker::Create(
- content::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
- content::PowerSaveBlocker::kReasonOther,
- "Upload in progress")),
- cancelled(false),
- weak_ptr_factory_(this) {}
-
- ~UploadFileInfo() {
- }
-
- // Useful for printf debugging.
- std::string DebugString() const {
- return "file_path=[" + file_path.AsUTF8Unsafe() +
- "], content_type=[" + content_type +
- "], content_length=[" + base::UintToString(content_length) +
- "]";
- }
-
- // Returns the callback to cancel the upload represented by this struct.
- CancelCallback GetCancelCallback() {
- return base::Bind(&UploadFileInfo::Cancel, weak_ptr_factory_.GetWeakPtr());
- }
-
- // The local file path of the file to be uploaded.
- const base::FilePath file_path;
-
- // Content-Type of file.
- const std::string content_type;
-
- // Callback to be invoked once the upload has finished.
- const UploadCompletionCallback completion_callback;
-
- // Callback to periodically notify the upload progress.
- const ProgressCallback progress_callback;
-
- // Location URL where file is to be uploaded to, returned from
- // InitiateUpload. Used for the subsequent ResumeUpload requests.
- GURL upload_location;
-
- // Header content-Length.
- int64 content_length;
-
- int64 next_start_position;
-
- // Blocks system suspend while upload is in progress.
- scoped_ptr<content::PowerSaveBlocker> power_save_blocker;
-
- // Fields for implementing cancellation. |cancel_callback| is non-null if
- // there is an in-flight HTTP request. In that case, |cancell_callback| will
- // cancel the operation. |cancelled| is initially false and turns to true
- // once Cancel() is called. DriveUploader will check this field before after
- // an async task other than HTTP requests and cancels the subsequent requests
- // if this is flagged to true.
- CancelCallback cancel_callback;
- bool cancelled;
-
- private:
- // Cancels the upload represented by this struct.
- void Cancel() {
- cancelled = true;
- if (!cancel_callback.is_null())
- cancel_callback.Run();
- }
-
- base::WeakPtrFactory<UploadFileInfo> weak_ptr_factory_;
- DISALLOW_COPY_AND_ASSIGN(UploadFileInfo);
-};
-
-DriveUploader::DriveUploader(
- DriveServiceInterface* drive_service,
- const scoped_refptr<base::TaskRunner>& blocking_task_runner)
- : drive_service_(drive_service),
- blocking_task_runner_(blocking_task_runner),
- weak_ptr_factory_(this) {
-}
-
-DriveUploader::~DriveUploader() {}
-
-CancelCallback DriveUploader::UploadNewFile(
- const std::string& parent_resource_id,
- const base::FilePath& local_file_path,
- const std::string& title,
- const std::string& content_type,
- const UploadNewFileOptions& options,
- const UploadCompletionCallback& callback,
- const ProgressCallback& progress_callback) {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(!parent_resource_id.empty());
- DCHECK(!local_file_path.empty());
- DCHECK(!title.empty());
- DCHECK(!content_type.empty());
- DCHECK(!callback.is_null());
-
- return StartUploadFile(
- scoped_ptr<UploadFileInfo>(new UploadFileInfo(
- local_file_path, content_type, callback, progress_callback)),
- base::Bind(&DriveUploader::CallUploadServiceAPINewFile,
- weak_ptr_factory_.GetWeakPtr(), parent_resource_id, title,
- options, current_batch_request_));
-}
-
-void DriveUploader::StartBatchProcessing() {
- DCHECK(current_batch_request_ == nullptr);
- current_batch_request_ =
- new RefCountedBatchRequest(drive_service_->StartBatchRequest().Pass());
-}
-
-void DriveUploader::StopBatchProcessing() {
- current_batch_request_ = nullptr;
-}
-
-CancelCallback DriveUploader::UploadExistingFile(
- const std::string& resource_id,
- const base::FilePath& local_file_path,
- const std::string& content_type,
- const UploadExistingFileOptions& options,
- const UploadCompletionCallback& callback,
- const ProgressCallback& progress_callback) {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(!resource_id.empty());
- DCHECK(!local_file_path.empty());
- DCHECK(!content_type.empty());
- DCHECK(!callback.is_null());
-
- return StartUploadFile(
- scoped_ptr<UploadFileInfo>(new UploadFileInfo(
- local_file_path, content_type, callback, progress_callback)),
- base::Bind(&DriveUploader::CallUploadServiceAPIExistingFile,
- weak_ptr_factory_.GetWeakPtr(), resource_id, options,
- current_batch_request_));
-}
-
-CancelCallback DriveUploader::ResumeUploadFile(
- const GURL& upload_location,
- const base::FilePath& local_file_path,
- const std::string& content_type,
- const UploadCompletionCallback& callback,
- const ProgressCallback& progress_callback) {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(!local_file_path.empty());
- DCHECK(!content_type.empty());
- DCHECK(!callback.is_null());
-
- scoped_ptr<UploadFileInfo> upload_file_info(new UploadFileInfo(
- local_file_path, content_type, callback, progress_callback));
- upload_file_info->upload_location = upload_location;
-
- return StartUploadFile(
- upload_file_info.Pass(),
- base::Bind(&DriveUploader::StartGetUploadStatus,
- weak_ptr_factory_.GetWeakPtr()));
-}
-
-CancelCallback DriveUploader::StartUploadFile(
- scoped_ptr<UploadFileInfo> upload_file_info,
- const StartInitiateUploadCallback& start_initiate_upload_callback) {
- DCHECK(thread_checker_.CalledOnValidThread());
- DVLOG(1) << "Uploading file: " << upload_file_info->DebugString();
-
- UploadFileInfo* info_ptr = upload_file_info.get();
- base::PostTaskAndReplyWithResult(
- blocking_task_runner_.get(),
- FROM_HERE,
- base::Bind(&base::GetFileSize,
- info_ptr->file_path,
- &info_ptr->content_length),
- base::Bind(&DriveUploader::StartUploadFileAfterGetFileSize,
- weak_ptr_factory_.GetWeakPtr(),
- base::Passed(&upload_file_info),
- start_initiate_upload_callback));
- return info_ptr->GetCancelCallback();
-}
-
-void DriveUploader::StartUploadFileAfterGetFileSize(
- scoped_ptr<UploadFileInfo> upload_file_info,
- const StartInitiateUploadCallback& start_initiate_upload_callback,
- bool get_file_size_result) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- if (!get_file_size_result) {
- UploadFailed(upload_file_info.Pass(), HTTP_NOT_FOUND);
- return;
- }
- DCHECK_GE(upload_file_info->content_length, 0);
-
- if (upload_file_info->cancelled) {
- UploadFailed(upload_file_info.Pass(), DRIVE_CANCELLED);
- return;
- }
- start_initiate_upload_callback.Run(upload_file_info.Pass());
-}
-
-void DriveUploader::CallUploadServiceAPINewFile(
- const std::string& parent_resource_id,
- const std::string& title,
- const UploadNewFileOptions& options,
- const scoped_refptr<RefCountedBatchRequest>& batch_request,
- scoped_ptr<UploadFileInfo> upload_file_info) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- UploadFileInfo* const info_ptr = upload_file_info.get();
- if (info_ptr->content_length <= kMaxMultipartUploadSize) {
- DriveServiceBatchOperationsInterface* service;
- // If this is a batched request, calls the API on the request instead.
- if (batch_request.get()) {
- service = batch_request->configurator();
- RecordDriveUploadProtocol(UPLOAD_METHOD_BATCH);
- } else {
- service = drive_service_;
- RecordDriveUploadProtocol(UPLOAD_METHOD_MULTIPART);
- }
- info_ptr->cancel_callback = service->MultipartUploadNewFile(
- info_ptr->content_type, info_ptr->content_length, parent_resource_id,
- title, info_ptr->file_path, options,
- base::Bind(&DriveUploader::OnMultipartUploadComplete,
- weak_ptr_factory_.GetWeakPtr(),
- base::Passed(&upload_file_info)),
- info_ptr->progress_callback);
- } else {
- RecordDriveUploadProtocol(UPLOAD_METHOD_RESUMABLE);
- info_ptr->cancel_callback = drive_service_->InitiateUploadNewFile(
- info_ptr->content_type, info_ptr->content_length, parent_resource_id,
- title, options, base::Bind(&DriveUploader::OnUploadLocationReceived,
- weak_ptr_factory_.GetWeakPtr(),
- base::Passed(&upload_file_info)));
- }
-}
-
-void DriveUploader::CallUploadServiceAPIExistingFile(
- const std::string& resource_id,
- const UploadExistingFileOptions& options,
- const scoped_refptr<RefCountedBatchRequest>& batch_request,
- scoped_ptr<UploadFileInfo> upload_file_info) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- UploadFileInfo* const info_ptr = upload_file_info.get();
- if (info_ptr->content_length <= kMaxMultipartUploadSize) {
- DriveServiceBatchOperationsInterface* service;
- // If this is a batched request, calls the API on the request instead.
- if (batch_request.get()) {
- service = batch_request->configurator();
- RecordDriveUploadProtocol(UPLOAD_METHOD_BATCH);
- } else {
- service = drive_service_;
- RecordDriveUploadProtocol(UPLOAD_METHOD_MULTIPART);
- }
- info_ptr->cancel_callback = service->MultipartUploadExistingFile(
- info_ptr->content_type, info_ptr->content_length, resource_id,
- info_ptr->file_path, options,
- base::Bind(&DriveUploader::OnMultipartUploadComplete,
- weak_ptr_factory_.GetWeakPtr(),
- base::Passed(&upload_file_info)),
- info_ptr->progress_callback);
- } else {
- RecordDriveUploadProtocol(UPLOAD_METHOD_RESUMABLE);
- info_ptr->cancel_callback = drive_service_->InitiateUploadExistingFile(
- info_ptr->content_type, info_ptr->content_length, resource_id, options,
- base::Bind(&DriveUploader::OnUploadLocationReceived,
- weak_ptr_factory_.GetWeakPtr(),
- base::Passed(&upload_file_info)));
- }
-}
-
-void DriveUploader::OnUploadLocationReceived(
- scoped_ptr<UploadFileInfo> upload_file_info,
- DriveApiErrorCode code,
- const GURL& upload_location) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- DVLOG(1) << "Got upload location [" << upload_location.spec()
- << "] for [" << upload_file_info->file_path.value() << "]";
-
- if (code != HTTP_SUCCESS) {
- if (code == HTTP_PRECONDITION)
- code = HTTP_CONFLICT; // ETag mismatch.
- UploadFailed(upload_file_info.Pass(), code);
- return;
- }
-
- upload_file_info->upload_location = upload_location;
- upload_file_info->next_start_position = 0;
- UploadNextChunk(upload_file_info.Pass());
-}
-
-void DriveUploader::StartGetUploadStatus(
- scoped_ptr<UploadFileInfo> upload_file_info) {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(upload_file_info);
-
- UploadFileInfo* info_ptr = upload_file_info.get();
- info_ptr->cancel_callback = drive_service_->GetUploadStatus(
- info_ptr->upload_location,
- info_ptr->content_length,
- base::Bind(&DriveUploader::OnUploadRangeResponseReceived,
- weak_ptr_factory_.GetWeakPtr(),
- base::Passed(&upload_file_info)));
-}
-
-void DriveUploader::UploadNextChunk(
- scoped_ptr<UploadFileInfo> upload_file_info) {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(upload_file_info);
- DCHECK_GE(upload_file_info->next_start_position, 0);
- DCHECK_LE(upload_file_info->next_start_position,
- upload_file_info->content_length);
-
- if (upload_file_info->cancelled) {
- UploadFailed(upload_file_info.Pass(), DRIVE_CANCELLED);
- return;
- }
-
- // Limit the size of data uploaded per each request by kUploadChunkSize.
- const int64 end_position = std::min(
- upload_file_info->content_length,
- upload_file_info->next_start_position + kUploadChunkSize);
-
- UploadFileInfo* info_ptr = upload_file_info.get();
- info_ptr->cancel_callback = drive_service_->ResumeUpload(
- info_ptr->upload_location,
- info_ptr->next_start_position,
- end_position,
- info_ptr->content_length,
- info_ptr->content_type,
- info_ptr->file_path,
- base::Bind(&DriveUploader::OnUploadRangeResponseReceived,
- weak_ptr_factory_.GetWeakPtr(),
- base::Passed(&upload_file_info)),
- base::Bind(&DriveUploader::OnUploadProgress,
- weak_ptr_factory_.GetWeakPtr(),
- info_ptr->progress_callback,
- info_ptr->next_start_position,
- info_ptr->content_length));
-}
-
-void DriveUploader::OnUploadRangeResponseReceived(
- scoped_ptr<UploadFileInfo> upload_file_info,
- const UploadRangeResponse& response,
- scoped_ptr<FileResource> entry) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- if (response.code == HTTP_CREATED || response.code == HTTP_SUCCESS) {
- // When uploading a new file, we expect HTTP_CREATED, and when uploading
- // an existing file (to overwrite), we expect HTTP_SUCCESS.
- // There is an exception: if we uploading an empty file, uploading a new
- // file also returns HTTP_SUCCESS on Drive API v2. The correct way of the
- // fix should be uploading the metadata only. However, to keep the
- // compatibility with GData WAPI during the migration period, we just
- // relax the condition here.
- // TODO(hidehiko): Upload metadata only for empty files, after GData WAPI
- // code is gone.
- DVLOG(1) << "Successfully created uploaded file=["
- << upload_file_info->file_path.value() << "]";
-
- // Done uploading.
- upload_file_info->completion_callback.Run(
- HTTP_SUCCESS, GURL(), entry.Pass());
- return;
- }
-
- // ETag mismatch.
- if (response.code == HTTP_PRECONDITION) {
- UploadFailed(upload_file_info.Pass(), HTTP_CONFLICT);
- return;
- }
-
- // If code is 308 (RESUME_INCOMPLETE) and |range_received| starts with 0
- // (meaning that the data is uploaded from the beginning of the file),
- // proceed to upload the next chunk.
- if (response.code != HTTP_RESUME_INCOMPLETE ||
- response.start_position_received != 0) {
- DVLOG(1)
- << "UploadNextChunk http code=" << response.code
- << ", start_position_received=" << response.start_position_received
- << ", end_position_received=" << response.end_position_received;
- UploadFailed(
- upload_file_info.Pass(),
- response.code == HTTP_FORBIDDEN ? DRIVE_NO_SPACE : response.code);
- return;
- }
-
- DVLOG(1) << "Received range " << response.start_position_received
- << "-" << response.end_position_received
- << " for [" << upload_file_info->file_path.value() << "]";
-
- upload_file_info->next_start_position = response.end_position_received;
- UploadNextChunk(upload_file_info.Pass());
-}
-
-void DriveUploader::OnUploadProgress(const ProgressCallback& callback,
- int64 start_position,
- int64 total_size,
- int64 progress_of_chunk,
- int64 total_of_chunk) {
- if (!callback.is_null())
- callback.Run(start_position + progress_of_chunk, total_size);
-}
-
-void DriveUploader::UploadFailed(scoped_ptr<UploadFileInfo> upload_file_info,
- DriveApiErrorCode error) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- DVLOG(1) << "Upload failed " << upload_file_info->DebugString();
-
- if (upload_file_info->next_start_position < 0) {
- // Discard the upload location because no request could succeed with it.
- // Maybe it's obsolete.
- upload_file_info->upload_location = GURL();
- }
-
- upload_file_info->completion_callback.Run(
- error, upload_file_info->upload_location, scoped_ptr<FileResource>());
-}
-
-void DriveUploader::OnMultipartUploadComplete(
- scoped_ptr<UploadFileInfo> upload_file_info,
- google_apis::DriveApiErrorCode error,
- scoped_ptr<FileResource> entry) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- if (error == HTTP_CREATED || error == HTTP_SUCCESS) {
- DVLOG(1) << "Successfully created uploaded file=["
- << upload_file_info->file_path.value() << "]";
- // Done uploading.
- upload_file_info->completion_callback.Run(
- HTTP_SUCCESS, upload_file_info->upload_location, entry.Pass());
- } else {
- DVLOG(1) << "Upload failed " << upload_file_info->DebugString();
- if (error == HTTP_PRECONDITION)
- error = HTTP_CONFLICT; // ETag mismatch.
- upload_file_info->completion_callback.Run(
- error, upload_file_info->upload_location, scoped_ptr<FileResource>());
- }
-}
-
-} // namespace drive
« no previous file with comments | « chrome/browser/drive/drive_uploader.h ('k') | chrome/browser/drive/drive_uploader_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698