summaryrefslogtreecommitdiff
path: root/chromium/services/network/public/cpp/network_mojom_traits_unittest.cc
blob: 1aee1d9fc560d3bfe781009786ecc3592e30aa34 (plain)
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
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/strings/string_util.h"
#include "base/test/task_environment.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/network/public/cpp/http_request_headers_mojom_traits.h"
#include "services/network/public/cpp/network_traits_test_service.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace network {

namespace {

class NetworkStructTraitsTest : public testing::Test,
                                public mojom::TraitsTestService {
 protected:
  NetworkStructTraitsTest() = default;

  mojo::PendingRemote<mojom::TraitsTestService> GetTraitsTestRemote() {
    mojo::PendingRemote<mojom::TraitsTestService> remote;
    traits_test_receivers_.Add(this, remote.InitWithNewPipeAndPassReceiver());
    return remote;
  }

 private:
  // TraitsTestService:
  void EchoHttpRequestHeaders(
      const net::HttpRequestHeaders& header,
      EchoHttpRequestHeadersCallback callback) override {
    std::move(callback).Run(header);
  }

  base::test::SingleThreadTaskEnvironment task_environment_;
  mojo::ReceiverSet<TraitsTestService> traits_test_receivers_;
  DISALLOW_COPY_AND_ASSIGN(NetworkStructTraitsTest);
};

}  // namespace

TEST_F(NetworkStructTraitsTest, HttpRequestHeaders_Basic) {
  net::HttpRequestHeaders headers;
  net::HttpRequestHeaders output;
  headers.SetHeader("Foo", "bar");
  mojo::Remote<mojom::TraitsTestService> remote(GetTraitsTestRemote());
  remote->EchoHttpRequestHeaders(headers, &output);
  std::string value;
  EXPECT_TRUE(output.GetHeader("Foo", &value));
  EXPECT_EQ("bar", value);
  EXPECT_FALSE(output.HasHeader("Fo"));
}

TEST_F(NetworkStructTraitsTest, HttpRequestHeaders_InvalidHeaderName) {
  // Check that non-token chars are disallowed.
  const unsigned char invalid_name_chars[] = {
      0x80, 0x19, '(', ')', '<', '>', '@', ',', ';', ':',
      '\\', '"',  '/', '[', ']', '?', '=', '{', '}'};
  for (char c : invalid_name_chars) {
    std::string invalid_name("foo");
    invalid_name.push_back(c);
    net::HttpRequestHeaders header;
    net::HttpRequestHeaders output;
    header.SetHeaderWithoutCheckForTesting(invalid_name, "foo");
    mojo::Remote<mojom::TraitsTestService> remote(GetTraitsTestRemote());
    remote->EchoHttpRequestHeaders(header, &output);
    std::string value;
    EXPECT_TRUE(output.IsEmpty());
  }
}

// Test cases are copied from HttpUtilTest.IsValidHeaderValue.
TEST_F(NetworkStructTraitsTest, HttpRequestHeaders_InvalidHeaderValue) {
  const char* const invalid_values[] = {
      "X-Requested-With: chrome${NUL}Sec-Unsafe: injected",
      "X-Requested-With: chrome\r\nSec-Unsafe: injected",
      "X-Requested-With: chrome\nSec-Unsafe: injected",
      "X-Requested-With: chrome\rSec-Unsafe: injected",
  };

  for (const std::string& value : invalid_values) {
    std::string replaced = value;
    base::ReplaceSubstringsAfterOffset(&replaced, 0, "${NUL}",
                                       std::string(1, '\0'));
    net::HttpRequestHeaders header;
    net::HttpRequestHeaders output;
    header.SetHeaderWithoutCheckForTesting("Foo", replaced);
    mojo::Remote<mojom::TraitsTestService> remote(GetTraitsTestRemote());
    remote->EchoHttpRequestHeaders(header, &output);
    EXPECT_FALSE(output.HasHeader("Foo"));
  }

  // Check that all characters permitted by RFC7230 3.2.6 are allowed.
  std::string allowed = "\t";
  for (char c = '\x20'; c < '\x7F'; ++c) {
    allowed.append(1, c);
  }
  for (int c = 0x80; c <= 0xFF; ++c) {
    allowed.append(1, static_cast<char>(c));
  }

  net::HttpRequestHeaders header;
  net::HttpRequestHeaders output;
  header.SetHeaderWithoutCheckForTesting("Foo", allowed);
  mojo::Remote<mojom::TraitsTestService> remote(GetTraitsTestRemote());
  remote->EchoHttpRequestHeaders(header, &output);
  EXPECT_TRUE(output.HasHeader("Foo"));
}

}  // namespace network