Commit 823a98dd authored by Rohit Rao's avatar Rohit Rao Committed by Commit Bot

[ios] Removes product data splitting code from breadcrumbs.

Breakpad supports product data values up to 2550 bytes long, so there is
no need for breadcrumbs to implement additional splitting internally.
This CL removes the code that splits breadcrumbs data across keys,
simplifies APIs around setting breadcrumbs, and removes any associated
unittests.

BUG=1068802

Change-Id: Ia33320bcbe69c799d62a2ef36cf0e4d11d9f4566
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2146932
Commit-Queue: Rohit Rao <rohitrao@chromium.org>
Reviewed-by: default avatarEugene But <eugenebut@chromium.org>
Cr-Commit-Position: refs/heads/master@{#760122}
parent 27038f20
...@@ -12,10 +12,8 @@ ...@@ -12,10 +12,8 @@
namespace breakpad_helper { namespace breakpad_helper {
// Key format for breadcrumbs attached to crash reports. Format string contains // Key for breadcrumbs attached to crash reports.
// %lu for index as there are multiple breadcrumbs keys uploaded to crash extern NSString* const kBreadcrumbsProductDataKey;
// server.
extern NSString* const kBreadcrumbs;
// Starts the crash handlers. This must be run as soon as possible to catch // Starts the crash handlers. This must be run as soon as possible to catch
// early crashes. // early crashes.
...@@ -133,10 +131,8 @@ void SetGridToVisibleTabAnimation(NSString* to_view_controller, ...@@ -133,10 +131,8 @@ void SetGridToVisibleTabAnimation(NSString* to_view_controller,
// tab. // tab.
void RemoveGridToVisibleTabAnimation(); void RemoveGridToVisibleTabAnimation();
// Sets keys with the given |breadcrumbs|. Each item in |breadcrumbs| will be // Sets a key with the given |breadcrumbs| events.
// stored separately with kBreadcrumbs+<index> key (where kBreadcrumbs0 stores void SetBreadcrumbEvents(NSString* breadcrumbs);
// the latest breadscrumbs).
void SetBreadcrumbEvents(NSArray* breadcrumbs);
// Sets a key in browser to store the playback state of media player (audio or // Sets a key in browser to store the playback state of media player (audio or
// video). This function records a new start. This function is called for each // video). This function records a new start. This function is called for each
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
namespace breakpad_helper { namespace breakpad_helper {
NSString* const kBreadcrumbs = @"breadcrumbs%lu"; NSString* const kBreadcrumbsProductDataKey = @"breadcrumbs";
namespace { namespace {
...@@ -370,13 +370,8 @@ void RemoveGridToVisibleTabAnimation() { ...@@ -370,13 +370,8 @@ void RemoveGridToVisibleTabAnimation() {
RemoveReportParameter(kGridToVisibleTabAnimation); RemoveReportParameter(kGridToVisibleTabAnimation);
} }
void SetBreadcrumbEvents(NSArray* breadcrumbs) { void SetBreadcrumbEvents(NSString* breadcrumbs) {
DCHECK_GT(breadcrumbs.count, 0U); AddReportParameter(kBreadcrumbsProductDataKey, breadcrumbs, /*async=*/true);
DCHECK_LE(breadcrumbs.count, 6U);
for (NSUInteger i = 0; i < breadcrumbs.count; i++) {
NSString* key = [NSString stringWithFormat:kBreadcrumbs, i];
AddReportParameter(key, breadcrumbs[i], /*async=*/true);
}
} }
void MediaStreamPlaybackDidStart() { void MediaStreamPlaybackDidStart() {
......
...@@ -4,7 +4,9 @@ ...@@ -4,7 +4,9 @@
#import "ios/chrome/browser/crash_report/breakpad_helper.h" #import "ios/chrome/browser/crash_report/breakpad_helper.h"
#include "base/strings/sys_string_conversions.h"
#include "ios/chrome/browser/crash_report/crash_report_helper.h" #include "ios/chrome/browser/crash_report/crash_report_helper.h"
#include "ios/chrome/browser/crash_report/crash_reporter_breadcrumb_observer.h"
#include "ios/chrome/browser/crash_report/main_thread_freeze_detector.h" #include "ios/chrome/browser/crash_report/main_thread_freeze_detector.h"
#import "ios/chrome/test/ocmock/OCMockObject+BreakpadControllerTesting.h" #import "ios/chrome/test/ocmock/OCMockObject+BreakpadControllerTesting.h"
#import "ios/testing/scoped_block_swizzler.h" #import "ios/testing/scoped_block_swizzler.h"
...@@ -78,18 +80,9 @@ TEST_F(BreakpadHelperTest, CrashReportUserApplicationStateAllKeys) { ...@@ -78,18 +80,9 @@ TEST_F(BreakpadHelperTest, CrashReportUserApplicationStateAllKeys) {
@"presented_view_controller", @"parent_view_controller"); @"presented_view_controller", @"parent_view_controller");
breakpad_helper::MediaStreamPlaybackDidStart(); breakpad_helper::MediaStreamPlaybackDidStart();
// Build a sample breadcrumbs string greater than the maximum value size as // Set a max-length breadcrumbs string.
// defined in Breakpad.h at the BreakpadSetKeyValue function comment. std::string breadcrumbs(kMaxBreadcrumbsDataLength, 'A');
NSMutableString* breadcrumbs = [[NSMutableString alloc] init]; breakpad_helper::SetBreadcrumbEvents(base::SysUTF8ToNSString(breadcrumbs));
while (breadcrumbs.length < 255) {
[breadcrumbs appendString:@"12:01 Fake Breadcrumb Event/n"];
}
NSMutableArray* events = [[NSMutableArray alloc] init];
for (int i = 0; i < breakpad::kBreadcrumbsKeyCount; i++) {
[events addObject:breadcrumbs];
}
breakpad_helper::SetBreadcrumbEvents(events);
} }
TEST_F(BreakpadHelperTest, GetCrashReportCount) { TEST_F(BreakpadHelperTest, GetCrashReportCount) {
......
...@@ -18,12 +18,6 @@ class WebStateList; ...@@ -18,12 +18,6 @@ class WebStateList;
namespace breakpad { namespace breakpad {
// Number of product data keys to use for breadcrumbs. Each product key allows
// to upload limited amount of data (kMaxProductDataLength), so having
// multiple keys makes breadcrumbs more useful by having access to more
// breadcrumbs on crash reports.
extern const int kBreadcrumbsKeyCount;
// Monitors the urls loaded by |web_state| to allow crash reports to contain the // Monitors the urls loaded by |web_state| to allow crash reports to contain the
// current loading url. // current loading url.
void MonitorURLsForWebState(web::WebState* web_state); void MonitorURLsForWebState(web::WebState* web_state);
......
...@@ -38,12 +38,6 @@ ...@@ -38,12 +38,6 @@
#error "This file requires ARC support." #error "This file requires ARC support."
#endif #endif
namespace breakpad {
// IMPORTANT: be careful if ever increasing this value, Breakpad reports have an
// overall size limit
const int kBreadcrumbsKeyCount = 1;
}
// WebStateListObserver that allows loaded urls to be sent to the crash server. // WebStateListObserver that allows loaded urls to be sent to the crash server.
@interface CrashReporterURLObserver @interface CrashReporterURLObserver
: NSObject <WebStateListObserving, CRWWebStateObserver> { : NSObject <WebStateListObserving, CRWWebStateObserver> {
...@@ -454,8 +448,6 @@ void ClearStateForWebStateList(WebStateList* web_state_list) { ...@@ -454,8 +448,6 @@ void ClearStateForWebStateList(WebStateList* web_state_list) {
void MonitorBreadcrumbManager(BreadcrumbManager* breadcrumb_manager) { void MonitorBreadcrumbManager(BreadcrumbManager* breadcrumb_manager) {
[[CrashReporterBreadcrumbObserver uniqueInstance] [[CrashReporterBreadcrumbObserver uniqueInstance]
observeBreadcrumbManager:breadcrumb_manager]; observeBreadcrumbManager:breadcrumb_manager];
[CrashReporterBreadcrumbObserver uniqueInstance].breadcrumbsKeyCount =
kBreadcrumbsKeyCount;
} }
void StopMonitoringBreadcrumbManager(BreadcrumbManager* breadcrumb_manager) { void StopMonitoringBreadcrumbManager(BreadcrumbManager* breadcrumb_manager) {
......
...@@ -12,8 +12,8 @@ ...@@ -12,8 +12,8 @@
#import "ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_observer_bridge.h" #import "ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_observer_bridge.h"
// The maximum string length for product data supported by Breakpad. // The maximum string length for breadcrumbs data.
extern const int kMaxProductDataLength; extern const NSUInteger kMaxBreadcrumbsDataLength;
// Combines breadcrumbs from multiple BreadcrumbManagers and sends the merged // Combines breadcrumbs from multiple BreadcrumbManagers and sends the merged
// breadcrumb events to breakpad for attachment to crash reports. // breadcrumb events to breakpad for attachment to crash reports.
...@@ -24,12 +24,6 @@ extern const int kMaxProductDataLength; ...@@ -24,12 +24,6 @@ extern const int kMaxProductDataLength;
// Creates a singleton instance. // Creates a singleton instance.
+ (CrashReporterBreadcrumbObserver*)uniqueInstance; + (CrashReporterBreadcrumbObserver*)uniqueInstance;
// Number of product data keys to use for breadcrumbs.
@property(nonatomic) NSUInteger breadcrumbsKeyCount;
// Maximum allowed length for a single product data value.
@property(nonatomic) NSUInteger maxProductDataLength;
// Starts collecting breadcrumb events logged to |breadcrumbManager|. // Starts collecting breadcrumb events logged to |breadcrumbManager|.
- (void)observeBreadcrumbManager:(BreadcrumbManager*)breadcrumbManager; - (void)observeBreadcrumbManager:(BreadcrumbManager*)breadcrumbManager;
......
...@@ -12,6 +12,10 @@ ...@@ -12,6 +12,10 @@
#error "This file requires ARC support." #error "This file requires ARC support."
#endif #endif
// The breadcrumbs size cannot be larger than the maximum length of a single
// Breakpad product data value (currently 2550 bytes).
const NSUInteger kMaxBreadcrumbsDataLength = 1530;
@interface CrashReporterBreadcrumbObserver () { @interface CrashReporterBreadcrumbObserver () {
// Map associating the observed BreadcrumbManager with the corresponding // Map associating the observed BreadcrumbManager with the corresponding
// observer bridge instances. // observer bridge instances.
...@@ -42,7 +46,6 @@ ...@@ -42,7 +46,6 @@
- (instancetype)init { - (instancetype)init {
if ((self = [super init])) { if ((self = [super init])) {
_breadcrumbs = [[NSMutableString alloc] init]; _breadcrumbs = [[NSMutableString alloc] init];
_maxProductDataLength = 1530U; // 6 keys * 255 bytes/key
} }
return self; return self;
} }
...@@ -80,26 +83,14 @@ ...@@ -80,26 +83,14 @@
NSString* eventWithSeperator = [NSString stringWithFormat:@"%@\n", event]; NSString* eventWithSeperator = [NSString stringWithFormat:@"%@\n", event];
[_breadcrumbs insertString:eventWithSeperator atIndex:0]; [_breadcrumbs insertString:eventWithSeperator atIndex:0];
NSUInteger maxBreadcrumbsLength = if (_breadcrumbs.length > kMaxBreadcrumbsDataLength) {
self.breadcrumbsKeyCount * self.maxProductDataLength; NSRange trimRange =
if (_breadcrumbs.length > maxBreadcrumbsLength) { NSMakeRange(kMaxBreadcrumbsDataLength,
NSRange trimRange = NSMakeRange(maxBreadcrumbsLength, _breadcrumbs.length - kMaxBreadcrumbsDataLength);
_breadcrumbs.length - maxBreadcrumbsLength);
[_breadcrumbs deleteCharactersInRange:trimRange]; [_breadcrumbs deleteCharactersInRange:trimRange];
} }
// Cut breadcrumbs strings into multiple pieces and upload with separate keys. breakpad_helper::SetBreadcrumbEvents(_breadcrumbs);
NSMutableArray* breadcrumbs =
[[NSMutableArray alloc] initWithCapacity:self.breadcrumbsKeyCount];
for (NSUInteger i = 0; i < self.breadcrumbsKeyCount &&
(i * self.maxProductDataLength) < _breadcrumbs.length;
i++) {
NSUInteger location = i * self.maxProductDataLength;
NSRange range = NSMakeRange(location, MIN(self.maxProductDataLength,
_breadcrumbs.length - location));
[breadcrumbs addObject:[_breadcrumbs substringWithRange:range]];
}
breakpad_helper::SetBreadcrumbEvents(breadcrumbs);
} }
@end @end
...@@ -101,8 +101,6 @@ TEST_F(CrashReporterBreadcrumbObserverTest, EventsAttachedToCrashReport) { ...@@ -101,8 +101,6 @@ TEST_F(CrashReporterBreadcrumbObserverTest, EventsAttachedToCrashReport) {
chrome_browser_state_.get()); chrome_browser_state_.get());
CrashReporterBreadcrumbObserver* crash_reporter_breadcrumb_observer = CrashReporterBreadcrumbObserver* crash_reporter_breadcrumb_observer =
[[CrashReporterBreadcrumbObserver alloc] init]; [[CrashReporterBreadcrumbObserver alloc] init];
crash_reporter_breadcrumb_observer.breadcrumbsKeyCount =
breakpad::kBreadcrumbsKeyCount;
[crash_reporter_breadcrumb_observer [crash_reporter_breadcrumb_observer
observeBreadcrumbManagerService:breadcrumb_service]; observeBreadcrumbManagerService:breadcrumb_service];
...@@ -118,66 +116,15 @@ TEST_F(CrashReporterBreadcrumbObserverTest, EventsAttachedToCrashReport) { ...@@ -118,66 +116,15 @@ TEST_F(CrashReporterBreadcrumbObserverTest, EventsAttachedToCrashReport) {
return return
[value isEqualToString:base::SysUTF8ToNSString(expected_breadcrumbs)]; [value isEqualToString:base::SysUTF8ToNSString(expected_breadcrumbs)];
}]; }];
NSString* key = [NSString stringWithFormat:breakpad_helper::kBreadcrumbs, 0];
[[mock_breakpad_controller_ expect] [[mock_breakpad_controller_ expect]
addUploadParameter:breadcrumbs_param_vaidation_block addUploadParameter:breadcrumbs_param_vaidation_block
forKey:key]; forKey:breakpad_helper::kBreadcrumbsProductDataKey];
breadcrumb_service->AddEvent(std::string("Breadcrumb Event")); breadcrumb_service->AddEvent(std::string("Breadcrumb Event"));
EXPECT_OCMOCK_VERIFY(mock_breakpad_controller_); EXPECT_OCMOCK_VERIFY(mock_breakpad_controller_);
} }
// Tests that breadcrumb are spit into multiple product data keys. // Tests that breadcrumbs string is cut when it exceeds the max allowed length.
TEST_F(CrashReporterBreadcrumbObserverTest, MultipleKeysAttachedToCrashReport) {
[[mock_breakpad_controller_ expect] start:NO];
breakpad_helper::SetEnabled(true);
BreadcrumbManagerKeyedService* breadcrumb_service =
BreadcrumbManagerKeyedServiceFactory::GetForBrowserState(
chrome_browser_state_.get());
CrashReporterBreadcrumbObserver* crash_reporter_breadcrumb_observer =
[[CrashReporterBreadcrumbObserver alloc] init];
crash_reporter_breadcrumb_observer.breadcrumbsKeyCount = 2;
const int max_product_data_length = 255;
crash_reporter_breadcrumb_observer.maxProductDataLength =
max_product_data_length;
[crash_reporter_breadcrumb_observer
observeBreadcrumbManagerService:breadcrumb_service];
int time_size = strlen("00:00 ");
int linebreak_size = strlen("\n");
int breadcrumb_size = max_product_data_length - time_size - linebreak_size;
std::string value1 = base::StringPrintf("%0*d", breadcrumb_size, 1);
id validation_block1 = [OCMArg checkWithBlock:^(id value) {
EXPECT_NSEQ(
base::SysUTF8ToNSString(value1),
[value substringWithRange:NSMakeRange(time_size, breadcrumb_size)]);
return YES;
}];
NSString* key0 = [NSString stringWithFormat:breakpad_helper::kBreadcrumbs, 0];
[[mock_breakpad_controller_ expect] addUploadParameter:validation_block1
forKey:key0];
breadcrumb_service->AddEvent(value1);
std::string value2 = base::StringPrintf("%0*d", breadcrumb_size, 2);
id validation_block2 = [OCMArg checkWithBlock:^(id value) {
EXPECT_NSEQ(
base::SysUTF8ToNSString(value2),
[value substringWithRange:NSMakeRange(time_size, breadcrumb_size)]);
return YES;
}];
NSString* key1 = [NSString stringWithFormat:breakpad_helper::kBreadcrumbs, 1];
[[mock_breakpad_controller_ expect] addUploadParameter:validation_block2
forKey:key0];
[[mock_breakpad_controller_ expect] addUploadParameter:validation_block1
forKey:key1];
breadcrumb_service->AddEvent(value2);
EXPECT_OCMOCK_VERIFY(mock_breakpad_controller_);
}
// Tests that breadcrumbs string is cut when it does not fit into 2 product data
// keys.
TEST_F(CrashReporterBreadcrumbObserverTest, ProductDataOverflow) { TEST_F(CrashReporterBreadcrumbObserverTest, ProductDataOverflow) {
[[mock_breakpad_controller_ expect] start:NO]; [[mock_breakpad_controller_ expect] start:NO];
breakpad_helper::SetEnabled(true); breakpad_helper::SetEnabled(true);
...@@ -187,58 +134,25 @@ TEST_F(CrashReporterBreadcrumbObserverTest, ProductDataOverflow) { ...@@ -187,58 +134,25 @@ TEST_F(CrashReporterBreadcrumbObserverTest, ProductDataOverflow) {
chrome_browser_state_.get()); chrome_browser_state_.get());
CrashReporterBreadcrumbObserver* crash_reporter_breadcrumb_observer = CrashReporterBreadcrumbObserver* crash_reporter_breadcrumb_observer =
[[CrashReporterBreadcrumbObserver alloc] init]; [[CrashReporterBreadcrumbObserver alloc] init];
// Testing with 2 keys requires less code and complexity.
crash_reporter_breadcrumb_observer.breadcrumbsKeyCount = 2;
const int max_product_data_length = 255;
crash_reporter_breadcrumb_observer.maxProductDataLength =
max_product_data_length;
[crash_reporter_breadcrumb_observer [crash_reporter_breadcrumb_observer
observeBreadcrumbManagerService:breadcrumb_service]; observeBreadcrumbManagerService:breadcrumb_service];
int time_size = strlen("00:00 "); // Build a sample breadcrumbs string greater than the maximum allowed size.
int linebreak_size = strlen("\n"); NSMutableString* breadcrumbs = [[NSMutableString alloc] init];
int breadcrumb_size = max_product_data_length - time_size - linebreak_size; while (breadcrumbs.length < kMaxBreadcrumbsDataLength) {
std::string value1 = base::StringPrintf("%0*d", breadcrumb_size, 1); [breadcrumbs appendString:@"12:01 Fake Breadcrumb Event/n"];
id validation_block1 = [OCMArg checkWithBlock:^(id value) { }
EXPECT_NSEQ( [breadcrumbs appendString:@"12:01 Fake Breadcrumb Event/n"];
base::SysUTF8ToNSString(value1), ASSERT_GT([breadcrumbs length], kMaxBreadcrumbsDataLength);
[value substringWithRange:NSMakeRange(time_size, breadcrumb_size)]);
return YES;
}];
NSString* key0 = [NSString stringWithFormat:breakpad_helper::kBreadcrumbs, 0];
[[mock_breakpad_controller_ expect] addUploadParameter:validation_block1
forKey:key0];
breadcrumb_service->AddEvent(value1);
std::string value2 = base::StringPrintf("%0*d", breadcrumb_size, 2);
id validation_block2 = [OCMArg checkWithBlock:^(id value) {
EXPECT_NSEQ(
base::SysUTF8ToNSString(value2),
[value substringWithRange:NSMakeRange(time_size, breadcrumb_size)]);
return YES;
}];
NSString* key1 = [NSString stringWithFormat:breakpad_helper::kBreadcrumbs, 1];
[[mock_breakpad_controller_ expect] addUploadParameter:validation_block2
forKey:key0];
[[mock_breakpad_controller_ expect] addUploadParameter:validation_block1
forKey:key1];
breadcrumb_service->AddEvent(value2);
// |value1| will be cut off as overflow. id validation_block = [OCMArg checkWithBlock:^(id value) {
std::string value3 = base::StringPrintf("%0*d", breadcrumb_size, 3); EXPECT_EQ(kMaxBreadcrumbsDataLength, [value length]);
id validation_block3 = [OCMArg checkWithBlock:^(id value) {
EXPECT_NSEQ(
base::SysUTF8ToNSString(value3),
[value substringWithRange:NSMakeRange(time_size, breadcrumb_size)]);
return YES; return YES;
}]; }];
[[mock_breakpad_controller_ expect] addUploadParameter:validation_block3 [[mock_breakpad_controller_ expect]
forKey:key0]; addUploadParameter:validation_block
[[mock_breakpad_controller_ expect] addUploadParameter:validation_block2 forKey:breakpad_helper::kBreadcrumbsProductDataKey];
forKey:key1]; breadcrumb_service->AddEvent(base::SysNSStringToUTF8(breadcrumbs));
breadcrumb_service->AddEvent(value3);
EXPECT_OCMOCK_VERIFY(mock_breakpad_controller_); EXPECT_OCMOCK_VERIFY(mock_breakpad_controller_);
} }
...@@ -258,16 +172,13 @@ TEST_F(CrashReporterBreadcrumbObserverTest, ...@@ -258,16 +172,13 @@ TEST_F(CrashReporterBreadcrumbObserverTest,
chrome_browser_state_.get()); chrome_browser_state_.get());
CrashReporterBreadcrumbObserver* crash_reporter_breadcrumb_observer = CrashReporterBreadcrumbObserver* crash_reporter_breadcrumb_observer =
[[CrashReporterBreadcrumbObserver alloc] init]; [[CrashReporterBreadcrumbObserver alloc] init];
crash_reporter_breadcrumb_observer.breadcrumbsKeyCount =
breakpad::kBreadcrumbsKeyCount;
[crash_reporter_breadcrumb_observer [crash_reporter_breadcrumb_observer
observeBreadcrumbManagerService:breadcrumb_service]; observeBreadcrumbManagerService:breadcrumb_service];
NSString* key = [NSString stringWithFormat:breakpad_helper::kBreadcrumbs, 0];
[[mock_breakpad_controller_ expect] [[mock_breakpad_controller_ expect]
addUploadParameter:StringParameterValidatorWithCountOfSubstring( addUploadParameter:StringParameterValidatorWithCountOfSubstring(
1, event_nsstring) 1, event_nsstring)
forKey:key]; forKey:breakpad_helper::kBreadcrumbsProductDataKey];
breadcrumb_service->AddEvent(event); breadcrumb_service->AddEvent(event);
ChromeBrowserState* otr_browser_state = ChromeBrowserState* otr_browser_state =
...@@ -281,7 +192,7 @@ TEST_F(CrashReporterBreadcrumbObserverTest, ...@@ -281,7 +192,7 @@ TEST_F(CrashReporterBreadcrumbObserverTest,
[[mock_breakpad_controller_ expect] [[mock_breakpad_controller_ expect]
addUploadParameter:StringParameterValidatorWithCountOfSubstring( addUploadParameter:StringParameterValidatorWithCountOfSubstring(
2, event_nsstring) 2, event_nsstring)
forKey:key]; forKey:breakpad_helper::kBreadcrumbsProductDataKey];
otr_breadcrumb_service->AddEvent(event); otr_breadcrumb_service->AddEvent(event);
TestChromeBrowserState::Builder test_cbs_builder; TestChromeBrowserState::Builder test_cbs_builder;
...@@ -296,7 +207,7 @@ TEST_F(CrashReporterBreadcrumbObserverTest, ...@@ -296,7 +207,7 @@ TEST_F(CrashReporterBreadcrumbObserverTest,
[[mock_breakpad_controller_ expect] [[mock_breakpad_controller_ expect]
addUploadParameter:StringParameterValidatorWithCountOfSubstring( addUploadParameter:StringParameterValidatorWithCountOfSubstring(
3, event_nsstring) 3, event_nsstring)
forKey:key]; forKey:breakpad_helper::kBreadcrumbsProductDataKey];
breadcrumb_service_2->AddEvent(event); breadcrumb_service_2->AddEvent(event);
EXPECT_OCMOCK_VERIFY(mock_breakpad_controller_); EXPECT_OCMOCK_VERIFY(mock_breakpad_controller_);
......
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