Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / drive / file_system / search_operation.cc
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.
4
5 #include "chrome/browser/chromeos/drive/file_system/search_operation.h"
6
7 #include <string>
8 #include <vector>
9
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 "content/public/browser/browser_thread.h"
20 #include "google_apis/drive/gdata_wapi_parser.h"
21 #include "url/gurl.h"
22
23 using content::BrowserThread;
24
25 namespace drive {
26 namespace file_system {
27 namespace {
28
29 // Computes the path of each item in |resource_list| returned from the server
30 // and stores to |result|, by using |resource_metadata|. If the metadata is not
31 // up-to-date and did not contain an item, adds the item to "drive/other" for
32 // temporally assigning a path.
33 FileError ResolveSearchResultOnBlockingPool(
34     internal::ResourceMetadata* resource_metadata,
35     scoped_ptr<google_apis::ResourceList> resource_list,
36     std::vector<SearchResultInfo>* result) {
37   DCHECK(resource_metadata);
38   DCHECK(result);
39
40   const ScopedVector<google_apis::ResourceEntry>& entries =
41       resource_list->entries();
42   result->reserve(entries.size());
43   for (size_t i = 0; i < entries.size(); ++i) {
44     std::string local_id;
45     FileError error = resource_metadata->GetIdByResourceId(
46         entries[i]->resource_id(), &local_id);
47
48     ResourceEntry entry;
49     if (error == FILE_ERROR_OK)
50       error = resource_metadata->GetResourceEntryById(local_id, &entry);
51
52     if (error == FILE_ERROR_NOT_FOUND) {
53       std::string original_parent_id;
54       if (!ConvertToResourceEntry(*entries[i], &entry, &original_parent_id))
55         continue;  // Skip non-file entries.
56
57       // The result is absent in local resource metadata. This can happen if
58       // the metadata is not synced to the latest server state yet. In that
59       // case, we temporarily add the file to the special "drive/other"
60       // directory in order to assign a path, which is needed to access the
61       // file through FileSystem API.
62       //
63       // It will be moved to the right place when the metadata gets synced
64       // in normal loading process in ChangeListProcessor.
65       entry.set_parent_local_id(util::kDriveOtherDirLocalId);
66       error = resource_metadata->AddEntry(entry, &local_id);
67     }
68     if (error != FILE_ERROR_OK)
69       return error;
70     result->push_back(
71         SearchResultInfo(resource_metadata->GetFilePath(local_id),
72                          entry.file_info().is_directory()));
73   }
74
75   return FILE_ERROR_OK;
76 }
77
78 }  // namespace
79
80 SearchOperation::SearchOperation(
81     base::SequencedTaskRunner* blocking_task_runner,
82     JobScheduler* scheduler,
83     internal::ResourceMetadata* metadata,
84     internal::LoaderController* loader_controller)
85     : blocking_task_runner_(blocking_task_runner),
86       scheduler_(scheduler),
87       metadata_(metadata),
88       loader_controller_(loader_controller),
89       weak_ptr_factory_(this) {
90 }
91
92 SearchOperation::~SearchOperation() {
93 }
94
95 void SearchOperation::Search(const std::string& search_query,
96                              const GURL& next_link,
97                              const SearchCallback& callback) {
98   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
99   DCHECK(!callback.is_null());
100
101   if (next_link.is_empty()) {
102     // This is first request for the |search_query|.
103     scheduler_->Search(
104         search_query,
105         base::Bind(&SearchOperation::SearchAfterGetResourceList,
106                    weak_ptr_factory_.GetWeakPtr(), callback));
107   } else {
108     // There is the remaining result so fetch it.
109     scheduler_->GetRemainingFileList(
110         next_link,
111         base::Bind(&SearchOperation::SearchAfterGetResourceList,
112                    weak_ptr_factory_.GetWeakPtr(), callback));
113   }
114 }
115
116 void SearchOperation::SearchAfterGetResourceList(
117     const SearchCallback& callback,
118     google_apis::GDataErrorCode gdata_error,
119     scoped_ptr<google_apis::ResourceList> resource_list) {
120   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
121   DCHECK(!callback.is_null());
122
123   FileError error = GDataToFileError(gdata_error);
124   if (error != FILE_ERROR_OK) {
125     callback.Run(error, GURL(), scoped_ptr<std::vector<SearchResultInfo> >());
126     return;
127   }
128
129   DCHECK(resource_list);
130
131   GURL next_url;
132   resource_list->GetNextFeedURL(&next_url);
133
134   scoped_ptr<std::vector<SearchResultInfo> > result(
135       new std::vector<SearchResultInfo>);
136   if (resource_list->entries().empty()) {
137     // Short cut. If the resource entry is empty, we don't need to refresh
138     // the resource metadata.
139     callback.Run(FILE_ERROR_OK, next_url, result.Pass());
140     return;
141   }
142
143   // ResolveSearchResultOnBlockingPool() may add entries newly created on the
144   // server to the local metadata.
145   // This may race with sync tasks so we should ask LoaderController here.
146   std::vector<SearchResultInfo>* result_ptr = result.get();
147   loader_controller_->ScheduleRun(base::Bind(
148       base::IgnoreResult(
149           &base::PostTaskAndReplyWithResult<FileError, FileError>),
150       blocking_task_runner_,
151       FROM_HERE,
152       base::Bind(&ResolveSearchResultOnBlockingPool,
153                  metadata_,
154                  base::Passed(&resource_list),
155                  result_ptr),
156       base::Bind(&SearchOperation::SearchAfterResolveSearchResult,
157                  weak_ptr_factory_.GetWeakPtr(),
158                  callback,
159                  next_url,
160                  base::Passed(&result))));
161 }
162
163 void SearchOperation::SearchAfterResolveSearchResult(
164     const SearchCallback& callback,
165     const GURL& next_link,
166     scoped_ptr<std::vector<SearchResultInfo> > result,
167     FileError error) {
168   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
169   DCHECK(!callback.is_null());
170   DCHECK(result);
171
172   if (error != FILE_ERROR_OK) {
173     callback.Run(error, GURL(), scoped_ptr<std::vector<SearchResultInfo> >());
174     return;
175   }
176
177   callback.Run(error, next_link, result.Pass());
178 }
179
180 }  // namespace file_system
181 }  // namespace drive