1 // Copyright 2019 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 "extensions/browser/api/declarative_net_request/filter_list_converter/converter.h"
6
7 #include "base/check_op.h"
8 #include "base/files/file_path.h"
9 #include "base/files/file_util.h"
10 #include "base/files/scoped_temp_dir.h"
11 #include "base/json/json_file_value_serializer.h"
12 #include "base/json/json_reader.h"
13 #include "base/optional.h"
14 #include "base/strings/string_util.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16
17 namespace extensions {
18 namespace declarative_net_request {
19 namespace filter_list_converter {
20 namespace {
21
TestConversion(std::vector<std::string> filter_list_rules,std::string json_result,WriteType write_type)22 void TestConversion(std::vector<std::string> filter_list_rules,
23 std::string json_result,
24 WriteType write_type) {
25 base::ScopedTempDir temp_dir;
26 CHECK(temp_dir.CreateUniqueTempDir());
27
28 base::FilePath input_path = temp_dir.GetPath().AppendASCII("filterlist.txt");
29 std::string filterlist = base::JoinString(filter_list_rules, "\n");
30 CHECK_EQ(filterlist.size(),
31 static_cast<size_t>(base::WriteFile(input_path, filterlist.c_str(),
32 filterlist.size())));
33
34 base::Optional<base::Value> expected_json =
35 base::JSONReader::Read(json_result);
36 CHECK(expected_json.has_value());
37
38 base::FilePath output_path = temp_dir.GetPath();
39 if (write_type == WriteType::kJSONRuleset)
40 output_path = output_path.AppendASCII("rules.json");
41
42 ConvertRuleset({input_path}, output_path, write_type, true /* noisy */);
43
44 base::FilePath output_json_path =
45 temp_dir.GetPath().AppendASCII("rules.json");
46 JSONFileValueDeserializer deserializer(output_json_path);
47 std::unique_ptr<base::Value> actual_json = deserializer.Deserialize(
48 nullptr /* error_code */, nullptr /* error_message */);
49 ASSERT_TRUE(actual_json.get());
50
51 EXPECT_EQ(*expected_json, *actual_json);
52
53 if (write_type == WriteType::kExtension) {
54 EXPECT_TRUE(
55 base::PathExists(temp_dir.GetPath().AppendASCII("manifest.json")));
56 }
57 }
58
59 class FilterListConverterTest : public ::testing::TestWithParam<WriteType> {};
60
TEST_P(FilterListConverterTest,Convert)61 TEST_P(FilterListConverterTest, Convert) {
62 std::vector<std::string> filter_list_rules = {
63 "||example.com^|$script,image,font",
64 "@@allowed.com$domain=example.com|~sub.example.com",
65 "|https://*.abc.com|$match-case,~image,third-party",
66 "abc.com$~third-party",
67 "@@||yahoo.com^$document,subdocument",
68 "@@||yahoo.com^$document",
69
70 // This rule is invalid and should be ignored.
71 "@@||yahoo.com^$document,script",
72
73 "@@||yahoo.com^$subdocument",
74 };
75
76 std::string expected_result = R"(
77 [ {
78 "action": {
79 "type": "block"
80 },
81 "condition": {
82 "isUrlFilterCaseSensitive": false,
83 "resourceTypes": [ "script", "image", "font" ],
84 "urlFilter": "||example.com^|"
85 },
86 "id": 1,
87 "priority": 1
88 }, {
89 "action": {
90 "type": "allow"
91 },
92 "condition": {
93 "domains": [ "example.com" ],
94 "excludedDomains": [ "sub.example.com" ],
95 "isUrlFilterCaseSensitive": false,
96 "urlFilter": "allowed.com"
97 },
98 "id": 2,
99 "priority": 1
100 }, {
101 "action": {
102 "type": "block"
103 },
104 "condition": {
105 "resourceTypes": [ "other", "script", "stylesheet", "object",
106 "xmlhttprequest", "sub_frame", "ping", "media", "font",
107 "websocket" ],
108 "urlFilter": "|https://*.abc.com|",
109 "domainType": "thirdParty"
110 },
111 "id": 3,
112 "priority": 1
113 }, {
114 "action": {
115 "type": "block"
116 },
117 "condition": {
118 "isUrlFilterCaseSensitive": false,
119 "urlFilter": "abc.com",
120 "domainType": "firstParty"
121 },
122 "id": 4,
123 "priority": 1
124 }, {
125 "action": {
126 "type": "allowAllRequests"
127 },
128 "condition": {
129 "isUrlFilterCaseSensitive": false,
130 "resourceTypes": [ "sub_frame", "main_frame" ],
131 "urlFilter": "||yahoo.com^"
132 },
133 "id": 5,
134 "priority": 1
135 }, {
136 "action": {
137 "type": "allowAllRequests"
138 },
139 "condition": {
140 "isUrlFilterCaseSensitive": false,
141 "resourceTypes": [ "main_frame" ],
142 "urlFilter": "||yahoo.com^"
143 },
144 "id": 6,
145 "priority": 1
146 }, {
147 "action": {
148 "type": "allow"
149 },
150 "condition": {
151 "isUrlFilterCaseSensitive": false,
152 "resourceTypes": [ "sub_frame" ],
153 "urlFilter": "||yahoo.com^"
154 },
155 "id": 7,
156 "priority": 1
157 } ]
158
159 )";
160
161 TestConversion(filter_list_rules, expected_result, GetParam());
162 }
163
164 INSTANTIATE_TEST_SUITE_P(All,
165 FilterListConverterTest,
166 ::testing::Values(WriteType::kExtension,
167 WriteType::kJSONRuleset));
168
169 } // namespace
170 } // namespace filter_list_converter
171 } // namespace declarative_net_request
172 } // namespace extensions
173