OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/websockets/websocket_stream.h" | 5 #include "net/websockets/websocket_stream.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <string> | 8 #include <string> |
9 #include <utility> | 9 #include <utility> |
10 #include <vector> | 10 #include <vector> |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
49 | 49 |
50 std::vector<HeaderKeyValuePair> ToVector(const HttpResponseHeaders& headers) { | 50 std::vector<HeaderKeyValuePair> ToVector(const HttpResponseHeaders& headers) { |
51 void* iter = NULL; | 51 void* iter = NULL; |
52 std::string name, value; | 52 std::string name, value; |
53 std::vector<HeaderKeyValuePair> result; | 53 std::vector<HeaderKeyValuePair> result; |
54 while (headers.EnumerateHeaderLines(&iter, &name, &value)) | 54 while (headers.EnumerateHeaderLines(&iter, &name, &value)) |
55 result.push_back(HeaderKeyValuePair(name, value)); | 55 result.push_back(HeaderKeyValuePair(name, value)); |
56 return result; | 56 return result; |
57 } | 57 } |
58 | 58 |
| 59 // Simple builder for a DeterministicSocketData object to save repetitive code. |
| 60 // It always sets the connect data to MockConnect(SYNCHRONOUS, OK), so it cannot |
| 61 // be used in tests where the connect fails. In practice, those tests never have |
| 62 // any read/write data and so can't benefit from it anyway. The arrays are not |
| 63 // copied. It is up to the caller to ensure they stay in scope until the test |
| 64 // ends. |
| 65 template <size_t reads_count, size_t writes_count> |
| 66 scoped_ptr<DeterministicSocketData> BuildSocketData( |
| 67 MockRead (&reads)[reads_count], |
| 68 MockWrite (&writes)[writes_count]) { |
| 69 scoped_ptr<DeterministicSocketData> socket_data( |
| 70 new DeterministicSocketData(reads, reads_count, writes, writes_count)); |
| 71 socket_data->set_connect_data(MockConnect(SYNCHRONOUS, OK)); |
| 72 socket_data->SetStop(reads_count + writes_count); |
| 73 return socket_data.Pass(); |
| 74 } |
| 75 |
| 76 // Builder for a DeterministicSocketData that expects nothing. This does not |
| 77 // set the connect data, so the calling code must do that explicitly. |
| 78 scoped_ptr<DeterministicSocketData> BuildNullSocketData() { |
| 79 return make_scoped_ptr(new DeterministicSocketData(NULL, 0, NULL, 0)); |
| 80 } |
| 81 |
59 // A sub-class of WebSocketHandshakeStreamCreateHelper which always sets a | 82 // A sub-class of WebSocketHandshakeStreamCreateHelper which always sets a |
60 // deterministic key to use in the WebSocket handshake. | 83 // deterministic key to use in the WebSocket handshake. |
61 class DeterministicKeyWebSocketHandshakeStreamCreateHelper | 84 class DeterministicKeyWebSocketHandshakeStreamCreateHelper |
62 : public WebSocketHandshakeStreamCreateHelper { | 85 : public WebSocketHandshakeStreamCreateHelper { |
63 public: | 86 public: |
64 DeterministicKeyWebSocketHandshakeStreamCreateHelper( | 87 DeterministicKeyWebSocketHandshakeStreamCreateHelper( |
65 WebSocketStream::ConnectDelegate* connect_delegate, | 88 WebSocketStream::ConnectDelegate* connect_delegate, |
66 const std::vector<std::string>& requested_subprotocols) | 89 const std::vector<std::string>& requested_subprotocols) |
67 : WebSocketHandshakeStreamCreateHelper(connect_delegate, | 90 : WebSocketHandshakeStreamCreateHelper(connect_delegate, |
68 requested_subprotocols) {} | 91 requested_subprotocols) {} |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
104 origin, | 127 origin, |
105 extra_request_headers, | 128 extra_request_headers, |
106 WebSocketStandardResponse(extra_response_headers)); | 129 WebSocketStandardResponse(extra_response_headers)); |
107 } | 130 } |
108 | 131 |
109 void CreateAndConnectRawExpectations( | 132 void CreateAndConnectRawExpectations( |
110 const std::string& socket_url, | 133 const std::string& socket_url, |
111 const std::vector<std::string>& sub_protocols, | 134 const std::vector<std::string>& sub_protocols, |
112 const std::string& origin, | 135 const std::string& origin, |
113 scoped_ptr<DeterministicSocketData> socket_data) { | 136 scoped_ptr<DeterministicSocketData> socket_data) { |
| 137 AddRawExpectations(socket_data.Pass()); |
| 138 CreateAndConnectStream(socket_url, sub_protocols, origin); |
| 139 } |
| 140 |
| 141 // Add additional raw expectations for sockets created before the final one. |
| 142 void AddRawExpectations(scoped_ptr<DeterministicSocketData> socket_data) { |
114 url_request_context_host_.AddRawExpectations(socket_data.Pass()); | 143 url_request_context_host_.AddRawExpectations(socket_data.Pass()); |
115 CreateAndConnectStream(socket_url, sub_protocols, origin); | |
116 } | 144 } |
117 | 145 |
118 // A wrapper for CreateAndConnectStreamForTesting that knows about our default | 146 // A wrapper for CreateAndConnectStreamForTesting that knows about our default |
119 // parameters. | 147 // parameters. |
120 void CreateAndConnectStream(const std::string& socket_url, | 148 void CreateAndConnectStream(const std::string& socket_url, |
121 const std::vector<std::string>& sub_protocols, | 149 const std::vector<std::string>& sub_protocols, |
122 const std::string& origin) { | 150 const std::string& origin) { |
123 for (size_t i = 0; i < ssl_data_.size(); ++i) { | 151 for (size_t i = 0; i < ssl_data_.size(); ++i) { |
124 scoped_ptr<SSLSocketDataProvider> ssl_data(ssl_data_[i]); | 152 scoped_ptr<SSLSocketDataProvider> ssl_data(ssl_data_[i]); |
125 ssl_data_[i] = NULL; | 153 ssl_data_[i] = NULL; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 stream.swap(owner_->stream_); | 188 stream.swap(owner_->stream_); |
161 } | 189 } |
162 | 190 |
163 virtual void OnFailure(const std::string& message) OVERRIDE { | 191 virtual void OnFailure(const std::string& message) OVERRIDE { |
164 owner_->has_failed_ = true; | 192 owner_->has_failed_ = true; |
165 owner_->failure_message_ = message; | 193 owner_->failure_message_ = message; |
166 } | 194 } |
167 | 195 |
168 virtual void OnStartOpeningHandshake( | 196 virtual void OnStartOpeningHandshake( |
169 scoped_ptr<WebSocketHandshakeRequestInfo> request) OVERRIDE { | 197 scoped_ptr<WebSocketHandshakeRequestInfo> request) OVERRIDE { |
170 if (owner_->request_info_) | 198 // Can be called multiple times (in the case of HTTP auth). Last call |
171 ADD_FAILURE(); | 199 // wins. |
172 owner_->request_info_ = request.Pass(); | 200 owner_->request_info_ = request.Pass(); |
173 } | 201 } |
174 virtual void OnFinishOpeningHandshake( | 202 virtual void OnFinishOpeningHandshake( |
175 scoped_ptr<WebSocketHandshakeResponseInfo> response) OVERRIDE { | 203 scoped_ptr<WebSocketHandshakeResponseInfo> response) OVERRIDE { |
176 if (owner_->response_info_) | 204 if (owner_->response_info_) |
177 ADD_FAILURE(); | 205 ADD_FAILURE(); |
178 owner_->response_info_ = response.Pass(); | 206 owner_->response_info_ = response.Pass(); |
179 } | 207 } |
180 virtual void OnSSLCertificateError( | 208 virtual void OnSSLCertificateError( |
181 scoped_ptr<WebSocketEventInterface::SSLErrorCallbacks> | 209 scoped_ptr<WebSocketEventInterface::SSLErrorCallbacks> |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
219 "ws://localhost/testing_path", | 247 "ws://localhost/testing_path", |
220 "/testing_path", | 248 "/testing_path", |
221 NoSubProtocols(), | 249 NoSubProtocols(), |
222 "http://localhost", | 250 "http://localhost", |
223 "", | 251 "", |
224 "Sec-WebSocket-Extensions: " + extensions_header_value + "\r\n"); | 252 "Sec-WebSocket-Extensions: " + extensions_header_value + "\r\n"); |
225 RunUntilIdle(); | 253 RunUntilIdle(); |
226 } | 254 } |
227 }; | 255 }; |
228 | 256 |
| 257 // Common code to construct expectations for authentication tests that receive |
| 258 // the auth challenge on one connection and then create a second connection to |
| 259 // send the authenticated request on. |
| 260 class CommonAuthTestHelper { |
| 261 public: |
| 262 CommonAuthTestHelper() : reads1_(), writes1_(), reads2_(), writes2_() {} |
| 263 |
| 264 scoped_ptr<DeterministicSocketData> BuildSocketData1( |
| 265 const std::string& response) { |
| 266 request1_ = WebSocketStandardRequest("/", "http://localhost", ""); |
| 267 writes1_[0] = MockWrite(SYNCHRONOUS, 0, request1_.c_str()); |
| 268 response1_ = response; |
| 269 reads1_[0] = MockRead(SYNCHRONOUS, 1, response1_.c_str()); |
| 270 reads1_[1] = MockRead(SYNCHRONOUS, OK, 2); // Close connection |
| 271 |
| 272 return BuildSocketData(reads1_, writes1_); |
| 273 } |
| 274 |
| 275 scoped_ptr<DeterministicSocketData> BuildSocketData2( |
| 276 const std::string& request, |
| 277 const std::string& response) { |
| 278 request2_ = request; |
| 279 response2_ = response; |
| 280 writes2_[0] = MockWrite(SYNCHRONOUS, 0, request2_.c_str()); |
| 281 reads2_[0] = MockRead(SYNCHRONOUS, 1, response2_.c_str()); |
| 282 return BuildSocketData(reads2_, writes2_); |
| 283 } |
| 284 |
| 285 private: |
| 286 // These need to be object-scoped since they have to remain valid until all |
| 287 // socket operations in the test are complete. |
| 288 std::string request1_; |
| 289 std::string request2_; |
| 290 std::string response1_; |
| 291 std::string response2_; |
| 292 MockRead reads1_[2]; |
| 293 MockWrite writes1_[1]; |
| 294 MockRead reads2_[1]; |
| 295 MockWrite writes2_[1]; |
| 296 |
| 297 DISALLOW_COPY_AND_ASSIGN(CommonAuthTestHelper); |
| 298 }; |
| 299 |
| 300 // Data and methods for BasicAuth tests. |
| 301 class WebSocketStreamCreateBasicAuthTest : public WebSocketStreamCreateTest { |
| 302 protected: |
| 303 void CreateAndConnectAuthHandshake(const std::string& url, |
| 304 const std::string& base64_user_pass, |
| 305 const std::string& response2) { |
| 306 AddRawExpectations(helper_.BuildSocketData1(kUnauthorizedResponse)); |
| 307 |
| 308 static const char request2format[] = |
| 309 "GET / HTTP/1.1\r\n" |
| 310 "Host: localhost\r\n" |
| 311 "Connection: Upgrade\r\n" |
| 312 "Pragma: no-cache\r\n" |
| 313 "Cache-Control: no-cache\r\n" |
| 314 "Authorization: Basic %s\r\n" |
| 315 "Upgrade: websocket\r\n" |
| 316 "Origin: http://localhost\r\n" |
| 317 "Sec-WebSocket-Version: 13\r\n" |
| 318 "User-Agent:\r\n" |
| 319 "Accept-Encoding: gzip,deflate\r\n" |
| 320 "Accept-Language: en-us,fr\r\n" |
| 321 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" |
| 322 "Sec-WebSocket-Extensions: permessage-deflate; " |
| 323 "client_max_window_bits\r\n" |
| 324 "\r\n"; |
| 325 const std::string request = |
| 326 base::StringPrintf(request2format, base64_user_pass.c_str()); |
| 327 CreateAndConnectRawExpectations( |
| 328 url, |
| 329 NoSubProtocols(), |
| 330 "http://localhost", |
| 331 helper_.BuildSocketData2(request, response2)); |
| 332 } |
| 333 |
| 334 static const char kUnauthorizedResponse[]; |
| 335 |
| 336 CommonAuthTestHelper helper_; |
| 337 }; |
| 338 |
| 339 class WebSocketStreamCreateDigestAuthTest : public WebSocketStreamCreateTest { |
| 340 protected: |
| 341 static const char kUnauthorizedResponse[]; |
| 342 static const char kAuthorizedRequest[]; |
| 343 |
| 344 CommonAuthTestHelper helper_; |
| 345 }; |
| 346 |
| 347 const char WebSocketStreamCreateBasicAuthTest::kUnauthorizedResponse[] = |
| 348 "HTTP/1.1 401 Unauthorized\r\n" |
| 349 "Content-Length: 0\r\n" |
| 350 "WWW-Authenticate: Basic realm=\"camelot\"\r\n" |
| 351 "\r\n"; |
| 352 |
| 353 // These negotiation values are borrowed from |
| 354 // http_auth_handler_digest_unittest.cc. Feel free to come up with new ones if |
| 355 // you are bored. Only the weakest (no qop) variants of Digest authentication |
| 356 // can be tested by this method, because the others involve random input. |
| 357 const char WebSocketStreamCreateDigestAuthTest::kUnauthorizedResponse[] = |
| 358 "HTTP/1.1 401 Unauthorized\r\n" |
| 359 "Content-Length: 0\r\n" |
| 360 "WWW-Authenticate: Digest realm=\"Oblivion\", nonce=\"nonce-value\"\r\n" |
| 361 "\r\n"; |
| 362 |
| 363 const char WebSocketStreamCreateDigestAuthTest::kAuthorizedRequest[] = |
| 364 "GET / HTTP/1.1\r\n" |
| 365 "Host: localhost\r\n" |
| 366 "Connection: Upgrade\r\n" |
| 367 "Pragma: no-cache\r\n" |
| 368 "Cache-Control: no-cache\r\n" |
| 369 "Authorization: Digest username=\"FooBar\", realm=\"Oblivion\", " |
| 370 "nonce=\"nonce-value\", uri=\"/\", " |
| 371 "response=\"f72ff54ebde2f928860f806ec04acd1b\"\r\n" |
| 372 "Upgrade: websocket\r\n" |
| 373 "Origin: http://localhost\r\n" |
| 374 "Sec-WebSocket-Version: 13\r\n" |
| 375 "User-Agent:\r\n" |
| 376 "Accept-Encoding: gzip,deflate\r\n" |
| 377 "Accept-Language: en-us,fr\r\n" |
| 378 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" |
| 379 "Sec-WebSocket-Extensions: permessage-deflate; " |
| 380 "client_max_window_bits\r\n" |
| 381 "\r\n"; |
| 382 |
229 class WebSocketStreamCreateUMATest : public ::testing::Test { | 383 class WebSocketStreamCreateUMATest : public ::testing::Test { |
230 public: | 384 public: |
231 // This enum should match with the enum in Delegate in websocket_stream.cc. | 385 // This enum should match with the enum in Delegate in websocket_stream.cc. |
232 enum HandshakeResult { | 386 enum HandshakeResult { |
233 INCOMPLETE, | 387 INCOMPLETE, |
234 CONNECTED, | 388 CONNECTED, |
235 FAILED, | 389 FAILED, |
236 NUM_HANDSHAKE_RESULT_TYPES, | 390 NUM_HANDSHAKE_RESULT_TYPES, |
237 }; | 391 }; |
238 | 392 |
(...skipping 672 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
911 stream_request_.reset(); | 1065 stream_request_.reset(); |
912 RunUntilIdle(); | 1066 RunUntilIdle(); |
913 EXPECT_FALSE(has_failed()); | 1067 EXPECT_FALSE(has_failed()); |
914 EXPECT_FALSE(stream_); | 1068 EXPECT_FALSE(stream_); |
915 EXPECT_FALSE(request_info_); | 1069 EXPECT_FALSE(request_info_); |
916 EXPECT_FALSE(response_info_); | 1070 EXPECT_FALSE(response_info_); |
917 } | 1071 } |
918 | 1072 |
919 // Connect failure must look just like negotiation failure. | 1073 // Connect failure must look just like negotiation failure. |
920 TEST_F(WebSocketStreamCreateTest, ConnectionFailure) { | 1074 TEST_F(WebSocketStreamCreateTest, ConnectionFailure) { |
921 scoped_ptr<DeterministicSocketData> socket_data( | 1075 scoped_ptr<DeterministicSocketData> socket_data(BuildNullSocketData()); |
922 new DeterministicSocketData(NULL, 0, NULL, 0)); | |
923 socket_data->set_connect_data( | 1076 socket_data->set_connect_data( |
924 MockConnect(SYNCHRONOUS, ERR_CONNECTION_REFUSED)); | 1077 MockConnect(SYNCHRONOUS, ERR_CONNECTION_REFUSED)); |
925 CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(), | 1078 CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(), |
926 "http://localhost", socket_data.Pass()); | 1079 "http://localhost", socket_data.Pass()); |
927 RunUntilIdle(); | 1080 RunUntilIdle(); |
928 EXPECT_TRUE(has_failed()); | 1081 EXPECT_TRUE(has_failed()); |
929 EXPECT_EQ("Error in connection establishment: net::ERR_CONNECTION_REFUSED", | 1082 EXPECT_EQ("Error in connection establishment: net::ERR_CONNECTION_REFUSED", |
930 failure_message()); | 1083 failure_message()); |
931 EXPECT_FALSE(request_info_); | 1084 EXPECT_FALSE(request_info_); |
932 EXPECT_FALSE(response_info_); | 1085 EXPECT_FALSE(response_info_); |
933 } | 1086 } |
934 | 1087 |
935 // Connect timeout must look just like any other failure. | 1088 // Connect timeout must look just like any other failure. |
936 TEST_F(WebSocketStreamCreateTest, ConnectionTimeout) { | 1089 TEST_F(WebSocketStreamCreateTest, ConnectionTimeout) { |
937 scoped_ptr<DeterministicSocketData> socket_data( | 1090 scoped_ptr<DeterministicSocketData> socket_data(BuildNullSocketData()); |
938 new DeterministicSocketData(NULL, 0, NULL, 0)); | |
939 socket_data->set_connect_data( | 1091 socket_data->set_connect_data( |
940 MockConnect(ASYNC, ERR_CONNECTION_TIMED_OUT)); | 1092 MockConnect(ASYNC, ERR_CONNECTION_TIMED_OUT)); |
941 CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(), | 1093 CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(), |
942 "http://localhost", socket_data.Pass()); | 1094 "http://localhost", socket_data.Pass()); |
943 RunUntilIdle(); | 1095 RunUntilIdle(); |
944 EXPECT_TRUE(has_failed()); | 1096 EXPECT_TRUE(has_failed()); |
945 EXPECT_EQ("Error in connection establishment: net::ERR_CONNECTION_TIMED_OUT", | 1097 EXPECT_EQ("Error in connection establishment: net::ERR_CONNECTION_TIMED_OUT", |
946 failure_message()); | 1098 failure_message()); |
947 } | 1099 } |
948 | 1100 |
949 // Cancellation during connect works. | 1101 // Cancellation during connect works. |
950 TEST_F(WebSocketStreamCreateTest, CancellationDuringConnect) { | 1102 TEST_F(WebSocketStreamCreateTest, CancellationDuringConnect) { |
951 scoped_ptr<DeterministicSocketData> socket_data( | 1103 scoped_ptr<DeterministicSocketData> socket_data(BuildNullSocketData()); |
952 new DeterministicSocketData(NULL, 0, NULL, 0)); | |
953 socket_data->set_connect_data(MockConnect(SYNCHRONOUS, ERR_IO_PENDING)); | 1104 socket_data->set_connect_data(MockConnect(SYNCHRONOUS, ERR_IO_PENDING)); |
954 CreateAndConnectRawExpectations("ws://localhost/", | 1105 CreateAndConnectRawExpectations("ws://localhost/", |
955 NoSubProtocols(), | 1106 NoSubProtocols(), |
956 "http://localhost", | 1107 "http://localhost", |
957 socket_data.Pass()); | 1108 socket_data.Pass()); |
958 stream_request_.reset(); | 1109 stream_request_.reset(); |
959 RunUntilIdle(); | 1110 RunUntilIdle(); |
960 EXPECT_FALSE(has_failed()); | 1111 EXPECT_FALSE(has_failed()); |
961 EXPECT_FALSE(stream_); | 1112 EXPECT_FALSE(stream_); |
962 } | 1113 } |
(...skipping 21 matching lines...) Expand all Loading... |
984 EXPECT_FALSE(response_info_); | 1135 EXPECT_FALSE(response_info_); |
985 } | 1136 } |
986 | 1137 |
987 // Cancellation during read of the response headers works. | 1138 // Cancellation during read of the response headers works. |
988 TEST_F(WebSocketStreamCreateTest, CancellationDuringRead) { | 1139 TEST_F(WebSocketStreamCreateTest, CancellationDuringRead) { |
989 std::string request = WebSocketStandardRequest("/", "http://localhost", ""); | 1140 std::string request = WebSocketStandardRequest("/", "http://localhost", ""); |
990 MockWrite writes[] = {MockWrite(ASYNC, 0, request.c_str())}; | 1141 MockWrite writes[] = {MockWrite(ASYNC, 0, request.c_str())}; |
991 MockRead reads[] = { | 1142 MockRead reads[] = { |
992 MockRead(ASYNC, 1, "HTTP/1.1 101 Switching Protocols\r\nUpgr"), | 1143 MockRead(ASYNC, 1, "HTTP/1.1 101 Switching Protocols\r\nUpgr"), |
993 }; | 1144 }; |
994 DeterministicSocketData* socket_data(new DeterministicSocketData( | 1145 scoped_ptr<DeterministicSocketData> socket_data( |
995 reads, arraysize(reads), writes, arraysize(writes))); | 1146 BuildSocketData(reads, writes)); |
996 socket_data->set_connect_data(MockConnect(SYNCHRONOUS, OK)); | |
997 socket_data->SetStop(1); | 1147 socket_data->SetStop(1); |
| 1148 DeterministicSocketData* socket_data_raw_ptr = socket_data.get(); |
998 CreateAndConnectRawExpectations("ws://localhost/", | 1149 CreateAndConnectRawExpectations("ws://localhost/", |
999 NoSubProtocols(), | 1150 NoSubProtocols(), |
1000 "http://localhost", | 1151 "http://localhost", |
1001 make_scoped_ptr(socket_data)); | 1152 socket_data.Pass()); |
1002 socket_data->Run(); | 1153 socket_data_raw_ptr->Run(); |
1003 stream_request_.reset(); | 1154 stream_request_.reset(); |
1004 RunUntilIdle(); | 1155 RunUntilIdle(); |
1005 EXPECT_FALSE(has_failed()); | 1156 EXPECT_FALSE(has_failed()); |
1006 EXPECT_FALSE(stream_); | 1157 EXPECT_FALSE(stream_); |
1007 EXPECT_TRUE(request_info_); | 1158 EXPECT_TRUE(request_info_); |
1008 EXPECT_FALSE(response_info_); | 1159 EXPECT_FALSE(response_info_); |
1009 } | 1160 } |
1010 | 1161 |
1011 // Over-size response headers (> 256KB) should not cause a crash. This is a | 1162 // Over-size response headers (> 256KB) should not cause a crash. This is a |
1012 // regression test for crbug.com/339456. It is based on the layout test | 1163 // regression test for crbug.com/339456. It is based on the layout test |
(...skipping 12 matching lines...) Expand all Loading... |
1025 EXPECT_FALSE(response_info_); | 1176 EXPECT_FALSE(response_info_); |
1026 } | 1177 } |
1027 | 1178 |
1028 // If the remote host closes the connection without sending headers, we should | 1179 // If the remote host closes the connection without sending headers, we should |
1029 // log the console message "Connection closed before receiving a handshake | 1180 // log the console message "Connection closed before receiving a handshake |
1030 // response". | 1181 // response". |
1031 TEST_F(WebSocketStreamCreateTest, NoResponse) { | 1182 TEST_F(WebSocketStreamCreateTest, NoResponse) { |
1032 std::string request = WebSocketStandardRequest("/", "http://localhost", ""); | 1183 std::string request = WebSocketStandardRequest("/", "http://localhost", ""); |
1033 MockWrite writes[] = {MockWrite(ASYNC, request.data(), request.size(), 0)}; | 1184 MockWrite writes[] = {MockWrite(ASYNC, request.data(), request.size(), 0)}; |
1034 MockRead reads[] = {MockRead(ASYNC, 0, 1)}; | 1185 MockRead reads[] = {MockRead(ASYNC, 0, 1)}; |
1035 DeterministicSocketData* socket_data(new DeterministicSocketData( | 1186 scoped_ptr<DeterministicSocketData> socket_data( |
1036 reads, arraysize(reads), writes, arraysize(writes))); | 1187 BuildSocketData(reads, writes)); |
1037 socket_data->set_connect_data(MockConnect(SYNCHRONOUS, OK)); | 1188 DeterministicSocketData* socket_data_raw_ptr = socket_data.get(); |
1038 CreateAndConnectRawExpectations("ws://localhost/", | 1189 CreateAndConnectRawExpectations("ws://localhost/", |
1039 NoSubProtocols(), | 1190 NoSubProtocols(), |
1040 "http://localhost", | 1191 "http://localhost", |
1041 make_scoped_ptr(socket_data)); | 1192 socket_data.Pass()); |
1042 socket_data->RunFor(2); | 1193 socket_data_raw_ptr->RunFor(2); |
1043 EXPECT_TRUE(has_failed()); | 1194 EXPECT_TRUE(has_failed()); |
1044 EXPECT_FALSE(stream_); | 1195 EXPECT_FALSE(stream_); |
1045 EXPECT_FALSE(response_info_); | 1196 EXPECT_FALSE(response_info_); |
1046 EXPECT_EQ("Connection closed before receiving a handshake response", | 1197 EXPECT_EQ("Connection closed before receiving a handshake response", |
1047 failure_message()); | 1198 failure_message()); |
1048 } | 1199 } |
1049 | 1200 |
1050 TEST_F(WebSocketStreamCreateTest, SelfSignedCertificateFailure) { | 1201 TEST_F(WebSocketStreamCreateTest, SelfSignedCertificateFailure) { |
1051 ssl_data_.push_back( | 1202 ssl_data_.push_back( |
1052 new SSLSocketDataProvider(ASYNC, ERR_CERT_AUTHORITY_INVALID)); | 1203 new SSLSocketDataProvider(ASYNC, ERR_CERT_AUTHORITY_INVALID)); |
1053 ssl_data_[0]->cert = | 1204 ssl_data_[0]->cert = |
1054 ImportCertFromFile(GetTestCertsDirectory(), "unittest.selfsigned.der"); | 1205 ImportCertFromFile(GetTestCertsDirectory(), "unittest.selfsigned.der"); |
1055 ASSERT_TRUE(ssl_data_[0]->cert); | 1206 ASSERT_TRUE(ssl_data_[0]->cert); |
1056 scoped_ptr<DeterministicSocketData> raw_socket_data( | 1207 scoped_ptr<DeterministicSocketData> raw_socket_data(BuildNullSocketData()); |
1057 new DeterministicSocketData(NULL, 0, NULL, 0)); | |
1058 CreateAndConnectRawExpectations("wss://localhost/", | 1208 CreateAndConnectRawExpectations("wss://localhost/", |
1059 NoSubProtocols(), | 1209 NoSubProtocols(), |
1060 "http://localhost", | 1210 "http://localhost", |
1061 raw_socket_data.Pass()); | 1211 raw_socket_data.Pass()); |
1062 RunUntilIdle(); | 1212 RunUntilIdle(); |
1063 EXPECT_FALSE(has_failed()); | 1213 EXPECT_FALSE(has_failed()); |
1064 ASSERT_TRUE(ssl_error_callbacks_); | 1214 ASSERT_TRUE(ssl_error_callbacks_); |
1065 ssl_error_callbacks_->CancelSSLRequest(ERR_CERT_AUTHORITY_INVALID, | 1215 ssl_error_callbacks_->CancelSSLRequest(ERR_CERT_AUTHORITY_INVALID, |
1066 &ssl_info_); | 1216 &ssl_info_); |
1067 RunUntilIdle(); | 1217 RunUntilIdle(); |
1068 EXPECT_TRUE(has_failed()); | 1218 EXPECT_TRUE(has_failed()); |
1069 } | 1219 } |
1070 | 1220 |
1071 TEST_F(WebSocketStreamCreateTest, SelfSignedCertificateSuccess) { | 1221 TEST_F(WebSocketStreamCreateTest, SelfSignedCertificateSuccess) { |
1072 scoped_ptr<SSLSocketDataProvider> ssl_data( | 1222 scoped_ptr<SSLSocketDataProvider> ssl_data( |
1073 new SSLSocketDataProvider(ASYNC, ERR_CERT_AUTHORITY_INVALID)); | 1223 new SSLSocketDataProvider(ASYNC, ERR_CERT_AUTHORITY_INVALID)); |
1074 ssl_data->cert = | 1224 ssl_data->cert = |
1075 ImportCertFromFile(GetTestCertsDirectory(), "unittest.selfsigned.der"); | 1225 ImportCertFromFile(GetTestCertsDirectory(), "unittest.selfsigned.der"); |
1076 ASSERT_TRUE(ssl_data->cert); | 1226 ASSERT_TRUE(ssl_data->cert); |
1077 ssl_data_.push_back(ssl_data.release()); | 1227 ssl_data_.push_back(ssl_data.release()); |
1078 ssl_data.reset(new SSLSocketDataProvider(ASYNC, OK)); | 1228 ssl_data.reset(new SSLSocketDataProvider(ASYNC, OK)); |
1079 ssl_data_.push_back(ssl_data.release()); | 1229 ssl_data_.push_back(ssl_data.release()); |
1080 url_request_context_host_.AddRawExpectations( | 1230 url_request_context_host_.AddRawExpectations(BuildNullSocketData()); |
1081 make_scoped_ptr(new DeterministicSocketData(NULL, 0, NULL, 0))); | |
1082 CreateAndConnectStandard( | 1231 CreateAndConnectStandard( |
1083 "wss://localhost/", "/", NoSubProtocols(), "http://localhost", "", ""); | 1232 "wss://localhost/", "/", NoSubProtocols(), "http://localhost", "", ""); |
1084 RunUntilIdle(); | 1233 RunUntilIdle(); |
1085 ASSERT_TRUE(ssl_error_callbacks_); | 1234 ASSERT_TRUE(ssl_error_callbacks_); |
1086 ssl_error_callbacks_->ContinueSSLRequest(); | 1235 ssl_error_callbacks_->ContinueSSLRequest(); |
1087 RunUntilIdle(); | 1236 RunUntilIdle(); |
1088 EXPECT_FALSE(has_failed()); | 1237 EXPECT_FALSE(has_failed()); |
1089 EXPECT_TRUE(stream_); | 1238 EXPECT_TRUE(stream_); |
1090 } | 1239 } |
1091 | 1240 |
| 1241 // If the server requests authorisation, but we have no credentials, the |
| 1242 // connection should fail cleanly. |
| 1243 TEST_F(WebSocketStreamCreateBasicAuthTest, FailureNoCredentials) { |
| 1244 CreateAndConnectCustomResponse("ws://localhost/", |
| 1245 "/", |
| 1246 NoSubProtocols(), |
| 1247 "http://localhost", |
| 1248 "", |
| 1249 kUnauthorizedResponse); |
| 1250 RunUntilIdle(); |
| 1251 EXPECT_TRUE(has_failed()); |
| 1252 EXPECT_EQ("HTTP Authentication failed; no valid credentials available", |
| 1253 failure_message()); |
| 1254 EXPECT_TRUE(response_info_); |
| 1255 } |
| 1256 |
| 1257 TEST_F(WebSocketStreamCreateBasicAuthTest, SuccessPasswordInUrl) { |
| 1258 CreateAndConnectAuthHandshake("ws://foo:bar@localhost/", |
| 1259 "Zm9vOmJhcg==", |
| 1260 WebSocketStandardResponse(std::string())); |
| 1261 RunUntilIdle(); |
| 1262 EXPECT_FALSE(has_failed()); |
| 1263 EXPECT_TRUE(stream_); |
| 1264 ASSERT_TRUE(response_info_); |
| 1265 EXPECT_EQ(101, response_info_->status_code); |
| 1266 } |
| 1267 |
| 1268 TEST_F(WebSocketStreamCreateBasicAuthTest, FailureIncorrectPasswordInUrl) { |
| 1269 CreateAndConnectAuthHandshake( |
| 1270 "ws://foo:baz@localhost/", "Zm9vOmJheg==", kUnauthorizedResponse); |
| 1271 RunUntilIdle(); |
| 1272 EXPECT_TRUE(has_failed()); |
| 1273 EXPECT_TRUE(response_info_); |
| 1274 } |
| 1275 |
| 1276 // Digest auth has the same connection semantics as Basic auth, so we can |
| 1277 // generally assume that whatever works for Basic auth will also work for |
| 1278 // Digest. There's just one test here, to confirm that it works at all. |
| 1279 TEST_F(WebSocketStreamCreateDigestAuthTest, DigestPasswordInUrl) { |
| 1280 AddRawExpectations(helper_.BuildSocketData1(kUnauthorizedResponse)); |
| 1281 |
| 1282 CreateAndConnectRawExpectations( |
| 1283 "ws://FooBar:pass@localhost/", |
| 1284 NoSubProtocols(), |
| 1285 "http://localhost", |
| 1286 helper_.BuildSocketData2(kAuthorizedRequest, |
| 1287 WebSocketStandardResponse(std::string()))); |
| 1288 RunUntilIdle(); |
| 1289 EXPECT_FALSE(has_failed()); |
| 1290 EXPECT_TRUE(stream_); |
| 1291 ASSERT_TRUE(response_info_); |
| 1292 EXPECT_EQ(101, response_info_->status_code); |
| 1293 } |
| 1294 |
1092 TEST_F(WebSocketStreamCreateUMATest, Incomplete) { | 1295 TEST_F(WebSocketStreamCreateUMATest, Incomplete) { |
1093 const std::string name("Net.WebSocket.HandshakeResult"); | 1296 const std::string name("Net.WebSocket.HandshakeResult"); |
1094 scoped_ptr<base::HistogramSamples> original(GetSamples(name)); | 1297 scoped_ptr<base::HistogramSamples> original(GetSamples(name)); |
1095 | 1298 |
1096 { | 1299 { |
1097 StreamCreation creation; | 1300 StreamCreation creation; |
1098 creation.CreateAndConnectStandard("ws://localhost/", | 1301 creation.CreateAndConnectStandard("ws://localhost/", |
1099 "/", | 1302 "/", |
1100 creation.NoSubProtocols(), | 1303 creation.NoSubProtocols(), |
1101 "http://localhost", | 1304 "http://localhost", |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1164 if (original) { | 1367 if (original) { |
1165 samples->Subtract(*original); // Cancel the original values. | 1368 samples->Subtract(*original); // Cancel the original values. |
1166 } | 1369 } |
1167 EXPECT_EQ(1, samples->GetCount(INCOMPLETE)); | 1370 EXPECT_EQ(1, samples->GetCount(INCOMPLETE)); |
1168 EXPECT_EQ(0, samples->GetCount(CONNECTED)); | 1371 EXPECT_EQ(0, samples->GetCount(CONNECTED)); |
1169 EXPECT_EQ(0, samples->GetCount(FAILED)); | 1372 EXPECT_EQ(0, samples->GetCount(FAILED)); |
1170 } | 1373 } |
1171 | 1374 |
1172 } // namespace | 1375 } // namespace |
1173 } // namespace net | 1376 } // namespace net |
OLD | NEW |