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

Unified Diff: components/wifi/wifi_service_mac.mm

Issue 64683014: Mac OS X-specific implementation of Networking Private API. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Made networkingPrivateApi available on OS X. Created 7 years, 1 month 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
« no previous file with comments | « components/wifi/wifi_service.cc ('k') | components/wifi/wifi_test.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: components/wifi/wifi_service_mac.mm
diff --git a/components/wifi/wifi_service_mac.mm b/components/wifi/wifi_service_mac.mm
new file mode 100644
index 0000000000000000000000000000000000000000..5cb78995b7d9e4a446c4fa08afe290ca6da8d47c
--- /dev/null
+++ b/components/wifi/wifi_service_mac.mm
@@ -0,0 +1,445 @@
+// Copyright 2013 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 "components/wifi/wifi_service.h"
+
+#include "base/bind.h"
+#include "base/message_loop/message_loop.h"
+#include "components/onc/onc_constants.h"
+
+#import <CoreWLAN/CoreWLAN.h>
+
+/*
+@interface WLANListener : NSObject {
+ NSMutableArray* i_interfaces;
+}
+@end
+
+@implementation WLANListener
+
+-(void) listInterfaces
+{
+ NSLog(@"listInterfaces");
+ [i_interfaces enumerateObjectsUsingBlock:^(
+ id obj,
+ NSUInteger idx,
+ BOOL *stop)
+ {
+ CWInterface *iface = obj;
+ NSLog( @"iface %@, SSID %@, BSSID %@", iface, iface.ssid, iface.bssid);
+ }];
+}
+
+
+-(void) handleInterfaceNotification:(NSNotification*) notification
+{
+ NSLog(@"Notification Received");
+ [self listInterfaces];
+}
+
+- (void) monitorWifi
+{
+ NSLog(@"monitorWifi");
+
+ [[NSNotificationCenter defaultCenter]
+ addObserver:self
+ selector:@selector(handleInterfaceNotification:)
+ name:CWModeDidChangeNotification
+ object:nil];
+ [[NSNotificationCenter defaultCenter]
+ addObserver:self
+ selector:@selector(handleInterfaceNotification:)
+ name:CWSSIDDidChangeNotification
+ object:nil];
+ [[NSNotificationCenter defaultCenter]
+ addObserver:self
+ selector:@selector(handleInterfaceNotification:)
+ name:CWBSSIDDidChangeNotification
+ object:nil];
+ [[NSNotificationCenter defaultCenter]
+ addObserver:self
+ selector:@selector(handleInterfaceNotification:)
+ name:CWCountryCodeDidChangeNotification
+ object:nil];
+ [[NSNotificationCenter defaultCenter]
+ addObserver:self
+ selector:@selector(handleInterfaceNotification:)
+ name:CWLinkDidChangeNotification
+ object:nil];
+ [[NSNotificationCenter defaultCenter]
+ addObserver:self
+ selector:@selector(handleInterfaceNotification:)
+ name:CWPowerDidChangeNotification
+ object:nil];
+
+ NSMutableArray* ifaces = [NSMutableArray new];
+ NSSet *wifiInterfaces = [CWInterface interfaceNames];
+ [wifiInterfaces enumerateObjectsUsingBlock:^(NSString *ifName, BOOL *stop)
+ {
+ CWInterface *iface = [CWInterface interfaceWithName:ifName];
+ if ( iface ) {
+ [ifaces addObject:iface];
+ }
+ }];
+ i_interfaces = ifaces;
+
+ [self listInterfaces];
+}
+@end
+*/
+namespace wifi {
+
+// Implementation of WiFiService for Windows.
+class WiFiServiceImpl : public WiFiService, base::NonThreadSafe {
+ public:
+ WiFiServiceImpl();
+ virtual ~WiFiServiceImpl();
+
+ // WiFiService interface implementation.
+ virtual void Initialize(
+ scoped_refptr<base::SequencedTaskRunner> task_runner) OVERRIDE;
+
+ virtual void UnInitialize() OVERRIDE;
+
+ // Get Properties of network identified by |network_guid|. Populates
+ // |properties| on success, |error| on failure.
+ virtual void GetProperties(const std::string& network_guid,
+ DictionaryValue* properties,
+ std::string* error) OVERRIDE;
+
+ // Set Properties of network identified by |network_guid|. Populates |error|
+ // on failure.
+ virtual void SetProperties(const std::string& network_guid,
+ scoped_ptr<base::DictionaryValue> properties,
+ std::string* error) OVERRIDE;
+
+ // Get list of visible networks. Populates |network_list| on success.
+ virtual void GetVisibleNetworks(ListValue* network_list) OVERRIDE;
+
+ // Request network scan. Send |NetworkListChanged| event on completion.
+ virtual void RequestNetworkScan() OVERRIDE;
+
+ // Start connect to network identified by |network_guid|. Populates |error|
+ // on failure.
+ virtual void StartConnect(const std::string& network_guid,
+ std::string* error) OVERRIDE;
+
+ // Start disconnect from network identified by |network_guid|. Populates
+ // |error| on failure.
+ virtual void StartDisconnect(const std::string& network_guid,
+ std::string* error) OVERRIDE;
+
+ // Set observers to run when |NetworksChanged| and |NetworksListChanged|
+ // events needs to be sent. Notifications are posted on |message_loop_proxy|.
+ virtual void SetEventObservers(
+ scoped_refptr<base::MessageLoopProxy> message_loop_proxy,
+ const NetworkGuidListCallback& networks_changed_observer,
+ const NetworkGuidListCallback& network_list_changed_observer) OVERRIDE;
+
+ private:
+ // Check |nsError| and if is not |nil|, then store |error_name|
+ // into |error|.
+ bool CheckError(NSError* nsError,
+ const char* error_name,
+ std::string* error) const;
+
+ // Get |ssid| from unique |network_guid|.
+ NSString* SSIDFromGUID(const std::string& network_guid) const {
+ return [NSString stringWithUTF8String:network_guid.c_str()];
+ }
+
+ // Get unique |network_guid| string based on |ssid|.
+ std::string GUIDFromSSID(NSString* ssid) const {
+ if (ssid == nil)
+ return std::string();
+ return std::string([ssid UTF8String]);
+ }
+
+ // Populate |properties| from |network|.
+ void NetworkPropertiesFromCWNetwork(const CWNetwork* network,
+ NetworkProperties* properties) const;
+
+ // Convert |CWSecurityMode| into onc::wifi::k{WPA|WEP}* security constant.
+ std::string SecurityFromCWSecurityMode(CWSecurityMode security) const;
+
+ // Get the list of visible wireless networks. If |network_guid| is not empty,
+ // then only return that network.
+ NSError* GetVisibleNetworkList(const std::string& network_guid,
+ NetworkList* network_list);
+
+ // Sort networks, so connected/connecting is up front, then by type:
+ // Ethernet, WiFi, Cellular, VPN
+ static void SortNetworks(NetworkList* networks);
+
+ // Notify |network_list_changed_observer_| that list of visible networks has
+ // changed to |networks|.
+ void NotifyNetworkListChanged(const NetworkList& networks);
+
+ // Notify |networks_changed_observer_| that network |network_guid| status has
+ // changed.
+ void NotifyNetworkChanged(const std::string& network_guid);
+
+ CWInterface* interface_;
+ //WLANListener* listener_;
+
+ // Observer to get notified when network(s) have changed (e.g. connect).
+ NetworkGuidListCallback networks_changed_observer_;
+ // Observer to get notified when network list has changed (scan complete).
+ NetworkGuidListCallback network_list_changed_observer_;
+ // MessageLoopProxy to post events on UI thread.
+ scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
+ // Task runner for worker tasks.
+ scoped_refptr<base::SequencedTaskRunner> task_runner_;
+
+ // Temporary storage of network properties indexed by |network_guid|.
+ DictionaryValue network_properties_;
+};
+
+WiFiServiceImpl::WiFiServiceImpl() {
+}
+
+WiFiServiceImpl::~WiFiServiceImpl() {
+}
+
+void WiFiServiceImpl::Initialize(
+ scoped_refptr<base::SequencedTaskRunner> task_runner) {
+ task_runner_.swap(task_runner);
+ interface_ = [CWInterface interface];
+ //listener_ = [WLANListener new];
+}
+
+void WiFiServiceImpl::UnInitialize() {}
+
+void WiFiServiceImpl::GetProperties(const std::string& network_guid,
+ DictionaryValue* properties,
+ std::string* error) {
+ NetworkList network;
+ NSError* nsError = GetVisibleNetworkList(network_guid, &network);
+ if (CheckError(nsError, "Error.GetProperties", error))
+ return;
+
+ if (!network.empty()) {
+ properties->Swap(network.front().ToValue(false).get());
+ } else {
+ *error = "Error.NotFound";
+ }
+}
+
+void WiFiServiceImpl::SetProperties(
+ const std::string& network_guid,
+ scoped_ptr<base::DictionaryValue> properties,
+ std::string* error) {
+ network_properties_.SetWithoutPathExpansion(network_guid,
+ properties.release());
+}
+
+void WiFiServiceImpl::GetVisibleNetworks(ListValue* network_list) {
+ NetworkList networks;
+ NSError* nsError = GetVisibleNetworkList(std::string(), &networks);
+ if (nsError == nil && !networks.empty()) {
+ SortNetworks(&networks);
+ for (WiFiService::NetworkList::const_iterator it = networks.begin();
+ it != networks.end();
+ ++it) {
+ scoped_ptr<DictionaryValue> network(it->ToValue(true));
+ network_list->Append(network.release());
+ }
+ }
+}
+
+void WiFiServiceImpl::RequestNetworkScan() {
+ NetworkList networks;
+ NSError* nsError = GetVisibleNetworkList(std::string(), &networks);
+ if (nsError == nil && !networks.empty()) {
+ NotifyNetworkListChanged(networks);
+ }
+}
+
+void WiFiServiceImpl::StartConnect(const std::string& network_guid,
+ std::string* error) {
+ NSError* nsError = nil;
+ NSSet* networks = [interface_
+ scanForNetworksWithName:SSIDFromGUID(network_guid)
+ error:&nsError];
+
+ if (CheckError(nsError, "Error.scanForNetworksWithName", error))
+ return;
+
+ CWNetwork* network = [networks anyObject];
+ if (network != nil) {
+ // Notify that currently connected network is being disconnected.
+ NotifyNetworkChanged(GUIDFromSSID([interface_ ssid]));
+ // Check whether WiFi Password is set in |network_properties_|
+ DictionaryValue* properties;
+ DictionaryValue* wifi;
+ std::string passphrase;
+ NSString* nsPassword = nil;
+ if (network_properties_.GetDictionaryWithoutPathExpansion(network_guid,
+ &properties) &&
+ properties->GetDictionary(onc::network_type::kWiFi, &wifi) &&
+ wifi->GetString(onc::wifi::kPassphrase, &passphrase)) {
+ nsPassword = [NSString stringWithUTF8String:passphrase.c_str()];
+ }
+
+ if ([interface_ associateToNetwork:network
+ password:nsPassword
+ error:&nsError]) {
+ NotifyNetworkChanged(network_guid);
+ } else {
+ [interface_ setPower:NO error:&nsError];
+ [interface_ setPower:YES error:&nsError];
+ if (CheckError(nsError, "Error.associateToNetwork", error))
+ return;
+ NotifyNetworkChanged(GUIDFromSSID([interface_ ssid]));
+ }
+ } else {
+ *error = "Error.NotFound";
+ }
+}
+
+void WiFiServiceImpl::StartDisconnect(const std::string& network_guid,
+ std::string* error) {
+ if (NSOrderedSame == [[interface_ ssid] compare:SSIDFromGUID(network_guid)]) {
+ [interface_ disassociate];
+ NotifyNetworkChanged(network_guid);
+ } else {
+ *error = "not-connected";
+ }
+}
+
+void WiFiServiceImpl::SetEventObservers(
+ scoped_refptr<base::MessageLoopProxy> message_loop_proxy,
+ const NetworkGuidListCallback& networks_changed_observer,
+ const NetworkGuidListCallback& network_list_changed_observer) {
+ message_loop_proxy_.swap(message_loop_proxy);
+ networks_changed_observer_ = networks_changed_observer;
+ network_list_changed_observer_ = network_list_changed_observer;
+}
+
+NSError* WiFiServiceImpl::GetVisibleNetworkList(const std::string& network_guid,
+ NetworkList* network_list) {
+
+ NSError* nsError = nil;
+ NSString* networkName = nil;
+
+ if (!network_guid.empty())
+ networkName = SSIDFromGUID(network_guid);
+
+ NSSet* networks = [interface_ scanForNetworksWithName:networkName
+ error:&nsError];
+ if (nsError != nil)
+ return nsError;
+
+ std::map<std::string, NetworkProperties&> network_guids;
+
+ CWNetwork* network;
+ for(network in networks) {
+ NetworkProperties network_properties;
+ NetworkPropertiesFromCWNetwork(network, &network_properties);
+
+ if (network_guids.find(network_properties.guid) == network_guids.end()) {
+ network_list->push_back(network_properties);
+ network_guids.insert(
+ std::pair<std::string, NetworkProperties&>(
+ network_properties.guid, network_list->back()));
+ } else {
+ NetworkProperties& existing = network_guids.at(network_properties.guid);
+ existing.frequency_set.insert(*network_properties.frequency_set.begin());
+ }
+ }
+ return nil;
+}
+
+bool WiFiServiceImpl::CheckError(NSError* nsError,
+ const char* error_name,
+ std::string* error) const {
+ if (nsError != nil) {
+ *error = error_name;
+ return true;
+ }
+ return false;
+}
+
+void WiFiServiceImpl::NetworkPropertiesFromCWNetwork(
+ const CWNetwork* network,
+ NetworkProperties* properties) const {
+
+ if (NSOrderedSame == [[network ssid] compare:[interface_ ssid]])
+ properties->connection_state = onc::connection_state::kConnected;
+ else
+ properties->connection_state = onc::connection_state::kNotConnected;
+
+ properties->ssid = [[network ssid] UTF8String];
+ properties->name = properties->ssid;
+ properties->guid = GUIDFromSSID([network ssid]);
+ properties->type = onc::network_type::kWiFi;
+
+ properties->bssid = [[network bssid] UTF8String];
+ if ([[network wlanChannel] channelBand] == kCWChannelBand2GHz)
+ properties->frequency = kFrequency2400;
+ else
+ properties->frequency = kFrequency5000;
+ properties->frequency_set.insert(properties->frequency);
+ properties->security =
+ SecurityFromCWSecurityMode([[network securityMode] intValue]);
+
+ properties->signal_strength = [[network rssi] intValue];
+}
+
+std::string WiFiServiceImpl::SecurityFromCWSecurityMode(
+ CWSecurityMode security) const {
+ switch (security) {
+ case kCWSecurityModeWPA_Enterprise:
+ case kCWSecurityModeWPA2_Enterprise:
+ return onc::wifi::kWPA_EAP;
+ case kCWSecurityModeWPA_PSK:
+ case kCWSecurityModeWPA2_PSK:
+ return onc::wifi::kWPA_PSK;
+ case kCWSecurityModeWEP:
+ return onc::wifi::kWEP_PSK;
+ case kCWSecurityModeOpen:
+ return onc::wifi::kNone;
+ // TODO(mef): Figure out correct mapping.
+ case kCWSecurityModeWPS:
+ case kCWSecurityModeDynamicWEP:
+ default:
+ return onc::wifi::kWPA_EAP;
+ }
+ return onc::wifi::kWPA_EAP;
+}
+
+void WiFiServiceImpl::SortNetworks(NetworkList* networks) {
+ networks->sort(NetworkProperties::OrderByType);
+}
+
+void WiFiServiceImpl::NotifyNetworkListChanged(const NetworkList& networks) {
+ if (network_list_changed_observer_.is_null())
+ return;
+
+ NetworkGuidList current_networks;
+ for (NetworkList::const_iterator it = networks.begin();
+ it != networks.end();
+ ++it) {
+ current_networks.push_back(it->guid);
+ }
+
+ message_loop_proxy_->PostTask(
+ FROM_HERE,
+ base::Bind(network_list_changed_observer_, current_networks));
+}
+
+void WiFiServiceImpl::NotifyNetworkChanged(const std::string& network_guid) {
+ if (networks_changed_observer_.is_null())
+ return;
+
+ DLOG(INFO) << "NotifyNetworkChanged: " << network_guid;
+ NetworkGuidList changed_networks(1, network_guid);
+ message_loop_proxy_->PostTask(
+ FROM_HERE,
+ base::Bind(networks_changed_observer_, changed_networks));
+}
+
+WiFiService* WiFiService::Create() { return new WiFiServiceImpl(); }
+
+} // namespace wifi
« no previous file with comments | « components/wifi/wifi_service.cc ('k') | components/wifi/wifi_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698