Home | History | Annotate | Download | only in login
      1 // Copyright (c) 2012 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/ui/webui/chromeos/login/network_state_informer.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/logging.h"
      9 #include "base/message_loop/message_loop.h"
     10 #include "chrome/browser/browser_process.h"
     11 #include "chrome/browser/chrome_notification_types.h"
     12 #include "chrome/browser/chromeos/net/proxy_config_handler.h"
     13 #include "chrome/browser/prefs/proxy_config_dictionary.h"
     14 #include "chrome/browser/prefs/proxy_prefs.h"
     15 #include "chromeos/network/network_state.h"
     16 #include "chromeos/network/network_state_handler.h"
     17 #include "net/proxy/proxy_config.h"
     18 #include "third_party/cros_system_api/dbus/service_constants.h"
     19 
     20 namespace chromeos {
     21 
     22 NetworkStateInformer::NetworkStateInformer()
     23     : state_(OFFLINE),
     24       weak_ptr_factory_(this) {
     25 }
     26 
     27 NetworkStateInformer::~NetworkStateInformer() {
     28   if (NetworkHandler::IsInitialized()) {
     29     NetworkHandler::Get()->network_state_handler()->RemoveObserver(
     30         this, FROM_HERE);
     31   }
     32   if (NetworkPortalDetector::IsEnabledInCommandLine() &&
     33       NetworkPortalDetector::GetInstance()) {
     34     NetworkPortalDetector::GetInstance()->RemoveObserver(this);
     35   }
     36 }
     37 
     38 void NetworkStateInformer::Init() {
     39   UpdateState();
     40   NetworkHandler::Get()->network_state_handler()->AddObserver(
     41       this, FROM_HERE);
     42 
     43   if (NetworkPortalDetector::IsEnabledInCommandLine() &&
     44       NetworkPortalDetector::GetInstance()) {
     45     NetworkPortalDetector::GetInstance()->AddAndFireObserver(this);
     46   }
     47 
     48   registrar_.Add(this,
     49                  chrome::NOTIFICATION_LOGIN_PROXY_CHANGED,
     50                  content::NotificationService::AllSources());
     51   registrar_.Add(this,
     52                  chrome::NOTIFICATION_SESSION_STARTED,
     53                  content::NotificationService::AllSources());
     54 }
     55 
     56 void NetworkStateInformer::AddObserver(NetworkStateInformerObserver* observer) {
     57   if (!observers_.HasObserver(observer))
     58     observers_.AddObserver(observer);
     59 }
     60 
     61 void NetworkStateInformer::RemoveObserver(
     62     NetworkStateInformerObserver* observer) {
     63   observers_.RemoveObserver(observer);
     64 }
     65 
     66 void NetworkStateInformer::NetworkManagerChanged() {
     67   UpdateStateAndNotify();
     68 }
     69 
     70 void NetworkStateInformer::DefaultNetworkChanged(const NetworkState* network) {
     71   UpdateStateAndNotify();
     72 }
     73 
     74 void NetworkStateInformer::OnPortalDetectionCompleted(
     75     const NetworkState* network,
     76     const NetworkPortalDetector::CaptivePortalState& state) {
     77   UpdateStateAndNotify();
     78 }
     79 
     80 void NetworkStateInformer::Observe(
     81     int type,
     82     const content::NotificationSource& source,
     83     const content::NotificationDetails& details) {
     84   if (type == chrome::NOTIFICATION_SESSION_STARTED)
     85     registrar_.RemoveAll();
     86   else if (type == chrome::NOTIFICATION_LOGIN_PROXY_CHANGED)
     87     SendStateToObservers(ErrorScreenActor::ERROR_REASON_PROXY_CONFIG_CHANGED);
     88   else
     89     NOTREACHED() << "Unknown notification: " << type;
     90 }
     91 
     92 void NetworkStateInformer::OnPortalDetected() {
     93   UpdateStateAndNotify();
     94 }
     95 
     96 bool NetworkStateInformer::UpdateState() {
     97   const NetworkState* default_network =
     98       NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
     99   State new_state = OFFLINE;
    100   std::string new_network_path;
    101   std::string new_network_type;
    102   if (default_network) {
    103     new_state = GetNetworkState(default_network);
    104     new_network_path = default_network->path();
    105     new_network_type = default_network->type();
    106   }
    107 
    108   bool updated = (new_state != state_) ||
    109       (new_network_path != network_path_) ||
    110       (new_network_type != network_type_);
    111   state_ = new_state;
    112   network_path_ = new_network_path;
    113   network_type_ = new_network_type;
    114 
    115   if (updated && state_ == ONLINE) {
    116     FOR_EACH_OBSERVER(NetworkStateInformerObserver, observers_,
    117                       OnNetworkReady());
    118   }
    119 
    120   return updated;
    121 }
    122 
    123 void NetworkStateInformer::UpdateStateAndNotify() {
    124   if (UpdateState())
    125     SendStateToObservers(ErrorScreenActor::ERROR_REASON_NETWORK_STATE_CHANGED);
    126   else
    127     SendStateToObservers(ErrorScreenActor::ERROR_REASON_UPDATE);
    128 }
    129 
    130 void NetworkStateInformer::SendStateToObservers(
    131     ErrorScreenActor::ErrorReason reason) {
    132   FOR_EACH_OBSERVER(NetworkStateInformerObserver, observers_,
    133       UpdateState(reason));
    134 }
    135 
    136 NetworkStateInformer::State NetworkStateInformer::GetNetworkState(
    137     const NetworkState* network) {
    138   DCHECK(network);
    139   if (NetworkPortalDetector::IsEnabledInCommandLine() &&
    140       NetworkPortalDetector::GetInstance()) {
    141     NetworkPortalDetector::CaptivePortalState state =
    142         NetworkPortalDetector::GetInstance()->GetCaptivePortalState(network);
    143     NetworkPortalDetector::CaptivePortalStatus status = state.status;
    144     if (status == NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN &&
    145         NetworkState::StateIsConnecting(network->connection_state())) {
    146       return CONNECTING;
    147     }
    148     // For proxy-less networks rely on shill's online state if
    149     // NetworkPortalDetector's state of current network is unknown.
    150     if (status == NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE ||
    151         (status == NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN &&
    152          !IsProxyConfigured(network) &&
    153          network->connection_state() == flimflam::kStateOnline)) {
    154       return ONLINE;
    155     }
    156     if (status ==
    157         NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED &&
    158         IsProxyConfigured(network)) {
    159       return PROXY_AUTH_REQUIRED;
    160     }
    161     if (status == NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL ||
    162         (status == NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN &&
    163          network->connection_state() == flimflam::kStatePortal))
    164       return CAPTIVE_PORTAL;
    165   } else {
    166     if (NetworkState::StateIsConnecting(network->connection_state()))
    167       return CONNECTING;
    168     if (network->connection_state() == flimflam::kStateOnline)
    169       return ONLINE;
    170     if (network->connection_state() == flimflam::kStatePortal)
    171       return CAPTIVE_PORTAL;
    172   }
    173   return OFFLINE;
    174 }
    175 
    176 bool NetworkStateInformer::IsProxyConfigured(const NetworkState* network) {
    177   DCHECK(network);
    178   onc::ONCSource onc_source = onc::ONC_SOURCE_NONE;
    179   scoped_ptr<ProxyConfigDictionary> proxy_dict =
    180       proxy_config::GetProxyConfigForNetwork(
    181           NULL, g_browser_process->local_state(), *network, &onc_source);
    182   ProxyPrefs::ProxyMode mode;
    183   return (proxy_dict &&
    184           proxy_dict->GetMode(&mode) &&
    185           mode == ProxyPrefs::MODE_FIXED_SERVERS);
    186 }
    187 
    188 }  // namespace chromeos
    189