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

Unified Diff: ios/chrome/browser/physical_web/physical_web_initial_state_recorder.mm

Issue 2458613004: Record the initial state of the Physical Web at startup (Closed)
Patch Set: changes for olivierrobin@, rohitrao@, sdefresne@ Created 4 years, 1 month 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 side-by-side diff with in-line comments
Download patch
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..43792b48aba515fa9ebf426173f380abf7400536
--- /dev/null
+++ b/ios/chrome/browser/physical_web/physical_web_initial_state_recorder.mm
@@ -0,0 +1,150 @@
+// 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"
+
+#import <CoreBluetooth/CoreBluetooth.h>
+#import <CoreLocation/CoreLocation.h>
+
+#include "base/mac/scoped_nsobject.h"
+#include "base/metrics/histogram.h"
+#include "components/prefs/pref_service.h"
+#include "ios/chrome/browser/physical_web/physical_web_constants.h"
+#include "ios/chrome/browser/pref_names.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.
+// This enum is used in a user metrics histogram. The states should not be
+// reordered or removed.
+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 recordedState_;
+ base::scoped_nsobject<CBCentralManager> centralManager_;
+}
+
+- (instancetype)initWithPrefService:(PrefService*)prefService {
+ self = [super init];
+ if (self) {
+ preferenceState_ = prefService->GetInteger(prefs::kIosPhysicalWebEnabled);
+ }
+ return self;
+}
+
+- (instancetype)init {
+ NOTREACHED();
+ return nil;
+}
+
+- (void)dealloc {
+ [centralManager_ setDelegate:nil];
+ centralManager_.reset();
+ [super dealloc];
+}
+
+- (void)centralManagerDidUpdateState:(CBCentralManager*)central {
+ // Remove ourselves as a delegate so we won't get notified for later changes
+ // to the Bluetooth enabled state.
+ [centralManager_ setDelegate:nil];
+
+ BOOL bluetoothEnabled = [centralManager_ state] == CBManagerStatePoweredOn;
+
+ BOOL locationServicesEnabled = [CLLocationManager locationServicesEnabled];
+
+ CLAuthorizationStatus authStatus = [CLLocationManager authorizationStatus];
+ BOOL locationAuthorized =
+ authStatus == kCLAuthorizationStatusAuthorizedWhenInUse ||
+ authStatus == kCLAuthorizationStatusAuthorizedAlways;
+
+ [self recordStateWithPreferenceState:preferenceState_
+ bluetoothEnabled:bluetoothEnabled
+ locationServicesEnabled:locationServicesEnabled
+ locationAuthorized:locationAuthorized];
+}
+
+- (void)collectAndRecordState {
+ if (recordedState_) {
+ return;
+ }
+ recordedState_ = YES;
+
+ // The Bluetooth enabled state must be checked asynchronously. When the state
+ // is ready, it will call our centralManagerDidUpdateState method.
+ centralManager_.reset([[CBCentralManager alloc]
+ initWithDelegate:self
+ queue:dispatch_get_main_queue()
+ options:@{
+ // By default, creating a CBCentralManager object with
+ // Bluetooth disabled will prompt the user to enable Bluetooth.
+ // Passing ShowPowerAlert=NO disables the prompt so we can
+ // check the Bluetooth enabled state silently.
+ CBCentralManagerOptionShowPowerAlertKey : @NO
+ }]);
+}
+
+- (void)recordStateWithPreferenceState:(int)preferenceState
+ bluetoothEnabled:(BOOL)bluetoothEnabled
+ locationServicesEnabled:(BOOL)locationServicesEnabled
+ locationAuthorized:(BOOL)locationAuthorized {
+ 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 (bluetoothEnabled) {
+ state |= BLUETOOTH_FLAG;
+ }
+
+ DCHECK(state < PHYSICAL_WEB_INITIAL_STATE_COUNT);
+ UMA_HISTOGRAM_ENUMERATION("PhysicalWeb.InitialState.IosChrome", state,
+ PHYSICAL_WEB_INITIAL_STATE_COUNT);
+}
+
+@end

Powered by Google App Engine
This is Rietveld 408576698