172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 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 "net/test/test_server.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <algorithm>
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <string>
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <vector>
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "build/build_config.h"
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#if defined(OS_MACOSX)
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/x509_certificate.h"
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
174a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "base/base64.h"
183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/command_line.h"
19513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/debug/leak_annotations.h"
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/file_util.h"
21ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/json/json_reader.h"
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/logging.h"
23ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h"
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/path_service.h"
253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_number_conversions.h"
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/utf_string_conversions.h"
27201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include "base/values.h"
283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "googleurl/src/gurl.h"
293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/base/host_port_pair.h"
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/host_resolver.h"
3172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "net/base/net_errors.h"
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/test_completion_callback.h"
3321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "net/base/test_root_certs.h"
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/socket/tcp_client_socket.h"
353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/test/python_utils.h"
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "testing/platform_test.h"
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
38513209b27ff55e2841eac0e4120199c23acce758Ben Murdochnamespace net {
39513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merricknamespace {
413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Number of connection attempts for tests.
433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst int kServerConnectionAttempts = 10;
443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Connection timeout in milliseconds for tests.
463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst int kServerConnectionTimeoutMs = 1000;
473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
48513209b27ff55e2841eac0e4120199c23acce758Ben Murdochstd::string GetHostname(TestServer::Type type,
49513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                        const TestServer::HTTPSOptions& options) {
50513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (type == TestServer::TYPE_HTTPS &&
51513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      options.server_certificate ==
52513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch          TestServer::HTTPSOptions::CERT_MISMATCHED_NAME) {
533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Return a different hostname string that resolves to the same hostname.
543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return "localhost";
553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return "127.0.0.1";
583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}  // namespace
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
62513209b27ff55e2841eac0e4120199c23acce758Ben MurdochTestServer::HTTPSOptions::HTTPSOptions()
63513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    : server_certificate(CERT_OK),
64513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      request_client_certificate(false),
65513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      bulk_ciphers(HTTPSOptions::BULK_CIPHER_ANY) {}
66513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
67513209b27ff55e2841eac0e4120199c23acce758Ben MurdochTestServer::HTTPSOptions::HTTPSOptions(
68513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    TestServer::HTTPSOptions::ServerCertificate cert)
69513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    : server_certificate(cert),
70513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      request_client_certificate(false),
71513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      bulk_ciphers(HTTPSOptions::BULK_CIPHER_ANY) {}
72513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
73513209b27ff55e2841eac0e4120199c23acce758Ben MurdochTestServer::HTTPSOptions::~HTTPSOptions() {}
74513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
75513209b27ff55e2841eac0e4120199c23acce758Ben MurdochFilePath TestServer::HTTPSOptions::GetCertificateFile() const {
76513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  switch (server_certificate) {
77513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    case CERT_OK:
78513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    case CERT_MISMATCHED_NAME:
79513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      return FilePath(FILE_PATH_LITERAL("ok_cert.pem"));
80513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    case CERT_EXPIRED:
81513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      return FilePath(FILE_PATH_LITERAL("expired_cert.pem"));
82513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    default:
83513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      NOTREACHED();
84513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
85513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return FilePath();
86513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
87513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
883345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTestServer::TestServer(Type type, const FilePath& document_root)
894a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    : type_(type),
904a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      started_(false) {
91513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  Init(document_root);
92513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
93513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
94513209b27ff55e2841eac0e4120199c23acce758Ben MurdochTestServer::TestServer(const HTTPSOptions& https_options,
95513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                       const FilePath& document_root)
964a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    : https_options_(https_options),
974a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      type_(TYPE_HTTPS),
984a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      started_(false) {
99513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  Init(document_root);
100513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
101513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
102513209b27ff55e2841eac0e4120199c23acce758Ben MurdochTestServer::~TestServer() {
10321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  TestRootCerts* root_certs = TestRootCerts::GetInstance();
10421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  root_certs->Clear();
105513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  Stop();
106513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
107513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
1083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool TestServer::Start() {
109513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (type_ == TYPE_HTTPS) {
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!LoadTestRootCert())
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return false;
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Get path to python server script
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  FilePath testserver_path;
1163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!PathService::Get(base::DIR_SOURCE_ROOT, &testserver_path)) {
1173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    LOG(ERROR) << "Failed to get DIR_SOURCE_ROOT";
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
1193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  testserver_path = testserver_path
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      .Append(FILE_PATH_LITERAL("net"))
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      .Append(FILE_PATH_LITERAL("tools"))
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      .Append(FILE_PATH_LITERAL("testserver"))
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      .Append(FILE_PATH_LITERAL("testserver.py"));
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!SetPythonPath())
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
1283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!LaunchPython(testserver_path))
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!WaitToStart()) {
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Stop();
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
13721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  allowed_port_.reset(new ScopedPortException(host_port_pair_.port()));
13821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
1394a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  started_ = true;
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool TestServer::Stop() {
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!process_handle_)
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return true;
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1474a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  started_ = false;
1484a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // First check if the process has already terminated.
1503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  bool ret = base::WaitForSingleProcess(process_handle_, 0);
1513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!ret)
1523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    ret = base::KillProcess(process_handle_, 1, true);
1533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (ret) {
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    base::CloseProcessHandle(process_handle_);
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    process_handle_ = base::kNullProcessHandle;
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
158731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    VLOG(1) << "Kill failed?";
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
1603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
16121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  allowed_port_.reset();
16221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return ret;
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1664a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochconst HostPortPair& TestServer::host_port_pair() const {
1674a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  DCHECK(started_);
1684a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  return host_port_pair_;
1694a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch}
1704a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
171201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochconst DictionaryValue& TestServer::server_data() const {
172201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  DCHECK(started_);
173201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return *server_data_;
174201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
175201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
1763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstd::string TestServer::GetScheme() const {
1773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  switch (type_) {
1783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case TYPE_FTP:
1793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return "ftp";
1803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case TYPE_HTTP:
1814a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    case TYPE_SYNC:
1823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return "http";
1833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case TYPE_HTTPS:
1843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return "https";
1853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    default:
1863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      NOTREACHED();
1873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
1883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return std::string();
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool TestServer::GetAddressList(AddressList* address_list) const {
1923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK(address_list);
1933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
194731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  scoped_ptr<HostResolver> resolver(
195513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      CreateSystemHostResolver(HostResolver::kDefaultParallelism, NULL, NULL));
1963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HostResolver::RequestInfo info(host_port_pair_);
1973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int rv = resolver->Resolve(info, address_list, NULL, NULL, BoundNetLog());
1983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (rv != net::OK) {
1993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    LOG(ERROR) << "Failed to resolve hostname: " << host_port_pair_.host();
2003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return false;
2013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
2023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return true;
2033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
2043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2054a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben MurdochGURL TestServer::GetURL(const std::string& path) const {
2063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return GURL(GetScheme() + "://" + host_port_pair_.ToString() +
2073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick              "/" + path);
2083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
2093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2103345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickGURL TestServer::GetURLWithUser(const std::string& path,
2114a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                                const std::string& user) const {
2123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return GURL(GetScheme() + "://" + user + "@" +
2133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick              host_port_pair_.ToString() +
2143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick              "/" + path);
2153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
2163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2173345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickGURL TestServer::GetURLWithUserAndPassword(const std::string& path,
2183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                           const std::string& user,
2194a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                                           const std::string& password) const {
2203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return GURL(GetScheme() + "://" + user + ":" + password +
2213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick              "@" + host_port_pair_.ToString() +
2223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick              "/" + path);
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2254a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// static
2264a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochbool TestServer::GetFilePathWithReplacements(
2274a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    const std::string& original_file_path,
2284a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    const std::vector<StringPair>& text_to_replace,
2294a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    std::string* replacement_path) {
2304a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  std::string new_file_path = original_file_path;
2314a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  bool first_query_parameter = true;
2324a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  const std::vector<StringPair>::const_iterator end = text_to_replace.end();
2334a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  for (std::vector<StringPair>::const_iterator it = text_to_replace.begin();
2344a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch       it != end;
2354a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch       ++it) {
2364a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    const std::string& old_text = it->first;
2374a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    const std::string& new_text = it->second;
2384a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    std::string base64_old;
2394a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    std::string base64_new;
2404a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    if (!base::Base64Encode(old_text, &base64_old))
2414a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      return false;
2424a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    if (!base::Base64Encode(new_text, &base64_new))
2434a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      return false;
2444a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    if (first_query_parameter) {
2454a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      new_file_path += "?";
2464a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      first_query_parameter = false;
2474a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    } else {
2484a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      new_file_path += "&";
2494a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    }
2504a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    new_file_path += "replace_text=";
2514a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    new_file_path += base64_old;
2524a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    new_file_path += ":";
2534a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    new_file_path += base64_new;
2544a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  }
2554a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
2564a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  *replacement_path = new_file_path;
2574a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  return true;
2584a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch}
2594a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
26072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid TestServer::Init(const FilePath& document_root) {
26172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // At this point, the port that the testserver will listen on is unknown.
26272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // The testserver will listen on an ephemeral port, and write the port
26372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // number out over a pipe that this TestServer object will read from. Once
26472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // that is complete, the host_port_pair_ will contain the actual port.
26572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  host_port_pair_ = HostPortPair(GetHostname(type_, https_options_), 0);
26672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  process_handle_ = base::kNullProcessHandle;
26772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
26872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  FilePath src_dir;
26972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  PathService::Get(base::DIR_SOURCE_ROOT, &src_dir);
27072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
27172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  document_root_ = src_dir.Append(document_root);
27272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
27372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  certificates_dir_ = src_dir.Append(FILE_PATH_LITERAL("net"))
27472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                       .Append(FILE_PATH_LITERAL("data"))
27572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                       .Append(FILE_PATH_LITERAL("ssl"))
27672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                       .Append(FILE_PATH_LITERAL("certificates"));
27772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
27872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
2793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool TestServer::SetPythonPath() {
2803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  FilePath third_party_dir;
2813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!PathService::Get(base::DIR_SOURCE_ROOT, &third_party_dir)) {
2823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    LOG(ERROR) << "Failed to get DIR_SOURCE_ROOT";
2833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return false;
2843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
2853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  third_party_dir = third_party_dir.Append(FILE_PATH_LITERAL("third_party"));
2863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
287201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // For simplejson. (simplejson, unlike all the other python modules
288201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // we include, doesn't have an extra 'simplejson' directory, so we
289201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // need to include its parent directory, i.e. third_party_dir).
290201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  AppendToPythonPath(third_party_dir);
291201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
2923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  AppendToPythonPath(third_party_dir.Append(FILE_PATH_LITERAL("tlslite")));
2933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  AppendToPythonPath(third_party_dir.Append(FILE_PATH_LITERAL("pyftpdlib")));
2943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Locate the Python code generated by the protocol buffers compiler.
2964a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  FilePath pyproto_code_dir;
2974a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (!GetPyProtoPath(&pyproto_code_dir)) {
29872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    LOG(WARNING) << "Cannot find pyproto dir for generated code. "
29972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                 << "Testserver features that rely on it will not work";
30072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return true;
3013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
302731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
3034a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  AppendToPythonPath(pyproto_code_dir);
3044a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  AppendToPythonPath(pyproto_code_dir.Append(FILE_PATH_LITERAL("sync_pb")));
3054a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  AppendToPythonPath(pyproto_code_dir.Append(
3064a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      FILE_PATH_LITERAL("device_management_pb")));
3073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return true;
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
31172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool TestServer::ParseServerData(const std::string& server_data) {
31272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  VLOG(1) << "Server data: " << server_data;
31372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  base::JSONReader json_reader;
31472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  scoped_ptr<Value> value(json_reader.JsonToValue(server_data, true, false));
31572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!value.get() ||
31672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      !value->IsType(Value::TYPE_DICTIONARY)) {
31772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    LOG(ERROR) << "Could not parse server data: "
31872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen               << json_reader.GetErrorMessage();
31972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return false;
32072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
32172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  server_data_.reset(static_cast<DictionaryValue*>(value.release()));
32272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  int port = 0;
32372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!server_data_->GetInteger("port", &port)) {
32472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    LOG(ERROR) << "Could not find port value";
32572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return false;
32672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
32772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if ((port <= 0) || (port > kuint16max)) {
32872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    LOG(ERROR) << "Invalid port value: " << port;
32972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return false;
33072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
33172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  host_port_pair_.set_port(port);
33272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return true;
33372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
33472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
33572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenFilePath TestServer::GetRootCertificatePath() const {
3363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return certificates_dir_.AppendASCII("root_ca_cert.crt");
337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool TestServer::LoadTestRootCert() {
34021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  TestRootCerts* root_certs = TestRootCerts::GetInstance();
34121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return root_certs->AddFromFile(GetRootCertificatePath());
342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
344513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool TestServer::AddCommandLineArguments(CommandLine* command_line) const {
345513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  command_line->AppendSwitchASCII("port",
346513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                  base::IntToString(host_port_pair_.port()));
347513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  command_line->AppendSwitchPath("data-dir", document_root_);
34872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
34972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (logging::GetMinLogLevel() == logging::LOG_VERBOSE) {
35072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    command_line->AppendArg("--log-to-console");
35172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
352513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
353513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (type_ == TYPE_FTP) {
354513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    command_line->AppendArg("-f");
3554a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  } else if (type_ == TYPE_SYNC) {
3564a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    command_line->AppendArg("--sync");
357513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  } else if (type_ == TYPE_HTTPS) {
358513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    FilePath certificate_path(certificates_dir_);
359513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    certificate_path = certificate_path.Append(
360513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        https_options_.GetCertificateFile());
361513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (!file_util::PathExists(certificate_path)) {
362513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      LOG(ERROR) << "Certificate path " << certificate_path.value()
363513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                 << " doesn't exist. Can't launch https server.";
364513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      return false;
365513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    }
366513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    command_line->AppendSwitchPath("https", certificate_path);
367513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
368513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (https_options_.request_client_certificate)
369513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      command_line->AppendSwitch("ssl-client-auth");
370513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
371513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    for (std::vector<FilePath>::const_iterator it =
372513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch             https_options_.client_authorities.begin();
373513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch         it != https_options_.client_authorities.end(); ++it) {
374513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      if (!file_util::PathExists(*it)) {
375513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        LOG(ERROR) << "Client authority path " << it->value()
376513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                   << " doesn't exist. Can't launch https server.";
377513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        return false;
378513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      }
379513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
380513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      command_line->AppendSwitchPath("ssl-client-ca", *it);
381513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    }
382513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
383513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    const char kBulkCipherSwitch[] = "ssl-bulk-cipher";
384513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (https_options_.bulk_ciphers & HTTPSOptions::BULK_CIPHER_RC4)
385513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      command_line->AppendSwitchASCII(kBulkCipherSwitch, "rc4");
386513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (https_options_.bulk_ciphers & HTTPSOptions::BULK_CIPHER_AES128)
387513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      command_line->AppendSwitchASCII(kBulkCipherSwitch, "aes128");
388513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (https_options_.bulk_ciphers & HTTPSOptions::BULK_CIPHER_AES256)
389513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      command_line->AppendSwitchASCII(kBulkCipherSwitch, "aes256");
390513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (https_options_.bulk_ciphers & HTTPSOptions::BULK_CIPHER_3DES)
391513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      command_line->AppendSwitchASCII(kBulkCipherSwitch, "3des");
392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
393513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
394513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return true;
395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace net
398