Home | History | Annotate | Download | only in browser
      1 // Copyright 2014 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 "apps/shell/browser/shell_network_controller_chromeos.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/location.h"
      9 #include "base/logging.h"
     10 #include "base/strings/stringprintf.h"
     11 #include "base/time/time.h"
     12 #include "chromeos/network/network_connection_handler.h"
     13 #include "chromeos/network/network_handler.h"
     14 #include "chromeos/network/network_handler_callbacks.h"
     15 #include "chromeos/network/network_state.h"
     16 #include "chromeos/network/network_state_handler.h"
     17 #include "third_party/cros_system_api/dbus/service_constants.h"
     18 
     19 namespace apps {
     20 
     21 namespace {
     22 
     23 // Frequency at which networks should be scanned when not connected.
     24 const int kScanIntervalSec = 10;
     25 
     26 void HandleEnableWifiError(
     27     const std::string& error_name,
     28     scoped_ptr<base::DictionaryValue> error_data) {
     29   LOG(WARNING) << "Unable to enable wifi: " << error_name;
     30 }
     31 
     32 // Returns a human-readable name for the network described by |state|.
     33 std::string GetNetworkName(const chromeos::NetworkState& state) {
     34   return !state.name().empty() ? state.name() :
     35       base::StringPrintf("[%s]", state.type().c_str());
     36 }
     37 
     38 // Returns true if shill is either connected or connecting to a network.
     39 bool IsConnectedOrConnecting() {
     40   chromeos::NetworkStateHandler* state_handler =
     41       chromeos::NetworkHandler::Get()->network_state_handler();
     42   return state_handler->ConnectedNetworkByType(
     43              chromeos::NetworkTypePattern::Default()) ||
     44          state_handler->ConnectingNetworkByType(
     45              chromeos::NetworkTypePattern::Default());
     46 }
     47 
     48 }  // namespace
     49 
     50 ShellNetworkController::ShellNetworkController()
     51     : waiting_for_connection_result_(false),
     52       weak_ptr_factory_(this) {
     53   chromeos::NetworkHandler::Initialize();
     54   chromeos::NetworkStateHandler* state_handler =
     55       chromeos::NetworkHandler::Get()->network_state_handler();
     56   DCHECK(state_handler);
     57   state_handler->AddObserver(this, FROM_HERE);
     58   state_handler->SetTechnologyEnabled(
     59       chromeos::NetworkTypePattern::Primitive(shill::kTypeWifi),
     60       true, base::Bind(&HandleEnableWifiError));
     61 
     62   if (!IsConnectedOrConnecting()) {
     63     RequestScan();
     64     SetScanningEnabled(true);
     65     ConnectIfUnconnected();
     66   }
     67 }
     68 
     69 ShellNetworkController::~ShellNetworkController() {
     70   chromeos::NetworkHandler::Get()->network_state_handler()->RemoveObserver(
     71       this, FROM_HERE);
     72   chromeos::NetworkHandler::Shutdown();
     73 }
     74 
     75 void ShellNetworkController::NetworkListChanged() {
     76   VLOG(1) << "Network list changed";
     77   ConnectIfUnconnected();
     78 }
     79 
     80 void ShellNetworkController::DefaultNetworkChanged(
     81     const chromeos::NetworkState* state) {
     82   if (state) {
     83     VLOG(1) << "Default network state changed:"
     84             << " name=" << GetNetworkName(*state)
     85             << " path=" << state->path()
     86             << " state=" << state->connection_state();
     87   } else {
     88     VLOG(1) << "Default network state changed: [no network]";
     89   }
     90 
     91   if (IsConnectedOrConnecting()) {
     92     SetScanningEnabled(false);
     93   } else {
     94     SetScanningEnabled(true);
     95     ConnectIfUnconnected();
     96   }
     97 }
     98 
     99 void ShellNetworkController::SetScanningEnabled(bool enabled) {
    100   const bool currently_enabled = scan_timer_.IsRunning();
    101   if (enabled == currently_enabled)
    102     return;
    103 
    104   VLOG(1) << (enabled ? "Starting" : "Stopping") << " scanning";
    105   if (enabled) {
    106     scan_timer_.Start(FROM_HERE,
    107                       base::TimeDelta::FromSeconds(kScanIntervalSec),
    108                       this, &ShellNetworkController::RequestScan);
    109   } else {
    110     scan_timer_.Stop();
    111   }
    112 }
    113 
    114 void ShellNetworkController::RequestScan() {
    115   VLOG(1) << "Requesting scan";
    116   chromeos::NetworkHandler::Get()->network_state_handler()->RequestScan();
    117 }
    118 
    119 // Attempts to connect to an available network if not already connecting or
    120 // connected.
    121 void ShellNetworkController::ConnectIfUnconnected() {
    122   chromeos::NetworkHandler* handler = chromeos::NetworkHandler::Get();
    123   DCHECK(handler);
    124   if (waiting_for_connection_result_ || IsConnectedOrConnecting())
    125     return;
    126 
    127   chromeos::NetworkStateHandler::NetworkStateList state_list;
    128   handler->network_state_handler()->GetVisibleNetworkListByType(
    129       chromeos::NetworkTypePattern::WiFi(), &state_list);
    130   for (chromeos::NetworkStateHandler::NetworkStateList::const_iterator it =
    131        state_list.begin(); it != state_list.end(); ++it) {
    132     const chromeos::NetworkState* state = *it;
    133     DCHECK(state);
    134     if (!state->connectable())
    135       continue;
    136 
    137     VLOG(1) << "Connecting to network " << GetNetworkName(*state)
    138             << " with path " << state->path() << " and strength "
    139             << state->signal_strength();
    140     waiting_for_connection_result_ = true;
    141     handler->network_connection_handler()->ConnectToNetwork(
    142         state->path(),
    143         base::Bind(&ShellNetworkController::HandleConnectionSuccess,
    144                    weak_ptr_factory_.GetWeakPtr()),
    145         base::Bind(&ShellNetworkController::HandleConnectionError,
    146                    weak_ptr_factory_.GetWeakPtr()),
    147         false /* check_error_state */);
    148 
    149     return;
    150   }
    151 
    152   VLOG(1) << "Didn't find any connectable networks";
    153 }
    154 
    155 void ShellNetworkController::HandleConnectionSuccess() {
    156   VLOG(1) << "Successfully connected to network";
    157   waiting_for_connection_result_ = false;
    158 }
    159 
    160 void ShellNetworkController::HandleConnectionError(
    161     const std::string& error_name,
    162     scoped_ptr<base::DictionaryValue> error_data) {
    163   LOG(WARNING) << "Unable to connect to network: " << error_name;
    164   waiting_for_connection_result_ = false;
    165 }
    166 
    167 }  // namespace apps
    168