Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / page / NetworkStateNotifier.cpp
1 /*
2  * Copyright (C) 2008 Apple Inc. All Rights Reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
24  */
25
26 #include "config.h"
27 #include "core/page/NetworkStateNotifier.h"
28
29 #include "core/dom/CrossThreadTask.h"
30 #include "core/dom/ExecutionContext.h"
31 #include "core/page/Page.h"
32 #include "wtf/Assertions.h"
33 #include "wtf/Functional.h"
34 #include "wtf/MainThread.h"
35 #include "wtf/StdLibExtras.h"
36 #include "wtf/Threading.h"
37
38 namespace blink {
39
40 NetworkStateNotifier& networkStateNotifier()
41 {
42     AtomicallyInitializedStatic(NetworkStateNotifier*, networkStateNotifier = new NetworkStateNotifier);
43     return *networkStateNotifier;
44 }
45
46 void NetworkStateNotifier::setOnLine(bool onLine)
47 {
48     ASSERT(isMainThread());
49
50     {
51         MutexLocker locker(m_mutex);
52         if (m_isOnLine == onLine)
53             return;
54
55         m_isOnLine = onLine;
56     }
57
58     Page::networkStateChanged(onLine);
59 }
60
61 void NetworkStateNotifier::setWebConnectionType(blink::WebConnectionType type)
62 {
63     ASSERT(isMainThread());
64     if (m_testUpdatesOnly)
65         return;
66
67     setWebConnectionTypeImpl(type);
68 }
69
70 void NetworkStateNotifier::setWebConnectionTypeImpl(blink::WebConnectionType type)
71 {
72     ASSERT(isMainThread());
73
74     MutexLocker locker(m_mutex);
75     if (m_type == type)
76         return;
77     m_type = type;
78
79     for (const auto& entry : m_observers) {
80         ExecutionContext* context = entry.key;
81         context->postTask(createCrossThreadTask(&NetworkStateNotifier::notifyObserversOnContext, this, AllowCrossThreadAccess(context), type));
82     }
83 }
84
85 void NetworkStateNotifier::addObserver(NetworkStateObserver* observer, ExecutionContext* context)
86 {
87     ASSERT(context->isContextThread());
88     ASSERT(observer);
89
90     MutexLocker locker(m_mutex);
91     ObserverListMap::AddResult result = m_observers.add(context, nullptr);
92     if (result.isNewEntry)
93         result.storedValue->value = adoptPtr(new ObserverList);
94
95     ASSERT(result.storedValue->value->observers.find(observer) == kNotFound);
96     result.storedValue->value->observers.append(observer);
97 }
98
99 void NetworkStateNotifier::removeObserver(NetworkStateObserver* observer, ExecutionContext* context)
100 {
101     ASSERT(context->isContextThread());
102     ASSERT(observer);
103
104     ObserverList* observerList = lockAndFindObserverList(context);
105     if (!observerList)
106         return;
107
108     Vector<NetworkStateObserver*>& observers = observerList->observers;
109     size_t index = observers.find(observer);
110     if (index != kNotFound) {
111         observers[index] = 0;
112         observerList->zeroedObservers.append(index);
113     }
114
115     if (!observerList->iterating && !observerList->zeroedObservers.isEmpty())
116         collectZeroedObservers(observerList, context);
117 }
118
119 void NetworkStateNotifier::setTestUpdatesOnly(bool updatesOnly)
120 {
121     ASSERT(isMainThread());
122     m_testUpdatesOnly = updatesOnly;
123 }
124
125 void NetworkStateNotifier::setWebConnectionTypeForTest(blink::WebConnectionType type)
126 {
127     ASSERT(isMainThread());
128     ASSERT(m_testUpdatesOnly);
129     setWebConnectionTypeImpl(type);
130 }
131
132 void NetworkStateNotifier::notifyObserversOnContext(ExecutionContext* context, blink::WebConnectionType type)
133 {
134     ObserverList* observerList = lockAndFindObserverList(context);
135
136     // The context could have been removed before the notification task got to run.
137     if (!observerList)
138         return;
139
140     ASSERT(context->isContextThread());
141
142     observerList->iterating = true;
143
144     for (size_t i = 0; i < observerList->observers.size(); ++i) {
145         // Observers removed during iteration are zeroed out, skip them.
146         if (observerList->observers[i])
147             observerList->observers[i]->connectionTypeChange(type);
148     }
149
150     observerList->iterating = false;
151
152     if (!observerList->zeroedObservers.isEmpty())
153         collectZeroedObservers(observerList, context);
154 }
155
156 NetworkStateNotifier::ObserverList* NetworkStateNotifier::lockAndFindObserverList(ExecutionContext* context)
157 {
158     MutexLocker locker(m_mutex);
159     ObserverListMap::iterator it = m_observers.find(context);
160     return it == m_observers.end() ? 0 : it->value.get();
161 }
162
163 void NetworkStateNotifier::collectZeroedObservers(ObserverList* list, ExecutionContext* context)
164 {
165     ASSERT(context->isContextThread());
166     ASSERT(!list->iterating);
167
168     // If any observers were removed during the iteration they will have
169     // 0 values, clean them up.
170     for (size_t i = 0; i < list->zeroedObservers.size(); ++i)
171         list->observers.remove(list->zeroedObservers[i]);
172
173     list->zeroedObservers.clear();
174
175     if (list->observers.isEmpty()) {
176         MutexLocker locker(m_mutex);
177         m_observers.remove(context); // deletes list
178     }
179 }
180
181 } // namespace blink