158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch// Copyright 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
558e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch#include "chrome/browser/extensions/api/networking_private/networking_private_event_router.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/json/json_writer.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/browser_process.h"
958e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch#include "chrome/browser/extensions/api/networking_private/networking_private_api.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/event_router_forwarder.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/profiles/profile.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/extensions/api/networking_private.h"
137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chromeos/network/network_event_log.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chromeos/network/network_state.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chromeos/network/network_state_handler.h"
16f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chromeos/network/network_state_handler_observer.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chromeos/network/onc/onc_signature.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chromeos/network/onc/onc_translator.h"
19116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chromeos/network/portal_detector/network_portal_detector.h"
20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "components/keyed_service/content/browser_context_dependency_manager.h"
214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "components/onc/onc_constants.h"
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_system.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/cros_system_api/dbus/service_constants.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using chromeos::NetworkHandler;
26c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochusing chromeos::NetworkPortalDetector;
27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using chromeos::NetworkState;
28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using chromeos::NetworkStateHandler;
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace extensions {
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class NetworkingPrivateEventRouterImpl
33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    : public NetworkingPrivateEventRouter,
34c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      public chromeos::NetworkStateHandlerObserver,
35c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      public NetworkPortalDetector::Observer {
36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public:
37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  explicit NetworkingPrivateEventRouterImpl(Profile* profile);
38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual ~NetworkingPrivateEventRouterImpl();
39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) protected:
41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // KeyedService overrides:
42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void Shutdown() OVERRIDE;
43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // EventRouter::Observer overrides:
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void OnListenerAdded(const EventListenerInfo& details) OVERRIDE;
46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void OnListenerRemoved(const EventListenerInfo& details) OVERRIDE;
47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // NetworkStateHandlerObserver overrides:
49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void NetworkListChanged() OVERRIDE;
50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void NetworkPropertiesUpdated(const NetworkState* network) OVERRIDE;
51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
52c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // NetworkPortalDetector::Observer overrides:
53c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  virtual void OnPortalDetectionCompleted(
54c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      const NetworkState* network,
55c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      const NetworkPortalDetector::CaptivePortalState& state) OVERRIDE;
56c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private:
58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Decide if we should listen for network changes or not. If there are any
59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // JavaScript listeners registered for the onNetworkChanged event, then we
60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // want to register for change notification from the network state handler.
61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Otherwise, we want to unregister and not be listening to network changes.
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  void StartOrStopListeningForNetworkChanges();
63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Profile* profile_;
65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bool listening_;
66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(NetworkingPrivateEventRouterImpl);
68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)};
69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)NetworkingPrivateEventRouterImpl::NetworkingPrivateEventRouterImpl(
71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    Profile* profile)
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : profile_(profile), listening_(false) {
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Register with the event router so we know when renderers are listening to
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // our events. We first check and see if there *is* an event router, because
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // some unit tests try to create all profile services, but don't initialize
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the event router first.
770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EventRouter* event_router = EventRouter::Get(profile_);
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (event_router) {
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    event_router->RegisterObserver(
80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        this, api::networking_private::OnNetworksChanged::kEventName);
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    event_router->RegisterObserver(
82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        this, api::networking_private::OnNetworkListChanged::kEventName);
83c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    event_router->RegisterObserver(
84c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        this, api::networking_private::OnPortalDetectionCompleted::kEventName);
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    StartOrStopListeningForNetworkChanges();
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
89f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)NetworkingPrivateEventRouterImpl::~NetworkingPrivateEventRouterImpl() {
907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK(!listening_);
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void NetworkingPrivateEventRouterImpl::Shutdown() {
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Unregister with the event router. We first check and see if there *is* an
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // event router, because some unit tests try to shutdown all profile services,
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // but didn't initialize the event router first.
970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EventRouter* event_router = EventRouter::Get(profile_);
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (event_router)
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    event_router->UnregisterObserver(this);
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (listening_) {
1027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    NetworkHandler::Get()->network_state_handler()->RemoveObserver(
1037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        this, FROM_HERE);
1047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  listening_ = false;
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void NetworkingPrivateEventRouterImpl::OnListenerAdded(
109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const EventListenerInfo& details) {
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Start listening to events from the network state handler.
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StartOrStopListeningForNetworkChanges();
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void NetworkingPrivateEventRouterImpl::OnListenerRemoved(
115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const EventListenerInfo& details) {
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Stop listening to events from the network state handler if there are no
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // more listeners.
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StartOrStopListeningForNetworkChanges();
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void NetworkingPrivateEventRouterImpl::StartOrStopListeningForNetworkChanges() {
1220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EventRouter* event_router = EventRouter::Get(profile_);
1233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  bool should_listen =
124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      event_router->HasEventListener(
125f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          api::networking_private::OnNetworksChanged::kEventName) ||
126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      event_router->HasEventListener(
127c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          api::networking_private::OnNetworkListChanged::kEventName) ||
128c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      event_router->HasEventListener(
129c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          api::networking_private::OnPortalDetectionCompleted::kEventName);
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (should_listen && !listening_) {
1327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    NetworkHandler::Get()->network_state_handler()->AddObserver(
1337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        this, FROM_HERE);
134c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    NetworkPortalDetector::Get()->AddObserver(this);
1357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  } else if (!should_listen && listening_) {
1367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    NetworkHandler::Get()->network_state_handler()->RemoveObserver(
1377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        this, FROM_HERE);
138c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    NetworkPortalDetector::Get()->RemoveObserver(this);
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  listening_ = should_listen;
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void NetworkingPrivateEventRouterImpl::NetworkListChanged() {
1440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EventRouter* event_router = EventRouter::Get(profile_);
1457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  NetworkStateHandler::NetworkStateList networks;
146f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  NetworkHandler::Get()->network_state_handler()->GetVisibleNetworkList(
147f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      &networks);
148f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!event_router->HasEventListener(
149f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)           api::networking_private::OnNetworkListChanged::kEventName)) {
1507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // TODO(stevenjb): Remove logging once crbug.com/256881 is fixed
1517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // (or at least reduce to LOG_DEBUG). Same with NET_LOG events below.
1527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    NET_LOG_EVENT("NetworkingPrivate.NetworkListChanged: No Listeners", "");
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
1557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  NET_LOG_EVENT("NetworkingPrivate.NetworkListChanged", "");
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::string> changes;
1597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  for (NetworkStateHandler::NetworkStateList::const_iterator iter =
160f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)           networks.begin();
161f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)       iter != networks.end();
162f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)       ++iter) {
163f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    changes.push_back((*iter)->guid());
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
166f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_ptr<base::ListValue> args(
167f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      api::networking_private::OnNetworkListChanged::Create(changes));
168f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_ptr<Event> extension_event(new Event(
169f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      api::networking_private::OnNetworkListChanged::kEventName, args.Pass()));
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  event_router->BroadcastEvent(extension_event.Pass());
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
173f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void NetworkingPrivateEventRouterImpl::NetworkPropertiesUpdated(
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const NetworkState* network) {
1750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EventRouter* event_router = EventRouter::Get(profile_);
176f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!event_router->HasEventListener(
177f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)           api::networking_private::OnNetworksChanged::kEventName)) {
1787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    NET_LOG_EVENT("NetworkingPrivate.NetworkPropertiesUpdated: No Listeners",
1797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                  network->path());
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
1827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  NET_LOG_EVENT("NetworkingPrivate.NetworkPropertiesUpdated",
1837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                network->path());
184f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_ptr<base::ListValue> args(
185f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      api::networking_private::OnNetworksChanged::Create(
186f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          std::vector<std::string>(1, network->guid())));
187f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_ptr<Event> extension_event(new Event(
188f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      api::networking_private::OnNetworksChanged::kEventName, args.Pass()));
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  event_router->BroadcastEvent(extension_event.Pass());
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
192c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid NetworkingPrivateEventRouterImpl::OnPortalDetectionCompleted(
193c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const NetworkState* network,
194c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const NetworkPortalDetector::CaptivePortalState& state) {
195f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const std::string path = network ? network->guid() : std::string();
196c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EventRouter* event_router = EventRouter::Get(profile_);
198c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!event_router->HasEventListener(
199c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          api::networking_private::OnPortalDetectionCompleted::kEventName)) {
200c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    NET_LOG_EVENT("NetworkingPrivate.OnPortalDetectionCompleted: No Listeners",
201c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                  path);
202c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return;
203c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
204c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  NET_LOG_EVENT("NetworkingPrivate.OnPortalDetectionCompleted", path);
205c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
206c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  api::networking_private::CaptivePortalStatus status =
207c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      api::networking_private::CAPTIVE_PORTAL_STATUS_UNKNOWN;
208c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  switch (state.status) {
209c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN:
210c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      status = api::networking_private::CAPTIVE_PORTAL_STATUS_UNKNOWN;
211c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      break;
212c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_OFFLINE:
213c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      status = api::networking_private::CAPTIVE_PORTAL_STATUS_OFFLINE;
214c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      break;
215c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE:
216c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      status = api::networking_private::CAPTIVE_PORTAL_STATUS_ONLINE;
217c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      break;
218c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL:
219c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      status = api::networking_private::CAPTIVE_PORTAL_STATUS_PORTAL;
220c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      break;
221c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED:
222c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      status =
223c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          api::networking_private::CAPTIVE_PORTAL_STATUS_PROXYAUTHREQUIRED;
224c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      break;
225c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    default:
226c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      NOTREACHED();
227c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      break;
228c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
229c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
230c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  scoped_ptr<base::ListValue> args(
231c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      api::networking_private::OnPortalDetectionCompleted::Create(
232c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          path, status));
233c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  scoped_ptr<Event> extension_event(
234c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      new Event(api::networking_private::OnPortalDetectionCompleted::kEventName,
235c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                args.Pass()));
236c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  event_router->BroadcastEvent(extension_event.Pass());
237c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
238c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
239f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)NetworkingPrivateEventRouter* NetworkingPrivateEventRouter::Create(
240f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    Profile* profile) {
241f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return new NetworkingPrivateEventRouterImpl(profile);
242f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
24358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch
244f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}  // namespace extensions
245