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

Side by Side Diff: sync/tools/sync_client.cc

Issue 2130453004: [Sync] Move //sync to //components/sync. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase. Created 4 years, 4 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
« no previous file with comments | « sync/tools/null_invalidation_state_tracker.cc ('k') | sync/tools/sync_listen_notifications.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012 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 <stdint.h>
6
7 #include <cstddef>
8 #include <cstdio>
9 #include <memory>
10 #include <string>
11 #include <utility>
12
13 #include "base/at_exit.h"
14 #include "base/command_line.h"
15 #include "base/compiler_specific.h"
16 #include "base/debug/stack_trace.h"
17 #include "base/files/scoped_temp_dir.h"
18 #include "base/json/json_writer.h"
19 #include "base/logging.h"
20 #include "base/memory/ptr_util.h"
21 #include "base/memory/ref_counted.h"
22 #include "base/memory/weak_ptr.h"
23 #include "base/message_loop/message_loop.h"
24 #include "base/rand_util.h"
25 #include "base/run_loop.h"
26 #include "base/task_runner.h"
27 #include "base/threading/thread.h"
28 #include "build/build_config.h"
29 #include "components/invalidation/impl/non_blocking_invalidator.h"
30 #include "components/invalidation/public/object_id_invalidation_map.h"
31 #include "components/sync_driver/invalidation_helper.h"
32 #include "jingle/notifier/base/notification_method.h"
33 #include "jingle/notifier/base/notifier_options.h"
34 #include "net/base/host_port_pair.h"
35 #include "net/base/network_change_notifier.h"
36 #include "net/dns/host_resolver.h"
37 #include "net/http/transport_security_state.h"
38 #include "net/url_request/url_request_test_util.h"
39 #include "sync/internal_api/public/base/cancelation_signal.h"
40 #include "sync/internal_api/public/base/model_type.h"
41 #include "sync/internal_api/public/base_node.h"
42 #include "sync/internal_api/public/engine/passive_model_worker.h"
43 #include "sync/internal_api/public/http_bridge.h"
44 #include "sync/internal_api/public/http_post_provider_factory.h"
45 #include "sync/internal_api/public/internal_components_factory_impl.h"
46 #include "sync/internal_api/public/read_node.h"
47 #include "sync/internal_api/public/sync_manager.h"
48 #include "sync/internal_api/public/sync_manager_factory.h"
49 #include "sync/internal_api/public/util/unrecoverable_error_handler.h"
50 #include "sync/internal_api/public/util/weak_handle.h"
51 #include "sync/js/js_event_details.h"
52 #include "sync/js/js_event_handler.h"
53 #include "sync/test/fake_encryptor.h"
54 #include "sync/tools/null_invalidation_state_tracker.h"
55 #include "url/gurl.h"
56
57 #if defined(OS_MACOSX)
58 #include "base/mac/scoped_nsautorelease_pool.h"
59 #endif
60
61 // This is a simple utility that initializes a sync client and
62 // prints out any events.
63
64 // TODO(akalin): Refactor to combine shared code with
65 // sync_listen_notifications.
66 namespace syncer {
67 namespace {
68
69 const char kEmailSwitch[] = "email";
70 const char kTokenSwitch[] = "token";
71 const char kXmppHostPortSwitch[] = "xmpp-host-port";
72 const char kXmppTrySslTcpFirstSwitch[] = "xmpp-try-ssltcp-first";
73 const char kXmppAllowInsecureConnectionSwitch[] =
74 "xmpp-allow-insecure-connection";
75 const char kSyncServiceURL[] = "https://clients4.google.com/chrome-sync/dev";
76
77 // Needed to use a real host resolver.
78 class MyTestURLRequestContext : public net::TestURLRequestContext {
79 public:
80 MyTestURLRequestContext() : TestURLRequestContext(true) {
81 context_storage_.set_host_resolver(
82 net::HostResolver::CreateDefaultResolver(NULL));
83 context_storage_.set_transport_security_state(
84 base::WrapUnique(new net::TransportSecurityState()));
85 Init();
86 }
87
88 ~MyTestURLRequestContext() override {}
89 };
90
91 class MyTestURLRequestContextGetter : public net::TestURLRequestContextGetter {
92 public:
93 explicit MyTestURLRequestContextGetter(
94 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
95 : TestURLRequestContextGetter(io_task_runner) {}
96
97 net::TestURLRequestContext* GetURLRequestContext() override {
98 // Construct |context_| lazily so it gets constructed on the right
99 // thread (the IO thread).
100 if (!context_)
101 context_.reset(new MyTestURLRequestContext());
102 return context_.get();
103 }
104
105 private:
106 ~MyTestURLRequestContextGetter() override {}
107
108 std::unique_ptr<MyTestURLRequestContext> context_;
109 };
110
111 // TODO(akalin): Use system encryptor once it's moved to sync/.
112 class NullEncryptor : public Encryptor {
113 public:
114 ~NullEncryptor() override {}
115
116 bool EncryptString(const std::string& plaintext,
117 std::string* ciphertext) override {
118 *ciphertext = plaintext;
119 return true;
120 }
121
122 bool DecryptString(const std::string& ciphertext,
123 std::string* plaintext) override {
124 *plaintext = ciphertext;
125 return true;
126 }
127 };
128
129 std::string ValueToString(const base::Value& value) {
130 std::string str;
131 base::JSONWriter::Write(value, &str);
132 return str;
133 }
134
135 class LoggingChangeDelegate : public SyncManager::ChangeDelegate {
136 public:
137 ~LoggingChangeDelegate() override {}
138
139 void OnChangesApplied(ModelType model_type,
140 int64_t model_version,
141 const BaseTransaction* trans,
142 const ImmutableChangeRecordList& changes) override {
143 LOG(INFO) << "Changes applied for "
144 << ModelTypeToString(model_type);
145 size_t i = 1;
146 size_t change_count = changes.Get().size();
147 for (ChangeRecordList::const_iterator it =
148 changes.Get().begin(); it != changes.Get().end(); ++it) {
149 std::unique_ptr<base::DictionaryValue> change_value(it->ToValue());
150 LOG(INFO) << "Change (" << i << "/" << change_count << "): "
151 << ValueToString(*change_value);
152 if (it->action != ChangeRecord::ACTION_DELETE) {
153 ReadNode node(trans);
154 CHECK_EQ(node.InitByIdLookup(it->id), BaseNode::INIT_OK);
155 std::unique_ptr<base::DictionaryValue> details(node.ToValue());
156 VLOG(1) << "Details: " << ValueToString(*details);
157 }
158 ++i;
159 }
160 }
161
162 void OnChangesComplete(ModelType model_type) override {
163 LOG(INFO) << "Changes complete for "
164 << ModelTypeToString(model_type);
165 }
166 };
167
168 class LoggingUnrecoverableErrorHandler
169 : public UnrecoverableErrorHandler {
170 public:
171 ~LoggingUnrecoverableErrorHandler() override {}
172
173 void OnUnrecoverableError(const tracked_objects::Location& from_here,
174 const std::string& message) override {
175 if (LOG_IS_ON(ERROR)) {
176 logging::LogMessage(from_here.file_name(), from_here.line_number(),
177 logging::LOG_ERROR).stream()
178 << message;
179 }
180 }
181 };
182
183 class LoggingJsEventHandler
184 : public JsEventHandler,
185 public base::SupportsWeakPtr<LoggingJsEventHandler> {
186 public:
187 ~LoggingJsEventHandler() override {}
188
189 void HandleJsEvent(const std::string& name,
190 const JsEventDetails& details) override {
191 VLOG(1) << name << ": " << details.ToString();
192 }
193 };
194
195 class InvalidationAdapter : public syncer::InvalidationInterface {
196 public:
197 explicit InvalidationAdapter(const syncer::Invalidation& invalidation)
198 : invalidation_(invalidation) {}
199 ~InvalidationAdapter() override {}
200
201 bool IsUnknownVersion() const override {
202 return invalidation_.is_unknown_version();
203 }
204
205 const std::string& GetPayload() const override {
206 return invalidation_.payload();
207 }
208
209 int64_t GetVersion() const override { return invalidation_.version(); }
210
211 void Acknowledge() override { invalidation_.Acknowledge(); }
212
213 void Drop() override { invalidation_.Drop(); }
214
215 private:
216 syncer::Invalidation invalidation_;
217 };
218
219 class InvalidatorShim : public InvalidationHandler {
220 public:
221 explicit InvalidatorShim(SyncManager* sync_manager)
222 : sync_manager_(sync_manager) {}
223
224 void OnInvalidatorStateChange(InvalidatorState state) override {
225 sync_manager_->SetInvalidatorEnabled(state == INVALIDATIONS_ENABLED);
226 }
227
228 void OnIncomingInvalidation(
229 const ObjectIdInvalidationMap& invalidation_map) override {
230 syncer::ObjectIdSet ids = invalidation_map.GetObjectIds();
231 for (syncer::ObjectIdSet::const_iterator ids_it = ids.begin();
232 ids_it != ids.end();
233 ++ids_it) {
234 syncer::ModelType type;
235 if (!NotificationTypeToRealModelType(ids_it->name(), &type)) {
236 DLOG(WARNING) << "Notification has invalid id: "
237 << syncer::ObjectIdToString(*ids_it);
238 } else {
239 syncer::SingleObjectInvalidationSet invalidation_set =
240 invalidation_map.ForObject(*ids_it);
241 for (syncer::SingleObjectInvalidationSet::const_iterator inv_it =
242 invalidation_set.begin();
243 inv_it != invalidation_set.end();
244 ++inv_it) {
245 std::unique_ptr<syncer::InvalidationInterface> inv_adapter(
246 new InvalidationAdapter(*inv_it));
247 sync_manager_->OnIncomingInvalidation(type, std::move(inv_adapter));
248 }
249 }
250 }
251 }
252
253 std::string GetOwnerName() const override { return "InvalidatorShim"; }
254
255 private:
256 SyncManager* sync_manager_;
257 };
258
259 void LogUnrecoverableErrorContext() {
260 base::debug::StackTrace().Print();
261 }
262
263 notifier::NotifierOptions ParseNotifierOptions(
264 const base::CommandLine& command_line,
265 const scoped_refptr<net::URLRequestContextGetter>& request_context_getter) {
266 notifier::NotifierOptions notifier_options;
267 notifier_options.request_context_getter = request_context_getter;
268 notifier_options.auth_mechanism = "X-OAUTH2";
269
270 if (command_line.HasSwitch(kXmppHostPortSwitch)) {
271 notifier_options.xmpp_host_port =
272 net::HostPortPair::FromString(
273 command_line.GetSwitchValueASCII(kXmppHostPortSwitch));
274 LOG(INFO) << "Using " << notifier_options.xmpp_host_port.ToString()
275 << " for test sync notification server.";
276 }
277
278 notifier_options.try_ssltcp_first =
279 command_line.HasSwitch(kXmppTrySslTcpFirstSwitch);
280 LOG_IF(INFO, notifier_options.try_ssltcp_first)
281 << "Trying SSL/TCP port before XMPP port for notifications.";
282
283 notifier_options.allow_insecure_connection =
284 command_line.HasSwitch(kXmppAllowInsecureConnectionSwitch);
285 LOG_IF(INFO, notifier_options.allow_insecure_connection)
286 << "Allowing insecure XMPP connections.";
287
288 return notifier_options;
289 }
290
291 void StubNetworkTimeUpdateCallback(const base::Time&,
292 const base::TimeDelta&,
293 const base::TimeDelta&) {
294 }
295
296 int SyncClientMain(int argc, char* argv[]) {
297 #if defined(OS_MACOSX)
298 base::mac::ScopedNSAutoreleasePool pool;
299 #endif
300 base::AtExitManager exit_manager;
301 base::CommandLine::Init(argc, argv);
302 logging::LoggingSettings settings;
303 settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
304 logging::InitLogging(settings);
305
306 base::MessageLoop sync_loop;
307 base::Thread io_thread("IO thread");
308 base::Thread::Options options;
309 options.message_loop_type = base::MessageLoop::TYPE_IO;
310 io_thread.StartWithOptions(options);
311
312 // Parse command line.
313 const base::CommandLine& command_line =
314 *base::CommandLine::ForCurrentProcess();
315 SyncCredentials credentials;
316 credentials.account_id = command_line.GetSwitchValueASCII(kEmailSwitch);
317 credentials.email = command_line.GetSwitchValueASCII(kEmailSwitch);
318 credentials.sync_token = command_line.GetSwitchValueASCII(kTokenSwitch);
319 // TODO(akalin): Write a wrapper script that gets a token for an
320 // email and password and passes that in to this utility.
321 if (credentials.email.empty() || credentials.sync_token.empty()) {
322 std::printf("Usage: %s --%s=foo@bar.com --%s=token\n"
323 "[--%s=host:port] [--%s] [--%s]\n"
324 "Run chrome and set a breakpoint on\n"
325 "syncer::SyncManagerImpl::UpdateCredentials() "
326 "after logging into\n"
327 "sync to get the token to pass into this utility.\n",
328 argv[0],
329 kEmailSwitch, kTokenSwitch, kXmppHostPortSwitch,
330 kXmppTrySslTcpFirstSwitch,
331 kXmppAllowInsecureConnectionSwitch);
332 return -1;
333 }
334
335 // Set up objects that monitor the network.
336 std::unique_ptr<net::NetworkChangeNotifier> network_change_notifier(
337 net::NetworkChangeNotifier::Create());
338
339 // Set up sync notifier factory.
340 const scoped_refptr<MyTestURLRequestContextGetter> context_getter =
341 new MyTestURLRequestContextGetter(io_thread.task_runner());
342 const notifier::NotifierOptions& notifier_options =
343 ParseNotifierOptions(command_line, context_getter);
344 syncer::NetworkChannelCreator network_channel_creator =
345 syncer::NonBlockingInvalidator::MakePushClientChannelCreator(
346 notifier_options);
347 const char kClientInfo[] = "standalone_sync_client";
348 std::string invalidator_id = base::RandBytesAsString(8);
349 NullInvalidationStateTracker null_invalidation_state_tracker;
350 std::unique_ptr<Invalidator> invalidator(new NonBlockingInvalidator(
351 network_channel_creator, invalidator_id,
352 null_invalidation_state_tracker.GetSavedInvalidations(),
353 null_invalidation_state_tracker.GetBootstrapData(),
354 &null_invalidation_state_tracker, kClientInfo,
355 notifier_options.request_context_getter));
356
357 // Set up database directory for the syncer.
358 base::ScopedTempDir database_dir;
359 CHECK(database_dir.CreateUniqueTempDir());
360
361 // Developers often add types to ModelTypeSet::All() before the server
362 // supports them. We need to be explicit about which types we want here.
363 ModelTypeSet model_types;
364 model_types.Put(BOOKMARKS);
365 model_types.Put(PREFERENCES);
366 model_types.Put(PASSWORDS);
367 model_types.Put(AUTOFILL);
368 model_types.Put(THEMES);
369 model_types.Put(TYPED_URLS);
370 model_types.Put(EXTENSIONS);
371 model_types.Put(NIGORI);
372 model_types.Put(SEARCH_ENGINES);
373 model_types.Put(SESSIONS);
374 model_types.Put(APPS);
375 model_types.Put(AUTOFILL_PROFILE);
376 model_types.Put(APP_SETTINGS);
377 model_types.Put(EXTENSION_SETTINGS);
378 model_types.Put(APP_NOTIFICATIONS);
379 model_types.Put(HISTORY_DELETE_DIRECTIVES);
380 model_types.Put(SYNCED_NOTIFICATIONS);
381 model_types.Put(SYNCED_NOTIFICATION_APP_INFO);
382 model_types.Put(DEVICE_INFO);
383 model_types.Put(EXPERIMENTS);
384 model_types.Put(PRIORITY_PREFERENCES);
385 model_types.Put(DICTIONARY);
386 model_types.Put(FAVICON_IMAGES);
387 model_types.Put(FAVICON_TRACKING);
388
389 ModelSafeRoutingInfo routing_info;
390 for (ModelTypeSet::Iterator it = model_types.First();
391 it.Good(); it.Inc()) {
392 routing_info[it.Get()] = GROUP_PASSIVE;
393 }
394 scoped_refptr<PassiveModelWorker> passive_model_safe_worker =
395 new PassiveModelWorker(nullptr);
396 std::vector<scoped_refptr<ModelSafeWorker> > workers;
397 workers.push_back(passive_model_safe_worker);
398
399 // Set up sync manager.
400 SyncManagerFactory sync_manager_factory;
401 std::unique_ptr<SyncManager> sync_manager =
402 sync_manager_factory.CreateSyncManager("sync_client manager");
403 LoggingJsEventHandler js_event_handler;
404 // Used only by InitialProcessMetadata(), so it's okay to leave this as NULL.
405 const scoped_refptr<base::TaskRunner> blocking_task_runner = NULL;
406 const char kUserAgent[] = "sync_client";
407 // TODO(akalin): Replace this with just the context getter once
408 // HttpPostProviderFactory is removed.
409 CancelationSignal factory_cancelation_signal;
410 std::unique_ptr<HttpPostProviderFactory> post_factory(new HttpBridgeFactory(
411 context_getter.get(), base::Bind(&StubNetworkTimeUpdateCallback),
412 &factory_cancelation_signal));
413 post_factory->Init(kUserAgent, BindToTrackerCallback());
414 // Used only when committing bookmarks, so it's okay to leave this
415 // as NULL.
416 ExtensionsActivity* extensions_activity = NULL;
417 LoggingChangeDelegate change_delegate;
418 const char kRestoredKeyForBootstrapping[] = "";
419 const char kRestoredKeystoreKeyForBootstrapping[] = "";
420 NullEncryptor null_encryptor;
421 InternalComponentsFactoryImpl::Switches factory_switches = {
422 InternalComponentsFactory::ENCRYPTION_KEYSTORE,
423 InternalComponentsFactory::BACKOFF_NORMAL
424 };
425 CancelationSignal scm_cancelation_signal;
426
427 SyncManager::InitArgs args;
428 args.database_location = database_dir.path();
429 args.event_handler = WeakHandle<JsEventHandler>(js_event_handler.AsWeakPtr());
430 args.service_url = GURL(kSyncServiceURL);
431 args.post_factory = std::move(post_factory);
432 args.workers = workers;
433 args.extensions_activity = extensions_activity;
434 args.change_delegate = &change_delegate;
435 args.credentials = credentials;
436 args.invalidator_client_id = invalidator_id;
437 args.restored_key_for_bootstrapping = kRestoredKeyForBootstrapping;
438 args.restored_keystore_key_for_bootstrapping =
439 kRestoredKeystoreKeyForBootstrapping;
440 args.internal_components_factory.reset(
441 new InternalComponentsFactoryImpl(factory_switches));
442 args.encryptor = &null_encryptor;
443 args.unrecoverable_error_handler = WeakHandle<UnrecoverableErrorHandler>();
444 args.report_unrecoverable_error_function =
445 base::Bind(LogUnrecoverableErrorContext);
446 args.cancelation_signal = &scm_cancelation_signal;
447 sync_manager->Init(&args);
448 // TODO(akalin): Avoid passing in model parameters multiple times by
449 // organizing handling of model types.
450 invalidator->UpdateCredentials(credentials.email, credentials.sync_token);
451 std::unique_ptr<InvalidatorShim> shim(
452 new InvalidatorShim(sync_manager.get()));
453 invalidator->RegisterHandler(shim.get());
454 CHECK(invalidator->UpdateRegisteredIds(
455 shim.get(), ModelTypeSetToObjectIdSet(model_types)));
456 sync_manager->StartSyncingNormally(routing_info, base::Time());
457
458 base::RunLoop().Run();
459
460 io_thread.Stop();
461 return 0;
462 }
463
464 } // namespace
465 } // namespace syncer
466
467 int main(int argc, char* argv[]) {
468 return syncer::SyncClientMain(argc, argv);
469 }
OLDNEW
« no previous file with comments | « sync/tools/null_invalidation_state_tracker.cc ('k') | sync/tools/sync_listen_notifications.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698