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/change_list_loader.h"
15 #include "chrome/browser/chromeos/drive/file_system_util.h"
16 #include "chrome/browser/chromeos/drive/job_scheduler.h"
17 #include "chrome/browser/chromeos/drive/resource_entry_conversion.h"
18 #include "chrome/browser/chromeos/drive/resource_metadata.h"
19 #include "chrome/browser/drive/drive_api_util.h"
20 #include "content/public/browser/browser_thread.h"
21 #include "google_apis/drive/drive_api_parser.h"
24 using content::BrowserThread
;
27 namespace file_system
{
30 // Computes the path of each item in |file_list| returned from the server
31 // and stores to |result|, by using |resource_metadata|. If the metadata is not
32 // up-to-date and did not contain an item, adds the item to "drive/other" for
33 // temporally assigning a path.
34 FileError
ResolveSearchResultOnBlockingPool(
35 internal::ResourceMetadata
* resource_metadata
,
36 scoped_ptr
<google_apis::FileList
> file_list
,
37 std::vector
<SearchResultInfo
>* result
) {
38 DCHECK(resource_metadata
);
41 const ScopedVector
<google_apis::FileResource
>& entries
= file_list
->items();
42 result
->reserve(entries
.size());
43 for (size_t i
= 0; i
< entries
.size(); ++i
) {
45 FileError error
= resource_metadata
->GetIdByResourceId(
46 entries
[i
]->file_id(), &local_id
);
49 if (error
== FILE_ERROR_OK
)
50 error
= resource_metadata
->GetResourceEntryById(local_id
, &entry
);
52 if (error
== FILE_ERROR_NOT_FOUND
) {
53 std::string original_parent_id
;
54 if (!ConvertFileResourceToResourceEntry(*entries
[i
], &entry
,
56 continue; // Skip non-file entries.
58 // The result is absent in local resource metadata. This can happen if
59 // the metadata is not synced to the latest server state yet. In that
60 // case, we temporarily add the file to the special "drive/other"
61 // directory in order to assign a path, which is needed to access the
62 // file through FileSystem API.
64 // It will be moved to the right place when the metadata gets synced
65 // in normal loading process in ChangeListProcessor.
66 entry
.set_parent_local_id(util::kDriveOtherDirLocalId
);
67 error
= resource_metadata
->AddEntry(entry
, &local_id
);
69 if (error
!= FILE_ERROR_OK
)
72 error
= resource_metadata
->GetFilePath(local_id
, &path
);
73 if (error
!= FILE_ERROR_OK
)
75 result
->push_back(SearchResultInfo(path
, entry
.file_info().is_directory()));
83 SearchOperation::SearchOperation(
84 base::SequencedTaskRunner
* blocking_task_runner
,
85 JobScheduler
* scheduler
,
86 internal::ResourceMetadata
* metadata
,
87 internal::LoaderController
* loader_controller
)
88 : blocking_task_runner_(blocking_task_runner
),
89 scheduler_(scheduler
),
91 loader_controller_(loader_controller
),
92 weak_ptr_factory_(this) {
95 SearchOperation::~SearchOperation() {
98 void SearchOperation::Search(const std::string
& search_query
,
99 const GURL
& next_link
,
100 const SearchCallback
& callback
) {
101 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
102 DCHECK(!callback
.is_null());
104 if (next_link
.is_empty()) {
105 // This is first request for the |search_query|.
108 base::Bind(&SearchOperation::SearchAfterGetFileList
,
109 weak_ptr_factory_
.GetWeakPtr(), callback
));
111 // There is the remaining result so fetch it.
112 scheduler_
->GetRemainingFileList(
114 base::Bind(&SearchOperation::SearchAfterGetFileList
,
115 weak_ptr_factory_
.GetWeakPtr(), callback
));
119 void SearchOperation::SearchAfterGetFileList(
120 const SearchCallback
& callback
,
121 google_apis::DriveApiErrorCode gdata_error
,
122 scoped_ptr
<google_apis::FileList
> file_list
) {
123 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
124 DCHECK(!callback
.is_null());
126 FileError error
= GDataToFileError(gdata_error
);
127 if (error
!= FILE_ERROR_OK
) {
128 callback
.Run(error
, GURL(), scoped_ptr
<std::vector
<SearchResultInfo
> >());
134 GURL next_url
= file_list
->next_link();
136 scoped_ptr
<std::vector
<SearchResultInfo
> > result(
137 new std::vector
<SearchResultInfo
>);
138 if (file_list
->items().empty()) {
139 // Short cut. If the resource entry is empty, we don't need to refresh
140 // the resource metadata.
141 callback
.Run(FILE_ERROR_OK
, next_url
, result
.Pass());
145 // ResolveSearchResultOnBlockingPool() may add entries newly created on the
146 // server to the local metadata.
147 // This may race with sync tasks so we should ask LoaderController here.
148 std::vector
<SearchResultInfo
>* result_ptr
= result
.get();
149 loader_controller_
->ScheduleRun(base::Bind(
151 &base::PostTaskAndReplyWithResult
<FileError
, FileError
>),
152 blocking_task_runner_
,
154 base::Bind(&ResolveSearchResultOnBlockingPool
,
156 base::Passed(&file_list
),
158 base::Bind(&SearchOperation::SearchAfterResolveSearchResult
,
159 weak_ptr_factory_
.GetWeakPtr(),
162 base::Passed(&result
))));
165 void SearchOperation::SearchAfterResolveSearchResult(
166 const SearchCallback
& callback
,
167 const GURL
& next_link
,
168 scoped_ptr
<std::vector
<SearchResultInfo
> > result
,
170 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
171 DCHECK(!callback
.is_null());
174 if (error
!= FILE_ERROR_OK
) {
175 callback
.Run(error
, GURL(), scoped_ptr
<std::vector
<SearchResultInfo
> >());
179 callback
.Run(error
, next_link
, result
.Pass());
182 } // namespace file_system