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 "content/public/browser/browser_thread.h"
19 #include "google_apis/drive/gdata_wapi_parser.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::kDriveOtherDirLocalId
);
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