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#ifndef NetworkStateNotifier_h
27#define NetworkStateNotifier_h
28
29#include "public/platform/WebConnectionType.h"
30#include "wtf/FastAllocBase.h"
31#include "wtf/HashMap.h"
32#include "wtf/Noncopyable.h"
33#include "wtf/ThreadingPrimitives.h"
34#include "wtf/Vector.h"
35
36namespace blink {
37
38class ExecutionContext;
39
40class NetworkStateNotifier {
41    WTF_MAKE_NONCOPYABLE(NetworkStateNotifier); WTF_MAKE_FAST_ALLOCATED;
42public:
43    class NetworkStateObserver {
44    public:
45        // Will be called on the thread of the context passed in addObserver.
46        virtual void connectionTypeChange(blink::WebConnectionType) = 0;
47    };
48
49    NetworkStateNotifier()
50        : m_isOnLine(true)
51        , m_type(blink::ConnectionTypeOther)
52        , m_testUpdatesOnly(false)
53    {
54    }
55
56    bool onLine() const
57    {
58        MutexLocker locker(m_mutex);
59        return m_isOnLine;
60    }
61
62    void setOnLine(bool);
63
64    blink::WebConnectionType connectionType() const
65    {
66        MutexLocker locker(m_mutex);
67        return m_type;
68    }
69
70    void setWebConnectionType(blink::WebConnectionType);
71
72    // Must be called on the context's thread. An added observer must be removed
73    // before its ExecutionContext is deleted. It's possible for an observer to
74    // be called twice for the same event if it is first removed and then added
75    // during notification.
76    void addObserver(NetworkStateObserver*, ExecutionContext*);
77    void removeObserver(NetworkStateObserver*, ExecutionContext*);
78
79    // The following functions are for testing purposes.
80
81    // When true, setWebConnectionType calls are ignored and only setWebConnectionTypeForTest
82    // can update the connection type. This is used for layout tests (see crbug.com/377736).
83    void setTestUpdatesOnly(bool);
84    // Tests should call this as it will change the type regardless of the value of m_testUpdatesOnly.
85    void setWebConnectionTypeForTest(blink::WebConnectionType);
86
87private:
88    struct ObserverList {
89        ObserverList()
90            : iterating(false)
91        {
92        }
93        bool iterating;
94        Vector<NetworkStateObserver*> observers;
95        Vector<size_t> zeroedObservers; // Indices in observers that are 0.
96    };
97
98    void setWebConnectionTypeImpl(blink::WebConnectionType);
99
100    typedef HashMap<ExecutionContext*, OwnPtr<ObserverList> > ObserverListMap;
101
102    void notifyObserversOnContext(ExecutionContext*, blink::WebConnectionType);
103
104    ObserverList* lockAndFindObserverList(ExecutionContext*);
105
106    // Removed observers are nulled out in the list in case the list is being
107    // iterated over. Once done iterating, call this to clean up nulled
108    // observers.
109    void collectZeroedObservers(ObserverList*, ExecutionContext*);
110
111    mutable Mutex m_mutex;
112    bool m_isOnLine;
113    blink::WebConnectionType m_type;
114    ObserverListMap m_observers;
115    bool m_testUpdatesOnly;
116};
117
118NetworkStateNotifier& networkStateNotifier();
119
120} // namespace blink
121
122#endif // NetworkStateNotifier_h
123