| Index: net/http/http_network_transaction_spdy21_unittest.cc | 
| =================================================================== | 
| --- net/http/http_network_transaction_spdy21_unittest.cc	(revision 138297) | 
| +++ net/http/http_network_transaction_spdy21_unittest.cc	(working copy) | 
| @@ -3724,8 +3724,8 @@ | 
|  | 
| // Test the request-challenge-retry sequence for basic auth when there is | 
| // an identity in the URL. The request should be sent as normal, but when | 
| -// it fails the identity from the URL is no longer used. | 
| -TEST_F(HttpNetworkTransactionSpdy21Test, IgnoreAuthIdentityInURL) { | 
| +// it fails the identity from the URL is used to answer the challenge. | 
| +TEST_F(HttpNetworkTransactionSpdy21Test, AuthIdentityInURL) { | 
| HttpRequestInfo request; | 
| request.method = "GET"; | 
| request.url = GURL("http://foo:b@r@www.google.com/"); | 
| @@ -3752,21 +3752,164 @@ | 
| MockRead(SYNCHRONOUS, ERR_FAILED), | 
| }; | 
|  | 
| +  // After the challenge above, the transaction will be restarted using the | 
| +  // identity from the url (foo, b@r) to answer the challenge. | 
| +  MockWrite data_writes2[] = { | 
| +    MockWrite("GET / HTTP/1.1\r\n" | 
| +              "Host: www.google.com\r\n" | 
| +              "Connection: keep-alive\r\n" | 
| +              "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"), | 
| +  }; | 
| + | 
| +  MockRead data_reads2[] = { | 
| +    MockRead("HTTP/1.0 200 OK\r\n"), | 
| +    MockRead("Content-Length: 100\r\n\r\n"), | 
| +    MockRead(SYNCHRONOUS, OK), | 
| +  }; | 
| + | 
| StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), | 
| data_writes1, arraysize(data_writes1)); | 
| +  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), | 
| +                                 data_writes2, arraysize(data_writes2)); | 
| session_deps.socket_factory.AddSocketDataProvider(&data1); | 
| +  session_deps.socket_factory.AddSocketDataProvider(&data2); | 
|  | 
| TestCompletionCallback callback1; | 
| int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); | 
| EXPECT_EQ(ERR_IO_PENDING, rv); | 
| rv = callback1.WaitForResult(); | 
| EXPECT_EQ(OK, rv); | 
| +  EXPECT_TRUE(trans->IsReadyToRestartForAuth()); | 
| + | 
| +  TestCompletionCallback callback2; | 
| +  rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback()); | 
| +  EXPECT_EQ(ERR_IO_PENDING, rv); | 
| +  rv = callback2.WaitForResult(); | 
| +  EXPECT_EQ(OK, rv); | 
| EXPECT_FALSE(trans->IsReadyToRestartForAuth()); | 
|  | 
| +  const HttpResponseInfo* response = trans->GetResponseInfo(); | 
| +  ASSERT_TRUE(response != NULL); | 
| + | 
| +  // There is no challenge info, since the identity in URL worked. | 
| +  EXPECT_TRUE(response->auth_challenge.get() == NULL); | 
| + | 
| +  EXPECT_EQ(100, response->headers->GetContentLength()); | 
| + | 
| // Empty the current queue. | 
| MessageLoop::current()->RunAllPending(); | 
| } | 
|  | 
| +// Test the request-challenge-retry sequence for basic auth when there is an | 
| +// incorrect identity in the URL. The identity from the URL should be used only | 
| +// once. | 
| +TEST_F(HttpNetworkTransactionSpdy21Test, WrongAuthIdentityInURL) { | 
| +  HttpRequestInfo request; | 
| +  request.method = "GET"; | 
| +  // Note: the URL has a username:password in it.  The password "baz" is | 
| +  // wrong (should be "bar"). | 
| +  request.url = GURL("http://foo:baz@www.google.com/"); | 
| + | 
| +  request.load_flags = LOAD_NORMAL; | 
| + | 
| +  SessionDependencies session_deps; | 
| +  scoped_ptr<HttpTransaction> trans( | 
| +      new HttpNetworkTransaction(CreateSession(&session_deps))); | 
| + | 
| +  MockWrite data_writes1[] = { | 
| +    MockWrite("GET / HTTP/1.1\r\n" | 
| +              "Host: www.google.com\r\n" | 
| +              "Connection: keep-alive\r\n\r\n"), | 
| +  }; | 
| + | 
| +  MockRead data_reads1[] = { | 
| +    MockRead("HTTP/1.0 401 Unauthorized\r\n"), | 
| +    MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), | 
| +    MockRead("Content-Length: 10\r\n\r\n"), | 
| +    MockRead(SYNCHRONOUS, ERR_FAILED), | 
| +  }; | 
| + | 
| +  // After the challenge above, the transaction will be restarted using the | 
| +  // identity from the url (foo, baz) to answer the challenge. | 
| +  MockWrite data_writes2[] = { | 
| +    MockWrite("GET / HTTP/1.1\r\n" | 
| +              "Host: www.google.com\r\n" | 
| +              "Connection: keep-alive\r\n" | 
| +              "Authorization: Basic Zm9vOmJheg==\r\n\r\n"), | 
| +  }; | 
| + | 
| +  MockRead data_reads2[] = { | 
| +    MockRead("HTTP/1.0 401 Unauthorized\r\n"), | 
| +    MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), | 
| +    MockRead("Content-Length: 10\r\n\r\n"), | 
| +    MockRead(SYNCHRONOUS, ERR_FAILED), | 
| +  }; | 
| + | 
| +  // After the challenge above, the transaction will be restarted using the | 
| +  // identity supplied by the user (foo, bar) to answer the challenge. | 
| +  MockWrite data_writes3[] = { | 
| +    MockWrite("GET / HTTP/1.1\r\n" | 
| +              "Host: www.google.com\r\n" | 
| +              "Connection: keep-alive\r\n" | 
| +              "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), | 
| +  }; | 
| + | 
| +  MockRead data_reads3[] = { | 
| +    MockRead("HTTP/1.0 200 OK\r\n"), | 
| +    MockRead("Content-Length: 100\r\n\r\n"), | 
| +    MockRead(SYNCHRONOUS, OK), | 
| +  }; | 
| + | 
| +  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), | 
| +                                 data_writes1, arraysize(data_writes1)); | 
| +  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), | 
| +                                 data_writes2, arraysize(data_writes2)); | 
| +  StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3), | 
| +                                 data_writes3, arraysize(data_writes3)); | 
| +  session_deps.socket_factory.AddSocketDataProvider(&data1); | 
| +  session_deps.socket_factory.AddSocketDataProvider(&data2); | 
| +  session_deps.socket_factory.AddSocketDataProvider(&data3); | 
| + | 
| +  TestCompletionCallback callback1; | 
| + | 
| +  int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); | 
| +  EXPECT_EQ(ERR_IO_PENDING, rv); | 
| + | 
| +  rv = callback1.WaitForResult(); | 
| +  EXPECT_EQ(OK, rv); | 
| + | 
| +  EXPECT_TRUE(trans->IsReadyToRestartForAuth()); | 
| +  TestCompletionCallback callback2; | 
| +  rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback()); | 
| +  EXPECT_EQ(ERR_IO_PENDING, rv); | 
| +  rv = callback2.WaitForResult(); | 
| +  EXPECT_EQ(OK, rv); | 
| +  EXPECT_FALSE(trans->IsReadyToRestartForAuth()); | 
| + | 
| +  const HttpResponseInfo* response = trans->GetResponseInfo(); | 
| +  ASSERT_TRUE(response != NULL); | 
| +  EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get())); | 
| + | 
| +  TestCompletionCallback callback3; | 
| +  rv = trans->RestartWithAuth( | 
| +      AuthCredentials(kFoo, kBar), callback3.callback()); | 
| +  EXPECT_EQ(ERR_IO_PENDING, rv); | 
| +  rv = callback3.WaitForResult(); | 
| +  EXPECT_EQ(OK, rv); | 
| +  EXPECT_FALSE(trans->IsReadyToRestartForAuth()); | 
| + | 
| +  response = trans->GetResponseInfo(); | 
| +  ASSERT_TRUE(response != NULL); | 
| + | 
| +  // There is no challenge info, since the identity worked. | 
| +  EXPECT_TRUE(response->auth_challenge.get() == NULL); | 
| + | 
| +  EXPECT_EQ(100, response->headers->GetContentLength()); | 
| + | 
| +  // Empty the current queue. | 
| +  MessageLoop::current()->RunAllPending(); | 
| +} | 
| + | 
| // Test that previously tried username/passwords for a realm get re-used. | 
| TEST_F(HttpNetworkTransactionSpdy21Test, BasicAuthCacheAndPreauth) { | 
| SessionDependencies session_deps; | 
|  |