15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "net/test/spawned_test_server/spawner_communicator.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_reader.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/supports_user_data.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/test/test_timeouts.h"
12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "build/build_config.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h"
160f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "net/base/request_priority.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/upload_bytes_element_reader.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/upload_data_stream.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_response_headers.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_test_util.h"
217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GURL GenerateSpawnerCommandURL(const std::string& command, uint16 port) {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Always performs HTTP request for sending command to the spawner server.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GURL(base::StringPrintf("%s:%u/%s", "http://127.0.0.1", port,
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 command.c_str()));
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int kBufferSize = 2048;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A class to hold all data needed to send a command to spawner server.
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SpawnerRequestData : public base::SupportsUserData::Data {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SpawnerRequestData(int id, int* result_code, std::string* data_received)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : request_id_(id),
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        buf_(new IOBuffer(kBufferSize)),
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result_code_(result_code),
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        data_received_(data_received),
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        response_started_count_(0) {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(result_code);
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *result_code_ = OK;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(data_received);
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_received_->clear();
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~SpawnerRequestData() {}
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool DoesRequestIdMatch(int request_id) const {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return request_id_ == request_id;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IOBuffer* buf() const { return buf_.get(); }
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool IsResultOK() const { return *result_code_ == OK; }
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ClearReceivedData() { data_received_->clear(); }
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetResultCode(int result_code) { *result_code_ = result_code; }
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void IncreaseResponseStartedCount() { response_started_count_++; }
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int response_started_count() const { return response_started_count_; }
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Write data read from URLRequest::Read() to |data_received_|. Returns true
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // if |num_bytes| is great than 0. |num_bytes| is 0 for EOF, < 0 on errors.
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ConsumeBytesRead(int num_bytes) {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Error while reading, or EOF.
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (num_bytes <= 0)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_received_->append(buf_->data(), num_bytes);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Unique ID for the current request.
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int request_id_;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Buffer that URLRequest writes into.
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<IOBuffer> buf_;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Holds the error condition that was hit on the current request, or OK.
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int* result_code_;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Data received from server;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string* data_received_;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Used to track how many times the OnResponseStarted get called after
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // sending a command to spawner server.
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int response_started_count_;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SpawnerRequestData);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SpawnerCommunicator::SpawnerCommunicator(uint16 port)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : io_thread_("spawner_communicator"),
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      event_(false, false),
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      port_(port),
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_id_(0),
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      weak_factory_(this),
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_running_(false) {}
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SpawnerCommunicator::~SpawnerCommunicator() {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!is_running_);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpawnerCommunicator::WaitForResponse() {
11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK_NE(base::MessageLoop::current(), io_thread_.message_loop());
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event_.Wait();
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event_.Reset();
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpawnerCommunicator::StartIOThread() {
12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK_NE(base::MessageLoop::current(), io_thread_.message_loop());
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_running_)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  allowed_port_.reset(new ScopedPortException(port_));
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Thread::Options options;
12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  options.message_loop_type = base::MessageLoop::TYPE_IO;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  is_running_ = io_thread_.StartWithOptions(options);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(is_running_);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpawnerCommunicator::Shutdown() {
13290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK_NE(base::MessageLoop::current(), io_thread_.message_loop());
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(is_running_);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The request and its context should be created and destroyed only on the
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // IO thread.
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!cur_request_.get());
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!context_.get());
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  is_running_ = false;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io_thread_.Stop();
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  allowed_port_.reset();
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpawnerCommunicator::SendCommandAndWaitForResult(
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& command,
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& post_data,
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int* result_code,
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string* data_received) {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!result_code || !data_received)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start the communicator thread to talk to test server spawner.
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StartIOThread();
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(io_thread_.message_loop());
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Since the method will be blocked until SpawnerCommunicator gets result
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // from the spawner server or timed-out. It's safe to use base::Unretained
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // when using base::Bind.
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &SpawnerCommunicator::SendCommandAndWaitForResultOnIOThread,
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Unretained(this), command, post_data, result_code, data_received));
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForResponse();
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpawnerCommunicator::SendCommandAndWaitForResultOnIOThread(
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& command,
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& post_data,
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int* result_code,
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string* data_received) {
16890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop* loop = io_thread_.message_loop();
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(loop);
17090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK_EQ(base::MessageLoop::current(), loop);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Prepare the URLRequest for sending the command.
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!cur_request_.get());
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  context_.reset(new TestURLRequestContext);
1750f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  cur_request_ = context_->CreateRequest(
1760f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      GenerateSpawnerCommandURL(command, port_), DEFAULT_PRIORITY, this);
1770f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  DCHECK(cur_request_);
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int current_request_id = ++next_id_;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SpawnerRequestData* data = new SpawnerRequestData(current_request_id,
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                    result_code,
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                    data_received);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(data);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cur_request_->SetUserData(this, data);
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (post_data.empty()) {
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cur_request_->set_method("GET");
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cur_request_->set_method("POST");
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<UploadElementReader> reader(
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        UploadOwnedBytesElementReader::CreateWithString(post_data));
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cur_request_->set_upload(make_scoped_ptr(
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        UploadDataStream::CreateWithReader(reader.Pass(), 0)));
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::HttpRequestHeaders headers;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    headers.SetHeader(net::HttpRequestHeaders::kContentType,
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      "application/json");
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cur_request_->SetExtraRequestHeaders(headers);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Post a task to timeout this request if it takes too long.
20090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->PostDelayedTask(
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
20290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::Bind(&SpawnerCommunicator::OnTimeout,
20390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 weak_factory_.GetWeakPtr(),
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 current_request_id),
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TestTimeouts::action_max_timeout());
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start the request.
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cur_request_->Start();
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpawnerCommunicator::OnTimeout(int id) {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Timeout tasks may outlive the URLRequest they reference. Make sure it
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is still applicable.
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!cur_request_.get())
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SpawnerRequestData* data =
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<SpawnerRequestData*>(cur_request_->GetUserData(this));
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(data);
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!data->DoesRequestIdMatch(id))
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set the result code and cancel the timed-out task.
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data->SetResultCode(ERR_TIMED_OUT);
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cur_request_->Cancel();
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OnSpawnerCommandCompleted(cur_request_.get());
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpawnerCommunicator::OnSpawnerCommandCompleted(URLRequest* request) {
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!cur_request_.get())
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(request, cur_request_.get());
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SpawnerRequestData* data =
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<SpawnerRequestData*>(cur_request_->GetUserData(this));
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(data);
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If request is faild,return the error code.
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!cur_request_->status().is_success())
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data->SetResultCode(cur_request_->status().error());
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!data->IsResultOK()) {
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "request failed, status: "
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << static_cast<int>(request->status().status())
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << ", error: " << request->status().error();
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Clear the buffer of received data if any net error happened.
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data->ClearReceivedData();
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(1, data->response_started_count());
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Clear current request to indicate the completion of sending a command
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to spawner server and getting the result.
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cur_request_.reset();
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  context_.reset();
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Invalidate the weak pointers on the IO thread.
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  weak_factory_.InvalidateWeakPtrs();
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wakeup the caller in user thread.
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event_.Signal();
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpawnerCommunicator::ReadResult(URLRequest* request) {
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(request, cur_request_.get());
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SpawnerRequestData* data =
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<SpawnerRequestData*>(cur_request_->GetUserData(this));
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(data);
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IOBuffer* buf = data->buf();
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read as many bytes as are available synchronously.
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (true) {
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int num_bytes;
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!request->Read(buf, kBufferSize, &num_bytes)) {
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Check whether the read failed synchronously.
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!request->status().is_io_pending())
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        OnSpawnerCommandCompleted(request);
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!data->ConsumeBytesRead(num_bytes)) {
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OnSpawnerCommandCompleted(request);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpawnerCommunicator::OnResponseStarted(URLRequest* request) {
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(request, cur_request_.get());
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SpawnerRequestData* data =
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<SpawnerRequestData*>(cur_request_->GetUserData(this));
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(data);
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data->IncreaseResponseStartedCount();
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!request->status().is_success()) {
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnSpawnerCommandCompleted(request);
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Require HTTP responses to have a success status code.
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (request->GetResponseCode() != 200) {
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Spawner server returned bad status: "
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << request->response_headers()->GetStatusLine();
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data->SetResultCode(ERR_FAILED);
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request->Cancel();
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnSpawnerCommandCompleted(request);
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadResult(request);
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpawnerCommunicator::OnReadCompleted(URLRequest* request, int num_bytes) {
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!cur_request_.get())
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(request, cur_request_.get());
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SpawnerRequestData* data =
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<SpawnerRequestData*>(cur_request_->GetUserData(this));
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(data);
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (data->ConsumeBytesRead(num_bytes)) {
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Keep reading.
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReadResult(request);
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnSpawnerCommandCompleted(request);
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SpawnerCommunicator::StartServer(const std::string& arguments,
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      uint16* port) {
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *port = 0;
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send the start command to spawner server to start the Python test server
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // on remote machine.
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string server_return_data;
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int result_code;
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendCommandAndWaitForResult("start", arguments, &result_code,
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              &server_return_data);
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (OK != result_code || server_return_data.empty())
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check whether the data returned from spawner server is JSON-formatted.
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<base::Value> value(base::JSONReader::Read(server_return_data));
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!value.get() || !value->IsType(base::Value::TYPE_DICTIONARY)) {
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Invalid server data: " << server_return_data.c_str();
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check whether spawner server returns valid data.
3467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  base::DictionaryValue* server_data =
3477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      static_cast<base::DictionaryValue*>(value.get());
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string message;
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!server_data->GetString("message", &message) || message != "started") {
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Invalid message in server data: ";
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int int_port;
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!server_data->GetInteger("port", &int_port) || int_port <= 0 ||
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int_port > kuint16max) {
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Invalid port value: " << int_port;
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *port = static_cast<uint16>(int_port);
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SpawnerCommunicator::StopServer() {
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It's OK to stop the SpawnerCommunicator without starting it. Some tests
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // have test server on their test fixture but do not actually use it.
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!is_running_)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When the test is done, ask the test server spawner to kill the test server
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // on the remote machine.
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string server_return_data;
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int result_code;
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendCommandAndWaitForResult("kill", "", &result_code, &server_return_data);
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Shutdown();
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (OK != result_code || server_return_data != "killed")
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
381