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