1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "config.h" 6 #include "modules/netinfo/NetworkInformation.h" 7 8 #include "core/dom/ExecutionContext.h" 9 #include "core/events/Event.h" 10 #include "core/page/NetworkStateNotifier.h" 11 #include "modules/EventTargetModules.h" 12 #include "wtf/text/WTFString.h" 13 14 namespace { 15 16 String connectionTypeToString(blink::WebConnectionType type) 17 { 18 switch (type) { 19 case blink::ConnectionTypeCellular: 20 return "cellular"; 21 case blink::ConnectionTypeBluetooth: 22 return "bluetooth"; 23 case blink::ConnectionTypeEthernet: 24 return "ethernet"; 25 case blink::ConnectionTypeWifi: 26 return "wifi"; 27 case blink::ConnectionTypeOther: 28 return "other"; 29 case blink::ConnectionTypeNone: 30 return "none"; 31 case blink::ConnectionTypeUnknown: 32 return "unknown"; 33 } 34 ASSERT_NOT_REACHED(); 35 return "none"; 36 } 37 38 } // namespace 39 40 namespace blink { 41 42 NetworkInformation* NetworkInformation::create(ExecutionContext* context) 43 { 44 NetworkInformation* connection = adoptRefCountedGarbageCollectedWillBeNoop(new NetworkInformation(context)); 45 connection->suspendIfNeeded(); 46 return connection; 47 } 48 49 NetworkInformation::~NetworkInformation() 50 { 51 ASSERT(!m_observing); 52 } 53 54 String NetworkInformation::type() const 55 { 56 // m_type is only updated when listening for events, so ask networkStateNotifier 57 // if not listening (crbug.com/379841). 58 if (!m_observing) 59 return connectionTypeToString(networkStateNotifier().connectionType()); 60 61 // If observing, return m_type which changes when the event fires, per spec. 62 return connectionTypeToString(m_type); 63 } 64 65 void NetworkInformation::connectionTypeChange(WebConnectionType type) 66 { 67 ASSERT(executionContext()->isContextThread()); 68 69 // This can happen if the observer removes and then adds itself again 70 // during notification. 71 if (m_type == type) 72 return; 73 74 m_type = type; 75 dispatchEvent(Event::create(EventTypeNames::typechange)); 76 } 77 78 const AtomicString& NetworkInformation::interfaceName() const 79 { 80 return EventTargetNames::NetworkInformation; 81 } 82 83 ExecutionContext* NetworkInformation::executionContext() const 84 { 85 return ActiveDOMObject::executionContext(); 86 } 87 88 bool NetworkInformation::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture) 89 { 90 if (!EventTargetWithInlineData::addEventListener(eventType, listener, useCapture)) 91 return false; 92 startObserving(); 93 return true; 94 } 95 96 bool NetworkInformation::removeEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture) 97 { 98 if (!EventTargetWithInlineData::removeEventListener(eventType, listener, useCapture)) 99 return false; 100 if (!hasEventListeners()) 101 stopObserving(); 102 return true; 103 } 104 105 void NetworkInformation::removeAllEventListeners() 106 { 107 EventTargetWithInlineData::removeAllEventListeners(); 108 ASSERT(!hasEventListeners()); 109 stopObserving(); 110 } 111 112 bool NetworkInformation::hasPendingActivity() const 113 { 114 ASSERT(m_contextStopped || m_observing == hasEventListeners()); 115 116 // Prevent collection of this object when there are active listeners. 117 return m_observing; 118 } 119 120 void NetworkInformation::stop() 121 { 122 m_contextStopped = true; 123 stopObserving(); 124 } 125 126 void NetworkInformation::startObserving() 127 { 128 if (!m_observing && !m_contextStopped) { 129 m_type = networkStateNotifier().connectionType(); 130 networkStateNotifier().addObserver(this, executionContext()); 131 m_observing = true; 132 } 133 } 134 135 void NetworkInformation::stopObserving() 136 { 137 if (m_observing) { 138 networkStateNotifier().removeObserver(this, executionContext()); 139 m_observing = false; 140 } 141 } 142 143 NetworkInformation::NetworkInformation(ExecutionContext* context) 144 : ActiveDOMObject(context) 145 , m_type(networkStateNotifier().connectionType()) 146 , m_observing(false) 147 , m_contextStopped(false) 148 { 149 } 150 151 } // namespace blink 152