Chromium Code Reviews| Index: Source/core/page/NetworkStateNotifier.cpp |
| diff --git a/Source/core/page/NetworkStateNotifier.cpp b/Source/core/page/NetworkStateNotifier.cpp |
| index 02cc4615c96408f4abcfc60bcea128654b09758d..34a19174dfda33c36e9e02ff63a69abc5a36d7ef 100644 |
| --- a/Source/core/page/NetworkStateNotifier.cpp |
| +++ b/Source/core/page/NetworkStateNotifier.cpp |
| @@ -26,8 +26,10 @@ |
| #include "config.h" |
| #include "core/page/NetworkStateNotifier.h" |
| +#include "core/dom/ExecutionContext.h" |
| #include "core/page/Page.h" |
| #include "wtf/Assertions.h" |
| +#include "wtf/Functional.h" |
| #include "wtf/MainThread.h" |
| #include "wtf/StdLibExtras.h" |
| #include "wtf/Threading.h" |
| @@ -55,4 +57,82 @@ void NetworkStateNotifier::setOnLine(bool onLine) |
| Page::networkStateChanged(onLine); |
| } |
| +void NetworkStateNotifier::setWebConnectionType(blink::WebNetworkConnection::ConnectionType type) |
| +{ |
| + ASSERT(isMainThread()); |
| + |
| + MutexLocker locker(m_mutex); |
| + if (m_type == type) |
| + return; |
| + m_type = type; |
| + |
| + for (ObserverListMap::iterator it = m_observers.begin(); it != m_observers.end(); ++it) { |
|
adamk
2014/05/20 15:00:36
What guarantees that the ExecutionContexts in this
jkarlin
2014/05/20 16:20:23
The observer must call removeObserver before the E
|
| + ExecutionContext* context = it->key; |
| + context->postTask(bind(&NetworkStateNotifier::notifyObserversOnContext, this, context, type)); |
| + } |
| +} |
| + |
| +void NetworkStateNotifier::notifyObserversOnContext(ExecutionContext* context, blink::WebNetworkConnection::ConnectionType type) |
| +{ |
| + ASSERT(context->isContextThread()); |
| + |
| + ObserverList* observerList = 0; |
| + |
| + { |
| + // The context could have been removed before we got here |
| + MutexLocker locker(m_mutex); |
|
adamk
2014/05/20 15:12:50
I think you need to lock for this entire method, e
jkarlin
2014/05/20 16:20:23
Nice catch, thanks. Made an alternate fix where th
|
| + ObserverListMap::iterator it = m_observers.find(context); |
| + if (it == m_observers.end()) |
| + return; |
| + observerList = &(it->value); |
| + } |
| + |
| + observerList->iterating = true; |
| + |
| + for (Vector<ObserverType>::iterator it = observerList->observers.begin(); it != observerList->observers.end(); ++it) |
| + (*it)->connectionTypeChange(type); |
| + |
| + observerList->iterating = false; |
| +} |
| + |
| +void NetworkStateNotifier::addObserver(ObserverType observer, ExecutionContext* context) |
| +{ |
| + ASSERT(context->isContextThread()); |
| + ASSERT(observer); |
| + |
| + MutexLocker locker(m_mutex); |
| + ObserverListMap::iterator it = m_observers.find(context); |
| + if (it == m_observers.end()) { |
| + m_observers.set(context, ObserverList()); |
| + it = m_observers.find(context); |
| + } |
| + ASSERT(!it->value.iterating); // Don't mutate observer list while notifying. |
| + it->value.observers.append(observer); |
| +} |
| + |
| +void NetworkStateNotifier::removeObserver(ObserverType observer, ExecutionContext* context) |
| +{ |
| + ASSERT(context->isContextThread()); |
| + ASSERT(observer); |
| + |
| + MutexLocker locker(m_mutex); |
| + ObserverListMap::iterator it = m_observers.find(context); |
| + if (it == m_observers.end()) |
| + return; |
| + |
| + ASSERT(!it->value.iterating); // Don't mutate observer list while notifying. |
| + |
| + Vector<ObserverType>* observers = &it->value.observers; |
| + |
| + for (size_t i = 0; i < observers->size(); ++i) { |
|
adamk
2014/05/20 15:00:36
Vector has a find() method (returning kNotFound if
jkarlin
2014/05/20 16:20:23
Done.
|
| + if (observers->at(i) == observer) { |
| + observers->remove(i); |
| + break; |
| + } |
| + } |
| + |
| + if (observers->isEmpty()) |
| + m_observers.remove(it); |
| } |
| + |
| +} // namespace WebCore |