OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #import "ios/chrome/common/physical_web/physical_web_scanner.h" | 5 #import "ios/chrome/common/physical_web/physical_web_scanner.h" |
6 | 6 |
7 #import <CoreBluetooth/CoreBluetooth.h> | 7 #import <CoreBluetooth/CoreBluetooth.h> |
8 | 8 |
9 #include <string> | 9 #include <string> |
10 #include <vector> | 10 #include <vector> |
11 | 11 |
12 #import "base/ios/weak_nsobject.h" | 12 #import "base/ios/weak_nsobject.h" |
13 #include "base/logging.h" | 13 #include "base/logging.h" |
14 #import "base/mac/scoped_nsobject.h" | 14 #import "base/mac/scoped_nsobject.h" |
15 #include "base/memory/ptr_util.h" | 15 #include "base/memory/ptr_util.h" |
16 #include "base/strings/sys_string_conversions.h" | 16 #include "base/strings/sys_string_conversions.h" |
17 #include "base/values.h" | 17 #include "base/values.h" |
18 #include "device/bluetooth/uribeacon/uri_encoder.h" | 18 #include "device/bluetooth/uribeacon/uri_encoder.h" |
19 #import "ios/chrome/common/physical_web/physical_web_device.h" | 19 #import "ios/chrome/common/physical_web/physical_web_device.h" |
20 #import "ios/chrome/common/physical_web/physical_web_request.h" | 20 #import "ios/chrome/common/physical_web/physical_web_request.h" |
21 #import "ios/chrome/common/physical_web/physical_web_types.h" | 21 #import "ios/chrome/common/physical_web/physical_web_types.h" |
22 | 22 |
23 namespace { | 23 namespace { |
24 | 24 |
25 NSString* const kUriBeaconServiceUUID = @"FED8"; | 25 NSString* const kUriBeaconServiceUUID = @"FED8"; |
26 NSString* const kEddystoneBeaconServiceUUID = @"FEAA"; | 26 NSString* const kEddystoneBeaconServiceUUID = @"FEAA"; |
27 | 27 |
28 // The length of time in seconds since a URL was last seen before it should be | |
29 // considered lost (ie, no longer nearby). | |
30 const NSTimeInterval kLostThresholdSeconds = 15.0; | |
31 // The time interval in seconds between checks for lost URLs. | |
32 const NSTimeInterval kUpdateIntervalSeconds = 6.0; | |
33 | |
28 enum BeaconType { | 34 enum BeaconType { |
29 BEACON_TYPE_NONE, | 35 BEACON_TYPE_NONE, |
30 BEACON_TYPE_URIBEACON, | 36 BEACON_TYPE_URIBEACON, |
31 BEACON_TYPE_EDDYSTONE, | 37 BEACON_TYPE_EDDYSTONE, |
32 }; | 38 }; |
33 | 39 |
34 } // namespace | 40 } // namespace |
35 | 41 |
36 @interface PhysicalWebScanner ()<CBCentralManagerDelegate> | 42 @interface PhysicalWebScanner ()<CBCentralManagerDelegate> |
37 | 43 |
38 // Decodes the UriBeacon information in the given |data| and a beacon |type| to | 44 // Decodes the UriBeacon information in the given |data| and a beacon |type| to |
39 // return an unresolved PhysicalWebDevice instance. It also stores the given | 45 // return an unresolved PhysicalWebDevice instance. It also stores the given |
40 // |rssi| in the result. | 46 // |rssi| in the result. |
41 + (PhysicalWebDevice*)newDeviceFromData:(NSData*)data | 47 + (PhysicalWebDevice*)newDeviceFromData:(NSData*)data |
42 rssi:(int)rssi | 48 rssi:(int)rssi |
43 type:(BeaconType)type; | 49 type:(BeaconType)type; |
44 // Starts the CoreBluetooth scanner when the bluetooth is powered on. | 50 // Starts the CoreBluetooth scanner when the bluetooth is powered on and starts |
51 // the update timer. | |
45 - (void)reallyStart; | 52 - (void)reallyStart; |
53 // Stops the CoreBluetooth scanner and update timer. | |
54 - (void)reallyStop; | |
55 // Timer callback to check for lost URLs based on the elapsed time since they | |
56 // were last seen. | |
57 - (void)onUpdate:(NSTimer*)timer; | |
Olivier
2016/10/19 10:22:54
NIT: rename. Update means there is an update.
Rena
mattreynolds
2016/10/19 18:20:21
Done.
| |
46 // Requests metadata of a device if the same URL has not been requested before. | 58 // Requests metadata of a device if the same URL has not been requested before. |
47 - (void)requestMetadataForDevice:(PhysicalWebDevice*)device; | 59 - (void)requestMetadataForDevice:(PhysicalWebDevice*)device; |
48 // Returns the beacon type given the advertisement data. | 60 // Returns the beacon type given the advertisement data. |
49 + (BeaconType)beaconTypeForAdvertisementData:(NSDictionary*)advertisementData; | 61 + (BeaconType)beaconTypeForAdvertisementData:(NSDictionary*)advertisementData; |
50 | 62 |
51 @end | 63 @end |
52 | 64 |
53 @implementation PhysicalWebScanner { | 65 @implementation PhysicalWebScanner { |
54 // Delegate that will be notified when the list of devices change. | 66 // Delegate that will be notified when the list of devices change. |
55 id<PhysicalWebScannerDelegate> delegate_; | 67 id<PhysicalWebScannerDelegate> delegate_; |
56 // The value of |started_| is YES when the scanner has been started and NO | 68 // The value of |started_| is YES when the scanner has been started and NO |
57 // when it's been stopped. The initial value is NO. | 69 // when it's been stopped. The initial value is NO. |
58 BOOL started_; | 70 BOOL started_; |
59 // The value is valid when the scanner has been started. If bluetooth is not | 71 // The value is valid when the scanner has been started. If bluetooth is not |
60 // powered on, the value is YES, if it's powered on and the CoreBluetooth | 72 // powered on, the value is YES, if it's powered on and the CoreBluetooth |
61 // scanner has started, the value is NO. | 73 // scanner has started, the value is NO. |
62 BOOL pendingStart_; | 74 BOOL pendingStart_; |
63 // List of PhysicalWebRequest that we're waiting the response from. | 75 // List of PhysicalWebRequest that we're waiting the response from. |
64 base::scoped_nsobject<NSMutableArray> pendingRequests_; | 76 base::scoped_nsobject<NSMutableArray> pendingRequests_; |
65 // List of resolved PhysicalWebDevice. | 77 // List of resolved PhysicalWebDevice. |
66 base::scoped_nsobject<NSMutableArray> devices_; | 78 base::scoped_nsobject<NSMutableArray> devices_; |
67 // List of URLs that have been resolved or have a pending resolution from a | 79 // List of URLs that have been resolved or have a pending resolution from a |
68 // PhysicalWebRequest. | 80 // PhysicalWebRequest. |
69 base::scoped_nsobject<NSMutableSet> devicesUrls_; | 81 base::scoped_nsobject<NSMutableSet> devicesUrls_; |
70 // List of final URLs that have been resolved. This set will help us | 82 // List of final URLs that have been resolved. This set will help us |
71 // deduplicate the final URLs. | 83 // deduplicate the final URLs. |
72 base::scoped_nsobject<NSMutableSet> finalUrls_; | 84 base::scoped_nsobject<NSMutableSet> finalUrls_; |
73 // CoreBluetooth scanner. | 85 // CoreBluetooth scanner. |
74 base::scoped_nsobject<CBCentralManager> centralManager_; | 86 base::scoped_nsobject<CBCentralManager> centralManager_; |
87 // When YES, we will notify the delegate if a previously nearby URL is lost | |
88 // and remove it from the list of nearby devices. | |
89 BOOL onLostDetectionEnabled_; | |
75 // The value is YES if network requests can be sent. | 90 // The value is YES if network requests can be sent. |
76 BOOL networkRequestEnabled_; | 91 BOOL networkRequestEnabled_; |
77 // List of unresolved PhysicalWebDevice when network requests are not enabled. | 92 // List of unresolved PhysicalWebDevice when network requests are not enabled. |
78 base::scoped_nsobject<NSMutableArray> unresolvedDevices_; | 93 base::scoped_nsobject<NSMutableArray> unresolvedDevices_; |
94 // A repeating timer to check for lost URLs. If the elapsed time since an URL | |
95 // was last seen exceeds a threshold, the URL is considered lost. | |
96 base::scoped_nsobject<NSTimer> updateTimer_; | |
79 } | 97 } |
80 | 98 |
99 @synthesize onLostDetectionEnabled = onLostDetectionEnabled_; | |
81 @synthesize networkRequestEnabled = networkRequestEnabled_; | 100 @synthesize networkRequestEnabled = networkRequestEnabled_; |
82 | 101 |
83 - (instancetype)initWithDelegate:(id<PhysicalWebScannerDelegate>)delegate { | 102 - (instancetype)initWithDelegate:(id<PhysicalWebScannerDelegate>)delegate { |
84 self = [super init]; | 103 self = [super init]; |
85 if (self) { | 104 if (self) { |
86 delegate_ = delegate; | 105 delegate_ = delegate; |
87 devices_.reset([[NSMutableArray alloc] init]); | 106 devices_.reset([[NSMutableArray alloc] init]); |
88 devicesUrls_.reset([[NSMutableSet alloc] init]); | 107 devicesUrls_.reset([[NSMutableSet alloc] init]); |
89 finalUrls_.reset([[NSMutableSet alloc] init]); | 108 finalUrls_.reset([[NSMutableSet alloc] init]); |
90 pendingRequests_.reset([[NSMutableArray alloc] init]); | 109 pendingRequests_.reset([[NSMutableArray alloc] init]); |
91 centralManager_.reset([[CBCentralManager alloc] | 110 centralManager_.reset([[CBCentralManager alloc] |
92 initWithDelegate:self | 111 initWithDelegate:self |
93 queue:dispatch_get_main_queue()]); | 112 queue:dispatch_get_main_queue()]); |
94 unresolvedDevices_.reset([[NSMutableArray alloc] init]); | 113 unresolvedDevices_.reset([[NSMutableArray alloc] init]); |
95 [[NSHTTPCookieStorage sharedHTTPCookieStorage] | 114 [[NSHTTPCookieStorage sharedHTTPCookieStorage] |
96 setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyNever]; | 115 setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyNever]; |
97 } | 116 } |
98 return self; | 117 return self; |
99 } | 118 } |
100 | 119 |
101 - (instancetype)init { | 120 - (instancetype)init { |
102 NOTREACHED(); | 121 NOTREACHED(); |
103 return nil; | 122 return nil; |
104 } | 123 } |
105 | 124 |
106 - (void)dealloc { | 125 - (void)dealloc { |
107 [centralManager_ setDelegate:nil]; | 126 [centralManager_ setDelegate:nil]; |
108 centralManager_.reset(); | 127 centralManager_.reset(); |
128 if (updateTimer_.get()) { | |
129 [updateTimer_ invalidate]; | |
130 updateTimer_.reset(); | |
131 } | |
109 [super dealloc]; | 132 [super dealloc]; |
110 } | 133 } |
111 | 134 |
112 - (void)start { | 135 - (void)start { |
113 [self stop]; | 136 [self stop]; |
114 [finalUrls_ removeAllObjects]; | 137 [finalUrls_ removeAllObjects]; |
115 [devicesUrls_ removeAllObjects]; | 138 [devicesUrls_ removeAllObjects]; |
116 [devices_ removeAllObjects]; | 139 [devices_ removeAllObjects]; |
117 started_ = YES; | 140 started_ = YES; |
118 if ([self bluetoothEnabled]) | 141 if ([self bluetoothEnabled]) |
119 [self reallyStart]; | 142 [self reallyStart]; |
120 else | 143 else |
121 pendingStart_ = YES; | 144 pendingStart_ = YES; |
122 } | 145 } |
123 | 146 |
124 - (void)stop { | 147 - (void)stop { |
125 if (!started_) | 148 if (!started_) |
126 return; | 149 return; |
127 for (PhysicalWebRequest* request in pendingRequests_.get()) { | 150 for (PhysicalWebRequest* request in pendingRequests_.get()) { |
128 [request cancel]; | 151 [request cancel]; |
129 } | 152 } |
130 [pendingRequests_ removeAllObjects]; | 153 [pendingRequests_ removeAllObjects]; |
131 if (!pendingStart_ && [self bluetoothEnabled]) { | 154 if (!pendingStart_ && [self bluetoothEnabled]) { |
132 [centralManager_ stopScan]; | 155 [self reallyStop]; |
133 } | 156 } |
134 pendingStart_ = NO; | 157 pendingStart_ = NO; |
135 started_ = NO; | 158 started_ = NO; |
136 } | 159 } |
137 | 160 |
138 - (NSArray*)devices { | 161 - (NSArray*)devices { |
139 return [devices_ sortedArrayUsingComparator:^(id obj1, id obj2) { | 162 return [devices_ sortedArrayUsingComparator:^(id obj1, id obj2) { |
140 PhysicalWebDevice* device1 = obj1; | 163 PhysicalWebDevice* device1 = obj1; |
141 PhysicalWebDevice* device2 = obj2; | 164 PhysicalWebDevice* device2 = obj2; |
142 // Sorts in ascending order. | 165 // Sorts in ascending order. |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
182 if (!networkRequestEnabled_) | 205 if (!networkRequestEnabled_) |
183 return; | 206 return; |
184 | 207 |
185 // Sends the pending requests. | 208 // Sends the pending requests. |
186 for (PhysicalWebDevice* device in unresolvedDevices_.get()) { | 209 for (PhysicalWebDevice* device in unresolvedDevices_.get()) { |
187 [self requestMetadataForDevice:device]; | 210 [self requestMetadataForDevice:device]; |
188 } | 211 } |
189 [unresolvedDevices_ removeAllObjects]; | 212 [unresolvedDevices_ removeAllObjects]; |
190 } | 213 } |
191 | 214 |
215 - (void)setOnLostDetectionEnabled:(BOOL)enabled { | |
216 BOOL oldOnLostDetectionEnabled = onLostDetectionEnabled_; | |
Olivier
2016/10/19 10:22:54
nit:
if (enabled == onLostDetectionEnabled_)
ret
mattreynolds
2016/10/19 18:20:22
Done.
| |
217 onLostDetectionEnabled_ = enabled; | |
218 if (started_ && oldOnLostDetectionEnabled != onLostDetectionEnabled_) { | |
219 [self start]; | |
220 } | |
221 } | |
222 | |
192 - (int)unresolvedBeaconsCount { | 223 - (int)unresolvedBeaconsCount { |
193 return [unresolvedDevices_ count]; | 224 return [unresolvedDevices_ count]; |
194 } | 225 } |
195 | 226 |
196 - (BOOL)bluetoothEnabled { | 227 - (BOOL)bluetoothEnabled { |
197 // TODO(crbug.com/619982): The CBManager base class appears to still be in | 228 // TODO(crbug.com/619982): The CBManager base class appears to still be in |
198 // flux. Unwind this #ifdef once the APIs settle. | 229 // flux. Unwind this #ifdef once the APIs settle. |
199 #if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 | 230 #if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 |
200 return [centralManager_ state] == CBManagerStatePoweredOn; | 231 return [centralManager_ state] == CBManagerStatePoweredOn; |
201 #else | 232 #else |
202 return [centralManager_ state] == CBCentralManagerStatePoweredOn; | 233 return [centralManager_ state] == CBCentralManagerStatePoweredOn; |
203 #endif | 234 #endif |
204 } | 235 } |
205 | 236 |
206 - (void)reallyStart { | 237 - (void)reallyStart { |
207 pendingStart_ = NO; | 238 pendingStart_ = NO; |
239 | |
240 if (updateTimer_.get()) { | |
241 [updateTimer_ invalidate]; | |
242 updateTimer_.reset(); | |
243 } | |
244 | |
208 NSArray* serviceUUIDs = @[ | 245 NSArray* serviceUUIDs = @[ |
209 [CBUUID UUIDWithString:kUriBeaconServiceUUID], | 246 [CBUUID UUIDWithString:kUriBeaconServiceUUID], |
210 [CBUUID UUIDWithString:kEddystoneBeaconServiceUUID] | 247 [CBUUID UUIDWithString:kEddystoneBeaconServiceUUID] |
211 ]; | 248 ]; |
212 [centralManager_ scanForPeripheralsWithServices:serviceUUIDs options:nil]; | 249 NSDictionary* options = nil; |
250 if (onLostDetectionEnabled_) { | |
251 // To detect lost URLs, we configure the scanner with the AllowDuplicates | |
252 // option enabled, which will notify us each time an advertising packet is | |
253 // received rather than only the first time. A URL is considered lost if the | |
254 // most recent sighting was more than |kLostThresholdSeconds| ago. | |
255 options = | |
256 [NSDictionary dictionaryWithObjectsAndKeys: | |
257 [NSNumber numberWithBool:YES], | |
258 CBCentralManagerScanOptionAllowDuplicatesKey, nil]; | |
Olivier
2016/10/19 10:22:54
Question:
Is this needed if we do the workaround?
mattreynolds
2016/10/19 18:20:21
I ran some tests and it seems it's not needed if w
| |
259 | |
260 // Register a repeating timer to periodically check for lost URLs. | |
261 updateTimer_.reset([NSTimer | |
262 scheduledTimerWithTimeInterval:kUpdateIntervalSeconds | |
263 target:self | |
264 selector:@selector(onUpdate:) | |
265 userInfo:nil | |
266 repeats:YES]); | |
267 } | |
268 [centralManager_ scanForPeripheralsWithServices:serviceUUIDs options:options]; | |
269 } | |
270 | |
271 - (void)reallyStop { | |
272 if (updateTimer_.get()) { | |
273 [updateTimer_ invalidate]; | |
274 updateTimer_.reset(); | |
275 } | |
276 | |
277 [centralManager_ stopScan]; | |
278 } | |
279 | |
280 - (void)onUpdate:(NSTimer*)timer { | |
281 NSDate* now = [NSDate date]; | |
282 NSMutableArray* lostDevices = [NSMutableArray array]; | |
283 NSMutableArray* lostUnresolvedDevices = [NSMutableArray array]; | |
284 NSMutableArray* lostScannedUrls = [NSMutableArray array]; | |
285 | |
286 for (PhysicalWebDevice* device in [self devices]) { | |
287 NSDate* scanTimestamp = [device scanTimestamp]; | |
288 NSTimeInterval elapsedSeconds = [now timeIntervalSinceDate:scanTimestamp]; | |
289 if (elapsedSeconds > kLostThresholdSeconds) { | |
290 [lostDevices addObject:device]; | |
291 [lostScannedUrls addObject:[device requestURL]]; | |
292 [devicesUrls_ removeObject:[device requestURL]]; | |
293 [finalUrls_ removeObject:[device url]]; | |
294 } | |
295 } | |
296 | |
297 for (PhysicalWebDevice* device in unresolvedDevices_.get()) { | |
298 NSDate* scanTimestamp = [device scanTimestamp]; | |
299 NSTimeInterval elapsedSeconds = [now timeIntervalSinceDate:scanTimestamp]; | |
300 if (elapsedSeconds > kLostThresholdSeconds) { | |
301 [lostUnresolvedDevices addObject:device]; | |
302 [lostScannedUrls addObject:[device requestURL]]; | |
303 [devicesUrls_ removeObject:[device requestURL]]; | |
304 } | |
305 } | |
306 | |
307 NSMutableArray* requestsToRemove = [NSMutableArray array]; | |
308 for (PhysicalWebRequest* request in pendingRequests_.get()) { | |
309 if ([lostScannedUrls containsObject:[request requestURL]]) { | |
310 [request cancel]; | |
311 [requestsToRemove addObject:request]; | |
312 } | |
313 } | |
314 | |
315 [devices_ removeObjectsInArray:lostDevices]; | |
316 [unresolvedDevices_ removeObjectsInArray:lostUnresolvedDevices]; | |
317 [pendingRequests_ removeObjectsInArray:requestsToRemove]; | |
318 | |
319 if ([lostDevices count]) { | |
320 [delegate_ scannerUpdatedDevices:self]; | |
321 } | |
322 | |
323 // Workaround for crbug.com/657056 | |
Olivier
2016/10/19 10:22:54
format
// TODO(crbug.com/657056): Remove this work
mattreynolds
2016/10/19 18:20:21
Done.
| |
324 // For unknown reasons, when scanning for longer periods (on the order of | |
325 // minutes), the scanner is less reliable at detecting all nearby URLs. As a | |
326 // workaround, we restart the scanner each time we check for lost URLs. | |
327 NSArray* serviceUUIDs = @[ | |
328 [CBUUID UUIDWithString:kUriBeaconServiceUUID], | |
329 [CBUUID UUIDWithString:kEddystoneBeaconServiceUUID] | |
330 ]; | |
331 NSDictionary* options = [NSDictionary | |
332 dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], | |
333 CBCentralManagerScanOptionAllowDuplicatesKey, | |
334 nil]; | |
335 [centralManager_ stopScan]; | |
336 [centralManager_ scanForPeripheralsWithServices:serviceUUIDs options:options]; | |
213 } | 337 } |
214 | 338 |
215 #pragma mark - | 339 #pragma mark - |
216 #pragma mark CBCentralManagerDelegate methods | 340 #pragma mark CBCentralManagerDelegate methods |
217 | 341 |
218 - (void)centralManagerDidUpdateState:(CBCentralManager*)central { | 342 - (void)centralManagerDidUpdateState:(CBCentralManager*)central { |
219 if ([self bluetoothEnabled]) { | 343 if ([self bluetoothEnabled]) { |
220 if (pendingStart_) | 344 if (pendingStart_) |
221 [self reallyStart]; | 345 [self reallyStart]; |
222 } else { | 346 } else { |
223 if (started_ && !pendingStart_) { | 347 if (started_ && !pendingStart_) { |
224 pendingStart_ = YES; | 348 pendingStart_ = YES; |
225 [centralManager_ stopScan]; | 349 [self reallyStop]; |
226 } | 350 } |
227 } | 351 } |
228 [delegate_ scannerBluetoothStatusUpdated:self]; | 352 [delegate_ scannerBluetoothStatusUpdated:self]; |
229 } | 353 } |
230 | 354 |
231 + (BeaconType)beaconTypeForAdvertisementData:(NSDictionary*)advertisementData { | 355 + (BeaconType)beaconTypeForAdvertisementData:(NSDictionary*)advertisementData { |
232 NSDictionary* serviceData = | 356 NSDictionary* serviceData = |
233 [advertisementData objectForKey:CBAdvertisementDataServiceDataKey]; | 357 [advertisementData objectForKey:CBAdvertisementDataServiceDataKey]; |
234 if ([serviceData objectForKey:[CBUUID UUIDWithString:kUriBeaconServiceUUID]]) | 358 if ([serviceData objectForKey:[CBUUID UUIDWithString:kUriBeaconServiceUUID]]) |
235 return BEACON_TYPE_URIBEACON; | 359 return BEACON_TYPE_URIBEACON; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
267 DCHECK(data); | 391 DCHECK(data); |
268 | 392 |
269 base::scoped_nsobject<PhysicalWebDevice> device([PhysicalWebScanner | 393 base::scoped_nsobject<PhysicalWebDevice> device([PhysicalWebScanner |
270 newDeviceFromData:data | 394 newDeviceFromData:data |
271 rssi:[RSSI intValue] | 395 rssi:[RSSI intValue] |
272 type:type]); | 396 type:type]); |
273 // Skip if the data couldn't be parsed. | 397 // Skip if the data couldn't be parsed. |
274 if (!device.get()) | 398 if (!device.get()) |
275 return; | 399 return; |
276 | 400 |
401 [device setScanTimestamp:[NSDate date]]; | |
402 | |
277 // Skip if the URL has already been seen. | 403 // Skip if the URL has already been seen. |
278 if ([devicesUrls_ containsObject:[device url]]) | 404 if ([devicesUrls_ containsObject:[device requestURL]]) |
mattreynolds
2016/10/19 18:20:21
found a bug: if the URL has already been seen, we
Olivier
2016/10/20 07:05:21
I don't get it.
You update the timestamp on the l
mattreynolds
2016/10/20 22:03:28
If this is the first time we've seen the device's
| |
279 return; | 405 return; |
280 [devicesUrls_ addObject:[device url]]; | 406 [devicesUrls_ addObject:[device requestURL]]; |
281 | 407 |
282 if (networkRequestEnabled_) { | 408 if (networkRequestEnabled_) { |
283 [self requestMetadataForDevice:device]; | 409 [self requestMetadataForDevice:device]; |
284 } else { | 410 } else { |
285 [unresolvedDevices_ addObject:device]; | 411 [unresolvedDevices_ addObject:device]; |
286 [delegate_ scannerUpdatedDevices:self]; | 412 [delegate_ scannerUpdatedDevices:self]; |
287 } | 413 } |
288 } | 414 } |
289 | 415 |
290 #pragma mark - | 416 #pragma mark - |
(...skipping 28 matching lines...) Expand all Loading... | |
319 std::string utf8URI; | 445 std::string utf8URI; |
320 device::DecodeUriBeaconUri(encodedURI, utf8URI); | 446 device::DecodeUriBeaconUri(encodedURI, utf8URI); |
321 NSString* uriString = base::SysUTF8ToNSString(utf8URI); | 447 NSString* uriString = base::SysUTF8ToNSString(utf8URI); |
322 NSURL* url = [NSURL URLWithString:uriString]; | 448 NSURL* url = [NSURL URLWithString:uriString]; |
323 | 449 |
324 // Ensure URL is valid. | 450 // Ensure URL is valid. |
325 if (!url) | 451 if (!url) |
326 return nil; | 452 return nil; |
327 | 453 |
328 return [[PhysicalWebDevice alloc] initWithURL:url | 454 return [[PhysicalWebDevice alloc] initWithURL:url |
329 requestURL:nil | 455 requestURL:url |
330 icon:nil | 456 icon:nil |
331 title:nil | 457 title:nil |
332 description:nil | 458 description:nil |
333 transmitPower:transmitPower | 459 transmitPower:transmitPower |
334 rssi:rssi | 460 rssi:rssi |
335 rank:physical_web::kMaxRank]; | 461 rank:physical_web::kMaxRank |
462 scanTimestamp:[NSDate date]]; | |
336 } | 463 } |
337 | 464 |
338 - (void)requestMetadataForDevice:(PhysicalWebDevice*)device { | 465 - (void)requestMetadataForDevice:(PhysicalWebDevice*)device { |
339 base::scoped_nsobject<PhysicalWebRequest> request( | 466 base::scoped_nsobject<PhysicalWebRequest> request( |
340 [[PhysicalWebRequest alloc] initWithDevice:device]); | 467 [[PhysicalWebRequest alloc] initWithDevice:device]); |
341 PhysicalWebRequest* strongRequest = request.get(); | 468 PhysicalWebRequest* strongRequest = request.get(); |
342 [pendingRequests_ addObject:strongRequest]; | 469 [pendingRequests_ addObject:strongRequest]; |
343 base::WeakNSObject<PhysicalWebScanner> weakSelf(self); | 470 base::WeakNSObject<PhysicalWebScanner> weakSelf(self); |
344 [request start:^(PhysicalWebDevice* device, NSError* error) { | 471 [request start:^(PhysicalWebDevice* device, NSError* error) { |
345 base::scoped_nsobject<PhysicalWebScanner> strongSelf([weakSelf retain]); | 472 base::scoped_nsobject<PhysicalWebScanner> strongSelf([weakSelf retain]); |
346 if (!strongSelf) { | 473 if (!strongSelf) { |
347 return; | 474 return; |
348 } | 475 } |
349 // ignore if there's an error. | 476 // ignore if there's an error. |
350 if (!error) { | 477 if (!error) { |
351 if (![strongSelf.get()->finalUrls_ containsObject:[device url]]) { | 478 if (![strongSelf.get()->finalUrls_ containsObject:[device url]]) { |
352 [strongSelf.get()->devices_ addObject:device]; | 479 [strongSelf.get()->devices_ addObject:device]; |
353 [strongSelf.get()->delegate_ scannerUpdatedDevices:weakSelf]; | 480 [strongSelf.get()->delegate_ scannerUpdatedDevices:weakSelf]; |
354 [strongSelf.get()->finalUrls_ addObject:[device url]]; | 481 [strongSelf.get()->finalUrls_ addObject:[device url]]; |
355 } | 482 } |
356 } | 483 } |
357 [strongSelf.get()->pendingRequests_ removeObject:strongRequest]; | 484 [strongSelf.get()->pendingRequests_ removeObject:strongRequest]; |
358 }]; | 485 }]; |
359 } | 486 } |
360 | 487 |
361 @end | 488 @end |
OLD | NEW |