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/extensions/api/networking_private/networking_private_api.h" 10 #include "chrome/browser/extensions/event_router_forwarder.h" 11 #include "chrome/browser/profiles/profile.h" 12 #include "chrome/common/extensions/api/networking_private.h" 13 #include "chromeos/network/network_event_log.h" 14 #include "chromeos/network/network_state.h" 15 #include "chromeos/network/network_state_handler.h" 16 #include "chromeos/network/network_state_handler_observer.h" 17 #include "chromeos/network/onc/onc_signature.h" 18 #include "chromeos/network/onc/onc_translator.h" 19 #include "chromeos/network/portal_detector/network_portal_detector.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