Popular sites on the NTP: check that experiment group StartsWith (rather than IS...
[chromium-blink-merge.git] / chrome / browser / chromeos / extensions / file_system_provider / file_system_provider_api.cc
blob402fd650ac2bd3d9c55cc1dbd9b399f232e32d35
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/extensions/file_system_provider/file_system_provider_api.h"
7 #include <string>
8 #include <vector>
10 #include "base/memory/linked_ptr.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/trace_event/trace_event.h"
13 #include "base/values.h"
14 #include "chrome/browser/chromeos/file_system_provider/provided_file_system_info.h"
15 #include "chrome/browser/chromeos/file_system_provider/provided_file_system_interface.h"
16 #include "chrome/browser/chromeos/file_system_provider/request_manager.h"
17 #include "chrome/browser/chromeos/file_system_provider/request_value.h"
18 #include "chrome/browser/chromeos/file_system_provider/service.h"
19 #include "chrome/common/extensions/api/file_system_provider.h"
20 #include "chrome/common/extensions/api/file_system_provider_internal.h"
21 #include "storage/browser/fileapi/watcher_manager.h"
23 using chromeos::file_system_provider::MountOptions;
24 using chromeos::file_system_provider::OpenedFiles;
25 using chromeos::file_system_provider::ProvidedFileSystemInfo;
26 using chromeos::file_system_provider::ProvidedFileSystemInterface;
27 using chromeos::file_system_provider::ProvidedFileSystemObserver;
28 using chromeos::file_system_provider::RequestValue;
29 using chromeos::file_system_provider::Service;
30 using chromeos::file_system_provider::Watchers;
32 namespace extensions {
33 namespace {
35 typedef std::vector<linked_ptr<api::file_system_provider::Change>> IDLChanges;
37 // Converts the change type from the IDL type to a native type. |changed_type|
38 // must be specified (not CHANGE_TYPE_NONE).
39 storage::WatcherManager::ChangeType ParseChangeType(
40 const api::file_system_provider::ChangeType& change_type) {
41 switch (change_type) {
42 case api::file_system_provider::CHANGE_TYPE_CHANGED:
43 return storage::WatcherManager::CHANGED;
44 case api::file_system_provider::CHANGE_TYPE_DELETED:
45 return storage::WatcherManager::DELETED;
46 default:
47 break;
49 NOTREACHED();
50 return storage::WatcherManager::CHANGED;
53 // Convert the change from the IDL type to a native type. The reason IDL types
54 // are not used is since they are imperfect, eg. paths are stored as strings.
55 ProvidedFileSystemObserver::Change ParseChange(
56 const api::file_system_provider::Change& change) {
57 ProvidedFileSystemObserver::Change result;
58 result.entry_path = base::FilePath::FromUTF8Unsafe(change.entry_path);
59 result.change_type = ParseChangeType(change.change_type);
60 return result;
63 // Converts a list of child changes from the IDL type to a native type.
64 scoped_ptr<ProvidedFileSystemObserver::Changes> ParseChanges(
65 const IDLChanges& changes) {
66 scoped_ptr<ProvidedFileSystemObserver::Changes> results(
67 new ProvidedFileSystemObserver::Changes);
68 for (const auto& change : changes) {
69 results->push_back(ParseChange(*change));
71 return results;
74 // Fills the IDL's FileSystemInfo with FSP's ProvidedFileSystemInfo and
75 // Watchers.
76 void FillFileSystemInfo(const ProvidedFileSystemInfo& file_system_info,
77 const Watchers& watchers,
78 const OpenedFiles& opened_files,
79 api::file_system_provider::FileSystemInfo* output) {
80 using api::file_system_provider::Watcher;
81 using api::file_system_provider::OpenedFile;
83 output->file_system_id = file_system_info.file_system_id();
84 output->display_name = file_system_info.display_name();
85 output->writable = file_system_info.writable();
86 output->opened_files_limit = file_system_info.opened_files_limit();
88 std::vector<linked_ptr<Watcher>> watcher_items;
89 for (const auto& watcher : watchers) {
90 const linked_ptr<Watcher> watcher_item(new Watcher);
91 watcher_item->entry_path = watcher.second.entry_path.value();
92 watcher_item->recursive = watcher.second.recursive;
93 if (!watcher.second.last_tag.empty())
94 watcher_item->last_tag.reset(new std::string(watcher.second.last_tag));
95 watcher_items.push_back(watcher_item);
97 output->watchers = watcher_items;
99 std::vector<linked_ptr<OpenedFile>> opened_file_items;
100 for (const auto& opened_file : opened_files) {
101 const linked_ptr<OpenedFile> opened_file_item(new OpenedFile);
102 opened_file_item->open_request_id = opened_file.first;
103 opened_file_item->file_path = opened_file.second.file_path.value();
104 switch (opened_file.second.mode) {
105 case chromeos::file_system_provider::OPEN_FILE_MODE_READ:
106 opened_file_item->mode =
107 extensions::api::file_system_provider::OPEN_FILE_MODE_READ;
108 break;
109 case chromeos::file_system_provider::OPEN_FILE_MODE_WRITE:
110 opened_file_item->mode =
111 extensions::api::file_system_provider::OPEN_FILE_MODE_WRITE;
112 break;
114 opened_file_items.push_back(opened_file_item);
116 output->opened_files = opened_file_items;
119 } // namespace
121 bool FileSystemProviderMountFunction::RunSync() {
122 using api::file_system_provider::Mount::Params;
123 const scoped_ptr<Params> params(Params::Create(*args_));
124 EXTENSION_FUNCTION_VALIDATE(params);
126 // It's an error if the file system Id is empty.
127 if (params->options.file_system_id.empty()) {
128 SetError(FileErrorToString(base::File::FILE_ERROR_INVALID_OPERATION));
129 return false;
132 // It's an error if the display name is empty.
133 if (params->options.display_name.empty()) {
134 SetError(FileErrorToString(base::File::FILE_ERROR_INVALID_OPERATION));
135 return false;
138 // If the opened files limit is set, then it must be larger or equal than 0.
139 if (params->options.opened_files_limit.get() &&
140 *params->options.opened_files_limit.get() < 0) {
141 SetError(FileErrorToString(base::File::FILE_ERROR_INVALID_OPERATION));
142 return false;
145 Service* const service = Service::Get(GetProfile());
146 DCHECK(service);
148 MountOptions options;
149 options.file_system_id = params->options.file_system_id;
150 options.display_name = params->options.display_name;
151 options.writable = params->options.writable;
152 options.opened_files_limit = params->options.opened_files_limit.get()
153 ? *params->options.opened_files_limit.get()
154 : 0;
155 options.supports_notify_tag = params->options.supports_notify_tag;
157 const base::File::Error result =
158 service->MountFileSystem(extension_id(), options);
159 if (result != base::File::FILE_OK) {
160 SetError(FileErrorToString(result));
161 return false;
164 return true;
167 bool FileSystemProviderUnmountFunction::RunSync() {
168 using api::file_system_provider::Unmount::Params;
169 scoped_ptr<Params> params(Params::Create(*args_));
170 EXTENSION_FUNCTION_VALIDATE(params);
172 Service* const service = Service::Get(GetProfile());
173 DCHECK(service);
175 const base::File::Error result =
176 service->UnmountFileSystem(extension_id(), params->options.file_system_id,
177 Service::UNMOUNT_REASON_USER);
178 if (result != base::File::FILE_OK) {
179 SetError(FileErrorToString(result));
180 return false;
183 return true;
186 bool FileSystemProviderGetAllFunction::RunSync() {
187 using api::file_system_provider::FileSystemInfo;
188 Service* const service = Service::Get(GetProfile());
189 DCHECK(service);
191 const std::vector<ProvidedFileSystemInfo> file_systems =
192 service->GetProvidedFileSystemInfoList();
193 std::vector<linked_ptr<FileSystemInfo>> items;
195 for (const auto& file_system_info : file_systems) {
196 if (file_system_info.extension_id() == extension_id()) {
197 const linked_ptr<FileSystemInfo> item(new FileSystemInfo);
199 chromeos::file_system_provider::ProvidedFileSystemInterface* const
200 file_system =
201 service->GetProvidedFileSystem(file_system_info.extension_id(),
202 file_system_info.file_system_id());
203 DCHECK(file_system);
205 FillFileSystemInfo(file_system_info, *file_system->GetWatchers(),
206 file_system->GetOpenedFiles(), item.get());
207 items.push_back(item);
211 SetResultList(api::file_system_provider::GetAll::Results::Create(items));
212 return true;
215 bool FileSystemProviderGetFunction::RunSync() {
216 using api::file_system_provider::Get::Params;
217 scoped_ptr<Params> params(Params::Create(*args_));
218 EXTENSION_FUNCTION_VALIDATE(params);
220 using api::file_system_provider::FileSystemInfo;
221 Service* const service = Service::Get(GetProfile());
222 DCHECK(service);
224 chromeos::file_system_provider::ProvidedFileSystemInterface* const
225 file_system = service->GetProvidedFileSystem(extension_id(),
226 params->file_system_id);
228 if (!file_system) {
229 SetError(FileErrorToString(base::File::FILE_ERROR_NOT_FOUND));
230 return false;
233 FileSystemInfo file_system_info;
234 FillFileSystemInfo(file_system->GetFileSystemInfo(),
235 *file_system->GetWatchers(), file_system->GetOpenedFiles(),
236 &file_system_info);
237 SetResultList(
238 api::file_system_provider::Get::Results::Create(file_system_info));
239 return true;
242 bool FileSystemProviderNotifyFunction::RunAsync() {
243 using api::file_system_provider::Notify::Params;
244 scoped_ptr<Params> params(Params::Create(*args_));
245 EXTENSION_FUNCTION_VALIDATE(params);
247 Service* const service = Service::Get(GetProfile());
248 DCHECK(service);
250 ProvidedFileSystemInterface* const file_system =
251 service->GetProvidedFileSystem(extension_id(),
252 params->options.file_system_id);
253 if (!file_system) {
254 SetError(FileErrorToString(base::File::FILE_ERROR_NOT_FOUND));
255 return false;
258 file_system->Notify(
259 base::FilePath::FromUTF8Unsafe(params->options.observed_path),
260 params->options.recursive, ParseChangeType(params->options.change_type),
261 params->options.changes.get()
262 ? ParseChanges(*params->options.changes.get())
263 : make_scoped_ptr(new ProvidedFileSystemObserver::Changes),
264 params->options.tag.get() ? *params->options.tag.get() : "",
265 base::Bind(&FileSystemProviderNotifyFunction::OnNotifyCompleted, this));
267 return true;
270 void FileSystemProviderNotifyFunction::OnNotifyCompleted(
271 base::File::Error result) {
272 if (result != base::File::FILE_OK) {
273 SetError(FileErrorToString(result));
274 SendResponse(false);
275 return;
278 SendResponse(true);
281 bool FileSystemProviderInternalUnmountRequestedSuccessFunction::RunWhenValid() {
282 using api::file_system_provider_internal::UnmountRequestedSuccess::Params;
283 scoped_ptr<Params> params(Params::Create(*args_));
284 EXTENSION_FUNCTION_VALIDATE(params);
286 return FulfillRequest(RequestValue::CreateForUnmountSuccess(params.Pass()),
287 false /* has_more */);
290 bool
291 FileSystemProviderInternalGetMetadataRequestedSuccessFunction::RunWhenValid() {
292 using api::file_system_provider_internal::GetMetadataRequestedSuccess::Params;
293 scoped_ptr<Params> params(Params::Create(*args_));
294 EXTENSION_FUNCTION_VALIDATE(params);
296 return FulfillRequest(
297 RequestValue::CreateForGetMetadataSuccess(params.Pass()),
298 false /* has_more */);
301 bool FileSystemProviderInternalGetActionsRequestedSuccessFunction::
302 RunWhenValid() {
303 using api::file_system_provider_internal::GetActionsRequestedSuccess::Params;
304 scoped_ptr<Params> params(Params::Create(*args_));
305 EXTENSION_FUNCTION_VALIDATE(params);
307 return FulfillRequest(RequestValue::CreateForGetActionsSuccess(params.Pass()),
308 false /* has_more */);
311 bool FileSystemProviderInternalReadDirectoryRequestedSuccessFunction::
312 RunWhenValid() {
313 using api::file_system_provider_internal::ReadDirectoryRequestedSuccess::
314 Params;
315 scoped_ptr<Params> params(Params::Create(*args_));
316 EXTENSION_FUNCTION_VALIDATE(params);
318 const bool has_more = params->has_more;
319 return FulfillRequest(
320 RequestValue::CreateForReadDirectorySuccess(params.Pass()), has_more);
323 bool
324 FileSystemProviderInternalReadFileRequestedSuccessFunction::RunWhenValid() {
325 TRACE_EVENT0("file_system_provider", "ReadFileRequestedSuccess");
326 using api::file_system_provider_internal::ReadFileRequestedSuccess::Params;
328 scoped_ptr<Params> params(Params::Create(*args_));
329 EXTENSION_FUNCTION_VALIDATE(params);
331 const bool has_more = params->has_more;
332 return FulfillRequest(RequestValue::CreateForReadFileSuccess(params.Pass()),
333 has_more);
336 bool
337 FileSystemProviderInternalOperationRequestedSuccessFunction::RunWhenValid() {
338 using api::file_system_provider_internal::OperationRequestedSuccess::Params;
339 scoped_ptr<Params> params(Params::Create(*args_));
340 EXTENSION_FUNCTION_VALIDATE(params);
342 return FulfillRequest(
343 scoped_ptr<RequestValue>(
344 RequestValue::CreateForOperationSuccess(params.Pass())),
345 false /* has_more */);
348 bool FileSystemProviderInternalOperationRequestedErrorFunction::RunWhenValid() {
349 using api::file_system_provider_internal::OperationRequestedError::Params;
350 scoped_ptr<Params> params(Params::Create(*args_));
351 EXTENSION_FUNCTION_VALIDATE(params);
353 const base::File::Error error = ProviderErrorToFileError(params->error);
354 return RejectRequest(RequestValue::CreateForOperationError(params.Pass()),
355 error);
358 } // namespace extensions