1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124

content / test / fake_network.cc [blame]

// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/test/fake_network.h"

#include "base/containers/span.h"
#include "base/feature_list.h"
#include "base/no_destructor.h"
#include "base/strings/string_util.h"
#include "net/http/http_util.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/parsed_headers.h"
#include "services/network/public/mojom/url_loader.mojom.h"
#include "services/network/public/mojom/url_response_head.mojom.h"

namespace content {

namespace {

const char kDefaultHttpHeader[] = "HTTP/1.1 200 OK\n\n";
const char kDefaultHttpBody[] = "this body came from the network";
const char kDefaultHttpHeaderForJS[] =
    "HTTP/1.1 200 OK\n"
    "Content-Type: application/javascript\n\n";
const char kDefaultHttpBodyForJS[] = "/*this body came from the network*/";

}  // namespace

struct FakeNetwork::ResponseInfo {
  ResponseInfo() = default;
  ResponseInfo(const std::string& headers,
               const std::string& body,
               bool network_accessed,
               net::Error error_code)
      : headers(headers),
        body(body),
        network_accessed(network_accessed),
        error_code(error_code) {}
  ~ResponseInfo() = default;

  ResponseInfo(ResponseInfo&& info) = default;
  ResponseInfo& operator=(ResponseInfo&& info) = default;

  GURL url;
  std::string headers;
  std::string body;
  bool network_accessed = true;
  net::Error error_code = net::OK;
};

FakeNetwork::FakeNetwork() = default;

FakeNetwork::~FakeNetwork() = default;

const FakeNetwork::ResponseInfo& FakeNetwork::FindResponseInfo(
    const GURL& url) const {
  auto it = response_info_map_.find(url);
  if (it != response_info_map_.end())
    return it->second;

  if (user_defined_default_response_info_)
    return *user_defined_default_response_info_;

  static const base::NoDestructor<ResponseInfo> kDefaultResponseInfo(
      kDefaultHttpHeader, kDefaultHttpBody, /*network_accessed=*/true, net::OK);
  static const base::NoDestructor<ResponseInfo> kDefaultJsResponseInfo(
      kDefaultHttpHeaderForJS, kDefaultHttpBodyForJS, /*network_accessed=*/true,
      net::OK);
  bool is_js =
      base::EndsWith(url.path(), ".js", base::CompareCase::INSENSITIVE_ASCII);

  return is_js ? *kDefaultJsResponseInfo : *kDefaultResponseInfo;
}

void FakeNetwork::SetDefaultResponse(const std::string& headers,
                                     const std::string& body,
                                     bool network_accessed,
                                     net::Error error_code) {
  user_defined_default_response_info_ =
      std::make_unique<FakeNetwork::ResponseInfo>(headers, body,
                                                  network_accessed, error_code);
}

void FakeNetwork::SetResponse(const GURL& url,
                              const std::string& headers,
                              const std::string& body,
                              bool network_accessed,
                              net::Error error_code) {
  response_info_map_[url] =
      ResponseInfo(headers, body, network_accessed, error_code);
}

bool FakeNetwork::HandleRequest(URLLoaderInterceptor::RequestParams* params) {
  const network::ResourceRequest& url_request = params->url_request;
  const ResponseInfo& response_info = FindResponseInfo(url_request.url);

  net::HttpResponseInfo info;
  info.headers = base::MakeRefCounted<net::HttpResponseHeaders>(
      net::HttpUtil::AssembleRawHeaders(response_info.headers));
  auto response = network::mojom::URLResponseHead::New();
  response->headers = info.headers;
  response->headers->GetMimeType(&response->mime_type);
  response->network_accessed = response_info.network_accessed;
  response->parsed_headers =
      network::PopulateParsedHeaders(info.headers.get(), url_request.url);
  mojo::Remote<network::mojom::URLLoaderClient>& client = params->client;

  mojo::ScopedDataPipeProducerHandle producer_handle;
  mojo::ScopedDataPipeConsumerHandle consumer_handle;
  CHECK_EQ(MOJO_RESULT_OK,
           mojo::CreateDataPipe(nullptr, producer_handle, consumer_handle));
  producer_handle->WriteAllData(base::as_byte_span(response_info.body));
  client->OnReceiveResponse(std::move(response), std::move(consumer_handle),
                            std::nullopt);

  network::URLLoaderCompletionStatus status;
  status.error_code = response_info.error_code;
  status.decoded_body_length = response_info.body.size();
  client->OnComplete(status);
  return true;
}

}  // namespace content