15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "net/test/url_request/url_request_mock_http_job.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
89ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/task_runner_util.h"
123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/threading/sequenced_worker_pool.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread_restrictions.h"
14c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "net/base/filename_util.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_response_headers.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_filter.h"
1746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "net/url_request/url_request_interceptor.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kMockHostname[] = "mock.http";
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const base::FilePath::CharType kMockHeaderFileSuffix[] =
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FILE_PATH_LITERAL(".mock-http-headers");
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace net {
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)class MockJobInterceptor : public net::URLRequestInterceptor {
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // When |map_all_requests_to_base_path| is true, all request should return the
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // contents of the file at |base_path|. When |map_all_requests_to_base_path|
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // is false, |base_path| is the file path leading to the root of the directory
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // to use as the root of the HTTP server.
331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  MockJobInterceptor(
341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      const base::FilePath& base_path,
351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      bool map_all_requests_to_base_path,
361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      const scoped_refptr<base::SequencedWorkerPool>& worker_pool)
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : base_path_(base_path),
381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        map_all_requests_to_base_path_(map_all_requests_to_base_path),
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        worker_pool_(worker_pool) {}
4046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  virtual ~MockJobInterceptor() {}
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // net::URLRequestJobFactory::ProtocolHandler implementation
4346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  virtual net::URLRequestJob* MaybeInterceptRequest(
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      net::URLRequest* request,
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      net::NetworkDelegate* network_delegate) const OVERRIDE {
461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return new URLRequestMockHTTPJob(
471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        request,
481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        network_delegate,
491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        map_all_requests_to_base_path_ ? base_path_ : GetOnDiskPath(request),
501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        worker_pool_->GetTaskRunnerWithShutdownBehavior(
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            base::SequencedWorkerPool::SKIP_ON_SHUTDOWN));
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath GetOnDiskPath(net::URLRequest* request) const {
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Conceptually we just want to "return base_path_ + request->url().path()".
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // But path in the request URL is in URL space (i.e. %-encoded spaces).
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // So first we convert base FilePath to a URL, then append the URL
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // path to that, and convert the final URL back to a FilePath.
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GURL file_url(net::FilePathToFileURL(base_path_));
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string url = file_url.spec() + request->url().path();
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath file_path;
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    net::FileURLToFilePath(GURL(url), &file_path);
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return file_path;
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::FilePath base_path_;
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const bool map_all_requests_to_base_path_;
691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const scoped_refptr<base::SequencedWorkerPool> worker_pool_;
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(MockJobInterceptor);
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistd::string DoFileIO(const base::FilePath& file_path) {
751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::FilePath header_file =
761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::FilePath(file_path.value() + kMockHeaderFileSuffix);
771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!base::PathExists(header_file)) {
791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // If there is no mock-http-headers file, fake a 200 OK.
801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return "HTTP/1.0 200 OK\n";
811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::string raw_headers;
841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::ReadFileToString(header_file, &raw_headers);
851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return raw_headers;
861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid URLRequestMockHTTPJob::AddUrlHandler(
921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const base::FilePath& base_path,
931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const scoped_refptr<base::SequencedWorkerPool>& worker_pool) {
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Add kMockHostname to net::URLRequestFilter.
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::URLRequestFilter* filter = net::URLRequestFilter::GetInstance();
9646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  filter->AddHostnameInterceptor(
971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      "http", kMockHostname, CreateInterceptor(base_path, worker_pool));
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void URLRequestMockHTTPJob::AddHostnameToFileHandler(
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& hostname,
1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const base::FilePath& file,
1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const scoped_refptr<base::SequencedWorkerPool>& worker_pool) {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::URLRequestFilter* filter = net::URLRequestFilter::GetInstance();
10646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  filter->AddHostnameInterceptor(
1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      "http", hostname, CreateInterceptorForSingleFile(file, worker_pool));
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)GURL URLRequestMockHTTPJob::GetMockUrl(const base::FilePath& path) {
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url = "http://";
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  url.append(kMockHostname);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  url.append("/");
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string path_str = path.MaybeAsASCII();
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!path_str.empty());  // We only expect ASCII paths in tests.
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  url.append(path_str);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GURL(url);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciscoped_ptr<net::URLRequestInterceptor> URLRequestMockHTTPJob::CreateInterceptor(
1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const base::FilePath& base_path,
1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const scoped_refptr<base::SequencedWorkerPool>& worker_pool) {
12546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return scoped_ptr<net::URLRequestInterceptor>(
1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new MockJobInterceptor(base_path, false, worker_pool));
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// static
13046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)scoped_ptr<net::URLRequestInterceptor>
13146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)URLRequestMockHTTPJob::CreateInterceptorForSingleFile(
1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const base::FilePath& file,
1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const scoped_refptr<base::SequencedWorkerPool>& worker_pool) {
13446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return scoped_ptr<net::URLRequestInterceptor>(
1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new MockJobInterceptor(file, true, worker_pool));
1364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)URLRequestMockHTTPJob::URLRequestMockHTTPJob(
1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    net::URLRequest* request,
1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    net::NetworkDelegate* network_delegate,
1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const base::FilePath& file_path,
1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const scoped_refptr<base::TaskRunner>& task_runner)
1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    : net::URLRequestFileJob(request, network_delegate, file_path, task_runner),
1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      task_runner_(task_runner),
1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      weak_ptr_factory_(this) {
1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciURLRequestMockHTTPJob::~URLRequestMockHTTPJob() {
1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Public virtual version.
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLRequestMockHTTPJob::GetResponseInfo(net::HttpResponseInfo* info) {
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Forward to private const version.
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetResponseInfoConst(info);
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool URLRequestMockHTTPJob::IsRedirectResponse(GURL* location,
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               int* http_status_code) {
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Override the net::URLRequestFileJob implementation to invoke the default
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // one based on HttpResponseInfo.
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return net::URLRequestJob::IsRedirectResponse(location, http_status_code);
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Public virtual version.
1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid URLRequestMockHTTPJob::Start() {
1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::PostTaskAndReplyWithResult(
1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      task_runner_.get(),
1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      FROM_HERE,
1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::Bind(&DoFileIO, file_path_),
1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::Bind(&URLRequestMockHTTPJob::GetRawHeaders,
1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 weak_ptr_factory_.GetWeakPtr()));
1721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid URLRequestMockHTTPJob::GetRawHeaders(std::string raw_headers) {
1754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Handle CRLF line-endings.
1764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ReplaceSubstringsAfterOffset(&raw_headers, 0, "\r\n", "\n");
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ParseRawHeaders expects \0 to end each header line.
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReplaceSubstringsAfterOffset(&raw_headers, 0, "\n", std::string("\0", 1));
1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  raw_headers_ = raw_headers;
1801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  URLRequestFileJob::Start();
1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Private const version.
1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid URLRequestMockHTTPJob::GetResponseInfoConst(
1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    net::HttpResponseInfo* info) const {
1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  info->headers = new net::HttpResponseHeaders(raw_headers_);
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool URLRequestMockHTTPJob::GetMimeType(std::string* mime_type) const {
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::HttpResponseInfo info;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetResponseInfoConst(&info);
192868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return info.headers.get() && info.headers->GetMimeType(mime_type);
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int URLRequestMockHTTPJob::GetResponseCode() const {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::HttpResponseInfo info;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetResponseInfoConst(&info);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we have headers, get the response code from them.
199868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (info.headers.get())
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return info.headers->response_code();
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return net::URLRequestJob::GetResponseCode();
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool URLRequestMockHTTPJob::GetCharset(std::string* charset) {
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::HttpResponseInfo info;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetResponseInfo(&info);
207868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return info.headers.get() && info.headers->GetCharset(charset);
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}  // namespace net
211