1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/test/url_request/url_request_failed_job.h"
6
7#include "base/bind.h"
8#include "base/logging.h"
9#include "base/message_loop/message_loop.h"
10#include "base/strings/string_number_conversions.h"
11#include "net/base/net_errors.h"
12#include "net/url_request/url_request.h"
13#include "net/url_request/url_request_filter.h"
14
15namespace net {
16namespace {
17
18const char kMockHostname[] = "mock.failed.request";
19
20// Gets the numeric net error code from URL of the form:
21// scheme://kMockHostname/error_code.  The error code must be a valid
22// net error code, and not net::OK or net::ERR_IO_PENDING.
23int GetErrorCode(net::URLRequest* request) {
24  int net_error;
25  std::string path = request->url().path();
26  if (path[0] == '/' && base::StringToInt(path.c_str() + 1, &net_error)) {
27    CHECK_LT(net_error, 0);
28    CHECK_NE(net_error, net::ERR_IO_PENDING);
29    return net_error;
30  }
31  NOTREACHED();
32  return net::ERR_UNEXPECTED;
33}
34
35GURL GetMockUrl(const std::string& scheme,
36                const std::string& hostname,
37                int net_error) {
38  CHECK_LT(net_error, 0);
39  CHECK_NE(net_error, net::ERR_IO_PENDING);
40  return GURL(scheme + "://" + hostname + "/" + base::IntToString(net_error));
41}
42
43}  // namespace
44
45URLRequestFailedJob::URLRequestFailedJob(net::URLRequest* request,
46                                         net::NetworkDelegate* network_delegate,
47                                         int net_error)
48    : net::URLRequestJob(request, network_delegate),
49      net_error_(net_error),
50      weak_factory_(this) {}
51
52void URLRequestFailedJob::Start() {
53  base::MessageLoop::current()->PostTask(
54      FROM_HERE,
55      base::Bind(&URLRequestFailedJob::StartAsync, weak_factory_.GetWeakPtr()));
56}
57
58// static
59void URLRequestFailedJob::AddUrlHandler() {
60  return AddUrlHandlerForHostname(kMockHostname);
61}
62
63// static
64void URLRequestFailedJob::AddUrlHandlerForHostname(
65    const std::string& hostname) {
66  // Add |hostname| to net::URLRequestFilter for HTTP and HTTPS.
67  net::URLRequestFilter* filter = net::URLRequestFilter::GetInstance();
68  filter->AddHostnameHandler("http", hostname, URLRequestFailedJob::Factory);
69  filter->AddHostnameHandler("https", hostname, URLRequestFailedJob::Factory);
70}
71
72// static
73GURL URLRequestFailedJob::GetMockHttpUrl(int net_error) {
74  return GetMockHttpUrlForHostname(net_error, kMockHostname);
75}
76
77// static
78GURL URLRequestFailedJob::GetMockHttpsUrl(int net_error) {
79  return GetMockHttpsUrlForHostname(net_error, kMockHostname);
80}
81
82// static
83GURL URLRequestFailedJob::GetMockHttpUrlForHostname(
84    int net_error, const std::string& hostname) {
85  return GetMockUrl("http", hostname, net_error);
86}
87
88// static
89GURL URLRequestFailedJob::GetMockHttpsUrlForHostname(
90    int net_error, const std::string& hostname) {
91  return GetMockUrl("https", hostname, net_error);
92}
93
94URLRequestFailedJob::~URLRequestFailedJob() {}
95
96// static
97net::URLRequestJob* URLRequestFailedJob::Factory(
98    net::URLRequest* request,
99    net::NetworkDelegate* network_delegate,
100    const std::string& scheme) {
101  return new URLRequestFailedJob(
102      request, network_delegate, GetErrorCode(request));
103}
104
105void URLRequestFailedJob::StartAsync() {
106  NotifyStartError(net::URLRequestStatus(net::URLRequestStatus::FAILED,
107                                         net_error_));
108}
109
110}  // namespace net
111