1// Copyright (c) 2011 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 <cstdio>
6#include <string>
7
8#include "base/at_exit.h"
9#include "base/base64.h"
10#include "base/command_line.h"
11#include "base/logging.h"
12#include "base/memory/ref_counted.h"
13#include "base/memory/scoped_ptr.h"
14#include "base/message_loop.h"
15#include "chrome/browser/sync/notifier/sync_notifier.h"
16#include "chrome/browser/sync/notifier/sync_notifier_factory.h"
17#include "chrome/browser/sync/notifier/sync_notifier_observer.h"
18#include "chrome/browser/sync/syncable/model_type.h"
19#include "chrome/browser/sync/syncable/model_type_payload_map.h"
20#include "chrome/test/test_url_request_context_getter.h"
21#include "content/browser/browser_thread.h"
22
23// This is a simple utility that initializes a sync notifier and
24// listens to any received notifications.
25
26namespace {
27
28// Class to print received notifications events.
29class NotificationPrinter : public sync_notifier::SyncNotifierObserver {
30 public:
31  NotificationPrinter() {}
32  virtual ~NotificationPrinter() {}
33
34  virtual void OnIncomingNotification(
35      const syncable::ModelTypePayloadMap& type_payloads) {
36    for (syncable::ModelTypePayloadMap::const_iterator it =
37             type_payloads.begin(); it != type_payloads.end(); ++it) {
38      LOG(INFO) << "Notification: type = "
39                << syncable::ModelTypeToString(it->first)
40                << ", payload = " << it->second;
41    }
42  }
43
44  virtual void OnNotificationStateChange(bool notifications_enabled) {
45    LOG(INFO) << "Notifications enabled: " << notifications_enabled;
46  }
47
48  virtual void StoreState(const std::string& state) {
49    std::string base64_state;
50    CHECK(base::Base64Encode(state, &base64_state));
51    LOG(INFO) << "Got state to store: " << base64_state;
52  }
53
54 private:
55  DISALLOW_COPY_AND_ASSIGN(NotificationPrinter);
56};
57
58}  // namespace
59
60int main(int argc, char* argv[]) {
61  base::AtExitManager exit_manager;
62  scoped_refptr<TestURLRequestContextGetter> request_context_getter(
63      new TestURLRequestContextGetter);
64  BrowserThread io_thread(BrowserThread::IO);
65  base::Thread::Options options;
66  options.message_loop_type = MessageLoop::TYPE_IO;
67  io_thread.StartWithOptions(options);
68  CommandLine::Init(argc, argv);
69  logging::InitLogging(
70      NULL,
71      logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG,
72      logging::LOCK_LOG_FILE,
73      logging::DELETE_OLD_LOG_FILE,
74      logging::DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS);
75
76  // Parse command line.
77  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
78  std::string email = command_line.GetSwitchValueASCII("email");
79  std::string token = command_line.GetSwitchValueASCII("token");
80  // TODO(akalin): Write a wrapper script that gets a token for an
81  // email and password and passes that in to this utility.
82  if (email.empty() || token.empty()) {
83    std::printf("Usage: %s --email=foo@bar.com --token=token\n\n"
84                "See sync_notifier_factory.cc for more switches.\n\n"
85                "Run chrome and set a breakpoint on "
86                "sync_api::SyncManager::SyncInternal::UpdateCredentials() "
87                "after logging into sync to get the token to pass into this "
88                "utility.\n",
89                argv[0]);
90    return -1;
91  }
92
93  // Needed by the SyncNotifier implementations.
94  MessageLoop main_loop;
95
96  const char kClientInfo[] = "sync_listen_notifications";
97  sync_notifier::SyncNotifierFactory sync_notifier_factory(kClientInfo);
98  scoped_ptr<sync_notifier::SyncNotifier> sync_notifier(
99      sync_notifier_factory.CreateSyncNotifier(command_line,
100                                               request_context_getter.get()));
101  NotificationPrinter notification_printer;
102  sync_notifier->AddObserver(&notification_printer);
103
104  sync_notifier->UpdateCredentials(email, token);
105  {
106    // Listen for notifications for all known types.
107    syncable::ModelTypeSet types;
108    for (int i = syncable::FIRST_REAL_MODEL_TYPE;
109         i < syncable::MODEL_TYPE_COUNT; ++i) {
110      types.insert(syncable::ModelTypeFromInt(i));
111    }
112    sync_notifier->UpdateEnabledTypes(types);
113  }
114
115  main_loop.Run();
116
117  sync_notifier->RemoveObserver(&notification_printer);
118  io_thread.Stop();
119  return 0;
120}
121