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
25 using drive::EventLogger;
26 using sync_file_system::SyncFileSystemServiceFactory;
27 using sync_file_system::SyncServiceState;
28
29 namespace syncfs_internals {
30
SyncFileSystemInternalsHandler(Profile * profile)31 SyncFileSystemInternalsHandler::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
~SyncFileSystemInternalsHandler()40 SyncFileSystemInternalsHandler::~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
RegisterMessages()50 void 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
OnSyncStateUpdated(const GURL & app_origin,sync_file_system::SyncServiceState state,const std::string & description)73 void 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
OnFileSynced(const fileapi::FileSystemURL & url,sync_file_system::SyncFileStatus status,sync_file_system::SyncAction action,sync_file_system::SyncDirection direction)88 void SyncFileSystemInternalsHandler::OnFileSynced(
89 const fileapi::FileSystemURL& url,
90 sync_file_system::SyncFileStatus status,
91 sync_file_system::SyncAction action,
92 sync_file_system::SyncDirection direction) {}
93
OnLogRecorded(const sync_file_system::TaskLogger::TaskLog & task_log)94 void SyncFileSystemInternalsHandler::OnLogRecorded(
95 const sync_file_system::TaskLogger::TaskLog& task_log) {
96 base::DictionaryValue dict;
97 int64 duration = (task_log.end_time - task_log.start_time).InMilliseconds();
98 dict.SetInteger("duration", duration);
99 dict.SetString("task_description", task_log.task_description);
100 dict.SetString("result_description", task_log.result_description);
101
102 scoped_ptr<base::ListValue> details(new base::ListValue);
103 details->AppendStrings(task_log.details);
104 dict.Set("details", details.release());
105 web_ui()->CallJavascriptFunction("TaskLog.onTaskLogRecorded", dict);
106 }
107
GetServiceStatus(const base::ListValue * args)108 void SyncFileSystemInternalsHandler::GetServiceStatus(
109 const base::ListValue* args) {
110 SyncServiceState state_enum = sync_file_system::SYNC_SERVICE_DISABLED;
111 sync_file_system::SyncFileSystemService* sync_service =
112 SyncFileSystemServiceFactory::GetForProfile(profile_);
113 if (sync_service)
114 state_enum = sync_service->GetSyncServiceState();
115 const std::string state_string = extensions::api::sync_file_system::ToString(
116 extensions::SyncServiceStateToExtensionEnum(state_enum));
117 web_ui()->CallJavascriptFunction("SyncService.onGetServiceStatus",
118 base::StringValue(state_string));
119 }
120
GetNotificationSource(const base::ListValue * args)121 void SyncFileSystemInternalsHandler::GetNotificationSource(
122 const base::ListValue* args) {
123 drive::DriveNotificationManager* drive_notification_manager =
124 drive::DriveNotificationManagerFactory::FindForBrowserContext(profile_);
125 if (!drive_notification_manager)
126 return;
127 bool xmpp_enabled = drive_notification_manager->push_notification_enabled();
128 std::string notification_source = xmpp_enabled ? "XMPP" : "Polling";
129 web_ui()->CallJavascriptFunction("SyncService.onGetNotificationSource",
130 base::StringValue(notification_source));
131 }
132
GetLog(const base::ListValue * args)133 void SyncFileSystemInternalsHandler::GetLog(
134 const base::ListValue* args) {
135 const std::vector<EventLogger::Event> log =
136 sync_file_system::util::GetLogHistory();
137
138 int last_log_id_sent;
139 if (!args->GetInteger(0, &last_log_id_sent))
140 last_log_id_sent = -1;
141
142 // Collate events which haven't been sent to WebUI yet.
143 base::ListValue list;
144 for (std::vector<EventLogger::Event>::const_iterator log_entry = log.begin();
145 log_entry != log.end();
146 ++log_entry) {
147 if (log_entry->id <= last_log_id_sent)
148 continue;
149
150 base::DictionaryValue* dict = new base::DictionaryValue;
151 dict->SetInteger("id", log_entry->id);
152 dict->SetString("time",
153 google_apis::util::FormatTimeAsStringLocaltime(log_entry->when));
154 dict->SetString("logEvent", log_entry->what);
155 list.Append(dict);
156 last_log_id_sent = log_entry->id;
157 }
158 if (list.empty())
159 return;
160
161 web_ui()->CallJavascriptFunction("SyncService.onGetLog", list);
162 }
163
ClearLogs(const base::ListValue * args)164 void SyncFileSystemInternalsHandler::ClearLogs(const base::ListValue* args) {
165 sync_file_system::util::ClearLog();
166 }
167
ObserveTaskLog(const base::ListValue * args)168 void SyncFileSystemInternalsHandler::ObserveTaskLog(
169 const base::ListValue* args) {
170 sync_file_system::SyncFileSystemService* sync_service =
171 SyncFileSystemServiceFactory::GetForProfile(profile_);
172 if (!sync_service)
173 return;
174 if (!observing_task_log_) {
175 observing_task_log_ = true;
176 sync_service->task_logger()->AddObserver(this);
177 }
178
179 DCHECK(sync_service->task_logger());
180 const sync_file_system::TaskLogger::LogList& log =
181 sync_service->task_logger()->GetLog();
182
183 for (sync_file_system::TaskLogger::LogList::const_iterator itr = log.begin();
184 itr != log.end(); ++itr)
185 OnLogRecorded(**itr);
186 }
187
188 } // namespace syncfs_internals
189