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 virtual ~ProvidedFileSystemsWebUIHandler();
139 // RequestManager::Observer overrides.
140 virtual void OnRequestCreated(
142 file_system_provider::RequestType type) override;
143 virtual void OnRequestDestroyed(int request_id) override;
144 virtual void OnRequestExecuted(int request_id) override;
145 virtual void OnRequestFulfilled(
147 const file_system_provider::RequestValue& result,
148 bool has_more) override;
149 virtual void OnRequestRejected(
151 const file_system_provider::RequestValue& result,
152 base::File::Error error) override;
153 virtual void OnRequestTimeouted(int request_id) override;
156 // content::WebUIMessageHandler overrides.
157 virtual void RegisterMessages() override;
159 // Gets a file system provider service for the current profile. If not found,
161 file_system_provider::Service* GetService();
163 // Invoked when updating file system list is requested.
164 void UpdateFileSystems(const base::ListValue* args);
166 // Invoked when a file system is selected from the list.
167 void SelectFileSystem(const base::ListValue* args);
169 std::string selected_extension_id;
170 std::string selected_file_system_id;
171 base::WeakPtrFactory<ProvidedFileSystemsWebUIHandler> weak_ptr_factory_;
173 DISALLOW_COPY_AND_ASSIGN(ProvidedFileSystemsWebUIHandler);
176 ProvidedFileSystemsWebUIHandler::~ProvidedFileSystemsWebUIHandler() {
177 // Stop observing the currently selected file system.
178 file_system_provider::Service* const service = GetService();
182 file_system_provider::ProvidedFileSystemInterface* const file_system =
183 service->GetProvidedFileSystem(selected_extension_id,
184 selected_file_system_id);
187 file_system_provider::RequestManager* const request_manager =
188 file_system->GetRequestManager();
189 DCHECK(request_manager);
190 request_manager->RemoveObserver(this);
194 void ProvidedFileSystemsWebUIHandler::OnRequestCreated(
196 file_system_provider::RequestType type) {
197 scoped_ptr<base::DictionaryValue> const event =
198 CreateRequestEvent(kRequestCreated, request_id);
199 event->SetString(kKeyRequestType,
200 file_system_provider::RequestTypeToString(type));
201 web_ui()->CallJavascriptFunction(kFunctionOnRequestEvent, *event);
204 void ProvidedFileSystemsWebUIHandler::OnRequestDestroyed(int request_id) {
205 scoped_ptr<base::DictionaryValue> const event =
206 CreateRequestEvent(kRequestDestroyed, request_id);
207 web_ui()->CallJavascriptFunction(kFunctionOnRequestEvent, *event);
210 void ProvidedFileSystemsWebUIHandler::OnRequestExecuted(int request_id) {
211 scoped_ptr<base::DictionaryValue> const event =
212 CreateRequestEvent(kRequestExecuted, request_id);
213 web_ui()->CallJavascriptFunction(kFunctionOnRequestEvent, *event);
216 void ProvidedFileSystemsWebUIHandler::OnRequestFulfilled(
218 const file_system_provider::RequestValue& result,
220 scoped_ptr<base::DictionaryValue> const event =
221 CreateRequestEvent(kRequestFulfilled, request_id);
222 event->SetBoolean(kKeyHasMore, has_more);
223 event->SetInteger(kKeyExecutionTime, GetExecutionTime(result));
224 event->SetInteger(kKeyValueSize, GetValueSize(result));
225 web_ui()->CallJavascriptFunction(kFunctionOnRequestEvent, *event);
228 void ProvidedFileSystemsWebUIHandler::OnRequestRejected(
230 const file_system_provider::RequestValue& result,
231 base::File::Error error) {
232 scoped_ptr<base::DictionaryValue> const event =
233 CreateRequestEvent(kRequestRejected, request_id);
234 event->SetString(kKeyError, base::File::ErrorToString(error));
235 event->SetInteger(kKeyExecutionTime, GetExecutionTime(result));
236 event->SetInteger(kKeyValueSize, GetValueSize(result));
237 web_ui()->CallJavascriptFunction(kFunctionOnRequestEvent, *event);
240 void ProvidedFileSystemsWebUIHandler::OnRequestTimeouted(int request_id) {
241 scoped_ptr<base::DictionaryValue> const event =
242 CreateRequestEvent(kRequestTimeouted, request_id);
243 web_ui()->CallJavascriptFunction(kFunctionOnRequestEvent, *event);
246 void ProvidedFileSystemsWebUIHandler::RegisterMessages() {
247 web_ui()->RegisterMessageCallback(
248 kFunctionUpdateFileSystems,
249 base::Bind(&ProvidedFileSystemsWebUIHandler::UpdateFileSystems,
250 weak_ptr_factory_.GetWeakPtr()));
251 web_ui()->RegisterMessageCallback(
252 kFunctionSelectFileSystem,
253 base::Bind(&ProvidedFileSystemsWebUIHandler::SelectFileSystem,
254 weak_ptr_factory_.GetWeakPtr()));
257 file_system_provider::Service* ProvidedFileSystemsWebUIHandler::GetService() {
258 DCHECK_CURRENTLY_ON(BrowserThread::UI);
260 Profile* const profile = Profile::FromWebUI(web_ui());
261 return file_system_provider::ServiceFactory::FindExisting(profile);
264 void ProvidedFileSystemsWebUIHandler::UpdateFileSystems(
265 const base::ListValue* args) {
266 DCHECK_CURRENTLY_ON(BrowserThread::UI);
268 file_system_provider::Service* const service = GetService();
272 base::ListValue items;
274 const std::vector<file_system_provider::ProvidedFileSystemInfo>
275 file_system_info_list = service->GetProvidedFileSystemInfoList();
277 for (size_t i = 0; i < file_system_info_list.size(); ++i) {
278 const file_system_provider::ProvidedFileSystemInfo file_system_info =
279 file_system_info_list[i];
281 file_system_provider::ProvidedFileSystemInterface* const file_system =
282 service->GetProvidedFileSystem(file_system_info.extension_id(),
283 file_system_info.file_system_id());
286 file_system_provider::RequestManager* const request_manager =
287 file_system->GetRequestManager();
288 DCHECK(request_manager);
290 base::DictionaryValue* item = new base::DictionaryValue();
291 item->SetString(kKeyId, file_system_info.file_system_id());
292 item->SetString(kKeyName, file_system_info.display_name());
293 item->SetString(kKeyExtensionId, file_system_info.extension_id());
294 item->SetString(kKeyMountPath,
295 file_system_info.mount_path().AsUTF8Unsafe());
296 item->SetInteger(kKeyActiveRequests,
297 request_manager->GetActiveRequestIds().size());
302 web_ui()->CallJavascriptFunction(kFunctionUpdateFileSystems, items);
305 void ProvidedFileSystemsWebUIHandler::SelectFileSystem(
306 const base::ListValue* args) {
307 DCHECK_CURRENTLY_ON(BrowserThread::UI);
309 file_system_provider::Service* const service = GetService();
313 std::string extension_id;
314 if (!args->GetString(0, &extension_id))
317 std::string file_system_id;
318 if (!args->GetString(1, &file_system_id))
321 // Stop observing the previously selected request manager.
323 file_system_provider::ProvidedFileSystemInterface* const file_system =
324 service->GetProvidedFileSystem(selected_extension_id,
325 selected_file_system_id);
327 file_system_provider::RequestManager* const request_manager =
328 file_system->GetRequestManager();
329 DCHECK(request_manager);
330 request_manager->RemoveObserver(this);
334 // Observe the selected file system.
335 file_system_provider::ProvidedFileSystemInterface* const file_system =
336 service->GetProvidedFileSystem(extension_id, file_system_id);
340 file_system_provider::RequestManager* const request_manager =
341 file_system->GetRequestManager();
342 DCHECK(request_manager);
344 request_manager->AddObserver(this);
345 selected_extension_id = extension_id;
346 selected_file_system_id = file_system_id;
351 ProvidedFileSystemsUI::ProvidedFileSystemsUI(content::WebUI* web_ui)
352 : WebUIController(web_ui) {
353 web_ui->AddMessageHandler(new ProvidedFileSystemsWebUIHandler());
355 content::WebUIDataSource* source = content::WebUIDataSource::Create(
356 chrome::kChromeUIProvidedFileSystemsHost);
357 source->AddResourcePath("provided_file_systems.css",
358 IDR_PROVIDED_FILE_SYSTEMS_CSS);
359 source->AddResourcePath("provided_file_systems.js",
360 IDR_PROVIDED_FILE_SYSTEMS_JS);
361 source->SetDefaultResource(IDR_PROVIDED_FILE_SYSTEMS_HTML);
363 Profile* profile = Profile::FromWebUI(web_ui);
364 content::WebUIDataSource::Add(profile, source);
367 } // namespace chromeos