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

Unified Diff: chrome/browser/sync_file_system/drive_backend/api_util.cc

Issue 23787003: [SyncFS] Move SyncFS V1 files from drive_backend to drive_backend_v1 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: move back metadata_db_migration_util* Created 7 years, 3 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
Index: chrome/browser/sync_file_system/drive_backend/api_util.cc
diff --git a/chrome/browser/sync_file_system/drive_backend/api_util.cc b/chrome/browser/sync_file_system/drive_backend/api_util.cc
deleted file mode 100644
index 050b141f0aabc33f441d14c9b2378a39c9776cb1..0000000000000000000000000000000000000000
--- a/chrome/browser/sync_file_system/drive_backend/api_util.cc
+++ /dev/null
@@ -1,1147 +0,0 @@
-// Copyright 2013 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/sync_file_system/drive_backend/api_util.h"
-
-#include <algorithm>
-#include <functional>
-#include <sstream>
-#include <string>
-
-#include "base/file_util.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/threading/sequenced_worker_pool.h"
-#include "base/values.h"
-#include "chrome/browser/drive/drive_api_service.h"
-#include "chrome/browser/drive/drive_api_util.h"
-#include "chrome/browser/drive/drive_uploader.h"
-#include "chrome/browser/drive/gdata_wapi_service.h"
-#include "chrome/browser/google_apis/drive_api_parser.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/signin/profile_oauth2_token_service.h"
-#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
-#include "chrome/browser/sync_file_system/drive_backend/drive_file_sync_util.h"
-#include "chrome/browser/sync_file_system/logger.h"
-#include "chrome/browser/sync_file_system/syncable_file_system_util.h"
-#include "chrome/common/extensions/extension.h"
-#include "content/public/browser/browser_thread.h"
-#include "extensions/common/constants.h"
-#include "net/base/mime_util.h"
-
-namespace sync_file_system {
-namespace drive_backend {
-
-namespace {
-
-enum ParentType {
- PARENT_TYPE_ROOT_OR_EMPTY,
- PARENT_TYPE_DIRECTORY,
-};
-
-const char kSyncRootDirectoryName[] = "Chrome Syncable FileSystem";
-const char kSyncRootDirectoryNameDev[] = "Chrome Syncable FileSystem Dev";
-const char kMimeTypeOctetStream[] = "application/octet-stream";
-
-const char kFakeServerBaseUrl[] = "https://fake_server/";
-const char kFakeDownloadServerBaseUrl[] = "https://fake_download_server/";
-
-void EmptyGDataErrorCodeCallback(google_apis::GDataErrorCode error) {}
-
-bool HasParentLinkTo(const ScopedVector<google_apis::Link>& links,
- const std::string& parent_resource_id,
- ParentType parent_type) {
- bool has_parent = false;
-
- for (ScopedVector<google_apis::Link>::const_iterator itr = links.begin();
- itr != links.end(); ++itr) {
- if ((*itr)->type() == google_apis::Link::LINK_PARENT) {
- has_parent = true;
- if (drive::util::ExtractResourceIdFromUrl((*itr)->href()) ==
- parent_resource_id)
- return true;
- }
- }
-
- return parent_type == PARENT_TYPE_ROOT_OR_EMPTY && !has_parent;
-}
-
-struct TitleAndParentQuery
- : std::unary_function<const google_apis::ResourceEntry*, bool> {
- TitleAndParentQuery(const std::string& title,
- const std::string& parent_resource_id,
- ParentType parent_type)
- : title(title),
- parent_resource_id(parent_resource_id),
- parent_type(parent_type) {}
-
- bool operator()(const google_apis::ResourceEntry* entry) const {
- return entry->title() == title &&
- HasParentLinkTo(entry->links(), parent_resource_id, parent_type);
- }
-
- const std::string& title;
- const std::string& parent_resource_id;
- ParentType parent_type;
-};
-
-void FilterEntriesByTitleAndParent(
- ScopedVector<google_apis::ResourceEntry>* entries,
- const std::string& title,
- const std::string& parent_resource_id,
- ParentType parent_type) {
- typedef ScopedVector<google_apis::ResourceEntry>::iterator iterator;
- iterator itr = std::partition(entries->begin(),
- entries->end(),
- TitleAndParentQuery(title,
- parent_resource_id,
- parent_type));
- entries->erase(itr, entries->end());
-}
-
-google_apis::ResourceEntry* GetDocumentByTitleAndParent(
- const ScopedVector<google_apis::ResourceEntry>& entries,
- const std::string& title,
- const std::string& parent_resource_id,
- ParentType parent_type) {
- typedef ScopedVector<google_apis::ResourceEntry>::const_iterator iterator;
- iterator found =
- std::find_if(entries.begin(),
- entries.end(),
- TitleAndParentQuery(title, parent_resource_id, parent_type));
- if (found != entries.end())
- return *found;
- return NULL;
-}
-
-void EntryAdapterForEnsureTitleUniqueness(
- scoped_ptr<google_apis::ResourceEntry> entry,
- const APIUtil::EnsureUniquenessCallback& callback,
- APIUtil::EnsureUniquenessStatus status,
- google_apis::GDataErrorCode error) {
- callback.Run(error, status, entry.Pass());
-}
-
-void UploadResultAdapter(const APIUtil::ResourceEntryCallback& callback,
- google_apis::GDataErrorCode error,
- const GURL& upload_location,
- scoped_ptr<google_apis::ResourceEntry> entry) {
- callback.Run(error, entry.Pass());
-}
-
-std::string GetMimeTypeFromTitle(const std::string& title) {
- base::FilePath::StringType extension =
- base::FilePath::FromUTF8Unsafe(title).Extension();
- std::string mime_type;
- if (extension.empty() ||
- !net::GetWellKnownMimeTypeFromExtension(extension.substr(1), &mime_type))
- return kMimeTypeOctetStream;
- return mime_type;
-}
-
-bool CreateTemporaryFile(const base::FilePath& dir_path,
- webkit_blob::ScopedFile* temp_file) {
- base::FilePath temp_file_path;
- const bool success = file_util::CreateDirectory(dir_path) &&
- file_util::CreateTemporaryFileInDir(dir_path, &temp_file_path);
- if (!success)
- return success;
- *temp_file =
- webkit_blob::ScopedFile(temp_file_path,
- webkit_blob::ScopedFile::DELETE_ON_SCOPE_OUT,
- base::MessageLoopProxy::current().get());
- return success;
-}
-
-} // namespace
-
-APIUtil::APIUtil(Profile* profile,
- const base::FilePath& temp_dir_path)
- : wapi_url_generator_(
- GURL(google_apis::GDataWapiUrlGenerator::kBaseUrlForProduction),
- GURL(google_apis::GDataWapiUrlGenerator::
- kBaseDownloadUrlForProduction)),
- drive_api_url_generator_(
- GURL(google_apis::DriveApiUrlGenerator::kBaseUrlForProduction),
- GURL(google_apis::DriveApiUrlGenerator::
- kBaseDownloadUrlForProduction)),
- upload_next_key_(0),
- temp_dir_path_(temp_dir_path) {
- OAuth2TokenService* oauth_service =
- ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
- if (IsDriveAPIDisabled()) {
- drive_service_.reset(new drive::GDataWapiService(
- oauth_service,
- profile->GetRequestContext(),
- content::BrowserThread::GetBlockingPool(),
- GURL(google_apis::GDataWapiUrlGenerator::kBaseUrlForProduction),
- GURL(google_apis::GDataWapiUrlGenerator::kBaseDownloadUrlForProduction),
- std::string() /* custom_user_agent */));
- } else {
- drive_service_.reset(new drive::DriveAPIService(
- oauth_service,
- profile->GetRequestContext(),
- content::BrowserThread::GetBlockingPool(),
- GURL(google_apis::DriveApiUrlGenerator::kBaseUrlForProduction),
- GURL(google_apis::DriveApiUrlGenerator::kBaseDownloadUrlForProduction),
- GURL(google_apis::GDataWapiUrlGenerator::kBaseUrlForProduction),
- std::string() /* custom_user_agent */));
- }
-
- drive_service_->Initialize();
- drive_service_->AddObserver(this);
- net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
-
- drive_uploader_.reset(new drive::DriveUploader(
- drive_service_.get(), content::BrowserThread::GetBlockingPool()));
-}
-
-scoped_ptr<APIUtil> APIUtil::CreateForTesting(
- const base::FilePath& temp_dir_path,
- scoped_ptr<drive::DriveServiceInterface> drive_service,
- scoped_ptr<drive::DriveUploaderInterface> drive_uploader) {
- return make_scoped_ptr(new APIUtil(
- temp_dir_path,
- GURL(kFakeServerBaseUrl),
- GURL(kFakeDownloadServerBaseUrl),
- drive_service.Pass(),
- drive_uploader.Pass()));
-}
-
-APIUtil::APIUtil(const base::FilePath& temp_dir_path,
- const GURL& base_url,
- const GURL& base_download_url,
- scoped_ptr<drive::DriveServiceInterface> drive_service,
- scoped_ptr<drive::DriveUploaderInterface> drive_uploader)
- : wapi_url_generator_(base_url, base_download_url),
- drive_api_url_generator_(base_url, base_download_url),
- upload_next_key_(0),
- temp_dir_path_(temp_dir_path) {
- drive_service_ = drive_service.Pass();
- drive_service_->Initialize();
- drive_service_->AddObserver(this);
- net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
-
- drive_uploader_ = drive_uploader.Pass();
-}
-
-APIUtil::~APIUtil() {
- DCHECK(CalledOnValidThread());
- net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
- drive_service_->RemoveObserver(this);
-}
-
-void APIUtil::AddObserver(APIUtilObserver* observer) {
- DCHECK(CalledOnValidThread());
- observers_.AddObserver(observer);
-}
-
-void APIUtil::RemoveObserver(APIUtilObserver* observer) {
- DCHECK(CalledOnValidThread());
- observers_.RemoveObserver(observer);
-}
-
-void APIUtil::GetDriveRootResourceId(const GDataErrorCallback& callback) {
- DCHECK(CalledOnValidThread());
- DCHECK(!IsDriveAPIDisabled());
- DVLOG(2) << "Getting resource id for Drive root";
-
- drive_service_->GetAboutResource(
- base::Bind(&APIUtil::DidGetDriveRootResourceId, AsWeakPtr(), callback));
-}
-
-void APIUtil::DidGetDriveRootResourceId(
- const GDataErrorCallback& callback,
- google_apis::GDataErrorCode error,
- scoped_ptr<google_apis::AboutResource> about_resource) {
- DCHECK(CalledOnValidThread());
-
- if (error != google_apis::HTTP_SUCCESS) {
- DVLOG(2) << "Error on getting resource id for Drive root: " << error;
- callback.Run(error);
- return;
- }
-
- DCHECK(about_resource);
- root_resource_id_ = about_resource->root_folder_id();
- DCHECK(!root_resource_id_.empty());
- DVLOG(2) << "Got resource id for Drive root: " << root_resource_id_;
- callback.Run(error);
-}
-
-void APIUtil::GetDriveDirectoryForSyncRoot(const ResourceIdCallback& callback) {
- DCHECK(CalledOnValidThread());
-
- if (GetRootResourceId().empty()) {
- GetDriveRootResourceId(
- base::Bind(&APIUtil::DidGetDriveRootResourceIdForGetSyncRoot,
- AsWeakPtr(), callback));
- return;
- }
-
- DVLOG(2) << "Getting Drive directory for SyncRoot";
- std::string directory_name(GetSyncRootDirectoryName());
- SearchByTitle(directory_name,
- std::string(),
- base::Bind(&APIUtil::DidGetDirectory,
- AsWeakPtr(),
- std::string(),
- directory_name,
- callback));
-}
-
-void APIUtil::DidGetDriveRootResourceIdForGetSyncRoot(
- const ResourceIdCallback& callback,
- google_apis::GDataErrorCode error) {
- DCHECK(CalledOnValidThread());
- if (error != google_apis::HTTP_SUCCESS) {
- DVLOG(2) << "Error on getting Drive directory for SyncRoot: " << error;
- callback.Run(error, std::string());
- return;
- }
- GetDriveDirectoryForSyncRoot(callback);
-}
-
-void APIUtil::GetDriveDirectoryForOrigin(
- const std::string& sync_root_resource_id,
- const GURL& origin,
- const ResourceIdCallback& callback) {
- DCHECK(CalledOnValidThread());
- DVLOG(2) << "Getting Drive directory for Origin: " << origin;
-
- std::string directory_name(OriginToDirectoryTitle(origin));
- SearchByTitle(directory_name,
- sync_root_resource_id,
- base::Bind(&APIUtil::DidGetDirectory,
- AsWeakPtr(),
- sync_root_resource_id,
- directory_name,
- callback));
-}
-
-void APIUtil::DidGetDirectory(const std::string& parent_resource_id,
- const std::string& directory_name,
- const ResourceIdCallback& callback,
- google_apis::GDataErrorCode error,
- scoped_ptr<google_apis::ResourceList> feed) {
- DCHECK(CalledOnValidThread());
- DCHECK(IsStringASCII(directory_name));
-
- if (error != google_apis::HTTP_SUCCESS) {
- DVLOG(2) << "Error on getting Drive directory: " << error;
- callback.Run(error, std::string());
- return;
- }
-
- std::string resource_id;
- ParentType parent_type = PARENT_TYPE_DIRECTORY;
- if (parent_resource_id.empty()) {
- resource_id = GetRootResourceId();
- DCHECK(!resource_id.empty());
- parent_type = PARENT_TYPE_ROOT_OR_EMPTY;
- } else {
- resource_id = parent_resource_id;
- }
- std::string title(directory_name);
- google_apis::ResourceEntry* entry = GetDocumentByTitleAndParent(
- feed->entries(), title, resource_id, parent_type);
- if (!entry) {
- DVLOG(2) << "Directory not found. Creating: " << directory_name;
- drive_service_->AddNewDirectory(resource_id,
- directory_name,
- base::Bind(&APIUtil::DidCreateDirectory,
- AsWeakPtr(),
- parent_resource_id,
- title,
- callback));
- return;
- }
- DVLOG(2) << "Found Drive directory.";
-
- // TODO(tzik): Handle error.
- DCHECK_EQ(google_apis::ENTRY_KIND_FOLDER, entry->kind());
- DCHECK_EQ(directory_name, entry->title());
-
- if (entry->title() == GetSyncRootDirectoryName())
- EnsureSyncRootIsNotInMyDrive(entry->resource_id());
-
- callback.Run(error, entry->resource_id());
-}
-
-void APIUtil::DidCreateDirectory(const std::string& parent_resource_id,
- const std::string& title,
- const ResourceIdCallback& callback,
- google_apis::GDataErrorCode error,
- scoped_ptr<google_apis::ResourceEntry> entry) {
- DCHECK(CalledOnValidThread());
-
- if (error != google_apis::HTTP_SUCCESS &&
- error != google_apis::HTTP_CREATED) {
- DVLOG(2) << "Error on creating Drive directory: " << error;
- callback.Run(error, std::string());
- return;
- }
- DVLOG(2) << "Created Drive directory.";
-
- DCHECK(entry);
- // Check if any other client creates a directory with same title.
- EnsureTitleUniqueness(
- parent_resource_id,
- title,
- base::Bind(&APIUtil::DidEnsureUniquenessForCreateDirectory,
- AsWeakPtr(),
- callback));
-}
-
-void APIUtil::DidEnsureUniquenessForCreateDirectory(
- const ResourceIdCallback& callback,
- google_apis::GDataErrorCode error,
- EnsureUniquenessStatus status,
- scoped_ptr<google_apis::ResourceEntry> entry) {
- DCHECK(CalledOnValidThread());
-
- if (error != google_apis::HTTP_SUCCESS) {
- callback.Run(error, std::string());
- return;
- }
-
- if (status == NO_DUPLICATES_FOUND)
- error = google_apis::HTTP_CREATED;
-
- DCHECK(entry) << "No entry: " << error;
-
- if (!entry->is_folder()) {
- // TODO(kinuko): Fix this. http://crbug.com/237090
- util::Log(
- logging::LOG_ERROR,
- FROM_HERE,
- "A file is left for CreateDirectory due to file-folder conflict!");
- callback.Run(google_apis::HTTP_CONFLICT, std::string());
- return;
- }
-
- if (entry->title() == GetSyncRootDirectoryName())
- EnsureSyncRootIsNotInMyDrive(entry->resource_id());
-
- callback.Run(error, entry->resource_id());
-}
-
-void APIUtil::GetLargestChangeStamp(const ChangeStampCallback& callback) {
- DCHECK(CalledOnValidThread());
- DVLOG(2) << "Getting largest change id";
-
- drive_service_->GetAboutResource(
- base::Bind(&APIUtil::DidGetLargestChangeStamp, AsWeakPtr(), callback));
-}
-
-void APIUtil::GetResourceEntry(const std::string& resource_id,
- const ResourceEntryCallback& callback) {
- DCHECK(CalledOnValidThread());
- DVLOG(2) << "Getting ResourceEntry for: " << resource_id;
-
- drive_service_->GetResourceEntry(
- resource_id,
- base::Bind(&APIUtil::DidGetResourceEntry, AsWeakPtr(), callback));
-}
-
-void APIUtil::DidGetLargestChangeStamp(
- const ChangeStampCallback& callback,
- google_apis::GDataErrorCode error,
- scoped_ptr<google_apis::AboutResource> about_resource) {
- DCHECK(CalledOnValidThread());
-
- int64 largest_change_id = 0;
- if (error == google_apis::HTTP_SUCCESS) {
- DCHECK(about_resource);
- largest_change_id = about_resource->largest_change_id();
- root_resource_id_ = about_resource->root_folder_id();
- DVLOG(2) << "Got largest change id: " << largest_change_id;
- } else {
- DVLOG(2) << "Error on getting largest change id: " << error;
- }
-
- callback.Run(error, largest_change_id);
-}
-
-void APIUtil::SearchByTitle(const std::string& title,
- const std::string& directory_resource_id,
- const ResourceListCallback& callback) {
- DCHECK(CalledOnValidThread());
- DCHECK(!title.empty());
- DVLOG(2) << "Searching resources in the directory [" << directory_resource_id
- << "] with title [" << title << "]";
-
- drive_service_->SearchByTitle(
- title,
- directory_resource_id,
- base::Bind(&APIUtil::DidGetResourceList, AsWeakPtr(), callback));
-}
-
-void APIUtil::ListFiles(const std::string& directory_resource_id,
- const ResourceListCallback& callback) {
- DCHECK(CalledOnValidThread());
- DVLOG(2) << "Listing resources in the directory [" << directory_resource_id
- << "]";
-
- drive_service_->GetResourceListInDirectory(directory_resource_id, callback);
-}
-
-void APIUtil::ListChanges(int64 start_changestamp,
- const ResourceListCallback& callback) {
- DCHECK(CalledOnValidThread());
- DVLOG(2) << "Listing changes since: " << start_changestamp;
-
- drive_service_->GetChangeList(
- start_changestamp,
- base::Bind(&APIUtil::DidGetResourceList, AsWeakPtr(), callback));
-}
-
-void APIUtil::ContinueListing(const GURL& next_link,
- const ResourceListCallback& callback) {
- DCHECK(CalledOnValidThread());
- DVLOG(2) << "Continue listing on feed: " << next_link.spec();
-
- drive_service_->GetRemainingFileList(
- next_link,
- base::Bind(&APIUtil::DidGetResourceList, AsWeakPtr(), callback));
-}
-
-void APIUtil::DownloadFile(const std::string& resource_id,
- const std::string& local_file_md5,
- const DownloadFileCallback& callback) {
- DCHECK(CalledOnValidThread());
- DCHECK(!temp_dir_path_.empty());
- DVLOG(2) << "Downloading file [" << resource_id << "]";
-
- scoped_ptr<webkit_blob::ScopedFile> temp_file(new webkit_blob::ScopedFile);
- webkit_blob::ScopedFile* temp_file_ptr = temp_file.get();
- content::BrowserThread::PostTaskAndReplyWithResult(
- content::BrowserThread::FILE, FROM_HERE,
- base::Bind(&CreateTemporaryFile, temp_dir_path_, temp_file_ptr),
- base::Bind(&APIUtil::DidGetTemporaryFileForDownload,
- AsWeakPtr(), resource_id, local_file_md5,
- base::Passed(&temp_file), callback));
-}
-
-void APIUtil::UploadNewFile(const std::string& directory_resource_id,
- const base::FilePath& local_file_path,
- const std::string& title,
- const UploadFileCallback& callback) {
- DCHECK(CalledOnValidThread());
- DVLOG(2) << "Uploading new file into the directory [" << directory_resource_id
- << "] with title [" << title << "]";
-
- std::string mime_type = GetMimeTypeFromTitle(title);
- UploadKey upload_key = RegisterUploadCallback(callback);
- ResourceEntryCallback did_upload_callback =
- base::Bind(&APIUtil::DidUploadNewFile,
- AsWeakPtr(),
- directory_resource_id,
- title,
- upload_key);
- drive_uploader_->UploadNewFile(
- directory_resource_id,
- local_file_path,
- title,
- mime_type,
- base::Bind(&UploadResultAdapter, did_upload_callback),
- google_apis::ProgressCallback());
-}
-
-void APIUtil::UploadExistingFile(const std::string& resource_id,
- const std::string& remote_file_md5,
- const base::FilePath& local_file_path,
- const UploadFileCallback& callback) {
- DCHECK(CalledOnValidThread());
- DVLOG(2) << "Uploading existing file [" << resource_id << "]";
- drive_service_->GetResourceEntry(
- resource_id,
- base::Bind(&APIUtil::DidGetResourceEntry,
- AsWeakPtr(),
- base::Bind(&APIUtil::UploadExistingFileInternal,
- AsWeakPtr(),
- remote_file_md5,
- local_file_path,
- callback)));
-}
-
-void APIUtil::CreateDirectory(const std::string& parent_resource_id,
- const std::string& title,
- const ResourceIdCallback& callback) {
- DCHECK(CalledOnValidThread());
- // TODO(kinuko): This will call EnsureTitleUniqueness and will delete
- // directories if there're duplicated directories. This must be ok
- // for current design but we'll need to merge directories when we support
- // 'real' directories.
- drive_service_->AddNewDirectory(parent_resource_id,
- title,
- base::Bind(&APIUtil::DidCreateDirectory,
- AsWeakPtr(),
- parent_resource_id,
- title,
- callback));
-}
-
-void APIUtil::DeleteFile(const std::string& resource_id,
- const std::string& remote_file_md5,
- const GDataErrorCallback& callback) {
- DCHECK(CalledOnValidThread());
- DVLOG(2) << "Deleting file: " << resource_id;
-
- // Load actual remote_file_md5 to check for conflict before deletion.
- if (!remote_file_md5.empty()) {
- drive_service_->GetResourceEntry(
- resource_id,
- base::Bind(&APIUtil::DidGetResourceEntry,
- AsWeakPtr(),
- base::Bind(&APIUtil::DeleteFileInternal,
- AsWeakPtr(),
- remote_file_md5,
- callback)));
- return;
- }
-
- // Expected remote_file_md5 is empty so do a force delete.
- drive_service_->DeleteResource(
- resource_id,
- std::string(),
- base::Bind(&APIUtil::DidDeleteFile, AsWeakPtr(), callback));
- return;
-}
-
-GURL APIUtil::ResourceIdToResourceLink(const std::string& resource_id) const {
- return IsDriveAPIDisabled()
- ? wapi_url_generator_.GenerateEditUrl(resource_id)
- : drive_api_url_generator_.GetFilesGetUrl(resource_id);
-}
-
-void APIUtil::EnsureSyncRootIsNotInMyDrive(
- const std::string& sync_root_resource_id) {
- DCHECK(CalledOnValidThread());
-
- if (GetRootResourceId().empty()) {
- GetDriveRootResourceId(
- base::Bind(&APIUtil::DidGetDriveRootResourceIdForEnsureSyncRoot,
- AsWeakPtr(), sync_root_resource_id));
- return;
- }
-
- DVLOG(2) << "Ensuring the sync root directory is not in 'My Drive'.";
- drive_service_->RemoveResourceFromDirectory(
- GetRootResourceId(),
- sync_root_resource_id,
- base::Bind(&EmptyGDataErrorCodeCallback));
-}
-
-void APIUtil::DidGetDriveRootResourceIdForEnsureSyncRoot(
- const std::string& sync_root_resource_id,
- google_apis::GDataErrorCode error) {
- DCHECK(CalledOnValidThread());
-
- if (error != google_apis::HTTP_SUCCESS) {
- DVLOG(2) << "Error on ensuring the sync root directory is not in"
- << " 'My Drive': " << error;
- // Give up ensuring the sync root directory is not in 'My Drive'. This will
- // be retried at some point.
- return;
- }
-
- DCHECK(!GetRootResourceId().empty());
- EnsureSyncRootIsNotInMyDrive(sync_root_resource_id);
-}
-
-// static
-// TODO(calvinlo): Delete this when Sync Directory Operations are supported by
-// default.
-std::string APIUtil::GetSyncRootDirectoryName() {
- return IsSyncFSDirectoryOperationEnabled() ? kSyncRootDirectoryNameDev
- : kSyncRootDirectoryName;
-}
-
-// static
-std::string APIUtil::OriginToDirectoryTitle(const GURL& origin) {
- DCHECK(origin.SchemeIs(extensions::kExtensionScheme));
- return origin.host();
-}
-
-// static
-GURL APIUtil::DirectoryTitleToOrigin(const std::string& title) {
- return extensions::Extension::GetBaseURLFromExtensionId(title);
-}
-
-void APIUtil::OnReadyToSendRequests() {
- DCHECK(CalledOnValidThread());
- FOR_EACH_OBSERVER(APIUtilObserver, observers_, OnAuthenticated());
-}
-
-void APIUtil::OnConnectionTypeChanged(
- net::NetworkChangeNotifier::ConnectionType type) {
- DCHECK(CalledOnValidThread());
- if (type != net::NetworkChangeNotifier::CONNECTION_NONE) {
- FOR_EACH_OBSERVER(APIUtilObserver, observers_, OnNetworkConnected());
- return;
- }
- // We're now disconnected, reset the drive_uploader_ to force stop
- // uploading, otherwise the uploader may get stuck.
- // TODO(kinuko): Check the uploader behavior if it's the expected behavior
- // (http://crbug.com/223818)
- CancelAllUploads(google_apis::GDATA_NO_CONNECTION);
-}
-
-void APIUtil::DidGetResourceList(
- const ResourceListCallback& callback,
- google_apis::GDataErrorCode error,
- scoped_ptr<google_apis::ResourceList> resource_list) {
- DCHECK(CalledOnValidThread());
-
- if (error != google_apis::HTTP_SUCCESS) {
- DVLOG(2) << "Error on listing resource: " << error;
- callback.Run(error, scoped_ptr<google_apis::ResourceList>());
- return;
- }
-
- DVLOG(2) << "Got resource list";
- DCHECK(resource_list);
- callback.Run(error, resource_list.Pass());
-}
-
-void APIUtil::DidGetResourceEntry(
- const ResourceEntryCallback& callback,
- google_apis::GDataErrorCode error,
- scoped_ptr<google_apis::ResourceEntry> entry) {
- DCHECK(CalledOnValidThread());
-
- if (error != google_apis::HTTP_SUCCESS) {
- DVLOG(2) << "Error on getting resource entry:" << error;
- callback.Run(error, scoped_ptr<google_apis::ResourceEntry>());
- return;
- }
-
- if (entry->deleted()) {
- DVLOG(2) << "Got resource entry, the entry was trashed.";
- callback.Run(google_apis::HTTP_NOT_FOUND, entry.Pass());
- return;
- }
-
- DVLOG(2) << "Got resource entry";
- DCHECK(entry);
- callback.Run(error, entry.Pass());
-}
-
-void APIUtil::DidGetTemporaryFileForDownload(
- const std::string& resource_id,
- const std::string& local_file_md5,
- scoped_ptr<webkit_blob::ScopedFile> local_file,
- const DownloadFileCallback& callback,
- bool success) {
- if (!success) {
- DVLOG(2) << "Error in creating a temp file under "
- << temp_dir_path_.value();
- callback.Run(google_apis::GDATA_FILE_ERROR, std::string(), 0, base::Time(),
- local_file.Pass());
- return;
- }
- drive_service_->GetResourceEntry(
- resource_id,
- base::Bind(&APIUtil::DidGetResourceEntry,
- AsWeakPtr(),
- base::Bind(&APIUtil::DownloadFileInternal,
- AsWeakPtr(),
- local_file_md5,
- base::Passed(&local_file),
- callback)));
-}
-
-void APIUtil::DownloadFileInternal(
- const std::string& local_file_md5,
- scoped_ptr<webkit_blob::ScopedFile> local_file,
- const DownloadFileCallback& callback,
- google_apis::GDataErrorCode error,
- scoped_ptr<google_apis::ResourceEntry> entry) {
- DCHECK(CalledOnValidThread());
-
- if (error != google_apis::HTTP_SUCCESS) {
- DVLOG(2) << "Error on getting resource entry for download";
- callback.Run(error, std::string(), 0, base::Time(),
- local_file.Pass());
- return;
- }
- DCHECK(entry);
-
- DVLOG(2) << "Got resource entry for download";
- // If local file and remote file are same, cancel the download.
- if (local_file_md5 == entry->file_md5()) {
- callback.Run(google_apis::HTTP_NOT_MODIFIED,
- local_file_md5,
- entry->file_size(),
- entry->updated_time(),
- local_file.Pass());
- return;
- }
-
- DVLOG(2) << "Downloading file: " << entry->resource_id();
- const std::string& resource_id = entry->resource_id();
- const base::FilePath& local_file_path = local_file->path();
- drive_service_->DownloadFile(local_file_path,
- resource_id,
- base::Bind(&APIUtil::DidDownloadFile,
- AsWeakPtr(),
- base::Passed(&entry),
- base::Passed(&local_file),
- callback),
- google_apis::GetContentCallback(),
- google_apis::ProgressCallback());
-}
-
-void APIUtil::DidDownloadFile(scoped_ptr<google_apis::ResourceEntry> entry,
- scoped_ptr<webkit_blob::ScopedFile> local_file,
- const DownloadFileCallback& callback,
- google_apis::GDataErrorCode error,
- const base::FilePath& downloaded_file_path) {
- DCHECK(CalledOnValidThread());
- if (error == google_apis::HTTP_SUCCESS)
- DVLOG(2) << "Download completed";
- else
- DVLOG(2) << "Error on downloading file: " << error;
-
- callback.Run(
- error, entry->file_md5(), entry->file_size(), entry->updated_time(),
- local_file.Pass());
-}
-
-void APIUtil::DidUploadNewFile(const std::string& parent_resource_id,
- const std::string& title,
- UploadKey upload_key,
- google_apis::GDataErrorCode error,
- scoped_ptr<google_apis::ResourceEntry> entry) {
- UploadFileCallback callback = GetAndUnregisterUploadCallback(upload_key);
- DCHECK(!callback.is_null());
- if (error != google_apis::HTTP_SUCCESS &&
- error != google_apis::HTTP_CREATED) {
- DVLOG(2) << "Error on uploading new file: " << error;
- callback.Run(error, std::string(), std::string());
- return;
- }
-
- DVLOG(2) << "Upload completed";
- EnsureTitleUniqueness(parent_resource_id,
- title,
- base::Bind(&APIUtil::DidEnsureUniquenessForCreateFile,
- AsWeakPtr(),
- entry->resource_id(),
- callback));
-}
-
-void APIUtil::DidEnsureUniquenessForCreateFile(
- const std::string& expected_resource_id,
- const UploadFileCallback& callback,
- google_apis::GDataErrorCode error,
- EnsureUniquenessStatus status,
- scoped_ptr<google_apis::ResourceEntry> entry) {
- if (error != google_apis::HTTP_SUCCESS) {
- DVLOG(2) << "Error on uploading new file: " << error;
- callback.Run(error, std::string(), std::string());
- return;
- }
-
- switch (status) {
- case NO_DUPLICATES_FOUND:
- // The file was uploaded successfully and no conflict was detected.
- DCHECK(entry);
- DVLOG(2) << "No conflict detected on uploading new file";
- callback.Run(
- google_apis::HTTP_CREATED, entry->resource_id(), entry->file_md5());
- return;
-
- case RESOLVED_DUPLICATES:
- // The file was uploaded successfully but a conflict was detected.
- // The duplicated file was deleted successfully.
- DCHECK(entry);
- if (entry->resource_id() != expected_resource_id) {
- // TODO(kinuko): We should check local vs remote md5 here.
- DVLOG(2) << "Conflict detected on uploading new file";
- callback.Run(google_apis::HTTP_CONFLICT,
- entry->resource_id(),
- entry->file_md5());
- return;
- }
-
- DVLOG(2) << "Conflict detected on uploading new file and resolved";
- callback.Run(
- google_apis::HTTP_CREATED, entry->resource_id(), entry->file_md5());
- return;
-
- default:
- NOTREACHED() << "Unknown status from EnsureTitleUniqueness:" << status
- << " for " << expected_resource_id;
- }
-}
-
-void APIUtil::UploadExistingFileInternal(
- const std::string& remote_file_md5,
- const base::FilePath& local_file_path,
- const UploadFileCallback& callback,
- google_apis::GDataErrorCode error,
- scoped_ptr<google_apis::ResourceEntry> entry) {
- DCHECK(CalledOnValidThread());
-
- if (error != google_apis::HTTP_SUCCESS) {
- DVLOG(2) << "Error on uploading existing file: " << error;
- callback.Run(error, std::string(), std::string());
- return;
- }
- DCHECK(entry);
-
- // If remote file's hash value is different from the expected one, conflict
- // might have occurred.
- if (!remote_file_md5.empty() && remote_file_md5 != entry->file_md5()) {
- DVLOG(2) << "Conflict detected before uploading existing file";
- callback.Run(google_apis::HTTP_CONFLICT, std::string(), std::string());
- return;
- }
-
- std::string mime_type = GetMimeTypeFromTitle(entry->title());
- UploadKey upload_key = RegisterUploadCallback(callback);
- ResourceEntryCallback did_upload_callback =
- base::Bind(&APIUtil::DidUploadExistingFile, AsWeakPtr(), upload_key);
- drive_uploader_->UploadExistingFile(
- entry->resource_id(),
- local_file_path,
- mime_type,
- entry->etag(),
- base::Bind(&UploadResultAdapter, did_upload_callback),
- google_apis::ProgressCallback());
-}
-
-bool APIUtil::IsAuthenticated() const {
- return drive_service_->HasRefreshToken();
-}
-
-void APIUtil::DidUploadExistingFile(
- UploadKey upload_key,
- google_apis::GDataErrorCode error,
- scoped_ptr<google_apis::ResourceEntry> entry) {
- DCHECK(CalledOnValidThread());
- UploadFileCallback callback = GetAndUnregisterUploadCallback(upload_key);
- DCHECK(!callback.is_null());
- if (error != google_apis::HTTP_SUCCESS) {
- DVLOG(2) << "Error on uploading existing file: " << error;
- callback.Run(error, std::string(), std::string());
- return;
- }
-
- DCHECK(entry);
- DVLOG(2) << "Upload completed";
- callback.Run(error, entry->resource_id(), entry->file_md5());
-}
-
-void APIUtil::DeleteFileInternal(const std::string& remote_file_md5,
- const GDataErrorCallback& callback,
- google_apis::GDataErrorCode error,
- scoped_ptr<google_apis::ResourceEntry> entry) {
- DCHECK(CalledOnValidThread());
-
- if (error != google_apis::HTTP_SUCCESS) {
- DVLOG(2) << "Error on getting resource entry for deleting file: " << error;
- callback.Run(error);
- return;
- }
- DCHECK(entry);
-
- // If remote file's hash value is different from the expected one, conflict
- // might have occurred.
- if (!remote_file_md5.empty() && remote_file_md5 != entry->file_md5()) {
- DVLOG(2) << "Conflict detected before deleting file";
- callback.Run(google_apis::HTTP_CONFLICT);
- return;
- }
- DVLOG(2) << "Got resource entry for deleting file";
-
- // Move the file to trash (don't delete it completely).
- drive_service_->DeleteResource(
- entry->resource_id(),
- entry->etag(),
- base::Bind(&APIUtil::DidDeleteFile, AsWeakPtr(), callback));
-}
-
-void APIUtil::DidDeleteFile(const GDataErrorCallback& callback,
- google_apis::GDataErrorCode error) {
- DCHECK(CalledOnValidThread());
- if (error == google_apis::HTTP_SUCCESS)
- DVLOG(2) << "Deletion completed";
- else
- DVLOG(2) << "Error on deleting file: " << error;
-
- callback.Run(error);
-}
-
-void APIUtil::EnsureTitleUniqueness(const std::string& parent_resource_id,
- const std::string& expected_title,
- const EnsureUniquenessCallback& callback) {
- DCHECK(CalledOnValidThread());
- DVLOG(2) << "Checking if there's no conflict on entry creation";
-
- const google_apis::GetResourceListCallback& bound_callback =
- base::Bind(&APIUtil::DidListEntriesToEnsureUniqueness,
- AsWeakPtr(),
- parent_resource_id,
- expected_title,
- callback);
-
- SearchByTitle(expected_title, parent_resource_id, bound_callback);
-}
-
-void APIUtil::DidListEntriesToEnsureUniqueness(
- const std::string& parent_resource_id,
- const std::string& expected_title,
- const EnsureUniquenessCallback& callback,
- google_apis::GDataErrorCode error,
- scoped_ptr<google_apis::ResourceList> feed) {
- DCHECK(CalledOnValidThread());
-
- if (error != google_apis::HTTP_SUCCESS) {
- DVLOG(2) << "Error on listing resource for ensuring title uniqueness";
- callback.Run(
- error, NO_DUPLICATES_FOUND, scoped_ptr<google_apis::ResourceEntry>());
- return;
- }
- DVLOG(2) << "Got resource list for ensuring title uniqueness";
-
- // This filtering is needed only on WAPI. Once we move to Drive API we can
- // drop this.
- std::string resource_id;
- ParentType parent_type = PARENT_TYPE_DIRECTORY;
- if (parent_resource_id.empty()) {
- resource_id = GetRootResourceId();
- DCHECK(!resource_id.empty());
- parent_type = PARENT_TYPE_ROOT_OR_EMPTY;
- } else {
- resource_id = parent_resource_id;
- }
- ScopedVector<google_apis::ResourceEntry> entries;
- entries.swap(*feed->mutable_entries());
- FilterEntriesByTitleAndParent(
- &entries, expected_title, resource_id, parent_type);
-
- if (entries.empty()) {
- DVLOG(2) << "Uploaded file is not found";
- callback.Run(google_apis::HTTP_NOT_FOUND,
- NO_DUPLICATES_FOUND,
- scoped_ptr<google_apis::ResourceEntry>());
- return;
- }
-
- if (entries.size() >= 2) {
- DVLOG(2) << "Conflict detected on creating entry";
- for (size_t i = 0; i < entries.size() - 1; ++i) {
- // TODO(tzik): Replace published_time with creation time after we move to
- // Drive API.
- if (entries[i]->published_time() < entries.back()->published_time())
- std::swap(entries[i], entries.back());
- }
-
- scoped_ptr<google_apis::ResourceEntry> earliest_entry(entries.back());
- entries.back() = NULL;
- entries.get().pop_back();
-
- DeleteEntriesForEnsuringTitleUniqueness(
- entries.Pass(),
- base::Bind(&EntryAdapterForEnsureTitleUniqueness,
- base::Passed(&earliest_entry),
- callback,
- RESOLVED_DUPLICATES));
- return;
- }
-
- DVLOG(2) << "no conflict detected";
- DCHECK_EQ(1u, entries.size());
- scoped_ptr<google_apis::ResourceEntry> entry(entries.front());
- entries.weak_clear();
-
- callback.Run(google_apis::HTTP_SUCCESS, NO_DUPLICATES_FOUND, entry.Pass());
-}
-
-void APIUtil::DeleteEntriesForEnsuringTitleUniqueness(
- ScopedVector<google_apis::ResourceEntry> entries,
- const GDataErrorCallback& callback) {
- DCHECK(CalledOnValidThread());
- DVLOG(2) << "Cleaning up conflict on entry creation";
-
- if (entries.empty()) {
- callback.Run(google_apis::HTTP_SUCCESS);
- return;
- }
-
- scoped_ptr<google_apis::ResourceEntry> entry(entries.back());
- entries.back() = NULL;
- entries.get().pop_back();
-
- // We don't care conflicts here as other clients may be also deleting this
- // file, so passing an empty etag.
- drive_service_->DeleteResource(
- entry->resource_id(),
- std::string(), // empty etag
- base::Bind(&APIUtil::DidDeleteEntriesForEnsuringTitleUniqueness,
- AsWeakPtr(),
- base::Passed(&entries),
- callback));
-}
-
-void APIUtil::DidDeleteEntriesForEnsuringTitleUniqueness(
- ScopedVector<google_apis::ResourceEntry> entries,
- const GDataErrorCallback& callback,
- google_apis::GDataErrorCode error) {
- DCHECK(CalledOnValidThread());
-
- if (error != google_apis::HTTP_SUCCESS &&
- error != google_apis::HTTP_NOT_FOUND) {
- DVLOG(2) << "Error on deleting file: " << error;
- callback.Run(error);
- return;
- }
-
- DVLOG(2) << "Deletion completed";
- DeleteEntriesForEnsuringTitleUniqueness(entries.Pass(), callback);
-}
-
-APIUtil::UploadKey APIUtil::RegisterUploadCallback(
- const UploadFileCallback& callback) {
- const bool inserted = upload_callback_map_.insert(
- std::make_pair(upload_next_key_, callback)).second;
- CHECK(inserted);
- return upload_next_key_++;
-}
-
-APIUtil::UploadFileCallback APIUtil::GetAndUnregisterUploadCallback(
- UploadKey key) {
- UploadFileCallback callback;
- UploadCallbackMap::iterator found = upload_callback_map_.find(key);
- if (found == upload_callback_map_.end())
- return callback;
- callback = found->second;
- upload_callback_map_.erase(found);
- return callback;
-}
-
-void APIUtil::CancelAllUploads(google_apis::GDataErrorCode error) {
- if (upload_callback_map_.empty())
- return;
- for (UploadCallbackMap::iterator iter = upload_callback_map_.begin();
- iter != upload_callback_map_.end();
- ++iter) {
- iter->second.Run(error, std::string(), std::string());
- }
- upload_callback_map_.clear();
- drive_uploader_.reset(new drive::DriveUploader(
- drive_service_.get(), content::BrowserThread::GetBlockingPool()));
-}
-
-std::string APIUtil::GetRootResourceId() const {
- if (IsDriveAPIDisabled())
- return drive_service_->GetRootResourceId();
- return root_resource_id_;
-}
-
-} // namespace drive_backend
-} // namespace sync_file_system

Powered by Google App Engine
This is Rietveld 408576698