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>
11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include <vector>
12a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
13a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/at_exit.h"
14a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/command_line.h"
15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/compiler_specific.h"
16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/logging.h"
17a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/memory/ref_counted.h"
18a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
19a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/message_loop/message_loop.h"
20a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/run_loop.h"
21a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/strings/string_number_conversions.h"
22a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/threading/thread.h"
23a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/threading/worker_pool.h"
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/time/default_clock.h"
25a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/values.h"
26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "google_apis/gcm/base/fake_encryptor.h"
27a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "google_apis/gcm/base/mcs_message.h"
28a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "google_apis/gcm/base/mcs_util.h"
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "google_apis/gcm/engine/checkin_request.h"
30a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "google_apis/gcm/engine/connection_factory_impl.h"
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "google_apis/gcm/engine/gcm_store_impl.h"
32010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "google_apis/gcm/engine/gservices_settings.h"
33a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "google_apis/gcm/engine/mcs_client.h"
3446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "google_apis/gcm/monitoring/fake_gcm_stats_recorder.h"
35a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/base/host_mapping_rules.h"
36a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/base/net_log_logger.h"
37a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/cert/cert_verifier.h"
38a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/dns/host_resolver.h"
39a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/http/http_auth_handler_factory.h"
40a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/http/http_network_session.h"
41a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/http/http_server_properties_impl.h"
42a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/http/transport_security_state.h"
43a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/socket/client_socket_factory.h"
44a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/socket/ssl_client_socket.h"
45a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/ssl/default_server_bound_cert_store.h"
46a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/ssl/server_bound_cert_service.h"
47a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/url_request/url_request_test_util.h"
48a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
49a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#if defined(OS_MACOSX)
50a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/mac/scoped_nsautorelease_pool.h"
51a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#endif
52a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
53a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// This is a simple utility that initializes an mcs client and
54a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// prints out any events.
55a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace gcm {
56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace {
57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const net::BackoffEntry::Policy kDefaultBackoffPolicy = {
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Number of initial errors (in sequence) to ignore before applying
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // exponential back-off rules.
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  0,
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Initial delay for exponential back-off in ms.
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  15000,  // 15 seconds.
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Factor by which the waiting time will be multiplied.
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  2,
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Fuzzing percentage. ex: 10% will spread requests randomly
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // between 90%-100% of the calculated time.
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  0.5,  // 50%.
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Maximum amount of time we are willing to delay our request in ms.
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  1000 * 60 * 5, // 5 minutes.
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Time to keep an entry from being discarded even when it
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // has no significant state, -1 to never discard.
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  -1,
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Don't use initial delay unless the last request was an error.
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  false,
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Default values used to communicate with the check-in server.
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kChromeVersion[] = "Chrome MCS Probe";
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// The default server to communicate with.
88a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const char kMCSServerHost[] = "mtalk.google.com";
89a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const uint16 kMCSServerPort = 5228;
90a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
91a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Command line switches.
92a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const char kRMQFileName[] = "rmq_file";
93a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const char kAndroidIdSwitch[] = "android_id";
94a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const char kSecretSwitch[] = "secret";
95a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const char kLogFileSwitch[] = "log-file";
96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const char kIgnoreCertSwitch[] = "ignore-certs";
97a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const char kServerHostSwitch[] = "host";
98a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const char kServerPortSwitch[] = "port";
99a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void MessageReceivedCallback(const MCSMessage& message) {
101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  LOG(INFO) << "Received message with id "
102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            << GetPersistentId(message.GetProtobuf()) << " and tag "
103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            << static_cast<int>(message.tag());
104a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
105a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (message.tag() == kDataMessageStanzaTag) {
106a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const mcs_proto::DataMessageStanza& data_message =
107a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        reinterpret_cast<const mcs_proto::DataMessageStanza&>(
108a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            message.GetProtobuf());
109a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DVLOG(1) << "  to: " << data_message.to();
110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DVLOG(1) << "  from: " << data_message.from();
111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DVLOG(1) << "  category: " << data_message.category();
112a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DVLOG(1) << "  sent: " << data_message.sent();
113a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    for (int i = 0; i < data_message.app_data_size(); ++i) {
114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      DVLOG(1) << "  App data " << i << " "
115a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)               << data_message.app_data(i).key() << " : "
116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)               << data_message.app_data(i).value();
117a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
120a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MessageSentCallback(int64 user_serial_number,
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                         const std::string& app_id,
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                         const std::string& message_id,
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                         MCSClient::MessageSendStatus status) {
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  LOG(INFO) << "Message sent. Serial number: " << user_serial_number
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            << " Application ID: " << app_id
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            << " Message ID: " << message_id
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            << " Message send status: " << status;
129a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
130a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
131a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Needed to use a real host resolver.
132a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class MyTestURLRequestContext : public net::TestURLRequestContext {
133a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) public:
134a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  MyTestURLRequestContext() : TestURLRequestContext(true) {
135a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    context_storage_.set_host_resolver(
136a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        net::HostResolver::CreateDefaultResolver(NULL));
137a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    context_storage_.set_transport_security_state(
138a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        new net::TransportSecurityState());
139a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    Init();
140a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
141a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
142a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual ~MyTestURLRequestContext() {}
143a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)};
144a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
145a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class MyTestURLRequestContextGetter : public net::TestURLRequestContextGetter {
146a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) public:
147a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  explicit MyTestURLRequestContextGetter(
148a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      const scoped_refptr<base::MessageLoopProxy>& io_message_loop_proxy)
149a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      : TestURLRequestContextGetter(io_message_loop_proxy) {}
150a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
151a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual net::TestURLRequestContext* GetURLRequestContext() OVERRIDE {
152a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // Construct |context_| lazily so it gets constructed on the right
153a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // thread (the IO thread).
154a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (!context_)
155a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      context_.reset(new MyTestURLRequestContext());
156a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return context_.get();
157a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
158a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
159a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) private:
160a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual ~MyTestURLRequestContextGetter() {}
161a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
162a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<MyTestURLRequestContext> context_;
163a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)};
164a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
165a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// A net log that logs all events by default.
166a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class MyTestNetLog : public net::NetLog {
167a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) public:
168a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  MyTestNetLog() {
169a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    SetBaseLogLevel(LOG_ALL);
170a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
171a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual ~MyTestNetLog() {}
172a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)};
173a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
174a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// A cert verifier that access all certificates.
175a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class MyTestCertVerifier : public net::CertVerifier {
176a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) public:
177a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  MyTestCertVerifier() {}
178a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual ~MyTestCertVerifier() {}
179a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
180a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual int Verify(net::X509Certificate* cert,
181a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                     const std::string& hostname,
182a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                     int flags,
183a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                     net::CRLSet* crl_set,
184a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                     net::CertVerifyResult* verify_result,
185a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                     const net::CompletionCallback& callback,
186a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                     RequestHandle* out_req,
187a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                     const net::BoundNetLog& net_log) OVERRIDE {
188a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return net::OK;
189a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
190a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
191a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual void CancelRequest(RequestHandle req) OVERRIDE {
192a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // Do nothing.
193a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
194a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)};
195a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
196a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class MCSProbe {
197a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) public:
198a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  MCSProbe(
199a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      const CommandLine& command_line,
200a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      scoped_refptr<net::URLRequestContextGetter> url_request_context_getter);
201a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ~MCSProbe();
202a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
203a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  void Start();
204a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
205a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  uint64 android_id() const { return android_id_; }
206a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  uint64 secret() const { return secret_; }
207a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
208a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) private:
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void CheckIn();
210a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  void InitializeNetworkState();
211a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  void BuildNetworkSession();
212a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void LoadCallback(scoped_ptr<GCMStore::LoadResult> load_result);
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void UpdateCallback(bool success);
2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void ErrorCallback();
216a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  void OnCheckInCompleted(
217a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      const checkin_proto::AndroidCheckinResponse& checkin_response);
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void StartMCSLogin();
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DefaultClock clock_;
221a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
222a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  CommandLine command_line_;
223a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::FilePath gcm_store_path_;
225a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  uint64 android_id_;
226a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  uint64 secret_;
227a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  std::string server_host_;
228a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  int server_port_;
229a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
230a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Network state.
231a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
232a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  MyTestNetLog net_log_;
233a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<net::NetLogLogger> logger_;
234a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<base::Value> net_constants_;
235a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<net::HostResolver> host_resolver_;
236a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<net::CertVerifier> cert_verifier_;
237a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<net::ServerBoundCertService> system_server_bound_cert_service_;
238a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<net::TransportSecurityState> transport_security_state_;
239a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<net::URLSecurityManager> url_security_manager_;
240a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<net::HttpAuthHandlerFactory> http_auth_handler_factory_;
241a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<net::HttpServerPropertiesImpl> http_server_properties_;
242a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<net::HostMappingRules> host_mapping_rules_;
243a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_refptr<net::HttpNetworkSession> network_session_;
244a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<net::ProxyService> proxy_service_;
245a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
24646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  FakeGCMStatsRecorder recorder_;
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<GCMStore> gcm_store_;
248a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<MCSClient> mcs_client_;
2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<CheckinRequest> checkin_request_;
250a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
251a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<ConnectionFactoryImpl> connection_factory_;
252a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
253a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::Thread file_thread_;
254a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
255a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<base::RunLoop> run_loop_;
256a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)};
257a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
258a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)MCSProbe::MCSProbe(
259a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const CommandLine& command_line,
260a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    scoped_refptr<net::URLRequestContextGetter> url_request_context_getter)
261a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    : command_line_(command_line),
2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      gcm_store_path_(base::FilePath(FILE_PATH_LITERAL("gcm_store"))),
263a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      android_id_(0),
264a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      secret_(0),
265a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      server_port_(0),
266a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      url_request_context_getter_(url_request_context_getter),
267a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      file_thread_("FileThread") {
268a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (command_line.HasSwitch(kRMQFileName)) {
2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    gcm_store_path_ = command_line.GetSwitchValuePath(kRMQFileName);
270a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
271a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (command_line.HasSwitch(kAndroidIdSwitch)) {
272a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::StringToUint64(command_line.GetSwitchValueASCII(kAndroidIdSwitch),
273a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                         &android_id_);
274a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
275a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (command_line.HasSwitch(kSecretSwitch)) {
276a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::StringToUint64(command_line.GetSwitchValueASCII(kSecretSwitch),
277a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                         &secret_);
278a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
279a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  server_host_ = kMCSServerHost;
280a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (command_line.HasSwitch(kServerHostSwitch)) {
281a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    server_host_ = command_line.GetSwitchValueASCII(kServerHostSwitch);
282a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
283a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  server_port_ = kMCSServerPort;
284a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (command_line.HasSwitch(kServerPortSwitch)) {
285a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::StringToInt(command_line.GetSwitchValueASCII(kServerPortSwitch),
286a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                      &server_port_);
287a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
288a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
289a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
290a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)MCSProbe::~MCSProbe() {
291a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  file_thread_.Stop();
292a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
293a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
294a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void MCSProbe::Start() {
295a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  file_thread_.Start();
296a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  InitializeNetworkState();
297a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  BuildNetworkSession();
298effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  std::vector<GURL> endpoints(1,
299effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                              GURL("https://" +
300effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                   net::HostPortPair(server_host_,
301effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                                     server_port_).ToString()));
302a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  connection_factory_.reset(
303effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      new ConnectionFactoryImpl(endpoints,
3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                kDefaultBackoffPolicy,
305a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                network_session_,
3065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                &net_log_,
3075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                &recorder_));
3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gcm_store_.reset(
309a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      new GCMStoreImpl(gcm_store_path_,
310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                       file_thread_.message_loop_proxy(),
311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                       make_scoped_ptr<Encryptor>(new FakeEncryptor)));
312a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  mcs_client_.reset(new MCSClient("probe",
313a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                  &clock_,
314a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                  connection_factory_.get(),
3150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                  gcm_store_.get(),
3160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                  &recorder_));
317a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  run_loop_.reset(new base::RunLoop());
3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gcm_store_->Load(base::Bind(&MCSProbe::LoadCallback,
3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              base::Unretained(this)));
320a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  run_loop_->Run();
321a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
322a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MCSProbe::LoadCallback(scoped_ptr<GCMStore::LoadResult> load_result) {
3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(load_result->success);
3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (android_id_ != 0 && secret_ != 0) {
3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DVLOG(1) << "Presetting MCS id " << android_id_;
3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    load_result->device_android_id = android_id_;
3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    load_result->device_security_token = secret_;
3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    gcm_store_->SetDeviceCredentials(android_id_,
3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     secret_,
3315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     base::Bind(&MCSProbe::UpdateCallback,
3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                base::Unretained(this)));
3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    android_id_ = load_result->device_android_id;
3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    secret_ = load_result->device_security_token;
3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DVLOG(1) << "Loaded MCS id " << android_id_;
3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  mcs_client_->Initialize(
3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(&MCSProbe::ErrorCallback, base::Unretained(this)),
3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(&MessageReceivedCallback),
3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(&MessageSentCallback),
3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      load_result.Pass());
3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!android_id_ || !secret_) {
3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DVLOG(1) << "Checkin to generate new MCS credentials.";
3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CheckIn();
3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  StartMCSLogin();
3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MCSProbe::UpdateCallback(bool success) {
3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
356a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void MCSProbe::InitializeNetworkState() {
357a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  FILE* log_file = NULL;
358a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (command_line_.HasSwitch(kLogFileSwitch)) {
359a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::FilePath log_path = command_line_.GetSwitchValuePath(kLogFileSwitch);
360a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#if defined(OS_WIN)
361a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    log_file = _wfopen(log_path.value().c_str(), L"w");
362a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#elif defined(OS_POSIX)
363a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    log_file = fopen(log_path.value().c_str(), "w");
364a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#endif
365a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
366a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  net_constants_.reset(net::NetLogLogger::GetConstants());
367a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (log_file != NULL) {
368a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    logger_.reset(new net::NetLogLogger(log_file, *net_constants_));
369a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    logger_->StartObserving(&net_log_);
370a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
371a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
372a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  host_resolver_ = net::HostResolver::CreateDefaultResolver(&net_log_);
373a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
374a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (command_line_.HasSwitch(kIgnoreCertSwitch)) {
375a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    cert_verifier_.reset(new MyTestCertVerifier());
376a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  } else {
377a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    cert_verifier_.reset(net::CertVerifier::CreateDefault());
378a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
379a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  system_server_bound_cert_service_.reset(
380a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      new net::ServerBoundCertService(
381a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          new net::DefaultServerBoundCertStore(NULL),
382a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          base::WorkerPool::GetTaskRunner(true)));
383a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
384a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  transport_security_state_.reset(new net::TransportSecurityState());
385a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  url_security_manager_.reset(net::URLSecurityManager::Create(NULL, NULL));
386a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  http_auth_handler_factory_.reset(
387a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      net::HttpAuthHandlerRegistryFactory::Create(
388a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          std::vector<std::string>(1, "basic"),
389a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          url_security_manager_.get(),
390a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          host_resolver_.get(),
391a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          std::string(),
392a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          false,
393a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          false));
394a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  http_server_properties_.reset(new net::HttpServerPropertiesImpl());
395a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  host_mapping_rules_.reset(new net::HostMappingRules());
396a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  proxy_service_.reset(net::ProxyService::CreateDirectWithNetLog(&net_log_));
397a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
398a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
399a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void MCSProbe::BuildNetworkSession() {
400a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  net::HttpNetworkSession::Params session_params;
401a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  session_params.host_resolver = host_resolver_.get();
402a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  session_params.cert_verifier = cert_verifier_.get();
403a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  session_params.server_bound_cert_service =
404a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      system_server_bound_cert_service_.get();
405a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  session_params.transport_security_state = transport_security_state_.get();
406a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  session_params.ssl_config_service = new net::SSLConfigServiceDefaults();
407a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  session_params.http_auth_handler_factory = http_auth_handler_factory_.get();
408a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  session_params.http_server_properties =
409a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      http_server_properties_->GetWeakPtr();
410a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  session_params.network_delegate = NULL;  // TODO(zea): implement?
411a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  session_params.host_mapping_rules = host_mapping_rules_.get();
412a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  session_params.ignore_certificate_errors = true;
413a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  session_params.testing_fixed_http_port = 0;
414a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  session_params.testing_fixed_https_port = 0;
415a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  session_params.net_log = &net_log_;
416a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  session_params.proxy_service = proxy_service_.get();
417a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
418a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  network_session_ = new net::HttpNetworkSession(session_params);
419a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
420a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MCSProbe::ErrorCallback() {
4225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  LOG(INFO) << "MCS error happened";
4235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MCSProbe::CheckIn() {
4265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  LOG(INFO) << "Check-in request initiated.";
4275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  checkin_proto::ChromeBuildProto chrome_build_proto;
4285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  chrome_build_proto.set_platform(
4295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      checkin_proto::ChromeBuildProto::PLATFORM_LINUX);
4305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  chrome_build_proto.set_channel(
4315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      checkin_proto::ChromeBuildProto::CHANNEL_CANARY);
4325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  chrome_build_proto.set_chrome_version(kChromeVersion);
433a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
434a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  CheckinRequest::RequestInfo request_info(
435f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      0, 0, std::string(), chrome_build_proto);
436a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
4375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  checkin_request_.reset(new CheckinRequest(
438010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      GServicesSettings::DefaultCheckinURL(),
439a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      request_info,
4405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      kDefaultBackoffPolicy,
441a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      base::Bind(&MCSProbe::OnCheckInCompleted, base::Unretained(this)),
442010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      url_request_context_getter_.get(),
443010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      &recorder_));
4445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  checkin_request_->Start();
4455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
447a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid MCSProbe::OnCheckInCompleted(
448a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const checkin_proto::AndroidCheckinResponse& checkin_response) {
449a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  bool success = checkin_response.has_android_id() &&
450a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                 checkin_response.android_id() != 0UL &&
451a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                 checkin_response.has_security_token() &&
452a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                 checkin_response.security_token() != 0UL;
4535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  LOG(INFO) << "Check-in request completion "
454a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch            << (success ? "success!" : "failure!");
455a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
456a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!success)
4575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
458a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
459a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  android_id_ = checkin_response.android_id();
460a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  secret_ = checkin_response.security_token();
4615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gcm_store_->SetDeviceCredentials(android_id_,
4635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   secret_,
4645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   base::Bind(&MCSProbe::UpdateCallback,
4655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                              base::Unretained(this)));
4665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  StartMCSLogin();
4685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MCSProbe::StartMCSLogin() {
4715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  LOG(INFO) << "MCS login initiated.";
4725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  mcs_client_->Login(android_id_, secret_);
474a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
475a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
476a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)int MCSProbeMain(int argc, char* argv[]) {
477a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::AtExitManager exit_manager;
478a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
479a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  CommandLine::Init(argc, argv);
480a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  logging::LoggingSettings settings;
481a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
482a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  logging::InitLogging(settings);
483a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
484a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::MessageLoopForIO message_loop;
485a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
486a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // For check-in and creating registration ids.
487a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const scoped_refptr<MyTestURLRequestContextGetter> context_getter =
488a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      new MyTestURLRequestContextGetter(
489a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          base::MessageLoop::current()->message_loop_proxy());
490a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
491a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
492a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
493a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  MCSProbe mcs_probe(command_line, context_getter);
494a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  mcs_probe.Start();
495a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
496a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::RunLoop run_loop;
497a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  run_loop.Run();
498a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
499a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return 0;
500a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
501a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
502a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}  // namespace
503a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}  // namespace gcm
504a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
505a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)int main(int argc, char* argv[]) {
506a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return gcm::MCSProbeMain(argc, argv);
507a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
508