| Index: chrome/browser/devtools/device/adb/mock_adb_server.cc
|
| diff --git a/chrome/browser/devtools/device/adb/mock_adb_server.cc b/chrome/browser/devtools/device/adb/mock_adb_server.cc
|
| index 96b52abb94f0d64ef19f7ff4260634e4eb38b855..64bfa12a0772756ceeabbef686b7c04f8fa210a4 100644
|
| --- a/chrome/browser/devtools/device/adb/mock_adb_server.cc
|
| +++ b/chrome/browser/devtools/device/adb/mock_adb_server.cc
|
| @@ -146,82 +146,84 @@ static const int kAdbPort = 5037;
|
|
|
| static const int kAdbMessageHeaderSize = 4;
|
|
|
| -
|
| -class SingleConnectionServer : base::NonThreadSafe {
|
| +class SimpleHttpServer : base::NonThreadSafe {
|
| public:
|
| class Parser {
|
| public:
|
| virtual int Consume(const char* data, int size) = 0;
|
| - virtual void Reset() = 0;
|
| -
|
| - protected:
|
| virtual ~Parser() {}
|
| };
|
|
|
| - SingleConnectionServer(
|
| - Parser* parser, net::IPEndPoint endpoint, int buffer_size);
|
| -
|
| - virtual ~SingleConnectionServer();
|
| + typedef base::Callback<void(const std::string&)> SendCallback;
|
| + typedef base::Callback<Parser*(const SendCallback&)> ParserFactory;
|
|
|
| - void Send(const std::string& message);
|
| + SimpleHttpServer(const ParserFactory& factory, net::IPEndPoint endpoint);
|
| + virtual ~SimpleHttpServer();
|
|
|
| private:
|
| - void SendData(const char* data, int size);
|
| + class Connection : base::NonThreadSafe {
|
| + public:
|
| + Connection(net::StreamSocket* socket, const ParserFactory& factory);
|
| + virtual ~Connection();
|
| +
|
| + private:
|
| + void Send(const std::string& message);
|
| + void ReadData();
|
| + void OnDataRead(int count);
|
| + void WriteData();
|
| + void OnDataWritten(int count);
|
| +
|
| + scoped_ptr<net::StreamSocket> socket_;
|
| + scoped_ptr<Parser> parser_;
|
| + scoped_refptr<net::GrowableIOBuffer> input_buffer_;
|
| + scoped_refptr<net::GrowableIOBuffer> output_buffer_;
|
| + int bytes_to_write_;
|
| + bool read_closed_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(Connection);
|
| + };
|
|
|
| void AcceptConnection();
|
| void OnAccepted(int result);
|
|
|
| - void ReadData();
|
| - void OnDataRead(int count);
|
| -
|
| - void WriteData();
|
| - void OnDataWritten(int count);
|
| -
|
| - Parser* parser_;
|
| - int bytes_to_write_;
|
| - scoped_ptr<net::TCPServerSocket> server_socket_;
|
| + ParserFactory factory_;
|
| + scoped_ptr<net::TCPServerSocket> socket_;
|
| scoped_ptr<net::StreamSocket> client_socket_;
|
| - scoped_refptr<net::GrowableIOBuffer> input_buffer_;
|
| - scoped_refptr<net::GrowableIOBuffer> output_buffer_;
|
|
|
| - DISALLOW_COPY_AND_ASSIGN(SingleConnectionServer);
|
| + DISALLOW_COPY_AND_ASSIGN(SimpleHttpServer);
|
| };
|
|
|
| -SingleConnectionServer::SingleConnectionServer(Parser* parser,
|
| - net::IPEndPoint endpoint,
|
| - int buffer_size)
|
| - : parser_(parser),
|
| - bytes_to_write_(0) {
|
| - CHECK(CalledOnValidThread());
|
| -
|
| - input_buffer_ = new net::GrowableIOBuffer();
|
| - input_buffer_->SetCapacity(buffer_size);
|
| -
|
| - output_buffer_ = new net::GrowableIOBuffer();
|
| -
|
| - server_socket_.reset(new net::TCPServerSocket(NULL, net::NetLog::Source()));
|
| - server_socket_->Listen(endpoint, 1);
|
| -
|
| +SimpleHttpServer::SimpleHttpServer(const ParserFactory& factory,
|
| + net::IPEndPoint endpoint)
|
| + : factory_(factory),
|
| + socket_(new net::TCPServerSocket(NULL, net::NetLog::Source())) {
|
| + socket_->Listen(endpoint, 5);
|
| AcceptConnection();
|
| }
|
|
|
| -SingleConnectionServer::~SingleConnectionServer() {
|
| - CHECK(CalledOnValidThread());
|
| -
|
| - server_socket_.reset();
|
| +SimpleHttpServer::~SimpleHttpServer() {
|
| +}
|
|
|
| - if (client_socket_) {
|
| - client_socket_->Disconnect();
|
| - client_socket_.reset();
|
| - }
|
| +SimpleHttpServer::Connection::Connection(net::StreamSocket* socket,
|
| + const ParserFactory& factory)
|
| + : socket_(socket),
|
| + parser_(factory.Run(base::Bind(&Connection::Send,
|
| + base::Unretained(this)))),
|
| + input_buffer_(new net::GrowableIOBuffer()),
|
| + output_buffer_(new net::GrowableIOBuffer()),
|
| + bytes_to_write_(0),
|
| + read_closed_(false) {
|
| + input_buffer_->SetCapacity(kBufferSize);
|
| + ReadData();
|
| }
|
|
|
| -void SingleConnectionServer::Send(const std::string& message) {
|
| - SendData(message.c_str(), message.size());
|
| +SimpleHttpServer::Connection::~Connection() {
|
| }
|
|
|
| -void SingleConnectionServer::SendData(const char* data, int size) {
|
| +void SimpleHttpServer::Connection::Send(const std::string& message) {
|
| CHECK(CalledOnValidThread());
|
| + const char* data = message.c_str();
|
| + int size = message.size();
|
|
|
| if ((output_buffer_->offset() + bytes_to_write_ + size) >
|
| output_buffer_->capacity()) {
|
| @@ -245,64 +247,36 @@ void SingleConnectionServer::SendData(const char* data, int size) {
|
| WriteData();
|
| }
|
|
|
| -void SingleConnectionServer::AcceptConnection() {
|
| - CHECK(CalledOnValidThread());
|
| -
|
| - if (client_socket_) {
|
| - client_socket_->Disconnect();
|
| - client_socket_.reset();
|
| - }
|
| -
|
| - int accept_result = server_socket_->Accept(&client_socket_,
|
| - base::Bind(&SingleConnectionServer::OnAccepted, base::Unretained(this)));
|
| -
|
| - if (accept_result != net::ERR_IO_PENDING)
|
| - base::MessageLoop::current()->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&SingleConnectionServer::OnAccepted,
|
| - base::Unretained(this),
|
| - accept_result));
|
| -}
|
| -
|
| -void SingleConnectionServer::OnAccepted(int result) {
|
| - CHECK(CalledOnValidThread());
|
| -
|
| - ASSERT_EQ(result, 0); // Fails if the socket is already in use.
|
| - parser_->Reset();
|
| - ReadData();
|
| -}
|
| -
|
| -void SingleConnectionServer::ReadData() {
|
| +void SimpleHttpServer::Connection::ReadData() {
|
| CHECK(CalledOnValidThread());
|
|
|
| if (input_buffer_->RemainingCapacity() == 0)
|
| input_buffer_->SetCapacity(input_buffer_->capacity() * 2);
|
|
|
| - int read_result = client_socket_->Read(
|
| + int read_result = socket_->Read(
|
| input_buffer_.get(),
|
| input_buffer_->RemainingCapacity(),
|
| - base::Bind(&SingleConnectionServer::OnDataRead, base::Unretained(this)));
|
| + base::Bind(&Connection::OnDataRead, base::Unretained(this)));
|
|
|
| if (read_result != net::ERR_IO_PENDING)
|
| OnDataRead(read_result);
|
| }
|
|
|
| -void SingleConnectionServer::OnDataRead(int count) {
|
| +void SimpleHttpServer::Connection::OnDataRead(int count) {
|
| CHECK(CalledOnValidThread());
|
| -
|
| if (count <= 0) {
|
| - AcceptConnection();
|
| + if (bytes_to_write_ == 0)
|
| + delete this;
|
| + else
|
| + read_closed_ = true;
|
| return;
|
| }
|
| -
|
| input_buffer_->set_offset(input_buffer_->offset() + count);
|
| -
|
| int bytes_processed;
|
|
|
| do {
|
| char* data = input_buffer_->StartOfBuffer();
|
| int data_size = input_buffer_->offset();
|
| -
|
| bytes_processed = parser_->Consume(data, data_size);
|
|
|
| if (bytes_processed) {
|
| @@ -310,36 +284,32 @@ void SingleConnectionServer::OnDataRead(int count) {
|
| input_buffer_->set_offset(data_size - bytes_processed);
|
| }
|
| } while (bytes_processed);
|
| -
|
| - // Posting is needed not to enter deep recursion in case too synchronous IO
|
| + // Posting to avoid deep recursion in case of synchronous IO
|
| base::MessageLoop::current()->PostTask(
|
| FROM_HERE,
|
| - base::Bind(&SingleConnectionServer::ReadData, base::Unretained(this)));
|
| + base::Bind(&Connection::ReadData, base::Unretained(this)));
|
| }
|
|
|
| -void SingleConnectionServer::WriteData() {
|
| +void SimpleHttpServer::Connection::WriteData() {
|
| CHECK(CalledOnValidThread());
|
| -
|
| CHECK_GE(output_buffer_->capacity(),
|
| output_buffer_->offset() + bytes_to_write_) << "Overflow";
|
|
|
| - int write_result = client_socket_->Write(
|
| + int write_result = socket_->Write(
|
| output_buffer_,
|
| bytes_to_write_,
|
| - base::Bind(&SingleConnectionServer::OnDataWritten,
|
| - base::Unretained(this)));
|
| + base::Bind(&Connection::OnDataWritten, base::Unretained(this)));
|
| +
|
| if (write_result != net::ERR_IO_PENDING)
|
| OnDataWritten(write_result);
|
| }
|
|
|
| -void SingleConnectionServer::OnDataWritten(int count) {
|
| +void SimpleHttpServer::Connection::OnDataWritten(int count) {
|
| CHECK(CalledOnValidThread());
|
| -
|
| if (count < 0) {
|
| - AcceptConnection();
|
| + delete this;
|
| return;
|
| }
|
| -
|
| CHECK_GT(count, 0);
|
| CHECK_GE(output_buffer_->capacity(),
|
| output_buffer_->offset() + bytes_to_write_) << "Overflow";
|
| @@ -348,26 +318,46 @@ void SingleConnectionServer::OnDataWritten(int count) {
|
| output_buffer_->set_offset(output_buffer_->offset() + count);
|
|
|
| if (bytes_to_write_ != 0)
|
| - // Posting is needed not to enter deep recursion in case too synchronous IO
|
| + // Posting to avoid deep recursion in case of synchronous IO
|
| + base::MessageLoop::current()->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&Connection::WriteData, base::Unretained(this)));
|
| + else if (read_closed_)
|
| + delete this;
|
| +}
|
| +
|
| +void SimpleHttpServer::AcceptConnection() {
|
| + CHECK(CalledOnValidThread());
|
| +
|
| + int accept_result = socket_->Accept(&client_socket_,
|
| + base::Bind(&SimpleHttpServer::OnAccepted, base::Unretained(this)));
|
| +
|
| + if (accept_result != net::ERR_IO_PENDING)
|
| base::MessageLoop::current()->PostTask(
|
| FROM_HERE,
|
| - base::Bind(&SingleConnectionServer::WriteData, base::Unretained(this)));
|
| + base::Bind(&SimpleHttpServer::OnAccepted,
|
| + base::Unretained(this),
|
| + accept_result));
|
| }
|
|
|
| +void SimpleHttpServer::OnAccepted(int result) {
|
| + CHECK(CalledOnValidThread());
|
| + ASSERT_EQ(result, 0); // Fails if the socket is already in use.
|
| + new Connection(client_socket_.release(), factory_);
|
| + AcceptConnection();
|
| +}
|
|
|
| -class MockAdbServer : SingleConnectionServer::Parser,
|
| - base::NonThreadSafe {
|
| +class AdbParser : SimpleHttpServer::Parser, base::NonThreadSafe {
|
| public:
|
| - MockAdbServer() {
|
| - CHECK(CalledOnValidThread());
|
| - net::IPAddressNumber address;
|
| - net::ParseIPLiteralToNumber("127.0.0.1", &address);
|
| - net::IPEndPoint endpoint(address, kAdbPort);
|
| - server_.reset(new SingleConnectionServer(this, endpoint, kBufferSize));
|
| + static Parser* Create(const SimpleHttpServer::SendCallback& callback) {
|
| + return new AdbParser(callback);
|
| }
|
|
|
| - virtual ~MockAdbServer() {
|
| - CHECK(CalledOnValidThread());
|
| + explicit AdbParser(const SimpleHttpServer::SendCallback& callback)
|
| + : callback_(callback) {
|
| + }
|
| +
|
| + virtual ~AdbParser() {
|
| }
|
|
|
| private:
|
| @@ -382,7 +372,6 @@ class MockAdbServer : SingleConnectionServer::Parser,
|
| }
|
| return 0;
|
| }
|
| -
|
| if (size >= kAdbMessageHeaderSize) {
|
| std::string message_header(data, kAdbMessageHeaderSize);
|
| int message_size;
|
| @@ -390,23 +379,14 @@ class MockAdbServer : SingleConnectionServer::Parser,
|
| EXPECT_TRUE(base::HexStringToInt(message_header, &message_size));
|
|
|
| if (size >= message_size + kAdbMessageHeaderSize) {
|
| - std::string message_body(data + kAdbMessageHeaderSize, message_size );
|
| -
|
| + std::string message_body(data + kAdbMessageHeaderSize, message_size);
|
| ProcessCommand(message_body);
|
| -
|
| return kAdbMessageHeaderSize + message_size;
|
| }
|
| }
|
| -
|
| return 0;
|
| }
|
|
|
| - virtual void Reset() OVERRIDE {
|
| - CHECK(CalledOnValidThread());
|
| - selected_device_ = std::string();
|
| - selected_socket_ = std::string();
|
| - }
|
| -
|
| void ProcessHTTPRequest(const std::string& request) {
|
| CHECK(CalledOnValidThread());
|
| std::vector<std::string> tokens;
|
| @@ -416,7 +396,6 @@ class MockAdbServer : SingleConnectionServer::Parser,
|
| CHECK_EQ("HTTP/1.1", tokens[2]);
|
|
|
| std::string path(tokens[1]);
|
| -
|
| if (path == kJsonPath)
|
| path = kJsonListPath;
|
|
|
| @@ -480,7 +459,9 @@ class MockAdbServer : SingleConnectionServer::Parser,
|
| }
|
| }
|
|
|
| - void SendResponse(const std::string& response) { Send("OKAY", response); }
|
| + void SendResponse(const std::string& response) {
|
| + Send("OKAY", response);
|
| + }
|
|
|
| void Send(const std::string& status, const std::string& response) {
|
| CHECK(CalledOnValidThread());
|
| @@ -496,8 +477,7 @@ class MockAdbServer : SingleConnectionServer::Parser,
|
| response_stream << kHexChars[ (size >> 4*i) & 0x0f ];
|
| response_stream << response;
|
| }
|
| -
|
| - server_->Send(response_stream.str());
|
| + callback_.Run(response_stream.str());
|
| }
|
|
|
| void SendHTTPResponse(const std::string& body) {
|
| @@ -505,21 +485,24 @@ class MockAdbServer : SingleConnectionServer::Parser,
|
| std::string response_data(base::StringPrintf(kHttpResponse,
|
| static_cast<int>(body.size()),
|
| body.c_str()));
|
| - server_->Send(response_data);
|
| + callback_.Run(response_data);
|
| }
|
|
|
| std::string selected_device_;
|
| std::string selected_socket_;
|
| -
|
| - scoped_ptr<SingleConnectionServer> server_;
|
| + SimpleHttpServer::SendCallback callback_;
|
| };
|
|
|
| -static MockAdbServer* mock_adb_server_ = NULL;
|
| +static SimpleHttpServer* mock_adb_server_ = NULL;
|
|
|
| void StartMockAdbServerOnIOThread() {
|
| CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| CHECK(mock_adb_server_ == NULL);
|
| - mock_adb_server_ = new MockAdbServer();
|
| + net::IPAddressNumber address;
|
| + net::ParseIPLiteralToNumber("127.0.0.1", &address);
|
| + net::IPEndPoint endpoint(address, kAdbPort);
|
| + mock_adb_server_ =
|
| + new SimpleHttpServer(base::Bind(&AdbParser::Create), endpoint);
|
| }
|
|
|
| void StopMockAdbServerOnIOThread() {
|
|
|