Home | History | Annotate | Download | only in chromeos
      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 
     41 const char kKeyName[] = "name";
     42 const char kKeyExtensionId[] = "extensionId";
     43 const char kKeyMountPath[] = "mountPath";
     44 const char kKeyActiveRequests[] = "activeRequests";
     45 
     46 const char kRequestCreated[] = "created";
     47 const char kRequestDestroyed[] = "destroyed";
     48 const char kRequestExecuted[] = "executed";
     49 const char kRequestFulfilled[] = "fulfilled";
     50 const char kRequestRejected[] = "rejected";
     51 const char kRequestTimeouted[] = "timeouted";
     52 
     53 const char kFunctionOnRequestEvent[] = "onRequestEvent";
     54 const char kFunctionUpdateFileSystems[] = "updateFileSystems";
     55 const char kFunctionSelectFileSystem[] = "selectFileSystem";
     56 
     57 // Creates a dictionary holding common fields for the onRequest* events.
     58 scoped_ptr<base::DictionaryValue> CreateRequestEvent(const std::string& type,
     59                                                      int request_id) {
     60   scoped_ptr<base::DictionaryValue> event(new base::DictionaryValue);
     61   event->SetInteger(kKeyId, request_id);
     62   event->SetString(kKeyEventType, type);
     63   event->SetDouble(kKeyTime, base::Time::Now().ToJsTime());
     64   return event.Pass();
     65 }
     66 
     67 // Class to handle messages from chrome://provided-file-systems.
     68 class ProvidedFileSystemsWebUIHandler
     69     : public content::WebUIMessageHandler,
     70       public file_system_provider::RequestManager::Observer {
     71  public:
     72   ProvidedFileSystemsWebUIHandler() : weak_ptr_factory_(this) {}
     73 
     74   virtual ~ProvidedFileSystemsWebUIHandler();
     75 
     76   // RequestManager::Observer overrides.
     77   virtual void OnRequestCreated(
     78       int request_id,
     79       file_system_provider::RequestType type) OVERRIDE;
     80   virtual void OnRequestDestroyed(int request_id) OVERRIDE;
     81   virtual void OnRequestExecuted(int request_id) OVERRIDE;
     82   virtual void OnRequestFulfilled(int request_id, bool has_more) OVERRIDE;
     83   virtual void OnRequestRejected(int request_id,
     84                                  base::File::Error error) OVERRIDE;
     85   virtual void OnRequestTimeouted(int request_id) OVERRIDE;
     86 
     87  private:
     88   // content::WebUIMessageHandler overrides.
     89   virtual void RegisterMessages() OVERRIDE;
     90 
     91   // Gets a file system provider service for the current profile. If not found,
     92   // then NULL.
     93   file_system_provider::Service* GetService();
     94 
     95   // Invoked when updating file system list is requested.
     96   void UpdateFileSystems(const base::ListValue* args);
     97 
     98   // Invoked when a file system is selected from the list.
     99   void SelectFileSystem(const base::ListValue* args);
    100 
    101   std::string selected_extension_id;
    102   std::string selected_file_system_id;
    103   base::WeakPtrFactory<ProvidedFileSystemsWebUIHandler> weak_ptr_factory_;
    104 
    105   DISALLOW_COPY_AND_ASSIGN(ProvidedFileSystemsWebUIHandler);
    106 };
    107 
    108 ProvidedFileSystemsWebUIHandler::~ProvidedFileSystemsWebUIHandler() {
    109   // Stop observing the currently selected file system.
    110   file_system_provider::Service* const service = GetService();
    111   if (!service)
    112     return;
    113 
    114   file_system_provider::ProvidedFileSystemInterface* const file_system =
    115       service->GetProvidedFileSystem(selected_extension_id,
    116                                      selected_file_system_id);
    117 
    118   if (file_system) {
    119     file_system_provider::RequestManager* const request_manager =
    120         file_system->GetRequestManager();
    121     DCHECK(request_manager);
    122     request_manager->RemoveObserver(this);
    123   }
    124 }
    125 
    126 void ProvidedFileSystemsWebUIHandler::OnRequestCreated(
    127     int request_id,
    128     file_system_provider::RequestType type) {
    129   scoped_ptr<base::DictionaryValue> const event =
    130       CreateRequestEvent(kRequestCreated, request_id);
    131   event->SetString(kKeyRequestType,
    132                    file_system_provider::RequestTypeToString(type));
    133   web_ui()->CallJavascriptFunction(kFunctionOnRequestEvent, *event);
    134 }
    135 
    136 void ProvidedFileSystemsWebUIHandler::OnRequestDestroyed(int request_id) {
    137   scoped_ptr<base::DictionaryValue> const event =
    138       CreateRequestEvent(kRequestDestroyed, request_id);
    139   web_ui()->CallJavascriptFunction(kFunctionOnRequestEvent, *event);
    140 }
    141 
    142 void ProvidedFileSystemsWebUIHandler::OnRequestExecuted(int request_id) {
    143   scoped_ptr<base::DictionaryValue> const event =
    144       CreateRequestEvent(kRequestExecuted, request_id);
    145   web_ui()->CallJavascriptFunction(kFunctionOnRequestEvent, *event);
    146 }
    147 
    148 void ProvidedFileSystemsWebUIHandler::OnRequestFulfilled(int request_id,
    149                                                          bool has_more) {
    150   scoped_ptr<base::DictionaryValue> const event =
    151       CreateRequestEvent(kRequestFulfilled, request_id);
    152   event->SetBoolean(kKeyHasMore, has_more);
    153   web_ui()->CallJavascriptFunction(kFunctionOnRequestEvent, *event);
    154 }
    155 
    156 void ProvidedFileSystemsWebUIHandler::OnRequestRejected(
    157     int request_id,
    158     base::File::Error error) {
    159   scoped_ptr<base::DictionaryValue> const event =
    160       CreateRequestEvent(kRequestRejected, request_id);
    161   event->SetString(kKeyError, base::File::ErrorToString(error));
    162   web_ui()->CallJavascriptFunction(kFunctionOnRequestEvent, *event);
    163 }
    164 
    165 void ProvidedFileSystemsWebUIHandler::OnRequestTimeouted(int request_id) {
    166   scoped_ptr<base::DictionaryValue> const event =
    167       CreateRequestEvent(kRequestTimeouted, request_id);
    168   web_ui()->CallJavascriptFunction(kFunctionOnRequestEvent, *event);
    169 }
    170 
    171 void ProvidedFileSystemsWebUIHandler::RegisterMessages() {
    172   web_ui()->RegisterMessageCallback(
    173       kFunctionUpdateFileSystems,
    174       base::Bind(&ProvidedFileSystemsWebUIHandler::UpdateFileSystems,
    175                  weak_ptr_factory_.GetWeakPtr()));
    176   web_ui()->RegisterMessageCallback(
    177       kFunctionSelectFileSystem,
    178       base::Bind(&ProvidedFileSystemsWebUIHandler::SelectFileSystem,
    179                  weak_ptr_factory_.GetWeakPtr()));
    180 }
    181 
    182 file_system_provider::Service* ProvidedFileSystemsWebUIHandler::GetService() {
    183   DCHECK_CURRENTLY_ON(BrowserThread::UI);
    184 
    185   Profile* const profile = Profile::FromWebUI(web_ui());
    186   return file_system_provider::ServiceFactory::FindExisting(profile);
    187 }
    188 
    189 void ProvidedFileSystemsWebUIHandler::UpdateFileSystems(
    190     const base::ListValue* args) {
    191   DCHECK_CURRENTLY_ON(BrowserThread::UI);
    192 
    193   file_system_provider::Service* const service = GetService();
    194   if (!service)
    195     return;
    196 
    197   base::ListValue items;
    198 
    199   const std::vector<file_system_provider::ProvidedFileSystemInfo>
    200       file_system_info_list = service->GetProvidedFileSystemInfoList();
    201 
    202   for (size_t i = 0; i < file_system_info_list.size(); ++i) {
    203     const file_system_provider::ProvidedFileSystemInfo file_system_info =
    204         file_system_info_list[i];
    205 
    206     file_system_provider::ProvidedFileSystemInterface* const file_system =
    207         service->GetProvidedFileSystem(file_system_info.extension_id(),
    208                                        file_system_info.file_system_id());
    209     DCHECK(file_system);
    210 
    211     file_system_provider::RequestManager* const request_manager =
    212         file_system->GetRequestManager();
    213     DCHECK(request_manager);
    214 
    215     base::DictionaryValue* item = new base::DictionaryValue();
    216     item->SetString(kKeyId, file_system_info.file_system_id());
    217     item->SetString(kKeyName, file_system_info.file_system_name());
    218     item->SetString(kKeyExtensionId, file_system_info.extension_id());
    219     item->SetString(kKeyMountPath,
    220                     file_system_info.mount_path().AsUTF8Unsafe());
    221     item->SetInteger(kKeyActiveRequests,
    222                      request_manager->GetActiveRequestsForLogging());
    223 
    224     items.Append(item);
    225   }
    226 
    227   web_ui()->CallJavascriptFunction(kFunctionUpdateFileSystems, items);
    228 }
    229 
    230 void ProvidedFileSystemsWebUIHandler::SelectFileSystem(
    231     const base::ListValue* args) {
    232   DCHECK_CURRENTLY_ON(BrowserThread::UI);
    233 
    234   file_system_provider::Service* const service = GetService();
    235   if (!service)
    236     return;
    237 
    238   std::string extension_id;
    239   if (!args->GetString(0, &extension_id))
    240     return;
    241 
    242   std::string file_system_id;
    243   if (!args->GetString(1, &file_system_id))
    244     return;
    245 
    246   // Stop observing the previously selected request manager.
    247   {
    248     file_system_provider::ProvidedFileSystemInterface* const file_system =
    249         service->GetProvidedFileSystem(selected_extension_id,
    250                                        selected_file_system_id);
    251     if (file_system) {
    252       file_system_provider::RequestManager* const request_manager =
    253           file_system->GetRequestManager();
    254       DCHECK(request_manager);
    255       request_manager->RemoveObserver(this);
    256     }
    257   }
    258 
    259   // Observe the selected file system.
    260   file_system_provider::ProvidedFileSystemInterface* const file_system =
    261       service->GetProvidedFileSystem(extension_id, file_system_id);
    262   if (!file_system)
    263     return;
    264 
    265   file_system_provider::RequestManager* const request_manager =
    266       file_system->GetRequestManager();
    267   DCHECK(request_manager);
    268 
    269   request_manager->AddObserver(this);
    270   selected_extension_id = extension_id;
    271   selected_file_system_id = file_system_id;
    272 }
    273 
    274 }  // namespace
    275 
    276 ProvidedFileSystemsUI::ProvidedFileSystemsUI(content::WebUI* web_ui)
    277     : WebUIController(web_ui) {
    278   web_ui->AddMessageHandler(new ProvidedFileSystemsWebUIHandler());
    279 
    280   content::WebUIDataSource* source = content::WebUIDataSource::Create(
    281       chrome::kChromeUIProvidedFileSystemsHost);
    282   source->AddResourcePath("provided_file_systems.css",
    283                           IDR_PROVIDED_FILE_SYSTEMS_CSS);
    284   source->AddResourcePath("provided_file_systems.js",
    285                           IDR_PROVIDED_FILE_SYSTEMS_JS);
    286   source->SetDefaultResource(IDR_PROVIDED_FILE_SYSTEMS_HTML);
    287 
    288   Profile* profile = Profile::FromWebUI(web_ui);
    289   content::WebUIDataSource::Add(profile, source);
    290 }
    291 
    292 }  // namespace chromeos
    293