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

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: fix retain loop Created 3 years, 11 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 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..623a8ef8d6090f7bdd5ebd1d2d609aca56e47a03
--- /dev/null
+++ b/ios/chrome/browser/physical_web/physical_web_initial_state_recorder.mm
@@ -0,0 +1,170 @@
+// 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 {
+
+const double kStartupDelaySeconds = 10.0;
+
+// 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<NSTimer> startupDelayTimer_;
+ 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 {
+ [self invalidate];
+ [super dealloc];
+}
+
+- (void)invalidate {
+ if (startupDelayTimer_.get()) {
+ [startupDelayTimer_ invalidate];
+ startupDelayTimer_.reset();
+ }
+ [centralManager_ setDelegate:nil];
+ centralManager_.reset();
+}
+
+- (void)centralManagerDidUpdateState:(CBCentralManager*)central {
+ [centralManager_ setDelegate:nil];
+ centralManager_.reset();
+
+ 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;
+ startupDelayTimer_.reset(
+ [[NSTimer scheduledTimerWithTimeInterval:kStartupDelaySeconds
+ target:self
+ selector:@selector(startupDelayElapsed:)
+ userInfo:nil
+ repeats:NO] retain]);
+}
+
+- (void)startupDelayElapsed:(NSTimer*)timer {
+ startupDelayTimer_.reset();
+
+ // 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
« no previous file with comments | « ios/chrome/browser/physical_web/physical_web_initial_state_recorder.h ('k') | tools/metrics/histograms/histograms.xml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698