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.
5 #include "chrome/browser/ui/webui/chromeos/provided_file_systems_ui.h"
10 #include "base/bind.h"
11 #include "base/files/file.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/memory/weak_ptr.h"
14 #include "base/values.h"
15 #include "chrome/browser/chromeos/file_system_provider/provided_file_system_info.h"
16 #include "chrome/browser/chromeos/file_system_provider/provided_file_system_interface.h"
17 #include "chrome/browser/chromeos/file_system_provider/request_manager.h"
18 #include "chrome/browser/chromeos/file_system_provider/service.h"
19 #include "chrome/browser/chromeos/file_system_provider/service_factory.h"
20 #include "chrome/browser/profiles/profile.h"
21 #include "chrome/common/url_constants.h"
22 #include "content/public/browser/browser_thread.h"
23 #include "content/public/browser/web_ui.h"
24 #include "content/public/browser/web_ui_data_source.h"
25 #include "content/public/browser/web_ui_message_handler.h"
26 #include "grit/browser_resources.h"
28 using content::BrowserThread
;
34 const char kKeyId
[] = "id";
35 const char kKeyEventType
[] = "eventType";
36 const char kKeyRequestType
[] = "requestType";
37 const char kKeyTime
[] = "time";
38 const char kKeyHasMore
[] = "hasMore";
39 const char kKeyError
[] = "error";
40 const char kKeyExecutionTime
[] = "executionTime";
41 const char kKeyValueSize
[] = "valueSize";
43 const char kKeyName
[] = "name";
44 const char kKeyExtensionId
[] = "extensionId";
45 const char kKeyMountPath
[] = "mountPath";
46 const char kKeyActiveRequests
[] = "activeRequests";
48 const char kRequestCreated
[] = "created";
49 const char kRequestDestroyed
[] = "destroyed";
50 const char kRequestExecuted
[] = "executed";
51 const char kRequestFulfilled
[] = "fulfilled";
52 const char kRequestRejected
[] = "rejected";
53 const char kRequestTimeouted
[] = "timeouted";
55 const char kFunctionOnRequestEvent
[] = "onRequestEvent";
56 const char kFunctionUpdateFileSystems
[] = "updateFileSystems";
57 const char kFunctionSelectFileSystem
[] = "selectFileSystem";
59 // Creates a dictionary holding common fields for the onRequest* events.
60 scoped_ptr
<base::DictionaryValue
> CreateRequestEvent(const std::string
& type
,
62 scoped_ptr
<base::DictionaryValue
> event(new base::DictionaryValue
);
63 event
->SetInteger(kKeyId
, request_id
);
64 event
->SetString(kKeyEventType
, type
);
65 event
->SetDouble(kKeyTime
, base::Time::Now().ToJsTime());
69 // Gets execution time from a RequestValue instance. If the |response| doesn't
70 // have execution time, then returns 0.
71 int GetExecutionTime(const file_system_provider::RequestValue
& response
) {
73 const extensions::api::file_system_provider_internal::
74 UnmountRequestedSuccess::Params
* value
=
75 response
.unmount_success_params();
77 return value
->execution_time
;
80 const extensions::api::file_system_provider_internal::
81 GetMetadataRequestedSuccess::Params
* value
=
82 response
.get_metadata_success_params();
84 return value
->execution_time
;
87 const extensions::api::file_system_provider_internal::
88 ReadDirectoryRequestedSuccess::Params
* value
=
89 response
.read_directory_success_params();
91 return value
->execution_time
;
94 const extensions::api::file_system_provider_internal::
95 ReadFileRequestedSuccess::Params
* value
=
96 response
.read_file_success_params();
98 return value
->execution_time
;
101 const extensions::api::file_system_provider_internal::
102 OperationRequestedSuccess::Params
* value
=
103 response
.operation_success_params();
105 return value
->execution_time
;
108 const extensions::api::file_system_provider_internal::
109 OperationRequestedError::Params
* value
=
110 response
.operation_error_params();
112 return value
->execution_time
;
118 // Gets value size in bytes from a RequestValue instance. If not available,
120 int GetValueSize(const file_system_provider::RequestValue
& response
) {
121 const extensions::api::file_system_provider_internal::
122 ReadFileRequestedSuccess::Params
* value
=
123 response
.read_file_success_params();
125 return value
->data
.size();
130 // Class to handle messages from chrome://provided-file-systems.
131 class ProvidedFileSystemsWebUIHandler
132 : public content::WebUIMessageHandler
,
133 public file_system_provider::RequestManager::Observer
{
135 ProvidedFileSystemsWebUIHandler() : weak_ptr_factory_(this) {}
137 ~ProvidedFileSystemsWebUIHandler() override
;
139 // RequestManager::Observer overrides.
140 void OnRequestCreated(int request_id
,
141 file_system_provider::RequestType type
) override
;
142 void OnRequestDestroyed(int request_id
) override
;
143 void OnRequestExecuted(int request_id
) override
;
144 void OnRequestFulfilled(int request_id
,
145 const file_system_provider::RequestValue
& result
,
146 bool has_more
) override
;
147 void OnRequestRejected(int request_id
,
148 const file_system_provider::RequestValue
& result
,
149 base::File::Error error
) override
;
150 void OnRequestTimeouted(int request_id
) override
;
153 // content::WebUIMessageHandler overrides.
154 void RegisterMessages() override
;
156 // Gets a file system provider service for the current profile. If not found,
158 file_system_provider::Service
* GetService();
160 // Invoked when updating file system list is requested.
161 void UpdateFileSystems(const base::ListValue
* args
);
163 // Invoked when a file system is selected from the list.
164 void SelectFileSystem(const base::ListValue
* args
);
166 std::string selected_extension_id
;
167 std::string selected_file_system_id
;
168 base::WeakPtrFactory
<ProvidedFileSystemsWebUIHandler
> weak_ptr_factory_
;
170 DISALLOW_COPY_AND_ASSIGN(ProvidedFileSystemsWebUIHandler
);
173 ProvidedFileSystemsWebUIHandler::~ProvidedFileSystemsWebUIHandler() {
174 // Stop observing the currently selected file system.
175 file_system_provider::Service
* const service
= GetService();
179 file_system_provider::ProvidedFileSystemInterface
* const file_system
=
180 service
->GetProvidedFileSystem(selected_extension_id
,
181 selected_file_system_id
);
184 file_system_provider::RequestManager
* const request_manager
=
185 file_system
->GetRequestManager();
186 DCHECK(request_manager
);
187 request_manager
->RemoveObserver(this);
191 void ProvidedFileSystemsWebUIHandler::OnRequestCreated(
193 file_system_provider::RequestType type
) {
194 scoped_ptr
<base::DictionaryValue
> const event
=
195 CreateRequestEvent(kRequestCreated
, request_id
);
196 event
->SetString(kKeyRequestType
,
197 file_system_provider::RequestTypeToString(type
));
198 web_ui()->CallJavascriptFunction(kFunctionOnRequestEvent
, *event
);
201 void ProvidedFileSystemsWebUIHandler::OnRequestDestroyed(int request_id
) {
202 scoped_ptr
<base::DictionaryValue
> const event
=
203 CreateRequestEvent(kRequestDestroyed
, request_id
);
204 web_ui()->CallJavascriptFunction(kFunctionOnRequestEvent
, *event
);
207 void ProvidedFileSystemsWebUIHandler::OnRequestExecuted(int request_id
) {
208 scoped_ptr
<base::DictionaryValue
> const event
=
209 CreateRequestEvent(kRequestExecuted
, request_id
);
210 web_ui()->CallJavascriptFunction(kFunctionOnRequestEvent
, *event
);
213 void ProvidedFileSystemsWebUIHandler::OnRequestFulfilled(
215 const file_system_provider::RequestValue
& result
,
217 scoped_ptr
<base::DictionaryValue
> const event
=
218 CreateRequestEvent(kRequestFulfilled
, request_id
);
219 event
->SetBoolean(kKeyHasMore
, has_more
);
220 event
->SetInteger(kKeyExecutionTime
, GetExecutionTime(result
));
221 event
->SetInteger(kKeyValueSize
, GetValueSize(result
));
222 web_ui()->CallJavascriptFunction(kFunctionOnRequestEvent
, *event
);
225 void ProvidedFileSystemsWebUIHandler::OnRequestRejected(
227 const file_system_provider::RequestValue
& result
,
228 base::File::Error error
) {
229 scoped_ptr
<base::DictionaryValue
> const event
=
230 CreateRequestEvent(kRequestRejected
, request_id
);
231 event
->SetString(kKeyError
, base::File::ErrorToString(error
));
232 event
->SetInteger(kKeyExecutionTime
, GetExecutionTime(result
));
233 event
->SetInteger(kKeyValueSize
, GetValueSize(result
));
234 web_ui()->CallJavascriptFunction(kFunctionOnRequestEvent
, *event
);
237 void ProvidedFileSystemsWebUIHandler::OnRequestTimeouted(int request_id
) {
238 scoped_ptr
<base::DictionaryValue
> const event
=
239 CreateRequestEvent(kRequestTimeouted
, request_id
);
240 web_ui()->CallJavascriptFunction(kFunctionOnRequestEvent
, *event
);
243 void ProvidedFileSystemsWebUIHandler::RegisterMessages() {
244 web_ui()->RegisterMessageCallback(
245 kFunctionUpdateFileSystems
,
246 base::Bind(&ProvidedFileSystemsWebUIHandler::UpdateFileSystems
,
247 weak_ptr_factory_
.GetWeakPtr()));
248 web_ui()->RegisterMessageCallback(
249 kFunctionSelectFileSystem
,
250 base::Bind(&ProvidedFileSystemsWebUIHandler::SelectFileSystem
,
251 weak_ptr_factory_
.GetWeakPtr()));
254 file_system_provider::Service
* ProvidedFileSystemsWebUIHandler::GetService() {
255 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
257 Profile
* const profile
= Profile::FromWebUI(web_ui());
258 return file_system_provider::ServiceFactory::FindExisting(profile
);
261 void ProvidedFileSystemsWebUIHandler::UpdateFileSystems(
262 const base::ListValue
* args
) {
263 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
265 file_system_provider::Service
* const service
= GetService();
269 base::ListValue items
;
271 const std::vector
<file_system_provider::ProvidedFileSystemInfo
>
272 file_system_info_list
= service
->GetProvidedFileSystemInfoList();
274 for (size_t i
= 0; i
< file_system_info_list
.size(); ++i
) {
275 const file_system_provider::ProvidedFileSystemInfo file_system_info
=
276 file_system_info_list
[i
];
278 file_system_provider::ProvidedFileSystemInterface
* const file_system
=
279 service
->GetProvidedFileSystem(file_system_info
.extension_id(),
280 file_system_info
.file_system_id());
283 file_system_provider::RequestManager
* const request_manager
=
284 file_system
->GetRequestManager();
285 DCHECK(request_manager
);
287 base::DictionaryValue
* item
= new base::DictionaryValue();
288 item
->SetString(kKeyId
, file_system_info
.file_system_id());
289 item
->SetString(kKeyName
, file_system_info
.display_name());
290 item
->SetString(kKeyExtensionId
, file_system_info
.extension_id());
291 item
->SetString(kKeyMountPath
,
292 file_system_info
.mount_path().AsUTF8Unsafe());
293 item
->SetInteger(kKeyActiveRequests
,
294 request_manager
->GetActiveRequestIds().size());
299 web_ui()->CallJavascriptFunction(kFunctionUpdateFileSystems
, items
);
302 void ProvidedFileSystemsWebUIHandler::SelectFileSystem(
303 const base::ListValue
* args
) {
304 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
306 file_system_provider::Service
* const service
= GetService();
310 std::string extension_id
;
311 if (!args
->GetString(0, &extension_id
))
314 std::string file_system_id
;
315 if (!args
->GetString(1, &file_system_id
))
318 // Stop observing the previously selected request manager.
320 file_system_provider::ProvidedFileSystemInterface
* const file_system
=
321 service
->GetProvidedFileSystem(selected_extension_id
,
322 selected_file_system_id
);
324 file_system_provider::RequestManager
* const request_manager
=
325 file_system
->GetRequestManager();
326 DCHECK(request_manager
);
327 request_manager
->RemoveObserver(this);
331 // Observe the selected file system.
332 file_system_provider::ProvidedFileSystemInterface
* const file_system
=
333 service
->GetProvidedFileSystem(extension_id
, file_system_id
);
337 file_system_provider::RequestManager
* const request_manager
=
338 file_system
->GetRequestManager();
339 DCHECK(request_manager
);
341 request_manager
->AddObserver(this);
342 selected_extension_id
= extension_id
;
343 selected_file_system_id
= file_system_id
;
348 ProvidedFileSystemsUI::ProvidedFileSystemsUI(content::WebUI
* web_ui
)
349 : WebUIController(web_ui
) {
350 web_ui
->AddMessageHandler(new ProvidedFileSystemsWebUIHandler());
352 content::WebUIDataSource
* source
= content::WebUIDataSource::Create(
353 chrome::kChromeUIProvidedFileSystemsHost
);
354 source
->AddResourcePath("provided_file_systems.css",
355 IDR_PROVIDED_FILE_SYSTEMS_CSS
);
356 source
->AddResourcePath("provided_file_systems.js",
357 IDR_PROVIDED_FILE_SYSTEMS_JS
);
358 source
->SetDefaultResource(IDR_PROVIDED_FILE_SYSTEMS_HTML
);
360 Profile
* profile
= Profile::FromWebUI(web_ui
);
361 content::WebUIDataSource::Add(profile
, source
);
364 } // namespace chromeos