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 namespace {
     23 
     24 const char kNetworkStateOffline[] = "offline";
     25 const char kNetworkStateOnline[] = "online";
     26 const char kNetworkStateCaptivePortal[] = "behind captive portal";
     27 const char kNetworkStateConnecting[] = "connecting";
     28 const char kNetworkStateProxyAuthRequired[] = "proxy auth required";
     29 
     30 bool HasDefaultNetworkProxyConfigured() {
     31   const FavoriteState* favorite =
     32       NetworkHandler::Get()->network_state_handler()->DefaultFavoriteNetwork();
     33   if (!favorite)
     34     return false;
     35   onc::ONCSource onc_source = onc::ONC_SOURCE_NONE;
     36   scoped_ptr<ProxyConfigDictionary> proxy_dict =
     37       proxy_config::GetProxyConfigForFavoriteNetwork(
     38           NULL, g_browser_process->local_state(), *favorite, &onc_source);
     39   ProxyPrefs::ProxyMode mode;
     40   return (proxy_dict && proxy_dict->GetMode(&mode) &&
     41           mode == ProxyPrefs::MODE_FIXED_SERVERS);
     42 }
     43 
     44 NetworkStateInformer::State GetStateForDefaultNetwork() {
     45   const NetworkState* network =
     46       NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
     47   if (!network)
     48     return NetworkStateInformer::OFFLINE;
     49 
     50   if (NetworkPortalDetector::Get()->IsEnabled()) {
     51     NetworkPortalDetector::CaptivePortalState state =
     52         NetworkPortalDetector::Get()->GetCaptivePortalState(network);
     53     NetworkPortalDetector::CaptivePortalStatus status = state.status;
     54     if (status == NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN &&
     55         NetworkState::StateIsConnecting(network->connection_state())) {
     56       return NetworkStateInformer::CONNECTING;
     57     }
     58     // For proxy-less networks rely on shill's online state if
     59     // NetworkPortalDetector's state of current network is unknown.
     60     if (status == NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE ||
     61         (status == NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN &&
     62          !HasDefaultNetworkProxyConfigured() &&
     63          network->connection_state() == shill::kStateOnline)) {
     64       return NetworkStateInformer::ONLINE;
     65     }
     66     if (status ==
     67             NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED &&
     68         HasDefaultNetworkProxyConfigured()) {
     69       return NetworkStateInformer::PROXY_AUTH_REQUIRED;
     70     }
     71     if (status == NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL ||
     72         (status == NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN &&
     73          network->connection_state() == shill::kStatePortal))
     74       return NetworkStateInformer::CAPTIVE_PORTAL;
     75   } else {
     76     if (NetworkState::StateIsConnecting(network->connection_state()))
     77       return NetworkStateInformer::CONNECTING;
     78     if (network->connection_state() == shill::kStateOnline)
     79       return NetworkStateInformer::ONLINE;
     80     if (network->connection_state() == shill::kStatePortal)
     81       return NetworkStateInformer::CAPTIVE_PORTAL;
     82   }
     83   return NetworkStateInformer::OFFLINE;
     84 }
     85 
     86 }  // namespace
     87 
     88 NetworkStateInformer::NetworkStateInformer()
     89     : state_(OFFLINE),
     90       weak_ptr_factory_(this) {
     91 }
     92 
     93 NetworkStateInformer::~NetworkStateInformer() {
     94   if (NetworkHandler::IsInitialized()) {
     95     NetworkHandler::Get()->network_state_handler()->RemoveObserver(
     96         this, FROM_HERE);
     97   }
     98   NetworkPortalDetector::Get()->RemoveObserver(this);
     99 }
    100 
    101 void NetworkStateInformer::Init() {
    102   UpdateState();
    103   NetworkHandler::Get()->network_state_handler()->AddObserver(
    104       this, FROM_HERE);
    105 
    106   NetworkPortalDetector::Get()->AddAndFireObserver(this);
    107 
    108   registrar_.Add(this,
    109                  chrome::NOTIFICATION_LOGIN_PROXY_CHANGED,
    110                  content::NotificationService::AllSources());
    111   registrar_.Add(this,
    112                  chrome::NOTIFICATION_SESSION_STARTED,
    113                  content::NotificationService::AllSources());
    114 }
    115 
    116 void NetworkStateInformer::AddObserver(NetworkStateInformerObserver* observer) {
    117   if (!observers_.HasObserver(observer))
    118     observers_.AddObserver(observer);
    119 }
    120 
    121 void NetworkStateInformer::RemoveObserver(
    122     NetworkStateInformerObserver* observer) {
    123   observers_.RemoveObserver(observer);
    124 }
    125 
    126 void NetworkStateInformer::DefaultNetworkChanged(const NetworkState* network) {
    127   UpdateStateAndNotify();
    128 }
    129 
    130 void NetworkStateInformer::OnPortalDetectionCompleted(
    131     const NetworkState* network,
    132     const NetworkPortalDetector::CaptivePortalState& state) {
    133   UpdateStateAndNotify();
    134 }
    135 
    136 void NetworkStateInformer::Observe(
    137     int type,
    138     const content::NotificationSource& source,
    139     const content::NotificationDetails& details) {
    140   if (type == chrome::NOTIFICATION_SESSION_STARTED)
    141     registrar_.RemoveAll();
    142   else if (type == chrome::NOTIFICATION_LOGIN_PROXY_CHANGED)
    143     SendStateToObservers(ErrorScreenActor::ERROR_REASON_PROXY_CONFIG_CHANGED);
    144   else
    145     NOTREACHED() << "Unknown notification: " << type;
    146 }
    147 
    148 void NetworkStateInformer::OnPortalDetected() {
    149   UpdateStateAndNotify();
    150 }
    151 
    152 // static
    153 const char* NetworkStateInformer::StatusString(State state) {
    154   switch (state) {
    155     case OFFLINE:
    156       return kNetworkStateOffline;
    157     case ONLINE:
    158       return kNetworkStateOnline;
    159     case CAPTIVE_PORTAL:
    160       return kNetworkStateCaptivePortal;
    161     case CONNECTING:
    162       return kNetworkStateConnecting;
    163     case PROXY_AUTH_REQUIRED:
    164       return kNetworkStateProxyAuthRequired;
    165     default:
    166       NOTREACHED();
    167       return NULL;
    168   }
    169 }
    170 
    171 bool NetworkStateInformer::UpdateState() {
    172   const NetworkState* default_network =
    173       NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
    174   State new_state = GetStateForDefaultNetwork();
    175   std::string new_network_path;
    176   std::string new_network_type;
    177   if (default_network) {
    178     new_network_path = default_network->path();
    179     new_network_type = default_network->type();
    180   }
    181 
    182   bool updated = (new_state != state_) ||
    183       (new_network_path != network_path_) ||
    184       (new_network_type != network_type_);
    185   state_ = new_state;
    186   network_path_ = new_network_path;
    187   network_type_ = new_network_type;
    188 
    189   if (updated && state_ == ONLINE) {
    190     FOR_EACH_OBSERVER(NetworkStateInformerObserver, observers_,
    191                       OnNetworkReady());
    192   }
    193 
    194   return updated;
    195 }
    196 
    197 void NetworkStateInformer::UpdateStateAndNotify() {
    198   if (UpdateState())
    199     SendStateToObservers(ErrorScreenActor::ERROR_REASON_NETWORK_STATE_CHANGED);
    200   else
    201     SendStateToObservers(ErrorScreenActor::ERROR_REASON_UPDATE);
    202 }
    203 
    204 void NetworkStateInformer::SendStateToObservers(
    205     ErrorScreenActor::ErrorReason reason) {
    206   FOR_EACH_OBSERVER(NetworkStateInformerObserver, observers_,
    207       UpdateState(reason));
    208 }
    209 
    210 }  // namespace chromeos
    211