1 | /* |
2 | * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
3 | * (C) 1999 Antti Koivisto (koivisto@kde.org) |
4 | * (C) 2001 Dirk Mueller (mueller@kde.org) |
5 | * (C) 2006 Alexey Proskuryakov (ap@webkit.org) |
6 | * Copyright (C) 2004-2009, 2011-2012, 2015 Apple Inc. All rights reserved. |
7 | * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) |
8 | * Copyright (C) 2008, 2009, 2011, 2012 Google Inc. All rights reserved. |
9 | * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) |
10 | * Copyright (C) Research In Motion Limited 2010-2011. All rights reserved. |
11 | * |
12 | * This library is free software; you can redistribute it and/or |
13 | * modify it under the terms of the GNU Library General Public |
14 | * License as published by the Free Software Foundation; either |
15 | * version 2 of the License, or (at your option) any later version. |
16 | * |
17 | * This library is distributed in the hope that it will be useful, |
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
20 | * Library General Public License for more details. |
21 | * |
22 | * You should have received a copy of the GNU Library General Public License |
23 | * along with this library; see the file COPYING.LIB. If not, write to |
24 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
25 | * Boston, MA 02110-1301, USA. |
26 | */ |
27 | |
28 | #include "config.h" |
29 | #include "ExtensionStyleSheets.h" |
30 | |
31 | #include "CSSStyleSheet.h" |
32 | #include "Element.h" |
33 | #include "HTMLLinkElement.h" |
34 | #include "HTMLStyleElement.h" |
35 | #include "Page.h" |
36 | #include "ProcessingInstruction.h" |
37 | #include "SVGStyleElement.h" |
38 | #include "Settings.h" |
39 | #include "StyleInvalidator.h" |
40 | #include "StyleResolver.h" |
41 | #include "StyleScope.h" |
42 | #include "StyleSheetContents.h" |
43 | #include "StyleSheetList.h" |
44 | #include "UserContentController.h" |
45 | #include "UserContentURLPattern.h" |
46 | #include "UserStyleSheet.h" |
47 | |
48 | namespace WebCore { |
49 | |
50 | #if ENABLE(CONTENT_EXTENSIONS) |
51 | using namespace ContentExtensions; |
52 | #endif |
53 | using namespace HTMLNames; |
54 | |
55 | ExtensionStyleSheets::ExtensionStyleSheets(Document& document) |
56 | : m_document(document) |
57 | { |
58 | } |
59 | |
60 | static Ref<CSSStyleSheet> createExtensionsStyleSheet(Document& document, URL url, const String& text, UserStyleLevel level) |
61 | { |
62 | auto contents = StyleSheetContents::create(url, CSSParserContext(document, url)); |
63 | auto styleSheet = CSSStyleSheet::create(contents.get(), document, true); |
64 | |
65 | contents->setIsUserStyleSheet(level == UserStyleUserLevel); |
66 | contents->parseString(text); |
67 | |
68 | return styleSheet; |
69 | } |
70 | |
71 | CSSStyleSheet* ExtensionStyleSheets::pageUserSheet() |
72 | { |
73 | if (m_pageUserSheet) |
74 | return m_pageUserSheet.get(); |
75 | |
76 | Page* owningPage = m_document.page(); |
77 | if (!owningPage) |
78 | return 0; |
79 | |
80 | String userSheetText = owningPage->userStyleSheet(); |
81 | if (userSheetText.isEmpty()) |
82 | return 0; |
83 | |
84 | m_pageUserSheet = createExtensionsStyleSheet(m_document, m_document.settings().userStyleSheetLocation(), userSheetText, UserStyleUserLevel); |
85 | |
86 | return m_pageUserSheet.get(); |
87 | } |
88 | |
89 | void ExtensionStyleSheets::clearPageUserSheet() |
90 | { |
91 | if (m_pageUserSheet) { |
92 | m_pageUserSheet = nullptr; |
93 | m_document.styleScope().didChangeStyleSheetEnvironment(); |
94 | } |
95 | } |
96 | |
97 | void ExtensionStyleSheets::updatePageUserSheet() |
98 | { |
99 | clearPageUserSheet(); |
100 | if (pageUserSheet()) |
101 | m_document.styleScope().didChangeStyleSheetEnvironment(); |
102 | } |
103 | |
104 | const Vector<RefPtr<CSSStyleSheet>>& ExtensionStyleSheets::injectedUserStyleSheets() const |
105 | { |
106 | updateInjectedStyleSheetCache(); |
107 | return m_injectedUserStyleSheets; |
108 | } |
109 | |
110 | const Vector<RefPtr<CSSStyleSheet>>& ExtensionStyleSheets::injectedAuthorStyleSheets() const |
111 | { |
112 | updateInjectedStyleSheetCache(); |
113 | return m_injectedAuthorStyleSheets; |
114 | } |
115 | |
116 | void ExtensionStyleSheets::updateInjectedStyleSheetCache() const |
117 | { |
118 | if (m_injectedStyleSheetCacheValid) |
119 | return; |
120 | m_injectedStyleSheetCacheValid = true; |
121 | m_injectedUserStyleSheets.clear(); |
122 | m_injectedAuthorStyleSheets.clear(); |
123 | |
124 | Page* owningPage = m_document.page(); |
125 | if (!owningPage) |
126 | return; |
127 | |
128 | owningPage->userContentProvider().forEachUserStyleSheet([&](const UserStyleSheet& userStyleSheet) { |
129 | if (userStyleSheet.injectedFrames() == InjectInTopFrameOnly && m_document.ownerElement()) |
130 | return; |
131 | |
132 | if (!UserContentURLPattern::matchesPatterns(m_document.url(), userStyleSheet.whitelist(), userStyleSheet.blacklist())) |
133 | return; |
134 | |
135 | auto sheet = createExtensionsStyleSheet(const_cast<Document&>(m_document), userStyleSheet.url(), userStyleSheet.source(), userStyleSheet.level()); |
136 | |
137 | if (userStyleSheet.level() == UserStyleUserLevel) |
138 | m_injectedUserStyleSheets.append(WTFMove(sheet)); |
139 | else |
140 | m_injectedAuthorStyleSheets.append(WTFMove(sheet)); |
141 | }); |
142 | } |
143 | |
144 | void ExtensionStyleSheets::invalidateInjectedStyleSheetCache() |
145 | { |
146 | m_injectedStyleSheetCacheValid = false; |
147 | m_document.styleScope().didChangeStyleSheetEnvironment(); |
148 | } |
149 | |
150 | void ExtensionStyleSheets::addUserStyleSheet(Ref<StyleSheetContents>&& userSheet) |
151 | { |
152 | ASSERT(userSheet.get().isUserStyleSheet()); |
153 | m_userStyleSheets.append(CSSStyleSheet::create(WTFMove(userSheet), m_document)); |
154 | m_document.styleScope().didChangeStyleSheetEnvironment(); |
155 | } |
156 | |
157 | void ExtensionStyleSheets::addAuthorStyleSheetForTesting(Ref<StyleSheetContents>&& authorSheet) |
158 | { |
159 | ASSERT(!authorSheet.get().isUserStyleSheet()); |
160 | m_authorStyleSheetsForTesting.append(CSSStyleSheet::create(WTFMove(authorSheet), m_document)); |
161 | m_document.styleScope().didChangeStyleSheetEnvironment(); |
162 | } |
163 | |
164 | #if ENABLE(CONTENT_EXTENSIONS) |
165 | void ExtensionStyleSheets::addDisplayNoneSelector(const String& identifier, const String& selector, uint32_t selectorID) |
166 | { |
167 | auto result = m_contentExtensionSelectorSheets.add(identifier, nullptr); |
168 | if (result.isNewEntry) { |
169 | result.iterator->value = ContentExtensionStyleSheet::create(m_document); |
170 | m_userStyleSheets.append(&result.iterator->value->styleSheet()); |
171 | } |
172 | |
173 | if (result.iterator->value->addDisplayNoneSelector(selector, selectorID)) |
174 | m_document.styleScope().didChangeStyleSheetEnvironment(); |
175 | } |
176 | |
177 | void ExtensionStyleSheets::maybeAddContentExtensionSheet(const String& identifier, StyleSheetContents& sheet) |
178 | { |
179 | ASSERT(sheet.isUserStyleSheet()); |
180 | |
181 | if (m_contentExtensionSheets.contains(identifier)) |
182 | return; |
183 | |
184 | Ref<CSSStyleSheet> cssSheet = CSSStyleSheet::create(sheet, m_document); |
185 | m_contentExtensionSheets.set(identifier, &cssSheet.get()); |
186 | m_userStyleSheets.append(adoptRef(cssSheet.leakRef())); |
187 | m_document.styleScope().didChangeStyleSheetEnvironment(); |
188 | |
189 | } |
190 | #endif // ENABLE(CONTENT_EXTENSIONS) |
191 | |
192 | void ExtensionStyleSheets::detachFromDocument() |
193 | { |
194 | if (m_pageUserSheet) |
195 | m_pageUserSheet->detachFromDocument(); |
196 | for (auto& sheet : m_injectedUserStyleSheets) |
197 | sheet->detachFromDocument(); |
198 | for (auto& sheet : m_injectedAuthorStyleSheets) |
199 | sheet->detachFromDocument(); |
200 | for (auto& sheet : m_userStyleSheets) |
201 | sheet->detachFromDocument(); |
202 | for (auto& sheet : m_authorStyleSheetsForTesting) |
203 | sheet->detachFromDocument(); |
204 | } |
205 | |
206 | } |
207 | |