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_interface.h"
15 #include "chrome/browser/chromeos/file_system_provider/request_manager.h"
16 #include "chrome/browser/chromeos/file_system_provider/request_value.h"
17 #include "chrome/browser/chromeos/file_system_provider/service.h"
18 #include "chrome/common/extensions/api/file_system_provider.h"
19 #include "chrome/common/extensions/api/file_system_provider_internal.h"
20 #include "storage/browser/fileapi/watcher_manager.h"
22 using chromeos::file_system_provider::MountOptions
;
23 using chromeos::file_system_provider::OpenedFiles
;
24 using chromeos::file_system_provider::ProvidedFileSystemInfo
;
25 using chromeos::file_system_provider::ProvidedFileSystemInterface
;
26 using chromeos::file_system_provider::ProvidedFileSystemObserver
;
27 using chromeos::file_system_provider::RequestValue
;
28 using chromeos::file_system_provider::Service
;
29 using chromeos::file_system_provider::Watchers
;
31 namespace extensions
{
34 typedef std::vector
<linked_ptr
<api::file_system_provider::Change
>> IDLChanges
;
36 // Converts the change type from the IDL type to a native type. |changed_type|
37 // must be specified (not CHANGE_TYPE_NONE).
38 storage::WatcherManager::ChangeType
ParseChangeType(
39 const api::file_system_provider::ChangeType
& change_type
) {
40 switch (change_type
) {
41 case api::file_system_provider::CHANGE_TYPE_CHANGED
:
42 return storage::WatcherManager::CHANGED
;
43 case api::file_system_provider::CHANGE_TYPE_DELETED
:
44 return storage::WatcherManager::DELETED
;
49 return storage::WatcherManager::CHANGED
;
52 // Convert the change from the IDL type to a native type. The reason IDL types
53 // are not used is since they are imperfect, eg. paths are stored as strings.
54 ProvidedFileSystemObserver::Change
ParseChange(
55 const api::file_system_provider::Change
& change
) {
56 ProvidedFileSystemObserver::Change result
;
57 result
.entry_path
= base::FilePath::FromUTF8Unsafe(change
.entry_path
);
58 result
.change_type
= ParseChangeType(change
.change_type
);
62 // Converts a list of child changes from the IDL type to a native type.
63 scoped_ptr
<ProvidedFileSystemObserver::Changes
> ParseChanges(
64 const IDLChanges
& changes
) {
65 scoped_ptr
<ProvidedFileSystemObserver::Changes
> results(
66 new ProvidedFileSystemObserver::Changes
);
67 for (const auto& change
: changes
) {
68 results
->push_back(ParseChange(*change
));
73 // Fills the IDL's FileSystemInfo with FSP's ProvidedFileSystemInfo and
75 void FillFileSystemInfo(const ProvidedFileSystemInfo
& file_system_info
,
76 const Watchers
& watchers
,
77 const OpenedFiles
& opened_files
,
78 api::file_system_provider::FileSystemInfo
* output
) {
79 using api::file_system_provider::Watcher
;
80 using api::file_system_provider::OpenedFile
;
82 output
->file_system_id
= file_system_info
.file_system_id();
83 output
->display_name
= file_system_info
.display_name();
84 output
->writable
= file_system_info
.writable();
85 output
->opened_files_limit
= file_system_info
.opened_files_limit();
87 std::vector
<linked_ptr
<Watcher
>> watcher_items
;
88 for (const auto& watcher
: watchers
) {
89 const linked_ptr
<Watcher
> watcher_item(new Watcher
);
90 watcher_item
->entry_path
= watcher
.second
.entry_path
.value();
91 watcher_item
->recursive
= watcher
.second
.recursive
;
92 if (!watcher
.second
.last_tag
.empty())
93 watcher_item
->last_tag
.reset(new std::string(watcher
.second
.last_tag
));
94 watcher_items
.push_back(watcher_item
);
96 output
->watchers
= watcher_items
;
98 std::vector
<linked_ptr
<OpenedFile
>> opened_file_items
;
99 for (const auto& opened_file
: opened_files
) {
100 const linked_ptr
<OpenedFile
> opened_file_item(new OpenedFile
);
101 opened_file_item
->open_request_id
= opened_file
.first
;
102 opened_file_item
->file_path
= opened_file
.second
.file_path
.value();
103 switch (opened_file
.second
.mode
) {
104 case chromeos::file_system_provider::OPEN_FILE_MODE_READ
:
105 opened_file_item
->mode
=
106 extensions::api::file_system_provider::OPEN_FILE_MODE_READ
;
108 case chromeos::file_system_provider::OPEN_FILE_MODE_WRITE
:
109 opened_file_item
->mode
=
110 extensions::api::file_system_provider::OPEN_FILE_MODE_WRITE
;
113 opened_file_items
.push_back(opened_file_item
);
115 output
->opened_files
= opened_file_items
;
120 bool FileSystemProviderMountFunction::RunSync() {
121 using api::file_system_provider::Mount::Params
;
122 const scoped_ptr
<Params
> params(Params::Create(*args_
));
123 EXTENSION_FUNCTION_VALIDATE(params
);
125 // It's an error if the file system Id is empty.
126 if (params
->options
.file_system_id
.empty()) {
127 SetError(FileErrorToString(base::File::FILE_ERROR_INVALID_OPERATION
));
131 // It's an error if the display name is empty.
132 if (params
->options
.display_name
.empty()) {
133 SetError(FileErrorToString(base::File::FILE_ERROR_INVALID_OPERATION
));
137 // If the opened files limit is set, then it must be larger or equal than 0.
138 if (params
->options
.opened_files_limit
.get() &&
139 *params
->options
.opened_files_limit
.get() < 0) {
140 SetError(FileErrorToString(base::File::FILE_ERROR_INVALID_OPERATION
));
144 Service
* const service
= Service::Get(GetProfile());
147 MountOptions options
;
148 options
.file_system_id
= params
->options
.file_system_id
;
149 options
.display_name
= params
->options
.display_name
;
150 options
.writable
= params
->options
.writable
;
151 options
.opened_files_limit
= params
->options
.opened_files_limit
.get()
152 ? *params
->options
.opened_files_limit
.get()
154 options
.supports_notify_tag
= params
->options
.supports_notify_tag
;
156 const base::File::Error result
=
157 service
->MountFileSystem(extension_id(), options
);
158 if (result
!= base::File::FILE_OK
) {
159 SetError(FileErrorToString(result
));
166 bool FileSystemProviderUnmountFunction::RunSync() {
167 using api::file_system_provider::Unmount::Params
;
168 scoped_ptr
<Params
> params(Params::Create(*args_
));
169 EXTENSION_FUNCTION_VALIDATE(params
);
171 Service
* const service
= Service::Get(GetProfile());
174 const base::File::Error result
=
175 service
->UnmountFileSystem(extension_id(), params
->options
.file_system_id
,
176 Service::UNMOUNT_REASON_USER
);
177 if (result
!= base::File::FILE_OK
) {
178 SetError(FileErrorToString(result
));
185 bool FileSystemProviderGetAllFunction::RunSync() {
186 using api::file_system_provider::FileSystemInfo
;
187 Service
* const service
= Service::Get(GetProfile());
190 const std::vector
<ProvidedFileSystemInfo
> file_systems
=
191 service
->GetProvidedFileSystemInfoList();
192 std::vector
<linked_ptr
<FileSystemInfo
>> items
;
194 for (const auto& file_system_info
: file_systems
) {
195 if (file_system_info
.extension_id() == extension_id()) {
196 const linked_ptr
<FileSystemInfo
> item(new FileSystemInfo
);
198 chromeos::file_system_provider::ProvidedFileSystemInterface
* const
200 service
->GetProvidedFileSystem(file_system_info
.extension_id(),
201 file_system_info
.file_system_id());
204 FillFileSystemInfo(file_system_info
, *file_system
->GetWatchers(),
205 file_system
->GetOpenedFiles(), item
.get());
206 items
.push_back(item
);
210 SetResultList(api::file_system_provider::GetAll::Results::Create(items
));
214 bool FileSystemProviderGetFunction::RunSync() {
215 using api::file_system_provider::Get::Params
;
216 scoped_ptr
<Params
> params(Params::Create(*args_
));
217 EXTENSION_FUNCTION_VALIDATE(params
);
219 using api::file_system_provider::FileSystemInfo
;
220 Service
* const service
= Service::Get(GetProfile());
223 chromeos::file_system_provider::ProvidedFileSystemInterface
* const
224 file_system
= service
->GetProvidedFileSystem(extension_id(),
225 params
->file_system_id
);
228 SetError(FileErrorToString(base::File::FILE_ERROR_NOT_FOUND
));
232 FileSystemInfo file_system_info
;
233 FillFileSystemInfo(file_system
->GetFileSystemInfo(),
234 *file_system
->GetWatchers(), file_system
->GetOpenedFiles(),
237 api::file_system_provider::Get::Results::Create(file_system_info
));
241 bool FileSystemProviderNotifyFunction::RunAsync() {
242 using api::file_system_provider::Notify::Params
;
243 scoped_ptr
<Params
> params(Params::Create(*args_
));
244 EXTENSION_FUNCTION_VALIDATE(params
);
246 Service
* const service
= Service::Get(GetProfile());
249 ProvidedFileSystemInterface
* const file_system
=
250 service
->GetProvidedFileSystem(extension_id(),
251 params
->options
.file_system_id
);
253 SetError(FileErrorToString(base::File::FILE_ERROR_NOT_FOUND
));
258 base::FilePath::FromUTF8Unsafe(params
->options
.observed_path
),
259 params
->options
.recursive
, ParseChangeType(params
->options
.change_type
),
260 params
->options
.changes
.get()
261 ? ParseChanges(*params
->options
.changes
.get())
262 : make_scoped_ptr(new ProvidedFileSystemObserver::Changes
),
263 params
->options
.tag
.get() ? *params
->options
.tag
.get() : "",
264 base::Bind(&FileSystemProviderNotifyFunction::OnNotifyCompleted
, this));
269 void FileSystemProviderNotifyFunction::OnNotifyCompleted(
270 base::File::Error result
) {
271 if (result
!= base::File::FILE_OK
) {
272 SetError(FileErrorToString(result
));
280 bool FileSystemProviderInternalUnmountRequestedSuccessFunction::RunWhenValid() {
281 using api::file_system_provider_internal::UnmountRequestedSuccess::Params
;
282 scoped_ptr
<Params
> params(Params::Create(*args_
));
283 EXTENSION_FUNCTION_VALIDATE(params
);
285 return FulfillRequest(RequestValue::CreateForUnmountSuccess(params
.Pass()),
286 false /* has_more */);
290 FileSystemProviderInternalGetMetadataRequestedSuccessFunction::RunWhenValid() {
291 using api::file_system_provider_internal::GetMetadataRequestedSuccess::Params
;
292 scoped_ptr
<Params
> params(Params::Create(*args_
));
293 EXTENSION_FUNCTION_VALIDATE(params
);
295 return FulfillRequest(
296 RequestValue::CreateForGetMetadataSuccess(params
.Pass()),
297 false /* has_more */);
300 bool FileSystemProviderInternalReadDirectoryRequestedSuccessFunction::
302 using api::file_system_provider_internal::ReadDirectoryRequestedSuccess::
304 scoped_ptr
<Params
> params(Params::Create(*args_
));
305 EXTENSION_FUNCTION_VALIDATE(params
);
307 const bool has_more
= params
->has_more
;
308 return FulfillRequest(
309 RequestValue::CreateForReadDirectorySuccess(params
.Pass()), has_more
);
313 FileSystemProviderInternalReadFileRequestedSuccessFunction::RunWhenValid() {
314 TRACE_EVENT0("file_system_provider", "ReadFileRequestedSuccess");
315 using api::file_system_provider_internal::ReadFileRequestedSuccess::Params
;
317 scoped_ptr
<Params
> params(Params::Create(*args_
));
318 EXTENSION_FUNCTION_VALIDATE(params
);
320 const bool has_more
= params
->has_more
;
321 return FulfillRequest(RequestValue::CreateForReadFileSuccess(params
.Pass()),
326 FileSystemProviderInternalOperationRequestedSuccessFunction::RunWhenValid() {
327 using api::file_system_provider_internal::OperationRequestedSuccess::Params
;
328 scoped_ptr
<Params
> params(Params::Create(*args_
));
329 EXTENSION_FUNCTION_VALIDATE(params
);
331 return FulfillRequest(
332 scoped_ptr
<RequestValue
>(
333 RequestValue::CreateForOperationSuccess(params
.Pass())),
334 false /* has_more */);
337 bool FileSystemProviderInternalOperationRequestedErrorFunction::RunWhenValid() {
338 using api::file_system_provider_internal::OperationRequestedError::Params
;
339 scoped_ptr
<Params
> params(Params::Create(*args_
));
340 EXTENSION_FUNCTION_VALIDATE(params
);
342 const base::File::Error error
= ProviderErrorToFileError(params
->error
);
343 return RejectRequest(RequestValue::CreateForOperationError(params
.Pass()),
347 } // namespace extensions