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. 4 5#include "chrome/browser/ui/webui/sync_file_system_internals/sync_file_system_internals_handler.h" 6 7#include <vector> 8 9#include "base/bind.h" 10#include "base/bind_helpers.h" 11#include "base/values.h" 12#include "chrome/browser/drive/drive_notification_manager.h" 13#include "chrome/browser/drive/drive_notification_manager_factory.h" 14#include "chrome/browser/extensions/api/sync_file_system/sync_file_system_api_helpers.h" 15#include "chrome/browser/profiles/profile.h" 16#include "chrome/browser/sync_file_system/logger.h" 17#include "chrome/browser/sync_file_system/sync_file_system_service.h" 18#include "chrome/browser/sync_file_system/sync_file_system_service_factory.h" 19#include "chrome/browser/sync_file_system/sync_service_state.h" 20#include "chrome/common/extensions/api/sync_file_system.h" 21#include "content/public/browser/storage_partition.h" 22#include "content/public/browser/web_ui.h" 23#include "google_apis/drive/time_util.h" 24 25using drive::EventLogger; 26using sync_file_system::SyncFileSystemServiceFactory; 27using sync_file_system::SyncServiceState; 28 29namespace syncfs_internals { 30 31SyncFileSystemInternalsHandler::SyncFileSystemInternalsHandler(Profile* profile) 32 : profile_(profile), 33 observing_task_log_(false) { 34 sync_file_system::SyncFileSystemService* sync_service = 35 SyncFileSystemServiceFactory::GetForProfile(profile); 36 if (sync_service) 37 sync_service->AddSyncEventObserver(this); 38} 39 40SyncFileSystemInternalsHandler::~SyncFileSystemInternalsHandler() { 41 sync_file_system::SyncFileSystemService* sync_service = 42 SyncFileSystemServiceFactory::GetForProfile(profile_); 43 if (!sync_service) 44 return; 45 sync_service->RemoveSyncEventObserver(this); 46 if (observing_task_log_) 47 sync_service->task_logger()->RemoveObserver(this); 48} 49 50void SyncFileSystemInternalsHandler::RegisterMessages() { 51 web_ui()->RegisterMessageCallback( 52 "getServiceStatus", 53 base::Bind(&SyncFileSystemInternalsHandler::GetServiceStatus, 54 base::Unretained(this))); 55 web_ui()->RegisterMessageCallback( 56 "getLog", 57 base::Bind(&SyncFileSystemInternalsHandler::GetLog, 58 base::Unretained(this))); 59 web_ui()->RegisterMessageCallback( 60 "clearLogs", 61 base::Bind(&SyncFileSystemInternalsHandler::ClearLogs, 62 base::Unretained(this))); 63 web_ui()->RegisterMessageCallback( 64 "getNotificationSource", 65 base::Bind(&SyncFileSystemInternalsHandler::GetNotificationSource, 66 base::Unretained(this))); 67 web_ui()->RegisterMessageCallback( 68 "observeTaskLog", 69 base::Bind(&SyncFileSystemInternalsHandler::ObserveTaskLog, 70 base::Unretained(this))); 71} 72 73void SyncFileSystemInternalsHandler::OnSyncStateUpdated( 74 const GURL& app_origin, 75 sync_file_system::SyncServiceState state, 76 const std::string& description) { 77 std::string state_string = extensions::api::sync_file_system::ToString( 78 extensions::SyncServiceStateToExtensionEnum(state)); 79 if (!description.empty()) 80 state_string += " (" + description + ")"; 81 82 // TODO(calvinlo): OnSyncStateUpdated should be updated to also provide the 83 // notification mechanism (XMPP or Polling). 84 web_ui()->CallJavascriptFunction("SyncService.onGetServiceStatus", 85 base::StringValue(state_string)); 86} 87 88void SyncFileSystemInternalsHandler::OnFileSynced( 89 const storage::FileSystemURL& url, 90 sync_file_system::SyncFileStatus status, 91 sync_file_system::SyncAction action, 92 sync_file_system::SyncDirection direction) { 93} 94 95void SyncFileSystemInternalsHandler::OnLogRecorded( 96 const sync_file_system::TaskLogger::TaskLog& task_log) { 97 base::DictionaryValue dict; 98 int64 duration = (task_log.end_time - task_log.start_time).InMilliseconds(); 99 dict.SetInteger("duration", duration); 100 dict.SetString("task_description", task_log.task_description); 101 dict.SetString("result_description", task_log.result_description); 102 103 scoped_ptr<base::ListValue> details(new base::ListValue); 104 details->AppendStrings(task_log.details); 105 dict.Set("details", details.release()); 106 web_ui()->CallJavascriptFunction("TaskLog.onTaskLogRecorded", dict); 107} 108 109void SyncFileSystemInternalsHandler::GetServiceStatus( 110 const base::ListValue* args) { 111 SyncServiceState state_enum = sync_file_system::SYNC_SERVICE_DISABLED; 112 sync_file_system::SyncFileSystemService* sync_service = 113 SyncFileSystemServiceFactory::GetForProfile(profile_); 114 if (sync_service) 115 state_enum = sync_service->GetSyncServiceState(); 116 const std::string state_string = extensions::api::sync_file_system::ToString( 117 extensions::SyncServiceStateToExtensionEnum(state_enum)); 118 web_ui()->CallJavascriptFunction("SyncService.onGetServiceStatus", 119 base::StringValue(state_string)); 120} 121 122void SyncFileSystemInternalsHandler::GetNotificationSource( 123 const base::ListValue* args) { 124 drive::DriveNotificationManager* drive_notification_manager = 125 drive::DriveNotificationManagerFactory::FindForBrowserContext(profile_); 126 if (!drive_notification_manager) 127 return; 128 bool xmpp_enabled = drive_notification_manager->push_notification_enabled(); 129 std::string notification_source = xmpp_enabled ? "XMPP" : "Polling"; 130 web_ui()->CallJavascriptFunction("SyncService.onGetNotificationSource", 131 base::StringValue(notification_source)); 132} 133 134void SyncFileSystemInternalsHandler::GetLog( 135 const base::ListValue* args) { 136 const std::vector<EventLogger::Event> log = 137 sync_file_system::util::GetLogHistory(); 138 139 int last_log_id_sent; 140 if (!args->GetInteger(0, &last_log_id_sent)) 141 last_log_id_sent = -1; 142 143 // Collate events which haven't been sent to WebUI yet. 144 base::ListValue list; 145 for (std::vector<EventLogger::Event>::const_iterator log_entry = log.begin(); 146 log_entry != log.end(); 147 ++log_entry) { 148 if (log_entry->id <= last_log_id_sent) 149 continue; 150 151 base::DictionaryValue* dict = new base::DictionaryValue; 152 dict->SetInteger("id", log_entry->id); 153 dict->SetString("time", 154 google_apis::util::FormatTimeAsStringLocaltime(log_entry->when)); 155 dict->SetString("logEvent", log_entry->what); 156 list.Append(dict); 157 last_log_id_sent = log_entry->id; 158 } 159 if (list.empty()) 160 return; 161 162 web_ui()->CallJavascriptFunction("SyncService.onGetLog", list); 163} 164 165void SyncFileSystemInternalsHandler::ClearLogs(const base::ListValue* args) { 166 sync_file_system::util::ClearLog(); 167} 168 169void SyncFileSystemInternalsHandler::ObserveTaskLog( 170 const base::ListValue* args) { 171 sync_file_system::SyncFileSystemService* sync_service = 172 SyncFileSystemServiceFactory::GetForProfile(profile_); 173 if (!sync_service) 174 return; 175 if (!observing_task_log_) { 176 observing_task_log_ = true; 177 sync_service->task_logger()->AddObserver(this); 178 } 179 180 DCHECK(sync_service->task_logger()); 181 const sync_file_system::TaskLogger::LogList& log = 182 sync_service->task_logger()->GetLog(); 183 184 for (sync_file_system::TaskLogger::LogList::const_iterator itr = log.begin(); 185 itr != log.end(); ++itr) 186 OnLogRecorded(**itr); 187} 188 189} // namespace syncfs_internals 190