Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / css / MediaQueryMatcher.cpp
index 61fc729..3d45bb9 100644 (file)
 #include "core/css/MediaList.h"
 #include "core/css/MediaQueryEvaluator.h"
 #include "core/css/MediaQueryList.h"
+#include "core/css/MediaQueryListEvent.h"
 #include "core/css/MediaQueryListListener.h"
 #include "core/css/resolver/StyleResolver.h"
 #include "core/dom/Document.h"
-#include "core/frame/Frame.h"
 #include "core/frame/FrameView.h"
+#include "core/frame/LocalFrame.h"
+#include "wtf/Vector.h"
 
-namespace WebCore {
+namespace blink {
 
-MediaQueryMatcher::Listener::Listener(PassRefPtr<MediaQueryListListener> listener, PassRefPtr<MediaQueryList> query)
-    : m_listener(listener)
-    , m_query(query)
+PassRefPtrWillBeRawPtr<MediaQueryMatcher> MediaQueryMatcher::create(Document& document)
 {
+    return adoptRefWillBeNoop(new MediaQueryMatcher(document));
 }
 
-MediaQueryMatcher::Listener::~Listener()
-{
-}
-
-void MediaQueryMatcher::Listener::evaluate(ScriptState* state, MediaQueryEvaluator* evaluator)
-{
-    bool notify;
-    m_query->evaluate(evaluator, notify);
-    if (notify)
-        m_listener->queryChanged(state, m_query.get());
-}
-
-MediaQueryMatcher::MediaQueryMatcher(Document* document)
-    : m_document(document)
-    , m_evaluationRound(1)
+MediaQueryMatcher::MediaQueryMatcher(Document& document)
+    : m_document(&document)
 {
     ASSERT(m_document);
 }
 
-MediaQueryMatcher::~MediaQueryMatcher()
-{
-}
-
-void MediaQueryMatcher::documentDestroyed()
-{
-    m_listeners.clear();
-    m_document = 0;
-}
+DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(MediaQueryMatcher)
 
-AtomicString MediaQueryMatcher::mediaType() const
+void MediaQueryMatcher::documentDetached()
 {
-    if (!m_document || !m_document->frame() || !m_document->frame()->view())
-        return nullAtom;
-
-    return m_document->frame()->view()->mediaType();
+    m_document = nullptr;
+    m_evaluator = nullptr;
 }
 
-PassOwnPtr<MediaQueryEvaluator> MediaQueryMatcher::prepareEvaluator() const
+PassOwnPtr<MediaQueryEvaluator> MediaQueryMatcher::createEvaluator() const
 {
     if (!m_document || !m_document->frame())
         return nullptr;
 
-    Element* documentElement = m_document->documentElement();
-    if (!documentElement)
-        return nullptr;
-
-    StyleResolver* styleResolver = m_document->styleResolver();
-    if (!styleResolver)
-        return nullptr;
-
-    RefPtr<RenderStyle> rootStyle = styleResolver->styleForElement(documentElement, 0 /*defaultParent*/, DisallowStyleSharing, MatchOnlyUserAgentRules);
-
-    return adoptPtr(new MediaQueryEvaluator(mediaType(), m_document->frame(), rootStyle.get()));
+    return adoptPtr(new MediaQueryEvaluator(m_document->frame()));
 }
 
 bool MediaQueryMatcher::evaluate(const MediaQuerySet* media)
 {
+    ASSERT(!m_document || m_document->frame() || !m_evaluator);
+
     if (!media)
         return false;
 
-    OwnPtr<MediaQueryEvaluator> evaluator(prepareEvaluator());
-    return evaluator && evaluator->eval(media);
+    // Cache the evaluator to avoid allocating one per evaluation.
+    if (!m_evaluator)
+        m_evaluator = createEvaluator();
+
+    if (m_evaluator)
+        return m_evaluator->eval(media);
+
+    return false;
 }
 
-PassRefPtr<MediaQueryList> MediaQueryMatcher::matchMedia(const String& query)
+PassRefPtrWillBeRawPtr<MediaQueryList> MediaQueryMatcher::matchMedia(const String& query)
 {
     if (!m_document)
-        return 0;
+        return nullptr;
 
-    RefPtr<MediaQuerySet> media = MediaQuerySet::create(query);
+    RefPtrWillBeRawPtr<MediaQuerySet> media = MediaQuerySet::create(query);
     // Add warning message to inspector whenever dpi/dpcm values are used for "screen" media.
     reportMediaQueryWarningIfNeeded(m_document, media.get());
-    return MediaQueryList::create(this, media, evaluate(media.get()));
+    return MediaQueryList::create(m_document, this, media);
 }
 
-void MediaQueryMatcher::addListener(PassRefPtr<MediaQueryListListener> listener, PassRefPtr<MediaQueryList> query)
+void MediaQueryMatcher::addMediaQueryList(MediaQueryList* query)
 {
     if (!m_document)
         return;
+    m_mediaLists.add(query);
+}
 
-    for (size_t i = 0; i < m_listeners.size(); ++i) {
-        if (*m_listeners[i]->listener() == *listener && m_listeners[i]->query() == query)
-            return;
-    }
+void MediaQueryMatcher::removeMediaQueryList(MediaQueryList* query)
+{
+    if (!m_document)
+        return;
+    m_mediaLists.remove(query);
+}
 
-    m_listeners.append(adoptPtr(new Listener(listener, query)));
+void MediaQueryMatcher::addViewportListener(PassRefPtrWillBeRawPtr<MediaQueryListListener> listener)
+{
+    if (!m_document)
+        return;
+    m_viewportListeners.add(listener);
 }
 
-void MediaQueryMatcher::removeListener(MediaQueryListListener* listener, MediaQueryList* query)
+void MediaQueryMatcher::removeViewportListener(PassRefPtrWillBeRawPtr<MediaQueryListListener> listener)
+{
+    if (!m_document)
+        return;
+    m_viewportListeners.remove(listener);
+}
+
+void MediaQueryMatcher::mediaFeaturesChanged()
 {
     if (!m_document)
         return;
 
-    for (size_t i = 0; i < m_listeners.size(); ++i) {
-        if (*m_listeners[i]->listener() == *listener && m_listeners[i]->query() == query) {
-            m_listeners.remove(i);
-            return;
+    WillBeHeapVector<RefPtrWillBeMember<MediaQueryListListener> > listenersToNotify;
+    for (const auto& list : m_mediaLists) {
+        if (list->mediaFeaturesChanged(&listenersToNotify)) {
+            RefPtrWillBeRawPtr<Event> event(MediaQueryListEvent::create(list));
+            event->setTarget(list);
+            m_document->enqueueUniqueAnimationFrameEvent(event);
         }
     }
+    m_document->enqueueMediaQueryChangeListeners(listenersToNotify);
 }
 
-void MediaQueryMatcher::styleResolverChanged()
+void MediaQueryMatcher::viewportChanged()
 {
     if (!m_document)
         return;
 
-    ScriptState* scriptState = m_document->frame() ? mainWorldScriptState(m_document->frame()) : 0;
-    if (!scriptState)
-        return;
+    WillBeHeapVector<RefPtrWillBeMember<MediaQueryListListener> > listenersToNotify;
+    for (const auto& listener : m_viewportListeners)
+        listenersToNotify.append(listener);
 
-    ++m_evaluationRound;
-    OwnPtr<MediaQueryEvaluator> evaluator = prepareEvaluator();
-    if (!evaluator)
-        return;
+    m_document->enqueueMediaQueryChangeListeners(listenersToNotify);
+}
 
-    for (size_t i = 0; i < m_listeners.size(); ++i)
-        m_listeners[i]->evaluate(scriptState, evaluator.get());
+void MediaQueryMatcher::trace(Visitor* visitor)
+{
+#if ENABLE(OILPAN)
+    visitor->trace(m_document);
+    visitor->trace(m_mediaLists);
+    visitor->trace(m_viewportListeners);
+#endif
 }
 
 }