Index: ios/chrome/browser/physical_web/physical_web_initial_state_recorder.mm |
diff --git a/ios/chrome/browser/physical_web/physical_web_initial_state_recorder.mm b/ios/chrome/browser/physical_web/physical_web_initial_state_recorder.mm |
new file mode 100644 |
index 0000000000000000000000000000000000000000..2ba4df5ce99e7a5955d785eea6d3c6ab2574c5d9 |
--- /dev/null |
+++ b/ios/chrome/browser/physical_web/physical_web_initial_state_recorder.mm |
@@ -0,0 +1,131 @@ |
+// Copyright 2016 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. |
+ |
+#import "ios/chrome/browser/physical_web/physical_web_initial_state_recorder.h" |
+ |
+#include "base/mac/scoped_nsobject.h" |
+#include "base/metrics/histogram.h" |
+#include "ios/chrome/browser/physical_web/physical_web_constants.h" |
+ |
+namespace { |
+ |
+// Initial state of settings relevant to the Physical Web feature. These are |
+// ordered so that bits 2:0 encode the Bluetooth enabled state, the Location |
+// Services enabled state, and whether Chrome has been granted the Location app |
+// permission. Bits 4:3 encode the Physical Web preference tristate. |
rohitrao (ping after 24h)
2016/10/31 19:41:08
This feels very brittle. There is no better way t
mattreynolds
2016/11/01 17:17:17
We could record the state separately, but combinin
|
+enum PhysicalWebInitialStateIosChrome { |
+ OPTOUT_BTOFF_LOCOFF_UNAUTH, |
+ OPTOUT_BTOFF_LOCOFF_AUTH, |
+ OPTOUT_BTOFF_LOCON_UNAUTH, |
+ OPTOUT_BTOFF_LOCON_AUTH, |
+ OPTOUT_BTON_LOCOFF_UNAUTH, |
+ OPTOUT_BTON_LOCOFF_AUTH, |
+ OPTOUT_BTON_LOCON_UNAUTH, |
+ OPTOUT_BTON_LOCON_AUTH, |
+ OPTIN_BTOFF_LOCOFF_UNAUTH, |
+ OPTIN_BTOFF_LOCOFF_AUTH, |
+ OPTIN_BTOFF_LOCON_UNAUTH, |
+ OPTIN_BTOFF_LOCON_AUTH, |
+ OPTIN_BTON_LOCOFF_UNAUTH, |
+ OPTIN_BTON_LOCOFF_AUTH, |
+ OPTIN_BTON_LOCON_UNAUTH, |
+ OPTIN_BTON_LOCON_AUTH, |
+ ONBOARDING_BTOFF_LOCOFF_UNAUTH, |
+ ONBOARDING_BTOFF_LOCOFF_AUTH, |
+ ONBOARDING_BTOFF_LOCON_UNAUTH, |
+ ONBOARDING_BTOFF_LOCON_AUTH, |
+ ONBOARDING_BTON_LOCOFF_UNAUTH, |
+ ONBOARDING_BTON_LOCOFF_AUTH, |
+ ONBOARDING_BTON_LOCON_UNAUTH, |
+ ONBOARDING_BTON_LOCON_AUTH, |
+ PHYSICAL_WEB_INITIAL_STATE_COUNT, |
+ |
+ // Helper flag values |
+ LOCATION_AUTHORIZED_FLAG = 1 << 0, |
+ LOCATION_SERVICES_FLAG = 1 << 1, |
+ BLUETOOTH_FLAG = 1 << 2, |
+ OPTIN_FLAG = 1 << 3, |
+ ONBOARDING_FLAG = 1 << 4, |
+}; |
+} // namespace |
+ |
+@implementation PhysicalWebInitialStateRecorder { |
+ int preferenceState_; |
+ BOOL locationServicesEnabled_; |
+ BOOL locationAuthorized_; |
+ BOOL bluetoothEnabled_; |
+ base::scoped_nsobject<CBCentralManager> centralManager_; |
+} |
+ |
+- (instancetype)initWithPreferenceState:(int)preferenceState |
+ locationServicesEnabled:(BOOL)locationServicesEnabled |
+ locationAuthorized:(BOOL)locationAuthorized { |
+ self = [super init]; |
+ if (self) { |
+ preferenceState_ = preferenceState; |
+ locationServicesEnabled_ = locationServicesEnabled; |
+ locationAuthorized_ = locationAuthorized; |
+ centralManager_.reset([[CBCentralManager alloc] |
+ initWithDelegate:self |
+ queue:dispatch_get_main_queue() |
+ options:@{ |
+ CBCentralManagerOptionShowPowerAlertKey : @NO |
+ }]); |
+ |
+ // Make sure we aren't released before the central manager reports back. |
+ [self retain]; |
+ } |
+ return self; |
+} |
+ |
+- (instancetype)init { |
+ NOTREACHED(); |
+ return nil; |
+} |
+ |
+- (void)dealloc { |
+ [centralManager_ setDelegate:nil]; |
+ centralManager_.reset(); |
+ [super dealloc]; |
+} |
+ |
+- (BOOL)bluetoothEnabled { |
+// TODO(crbug.com/619982): The CBManager base class appears to still be in |
+// flux. Unwind this #ifdef once the APIs settle. |
rohitrao (ping after 24h)
2016/10/31 19:41:08
Have the APIs settled now that iOS10 is out for re
mattreynolds
2016/11/01 17:17:16
Yeah, I think we can remove the #ifdef now.
|
+#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 |
+ return [centralManager_ state] == CBManagerStatePoweredOn; |
+#else |
+ return [centralManager_ state] == CBCentralManagerStatePoweredOn; |
+#endif |
+} |
+ |
+- (void)centralManagerDidUpdateState:(CBCentralManager*)central { |
+ [self recordInitialStateAndFinish]; |
+} |
+ |
+- (void)recordInitialStateAndFinish { |
+ int state = 0; |
+ if (preferenceState_ == physical_web::kPhysicalWebOn) { |
+ state |= OPTIN_FLAG; |
+ } else if (preferenceState_ == physical_web::kPhysicalWebOnboarding) { |
+ state |= ONBOARDING_FLAG; |
+ } |
+ if (locationServicesEnabled_) { |
+ state |= LOCATION_SERVICES_FLAG; |
+ } |
+ if (locationAuthorized_) { |
+ state |= LOCATION_AUTHORIZED_FLAG; |
+ } |
+ if ([self bluetoothEnabled]) { |
+ state |= BLUETOOTH_FLAG; |
+ } |
+ |
+ DCHECK(state < PHYSICAL_WEB_INITIAL_STATE_COUNT); |
+ UMA_HISTOGRAM_ENUMERATION("PhysicalWeb.InitialState.IosChrome", state, |
+ PHYSICAL_WEB_INITIAL_STATE_COUNT); |
+ |
+ [self release]; |
+} |
+ |
+@end |