7d5c2d390e6b12ffdfb0f4e3906d72ad6dc23c68
[WebKit-https.git] / Source / WebCore / platform / ContentFilter.cpp
1 /*
2  * Copyright (C) 2013 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 #include "ContentFilter.h"
28
29 #if ENABLE(CONTENT_FILTERING)
30
31 #include "NetworkExtensionContentFilter.h"
32 #include "ParentalControlsContentFilter.h"
33 #include <wtf/NeverDestroyed.h>
34 #include <wtf/Vector.h>
35
36 namespace WebCore {
37
38 Vector<ContentFilter::Type>& ContentFilter::types()
39 {
40     static NeverDestroyed<Vector<ContentFilter::Type>> types {
41         Vector<ContentFilter::Type> {
42             type<ParentalControlsContentFilter>(),
43 #if HAVE(NETWORK_EXTENSION)
44             type<NetworkExtensionContentFilter>()
45 #endif
46         }
47     };
48     return types;
49 }
50
51 class ContentFilterCollection final : public ContentFilter {
52 public:
53     using Container = Vector<std::unique_ptr<ContentFilter>>;
54
55     explicit ContentFilterCollection(Container);
56
57     void addData(const char* data, int length) override;
58     void finishedAddingData() override;
59     bool needsMoreData() const override;
60     bool didBlockData() const override;
61     const char* getReplacementData(int& length) const override;
62     ContentFilterUnblockHandler unblockHandler() const override;
63
64 private:
65     Container m_contentFilters;
66 };
67
68 std::unique_ptr<ContentFilter> ContentFilter::createIfNeeded(const ResourceResponse& response)
69 {
70     ContentFilterCollection::Container filters;
71     for (auto& type : types()) {
72         if (type.canHandleResponse(response))
73             filters.append(type.create(response));
74     }
75
76     if (filters.isEmpty())
77         return nullptr;
78
79     return std::make_unique<ContentFilterCollection>(WTF::move(filters));
80 }
81
82 ContentFilterCollection::ContentFilterCollection(Container contentFilters)
83     : m_contentFilters { WTF::move(contentFilters) }
84 {
85     ASSERT(!m_contentFilters.isEmpty());
86 }
87
88 void ContentFilterCollection::addData(const char* data, int length)
89 {
90     ASSERT(needsMoreData());
91
92     for (auto& contentFilter : m_contentFilters)
93         contentFilter->addData(data, length);
94 }
95     
96 void ContentFilterCollection::finishedAddingData()
97 {
98     ASSERT(needsMoreData());
99
100     for (auto& contentFilter : m_contentFilters)
101         contentFilter->finishedAddingData();
102
103     ASSERT(!needsMoreData());
104 }
105
106 bool ContentFilterCollection::needsMoreData() const
107 {
108     for (auto& contentFilter : m_contentFilters) {
109         if (contentFilter->needsMoreData())
110             return true;
111     }
112
113     return false;
114 }
115
116 bool ContentFilterCollection::didBlockData() const
117 {
118     for (auto& contentFilter : m_contentFilters) {
119         if (contentFilter->didBlockData())
120             return true;
121     }
122
123     return false;
124 }
125
126 const char* ContentFilterCollection::getReplacementData(int& length) const
127 {
128     ASSERT(!needsMoreData());
129
130     for (auto& contentFilter : m_contentFilters) {
131         if (contentFilter->didBlockData())
132             return contentFilter->getReplacementData(length);
133     }
134
135     return m_contentFilters[0]->getReplacementData(length);
136 }
137
138 ContentFilterUnblockHandler ContentFilterCollection::unblockHandler() const
139 {
140     ASSERT(didBlockData());
141
142     for (auto& contentFilter : m_contentFilters) {
143         if (contentFilter->didBlockData())
144             return contentFilter->unblockHandler();
145     }
146
147     ASSERT_NOT_REACHED();
148     return { };
149 }
150
151 } // namespace WebCore
152
153 #endif // ENABLE(CONTENT_FILTERING)