| OLD | NEW |
| (Empty) | |
| 1 // Copyright (c) 2010 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 // Implements a WLAN API binding for CoreWLAN, as available on OSX 10.6 |
| 6 |
| 7 #include "chrome/browser/geolocation/wifi_data_provider_mac.h" |
| 8 |
| 9 #import <Foundation/Foundation.h> |
| 10 |
| 11 #include "base/scoped_nsautorelease_pool.h" |
| 12 #include "base/scoped_nsobject.h" |
| 13 |
| 14 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 |
| 15 // If building on 10.6 we can include the framework header directly. |
| 16 #import <CoreWLAN/CoreWLAN.h> |
| 17 |
| 18 #else |
| 19 // Otherwise just define the interfaces we require. Class definitions required |
| 20 // as we treat warnings as errors so we can't pass message to an untyped id. |
| 21 |
| 22 @interface CWInterface : NSObject |
| 23 + (CWInterface*)interface; |
| 24 - (NSArray*)scanForNetworksWithParameters:(NSDictionary*)parameters |
| 25 error:(NSError**)error; |
| 26 @end |
| 27 |
| 28 @interface CWNetwork : NSObject <NSCopying, NSCoding> |
| 29 @property(readonly) NSString* ssid; |
| 30 @property(readonly) NSString* bssid; |
| 31 @property(readonly) NSData* bssidData; |
| 32 @property(readonly) NSNumber* securityMode; |
| 33 @property(readonly) NSNumber* phyMode; |
| 34 @property(readonly) NSNumber* channel; |
| 35 @property(readonly) NSNumber* rssi; |
| 36 @property(readonly) NSNumber* noise; |
| 37 @property(readonly) NSData* ieData; |
| 38 @property(readonly) BOOL isIBSS; |
| 39 - (BOOL)isEqualToNetwork:(CWNetwork*)network; |
| 40 @end |
| 41 |
| 42 // String literals derived empirically on an OSX 10.6 machine (XCode 3.2.1). |
| 43 // Commented out to avoid unused variables warnings; comment back in as needed. |
| 44 |
| 45 // static const NSString* kCWAssocKey8021XProfile = @"ASSOC_KEY_8021X_PROFILE"; |
| 46 // static const NSString* kCWAssocKeyPassphrase = @"ASSOC_KEY_PASSPHRASE"; |
| 47 // static const NSString* kCWBSSIDDidChangeNotification = |
| 48 // @"BSSID_CHANGED_NOTIFICATION"; |
| 49 // static const NSString* kCWCountryCodeDidChangeNotification = |
| 50 // @"COUNTRY_CODE_CHANGED_NOTIFICATION"; |
| 51 // static const NSString* kCWErrorDomain = @"APPLE80211_ERROR_DOMAIN"; |
| 52 // static const NSString* kCWIBSSKeyChannel = @"IBSS_KEY_CHANNEL"; |
| 53 // static const NSString* kCWIBSSKeyPassphrase = @"IBSS_KEY_PASSPHRASE"; |
| 54 // static const NSString* kCWIBSSKeySSID = @"IBSS_KEY_SSID"; |
| 55 // static const NSString* kCWLinkDidChangeNotification = |
| 56 // @"LINK_CHANGED_NOTIFICATION"; |
| 57 // static const NSString* kCWModeDidChangeNotification = |
| 58 // @"MODE_CHANGED_NOTIFICATION"; |
| 59 // static const NSString* kCWPowerDidChangeNotification = |
| 60 // @"POWER_CHANGED_NOTIFICATION"; |
| 61 // static const NSString* kCWScanKeyBSSID = @"BSSID"; |
| 62 // static const NSString* kCWScanKeyDwellTime = @"SCAN_DWELL_TIME"; |
| 63 static const NSString* kCWScanKeyMerge = @"SCAN_MERGE"; |
| 64 // static const NSString* kCWScanKeyRestTime = @"SCAN_REST_TIME"; |
| 65 // static const NSString* kCWScanKeyScanType = @"SCAN_TYPE"; |
| 66 // static const NSString* kCWScanKeySSID = @"SSID_STR"; |
| 67 // static const NSString* kCWSSIDDidChangeNotification = |
| 68 // @"SSID_CHANGED_NOTIFICATION"; |
| 69 |
| 70 #endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 |
| 71 |
| 72 class CoreWlanApi : public WifiDataProviderCommon::WlanApiInterface { |
| 73 public: |
| 74 CoreWlanApi() {} |
| 75 |
| 76 // Must be called before any other interface method. Will return false if the |
| 77 // CoreWLAN framework cannot be initialized (e.g. running on pre-10.6 OSX), |
| 78 // in which case no other method may be called. |
| 79 bool Init(); |
| 80 |
| 81 // WlanApiInterface |
| 82 virtual bool GetAccessPointData(WifiData::AccessPointDataSet* data); |
| 83 |
| 84 private: |
| 85 scoped_nsobject<NSBundle> bundle_; |
| 86 scoped_nsobject<CWInterface> corewlan_interface_; |
| 87 |
| 88 DISALLOW_COPY_AND_ASSIGN(CoreWlanApi); |
| 89 }; |
| 90 |
| 91 bool CoreWlanApi::Init() { |
| 92 // As the WLAN api binding runs on its own thread, we need to provide our own |
| 93 // auto release pool. It's simplest to do this as an automatic variable in |
| 94 // each method that needs it, to ensure the scoping is correct and does not |
| 95 // interfere with any other code using autorelease pools on the thread. |
| 96 base::ScopedNSAutoreleasePool auto_pool; |
| 97 bundle_.reset([[NSBundle alloc] |
| 98 initWithPath:@"/System/Library/Frameworks/CoreWLAN.framework"]); |
| 99 if (!bundle_) { |
| 100 DLOG(INFO) << "Failed to load the CoreWLAN framework bundle"; |
| 101 return false; |
| 102 } |
| 103 corewlan_interface_.reset([[bundle_ classNamed:@"CWInterface"] interface]); |
| 104 if (!corewlan_interface_) { |
| 105 DLOG(INFO) << "Failed to create the CWInterface instance"; |
| 106 return false; |
| 107 } |
| 108 [corewlan_interface_ retain]; |
| 109 return true; |
| 110 } |
| 111 |
| 112 bool CoreWlanApi::GetAccessPointData(WifiData::AccessPointDataSet* data) { |
| 113 base::ScopedNSAutoreleasePool auto_pool; |
| 114 DCHECK(corewlan_interface_); |
| 115 NSError* err = nil; |
| 116 // Initialize the scan parameters with scan key merging disabled, so we get |
| 117 // every AP listed in the scan without any SSID de-duping logic. |
| 118 NSDictionary* params = |
| 119 [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO] |
| 120 forKey:kCWScanKeyMerge]; |
| 121 |
| 122 NSArray* scan = [corewlan_interface_ scanForNetworksWithParameters:params |
| 123 error:&err]; |
| 124 |
| 125 const int error_code = [err code]; |
| 126 const int count = [scan count]; |
| 127 if (error_code && !count) { |
| 128 DLOG(WARNING) << "CoreWLAN scan failed " << error_code; |
| 129 return false; |
| 130 } |
| 131 DLOG(INFO) << "Found " << count << " wifi APs"; |
| 132 |
| 133 for (CWNetwork* network in scan) { |
| 134 DCHECK(network); |
| 135 AccessPointData access_point_data; |
| 136 NSData* mac = [network bssidData]; |
| 137 DCHECK([mac length] == 6); |
| 138 access_point_data.mac_address = MacAddressAsString16( |
| 139 static_cast<const uint8*>([mac bytes])); |
| 140 access_point_data.radio_signal_strength = [[network rssi] intValue]; |
| 141 access_point_data.channel = [[network channel] intValue]; |
| 142 access_point_data.signal_to_noise = |
| 143 access_point_data.radio_signal_strength - [[network noise] intValue]; |
| 144 access_point_data.ssid = UTF8ToUTF16([[network ssid] UTF8String]); |
| 145 data->insert(access_point_data); |
| 146 } |
| 147 return true; |
| 148 } |
| 149 |
| 150 WifiDataProviderCommon::WlanApiInterface* NewCoreWlanApi() { |
| 151 scoped_ptr<CoreWlanApi> self(new CoreWlanApi); |
| 152 if (self->Init()) |
| 153 return self.release(); |
| 154 |
| 155 return NULL; |
| 156 } |
| OLD | NEW |