OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/browser/physical_web/physical_web_initial_state_recorder.h" | 5 #import "ios/chrome/browser/physical_web/physical_web_initial_state_recorder.h" |
6 | 6 |
7 #import <CoreBluetooth/CoreBluetooth.h> | 7 #import <CoreBluetooth/CoreBluetooth.h> |
8 #import <CoreLocation/CoreLocation.h> | 8 #import <CoreLocation/CoreLocation.h> |
9 | 9 |
10 #include "base/mac/scoped_nsobject.h" | |
11 #include "base/metrics/histogram_macros.h" | 10 #include "base/metrics/histogram_macros.h" |
12 #include "components/prefs/pref_service.h" | 11 #include "components/prefs/pref_service.h" |
13 #include "ios/chrome/browser/physical_web/physical_web_constants.h" | 12 #include "ios/chrome/browser/physical_web/physical_web_constants.h" |
14 #include "ios/chrome/browser/pref_names.h" | 13 #include "ios/chrome/browser/pref_names.h" |
15 | 14 |
| 15 #if !defined(__has_feature) || !__has_feature(objc_arc) |
| 16 #error "This file requires ARC support." |
| 17 #endif |
| 18 |
16 namespace { | 19 namespace { |
17 | 20 |
18 const double kStartupDelaySeconds = 10.0; | 21 const double kStartupDelaySeconds = 10.0; |
19 | 22 |
20 // Initial state of settings relevant to the Physical Web feature. These are | 23 // Initial state of settings relevant to the Physical Web feature. These are |
21 // ordered so that bits 2:0 encode the Bluetooth enabled state, the Location | 24 // ordered so that bits 2:0 encode the Bluetooth enabled state, the Location |
22 // Services enabled state, and whether Chrome has been granted the Location app | 25 // Services enabled state, and whether Chrome has been granted the Location app |
23 // permission. Bits 4:3 encode the Physical Web preference tristate. | 26 // permission. Bits 4:3 encode the Physical Web preference tristate. |
24 // This enum is used in a user metrics histogram. The states should not be | 27 // This enum is used in a user metrics histogram. The states should not be |
25 // reordered or removed. | 28 // reordered or removed. |
(...skipping 29 matching lines...) Expand all Loading... |
55 LOCATION_SERVICES_FLAG = 1 << 1, | 58 LOCATION_SERVICES_FLAG = 1 << 1, |
56 BLUETOOTH_FLAG = 1 << 2, | 59 BLUETOOTH_FLAG = 1 << 2, |
57 OPTIN_FLAG = 1 << 3, | 60 OPTIN_FLAG = 1 << 3, |
58 ONBOARDING_FLAG = 1 << 4, | 61 ONBOARDING_FLAG = 1 << 4, |
59 }; | 62 }; |
60 } // namespace | 63 } // namespace |
61 | 64 |
62 @implementation PhysicalWebInitialStateRecorder { | 65 @implementation PhysicalWebInitialStateRecorder { |
63 int preferenceState_; | 66 int preferenceState_; |
64 BOOL recordedState_; | 67 BOOL recordedState_; |
65 base::scoped_nsobject<NSTimer> startupDelayTimer_; | 68 NSTimer* startupDelayTimer_; |
66 base::scoped_nsobject<CBCentralManager> centralManager_; | 69 CBCentralManager* centralManager_; |
67 } | 70 } |
68 | 71 |
69 - (instancetype)initWithPrefService:(PrefService*)prefService { | 72 - (instancetype)initWithPrefService:(PrefService*)prefService { |
70 self = [super init]; | 73 self = [super init]; |
71 if (self) { | 74 if (self) { |
72 preferenceState_ = prefService->GetInteger(prefs::kIosPhysicalWebEnabled); | 75 preferenceState_ = prefService->GetInteger(prefs::kIosPhysicalWebEnabled); |
73 } | 76 } |
74 return self; | 77 return self; |
75 } | 78 } |
76 | 79 |
77 - (instancetype)init { | 80 - (instancetype)init { |
78 NOTREACHED(); | 81 NOTREACHED(); |
79 return nil; | 82 return nil; |
80 } | 83 } |
81 | 84 |
82 - (void)dealloc { | 85 - (void)dealloc { |
83 [self invalidate]; | 86 [self invalidate]; |
84 [super dealloc]; | |
85 } | 87 } |
86 | 88 |
87 - (void)invalidate { | 89 - (void)invalidate { |
88 if (startupDelayTimer_.get()) { | 90 if (startupDelayTimer_) { |
89 [startupDelayTimer_ invalidate]; | 91 [startupDelayTimer_ invalidate]; |
90 startupDelayTimer_.reset(); | 92 startupDelayTimer_ = nil; |
91 } | 93 } |
92 [centralManager_ setDelegate:nil]; | 94 [centralManager_ setDelegate:nil]; |
93 centralManager_.reset(); | 95 centralManager_ = nil; |
94 } | 96 } |
95 | 97 |
96 - (void)centralManagerDidUpdateState:(CBCentralManager*)central { | 98 - (void)centralManagerDidUpdateState:(CBCentralManager*)central { |
97 [centralManager_ setDelegate:nil]; | 99 [centralManager_ setDelegate:nil]; |
98 centralManager_.reset(); | 100 centralManager_ = nil; |
99 | 101 |
100 BOOL bluetoothEnabled = [centralManager_ state] == CBManagerStatePoweredOn; | 102 BOOL bluetoothEnabled = [centralManager_ state] == CBManagerStatePoweredOn; |
101 | 103 |
102 BOOL locationServicesEnabled = [CLLocationManager locationServicesEnabled]; | 104 BOOL locationServicesEnabled = [CLLocationManager locationServicesEnabled]; |
103 | 105 |
104 CLAuthorizationStatus authStatus = [CLLocationManager authorizationStatus]; | 106 CLAuthorizationStatus authStatus = [CLLocationManager authorizationStatus]; |
105 BOOL locationAuthorized = | 107 BOOL locationAuthorized = |
106 authStatus == kCLAuthorizationStatusAuthorizedWhenInUse || | 108 authStatus == kCLAuthorizationStatusAuthorizedWhenInUse || |
107 authStatus == kCLAuthorizationStatusAuthorizedAlways; | 109 authStatus == kCLAuthorizationStatusAuthorizedAlways; |
108 | 110 |
109 [self recordStateWithPreferenceState:preferenceState_ | 111 [self recordStateWithPreferenceState:preferenceState_ |
110 bluetoothEnabled:bluetoothEnabled | 112 bluetoothEnabled:bluetoothEnabled |
111 locationServicesEnabled:locationServicesEnabled | 113 locationServicesEnabled:locationServicesEnabled |
112 locationAuthorized:locationAuthorized]; | 114 locationAuthorized:locationAuthorized]; |
113 } | 115 } |
114 | 116 |
115 - (void)collectAndRecordState { | 117 - (void)collectAndRecordState { |
116 if (recordedState_) { | 118 if (recordedState_) { |
117 return; | 119 return; |
118 } | 120 } |
119 recordedState_ = YES; | 121 recordedState_ = YES; |
120 startupDelayTimer_.reset( | 122 startupDelayTimer_ = |
121 [[NSTimer scheduledTimerWithTimeInterval:kStartupDelaySeconds | 123 [NSTimer scheduledTimerWithTimeInterval:kStartupDelaySeconds |
122 target:self | 124 target:self |
123 selector:@selector(startupDelayElapsed:) | 125 selector:@selector(startupDelayElapsed:) |
124 userInfo:nil | 126 userInfo:nil |
125 repeats:NO] retain]); | 127 repeats:NO]; |
126 } | 128 } |
127 | 129 |
128 - (void)startupDelayElapsed:(NSTimer*)timer { | 130 - (void)startupDelayElapsed:(NSTimer*)timer { |
129 startupDelayTimer_.reset(); | 131 startupDelayTimer_ = nil; |
130 | 132 |
131 // The Bluetooth enabled state must be checked asynchronously. When the state | 133 // The Bluetooth enabled state must be checked asynchronously. When the state |
132 // is ready, it will call our centralManagerDidUpdateState method. | 134 // is ready, it will call our centralManagerDidUpdateState method. |
133 centralManager_.reset([[CBCentralManager alloc] | 135 centralManager_ = [[CBCentralManager alloc] |
134 initWithDelegate:self | 136 initWithDelegate:self |
135 queue:dispatch_get_main_queue() | 137 queue:dispatch_get_main_queue() |
136 options:@{ | 138 options:@{ |
137 // By default, creating a CBCentralManager object with | 139 // By default, creating a CBCentralManager object with |
138 // Bluetooth disabled will prompt the user to enable Bluetooth. | 140 // Bluetooth disabled will prompt the user to enable Bluetooth. |
139 // Passing ShowPowerAlert=NO disables the prompt so we can | 141 // Passing ShowPowerAlert=NO disables the prompt so we can |
140 // check the Bluetooth enabled state silently. | 142 // check the Bluetooth enabled state silently. |
141 CBCentralManagerOptionShowPowerAlertKey : @NO | 143 CBCentralManagerOptionShowPowerAlertKey : @NO |
142 }]); | 144 }]; |
143 } | 145 } |
144 | 146 |
145 - (void)recordStateWithPreferenceState:(int)preferenceState | 147 - (void)recordStateWithPreferenceState:(int)preferenceState |
146 bluetoothEnabled:(BOOL)bluetoothEnabled | 148 bluetoothEnabled:(BOOL)bluetoothEnabled |
147 locationServicesEnabled:(BOOL)locationServicesEnabled | 149 locationServicesEnabled:(BOOL)locationServicesEnabled |
148 locationAuthorized:(BOOL)locationAuthorized { | 150 locationAuthorized:(BOOL)locationAuthorized { |
149 int state = 0; | 151 int state = 0; |
150 if (preferenceState == physical_web::kPhysicalWebOn) { | 152 if (preferenceState == physical_web::kPhysicalWebOn) { |
151 state |= OPTIN_FLAG; | 153 state |= OPTIN_FLAG; |
152 } else if (preferenceState == physical_web::kPhysicalWebOnboarding) { | 154 } else if (preferenceState == physical_web::kPhysicalWebOnboarding) { |
153 state |= ONBOARDING_FLAG; | 155 state |= ONBOARDING_FLAG; |
154 } | 156 } |
155 if (locationServicesEnabled) { | 157 if (locationServicesEnabled) { |
156 state |= LOCATION_SERVICES_FLAG; | 158 state |= LOCATION_SERVICES_FLAG; |
157 } | 159 } |
158 if (locationAuthorized) { | 160 if (locationAuthorized) { |
159 state |= LOCATION_AUTHORIZED_FLAG; | 161 state |= LOCATION_AUTHORIZED_FLAG; |
160 } | 162 } |
161 if (bluetoothEnabled) { | 163 if (bluetoothEnabled) { |
162 state |= BLUETOOTH_FLAG; | 164 state |= BLUETOOTH_FLAG; |
163 } | 165 } |
164 | 166 |
165 DCHECK(state < PHYSICAL_WEB_INITIAL_STATE_COUNT); | 167 DCHECK(state < PHYSICAL_WEB_INITIAL_STATE_COUNT); |
166 UMA_HISTOGRAM_ENUMERATION("PhysicalWeb.InitialState.IosChrome", state, | 168 UMA_HISTOGRAM_ENUMERATION("PhysicalWeb.InitialState.IosChrome", state, |
167 PHYSICAL_WEB_INITIAL_STATE_COUNT); | 169 PHYSICAL_WEB_INITIAL_STATE_COUNT); |
168 } | 170 } |
169 | 171 |
170 @end | 172 @end |
OLD | NEW |