Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3813)

Unified Diff: chrome/browser/local_discovery/wifi/wifi_manager_nonchromeos.cc

Issue 226883002: WiFi client for GCD bootstrapping (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/local_discovery/wifi/wifi_manager_nonchromeos.cc
diff --git a/chrome/browser/local_discovery/wifi/wifi_manager_nonchromeos.cc b/chrome/browser/local_discovery/wifi/wifi_manager_nonchromeos.cc
new file mode 100644
index 0000000000000000000000000000000000000000..9568c82684e75e2d33c7baf2692f4dfa865fe3d1
--- /dev/null
+++ b/chrome/browser/local_discovery/wifi/wifi_manager_nonchromeos.cc
@@ -0,0 +1,550 @@
+// Copyright 2014 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 "base/cancelable_callback.h"
+#include "base/threading/sequenced_worker_pool.h"
+#include "base/threading/thread.h"
+#include "chrome/browser/local_discovery/wifi/wifi_manager_nonchromeos.h"
+#include "components/onc/onc_constants.h"
+#include "components/wifi/wifi_service.h"
+#include "content/public/browser/browser_thread.h"
+
+using ::wifi::WiFiService;
+
+namespace local_discovery {
+
+namespace wifi {
+
+namespace {
+
+const int kConnectionTimeoutSeconds = 10;
+
+scoped_ptr<base::DictionaryValue> MakeProperties(const std::string& ssid,
+ const std::string& password) {
+ scoped_ptr<base::DictionaryValue> properties(new base::DictionaryValue);
+
+ properties->SetString(onc::network_config::kType, onc::network_type::kWiFi);
+ base::DictionaryValue* wifi = new base::DictionaryValue;
+ properties->Set(onc::network_config::kWiFi, wifi);
+
+ wifi->SetString(onc::wifi::kSSID, ssid);
+ wifi->SetString(onc::wifi::kPassphrase, password);
+
+ return properties.Pass();
+}
+
+} // namespace
+
+class WifiManagerNonChromeos::NetworkListWatcherImpl
+ : public NetworkListWatcher {
+ public:
+ NetworkListWatcherImpl(const WifiManager::SSIDListCallback& callback,
+ base::WeakPtr<WifiManagerNonChromeos> wifi_manager);
+ virtual ~NetworkListWatcherImpl();
+
+ virtual void Start() OVERRIDE;
+
+ void OnNetworkListChanged(const std::vector<NetworkProperties>& ssid_list);
stevenjb 2014/05/23 16:42:40 I think this class would be better named NetworkLi
Noam Samuel 2014/05/24 00:15:39 Obsolete, see above.
+
+ private:
+ WifiManager::SSIDListCallback callback_;
+ bool started_;
+ base::WeakPtr<WifiManagerNonChromeos> wifi_manager_;
+
+ DISALLOW_COPY_AND_ASSIGN(NetworkListWatcherImpl);
+};
+
+class WifiManagerNonChromeos::WifiServiceWrapper {
+ public:
+ WifiServiceWrapper(
+ const base::Callback<void(const base::Closure&)>& post_callback,
+ const WifiManager::SSIDListCallback& network_list_update);
+
+ ~WifiServiceWrapper();
+
+ void Start();
+
+ void GetSSIDList(const WifiManager::SSIDListCallback& callback);
+
+ void ConfigureAndConnectPskNetwork(
+ const std::string& ssid,
+ const std::string& password,
+ const WifiManager::SuccessCallback& callback);
+
+ base::WeakPtr<WifiManagerNonChromeos::WifiServiceWrapper> AsWeakPtr();
+
+ void RequestScan();
+
+ void ConnectToNetworkByID(const std::string& network_guid,
+ const WifiManager::SuccessCallback& callback);
+
+ void RequestNetworkCredentials(
+ const std::string& network_guid,
+ const WifiManager::CredentialsCallback& callback);
+
+ private:
+ void GetSSIDListInternal(std::vector<NetworkProperties>* ssid_list);
+
+ void OnNetworkListChangedEvent(const std::vector<std::string>& network_guids);
+
+ void OnNetworksChangedEvent(const std::vector<std::string>& network_guids);
+
+ std::string GetConnectedGUID();
+
+ bool IsConnected(const std::string& network_guid);
+
+ void OnConnectToNetworkTimeout();
+
+ scoped_ptr<WiFiService> wifi_service_;
+
+ base::Callback<void(const base::Closure&)> post_callback_;
+ WifiManager::SSIDListCallback network_list_update_;
+
+ WifiManager::SuccessCallback connect_success_callback_;
+ base::CancelableClosure connect_failure_callback_;
+ std::string connected_network_guid_; // SSID of previously connected network.
Vitaly Buka (NO REVIEWS) 2014/05/23 17:49:16 // SSID of network we are connecting to. std::stri
Noam Samuel 2014/05/24 00:15:39 Done.
+ std::string
+ connecting_network_guid_; // SSID of network we are connecting to.
+
+ base::WeakPtrFactory<WifiServiceWrapper> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(WifiServiceWrapper);
+};
+
stevenjb 2014/05/23 16:42:40 Either move the implementations just below each cl
Noam Samuel 2014/05/24 00:15:39 Obsolete, see above.
+WifiManagerNonChromeos::NetworkListWatcherImpl::NetworkListWatcherImpl(
+ const WifiManager::SSIDListCallback& callback,
+ base::WeakPtr<WifiManagerNonChromeos> wifi_manager)
+ : callback_(callback), started_(false), wifi_manager_(wifi_manager) {
+}
+
+WifiManagerNonChromeos::NetworkListWatcherImpl::~NetworkListWatcherImpl() {
+ if (started_ && wifi_manager_)
+ wifi_manager_->RemoveObserver(this);
+}
+
+void WifiManagerNonChromeos::NetworkListWatcherImpl::Start() {
+ DCHECK(!started_);
+
+ if (wifi_manager_)
+ wifi_manager_->AddObserver(this);
+}
+
+void WifiManagerNonChromeos::NetworkListWatcherImpl::OnNetworkListChanged(
+ const std::vector<NetworkProperties>& ssid_list) {
+ callback_.Run(ssid_list);
+}
+
+WifiManagerNonChromeos::WifiServiceWrapper::WifiServiceWrapper(
+ const base::Callback<void(const base::Closure&)>& post_callback,
+ const WifiManager::SSIDListCallback& network_list_update)
+ : post_callback_(post_callback),
+ network_list_update_(network_list_update),
+ weak_factory_(this) {
+}
+
+WifiManagerNonChromeos::WifiServiceWrapper::~WifiServiceWrapper() {
+}
+
+void WifiManagerNonChromeos::WifiServiceWrapper::Start() {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
+ wifi_service_.reset(WiFiService::Create());
+
+ wifi_service_->Initialize(base::MessageLoopProxy::current());
+
+ wifi_service_->SetEventObservers(
+ base::MessageLoopProxy::current(),
+ base::Bind(&WifiServiceWrapper::OnNetworksChangedEvent,
+ base::Unretained(this)),
+ base::Bind(&WifiServiceWrapper::OnNetworkListChangedEvent,
+ base::Unretained(this)));
+}
+
+void WifiManagerNonChromeos::WifiServiceWrapper::GetSSIDList(
+ const WifiManager::SSIDListCallback& callback) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
+
+ std::vector<NetworkProperties> network_property_list;
+
+ GetSSIDListInternal(&network_property_list);
+
+ content::BrowserThread::PostTask(
+ content::BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(post_callback_, base::Bind(callback, network_property_list)));
stevenjb 2014/05/23 16:42:40 This requires copying the entire vector in the bin
Noam Samuel 2014/05/24 00:15:39 I assume you mean scoped_ptr<std::vector>, and not
+}
+
+void WifiManagerNonChromeos::WifiServiceWrapper::ConfigureAndConnectPskNetwork(
+ const std::string& ssid,
+ const std::string& password,
+ const WifiManager::SuccessCallback& callback) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
+ scoped_ptr<base::DictionaryValue> properties = MakeProperties(ssid, password);
mef 2014/05/23 18:22:50 You also need a to pass in wifi security type: htt
Noam Samuel 2014/05/24 00:15:39 Done-ish. For now this'll work since this method i
+
+ std::string network_guid;
+ std::string error_string;
+ wifi_service_->CreateNetwork(
+ false, properties.Pass(), &network_guid, &error_string);
stevenjb 2014/05/23 16:42:40 Is this a no-op if a matching network is already c
mef 2014/05/23 18:22:50 CreateNetwork will return an error if matching net
Noam Samuel 2014/05/24 00:15:39 Added comment
+
+ // If we cannot create the network, attempt to configure and connect to an
+ // existing network.
+ bool error = false;
+ if (!error_string.empty()) {
+ error_string.clear();
+ std::vector<NetworkProperties> network_property_list;
+ GetSSIDListInternal(&network_property_list);
+
+ network_guid.clear();
+ for (std::vector<NetworkProperties>::iterator it =
+ network_property_list.begin();
Vitaly Buka (NO REVIEWS) 2014/05/23 17:49:16 with indexes it's just one line for statement
Noam Samuel 2014/05/24 00:15:39 Done.
+ it != network_property_list.end();
+ ++it) {
+ if (it->ssid == ssid) {
stevenjb 2014/05/23 16:42:40 On Chrome OS it is possible to have more than one
mef 2014/05/23 18:22:50 WiFiService currently doesn't support multiple sec
Noam Samuel 2014/05/24 00:15:39 Added TODO
+ network_guid = it->internal_id;
+ break;
+ }
+ }
+
+ if (network_guid.empty()) {
+ error = true; // Could not create the network but it is not configured.
stevenjb 2014/05/23 16:42:40 nit: s/but/and
Noam Samuel 2014/05/24 00:15:39 Done.
+ } else {
+ properties = MakeProperties(ssid, password);
+ wifi_service_->SetProperties(
+ network_guid, properties.Pass(), &error_string);
+
+ if (!error_string.empty()) {
+ LOG(ERROR) << "Could not set properties on network: " << error_string;
+ error = true;
+ }
+ }
+ }
+
+ if (!error) {
+ ConnectToNetworkByID(network_guid, callback);
+ } else {
+ content::BrowserThread::PostTask(
+ content::BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(post_callback_, base::Bind(callback, !error)));
stevenjb 2014/05/23 16:42:40 nit: s/!error/false /* success *//
Noam Samuel 2014/05/24 00:15:39 Done.
+ }
+}
+
+void WifiManagerNonChromeos::WifiServiceWrapper::OnNetworkListChangedEvent(
+ const std::vector<std::string>& network_guids) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
+ std::vector<NetworkProperties> ssid_list;
+ GetSSIDListInternal(&ssid_list);
+ content::BrowserThread::PostTask(content::BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(network_list_update_, ssid_list));
+}
+
+void WifiManagerNonChromeos::WifiServiceWrapper::OnNetworksChangedEvent(
+ const std::vector<std::string>& network_guids) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
+ if (connecting_network_guid_.empty() ||
+ !IsConnected(connecting_network_guid_)) {
+ return;
+ }
+
+ connecting_network_guid_.clear();
+ connect_failure_callback_.Cancel();
+
+ content::BrowserThread::PostTask(
+ content::BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(post_callback_, base::Bind(connect_success_callback_, true)));
+
+ connect_success_callback_.Reset();
+}
+
+base::WeakPtr<WifiManagerNonChromeos::WifiServiceWrapper>
+WifiManagerNonChromeos::WifiServiceWrapper::AsWeakPtr() {
+ return weak_factory_.GetWeakPtr();
+}
+
+void WifiManagerNonChromeos::WifiServiceWrapper::RequestScan() {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
+ wifi_service_->RequestNetworkScan();
+}
+
+void WifiManagerNonChromeos::WifiServiceWrapper::ConnectToNetworkByID(
+ const std::string& network_guid,
+ const WifiManager::SuccessCallback& callback) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
+
+ std::string connected_network_id = GetConnectedGUID();
+ std::string error_string;
+ wifi_service_->StartConnect(network_guid, &error_string);
+
+ bool error = false;
+ if (!error_string.empty()) {
+ LOG(ERROR) << "Could not connect to network by ID: " << error_string;
+ error = true;
+ wifi_service_->StartConnect(connected_network_id, &error_string);
+ }
+
+ bool connected = IsConnected(network_guid);
+
+ if (error || connected) {
+ content::BrowserThread::PostTask(
+ content::BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(post_callback_, base::Bind(callback, !error && connected)));
stevenjb 2014/05/23 16:42:40 nit: s/!error && connected/!error/
Noam Samuel 2014/05/24 00:15:39 Done.
+ return;
+ }
+
+ connect_success_callback_ = callback;
+ connecting_network_guid_ = network_guid;
+ connected_network_guid_ = connected_network_id;
+
+ connect_failure_callback_.Reset(base::Bind(
+ &WifiServiceWrapper::OnConnectToNetworkTimeout, base::Unretained(this)));
+
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ connect_failure_callback_.callback(),
+ base::TimeDelta::FromSeconds(kConnectionTimeoutSeconds));
+}
+
+void WifiManagerNonChromeos::WifiServiceWrapper::OnConnectToNetworkTimeout() {
+ bool connected = IsConnected(connecting_network_guid_);
+ std::string error_string;
+
+ if (!connected)
+ wifi_service_->StartConnect(connected_network_guid_, &error_string);
+
+ connecting_network_guid_.clear();
+
+ content::BrowserThread::PostTask(
+ content::BrowserThread::UI,
Vitaly Buka (NO REVIEWS) 2014/05/23 17:49:16 Extract following into method. content::BrowserThr
Noam Samuel 2014/05/24 00:15:39 Done.
+ FROM_HERE,
+ base::Bind(post_callback_,
+ base::Bind(connect_success_callback_, connected)));
Vitaly Buka (NO REVIEWS) 2014/05/23 17:49:16 maybe save some callback_runner_ in constructor in
Noam Samuel 2014/05/24 00:15:39 Done.
+
+ connect_success_callback_.Reset();
+}
+
+void WifiManagerNonChromeos::WifiServiceWrapper::RequestNetworkCredentials(
+ const std::string& network_guid,
+ const WifiManager::CredentialsCallback& callback) {
+#if defined(OS_WIN)
+ NOTIMPLEMENTED();
+
+ content::BrowserThread::PostTask(
+ content::BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(post_callback_,
+ base::Bind(callback, false, std::string(), std::string())));
stevenjb 2014/05/23 16:42:40 nit: maybe declare error, ssid, and key above the
Noam Samuel 2014/05/24 00:15:39 Done.
+#else
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
Vitaly Buka (NO REVIEWS) 2014/05/23 17:49:16 move outside DCHECK FILE?
Noam Samuel 2014/05/24 00:15:39 Done.
+ base::DictionaryValue properties;
+ std::string error_string;
+ wifi_service_->GetProperties(network_guid, &properties, &error_string);
+
+ bool error = false;
+ if (!error_string.empty()) {
+ LOG(ERROR) << "Could not get network properties: " << error_string;
+ error = true;
+ }
+
+ std::string ssid;
+ if (!properties.GetString(onc::network_config::kName, &ssid)) {
+ LOG(ERROR) << "Could not get network SSID";
+ error = true;
+ }
+
+ std::string key;
+ if (!error) {
+ wifi_service_->GetKeyFromSystem(network_guid, &key, &error_string);
+
+ if (!error_string.empty()) {
+ LOG(ERROR) << "Could not get key from system: " << error_string;
+ error = true;
+ }
+ }
+
+ content::BrowserThread::PostTask(
+ content::BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(post_callback_, base::Bind(callback, !error, ssid, key)));
+#endif // OS_WIN
+}
+
+void WifiManagerNonChromeos::WifiServiceWrapper::GetSSIDListInternal(
+ std::vector<NetworkProperties>* ssid_list) {
+ base::ListValue visible_networks;
+
+ wifi_service_->GetVisibleNetworks(onc::network_type::kWiFi,
+ &visible_networks);
+
+ for (size_t i = 0; i < visible_networks.GetSize(); i++) {
+ const base::DictionaryValue* network_value = NULL;
+ NetworkProperties network_properties;
+ std::string connection_status;
+
+ if (!visible_networks.GetDictionary(i, &network_value) ||
+ !network_value->GetString(onc::network_config::kName,
+ &network_properties.ssid) ||
+ !network_value->GetString(onc::network_config::kGUID,
+ &network_properties.internal_id) ||
+ !network_value->GetString(onc::network_config::kConnectionState,
+ &connection_status)) {
+ NOTREACHED();
+ continue;
+ }
+
+ network_properties.connected =
+ (connection_status == onc::connection_state::kConnected);
+
+ ssid_list->push_back(network_properties);
+ }
+}
+
+std::string WifiManagerNonChromeos::WifiServiceWrapper::GetConnectedGUID() {
+ std::vector<NetworkProperties> ssid_list;
+ GetSSIDListInternal(&ssid_list);
+
+ for (std::vector<NetworkProperties>::const_iterator it = ssid_list.begin();
+ it != ssid_list.end();
+ ++it) {
+ if (it->connected) {
+ return it->internal_id;
+ }
stevenjb 2014/05/23 16:42:40 nit: {} unnecessary.
Noam Samuel 2014/05/24 00:15:39 Done.
+ }
+
+ return "";
+}
+
+bool WifiManagerNonChromeos::WifiServiceWrapper::IsConnected(
+ const std::string& network_guid) {
+ std::vector<NetworkProperties> ssid_list;
+ GetSSIDListInternal(&ssid_list);
+
+ for (std::vector<NetworkProperties>::const_iterator it = ssid_list.begin();
+ it != ssid_list.end();
+ ++it) {
+ if (it->connected && it->internal_id == network_guid) {
+ return true;
+ }
stevenjb 2014/05/23 16:42:40 nit: {} unnecessary.
Noam Samuel 2014/05/24 00:15:39 Done.
+ }
+
+ return false;
+}
+
+scoped_ptr<WifiManager> WifiManager::Create() {
+ return scoped_ptr<WifiManager>(new WifiManagerNonChromeos());
+}
+
+WifiManagerNonChromeos::WifiManagerNonChromeos()
+ : wifi_wrapper_(NULL), weak_factory_(this) {
+}
+
+WifiManagerNonChromeos::~WifiManagerNonChromeos() {
+ if (wifi_wrapper_) {
+ content::BrowserThread::DeleteSoon(
+ content::BrowserThread::FILE, FROM_HERE, wifi_wrapper_);
+ }
+}
+
+void WifiManagerNonChromeos::Start() {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ task_runner_ = content::BrowserThread::GetMessageLoopProxyForThread(
+ content::BrowserThread::FILE);
+
+ // Allocated on UI thread, but all initialization is done on file
+ // thread. Destroyed on file thread, which should be safe since all of the
+ // thread-unsafe members are created on the file thread.
+ wifi_wrapper_ = new WifiServiceWrapper(
+ base::Bind(&WifiManagerNonChromeos::PostClosure,
+ weak_factory_.GetWeakPtr()),
+ base::Bind(&WifiManagerNonChromeos::OnNetworkListChanged,
+ weak_factory_.GetWeakPtr()));
+
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&WifiServiceWrapper::Start, wifi_wrapper_->AsWeakPtr()));
+}
+
+void WifiManagerNonChromeos::GetSSIDList(const SSIDListCallback& callback) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ task_runner_->PostTask(FROM_HERE,
+ base::Bind(&WifiServiceWrapper::GetSSIDList,
+ wifi_wrapper_->AsWeakPtr(),
+ callback));
+}
+
+void WifiManagerNonChromeos::RequestScan() {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&WifiServiceWrapper::RequestScan, wifi_wrapper_->AsWeakPtr()));
+}
+
+void WifiManagerNonChromeos::OnNetworkListChanged(
+ const std::vector<NetworkProperties>& ssid_list) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ FOR_EACH_OBSERVER(NetworkListWatcherImpl,
+ network_list_observers_,
+ OnNetworkListChanged(ssid_list));
+}
+
+void WifiManagerNonChromeos::PostClosure(const base::Closure& callback) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ callback.Run();
+}
+
+void WifiManagerNonChromeos::ConfigureAndConnectNetwork(
+ const std::string& ssid,
+ const WifiCredentials& credentials,
+ const SuccessCallback& callback) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&WifiServiceWrapper::ConfigureAndConnectPskNetwork,
+ wifi_wrapper_->AsWeakPtr(),
+ ssid,
+ credentials.psk,
+ callback));
+}
+
+void WifiManagerNonChromeos::ConnectToNetworkByID(
+ const std::string& internal_id,
+ const SuccessCallback& callback) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ task_runner_->PostTask(FROM_HERE,
+ base::Bind(&WifiServiceWrapper::ConnectToNetworkByID,
+ wifi_wrapper_->AsWeakPtr(),
+ internal_id,
+ callback));
+}
+
+void WifiManagerNonChromeos::RequestNetworkCredentials(
+ const std::string& internal_id,
+ const CredentialsCallback& callback) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&WifiServiceWrapper::RequestNetworkCredentials,
+ wifi_wrapper_->AsWeakPtr(),
+ internal_id,
+ callback));
+}
+
+scoped_ptr<NetworkListWatcher> WifiManagerNonChromeos::CreateNetworkListWatcher(
+ const SSIDListCallback& callback) {
+ return scoped_ptr<NetworkListWatcher>(
+ new NetworkListWatcherImpl(callback, weak_factory_.GetWeakPtr()));
+}
+
+void WifiManagerNonChromeos::AddObserver(NetworkListWatcherImpl* observer) {
+ network_list_observers_.AddObserver(observer);
+}
+
+void WifiManagerNonChromeos::RemoveObserver(NetworkListWatcherImpl* observer) {
+ network_list_observers_.RemoveObserver(observer);
+}
+
+} // namespace wifi
+
+} // namespace local_discovery

Powered by Google App Engine
This is Rietveld 408576698