1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/chromeos/drive/file_system/search_operation.h"
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/callback.h"
13 #include "base/task_runner_util.h"
14 #include "chrome/browser/chromeos/drive/file_system_util.h"
15 #include "chrome/browser/chromeos/drive/job_scheduler.h"
16 #include "chrome/browser/chromeos/drive/resource_entry_conversion.h"
17 #include "chrome/browser/chromeos/drive/resource_metadata.h"
18 #include "chrome/browser/google_apis/gdata_wapi_parser.h"
19 #include "content/public/browser/browser_thread.h"
22 using content::BrowserThread;
25 namespace file_system {
28 // Computes the path of each item in |resource_list| returned from the server
29 // and stores to |result|, by using |resource_metadata|. If the metadata is not
30 // up-to-date and did not contain an item, adds the item to "drive/other" for
31 // temporally assigning a path.
32 FileError ResolveSearchResultOnBlockingPool(
33 internal::ResourceMetadata* resource_metadata,
34 scoped_ptr<google_apis::ResourceList> resource_list,
35 std::vector<SearchResultInfo>* result) {
36 DCHECK(resource_metadata);
39 const ScopedVector<google_apis::ResourceEntry>& entries =
40 resource_list->entries();
41 result->reserve(entries.size());
42 for (size_t i = 0; i < entries.size(); ++i) {
44 FileError error = resource_metadata->GetIdByResourceId(
45 entries[i]->resource_id(), &local_id);
48 if (error == FILE_ERROR_OK)
49 error = resource_metadata->GetResourceEntryById(local_id, &entry);
51 if (error == FILE_ERROR_NOT_FOUND) {
52 std::string original_parent_id;
53 if (!ConvertToResourceEntry(*entries[i], &entry, &original_parent_id))
54 continue; // Skip non-file entries.
56 // The result is absent in local resource metadata. This can happen if
57 // the metadata is not synced to the latest server state yet. In that
58 // case, we temporarily add the file to the special "drive/other"
59 // directory in order to assign a path, which is needed to access the
60 // file through FileSystem API.
62 // It will be moved to the right place when the metadata gets synced
63 // in normal loading process in ChangeListProcessor.
64 entry.set_parent_local_id(util::kDriveOtherDirSpecialResourceId);
65 error = resource_metadata->AddEntry(entry, &local_id);
67 if (error != FILE_ERROR_OK)
70 SearchResultInfo(resource_metadata->GetFilePath(local_id),
71 entry.file_info().is_directory()));
79 SearchOperation::SearchOperation(
80 base::SequencedTaskRunner* blocking_task_runner,
81 JobScheduler* scheduler,
82 internal::ResourceMetadata* metadata)
83 : blocking_task_runner_(blocking_task_runner),
84 scheduler_(scheduler),
86 weak_ptr_factory_(this) {
89 SearchOperation::~SearchOperation() {
92 void SearchOperation::Search(const std::string& search_query,
93 const GURL& next_link,
94 const SearchCallback& callback) {
95 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
96 DCHECK(!callback.is_null());
98 if (next_link.is_empty()) {
99 // This is first request for the |search_query|.
102 base::Bind(&SearchOperation::SearchAfterGetResourceList,
103 weak_ptr_factory_.GetWeakPtr(), callback));
105 // There is the remaining result so fetch it.
106 scheduler_->GetRemainingFileList(
108 base::Bind(&SearchOperation::SearchAfterGetResourceList,
109 weak_ptr_factory_.GetWeakPtr(), callback));
113 void SearchOperation::SearchAfterGetResourceList(
114 const SearchCallback& callback,
115 google_apis::GDataErrorCode gdata_error,
116 scoped_ptr<google_apis::ResourceList> resource_list) {
117 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
118 DCHECK(!callback.is_null());
120 FileError error = GDataToFileError(gdata_error);
121 if (error != FILE_ERROR_OK) {
122 callback.Run(error, GURL(), scoped_ptr<std::vector<SearchResultInfo> >());
126 DCHECK(resource_list);
129 resource_list->GetNextFeedURL(&next_url);
131 scoped_ptr<std::vector<SearchResultInfo> > result(
132 new std::vector<SearchResultInfo>);
133 if (resource_list->entries().empty()) {
134 // Short cut. If the resource entry is empty, we don't need to refresh
135 // the resource metadata.
136 callback.Run(FILE_ERROR_OK, next_url, result.Pass());
140 std::vector<SearchResultInfo>* result_ptr = result.get();
141 base::PostTaskAndReplyWithResult(
142 blocking_task_runner_.get(),
144 base::Bind(&ResolveSearchResultOnBlockingPool,
146 base::Passed(&resource_list),
148 base::Bind(&SearchOperation::SearchAfterResolveSearchResult,
149 weak_ptr_factory_.GetWeakPtr(),
152 base::Passed(&result)));
155 void SearchOperation::SearchAfterResolveSearchResult(
156 const SearchCallback& callback,
157 const GURL& next_link,
158 scoped_ptr<std::vector<SearchResultInfo> > result,
160 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
161 DCHECK(!callback.is_null());
164 if (error != FILE_ERROR_OK) {
165 callback.Run(error, GURL(), scoped_ptr<std::vector<SearchResultInfo> >());
169 callback.Run(error, next_link, result.Pass());
172 } // namespace file_system