22// Use of this source code is governed by a BSD-style license that can be
33// found in the LICENSE file.
44
5+ import * as fs from 'fs' ;
6+ import * as os from 'os' ;
57import * as path from 'path' ;
68import * as puppeteer from 'puppeteer-core' ;
79import * as url from 'url' ;
@@ -24,6 +26,55 @@ export class BrowserWrapper {
2426 async createBrowserContext ( ) {
2527 return await this . browser . createBrowserContext ( ) ;
2628 }
29+
30+ copyCrahsDumps ( ) {
31+ const crashesPath = this . #getCrashpadDir( ) ;
32+ if ( ! fs . existsSync ( crashesPath ) ) {
33+ // TODO (liviurau): Determine where exactly does Crashpad store the dumps on
34+ // Linux and Windows.
35+ console . error ( 'No crash dumps found at location ' , crashesPath ) ;
36+ return ;
37+ }
38+ for ( const file of fs . readdirSync ( crashesPath ) ) {
39+ console . error ( 'Collecting crash dump:' , file ) ;
40+ fs . copyFileSync ( path . join ( crashesPath , file ) , path . join ( TestConfig . artifactsDir , file ) ) ;
41+ }
42+ }
43+
44+ #getCrashpadDir( ) {
45+ // TODO (liviurau): generate a tmp dir and pass when launching puppeteer
46+ // instead of parsing it out of args
47+ const userDataArg = this . browser . process ( ) ?. spawnargs . find ( arg => arg . startsWith ( '--user-data-dir=' ) ) ;
48+ if ( userDataArg ) {
49+ const configuredPath = path . join ( userDataArg . split ( '=' ) [ 1 ] , 'Crashpad' , 'pending' ) ;
50+ // `--user-data-dir` generally does not contain Craspad files on any
51+ // platform. In the future this might get properly aligned so we search
52+ // here first.
53+ if ( fs . existsSync ( configuredPath ) ) {
54+ return configuredPath ;
55+ }
56+ }
57+ const homeDir = os . homedir ( ) ;
58+ const platform = os . platform ( ) ;
59+ switch ( platform ) {
60+ case 'darwin' :
61+ return path . join (
62+ homeDir , 'Library' , 'Application Support' , 'Google' , 'Chrome for Testing' , 'Crashpad' , 'pending' ) ;
63+ case 'win32' : {
64+ const localAppData = path . join (
65+ process . env . LOCALAPPDATA ?? '' , 'Google' , 'Chrome for Testing' , 'User Data' , 'Crashpad' , 'pending' ) ;
66+ if ( fs . existsSync ( localAppData ) ) {
67+ return localAppData ;
68+ }
69+ return path . join (
70+ homeDir , 'AppData' , 'Local' , 'Google' , 'Chrome for Testing' , 'User Data' , 'Crashpad' , 'pending' ) ;
71+ }
72+ case 'linux' :
73+ return path . join ( homeDir , '.config' , 'google-chrome-for-testing' , 'Crashpad' , 'pending' ) ;
74+ default :
75+ throw new Error ( `Unsupported platform: ${ platform } ` ) ;
76+ }
77+ }
2778}
2879export class Launcher {
2980 static async browserSetup ( settings : BrowserSettings ) {
@@ -52,6 +103,9 @@ export class Launcher {
52103 `--disable-features=${ disabledFeatures . join ( ',' ) } ` ,
53104 '--auto-open-devtools-for-tabs' ,
54105 `--custom-devtools-frontend=${ frontEndDirectory } ` ,
106+ '--enable-crash-reporter' ,
107+ // This has no effect (see https://crbug.com/435638630)
108+ `--crash-dumps-dir=${ TestConfig . artifactsDir } ` ,
55109 ] ;
56110 const headless = TestConfig . headless ;
57111 // CDP commands in e2e and interaction should not generally take
@@ -65,6 +119,10 @@ export class Launcher {
65119 dumpio : ! headless || Boolean ( process . env [ 'LUCI_CONTEXT' ] ) ,
66120 protocolTimeout,
67121 networkEnabled : false ,
122+ ignoreDefaultArgs : [
123+ '--disable-crash-reporter' ,
124+ '--disable-breakpad' ,
125+ ] ,
68126 } ;
69127
70128 TestConfig . configureChrome ( executablePath ) ;
0 commit comments