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

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

Issue 2704083002: Remove Page dependency from NetworkStateNotifier (Closed)
Patch Set: nullcheck for tests 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(
88 WebTaskRunner* taskRunner) { 96 NetworkStateObserver* observer,
89 DCHECK(taskRunner->runsTasksOnCurrentThread()); 97 PassRefPtr<WebTaskRunner> taskRunner) {
90 DCHECK(observer); 98 addObserver(m_connectionObservers, observer, std::move(taskRunner));
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 } 99 }
100 100
101 void NetworkStateNotifier::removeObserver(NetworkStateObserver* observer, 101 void NetworkStateNotifier::addOnLineObserver(
102 WebTaskRunner* taskRunner) { 102 NetworkStateObserver* observer,
103 DCHECK(taskRunner->runsTasksOnCurrentThread()); 103 PassRefPtr<WebTaskRunner> taskRunner) {
104 DCHECK(observer); 104 addObserver(m_onLineStateObservers, observer, std::move(taskRunner));
105 }
105 106
106 ObserverList* observerList = lockAndFindObserverList(taskRunner); 107 void NetworkStateNotifier::removeConnectionObserver(
107 if (!observerList) 108 NetworkStateObserver* observer,
108 return; 109 PassRefPtr<WebTaskRunner> taskRunner) {
110 removeObserver(m_connectionObservers, observer, std::move(taskRunner));
111 }
109 112
110 Vector<NetworkStateObserver*>& observers = observerList->observers; 113 void NetworkStateNotifier::removeOnLineObserver(
111 size_t index = observers.find(observer); 114 NetworkStateObserver* observer,
112 if (index != kNotFound) { 115 PassRefPtr<WebTaskRunner> taskRunner) {
113 observers[index] = 0; 116 removeObserver(m_onLineStateObservers, observer, std::move(taskRunner));
114 observerList->zeroedObservers.push_back(index);
115 }
116
117 if (!observerList->iterating && !observerList->zeroedObservers.isEmpty())
118 collectZeroedObservers(observerList, taskRunner);
119 } 117 }
120 118
121 void NetworkStateNotifier::setOverride(bool onLine, 119 void NetworkStateNotifier::setOverride(bool onLine,
122 WebConnectionType type, 120 WebConnectionType type,
123 double maxBandwidthMbps) { 121 double maxBandwidthMbps) {
124 DCHECK(isMainThread()); 122 DCHECK(isMainThread());
125 ScopedNotifier notifier(*this); 123 ScopedNotifier notifier(*this);
126 { 124 {
127 MutexLocker locker(m_mutex); 125 MutexLocker locker(m_mutex);
128 m_hasOverride = true; 126 m_hasOverride = true;
129 m_override.onLineInitialized = true; 127 m_override.onLineInitialized = true;
130 m_override.onLine = onLine; 128 m_override.onLine = onLine;
131 m_override.connectionInitialized = true; 129 m_override.connectionInitialized = true;
132 m_override.type = type; 130 m_override.type = type;
133 m_override.maxBandwidthMbps = maxBandwidthMbps; 131 m_override.maxBandwidthMbps = maxBandwidthMbps;
134 } 132 }
135 } 133 }
136 134
137 void NetworkStateNotifier::clearOverride() { 135 void NetworkStateNotifier::clearOverride() {
138 DCHECK(isMainThread()); 136 DCHECK(isMainThread());
139 ScopedNotifier notifier(*this); 137 ScopedNotifier notifier(*this);
140 { 138 {
141 MutexLocker locker(m_mutex); 139 MutexLocker locker(m_mutex);
142 m_hasOverride = false; 140 m_hasOverride = false;
143 } 141 }
144 } 142 }
145 143
146 void NetworkStateNotifier::notifyObservers(WebConnectionType type, 144 void NetworkStateNotifier::notifyObservers(ObserverListMap& map,
147 double maxBandwidthMbps) { 145 ObserverType type,
146 const NetworkState& state) {
148 DCHECK(isMainThread()); 147 DCHECK(isMainThread());
149 MutexLocker locker(m_mutex); 148 MutexLocker locker(m_mutex);
150 for (const auto& entry : m_observers) { 149 for (const auto& entry : map) {
151 WebTaskRunner* taskRunner = entry.key; 150 RefPtr<WebTaskRunner> taskRunner = entry.key;
152 taskRunner->postTask( 151 taskRunner->postTask(
153 BLINK_FROM_HERE, 152 BLINK_FROM_HERE,
154 crossThreadBind(&NetworkStateNotifier:: 153 crossThreadBind(&NetworkStateNotifier::notifyObserversOnTaskRunner,
155 notifyObserversOfConnectionChangeOnTaskRunner, 154 crossThreadUnretained(this),
156 crossThreadUnretained(this), type, maxBandwidthMbps, 155 crossThreadUnretained(&map), type, taskRunner, state));
157 crossThreadUnretained(taskRunner)));
158 } 156 }
159 } 157 }
160 158
161 void NetworkStateNotifier::notifyObserversOfConnectionChangeOnTaskRunner( 159 void NetworkStateNotifier::notifyObserversOnTaskRunner(
162 WebConnectionType type, 160 ObserverListMap* map,
163 double maxBandwidthMbps, 161 ObserverType type,
164 WebTaskRunner* taskRunner) { 162 PassRefPtr<WebTaskRunner> passTaskRunner,
165 ObserverList* observerList = lockAndFindObserverList(taskRunner); 163 const NetworkState& state) {
164 RefPtr<WebTaskRunner> taskRunner = passTaskRunner;
165 ObserverList* observerList = lockAndFindObserverList(*map, taskRunner);
166 166
167 // The context could have been removed before the notification task got to 167 // The context could have been removed before the notification task got to
168 // run. 168 // run.
169 if (!observerList) 169 if (!observerList)
170 return; 170 return;
171 171
172 DCHECK(taskRunner->runsTasksOnCurrentThread()); 172 DCHECK(taskRunner->runsTasksOnCurrentThread());
173 173
174 observerList->iterating = true; 174 observerList->iterating = true;
175 175
176 for (size_t i = 0; i < observerList->observers.size(); ++i) { 176 for (size_t i = 0; i < observerList->observers.size(); ++i) {
177 // Observers removed during iteration are zeroed out, skip them. 177 // Observers removed during iteration are zeroed out, skip them.
178 if (observerList->observers[i]) 178 if (!observerList->observers[i])
179 observerList->observers[i]->connectionChange(type, maxBandwidthMbps); 179 continue;
180 switch (type) {
181 case ObserverType::ONLINE_STATE:
182 observerList->observers[i]->onLineStateChange(state.onLine);
183 continue;
184 case ObserverType::CONNECTION_TYPE:
185 observerList->observers[i]->connectionChange(state.type,
186 state.maxBandwidthMbps);
187 continue;
188 }
189 NOTREACHED();
180 } 190 }
181 191
182 observerList->iterating = false; 192 observerList->iterating = false;
183 193
184 if (!observerList->zeroedObservers.isEmpty()) 194 if (!observerList->zeroedObservers.isEmpty())
185 collectZeroedObservers(observerList, taskRunner); 195 collectZeroedObservers(*map, observerList, taskRunner);
196 }
197
198 void NetworkStateNotifier::addObserver(ObserverListMap& map,
199 NetworkStateObserver* observer,
200 PassRefPtr<WebTaskRunner> taskRunner) {
201 DCHECK(taskRunner->runsTasksOnCurrentThread());
202 DCHECK(observer);
203
204 MutexLocker locker(m_mutex);
205 ObserverListMap::AddResult result =
206 map.insert(std::move(taskRunner), nullptr);
207 if (result.isNewEntry)
208 result.storedValue->value = WTF::makeUnique<ObserverList>();
209
210 DCHECK(result.storedValue->value->observers.find(observer) == kNotFound);
211 result.storedValue->value->observers.push_back(observer);
212 }
213
214 void NetworkStateNotifier::removeObserver(
215 ObserverListMap& map,
216 NetworkStateObserver* observer,
217 PassRefPtr<WebTaskRunner> passTaskRunner) {
218 RefPtr<WebTaskRunner> taskRunner = passTaskRunner;
219 DCHECK(taskRunner->runsTasksOnCurrentThread());
220 DCHECK(observer);
221
222 ObserverList* observerList = lockAndFindObserverList(map, taskRunner);
223 if (!observerList)
224 return;
225
226 Vector<NetworkStateObserver*>& observers = observerList->observers;
227 size_t index = observers.find(observer);
228 if (index != kNotFound) {
229 observers[index] = 0;
230 observerList->zeroedObservers.push_back(index);
231 }
232
233 if (!observerList->iterating && !observerList->zeroedObservers.isEmpty())
234 collectZeroedObservers(map, observerList, taskRunner);
186 } 235 }
187 236
188 NetworkStateNotifier::ObserverList* 237 NetworkStateNotifier::ObserverList*
189 NetworkStateNotifier::lockAndFindObserverList(WebTaskRunner* taskRunner) { 238 NetworkStateNotifier::lockAndFindObserverList(
239 ObserverListMap& map,
240 PassRefPtr<WebTaskRunner> taskRunner) {
190 MutexLocker locker(m_mutex); 241 MutexLocker locker(m_mutex);
191 ObserverListMap::iterator it = m_observers.find(taskRunner); 242 ObserverListMap::iterator it = map.find(taskRunner);
192 return it == m_observers.end() ? nullptr : it->value.get(); 243 return it == map.end() ? nullptr : it->value.get();
193 } 244 }
194 245
195 void NetworkStateNotifier::collectZeroedObservers(ObserverList* list, 246 void NetworkStateNotifier::collectZeroedObservers(
196 WebTaskRunner* taskRunner) { 247 ObserverListMap& map,
248 ObserverList* list,
249 PassRefPtr<WebTaskRunner> taskRunner) {
197 DCHECK(taskRunner->runsTasksOnCurrentThread()); 250 DCHECK(taskRunner->runsTasksOnCurrentThread());
198 DCHECK(!list->iterating); 251 DCHECK(!list->iterating);
199 252
200 // If any observers were removed during the iteration they will have 253 // If any observers were removed during the iteration they will have
201 // 0 values, clean them up. 254 // 0 values, clean them up.
202 for (size_t i = 0; i < list->zeroedObservers.size(); ++i) 255 for (size_t i = 0; i < list->zeroedObservers.size(); ++i)
203 list->observers.remove(list->zeroedObservers[i]); 256 list->observers.remove(list->zeroedObservers[i]);
204 257
205 list->zeroedObservers.clear(); 258 list->zeroedObservers.clear();
206 259
207 if (list->observers.isEmpty()) { 260 if (list->observers.isEmpty()) {
208 MutexLocker locker(m_mutex); 261 MutexLocker locker(m_mutex);
209 m_observers.erase(taskRunner); // deletes list 262 map.erase(taskRunner); // deletes list
210 } 263 }
211 } 264 }
212 265
213 } // namespace blink 266 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698