• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
HandleEnableWifiError(const std::string & error_name,scoped_ptr<base::DictionaryValue> error_data)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|.
GetNetworkName(const chromeos::NetworkState & 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.
IsConnectedOrConnecting()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 
ShellNetworkController()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 
~ShellNetworkController()69 ShellNetworkController::~ShellNetworkController() {
70   chromeos::NetworkHandler::Get()->network_state_handler()->RemoveObserver(
71       this, FROM_HERE);
72   chromeos::NetworkHandler::Shutdown();
73 }
74 
NetworkListChanged()75 void ShellNetworkController::NetworkListChanged() {
76   VLOG(1) << "Network list changed";
77   ConnectIfUnconnected();
78 }
79 
DefaultNetworkChanged(const chromeos::NetworkState * state)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 
SetScanningEnabled(bool enabled)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 
RequestScan()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.
ConnectIfUnconnected()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 
HandleConnectionSuccess()155 void ShellNetworkController::HandleConnectionSuccess() {
156   VLOG(1) << "Successfully connected to network";
157   waiting_for_connection_result_ = false;
158 }
159 
HandleConnectionError(const std::string & error_name,scoped_ptr<base::DictionaryValue> error_data)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