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 |