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

Side by Side Diff: ios/chrome/app/application_delegate/metrics_mediator.mm

Issue 2580363002: Upstream Chrome on iOS source code [1/11]. (Closed)
Patch Set: Created 4 years 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 unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #import "ios/chrome/app/application_delegate/metrics_mediator.h"
6
7 #include "base/ios/weak_nsobject.h"
8 #include "base/mac/bind_objc_block.h"
9 #include "base/metrics/user_metrics_action.h"
10 #include "base/strings/sys_string_conversions.h"
11 #include "components/crash/core/common/crash_keys.h"
12 #include "components/metrics/metrics_pref_names.h"
13 #include "components/metrics/metrics_service.h"
14 #include "components/prefs/pref_service.h"
15 #import "ios/chrome/app/application_delegate/startup_information.h"
16 #include "ios/chrome/browser/application_context.h"
17 #include "ios/chrome/browser/chrome_url_constants.h"
18 #include "ios/chrome/browser/crash_report/breakpad_helper.h"
19 #import "ios/chrome/browser/crash_report/crash_report_background_uploader.h"
20 #include "ios/chrome/browser/experimental_flags.h"
21 #include "ios/chrome/browser/metrics/first_user_action_recorder.h"
22 #import "ios/chrome/browser/metrics/previous_session_info.h"
23 #import "ios/chrome/browser/net/connection_type_observer_bridge.h"
24 #include "ios/chrome/browser/pref_names.h"
25 #import "ios/chrome/browser/tabs/tab.h"
26 #import "ios/chrome/browser/tabs/tab_model.h"
27 #import "ios/chrome/browser/ui/main/browser_view_information.h"
28 #include "ios/chrome/common/app_group/app_group_metrics_mainapp.h"
29 #include "ios/public/provider/chrome/browser/chrome_browser_provider.h"
30 #include "ios/public/provider/chrome/browser/distribution/app_distribution_provi der.h"
31 #include "ios/web/public/web_thread.h"
32 #include "url/gurl.h"
33
34 namespace {
35 // The amount of time (in seconds) between two background fetch calls.
36 // TODO(crbug.com/496172): Re-enable background fetch.
37 const NSTimeInterval kBackgroundFetchIntervalDelay =
38 UIApplicationBackgroundFetchIntervalNever;
39 // The amount of time (in seconds) to wait for the user to start a new task.
40 const NSTimeInterval kFirstUserActionTimeout = 30.0;
41 } // namespace
42
43 namespace metrics_mediator {
44 NSString* const kAppEnteredBackgroundDateKey = @"kAppEnteredBackgroundDate";
45 } // namespace metrics_mediator_constants
46
47 using metrics_mediator::kAppEnteredBackgroundDateKey;
48
49 @interface MetricsMediator ()<CRConnectionTypeObserverBridge> {
50 // Whether or not the crash reports present at startup have been processed to
51 // determine if the last app lifetime ended in an OOM crash.
52 BOOL _hasProcessedCrashReportsPresentAtStartup;
53
54 // Observer for the connection type. Contains a valid object only if the
55 // metrics setting is set to wifi-only.
56 std::unique_ptr<ConnectionTypeObserverBridge> connectionTypeObserverBridge_;
57 }
58
59 // Starts or stops metrics recording and/or uploading.
60 - (void)setMetricsEnabled:(BOOL)enabled withUploading:(BOOL)allowUploading;
61 // Sets variables needed by the app_group application to collect UMA data.
62 // Process the pending logs produced by extensions.
63 // Called on start (cold and warm) and UMA settings change to update the
64 // collecting settings in extensions.
65 - (void)setAppGroupMetricsEnabled:(BOOL)enabled;
66 // Processes crash reports present at startup.
67 - (void)processCrashReportsPresentAtStartup;
68 // Starts or stops crash recording and/or uploading.
69 - (void)setBreakpadEnabled:(BOOL)enabled withUploading:(BOOL)allowUploading;
70 // Starts or stops watching for wwan events.
71 - (void)setWatchWWANEnabled:(BOOL)enabled;
72 // Enable/disable transmission of accumulated logs and crash reports (dumps).
73 - (void)setReporting:(BOOL)enableReporting;
74 // Enable/Disable uploading crash reports.
75 - (void)setBreakpadUploadingEnabled:(BOOL)enableUploading;
76 // Returns YES if the metrics are enabled and the reporting is wifi-only.
77 - (BOOL)isMetricsReportingEnabledWifiOnly;
78 // Update metrics prefs on a permission (opt-in/out) change. When opting out,
79 // this clears various client ids. When opting in, this resets saving crash
80 // prefs, so as not to trigger upload of various stale data.
81 // Mirrors the function in metrics_reporting_state.cc.
82 - (void)updateMetricsPrefsOnPermissionChange:(BOOL)enabled;
83 // Logs the number of tabs with UMAHistogramCount100 and allows testing.
84 + (void)recordNumTabAtStartup:(int)numTabs;
85 // Logs the number of tabs with UMAHistogramCount100 and allows testing.
86 + (void)recordNumTabAtResume:(int)numTabs;
87
88 @end
89
90 @implementation MetricsMediator
91
92 #pragma mark - Public methods.
93
94 + (void)logStartupDuration:(id<StartupInformation>)startupInformation {
95 if (![startupInformation isColdStart])
96 return;
97
98 base::TimeDelta startDuration =
99 base::TimeTicks::Now() - [startupInformation appLaunchTime];
100 if ([startupInformation startupParameters]) {
101 UMA_HISTOGRAM_TIMES("Startup.ColdStartWithExternalURLTime", startDuration);
102 } else {
103 UMA_HISTOGRAM_TIMES("Startup.ColdStartWithoutExternalURLTime",
104 startDuration);
105 }
106 }
107
108 + (void)logDateInUserDefaults {
109 [[NSUserDefaults standardUserDefaults]
110 setObject:[NSDate date]
111 forKey:metrics_mediator::kAppEnteredBackgroundDateKey];
112 }
113
114 + (void)logLaunchMetricsWithStartupInformation:
115 (id<StartupInformation>)startupInformation
116 browserViewInformation:
117 (id<BrowserViewInformation>)browserViewInformation {
118 int numTabs = static_cast<int>([[browserViewInformation mainTabModel] count]);
119 if (startupInformation.isColdStart) {
120 [self recordNumTabAtStartup:numTabs];
121 } else {
122 [self recordNumTabAtResume:numTabs];
123 }
124
125 if (UIAccessibilityIsVoiceOverRunning()) {
126 base::RecordAction(
127 base::UserMetricsAction("MobileVoiceOverActiveOnLaunch"));
128 }
129
130 // Create the first user action recorder and schedule a task to expire it
131 // after some timeout. If unable to determine the last time the app entered
132 // the background (i.e. either first run or restore after crash), don't bother
133 // recording the first user action since fresh start wouldn't be triggered.
134 NSDate* lastAppClose = [[NSUserDefaults standardUserDefaults]
135 objectForKey:kAppEnteredBackgroundDateKey];
136 if (lastAppClose) {
137 NSTimeInterval interval = -[lastAppClose timeIntervalSinceNow];
138 [startupInformation
139 activateFirstUserActionRecorderWithBackgroundTime:interval];
140 GURL ntpUrl = GURL(kChromeUINewTabURL);
141
142 Tab* currentTab = [[browserViewInformation currentTabModel] currentTab];
143 if (currentTab && [currentTab url] == ntpUrl) {
144 startupInformation.firstUserActionRecorder->RecordStartOnNTP();
145 [startupInformation resetFirstUserActionRecorder];
146 } else {
147 [startupInformation
148 expireFirstUserActionRecorderAfterDelay:kFirstUserActionTimeout];
149 }
150 // Remove the value so it's not reused if the app crashes.
151 [[NSUserDefaults standardUserDefaults]
152 removeObjectForKey:kAppEnteredBackgroundDateKey];
153 }
154 }
155
156 - (void)updateMetricsStateBasedOnPrefsUserTriggered:(BOOL)isUserTriggered {
157 BOOL optIn = [self areMetricsEnabled];
158 BOOL allowUploading = [self isUploadingEnabled];
159 BOOL wifiOnly = GetApplicationContext()->GetLocalState()->GetBoolean(
160 prefs::kMetricsReportingWifiOnly);
161
162 if (isUserTriggered)
163 [self updateMetricsPrefsOnPermissionChange:optIn];
164 [self setMetricsEnabled:optIn withUploading:allowUploading];
165 [self setBreakpadEnabled:optIn withUploading:allowUploading];
166 [self setWatchWWANEnabled:(optIn && wifiOnly)];
167 }
168
169 - (BOOL)areMetricsEnabled {
170 // If this if-def changes, it needs to be changed in
171 // IOSChromeMainParts::IsMetricsReportingEnabled and settings_egtest.mm.
172 #if defined(GOOGLE_CHROME_BUILD)
173 BOOL optIn = GetApplicationContext()->GetLocalState()->GetBoolean(
174 metrics::prefs::kMetricsReportingEnabled);
175 #else
176 // If a startup crash has been requested, then pretend that metrics have been
177 // enabled, so that the app will go into recovery mode.
178 BOOL optIn = experimental_flags::IsStartupCrashEnabled();
179 #endif
180 return optIn;
181 }
182
183 - (BOOL)isUploadingEnabled {
184 BOOL optIn = [self areMetricsEnabled];
185 BOOL wifiOnly = GetApplicationContext()->GetLocalState()->GetBoolean(
186 prefs::kMetricsReportingWifiOnly);
187 BOOL allowUploading = optIn;
188 if (optIn && wifiOnly) {
189 BOOL usingWWAN = net::NetworkChangeNotifier::IsConnectionCellular(
190 net::NetworkChangeNotifier::GetConnectionType());
191 allowUploading = !usingWWAN;
192 }
193 return allowUploading;
194 }
195
196 #pragma mark - Internal methods.
197
198 - (void)setMetricsEnabled:(BOOL)enabled withUploading:(BOOL)allowUploading {
199 metrics::MetricsService* metrics =
200 GetApplicationContext()->GetMetricsService();
201 DCHECK(metrics);
202 if (!metrics)
203 return;
204 if (enabled) {
205 [[UIApplication sharedApplication]
206 setMinimumBackgroundFetchInterval:kBackgroundFetchIntervalDelay];
207 if (!metrics->recording_active())
208 metrics->Start();
209
210 if (allowUploading)
211 metrics->EnableReporting();
212 else
213 metrics->DisableReporting();
214 } else {
215 if (metrics->recording_active())
216 metrics->Stop();
217 [[UIApplication sharedApplication]
218 setMinimumBackgroundFetchInterval:
219 UIApplicationBackgroundFetchIntervalNever];
220 }
221 }
222
223 - (void)setAppGroupMetricsEnabled:(BOOL)enabled {
224 metrics::MetricsService* metrics =
225 GetApplicationContext()->GetMetricsService();
226 if (enabled) {
227 PrefService* prefs = GetApplicationContext()->GetLocalState();
228 NSString* brandCode =
229 base::SysUTF8ToNSString(ios::GetChromeBrowserProvider()
230 ->GetAppDistributionProvider()
231 ->GetDistributionBrandCode());
232 app_group::main_app::EnableMetrics(
233 base::SysUTF8ToNSString(metrics->GetClientId()), brandCode,
234 prefs->GetInt64(metrics::prefs::kInstallDate),
235 prefs->GetInt64(metrics::prefs::kMetricsReportingEnabledTimestamp));
236 } else {
237 app_group::main_app::DisableMetrics();
238 }
239
240 // If metrics are enabled, process the logs. Otherwise, just delete them.
241 base::mac::ScopedBlock<app_group::ProceduralBlockWithData> callback;
242 if (enabled) {
243 callback.reset(
244 ^(NSData* log_content) {
245 std::string log(static_cast<const char*>([log_content bytes]),
246 static_cast<size_t>([log_content length]));
247 web::WebThread::PostTask(web::WebThread::UI, FROM_HERE,
248 base::BindBlock(^{
249 metrics->PushExternalLog(log);
250 }));
251 },
252 base::scoped_policy::RETAIN);
253 }
254
255 web::WebThread::PostTask(
256 web::WebThread::FILE, FROM_HERE,
257 base::Bind(&app_group::main_app::ProcessPendingLogs, callback));
258 }
259
260 - (void)processCrashReportsPresentAtStartup {
261 _hasProcessedCrashReportsPresentAtStartup = YES;
262
263 breakpad_helper::GetCrashReportCount(^(int crashReportCount) {
264 [[CrashReportBackgroundUploader sharedInstance]
265 setHasPendingCrashReportsToUploadAtStartup:(crashReportCount > 0)];
266 });
267 }
268
269 - (void)setBreakpadEnabled:(BOOL)enabled withUploading:(BOOL)allowUploading {
270 if (enabled) {
271 breakpad_helper::SetEnabled(true);
272
273 // Do some processing of the crash reports present at startup. Note that
274 // this processing must be done before uploading is enabled because once
275 // uploading starts the number of crash reports present will begin to
276 // decrease as they are uploaded. The ordering is ensured here because both
277 // the crash report processing and the upload enabling are handled by
278 // posting blocks to a single |dispath_queue_t| in BreakpadController.
279 if (!_hasProcessedCrashReportsPresentAtStartup && allowUploading) {
280 [self processCrashReportsPresentAtStartup];
281 }
282 [self setBreakpadUploadingEnabled:(![[PreviousSessionInfo sharedInstance]
283 isFirstSessionAfterUpgrade] &&
284 allowUploading)];
285 } else {
286 breakpad_helper::SetEnabled(false);
287 }
288 }
289
290 - (void)setWatchWWANEnabled:(BOOL)enabled {
291 if (!enabled) {
292 connectionTypeObserverBridge_.reset();
293 return;
294 }
295
296 if (!connectionTypeObserverBridge_) {
297 connectionTypeObserverBridge_.reset(new ConnectionTypeObserverBridge(self));
298 }
299 }
300
301 - (void)updateMetricsPrefsOnPermissionChange:(BOOL)enabled {
302 // TODO(crbug.com/635669): Consolidate with metrics_reporting_state.cc
303 // function.
304 metrics::MetricsService* metrics =
305 GetApplicationContext()->GetMetricsService();
306 DCHECK(metrics);
307 if (!metrics)
308 return;
309 if (enabled) {
310 // When a user opts in to the metrics reporting service, the previously
311 // collected data should be cleared to ensure that nothing is reported
312 // before a user opts in and all reported data is accurate.
313 if (!metrics->recording_active())
314 metrics->ClearSavedStabilityMetrics();
315 } else {
316 // Clear the client id pref when opting out.
317 // Note: Clearing client id will not affect the running state (e.g. field
318 // trial randomization), as the pref is only read on startup.
319 GetApplicationContext()->GetLocalState()->ClearPref(
320 metrics::prefs::kMetricsClientID);
321 GetApplicationContext()->GetLocalState()->ClearPref(
322 metrics::prefs::kMetricsReportingEnabledTimestamp);
323 crash_keys::ClearMetricsClientId();
324 }
325 }
326
327 + (void)disableReporting {
328 breakpad_helper::SetUploadingEnabled(false);
329 metrics::MetricsService* metrics =
330 GetApplicationContext()->GetMetricsService();
331 DCHECK(metrics);
332 metrics->DisableReporting();
333 }
334
335 + (void)applicationDidEnterBackground:(NSInteger)memoryWarningCount {
336 base::RecordAction(base::UserMetricsAction("MobileEnteredBackground"));
337 UMA_HISTOGRAM_COUNTS_100("MemoryWarning.OccurrencesPerSession",
338 memoryWarningCount);
339 }
340
341 #pragma mark - CRConnectionTypeObserverBridge implementation
342
343 - (void)connectionTypeChanged:(net::NetworkChangeNotifier::ConnectionType)type {
344 BOOL wwanEnabled = net::NetworkChangeNotifier::IsConnectionCellular(type);
345 // Currently the MainController only cares about WWAN state for the metrics
346 // reporting preference. If it's disabled, or the wifi-only preference is
347 // not set, we don't care. In fact, we should not even be getting this call.
348 DCHECK([self isMetricsReportingEnabledWifiOnly]);
349 // |wwanEnabled| is true if a cellular connection such as EDGE or GPRS is
350 // used. Otherwise, either there is no connection available, or another link
351 // (such as WiFi) is used.
352 if (wwanEnabled) {
353 // If WWAN mode is on, wifi-only prefs should be disabled.
354 // For the crash reporter, we still want to record the crashes.
355 [self setBreakpadUploadingEnabled:NO];
356 [self setReporting:NO];
357 } else if ([self areMetricsEnabled]) {
358 // Double-check that the metrics reporting preference is enabled.
359 if (![[PreviousSessionInfo sharedInstance] isFirstSessionAfterUpgrade])
360 [self setBreakpadUploadingEnabled:YES];
361 [self setReporting:YES];
362 }
363 }
364
365 #pragma mark - interfaces methods
366
367 + (void)recordNumTabAtStartup:(int)numTabs {
368 UMA_HISTOGRAM_COUNTS_100("Tabs.CountAtStartup", numTabs);
369 }
370
371 + (void)recordNumTabAtResume:(int)numTabs {
372 UMA_HISTOGRAM_COUNTS_100("Tabs.CountAtResume", numTabs);
373 }
374
375 - (void)setBreakpadUploadingEnabled:(BOOL)enableUploading {
376 breakpad_helper::SetUploadingEnabled(enableUploading);
377 }
378
379 - (void)setReporting:(BOOL)enableReporting {
380 if (enableReporting) {
381 GetApplicationContext()->GetMetricsService()->EnableReporting();
382 } else {
383 GetApplicationContext()->GetMetricsService()->DisableReporting();
384 }
385 }
386
387 - (BOOL)isMetricsReportingEnabledWifiOnly {
388 return GetApplicationContext()->GetLocalState()->GetBoolean(
389 metrics::prefs::kMetricsReportingEnabled) &&
390 GetApplicationContext()->GetLocalState()->GetBoolean(
391 prefs::kMetricsReportingWifiOnly);
392 }
393
394 @end
OLDNEW
« no previous file with comments | « ios/chrome/app/application_delegate/metrics_mediator.h ('k') | ios/chrome/app/application_delegate/metrics_mediator_testing.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698