browsertime 16.16.0 → 17.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +52 -0
- package/bin/browsertime.js +43 -43
- package/bin/browsertimeWebPageReplay.js +10 -9
- package/browserscripts/pageinfo/generator.js +1 -1
- package/index.js +14 -13
- package/lib/android/gnirehtet.js +14 -15
- package/lib/android/index.js +92 -89
- package/lib/android/root.js +6 -9
- package/lib/chrome/chromeDevtoolsProtocol.js +46 -45
- package/lib/chrome/har.js +12 -13
- package/lib/chrome/longTaskMetrics.js +3 -5
- package/lib/chrome/parseCpuTrace.js +13 -10
- package/lib/chrome/settings/chromeAndroidOptions.js +1 -3
- package/lib/chrome/settings/chromeDesktopOptions.js +1 -3
- package/lib/chrome/settings/traceCategories.js +1 -3
- package/lib/chrome/traceCategoriesParser.js +35 -36
- package/lib/chrome/webdriver/builder.js +18 -26
- package/lib/chrome/webdriver/chromium.js +56 -46
- package/lib/chrome/webdriver/setupChromiumOptions.js +32 -27
- package/lib/connectivity/humble.js +13 -14
- package/lib/connectivity/index.js +74 -77
- package/lib/connectivity/trafficShapeParser.js +31 -35
- package/lib/core/engine/collector.js +25 -22
- package/lib/core/engine/command/addText.js +24 -27
- package/lib/core/engine/command/android.js +7 -11
- package/lib/core/engine/command/cache.js +3 -4
- package/lib/core/engine/command/chromeDevToolsProtocol.js +20 -20
- package/lib/core/engine/command/click.js +48 -49
- package/lib/core/engine/command/debug.js +3 -4
- package/lib/core/engine/command/javaScript.js +18 -19
- package/lib/core/engine/command/measure.js +31 -37
- package/lib/core/engine/command/meta.js +1 -4
- package/lib/core/engine/command/mouse/clickAndHold.js +36 -39
- package/lib/core/engine/command/mouse/contextClick.js +17 -18
- package/lib/core/engine/command/mouse/doubleClick.js +17 -19
- package/lib/core/engine/command/mouse/index.js +5 -9
- package/lib/core/engine/command/mouse/mouseMove.js +19 -23
- package/lib/core/engine/command/mouse/singleClick.js +15 -19
- package/lib/core/engine/command/navigation.js +12 -14
- package/lib/core/engine/command/screenshot.js +1 -4
- package/lib/core/engine/command/scroll.js +4 -7
- package/lib/core/engine/command/select.js +26 -26
- package/lib/core/engine/command/set.js +25 -23
- package/lib/core/engine/command/stopWatch.js +5 -8
- package/lib/core/engine/command/switch.js +18 -20
- package/lib/core/engine/command/util/lcpHighlightScript.js +1 -2
- package/lib/core/engine/command/util/lsHighlightScript.js +1 -2
- package/lib/core/engine/command/wait.js +18 -18
- package/lib/core/engine/index.js +81 -71
- package/lib/core/engine/iteration.js +93 -79
- package/lib/core/engine/run.js +5 -9
- package/lib/core/pageCompleteChecks/defaultPageCompleteCheck.js +1 -2
- package/lib/core/pageCompleteChecks/pageCompleteCheckByInactivity.js +1 -3
- package/lib/core/pageCompleteChecks/spaInactivity.js +1 -3
- package/lib/core/seleniumRunner.js +92 -100
- package/lib/core/webdriver/index.js +24 -21
- package/lib/edge/webdriver/builder.js +21 -26
- package/lib/extensionserver/httpServer.js +17 -21
- package/lib/extensionserver/index.js +8 -12
- package/lib/extensionserver/setup.js +12 -12
- package/lib/firefox/geckoProfiler.js +27 -21
- package/lib/firefox/getHAR.js +7 -8
- package/lib/firefox/memoryReport.js +9 -11
- package/lib/firefox/perfStats.js +5 -7
- package/lib/firefox/settings/disableSafeBrowsingPreferences.js +1 -3
- package/lib/firefox/settings/disableTrackingProtectionPreferences.js +1 -3
- package/lib/firefox/settings/firefoxPreferences.js +2 -4
- package/lib/firefox/settings/geckoProfilerDefaults.js +5 -9
- package/lib/firefox/webdriver/builder.js +66 -63
- package/lib/firefox/webdriver/firefox.js +43 -48
- package/lib/safari/webdriver/builder.js +4 -5
- package/lib/safari/webdriver/safari.js +4 -8
- package/lib/screenshot/defaults.js +1 -3
- package/lib/screenshot/index.js +24 -21
- package/lib/support/browserScript.js +65 -56
- package/lib/support/cli.js +123 -85
- package/lib/support/dns.js +6 -7
- package/lib/support/engineUtils.js +85 -38
- package/lib/support/errors.js +4 -13
- package/lib/support/fileUtil.js +81 -68
- package/lib/support/filters.js +15 -20
- package/lib/support/getViewPort.js +6 -7
- package/lib/support/har/index.js +208 -216
- package/lib/support/images/index.js +54 -26
- package/lib/support/logging.js +20 -17
- package/lib/support/pathToFolder.js +18 -23
- package/lib/support/preURL.js +5 -6
- package/lib/support/processes.js +4 -6
- package/lib/support/setResourceTimingBufferSize.js +2 -4
- package/lib/support/statistics.js +58 -56
- package/lib/support/stop.js +7 -8
- package/lib/support/storageManager.js +44 -44
- package/lib/support/tcpdump.js +22 -16
- package/lib/support/userTiming.js +7 -13
- package/lib/support/util.js +204 -224
- package/lib/support/xvfb.js +11 -13
- package/lib/video/defaults.js +6 -10
- package/lib/video/postprocessing/finetune/addTextToVideo.js +15 -15
- package/lib/video/postprocessing/finetune/convertFps.js +14 -8
- package/lib/video/postprocessing/finetune/getFont.js +7 -9
- package/lib/video/postprocessing/finetune/getTimingMetrics.js +19 -18
- package/lib/video/postprocessing/finetune/index.js +40 -36
- package/lib/video/postprocessing/finetune/removeOrange.js +10 -11
- package/lib/video/postprocessing/visualmetrics/extraMetrics.js +17 -13
- package/lib/video/postprocessing/visualmetrics/getVideoMetrics.js +12 -13
- package/lib/video/postprocessing/visualmetrics/visualMetrics.js +117 -128
- package/lib/video/screenRecording/android/recorder.js +12 -17
- package/lib/video/screenRecording/desktop/convert.js +13 -11
- package/lib/video/screenRecording/desktop/desktopRecorder.js +29 -24
- package/lib/video/screenRecording/desktop/ffmpegRecorder.js +60 -63
- package/lib/video/screenRecording/desktop/osx/getSPDisplaysDataType.js +4 -6
- package/lib/video/screenRecording/desktop/osx/getScreen.js +9 -10
- package/lib/video/screenRecording/firefox/firefoxWindowRecorder.js +54 -54
- package/lib/video/screenRecording/ios/convertToMp4.js +10 -11
- package/lib/video/screenRecording/ios/iosRecorder.js +23 -21
- package/lib/video/screenRecording/iosSimulator/convertToMp4.js +10 -11
- package/lib/video/screenRecording/iosSimulator/recorder.js +10 -9
- package/lib/video/screenRecording/recorder.js +8 -9
- package/lib/video/screenRecording/setOrangeBackground.js +5 -6
- package/lib/video/video.js +28 -34
- package/package.json +19 -17
|
@@ -1,21 +1,20 @@
|
|
|
1
|
-
|
|
1
|
+
import intel from 'intel';
|
|
2
|
+
import { computeMainThreadTasks } from '@sitespeed.io/tracium';
|
|
3
|
+
const log = intel.getLogger('browsertime.chrome.cpu');
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
const Tracium = require('@sitespeed.io/tracium');
|
|
5
|
-
|
|
6
|
-
function round(num, decimals = 3) {
|
|
5
|
+
function round(number_, decimals = 3) {
|
|
7
6
|
const pow = Math.pow(10, decimals);
|
|
8
|
-
return Math.round(
|
|
7
|
+
return Math.round(number_ * pow) / pow;
|
|
9
8
|
}
|
|
10
9
|
|
|
11
10
|
function slowestFirst(a, b) {
|
|
12
11
|
return b.value - a.value;
|
|
13
12
|
}
|
|
14
13
|
|
|
15
|
-
|
|
14
|
+
export default async (tracelog, url) => {
|
|
16
15
|
try {
|
|
17
16
|
log.debug('Start parse Chrome trace log using Tracium.');
|
|
18
|
-
const tasks =
|
|
17
|
+
const tasks = computeMainThreadTasks(tracelog, {
|
|
19
18
|
flatten: true
|
|
20
19
|
});
|
|
21
20
|
log.debug('Finished parsing the trace log using Tracium.');
|
|
@@ -80,8 +79,12 @@ module.exports = async (tracelog, url) => {
|
|
|
80
79
|
|
|
81
80
|
log.debug('Chrome trace log finished parsed and sorted.');
|
|
82
81
|
return { categories, events, urls: cleanedUrls };
|
|
83
|
-
} catch (
|
|
84
|
-
log.error(
|
|
82
|
+
} catch (error) {
|
|
83
|
+
log.error(
|
|
84
|
+
'Could not parse the trace log from Chrome for url %s',
|
|
85
|
+
url,
|
|
86
|
+
error
|
|
87
|
+
);
|
|
85
88
|
return {};
|
|
86
89
|
}
|
|
87
90
|
};
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
2
|
* Options when we run Chrome on Android
|
|
5
3
|
* see https://github.com/GoogleChrome/chrome-launcher/blob/master/docs/chrome-flags-for-tools.md
|
|
6
4
|
* https://peter.sh/experiments/chromium-command-line-switches/
|
|
7
5
|
*/
|
|
8
|
-
|
|
6
|
+
export default [
|
|
9
7
|
'--disable-fre',
|
|
10
8
|
// : Disable reporting to UMA, but allows for collection
|
|
11
9
|
'--metrics-recording-only',
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
1
|
// See https://github.com/GoogleChrome/chrome-launcher/blob/master/docs/chrome-flags-for-tools.md
|
|
4
2
|
// https://peter.sh/experiments/chromium-command-line-switches/
|
|
5
|
-
|
|
3
|
+
export default [
|
|
6
4
|
'--disable-background-networking',
|
|
7
5
|
'--no-default-browser-check',
|
|
8
6
|
'--no-first-run',
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const log = require('intel').getLogger('browsertime.chrome.trace');
|
|
1
|
+
import intel from 'intel';
|
|
2
|
+
const log = intel.getLogger('browsertime.chrome.trace');
|
|
4
3
|
|
|
5
4
|
// Adopting the Lighthouse way to clean the Trace log
|
|
6
5
|
// https://github.com/GoogleChrome/lighthouse/blob/50a68ab2bf0115427e767e5e40dfe6be671902fe/lighthouse-core/config/config.js#L29-L110
|
|
@@ -15,20 +14,20 @@ function cleanTrace(trace, url) {
|
|
|
15
14
|
const threads = [];
|
|
16
15
|
const countsByThread = {};
|
|
17
16
|
const traceStartEvents = [];
|
|
18
|
-
const makeMockEvent = (
|
|
17
|
+
const makeMockEvent = (event, ts) => {
|
|
19
18
|
return {
|
|
20
|
-
pid:
|
|
21
|
-
tid:
|
|
19
|
+
pid: event.pid,
|
|
20
|
+
tid: event.tid,
|
|
22
21
|
ts: ts || 0, // default to 0 for now
|
|
23
22
|
ph: 'I',
|
|
24
23
|
cat: 'disabled-by-default-devtools.timeline',
|
|
25
24
|
name: 'TracingStartedInPage',
|
|
26
25
|
args: {
|
|
27
26
|
data: {
|
|
28
|
-
page:
|
|
27
|
+
page: event.frame,
|
|
29
28
|
frames: [
|
|
30
29
|
{
|
|
31
|
-
frame:
|
|
30
|
+
frame: event.frame,
|
|
32
31
|
name: '',
|
|
33
32
|
url: url
|
|
34
33
|
}
|
|
@@ -39,7 +38,8 @@ function cleanTrace(trace, url) {
|
|
|
39
38
|
};
|
|
40
39
|
};
|
|
41
40
|
|
|
42
|
-
|
|
41
|
+
// eslint-disable-next-line unicorn/consistent-function-scoping
|
|
42
|
+
const makeNavStart = (event, ts, tts, fid, url) => {
|
|
43
43
|
return {
|
|
44
44
|
args: {
|
|
45
45
|
data: {
|
|
@@ -52,8 +52,8 @@ function cleanTrace(trace, url) {
|
|
|
52
52
|
cat: 'blink.user_timing',
|
|
53
53
|
name: 'navigationStart',
|
|
54
54
|
ph: 'R',
|
|
55
|
-
pid:
|
|
56
|
-
tid:
|
|
55
|
+
pid: event.pid,
|
|
56
|
+
tid: event.tid,
|
|
57
57
|
ts: ts || 0,
|
|
58
58
|
tts: tts || 0
|
|
59
59
|
};
|
|
@@ -64,27 +64,29 @@ function cleanTrace(trace, url) {
|
|
|
64
64
|
let name;
|
|
65
65
|
let counter;
|
|
66
66
|
|
|
67
|
-
traceEvents.
|
|
68
|
-
if (
|
|
69
|
-
traceStartEvents.push(
|
|
67
|
+
for (const [index_, event] of traceEvents.entries()) {
|
|
68
|
+
if (event.name.startsWith('TracingStartedIn')) {
|
|
69
|
+
traceStartEvents.push(index_);
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
// find the event's frame
|
|
73
73
|
data =
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
event.args &&
|
|
75
|
+
(event.args.data || event.args.beginData || event.args.counters);
|
|
76
|
+
frame =
|
|
77
|
+
(event.args && event.args.frame) || (data && (data.frame || data.page));
|
|
76
78
|
|
|
77
79
|
if (!frame) {
|
|
78
|
-
|
|
80
|
+
continue;
|
|
79
81
|
}
|
|
80
82
|
|
|
81
83
|
// Increase occurences count of the frame
|
|
82
|
-
name = `pid${
|
|
84
|
+
name = `pid${event.pid}-tid${event.tid}-frame${frame}`;
|
|
83
85
|
counter = countsByThread[name];
|
|
84
86
|
if (!counter) {
|
|
85
87
|
counter = {
|
|
86
|
-
pid:
|
|
87
|
-
tid:
|
|
88
|
+
pid: event.pid,
|
|
89
|
+
tid: event.tid,
|
|
88
90
|
frame: frame,
|
|
89
91
|
count: 0
|
|
90
92
|
};
|
|
@@ -92,7 +94,7 @@ function cleanTrace(trace, url) {
|
|
|
92
94
|
threads.push(counter);
|
|
93
95
|
}
|
|
94
96
|
counter.count++;
|
|
95
|
-
}
|
|
97
|
+
}
|
|
96
98
|
|
|
97
99
|
// find most active thread (and frame)
|
|
98
100
|
threads.sort((a, b) => b.count - a.count);
|
|
@@ -107,10 +109,10 @@ function cleanTrace(trace, url) {
|
|
|
107
109
|
traceEvents[traceStartEvents[0]] && traceEvents[traceStartEvents[0]].tts;
|
|
108
110
|
|
|
109
111
|
// account for offset after removing items
|
|
110
|
-
let
|
|
112
|
+
let index = 0;
|
|
111
113
|
for (let dup of traceStartEvents) {
|
|
112
|
-
traceEvents.splice(dup -
|
|
113
|
-
|
|
114
|
+
traceEvents.splice(dup - index, 1);
|
|
115
|
+
index++;
|
|
114
116
|
}
|
|
115
117
|
|
|
116
118
|
// Add a new TracingStartedInPage event based on most active thread
|
|
@@ -151,15 +153,12 @@ function cleanTrace(trace, url) {
|
|
|
151
153
|
return trace;
|
|
152
154
|
}
|
|
153
155
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
return cleanTrace({ traceEvents: events }, url);
|
|
164
|
-
}
|
|
165
|
-
};
|
|
156
|
+
export function parse(events, url) {
|
|
157
|
+
// const cleaned = [];
|
|
158
|
+
/*for (let event of events) {
|
|
159
|
+
if (event.method === 'Tracing.dataCollected') {
|
|
160
|
+
cleaned.push(event.params);
|
|
161
|
+
}
|
|
162
|
+
}*/
|
|
163
|
+
return cleanTrace({ traceEvents: events }, url);
|
|
164
|
+
}
|
|
@@ -1,28 +1,26 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const get = require('lodash.get');
|
|
9
|
-
const setupChromiumOptions = require('./setupChromiumOptions');
|
|
1
|
+
import pick from 'lodash.pick';
|
|
2
|
+
import isEmpty from 'lodash.isempty';
|
|
3
|
+
import get from 'lodash.get';
|
|
4
|
+
import { logging } from 'selenium-webdriver';
|
|
5
|
+
import { ServiceBuilder, Options } from 'selenium-webdriver/chrome.js';
|
|
6
|
+
import { pac, manual } from 'selenium-webdriver/proxy.js';
|
|
7
|
+
import setupChromiumOptions from './setupChromiumOptions.js';
|
|
10
8
|
|
|
11
9
|
/**
|
|
12
10
|
* Configure a WebDriver builder based on the specified options.
|
|
13
11
|
* @param builder
|
|
14
12
|
* @param {Object} options the options for a web driver.
|
|
15
13
|
*/
|
|
16
|
-
|
|
14
|
+
export async function configureBuilder(builder, baseDir, options) {
|
|
17
15
|
const chromeConfig = options.chrome || {};
|
|
18
16
|
|
|
19
17
|
let chromedriverPath = get(chromeConfig, 'chromedriverPath');
|
|
20
18
|
if (!chromedriverPath) {
|
|
21
|
-
|
|
22
|
-
chromedriverPath = chromedriver.binPath();
|
|
19
|
+
let chromedriver = await import('@sitespeed.io/chromedriver');
|
|
20
|
+
chromedriverPath = chromedriver.default.binPath();
|
|
23
21
|
}
|
|
24
22
|
|
|
25
|
-
const serviceBuilder = new
|
|
23
|
+
const serviceBuilder = new ServiceBuilder(chromedriverPath);
|
|
26
24
|
|
|
27
25
|
// Remove the check that matches the Chromedriver version with Chrome version.
|
|
28
26
|
serviceBuilder.addArguments('--disable-build-check');
|
|
@@ -44,27 +42,21 @@ module.exports.configureBuilder = function (builder, baseDir, options) {
|
|
|
44
42
|
const proxyPacSettings = pick(options.proxy, ['pac']);
|
|
45
43
|
|
|
46
44
|
if (!isEmpty(proxyPacSettings)) {
|
|
47
|
-
builder.setProxy(
|
|
45
|
+
builder.setProxy(pac(proxyPacSettings));
|
|
48
46
|
}
|
|
49
47
|
|
|
50
48
|
const proxySettings = pick(options.proxy, ['ftp', 'http', 'https', 'bypass']);
|
|
51
49
|
|
|
52
50
|
if (!isEmpty(proxySettings)) {
|
|
53
|
-
builder.setProxy(
|
|
51
|
+
builder.setProxy(manual(proxySettings));
|
|
54
52
|
}
|
|
55
53
|
|
|
56
|
-
let chromeOptions = new
|
|
57
|
-
let logPrefs = new
|
|
58
|
-
logPrefs.setLevel(
|
|
59
|
-
webdriver.logging.Type.PERFORMANCE,
|
|
60
|
-
webdriver.logging.Level.ALL
|
|
61
|
-
);
|
|
54
|
+
let chromeOptions = new Options();
|
|
55
|
+
let logPrefs = new logging.Preferences();
|
|
56
|
+
logPrefs.setLevel(logging.Type.PERFORMANCE, logging.Level.ALL);
|
|
62
57
|
|
|
63
58
|
if (chromeConfig.collectConsoleLog) {
|
|
64
|
-
logPrefs.setLevel(
|
|
65
|
-
webdriver.logging.Type.BROWSER,
|
|
66
|
-
webdriver.logging.Level.ALL
|
|
67
|
-
);
|
|
59
|
+
logPrefs.setLevel(logging.Type.BROWSER, logging.Level.ALL);
|
|
68
60
|
}
|
|
69
61
|
|
|
70
62
|
chromeOptions.setLoggingPrefs(logPrefs);
|
|
@@ -77,4 +69,4 @@ module.exports.configureBuilder = function (builder, baseDir, options) {
|
|
|
77
69
|
setupChromiumOptions(chromeOptions, chromeConfig, options, baseDir);
|
|
78
70
|
|
|
79
71
|
builder.setChromeOptions(chromeOptions);
|
|
80
|
-
}
|
|
72
|
+
}
|
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const unlink = promisify(
|
|
19
|
-
const rm = promisify(
|
|
1
|
+
import { promisify } from 'node:util';
|
|
2
|
+
import { unlink as _unlink, rm as _rm } from 'node:fs';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { logging } from 'selenium-webdriver';
|
|
5
|
+
import intel from 'intel';
|
|
6
|
+
const log = intel.getLogger('browsertime.chrome');
|
|
7
|
+
const { Type } = logging;
|
|
8
|
+
import cpuMetrics from '../longTaskMetrics.js';
|
|
9
|
+
import parseCpuTrace from '../parseCpuTrace.js';
|
|
10
|
+
import har from '../har.js';
|
|
11
|
+
import { getEmptyHAR, mergeHars } from '../../support/har/index.js';
|
|
12
|
+
import { toArray } from '../../support/util.js';
|
|
13
|
+
import { logging as _logging } from 'selenium-webdriver';
|
|
14
|
+
import { parse } from '../traceCategoriesParser.js';
|
|
15
|
+
import pathToFolder from '../../support/pathToFolder.js';
|
|
16
|
+
import ChromeDevtoolsProtocol from '../chromeDevtoolsProtocol.js';
|
|
17
|
+
import { Android, isAndroidConfigured } from '../../android/index.js';
|
|
18
|
+
const unlink = promisify(_unlink);
|
|
19
|
+
const rm = promisify(_rm);
|
|
20
20
|
|
|
21
21
|
class Chromium {
|
|
22
22
|
constructor(storageManager, options) {
|
|
@@ -41,7 +41,7 @@ class Chromium {
|
|
|
41
41
|
*/
|
|
42
42
|
async beforeBrowserStart() {
|
|
43
43
|
this.events = [];
|
|
44
|
-
if (this.options
|
|
44
|
+
if (isAndroidConfigured(this.options)) {
|
|
45
45
|
this.android = new Android(this.options);
|
|
46
46
|
if (this.options.androidPower) {
|
|
47
47
|
await this.android.startPowerTesting();
|
|
@@ -64,7 +64,7 @@ class Chromium {
|
|
|
64
64
|
// We create the cdp as early as possible so it can be used in scripts
|
|
65
65
|
// https://bugs.chromium.org/p/chromium/issues/detail?id=824626
|
|
66
66
|
// https://github.com/cyrus-and/chrome-remote-interface/issues/332
|
|
67
|
-
if (this.options
|
|
67
|
+
if (isAndroidConfigured(this.options)) {
|
|
68
68
|
await this.android.addDevtoolsFw();
|
|
69
69
|
}
|
|
70
70
|
|
|
@@ -224,12 +224,12 @@ class Chromium {
|
|
|
224
224
|
|
|
225
225
|
if (this.chrome.collectNetLog && !this.chrome.android) {
|
|
226
226
|
await this.storageManager.createSubDataDir(
|
|
227
|
-
|
|
227
|
+
join(pathToFolder(result.url, this.options))
|
|
228
228
|
);
|
|
229
229
|
|
|
230
230
|
await this.storageManager.gzip(
|
|
231
231
|
`${this.baseDir}/chromeNetlog.json`,
|
|
232
|
-
|
|
232
|
+
join(
|
|
233
233
|
this.baseDir,
|
|
234
234
|
pathToFolder(result.url, this.options),
|
|
235
235
|
`chromeNetlog-${index}.json.gz`
|
|
@@ -242,7 +242,7 @@ class Chromium {
|
|
|
242
242
|
result.extraJson = {};
|
|
243
243
|
}
|
|
244
244
|
result.extraJson[`console-${index}.json`] = await runner.getLogs(
|
|
245
|
-
|
|
245
|
+
_logging.Type.BROWSER
|
|
246
246
|
);
|
|
247
247
|
}
|
|
248
248
|
|
|
@@ -268,17 +268,29 @@ class Chromium {
|
|
|
268
268
|
const cleanedMetrics = {};
|
|
269
269
|
let ns, fmp;
|
|
270
270
|
for (let m of rawCDPMetrics.metrics) {
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
271
|
+
switch (m.name) {
|
|
272
|
+
case 'DomContentLoaded':
|
|
273
|
+
case 'Timestamp': {
|
|
274
|
+
// skip
|
|
275
|
+
|
|
276
|
+
break;
|
|
277
|
+
}
|
|
278
|
+
case 'FirstMeaningfulPaint': {
|
|
279
|
+
fmp = m.value;
|
|
280
|
+
|
|
281
|
+
break;
|
|
282
|
+
}
|
|
283
|
+
case 'NavigationStart': {
|
|
284
|
+
ns = m.value;
|
|
285
|
+
|
|
286
|
+
break;
|
|
287
|
+
}
|
|
288
|
+
default: {
|
|
289
|
+
if (m.name.includes('Duration')) {
|
|
290
|
+
cleanedMetrics[m.name] = m.value * 1000;
|
|
291
|
+
} else {
|
|
292
|
+
cleanedMetrics[m.name] = m.value;
|
|
293
|
+
}
|
|
282
294
|
}
|
|
283
295
|
}
|
|
284
296
|
}
|
|
@@ -303,13 +315,13 @@ class Chromium {
|
|
|
303
315
|
|
|
304
316
|
if (this.chrome.collectNetLog && this.chrome.android) {
|
|
305
317
|
// THIS needs to be unique per page
|
|
306
|
-
const filename =
|
|
318
|
+
const filename = join(
|
|
307
319
|
this.baseDir,
|
|
308
320
|
pathToFolder(result.url, this.options),
|
|
309
321
|
`chromeNetlog-${index}.json`
|
|
310
322
|
);
|
|
311
323
|
|
|
312
|
-
const gzFilename =
|
|
324
|
+
const gzFilename = join(
|
|
313
325
|
this.baseDir,
|
|
314
326
|
pathToFolder(result.url, this.options),
|
|
315
327
|
`chromeNetlog-${index}.json.gz`
|
|
@@ -320,7 +332,7 @@ class Chromium {
|
|
|
320
332
|
}
|
|
321
333
|
|
|
322
334
|
if (this.collectTracingEvents) {
|
|
323
|
-
const trace =
|
|
335
|
+
const trace = parse(this.events, result.url);
|
|
324
336
|
result.extraJson[`trace-${index}.json`] = trace;
|
|
325
337
|
const cpu = await parseCpuTrace(trace, result.url);
|
|
326
338
|
result.cpu = cpu;
|
|
@@ -433,7 +445,7 @@ class Chromium {
|
|
|
433
445
|
if (this.skipHar) {
|
|
434
446
|
return;
|
|
435
447
|
}
|
|
436
|
-
this.hars.push(
|
|
448
|
+
this.hars.push(getEmptyHAR(url, this.options.browser));
|
|
437
449
|
}
|
|
438
450
|
|
|
439
451
|
/**
|
|
@@ -464,15 +476,15 @@ class Chromium {
|
|
|
464
476
|
this.chrome.cleanUserDataDir &&
|
|
465
477
|
!this.chrome.android
|
|
466
478
|
) {
|
|
467
|
-
const args =
|
|
479
|
+
const args = toArray(this.chrome.args);
|
|
468
480
|
for (let arg of args) {
|
|
469
481
|
if (arg.includes('user-data-dir')) {
|
|
470
482
|
const userDataDir = arg.split('=')[1];
|
|
471
483
|
try {
|
|
472
484
|
await rm(userDataDir, { recursive: true });
|
|
473
485
|
log.info(`Deleted user data dir: ${userDataDir}`);
|
|
474
|
-
} catch (
|
|
475
|
-
log.error(`Could not delete user data dir: ${userDataDir}`,
|
|
486
|
+
} catch (error) {
|
|
487
|
+
log.error(`Could not delete user data dir: ${userDataDir}`, error);
|
|
476
488
|
}
|
|
477
489
|
}
|
|
478
490
|
}
|
|
@@ -480,9 +492,7 @@ class Chromium {
|
|
|
480
492
|
}
|
|
481
493
|
|
|
482
494
|
async getHARs() {
|
|
483
|
-
|
|
484
|
-
return { har: harBuilder.mergeHars(this.hars) };
|
|
485
|
-
} else return {};
|
|
495
|
+
return !this.skipHar ? { har: mergeHars(this.hars) } : {};
|
|
486
496
|
}
|
|
487
497
|
|
|
488
498
|
async setCookies(url, cookies) {
|
|
@@ -490,4 +500,4 @@ class Chromium {
|
|
|
490
500
|
}
|
|
491
501
|
}
|
|
492
502
|
|
|
493
|
-
|
|
503
|
+
export default Chromium;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import intel from 'intel';
|
|
3
|
+
import defaultChromeOptions from '../settings/chromeDesktopOptions.js';
|
|
4
|
+
import defaultAndroidChromeOptions from '../settings/chromeAndroidOptions.js';
|
|
5
|
+
import getViewPort from '../../support/getViewPort.js';
|
|
6
|
+
import { toArray } from '../../support/util.js';
|
|
7
|
+
import { isAndroidConfigured } from '../../android/index.js';
|
|
8
|
+
const log = intel.getLogger('browsertime.chrome');
|
|
7
9
|
|
|
8
10
|
const CHROME_AMD_EDGE_INTERNAL_PHONE_HOME = [
|
|
9
11
|
'"MAP cache.pack.google.com 127.0.0.1"',
|
|
@@ -16,9 +18,10 @@ const CHROME_AMD_EDGE_INTERNAL_PHONE_HOME = [
|
|
|
16
18
|
'"MAP optimizationguide-pa.googleapis.com 127.0.0.1"'
|
|
17
19
|
];
|
|
18
20
|
|
|
19
|
-
|
|
21
|
+
export default function (seleniumOptions, browserOptions, options, baseDir) {
|
|
20
22
|
// Fixing save password popup, only on Desktop
|
|
21
|
-
|
|
23
|
+
|
|
24
|
+
if (!isAndroidConfigured(options)) {
|
|
22
25
|
seleniumOptions.setUserPreferences({
|
|
23
26
|
'profile.password_manager_enable': false,
|
|
24
27
|
'profile.default_content_setting_values.notifications': 2,
|
|
@@ -53,7 +56,7 @@ module.exports = function (seleniumOptions, browserOptions, options, baseDir) {
|
|
|
53
56
|
browserOptions.webPageReplayHostResolver &&
|
|
54
57
|
browserOptions.webPageReplayRecord
|
|
55
58
|
) {
|
|
56
|
-
const firstPartyDomains =
|
|
59
|
+
const firstPartyDomains = toArray(browserOptions.blockDomainsExcept);
|
|
57
60
|
let excludes = '';
|
|
58
61
|
for (let domain of firstPartyDomains) {
|
|
59
62
|
excludes += ` MAP ${domain}:80 127.0.0.1:${browserOptions.webPageReplayHTTPPort},`;
|
|
@@ -70,18 +73,18 @@ module.exports = function (seleniumOptions, browserOptions, options, baseDir) {
|
|
|
70
73
|
} // If we do not use WebPageReplay but wanna block on domain
|
|
71
74
|
else if (browserOptions.blockDomainsExcept) {
|
|
72
75
|
let excludes = '';
|
|
73
|
-
let excludesDomains =
|
|
76
|
+
let excludesDomains = toArray(browserOptions.blockDomainsExcept);
|
|
74
77
|
for (let domain of excludesDomains) {
|
|
75
78
|
excludes += 'MAP * 127.0.0.1, EXCLUDE ' + domain + ',';
|
|
76
79
|
}
|
|
77
80
|
seleniumOptions.addArguments('--host-resolver-rules=' + excludes);
|
|
78
81
|
} else {
|
|
79
82
|
// Make sure we only set this if we do not have any other host resolver rules
|
|
80
|
-
const
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
+
const chromeCommandLineArguments = toArray(browserOptions.args);
|
|
84
|
+
const argumentsWithHostResolverRules = chromeCommandLineArguments.filter(
|
|
85
|
+
argument => argument.includes('host-resolver-rules')
|
|
83
86
|
);
|
|
84
|
-
if (
|
|
87
|
+
if (argumentsWithHostResolverRules.length === 0) {
|
|
85
88
|
seleniumOptions.addArguments(
|
|
86
89
|
'--host-resolver-rules=' + CHROME_AMD_EDGE_INTERNAL_PHONE_HOME.join(',')
|
|
87
90
|
);
|
|
@@ -94,7 +97,7 @@ module.exports = function (seleniumOptions, browserOptions, options, baseDir) {
|
|
|
94
97
|
: options.extension;
|
|
95
98
|
for (const extension of extensions) {
|
|
96
99
|
seleniumOptions.addExtensions(
|
|
97
|
-
|
|
100
|
+
readFileSync(extension, { encoding: 'base64' })
|
|
98
101
|
);
|
|
99
102
|
}
|
|
100
103
|
}
|
|
@@ -103,8 +106,8 @@ module.exports = function (seleniumOptions, browserOptions, options, baseDir) {
|
|
|
103
106
|
seleniumOptions.addArguments('--auto-open-devtools-for-tabs');
|
|
104
107
|
}
|
|
105
108
|
|
|
106
|
-
const
|
|
107
|
-
seleniumOptions.setPerfLoggingPrefs(
|
|
109
|
+
const perfLogConfig = { enableNetwork: true, enablePage: true };
|
|
110
|
+
seleniumOptions.setPerfLoggingPrefs(perfLogConfig);
|
|
108
111
|
|
|
109
112
|
if (options.userAgent) {
|
|
110
113
|
seleniumOptions.addArguments('--user-agent=' + options.userAgent);
|
|
@@ -115,7 +118,9 @@ module.exports = function (seleniumOptions, browserOptions, options, baseDir) {
|
|
|
115
118
|
}
|
|
116
119
|
|
|
117
120
|
if (browserOptions.collectNetLog) {
|
|
118
|
-
const dir = !browserOptions
|
|
121
|
+
const dir = !isAndroidConfigured(browserOptions)
|
|
122
|
+
? baseDir
|
|
123
|
+
: '/data/local/tmp';
|
|
119
124
|
seleniumOptions.addArguments(`--log-net-log=${dir}/chromeNetlog.json`);
|
|
120
125
|
const level = browserOptions.netLogCaptureMode || 'IncludeSensitive';
|
|
121
126
|
seleniumOptions.addArguments(`--net-log-capture-mode=${level}`);
|
|
@@ -141,17 +146,17 @@ module.exports = function (seleniumOptions, browserOptions, options, baseDir) {
|
|
|
141
146
|
// for new profiles
|
|
142
147
|
// disable it with ChromeWhatsNewUI
|
|
143
148
|
if (browserOptions.args) {
|
|
144
|
-
const
|
|
145
|
-
for (const
|
|
149
|
+
const chromeCommandLineArguments = toArray(browserOptions.args);
|
|
150
|
+
for (const argument of chromeCommandLineArguments) {
|
|
146
151
|
if (
|
|
147
|
-
|
|
148
|
-
|
|
152
|
+
argument.includes('disable-features') &&
|
|
153
|
+
!argument.includes('ChromeWhatsNewUI')
|
|
149
154
|
) {
|
|
150
|
-
seleniumOptions.addArguments(`${
|
|
151
|
-
log.debug('Set Chrome args %j', `${
|
|
155
|
+
seleniumOptions.addArguments(`${argument},ChromeWhatsNewUI`);
|
|
156
|
+
log.debug('Set Chrome args %j', `${argument},ChromeWhatsNewUI`);
|
|
152
157
|
} else {
|
|
153
|
-
seleniumOptions.addArguments(
|
|
154
|
-
log.debug('Set Chrome args %j',
|
|
158
|
+
seleniumOptions.addArguments(argument);
|
|
159
|
+
log.debug('Set Chrome args %j', argument);
|
|
155
160
|
}
|
|
156
161
|
}
|
|
157
162
|
} else {
|
|
@@ -188,4 +193,4 @@ module.exports = function (seleniumOptions, browserOptions, options, baseDir) {
|
|
|
188
193
|
|
|
189
194
|
log.debug('Setting the following Selenium options: %j', seleniumOptions);
|
|
190
195
|
return seleniumOptions;
|
|
191
|
-
}
|
|
196
|
+
}
|