Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(448)

Side by Side Diff: chrome/browser/ui/webui/sync_internals_message_handler.cc

Issue 2898723003: [Sync] Migrate SyncInternalsMessageHandler off CallJavascriptFunctionUnsafe. (Closed)
Patch Set: More updates for dbeam. Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698