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
48namespace WebCore {
49
50#if ENABLE(CONTENT_EXTENSIONS)
51using namespace ContentExtensions;
52#endif
53using namespace HTMLNames;
54
55ExtensionStyleSheets::ExtensionStyleSheets(Document& document)
56 : m_document(document)
57{
58}
59
60static 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
71CSSStyleSheet* 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
89void ExtensionStyleSheets::clearPageUserSheet()
90{
91 if (m_pageUserSheet) {
92 m_pageUserSheet = nullptr;
93 m_document.styleScope().didChangeStyleSheetEnvironment();
94 }
95}
96
97void ExtensionStyleSheets::updatePageUserSheet()
98{
99 clearPageUserSheet();
100 if (pageUserSheet())
101 m_document.styleScope().didChangeStyleSheetEnvironment();
102}
103
104const Vector<RefPtr<CSSStyleSheet>>& ExtensionStyleSheets::injectedUserStyleSheets() const
105{
106 updateInjectedStyleSheetCache();
107 return m_injectedUserStyleSheets;
108}
109
110const Vector<RefPtr<CSSStyleSheet>>& ExtensionStyleSheets::injectedAuthorStyleSheets() const
111{
112 updateInjectedStyleSheetCache();
113 return m_injectedAuthorStyleSheets;
114}
115
116void 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
144void ExtensionStyleSheets::invalidateInjectedStyleSheetCache()
145{
146 m_injectedStyleSheetCacheValid = false;
147 m_document.styleScope().didChangeStyleSheetEnvironment();
148}
149
150void 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
157void 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)
165void 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
177void 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
192void 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