• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 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/local_discovery/storage/privet_filesystem_operations.h"
6 
7 #include "chrome/browser/local_discovery/storage/privet_filesystem_constants.h"
8 
9 namespace local_discovery {
10 
PrivetFileSystemOperationFactory(content::BrowserContext * browser_context)11 PrivetFileSystemOperationFactory::PrivetFileSystemOperationFactory(
12     content::BrowserContext* browser_context)
13     : browser_context_(browser_context), weak_factory_(this) {}
14 
~PrivetFileSystemOperationFactory()15 PrivetFileSystemOperationFactory::~PrivetFileSystemOperationFactory() {
16   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
17   RemoveAllOperations();
18 }
19 
GetFileInfo(const fileapi::FileSystemURL & url,const fileapi::AsyncFileUtil::GetFileInfoCallback & callback)20 void PrivetFileSystemOperationFactory::GetFileInfo(
21     const fileapi::FileSystemURL& url,
22     const fileapi::AsyncFileUtil::GetFileInfoCallback& callback) {
23   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
24   PrivetFileSystemAsyncOperation* operation =
25       new PrivetFileSystemDetailsOperation(
26           url.path(), browser_context_, this, &attribute_cache_, callback);
27   async_operations_.insert(operation);
28   operation->Start();
29 }
30 
ReadDirectory(const fileapi::FileSystemURL & url,const fileapi::AsyncFileUtil::ReadDirectoryCallback & callback)31 void PrivetFileSystemOperationFactory::ReadDirectory(
32     const fileapi::FileSystemURL& url,
33     const fileapi::AsyncFileUtil::ReadDirectoryCallback& callback) {
34   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
35   PrivetFileSystemAsyncOperation* operation = new PrivetFileSystemListOperation(
36       url.path(), browser_context_, this, &attribute_cache_, callback);
37   async_operations_.insert(operation);
38   operation->Start();
39 }
40 
RemoveOperation(PrivetFileSystemAsyncOperation * operation)41 void PrivetFileSystemOperationFactory::RemoveOperation(
42     PrivetFileSystemAsyncOperation* operation) {
43   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
44   async_operations_.erase(operation);
45   delete operation;
46 }
47 
RemoveAllOperations()48 void PrivetFileSystemOperationFactory::RemoveAllOperations() {
49   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
50   STLDeleteElements(&async_operations_);
51 }
52 
PrivetFileSystemAsyncOperationUtil(const base::FilePath & full_path,content::BrowserContext * browser_context,Delegate * delegate)53 PrivetFileSystemAsyncOperationUtil::PrivetFileSystemAsyncOperationUtil(
54     const base::FilePath& full_path,
55     content::BrowserContext* browser_context,
56     Delegate* delegate)
57     : parsed_path_(full_path),
58       browser_context_(browser_context),
59       delegate_(delegate),
60       weak_factory_(this) {
61   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
62 }
63 
~PrivetFileSystemAsyncOperationUtil()64 PrivetFileSystemAsyncOperationUtil::~PrivetFileSystemAsyncOperationUtil() {
65   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
66 }
67 
Start()68 void PrivetFileSystemAsyncOperationUtil::Start() {
69   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
70   request_context_ = browser_context_->GetRequestContext();
71   service_discovery_client_ = ServiceDiscoverySharedClient::GetInstance();
72   privet_device_resolver_.reset(new PrivetDeviceResolver(
73       service_discovery_client_.get(),
74       parsed_path_.service_name,
75       base::Bind(
76           &PrivetFileSystemAsyncOperationUtil::OnGotDeviceDescription,
77           base::Unretained(this))));
78   privet_device_resolver_->Start();
79 }
80 
OnGotDeviceDescription(bool success,const DeviceDescription & device_description)81 void PrivetFileSystemAsyncOperationUtil::OnGotDeviceDescription(
82     bool success, const DeviceDescription& device_description) {
83   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
84   if (!success) {
85     delegate_->PrivetFileSystemResolved(NULL, parsed_path_.path);
86     return;
87   }
88 
89   privet_async_factory_ = PrivetHTTPAsynchronousFactory::CreateInstance(
90       service_discovery_client_.get(), request_context_.get());
91   privet_http_resolution_ = privet_async_factory_->CreatePrivetHTTP(
92       parsed_path_.service_name,
93       device_description.address,
94       base::Bind(&PrivetFileSystemAsyncOperationUtil::OnGotPrivetHTTP,
95                  base::Unretained(this)));
96   privet_http_resolution_->Start();
97 }
98 
OnGotPrivetHTTP(scoped_ptr<PrivetHTTPClient> privet_http_client)99 void PrivetFileSystemAsyncOperationUtil::OnGotPrivetHTTP(
100     scoped_ptr<PrivetHTTPClient> privet_http_client) {
101   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
102   privet_client_ = PrivetV1HTTPClient::CreateDefault(privet_http_client.Pass());
103   delegate_->PrivetFileSystemResolved(privet_client_.get(),
104                                       parsed_path_.path);
105 }
106 
PrivetFileSystemListOperation(const base::FilePath & full_path,content::BrowserContext * browser_context,PrivetFileSystemAsyncOperationContainer * container,PrivetFileSystemAttributeCache * attribute_cache,const fileapi::AsyncFileUtil::ReadDirectoryCallback & callback)107 PrivetFileSystemListOperation::PrivetFileSystemListOperation(
108     const base::FilePath& full_path,
109     content::BrowserContext* browser_context,
110     PrivetFileSystemAsyncOperationContainer* container,
111     PrivetFileSystemAttributeCache* attribute_cache,
112     const fileapi::AsyncFileUtil::ReadDirectoryCallback& callback)
113     : core_(full_path, browser_context, this),
114       full_path_(full_path),
115       container_(container),
116       attribute_cache_(attribute_cache),
117       callback_(callback) {
118   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
119 }
120 
~PrivetFileSystemListOperation()121 PrivetFileSystemListOperation::~PrivetFileSystemListOperation() {
122   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
123 }
124 
Start()125 void PrivetFileSystemListOperation::Start() {
126   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
127   core_.Start();
128 }
129 
PrivetFileSystemResolved(PrivetV1HTTPClient * http_client,const std::string & path)130 void PrivetFileSystemListOperation::PrivetFileSystemResolved(
131     PrivetV1HTTPClient* http_client,
132     const std::string& path) {
133   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
134   if (!http_client) {
135     SignalError();
136     return;
137   }
138 
139   list_operation_ = http_client->CreateStorageListOperation(
140       path,
141       base::Bind(&PrivetFileSystemListOperation::OnStorageListResult,
142                  base::Unretained(this)));
143     list_operation_->Start();
144 }
145 
OnStorageListResult(const base::DictionaryValue * value)146 void PrivetFileSystemListOperation::OnStorageListResult(
147     const base::DictionaryValue* value) {
148   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
149   list_operation_.reset();
150 
151   if (!value) {
152     SignalError();
153     return;
154   }
155 
156   attribute_cache_->AddFileInfoFromJSON(full_path_, value);
157 
158   fileapi::AsyncFileUtil::EntryList entry_list;
159 
160   const base::ListValue* entries;
161   if (!value->GetList(kPrivetListEntries, &entries)) {
162     SignalError();
163     return;
164   }
165 
166   for (size_t i = 0; i < entries->GetSize(); i++) {
167     const base::DictionaryValue* entry_value;
168     if (!entries->GetDictionary(i, &entry_value)) {
169       SignalError();
170       return;
171     }
172 
173     std::string name;
174     std::string type;
175     int size = 0;
176 
177     entry_value->GetString(kPrivetListKeyName, &name);
178     entry_value->GetString(kPrivetListKeyType, &type);
179     entry_value->GetInteger(kPrivetListKeySize, &size);
180 
181     fileapi::DirectoryEntry entry(
182         name,
183         (type == kPrivetListTypeDir) ?
184         fileapi::DirectoryEntry::DIRECTORY : fileapi::DirectoryEntry::FILE,
185         size,
186         base::Time() /* TODO(noamsml) */);
187 
188     entry_list.push_back(entry);
189   }
190 
191   TriggerCallbackAndDestroy(base::File::FILE_OK, entry_list, false);
192 }
193 
SignalError()194 void PrivetFileSystemListOperation::SignalError() {
195   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
196   TriggerCallbackAndDestroy(base::File::FILE_ERROR_FAILED,
197                             fileapi::AsyncFileUtil::EntryList(),
198                             false);
199 }
200 
TriggerCallbackAndDestroy(base::File::Error result,const fileapi::AsyncFileUtil::EntryList & file_list,bool has_more)201 void PrivetFileSystemListOperation::TriggerCallbackAndDestroy(
202     base::File::Error result,
203     const fileapi::AsyncFileUtil::EntryList& file_list,
204     bool has_more) {
205   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
206   content::BrowserThread::PostTask(
207       content::BrowserThread::IO,
208       FROM_HERE,
209       base::Bind(callback_, result, file_list, has_more));
210   container_->RemoveOperation(this);
211 }
212 
PrivetFileSystemDetailsOperation(const base::FilePath & full_path,content::BrowserContext * browser_context,PrivetFileSystemAsyncOperationContainer * container,PrivetFileSystemAttributeCache * attribute_cache,const fileapi::AsyncFileUtil::GetFileInfoCallback & callback)213 PrivetFileSystemDetailsOperation::PrivetFileSystemDetailsOperation(
214     const base::FilePath& full_path,
215     content::BrowserContext* browser_context,
216     PrivetFileSystemAsyncOperationContainer* container,
217     PrivetFileSystemAttributeCache* attribute_cache,
218     const fileapi::AsyncFileUtil::GetFileInfoCallback& callback)
219     : core_(full_path, browser_context, this),
220       full_path_(full_path),
221       container_(container),
222       attribute_cache_(attribute_cache),
223       callback_(callback) {
224   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
225 }
226 
~PrivetFileSystemDetailsOperation()227 PrivetFileSystemDetailsOperation::~PrivetFileSystemDetailsOperation() {
228   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
229 }
230 
Start()231 void PrivetFileSystemDetailsOperation::Start() {
232   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
233   const base::File::Info* info = attribute_cache_->GetFileInfo(full_path_);
234   if (info) {
235     TriggerCallbackAndDestroy(base::File::FILE_OK, *info);
236     return;
237   }
238 
239   core_.Start();
240 }
241 
PrivetFileSystemResolved(PrivetV1HTTPClient * http_client,const std::string & path)242 void PrivetFileSystemDetailsOperation::PrivetFileSystemResolved(
243     PrivetV1HTTPClient* http_client,
244     const std::string& path) {
245   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
246   if (!http_client) {
247     SignalError();
248     return;
249   }
250 
251   list_operation_ = http_client->CreateStorageListOperation(
252       path,
253       base::Bind(&PrivetFileSystemDetailsOperation::OnStorageListResult,
254                  base::Unretained(this)));
255   list_operation_->Start();
256 }
257 
OnStorageListResult(const base::DictionaryValue * value)258 void PrivetFileSystemDetailsOperation::OnStorageListResult(
259     const base::DictionaryValue* value) {
260   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
261   list_operation_.reset();
262 
263   attribute_cache_->AddFileInfoFromJSON(full_path_, value);
264   const base::File::Info* info = attribute_cache_->GetFileInfo(full_path_);
265 
266   if (info) {
267     TriggerCallbackAndDestroy(base::File::FILE_OK, *info);
268   } else {
269     SignalError();
270   }
271 }
272 
SignalError()273 void PrivetFileSystemDetailsOperation::SignalError() {
274   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
275   TriggerCallbackAndDestroy(base::File::FILE_ERROR_FAILED, base::File::Info());
276 }
277 
TriggerCallbackAndDestroy(base::File::Error result,const base::File::Info & info)278 void PrivetFileSystemDetailsOperation::TriggerCallbackAndDestroy(
279     base::File::Error result,
280     const base::File::Info& info) {
281   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
282   content::BrowserThread::PostTask(content::BrowserThread::IO,
283                                    FROM_HERE,
284                                    base::Bind(callback_, result, info));
285   container_->RemoveOperation(this);
286 }
287 
288 }  // namespace local_discovery
289