Extend URL filter's Term definition to support groups/subpatterns
[WebKit-https.git] / Tools / TestWebKitAPI / Tests / WebCore / ContentExtensions.cpp
1 /*
2  * Copyright (C) 2015 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
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.
12  *
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.
24  */
25
26 #include "config.h"
27
28 #include "PlatformUtilities.h"
29 #include <JavaScriptCore/InitializeThreading.h>
30 #include <WebCore/ContentExtensionCompiler.h>
31 #include <WebCore/ContentExtensionsBackend.h>
32 #include <WebCore/URL.h>
33 #include <wtf/MainThread.h>
34 #include <wtf/RunLoop.h>
35
36 namespace WebCore {
37 namespace ContentExtensions {
38 inline std::ostream& operator<<(std::ostream& os, const ActionType& action)
39 {
40     switch (action) {
41     case ActionType::BlockLoad:
42         return os << "ContentFilterAction::BlockLoad";
43     case ActionType::BlockCookies:
44         return os << "ContentFilterAction::BlockCookies";
45     case ActionType::CSSDisplayNone:
46         return os << "ContentFilterAction::CSSDisplayNone";
47     case ActionType::IgnorePreviousRules:
48         return os << "ContentFilterAction::IgnorePreviousRules";
49     case ActionType::InvalidAction:
50         return os << "ContentFilterAction::InvalidAction";
51     }
52 }
53 }
54 }
55
56 using namespace WebCore;
57
58 namespace TestWebKitAPI {
59
60 class ContentExtensionTest : public testing::Test {
61 public:
62     virtual void SetUp()
63     {
64         WTF::initializeMainThread();
65         JSC::initializeThreading();
66         RunLoop::initializeMainRunLoop();
67     }
68 };
69
70 class InMemoryCompiledContentExtension : public ContentExtensions::CompiledContentExtension {
71 public:
72     static RefPtr<InMemoryCompiledContentExtension> create(ContentExtensions::CompiledContentExtensionData&& data)
73     {
74         return adoptRef(new InMemoryCompiledContentExtension(WTF::move(data)));
75     }
76
77     virtual ~InMemoryCompiledContentExtension()
78     {
79     }
80
81     virtual const ContentExtensions::DFABytecode* bytecode() const override { return m_data.bytecode.data(); }
82     virtual unsigned bytecodeLength() const override { return m_data.bytecode.size(); }
83     virtual const ContentExtensions::SerializedActionByte* actions() const override { return m_data.actions.data(); }
84     virtual unsigned actionsLength() const override { return m_data.actions.size(); }
85
86 private:
87     InMemoryCompiledContentExtension(ContentExtensions::CompiledContentExtensionData&& data)
88         : m_data(WTF::move(data))
89     {
90     }
91
92     ContentExtensions::CompiledContentExtensionData m_data;
93 };
94
95 void static testURL(ContentExtensions::ContentExtensionsBackend contentExtensionsBackend, const URL& url, Vector<ContentExtensions::ActionType> expectedActions)
96 {
97     auto actions = contentExtensionsBackend.actionsForURL(url);
98     EXPECT_EQ(expectedActions.size(), actions.size());
99     if (expectedActions.size() != actions.size())
100         return;
101
102     for (unsigned i = 0; i < expectedActions.size(); ++i)
103         EXPECT_EQ(expectedActions[i], actions[i].type());
104 }
105
106 const char* basicFilter = "[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\".*webkit.org\"}}]";
107
108 TEST_F(ContentExtensionTest, Basic)
109 {
110     auto extensionData = ContentExtensions::compileRuleList(basicFilter);
111     auto extension = InMemoryCompiledContentExtension::create(WTF::move(extensionData));
112
113     ContentExtensions::ContentExtensionsBackend backend;
114     backend.addContentExtension("testFilter", extension);
115
116     testURL(backend, URL(ParsedURLString, "http://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
117 }
118
119 const char* patternsStartingWithGroupFilter = "[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(http://whatwg\\\\.org/)?webkit\134\134.org\"}}]";
120
121 TEST_F(ContentExtensionTest, PatternStartingWithGroup)
122 {
123     auto extensionData = ContentExtensions::compileRuleList(patternsStartingWithGroupFilter);
124     auto extension = InMemoryCompiledContentExtension::create(WTF::move(extensionData));
125
126     ContentExtensions::ContentExtensionsBackend backend;
127     backend.addContentExtension("PatternNestedGroupsFilter", extension);
128
129     testURL(backend, URL(URL(), "http://whatwg.org/webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
130     testURL(backend, URL(URL(), "http://whatwg.org/webkit.org"), { ContentExtensions::ActionType::BlockLoad });
131     testURL(backend, URL(URL(), "http://webkit.org/"), { });
132     testURL(backend, URL(URL(), "http://whatwg.org/"), { });
133     testURL(backend, URL(URL(), "http://whatwg.org"), { });
134 }
135
136 const char* patternNestedGroupsFilter = "[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"http://webkit\\\\.org/(foo(bar)*)+\"}}]";
137
138 TEST_F(ContentExtensionTest, PatternNestedGroups)
139 {
140     auto extensionData = ContentExtensions::compileRuleList(patternNestedGroupsFilter);
141     auto extension = InMemoryCompiledContentExtension::create(WTF::move(extensionData));
142
143     ContentExtensions::ContentExtensionsBackend backend;
144     backend.addContentExtension("PatternNestedGroupsFilter", extension);
145
146     testURL(backend, URL(URL(), "http://webkit.org/foo"), { ContentExtensions::ActionType::BlockLoad });
147     testURL(backend, URL(URL(), "http://webkit.org/foobar"), { ContentExtensions::ActionType::BlockLoad });
148     testURL(backend, URL(URL(), "http://webkit.org/foobarbar"), { ContentExtensions::ActionType::BlockLoad });
149     testURL(backend, URL(URL(), "http://webkit.org/foofoobar"), { ContentExtensions::ActionType::BlockLoad });
150     testURL(backend, URL(URL(), "http://webkit.org/foobarfoobar"), { ContentExtensions::ActionType::BlockLoad });
151     testURL(backend, URL(URL(), "http://webkit.org/foob"), { ContentExtensions::ActionType::BlockLoad });
152     testURL(backend, URL(URL(), "http://webkit.org/foor"), { ContentExtensions::ActionType::BlockLoad });
153
154
155     testURL(backend, URL(URL(), "http://webkit.org/"), { });
156     testURL(backend, URL(URL(), "http://webkit.org/bar"), { });
157     testURL(backend, URL(URL(), "http://webkit.org/fobar"), { });
158 }
159
160 } // namespace TestWebKitAPI