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/debug/trace_event.h"
11 #include "base/memory/linked_ptr.h"
12 #include "base/memory/scoped_ptr.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"
21 using chromeos::file_system_provider::MountOptions
;
22 using chromeos::file_system_provider::ProvidedFileSystemInfo
;
23 using chromeos::file_system_provider::ProvidedFileSystemInterface
;
24 using chromeos::file_system_provider::ProvidedFileSystemObserver
;
25 using chromeos::file_system_provider::RequestValue
;
26 using chromeos::file_system_provider::Service
;
28 namespace extensions
{
31 typedef std::vector
<linked_ptr
<api::file_system_provider::ChildChange
>>
34 const char kNotifyFailedErrorMessage
[] =
35 "Sending a response for the request failed.";
36 const char kInvalidNotificationErrorMessage
[] = "The notification is invalid.";
38 // Converts the change type from the IDL type to a native type. |changed_type|
39 // must be specified (not CHANGE_TYPE_NONE).
40 ProvidedFileSystemObserver::ChangeType
ParseChangeType(
41 const api::file_system_provider::ChangeType
& change_type
) {
42 switch (change_type
) {
43 case api::file_system_provider::CHANGE_TYPE_CHANGED
:
44 return ProvidedFileSystemObserver::CHANGED
;
45 case api::file_system_provider::CHANGE_TYPE_DELETED
:
46 return ProvidedFileSystemObserver::DELETED
;
51 return ProvidedFileSystemObserver::CHANGED
;
54 // Convert the child change from the IDL type to a native type. The reason IDL
55 // types are not used is since they are imperfect, eg. paths are stored as
57 ProvidedFileSystemObserver::ChildChange
ParseChildChange(
58 const api::file_system_provider::ChildChange
& child_change
) {
59 ProvidedFileSystemObserver::ChildChange result
;
60 result
.entry_path
= base::FilePath::FromUTF8Unsafe(child_change
.entry_path
);
61 result
.change_type
= ParseChangeType(child_change
.change_type
);
65 // Converts a list of child changes from the IDL type to a native type.
66 scoped_ptr
<ProvidedFileSystemObserver::ChildChanges
> ParseChildChanges(
67 const IDLChildChanges
& child_changes
) {
68 scoped_ptr
<ProvidedFileSystemObserver::ChildChanges
> results(
69 new ProvidedFileSystemObserver::ChildChanges
);
70 for (IDLChildChanges::const_iterator it
= child_changes
.begin();
71 it
!= child_changes
.end();
73 results
->push_back(ParseChildChange(*it
->get()));
80 bool FileSystemProviderMountFunction::RunSync() {
81 using api::file_system_provider::Mount::Params
;
82 const scoped_ptr
<Params
> params(Params::Create(*args_
));
83 EXTENSION_FUNCTION_VALIDATE(params
);
85 // It's an error if the file system Id is empty.
86 if (params
->options
.file_system_id
.empty()) {
87 base::ListValue
* const result
= new base::ListValue();
88 result
->Append(CreateError(kSecurityErrorName
, kEmptyIdErrorMessage
));
93 // It's an error if the display name is empty.
94 if (params
->options
.display_name
.empty()) {
95 base::ListValue
* const result
= new base::ListValue();
96 result
->Append(CreateError(kSecurityErrorName
,
97 kEmptyNameErrorMessage
));
102 Service
* const service
= Service::Get(GetProfile());
107 MountOptions options
;
108 options
.file_system_id
= params
->options
.file_system_id
;
109 options
.display_name
= params
->options
.display_name
;
110 options
.writable
= params
->options
.writable
;
111 options
.supports_notify_tag
= params
->options
.supports_notify_tag
;
113 // TODO(mtomasz): Pass more detailed errors, rather than just a bool.
114 if (!service
->MountFileSystem(extension_id(), options
)) {
115 base::ListValue
* const result
= new base::ListValue();
116 result
->Append(CreateError(kSecurityErrorName
, kMountFailedErrorMessage
));
121 base::ListValue
* result
= new base::ListValue();
126 bool FileSystemProviderUnmountFunction::RunSync() {
127 using api::file_system_provider::Unmount::Params
;
128 scoped_ptr
<Params
> params(Params::Create(*args_
));
129 EXTENSION_FUNCTION_VALIDATE(params
);
131 Service
* const service
= Service::Get(GetProfile());
136 if (!service
->UnmountFileSystem(extension_id(),
137 params
->options
.file_system_id
,
138 Service::UNMOUNT_REASON_USER
)) {
139 // TODO(mtomasz): Pass more detailed errors, rather than just a bool.
140 base::ListValue
* result
= new base::ListValue();
141 result
->Append(CreateError(kSecurityErrorName
, kUnmountFailedErrorMessage
));
146 base::ListValue
* const result
= new base::ListValue();
151 bool FileSystemProviderGetAllFunction::RunSync() {
152 using api::file_system_provider::FileSystemInfo
;
153 Service
* const service
= Service::Get(GetProfile());
158 const std::vector
<ProvidedFileSystemInfo
> file_systems
=
159 service
->GetProvidedFileSystemInfoList();
160 std::vector
<linked_ptr
<FileSystemInfo
> > items
;
162 for (size_t i
= 0; i
< file_systems
.size(); ++i
) {
163 if (file_systems
[i
].extension_id() == extension_id()) {
164 linked_ptr
<FileSystemInfo
> item(new FileSystemInfo
);
165 item
->file_system_id
= file_systems
[i
].file_system_id();
166 item
->display_name
= file_systems
[i
].display_name();
167 item
->writable
= file_systems
[i
].writable();
168 items
.push_back(item
);
172 SetResultList(api::file_system_provider::GetAll::Results::Create(items
));
176 bool FileSystemProviderNotifyFunction::RunSync() {
177 using api::file_system_provider::Notify::Params
;
178 scoped_ptr
<Params
> params(Params::Create(*args_
));
179 EXTENSION_FUNCTION_VALIDATE(params
);
181 Service
* const service
= Service::Get(GetProfile());
186 ProvidedFileSystemInterface
* const file_system
=
187 service
->GetProvidedFileSystem(extension_id(),
188 params
->options
.file_system_id
);
190 base::ListValue
* const result
= new base::ListValue();
191 result
->Append(CreateError(kNotFoundErrorName
, kNotifyFailedErrorMessage
));
196 if (!file_system
->Notify(
197 base::FilePath::FromUTF8Unsafe(params
->options
.observed_path
),
198 ParseChangeType(params
->options
.change_type
),
199 params
->options
.child_changes
.get()
200 ? ParseChildChanges(*params
->options
.child_changes
.get())
201 : make_scoped_ptr(new ProvidedFileSystemObserver::ChildChanges
),
202 params
->options
.tag
.get() ? *params
->options
.tag
.get() : "")) {
203 base::ListValue
* const result
= new base::ListValue();
205 CreateError(kSecurityErrorName
, kInvalidNotificationErrorMessage
));
210 base::ListValue
* const result
= new base::ListValue();
215 bool FileSystemProviderInternalUnmountRequestedSuccessFunction::RunWhenValid() {
216 using api::file_system_provider_internal::UnmountRequestedSuccess::Params
;
217 scoped_ptr
<Params
> params(Params::Create(*args_
));
218 EXTENSION_FUNCTION_VALIDATE(params
);
220 FulfillRequest(RequestValue::CreateForUnmountSuccess(params
.Pass()),
221 false /* has_more */);
226 FileSystemProviderInternalGetMetadataRequestedSuccessFunction::RunWhenValid() {
227 using api::file_system_provider_internal::GetMetadataRequestedSuccess::Params
;
228 scoped_ptr
<Params
> params(Params::Create(*args_
));
229 EXTENSION_FUNCTION_VALIDATE(params
);
231 FulfillRequest(RequestValue::CreateForGetMetadataSuccess(params
.Pass()),
232 false /* has_more */);
236 bool FileSystemProviderInternalReadDirectoryRequestedSuccessFunction::
238 using api::file_system_provider_internal::ReadDirectoryRequestedSuccess::
240 scoped_ptr
<Params
> params(Params::Create(*args_
));
241 EXTENSION_FUNCTION_VALIDATE(params
);
243 const bool has_more
= params
->has_more
;
244 FulfillRequest(RequestValue::CreateForReadDirectorySuccess(params
.Pass()),
250 FileSystemProviderInternalReadFileRequestedSuccessFunction::RunWhenValid() {
251 TRACE_EVENT0("file_system_provider", "ReadFileRequestedSuccess");
252 using api::file_system_provider_internal::ReadFileRequestedSuccess::Params
;
254 scoped_ptr
<Params
> params(Params::Create(*args_
));
255 EXTENSION_FUNCTION_VALIDATE(params
);
257 const bool has_more
= params
->has_more
;
258 FulfillRequest(RequestValue::CreateForReadFileSuccess(params
.Pass()),
264 FileSystemProviderInternalOperationRequestedSuccessFunction::RunWhenValid() {
265 using api::file_system_provider_internal::OperationRequestedSuccess::Params
;
266 scoped_ptr
<Params
> params(Params::Create(*args_
));
267 EXTENSION_FUNCTION_VALIDATE(params
);
269 FulfillRequest(scoped_ptr
<RequestValue
>(
270 RequestValue::CreateForOperationSuccess(params
.Pass())),
271 false /* has_more */);
275 bool FileSystemProviderInternalOperationRequestedErrorFunction::RunWhenValid() {
276 using api::file_system_provider_internal::OperationRequestedError::Params
;
277 scoped_ptr
<Params
> params(Params::Create(*args_
));
278 EXTENSION_FUNCTION_VALIDATE(params
);
280 const base::File::Error error
= ProviderErrorToFileError(params
->error
);
281 RejectRequest(RequestValue::CreateForOperationError(params
.Pass()), error
);
285 } // namespace extensions