- add sources.
[platform/framework/web/crosswalk.git] / src / sync / tools / sync_listen_notifications.cc
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 <cstddef>
6 #include <cstdio>
7 #include <string>
8
9 #include "base/at_exit.h"
10 #include "base/command_line.h"
11 #include "base/compiler_specific.h"
12 #include "base/logging.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/message_loop/message_loop.h"
16 #include "base/rand_util.h"
17 #include "base/threading/thread.h"
18 #include "jingle/notifier/base/notification_method.h"
19 #include "jingle/notifier/base/notifier_options.h"
20 #include "net/base/host_port_pair.h"
21 #include "net/base/network_change_notifier.h"
22 #include "net/dns/host_resolver.h"
23 #include "net/http/transport_security_state.h"
24 #include "net/url_request/url_request_test_util.h"
25 #include "sync/internal_api/public/base/model_type.h"
26 #include "sync/notifier/invalidation_handler.h"
27 #include "sync/notifier/invalidation_state_tracker.h"
28 #include "sync/notifier/invalidation_util.h"
29 #include "sync/notifier/invalidator.h"
30 #include "sync/notifier/non_blocking_invalidator.h"
31 #include "sync/tools/null_invalidation_state_tracker.h"
32
33 #if defined(OS_MACOSX)
34 #include "base/mac/scoped_nsautorelease_pool.h"
35 #endif
36
37 // This is a simple utility that initializes a sync notifier and
38 // listens to any received notifications.
39
40 namespace syncer {
41 namespace {
42
43 const char kEmailSwitch[] = "email";
44 const char kTokenSwitch[] = "token";
45 const char kHostPortSwitch[] = "host-port";
46 const char kTrySslTcpFirstSwitch[] = "try-ssltcp-first";
47 const char kAllowInsecureConnectionSwitch[] = "allow-insecure-connection";
48
49 // Class to print received notifications events.
50 class NotificationPrinter : public InvalidationHandler {
51  public:
52   NotificationPrinter() {}
53   virtual ~NotificationPrinter() {}
54
55   virtual void OnInvalidatorStateChange(InvalidatorState state) OVERRIDE {
56     LOG(INFO) << "Invalidator state changed to "
57               << InvalidatorStateToString(state);
58   }
59
60   virtual void OnIncomingInvalidation(
61       const ObjectIdInvalidationMap& invalidation_map) OVERRIDE {
62     ObjectIdSet ids = invalidation_map.GetObjectIds();
63     for (ObjectIdSet::const_iterator it = ids.begin(); it != ids.end(); ++it) {
64       LOG(INFO) << "Remote invalidation: "
65                 << invalidation_map.ToString();
66     }
67   }
68
69  private:
70   DISALLOW_COPY_AND_ASSIGN(NotificationPrinter);
71 };
72
73 // Needed to use a real host resolver.
74 class MyTestURLRequestContext : public net::TestURLRequestContext {
75  public:
76   MyTestURLRequestContext() : TestURLRequestContext(true) {
77     context_storage_.set_host_resolver(
78         net::HostResolver::CreateDefaultResolver(NULL));
79     context_storage_.set_transport_security_state(
80         new net::TransportSecurityState());
81     Init();
82   }
83
84   virtual ~MyTestURLRequestContext() {}
85 };
86
87 class MyTestURLRequestContextGetter : public net::TestURLRequestContextGetter {
88  public:
89   explicit MyTestURLRequestContextGetter(
90       const scoped_refptr<base::MessageLoopProxy>& io_message_loop_proxy)
91       : TestURLRequestContextGetter(io_message_loop_proxy) {}
92
93   virtual net::TestURLRequestContext* GetURLRequestContext() OVERRIDE {
94     // Construct |context_| lazily so it gets constructed on the right
95     // thread (the IO thread).
96     if (!context_)
97       context_.reset(new MyTestURLRequestContext());
98     return context_.get();
99   }
100
101  private:
102   virtual ~MyTestURLRequestContextGetter() {}
103
104   scoped_ptr<MyTestURLRequestContext> context_;
105 };
106
107 notifier::NotifierOptions ParseNotifierOptions(
108     const CommandLine& command_line,
109     const scoped_refptr<net::URLRequestContextGetter>&
110         request_context_getter) {
111   notifier::NotifierOptions notifier_options;
112   notifier_options.request_context_getter = request_context_getter;
113
114   if (command_line.HasSwitch(kHostPortSwitch)) {
115     notifier_options.xmpp_host_port =
116         net::HostPortPair::FromString(
117             command_line.GetSwitchValueASCII(kHostPortSwitch));
118     LOG(INFO) << "Using " << notifier_options.xmpp_host_port.ToString()
119               << " for test sync notification server.";
120   }
121
122   notifier_options.try_ssltcp_first =
123       command_line.HasSwitch(kTrySslTcpFirstSwitch);
124   LOG_IF(INFO, notifier_options.try_ssltcp_first)
125       << "Trying SSL/TCP port before XMPP port for notifications.";
126
127   notifier_options.allow_insecure_connection =
128       command_line.HasSwitch(kAllowInsecureConnectionSwitch);
129   LOG_IF(INFO, notifier_options.allow_insecure_connection)
130       << "Allowing insecure XMPP connections.";
131
132   return notifier_options;
133 }
134
135 int SyncListenNotificationsMain(int argc, char* argv[]) {
136   using namespace syncer;
137 #if defined(OS_MACOSX)
138   base::mac::ScopedNSAutoreleasePool pool;
139 #endif
140   base::AtExitManager exit_manager;
141   CommandLine::Init(argc, argv);
142   logging::LoggingSettings settings;
143   settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
144   logging::InitLogging(settings);
145
146   base::MessageLoop ui_loop;
147   base::Thread io_thread("IO thread");
148   base::Thread::Options options;
149   options.message_loop_type = base::MessageLoop::TYPE_IO;
150   io_thread.StartWithOptions(options);
151
152   // Parse command line.
153   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
154   std::string email = command_line.GetSwitchValueASCII(kEmailSwitch);
155   std::string token = command_line.GetSwitchValueASCII(kTokenSwitch);
156   // TODO(akalin): Write a wrapper script that gets a token for an
157   // email and password and passes that in to this utility.
158   if (email.empty() || token.empty()) {
159     std::printf("Usage: %s --%s=foo@bar.com --%s=token\n"
160                 "[--%s=host:port] [--%s] [--%s]\n"
161                 "Run chrome and set a breakpoint on\n"
162                 "syncer::SyncManagerImpl::UpdateCredentials() "
163                 "after logging into\n"
164                 "sync to get the token to pass into this utility.\n",
165                 argv[0],
166                 kEmailSwitch, kTokenSwitch, kHostPortSwitch,
167                 kTrySslTcpFirstSwitch, kAllowInsecureConnectionSwitch);
168     return -1;
169   }
170
171   // Set up objects that monitor the network.
172   scoped_ptr<net::NetworkChangeNotifier> network_change_notifier(
173       net::NetworkChangeNotifier::Create());
174
175   const notifier::NotifierOptions& notifier_options =
176       ParseNotifierOptions(
177           command_line,
178           new MyTestURLRequestContextGetter(io_thread.message_loop_proxy()));
179   const char kClientInfo[] = "sync_listen_notifications";
180   NullInvalidationStateTracker null_invalidation_state_tracker;
181   scoped_ptr<Invalidator> invalidator(
182       new NonBlockingInvalidator(
183           notifier_options,
184           base::RandBytesAsString(8),
185           null_invalidation_state_tracker.GetAllInvalidationStates(),
186           null_invalidation_state_tracker.GetBootstrapData(),
187           WeakHandle<InvalidationStateTracker>(
188               null_invalidation_state_tracker.AsWeakPtr()),
189           kClientInfo));
190
191   NotificationPrinter notification_printer;
192
193   invalidator->UpdateCredentials(email, token);
194
195   // Listen for notifications for all known types.
196   invalidator->RegisterHandler(&notification_printer);
197   invalidator->UpdateRegisteredIds(
198       &notification_printer, ModelTypeSetToObjectIdSet(ModelTypeSet::All()));
199
200   ui_loop.Run();
201
202   invalidator->UnregisterHandler(&notification_printer);
203   io_thread.Stop();
204   return 0;
205 }
206
207 }  // namespace
208 }  // namespace syncer
209
210 int main(int argc, char* argv[]) {
211   return syncer::SyncListenNotificationsMain(argc, argv);
212 }