Home | History | Annotate | Download | only in networking_private
      1 // Copyright 2013 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 "chrome/browser/extensions/api/networking_private/networking_private_event_router.h"
      6 
      7 #include "base/json/json_writer.h"
      8 #include "chrome/browser/browser_process.h"
      9 #include "chrome/browser/chromeos/net/network_portal_detector.h"
     10 #include "chrome/browser/extensions/api/networking_private/networking_private_api.h"
     11 #include "chrome/browser/extensions/event_router_forwarder.h"
     12 #include "chrome/browser/profiles/profile.h"
     13 #include "chrome/common/extensions/api/networking_private.h"
     14 #include "chromeos/network/network_event_log.h"
     15 #include "chromeos/network/network_state.h"
     16 #include "chromeos/network/network_state_handler.h"
     17 #include "chromeos/network/network_state_handler_observer.h"
     18 #include "chromeos/network/onc/onc_signature.h"
     19 #include "chromeos/network/onc/onc_translator.h"
     20 #include "components/keyed_service/content/browser_context_dependency_manager.h"
     21 #include "components/onc/onc_constants.h"
     22 #include "extensions/browser/extension_system.h"
     23 #include "third_party/cros_system_api/dbus/service_constants.h"
     24 
     25 using chromeos::NetworkHandler;
     26 using chromeos::NetworkPortalDetector;
     27 using chromeos::NetworkState;
     28 using chromeos::NetworkStateHandler;
     29 
     30 namespace extensions {
     31 
     32 class NetworkingPrivateEventRouterImpl
     33     : public NetworkingPrivateEventRouter,
     34       public chromeos::NetworkStateHandlerObserver,
     35       public NetworkPortalDetector::Observer {
     36  public:
     37   explicit NetworkingPrivateEventRouterImpl(Profile* profile);
     38   virtual ~NetworkingPrivateEventRouterImpl();
     39 
     40  protected:
     41   // KeyedService overrides:
     42   virtual void Shutdown() OVERRIDE;
     43 
     44   // EventRouter::Observer overrides:
     45   virtual void OnListenerAdded(const EventListenerInfo& details) OVERRIDE;
     46   virtual void OnListenerRemoved(const EventListenerInfo& details) OVERRIDE;
     47 
     48   // NetworkStateHandlerObserver overrides:
     49   virtual void NetworkListChanged() OVERRIDE;
     50   virtual void NetworkPropertiesUpdated(const NetworkState* network) OVERRIDE;
     51 
     52   // NetworkPortalDetector::Observer overrides:
     53   virtual void OnPortalDetectionCompleted(
     54       const NetworkState* network,
     55       const NetworkPortalDetector::CaptivePortalState& state) OVERRIDE;
     56 
     57  private:
     58   // Decide if we should listen for network changes or not. If there are any
     59   // JavaScript listeners registered for the onNetworkChanged event, then we
     60   // want to register for change notification from the network state handler.
     61   // Otherwise, we want to unregister and not be listening to network changes.
     62   void StartOrStopListeningForNetworkChanges();
     63 
     64   Profile* profile_;
     65   bool listening_;
     66 
     67   DISALLOW_COPY_AND_ASSIGN(NetworkingPrivateEventRouterImpl);
     68 };
     69 
     70 NetworkingPrivateEventRouterImpl::NetworkingPrivateEventRouterImpl(
     71     Profile* profile)
     72     : profile_(profile), listening_(false) {
     73   // Register with the event router so we know when renderers are listening to
     74   // our events. We first check and see if there *is* an event router, because
     75   // some unit tests try to create all profile services, but don't initialize
     76   // the event router first.
     77   EventRouter* event_router = EventRouter::Get(profile_);
     78   if (event_router) {
     79     event_router->RegisterObserver(
     80         this, api::networking_private::OnNetworksChanged::kEventName);
     81     event_router->RegisterObserver(
     82         this, api::networking_private::OnNetworkListChanged::kEventName);
     83     event_router->RegisterObserver(
     84         this, api::networking_private::OnPortalDetectionCompleted::kEventName);
     85     StartOrStopListeningForNetworkChanges();
     86   }
     87 }
     88 
     89 NetworkingPrivateEventRouterImpl::~NetworkingPrivateEventRouterImpl() {
     90   DCHECK(!listening_);
     91 }
     92 
     93 void NetworkingPrivateEventRouterImpl::Shutdown() {
     94   // Unregister with the event router. We first check and see if there *is* an
     95   // event router, because some unit tests try to shutdown all profile services,
     96   // but didn't initialize the event router first.
     97   EventRouter* event_router = EventRouter::Get(profile_);
     98   if (event_router)
     99     event_router->UnregisterObserver(this);
    100 
    101   if (listening_) {
    102     NetworkHandler::Get()->network_state_handler()->RemoveObserver(
    103         this, FROM_HERE);
    104   }
    105   listening_ = false;
    106 }
    107 
    108 void NetworkingPrivateEventRouterImpl::OnListenerAdded(
    109     const EventListenerInfo& details) {
    110   // Start listening to events from the network state handler.
    111   StartOrStopListeningForNetworkChanges();
    112 }
    113 
    114 void NetworkingPrivateEventRouterImpl::OnListenerRemoved(
    115     const EventListenerInfo& details) {
    116   // Stop listening to events from the network state handler if there are no
    117   // more listeners.
    118   StartOrStopListeningForNetworkChanges();
    119 }
    120 
    121 void NetworkingPrivateEventRouterImpl::StartOrStopListeningForNetworkChanges() {
    122   EventRouter* event_router = EventRouter::Get(profile_);
    123   bool should_listen =
    124       event_router->HasEventListener(
    125           api::networking_private::OnNetworksChanged::kEventName) ||
    126       event_router->HasEventListener(
    127           api::networking_private::OnNetworkListChanged::kEventName) ||
    128       event_router->HasEventListener(
    129           api::networking_private::OnPortalDetectionCompleted::kEventName);
    130 
    131   if (should_listen && !listening_) {
    132     NetworkHandler::Get()->network_state_handler()->AddObserver(
    133         this, FROM_HERE);
    134     NetworkPortalDetector::Get()->AddObserver(this);
    135   } else if (!should_listen && listening_) {
    136     NetworkHandler::Get()->network_state_handler()->RemoveObserver(
    137         this, FROM_HERE);
    138     NetworkPortalDetector::Get()->RemoveObserver(this);
    139   }
    140   listening_ = should_listen;
    141 }
    142 
    143 void NetworkingPrivateEventRouterImpl::NetworkListChanged() {
    144   EventRouter* event_router = EventRouter::Get(profile_);
    145   NetworkStateHandler::NetworkStateList networks;
    146   NetworkHandler::Get()->network_state_handler()->GetVisibleNetworkList(
    147       &networks);
    148   if (!event_router->HasEventListener(
    149            api::networking_private::OnNetworkListChanged::kEventName)) {
    150     // TODO(stevenjb): Remove logging once crbug.com/256881 is fixed
    151     // (or at least reduce to LOG_DEBUG). Same with NET_LOG events below.
    152     NET_LOG_EVENT("NetworkingPrivate.NetworkListChanged: No Listeners", "");
    153     return;
    154   }
    155 
    156   NET_LOG_EVENT("NetworkingPrivate.NetworkListChanged", "");
    157 
    158   std::vector<std::string> changes;
    159   for (NetworkStateHandler::NetworkStateList::const_iterator iter =
    160            networks.begin();
    161        iter != networks.end();
    162        ++iter) {
    163     changes.push_back((*iter)->guid());
    164   }
    165 
    166   scoped_ptr<base::ListValue> args(
    167       api::networking_private::OnNetworkListChanged::Create(changes));
    168   scoped_ptr<Event> extension_event(new Event(
    169       api::networking_private::OnNetworkListChanged::kEventName, args.Pass()));
    170   event_router->BroadcastEvent(extension_event.Pass());
    171 }
    172 
    173 void NetworkingPrivateEventRouterImpl::NetworkPropertiesUpdated(
    174     const NetworkState* network) {
    175   EventRouter* event_router = EventRouter::Get(profile_);
    176   if (!event_router->HasEventListener(
    177            api::networking_private::OnNetworksChanged::kEventName)) {
    178     NET_LOG_EVENT("NetworkingPrivate.NetworkPropertiesUpdated: No Listeners",
    179                   network->path());
    180     return;
    181   }
    182   NET_LOG_EVENT("NetworkingPrivate.NetworkPropertiesUpdated",
    183                 network->path());
    184   scoped_ptr<base::ListValue> args(
    185       api::networking_private::OnNetworksChanged::Create(
    186           std::vector<std::string>(1, network->guid())));
    187   scoped_ptr<Event> extension_event(new Event(
    188       api::networking_private::OnNetworksChanged::kEventName, args.Pass()));
    189   event_router->BroadcastEvent(extension_event.Pass());
    190 }
    191 
    192 void NetworkingPrivateEventRouterImpl::OnPortalDetectionCompleted(
    193     const NetworkState* network,
    194     const NetworkPortalDetector::CaptivePortalState& state) {
    195   const std::string path = network ? network->guid() : std::string();
    196 
    197   EventRouter* event_router = EventRouter::Get(profile_);
    198   if (!event_router->HasEventListener(
    199           api::networking_private::OnPortalDetectionCompleted::kEventName)) {
    200     NET_LOG_EVENT("NetworkingPrivate.OnPortalDetectionCompleted: No Listeners",
    201                   path);
    202     return;
    203   }
    204   NET_LOG_EVENT("NetworkingPrivate.OnPortalDetectionCompleted", path);
    205 
    206   api::networking_private::CaptivePortalStatus status =
    207       api::networking_private::CAPTIVE_PORTAL_STATUS_UNKNOWN;
    208   switch (state.status) {
    209     case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN:
    210       status = api::networking_private::CAPTIVE_PORTAL_STATUS_UNKNOWN;
    211       break;
    212     case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_OFFLINE:
    213       status = api::networking_private::CAPTIVE_PORTAL_STATUS_OFFLINE;
    214       break;
    215     case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE:
    216       status = api::networking_private::CAPTIVE_PORTAL_STATUS_ONLINE;
    217       break;
    218     case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL:
    219       status = api::networking_private::CAPTIVE_PORTAL_STATUS_PORTAL;
    220       break;
    221     case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED:
    222       status =
    223           api::networking_private::CAPTIVE_PORTAL_STATUS_PROXYAUTHREQUIRED;
    224       break;
    225     default:
    226       NOTREACHED();
    227       break;
    228   }
    229 
    230   scoped_ptr<base::ListValue> args(
    231       api::networking_private::OnPortalDetectionCompleted::Create(
    232           path, status));
    233   scoped_ptr<Event> extension_event(
    234       new Event(api::networking_private::OnPortalDetectionCompleted::kEventName,
    235                 args.Pass()));
    236   event_router->BroadcastEvent(extension_event.Pass());
    237 }
    238 
    239 NetworkingPrivateEventRouter* NetworkingPrivateEventRouter::Create(
    240     Profile* profile) {
    241   return new NetworkingPrivateEventRouterImpl(profile);
    242 }
    243 
    244 }  // namespace extensions
    245