Commit 887d5d28 authored by Eugene But's avatar Eugene But Committed by Commit Bot

[ios] Add variations to synthetic crash reports

Synthetic crash reports created for UTEs (unexpected termination events)
to provide some information about the crash. Synthetic crash reports can
contain Breadcrumbs, session uptime, OS version, Device Type and other
similar information to understand why app has crashed. Variations will
help with slicing crashes by Finch study and look for culprits among
launched features.

Bug: 1103752
Change-Id: I440d5acaf7fab5b5d81d6137e2ae4603c78e5330
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2462822
Commit-Queue: Eugene But <eugenebut@chromium.org>
Reviewed-by: default avatarLei Zhang <thestig@chromium.org>
Reviewed-by: default avatarOlivier Robin <olivierrobin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#817218}
parent f9c17f09
...@@ -99,6 +99,7 @@ target(crash_key_target_type, "crash_key_lib") { ...@@ -99,6 +99,7 @@ target(crash_key_target_type, "crash_key_lib") {
if (is_ios) { if (is_ios) {
sources += [ "crash_key_breakpad_ios.mm" ] sources += [ "crash_key_breakpad_ios.mm" ]
deps += [ "//components/previous_session_info" ]
configs += [ "//build/config/compiler:enable_arc" ] configs += [ "//build/config/compiler:enable_arc" ]
} else { } else {
......
include_rules = [ include_rules = [
"+components/gwp_asan/buildflags/buildflags.h", "+components/gwp_asan/buildflags/buildflags.h",
"+components/gwp_asan/client/sampling_malloc_shims.h", "+components/gwp_asan/client/sampling_malloc_shims.h",
"+components/previous_session_info/previous_session_info.h",
"+third_party/breakpad/breakpad/src/client/ios/Breakpad.h", "+third_party/breakpad/breakpad/src/client/ios/Breakpad.h",
"+third_party/breakpad/breakpad/src/client/ios/BreakpadController.h", "+third_party/breakpad/breakpad/src/client/ios/BreakpadController.h",
] ]
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "base/strings/sys_string_conversions.h" #include "base/strings/sys_string_conversions.h"
#include "components/crash/core/common/crash_key_base_support.h" #include "components/crash/core/common/crash_key_base_support.h"
#import "components/previous_session_info/previous_session_info.h"
#import "third_party/breakpad/breakpad/src/client/ios/Breakpad.h" #import "third_party/breakpad/breakpad/src/client/ios/Breakpad.h"
#import "third_party/breakpad/breakpad/src/client/ios/BreakpadController.h" #import "third_party/breakpad/breakpad/src/client/ios/BreakpadController.h"
...@@ -55,6 +56,9 @@ void CrashKeyStringImpl::Set(base::StringPiece value) { ...@@ -55,6 +56,9 @@ void CrashKeyStringImpl::Set(base::StringPiece value) {
WithBreakpadRefAsync(^(BreakpadRef ref) { WithBreakpadRefAsync(^(BreakpadRef ref) {
BreakpadAddUploadParameter(ref, key, value_ns); BreakpadAddUploadParameter(ref, key, value_ns);
}); });
[[PreviousSessionInfo sharedInstance] setReportParameterValue:value_ns
forKey:key];
} }
void CrashKeyStringImpl::Clear() { void CrashKeyStringImpl::Clear() {
...@@ -63,6 +67,7 @@ void CrashKeyStringImpl::Clear() { ...@@ -63,6 +67,7 @@ void CrashKeyStringImpl::Clear() {
WithBreakpadRefAsync(^(BreakpadRef ref) { WithBreakpadRefAsync(^(BreakpadRef ref) {
BreakpadRemoveUploadParameter(ref, key); BreakpadRemoveUploadParameter(ref, key);
}); });
[[PreviousSessionInfo sharedInstance] removeReportParameterForKey:key];
} }
bool CrashKeyStringImpl::is_set() const { bool CrashKeyStringImpl::is_set() const {
......
...@@ -24,8 +24,8 @@ extern NSString* const kPreviousSessionInfoRestoringSession; ...@@ -24,8 +24,8 @@ extern NSString* const kPreviousSessionInfoRestoringSession;
// Key in the UserDefaults for an array which contains the ids for the connected // Key in the UserDefaults for an array which contains the ids for the connected
// scene sessions on the previous run. // scene sessions on the previous run.
extern NSString* const kPreviousSessionInfoConnectedSceneSessionIDs; extern NSString* const kPreviousSessionInfoConnectedSceneSessionIDs;
// Key in the UserDefaults for a dictionary with navigation URLs. // Key in the UserDefaults for a dictionary with session info params.
extern NSString* const kPreviousSessionInfoURLs; extern NSString* const kPreviousSessionInfoParams;
// The values of this enum are persisted (both to NSUserDefaults and logs) and // The values of this enum are persisted (both to NSUserDefaults and logs) and
// represent the state of the last session (which may have been running a // represent the state of the last session (which may have been running a
...@@ -128,9 +128,9 @@ enum class DeviceBatteryState { ...@@ -128,9 +128,9 @@ enum class DeviceBatteryState {
@property(nonatomic, readonly) @property(nonatomic, readonly)
NSMutableSet<NSString*>* connectedSceneSessionsIDs; NSMutableSet<NSString*>* connectedSceneSessionsIDs;
// Pending and committed navigation URLs. // Crash report parameters as key-value pairs.
@property(nonatomic, readonly) @property(nonatomic, readonly)
NSDictionary<NSString*, NSString*>* reportParameterURLs; NSDictionary<NSString*, NSString*>* reportParameters;
// Singleton PreviousSessionInfo. During the lifetime of the app, the returned // Singleton PreviousSessionInfo. During the lifetime of the app, the returned
// object is the same, and describes the previous session, even after a new // object is the same, and describes the previous session, even after a new
...@@ -185,7 +185,8 @@ enum class DeviceBatteryState { ...@@ -185,7 +185,8 @@ enum class DeviceBatteryState {
// gets destructed. // gets destructed.
- (void)resetSessionRestorationFlag; - (void)resetSessionRestorationFlag;
// Records information about pending and committed navigation URLs. // Records information crash report parameters.
- (void)setReportParameterValue:(NSString*)value forKey:(NSString*)key;
- (void)setReportParameterURL:(const GURL&)URL forKey:(NSString*)key; - (void)setReportParameterURL:(const GURL&)URL forKey:(NSString*)key;
- (void)removeReportParameterForKey:(NSString*)key; - (void)removeReportParameterForKey:(NSString*)key;
......
...@@ -105,7 +105,7 @@ NSString* const kPreviousSessionInfoRestoringSession = ...@@ -105,7 +105,7 @@ NSString* const kPreviousSessionInfoRestoringSession =
@"PreviousSessionInfoRestoringSession"; @"PreviousSessionInfoRestoringSession";
NSString* const kPreviousSessionInfoConnectedSceneSessionIDs = NSString* const kPreviousSessionInfoConnectedSceneSessionIDs =
@"PreviousSessionInfoConnectedSceneSessionIDs"; @"PreviousSessionInfoConnectedSceneSessionIDs";
NSString* const kPreviousSessionInfoURLs = @"PreviousSessionInfoURLs"; NSString* const kPreviousSessionInfoParams = @"PreviousSessionInfoParams";
} // namespace previous_session_info_constants } // namespace previous_session_info_constants
@interface PreviousSessionInfo () @interface PreviousSessionInfo ()
...@@ -136,8 +136,7 @@ NSString* const kPreviousSessionInfoURLs = @"PreviousSessionInfoURLs"; ...@@ -136,8 +136,7 @@ NSString* const kPreviousSessionInfoURLs = @"PreviousSessionInfoURLs";
@property(nonatomic, strong) NSDate* sessionEndTime; @property(nonatomic, strong) NSDate* sessionEndTime;
@property(nonatomic, assign) BOOL terminatedDuringSessionRestoration; @property(nonatomic, assign) BOOL terminatedDuringSessionRestoration;
@property(nonatomic, strong) NSMutableSet<NSString*>* connectedSceneSessionsIDs; @property(nonatomic, strong) NSMutableSet<NSString*>* connectedSceneSessionsIDs;
@property(nonatomic, copy) @property(nonatomic, copy) NSDictionary<NSString*, NSString*>* reportParameters;
NSDictionary<NSString*, NSString*>* reportParameterURLs;
@end @end
...@@ -225,9 +224,9 @@ static PreviousSessionInfo* gSharedInstance = nil; ...@@ -225,9 +224,9 @@ static PreviousSessionInfo* gSharedInstance = nil;
[defaults boolForKey:previous_session_info_constants:: [defaults boolForKey:previous_session_info_constants::
kPreviousSessionInfoRestoringSession]; kPreviousSessionInfoRestoringSession];
gSharedInstance.reportParameterURLs = gSharedInstance.reportParameters =
[defaults dictionaryForKey:previous_session_info_constants:: [defaults dictionaryForKey:previous_session_info_constants::
kPreviousSessionInfoURLs]; kPreviousSessionInfoParams];
} }
return gSharedInstance; return gSharedInstance;
} }
...@@ -529,25 +528,31 @@ static PreviousSessionInfo* gSharedInstance = nil; ...@@ -529,25 +528,31 @@ static PreviousSessionInfo* gSharedInstance = nil;
[NSUserDefaults.standardUserDefaults synchronize]; [NSUserDefaults.standardUserDefaults synchronize];
} }
- (void)setReportParameterURL:(const GURL&)URL forKey:(NSString*)key { - (void)setReportParameterValue:(NSString*)value forKey:(NSString*)key {
NSMutableDictionary* URLs = [[NSUserDefaults.standardUserDefaults NSMutableDictionary* params = [[NSUserDefaults.standardUserDefaults
dictionaryForKey:previous_session_info_constants:: dictionaryForKey:previous_session_info_constants::
kPreviousSessionInfoURLs] mutableCopy]; kPreviousSessionInfoParams] mutableCopy];
if (!URLs) { if (!params) {
URLs = [NSMutableDictionary dictionaryWithCapacity:1]; params = [NSMutableDictionary dictionaryWithCapacity:1];
} }
// Store only URL origin (not whole URL spec) as requested by Privacy Team. params[key] = value;
URLs[key] = base::SysUTF8ToNSString(URL.GetOrigin().spec().c_str());
[NSUserDefaults.standardUserDefaults [NSUserDefaults.standardUserDefaults
setObject:URLs setObject:params
forKey:previous_session_info_constants::kPreviousSessionInfoURLs]; forKey:previous_session_info_constants::kPreviousSessionInfoParams];
[NSUserDefaults.standardUserDefaults synchronize]; [NSUserDefaults.standardUserDefaults synchronize];
} }
- (void)setReportParameterURL:(const GURL&)URL forKey:(NSString*)key {
// Store only URL origin (not whole URL spec) as requested by Privacy Team.
[self setReportParameterValue:base::SysUTF8ToNSString(
URL.GetOrigin().spec().c_str())
forKey:key];
}
- (void)removeReportParameterForKey:(NSString*)key { - (void)removeReportParameterForKey:(NSString*)key {
NSMutableDictionary* URLs = [[NSUserDefaults.standardUserDefaults NSMutableDictionary* URLs = [[NSUserDefaults.standardUserDefaults
dictionaryForKey:previous_session_info_constants:: dictionaryForKey:previous_session_info_constants::
kPreviousSessionInfoURLs] mutableCopy]; kPreviousSessionInfoParams] mutableCopy];
if (URLs) { if (URLs) {
URLs[key] = nil; URLs[key] = nil;
if (URLs.count == 0) { if (URLs.count == 0) {
...@@ -555,7 +560,7 @@ static PreviousSessionInfo* gSharedInstance = nil; ...@@ -555,7 +560,7 @@ static PreviousSessionInfo* gSharedInstance = nil;
} }
[NSUserDefaults.standardUserDefaults [NSUserDefaults.standardUserDefaults
setObject:URLs setObject:URLs
forKey:previous_session_info_constants::kPreviousSessionInfoURLs]; forKey:previous_session_info_constants::kPreviousSessionInfoParams];
[NSUserDefaults.standardUserDefaults synchronize]; [NSUserDefaults.standardUserDefaults synchronize];
} }
} }
......
...@@ -22,8 +22,7 @@ ...@@ -22,8 +22,7 @@
@property(nonatomic, strong) NSDate* sessionEndTime; @property(nonatomic, strong) NSDate* sessionEndTime;
@property(nonatomic, assign) BOOL terminatedDuringSessionRestoration; @property(nonatomic, assign) BOOL terminatedDuringSessionRestoration;
@property(nonatomic, strong) NSMutableSet<NSString*>* connectedSceneSessionsIDs; @property(nonatomic, strong) NSMutableSet<NSString*>* connectedSceneSessionsIDs;
@property(nonatomic, copy) @property(nonatomic, copy) NSDictionary<NSString*, NSString*>* reportParameters;
NSDictionary<NSString*, NSString*>* reportParameterURLs;
+ (void)resetSharedInstanceForTesting; + (void)resetSharedInstanceForTesting;
......
...@@ -472,21 +472,21 @@ TEST_F(PreviousSessionInfoTest, ...@@ -472,21 +472,21 @@ TEST_F(PreviousSessionInfoTest,
terminatedDuringSessionRestoration]); terminatedDuringSessionRestoration]);
} }
// Tests added and removing navigation URLs. // Tests adding and removing report parameters.
TEST_F(PreviousSessionInfoTest, ReportParameterURLs) { TEST_F(PreviousSessionInfoTest, ReportParameters) {
// Default state. // Default state.
[NSUserDefaults.standardUserDefaults [NSUserDefaults.standardUserDefaults
removeObjectForKey:previous_session_info_constants:: removeObjectForKey:previous_session_info_constants::
kPreviousSessionInfoURLs]; kPreviousSessionInfoParams];
[PreviousSessionInfo resetSharedInstanceForTesting]; [PreviousSessionInfo resetSharedInstanceForTesting];
EXPECT_FALSE([PreviousSessionInfo sharedInstance].reportParameterURLs); EXPECT_FALSE([PreviousSessionInfo sharedInstance].reportParameters);
// Removing non-existing key does not crash. // Removing non-existing key does not crash.
NSString* const kKey0 = @"url0"; NSString* const kKey0 = @"url0";
[[PreviousSessionInfo sharedInstance] removeReportParameterForKey:kKey0]; [[PreviousSessionInfo sharedInstance] removeReportParameterForKey:kKey0];
[PreviousSessionInfo resetSharedInstanceForTesting]; [PreviousSessionInfo resetSharedInstanceForTesting];
EXPECT_FALSE([PreviousSessionInfo sharedInstance].reportParameterURLs); EXPECT_FALSE([PreviousSessionInfo sharedInstance].reportParameters);
// Add first URL. // Add first URL.
[[PreviousSessionInfo sharedInstance] [[PreviousSessionInfo sharedInstance]
...@@ -495,10 +495,10 @@ TEST_F(PreviousSessionInfoTest, ReportParameterURLs) { ...@@ -495,10 +495,10 @@ TEST_F(PreviousSessionInfoTest, ReportParameterURLs) {
NSDictionary<NSString*, NSString*>* URLs = NSDictionary<NSString*, NSString*>* URLs =
[NSUserDefaults.standardUserDefaults [NSUserDefaults.standardUserDefaults
dictionaryForKey:previous_session_info_constants:: dictionaryForKey:previous_session_info_constants::
kPreviousSessionInfoURLs]; kPreviousSessionInfoParams];
EXPECT_NSEQ(@{kKey0 : @"https://example.test/"}, URLs); // stores only origin EXPECT_NSEQ(@{kKey0 : @"https://example.test/"}, URLs); // stores only origin
[PreviousSessionInfo resetSharedInstanceForTesting]; [PreviousSessionInfo resetSharedInstanceForTesting];
EXPECT_NSEQ(URLs, [[PreviousSessionInfo sharedInstance] reportParameterURLs]); EXPECT_NSEQ(URLs, [[PreviousSessionInfo sharedInstance] reportParameters]);
// Update first URL. // Update first URL.
[[PreviousSessionInfo sharedInstance] [[PreviousSessionInfo sharedInstance]
...@@ -506,10 +506,10 @@ TEST_F(PreviousSessionInfoTest, ReportParameterURLs) { ...@@ -506,10 +506,10 @@ TEST_F(PreviousSessionInfoTest, ReportParameterURLs) {
forKey:kKey0]; forKey:kKey0];
URLs = [NSUserDefaults.standardUserDefaults URLs = [NSUserDefaults.standardUserDefaults
dictionaryForKey:previous_session_info_constants:: dictionaryForKey:previous_session_info_constants::
kPreviousSessionInfoURLs]; kPreviousSessionInfoParams];
EXPECT_NSEQ(@{kKey0 : @"https://example2.test/"}, URLs); EXPECT_NSEQ(@{kKey0 : @"https://example2.test/"}, URLs);
[PreviousSessionInfo resetSharedInstanceForTesting]; [PreviousSessionInfo resetSharedInstanceForTesting];
EXPECT_NSEQ(URLs, [[PreviousSessionInfo sharedInstance] reportParameterURLs]); EXPECT_NSEQ(URLs, [[PreviousSessionInfo sharedInstance] reportParameters]);
// Add second URL. // Add second URL.
NSString* const kKey1 = @"url1"; NSString* const kKey1 = @"url1";
...@@ -518,37 +518,37 @@ TEST_F(PreviousSessionInfoTest, ReportParameterURLs) { ...@@ -518,37 +518,37 @@ TEST_F(PreviousSessionInfoTest, ReportParameterURLs) {
forKey:kKey1]; forKey:kKey1];
URLs = [NSUserDefaults.standardUserDefaults URLs = [NSUserDefaults.standardUserDefaults
dictionaryForKey:previous_session_info_constants:: dictionaryForKey:previous_session_info_constants::
kPreviousSessionInfoURLs]; kPreviousSessionInfoParams];
NSDictionary<NSString*, NSString*>* expected = @{ NSDictionary<NSString*, NSString*>* expected = @{
kKey0 : @"https://example2.test/", kKey0 : @"https://example2.test/",
kKey1 : @"https://example3.test/", kKey1 : @"https://example3.test/",
}; };
EXPECT_NSEQ(expected, URLs); EXPECT_NSEQ(expected, URLs);
[PreviousSessionInfo resetSharedInstanceForTesting]; [PreviousSessionInfo resetSharedInstanceForTesting];
EXPECT_NSEQ(URLs, [[PreviousSessionInfo sharedInstance] reportParameterURLs]); EXPECT_NSEQ(URLs, [[PreviousSessionInfo sharedInstance] reportParameters]);
// Removing non-existing key does not crash. // Removing non-existing key does not crash.
[[PreviousSessionInfo sharedInstance] removeReportParameterForKey:@"url2"]; [[PreviousSessionInfo sharedInstance] removeReportParameterForKey:@"url2"];
[PreviousSessionInfo resetSharedInstanceForTesting]; [PreviousSessionInfo resetSharedInstanceForTesting];
EXPECT_NSEQ(URLs, [[PreviousSessionInfo sharedInstance] reportParameterURLs]); EXPECT_NSEQ(URLs, [[PreviousSessionInfo sharedInstance] reportParameters]);
// Remove first URL. // Remove first URL.
[[PreviousSessionInfo sharedInstance] removeReportParameterForKey:kKey0]; [[PreviousSessionInfo sharedInstance] removeReportParameterForKey:kKey0];
URLs = [NSUserDefaults.standardUserDefaults URLs = [NSUserDefaults.standardUserDefaults
dictionaryForKey:previous_session_info_constants:: dictionaryForKey:previous_session_info_constants::
kPreviousSessionInfoURLs]; kPreviousSessionInfoParams];
EXPECT_NSEQ(@{kKey1 : @"https://example3.test/"}, URLs); EXPECT_NSEQ(@{kKey1 : @"https://example3.test/"}, URLs);
[PreviousSessionInfo resetSharedInstanceForTesting]; [PreviousSessionInfo resetSharedInstanceForTesting];
EXPECT_NSEQ(URLs, [[PreviousSessionInfo sharedInstance] reportParameterURLs]); EXPECT_NSEQ(URLs, [[PreviousSessionInfo sharedInstance] reportParameters]);
// Remove second URL. // Remove second URL.
[[PreviousSessionInfo sharedInstance] removeReportParameterForKey:kKey1]; [[PreviousSessionInfo sharedInstance] removeReportParameterForKey:kKey1];
URLs = [NSUserDefaults.standardUserDefaults URLs = [NSUserDefaults.standardUserDefaults
dictionaryForKey:previous_session_info_constants:: dictionaryForKey:previous_session_info_constants::
kPreviousSessionInfoURLs]; kPreviousSessionInfoParams];
EXPECT_FALSE(URLs); EXPECT_FALSE(URLs);
[PreviousSessionInfo resetSharedInstanceForTesting]; [PreviousSessionInfo resetSharedInstanceForTesting];
EXPECT_FALSE([[PreviousSessionInfo sharedInstance] reportParameterURLs]); EXPECT_FALSE([[PreviousSessionInfo sharedInstance] reportParameters]);
[PreviousSessionInfo resetSharedInstanceForTesting]; [PreviousSessionInfo resetSharedInstanceForTesting];
} }
......
...@@ -93,12 +93,12 @@ void CreateSyntheticCrashReportForUte( ...@@ -93,12 +93,12 @@ void CreateSyntheticCrashReportForUte(
AppendConfig(config, "BreakpadServerParameterPrefix_platform", AppendConfig(config, "BreakpadServerParameterPrefix_platform",
base::SysInfo::HardwareModelName()); base::SysInfo::HardwareModelName());
for (NSString* key in previous_session.reportParameterURLs.allKeys) { for (NSString* key in previous_session.reportParameters.allKeys) {
AppendConfig( AppendConfig(
config, config,
base::StringPrintf("BreakpadServerParameterPrefix_%s", base::StringPrintf("BreakpadServerParameterPrefix_%s",
base::SysNSStringToUTF8(key).c_str()), base::SysNSStringToUTF8(key).c_str()),
base::SysNSStringToUTF8(previous_session.reportParameterURLs[key])); base::SysNSStringToUTF8(previous_session.reportParameters[key]));
} }
if (previous_session.sessionStartTime && previous_session.sessionEndTime) { if (previous_session.sessionStartTime && previous_session.sessionEndTime) {
......
...@@ -41,7 +41,7 @@ TEST_F(SyntheticCrashReportUtilTest, CreateSyntheticCrashReportForUte) { ...@@ -41,7 +41,7 @@ TEST_F(SyntheticCrashReportUtilTest, CreateSyntheticCrashReportForUte) {
previous_session.OSVersion = kOSVersion; previous_session.OSVersion = kOSVersion;
previous_session.terminatedDuringSessionRestoration = YES; previous_session.terminatedDuringSessionRestoration = YES;
NSString* const kURL = @"URL"; NSString* const kURL = @"URL";
previous_session.reportParameterURLs = @{@"url" : kURL}; previous_session.reportParameters = @{@"url" : kURL};
previous_session.sessionStartTime = [NSDate date]; previous_session.sessionStartTime = [NSDate date];
const NSTimeInterval kUptimeMs = 5000; const NSTimeInterval kUptimeMs = 5000;
previous_session.sessionEndTime = [previous_session.sessionStartTime previous_session.sessionEndTime = [previous_session.sessionStartTime
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment