Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / webui / chromeos / provided_file_systems_ui.cc
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.
4
5 #include "chrome/browser/ui/webui/chromeos/provided_file_systems_ui.h"
6
7 #include <string>
8 #include <vector>
9
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"
27
28 using content::BrowserThread;
29
30 namespace chromeos {
31
32 namespace {
33
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";
42
43 const char kKeyName[] = "name";
44 const char kKeyExtensionId[] = "extensionId";
45 const char kKeyMountPath[] = "mountPath";
46 const char kKeyActiveRequests[] = "activeRequests";
47
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";
54
55 const char kFunctionOnRequestEvent[] = "onRequestEvent";
56 const char kFunctionUpdateFileSystems[] = "updateFileSystems";
57 const char kFunctionSelectFileSystem[] = "selectFileSystem";
58
59 // Creates a dictionary holding common fields for the onRequest* events.
60 scoped_ptr<base::DictionaryValue> CreateRequestEvent(const std::string& type,
61                                                      int request_id) {
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());
66   return event.Pass();
67 }
68
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) {
72   {
73     const extensions::api::file_system_provider_internal::
74         UnmountRequestedSuccess::Params* value =
75             response.unmount_success_params();
76     if (value)
77       return value->execution_time;
78   }
79   {
80     const extensions::api::file_system_provider_internal::
81         GetMetadataRequestedSuccess::Params* value =
82             response.get_metadata_success_params();
83     if (value)
84       return value->execution_time;
85   }
86   {
87     const extensions::api::file_system_provider_internal::
88         ReadDirectoryRequestedSuccess::Params* value =
89             response.read_directory_success_params();
90     if (value)
91       return value->execution_time;
92   }
93   {
94     const extensions::api::file_system_provider_internal::
95         ReadFileRequestedSuccess::Params* value =
96             response.read_file_success_params();
97     if (value)
98       return value->execution_time;
99   }
100   {
101     const extensions::api::file_system_provider_internal::
102         OperationRequestedSuccess::Params* value =
103             response.operation_success_params();
104     if (value)
105       return value->execution_time;
106   }
107   {
108     const extensions::api::file_system_provider_internal::
109         OperationRequestedError::Params* value =
110             response.operation_error_params();
111     if (value)
112       return value->execution_time;
113   }
114
115   return 0;
116 }
117
118 // Gets value size in bytes from a RequestValue instance. If not available,
119 // then returns 0.
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();
124   if (value)
125     return value->data.size();
126
127   return 0;
128 }
129
130 // Class to handle messages from chrome://provided-file-systems.
131 class ProvidedFileSystemsWebUIHandler
132     : public content::WebUIMessageHandler,
133       public file_system_provider::RequestManager::Observer {
134  public:
135   ProvidedFileSystemsWebUIHandler() : weak_ptr_factory_(this) {}
136
137   virtual ~ProvidedFileSystemsWebUIHandler();
138
139   // RequestManager::Observer overrides.
140   virtual void OnRequestCreated(
141       int request_id,
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(
146       int request_id,
147       const file_system_provider::RequestValue& result,
148       bool has_more) OVERRIDE;
149   virtual void OnRequestRejected(
150       int request_id,
151       const file_system_provider::RequestValue& result,
152       base::File::Error error) OVERRIDE;
153   virtual void OnRequestTimeouted(int request_id) OVERRIDE;
154
155  private:
156   // content::WebUIMessageHandler overrides.
157   virtual void RegisterMessages() OVERRIDE;
158
159   // Gets a file system provider service for the current profile. If not found,
160   // then NULL.
161   file_system_provider::Service* GetService();
162
163   // Invoked when updating file system list is requested.
164   void UpdateFileSystems(const base::ListValue* args);
165
166   // Invoked when a file system is selected from the list.
167   void SelectFileSystem(const base::ListValue* args);
168
169   std::string selected_extension_id;
170   std::string selected_file_system_id;
171   base::WeakPtrFactory<ProvidedFileSystemsWebUIHandler> weak_ptr_factory_;
172
173   DISALLOW_COPY_AND_ASSIGN(ProvidedFileSystemsWebUIHandler);
174 };
175
176 ProvidedFileSystemsWebUIHandler::~ProvidedFileSystemsWebUIHandler() {
177   // Stop observing the currently selected file system.
178   file_system_provider::Service* const service = GetService();
179   if (!service)
180     return;
181
182   file_system_provider::ProvidedFileSystemInterface* const file_system =
183       service->GetProvidedFileSystem(selected_extension_id,
184                                      selected_file_system_id);
185
186   if (file_system) {
187     file_system_provider::RequestManager* const request_manager =
188         file_system->GetRequestManager();
189     DCHECK(request_manager);
190     request_manager->RemoveObserver(this);
191   }
192 }
193
194 void ProvidedFileSystemsWebUIHandler::OnRequestCreated(
195     int request_id,
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);
202 }
203
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);
208 }
209
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);
214 }
215
216 void ProvidedFileSystemsWebUIHandler::OnRequestFulfilled(
217     int request_id,
218     const file_system_provider::RequestValue& result,
219     bool has_more) {
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);
226 }
227
228 void ProvidedFileSystemsWebUIHandler::OnRequestRejected(
229     int request_id,
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);
238 }
239
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);
244 }
245
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()));
255 }
256
257 file_system_provider::Service* ProvidedFileSystemsWebUIHandler::GetService() {
258   DCHECK_CURRENTLY_ON(BrowserThread::UI);
259
260   Profile* const profile = Profile::FromWebUI(web_ui());
261   return file_system_provider::ServiceFactory::FindExisting(profile);
262 }
263
264 void ProvidedFileSystemsWebUIHandler::UpdateFileSystems(
265     const base::ListValue* args) {
266   DCHECK_CURRENTLY_ON(BrowserThread::UI);
267
268   file_system_provider::Service* const service = GetService();
269   if (!service)
270     return;
271
272   base::ListValue items;
273
274   const std::vector<file_system_provider::ProvidedFileSystemInfo>
275       file_system_info_list = service->GetProvidedFileSystemInfoList();
276
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];
280
281     file_system_provider::ProvidedFileSystemInterface* const file_system =
282         service->GetProvidedFileSystem(file_system_info.extension_id(),
283                                        file_system_info.file_system_id());
284     DCHECK(file_system);
285
286     file_system_provider::RequestManager* const request_manager =
287         file_system->GetRequestManager();
288     DCHECK(request_manager);
289
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->GetActiveRequestsForLogging());
298
299     items.Append(item);
300   }
301
302   web_ui()->CallJavascriptFunction(kFunctionUpdateFileSystems, items);
303 }
304
305 void ProvidedFileSystemsWebUIHandler::SelectFileSystem(
306     const base::ListValue* args) {
307   DCHECK_CURRENTLY_ON(BrowserThread::UI);
308
309   file_system_provider::Service* const service = GetService();
310   if (!service)
311     return;
312
313   std::string extension_id;
314   if (!args->GetString(0, &extension_id))
315     return;
316
317   std::string file_system_id;
318   if (!args->GetString(1, &file_system_id))
319     return;
320
321   // Stop observing the previously selected request manager.
322   {
323     file_system_provider::ProvidedFileSystemInterface* const file_system =
324         service->GetProvidedFileSystem(selected_extension_id,
325                                        selected_file_system_id);
326     if (file_system) {
327       file_system_provider::RequestManager* const request_manager =
328           file_system->GetRequestManager();
329       DCHECK(request_manager);
330       request_manager->RemoveObserver(this);
331     }
332   }
333
334   // Observe the selected file system.
335   file_system_provider::ProvidedFileSystemInterface* const file_system =
336       service->GetProvidedFileSystem(extension_id, file_system_id);
337   if (!file_system)
338     return;
339
340   file_system_provider::RequestManager* const request_manager =
341       file_system->GetRequestManager();
342   DCHECK(request_manager);
343
344   request_manager->AddObserver(this);
345   selected_extension_id = extension_id;
346   selected_file_system_id = file_system_id;
347 }
348
349 }  // namespace
350
351 ProvidedFileSystemsUI::ProvidedFileSystemsUI(content::WebUI* web_ui)
352     : WebUIController(web_ui) {
353   web_ui->AddMessageHandler(new ProvidedFileSystemsWebUIHandler());
354
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);
362
363   Profile* profile = Profile::FromWebUI(web_ui);
364   content::WebUIDataSource::Add(profile, source);
365 }
366
367 }  // namespace chromeos