OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. | 2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
11 * documentation and/or other materials provided with the distribution. | 11 * documentation and/or other materials provided with the distribution. |
12 * | 12 * |
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY | 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR | 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
24 */ | 24 */ |
25 | 25 |
26 #include "config.h" | 26 #include "config.h" |
27 #include "core/page/NetworkStateNotifier.h" | 27 #include "core/page/NetworkStateNotifier.h" |
28 | 28 |
29 #include "core/dom/ExecutionContext.h" | |
29 #include "core/page/Page.h" | 30 #include "core/page/Page.h" |
30 #include "wtf/Assertions.h" | 31 #include "wtf/Assertions.h" |
32 #include "wtf/Functional.h" | |
31 #include "wtf/MainThread.h" | 33 #include "wtf/MainThread.h" |
32 #include "wtf/StdLibExtras.h" | 34 #include "wtf/StdLibExtras.h" |
33 #include "wtf/Threading.h" | 35 #include "wtf/Threading.h" |
34 | 36 |
35 namespace WebCore { | 37 namespace WebCore { |
36 | 38 |
37 NetworkStateNotifier& networkStateNotifier() | 39 NetworkStateNotifier& networkStateNotifier() |
38 { | 40 { |
39 AtomicallyInitializedStatic(NetworkStateNotifier*, networkStateNotifier = ne w NetworkStateNotifier); | 41 AtomicallyInitializedStatic(NetworkStateNotifier*, networkStateNotifier = ne w NetworkStateNotifier); |
40 return *networkStateNotifier; | 42 return *networkStateNotifier; |
41 } | 43 } |
42 | 44 |
43 void NetworkStateNotifier::setOnLine(bool onLine) | 45 void NetworkStateNotifier::setOnLine(bool onLine) |
44 { | 46 { |
45 ASSERT(isMainThread()); | 47 ASSERT(isMainThread()); |
46 | 48 |
47 { | 49 { |
48 MutexLocker locker(m_mutex); | 50 MutexLocker locker(m_mutex); |
49 if (m_isOnLine == onLine) | 51 if (m_isOnLine == onLine) |
50 return; | 52 return; |
51 | 53 |
52 m_isOnLine = onLine; | 54 m_isOnLine = onLine; |
53 } | 55 } |
54 | 56 |
55 Page::networkStateChanged(onLine); | 57 Page::networkStateChanged(onLine); |
56 } | 58 } |
57 | 59 |
60 void NetworkStateNotifier::setWebConnectionType(blink::WebNetworkConnection::Con nectionType type) | |
61 { | |
62 ASSERT(isMainThread()); | |
63 | |
64 MutexLocker locker(m_mutex); | |
65 if (m_type == type) | |
66 return; | |
67 m_type = type; | |
68 | |
69 for (ObserverListMap::iterator it = m_observers.begin(); it != m_observers.e nd(); ++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
| |
70 ExecutionContext* context = it->key; | |
71 context->postTask(bind(&NetworkStateNotifier::notifyObserversOnContext, this, context, type)); | |
72 } | |
58 } | 73 } |
74 | |
75 void NetworkStateNotifier::notifyObserversOnContext(ExecutionContext* context, b link::WebNetworkConnection::ConnectionType type) | |
76 { | |
77 ASSERT(context->isContextThread()); | |
78 | |
79 ObserverList* observerList = 0; | |
80 | |
81 { | |
82 // The context could have been removed before we got here | |
83 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
| |
84 ObserverListMap::iterator it = m_observers.find(context); | |
85 if (it == m_observers.end()) | |
86 return; | |
87 observerList = &(it->value); | |
88 } | |
89 | |
90 observerList->iterating = true; | |
91 | |
92 for (Vector<ObserverType>::iterator it = observerList->observers.begin(); it != observerList->observers.end(); ++it) | |
93 (*it)->connectionTypeChange(type); | |
94 | |
95 observerList->iterating = false; | |
96 } | |
97 | |
98 void NetworkStateNotifier::addObserver(ObserverType observer, ExecutionContext* context) | |
99 { | |
100 ASSERT(context->isContextThread()); | |
101 ASSERT(observer); | |
102 | |
103 MutexLocker locker(m_mutex); | |
104 ObserverListMap::iterator it = m_observers.find(context); | |
105 if (it == m_observers.end()) { | |
106 m_observers.set(context, ObserverList()); | |
107 it = m_observers.find(context); | |
108 } | |
109 ASSERT(!it->value.iterating); // Don't mutate observer list while notifying. | |
110 it->value.observers.append(observer); | |
111 } | |
112 | |
113 void NetworkStateNotifier::removeObserver(ObserverType observer, ExecutionContex t* context) | |
114 { | |
115 ASSERT(context->isContextThread()); | |
116 ASSERT(observer); | |
117 | |
118 MutexLocker locker(m_mutex); | |
119 ObserverListMap::iterator it = m_observers.find(context); | |
120 if (it == m_observers.end()) | |
121 return; | |
122 | |
123 ASSERT(!it->value.iterating); // Don't mutate observer list while notifying. | |
124 | |
125 Vector<ObserverType>* observers = &it->value.observers; | |
126 | |
127 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.
| |
128 if (observers->at(i) == observer) { | |
129 observers->remove(i); | |
130 break; | |
131 } | |
132 } | |
133 | |
134 if (observers->isEmpty()) | |
135 m_observers.remove(it); | |
136 } | |
137 | |
138 } // namespace WebCore | |
OLD | NEW |