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