| // Copyright 2013 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #include "net/websockets/websocket_test_util.h" | 
 |  | 
 | #include <algorithm> | 
 | #include <vector> | 
 |  | 
 | #include "base/basictypes.h" | 
 | #include "base/memory/scoped_vector.h" | 
 | #include "base/stl_util.h" | 
 | #include "base/strings/stringprintf.h" | 
 | #include "net/socket/socket_test_util.h" | 
 |  | 
 | namespace net { | 
 |  | 
 | namespace { | 
 | const uint64 kA = | 
 |     (static_cast<uint64>(0x5851f42d) << 32) + static_cast<uint64>(0x4c957f2d); | 
 | const uint64 kC = 12345; | 
 | const uint64 kM = static_cast<uint64>(1) << 48; | 
 |  | 
 | }  // namespace | 
 |  | 
 | LinearCongruentialGenerator::LinearCongruentialGenerator(uint32 seed) | 
 |     : current_(seed) {} | 
 |  | 
 | uint32 LinearCongruentialGenerator::Generate() { | 
 |   uint64 result = current_; | 
 |   current_ = (current_ * kA + kC) % kM; | 
 |   return static_cast<uint32>(result >> 16); | 
 | } | 
 |  | 
 | std::string WebSocketStandardRequest(const std::string& path, | 
 |                                      const std::string& origin, | 
 |                                      const std::string& extra_headers) { | 
 |   // Unrelated changes in net/http may change the order and default-values of | 
 |   // HTTP headers, causing WebSocket tests to fail. It is safe to update this | 
 |   // string in that case. | 
 |   return base::StringPrintf( | 
 |       "GET %s HTTP/1.1\r\n" | 
 |       "Host: localhost\r\n" | 
 |       "Connection: Upgrade\r\n" | 
 |       "Pragma: no-cache\r\n" | 
 |       "Cache-Control: no-cache\r\n" | 
 |       "Upgrade: websocket\r\n" | 
 |       "Origin: %s\r\n" | 
 |       "Sec-WebSocket-Version: 13\r\n" | 
 |       "User-Agent:\r\n" | 
 |       "Accept-Encoding: gzip, deflate\r\n" | 
 |       "Accept-Language: en-us,fr\r\n" | 
 |       "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" | 
 |       "Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits\r\n" | 
 |       "%s\r\n", | 
 |       path.c_str(), | 
 |       origin.c_str(), | 
 |       extra_headers.c_str()); | 
 | } | 
 |  | 
 | std::string WebSocketStandardResponse(const std::string& extra_headers) { | 
 |   return base::StringPrintf( | 
 |       "HTTP/1.1 101 Switching Protocols\r\n" | 
 |       "Upgrade: websocket\r\n" | 
 |       "Connection: Upgrade\r\n" | 
 |       "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" | 
 |       "%s\r\n", | 
 |       extra_headers.c_str()); | 
 | } | 
 |  | 
 | struct WebSocketDeterministicMockClientSocketFactoryMaker::Detail { | 
 |   std::string expect_written; | 
 |   std::string return_to_read; | 
 |   std::vector<MockRead> reads; | 
 |   MockWrite write; | 
 |   ScopedVector<DeterministicSocketData> socket_data_vector; | 
 |   ScopedVector<SSLSocketDataProvider> ssl_socket_data_vector; | 
 |   DeterministicMockClientSocketFactory factory; | 
 | }; | 
 |  | 
 | WebSocketDeterministicMockClientSocketFactoryMaker:: | 
 |     WebSocketDeterministicMockClientSocketFactoryMaker() | 
 |     : detail_(new Detail) {} | 
 |  | 
 | WebSocketDeterministicMockClientSocketFactoryMaker:: | 
 |     ~WebSocketDeterministicMockClientSocketFactoryMaker() {} | 
 |  | 
 | DeterministicMockClientSocketFactory* | 
 | WebSocketDeterministicMockClientSocketFactoryMaker::factory() { | 
 |   return &detail_->factory; | 
 | } | 
 |  | 
 | void WebSocketDeterministicMockClientSocketFactoryMaker::SetExpectations( | 
 |     const std::string& expect_written, | 
 |     const std::string& return_to_read) { | 
 |   const size_t kHttpStreamParserBufferSize = 4096; | 
 |   // We need to extend the lifetime of these strings. | 
 |   detail_->expect_written = expect_written; | 
 |   detail_->return_to_read = return_to_read; | 
 |   int sequence = 0; | 
 |   detail_->write = MockWrite(SYNCHRONOUS, | 
 |                              detail_->expect_written.data(), | 
 |                              detail_->expect_written.size(), | 
 |                              sequence++); | 
 |   // HttpStreamParser reads 4KB at a time. We need to take this implementation | 
 |   // detail into account if |return_to_read| is big enough. | 
 |   for (size_t place = 0; place < detail_->return_to_read.size(); | 
 |        place += kHttpStreamParserBufferSize) { | 
 |     detail_->reads.push_back( | 
 |         MockRead(SYNCHRONOUS, detail_->return_to_read.data() + place, | 
 |                  std::min(detail_->return_to_read.size() - place, | 
 |                           kHttpStreamParserBufferSize), | 
 |                  sequence++)); | 
 |   } | 
 |   scoped_ptr<DeterministicSocketData> socket_data( | 
 |       new DeterministicSocketData(vector_as_array(&detail_->reads), | 
 |                                   detail_->reads.size(), | 
 |                                   &detail_->write, | 
 |                                   1)); | 
 |   socket_data->set_connect_data(MockConnect(SYNCHRONOUS, OK)); | 
 |   socket_data->SetStop(sequence); | 
 |   AddRawExpectations(socket_data.Pass()); | 
 | } | 
 |  | 
 | void WebSocketDeterministicMockClientSocketFactoryMaker::AddRawExpectations( | 
 |     scoped_ptr<DeterministicSocketData> socket_data) { | 
 |   detail_->factory.AddSocketDataProvider(socket_data.get()); | 
 |   detail_->socket_data_vector.push_back(socket_data.release()); | 
 | } | 
 |  | 
 | void | 
 | WebSocketDeterministicMockClientSocketFactoryMaker::AddSSLSocketDataProvider( | 
 |     scoped_ptr<SSLSocketDataProvider> ssl_socket_data) { | 
 |   detail_->factory.AddSSLSocketDataProvider(ssl_socket_data.get()); | 
 |   detail_->ssl_socket_data_vector.push_back(ssl_socket_data.release()); | 
 | } | 
 |  | 
 | WebSocketTestURLRequestContextHost::WebSocketTestURLRequestContextHost() | 
 |     : url_request_context_(true), url_request_context_initialized_(false) { | 
 |   url_request_context_.set_client_socket_factory(maker_.factory()); | 
 | } | 
 |  | 
 | WebSocketTestURLRequestContextHost::~WebSocketTestURLRequestContextHost() {} | 
 |  | 
 | void WebSocketTestURLRequestContextHost::AddRawExpectations( | 
 |     scoped_ptr<DeterministicSocketData> socket_data) { | 
 |   maker_.AddRawExpectations(socket_data.Pass()); | 
 | } | 
 |  | 
 | void WebSocketTestURLRequestContextHost::AddSSLSocketDataProvider( | 
 |     scoped_ptr<SSLSocketDataProvider> ssl_socket_data) { | 
 |   maker_.AddSSLSocketDataProvider(ssl_socket_data.Pass()); | 
 | } | 
 |  | 
 | TestURLRequestContext* | 
 | WebSocketTestURLRequestContextHost::GetURLRequestContext() { | 
 |   if (!url_request_context_initialized_) { | 
 |     url_request_context_.Init(); | 
 |     // A Network Delegate is required to make the URLRequest::Delegate work. | 
 |     url_request_context_.set_network_delegate(&network_delegate_); | 
 |     url_request_context_initialized_ = true; | 
 |   } | 
 |   return &url_request_context_; | 
 | } | 
 |  | 
 | }  // namespace net |