sync_listen_notifications.cc revision 72a454cd3513ac24fbdd0e0cb9ad70b86a99b801
1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <string>
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <vector>
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/at_exit.h"
9731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/base64.h"
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/command_line.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/logging.h"
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/message_loop.h"
133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/observer_list.h"
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h"
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/task.h"
163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/weak_ptr.h"
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/notifier/cache_invalidation_packet_handler.h"
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/notifier/chrome_invalidation_client.h"
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/notifier/chrome_system_resources.h"
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/sync_constants.h"
213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "jingle/notifier/base/xmpp_connection.h"
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "jingle/notifier/listener/listen_task.h"
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "jingle/notifier/listener/notification_constants.h"
24513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "jingle/notifier/listener/notification_defines.h"
25513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "jingle/notifier/listener/send_update_task.h"
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "jingle/notifier/listener/subscribe_task.h"
273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "jingle/notifier/listener/xml_element_util.h"
2821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "net/base/cert_verifier.h"
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/ssl_config_service.h"
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/socket/client_socket_factory.h"
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "talk/base/cryptstring.h"
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "talk/base/logging.h"
33513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "talk/base/sigslot.h"
343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "talk/base/task.h"
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "talk/xmpp/jid.h"
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "talk/xmpp/xmppclientsettings.h"
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "talk/xmpp/constants.h"
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "talk/xmpp/xmppengine.h"
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This is a simple utility that logs into an XMPP server, subscribes
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// to Sync notifications, and prints out any such notifications that
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// are received.
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace {
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Main class that listens for and handles messages from the XMPP
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// client.
483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickclass XmppNotificationClient : public notifier::XmppConnection::Delegate {
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // An observer is notified when we are logged into XMPP or when an
513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // error occurs.
523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  class Observer {
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   public:
543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    virtual ~Observer() {}
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    virtual void OnConnect(base::WeakPtr<talk_base::Task> base_task) = 0;
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    virtual void OnError() = 0;
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  template <class T> XmppNotificationClient(T begin, T end) {
623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    for (T it = begin; it != end; ++it) {
633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      observer_list_.AddObserver(*it);
643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  virtual ~XmppNotificationClient() {}
683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Connect with the given XMPP settings and run until disconnected.
7021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  void Run(const buzz::XmppClientSettings& xmpp_client_settings,
7121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen           net::CertVerifier* cert_verifier) {
723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    DCHECK(!xmpp_connection_.get());
733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    xmpp_connection_.reset(
7421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        new notifier::XmppConnection(xmpp_client_settings, cert_verifier,
7521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                     this, NULL));
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MessageLoop::current()->Run();
773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    DCHECK(!xmpp_connection_.get());
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  virtual void OnConnect(base::WeakPtr<talk_base::Task> base_task) {
813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    FOR_EACH_OBSERVER(Observer, observer_list_, OnConnect(base_task));
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  virtual void OnError(buzz::XmppEngine::Error error, int subcode,
853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                       const buzz::XmlElement* stream_error) {
863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    LOG(INFO) << "Error: " << error << ", subcode: " << subcode;
873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (stream_error) {
883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      LOG(INFO) << "Stream error: "
893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                << notifier::XmlElementToString(*stream_error);
903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    FOR_EACH_OBSERVER(Observer, observer_list_, OnError());
923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // This has to go before the message loop quits.
933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    xmpp_connection_.reset();
943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    MessageLoop::current()->Quit();
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick private:
983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ObserverList<Observer> observer_list_;
993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<notifier::XmppConnection> xmpp_connection_;
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DISALLOW_COPY_AND_ASSIGN(XmppNotificationClient);
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Delegate for legacy notifications.
105513209b27ff55e2841eac0e4120199c23acce758Ben Murdochclass LegacyNotifierDelegate
106513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    : public XmppNotificationClient::Observer,
107513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      public sigslot::has_slots<> {
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
109513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  explicit LegacyNotifierDelegate(bool send_initial_update)
110513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      : send_initial_update_(send_initial_update) {}
111513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual ~LegacyNotifierDelegate() {}
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  virtual void OnConnect(base::WeakPtr<talk_base::Task> base_task) {
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    LOG(INFO) << "Logged in";
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::vector<std::string> subscribed_services_list;
117513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    subscribed_services_list.push_back(browser_sync::kSyncServiceUrl);
1183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Owned by base_task.
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    notifier::SubscribeTask* subscribe_task =
1203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        new notifier::SubscribeTask(base_task, subscribed_services_list);
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    subscribe_task->Start();
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Owned by xmpp_client.
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    notifier::ListenTask* listen_task =
1243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        new notifier::ListenTask(base_task);
125513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    listen_task->SignalUpdateAvailable.connect(
126513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        this, &LegacyNotifierDelegate::OnUpdateAvailable);
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    listen_task->Start();
128513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (send_initial_update_) {
129513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      // Owned by xmpp_client.
130513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      notifier::SendUpdateTask* send_update_task =
131513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch          new notifier::SendUpdateTask(base_task,
132513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                       OutgoingNotificationData());
133513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      send_update_task->Start();
134513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    }
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  virtual void OnError() {}
138513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
139513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  void OnUpdateAvailable(
140513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      const IncomingNotificationData& notification_data) {
141513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    LOG(INFO) << "Notification received: "
142513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch              << notification_data.service_url << " "
143513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch              << notification_data.service_specific_data;
144513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
145513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
146513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch private:
147513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  bool send_initial_update_;
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The actual listener for sync notifications.
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass ChromeInvalidationListener
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : public sync_notifier::ChromeInvalidationClient::Listener {
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ChromeInvalidationListener() {}
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
15672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  virtual void OnInvalidate(syncable::ModelType model_type,
15772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                            const std::string& payload) {
15872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    LOG(INFO) << "OnInvalidate: "
15972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen              << syncable::ModelTypeToString(model_type) << " - " << payload;
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // A real implementation would respond to the invalidation.
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void OnInvalidateAll() {
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    LOG(INFO) << "InvalidateAll";
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // A real implementation would loop over the current registered
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // data types and send notifications for those.
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DISALLOW_COPY_AND_ASSIGN(ChromeInvalidationListener);
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
173513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// Delegate for server-issued notifications.
174513209b27ff55e2841eac0e4120199c23acce758Ben Murdochclass ServerNotifierDelegate
175731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    : public XmppNotificationClient::Observer,
176731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      public sync_notifier::StateWriter {
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
178513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  explicit ServerNotifierDelegate(
179513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      const std::string& server_notifier_state)
180513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      : server_notifier_state_(server_notifier_state) {}
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
182513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  virtual ~ServerNotifierDelegate() {}
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  virtual void OnConnect(base::WeakPtr<talk_base::Task> base_task) {
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    LOG(INFO) << "Logged in";
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // TODO(akalin): app_name should be per-client unique.
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const std::string kAppName = "cc_sync_listen_notifications";
18972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const std::string kAppInfo = kAppName;
19072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    chrome_invalidation_client_.Start(kAppName, kAppInfo,
19172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                      server_notifier_state_,
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                      &chrome_invalidation_listener_,
193731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                      this, base_task);
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    chrome_invalidation_client_.RegisterTypes();
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  virtual void OnError() {
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    chrome_invalidation_client_.Stop();
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
201731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  virtual void WriteState(const std::string& state) {
202731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    std::string base64_state;
203731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    CHECK(base::Base64Encode(state, &base64_state));
204731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    LOG(INFO) << "New state: " << base64_state;
205731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
206731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ChromeInvalidationListener chrome_invalidation_listener_;
209731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // Opaque blob capturing the notifications state of a previous run
210731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // (i.e., the base64-decoded value of a string output by
211731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // WriteState()).
212513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  std::string server_notifier_state_;
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  sync_notifier::ChromeInvalidationClient chrome_invalidation_client_;
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint main(int argc, char* argv[]) {
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  base::AtExitManager exit_manager;
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CommandLine::Init(argc, argv);
22172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  logging::InitLogging(
22272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      NULL,
22372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG,
22472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      logging::LOCK_LOG_FILE,
22572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      logging::DELETE_OLD_LOG_FILE,
22672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      logging::DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS);
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(akalin): Make sure that all log messages are printed to the
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // console, even on Windows (SetMinLogLevel isn't enough).
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  talk_base::LogMessage::LogToDebug(talk_base::LS_VERBOSE);
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Parse command line.
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
233513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  std::string email = command_line.GetSwitchValueASCII("email");
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (email.empty()) {
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    printf("Usage: %s --email=foo@bar.com [--password=mypassword] "
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch           "[--server=talk.google.com] [--port=5222] [--allow-plain] "
237513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch           "[--disable-tls] [--use-ssl-tcp] [--server-notifier-state] "
238513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch           "[--use-legacy-notifier] "
239513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch           "[--legacy-notifier-send-initial-update]\n",
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch           argv[0]);
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return -1;
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
243513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  std::string password = command_line.GetSwitchValueASCII("password");
244513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  std::string server = command_line.GetSwitchValueASCII("server");
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (server.empty()) {
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    server = "talk.google.com";
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
248513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  std::string port_str = command_line.GetSwitchValueASCII("port");
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int port = 5222;
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!port_str.empty()) {
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int port_from_port_str = std::strtol(port_str.c_str(), NULL, 10);
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (port_from_port_str == 0) {
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      LOG(WARNING) << "Invalid port " << port_str << "; using default";
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      port = port_from_port_str;
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
258513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  bool allow_plain = command_line.HasSwitch("allow-plain");
259513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  bool disable_tls = command_line.HasSwitch("disable-tls");
260513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  bool use_ssl_tcp = command_line.HasSwitch("use-ssl-tcp");
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (use_ssl_tcp && (port != 443)) {
262513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    LOG(WARNING) << "--use-ssl-tcp is set but port is " << port
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                 << " instead of 443";
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
265513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  std::string server_notifier_state;
266513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  std::string server_notifier_state_encoded =
267513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      command_line.GetSwitchValueASCII("server-notifier-state");
268513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (!server_notifier_state_encoded.empty() &&
269513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      !base::Base64Decode(server_notifier_state_encoded,
270513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                          &server_notifier_state)) {
271731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    LOG(ERROR) << "Could not decode state: "
272513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch               << server_notifier_state_encoded;
273731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
274513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  bool use_legacy_notifier = command_line.HasSwitch("use-legacy-notifier");
275513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  bool legacy_notifier_send_initial_update =
276513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      command_line.HasSwitch("legacy-notifier-send-initial-update");
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Build XMPP client settings.
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  buzz::XmppClientSettings xmpp_client_settings;
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  buzz::Jid jid(email);
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  xmpp_client_settings.set_user(jid.node());
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  xmpp_client_settings.set_resource("cc_sync_listen_notifications");
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  xmpp_client_settings.set_host(jid.domain());
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  xmpp_client_settings.set_allow_plain(allow_plain);
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  xmpp_client_settings.set_use_tls(!disable_tls);
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (use_ssl_tcp) {
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    xmpp_client_settings.set_protocol(cricket::PROTO_SSLTCP);
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  talk_base::InsecureCryptStringImpl insecure_crypt_string;
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  insecure_crypt_string.password() = password;
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  xmpp_client_settings.set_pass(
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      talk_base::CryptString(insecure_crypt_string));
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  talk_base::SocketAddress addr(server, port);
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!addr.ResolveIP()) {
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    LOG(ERROR) << "Could not resolve " << addr.ToString();
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return -1;
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  xmpp_client_settings.set_server(addr);
299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
30021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  net::CertVerifier cert_verifier;
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoopForIO message_loop;
302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Connect and listen.
304513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  ServerNotifierDelegate server_notifier_delegate(
305513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      server_notifier_state);
306513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  LegacyNotifierDelegate legacy_notifier_delegate(
307513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      legacy_notifier_send_initial_update);
3083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::vector<XmppNotificationClient::Observer*> observers;
309513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (use_legacy_notifier) {
3103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    observers.push_back(&legacy_notifier_delegate);
311513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  } else {
312513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    observers.push_back(&server_notifier_delegate);
313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
3143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  XmppNotificationClient xmpp_notification_client(
3153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      observers.begin(), observers.end());
31621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  xmpp_notification_client.Run(xmpp_client_settings, &cert_verifier);
317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return 0;
319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
320