| 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
|
|
|