OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/ui/webui/sync_internals_message_handler.h" | 5 #include "chrome/browser/ui/webui/sync_internals_message_handler.h" |
6 | 6 |
| 7 #include <stdint.h> |
| 8 |
7 #include <utility> | 9 #include <utility> |
8 #include <vector> | 10 #include <vector> |
9 | 11 |
10 #include "base/logging.h" | 12 #include "base/logging.h" |
11 #include "base/memory/ptr_util.h" | 13 #include "base/memory/ptr_util.h" |
12 #include "chrome/browser/profiles/profile.h" | 14 #include "chrome/browser/profiles/profile.h" |
13 #include "chrome/browser/sync/profile_sync_service_factory.h" | 15 #include "chrome/browser/sync/profile_sync_service_factory.h" |
14 #include "chrome/common/channel_info.h" | 16 #include "chrome/common/channel_info.h" |
15 #include "components/browser_sync/profile_sync_service.h" | 17 #include "components/browser_sync/profile_sync_service.h" |
16 #include "components/signin/core/browser/signin_manager_base.h" | |
17 #include "components/sync/base/weak_handle.h" | 18 #include "components/sync/base/weak_handle.h" |
18 #include "components/sync/driver/about_sync_util.h" | 19 #include "components/sync/driver/about_sync_util.h" |
19 #include "components/sync/driver/sync_service.h" | 20 #include "components/sync/driver/sync_service.h" |
20 #include "components/sync/engine/cycle/commit_counters.h" | 21 #include "components/sync/engine/cycle/commit_counters.h" |
21 #include "components/sync/engine/cycle/status_counters.h" | 22 #include "components/sync/engine/cycle/status_counters.h" |
22 #include "components/sync/engine/cycle/update_counters.h" | 23 #include "components/sync/engine/cycle/update_counters.h" |
23 #include "components/sync/engine/events/protocol_event.h" | 24 #include "components/sync/engine/events/protocol_event.h" |
24 #include "components/sync/js/js_event_details.h" | 25 #include "components/sync/js/js_event_details.h" |
25 #include "content/public/browser/browser_thread.h" | 26 #include "content/public/browser/browser_thread.h" |
26 #include "content/public/browser/web_ui.h" | 27 #include "content/public/browser/web_ui.h" |
27 | 28 |
| 29 using base::DictionaryValue; |
| 30 using base::ListValue; |
| 31 using base::Value; |
28 using browser_sync::ProfileSyncService; | 32 using browser_sync::ProfileSyncService; |
29 using syncer::JsEventDetails; | 33 using syncer::JsEventDetails; |
30 using syncer::ModelTypeSet; | 34 using syncer::ModelTypeSet; |
| 35 using syncer::SyncService; |
31 using syncer::WeakHandle; | 36 using syncer::WeakHandle; |
32 | 37 |
33 namespace { | |
34 class UtilAboutSyncDataExtractor : public AboutSyncDataExtractor { | |
35 public: | |
36 std::unique_ptr<base::DictionaryValue> ConstructAboutInformation( | |
37 syncer::SyncService* service, | |
38 SigninManagerBase* signin) override { | |
39 return syncer::sync_ui_util::ConstructAboutInformation( | |
40 service, signin, chrome::GetChannel()); | |
41 } | |
42 }; | |
43 } // namespace | |
44 | |
45 SyncInternalsMessageHandler::SyncInternalsMessageHandler() | 38 SyncInternalsMessageHandler::SyncInternalsMessageHandler() |
46 : SyncInternalsMessageHandler( | 39 : SyncInternalsMessageHandler( |
47 base::MakeUnique<UtilAboutSyncDataExtractor>()) {} | 40 base::BindRepeating( |
| 41 &SyncInternalsMessageHandler::BindForSyncServiceProvider, |
| 42 base::Unretained(this)), |
| 43 base::BindRepeating( |
| 44 &syncer::sync_ui_util::ConstructAboutInformation)) {} |
48 | 45 |
49 SyncInternalsMessageHandler::SyncInternalsMessageHandler( | 46 SyncInternalsMessageHandler::SyncInternalsMessageHandler( |
50 std::unique_ptr<AboutSyncDataExtractor> about_sync_data_extractor) | 47 SyncServiceProvider sync_service_provider, |
51 : about_sync_data_extractor_(std::move(about_sync_data_extractor)), | 48 AboutSyncDataDelegate about_sync_data_delegate) |
| 49 : sync_service_provider_(std::move(sync_service_provider)), |
| 50 about_sync_data_delegate_(std::move(about_sync_data_delegate)), |
52 weak_ptr_factory_(this) {} | 51 weak_ptr_factory_(this) {} |
53 | 52 |
54 SyncInternalsMessageHandler::~SyncInternalsMessageHandler() { | 53 SyncInternalsMessageHandler::~SyncInternalsMessageHandler() { |
55 if (js_controller_) | 54 UnregisterModelNotifications(); |
56 js_controller_->RemoveJsEventHandler(this); | 55 } |
57 | 56 |
58 ProfileSyncService* service = GetProfileSyncService(); | 57 void SyncInternalsMessageHandler::OnJavascriptDisallowed() { |
59 if (service && service->HasObserver(this)) { | 58 // Invaliding weak ptrs works well here because the only weak ptr we vend is |
60 service->RemoveObserver(this); | 59 // to the sync side to give us information that should be used to populate the |
61 service->RemoveProtocolEventObserver(this); | 60 // javascript side. If javascript is disallowed, we don't care about updating |
62 } | 61 // the UI with data, so dropping those callbacks is fine. |
63 | 62 weak_ptr_factory_.InvalidateWeakPtrs(); |
64 if (service && is_registered_for_counters_) { | 63 UnregisterModelNotifications(); |
65 service->RemoveTypeDebugInfoObserver(this); | |
66 } | |
67 } | 64 } |
68 | 65 |
69 void SyncInternalsMessageHandler::RegisterMessages() { | 66 void SyncInternalsMessageHandler::RegisterMessages() { |
70 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 67 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
71 | 68 |
72 web_ui()->RegisterMessageCallback( | 69 web_ui()->RegisterMessageCallback( |
73 syncer::sync_ui_util::kRegisterForEvents, | 70 syncer::sync_ui_util::kRegisterForEvents, |
74 base::Bind(&SyncInternalsMessageHandler::HandleRegisterForEvents, | 71 base::Bind(&SyncInternalsMessageHandler::HandleRegisterForEvents, |
75 base::Unretained(this))); | 72 base::Unretained(this))); |
76 | 73 |
(...skipping 12 matching lines...) Expand all Loading... |
89 base::Bind(&SyncInternalsMessageHandler::HandleRequestListOfTypes, | 86 base::Bind(&SyncInternalsMessageHandler::HandleRequestListOfTypes, |
90 base::Unretained(this))); | 87 base::Unretained(this))); |
91 | 88 |
92 web_ui()->RegisterMessageCallback( | 89 web_ui()->RegisterMessageCallback( |
93 syncer::sync_ui_util::kGetAllNodes, | 90 syncer::sync_ui_util::kGetAllNodes, |
94 base::Bind(&SyncInternalsMessageHandler::HandleGetAllNodes, | 91 base::Bind(&SyncInternalsMessageHandler::HandleGetAllNodes, |
95 base::Unretained(this))); | 92 base::Unretained(this))); |
96 } | 93 } |
97 | 94 |
98 void SyncInternalsMessageHandler::HandleRegisterForEvents( | 95 void SyncInternalsMessageHandler::HandleRegisterForEvents( |
99 const base::ListValue* args) { | 96 const ListValue* args) { |
100 DCHECK(args->empty()); | 97 DCHECK(args->empty()); |
| 98 AllowJavascript(); |
101 | 99 |
102 // is_registered_ flag protects us from double-registering. This could | 100 // is_registered_ flag protects us from double-registering. This could |
103 // happen on a page refresh, where the JavaScript gets re-run but the | 101 // happen on a page refresh, where the JavaScript gets re-run but the |
104 // message handler remains unchanged. | 102 // message handler remains unchanged. |
105 ProfileSyncService* service = GetProfileSyncService(); | 103 SyncService* service = sync_service_provider_.Run(); |
106 if (service && !is_registered_) { | 104 if (service && !is_registered_) { |
107 service->AddObserver(this); | 105 service->AddObserver(this); |
108 service->AddProtocolEventObserver(this); | 106 service->AddProtocolEventObserver(this); |
109 js_controller_ = service->GetJsController(); | 107 js_controller_ = service->GetJsController(); |
110 js_controller_->AddJsEventHandler(this); | 108 js_controller_->AddJsEventHandler(this); |
111 is_registered_ = true; | 109 is_registered_ = true; |
112 } | 110 } |
113 } | 111 } |
114 | 112 |
115 void SyncInternalsMessageHandler::HandleRegisterForPerTypeCounters( | 113 void SyncInternalsMessageHandler::HandleRegisterForPerTypeCounters( |
116 const base::ListValue* args) { | 114 const ListValue* args) { |
117 DCHECK(args->empty()); | 115 DCHECK(args->empty()); |
| 116 AllowJavascript(); |
118 | 117 |
119 if (ProfileSyncService* service = GetProfileSyncService()) { | 118 SyncService* service = sync_service_provider_.Run(); |
120 if (!is_registered_for_counters_) { | 119 if (!service) |
121 service->AddTypeDebugInfoObserver(this); | 120 return; |
122 is_registered_for_counters_ = true; | 121 |
123 } else { | 122 if (!is_registered_for_counters_) { |
124 // Re-register to ensure counters get re-emitted. | 123 service->AddTypeDebugInfoObserver(this); |
125 service->RemoveTypeDebugInfoObserver(this); | 124 is_registered_for_counters_ = true; |
126 service->AddTypeDebugInfoObserver(this); | 125 } else { |
127 } | 126 // Re-register to ensure counters get re-emitted. |
| 127 service->RemoveTypeDebugInfoObserver(this); |
| 128 service->AddTypeDebugInfoObserver(this); |
128 } | 129 } |
129 } | 130 } |
130 | 131 |
131 void SyncInternalsMessageHandler::HandleRequestUpdatedAboutInfo( | 132 void SyncInternalsMessageHandler::HandleRequestUpdatedAboutInfo( |
132 const base::ListValue* args) { | 133 const ListValue* args) { |
133 DCHECK(args->empty()); | 134 DCHECK(args->empty()); |
| 135 AllowJavascript(); |
134 SendAboutInfo(); | 136 SendAboutInfo(); |
135 } | 137 } |
136 | 138 |
137 void SyncInternalsMessageHandler::HandleRequestListOfTypes( | 139 void SyncInternalsMessageHandler::HandleRequestListOfTypes( |
138 const base::ListValue* args) { | 140 const ListValue* args) { |
139 DCHECK(args->empty()); | 141 DCHECK(args->empty()); |
140 base::DictionaryValue event_details; | 142 AllowJavascript(); |
141 std::unique_ptr<base::ListValue> type_list(new base::ListValue()); | 143 |
| 144 DictionaryValue event_details; |
| 145 auto type_list = base::MakeUnique<ListValue>(); |
142 ModelTypeSet protocol_types = syncer::ProtocolTypes(); | 146 ModelTypeSet protocol_types = syncer::ProtocolTypes(); |
143 for (ModelTypeSet::Iterator it = protocol_types.First(); | 147 for (ModelTypeSet::Iterator it = protocol_types.First(); it.Good(); |
144 it.Good(); it.Inc()) { | 148 it.Inc()) { |
145 type_list->AppendString(ModelTypeToString(it.Get())); | 149 type_list->AppendString(ModelTypeToString(it.Get())); |
146 } | 150 } |
147 event_details.Set(syncer::sync_ui_util::kTypes, std::move(type_list)); | 151 event_details.Set(syncer::sync_ui_util::kTypes, std::move(type_list)); |
148 web_ui()->CallJavascriptFunctionUnsafe( | 152 DispatchEvent(syncer::sync_ui_util::kOnReceivedListOfTypes, event_details); |
149 syncer::sync_ui_util::kDispatchEvent, | |
150 base::Value(syncer::sync_ui_util::kOnReceivedListOfTypes), event_details); | |
151 } | 153 } |
152 | 154 |
153 void SyncInternalsMessageHandler::HandleGetAllNodes( | 155 void SyncInternalsMessageHandler::HandleGetAllNodes(const ListValue* args) { |
154 const base::ListValue* args) { | |
155 DCHECK_EQ(1U, args->GetSize()); | 156 DCHECK_EQ(1U, args->GetSize()); |
| 157 AllowJavascript(); |
| 158 |
156 int request_id = 0; | 159 int request_id = 0; |
157 bool success = ExtractIntegerValue(args, &request_id); | 160 bool success = ExtractIntegerValue(args, &request_id); |
158 DCHECK(success); | 161 DCHECK(success); |
159 | 162 |
160 ProfileSyncService* service = GetProfileSyncService(); | 163 SyncService* service = sync_service_provider_.Run(); |
161 if (service) { | 164 if (service) { |
| 165 // This opens up the possibility of non-javascript code calling us |
| 166 // asynchronously, and potentially at times we're not allowed to call into |
| 167 // the javascript side. We guard against this by invalidating this weak ptr |
| 168 // should javascript become disallowed. |
162 service->GetAllNodes( | 169 service->GetAllNodes( |
163 base::Bind(&SyncInternalsMessageHandler::OnReceivedAllNodes, | 170 base::Bind(&SyncInternalsMessageHandler::OnReceivedAllNodes, |
164 weak_ptr_factory_.GetWeakPtr(), request_id)); | 171 weak_ptr_factory_.GetWeakPtr(), request_id)); |
165 } | 172 } |
166 } | 173 } |
167 | 174 |
168 void SyncInternalsMessageHandler::OnReceivedAllNodes( | 175 void SyncInternalsMessageHandler::OnReceivedAllNodes( |
169 int request_id, | 176 int request_id, |
170 std::unique_ptr<base::ListValue> nodes) { | 177 std::unique_ptr<ListValue> nodes) { |
171 base::Value id(request_id); | 178 CallJavascriptFunction(syncer::sync_ui_util::kGetAllNodesCallback, |
172 web_ui()->CallJavascriptFunctionUnsafe( | 179 Value(request_id), *nodes); |
173 syncer::sync_ui_util::kGetAllNodesCallback, id, *nodes); | |
174 } | 180 } |
175 | 181 |
176 void SyncInternalsMessageHandler::OnStateChanged(syncer::SyncService* sync) { | 182 void SyncInternalsMessageHandler::OnStateChanged(SyncService* sync) { |
177 SendAboutInfo(); | 183 SendAboutInfo(); |
178 } | 184 } |
179 | 185 |
180 void SyncInternalsMessageHandler::OnProtocolEvent( | 186 void SyncInternalsMessageHandler::OnProtocolEvent( |
181 const syncer::ProtocolEvent& event) { | 187 const syncer::ProtocolEvent& event) { |
182 std::unique_ptr<base::DictionaryValue> value( | 188 std::unique_ptr<DictionaryValue> value(syncer::ProtocolEvent::ToValue(event)); |
183 syncer::ProtocolEvent::ToValue(event)); | 189 DispatchEvent(syncer::sync_ui_util::kOnProtocolEvent, *value); |
184 web_ui()->CallJavascriptFunctionUnsafe( | |
185 syncer::sync_ui_util::kDispatchEvent, | |
186 base::Value(syncer::sync_ui_util::kOnProtocolEvent), *value); | |
187 } | 190 } |
188 | 191 |
189 void SyncInternalsMessageHandler::OnCommitCountersUpdated( | 192 void SyncInternalsMessageHandler::OnCommitCountersUpdated( |
190 syncer::ModelType type, | 193 syncer::ModelType type, |
191 const syncer::CommitCounters& counters) { | 194 const syncer::CommitCounters& counters) { |
192 EmitCounterUpdate(type, syncer::sync_ui_util::kCommit, counters.ToValue()); | 195 EmitCounterUpdate(type, syncer::sync_ui_util::kCommit, counters.ToValue()); |
193 } | 196 } |
194 | 197 |
195 void SyncInternalsMessageHandler::OnUpdateCountersUpdated( | 198 void SyncInternalsMessageHandler::OnUpdateCountersUpdated( |
196 syncer::ModelType type, | 199 syncer::ModelType type, |
197 const syncer::UpdateCounters& counters) { | 200 const syncer::UpdateCounters& counters) { |
198 EmitCounterUpdate(type, syncer::sync_ui_util::kUpdate, counters.ToValue()); | 201 EmitCounterUpdate(type, syncer::sync_ui_util::kUpdate, counters.ToValue()); |
199 } | 202 } |
200 | 203 |
201 void SyncInternalsMessageHandler::OnStatusCountersUpdated( | 204 void SyncInternalsMessageHandler::OnStatusCountersUpdated( |
202 syncer::ModelType type, | 205 syncer::ModelType type, |
203 const syncer::StatusCounters& counters) { | 206 const syncer::StatusCounters& counters) { |
204 EmitCounterUpdate(type, syncer::sync_ui_util::kStatus, counters.ToValue()); | 207 EmitCounterUpdate(type, syncer::sync_ui_util::kStatus, counters.ToValue()); |
205 } | 208 } |
206 | 209 |
207 void SyncInternalsMessageHandler::EmitCounterUpdate( | 210 void SyncInternalsMessageHandler::EmitCounterUpdate( |
208 syncer::ModelType type, | 211 syncer::ModelType type, |
209 const std::string& counter_type, | 212 const std::string& counter_type, |
210 std::unique_ptr<base::DictionaryValue> value) { | 213 std::unique_ptr<DictionaryValue> value) { |
211 std::unique_ptr<base::DictionaryValue> details(new base::DictionaryValue()); | 214 auto details = base::MakeUnique<DictionaryValue>(); |
212 details->SetString(syncer::sync_ui_util::kModelType, ModelTypeToString(type)); | 215 details->SetString(syncer::sync_ui_util::kModelType, ModelTypeToString(type)); |
213 details->SetString(syncer::sync_ui_util::kCounterType, counter_type); | 216 details->SetString(syncer::sync_ui_util::kCounterType, counter_type); |
214 details->Set(syncer::sync_ui_util::kCounters, std::move(value)); | 217 details->Set(syncer::sync_ui_util::kCounters, std::move(value)); |
215 web_ui()->CallJavascriptFunctionUnsafe( | 218 DispatchEvent(syncer::sync_ui_util::kOnCountersUpdated, *details); |
216 syncer::sync_ui_util::kDispatchEvent, | |
217 base::Value(syncer::sync_ui_util::kOnCountersUpdated), *details); | |
218 } | 219 } |
219 | 220 |
220 void SyncInternalsMessageHandler::HandleJsEvent( | 221 void SyncInternalsMessageHandler::HandleJsEvent( |
221 const std::string& name, | 222 const std::string& name, |
222 const JsEventDetails& details) { | 223 const JsEventDetails& details) { |
223 DVLOG(1) << "Handling event: " << name | 224 DVLOG(1) << "Handling event: " << name |
224 << " with details " << details.ToString(); | 225 << " with details " << details.ToString(); |
225 web_ui()->CallJavascriptFunctionUnsafe(syncer::sync_ui_util::kDispatchEvent, | 226 DispatchEvent(name, details.Get()); |
226 base::Value(name), details.Get()); | |
227 } | 227 } |
228 | 228 |
229 void SyncInternalsMessageHandler::SendAboutInfo() { | 229 void SyncInternalsMessageHandler::SendAboutInfo() { |
230 ProfileSyncService* sync_service = GetProfileSyncService(); | 230 std::unique_ptr<DictionaryValue> value = about_sync_data_delegate_.Run( |
231 SigninManagerBase* signin = sync_service ? sync_service->signin() : nullptr; | 231 sync_service_provider_.Run(), chrome::GetChannel()); |
232 std::unique_ptr<base::DictionaryValue> value = | 232 DispatchEvent(syncer::sync_ui_util::kOnAboutInfoUpdated, *value); |
233 about_sync_data_extractor_->ConstructAboutInformation(sync_service, | |
234 signin); | |
235 web_ui()->CallJavascriptFunctionUnsafe( | |
236 syncer::sync_ui_util::kDispatchEvent, | |
237 base::Value(syncer::sync_ui_util::kOnAboutInfoUpdated), *value); | |
238 } | 233 } |
239 | 234 |
240 // Gets the ProfileSyncService of the underlying original profile. | 235 SyncService* SyncInternalsMessageHandler::BindForSyncServiceProvider() { |
241 // May return NULL (e.g., if sync is disabled on the command line). | |
242 ProfileSyncService* SyncInternalsMessageHandler::GetProfileSyncService() { | |
243 Profile* profile = Profile::FromWebUI(web_ui()); | |
244 return ProfileSyncServiceFactory::GetForProfile( | 236 return ProfileSyncServiceFactory::GetForProfile( |
245 profile->GetOriginalProfile()); | 237 Profile::FromWebUI(web_ui())->GetOriginalProfile()); |
246 } | 238 } |
| 239 |
| 240 void SyncInternalsMessageHandler::DispatchEvent(const std::string& name, |
| 241 const Value& details_value) { |
| 242 CallJavascriptFunction(syncer::sync_ui_util::kDispatchEvent, Value(name), |
| 243 details_value); |
| 244 } |
| 245 |
| 246 void SyncInternalsMessageHandler::UnregisterModelNotifications() { |
| 247 SyncService* service = sync_service_provider_.Run(); |
| 248 if (!service) |
| 249 return; |
| 250 |
| 251 // Cannot use ScopedObserver to do all the tracking because most don't follow |
| 252 // AddObserver/RemoveObserver method naming style. |
| 253 if (is_registered_) { |
| 254 DCHECK(js_controller_); |
| 255 service->RemoveObserver(this); |
| 256 service->RemoveProtocolEventObserver(this); |
| 257 js_controller_->RemoveJsEventHandler(this); |
| 258 js_controller_ = nullptr; |
| 259 is_registered_ = false; |
| 260 } |
| 261 |
| 262 if (is_registered_for_counters_) { |
| 263 service->RemoveTypeDebugInfoObserver(this); |
| 264 is_registered_for_counters_ = false; |
| 265 } |
| 266 } |
OLD | NEW |