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

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

Issue 2872023002: [Sync] Add a simple UI to sync-internals to create UserEvents. (Closed)
Patch Set: Fixed unittests. 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
12 #include "base/feature_list.h"
10 #include "base/logging.h" 13 #include "base/logging.h"
11 #include "base/memory/ptr_util.h" 14 #include "base/memory/ptr_util.h"
15 #include "base/strings/string_number_conversions.h"
12 #include "chrome/browser/profiles/profile.h" 16 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/browser/sync/profile_sync_service_factory.h" 17 #include "chrome/browser/sync/profile_sync_service_factory.h"
18 #include "chrome/browser/sync/user_event_service_factory.h"
14 #include "chrome/common/channel_info.h" 19 #include "chrome/common/channel_info.h"
15 #include "components/browser_sync/profile_sync_service.h" 20 #include "components/browser_sync/profile_sync_service.h"
16 #include "components/signin/core/browser/signin_manager_base.h" 21 #include "components/signin/core/browser/signin_manager_base.h"
17 #include "components/sync/base/weak_handle.h" 22 #include "components/sync/base/weak_handle.h"
18 #include "components/sync/driver/about_sync_util.h" 23 #include "components/sync/driver/about_sync_util.h"
24 #include "components/sync/driver/sync_driver_switches.h"
19 #include "components/sync/driver/sync_service.h" 25 #include "components/sync/driver/sync_service.h"
20 #include "components/sync/engine/cycle/commit_counters.h" 26 #include "components/sync/engine/cycle/commit_counters.h"
21 #include "components/sync/engine/cycle/status_counters.h" 27 #include "components/sync/engine/cycle/status_counters.h"
22 #include "components/sync/engine/cycle/update_counters.h" 28 #include "components/sync/engine/cycle/update_counters.h"
23 #include "components/sync/engine/events/protocol_event.h" 29 #include "components/sync/engine/events/protocol_event.h"
24 #include "components/sync/js/js_event_details.h" 30 #include "components/sync/js/js_event_details.h"
31 #include "components/sync/protocol/sync.pb.h"
32 #include "components/sync/user_events/user_event_service.h"
25 #include "content/public/browser/browser_thread.h" 33 #include "content/public/browser/browser_thread.h"
26 #include "content/public/browser/web_ui.h" 34 #include "content/public/browser/web_ui.h"
27 35
36 using base::Value;
28 using browser_sync::ProfileSyncService; 37 using browser_sync::ProfileSyncService;
29 using syncer::JsEventDetails; 38 using syncer::JsEventDetails;
30 using syncer::ModelTypeSet; 39 using syncer::ModelTypeSet;
31 using syncer::WeakHandle; 40 using syncer::WeakHandle;
32 41
33 namespace { 42 namespace {
43
44 // Converts the string at |index| in |list| to an int, defaulting to 0 on error.
45 int64_t StringAtIndexToInt64(const base::ListValue* list, int index) {
46 std::string str;
47 if (list->GetString(index, &str)) {
48 int64_t integer = 0;
49 if (base::StringToInt64(str, &integer)) {
50 return integer;
51 }
Dan Beam 2017/05/16 22:40:54 no curlies
skym 2017/05/22 21:55:48 How strongly do you feel about this? It seems that
52 }
53 return 0;
54 }
55
34 class UtilAboutSyncDataExtractor : public AboutSyncDataExtractor { 56 class UtilAboutSyncDataExtractor : public AboutSyncDataExtractor {
35 public: 57 public:
36 std::unique_ptr<base::DictionaryValue> ConstructAboutInformation( 58 std::unique_ptr<base::DictionaryValue> ConstructAboutInformation(
37 syncer::SyncService* service, 59 syncer::SyncService* service,
38 SigninManagerBase* signin) override { 60 SigninManagerBase* signin) override {
39 return syncer::sync_ui_util::ConstructAboutInformation( 61 return syncer::sync_ui_util::ConstructAboutInformation(
40 service, signin, chrome::GetChannel()); 62 service, signin, chrome::GetChannel());
41 } 63 }
42 }; 64 };
65
43 } // namespace 66 } // namespace
44 67
45 SyncInternalsMessageHandler::SyncInternalsMessageHandler() 68 SyncInternalsMessageHandler::SyncInternalsMessageHandler()
46 : SyncInternalsMessageHandler( 69 : SyncInternalsMessageHandler(
47 base::MakeUnique<UtilAboutSyncDataExtractor>()) {} 70 base::MakeUnique<UtilAboutSyncDataExtractor>()) {}
48 71
49 SyncInternalsMessageHandler::SyncInternalsMessageHandler( 72 SyncInternalsMessageHandler::SyncInternalsMessageHandler(
50 std::unique_ptr<AboutSyncDataExtractor> about_sync_data_extractor) 73 std::unique_ptr<AboutSyncDataExtractor> about_sync_data_extractor)
51 : about_sync_data_extractor_(std::move(about_sync_data_extractor)), 74 : about_sync_data_extractor_(std::move(about_sync_data_extractor)),
52 weak_ptr_factory_(this) {} 75 weak_ptr_factory_(this) {}
53 76
54 SyncInternalsMessageHandler::~SyncInternalsMessageHandler() { 77 SyncInternalsMessageHandler::~SyncInternalsMessageHandler() {
55 if (js_controller_) 78 if (js_controller_)
56 js_controller_->RemoveJsEventHandler(this); 79 js_controller_->RemoveJsEventHandler(this);
57 80
58 ProfileSyncService* service = GetProfileSyncService(); 81 ProfileSyncService* service = GetProfileSyncService();
59 if (service && service->HasObserver(this)) { 82 if (service && service->HasObserver(this)) {
60 service->RemoveObserver(this); 83 service->RemoveObserver(this);
61 service->RemoveProtocolEventObserver(this); 84 service->RemoveProtocolEventObserver(this);
62 } 85 }
63 86
64 if (service && is_registered_for_counters_) { 87 if (service && is_registered_for_counters_) {
65 service->RemoveTypeDebugInfoObserver(this); 88 service->RemoveTypeDebugInfoObserver(this);
66 } 89 }
Dan Beam 2017/05/16 22:40:54 you probably want to put this in a OnJavascriptDis
skym 2017/05/22 21:55:48 Done in https://codereview.chromium.org/2898723003
67 } 90 }
68 91
69 void SyncInternalsMessageHandler::RegisterMessages() { 92 void SyncInternalsMessageHandler::RegisterMessages() {
70 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 93 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
71 94
72 web_ui()->RegisterMessageCallback( 95 web_ui()->RegisterMessageCallback(
73 syncer::sync_ui_util::kRegisterForEvents, 96 syncer::sync_ui_util::kRegisterForEvents,
74 base::Bind(&SyncInternalsMessageHandler::HandleRegisterForEvents, 97 base::Bind(&SyncInternalsMessageHandler::HandleRegisterForEvents,
75 base::Unretained(this))); 98 base::Unretained(this)));
76 99
77 web_ui()->RegisterMessageCallback( 100 web_ui()->RegisterMessageCallback(
78 syncer::sync_ui_util::kRegisterForPerTypeCounters, 101 syncer::sync_ui_util::kRegisterForPerTypeCounters,
79 base::Bind(&SyncInternalsMessageHandler::HandleRegisterForPerTypeCounters, 102 base::Bind(&SyncInternalsMessageHandler::HandleRegisterForPerTypeCounters,
80 base::Unretained(this))); 103 base::Unretained(this)));
81 104
82 web_ui()->RegisterMessageCallback( 105 web_ui()->RegisterMessageCallback(
83 syncer::sync_ui_util::kRequestUpdatedAboutInfo, 106 syncer::sync_ui_util::kRequestUpdatedAboutInfo,
84 base::Bind(&SyncInternalsMessageHandler::HandleRequestUpdatedAboutInfo, 107 base::Bind(&SyncInternalsMessageHandler::HandleRequestUpdatedAboutInfo,
85 base::Unretained(this))); 108 base::Unretained(this)));
86 109
87 web_ui()->RegisterMessageCallback( 110 web_ui()->RegisterMessageCallback(
88 syncer::sync_ui_util::kRequestListOfTypes, 111 syncer::sync_ui_util::kRequestListOfTypes,
89 base::Bind(&SyncInternalsMessageHandler::HandleRequestListOfTypes, 112 base::Bind(&SyncInternalsMessageHandler::HandleRequestListOfTypes,
90 base::Unretained(this))); 113 base::Unretained(this)));
91 114
92 web_ui()->RegisterMessageCallback( 115 web_ui()->RegisterMessageCallback(
93 syncer::sync_ui_util::kGetAllNodes, 116 syncer::sync_ui_util::kGetAllNodes,
94 base::Bind(&SyncInternalsMessageHandler::HandleGetAllNodes, 117 base::Bind(&SyncInternalsMessageHandler::HandleGetAllNodes,
95 base::Unretained(this))); 118 base::Unretained(this)));
119
120 web_ui()->RegisterMessageCallback(
121 syncer::sync_ui_util::kRequestUserEventsVisibility,
122 base::Bind(
123 &SyncInternalsMessageHandler::HandleRequestUserEventsVisibility,
124 base::Unretained(this)));
125
126 web_ui()->RegisterMessageCallback(
127 syncer::sync_ui_util::kWriteUserEvent,
128 base::Bind(&SyncInternalsMessageHandler::HandleWriteUserEvent,
129 base::Unretained(this)));
96 } 130 }
97 131
98 void SyncInternalsMessageHandler::HandleRegisterForEvents( 132 void SyncInternalsMessageHandler::HandleRegisterForEvents(
99 const base::ListValue* args) { 133 const base::ListValue* args) {
100 DCHECK(args->empty()); 134 DCHECK(args->empty());
135 AllowJavascript();
101 136
102 // is_registered_ flag protects us from double-registering. This could 137 // is_registered_ flag protects us from double-registering. This could
103 // happen on a page refresh, where the JavaScript gets re-run but the 138 // happen on a page refresh, where the JavaScript gets re-run but the
104 // message handler remains unchanged. 139 // message handler remains unchanged.
105 ProfileSyncService* service = GetProfileSyncService(); 140 ProfileSyncService* service = GetProfileSyncService();
106 if (service && !is_registered_) { 141 if (service && !is_registered_) {
107 service->AddObserver(this); 142 service->AddObserver(this);
108 service->AddProtocolEventObserver(this); 143 service->AddProtocolEventObserver(this);
109 js_controller_ = service->GetJsController(); 144 js_controller_ = service->GetJsController();
110 js_controller_->AddJsEventHandler(this); 145 js_controller_->AddJsEventHandler(this);
111 is_registered_ = true; 146 is_registered_ = true;
112 } 147 }
113 } 148 }
114 149
115 void SyncInternalsMessageHandler::HandleRegisterForPerTypeCounters( 150 void SyncInternalsMessageHandler::HandleRegisterForPerTypeCounters(
116 const base::ListValue* args) { 151 const base::ListValue* args) {
117 DCHECK(args->empty()); 152 DCHECK(args->empty());
153 AllowJavascript();
118 154
119 if (ProfileSyncService* service = GetProfileSyncService()) { 155 if (ProfileSyncService* service = GetProfileSyncService()) {
120 if (!is_registered_for_counters_) { 156 if (!is_registered_for_counters_) {
121 service->AddTypeDebugInfoObserver(this); 157 service->AddTypeDebugInfoObserver(this);
122 is_registered_for_counters_ = true; 158 is_registered_for_counters_ = true;
123 } else { 159 } else {
124 // Re-register to ensure counters get re-emitted. 160 // Re-register to ensure counters get re-emitted.
125 service->RemoveTypeDebugInfoObserver(this); 161 service->RemoveTypeDebugInfoObserver(this);
126 service->AddTypeDebugInfoObserver(this); 162 service->AddTypeDebugInfoObserver(this);
127 } 163 }
128 } 164 }
129 } 165 }
130 166
131 void SyncInternalsMessageHandler::HandleRequestUpdatedAboutInfo( 167 void SyncInternalsMessageHandler::HandleRequestUpdatedAboutInfo(
132 const base::ListValue* args) { 168 const base::ListValue* args) {
133 DCHECK(args->empty()); 169 DCHECK(args->empty());
170 AllowJavascript();
134 SendAboutInfo(); 171 SendAboutInfo();
135 } 172 }
136 173
137 void SyncInternalsMessageHandler::HandleRequestListOfTypes( 174 void SyncInternalsMessageHandler::HandleRequestListOfTypes(
138 const base::ListValue* args) { 175 const base::ListValue* args) {
139 DCHECK(args->empty()); 176 DCHECK(args->empty());
177 AllowJavascript();
178
140 base::DictionaryValue event_details; 179 base::DictionaryValue event_details;
141 std::unique_ptr<base::ListValue> type_list(new base::ListValue()); 180 std::unique_ptr<base::ListValue> type_list(new base::ListValue());
142 ModelTypeSet protocol_types = syncer::ProtocolTypes(); 181 ModelTypeSet protocol_types = syncer::ProtocolTypes();
143 for (ModelTypeSet::Iterator it = protocol_types.First(); 182 for (ModelTypeSet::Iterator it = protocol_types.First();
144 it.Good(); it.Inc()) { 183 it.Good(); it.Inc()) {
145 type_list->AppendString(ModelTypeToString(it.Get())); 184 type_list->AppendString(ModelTypeToString(it.Get()));
146 } 185 }
147 event_details.Set(syncer::sync_ui_util::kTypes, type_list.release()); 186 event_details.Set(syncer::sync_ui_util::kTypes, type_list.release());
148 web_ui()->CallJavascriptFunctionUnsafe( 187 TryCallDispatch(Value(syncer::sync_ui_util::kOnReceivedListOfTypes),
149 syncer::sync_ui_util::kDispatchEvent, 188 event_details);
150 base::Value(syncer::sync_ui_util::kOnReceivedListOfTypes), event_details);
151 } 189 }
152 190
153 void SyncInternalsMessageHandler::HandleGetAllNodes( 191 void SyncInternalsMessageHandler::HandleGetAllNodes(
154 const base::ListValue* args) { 192 const base::ListValue* args) {
155 DCHECK_EQ(1U, args->GetSize()); 193 DCHECK_EQ(1U, args->GetSize());
194 AllowJavascript();
195
156 int request_id = 0; 196 int request_id = 0;
157 bool success = ExtractIntegerValue(args, &request_id); 197 bool success = ExtractIntegerValue(args, &request_id);
158 DCHECK(success); 198 DCHECK(success);
159 199
160 ProfileSyncService* service = GetProfileSyncService(); 200 ProfileSyncService* service = GetProfileSyncService();
161 if (service) { 201 if (service) {
162 service->GetAllNodes( 202 service->GetAllNodes(
163 base::Bind(&SyncInternalsMessageHandler::OnReceivedAllNodes, 203 base::Bind(&SyncInternalsMessageHandler::OnReceivedAllNodes,
164 weak_ptr_factory_.GetWeakPtr(), request_id)); 204 weak_ptr_factory_.GetWeakPtr(), request_id));
Dan Beam 2017/05/16 22:40:53 for something like this, the weak_ptr_factory_ is
skym 2017/05/22 21:55:48 You're right, and I didn't have a try in OnReceive
165 } 205 }
166 } 206 }
167 207
208 void SyncInternalsMessageHandler::HandleRequestUserEventsVisibility(
209 const base::ListValue* args) {
210 DCHECK(args->empty());
211 AllowJavascript();
212 CallJavascriptFunction(
213 syncer::sync_ui_util::kUserEventsVisibilityCallback,
214 Value(base::FeatureList::IsEnabled(switches::kSyncUserEvents)));
215 }
216
217 void SyncInternalsMessageHandler::HandleWriteUserEvent(
218 const base::ListValue* args) {
219 DCHECK_EQ(2U, args->GetSize());
220 AllowJavascript();
221
222 Profile* profile = Profile::FromWebUI(web_ui());
223 syncer::UserEventService* user_event_service =
224 browser_sync::UserEventServiceFactory::GetForProfile(
225 profile->GetOriginalProfile());
226
227 sync_pb::UserEventSpecifics event_specifics;
228 event_specifics.set_event_time_usec(StringAtIndexToInt64(args, 0));
229 event_specifics.set_navigation_id(StringAtIndexToInt64(args, 1));
230 user_event_service->RecordUserEvent(event_specifics);
231 }
232
168 void SyncInternalsMessageHandler::OnReceivedAllNodes( 233 void SyncInternalsMessageHandler::OnReceivedAllNodes(
169 int request_id, 234 int request_id,
170 std::unique_ptr<base::ListValue> nodes) { 235 std::unique_ptr<base::ListValue> nodes) {
171 base::Value id(request_id); 236 Value id(request_id);
172 web_ui()->CallJavascriptFunctionUnsafe( 237 CallJavascriptFunction(syncer::sync_ui_util::kGetAllNodesCallback, id,
173 syncer::sync_ui_util::kGetAllNodesCallback, id, *nodes); 238 *nodes);
174 } 239 }
175 240
176 void SyncInternalsMessageHandler::OnStateChanged(syncer::SyncService* sync) { 241 void SyncInternalsMessageHandler::OnStateChanged(syncer::SyncService* sync) {
177 SendAboutInfo(); 242 SendAboutInfo();
178 } 243 }
179 244
180 void SyncInternalsMessageHandler::OnProtocolEvent( 245 void SyncInternalsMessageHandler::OnProtocolEvent(
181 const syncer::ProtocolEvent& event) { 246 const syncer::ProtocolEvent& event) {
182 std::unique_ptr<base::DictionaryValue> value( 247 std::unique_ptr<base::DictionaryValue> value(
183 syncer::ProtocolEvent::ToValue(event)); 248 syncer::ProtocolEvent::ToValue(event));
184 web_ui()->CallJavascriptFunctionUnsafe( 249 TryCallDispatch(Value(syncer::sync_ui_util::kOnProtocolEvent), *value);
185 syncer::sync_ui_util::kDispatchEvent,
186 base::Value(syncer::sync_ui_util::kOnProtocolEvent), *value);
187 } 250 }
188 251
189 void SyncInternalsMessageHandler::OnCommitCountersUpdated( 252 void SyncInternalsMessageHandler::OnCommitCountersUpdated(
190 syncer::ModelType type, 253 syncer::ModelType type,
191 const syncer::CommitCounters& counters) { 254 const syncer::CommitCounters& counters) {
192 EmitCounterUpdate(type, syncer::sync_ui_util::kCommit, counters.ToValue()); 255 EmitCounterUpdate(type, syncer::sync_ui_util::kCommit, counters.ToValue());
193 } 256 }
194 257
195 void SyncInternalsMessageHandler::OnUpdateCountersUpdated( 258 void SyncInternalsMessageHandler::OnUpdateCountersUpdated(
196 syncer::ModelType type, 259 syncer::ModelType type,
197 const syncer::UpdateCounters& counters) { 260 const syncer::UpdateCounters& counters) {
198 EmitCounterUpdate(type, syncer::sync_ui_util::kUpdate, counters.ToValue()); 261 EmitCounterUpdate(type, syncer::sync_ui_util::kUpdate, counters.ToValue());
199 } 262 }
200 263
201 void SyncInternalsMessageHandler::OnStatusCountersUpdated( 264 void SyncInternalsMessageHandler::OnStatusCountersUpdated(
202 syncer::ModelType type, 265 syncer::ModelType type,
203 const syncer::StatusCounters& counters) { 266 const syncer::StatusCounters& counters) {
204 EmitCounterUpdate(type, syncer::sync_ui_util::kStatus, counters.ToValue()); 267 EmitCounterUpdate(type, syncer::sync_ui_util::kStatus, counters.ToValue());
205 } 268 }
206 269
207 void SyncInternalsMessageHandler::EmitCounterUpdate( 270 void SyncInternalsMessageHandler::EmitCounterUpdate(
208 syncer::ModelType type, 271 syncer::ModelType type,
209 const std::string& counter_type, 272 const std::string& counter_type,
210 std::unique_ptr<base::DictionaryValue> value) { 273 std::unique_ptr<base::DictionaryValue> value) {
211 std::unique_ptr<base::DictionaryValue> details(new base::DictionaryValue()); 274 std::unique_ptr<base::DictionaryValue> details(new base::DictionaryValue());
212 details->SetString(syncer::sync_ui_util::kModelType, ModelTypeToString(type)); 275 details->SetString(syncer::sync_ui_util::kModelType, ModelTypeToString(type));
213 details->SetString(syncer::sync_ui_util::kCounterType, counter_type); 276 details->SetString(syncer::sync_ui_util::kCounterType, counter_type);
214 details->Set(syncer::sync_ui_util::kCounters, value.release()); 277 details->Set(syncer::sync_ui_util::kCounters, value.release());
215 web_ui()->CallJavascriptFunctionUnsafe( 278 TryCallDispatch(Value(syncer::sync_ui_util::kOnCountersUpdated), *details);
216 syncer::sync_ui_util::kDispatchEvent,
217 base::Value(syncer::sync_ui_util::kOnCountersUpdated), *details);
218 } 279 }
219 280
220 void SyncInternalsMessageHandler::HandleJsEvent( 281 void SyncInternalsMessageHandler::HandleJsEvent(
221 const std::string& name, 282 const std::string& name,
222 const JsEventDetails& details) { 283 const JsEventDetails& details) {
284 AllowJavascript();
285
223 DVLOG(1) << "Handling event: " << name 286 DVLOG(1) << "Handling event: " << name
224 << " with details " << details.ToString(); 287 << " with details " << details.ToString();
225 web_ui()->CallJavascriptFunctionUnsafe(syncer::sync_ui_util::kDispatchEvent, 288 TryCallDispatch(Value(name), details.Get());
Dan Beam 2017/05/16 22:40:54 i don't really see how doing AllowJavascript() the
skym 2017/05/22 21:55:48 Whoops, that was sloppy of me, thanks for catching
226 base::Value(name), details.Get());
227 } 289 }
228 290
229 void SyncInternalsMessageHandler::SendAboutInfo() { 291 void SyncInternalsMessageHandler::SendAboutInfo() {
230 ProfileSyncService* sync_service = GetProfileSyncService(); 292 ProfileSyncService* sync_service = GetProfileSyncService();
231 SigninManagerBase* signin = sync_service ? sync_service->signin() : nullptr; 293 SigninManagerBase* signin = sync_service ? sync_service->signin() : nullptr;
232 std::unique_ptr<base::DictionaryValue> value = 294 std::unique_ptr<base::DictionaryValue> value =
233 about_sync_data_extractor_->ConstructAboutInformation(sync_service, 295 about_sync_data_extractor_->ConstructAboutInformation(sync_service,
234 signin); 296 signin);
235 web_ui()->CallJavascriptFunctionUnsafe( 297 TryCallDispatch(Value(syncer::sync_ui_util::kOnAboutInfoUpdated), *value);
236 syncer::sync_ui_util::kDispatchEvent,
237 base::Value(syncer::sync_ui_util::kOnAboutInfoUpdated), *value);
238 } 298 }
239 299
240 // Gets the ProfileSyncService of the underlying original profile. 300 // Gets the ProfileSyncService of the underlying original profile.
241 // May return NULL (e.g., if sync is disabled on the command line). 301 // May return NULL (e.g., if sync is disabled on the command line).
242 ProfileSyncService* SyncInternalsMessageHandler::GetProfileSyncService() { 302 ProfileSyncService* SyncInternalsMessageHandler::GetProfileSyncService() {
243 Profile* profile = Profile::FromWebUI(web_ui()); 303 Profile* profile = Profile::FromWebUI(web_ui());
244 return ProfileSyncServiceFactory::GetForProfile( 304 return ProfileSyncServiceFactory::GetForProfile(
245 profile->GetOriginalProfile()); 305 profile->GetOriginalProfile());
246 } 306 }
307
308 void SyncInternalsMessageHandler::TryCallDispatch(const Value& name_value,
309 const Value& details_value) {
310 if (IsJavascriptAllowed()) {
Dan Beam 2017/05/16 22:40:54 this does work but maybe it'd be easier just to di
skym 2017/05/22 21:55:48 Done in https://codereview.chromium.org/2898723003
311 CallJavascriptFunction(syncer::sync_ui_util::kDispatchEvent, name_value,
312 details_value);
313 }
314 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698