 Chromium Code Reviews
 Chromium Code Reviews Issue 348893004:
  Rework MediaQueryMatcher to batch up listener notification  (Closed) 
  Base URL: svn://svn.chromium.org/blink/trunk
    
  
    Issue 348893004:
  Rework MediaQueryMatcher to batch up listener notification  (Closed) 
  Base URL: svn://svn.chromium.org/blink/trunk| OLD | NEW | 
|---|---|
| 1 /* | 1 /* | 
| 2 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) | 2 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) | 
| 3 * | 3 * | 
| 4 * This library is free software; you can redistribute it and/or | 4 * This library is free software; you can redistribute it and/or | 
| 5 * modify it under the terms of the GNU Library General Public | 5 * modify it under the terms of the GNU Library General Public | 
| 6 * License as published by the Free Software Foundation; either | 6 * License as published by the Free Software Foundation; either | 
| 7 * version 2 of the License, or (at your option) any later version. | 7 * version 2 of the License, or (at your option) any later version. | 
| 8 * | 8 * | 
| 9 * This library is distributed in the hope that it will be useful, | 9 * This library is distributed in the hope that it will be useful, | 
| 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
| (...skipping 13 matching lines...) Expand all Loading... | |
| 24 #include "core/css/MediaQueryEvaluator.h" | 24 #include "core/css/MediaQueryEvaluator.h" | 
| 25 #include "core/css/MediaQueryList.h" | 25 #include "core/css/MediaQueryList.h" | 
| 26 #include "core/css/MediaQueryListListener.h" | 26 #include "core/css/MediaQueryListListener.h" | 
| 27 #include "core/css/resolver/StyleResolver.h" | 27 #include "core/css/resolver/StyleResolver.h" | 
| 28 #include "core/dom/Document.h" | 28 #include "core/dom/Document.h" | 
| 29 #include "core/frame/FrameView.h" | 29 #include "core/frame/FrameView.h" | 
| 30 #include "core/frame/LocalFrame.h" | 30 #include "core/frame/LocalFrame.h" | 
| 31 | 31 | 
| 32 namespace WebCore { | 32 namespace WebCore { | 
| 33 | 33 | 
| 34 MediaQueryMatcher::Listener::Listener(PassRefPtrWillBeRawPtr<MediaQueryListListe ner> listener, PassRefPtrWillBeRawPtr<MediaQueryList> query) | 34 MediaQueryMatcher::MediaQueryMatcher(Document& document) | 
| 35 : m_listener(listener) | 35 : m_document(&document) | 
| 36 , m_query(query) | |
| 37 { | |
| 38 } | |
| 39 | |
| 40 void MediaQueryMatcher::Listener::evaluate(MediaQueryEvaluator* evaluator) | |
| 41 { | |
| 42 if (m_query->evaluate(evaluator)) | |
| 43 m_listener->queryChanged(m_query.get()); | |
| 44 } | |
| 45 | |
| 46 void MediaQueryMatcher::Listener::trace(Visitor* visitor) | |
| 47 { | |
| 48 visitor->trace(m_listener); | |
| 49 visitor->trace(m_query); | |
| 50 } | |
| 51 | |
| 52 MediaQueryMatcher::MediaQueryMatcher(Document* document) | |
| 53 : m_document(document) | |
| 54 , m_evaluationRound(1) | |
| 55 { | 36 { | 
| 56 ASSERT(m_document); | 37 ASSERT(m_document); | 
| 57 } | 38 } | 
| 58 | 39 | 
| 59 DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(MediaQueryMatcher) | 40 DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(MediaQueryMatcher) | 
| 60 | 41 | 
| 61 void MediaQueryMatcher::documentDestroyed() | 42 void MediaQueryMatcher::documentDetached() | 
| 62 { | 43 { | 
| 63 m_listeners.clear(); | |
| 64 m_document = nullptr; | 44 m_document = nullptr; | 
| 45 | |
| 46 // Take a ref to each MediaQuerylist as removing the listeners in documentDe tached | |
| 
esprehn
2014/06/26 05:43:24
typo, MediaQueryList
 
cbiesinger
2014/06/26 20:27:59
Done.
 | |
| 47 // could release the last ref and mutate the m_mediaLists. | |
| 48 WillBeHeapVector<RefPtrWillBeMember<MediaQueryList> > lists; | |
| 49 copyToVector(m_mediaLists, lists); | |
| 50 | |
| 51 for (size_t i = 0; i < lists.size(); ++i) | |
| 52 lists[i]->documentDetached(); | |
| 65 } | 53 } | 
| 66 | 54 | 
| 67 AtomicString MediaQueryMatcher::mediaType() const | 55 AtomicString MediaQueryMatcher::mediaType() const | 
| 68 { | 56 { | 
| 69 if (!m_document || !m_document->frame() || !m_document->frame()->view()) | 57 if (!m_document || !m_document->frame() || !m_document->frame()->view()) | 
| 70 return nullAtom; | 58 return nullAtom; | 
| 71 | 59 | 
| 72 return m_document->frame()->view()->mediaType(); | 60 return m_document->frame()->view()->mediaType(); | 
| 73 } | 61 } | 
| 74 | 62 | 
| 75 PassOwnPtr<MediaQueryEvaluator> MediaQueryMatcher::prepareEvaluator() const | 63 PassOwnPtr<MediaQueryEvaluator> MediaQueryMatcher::createEvaluator() const | 
| 76 { | 64 { | 
| 77 if (!m_document || !m_document->frame()) | 65 if (!m_document || !m_document->frame()) | 
| 78 return nullptr; | 66 return nullptr; | 
| 79 | 67 | 
| 80 return adoptPtr(new MediaQueryEvaluator(mediaType(), m_document->frame())); | 68 return adoptPtr(new MediaQueryEvaluator(mediaType(), m_document->frame())); | 
| 81 } | 69 } | 
| 82 | 70 | 
| 83 bool MediaQueryMatcher::evaluate(const MediaQuerySet* media) | 71 bool MediaQueryMatcher::evaluate(const MediaQuerySet* media) | 
| 84 { | 72 { | 
| 85 if (!media) | 73 if (!media) | 
| 86 return false; | 74 return false; | 
| 87 | 75 | 
| 88 OwnPtr<MediaQueryEvaluator> evaluator(prepareEvaluator()); | 76 if (m_evaluator) | 
| 89 return evaluator && evaluator->eval(media); | 77 return m_evaluator->eval(media); | 
| 78 | |
| 79 if (OwnPtr<MediaQueryEvaluator> evaluator = createEvaluator()) | |
| 80 return evaluator->eval(media); | |
| 81 | |
| 82 return false; | |
| 90 } | 83 } | 
| 91 | 84 | 
| 92 PassRefPtrWillBeRawPtr<MediaQueryList> MediaQueryMatcher::matchMedia(const Strin g& query) | 85 PassRefPtrWillBeRawPtr<MediaQueryList> MediaQueryMatcher::matchMedia(const Strin g& query) | 
| 93 { | 86 { | 
| 94 if (!m_document) | 87 if (!m_document) | 
| 95 return nullptr; | 88 return nullptr; | 
| 96 | 89 | 
| 97 RefPtrWillBeRawPtr<MediaQuerySet> media = MediaQuerySet::create(query); | 90 RefPtrWillBeRawPtr<MediaQuerySet> media = MediaQuerySet::create(query); | 
| 98 // Add warning message to inspector whenever dpi/dpcm values are used for "s creen" media. | 91 // Add warning message to inspector whenever dpi/dpcm values are used for "s creen" media. | 
| 99 reportMediaQueryWarningIfNeeded(m_document, media.get()); | 92 reportMediaQueryWarningIfNeeded(m_document, media.get()); | 
| 100 return MediaQueryList::create(this, media, evaluate(media.get())); | 93 return MediaQueryList::create(this, media); | 
| 101 } | 94 } | 
| 102 | 95 | 
| 103 void MediaQueryMatcher::addListener(PassRefPtrWillBeRawPtr<MediaQueryListListene r> listener, PassRefPtrWillBeRawPtr<MediaQueryList> query) | 96 void MediaQueryMatcher::addMediaQueryList(MediaQueryList* query) | 
| 97 { | |
| 98 if (!m_document) | |
| 99 return; | |
| 100 m_mediaLists.add(query); | |
| 101 } | |
| 102 | |
| 103 void MediaQueryMatcher::removeMediaQueryList(MediaQueryList* query) | |
| 104 { | |
| 105 if (!m_document) | |
| 106 return; | |
| 107 m_mediaLists.remove(query); | |
| 108 } | |
| 109 | |
| 110 void MediaQueryMatcher::mediaFeaturesChanged() | |
| 104 { | 111 { | 
| 105 if (!m_document) | 112 if (!m_document) | 
| 106 return; | 113 return; | 
| 107 | 114 | 
| 108 for (size_t i = 0; i < m_listeners.size(); ++i) { | 115 // Cache an evaluator so we don't allocate one for each list below. | 
| 109 if (*m_listeners[i]->listener() == *listener && m_listeners[i]->query() == query) | 116 m_evaluator = createEvaluator(); | 
| 110 return; | 117 if (!m_evaluator) | 
| 111 } | |
| 112 | |
| 113 m_listeners.append(adoptPtrWillBeNoop(new Listener(listener, query))); | |
| 114 } | |
| 115 | |
| 116 void MediaQueryMatcher::removeListener(MediaQueryListListener* listener, MediaQu eryList* query) | |
| 117 { | |
| 118 if (!m_document) | |
| 119 return; | 118 return; | 
| 120 | 119 | 
| 121 for (size_t i = 0; i < m_listeners.size(); ++i) { | 120 WillBeHeapVector<RefPtrWillBeMember<MediaQueryListListener> > listenersToNot ify; | 
| 122 if (*m_listeners[i]->listener() == *listener && m_listeners[i]->query() == query) { | 121 for (MediaQueryListSet::iterator it = m_mediaLists.begin(); it != m_mediaLis ts.end(); ++it) | 
| 123 m_listeners.remove(i); | 122 (*it)->mediaFeaturesChanged(&listenersToNotify); | 
| 124 return; | |
| 125 } | |
| 126 } | |
| 127 } | |
| 128 | 123 | 
| 129 void MediaQueryMatcher::styleResolverChanged() | 124 m_evaluator = nullptr; | 
| 130 { | 125 // FIXME: This should be async! We're running script inside ::layout() or :: updateRenderTree(). | 
| 131 if (!m_document) | 126 for (size_t i = 0; i < listenersToNotify.size(); ++i) | 
| 132 return; | 127 listenersToNotify[i]->call(); | 
| 133 | |
| 134 ++m_evaluationRound; | |
| 135 OwnPtr<MediaQueryEvaluator> evaluator = prepareEvaluator(); | |
| 136 if (!evaluator) | |
| 137 return; | |
| 138 | |
| 139 for (size_t i = 0; i < m_listeners.size(); ++i) | |
| 140 m_listeners[i]->evaluate(evaluator.get()); | |
| 141 } | 128 } | 
| 142 | 129 | 
| 143 void MediaQueryMatcher::trace(Visitor* visitor) | 130 void MediaQueryMatcher::trace(Visitor* visitor) | 
| 144 { | 131 { | 
| 145 visitor->trace(m_document); | 132 visitor->trace(m_document); | 
| 146 // We don't support tracing of vectors of OwnPtrs (ie. Vector<OwnPtr<Listene r> >). | 133 visitor->trace(m_mediaLists); | 
| 147 // Since this is a transitional object we are just ifdef'ing it out when oil pan is not enabled. | |
| 148 #if ENABLE(OILPAN) | |
| 149 visitor->trace(m_listeners); | |
| 150 #endif | |
| 151 } | 134 } | 
| 152 | 135 | 
| 153 } | 136 } | 
| OLD | NEW |