OLD | NEW |
1 /* | 1 /* |
2 * This file is part of Adblock Plus <https://adblockplus.org/>, | 2 * This file is part of Adblock Plus <https://adblockplus.org/>, |
3 * Copyright (C) 2006-2016 Eyeo GmbH | 3 * Copyright (C) 2006-2016 Eyeo GmbH |
4 * | 4 * |
5 * Adblock Plus is free software: you can redistribute it and/or modify | 5 * Adblock Plus is free software: you can redistribute it and/or modify |
6 * it under the terms of the GNU General Public License version 3 as | 6 * it under the terms of the GNU General Public License version 3 as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
8 * | 8 * |
9 * Adblock Plus is distributed in the hope that it will be useful, | 9 * Adblock Plus is distributed in the hope that it will be useful, |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 * GNU General Public License for more details. | 12 * GNU General Public License for more details. |
13 * | 13 * |
14 * You should have received a copy of the GNU General Public License | 14 * You should have received a copy of the GNU General Public License |
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. | 15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. |
16 */ | 16 */ |
17 | 17 |
18 #include <sstream> | 18 #include <sstream> |
19 #include "BaseJsTest.h" | 19 #include "BaseJsTest.h" |
20 #include "../src/Thread.h" | 20 #include "../src/Thread.h" |
| 21 #include <atomic> |
| 22 #include <mutex> |
| 23 |
| 24 using namespace AdblockPlus; |
21 | 25 |
22 namespace | 26 namespace |
23 { | 27 { |
24 class MockWebRequest : public AdblockPlus::WebRequest | 28 class MockWebRequest : public AdblockPlus::WebRequest |
25 { | 29 { |
26 public: | 30 public: |
27 AdblockPlus::ServerResponse GET(const std::string& url, const AdblockPlus::H
eaderList& requestHeaders) const | 31 AdblockPlus::ServerResponse GET(const std::string& url, const AdblockPlus::H
eaderList& requestHeaders) const |
28 { | 32 { |
29 AdblockPlus::Sleep(50); | 33 AdblockPlus::Sleep(50); |
30 | 34 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
67 { | 71 { |
68 jsEngine->Evaluate("_webRequest.GET('http://example.com/', {X: 'Y'}, function(
result) {foo = result;} )"); | 72 jsEngine->Evaluate("_webRequest.GET('http://example.com/', {X: 'Y'}, function(
result) {foo = result;} )"); |
69 ASSERT_TRUE(jsEngine->Evaluate("this.foo")->IsUndefined()); | 73 ASSERT_TRUE(jsEngine->Evaluate("this.foo")->IsUndefined()); |
70 AdblockPlus::Sleep(200); | 74 AdblockPlus::Sleep(200); |
71 ASSERT_EQ(AdblockPlus::WebRequest::NS_OK, jsEngine->Evaluate("foo.status")->As
Int()); | 75 ASSERT_EQ(AdblockPlus::WebRequest::NS_OK, jsEngine->Evaluate("foo.status")->As
Int()); |
72 ASSERT_EQ(123, jsEngine->Evaluate("foo.responseStatus")->AsInt()); | 76 ASSERT_EQ(123, jsEngine->Evaluate("foo.responseStatus")->AsInt()); |
73 ASSERT_EQ("http://example.com/\nX\nY", jsEngine->Evaluate("foo.responseText")-
>AsString()); | 77 ASSERT_EQ("http://example.com/\nX\nY", jsEngine->Evaluate("foo.responseText")-
>AsString()); |
74 ASSERT_EQ("{\"Foo\":\"Bar\"}", jsEngine->Evaluate("JSON.stringify(foo.response
Headers)")->AsString()); | 78 ASSERT_EQ("{\"Foo\":\"Bar\"}", jsEngine->Evaluate("JSON.stringify(foo.response
Headers)")->AsString()); |
75 } | 79 } |
76 | 80 |
| 81 TEST_F(MockWebRequestTest, ConnectionIsAllowedOnJsEngine) |
| 82 { |
| 83 std::atomic<int> isConnectionAllowedCalledTimes(0); |
| 84 jsEngine->SetIsConnectionAllowedCallback([&isConnectionAllowedCalledTimes]()->
bool |
| 85 { |
| 86 ++isConnectionAllowedCalledTimes; |
| 87 return true; |
| 88 }); |
| 89 jsEngine->Evaluate("_webRequest.GET('http://example.com/', {X: 'Y'}, function(
result) {foo = result;} )"); |
| 90 ASSERT_TRUE(jsEngine->Evaluate("this.foo")->IsUndefined()); |
| 91 AdblockPlus::Sleep(200); |
| 92 EXPECT_EQ(1u, isConnectionAllowedCalledTimes); |
| 93 EXPECT_EQ(AdblockPlus::WebRequest::NS_OK, jsEngine->Evaluate("foo.status")->As
Int()); |
| 94 EXPECT_EQ(123, jsEngine->Evaluate("foo.responseStatus")->AsInt()); |
| 95 EXPECT_EQ("http://example.com/\nX\nY", jsEngine->Evaluate("foo.responseText")-
>AsString()); |
| 96 EXPECT_EQ("{\"Foo\":\"Bar\"}", jsEngine->Evaluate("JSON.stringify(foo.response
Headers)")->AsString()); |
| 97 } |
| 98 |
| 99 TEST_F(MockWebRequestTest, ConnectionIsNotAllowedOnJsEngine) |
| 100 { |
| 101 std::atomic<int> isConnectionAllowedCalledTimes(0); |
| 102 jsEngine->SetIsConnectionAllowedCallback([&isConnectionAllowedCalledTimes]()->
bool |
| 103 { |
| 104 ++isConnectionAllowedCalledTimes; |
| 105 return false; |
| 106 }); |
| 107 jsEngine->Evaluate("_webRequest.GET('http://example.com/', {X: 'Y'}, function(
result) {foo = result;} )"); |
| 108 ASSERT_TRUE(jsEngine->Evaluate("this.foo")->IsUndefined()); |
| 109 AdblockPlus::Sleep(200); |
| 110 EXPECT_EQ(1u, isConnectionAllowedCalledTimes); |
| 111 EXPECT_EQ(AdblockPlus::WebRequest::NS_ERROR_CONNECTION_REFUSED, jsEngine->Eval
uate("foo.status")->AsInt()); |
| 112 EXPECT_EQ(0, jsEngine->Evaluate("foo.responseStatus")->AsInt()); |
| 113 EXPECT_EQ("", jsEngine->Evaluate("foo.responseText")->AsString()); |
| 114 EXPECT_EQ("{}", jsEngine->Evaluate("JSON.stringify(foo.responseHeaders)")->AsS
tring()); |
| 115 } |
| 116 |
| 117 namespace |
| 118 { |
| 119 class SyncStrings |
| 120 { |
| 121 public: |
| 122 void Add(const std::string* value) |
| 123 { |
| 124 std::lock_guard<std::mutex> lock(mutex); |
| 125 strings.emplace_back(!!value, value ? *value : ""); |
| 126 } |
| 127 std::vector<std::pair<bool, std::string>> GetStrings() const |
| 128 { |
| 129 std::lock_guard<std::mutex> lock(mutex); |
| 130 return strings; |
| 131 } |
| 132 void Clear() |
| 133 { |
| 134 std::lock_guard<std::mutex> lock(mutex); |
| 135 strings.clear(); |
| 136 } |
| 137 private: |
| 138 mutable std::mutex mutex; |
| 139 std::vector<std::pair<bool, std::string>> strings; |
| 140 }; |
| 141 } |
| 142 |
| 143 TEST_F(MockWebRequestTest, ConnectionIsAllowedOnFilterEngine1) |
| 144 { |
| 145 FilterEngine::CreateParameters createParams; |
| 146 std::string predefinedAllowedConnectionType = "non-metered"; |
| 147 createParams.preconfiguredPrefs.emplace("allowed_connection_type", jsEngine->N
ewValue(predefinedAllowedConnectionType)); |
| 148 auto receivedConnectionTypes = std::make_shared<SyncStrings>(); |
| 149 createParams.isConnectionAllowed = [receivedConnectionTypes](const std::string
* allowedConnectionType)->bool { |
| 150 receivedConnectionTypes->Add(allowedConnectionType); |
| 151 return true; |
| 152 }; |
| 153 auto filterEngine = FilterEngine::Create(jsEngine, createParams); |
| 154 jsEngine->Evaluate("_webRequest.GET('http://example.com/', {X: 'Y'}, function(
result) {foo = result;} )"); |
| 155 ASSERT_TRUE(jsEngine->Evaluate("this.foo")->IsUndefined()); |
| 156 AdblockPlus::Sleep(200); |
| 157 auto receivedConnectionTypesStrings = receivedConnectionTypes->GetStrings(); |
| 158 EXPECT_FALSE(receivedConnectionTypesStrings.empty()); |
| 159 for (const auto& connectionType : receivedConnectionTypesStrings) |
| 160 { |
| 161 EXPECT_TRUE(connectionType.first); |
| 162 EXPECT_EQ(predefinedAllowedConnectionType, connectionType.second); |
| 163 } |
| 164 EXPECT_EQ(AdblockPlus::WebRequest::NS_OK, jsEngine->Evaluate("foo.status")->As
Int()); |
| 165 EXPECT_EQ(123, jsEngine->Evaluate("foo.responseStatus")->AsInt()); |
| 166 EXPECT_EQ("http://example.com/\nX\nY", jsEngine->Evaluate("foo.responseText")-
>AsString()); |
| 167 EXPECT_EQ("{\"Foo\":\"Bar\"}", jsEngine->Evaluate("JSON.stringify(foo.response
Headers)")->AsString()); |
| 168 } |
| 169 |
| 170 TEST_F(MockWebRequestTest, ConnectionIsAllowedOnFilterEngine2) |
| 171 { |
| 172 FilterEngine::CreateParameters createParams; |
| 173 auto receivedConnectionTypes = std::make_shared<SyncStrings>(); |
| 174 createParams.isConnectionAllowed = [receivedConnectionTypes](const std::string
* allowedConnectionType)->bool { |
| 175 receivedConnectionTypes->Add(allowedConnectionType); |
| 176 return true; |
| 177 }; |
| 178 auto filterEngine = FilterEngine::Create(jsEngine, createParams); |
| 179 jsEngine->Evaluate("_webRequest.GET('http://example.com/', {X: 'Y'}, function(
result) {foo = result;} )"); |
| 180 ASSERT_TRUE(jsEngine->Evaluate("this.foo")->IsUndefined()); |
| 181 AdblockPlus::Sleep(200); |
| 182 auto receivedConnectionTypesStrings = receivedConnectionTypes->GetStrings(); |
| 183 EXPECT_FALSE(receivedConnectionTypesStrings.empty()); |
| 184 for (const auto& connectionType : receivedConnectionTypesStrings) |
| 185 { |
| 186 EXPECT_FALSE(connectionType.first); |
| 187 } |
| 188 EXPECT_EQ(AdblockPlus::WebRequest::NS_OK, jsEngine->Evaluate("foo.status")->As
Int()); |
| 189 EXPECT_EQ(123, jsEngine->Evaluate("foo.responseStatus")->AsInt()); |
| 190 EXPECT_EQ("http://example.com/\nX\nY", jsEngine->Evaluate("foo.responseText")-
>AsString()); |
| 191 EXPECT_EQ("{\"Foo\":\"Bar\"}", jsEngine->Evaluate("JSON.stringify(foo.response
Headers)")->AsString()); |
| 192 } |
| 193 |
| 194 TEST_F(MockWebRequestTest, ConnectionIsAllowedOnFilterEngine3) |
| 195 { |
| 196 // initially allowed connection type is not defined |
| 197 FilterEngine::CreateParameters createParams; |
| 198 auto receivedConnectionTypes = std::make_shared<SyncStrings>(); |
| 199 createParams.isConnectionAllowed = [receivedConnectionTypes](const std::string
* allowedConnectionType)->bool { |
| 200 receivedConnectionTypes->Add(allowedConnectionType); |
| 201 return true; |
| 202 }; |
| 203 auto filterEngine = FilterEngine::Create(jsEngine, createParams); |
| 204 |
| 205 jsEngine->Evaluate("_webRequest.GET('http://example.com/', {X: 'Y'}, function(
result) {foo = result;} )"); |
| 206 ASSERT_TRUE(jsEngine->Evaluate("this.foo")->IsUndefined()); |
| 207 AdblockPlus::Sleep(200); |
| 208 auto receivedConnectionTypesStrings = receivedConnectionTypes->GetStrings(); |
| 209 EXPECT_FALSE(receivedConnectionTypesStrings.empty()); |
| 210 for (const auto& connectionType : receivedConnectionTypesStrings) |
| 211 { |
| 212 EXPECT_FALSE(connectionType.first); |
| 213 } |
| 214 EXPECT_EQ(AdblockPlus::WebRequest::NS_OK, jsEngine->Evaluate("foo.status")->As
Int()); |
| 215 EXPECT_EQ(123, jsEngine->Evaluate("foo.responseStatus")->AsInt()); |
| 216 EXPECT_EQ("http://example.com/\nX\nY", jsEngine->Evaluate("foo.responseText")-
>AsString()); |
| 217 EXPECT_EQ("{\"Foo\":\"Bar\"}", jsEngine->Evaluate("JSON.stringify(foo.response
Headers)")->AsString()); |
| 218 |
| 219 // set allowed connection type |
| 220 std::string allowedConnectionType = "test-connection"; |
| 221 filterEngine->SetAllowedConnectionType(&allowedConnectionType); |
| 222 receivedConnectionTypes->Clear(); |
| 223 jsEngine->Evaluate("_webRequest.GET('http://example.com/', {X: 'Y'}, function(
result) {foo = result;} )"); |
| 224 AdblockPlus::Sleep(200); |
| 225 receivedConnectionTypesStrings = receivedConnectionTypes->GetStrings(); |
| 226 EXPECT_FALSE(receivedConnectionTypesStrings.empty()); |
| 227 for (const auto& connectionType : receivedConnectionTypesStrings) |
| 228 { |
| 229 EXPECT_TRUE(connectionType.first); |
| 230 EXPECT_EQ(allowedConnectionType, connectionType.second); |
| 231 } |
| 232 |
| 233 // remove allowed connection type |
| 234 filterEngine->SetAllowedConnectionType(nullptr); |
| 235 receivedConnectionTypes->Clear(); |
| 236 jsEngine->Evaluate("_webRequest.GET('http://example.com/', {X: 'Y'}, function(
result) {foo = result;} )"); |
| 237 AdblockPlus::Sleep(200); |
| 238 receivedConnectionTypesStrings = receivedConnectionTypes->GetStrings(); |
| 239 EXPECT_FALSE(receivedConnectionTypesStrings.empty()); |
| 240 for (const auto& connectionType : receivedConnectionTypesStrings) |
| 241 { |
| 242 EXPECT_FALSE(connectionType.first); |
| 243 } |
| 244 } |
| 245 |
| 246 TEST_F(MockWebRequestTest, ConnectionIsNotAllowedOnFilterEngine) |
| 247 { |
| 248 FilterEngine::CreateParameters createParams; |
| 249 std::string predefinedAllowedConnectionType = "non-metered"; |
| 250 createParams.preconfiguredPrefs.emplace("allowed_connection_type", jsEngine->N
ewValue(predefinedAllowedConnectionType)); |
| 251 auto receivedConnectionTypes = std::make_shared<SyncStrings>(); |
| 252 createParams.isConnectionAllowed = [receivedConnectionTypes](const std::string
* allowedConnectionType)->bool { |
| 253 receivedConnectionTypes->Add(allowedConnectionType); |
| 254 return false; |
| 255 }; |
| 256 auto filterEngine = FilterEngine::Create(jsEngine, createParams); |
| 257 jsEngine->Evaluate("_webRequest.GET('http://example.com/', {X: 'Y'}, function(
result) {foo = result;} )"); |
| 258 ASSERT_TRUE(jsEngine->Evaluate("this.foo")->IsUndefined()); |
| 259 AdblockPlus::Sleep(200); |
| 260 auto receivedConnectionTypesStrings = receivedConnectionTypes->GetStrings(); |
| 261 EXPECT_FALSE(receivedConnectionTypesStrings.empty()); |
| 262 for (const auto& connectionType : receivedConnectionTypesStrings) |
| 263 { |
| 264 EXPECT_TRUE(connectionType.first); |
| 265 EXPECT_EQ(predefinedAllowedConnectionType, connectionType.second); |
| 266 } |
| 267 EXPECT_EQ(AdblockPlus::WebRequest::NS_ERROR_CONNECTION_REFUSED, jsEngine->Eval
uate("foo.status")->AsInt()); |
| 268 EXPECT_EQ(0, jsEngine->Evaluate("foo.responseStatus")->AsInt()); |
| 269 EXPECT_EQ("", jsEngine->Evaluate("foo.responseText")->AsString()); |
| 270 EXPECT_EQ("{}", jsEngine->Evaluate("JSON.stringify(foo.responseHeaders)")->AsS
tring()); |
| 271 } |
| 272 |
77 #if defined(HAVE_CURL) || defined(_WIN32) | 273 #if defined(HAVE_CURL) || defined(_WIN32) |
78 TEST_F(DefaultWebRequestTest, RealWebRequest) | 274 TEST_F(DefaultWebRequestTest, RealWebRequest) |
79 { | 275 { |
80 // This URL should redirect to easylist-downloads.adblockplus.org and we | 276 // This URL should redirect to easylist-downloads.adblockplus.org and we |
81 // should get the actual filter list back. | 277 // should get the actual filter list back. |
82 jsEngine->Evaluate("_webRequest.GET('https://easylist-downloads.adblockplus.or
g/easylist.txt', {}, function(result) {foo = result;} )"); | 278 jsEngine->Evaluate("_webRequest.GET('https://easylist-downloads.adblockplus.or
g/easylist.txt', {}, function(result) {foo = result;} )"); |
83 do | 279 do |
84 { | 280 { |
85 AdblockPlus::Sleep(200); | 281 AdblockPlus::Sleep(200); |
86 } while (jsEngine->Evaluate("this.foo")->IsUndefined()); | 282 } while (jsEngine->Evaluate("this.foo")->IsUndefined()); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
125 AdblockPlus::Sleep(200); | 321 AdblockPlus::Sleep(200); |
126 } while (jsEngine->Evaluate("this.foo")->IsUndefined()); | 322 } while (jsEngine->Evaluate("this.foo")->IsUndefined()); |
127 ASSERT_EQ(AdblockPlus::WebRequest::NS_ERROR_FAILURE, jsEngine->Evaluate("foo.s
tatus")->AsInt()); | 323 ASSERT_EQ(AdblockPlus::WebRequest::NS_ERROR_FAILURE, jsEngine->Evaluate("foo.s
tatus")->AsInt()); |
128 ASSERT_EQ(0, jsEngine->Evaluate("foo.responseStatus")->AsInt()); | 324 ASSERT_EQ(0, jsEngine->Evaluate("foo.responseStatus")->AsInt()); |
129 ASSERT_EQ("", jsEngine->Evaluate("foo.responseText")->AsString()); | 325 ASSERT_EQ("", jsEngine->Evaluate("foo.responseText")->AsString()); |
130 ASSERT_EQ("{}", jsEngine->Evaluate("JSON.stringify(foo.responseHeaders)")->AsS
tring()); | 326 ASSERT_EQ("{}", jsEngine->Evaluate("JSON.stringify(foo.responseHeaders)")->AsS
tring()); |
131 } | 327 } |
132 | 328 |
133 TEST_F(DefaultWebRequestTest, XMLHttpRequest) | 329 TEST_F(DefaultWebRequestTest, XMLHttpRequest) |
134 { | 330 { |
135 AdblockPlus::FilterEngine filterEngine(jsEngine); | 331 auto filterEngine = AdblockPlus::FilterEngine::Create(jsEngine); |
136 | 332 |
137 jsEngine->Evaluate("\ | 333 jsEngine->Evaluate("\ |
138 var result;\ | 334 var result;\ |
139 var request = new XMLHttpRequest();\ | 335 var request = new XMLHttpRequest();\ |
140 request.open('GET', 'https://easylist-downloads.adblockplus.org/easylist.txt
');\ | 336 request.open('GET', 'https://easylist-downloads.adblockplus.org/easylist.txt
');\ |
141 request.setRequestHeader('X', 'Y');\ | 337 request.setRequestHeader('X', 'Y');\ |
142 request.overrideMimeType('text/plain');\ | 338 request.overrideMimeType('text/plain');\ |
143 request.addEventListener('load', function() {result = request.responseText;}
, false);\ | 339 request.addEventListener('load', function() {result = request.responseText;}
, false);\ |
144 request.addEventListener('error', function() {result = 'error';}, false);\ | 340 request.addEventListener('error', function() {result = 'error';}, false);\ |
145 request.send(null);"); | 341 request.send(null);"); |
146 do | 342 do |
147 { | 343 { |
148 AdblockPlus::Sleep(200); | 344 AdblockPlus::Sleep(200); |
149 } while (jsEngine->Evaluate("result")->IsUndefined()); | 345 } while (jsEngine->Evaluate("result")->IsUndefined()); |
150 ASSERT_EQ(AdblockPlus::WebRequest::NS_ERROR_FAILURE, jsEngine->Evaluate("reque
st.channel.status")->AsInt()); | 346 ASSERT_EQ(AdblockPlus::WebRequest::NS_ERROR_FAILURE, jsEngine->Evaluate("reque
st.channel.status")->AsInt()); |
151 ASSERT_EQ(0, jsEngine->Evaluate("request.status")->AsInt()); | 347 ASSERT_EQ(0, jsEngine->Evaluate("request.status")->AsInt()); |
152 ASSERT_EQ("error", jsEngine->Evaluate("result")->AsString()); | 348 ASSERT_EQ("error", jsEngine->Evaluate("result")->AsString()); |
153 ASSERT_TRUE(jsEngine->Evaluate("request.getResponseHeader('Content-Type')")->I
sNull()); | 349 ASSERT_TRUE(jsEngine->Evaluate("request.getResponseHeader('Content-Type')")->I
sNull()); |
154 } | 350 } |
155 | 351 |
156 #endif | 352 #endif |
OLD | NEW |