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