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.
5 #include "chrome/browser/ui/webui/chromeos/login/network_state_informer.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"
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";
30 bool HasDefaultNetworkProxyConfigured() {
31 const NetworkState* network =
32 NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
35 onc::ONCSource onc_source = onc::ONC_SOURCE_NONE;
36 scoped_ptr<ProxyConfigDictionary> proxy_dict =
37 proxy_config::GetProxyConfigForNetwork(
38 NULL, g_browser_process->local_state(), *network, &onc_source);
39 ProxyPrefs::ProxyMode mode;
40 return (proxy_dict && proxy_dict->GetMode(&mode) &&
41 mode == ProxyPrefs::MODE_FIXED_SERVERS);
44 NetworkStateInformer::State GetStateForDefaultNetwork() {
45 const NetworkState* network =
46 NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
48 return NetworkStateInformer::OFFLINE;
50 if (NetworkPortalDetector::Get()->IsEnabled()) {
51 NetworkPortalDetector::CaptivePortalState state =
52 NetworkPortalDetector::Get()->GetCaptivePortalState(network->guid());
53 NetworkPortalDetector::CaptivePortalStatus status = state.status;
54 if (status == NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN &&
55 NetworkState::StateIsConnecting(network->connection_state())) {
56 return NetworkStateInformer::CONNECTING;
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;
67 NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED &&
68 HasDefaultNetworkProxyConfigured()) {
69 return NetworkStateInformer::PROXY_AUTH_REQUIRED;
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;
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;
83 return NetworkStateInformer::OFFLINE;
88 NetworkStateInformer::NetworkStateInformer()
90 weak_ptr_factory_(this) {
93 NetworkStateInformer::~NetworkStateInformer() {
94 if (NetworkHandler::IsInitialized()) {
95 NetworkHandler::Get()->network_state_handler()->RemoveObserver(
98 NetworkPortalDetector::Get()->RemoveObserver(this);
101 void NetworkStateInformer::Init() {
103 NetworkHandler::Get()->network_state_handler()->AddObserver(
106 NetworkPortalDetector::Get()->AddAndFireObserver(this);
109 chrome::NOTIFICATION_LOGIN_PROXY_CHANGED,
110 content::NotificationService::AllSources());
112 chrome::NOTIFICATION_SESSION_STARTED,
113 content::NotificationService::AllSources());
116 void NetworkStateInformer::AddObserver(NetworkStateInformerObserver* observer) {
117 if (!observers_.HasObserver(observer))
118 observers_.AddObserver(observer);
121 void NetworkStateInformer::RemoveObserver(
122 NetworkStateInformerObserver* observer) {
123 observers_.RemoveObserver(observer);
126 void NetworkStateInformer::DefaultNetworkChanged(const NetworkState* network) {
127 UpdateStateAndNotify();
130 void NetworkStateInformer::OnPortalDetectionCompleted(
131 const NetworkState* network,
132 const NetworkPortalDetector::CaptivePortalState& state) {
133 UpdateStateAndNotify();
136 void NetworkStateInformer::Observe(
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);
145 NOTREACHED() << "Unknown notification: " << type;
148 #if !defined(USE_ATHENA)
149 void NetworkStateInformer::OnPortalDetected() {
150 UpdateStateAndNotify();
155 const char* NetworkStateInformer::StatusString(State state) {
158 return kNetworkStateOffline;
160 return kNetworkStateOnline;
162 return kNetworkStateCaptivePortal;
164 return kNetworkStateConnecting;
165 case PROXY_AUTH_REQUIRED:
166 return kNetworkStateProxyAuthRequired;
173 bool NetworkStateInformer::UpdateState() {
174 const NetworkState* default_network =
175 NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
176 State new_state = GetStateForDefaultNetwork();
177 std::string new_network_path;
178 std::string new_network_type;
179 if (default_network) {
180 new_network_path = default_network->path();
181 new_network_type = default_network->type();
184 bool updated = (new_state != state_) ||
185 (new_network_path != network_path_) ||
186 (new_network_type != network_type_);
188 network_path_ = new_network_path;
189 network_type_ = new_network_type;
191 if (updated && state_ == ONLINE) {
192 FOR_EACH_OBSERVER(NetworkStateInformerObserver, observers_,
199 void NetworkStateInformer::UpdateStateAndNotify() {
201 SendStateToObservers(ErrorScreenActor::ERROR_REASON_NETWORK_STATE_CHANGED);
203 SendStateToObservers(ErrorScreenActor::ERROR_REASON_UPDATE);
206 void NetworkStateInformer::SendStateToObservers(
207 ErrorScreenActor::ErrorReason reason) {
208 FOR_EACH_OBSERVER(NetworkStateInformerObserver, observers_,
209 UpdateState(reason));
212 } // namespace chromeos