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

Unified Diff: chrome/browser/chromeos/gdata/gdata_file_system.cc

Issue 10274002: Add gdata content search (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: ben & zel Created 8 years, 8 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/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..7c96d47fd8d7fe21e6c673104b03707eefd70ce7 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 should_fetch_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),
+ should_fetch_multiple_feeds(should_fetch_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 should_fetch_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(),
+ should_fetch_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));
+ 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);
+ }
}
void GDataFileSystem::TransferFile(const FilePath& local_file_path,
@@ -1358,25 +1417,28 @@ 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;
+ FilePath dest_file_path;
std::string src_file_resource_id;
bool src_file_is_hosted_document = false;
{
base::AutoLock lock(lock_);
- GDataEntry* src_entry = GetGDataEntryByPath(src_file_path);
+ GDataEntry* src_entry = GetGDataEntryByPath(original_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()) {
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,9 +1446,21 @@ 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();
+ // |original_src_file_path| and |original_dest_file_path| don't have to
+ // necessary be equal to |src_entry|'s or |dest_entry|'s file path (e.g.
+ // paths used to display gdata content search results).
+ // That's why, instead of using |original_src_file_path| and
+ // |original_dest_file_path|, we will get file paths to use in copy
+ // operation from the entries.
+ src_file_path = src_entry->GetFilePath();
+ dest_parent_path = dest_parent->GetFilePath();
+ dest_file_path = dest_parent_path.Append(dest_file_path.BaseName());
}
}
+ DCHECK(!src_file_path.empty());
+ DCHECK(!dest_file_path.empty());
+
if (error != base::PLATFORM_FILE_OK) {
if (!callback.is_null())
MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback, error));
@@ -1534,24 +1608,42 @@ 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;
+ FilePath dest_file_path;
+ FilePath dest_name = original_dest_file_path.BaseName();
{
// This scoped lock needs to be released before calling Rename() below.
base::AutoLock lock(lock_);
- GDataEntry* src_entry = GetGDataEntryByPath(src_file_path);
+ GDataEntry* src_entry = GetGDataEntryByPath(original_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 (original_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::ParseSearchFileName(dest_name.value(), &resource_id, &file_name);
+ if (!file_name.empty())
+ dest_name = FilePath(file_name);
+ }
}
if (error != base::PLATFORM_FILE_OK) {
@@ -1561,16 +1653,29 @@ void GDataFileSystem::MoveOnUIThread(const FilePath& src_file_path,
}
return;
}
+ // |original_src_file_path| and |original_dest_file_path| don't have to
+ // necessary be equal to |src_entry|'s or |dest_entry|'s file path (e.g.
+ // paths used to display gdata content search results).
+ // That's why, instead of using |original_src_file_path| and
+ // |original_dest_file_path|, we will get file paths to use in move
+ // operation from the entries.
+ 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);
}
+ DCHECK(!src_file_path.empty());
+ DCHECK(!dest_file_path.empty());
+
// 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;
}
@@ -1720,7 +1825,7 @@ void GDataFileSystem::RemoveOnUIThread(
base::Bind(&GDataFileSystem::OnRemovedDocument,
ui_weak_ptr_,
callback,
- file_path));
+ entry->GetFilePath()));
}
void GDataFileSystem::CreateDirectory(
@@ -1756,6 +1861,14 @@ void GDataFileSystem::CreateDirectoryOnUIThread(
const FileOperationCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ if (!ShouldCreateDirectory(directory_path)) {
+ 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 +2783,93 @@ void GDataFileSystem::OnCreateDirectoryCompleted(
}
}
-void GDataFileSystem::OnGetDocuments(GetDocumentsParams* params,
+void GDataFileSystem::OnSearch(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::SearchAsync(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::SearchAsyncOnUIThread,
+ ui_weak_ptr_,
+ search_query,
+ base::Bind(&RelayReadDirectoryCallback,
+ base::MessageLoopProxy::current(),
+ callback)));
+ DCHECK(posted);
+ return;
+ }
+
+ SearchAsyncOnUIThread(search_query, callback);
+}
+
+void GDataFileSystem::SearchAsyncOnUIThread(
+ const std::string& search_query,
+ const ReadDirectoryCallback& callback) {
+ scoped_ptr<std::vector<DocumentFeed*> > feed_list(
+ new std::vector<DocumentFeed*>);
+
+ LoadFeedFromServer(0, 0, // We don't use change stamps when fetching search
+ // data; we always fetch the whole result feed.
+ false, // Stop fetching search results after first feed
+ // chunk to avoid displaying huge number of search
+ // results (especially since we don't cache them).
+ FilePath(), // Not used.
+ search_query,
+ FindEntryCallback(), // Not used.
+ base::Bind(&GDataFileSystem::OnSearch,
+ 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 +2877,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 +2893,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 +2905,30 @@ 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->should_fetch_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->search_file_path,
- params->callback))));
+ new GetDocumentsParams(
+ params->start_changestamp,
+ params->root_feed_changestamp,
+ params->feed_list.release(),
+ params->should_fetch_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 +3692,7 @@ base::PlatformFileError GDataFileSystem::AddNewDirectory(
parent_dir->AddEntry(new_entry);
- NotifyDirectoryChanged(directory_path);
+ NotifyDirectoryChanged(entry->GetFilePath());
return base::PLATFORM_FILE_OK;
}
@@ -4777,4 +4959,15 @@ void SetFreeDiskSpaceGetterForTesting(FreeDiskSpaceGetterInterface* getter) {
global_free_disk_getter_for_testing = getter;
}
+bool GDataFileSystem::ShouldCreateDirectory(const FilePath& directory_path) {
+ // We allow directory creation for paths that are on gdata file system
+ // (GDATA_SEARCH_PATH_INVALID) and paths that reference actual gdata file
+ // system path (GDATA_SEARCH_PATH_RESULT_CHILD).
+ util::GDataSearchPathType path_type =
+ util::GetSearchPathStatus(directory_path);
+ return path_type == util::GDATA_SEARCH_PATH_INVALID ||
+ path_type == util::GDATA_SEARCH_PATH_RESULT_CHILD;
+
+}
+
} // namespace gdata

Powered by Google App Engine
This is Rietveld 408576698