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

Side by Side Diff: content/browser/geolocation/wifi_data_provider_corewlan_mac.mm

Issue 6597044: Revert 76228 - Move core pieces of geolocation from chrome to content.This is... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 9 years, 9 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(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 "content/browser/geolocation/wifi_data_provider_mac.h"
8
9 #include <dlfcn.h>
10 #import <Foundation/Foundation.h>
11
12 #include "base/mac/scoped_nsautorelease_pool.h"
13 #include "base/scoped_nsobject.h"
14 #include "base/sys_string_conversions.h"
15
16 // Define a subset of the CoreWLAN interfaces we require. We can't depend on
17 // CoreWLAN.h existing as we need to build on 10.5 SDKs. We can't just send
18 // messages to an untyped id due to the build treating warnings as errors,
19 // hence the reason we need class definitions.
20 // TODO(joth): When we build all 10.6 code exclusively 10.6 SDK (or later)
21 // tidy this up to use the framework directly. See http://crbug.com/37703
22
23 @interface CWInterface : NSObject
24 + (CWInterface*)interface;
25 + (CWInterface*)interfaceWithName:(NSString*)name;
26 + (NSArray*)supportedInterfaces;
27 - (NSArray*)scanForNetworksWithParameters:(NSDictionary*)parameters
28 error:(NSError**)error;
29 @end
30
31 @interface CWNetwork : NSObject <NSCopying, NSCoding>
32 @property (nonatomic, readonly) NSString* ssid;
33 @property (nonatomic, readonly) NSString* bssid;
34 @property (nonatomic, readonly) NSData* bssidData;
35 @property (nonatomic, readonly) NSNumber* securityMode;
36 @property (nonatomic, readonly) NSNumber* phyMode;
37 @property (nonatomic, readonly) NSNumber* channel;
38 @property (nonatomic, readonly) NSNumber* rssi;
39 @property (nonatomic, readonly) NSNumber* noise;
40 @property (nonatomic, readonly) NSData* ieData;
41 @property (nonatomic, readonly) BOOL isIBSS;
42 - (BOOL)isEqualToNetwork:(CWNetwork*)network;
43 @end
44
45 class CoreWlanApi : public WifiDataProviderCommon::WlanApiInterface {
46 public:
47 CoreWlanApi() {}
48
49 // Must be called before any other interface method. Will return false if the
50 // CoreWLAN framework cannot be initialized (e.g. running on pre-10.6 OSX),
51 // in which case no other method may be called.
52 bool Init();
53
54 // WlanApiInterface
55 virtual bool GetAccessPointData(WifiData::AccessPointDataSet* data);
56
57 private:
58 scoped_nsobject<NSBundle> bundle_;
59 scoped_nsobject<NSString> merge_key_;
60
61 DISALLOW_COPY_AND_ASSIGN(CoreWlanApi);
62 };
63
64 bool CoreWlanApi::Init() {
65 // As the WLAN api binding runs on its own thread, we need to provide our own
66 // auto release pool. It's simplest to do this as an automatic variable in
67 // each method that needs it, to ensure the scoping is correct and does not
68 // interfere with any other code using autorelease pools on the thread.
69 base::mac::ScopedNSAutoreleasePool auto_pool;
70 bundle_.reset([[NSBundle alloc]
71 initWithPath:@"/System/Library/Frameworks/CoreWLAN.framework"]);
72 if (!bundle_) {
73 DVLOG(1) << "Failed to load the CoreWLAN framework bundle";
74 return false;
75 }
76
77 // Dynamically look up the value of the kCWScanKeyMerge (i.e. without build
78 // time dependency on the 10.6 specific library).
79 void* dl_handle = dlopen([[bundle_ executablePath] fileSystemRepresentation],
80 RTLD_LAZY | RTLD_LOCAL);
81 if (dl_handle) {
82 NSString* key = *reinterpret_cast<NSString**>(dlsym(dl_handle,
83 "kCWScanKeyMerge"));
84 if (key)
85 merge_key_.reset([key copy]);
86 }
87 // "Leak" dl_handle rather than dlclose it, to ensure |merge_key_|
88 // remains valid.
89 if (!merge_key_.get()) {
90 // Fall back to a known-working value should the lookup fail (if
91 // this value is itself wrong it's not the end of the world, we might just
92 // get very slightly lower quality location fixes due to SSID merges).
93 DLOG(WARNING) << "Could not dynamically load the CoreWLAN merge key";
94 merge_key_.reset([@"SCAN_MERGE" retain]);
95 }
96
97 return true;
98 }
99
100 bool CoreWlanApi::GetAccessPointData(WifiData::AccessPointDataSet* data) {
101 base::mac::ScopedNSAutoreleasePool auto_pool;
102 // Initialize the scan parameters with scan key merging disabled, so we get
103 // every AP listed in the scan without any SSID de-duping logic.
104 NSDictionary* params =
105 [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO]
106 forKey:merge_key_.get()];
107
108 Class cw_interface_class = [bundle_ classNamed:@"CWInterface"];
109 NSArray* supported_interfaces = [cw_interface_class supportedInterfaces];
110 uint interface_error_count = 0;
111 for (NSString* interface_name in supported_interfaces) {
112 CWInterface* corewlan_interface =
113 [cw_interface_class interfaceWithName:interface_name];
114 if (!corewlan_interface) {
115 DLOG(WARNING) << interface_name << ": initWithName failed";
116 ++interface_error_count;
117 continue;
118 }
119
120 NSError* err = nil;
121 NSArray* scan = [corewlan_interface scanForNetworksWithParameters:params
122 error:&err];
123 const int error_code = [err code];
124 const int count = [scan count];
125 // We could get an error code but count != 0 if the scan was interrupted,
126 // for example. For our purposes this is not fatal, so process as normal.
127 if (error_code && count == 0) {
128 DLOG(WARNING) << interface_name << ": CoreWLAN scan failed with error "
129 << error_code;
130 ++interface_error_count;
131 continue;
132 }
133 DVLOG(1) << interface_name << ": found " << count << " wifi APs";
134
135 for (CWNetwork* network in scan) {
136 DCHECK(network);
137 AccessPointData access_point_data;
138 NSData* mac = [network bssidData];
139 DCHECK([mac length] == 6);
140 access_point_data.mac_address = MacAddressAsString16(
141 static_cast<const uint8*>([mac bytes]));
142 access_point_data.radio_signal_strength = [[network rssi] intValue];
143 access_point_data.channel = [[network channel] intValue];
144 access_point_data.signal_to_noise =
145 access_point_data.radio_signal_strength - [[network noise] intValue];
146 access_point_data.ssid = base::SysNSStringToUTF16([network ssid]);
147 data->insert(access_point_data);
148 }
149 }
150 // Return true even if some interfaces failed to scan, so long as at least
151 // one interface did not fail.
152 return interface_error_count == 0 ||
153 [supported_interfaces count] > interface_error_count;
154 }
155
156 WifiDataProviderCommon::WlanApiInterface* NewCoreWlanApi() {
157 scoped_ptr<CoreWlanApi> self(new CoreWlanApi);
158 if (self->Init())
159 return self.release();
160
161 return NULL;
162 }
OLDNEW
« no previous file with comments | « content/browser/geolocation/wifi_data_provider_common_win.cc ('k') | content/browser/geolocation/wifi_data_provider_linux.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698