- add sources.
[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/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"
20 #include "url/gurl.h"
21
22 using content::BrowserThread;
23
24 namespace drive {
25 namespace file_system {
26 namespace {
27
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);
37   DCHECK(result);
38
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) {
43     std::string local_id;
44     FileError error = resource_metadata->GetIdByResourceId(
45         entries[i]->resource_id(), &local_id);
46
47     ResourceEntry entry;
48     if (error == FILE_ERROR_OK)
49       error = resource_metadata->GetResourceEntryById(local_id, &entry);
50
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.
55
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.
61       //
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);
66     }
67     if (error != FILE_ERROR_OK)
68       return error;
69     result->push_back(
70         SearchResultInfo(resource_metadata->GetFilePath(local_id),
71                          entry.file_info().is_directory()));
72   }
73
74   return FILE_ERROR_OK;
75 }
76
77 }  // namespace
78
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),
85       metadata_(metadata),
86       weak_ptr_factory_(this) {
87 }
88
89 SearchOperation::~SearchOperation() {
90 }
91
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());
97
98   if (next_link.is_empty()) {
99     // This is first request for the |search_query|.
100     scheduler_->Search(
101         search_query,
102         base::Bind(&SearchOperation::SearchAfterGetResourceList,
103                    weak_ptr_factory_.GetWeakPtr(), callback));
104   } else {
105     // There is the remaining result so fetch it.
106     scheduler_->GetRemainingFileList(
107         next_link,
108         base::Bind(&SearchOperation::SearchAfterGetResourceList,
109                    weak_ptr_factory_.GetWeakPtr(), callback));
110   }
111 }
112
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());
119
120   FileError error = GDataToFileError(gdata_error);
121   if (error != FILE_ERROR_OK) {
122     callback.Run(error, GURL(), scoped_ptr<std::vector<SearchResultInfo> >());
123     return;
124   }
125
126   DCHECK(resource_list);
127
128   GURL next_url;
129   resource_list->GetNextFeedURL(&next_url);
130
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());
137     return;
138   }
139
140   std::vector<SearchResultInfo>* result_ptr = result.get();
141   base::PostTaskAndReplyWithResult(
142       blocking_task_runner_.get(),
143       FROM_HERE,
144       base::Bind(&ResolveSearchResultOnBlockingPool,
145                  metadata_,
146                  base::Passed(&resource_list),
147                  result_ptr),
148       base::Bind(&SearchOperation::SearchAfterResolveSearchResult,
149                  weak_ptr_factory_.GetWeakPtr(),
150                  callback,
151                  next_url,
152                  base::Passed(&result)));
153 }
154
155 void SearchOperation::SearchAfterResolveSearchResult(
156     const SearchCallback& callback,
157     const GURL& next_link,
158     scoped_ptr<std::vector<SearchResultInfo> > result,
159     FileError error) {
160   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
161   DCHECK(!callback.is_null());
162   DCHECK(result);
163
164   if (error != FILE_ERROR_OK) {
165     callback.Run(error, GURL(), scoped_ptr<std::vector<SearchResultInfo> >());
166     return;
167   }
168
169   callback.Run(error, next_link, result.Pass());
170 }
171
172 }  // namespace file_system
173 }  // namespace drive