Home | History | Annotate | Download | only in netinfo
      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