Prepare to use CSS selectors in content extensions.
[WebKit-https.git] / Source / WebCore / page / UserContentController.cpp
1 /*
2  * Copyright (C) 2014, 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 #include "UserContentController.h"
28
29 #include "DOMWrapperWorld.h"
30 #include "Document.h"
31 #include "MainFrame.h"
32 #include "Page.h"
33 #include "UserScript.h"
34 #include "UserStyleSheet.h"
35
36 #if ENABLE(USER_MESSAGE_HANDLERS)
37 #include "UserMessageHandlerDescriptor.h"
38 #endif
39
40 #if ENABLE(CONTENT_EXTENSIONS)
41 #include "ContentExtensionsBackend.h"
42 #include "ContentExtensionsManager.h"
43 #endif
44
45 namespace WebCore {
46
47 RefPtr<UserContentController> UserContentController::create()
48 {
49     return adoptRef(new UserContentController);
50 }
51
52 UserContentController::UserContentController()
53 {
54 }
55
56 UserContentController::~UserContentController()
57 {
58 }
59
60 void UserContentController::addPage(Page& page)
61 {
62     ASSERT(!m_pages.contains(&page));
63     m_pages.add(&page);
64 }
65
66 void UserContentController::removePage(Page& page)
67 {
68     ASSERT(m_pages.contains(&page));
69     m_pages.remove(&page);
70 }
71
72 void UserContentController::addUserScript(DOMWrapperWorld& world, std::unique_ptr<UserScript> userScript)
73 {
74     if (!m_userScripts)
75         m_userScripts = std::make_unique<UserScriptMap>();
76
77     auto& scriptsInWorld = m_userScripts->add(&world, nullptr).iterator->value;
78     if (!scriptsInWorld)
79         scriptsInWorld = std::make_unique<UserScriptVector>();
80     scriptsInWorld->append(WTF::move(userScript));
81 }
82
83 void UserContentController::removeUserScript(DOMWrapperWorld& world, const URL& url)
84 {
85     if (!m_userScripts)
86         return;
87
88     auto it = m_userScripts->find(&world);
89     if (it == m_userScripts->end())
90         return;
91
92     auto scripts = it->value.get();
93     for (int i = scripts->size() - 1; i >= 0; --i) {
94         if (scripts->at(i)->url() == url)
95             scripts->remove(i);
96     }
97
98     if (scripts->isEmpty())
99         m_userScripts->remove(it);
100 }
101
102 void UserContentController::removeUserScripts(DOMWrapperWorld& world)
103 {
104     if (!m_userScripts)
105         return;
106
107     m_userScripts->remove(&world);
108 }
109
110 void UserContentController::addUserStyleSheet(DOMWrapperWorld& world, std::unique_ptr<UserStyleSheet> userStyleSheet, UserStyleInjectionTime injectionTime)
111 {
112     if (!m_userStyleSheets)
113         m_userStyleSheets = std::make_unique<UserStyleSheetMap>();
114
115     auto& styleSheetsInWorld = m_userStyleSheets->add(&world, nullptr).iterator->value;
116     if (!styleSheetsInWorld)
117         styleSheetsInWorld = std::make_unique<UserStyleSheetVector>();
118     styleSheetsInWorld->append(WTF::move(userStyleSheet));
119
120     if (injectionTime == InjectInExistingDocuments)
121         invalidateInjectedStyleSheetCacheInAllFrames();
122 }
123
124 void UserContentController::removeUserStyleSheet(DOMWrapperWorld& world, const URL& url)
125 {
126     if (!m_userStyleSheets)
127         return;
128
129     auto it = m_userStyleSheets->find(&world);
130     if (it == m_userStyleSheets->end())
131         return;
132
133     auto& stylesheets = *it->value;
134
135     bool sheetsChanged = false;
136     for (int i = stylesheets.size() - 1; i >= 0; --i) {
137         if (stylesheets[i]->url() == url) {
138             stylesheets.remove(i);
139             sheetsChanged = true;
140         }
141     }
142
143     if (!sheetsChanged)
144         return;
145
146     if (stylesheets.isEmpty())
147         m_userStyleSheets->remove(it);
148
149     invalidateInjectedStyleSheetCacheInAllFrames();
150 }
151
152 void UserContentController::removeUserStyleSheets(DOMWrapperWorld& world)
153 {
154     if (!m_userStyleSheets)
155         return;
156
157     if (!m_userStyleSheets->remove(&world))
158         return;
159
160     invalidateInjectedStyleSheetCacheInAllFrames();
161 }
162
163 #if ENABLE(USER_MESSAGE_HANDLERS)
164 void UserContentController::addUserMessageHandlerDescriptor(UserMessageHandlerDescriptor& descriptor)
165 {
166     if (!m_userMessageHandlerDescriptors)
167         m_userMessageHandlerDescriptors = std::make_unique<UserMessageHandlerDescriptorMap>();
168
169     m_userMessageHandlerDescriptors->add(std::make_pair(descriptor.name(), &descriptor.world()), &descriptor);
170 }
171
172 void UserContentController::removeUserMessageHandlerDescriptor(UserMessageHandlerDescriptor& descriptor)
173 {
174     if (!m_userMessageHandlerDescriptors)
175         return;
176
177     m_userMessageHandlerDescriptors->remove(std::make_pair(descriptor.name(), &descriptor.world()));
178 }
179 #endif
180
181 #if ENABLE(CONTENT_EXTENSIONS)
182 void UserContentController::addUserContentFilter(const String& name, const String& ruleList)
183 {
184     if (!m_contentExtensionBackend)
185         m_contentExtensionBackend = std::make_unique<ContentExtensions::ContentExtensionsBackend>();
186     
187     m_contentExtensionBackend->setRuleList(name, ContentExtensions::ExtensionsManager::createRuleList(ruleList));
188 }
189
190 void UserContentController::removeUserContentFilter(const String& name)
191 {
192     if (!m_contentExtensionBackend)
193         return;
194
195     m_contentExtensionBackend->removeRuleList(name);
196 }
197
198 void UserContentController::removeAllUserContentFilters()
199 {
200     if (!m_contentExtensionBackend)
201         return;
202
203     m_contentExtensionBackend->removeAllRuleLists();
204 }
205
206 Vector<ContentExtensions::Action> UserContentController::actionsForURL(const URL& url)
207 {
208     if (!m_contentExtensionBackend)
209         return Vector<ContentExtensions::Action>();
210
211     return m_contentExtensionBackend->actionsForURL(url);
212 }
213
214 #endif
215
216 void UserContentController::removeAllUserContent()
217 {
218     m_userScripts = nullptr;
219
220     if (m_userStyleSheets) {
221         m_userStyleSheets = nullptr;
222         invalidateInjectedStyleSheetCacheInAllFrames();
223     }
224 }
225
226 void UserContentController::invalidateInjectedStyleSheetCacheInAllFrames()
227 {
228     for (auto& page : m_pages) {
229         for (Frame* frame = &page->mainFrame(); frame; frame = frame->tree().traverseNext()) {
230             frame->document()->styleSheetCollection().invalidateInjectedStyleSheetCache();
231             frame->document()->styleResolverChanged(DeferRecalcStyle);
232         }
233     }
234 }
235
236 } // namespace WebCore