[Content Extensions] Split parsing and compiling of content extensions into their...
[WebKit-https.git] / Source / WebCore / contentextensions / ContentExtensionsBackend.cpp
1 /*
2  * Copyright (C) 2014 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 "ContentExtensionsBackend.h"
28
29 #if ENABLE(CONTENT_EXTENSIONS)
30
31 #include "CompiledContentExtension.h"
32 #include "DFABytecodeInterpreter.h"
33 #include "URL.h"
34 #include <wtf/text/CString.h>
35
36 namespace WebCore {
37
38 namespace ContentExtensions {
39     
40 void ContentExtensionsBackend::addContentExtension(const String& identifier, RefPtr<CompiledContentExtension> compiledContentExtension)
41 {
42     ASSERT(!identifier.isEmpty());
43     if (identifier.isEmpty())
44         return;
45
46     if (!compiledContentExtension) {
47         removeContentExtension(identifier);
48         return;
49     }
50
51     m_contentExtensions.set(identifier, compiledContentExtension);
52 }
53
54 void ContentExtensionsBackend::removeContentExtension(const String& identifier)
55 {
56     m_contentExtensions.remove(identifier);
57 }
58
59 void ContentExtensionsBackend::removeAllContentExtensions()
60 {
61     m_contentExtensions.clear();
62 }
63
64 Vector<Action> ContentExtensionsBackend::actionsForURL(const URL& url)
65 {
66     const String& urlString = url.string();
67     ASSERT_WITH_MESSAGE(urlString.containsOnlyASCII(), "A decoded URL should only contain ASCII characters. The matching algorithm assumes the input is ASCII.");
68     const CString& urlCString = urlString.utf8();
69
70     Vector<Action> actions;
71     for (auto& compiledContentExtension : m_contentExtensions.values()) {
72         DFABytecodeInterpreter interpreter(compiledContentExtension->bytecode());
73         DFABytecodeInterpreter::Actions triggeredActions = interpreter.interpret(urlCString);
74         
75         if (!triggeredActions.isEmpty()) {
76             Vector<unsigned> actionLocations;
77             actionLocations.reserveInitialCapacity(triggeredActions.size());
78             for (auto actionLocation : triggeredActions)
79                 actionLocations.append(static_cast<unsigned>(actionLocation));
80             std::sort(actionLocations.begin(), actionLocations.end());
81             
82             // Add actions in reverse order to properly deal with IgnorePreviousRules.
83             for (unsigned i = actionLocations.size(); i; i--) {
84                 Action action = Action::deserialize(compiledContentExtension->actions(), actionLocations[i - 1]);
85                 if (action.type() == ActionType::IgnorePreviousRules)
86                     break;
87                 actions.append(action);
88                 if (action.type() == ActionType::BlockLoad)
89                     break;
90             }
91         }
92     }
93     return actions;
94 }
95
96 } // namespace ContentExtensions
97
98 } // namespace WebCore
99
100 #endif // ENABLE(CONTENT_EXTENSIONS)