Chromium Code Reviews| Index: chrome/browser/chromeos/gdata/gdata_file_system.cc |
| diff --git a/chrome/browser/chromeos/gdata/gdata_file_system.cc b/chrome/browser/chromeos/gdata/gdata_file_system.cc |
| index bd79a7fada83c8cb2e48f257cbe1f9bfb8cc4cde..ec9e1f0341f122f0135512c82fb0517511347323 100644 |
| --- a/chrome/browser/chromeos/gdata/gdata_file_system.cc |
| +++ b/chrome/browser/chromeos/gdata/gdata_file_system.cc |
| @@ -862,12 +862,16 @@ GDataFileSystem::GetDocumentsParams::GetDocumentsParams( |
| int start_changestamp, |
| int root_feed_changestamp, |
| std::vector<DocumentFeed*>* feed_list, |
| + bool allow_multiple_feeds, |
| const FilePath& search_file_path, |
| + const std::string& search_query, |
| const FindEntryCallback& callback) |
| : start_changestamp(start_changestamp), |
| root_feed_changestamp(root_feed_changestamp), |
| feed_list(feed_list), |
| + allow_multiple_feeds(allow_multiple_feeds), |
| search_file_path(search_file_path), |
| + search_query(search_query), |
| callback(callback) { |
| } |
| @@ -1128,7 +1132,13 @@ void GDataFileSystem::OnGetAccountMetadata( |
| base::PlatformFileError error = GDataToPlatformError(status); |
| if (error != base::PLATFORM_FILE_OK) { |
| // Get changes starting from the next changestamp from what we have locally. |
| - LoadFeedFromServer(local_changestamp + 1, 0, search_file_path, callback); |
| + LoadFeedFromServer(local_changestamp + 1, 0, |
| + true, |
| + search_file_path, |
| + std::string() /* no search query*/, |
| + callback, |
| + base::Bind(&GDataFileSystem::OnFeedFromServerLoaded, |
| + ui_weak_ptr_)); |
| return; |
| } |
| @@ -1136,7 +1146,13 @@ void GDataFileSystem::OnGetAccountMetadata( |
| if (feed_data.get()) |
| feed = AccountMetadataFeed::CreateFrom(*feed_data); |
| if (!feed.get()) { |
| - LoadFeedFromServer(local_changestamp + 1, 0, search_file_path, callback); |
| + LoadFeedFromServer(local_changestamp + 1, 0, |
| + true, |
| + search_file_path, |
| + std::string() /* no search query*/, |
| + callback, |
| + base::Bind(&GDataFileSystem::OnFeedFromServerLoaded, |
| + ui_weak_ptr_)); |
| return; |
| } |
| @@ -1170,15 +1186,22 @@ void GDataFileSystem::OnGetAccountMetadata( |
| // Load changes from the server. |
| LoadFeedFromServer(local_changestamp > 0 ? local_changestamp + 1 : 0, |
| feed->largest_changestamp(), |
| + true, |
| search_file_path, |
| - callback); |
| + std::string() /* no search query*/, |
| + callback, |
| + base::Bind(&GDataFileSystem::OnFeedFromServerLoaded, |
| + ui_weak_ptr_)); |
| } |
| void GDataFileSystem::LoadFeedFromServer( |
| int start_changestamp, |
| int root_feed_changestamp, |
| + bool allow_multiple_feeds, |
| const FilePath& search_file_path, |
| - const FindEntryCallback& callback) { |
| + const std::string& search_query, |
| + const FindEntryCallback& entry_found_callback, |
| + const LoadDocumentFeedCallback& feed_load_callback) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| // ...then also kick off document feed fetching from the server as well. |
| @@ -1191,13 +1214,49 @@ void GDataFileSystem::LoadFeedFromServer( |
| documents_service_->GetDocuments( |
| GURL(), // root feed start. |
| start_changestamp, |
| + search_query, |
| base::Bind(&GDataFileSystem::OnGetDocuments, |
| ui_weak_ptr_, |
| + feed_load_callback, |
| base::Owned(new GetDocumentsParams(start_changestamp, |
| root_feed_changestamp, |
| feed_list.release(), |
| + allow_multiple_feeds, |
| search_file_path, |
| - callback)))); |
| + search_query, |
| + entry_found_callback)))); |
| +} |
| + |
| +void GDataFileSystem::OnFeedFromServerLoaded(GetDocumentsParams* params, |
| + base::PlatformFileError error) { |
| + if (error != base::PLATFORM_FILE_OK) { |
| + params->callback.Run(error, FilePath(), |
| + reinterpret_cast<GDataEntry*>(NULL)); |
|
satorux1
2012/05/03 17:58:34
indentation is off?
tbarzic
2012/05/03 23:56:17
Done.
|
| + return; |
| + } |
| + |
| + error = UpdateFromFeed(*params->feed_list, |
| + FROM_SERVER, |
| + params->start_changestamp, |
| + params->root_feed_changestamp); |
| + |
| + if (error != base::PLATFORM_FILE_OK) { |
| + if (!params->callback.is_null()) { |
| + params->callback.Run(error, FilePath(), |
| + reinterpret_cast<GDataEntry*>(NULL)); |
|
satorux1
2012/05/03 17:58:34
indentation is off?
tbarzic
2012/05/03 23:56:17
Done.
|
| + } |
| + |
| + return; |
| + } |
| + |
| + // Save file system metadata to disk. |
| + SaveFileSystemAsProto(); |
| + |
| + // If we had someone to report this too, then this retrieval was done in a |
| + // context of search... so continue search. |
| + if (!params->callback.is_null()) { |
| + FindEntryByPathSyncOnUIThread(params->search_file_path, params->callback); |
| + } |
| } |
| void GDataFileSystem::TransferFile(const FilePath& local_file_path, |
| @@ -1358,13 +1417,16 @@ void GDataFileSystem::Copy(const FilePath& src_file_path, |
| CopyOnUIThread(src_file_path, dest_file_path, callback); |
| } |
| -void GDataFileSystem::CopyOnUIThread(const FilePath& src_file_path, |
| - const FilePath& dest_file_path, |
| +void GDataFileSystem::CopyOnUIThread(const FilePath& original_src_file_path, |
| + const FilePath& original_dest_file_path, |
| const FileOperationCallback& callback) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| base::PlatformFileError error = base::PLATFORM_FILE_OK; |
| - FilePath dest_parent_path = dest_file_path.DirName(); |
| + FilePath dest_parent_path = original_dest_file_path.DirName(); |
| + |
| + FilePath src_file_path = original_src_file_path; |
| + FilePath dest_file_path = original_dest_file_path; |
|
satorux1
2012/05/03 17:58:34
If I understand right, you don't have to initializ
tbarzic
2012/05/03 23:56:17
Done.
|
| std::string src_file_resource_id; |
| bool src_file_is_hosted_document = false; |
| @@ -1376,7 +1438,7 @@ void GDataFileSystem::CopyOnUIThread(const FilePath& src_file_path, |
| error = base::PLATFORM_FILE_ERROR_NOT_FOUND; |
| } else if (!dest_parent->AsGDataDirectory()) { |
| error = base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY; |
| - } else if (!src_entry->AsGDataFile()) { |
| + } else if (!src_entry->AsGDataFile() || dest_parent->is_detached()) { |
| // TODO(benchan): Implement copy for directories. In the interim, |
| // we handle recursive directory copy in the file manager. |
| error = base::PLATFORM_FILE_ERROR_INVALID_OPERATION; |
| @@ -1384,6 +1446,12 @@ void GDataFileSystem::CopyOnUIThread(const FilePath& src_file_path, |
| src_file_resource_id = src_entry->resource_id(); |
| src_file_is_hosted_document = |
| src_entry->AsGDataFile()->is_hosted_document(); |
| + // If original source or destinatino paths are virtual (e.g. paths used to |
| + // show content search results), we don't want to use them to perform copy |
| + // operation. Instead we use file paths of the files they point to. |
| + src_file_path = src_entry->GetFilePath(); |
| + dest_parent_path = dest_parent->GetFilePath(); |
|
satorux1
2012/05/03 17:58:34
This code path is used for regular paths (not sear
tbarzic
2012/05/03 23:56:17
Done.
|
| + dest_file_path = dest_parent_path.Append(dest_file_path.BaseName()); |
| } |
| } |
|
satorux1
2012/05/03 17:58:34
might want to add:
DCHECK(!src_file_path.empty())
tbarzic
2012/05/03 23:56:17
Done.
|
| @@ -1534,13 +1602,17 @@ void GDataFileSystem::Move(const FilePath& src_file_path, |
| MoveOnUIThread(src_file_path, dest_file_path, callback); |
| } |
| -void GDataFileSystem::MoveOnUIThread(const FilePath& src_file_path, |
| - const FilePath& dest_file_path, |
| +void GDataFileSystem::MoveOnUIThread(const FilePath& original_src_file_path, |
| + const FilePath& original_dest_file_path, |
| const FileOperationCallback& callback) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| base::PlatformFileError error = base::PLATFORM_FILE_OK; |
| - FilePath dest_parent_path = dest_file_path.DirName(); |
| + FilePath dest_parent_path = original_dest_file_path.DirName(); |
| + |
| + FilePath src_file_path = original_src_file_path; |
| + FilePath dest_file_path = original_dest_file_path; |
| + FilePath dest_name = dest_file_path.BaseName(); |
| { |
| // This scoped lock needs to be released before calling Rename() below. |
| @@ -1549,9 +1621,23 @@ void GDataFileSystem::MoveOnUIThread(const FilePath& src_file_path, |
| GDataEntry* dest_parent = GetGDataEntryByPath(dest_parent_path); |
| if (!src_entry || !dest_parent) { |
| error = base::PLATFORM_FILE_ERROR_NOT_FOUND; |
| - } else { |
| - if (!dest_parent->AsGDataDirectory()) |
| + } else if (!dest_parent->AsGDataDirectory()) { |
| error = base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY; |
| + } else if (dest_parent->is_detached()){ |
| + // We allow moving to a directory without file system root only if it's |
| + // done as part of renaming (i.e. source and destination parent paths are |
| + // the same). |
| + if (src_file_path.DirName() != dest_parent_path) { |
| + error = base::PLATFORM_FILE_ERROR_INVALID_OPERATION; |
| + } else { |
| + // If we are indeed renaming, we have to strip resource id from the file |
| + // name. |
| + std::string resource_id; |
| + std::string file_name; |
| + util::CrackSearchFileName(dest_name.value(), &resource_id, &file_name); |
| + if (!file_name.empty()) |
| + dest_name = FilePath(file_name); |
| + } |
| } |
| if (error != base::PLATFORM_FILE_OK) { |
| @@ -1561,16 +1647,20 @@ void GDataFileSystem::MoveOnUIThread(const FilePath& src_file_path, |
| } |
| return; |
| } |
| + src_file_path = src_entry->GetFilePath(); |
| + if (!dest_parent->is_detached()) |
| + dest_parent_path = dest_parent->GetFilePath(); |
| + dest_file_path = dest_parent_path.Append(dest_name); |
| } |
| // If the file/directory is moved to the same directory, just rename it. |
| - if (src_file_path.DirName() == dest_parent_path) { |
| + if (original_src_file_path.DirName() == dest_parent_path) { |
| FilePathUpdateCallback final_file_path_update_callback = |
| base::Bind(&GDataFileSystem::OnFilePathUpdated, |
| ui_weak_ptr_, |
| callback); |
| - Rename(src_file_path, dest_file_path.BaseName().value(), |
| + Rename(original_src_file_path, dest_name.value(), |
| final_file_path_update_callback); |
| return; |
| } |
| @@ -1710,7 +1800,7 @@ void GDataFileSystem::RemoveOnUIThread( |
| if (!callback.is_null()) { |
| MessageLoop::current()->PostTask( |
| FROM_HERE, |
| - base::Bind(callback, base::PLATFORM_FILE_ERROR_NOT_FOUND)); |
| + base::Bind(callback, base::PLATFORM_FILE_OK)); |
|
satorux1
2012/05/03 17:58:34
Why is it OK? The entry wasn't found, right? pleas
tbarzic
2012/05/03 23:56:17
Done.
|
| } |
| return; |
| } |
| @@ -1720,7 +1810,7 @@ void GDataFileSystem::RemoveOnUIThread( |
| base::Bind(&GDataFileSystem::OnRemovedDocument, |
| ui_weak_ptr_, |
| callback, |
| - file_path)); |
| + entry->GetFilePath())); |
|
satorux1
2012/05/03 17:58:34
why is this changed? file_path == entry->GetFilePa
tbarzic
2012/05/03 23:56:17
not necessary.
if file_path is in gdata search res
satorux1
2012/05/04 01:48:40
I see then, could you add it as a comment?
|
| } |
| void GDataFileSystem::CreateDirectory( |
| @@ -1756,6 +1846,20 @@ void GDataFileSystem::CreateDirectoryOnUIThread( |
| const FileOperationCallback& callback) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + // We don't want ot allow creating new directories in virtual search |
| + // directories. Also directory "gdata/.search" should be reserved. |
| + util::GDataSearchPathType path_type = |
| + util::GetSearchPathStatus(directory_path); |
| + if (path_type == util::GDATA_SEARCH_PATH_ROOT || |
| + path_type == util::GDATA_SEARCH_PATH_QUERY || |
| + path_type == util::GDATA_SEARCH_PATH_RESULT) { |
|
satorux1
2012/05/03 17:58:34
maybe:
if (util::IsSearchDirectoryPath(directory
tbarzic
2012/05/03 23:56:17
Done.
|
| + if (!callback.is_null()) { |
| + MessageLoop::current()->PostTask(FROM_HERE, |
| + base::Bind(callback, base::PLATFORM_FILE_ERROR_INVALID_OPERATION)); |
| + } |
| + return; |
| + } |
| + |
| FilePath last_parent_dir_path; |
| FilePath first_missing_path; |
| GURL last_parent_dir_url; |
| @@ -2670,7 +2774,90 @@ void GDataFileSystem::OnCreateDirectoryCompleted( |
| } |
| } |
| -void GDataFileSystem::OnGetDocuments(GetDocumentsParams* params, |
| +void GDataFileSystem::OnSearchContent(const ReadDirectoryCallback& callback, |
| + GetDocumentsParams* params, |
| + base::PlatformFileError error) { |
| + // The search results will be returned using virtual directory. |
| + // The directory is not really part of the file system, so it has no parent or |
| + // root. |
| + scoped_ptr<GDataDirectory> search_dir(new GDataDirectory(NULL, NULL)); |
| + |
| + base::AutoLock lock(lock_); |
| + |
| + int delta_feed_changestamp = 0; |
| + int num_regular_files = 0; |
| + int num_hosted_documents = 0; |
| + FileResourceIdMap file_map; |
| + if (error == base::PLATFORM_FILE_OK) { |
| + error = FeedToFileResourceMap(*params->feed_list, |
| + &file_map, |
| + &delta_feed_changestamp, |
| + &num_regular_files, |
| + &num_hosted_documents); |
| + } |
| + |
| + if (error == base::PLATFORM_FILE_OK) { |
| + std::set<FilePath> ignored; |
| + |
| + // Go through all entires generated by the feed and add them to the search |
| + // result directory. |
| + for (FileResourceIdMap::const_iterator it = file_map.begin(); |
| + it != file_map.end(); ++it) { |
| + scoped_ptr<GDataEntry> entry(it->second); |
| + DCHECK_EQ(it->first, entry->resource_id()); |
| + DCHECK(!entry->is_deleted()); |
| + |
| + entry->set_title(entry->resource_id() + "." + entry->title()); |
| + |
| + search_dir->AddEntry(entry.release()); |
| + } |
| + } |
| + |
| + scoped_ptr<GDataDirectoryProto> directory_proto(new GDataDirectoryProto); |
| + search_dir->ToProto(directory_proto.get()); |
| + |
| + if (!callback.is_null()) { |
| + callback.Run(error, directory_proto.Pass()); |
| + } |
| +} |
| + |
| +void GDataFileSystem::SearchContent(const std::string& search_query, |
| + const ReadDirectoryCallback& callback) { |
| + if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + const bool posted = BrowserThread::PostTask( |
| + BrowserThread::UI, |
| + FROM_HERE, |
| + base::Bind(&GDataFileSystem::SearchContentOnUIThread, |
| + ui_weak_ptr_, |
| + search_query, |
| + base::Bind(&RelayReadDirectoryCallback, |
| + base::MessageLoopProxy::current(), |
| + callback))); |
| + DCHECK(posted); |
| + return; |
| + } |
| + |
| + SearchContentOnUIThread(search_query, callback); |
| +} |
| + |
| +void GDataFileSystem::SearchContentOnUIThread( |
| + const std::string& search_query, |
| + const ReadDirectoryCallback& callback) { |
| + scoped_ptr<std::vector<DocumentFeed*> > feed_list( |
| + new std::vector<DocumentFeed*>); |
| + |
| + LoadFeedFromServer(0, 0, |
| + false, |
|
satorux1
2012/05/03 17:58:34
could you add comments to 0,0,false? they look cry
tbarzic
2012/05/03 23:56:17
yeah, I came to the same conclusion looking at the
|
| + FilePath(), |
| + search_query, |
| + FindEntryCallback(), |
| + base::Bind(&GDataFileSystem::OnSearchContent, |
| + ui_weak_ptr_, callback)); |
| +} |
| + |
| +void GDataFileSystem::OnGetDocuments(const LoadDocumentFeedCallback& callback, |
| + GetDocumentsParams* params, |
| GDataErrorCode status, |
| scoped_ptr<base::Value> data) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| @@ -2678,14 +2865,12 @@ void GDataFileSystem::OnGetDocuments(GetDocumentsParams* params, |
| base::PlatformFileError error = GDataToPlatformError(status); |
| if (error == base::PLATFORM_FILE_OK && |
| (!data.get() || data->GetType() != Value::TYPE_DICTIONARY)) { |
| - LOG(WARNING) << "No feed content!"; |
| error = base::PLATFORM_FILE_ERROR_FAILED; |
| } |
| if (error != base::PLATFORM_FILE_OK) { |
| - if (!params->callback.is_null()) { |
| - params->callback.Run(error, FilePath(), |
| - reinterpret_cast<GDataEntry*>(NULL)); |
| + if (!callback.is_null()) { |
| + callback.Run(params, error); |
| } |
| return; |
| @@ -2696,9 +2881,8 @@ void GDataFileSystem::OnGetDocuments(GetDocumentsParams* params, |
| GURL next_feed_url; |
| scoped_ptr<DocumentFeed> current_feed(DocumentFeed::ExtractAndParse(*data)); |
| if (!current_feed.get()) { |
| - if (!params->callback.is_null()) { |
| - params->callback.Run(base::PLATFORM_FILE_ERROR_FAILED, FilePath(), |
| - reinterpret_cast<GDataEntry*>(NULL)); |
| + if (!callback.is_null()) { |
| + callback.Run(params, base::PLATFORM_FILE_ERROR_FAILED); |
| } |
| return; |
| @@ -2709,44 +2893,29 @@ void GDataFileSystem::OnGetDocuments(GetDocumentsParams* params, |
| params->feed_list->push_back(current_feed.release()); |
| // Check if we need to collect more data to complete the directory list. |
| - if (has_next_feed_url && !next_feed_url.is_empty()) { |
| + if (params->allow_multiple_feeds && has_next_feed_url && |
| + !next_feed_url.is_empty()) { |
| // Kick of the remaining part of the feeds. |
| documents_service_->GetDocuments( |
| next_feed_url, |
| params->start_changestamp, |
| + params->search_query, |
| base::Bind(&GDataFileSystem::OnGetDocuments, |
| ui_weak_ptr_, |
| + callback, |
| base::Owned( |
| new GetDocumentsParams(params->start_changestamp, |
| params->root_feed_changestamp, |
| params->feed_list.release(), |
| + params->allow_multiple_feeds, |
| params->search_file_path, |
| + params->search_query, |
| params->callback)))); |
| return; |
| } |
| - error = UpdateFromFeed(*params->feed_list, |
| - FROM_SERVER, |
| - params->start_changestamp, |
| - params->root_feed_changestamp); |
| - |
| - if (error != base::PLATFORM_FILE_OK) { |
| - if (!params->callback.is_null()) { |
| - params->callback.Run(error, FilePath(), |
| - reinterpret_cast<GDataEntry*>(NULL)); |
| - } |
| - |
| - return; |
| - } |
| - |
| - // Save file system metadata to disk. |
| - SaveFileSystemAsProto(); |
| - |
| - // If we had someone to report this too, then this retrieval was done in a |
| - // context of search... so continue search. |
| - if (!params->callback.is_null()) { |
| - FindEntryByPathSyncOnUIThread(params->search_file_path, params->callback); |
| - } |
| + if (!callback.is_null()) |
| + callback.Run(params, error); |
| } |
| void GDataFileSystem::LoadRootFeedFromCache( |
| @@ -3510,7 +3679,7 @@ base::PlatformFileError GDataFileSystem::AddNewDirectory( |
| parent_dir->AddEntry(new_entry); |
| - NotifyDirectoryChanged(directory_path); |
| + NotifyDirectoryChanged(entry->GetFilePath()); |
| return base::PLATFORM_FILE_OK; |
| } |