REGRESSION(r244635): [GTK] Wrong background color used in non-dark mode
[WebKit-https.git] / Source / WebCore / css / MediaQueryMatcher.cpp
1 /*
2  * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
3  *
4  *  This library is free software; you can redistribute it and/or
5  *  modify it under the terms of the GNU Library General Public
6  *  License as published by the Free Software Foundation; either
7  *  version 2 of the License, or (at your option) any later version.
8  *
9  *  This library is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  *  Library General Public License for more details.
13  *
14  *  You should have received a copy of the GNU Library General Public License
15  *  along with this library; see the file COPYING.LIB.  If not, write to
16  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  *  Boston, MA 02110-1301, USA.
18  */
19
20 #include "config.h"
21 #include "MediaQueryMatcher.h"
22
23 #include "Document.h"
24 #include "Frame.h"
25 #include "FrameView.h"
26 #include "Logging.h"
27 #include "MediaList.h"
28 #include "MediaQueryEvaluator.h"
29 #include "MediaQueryList.h"
30 #include "MediaQueryListListener.h"
31 #include "MediaQueryParserContext.h"
32 #include "NodeRenderStyle.h"
33 #include "RenderElement.h"
34 #include "StyleResolver.h"
35 #include "StyleScope.h"
36 #include <wtf/text/TextStream.h>
37
38 namespace WebCore {
39
40 MediaQueryMatcher::MediaQueryMatcher(Document& document)
41     : m_document(makeWeakPtr(document))
42 {
43 }
44
45 MediaQueryMatcher::~MediaQueryMatcher() = default;
46
47 void MediaQueryMatcher::documentDestroyed()
48 {
49     m_listeners.clear();
50     m_document = nullptr;
51 }
52
53 String MediaQueryMatcher::mediaType() const
54 {
55     if (!m_document || !m_document->frame() || !m_document->frame()->view())
56         return String();
57
58     return m_document->frame()->view()->mediaType();
59 }
60
61 std::unique_ptr<RenderStyle> MediaQueryMatcher::documentElementUserAgentStyle() const
62 {
63     if (!m_document || !m_document->frame())
64         return nullptr;
65
66     auto* documentElement = m_document->documentElement();
67     if (!documentElement)
68         return nullptr;
69
70     return m_document->styleScope().resolver().styleForElement(*documentElement, m_document->renderStyle(), nullptr, RuleMatchingBehavior::MatchOnlyUserAgentRules).renderStyle;
71 }
72
73 bool MediaQueryMatcher::evaluate(const MediaQuerySet& media)
74 {
75     auto style = documentElementUserAgentStyle();
76     if (!style)
77         return false;
78     return MediaQueryEvaluator { mediaType(), *m_document, style.get() }.evaluate(media);
79 }
80
81 RefPtr<MediaQueryList> MediaQueryMatcher::matchMedia(const String& query)
82 {
83     if (!m_document)
84         return nullptr;
85
86     auto media = MediaQuerySet::create(query, MediaQueryParserContext(*m_document));
87     reportMediaQueryWarningIfNeeded(m_document.get(), media.ptr());
88     bool result = evaluate(media.get());
89     return MediaQueryList::create(*this, WTFMove(media), result);
90 }
91
92 void MediaQueryMatcher::addListener(Ref<MediaQueryListListener>&& listener, MediaQueryList& query)
93 {
94     if (!m_document)
95         return;
96
97     for (auto& existingListener : m_listeners) {
98         if (existingListener.listener.get() == listener.get() && existingListener.query.ptr() == &query)
99             return;
100     }
101
102     m_listeners.append(Listener { WTFMove(listener), query });
103 }
104
105 void MediaQueryMatcher::removeListener(MediaQueryListListener& listener, MediaQueryList& query)
106 {
107     m_listeners.removeFirstMatching([&listener, &query](auto& existingListener) {
108         return existingListener.listener.get() == listener && existingListener.query.ptr() == &query;
109     });
110 }
111
112 void MediaQueryMatcher::styleResolverChanged()
113 {
114     ASSERT(m_document);
115
116     ++m_evaluationRound;
117
118     auto style = documentElementUserAgentStyle();
119     if (!style)
120         return;
121
122     LOG_WITH_STREAM(MediaQueries, stream << "MediaQueryMatcher::styleResolverChanged " << m_document->url());
123
124     MediaQueryEvaluator evaluator { mediaType(), *m_document, style.get() };
125     Vector<Listener> listeners;
126     listeners.reserveInitialCapacity(m_listeners.size());
127     for (auto& listener : m_listeners)
128         listeners.uncheckedAppend({ listener.listener.copyRef(), listener.query.copyRef() });
129     for (auto& listener : listeners) {
130         bool notify;
131         listener.query->evaluate(evaluator, notify);
132         if (notify)
133             listener.listener->handleEvent(listener.query);
134     }
135 }
136
137 } // namespace WebCore