blob: a88afa71f46dccdf010bd676428f870091f19dc4 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/webui/chromeos/login/network_state_informer.h"
#include "base/bind.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chromeos/net/proxy_config_handler.h"
#include "chrome/browser/prefs/proxy_config_dictionary.h"
#include "chrome/browser/prefs/proxy_prefs.h"
#include "chromeos/network/network_state.h"
#include "chromeos/network/network_state_handler.h"
#include "net/proxy/proxy_config.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
namespace chromeos {
NetworkStateInformer::NetworkStateInformer()
: state_(OFFLINE),
weak_ptr_factory_(this) {
}
NetworkStateInformer::~NetworkStateInformer() {
if (NetworkHandler::IsInitialized()) {
NetworkHandler::Get()->network_state_handler()->RemoveObserver(
this, FROM_HERE);
}
if (NetworkPortalDetector::IsEnabledInCommandLine() &&
NetworkPortalDetector::GetInstance()) {
NetworkPortalDetector::GetInstance()->RemoveObserver(this);
}
}
void NetworkStateInformer::Init() {
UpdateState();
NetworkHandler::Get()->network_state_handler()->AddObserver(
this, FROM_HERE);
if (NetworkPortalDetector::IsEnabledInCommandLine() &&
NetworkPortalDetector::GetInstance()) {
NetworkPortalDetector::GetInstance()->AddAndFireObserver(this);
}
registrar_.Add(this,
chrome::NOTIFICATION_LOGIN_PROXY_CHANGED,
content::NotificationService::AllSources());
registrar_.Add(this,
chrome::NOTIFICATION_SESSION_STARTED,
content::NotificationService::AllSources());
}
void NetworkStateInformer::AddObserver(NetworkStateInformerObserver* observer) {
if (!observers_.HasObserver(observer))
observers_.AddObserver(observer);
}
void NetworkStateInformer::RemoveObserver(
NetworkStateInformerObserver* observer) {
observers_.RemoveObserver(observer);
}
void NetworkStateInformer::DefaultNetworkChanged(const NetworkState* network) {
UpdateStateAndNotify();
}
void NetworkStateInformer::OnPortalDetectionCompleted(
const NetworkState* network,
const NetworkPortalDetector::CaptivePortalState& state) {
UpdateStateAndNotify();
}
void NetworkStateInformer::Observe(
int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
if (type == chrome::NOTIFICATION_SESSION_STARTED)
registrar_.RemoveAll();
else if (type == chrome::NOTIFICATION_LOGIN_PROXY_CHANGED)
SendStateToObservers(ErrorScreenActor::ERROR_REASON_PROXY_CONFIG_CHANGED);
else
NOTREACHED() << "Unknown notification: " << type;
}
void NetworkStateInformer::OnPortalDetected() {
UpdateStateAndNotify();
}
bool NetworkStateInformer::UpdateState() {
const NetworkState* default_network =
NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
State new_state = OFFLINE;
std::string new_network_path;
std::string new_network_type;
if (default_network) {
new_state = GetNetworkState(default_network);
new_network_path = default_network->path();
new_network_type = default_network->type();
}
bool updated = (new_state != state_) ||
(new_network_path != network_path_) ||
(new_network_type != network_type_);
state_ = new_state;
network_path_ = new_network_path;
network_type_ = new_network_type;
if (updated && state_ == ONLINE) {
FOR_EACH_OBSERVER(NetworkStateInformerObserver, observers_,
OnNetworkReady());
}
return updated;
}
void NetworkStateInformer::UpdateStateAndNotify() {
if (UpdateState())
SendStateToObservers(ErrorScreenActor::ERROR_REASON_NETWORK_STATE_CHANGED);
else
SendStateToObservers(ErrorScreenActor::ERROR_REASON_UPDATE);
}
void NetworkStateInformer::SendStateToObservers(
ErrorScreenActor::ErrorReason reason) {
FOR_EACH_OBSERVER(NetworkStateInformerObserver, observers_,
UpdateState(reason));
}
NetworkStateInformer::State NetworkStateInformer::GetNetworkState(
const NetworkState* network) {
DCHECK(network);
if (NetworkPortalDetector::IsEnabledInCommandLine() &&
NetworkPortalDetector::GetInstance()) {
NetworkPortalDetector::CaptivePortalState state =
NetworkPortalDetector::GetInstance()->GetCaptivePortalState(network);
NetworkPortalDetector::CaptivePortalStatus status = state.status;
if (status == NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN &&
NetworkState::StateIsConnecting(network->connection_state())) {
return CONNECTING;
}
// For proxy-less networks rely on shill's online state if
// NetworkPortalDetector's state of current network is unknown.
if (status == NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE ||
(status == NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN &&
!IsProxyConfigured(network) &&
network->connection_state() == flimflam::kStateOnline)) {
return ONLINE;
}
if (status ==
NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED &&
IsProxyConfigured(network)) {
return PROXY_AUTH_REQUIRED;
}
if (status == NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL ||
(status == NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN &&
network->connection_state() == flimflam::kStatePortal))
return CAPTIVE_PORTAL;
} else {
if (NetworkState::StateIsConnecting(network->connection_state()))
return CONNECTING;
if (network->connection_state() == flimflam::kStateOnline)
return ONLINE;
if (network->connection_state() == flimflam::kStatePortal)
return CAPTIVE_PORTAL;
}
return OFFLINE;
}
bool NetworkStateInformer::IsProxyConfigured(const NetworkState* network) {
DCHECK(network);
onc::ONCSource onc_source = onc::ONC_SOURCE_NONE;
scoped_ptr<ProxyConfigDictionary> proxy_dict =
proxy_config::GetProxyConfigForNetwork(
NULL, g_browser_process->local_state(), *network, &onc_source);
ProxyPrefs::ProxyMode mode;
return (proxy_dict &&
proxy_dict->GetMode(&mode) &&
mode == ProxyPrefs::MODE_FIXED_SERVERS);
}
} // namespace chromeos