Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(258)

Side by Side Diff: third_party/WebKit/Source/core/page/NetworkStateNotifier.cpp

Issue 2704083002: Remove Page dependency from NetworkStateNotifier (Closed)
Patch Set: DOMWindow -> Document Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "core/page/NetworkStateNotifier.h" 26 #include "core/page/NetworkStateNotifier.h"
27 27
28 #include "core/dom/TaskRunnerHelper.h"
29 #include "core/page/Page.h"
30 #include "platform/CrossThreadFunctional.h" 28 #include "platform/CrossThreadFunctional.h"
31 #include "wtf/Assertions.h" 29 #include "wtf/Assertions.h"
32 #include "wtf/Functional.h" 30 #include "wtf/Functional.h"
33 #include "wtf/PtrUtil.h" 31 #include "wtf/PtrUtil.h"
34 #include "wtf/StdLibExtras.h" 32 #include "wtf/StdLibExtras.h"
35 #include "wtf/Threading.h" 33 #include "wtf/Threading.h"
36 34
37 namespace blink { 35 namespace blink {
38 36
37 template <>
38 struct CrossThreadCopier<NetworkStateNotifier::NetworkState>
39 : public CrossThreadCopierPassThrough<NetworkStateNotifier::NetworkState> {
40 STATIC_ONLY(CrossThreadCopier);
41 };
42
39 NetworkStateNotifier& networkStateNotifier() { 43 NetworkStateNotifier& networkStateNotifier() {
40 DEFINE_THREAD_SAFE_STATIC_LOCAL(NetworkStateNotifier, networkStateNotifier, 44 DEFINE_THREAD_SAFE_STATIC_LOCAL(NetworkStateNotifier, networkStateNotifier,
41 new NetworkStateNotifier); 45 new NetworkStateNotifier);
42 return networkStateNotifier; 46 return networkStateNotifier;
43 } 47 }
44 48
45 NetworkStateNotifier::ScopedNotifier::ScopedNotifier( 49 NetworkStateNotifier::ScopedNotifier::ScopedNotifier(
46 NetworkStateNotifier& notifier) 50 NetworkStateNotifier& notifier)
47 : m_notifier(notifier) { 51 : m_notifier(notifier) {
48 DCHECK(isMainThread()); 52 DCHECK(isMainThread());
49 m_before = 53 m_before =
50 m_notifier.m_hasOverride ? m_notifier.m_override : m_notifier.m_state; 54 m_notifier.m_hasOverride ? m_notifier.m_override : m_notifier.m_state;
51 } 55 }
52 56
53 NetworkStateNotifier::ScopedNotifier::~ScopedNotifier() { 57 NetworkStateNotifier::ScopedNotifier::~ScopedNotifier() {
54 DCHECK(isMainThread()); 58 DCHECK(isMainThread());
55 const NetworkState& after = 59 const NetworkState& after =
56 m_notifier.m_hasOverride ? m_notifier.m_override : m_notifier.m_state; 60 m_notifier.m_hasOverride ? m_notifier.m_override : m_notifier.m_state;
57 if ((after.type != m_before.type || 61 if ((after.type != m_before.type ||
58 after.maxBandwidthMbps != m_before.maxBandwidthMbps) && 62 after.maxBandwidthMbps != m_before.maxBandwidthMbps) &&
59 m_before.connectionInitialized) 63 m_before.connectionInitialized) {
60 m_notifier.notifyObservers(after.type, after.maxBandwidthMbps); 64 m_notifier.notifyObservers(m_notifier.m_connectionObservers,
61 if (after.onLine != m_before.onLine && m_before.onLineInitialized) 65 ObserverType::CONNECTION_TYPE, after);
62 Page::networkStateChanged(after.onLine); 66 }
67 if (after.onLine != m_before.onLine && m_before.onLineInitialized) {
68 m_notifier.notifyObservers(m_notifier.m_onLineStateObservers,
69 ObserverType::ONLINE_STATE, after);
70 }
63 } 71 }
64 72
65 void NetworkStateNotifier::setOnLine(bool onLine) { 73 void NetworkStateNotifier::setOnLine(bool onLine) {
66 DCHECK(isMainThread()); 74 DCHECK(isMainThread());
67 ScopedNotifier notifier(*this); 75 ScopedNotifier notifier(*this);
68 { 76 {
69 MutexLocker locker(m_mutex); 77 MutexLocker locker(m_mutex);
70 m_state.onLineInitialized = true; 78 m_state.onLineInitialized = true;
71 m_state.onLine = onLine; 79 m_state.onLine = onLine;
72 } 80 }
73 } 81 }
74 82
75 void NetworkStateNotifier::setWebConnection(WebConnectionType type, 83 void NetworkStateNotifier::setWebConnection(WebConnectionType type,
76 double maxBandwidthMbps) { 84 double maxBandwidthMbps) {
77 DCHECK(isMainThread()); 85 DCHECK(isMainThread());
78 ScopedNotifier notifier(*this); 86 ScopedNotifier notifier(*this);
79 { 87 {
80 MutexLocker locker(m_mutex); 88 MutexLocker locker(m_mutex);
81 m_state.connectionInitialized = true; 89 m_state.connectionInitialized = true;
82 m_state.type = type; 90 m_state.type = type;
83 m_state.maxBandwidthMbps = maxBandwidthMbps; 91 m_state.maxBandwidthMbps = maxBandwidthMbps;
84 } 92 }
85 } 93 }
86 94
87 void NetworkStateNotifier::addObserver(NetworkStateObserver* observer, 95 void NetworkStateNotifier::addConnectionObserver(NetworkStateObserver* observer,
88 WebTaskRunner* taskRunner) { 96 WebTaskRunner* taskRunner) {
89 DCHECK(taskRunner->runsTasksOnCurrentThread()); 97 addObserver(m_connectionObservers, observer, taskRunner);
90 DCHECK(observer);
91
92 MutexLocker locker(m_mutex);
93 ObserverListMap::AddResult result = m_observers.insert(taskRunner, nullptr);
94 if (result.isNewEntry)
95 result.storedValue->value = WTF::wrapUnique(new ObserverList);
96
97 DCHECK(result.storedValue->value->observers.find(observer) == kNotFound);
98 result.storedValue->value->observers.push_back(observer);
99 } 98 }
100 99
101 void NetworkStateNotifier::removeObserver(NetworkStateObserver* observer, 100 void NetworkStateNotifier::addOnLineObserver(NetworkStateObserver* observer,
102 WebTaskRunner* taskRunner) { 101 WebTaskRunner* taskRunner) {
103 DCHECK(taskRunner->runsTasksOnCurrentThread()); 102 addObserver(m_onLineStateObservers, observer, taskRunner);
104 DCHECK(observer); 103 }
105 104
106 ObserverList* observerList = lockAndFindObserverList(taskRunner); 105 void NetworkStateNotifier::removeConnectionObserver(
107 if (!observerList) 106 NetworkStateObserver* observer,
108 return; 107 WebTaskRunner* taskRunner) {
108 removeObserver(m_connectionObservers, observer, taskRunner);
109 }
109 110
110 Vector<NetworkStateObserver*>& observers = observerList->observers; 111 void NetworkStateNotifier::removeOnLineObserver(NetworkStateObserver* observer,
111 size_t index = observers.find(observer); 112 WebTaskRunner* taskRunner) {
112 if (index != kNotFound) { 113 removeObserver(m_onLineStateObservers, observer, taskRunner);
113 observers[index] = 0;
114 observerList->zeroedObservers.push_back(index);
115 }
116
117 if (!observerList->iterating && !observerList->zeroedObservers.isEmpty())
118 collectZeroedObservers(observerList, taskRunner);
119 } 114 }
120 115
121 void NetworkStateNotifier::setOverride(bool onLine, 116 void NetworkStateNotifier::setOverride(bool onLine,
122 WebConnectionType type, 117 WebConnectionType type,
123 double maxBandwidthMbps) { 118 double maxBandwidthMbps) {
124 DCHECK(isMainThread()); 119 DCHECK(isMainThread());
125 ScopedNotifier notifier(*this); 120 ScopedNotifier notifier(*this);
126 { 121 {
127 MutexLocker locker(m_mutex); 122 MutexLocker locker(m_mutex);
128 m_hasOverride = true; 123 m_hasOverride = true;
129 m_override.onLineInitialized = true; 124 m_override.onLineInitialized = true;
130 m_override.onLine = onLine; 125 m_override.onLine = onLine;
131 m_override.connectionInitialized = true; 126 m_override.connectionInitialized = true;
132 m_override.type = type; 127 m_override.type = type;
133 m_override.maxBandwidthMbps = maxBandwidthMbps; 128 m_override.maxBandwidthMbps = maxBandwidthMbps;
134 } 129 }
135 } 130 }
136 131
137 void NetworkStateNotifier::clearOverride() { 132 void NetworkStateNotifier::clearOverride() {
138 DCHECK(isMainThread()); 133 DCHECK(isMainThread());
139 ScopedNotifier notifier(*this); 134 ScopedNotifier notifier(*this);
140 { 135 {
141 MutexLocker locker(m_mutex); 136 MutexLocker locker(m_mutex);
142 m_hasOverride = false; 137 m_hasOverride = false;
143 } 138 }
144 } 139 }
145 140
146 void NetworkStateNotifier::notifyObservers(WebConnectionType type, 141 void NetworkStateNotifier::notifyObservers(ObserverListMap& map,
147 double maxBandwidthMbps) { 142 ObserverType type,
143 const NetworkState& state) {
148 DCHECK(isMainThread()); 144 DCHECK(isMainThread());
149 MutexLocker locker(m_mutex); 145 MutexLocker locker(m_mutex);
150 for (const auto& entry : m_observers) { 146 for (const auto& entry : map) {
151 WebTaskRunner* taskRunner = entry.key; 147 WebTaskRunner* taskRunner = entry.key;
152 taskRunner->postTask( 148 taskRunner->postTask(
153 BLINK_FROM_HERE, 149 BLINK_FROM_HERE,
154 crossThreadBind(&NetworkStateNotifier:: 150 crossThreadBind(&NetworkStateNotifier::notifyObserversOnTaskRunner,
155 notifyObserversOfConnectionChangeOnTaskRunner, 151 crossThreadUnretained(this),
156 crossThreadUnretained(this), type, maxBandwidthMbps, 152 crossThreadUnretained(&map), type,
157 crossThreadUnretained(taskRunner))); 153 crossThreadUnretained(taskRunner), state));
158 } 154 }
159 } 155 }
160 156
161 void NetworkStateNotifier::notifyObserversOfConnectionChangeOnTaskRunner( 157 void NetworkStateNotifier::notifyObserversOnTaskRunner(
162 WebConnectionType type, 158 ObserverListMap* map,
163 double maxBandwidthMbps, 159 ObserverType type,
164 WebTaskRunner* taskRunner) { 160 WebTaskRunner* taskRunner,
165 ObserverList* observerList = lockAndFindObserverList(taskRunner); 161 const NetworkState& state) {
162 ObserverList* observerList = lockAndFindObserverList(*map, taskRunner);
166 163
167 // The context could have been removed before the notification task got to 164 // The context could have been removed before the notification task got to
168 // run. 165 // run.
169 if (!observerList) 166 if (!observerList)
170 return; 167 return;
171 168
172 DCHECK(taskRunner->runsTasksOnCurrentThread()); 169 DCHECK(taskRunner->runsTasksOnCurrentThread());
173 170
174 observerList->iterating = true; 171 observerList->iterating = true;
175 172
176 for (size_t i = 0; i < observerList->observers.size(); ++i) { 173 for (size_t i = 0; i < observerList->observers.size(); ++i) {
177 // Observers removed during iteration are zeroed out, skip them. 174 // Observers removed during iteration are zeroed out, skip them.
178 if (observerList->observers[i]) 175 if (!observerList->observers[i])
179 observerList->observers[i]->connectionChange(type, maxBandwidthMbps); 176 continue;
177 switch (type) {
178 case ObserverType::ONLINE_STATE:
179 observerList->observers[i]->onLineStateChange(state.onLine);
180 continue;
181 case ObserverType::CONNECTION_TYPE:
182 observerList->observers[i]->connectionChange(state.type,
183 state.maxBandwidthMbps);
184 continue;
185 }
186 NOTREACHED();
180 } 187 }
181 188
182 observerList->iterating = false; 189 observerList->iterating = false;
183 190
184 if (!observerList->zeroedObservers.isEmpty()) 191 if (!observerList->zeroedObservers.isEmpty())
185 collectZeroedObservers(observerList, taskRunner); 192 collectZeroedObservers(*map, observerList, taskRunner);
193 }
194
195 void NetworkStateNotifier::addObserver(ObserverListMap& map,
196 NetworkStateObserver* observer,
197 WebTaskRunner* taskRunner) {
198 DCHECK(taskRunner->runsTasksOnCurrentThread());
199 DCHECK(observer);
200
201 MutexLocker locker(m_mutex);
202 ObserverListMap::AddResult result = map.insert(taskRunner, nullptr);
203 if (result.isNewEntry)
204 result.storedValue->value = WTF::wrapUnique(new ObserverList);
205
206 DCHECK(result.storedValue->value->observers.find(observer) == kNotFound);
207 result.storedValue->value->observers.push_back(observer);
208 }
209
210 void NetworkStateNotifier::removeObserver(ObserverListMap& map,
211 NetworkStateObserver* observer,
212 WebTaskRunner* taskRunner) {
213 DCHECK(taskRunner->runsTasksOnCurrentThread());
214 DCHECK(observer);
215
216 ObserverList* observerList = lockAndFindObserverList(map, taskRunner);
217 if (!observerList)
218 return;
219
220 Vector<NetworkStateObserver*>& observers = observerList->observers;
221 size_t index = observers.find(observer);
222 if (index != kNotFound) {
223 observers[index] = 0;
224 observerList->zeroedObservers.push_back(index);
225 }
226
227 if (!observerList->iterating && !observerList->zeroedObservers.isEmpty())
228 collectZeroedObservers(map, observerList, taskRunner);
186 } 229 }
187 230
188 NetworkStateNotifier::ObserverList* 231 NetworkStateNotifier::ObserverList*
189 NetworkStateNotifier::lockAndFindObserverList(WebTaskRunner* taskRunner) { 232 NetworkStateNotifier::lockAndFindObserverList(ObserverListMap& map,
233 WebTaskRunner* taskRunner) {
190 MutexLocker locker(m_mutex); 234 MutexLocker locker(m_mutex);
191 ObserverListMap::iterator it = m_observers.find(taskRunner); 235 ObserverListMap::iterator it = map.find(taskRunner);
192 return it == m_observers.end() ? nullptr : it->value.get(); 236 return it == map.end() ? nullptr : it->value.get();
193 } 237 }
194 238
195 void NetworkStateNotifier::collectZeroedObservers(ObserverList* list, 239 void NetworkStateNotifier::collectZeroedObservers(ObserverListMap& map,
240 ObserverList* list,
196 WebTaskRunner* taskRunner) { 241 WebTaskRunner* taskRunner) {
197 DCHECK(taskRunner->runsTasksOnCurrentThread()); 242 DCHECK(taskRunner->runsTasksOnCurrentThread());
198 DCHECK(!list->iterating); 243 DCHECK(!list->iterating);
199 244
200 // If any observers were removed during the iteration they will have 245 // If any observers were removed during the iteration they will have
201 // 0 values, clean them up. 246 // 0 values, clean them up.
202 for (size_t i = 0; i < list->zeroedObservers.size(); ++i) 247 for (size_t i = 0; i < list->zeroedObservers.size(); ++i)
203 list->observers.remove(list->zeroedObservers[i]); 248 list->observers.remove(list->zeroedObservers[i]);
204 249
205 list->zeroedObservers.clear(); 250 list->zeroedObservers.clear();
206 251
207 if (list->observers.isEmpty()) { 252 if (list->observers.isEmpty()) {
208 MutexLocker locker(m_mutex); 253 MutexLocker locker(m_mutex);
209 m_observers.erase(taskRunner); // deletes list 254 map.erase(taskRunner); // deletes list
210 } 255 }
211 } 256 }
212 257
213 } // namespace blink 258 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698