diff options
author | zelidrag@chromium.org <zelidrag@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-24 21:09:43 +0000 |
---|---|---|
committer | zelidrag@chromium.org <zelidrag@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-24 21:09:43 +0000 |
commit | 71f2be8ac4c9024f9a7286545d06c921f50f18f3 (patch) | |
tree | 77d45637476f804235d948d53d2920eba27a7d71 /chrome/browser/chromeos/gdata | |
parent | f3dc6fbc4d1ae9591fb59bdcba591fec5a2e7187 (diff) | |
download | chromium_src-71f2be8ac4c9024f9a7286545d06c921f50f18f3.zip chromium_src-71f2be8ac4c9024f9a7286545d06c921f50f18f3.tar.gz chromium_src-71f2be8ac4c9024f9a7286545d06c921f50f18f3.tar.bz2 |
Implemented GDataFileSystem::TransferFile() method. It uploads file from the local path directly to gdata server.
BUG=chromium-os:28331
TEST=none
Review URL: https://chromiumcodereview.appspot.com/9850001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@128775 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/chromeos/gdata')
10 files changed, 209 insertions, 44 deletions
diff --git a/chrome/browser/chromeos/gdata/gdata_download_observer.cc b/chrome/browser/chromeos/gdata/gdata_download_observer.cc index 15b8d7e..f5cc19c 100644 --- a/chrome/browser/chromeos/gdata/gdata_download_observer.cc +++ b/chrome/browser/chromeos/gdata/gdata_download_observer.cc @@ -300,7 +300,9 @@ UploadFileInfo* GDataDownloadObserver::CreateUploadFileInfo( return upload_file_info; } -void GDataDownloadObserver::OnUploadComplete(int32 download_id) { +void GDataDownloadObserver::OnUploadComplete(int32 download_id, + base::PlatformFileError error, + DocumentEntry* unused_entry) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DownloadMap::iterator iter = pending_downloads_.find(download_id); if (iter == pending_downloads_.end()) diff --git a/chrome/browser/chromeos/gdata/gdata_download_observer.h b/chrome/browser/chromeos/gdata/gdata_download_observer.h index b3e9d6b..ef67487 100644 --- a/chrome/browser/chromeos/gdata/gdata_download_observer.h +++ b/chrome/browser/chromeos/gdata/gdata_download_observer.h @@ -10,11 +10,13 @@ #include "base/callback.h" #include "base/memory/weak_ptr.h" +#include "base/platform_file.h" #include "content/public/browser/download_item.h" #include "content/public/browser/download_manager.h" namespace gdata { +class DocumentEntry; class GDataUploader; struct UploadFileInfo; @@ -88,9 +90,11 @@ class GDataDownloadObserver : public content::DownloadManager::Observer, UploadFileInfo* CreateUploadFileInfo(content::DownloadItem* download); // Callback invoked by GDataUploader when the upload associated with - // |download_id| has completed. This function invokes the - // MaybeCompleteDownload() method on the DownloadItem to allow it to complete. - void OnUploadComplete(int32 download_id); + // |download_id| has completed. |error| indicated whether the + // call was successful. This function invokes the MaybeCompleteDownload() + // method on the DownloadItem to allow it to complete. + void OnUploadComplete(int32 download_id, base::PlatformFileError error, + DocumentEntry* unused_entry); // Private data. // Use GDataUploader to trigger file uploads. diff --git a/chrome/browser/chromeos/gdata/gdata_file_system.cc b/chrome/browser/chromeos/gdata/gdata_file_system.cc index 117cf5a..75f1ffd 100644 --- a/chrome/browser/chromeos/gdata/gdata_file_system.cc +++ b/chrome/browser/chromeos/gdata/gdata_file_system.cc @@ -22,10 +22,13 @@ #include "chrome/browser/chromeos/gdata/gdata_documents_service.h" #include "chrome/browser/chromeos/gdata/gdata_download_observer.h" #include "chrome/browser/chromeos/gdata/gdata_sync_client.h" +#include "chrome/browser/chromeos/gdata/gdata_system_service.h" +#include "chrome/browser/chromeos/gdata/gdata_upload_file_info.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_paths_internal.h" #include "content/public/browser/browser_thread.h" +#include "net/base/mime_util.h" #include "webkit/fileapi/file_system_file_util_proxy.h" #include "webkit/fileapi/file_system_types.h" #include "webkit/fileapi/file_system_util.h" @@ -34,6 +37,7 @@ using content::BrowserThread; namespace { +const char kApplicationOctetStream[] = "application/octet-stream"; const FilePath::CharType kGDataRootDirectory[] = FILE_PATH_LITERAL("gdata"); const char kFeedField[] = "feed"; const char kWildCard[] = "*"; @@ -551,14 +555,117 @@ void GDataFileSystem::LoadFeedFromServer( void GDataFileSystem::TransferFile(const FilePath& local_file_path, const FilePath& remote_dest_file_path, const FileOperationCallback& callback) { - // TODO(zelidrag): Wire this with GDataUploader stack. - if (!callback.is_null()) { - MessageLoop::current()->PostTask(FROM_HERE, - base::Bind(callback, base::PLATFORM_FILE_ERROR_NOT_EMPTY)); + base::AutoLock lock(lock_); + // Make sure the destination directory exists + GDataFileBase* dest_dir = GetGDataFileInfoFromPath( + remote_dest_file_path.DirName()); + if (!dest_dir || !dest_dir->AsGDataDirectory()) { + base::MessageLoopProxy::current()->PostTask(FROM_HERE, + base::Bind(callback, base::PLATFORM_FILE_ERROR_NOT_FOUND)); + return; } - return; + + BrowserThread::PostBlockingPoolTask(FROM_HERE, + base::Bind(&GDataFileSystem::CreateUploadFileInfoOnIOThreadPool, + local_file_path, + remote_dest_file_path, + base::Bind(&GDataFileSystem::StartFileUploadOnUIThread, + ui_weak_ptr_factory_->GetWeakPtr(), + base::MessageLoopProxy::current(), + callback))); } +void GDataFileSystem::StartFileUploadOnUIThread( + scoped_refptr<base::MessageLoopProxy> proxy, + const FileOperationCallback& callback, + base::PlatformFileError error, + scoped_ptr<UploadFileInfo> upload_file_info) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + GDataSystemService* service = + GDataSystemServiceFactory::GetForProfile(profile_); + + if (error == base::PLATFORM_FILE_OK) { + if (!service || !upload_file_info.get()) + error = base::PLATFORM_FILE_ERROR_FAILED; + } + + if (error != base::PLATFORM_FILE_OK) { + if (!callback.is_null()) + proxy->PostTask(FROM_HERE, base::Bind(callback, error)); + + return; + } + + upload_file_info->completion_callback = + base::Bind(&GDataFileSystem::OnTransferCompleted, + GetWeakPtrForCurrentThread(), + upload_file_info->file_path, + upload_file_info->gdata_path, + proxy, + callback); + + service->uploader()->UploadFile(upload_file_info.release()); +} + +void GDataFileSystem::OnTransferCompleted( + const FilePath& local_file_path, + const FilePath& remote_dest_file_path, + scoped_refptr<base::MessageLoopProxy> proxy, + const FileOperationCallback& callback, + base::PlatformFileError error, + DocumentEntry* entry) { + if (error == base::PLATFORM_FILE_OK && entry) { + AddUploadedFile(remote_dest_file_path.DirName(), + entry, + local_file_path, + FILE_OPERATION_COPY); + } + proxy->PostTask(FROM_HERE, base::Bind(callback, error)); +} + +// static. +void GDataFileSystem::CreateUploadFileInfoOnIOThreadPool( + const FilePath& local_file, + const FilePath& remote_dest_file, + const CreateUploadFileInfoCallback& callback) { + scoped_ptr<UploadFileInfo> upload_file_info; + + int64 file_size; + if (!file_util::GetFileSize(local_file, &file_size)) { + BrowserThread::PostTask( + BrowserThread::UI, + FROM_HERE, + base::Bind(callback, + base::PLATFORM_FILE_ERROR_NOT_FOUND, + base::Passed(&upload_file_info))); + + return; + } + + upload_file_info.reset(new UploadFileInfo()); + upload_file_info->file_path = local_file; + upload_file_info->file_size = file_size; + // Extract the final path from DownloadItem. + upload_file_info->gdata_path = remote_dest_file; + // Use the file name as the title. + upload_file_info->title = remote_dest_file.BaseName().value(); + upload_file_info->content_length = file_size; + upload_file_info->all_bytes_present = true; + std::string mime_type; + if (!net::GetMimeTypeFromExtension(local_file.Extension(), + &upload_file_info->content_type)) { + upload_file_info->content_type= kApplicationOctetStream; + } + + BrowserThread::PostTask( + BrowserThread::UI, + FROM_HERE, + base::Bind(callback, + base::PLATFORM_FILE_OK, + base::Passed(&upload_file_info))); +} + + void GDataFileSystem::Copy(const FilePath& src_file_path, const FilePath& dest_file_path, const FileOperationCallback& callback) { @@ -1623,7 +1730,13 @@ void GDataFileSystem::SaveFeedOnIOThreadPool( FilePath file_name = meta_cache_path.Append(name); std::string json; +#ifndef NDEBUG + base::JSONWriter::WriteWithOptions(feed.get(), + base::JSONWriter::OPTIONS_PRETTY_PRINT, + &json); +#else base::JSONWriter::Write(feed.get(), &json); +#endif int file_size = static_cast<int>(json.length()); if (file_util::WriteFile(file_name, json.data(), file_size) != file_size) { @@ -2077,12 +2190,13 @@ base::PlatformFileError GDataFileSystem::RemoveFileFromGData( return base::PLATFORM_FILE_OK; } -void GDataFileSystem::AddDownloadedFile(const FilePath& virtual_dir_path, - scoped_ptr<gdata::DocumentEntry> entry, - const FilePath& file_content_path) { +void GDataFileSystem::AddUploadedFile(const FilePath& virtual_dir_path, + gdata::DocumentEntry* entry, + const FilePath& file_content_path, + FileOperationType cache_operation) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - if (!entry.get()) { + if (!entry) { NOTREACHED(); return; } @@ -2100,7 +2214,7 @@ void GDataFileSystem::AddDownloadedFile(const FilePath& virtual_dir_path, return; scoped_ptr<GDataFileBase> new_file( - GDataFileBase::FromDocumentEntry(parent_dir, entry.get(), root_.get())); + GDataFileBase::FromDocumentEntry(parent_dir, entry, root_.get())); if (!new_file.get()) return; @@ -2111,7 +2225,8 @@ void GDataFileSystem::AddDownloadedFile(const FilePath& virtual_dir_path, parent_dir->AddFile(new_file.release()); } NotifyDirectoryChanged(virtual_dir_path); - StoreToCache(resource_id, md5, file_content_path, FILE_OPERATION_MOVE, + + StoreToCache(resource_id, md5, file_content_path, cache_operation, CacheOperationCallback()); } diff --git a/chrome/browser/chromeos/gdata/gdata_file_system.h b/chrome/browser/chromeos/gdata/gdata_file_system.h index e3965ca..d7a8716 100644 --- a/chrome/browser/chromeos/gdata/gdata_file_system.h +++ b/chrome/browser/chromeos/gdata/gdata_file_system.h @@ -33,6 +33,11 @@ class WaitableEvent; namespace gdata { class DocumentsServiceInterface; +struct UploadFileInfo; + +// Used for file operations like removing files. +typedef base::Callback<void(base::PlatformFileError error)> + FileOperationCallback; // Callback for completion of cache operation. typedef base::Callback<void(base::PlatformFileError error, @@ -56,10 +61,6 @@ typedef base::Callback<void(base::PlatformFileError error, GDataFileBase* file)> FindFileCallback; -// Used for file operations like removing files. -typedef base::Callback<void(base::PlatformFileError error)> - FileOperationCallback; - // Used to get files from the file system. typedef base::Callback<void(base::PlatformFileError error, const FilePath& file_path, @@ -361,9 +362,10 @@ class GDataFileSystemInterface { // Creates a new file from |entry| under |virtual_dir_path|. Stored its // content from |file_content_path| into the cache. - virtual void AddDownloadedFile(const FilePath& virtual_dir_path, - scoped_ptr<DocumentEntry> entry, - const FilePath& file_content_path) = 0; + virtual void AddUploadedFile(const FilePath& virtual_dir_path, + DocumentEntry* entry, + const FilePath& file_content_path, + FileOperationType cache_operation) = 0; }; // The production implementation of GDataFileSystemInterface. @@ -431,9 +433,10 @@ class GDataFileSystem : public GDataFileSystemInterface { CachedFileOrigin file_orign) const OVERRIDE; virtual void GetAvailableSpace( const GetAvailableSpaceCallback& callback) OVERRIDE; - virtual void AddDownloadedFile(const FilePath& virtual_dir_path, - scoped_ptr<DocumentEntry> entry, - const FilePath& file_content_path) OVERRIDE; + virtual void AddUploadedFile(const FilePath& virtual_dir_path, + DocumentEntry* entry, + const FilePath& file_content_path, + FileOperationType cache_operation) OVERRIDE; private: friend class GDataUploader; @@ -490,6 +493,12 @@ class GDataFileSystem : public GDataFileSystemInterface { const CacheOperationCallback& callback)> CacheOperationIntermediateCallback; + // Internal intermediate callback for dealing with results of + // CreateUploadFileInfoOnIOThreadPool() method. + typedef base::Callback<void(base::PlatformFileError error, + scoped_ptr<UploadFileInfo> upload_file_info)> + CreateUploadFileInfoCallback; + // Parameters to pass from calling thread to all cache file operations tasks // on IO thread pool. struct ModifyCacheStateParams { @@ -801,6 +810,30 @@ class GDataFileSystem : public GDataFileSystemInterface { const std::string& md5); void NotifyDirectoryChanged(const FilePath& directory_path); + // Helper function that completes bookkeeping tasks related to + // completed file transfer. + void OnTransferCompleted( + const FilePath& local_file_path, + const FilePath& remote_dest_file_path, + scoped_refptr<base::MessageLoopProxy> proxy, + const FileOperationCallback& callback, + base::PlatformFileError error, + DocumentEntry* entry); + + // Kicks off file upload once it receives |upload_file_info|. + void StartFileUploadOnUIThread( + scoped_refptr<base::MessageLoopProxy> proxy, + const FileOperationCallback& callback, + base::PlatformFileError error, + scoped_ptr<UploadFileInfo> upload_file_info); + + // Reads properties of |local_file| and fills in values of UploadFileInfo + // which are returned through |callback| on UI thread. + static void CreateUploadFileInfoOnIOThreadPool( + const FilePath& local_file, + const FilePath& remote_dest_file, + const CreateUploadFileInfoCallback& callback); + // Cache entry points from within GDataFileSystem. // The functionalities of GData blob cache include: // - stores downloaded gdata files on disk, indexed by the resource_id and md5 diff --git a/chrome/browser/chromeos/gdata/gdata_operations.cc b/chrome/browser/chromeos/gdata/gdata_operations.cc index 6b5ebec..ac37665 100644 --- a/chrome/browser/chromeos/gdata/gdata_operations.cc +++ b/chrome/browser/chromeos/gdata/gdata_operations.cc @@ -790,7 +790,9 @@ URLFetcher::RequestType InitiateUploadOperation::GetRequestType() const { std::vector<std::string> InitiateUploadOperation::GetExtraRequestHeaders() const { std::vector<std::string> headers; - headers.push_back(kUploadContentType + params_.content_type); + if (!params_.content_type.empty()) + headers.push_back(kUploadContentType + params_.content_type); + headers.push_back( kUploadContentLength + base::Int64ToString(params_.content_length)); return headers; diff --git a/chrome/browser/chromeos/gdata/gdata_parser.cc b/chrome/browser/chromeos/gdata/gdata_parser.cc index 4cfd3c3..a7fb3a0 100644 --- a/chrome/browser/chromeos/gdata/gdata_parser.cc +++ b/chrome/browser/chromeos/gdata/gdata_parser.cc @@ -73,9 +73,9 @@ const LinkTypeMap kLinkTypeMap[] = { { Link::EDIT_MEDIA, "edit-media" }, { Link::ALT_EDIT_MEDIA, - "alt-edit-media" }, + "http://schemas.google.com/docs/2007#alt-edit-media" }, { Link::ALT_POST, - "alt-post" }, + "http://schemas.google.com/docs/2007#alt-post" }, { Link::FEED, "http://schemas.google.com/g/2005#feed"}, { Link::POST, diff --git a/chrome/browser/chromeos/gdata/gdata_system_service.h b/chrome/browser/chromeos/gdata/gdata_system_service.h index 86754bb..befe0b5 100644 --- a/chrome/browser/chromeos/gdata/gdata_system_service.h +++ b/chrome/browser/chromeos/gdata/gdata_system_service.h @@ -29,6 +29,9 @@ class GDataSystemService : public ProfileKeyedService { // Returns the file system instance. GDataFileSystem* file_system() { return file_system_.get(); } + // Returns the uploader instance. + GDataUploader* uploader() { return uploader_.get(); } + // ProfileKeyedService override: virtual void Shutdown() OVERRIDE; diff --git a/chrome/browser/chromeos/gdata/gdata_upload_file_info.h b/chrome/browser/chromeos/gdata/gdata_upload_file_info.h index 1d5e2b7..42b2772 100644 --- a/chrome/browser/chromeos/gdata/gdata_upload_file_info.h +++ b/chrome/browser/chromeos/gdata/gdata_upload_file_info.h @@ -26,11 +26,14 @@ namespace gdata { class DocumentEntry; +// Used for file operations like removing files. +typedef base::Callback<void(base::PlatformFileError error, + DocumentEntry* entry)> + UploadCompletionCallback; + // Structure containing current upload information of file, passed between // DocumentsService methods and callbacks. struct UploadFileInfo { - typedef base::Closure UploadFileCallback; - UploadFileInfo(); ~UploadFileInfo(); @@ -79,7 +82,7 @@ struct UploadFileInfo { scoped_ptr<DocumentEntry> entry; // Callback to be invoked once the upload has completed. - UploadFileCallback completion_callback; + UploadCompletionCallback completion_callback; }; } // namespace gdata diff --git a/chrome/browser/chromeos/gdata/gdata_uploader.cc b/chrome/browser/chromeos/gdata/gdata_uploader.cc index d8d866b..256502d 100644 --- a/chrome/browser/chromeos/gdata/gdata_uploader.cc +++ b/chrome/browser/chromeos/gdata/gdata_uploader.cc @@ -125,8 +125,10 @@ UploadFileInfo* GDataUploader::GetUploadFileInfo(int upload_id) const { void GDataUploader::RemovePendingUpload(UploadFileInfo* upload_file_info) { pending_uploads_.erase(upload_file_info->upload_id); - if (!upload_file_info->completion_callback.is_null()) - upload_file_info->completion_callback.Run(); + if (!upload_file_info->completion_callback.is_null()) { + upload_file_info->completion_callback.Run( + base::PLATFORM_FILE_ERROR_ABORT, NULL); + } // The file stream is closed by the destructor asynchronously. delete upload_file_info->file_stream; delete upload_file_info; @@ -301,7 +303,9 @@ void GDataUploader::OnResumeUploadResponseReceived( // Done uploading. upload_file_info->entry = entry.Pass(); if (!upload_file_info->completion_callback.is_null()) { - upload_file_info->completion_callback.Run(); + upload_file_info->completion_callback.Run( + base::PLATFORM_FILE_OK, + upload_file_info->entry.get()); upload_file_info->completion_callback.Reset(); } return; @@ -341,10 +345,11 @@ void GDataUploader::OnResumeUploadResponseReceived( } void GDataUploader::UploadComplete(UploadFileInfo* upload_file_info) { - DVLOG(1) << "UploadComplete " << upload_file_info->entry.get(); - file_system_->AddDownloadedFile(upload_file_info->gdata_path.DirName(), - upload_file_info->entry.Pass(), - upload_file_info->file_path); + DVLOG(1) << "UploadComplete " << upload_file_info->file_path.value(); + file_system_->AddUploadedFile(upload_file_info->gdata_path.DirName(), + upload_file_info->entry.get(), + upload_file_info->file_path, + GDataFileSystemInterface::FILE_OPERATION_MOVE); RemovePendingUpload(upload_file_info); } diff --git a/chrome/browser/chromeos/gdata/mock_gdata_file_system.h b/chrome/browser/chromeos/gdata/mock_gdata_file_system.h index fabc2f2..9a5b9d8 100644 --- a/chrome/browser/chromeos/gdata/mock_gdata_file_system.h +++ b/chrome/browser/chromeos/gdata/mock_gdata_file_system.h @@ -72,12 +72,10 @@ class MockGDataFileSystem : public GDataFileSystemInterface { CachedFileOrigin)); MOCK_METHOD1(GetAvailableSpace, void(const GetAvailableSpaceCallback& callback)); - - // scoped_ptr can't be copied. - // TODO(achuith): Figure out how to mock this. - virtual void AddDownloadedFile(const FilePath&, - scoped_ptr<DocumentEntry> entry, - const FilePath& file_content_path) OVERRIDE {} + MOCK_METHOD4(AddUploadedFile, void(const FilePath& file, + DocumentEntry* entry, + const FilePath& file_content_path, + FileOperationType cache_operation)); }; } // namespace gdata |