1a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// found in the LICENSE file.
4a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)//
5a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// A standalone tool for testing MCS connections and the MCS client on their
6a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// own.
7a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
8a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <cstddef>
9a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <cstdio>
10a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <string>
11a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
12a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/at_exit.h"
13a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/command_line.h"
14a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/compiler_specific.h"
15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/logging.h"
16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/memory/ref_counted.h"
17a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
18a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/message_loop/message_loop.h"
19a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/run_loop.h"
20a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/strings/string_number_conversions.h"
21a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/threading/thread.h"
22a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/threading/worker_pool.h"
23a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/values.h"
24a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "google_apis/gcm/base/mcs_message.h"
25a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "google_apis/gcm/base/mcs_util.h"
26a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "google_apis/gcm/engine/connection_factory_impl.h"
27a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "google_apis/gcm/engine/mcs_client.h"
28a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/base/host_mapping_rules.h"
29a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/base/net_log_logger.h"
30a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/cert/cert_verifier.h"
31a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/dns/host_resolver.h"
32a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/http/http_auth_handler_factory.h"
33a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/http/http_network_session.h"
34a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/http/http_server_properties_impl.h"
35a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/http/transport_security_state.h"
36a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/socket/client_socket_factory.h"
37a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/socket/ssl_client_socket.h"
38a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/ssl/default_server_bound_cert_store.h"
39a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/ssl/server_bound_cert_service.h"
40a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/url_request/url_request_test_util.h"
41a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
42a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#if defined(OS_MACOSX)
43a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/mac/scoped_nsautorelease_pool.h"
44a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#endif
45a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
46a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// This is a simple utility that initializes an mcs client and
47a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// prints out any events.
48a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace gcm {
49a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace {
50a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
51a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// The default server to communicate with.
52a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const char kMCSServerHost[] = "mtalk.google.com";
53a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const uint16 kMCSServerPort = 5228;
54a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
55a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Command line switches.
56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const char kRMQFileName[] = "rmq_file";
57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const char kAndroidIdSwitch[] = "android_id";
58a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const char kSecretSwitch[] = "secret";
59a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const char kLogFileSwitch[] = "log-file";
60a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const char kIgnoreCertSwitch[] = "ignore-certs";
61a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const char kServerHostSwitch[] = "host";
62a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const char kServerPortSwitch[] = "port";
63a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void MessageReceivedCallback(const MCSMessage& message) {
65a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  LOG(INFO) << "Received message with id "
66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            << GetPersistentId(message.GetProtobuf()) << " and tag "
67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            << static_cast<int>(message.tag());
68a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
69a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (message.tag() == kDataMessageStanzaTag) {
70a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const mcs_proto::DataMessageStanza& data_message =
71a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        reinterpret_cast<const mcs_proto::DataMessageStanza&>(
72a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            message.GetProtobuf());
73a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DVLOG(1) << "  to: " << data_message.to();
74a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DVLOG(1) << "  from: " << data_message.from();
75a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DVLOG(1) << "  category: " << data_message.category();
76a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DVLOG(1) << "  sent: " << data_message.sent();
77a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    for (int i = 0; i < data_message.app_data_size(); ++i) {
78a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      DVLOG(1) << "  App data " << i << " "
79a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)               << data_message.app_data(i).key() << " : "
80a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)               << data_message.app_data(i).value();
81a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
82a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
83a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
84a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
85a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void MessageSentCallback(const std::string& local_id) {
86a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  LOG(INFO) << "Message sent. Status: " << local_id;
87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
88a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
89a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Needed to use a real host resolver.
90a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class MyTestURLRequestContext : public net::TestURLRequestContext {
91a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) public:
92a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  MyTestURLRequestContext() : TestURLRequestContext(true) {
93a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    context_storage_.set_host_resolver(
94a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        net::HostResolver::CreateDefaultResolver(NULL));
95a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    context_storage_.set_transport_security_state(
96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        new net::TransportSecurityState());
97a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    Init();
98a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
99a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual ~MyTestURLRequestContext() {}
101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)};
102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class MyTestURLRequestContextGetter : public net::TestURLRequestContextGetter {
104a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) public:
105a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  explicit MyTestURLRequestContextGetter(
106a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      const scoped_refptr<base::MessageLoopProxy>& io_message_loop_proxy)
107a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      : TestURLRequestContextGetter(io_message_loop_proxy) {}
108a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
109a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual net::TestURLRequestContext* GetURLRequestContext() OVERRIDE {
110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // Construct |context_| lazily so it gets constructed on the right
111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // thread (the IO thread).
112a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (!context_)
113a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      context_.reset(new MyTestURLRequestContext());
114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return context_.get();
115a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
117a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) private:
118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual ~MyTestURLRequestContextGetter() {}
119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
120a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<MyTestURLRequestContext> context_;
121a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)};
122a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
123a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// A net log that logs all events by default.
124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class MyTestNetLog : public net::NetLog {
125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) public:
126a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  MyTestNetLog() {
127a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    SetBaseLogLevel(LOG_ALL);
128a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
129a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual ~MyTestNetLog() {}
130a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)};
131a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
132a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// A cert verifier that access all certificates.
133a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class MyTestCertVerifier : public net::CertVerifier {
134a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) public:
135a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  MyTestCertVerifier() {}
136a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual ~MyTestCertVerifier() {}
137a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
138a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual int Verify(net::X509Certificate* cert,
139a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                     const std::string& hostname,
140a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                     int flags,
141a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                     net::CRLSet* crl_set,
142a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                     net::CertVerifyResult* verify_result,
143a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                     const net::CompletionCallback& callback,
144a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                     RequestHandle* out_req,
145a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                     const net::BoundNetLog& net_log) OVERRIDE {
146a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return net::OK;
147a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
148a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
149a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual void CancelRequest(RequestHandle req) OVERRIDE {
150a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // Do nothing.
151a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
152a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)};
153a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
154a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class MCSProbe {
155a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) public:
156a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  MCSProbe(
157a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      const CommandLine& command_line,
158a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      scoped_refptr<net::URLRequestContextGetter> url_request_context_getter);
159a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ~MCSProbe();
160a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
161a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  void Start();
162a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
163a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  uint64 android_id() const { return android_id_; }
164a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  uint64 secret() const { return secret_; }
165a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
166a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) private:
167a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  void InitializeNetworkState();
168a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  void BuildNetworkSession();
169a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
170a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  void InitializationCallback(bool success,
171a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                              uint64 restored_android_id,
172a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                              uint64 restored_security_token);
173a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
174a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  CommandLine command_line_;
175a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
176a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::FilePath rmq_path_;
177a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  uint64 android_id_;
178a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  uint64 secret_;
179a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  std::string server_host_;
180a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  int server_port_;
181a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
182a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Network state.
183a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
184a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  MyTestNetLog net_log_;
185a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<net::NetLogLogger> logger_;
186a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<base::Value> net_constants_;
187a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<net::HostResolver> host_resolver_;
188a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<net::CertVerifier> cert_verifier_;
189a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<net::ServerBoundCertService> system_server_bound_cert_service_;
190a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<net::TransportSecurityState> transport_security_state_;
191a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<net::URLSecurityManager> url_security_manager_;
192a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<net::HttpAuthHandlerFactory> http_auth_handler_factory_;
193a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<net::HttpServerPropertiesImpl> http_server_properties_;
194a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<net::HostMappingRules> host_mapping_rules_;
195a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_refptr<net::HttpNetworkSession> network_session_;
196a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<net::ProxyService> proxy_service_;
197a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
198a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<MCSClient> mcs_client_;
199a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
200a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<ConnectionFactoryImpl> connection_factory_;
201a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
202a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::Thread file_thread_;
203a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
204a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<base::RunLoop> run_loop_;
205a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)};
206a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
207a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)MCSProbe::MCSProbe(
208a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const CommandLine& command_line,
209a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    scoped_refptr<net::URLRequestContextGetter> url_request_context_getter)
210a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    : command_line_(command_line),
211a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      rmq_path_(base::FilePath(FILE_PATH_LITERAL("gcm_rmq_store"))),
212a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      android_id_(0),
213a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      secret_(0),
214a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      server_port_(0),
215a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      url_request_context_getter_(url_request_context_getter),
216a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      file_thread_("FileThread") {
217a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (command_line.HasSwitch(kRMQFileName)) {
218a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    rmq_path_ = command_line.GetSwitchValuePath(kRMQFileName);
219a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
220a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (command_line.HasSwitch(kAndroidIdSwitch)) {
221a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::StringToUint64(command_line.GetSwitchValueASCII(kAndroidIdSwitch),
222a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                         &android_id_);
223a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
224a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (command_line.HasSwitch(kSecretSwitch)) {
225a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::StringToUint64(command_line.GetSwitchValueASCII(kSecretSwitch),
226a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                         &secret_);
227a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
228a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  server_host_ = kMCSServerHost;
229a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (command_line.HasSwitch(kServerHostSwitch)) {
230a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    server_host_ = command_line.GetSwitchValueASCII(kServerHostSwitch);
231a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
232a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  server_port_ = kMCSServerPort;
233a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (command_line.HasSwitch(kServerPortSwitch)) {
234a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::StringToInt(command_line.GetSwitchValueASCII(kServerPortSwitch),
235a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                      &server_port_);
236a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
237a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
238a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
239a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)MCSProbe::~MCSProbe() {
240a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  file_thread_.Stop();
241a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
242a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
243a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void MCSProbe::Start() {
244a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  file_thread_.Start();
245a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  InitializeNetworkState();
246a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  BuildNetworkSession();
247a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  connection_factory_.reset(
248a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      new ConnectionFactoryImpl(GURL("https://" + net::HostPortPair(
249a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                    server_host_, server_port_).ToString()),
250a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                network_session_,
251a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                &net_log_));
252a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  mcs_client_.reset(new MCSClient(rmq_path_,
253a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                  connection_factory_.get(),
254a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                  file_thread_.message_loop_proxy()));
255a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  run_loop_.reset(new base::RunLoop());
256a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  mcs_client_->Initialize(base::Bind(&MCSProbe::InitializationCallback,
257a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                     base::Unretained(this)),
258a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                          base::Bind(&MessageReceivedCallback),
259a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                          base::Bind(&MessageSentCallback));
260a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  run_loop_->Run();
261a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
262a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
263a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void MCSProbe::InitializeNetworkState() {
264a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  FILE* log_file = NULL;
265a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (command_line_.HasSwitch(kLogFileSwitch)) {
266a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::FilePath log_path = command_line_.GetSwitchValuePath(kLogFileSwitch);
267a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#if defined(OS_WIN)
268a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    log_file = _wfopen(log_path.value().c_str(), L"w");
269a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#elif defined(OS_POSIX)
270a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    log_file = fopen(log_path.value().c_str(), "w");
271a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#endif
272a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
273a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  net_constants_.reset(net::NetLogLogger::GetConstants());
274a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (log_file != NULL) {
275a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    logger_.reset(new net::NetLogLogger(log_file, *net_constants_));
276a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    logger_->StartObserving(&net_log_);
277a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
278a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
279a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  host_resolver_ = net::HostResolver::CreateDefaultResolver(&net_log_);
280a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
281a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (command_line_.HasSwitch(kIgnoreCertSwitch)) {
282a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    cert_verifier_.reset(new MyTestCertVerifier());
283a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  } else {
284a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    cert_verifier_.reset(net::CertVerifier::CreateDefault());
285a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
286a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  system_server_bound_cert_service_.reset(
287a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      new net::ServerBoundCertService(
288a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          new net::DefaultServerBoundCertStore(NULL),
289a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          base::WorkerPool::GetTaskRunner(true)));
290a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
291a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  transport_security_state_.reset(new net::TransportSecurityState());
292a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  url_security_manager_.reset(net::URLSecurityManager::Create(NULL, NULL));
293a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  http_auth_handler_factory_.reset(
294a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      net::HttpAuthHandlerRegistryFactory::Create(
295a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          std::vector<std::string>(1, "basic"),
296a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          url_security_manager_.get(),
297a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          host_resolver_.get(),
298a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          std::string(),
299a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          false,
300a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          false));
301a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  http_server_properties_.reset(new net::HttpServerPropertiesImpl());
302a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  host_mapping_rules_.reset(new net::HostMappingRules());
303a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  proxy_service_.reset(net::ProxyService::CreateDirectWithNetLog(&net_log_));
304a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
305a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
306a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void MCSProbe::BuildNetworkSession() {
307a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  net::HttpNetworkSession::Params session_params;
308a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  session_params.host_resolver = host_resolver_.get();
309a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  session_params.cert_verifier = cert_verifier_.get();
310a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  session_params.server_bound_cert_service =
311a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      system_server_bound_cert_service_.get();
312a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  session_params.transport_security_state = transport_security_state_.get();
313a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  session_params.ssl_config_service = new net::SSLConfigServiceDefaults();
314a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  session_params.http_auth_handler_factory = http_auth_handler_factory_.get();
315a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  session_params.http_server_properties =
316a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      http_server_properties_->GetWeakPtr();
317a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  session_params.network_delegate = NULL;  // TODO(zea): implement?
318a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  session_params.host_mapping_rules = host_mapping_rules_.get();
319a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  session_params.ignore_certificate_errors = true;
320a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  session_params.http_pipelining_enabled = false;
321a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  session_params.testing_fixed_http_port = 0;
322a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  session_params.testing_fixed_https_port = 0;
323a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  session_params.net_log = &net_log_;
324a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  session_params.proxy_service = proxy_service_.get();
325a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
326a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  network_session_ = new net::HttpNetworkSession(session_params);
327a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
328a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
329a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void MCSProbe::InitializationCallback(bool success,
330a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                      uint64 restored_android_id,
331a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                      uint64 restored_security_token) {
332a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  LOG(INFO) << "Initialization " << (success ? "success!" : "failure!");
333a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (restored_android_id && restored_security_token) {
334a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    android_id_ = restored_android_id;
335a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    secret_ = restored_security_token;
336a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
337a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (success)
338a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    mcs_client_->Login(android_id_, secret_);
339a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
340a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
341a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)int MCSProbeMain(int argc, char* argv[]) {
342a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::AtExitManager exit_manager;
343a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
344a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  CommandLine::Init(argc, argv);
345a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  logging::LoggingSettings settings;
346a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
347a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  logging::InitLogging(settings);
348a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
349a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::MessageLoopForIO message_loop;
350a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
351a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // For check-in and creating registration ids.
352a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const scoped_refptr<MyTestURLRequestContextGetter> context_getter =
353a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      new MyTestURLRequestContextGetter(
354a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          base::MessageLoop::current()->message_loop_proxy());
355a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
356a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
357a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
358a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  MCSProbe mcs_probe(command_line, context_getter);
359a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  mcs_probe.Start();
360a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
361a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::RunLoop run_loop;
362a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  run_loop.Run();
363a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
364a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return 0;
365a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
366a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
367a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}  // namespace
368a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}  // namespace gcm
369a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
370a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)int main(int argc, char* argv[]) {
371a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return gcm::MCSProbeMain(argc, argv);
372a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
373