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"
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
{
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
;
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
);
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
));
74 // Fills the IDL's FileSystemInfo with FSP's ProvidedFileSystemInfo and
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
;
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
;
114 opened_file_items
.push_back(opened_file_item
);
116 output
->opened_files
= opened_file_items
;
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
));
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
));
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
));
145 Service
* const service
= Service::Get(GetProfile());
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()
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
));
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());
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
));
186 bool FileSystemProviderGetAllFunction::RunSync() {
187 using api::file_system_provider::FileSystemInfo
;
188 Service
* const service
= Service::Get(GetProfile());
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
201 service
->GetProvidedFileSystem(file_system_info
.extension_id(),
202 file_system_info
.file_system_id());
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
));
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());
224 chromeos::file_system_provider::ProvidedFileSystemInterface
* const
225 file_system
= service
->GetProvidedFileSystem(extension_id(),
226 params
->file_system_id
);
229 SetError(FileErrorToString(base::File::FILE_ERROR_NOT_FOUND
));
233 FileSystemInfo file_system_info
;
234 FillFileSystemInfo(file_system
->GetFileSystemInfo(),
235 *file_system
->GetWatchers(), file_system
->GetOpenedFiles(),
238 api::file_system_provider::Get::Results::Create(file_system_info
));
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());
250 ProvidedFileSystemInterface
* const file_system
=
251 service
->GetProvidedFileSystem(extension_id(),
252 params
->options
.file_system_id
);
254 SetError(FileErrorToString(base::File::FILE_ERROR_NOT_FOUND
));
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));
270 void FileSystemProviderNotifyFunction::OnNotifyCompleted(
271 base::File::Error result
) {
272 if (result
!= base::File::FILE_OK
) {
273 SetError(FileErrorToString(result
));
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 */);
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::
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::
313 using api::file_system_provider_internal::ReadDirectoryRequestedSuccess::
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
);
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()),
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()),
358 } // namespace extensions