12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/url_request/url_request_http_job.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <cstddef>
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/compiler_specific.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/ref_counted.h"
111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/memory/scoped_ptr.h"
12a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/run_loop.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/auth.h"
140f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "net/base/request_priority.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/http/http_transaction_factory.h"
16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "net/http/http_transaction_test_util.h"
17a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/socket/socket_test_util.h"
181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "net/url_request/url_request.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/url_request/url_request_status.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/url_request/url_request_test_util.h"
21a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/websockets/websocket_handshake_stream_base.h"
22a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace net {
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
30a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)using ::testing::Return;
31a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Inherit from URLRequestHttpJob to expose the priority and some
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// other hidden functions.
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class TestURLRequestHttpJob : public URLRequestHttpJob {
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  explicit TestURLRequestHttpJob(URLRequest* request)
37a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      : URLRequestHttpJob(request, request->context()->network_delegate(),
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          request->context()->http_user_agent_settings()) {}
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  using URLRequestHttpJob::SetPriority;
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  using URLRequestHttpJob::Start;
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  using URLRequestHttpJob::Kill;
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  using URLRequestHttpJob::priority;
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) protected:
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~TestURLRequestHttpJob() {}
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class URLRequestHttpJobTest : public ::testing::Test {
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) protected:
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  URLRequestHttpJobTest()
521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      : req_(context_.CreateRequest(GURL("http://www.example.com"),
531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                    DEFAULT_PRIORITY,
541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                    &delegate_,
551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                    NULL)) {
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    context_.set_http_transaction_factory(&network_layer_);
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  bool TransactionAcceptsSdchEncoding() {
6003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    base::WeakPtr<MockNetworkTransaction> transaction(
6103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        network_layer_.last_transaction());
6203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    EXPECT_TRUE(transaction);
6303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (!transaction) return false;
6403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
6503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const HttpRequestInfo* request_info = transaction->request();
6603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    EXPECT_TRUE(request_info);
6703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (!request_info) return false;
6803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
6903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    std::string encoding_headers;
7003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    bool get_success = request_info->extra_headers.GetHeader(
7103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        "Accept-Encoding", &encoding_headers);
7203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    EXPECT_TRUE(get_success);
7303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (!get_success) return false;
7403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
7503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    // This check isn't wrapped with EXPECT* macros because different
7603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    // results from this function may be expected in different tests.
7703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    std::vector<std::string> tokens;
781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    size_t num_tokens = Tokenize(encoding_headers, ", ", &tokens);
7903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    for (size_t i = 0; i < num_tokens; i++) {
8003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      if (!base::strncasecmp(tokens[i].data(), "sdch", tokens[i].length()))
8103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        return true;
8203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    }
8303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return false;
8403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
8503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
8603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  void EnableSdch() {
8703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    context_.SetSdchManager(scoped_ptr<SdchManager>(new SdchManager).Pass());
8803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
8903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockNetworkLayer network_layer_;
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestURLRequestContext context_;
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestDelegate delegate_;
931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<URLRequest> req_;
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Make sure that SetPriority actually sets the URLRequestHttpJob's
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// priority, both before and after start.
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(URLRequestHttpJobTest, SetPriorityBasic) {
991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_refptr<TestURLRequestHttpJob> job(
1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new TestURLRequestHttpJob(req_.get()));
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DEFAULT_PRIORITY, job->priority());
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  job->SetPriority(LOWEST);
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(LOWEST, job->priority());
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  job->SetPriority(LOW);
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(LOW, job->priority());
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  job->Start();
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(LOW, job->priority());
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  job->SetPriority(MEDIUM);
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(MEDIUM, job->priority());
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Make sure that URLRequestHttpJob passes on its priority to its
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// transaction on start.
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(URLRequestHttpJobTest, SetTransactionPriorityOnStart) {
1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_refptr<TestURLRequestHttpJob> job(
1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new TestURLRequestHttpJob(req_.get()));
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  job->SetPriority(LOW);
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(network_layer_.last_transaction());
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  job->Start();
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(network_layer_.last_transaction());
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(LOW, network_layer_.last_transaction()->priority());
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Make sure that URLRequestHttpJob passes on its priority updates to
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// its transaction.
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(URLRequestHttpJobTest, SetTransactionPriority) {
1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_refptr<TestURLRequestHttpJob> job(
1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new TestURLRequestHttpJob(req_.get()));
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  job->SetPriority(LOW);
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  job->Start();
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(network_layer_.last_transaction());
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(LOW, network_layer_.last_transaction()->priority());
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  job->SetPriority(HIGHEST);
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(HIGHEST, network_layer_.last_transaction()->priority());
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Make sure that URLRequestHttpJob passes on its priority updates to
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// newly-created transactions after the first one.
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(URLRequestHttpJobTest, SetSubsequentTransactionPriority) {
1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_refptr<TestURLRequestHttpJob> job(
1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new TestURLRequestHttpJob(req_.get()));
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  job->Start();
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  job->SetPriority(LOW);
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(network_layer_.last_transaction());
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(LOW, network_layer_.last_transaction()->priority());
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  job->Kill();
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  network_layer_.ClearLastTransaction();
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Creates a second transaction.
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  job->Start();
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(network_layer_.last_transaction());
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(LOW, network_layer_.last_transaction()->priority());
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
16503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Confirm we do advertise SDCH encoding in the case of a GET.
16603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)TEST_F(URLRequestHttpJobTest, SdchAdvertisementGet) {
16703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  EnableSdch();
1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  req_->set_method("GET");  // Redundant with default.
1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_refptr<TestURLRequestHttpJob> job(
1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new TestURLRequestHttpJob(req_.get()));
17103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  job->Start();
17203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  EXPECT_TRUE(TransactionAcceptsSdchEncoding());
17303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
17403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
17503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Confirm we don't advertise SDCH encoding in the case of a POST.
17603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)TEST_F(URLRequestHttpJobTest, SdchAdvertisementPost) {
17703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  EnableSdch();
1781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  req_->set_method("POST");
1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_refptr<TestURLRequestHttpJob> job(
1801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new TestURLRequestHttpJob(req_.get()));
18103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  job->Start();
18203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  EXPECT_FALSE(TransactionAcceptsSdchEncoding());
18303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
18403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
185a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// This base class just serves to set up some things before the TestURLRequest
186a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// constructor is called.
187a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class URLRequestHttpJobWebSocketTestBase : public ::testing::Test {
188a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) protected:
189a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  URLRequestHttpJobWebSocketTestBase() : socket_data_(NULL, 0, NULL, 0),
190a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                         context_(true) {
191a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // A Network Delegate is required for the WebSocketHandshakeStreamBase
192a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // object to be passed on to the HttpNetworkTransaction.
193a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    context_.set_network_delegate(&network_delegate_);
194a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
195a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // Attempting to create real ClientSocketHandles is not going to work out so
196a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // well. Set up a fake socket factory.
197a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    socket_factory_.AddSocketDataProvider(&socket_data_);
198a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    context_.set_client_socket_factory(&socket_factory_);
199a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    context_.Init();
200a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
201a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
202a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  StaticSocketDataProvider socket_data_;
203a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  TestNetworkDelegate network_delegate_;
204a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  MockClientSocketFactory socket_factory_;
205a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  TestURLRequestContext context_;
206a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)};
207a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
208a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class URLRequestHttpJobWebSocketTest
209a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    : public URLRequestHttpJobWebSocketTestBase {
210a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) protected:
211a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  URLRequestHttpJobWebSocketTest()
2121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      : req_(context_.CreateRequest(GURL("ws://www.example.com"),
2131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                    DEFAULT_PRIORITY,
2141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                    &delegate_,
2151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                    NULL)) {
216a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // The TestNetworkDelegate expects a call to NotifyBeforeURLRequest before
217a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // anything else happens.
218a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    GURL url("ws://localhost/");
219a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    TestCompletionCallback dummy;
2201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    network_delegate_.NotifyBeforeURLRequest(
2211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        req_.get(), dummy.callback(), &url);
222a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
223a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
224a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  TestDelegate delegate_;
2251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<URLRequest> req_;
226a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)};
227a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
228a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class MockCreateHelper : public WebSocketHandshakeStreamBase::CreateHelper {
229a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) public:
230a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // GoogleMock does not appear to play nicely with move-only types like
231a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // scoped_ptr, so this forwarding method acts as a workaround.
232a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual WebSocketHandshakeStreamBase* CreateBasicStream(
233a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      scoped_ptr<ClientSocketHandle> connection,
234a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      bool using_proxy) OVERRIDE {
235a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // Discard the arguments since we don't need them anyway.
236a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return CreateBasicStreamMock();
237a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
238a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
239a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  MOCK_METHOD0(CreateBasicStreamMock,
240a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)               WebSocketHandshakeStreamBase*());
241a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
242a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  MOCK_METHOD2(CreateSpdyStream,
243a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)               WebSocketHandshakeStreamBase*(const base::WeakPtr<SpdySession>&,
244a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                             bool));
245a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)};
246a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
247a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class FakeWebSocketHandshakeStream : public WebSocketHandshakeStreamBase {
248a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) public:
249a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  FakeWebSocketHandshakeStream() : initialize_stream_was_called_(false) {}
250a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
251a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  bool initialize_stream_was_called() const {
252a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return initialize_stream_was_called_;
253a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
254a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
255a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Fake implementation of HttpStreamBase methods.
256a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual int InitializeStream(const HttpRequestInfo* request_info,
257a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                               RequestPriority priority,
258a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                               const BoundNetLog& net_log,
259a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                               const CompletionCallback& callback) OVERRIDE {
260a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    initialize_stream_was_called_ = true;
261a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return ERR_IO_PENDING;
262a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
263a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
264a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual int SendRequest(const HttpRequestHeaders& request_headers,
265a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                          HttpResponseInfo* response,
266a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                          const CompletionCallback& callback) OVERRIDE {
267a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return ERR_IO_PENDING;
268a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
269a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
270a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual int ReadResponseHeaders(const CompletionCallback& callback) OVERRIDE {
271a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return ERR_IO_PENDING;
272a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
273a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
274a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual int ReadResponseBody(IOBuffer* buf,
275a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                               int buf_len,
276a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                               const CompletionCallback& callback) OVERRIDE {
277a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return ERR_IO_PENDING;
278a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
279a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
280a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual void Close(bool not_reusable) OVERRIDE {}
281a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
282a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual bool IsResponseBodyComplete() const OVERRIDE { return false; }
283a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
284a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual bool CanFindEndOfResponse() const OVERRIDE { return false; }
285a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
286a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual bool IsConnectionReused() const OVERRIDE { return false; }
287a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual void SetConnectionReused() OVERRIDE {}
288a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
289a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual bool IsConnectionReusable() const OVERRIDE { return false; }
290a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual int64 GetTotalReceivedBytes() const OVERRIDE { return 0; }
2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
293a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const
294a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      OVERRIDE {
295a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return false;
296a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
297a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
298a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual void GetSSLInfo(SSLInfo* ssl_info) OVERRIDE {}
299a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
300a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info)
301a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      OVERRIDE {}
302a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
303a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual bool IsSpdyHttpStream() const OVERRIDE { return false; }
304a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
305a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual void Drain(HttpNetworkSession* session) OVERRIDE {}
306a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
307a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual void SetPriority(RequestPriority priority) OVERRIDE {}
308a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
309a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Fake implementation of WebSocketHandshakeStreamBase method(s)
310a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual scoped_ptr<WebSocketStream> Upgrade() OVERRIDE {
311a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return scoped_ptr<WebSocketStream>();
312a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
313a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
314a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) private:
315a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  bool initialize_stream_was_called_;
316a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)};
317a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
318a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(URLRequestHttpJobWebSocketTest, RejectedWithoutCreateHelper) {
3191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_refptr<TestURLRequestHttpJob> job(
3201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new TestURLRequestHttpJob(req_.get()));
321a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  job->Start();
322a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
3231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(URLRequestStatus::FAILED, req_->status().status());
3241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(ERR_DISALLOWED_URL_SCHEME, req_->status().error());
325a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
326a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
327a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(URLRequestHttpJobWebSocketTest, CreateHelperPassedThrough) {
3281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_refptr<TestURLRequestHttpJob> job(
3291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new TestURLRequestHttpJob(req_.get()));
330a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<MockCreateHelper> create_helper(
331a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      new ::testing::StrictMock<MockCreateHelper>());
332a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  FakeWebSocketHandshakeStream* fake_handshake_stream(
333a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      new FakeWebSocketHandshakeStream);
334a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Ownership of fake_handshake_stream is transferred when CreateBasicStream()
335a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // is called.
336a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_CALL(*create_helper, CreateBasicStreamMock())
337a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      .WillOnce(Return(fake_handshake_stream));
3381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  req_->SetUserData(WebSocketHandshakeStreamBase::CreateHelper::DataKey(),
3391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    create_helper.release());
3401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  req_->SetLoadFlags(LOAD_DISABLE_CACHE);
341a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  job->Start();
342a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
3431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(URLRequestStatus::IO_PENDING, req_->status().status());
344a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_TRUE(fake_handshake_stream->initialize_stream_was_called());
345a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
346a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace net
350