2 * Copyright (C) 2015 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
28 #include "PlatformUtilities.h"
29 #include <JavaScriptCore/InitializeThreading.h>
30 #include <WebCore/CombinedURLFilters.h>
31 #include <WebCore/ContentExtensionCompiler.h>
32 #include <WebCore/ContentExtensionError.h>
33 #include <WebCore/ContentExtensionsBackend.h>
34 #include <WebCore/DFA.h>
35 #include <WebCore/DFABytecodeCompiler.h>
36 #include <WebCore/DFABytecodeInterpreter.h>
37 #include <WebCore/NFA.h>
38 #include <WebCore/NFAToDFA.h>
39 #include <WebCore/ResourceLoadInfo.h>
40 #include <WebCore/URL.h>
41 #include <WebCore/URLFilterParser.h>
42 #include <wtf/MainThread.h>
43 #include <wtf/RunLoop.h>
44 #include <wtf/text/CString.h>
45 #include <wtf/text/StringBuilder.h>
48 namespace ContentExtensions {
49 inline std::ostream& operator<<(std::ostream& os, const ActionType& action)
52 case ActionType::BlockLoad:
53 return os << "ContentFilterAction::BlockLoad";
54 case ActionType::BlockCookies:
55 return os << "ContentFilterAction::BlockCookies";
56 case ActionType::CSSDisplayNoneSelector:
57 return os << "ContentFilterAction::CSSDisplayNone";
58 case ActionType::CSSDisplayNoneStyleSheet:
59 return os << "ContentFilterAction::CSSDisplayNoneStyleSheet";
60 case ActionType::IgnorePreviousRules:
61 return os << "ContentFilterAction::IgnorePreviousRules";
62 case ActionType::InvalidAction:
63 return os << "ContentFilterAction::InvalidAction";
69 using namespace WebCore;
71 namespace TestWebKitAPI {
73 class ContentExtensionTest : public testing::Test {
77 WTF::initializeMainThread();
78 JSC::initializeThreading();
79 RunLoop::initializeMainRunLoop();
83 struct CompiledContentExtensionData {
84 Vector<ContentExtensions::SerializedActionByte> actions;
85 Vector<ContentExtensions::DFABytecode> filtersWithoutDomains;
86 Vector<ContentExtensions::DFABytecode> filtersWithDomains;
87 Vector<ContentExtensions::DFABytecode> domainFilters;
90 class InMemoryContentExtensionCompilationClient final : public ContentExtensions::ContentExtensionCompilationClient {
92 InMemoryContentExtensionCompilationClient(CompiledContentExtensionData& data)
95 EXPECT_EQ(data.actions.size(), 0ull);
96 EXPECT_EQ(data.filtersWithoutDomains.size(), 0ull);
97 EXPECT_EQ(data.filtersWithDomains.size(), 0ull);
98 EXPECT_EQ(data.domainFilters.size(), 0ull);
101 virtual void writeActions(Vector<ContentExtensions::SerializedActionByte>&& actions) override
103 EXPECT_FALSE(finalized);
104 EXPECT_EQ(m_data.actions.size(), 0ull);
105 EXPECT_EQ(m_data.filtersWithoutDomains.size(), 0ull);
106 EXPECT_EQ(m_data.filtersWithDomains.size(), 0ull);
107 EXPECT_EQ(m_data.domainFilters.size(), 0ull);
108 m_data.actions.appendVector(actions);
111 virtual void writeFiltersWithoutDomainsBytecode(Vector<ContentExtensions::DFABytecode>&& bytecode) override
113 EXPECT_FALSE(finalized);
114 EXPECT_EQ(m_data.filtersWithDomains.size(), 0ull);
115 EXPECT_EQ(m_data.domainFilters.size(), 0ull);
116 m_data.filtersWithoutDomains.appendVector(bytecode);
119 virtual void writeFiltersWithDomainsBytecode(Vector<ContentExtensions::DFABytecode>&& bytecode) override
121 EXPECT_FALSE(finalized);
122 EXPECT_EQ(m_data.domainFilters.size(), 0ull);
123 m_data.filtersWithDomains.appendVector(bytecode);
126 virtual void writeDomainFiltersBytecode(Vector<ContentExtensions::DFABytecode>&& bytecode) override
128 EXPECT_FALSE(finalized);
129 m_data.domainFilters.appendVector(bytecode);
132 virtual void finalize() override
138 CompiledContentExtensionData& m_data;
139 bool finalized { false };
142 class InMemoryCompiledContentExtension : public ContentExtensions::CompiledContentExtension {
144 static RefPtr<InMemoryCompiledContentExtension> createFromFilter(String&& filter)
146 CompiledContentExtensionData extensionData;
147 InMemoryContentExtensionCompilationClient client(extensionData);
148 auto compilerError = ContentExtensions::compileRuleList(client, WTF::move(filter));
150 // Compiling should always succeed here. We have other tests for compile failures.
155 return InMemoryCompiledContentExtension::create(WTF::move(extensionData));
158 static RefPtr<InMemoryCompiledContentExtension> create(CompiledContentExtensionData&& data)
160 return adoptRef(new InMemoryCompiledContentExtension(WTF::move(data)));
163 virtual ~InMemoryCompiledContentExtension()
167 virtual const ContentExtensions::SerializedActionByte* actions() const override { return m_data.actions.data(); }
168 virtual unsigned actionsLength() const override { return m_data.actions.size(); }
169 virtual const ContentExtensions::DFABytecode* filtersWithoutDomainsBytecode() const override { return m_data.filtersWithoutDomains.data(); }
170 virtual unsigned filtersWithoutDomainsBytecodeLength() const override { return m_data.filtersWithoutDomains.size(); }
171 virtual const ContentExtensions::DFABytecode* filtersWithDomainsBytecode() const override { return m_data.filtersWithDomains.data(); }
172 virtual unsigned filtersWithDomainsBytecodeLength() const override { return m_data.filtersWithDomains.size(); }
173 virtual const ContentExtensions::DFABytecode* domainFiltersBytecode() const override { return m_data.domainFilters.data(); }
174 virtual unsigned domainFiltersBytecodeLength() const override { return m_data.domainFilters.size(); }
177 InMemoryCompiledContentExtension(CompiledContentExtensionData&& data)
178 : m_data(WTF::move(data))
182 CompiledContentExtensionData m_data;
185 void static testRequest(ContentExtensions::ContentExtensionsBackend contentExtensionsBackend, const ResourceLoadInfo& resourceLoadInfo, Vector<ContentExtensions::ActionType> expectedActions, bool ignorePreviousRules = false)
187 auto actions = contentExtensionsBackend.actionsForResourceLoad(resourceLoadInfo);
188 unsigned expectedSize = actions.size();
189 if (!ignorePreviousRules)
190 expectedSize--; // The last action is applying the compiled stylesheet.
192 EXPECT_EQ(expectedActions.size(), expectedSize);
193 if (expectedActions.size() != expectedSize)
196 for (unsigned i = 0; i < expectedActions.size(); ++i)
197 EXPECT_EQ(expectedActions[i], actions[i].type());
198 if (!ignorePreviousRules)
199 EXPECT_EQ(actions[actions.size() - 1].type(), ContentExtensions::ActionType::CSSDisplayNoneStyleSheet);
202 static ResourceLoadInfo mainDocumentRequest(const char* url, ResourceType resourceType = ResourceType::Document)
204 return { URL(URL(), url), URL(URL(), url), resourceType };
207 static ResourceLoadInfo subResourceRequest(const char* url, const char* mainDocumentURL, ResourceType resourceType = ResourceType::Document)
209 return { URL(URL(), url), URL(URL(), mainDocumentURL), resourceType };
212 ContentExtensions::ContentExtensionsBackend makeBackend(const char* json)
214 auto extension = InMemoryCompiledContentExtension::createFromFilter(json);
215 ContentExtensions::ContentExtensionsBackend backend;
216 backend.addContentExtension("testFilter", extension);
220 static Vector<ContentExtensions::NFA> createNFAs(ContentExtensions::CombinedURLFilters& combinedURLFilters)
222 Vector<ContentExtensions::NFA> nfas;
224 combinedURLFilters.processNFAs(std::numeric_limits<size_t>::max(), [&](ContentExtensions::NFA&& nfa) {
225 nfas.append(WTF::move(nfa));
231 TEST_F(ContentExtensionTest, Basic)
233 auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\"}}]");
235 testRequest(backend, mainDocumentRequest("http://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
238 TEST_F(ContentExtensionTest, RangeBasic)
240 auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"w[0-9]c\", \"url-filter-is-case-sensitive\":true}},"
241 "{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"[A-H][a-z]cko\", \"url-filter-is-case-sensitive\":true}}]");
243 testRequest(backend, mainDocumentRequest("http://w3c.org"), { ContentExtensions::ActionType::BlockLoad });
244 testRequest(backend, mainDocumentRequest("w2c://whatwg.org/"), { ContentExtensions::ActionType::BlockLoad });
245 testRequest(backend, mainDocumentRequest("http://webkit.org/w0c"), { ContentExtensions::ActionType::BlockLoad });
246 testRequest(backend, mainDocumentRequest("http://webkit.org/wac"), { });
247 testRequest(backend, mainDocumentRequest("http://webkit.org/wAc"), { });
249 // Note: URL parsing and canonicalization lowercase the scheme and hostname.
250 testRequest(backend, mainDocumentRequest("Aacko://webkit.org"), { });
251 testRequest(backend, mainDocumentRequest("aacko://webkit.org"), { });
252 testRequest(backend, mainDocumentRequest("http://gCcko.org/"), { });
253 testRequest(backend, mainDocumentRequest("http://gccko.org/"), { });
255 testRequest(backend, mainDocumentRequest("http://webkit.org/Gecko"), { ContentExtensions::ActionType::BlockCookies });
256 testRequest(backend, mainDocumentRequest("http://webkit.org/gecko"), { });
257 testRequest(backend, mainDocumentRequest("http://webkit.org/GEcko"), { });
260 TEST_F(ContentExtensionTest, RangeExclusionGeneratingUniversalTransition)
262 // Transition of the type ([^X]X) effictively transition on every input.
263 auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[^a]+afoobar\"}}]");
265 testRequest(backend, mainDocumentRequest("http://w3c.org"), { });
267 testRequest(backend, mainDocumentRequest("http://w3c.org/foobafoobar"), { ContentExtensions::ActionType::BlockLoad });
268 testRequest(backend, mainDocumentRequest("http://w3c.org/foobarfoobar"), { });
269 testRequest(backend, mainDocumentRequest("http://w3c.org/FOOBAFOOBAR"), { ContentExtensions::ActionType::BlockLoad });
270 testRequest(backend, mainDocumentRequest("http://w3c.org/FOOBARFOOBAR"), { });
272 // The character before the "a" prefix cannot be another "a".
273 testRequest(backend, mainDocumentRequest("http://w3c.org/aafoobar"), { });
274 testRequest(backend, mainDocumentRequest("http://w3c.org/Aafoobar"), { });
275 testRequest(backend, mainDocumentRequest("http://w3c.org/aAfoobar"), { });
276 testRequest(backend, mainDocumentRequest("http://w3c.org/AAfoobar"), { });
279 TEST_F(ContentExtensionTest, PatternStartingWithGroup)
281 auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(http://whatwg\\\\.org/)?webkit\134\134.org\"}}]");
283 testRequest(backend, mainDocumentRequest("http://whatwg.org/webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
284 testRequest(backend, mainDocumentRequest("http://whatwg.org/webkit.org"), { ContentExtensions::ActionType::BlockLoad });
285 testRequest(backend, mainDocumentRequest("http://webkit.org/"), { });
286 testRequest(backend, mainDocumentRequest("http://whatwg.org/"), { });
287 testRequest(backend, mainDocumentRequest("http://whatwg.org"), { });
290 TEST_F(ContentExtensionTest, PatternNestedGroups)
292 auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^http://webkit\\\\.org/(foo(bar)*)+\"}}]");
294 testRequest(backend, mainDocumentRequest("http://webkit.org/foo"), { ContentExtensions::ActionType::BlockLoad });
295 testRequest(backend, mainDocumentRequest("http://webkit.org/foobar"), { ContentExtensions::ActionType::BlockLoad });
296 testRequest(backend, mainDocumentRequest("http://webkit.org/foobarbar"), { ContentExtensions::ActionType::BlockLoad });
297 testRequest(backend, mainDocumentRequest("http://webkit.org/foofoobar"), { ContentExtensions::ActionType::BlockLoad });
298 testRequest(backend, mainDocumentRequest("http://webkit.org/foobarfoobar"), { ContentExtensions::ActionType::BlockLoad });
299 testRequest(backend, mainDocumentRequest("http://webkit.org/foob"), { ContentExtensions::ActionType::BlockLoad });
300 testRequest(backend, mainDocumentRequest("http://webkit.org/foor"), { ContentExtensions::ActionType::BlockLoad });
302 testRequest(backend, mainDocumentRequest("http://webkit.org/"), { });
303 testRequest(backend, mainDocumentRequest("http://webkit.org/bar"), { });
304 testRequest(backend, mainDocumentRequest("http://webkit.org/fobar"), { });
307 TEST_F(ContentExtensionTest, MatchPastEndOfString)
309 auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\".+\"}}]");
311 testRequest(backend, mainDocumentRequest("http://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
312 testRequest(backend, mainDocumentRequest("http://webkit.org/foo"), { ContentExtensions::ActionType::BlockLoad });
313 testRequest(backend, mainDocumentRequest("http://webkit.org/foobar"), { ContentExtensions::ActionType::BlockLoad });
314 testRequest(backend, mainDocumentRequest("http://webkit.org/foobarbar"), { ContentExtensions::ActionType::BlockLoad });
315 testRequest(backend, mainDocumentRequest("http://webkit.org/foofoobar"), { ContentExtensions::ActionType::BlockLoad });
316 testRequest(backend, mainDocumentRequest("http://webkit.org/foobarfoobar"), { ContentExtensions::ActionType::BlockLoad });
317 testRequest(backend, mainDocumentRequest("http://webkit.org/foob"), { ContentExtensions::ActionType::BlockLoad });
318 testRequest(backend, mainDocumentRequest("http://webkit.org/foor"), { ContentExtensions::ActionType::BlockLoad });
321 TEST_F(ContentExtensionTest, StartOfLineAssertion)
323 auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^foobar\"}}]");
325 testRequest(backend, mainDocumentRequest("foobar://webkit.org/foobar"), { ContentExtensions::ActionType::BlockLoad });
326 testRequest(backend, mainDocumentRequest("foobars:///foobar"), { ContentExtensions::ActionType::BlockLoad });
327 testRequest(backend, mainDocumentRequest("foobarfoobar:///foobarfoobarfoobar"), { ContentExtensions::ActionType::BlockLoad });
329 testRequest(backend, mainDocumentRequest("http://webkit.org/foobarfoo"), { });
330 testRequest(backend, mainDocumentRequest("http://webkit.org/foobarf"), { });
331 testRequest(backend, mainDocumentRequest("http://foobar.org/"), { });
332 testRequest(backend, mainDocumentRequest("http://foobar.org/"), { });
335 TEST_F(ContentExtensionTest, EndOfLineAssertion)
337 auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"foobar$\"}}]");
339 testRequest(backend, mainDocumentRequest("http://webkit.org/foobar"), { ContentExtensions::ActionType::BlockLoad });
340 testRequest(backend, mainDocumentRequest("file:///foobar"), { ContentExtensions::ActionType::BlockLoad });
341 testRequest(backend, mainDocumentRequest("file:///foobarfoobarfoobar"), { ContentExtensions::ActionType::BlockLoad });
343 testRequest(backend, mainDocumentRequest("http://webkit.org/foobarfoo"), { });
344 testRequest(backend, mainDocumentRequest("http://webkit.org/foobarf"), { });
347 TEST_F(ContentExtensionTest, EndOfLineAssertionWithInvertedCharacterSet)
349 auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[^y]$\"}}]");
351 testRequest(backend, mainDocumentRequest("http://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
352 testRequest(backend, mainDocumentRequest("http://webkit.org/a"), { ContentExtensions::ActionType::BlockLoad });
353 testRequest(backend, mainDocumentRequest("http://webkit.org/foobar"), { ContentExtensions::ActionType::BlockLoad });
354 testRequest(backend, mainDocumentRequest("http://webkit.org/Ya"), { ContentExtensions::ActionType::BlockLoad });
355 testRequest(backend, mainDocumentRequest("http://webkit.org/yFoobar"), { ContentExtensions::ActionType::BlockLoad });
356 testRequest(backend, mainDocumentRequest("http://webkit.org/y"), { });
357 testRequest(backend, mainDocumentRequest("http://webkit.org/Y"), { });
358 testRequest(backend, mainDocumentRequest("http://webkit.org/foobary"), { });
359 testRequest(backend, mainDocumentRequest("http://webkit.org/foobarY"), { });
362 TEST_F(ContentExtensionTest, PrefixInfixSuffixExactMatch)
364 auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"infix\"}},"
365 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^prefix\"}},"
366 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"suffix$\"}},"
367 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^http://exact\\\\.org/$\"}}]");
369 testRequest(backend, mainDocumentRequest("infix://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
370 testRequest(backend, mainDocumentRequest("http://infix.org/"), { ContentExtensions::ActionType::BlockLoad });
371 testRequest(backend, mainDocumentRequest("https://webkit.org/infix"), { ContentExtensions::ActionType::BlockLoad });
373 testRequest(backend, mainDocumentRequest("prefix://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
374 testRequest(backend, mainDocumentRequest("https://prefix.org/"), { });
375 testRequest(backend, mainDocumentRequest("https://webkit.org/prefix"), { });
377 testRequest(backend, mainDocumentRequest("https://webkit.org/suffix"), { ContentExtensions::ActionType::BlockLoad });
378 testRequest(backend, mainDocumentRequest("https://suffix.org/"), { });
379 testRequest(backend, mainDocumentRequest("suffix://webkit.org/"), { });
381 testRequest(backend, mainDocumentRequest("http://exact.org/"), { ContentExtensions::ActionType::BlockLoad });
382 testRequest(backend, mainDocumentRequest("http://exact.org/oops"), { });
385 TEST_F(ContentExtensionTest, DuplicatedMatchAllTermsInVariousFormat)
387 auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\".*.*(.)*(.*)(.+)*(.?)*infix\"}},"
388 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"pre(.?)+(.+)?post\"}}]");
390 testRequest(backend, mainDocumentRequest("infix://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
391 testRequest(backend, mainDocumentRequest("http://infix.org/"), { ContentExtensions::ActionType::BlockLoad });
392 testRequest(backend, mainDocumentRequest("https://webkit.org/infix"), { ContentExtensions::ActionType::BlockLoad });
394 testRequest(backend, mainDocumentRequest("pre://webkit.org/post"), { ContentExtensions::ActionType::BlockLoad });
395 testRequest(backend, mainDocumentRequest("http://prepost.org/"), { ContentExtensions::ActionType::BlockLoad });
396 testRequest(backend, mainDocumentRequest("https://pre.org/posttail"), { ContentExtensions::ActionType::BlockLoad });
397 testRequest(backend, mainDocumentRequest("https://pre.pre/posttail"), { ContentExtensions::ActionType::BlockLoad });
398 testRequest(backend, mainDocumentRequest("https://pre.org/posttailpost"), { ContentExtensions::ActionType::BlockLoad });
400 testRequest(backend, mainDocumentRequest("https://post.org/pre"), { });
401 testRequest(backend, mainDocumentRequest("https://pre.org/pre"), { });
402 testRequest(backend, mainDocumentRequest("https://post.org/post"), { });
405 TEST_F(ContentExtensionTest, DomainTriggers)
407 auto ifDomainBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"if-domain\":[\"webkit.org\"]}}]");
408 testRequest(ifDomainBackend, mainDocumentRequest("http://webkit.org/test.htm"), { });
409 testRequest(ifDomainBackend, mainDocumentRequest("http://bugs.webkit.org/test.htm"), { });
410 testRequest(ifDomainBackend, mainDocumentRequest("http://webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
411 testRequest(ifDomainBackend, mainDocumentRequest("http://bugs.webkit.org/test.html"), { });
412 testRequest(ifDomainBackend, mainDocumentRequest("http://sub2.sub1.webkit.org/test.html"), { });
413 testRequest(ifDomainBackend, mainDocumentRequest("http://not_webkit.org/test.htm"), { });
414 testRequest(ifDomainBackend, mainDocumentRequest("http://webkit.organization/test.htm"), { });
415 testRequest(ifDomainBackend, mainDocumentRequest("http://not_webkit.org/test.html"), { });
416 testRequest(ifDomainBackend, mainDocumentRequest("http://webkit.organization/test.html"), { });
418 auto unlessDomainBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"unless-domain\":[\"webkit.org\"]}}]");
419 testRequest(unlessDomainBackend, mainDocumentRequest("http://webkit.org/test.htm"), { });
420 testRequest(unlessDomainBackend, mainDocumentRequest("http://bugs.webkit.org/test.htm"), { });
421 testRequest(unlessDomainBackend, mainDocumentRequest("http://webkit.org/test.html"), { });
422 testRequest(unlessDomainBackend, mainDocumentRequest("http://bugs.webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
423 testRequest(unlessDomainBackend, mainDocumentRequest("http://sub2.sub1.webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
424 testRequest(unlessDomainBackend, mainDocumentRequest("http://not_webkit.org/test.htm"), { });
425 testRequest(unlessDomainBackend, mainDocumentRequest("http://webkit.organization/test.htm"), { });
426 testRequest(unlessDomainBackend, mainDocumentRequest("http://not_webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
427 testRequest(unlessDomainBackend, mainDocumentRequest("http://webkit.organization/test.html"), { ContentExtensions::ActionType::BlockLoad });
429 auto ifDomainStarBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"if-domain\":[\"*webkit.org\"]}}]");
430 testRequest(ifDomainStarBackend, mainDocumentRequest("http://webkit.org/test.htm"), { });
431 testRequest(ifDomainStarBackend, mainDocumentRequest("http://bugs.webkit.org/test.htm"), { });
432 testRequest(ifDomainStarBackend, mainDocumentRequest("http://webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
433 testRequest(ifDomainStarBackend, mainDocumentRequest("http://bugs.webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
434 testRequest(ifDomainStarBackend, mainDocumentRequest("http://sub2.sub1.webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
435 testRequest(ifDomainStarBackend, mainDocumentRequest("http://not_webkit.org/test.htm"), { });
436 testRequest(ifDomainStarBackend, mainDocumentRequest("http://webkit.organization/test.htm"), { });
437 testRequest(ifDomainStarBackend, mainDocumentRequest("http://not_webkit.org/test.html"), { });
438 testRequest(ifDomainStarBackend, mainDocumentRequest("http://webkit.organization/test.html"), { });
440 auto unlessDomainStarBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"unless-domain\":[\"*webkit.org\"]}}]");
441 testRequest(unlessDomainStarBackend, mainDocumentRequest("http://webkit.org/test.htm"), { });
442 testRequest(unlessDomainStarBackend, mainDocumentRequest("http://bugs.webkit.org/test.htm"), { });
443 testRequest(unlessDomainStarBackend, mainDocumentRequest("http://webkit.org/test.html"), { });
444 testRequest(unlessDomainStarBackend, mainDocumentRequest("http://bugs.webkit.org/test.html"), { });
445 testRequest(unlessDomainStarBackend, mainDocumentRequest("http://sub2.sub1.webkit.org/test.html"), { });
446 testRequest(unlessDomainStarBackend, mainDocumentRequest("http://not_webkit.org/test.htm"), { });
447 testRequest(unlessDomainStarBackend, mainDocumentRequest("http://webkit.organization/test.htm"), { });
448 testRequest(unlessDomainStarBackend, mainDocumentRequest("http://not_webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
449 testRequest(unlessDomainStarBackend, mainDocumentRequest("http://webkit.organization/test.html"), { ContentExtensions::ActionType::BlockLoad });
451 auto ifSubDomainBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"if-domain\":[\"sub1.webkit.org\"]}}]");
452 testRequest(ifSubDomainBackend, mainDocumentRequest("http://webkit.org/test.html"), { });
453 testRequest(ifSubDomainBackend, mainDocumentRequest("http://bugs.webkit.org/test.html"), { });
454 testRequest(ifSubDomainBackend, mainDocumentRequest("http://sub1.webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
455 testRequest(ifSubDomainBackend, mainDocumentRequest("http://sub2.sub1.webkit.org/test.html"), { });
457 auto ifSubDomainStarBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"if-domain\":[\"*sub1.webkit.org\"]}}]");
458 testRequest(ifSubDomainStarBackend, mainDocumentRequest("http://webkit.org/test.html"), { });
459 testRequest(ifSubDomainStarBackend, mainDocumentRequest("http://bugs.webkit.org/test.html"), { });
460 testRequest(ifSubDomainStarBackend, mainDocumentRequest("http://sub1.webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
461 testRequest(ifSubDomainStarBackend, mainDocumentRequest("http://sub2.sub1.webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
463 auto unlessSubDomainBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"unless-domain\":[\"sub1.webkit.org\"]}}]");
464 testRequest(unlessSubDomainBackend, mainDocumentRequest("http://webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
465 testRequest(unlessSubDomainBackend, mainDocumentRequest("http://bugs.webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
466 testRequest(unlessSubDomainBackend, mainDocumentRequest("http://sub1.webkit.org/test.html"), { });
467 testRequest(unlessSubDomainBackend, mainDocumentRequest("http://sub2.sub1.webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
469 auto unlessSubDomainStarBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"unless-domain\":[\"*sub1.webkit.org\"]}}]");
470 testRequest(unlessSubDomainStarBackend, mainDocumentRequest("http://webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
471 testRequest(unlessSubDomainStarBackend, mainDocumentRequest("http://bugs.webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
472 testRequest(unlessSubDomainStarBackend, mainDocumentRequest("http://sub1.webkit.org/test.html"), { });
473 testRequest(unlessSubDomainStarBackend, mainDocumentRequest("http://sub2.sub1.webkit.org/test.html"), { });
475 auto combinedBackend1 = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test_block_load\", \"if-domain\":[\"webkit.org\"]}},"
476 "{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"test_block_cookies\", \"unless-domain\":[\"webkit.org\"]}}]");
477 testRequest(combinedBackend1, mainDocumentRequest("http://webkit.org"), { });
478 testRequest(combinedBackend1, mainDocumentRequest("http://not_webkit.org"), { });
479 testRequest(combinedBackend1, mainDocumentRequest("http://webkit.org/test_block_load.html"), { ContentExtensions::ActionType::BlockLoad });
480 testRequest(combinedBackend1, subResourceRequest("http://whatwg.org/test_block_load.html", "http://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
481 testRequest(combinedBackend1, subResourceRequest("http://whatwg.org/shouldnt_match.html", "http://webkit.org/"), { });
482 testRequest(combinedBackend1, subResourceRequest("http://whatwg.org/test_block_load.html", "http://not_webkit.org/"), { });
483 testRequest(combinedBackend1, subResourceRequest("http://whatwg.org/shouldnt_match.html", "http://not_webkit.org/"), { });
484 testRequest(combinedBackend1, mainDocumentRequest("http://webkit.org/test_block_cookies.html"), { });
485 testRequest(combinedBackend1, subResourceRequest("http://whatwg.org/test_block_cookies.html", "http://webkit.org/"), { });
486 testRequest(combinedBackend1, subResourceRequest("http://whatwg.org/shouldnt_match.html", "http://webkit.org/"), { });
487 testRequest(combinedBackend1, subResourceRequest("http://whatwg.org/test_block_cookies.html", "http://not_webkit.org/path/to/main/document.html"), { ContentExtensions::ActionType::BlockCookies });
488 testRequest(combinedBackend1, subResourceRequest("http://whatwg.org/shouldnt_match.html", "http://not_webkit.org/"), { });
490 auto combinedBackend2 = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test_block_load\\\\.html\", \"if-domain\":[\"webkit.org\"]}},"
491 "{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"test_block_cookies\\\\.html\", \"unless-domain\":[\"w3c.org\"]}},"
492 "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"test_css\\\\.html\"}}]");
493 testRequest(combinedBackend2, mainDocumentRequest("http://webkit.org/test_css.html"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
494 testRequest(combinedBackend2, mainDocumentRequest("http://webkit.org/test_css.htm"), { });
495 testRequest(combinedBackend2, mainDocumentRequest("http://webkit.org/test_block_load.html"), { ContentExtensions::ActionType::BlockLoad });
496 testRequest(combinedBackend2, mainDocumentRequest("http://not_webkit.org/test_block_load.html"), { });
497 testRequest(combinedBackend2, mainDocumentRequest("http://not_webkit.org/test_css.html"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
498 testRequest(combinedBackend2, mainDocumentRequest("http://webkit.org/TEST_CSS.hTmL/test_block_load.html"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad});
499 testRequest(combinedBackend2, mainDocumentRequest("http://w3c.org/test_css.html"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
500 testRequest(combinedBackend2, mainDocumentRequest("http://w3c.org/test_block_load.html"), { });
501 testRequest(combinedBackend2, mainDocumentRequest("http://w3c.org/test_block_cookies.html"), { });
502 testRequest(combinedBackend2, mainDocumentRequest("http://w3c.org/test_css.html/test_block_cookies.html"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
503 testRequest(combinedBackend2, mainDocumentRequest("http://not_w3c.org/test_block_cookies.html"), { ContentExtensions::ActionType::BlockCookies });
504 testRequest(combinedBackend2, mainDocumentRequest("http://not_w3c.org/test_css.html/test_block_cookies.html"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockCookies });
506 auto ifDomainWithFlagsBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\", \"if-domain\":[\"webkit.org\"],\"resource-type\":[\"image\"]}}]");
507 testRequest(ifDomainWithFlagsBackend, mainDocumentRequest("http://webkit.org/test.html"), { });
508 testRequest(ifDomainWithFlagsBackend, mainDocumentRequest("http://webkit.org/test.png", ResourceType::Image), { ContentExtensions::ActionType::BlockLoad });
509 testRequest(ifDomainWithFlagsBackend, mainDocumentRequest("http://not_webkit.org/test.html"), { });
510 testRequest(ifDomainWithFlagsBackend, mainDocumentRequest("http://not_webkit.org/test.png", ResourceType::Image), { });
512 auto unlessDomainWithFlagsBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\", \"unless-domain\":[\"webkit.org\"],\"resource-type\":[\"image\"]}}]");
513 testRequest(unlessDomainWithFlagsBackend, mainDocumentRequest("http://webkit.org/test.html"), { });
514 testRequest(unlessDomainWithFlagsBackend, mainDocumentRequest("http://webkit.org/test.png", ResourceType::Image), { });
515 testRequest(unlessDomainWithFlagsBackend, mainDocumentRequest("http://not_webkit.org/test.html"), { });
516 testRequest(unlessDomainWithFlagsBackend, mainDocumentRequest("http://not_webkit.org/test.png", ResourceType::Image), { ContentExtensions::ActionType::BlockLoad });
518 // Domains should not be interepted as regular expressions.
519 auto domainRegexBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"if-domain\":[\"we?bkit.org\"]}}]");
520 testRequest(domainRegexBackend, mainDocumentRequest("http://webkit.org/test.html"), { });
521 testRequest(domainRegexBackend, mainDocumentRequest("http://wbkit.org/test.html"), { });
523 auto multipleIfDomainsBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"if-domain\":[\"webkit.org\", \"w3c.org\"]}}]");
524 testRequest(multipleIfDomainsBackend, mainDocumentRequest("http://webkit.org/test.htm"), { });
525 testRequest(multipleIfDomainsBackend, mainDocumentRequest("http://webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
526 testRequest(multipleIfDomainsBackend, mainDocumentRequest("http://w3c.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
527 testRequest(multipleIfDomainsBackend, mainDocumentRequest("http://whatwg.org/test.html"), { });
529 auto multipleUnlessDomainsBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"unless-domain\":[\"webkit.org\", \"w3c.org\"]}}]");
530 testRequest(multipleUnlessDomainsBackend, mainDocumentRequest("http://webkit.org/test.htm"), { });
531 testRequest(multipleUnlessDomainsBackend, mainDocumentRequest("http://webkit.org/test.html"), { });
532 testRequest(multipleUnlessDomainsBackend, mainDocumentRequest("http://w3c.org/test.html"), { });
533 testRequest(multipleUnlessDomainsBackend, mainDocumentRequest("http://whatwg.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
535 // FIXME: Add and test domain-specific popup-only blocking (with layout tests).
538 TEST_F(ContentExtensionTest, MultipleExtensions)
540 auto extension1 = InMemoryCompiledContentExtension::createFromFilter("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"block_load\"}}]");
541 auto extension2 = InMemoryCompiledContentExtension::createFromFilter("[{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"block_cookies\"}}]");
542 ContentExtensions::ContentExtensionsBackend backend;
543 backend.addContentExtension("testFilter1", extension1);
544 backend.addContentExtension("testFilter2", extension2);
546 // These each have two display:none stylesheets. The second one is implied by using the default parameter ignorePreviousRules = false.
547 testRequest(backend, mainDocumentRequest("http://webkit.org"), { ContentExtensions::ActionType::CSSDisplayNoneStyleSheet });
548 testRequest(backend, mainDocumentRequest("http://webkit.org/block_load.html"), { ContentExtensions::ActionType::CSSDisplayNoneStyleSheet, ContentExtensions::ActionType::BlockLoad});
549 testRequest(backend, mainDocumentRequest("http://webkit.org/block_cookies.html"), { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::CSSDisplayNoneStyleSheet});
550 testRequest(backend, mainDocumentRequest("http://webkit.org/block_load/block_cookies.html"), { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::CSSDisplayNoneStyleSheet, ContentExtensions::ActionType::BlockLoad });
551 testRequest(backend, mainDocumentRequest("http://webkit.org/block_cookies/block_load.html"), { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::CSSDisplayNoneStyleSheet, ContentExtensions::ActionType::BlockLoad });
553 auto ignoreExtension1 = InMemoryCompiledContentExtension::createFromFilter("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"block_load\"}},"
554 "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"ignore1\"}}]");
555 auto ignoreExtension2 = InMemoryCompiledContentExtension::createFromFilter("[{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"block_cookies\"}},"
556 "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"ignore2\"}}]");
557 ContentExtensions::ContentExtensionsBackend backendWithIgnore;
558 backendWithIgnore.addContentExtension("testFilter1", ignoreExtension1);
559 backendWithIgnore.addContentExtension("testFilter2", ignoreExtension2);
561 testRequest(backendWithIgnore, mainDocumentRequest("http://webkit.org"), { ContentExtensions::ActionType::CSSDisplayNoneStyleSheet, ContentExtensions::ActionType::CSSDisplayNoneStyleSheet }, true);
562 testRequest(backendWithIgnore, mainDocumentRequest("http://webkit.org/block_load/ignore1.html"), { ContentExtensions::ActionType::CSSDisplayNoneStyleSheet }, true);
563 testRequest(backendWithIgnore, mainDocumentRequest("http://webkit.org/block_cookies/ignore1.html"), { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::CSSDisplayNoneStyleSheet}, true);
564 testRequest(backendWithIgnore, mainDocumentRequest("http://webkit.org/block_load/ignore2.html"), { ContentExtensions::ActionType::BlockLoad, ContentExtensions::ActionType::CSSDisplayNoneStyleSheet }, true);
565 testRequest(backendWithIgnore, mainDocumentRequest("http://webkit.org/block_cookies/ignore2.html"), { ContentExtensions::ActionType::CSSDisplayNoneStyleSheet}, true);
566 testRequest(backendWithIgnore, mainDocumentRequest("http://webkit.org/block_load/block_cookies/ignore1/ignore2.html"), { }, true);
569 TEST_F(ContentExtensionTest, TermsKnownToMatchAnything)
571 auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^pre1.*post1$\"}},"
572 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^pre2(.*)post2$\"}},"
573 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^pre3(.*)?post3$\"}},"
574 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^pre4(.*)+post4$\"}},"
575 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^pre5(.*)*post5$\"}},"
576 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^pre6(.)*post6$\"}},"
577 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^pre7(.+)*post7$\"}},"
578 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^pre8(.?)*post8$\"}},"
579 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^pre9(.+)?post9$\"}},"
580 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^pre0(.?)+post0$\"}}]");
582 testRequest(backend, mainDocumentRequest("pre1://webkit.org/post1"), { ContentExtensions::ActionType::BlockLoad });
583 testRequest(backend, mainDocumentRequest("pre2://webkit.org/post2"), { ContentExtensions::ActionType::BlockLoad });
584 testRequest(backend, mainDocumentRequest("pre3://webkit.org/post3"), { ContentExtensions::ActionType::BlockLoad });
585 testRequest(backend, mainDocumentRequest("pre4://webkit.org/post4"), { ContentExtensions::ActionType::BlockLoad });
586 testRequest(backend, mainDocumentRequest("pre5://webkit.org/post5"), { ContentExtensions::ActionType::BlockLoad });
587 testRequest(backend, mainDocumentRequest("pre6://webkit.org/post6"), { ContentExtensions::ActionType::BlockLoad });
588 testRequest(backend, mainDocumentRequest("pre7://webkit.org/post7"), { ContentExtensions::ActionType::BlockLoad });
589 testRequest(backend, mainDocumentRequest("pre8://webkit.org/post8"), { ContentExtensions::ActionType::BlockLoad });
590 testRequest(backend, mainDocumentRequest("pre9://webkit.org/post9"), { ContentExtensions::ActionType::BlockLoad });
591 testRequest(backend, mainDocumentRequest("pre0://webkit.org/post0"), { ContentExtensions::ActionType::BlockLoad });
593 testRequest(backend, mainDocumentRequest("pre1://webkit.org/post2"), { });
594 testRequest(backend, mainDocumentRequest("pre2://webkit.org/post3"), { });
595 testRequest(backend, mainDocumentRequest("pre3://webkit.org/post4"), { });
596 testRequest(backend, mainDocumentRequest("pre4://webkit.org/post5"), { });
597 testRequest(backend, mainDocumentRequest("pre5://webkit.org/post6"), { });
598 testRequest(backend, mainDocumentRequest("pre6://webkit.org/post7"), { });
599 testRequest(backend, mainDocumentRequest("pre7://webkit.org/post8"), { });
600 testRequest(backend, mainDocumentRequest("pre8://webkit.org/post9"), { });
601 testRequest(backend, mainDocumentRequest("pre9://webkit.org/post0"), { });
602 testRequest(backend, mainDocumentRequest("pre0://webkit.org/post1"), { });
604 testRequest(backend, mainDocumentRequest("pre0://webkit.org/post1"), { });
605 testRequest(backend, mainDocumentRequest("pre1://webkit.org/post2"), { });
606 testRequest(backend, mainDocumentRequest("pre2://webkit.org/post3"), { });
607 testRequest(backend, mainDocumentRequest("pre3://webkit.org/post4"), { });
608 testRequest(backend, mainDocumentRequest("pre4://webkit.org/post5"), { });
609 testRequest(backend, mainDocumentRequest("pre5://webkit.org/post6"), { });
610 testRequest(backend, mainDocumentRequest("pre6://webkit.org/post7"), { });
611 testRequest(backend, mainDocumentRequest("pre7://webkit.org/post8"), { });
612 testRequest(backend, mainDocumentRequest("pre8://webkit.org/post9"), { });
613 testRequest(backend, mainDocumentRequest("pre9://webkit.org/post0"), { });
616 TEST_F(ContentExtensionTest, TrailingDotStar)
618 auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"foo.*$\"}},"
619 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"bar(.*)$\"}}]");
621 testRequest(backend, mainDocumentRequest("https://webkit.org/"), { });
623 testRequest(backend, mainDocumentRequest("foo://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
624 testRequest(backend, mainDocumentRequest("https://foo.org/"), { ContentExtensions::ActionType::BlockLoad });
625 testRequest(backend, mainDocumentRequest("https://webkit.foo/"), { ContentExtensions::ActionType::BlockLoad });
626 testRequest(backend, mainDocumentRequest("https://webkit.org/foo"), { ContentExtensions::ActionType::BlockLoad });
628 testRequest(backend, mainDocumentRequest("bar://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
629 testRequest(backend, mainDocumentRequest("https://bar.org/"), { ContentExtensions::ActionType::BlockLoad });
630 testRequest(backend, mainDocumentRequest("https://webkit.bar/"), { ContentExtensions::ActionType::BlockLoad });
631 testRequest(backend, mainDocumentRequest("https://webkit.org/bar"), { ContentExtensions::ActionType::BlockLoad });
634 TEST_F(ContentExtensionTest, TrailingTermsCarryingNoData)
636 auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"foob?a?r?\"}},"
637 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"bazo(ok)?a?$\"}},"
638 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"cats*$\"}}]");
640 testRequest(backend, mainDocumentRequest("https://webkit.org/"), { });
642 // Anything is fine after foo.
643 testRequest(backend, mainDocumentRequest("https://webkit.org/foo"), { ContentExtensions::ActionType::BlockLoad });
644 testRequest(backend, mainDocumentRequest("https://webkit.org/foob"), { ContentExtensions::ActionType::BlockLoad });
645 testRequest(backend, mainDocumentRequest("https://webkit.org/fooc"), { ContentExtensions::ActionType::BlockLoad });
646 testRequest(backend, mainDocumentRequest("https://webkit.org/fooba"), { ContentExtensions::ActionType::BlockLoad });
647 testRequest(backend, mainDocumentRequest("https://webkit.org/foobar"), { ContentExtensions::ActionType::BlockLoad });
648 testRequest(backend, mainDocumentRequest("https://webkit.org/foobar-stuff"), { ContentExtensions::ActionType::BlockLoad });
650 // Bazooka has to be at the tail without any character not defined by the filter.
651 testRequest(backend, mainDocumentRequest("https://webkit.org/baz"), { });
652 testRequest(backend, mainDocumentRequest("https://webkit.org/bazo"), { ContentExtensions::ActionType::BlockLoad });
653 testRequest(backend, mainDocumentRequest("https://webkit.org/bazoa"), { ContentExtensions::ActionType::BlockLoad });
654 testRequest(backend, mainDocumentRequest("https://webkit.org/bazob"), { });
655 testRequest(backend, mainDocumentRequest("https://webkit.org/bazoo"), { });
656 testRequest(backend, mainDocumentRequest("https://webkit.org/bazook"), { ContentExtensions::ActionType::BlockLoad });
657 testRequest(backend, mainDocumentRequest("https://webkit.org/bazookb"), { });
658 testRequest(backend, mainDocumentRequest("https://webkit.org/bazooka"), { ContentExtensions::ActionType::BlockLoad });
659 testRequest(backend, mainDocumentRequest("https://webkit.org/bazookaa"), { });
661 // The pattern must finish with cat, with any number of 's' following it, but no other character.
662 testRequest(backend, mainDocumentRequest("https://cat.org/"), { });
663 testRequest(backend, mainDocumentRequest("https://cats.org/"), { });
664 testRequest(backend, mainDocumentRequest("https://webkit.org/cat"), { ContentExtensions::ActionType::BlockLoad });
665 testRequest(backend, mainDocumentRequest("https://webkit.org/cats"), { ContentExtensions::ActionType::BlockLoad });
666 testRequest(backend, mainDocumentRequest("https://webkit.org/catss"), { ContentExtensions::ActionType::BlockLoad });
667 testRequest(backend, mainDocumentRequest("https://webkit.org/catsss"), { ContentExtensions::ActionType::BlockLoad });
668 testRequest(backend, mainDocumentRequest("https://webkit.org/catso"), { });
671 TEST_F(ContentExtensionTest, LoadType)
673 auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"load-type\":[\"third-party\"]}},"
674 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"whatwg.org\",\"load-type\":[\"first-party\"]}},"
675 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"alwaysblock.pdf\"}}]");
677 testRequest(backend, mainDocumentRequest("http://webkit.org"), { });
678 testRequest(backend, {URL(URL(), "http://webkit.org"), URL(URL(), "http://not_webkit.org"), ResourceType::Document}, { ContentExtensions::ActionType::BlockLoad });
680 testRequest(backend, mainDocumentRequest("http://whatwg.org"), { ContentExtensions::ActionType::BlockLoad });
681 testRequest(backend, {URL(URL(), "http://whatwg.org"), URL(URL(), "http://not_whatwg.org"), ResourceType::Document}, { });
683 testRequest(backend, mainDocumentRequest("http://foobar.org/alwaysblock.pdf"), { ContentExtensions::ActionType::BlockLoad });
684 testRequest(backend, {URL(URL(), "http://foobar.org/alwaysblock.pdf"), URL(URL(), "http://not_foobar.org/alwaysblock.pdf"), ResourceType::Document}, { ContentExtensions::ActionType::BlockLoad });
687 TEST_F(ContentExtensionTest, ResourceType)
689 auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"block_all_types.org\",\"resource-type\":[\"document\",\"image\",\"style-sheet\",\"script\",\"font\",\"raw\",\"svg-document\",\"media\",\"popup\"]}},"
690 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"block_only_images\",\"resource-type\":[\"image\"]}}]");
692 testRequest(backend, mainDocumentRequest("http://block_all_types.org", ResourceType::Document), { ContentExtensions::ActionType::BlockLoad });
693 testRequest(backend, mainDocumentRequest("http://block_all_types.org", ResourceType::Image), { ContentExtensions::ActionType::BlockLoad });
694 testRequest(backend, mainDocumentRequest("http://block_all_types.org", ResourceType::StyleSheet), { ContentExtensions::ActionType::BlockLoad });
695 testRequest(backend, mainDocumentRequest("http://block_all_types.org", ResourceType::Script), { ContentExtensions::ActionType::BlockLoad });
696 testRequest(backend, mainDocumentRequest("http://block_all_types.org", ResourceType::Font), { ContentExtensions::ActionType::BlockLoad });
697 testRequest(backend, mainDocumentRequest("http://block_all_types.org", ResourceType::Raw), { ContentExtensions::ActionType::BlockLoad });
698 testRequest(backend, mainDocumentRequest("http://block_all_types.org", ResourceType::SVGDocument), { ContentExtensions::ActionType::BlockLoad });
699 testRequest(backend, mainDocumentRequest("http://block_all_types.org", ResourceType::Media), { ContentExtensions::ActionType::BlockLoad });
700 testRequest(backend, mainDocumentRequest("http://block_all_types.org", ResourceType::Popup), { ContentExtensions::ActionType::BlockLoad });
701 testRequest(backend, mainDocumentRequest("http://block_only_images.org", ResourceType::Image), { ContentExtensions::ActionType::BlockLoad });
702 testRequest(backend, mainDocumentRequest("http://block_only_images.org", ResourceType::Document), { });
705 TEST_F(ContentExtensionTest, ResourceAndLoadType)
707 auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"BlockOnlyIfThirdPartyAndScript\",\"resource-type\":[\"script\"],\"load-type\":[\"third-party\"]}}]");
709 testRequest(backend, subResourceRequest("http://webkit.org/BlockOnlyIfThirdPartyAndScript.js", "http://webkit.org", ResourceType::Script), { });
710 testRequest(backend, subResourceRequest("http://webkit.org/BlockOnlyIfThirdPartyAndScript.png", "http://not_webkit.org", ResourceType::Image), { });
711 testRequest(backend, subResourceRequest("http://webkit.org/BlockOnlyIfThirdPartyAndScript.js", "http://not_webkit.org", ResourceType::Script), { ContentExtensions::ActionType::BlockLoad });
714 TEST_F(ContentExtensionTest, ResourceOrLoadTypeMatchingEverything)
716 auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\".*\",\"resource-type\":[\"image\"]}},"
717 "{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\".*\",\"load-type\":[\"third-party\"]}},"
718 "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\".*\",\"load-type\":[\"first-party\"]}}]");
720 testRequest(backend, mainDocumentRequest("http://webkit.org"), { }, true);
721 testRequest(backend, {URL(URL(), "http://webkit.org"), URL(URL(), "http://not_webkit.org"), ResourceType::Document}, { ContentExtensions::ActionType::BlockCookies });
722 testRequest(backend, {URL(URL(), "http://webkit.org"), URL(URL(), "http://not_webkit.org"), ResourceType::Image}, { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::BlockLoad });
725 TEST_F(ContentExtensionTest, WideNFA)
727 // Make an NFA with about 1400 nodes.
728 StringBuilder ruleList;
729 ruleList.append('[');
730 for (char c1 = 'A'; c1 <= 'Z'; ++c1) {
731 for (char c2 = 'A'; c2 <= 'C'; ++c2) {
732 for (char c3 = 'A'; c3 <= 'C'; ++c3) {
733 if (c1 != 'A' || c2 != 'A' || c3 != 'A')
734 ruleList.append(',');
735 ruleList.append("{\"action\":{\"type\":\"");
737 // Put an ignore-previous-rules near the middle.
738 if (c1 == 'L' && c2 == 'A' && c3 == 'A')
739 ruleList.append("ignore-previous-rules");
741 ruleList.append("block");
743 ruleList.append("\"},\"trigger\":{\"url-filter\":\".*");
747 ruleList.append("\", \"url-filter-is-case-sensitive\":true}}");
751 ruleList.append(']');
753 auto backend = makeBackend(ruleList.toString().utf8().data());
755 testRequest(backend, mainDocumentRequest("http://webkit.org/AAA"), { ContentExtensions::ActionType::BlockLoad });
756 testRequest(backend, mainDocumentRequest("http://webkit.org/ZAA"), { ContentExtensions::ActionType::BlockLoad });
757 testRequest(backend, mainDocumentRequest("http://webkit.org/LAA/AAA"), { }, true);
758 testRequest(backend, mainDocumentRequest("http://webkit.org/LAA/MAA"), { ContentExtensions::ActionType::BlockLoad }, true);
759 testRequest(backend, mainDocumentRequest("http://webkit.org/"), { });
762 TEST_F(ContentExtensionTest, DeepNFA)
764 const unsigned size = 100000;
766 ContentExtensions::CombinedURLFilters combinedURLFilters;
767 ContentExtensions::URLFilterParser parser(combinedURLFilters);
769 // FIXME: DFAToNFA::convert takes way too long on these deep NFAs. We should optimize for that case.
771 StringBuilder lotsOfAs;
772 for (unsigned i = 0; i < size; ++i)
773 lotsOfAs.append('A');
774 EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern(lotsOfAs.toString().utf8().data(), false, 0));
776 // FIXME: Yarr ought to be able to handle 2MB regular expressions.
777 StringBuilder tooManyAs;
778 for (unsigned i = 0; i < size * 20; ++i)
779 tooManyAs.append('A');
780 EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::YarrError, parser.addPattern(tooManyAs.toString().utf8().data(), false, 0));
782 StringBuilder nestedGroups;
783 for (unsigned i = 0; i < size; ++i)
784 nestedGroups.append('(');
785 for (unsigned i = 0; i < size; ++i)
786 nestedGroups.append("B)");
787 // FIXME: Add nestedGroups. Right now it also takes too long. It should be optimized.
789 // This should not crash and not timeout.
790 EXPECT_EQ(1ul, createNFAs(combinedURLFilters).size());
793 void checkCompilerError(const char* json, std::error_code expectedError)
795 CompiledContentExtensionData extensionData;
796 InMemoryContentExtensionCompilationClient client(extensionData);
797 std::error_code compilerError = ContentExtensions::compileRuleList(client, json);
798 EXPECT_EQ(compilerError.value(), expectedError.value());
799 if (compilerError.value())
800 EXPECT_STREQ(compilerError.category().name(), expectedError.category().name());
803 TEST_F(ContentExtensionTest, MatchesEverything)
805 // Only css-display-none rules with triggers that match everything, no domain rules, and no flags
806 // should go in the global display:none stylesheet. css-display-none rules with domain rules or flags
807 // are applied separately on pages where they apply.
808 auto backend1 = makeBackend("[{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\".*\"}}]");
809 EXPECT_TRUE(nullptr != backend1.globalDisplayNoneStyleSheet(ASCIILiteral("testFilter")));
810 testRequest(backend1, mainDocumentRequest("http://webkit.org"), { }); // Selector is in global stylesheet.
812 auto backend2 = makeBackend("[{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\".*\",\"if-domain\":[\"webkit.org\"]}}]");
813 EXPECT_EQ(nullptr, backend2.globalDisplayNoneStyleSheet(ASCIILiteral("testFilter")));
814 testRequest(backend2, mainDocumentRequest("http://webkit.org"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
815 testRequest(backend2, mainDocumentRequest("http://w3c.org"), { });
817 auto backend3 = makeBackend("[{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\".*\",\"unless-domain\":[\"webkit.org\"]}}]");
818 EXPECT_EQ(nullptr, backend3.globalDisplayNoneStyleSheet(ASCIILiteral("testFilter")));
819 testRequest(backend3, mainDocumentRequest("http://webkit.org"), { });
820 testRequest(backend3, mainDocumentRequest("http://w3c.org"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
822 auto backend4 = makeBackend("[{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\".*\",\"load-type\":[\"third-party\"]}}]");
823 EXPECT_EQ(nullptr, backend4.globalDisplayNoneStyleSheet(ASCIILiteral("testFilter")));
824 testRequest(backend4, mainDocumentRequest("http://webkit.org"), { });
825 testRequest(backend4, subResourceRequest("http://not_webkit.org", "http://webkit.org"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
827 // css-display-none rules after ignore-previous-rules should not be put in the default stylesheet.
828 auto backend5 = makeBackend("[{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\".*\"}},"
829 "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\".*\"}}]");
830 EXPECT_EQ(nullptr, backend5.globalDisplayNoneStyleSheet(ASCIILiteral("testFilter")));
831 testRequest(backend5, mainDocumentRequest("http://webkit.org"), { ContentExtensions::ActionType::CSSDisplayNoneSelector }, true);
834 TEST_F(ContentExtensionTest, InvalidJSON)
836 checkCompilerError("[", ContentExtensions::ContentExtensionError::JSONInvalid);
837 checkCompilerError("123", ContentExtensions::ContentExtensionError::JSONTopLevelStructureNotAnObject);
838 checkCompilerError("{}", ContentExtensions::ContentExtensionError::JSONTopLevelStructureNotAnArray);
839 // FIXME: Add unit test for JSONInvalidRule if that is possible to hit.
840 checkCompilerError("[]", ContentExtensions::ContentExtensionError::JSONContainsNoRules);
842 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":5}]",
843 ContentExtensions::ContentExtensionError::JSONInvalidTrigger);
844 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"\"}}]",
845 ContentExtensions::ContentExtensionError::JSONInvalidURLFilterInTrigger);
846 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":{}}}]",
847 ContentExtensions::ContentExtensionError::JSONInvalidURLFilterInTrigger);
849 // FIXME: Add unit test for JSONInvalidObjectInTriggerFlagsArray if that is possible to hit.
850 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"load-type\":{}}}]",
851 ContentExtensions::ContentExtensionError::JSONInvalidTriggerFlagsArray);
852 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"load-type\":[\"invalid\"]}}]",
853 ContentExtensions::ContentExtensionError::JSONInvalidStringInTriggerFlagsArray);
854 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"load-type\":[5]}}]",
855 ContentExtensions::ContentExtensionError::JSONInvalidStringInTriggerFlagsArray);
856 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"load-type\":5}}]",
857 ContentExtensions::ContentExtensionError::JSONInvalidTriggerFlagsArray);
858 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"load-type\":\"first-party\"}}]",
859 ContentExtensions::ContentExtensionError::JSONInvalidTriggerFlagsArray);
860 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"load-type\":null}}]",
861 ContentExtensions::ContentExtensionError::JSONInvalidTriggerFlagsArray);
862 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"load-type\":false}}]",
863 ContentExtensions::ContentExtensionError::JSONInvalidTriggerFlagsArray);
864 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"resource-type\":{}}}]",
865 ContentExtensions::ContentExtensionError::JSONInvalidTriggerFlagsArray);
866 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"resource-type\":[\"invalid\"]}}]",
867 ContentExtensions::ContentExtensionError::JSONInvalidStringInTriggerFlagsArray);
868 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"resource-type\":[5]}}]",
869 ContentExtensions::ContentExtensionError::JSONInvalidStringInTriggerFlagsArray);
870 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"resource-type\":5}}]",
871 ContentExtensions::ContentExtensionError::JSONInvalidTriggerFlagsArray);
872 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"resource-type\":\"document\"}}]",
873 ContentExtensions::ContentExtensionError::JSONInvalidTriggerFlagsArray);
874 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"resource-type\":null}}]",
875 ContentExtensions::ContentExtensionError::JSONInvalidTriggerFlagsArray);
876 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"resource-type\":false}}]",
877 ContentExtensions::ContentExtensionError::JSONInvalidTriggerFlagsArray);
881 for (unsigned i = 0; i < 49999; ++i)
882 rules.append("{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"a\"}},");
883 String rules50000 = rules.toString();
884 String rules50001 = rules.toString();
885 rules50000.append("{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"a\"}}]");
886 rules50001.append("{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"a\"}},{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"a\"}}]");
887 checkCompilerError(rules50000.utf8().data(), { });
888 checkCompilerError(rules50001.utf8().data(), ContentExtensions::ContentExtensionError::JSONTooManyRules);
890 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":{}}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
891 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":[5]}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
892 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":[\"a\"]}}]", { });
893 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":\"a\"}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
894 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":false}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
895 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":null}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
896 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":{}}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
897 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":[5]}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
898 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":[\"\"]}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
899 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":\"a\"}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
900 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":null}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
901 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":false}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
902 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":[\"A\"]}}]", ContentExtensions::ContentExtensionError::JSONDomainNotLowerCaseASCII);
903 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":[\"\\u00DC\"]}}]", ContentExtensions::ContentExtensionError::JSONDomainNotLowerCaseASCII);
904 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":[\"0\"]}}]", { });
905 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":[\"a\"]}}]", { });
907 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":[],\"unless-domain\":[\"a\"]}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
908 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":[]}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
909 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":5}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
910 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":5}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
911 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":5,\"unless-domain\":5}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
912 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":[]}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
914 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":[\"a\"],\"unless-domain\":[]}}]", ContentExtensions::ContentExtensionError::JSONUnlessAndIfDomain);
915 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":[\"a\"],\"unless-domain\":[\"a\"]}}]", ContentExtensions::ContentExtensionError::JSONUnlessAndIfDomain);
917 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\", \"unexpected-identifier-should-be-ignored\":5}}]", { });
919 checkCompilerError("[{\"action\":5,\"trigger\":{\"url-filter\":\"webkit.org\"}}]",
920 ContentExtensions::ContentExtensionError::JSONInvalidAction);
921 checkCompilerError("[{\"action\":{\"type\":\"invalid\"},\"trigger\":{\"url-filter\":\"webkit.org\"}}]",
922 ContentExtensions::ContentExtensionError::JSONInvalidActionType);
923 checkCompilerError("[{\"action\":{\"type\":\"css-display-none\"},\"trigger\":{\"url-filter\":\"webkit.org\"}}]",
924 ContentExtensions::ContentExtensionError::JSONInvalidCSSDisplayNoneActionType);
926 checkCompilerError("[{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"webkit.org\"}},"
927 "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\".*\"}}]", { });
928 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\".*\",\"if-domain\":[\"a\"]}}]", { });
929 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\".*\",\"unless-domain\":[\"a\"]}}]", { });
930 checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[\"}}]",
931 ContentExtensions::ContentExtensionError::JSONInvalidRegex);
934 TEST_F(ContentExtensionTest, StrictPrefixSeparatedMachines1)
936 auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^.*foo\"}},"
937 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"bar$\"}},"
938 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[ab]+bang\"}}]");
940 testRequest(backend, mainDocumentRequest("http://webkit.org/foo"), { ContentExtensions::ActionType::BlockLoad });
941 testRequest(backend, mainDocumentRequest("foo://webkit.org/bar"), { ContentExtensions::ActionType::BlockLoad });
942 testRequest(backend, mainDocumentRequest("http://webkit.org/bar"), { ContentExtensions::ActionType::BlockLoad });
943 testRequest(backend, mainDocumentRequest("bar://webkit.org/bar"), { ContentExtensions::ActionType::BlockLoad });
945 testRequest(backend, mainDocumentRequest("abang://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
946 testRequest(backend, mainDocumentRequest("bbang://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
947 testRequest(backend, mainDocumentRequest("cbang://webkit.org/"), { });
948 testRequest(backend, mainDocumentRequest("http://webkit.org/bang"), { });
949 testRequest(backend, mainDocumentRequest("bang://webkit.org/"), { });
952 TEST_F(ContentExtensionTest, StrictPrefixSeparatedMachines1Partitioning)
954 ContentExtensions::CombinedURLFilters combinedURLFilters;
955 ContentExtensions::URLFilterParser parser(combinedURLFilters);
957 // Those two share a prefix.
958 EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("^.*foo", false, 0));
959 EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("bar$", false, 1));
962 EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("^[ab]+bang", false, 0));
964 EXPECT_EQ(2ul, createNFAs(combinedURLFilters).size());
967 TEST_F(ContentExtensionTest, StrictPrefixSeparatedMachines2)
969 auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^foo\"}},"
970 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^.*[a-c]+bar\"}},"
971 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^webkit:\"}},"
972 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[a-c]+b+oom\"}}]");
974 testRequest(backend, mainDocumentRequest("http://webkit.org/"), { });
975 testRequest(backend, mainDocumentRequest("foo://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
976 testRequest(backend, mainDocumentRequest("webkit://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
978 testRequest(backend, mainDocumentRequest("http://bar.org/"), { });
979 testRequest(backend, mainDocumentRequest("http://abar.org/"), { ContentExtensions::ActionType::BlockLoad });
980 testRequest(backend, mainDocumentRequest("http://bbar.org/"), { ContentExtensions::ActionType::BlockLoad });
981 testRequest(backend, mainDocumentRequest("http://cbar.org/"), { ContentExtensions::ActionType::BlockLoad });
982 testRequest(backend, mainDocumentRequest("http://abcbar.org/"), { ContentExtensions::ActionType::BlockLoad });
983 testRequest(backend, mainDocumentRequest("http://dbar.org/"), { });
986 TEST_F(ContentExtensionTest, StrictPrefixSeparatedMachines2Partitioning)
988 ContentExtensions::CombinedURLFilters combinedURLFilters;
989 ContentExtensions::URLFilterParser parser(combinedURLFilters);
991 EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("^foo", false, 0));
992 EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("^.*[a-c]+bar", false, 1));
993 EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("^webkit:", false, 2));
994 EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("[a-c]+b+oom", false, 3));
996 // "^foo" and "^webkit:" can be grouped, the other two have a variable prefix.
997 EXPECT_EQ(3ul, createNFAs(combinedURLFilters).size());
1000 TEST_F(ContentExtensionTest, StrictPrefixSeparatedMachines3)
1002 auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"A*D\"}},"
1003 "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"A*BA+\"}},"
1004 "{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"A*BC\"}}]");
1006 testRequest(backend, mainDocumentRequest("http://webkit.org/D"), { ContentExtensions::ActionType::BlockLoad });
1007 testRequest(backend, mainDocumentRequest("http://webkit.org/AAD"), { ContentExtensions::ActionType::BlockLoad });
1008 testRequest(backend, mainDocumentRequest("http://webkit.org/AB"), { });
1009 testRequest(backend, mainDocumentRequest("http://webkit.org/ABA"), { }, true);
1010 testRequest(backend, mainDocumentRequest("http://webkit.org/ABAD"), { }, true);
1011 testRequest(backend, mainDocumentRequest("http://webkit.org/BC"), { ContentExtensions::ActionType::BlockCookies });
1012 testRequest(backend, mainDocumentRequest("http://webkit.org/ABC"), { ContentExtensions::ActionType::BlockCookies });
1013 testRequest(backend, mainDocumentRequest("http://webkit.org/ABABC"), { ContentExtensions::ActionType::BlockCookies }, true);
1014 testRequest(backend, mainDocumentRequest("http://webkit.org/ABABCAD"), { ContentExtensions::ActionType::BlockCookies }, true);
1015 testRequest(backend, mainDocumentRequest("http://webkit.org/ABCAD"), { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::BlockLoad });
1018 TEST_F(ContentExtensionTest, StrictPrefixSeparatedMachines3Partitioning)
1020 ContentExtensions::CombinedURLFilters combinedURLFilters;
1021 ContentExtensions::URLFilterParser parser(combinedURLFilters);
1023 EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("A*D", false, 0));
1024 EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("A*BA+", false, 1));
1025 EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("A*BC", false, 2));
1027 // "A*A" and "A*BC" can be grouped, "A*BA+" should not.
1028 EXPECT_EQ(2ul, createNFAs(combinedURLFilters).size());
1031 TEST_F(ContentExtensionTest, SplittingLargeNFAs)
1033 const size_t expectedNFACounts[16] = {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1, 1};
1035 for (size_t i = 0; i < 16; i++) {
1036 ContentExtensions::CombinedURLFilters combinedURLFilters;
1037 ContentExtensions::URLFilterParser parser(combinedURLFilters);
1039 EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("A+BBB", false, 1));
1040 EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("A+CCC", false, 2));
1041 EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("A+DDD", false, 2));
1043 Vector<ContentExtensions::NFA> nfas;
1044 combinedURLFilters.processNFAs(i, [&](ContentExtensions::NFA&& nfa) {
1045 nfas.append(WTF::move(nfa));
1047 EXPECT_EQ(nfas.size(), expectedNFACounts[i]);
1049 Vector<ContentExtensions::DFA> dfas;
1050 for (auto& nfa : nfas)
1051 dfas.append(ContentExtensions::NFAToDFA::convert(nfa));
1053 Vector<ContentExtensions::DFABytecode> combinedBytecode;
1054 for (const auto& dfa : dfas) {
1055 Vector<ContentExtensions::DFABytecode> bytecode;
1056 ContentExtensions::DFABytecodeCompiler compiler(dfa, bytecode);
1058 combinedBytecode.appendVector(bytecode);
1061 Vector<bool> pagesUsed;
1062 ContentExtensions::DFABytecodeInterpreter interpreter(&combinedBytecode[0], combinedBytecode.size(), pagesUsed);
1064 EXPECT_EQ(interpreter.interpret("ABBBX", 0).size(), 1ull);
1065 EXPECT_EQ(interpreter.interpret("ACCCX", 0).size(), 1ull);
1066 EXPECT_EQ(interpreter.interpret("ADDDX", 0).size(), 1ull);
1067 EXPECT_EQ(interpreter.interpret("XBBBX", 0).size(), 0ull);
1068 EXPECT_EQ(interpreter.interpret("ABBX", 0).size(), 0ull);
1069 EXPECT_EQ(interpreter.interpret("ACCX", 0).size(), 0ull);
1070 EXPECT_EQ(interpreter.interpret("ADDX", 0).size(), 0ull);
1074 TEST_F(ContentExtensionTest, QuantifierInGroup)
1076 ContentExtensions::CombinedURLFilters combinedURLFilters;
1077 ContentExtensions::URLFilterParser parser(combinedURLFilters);
1079 EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("(((A+)B)C)", false, 0));
1080 EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("(((A)B+)C)", false, 1));
1081 EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("(((A)B+)C)D", false, 2));
1082 EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("(((A)B)C+)", false, 3));
1083 EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("(((A)B)C)", false, 4));
1085 // (((A)B+)C) and (((A)B+)C)D should be in the same NFA.
1086 EXPECT_EQ(4ul, createNFAs(combinedURLFilters).size());
1089 static void testPatternStatus(String pattern, ContentExtensions::URLFilterParser::ParseStatus status)
1091 ContentExtensions::CombinedURLFilters combinedURLFilters;
1092 ContentExtensions::URLFilterParser parser(combinedURLFilters);
1093 EXPECT_EQ(status, parser.addPattern(pattern, false, 0));
1096 TEST_F(ContentExtensionTest, ParsingFailures)
1098 testPatternStatus("a*b?.*.?[a-z]?[a-z]*", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1099 testPatternStatus("a*b?.*.?[a-z]?[a-z]+", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1100 testPatternStatus("a*b?.*.?[a-z]?[a-z]", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1101 testPatternStatus(".*?a", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1102 testPatternStatus(".*a", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1104 testPatternStatus("(?!)", ContentExtensions::URLFilterParser::ParseStatus::Group);
1105 testPatternStatus("(?=)", ContentExtensions::URLFilterParser::ParseStatus::Group);
1106 testPatternStatus("(?!a)", ContentExtensions::URLFilterParser::ParseStatus::Group);
1107 testPatternStatus("(?=a)", ContentExtensions::URLFilterParser::ParseStatus::Group);
1108 testPatternStatus("(regex)", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1109 testPatternStatus("(regex", ContentExtensions::URLFilterParser::ParseStatus::YarrError);
1110 testPatternStatus("((regex)", ContentExtensions::URLFilterParser::ParseStatus::YarrError);
1111 testPatternStatus("(?:regex)", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1112 testPatternStatus("(?:regex", ContentExtensions::URLFilterParser::ParseStatus::YarrError);
1113 testPatternStatus("[^.]+", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1115 testPatternStatus("a++", ContentExtensions::URLFilterParser::ParseStatus::YarrError);
1116 testPatternStatus("[a]++", ContentExtensions::URLFilterParser::ParseStatus::YarrError);
1117 testPatternStatus("+", ContentExtensions::URLFilterParser::ParseStatus::YarrError);
1119 testPatternStatus("[", ContentExtensions::URLFilterParser::ParseStatus::YarrError);
1120 testPatternStatus("[a}", ContentExtensions::URLFilterParser::ParseStatus::YarrError);
1122 // FIXME: Look into why these do not cause YARR parsing errors. They probably should.
1123 testPatternStatus("a]", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1124 testPatternStatus("{", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1125 testPatternStatus("{[a]", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1126 testPatternStatus("{0", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1127 testPatternStatus("{0,", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1128 testPatternStatus("{0,1", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1129 testPatternStatus("a{0,1", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1130 testPatternStatus("a{a,b}", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1132 const char nonASCII[2] = {-1, '\0'};
1133 testPatternStatus(nonASCII, ContentExtensions::URLFilterParser::ParseStatus::NonASCII);
1134 testPatternStatus("\\xff", ContentExtensions::URLFilterParser::ParseStatus::NonASCII);
1136 testPatternStatus("\\x\\r\\n", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1137 testPatternStatus("\\b", ContentExtensions::URLFilterParser::ParseStatus::WordBoundary);
1138 testPatternStatus("[\\d]", ContentExtensions::URLFilterParser::ParseStatus::AtomCharacter);
1139 testPatternStatus("\\d\\D\\w\\s\\v\\h\\i\\c", ContentExtensions::URLFilterParser::ParseStatus::UnsupportedCharacterClass);
1141 testPatternStatus("this|that", ContentExtensions::URLFilterParser::ParseStatus::Disjunction);
1142 testPatternStatus("a{0,1}b", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1143 testPatternStatus("a{0,2}b", ContentExtensions::URLFilterParser::ParseStatus::InvalidQuantifier);
1144 testPatternStatus("", ContentExtensions::URLFilterParser::ParseStatus::EmptyPattern);
1145 testPatternStatus("$$", ContentExtensions::URLFilterParser::ParseStatus::MisplacedEndOfLine);
1146 testPatternStatus("a^", ContentExtensions::URLFilterParser::ParseStatus::MisplacedStartOfLine);
1147 testPatternStatus("(^)", ContentExtensions::URLFilterParser::ParseStatus::MisplacedStartOfLine);
1149 testPatternStatus("(a)\\1", ContentExtensions::URLFilterParser::ParseStatus::Ok); // This should be BackReference, right?
1152 TEST_F(ContentExtensionTest, PatternMatchingTheEmptyString)
1155 testPatternStatus(".*", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1156 testPatternStatus("a*", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1157 testPatternStatus(".?", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1158 testPatternStatus("a?", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1161 testPatternStatus("[a-z]*", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1162 testPatternStatus("[a-z]?", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1165 testPatternStatus("(foobar)*", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1166 testPatternStatus("(foobar)?", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1167 testPatternStatus("(.*)", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1168 testPatternStatus("(a*)", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1169 testPatternStatus("(.?)", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1170 testPatternStatus("(a?)", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1171 testPatternStatus("([a-z]*)", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1172 testPatternStatus("([a-z]?)", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1174 testPatternStatus("(.)*", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1175 testPatternStatus("(.+)*", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1176 testPatternStatus("(.?)*", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1177 testPatternStatus("(.*)*", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1178 testPatternStatus("(.+)?", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1179 testPatternStatus("(.?)+", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1182 testPatternStatus("((foo)?((.)*)(bar)*)", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1185 TEST_F(ContentExtensionTest, MinimizingWithMoreFinalStatesThanNonFinalStates)
1187 auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^h[a-z://]+\"}},"
1188 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^http://foo.com/\"}},"
1189 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^http://bar.com/\"}}]");
1191 testRequest(backend, mainDocumentRequest("http://foo.com/"), { ContentExtensions::ActionType::BlockLoad });
1192 testRequest(backend, mainDocumentRequest("http://bar.com/"), { ContentExtensions::ActionType::BlockLoad });
1193 testRequest(backend, mainDocumentRequest("attp://foo.com/"), { });
1194 testRequest(backend, mainDocumentRequest("attp://bar.com/"), { });
1196 testRequest(backend, mainDocumentRequest("http://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1197 testRequest(backend, mainDocumentRequest("https://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1198 testRequest(backend, mainDocumentRequest("bttp://webkit.org/"), { });
1199 testRequest(backend, mainDocumentRequest("bttps://webkit.org/"), { });
1200 testRequest(backend, mainDocumentRequest("http://webkit.org/b"), { ContentExtensions::ActionType::BlockLoad });
1201 testRequest(backend, mainDocumentRequest("https://webkit.org/b"), { ContentExtensions::ActionType::BlockLoad });
1202 testRequest(backend, mainDocumentRequest("cttp://webkit.org/B"), { });
1203 testRequest(backend, mainDocumentRequest("cttps://webkit.org/B"), { });
1206 TEST_F(ContentExtensionTest, StatesWithDifferentActionsAreNotUnified1)
1208 auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^http://www.webkit.org/\"}},"
1209 "{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"^https://www.webkit.org/\"}},"
1210 "{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"^attps://www.webkit.org/\"}}]");
1212 testRequest(backend, mainDocumentRequest("http://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1213 testRequest(backend, mainDocumentRequest("https://www.webkit.org/"), { ContentExtensions::ActionType::BlockCookies });
1214 testRequest(backend, mainDocumentRequest("attps://www.webkit.org/"), { ContentExtensions::ActionType::BlockCookies });
1215 testRequest(backend, mainDocumentRequest("http://www.webkit.org/a"), { ContentExtensions::ActionType::BlockLoad });
1216 testRequest(backend, mainDocumentRequest("https://www.webkit.org/B"), { ContentExtensions::ActionType::BlockCookies });
1217 testRequest(backend, mainDocumentRequest("attps://www.webkit.org/c"), { ContentExtensions::ActionType::BlockCookies });
1218 testRequest(backend, mainDocumentRequest("http://www.whatwg.org/"), { });
1219 testRequest(backend, mainDocumentRequest("https://www.whatwg.org/"), { });
1220 testRequest(backend, mainDocumentRequest("attps://www.whatwg.org/"), { });
1223 TEST_F(ContentExtensionTest, StatesWithDifferentActionsAreNotUnified2)
1225 auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^http://www.webkit.org/\"}},"
1226 "{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"^https://www.webkit.org/\"}},"
1227 "{\"action\":{\"type\":\"css-display-none\", \"selector\":\"#foo\"},\"trigger\":{\"url-filter\":\"^https://www.webkit.org/\"}}]");
1229 testRequest(backend, mainDocumentRequest("http://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1230 testRequest(backend, mainDocumentRequest("https://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockCookies });
1231 testRequest(backend, mainDocumentRequest("https://www.whatwg.org/"), { });
1232 testRequest(backend, mainDocumentRequest("attps://www.whatwg.org/"), { });
1235 // The order in which transitions from the root will be processed is unpredictable.
1236 // To exercises the various options, this test exists in various version exchanging the transition to the final state.
1237 TEST_F(ContentExtensionTest, FallbackTransitionsWithDifferentiatorDoNotMerge1)
1239 auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^a.a\"}},"
1240 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^b.a\"}},"
1241 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^bac\"}},"
1242 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^bbc\"}},"
1243 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^BCC\"}}]");
1245 testRequest(backend, mainDocumentRequest("aza://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1246 testRequest(backend, mainDocumentRequest("bza://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1247 testRequest(backend, mainDocumentRequest("bac://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1248 testRequest(backend, mainDocumentRequest("bbc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1249 testRequest(backend, mainDocumentRequest("bcc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1251 testRequest(backend, mainDocumentRequest("aac://www.webkit.org/"), { });
1252 testRequest(backend, mainDocumentRequest("abc://www.webkit.org/"), { });
1253 testRequest(backend, mainDocumentRequest("acc://www.webkit.org/"), { });
1255 testRequest(backend, mainDocumentRequest("bzc://www.webkit.org/"), { });
1256 testRequest(backend, mainDocumentRequest("bzc://www.webkit.org/"), { });
1257 testRequest(backend, mainDocumentRequest("bzc://www.webkit.org/"), { });
1259 TEST_F(ContentExtensionTest, FallbackTransitionsWithDifferentiatorDoNotMerge2)
1261 auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^bac\"}},"
1262 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^bbc\"}},"
1263 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^BCC\"}},"
1264 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^a.a\"}},"
1265 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^b.a\"}}]");
1267 testRequest(backend, mainDocumentRequest("aza://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1268 testRequest(backend, mainDocumentRequest("bza://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1269 testRequest(backend, mainDocumentRequest("bac://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1270 testRequest(backend, mainDocumentRequest("bbc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1271 testRequest(backend, mainDocumentRequest("bcc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1273 testRequest(backend, mainDocumentRequest("aac://www.webkit.org/"), { });
1274 testRequest(backend, mainDocumentRequest("abc://www.webkit.org/"), { });
1275 testRequest(backend, mainDocumentRequest("acc://www.webkit.org/"), { });
1277 testRequest(backend, mainDocumentRequest("bzc://www.webkit.org/"), { });
1278 testRequest(backend, mainDocumentRequest("bzc://www.webkit.org/"), { });
1279 testRequest(backend, mainDocumentRequest("bzc://www.webkit.org/"), { });
1281 TEST_F(ContentExtensionTest, FallbackTransitionsWithDifferentiatorDoNotMerge3)
1283 auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^a.c\"}},"
1284 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^b.c\"}},"
1285 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^baa\"}},"
1286 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^bba\"}},"
1287 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^BCA\"}}]");
1289 testRequest(backend, mainDocumentRequest("azc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1290 testRequest(backend, mainDocumentRequest("bzc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1291 testRequest(backend, mainDocumentRequest("baa://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1292 testRequest(backend, mainDocumentRequest("bba://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1293 testRequest(backend, mainDocumentRequest("bca://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1295 testRequest(backend, mainDocumentRequest("aaa://www.webkit.org/"), { });
1296 testRequest(backend, mainDocumentRequest("aba://www.webkit.org/"), { });
1297 testRequest(backend, mainDocumentRequest("aca://www.webkit.org/"), { });
1299 testRequest(backend, mainDocumentRequest("bza://www.webkit.org/"), { });
1300 testRequest(backend, mainDocumentRequest("bza://www.webkit.org/"), { });
1301 testRequest(backend, mainDocumentRequest("bza://www.webkit.org/"), { });
1303 TEST_F(ContentExtensionTest, FallbackTransitionsWithDifferentiatorDoNotMerge4)
1305 auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^baa\"}},"
1306 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^bba\"}},"
1307 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^BCA\"}},"
1308 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^a.c\"}},"
1309 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^b.c\"}}]");
1311 testRequest(backend, mainDocumentRequest("azc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1312 testRequest(backend, mainDocumentRequest("bzc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1313 testRequest(backend, mainDocumentRequest("baa://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1314 testRequest(backend, mainDocumentRequest("bba://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1315 testRequest(backend, mainDocumentRequest("bca://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1317 testRequest(backend, mainDocumentRequest("aaa://www.webkit.org/"), { });
1318 testRequest(backend, mainDocumentRequest("aba://www.webkit.org/"), { });
1319 testRequest(backend, mainDocumentRequest("aca://www.webkit.org/"), { });
1321 testRequest(backend, mainDocumentRequest("bza://www.webkit.org/"), { });
1322 testRequest(backend, mainDocumentRequest("bza://www.webkit.org/"), { });
1323 testRequest(backend, mainDocumentRequest("bza://www.webkit.org/"), { });
1326 TEST_F(ContentExtensionTest, FallbackTransitionsToOtherNodeInSameGroupDoesNotDifferentiateGroup)
1328 auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^aac\"}},"
1329 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^a.c\"}},"
1330 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^b.c\"}}]");
1332 testRequest(backend, mainDocumentRequest("aac://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1333 testRequest(backend, mainDocumentRequest("abc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1334 testRequest(backend, mainDocumentRequest("bac://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1335 testRequest(backend, mainDocumentRequest("abc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1337 testRequest(backend, mainDocumentRequest("aaa://www.webkit.org/"), { });
1338 testRequest(backend, mainDocumentRequest("aca://www.webkit.org/"), { });
1339 testRequest(backend, mainDocumentRequest("baa://www.webkit.org/"), { });
1342 TEST_F(ContentExtensionTest, SimpleFallBackTransitionDifferentiator1)
1344 auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^a.bc.de\"}},"
1345 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^a.bd.ef\"}}]");
1347 testRequest(backend, mainDocumentRequest("abbccde://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1348 testRequest(backend, mainDocumentRequest("aabcdde://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1349 testRequest(backend, mainDocumentRequest("aabddef://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1350 testRequest(backend, mainDocumentRequest("aabddef://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1352 testRequest(backend, mainDocumentRequest("abcde://www.webkit.org/"), { });
1353 testRequest(backend, mainDocumentRequest("abdef://www.webkit.org/"), { });
1356 TEST_F(ContentExtensionTest, SimpleFallBackTransitionDifferentiator2)
1358 auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^cb.\"}},"
1359 "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^db.b\"}}]");
1361 testRequest(backend, mainDocumentRequest("cba://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1362 testRequest(backend, mainDocumentRequest("cbb://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1363 testRequest(backend, mainDocumentRequest("dbab://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1364 testRequest(backend, mainDocumentRequest("dbxb://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1366 testRequest(backend, mainDocumentRequest("cca://www.webkit.org/"), { });
1367 testRequest(backend, mainDocumentRequest("dddd://www.webkit.org/"), { });
1368 testRequest(backend, mainDocumentRequest("bbbb://www.webkit.org/"), { });
1371 } // namespace TestWebKitAPI