-
Notifications
You must be signed in to change notification settings - Fork 9.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
core(full-page-screenshot): leave emulated width unchanged #13643
Changes from 8 commits
dd6db6b
d6b15cb
8e7f036
6e30d53
c258a74
15d7e1d
de92e5d
66147e1
dc9f4c8
f49b1c7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -70,21 +70,22 @@ class FullPageScreenshot extends FRGatherer { | |
|
||
/** | ||
* @param {LH.Gatherer.FRTransitionalContext} context | ||
* @param {{height: number, width: number, mobile: boolean}} deviceMetrics | ||
* @return {Promise<LH.Artifacts.FullPageScreenshot['screenshot']>} | ||
*/ | ||
async _takeScreenshot(context) { | ||
async _takeScreenshot(context, deviceMetrics) { | ||
const session = context.driver.defaultSession; | ||
const maxTextureSize = await this.getMaxTextureSize(context); | ||
const metrics = await session.sendCommand('Page.getLayoutMetrics'); | ||
|
||
// Width should match emulated width, without considering content overhang. | ||
// Both layoutViewport and visualViewport capture this. visualViewport accounts | ||
// for page zoom/scale, which we currently don't account for (or expect). So we use layoutViewport.width. | ||
// Note: If the page is zoomed, many assumptions fail. | ||
// | ||
// Height should be as tall as the content. So we use contentSize.height | ||
const width = Math.min(metrics.layoutViewport.clientWidth, maxTextureSize); | ||
const height = Math.min(metrics.contentSize.height, maxTextureSize); | ||
// Height should be as tall as the content. | ||
// Scale the emulated height to reach the content height. | ||
const fullHeight = Math.round( | ||
deviceMetrics.height * | ||
metrics.contentSize.height / | ||
metrics.layoutViewport.clientHeight | ||
); | ||
const height = Math.min(fullHeight, maxTextureSize); | ||
|
||
// Setup network monitor before we change the viewport. | ||
const networkMonitor = new NetworkMonitor(session); | ||
|
@@ -98,13 +99,10 @@ class FullPageScreenshot extends FRGatherer { | |
await networkMonitor.enable(); | ||
|
||
await session.sendCommand('Emulation.setDeviceMetricsOverride', { | ||
// If we're gathering with mobile screenEmulation on (overlay scrollbars, etc), continue to use that for this screenshot. | ||
mobile: context.settings.screenEmulation.mobile, | ||
height, | ||
width, | ||
mobile: deviceMetrics.mobile, | ||
deviceScaleFactor: 1, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the https://output.jsbin.com/koqamuh/4/quiet test case does find a related problem in this branch.. on master the colorcontrast results work all the way up to 16300 px There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah setting a DPR of 1 will also reduce the image "filesize". Going off #11121 (comment) I'm fine keeping the DPR at 1 for the FPS. The content change in #13642 appears to be from us changing the viewport width anyway. |
||
scale: 1, | ||
screenOrientation: {angle: 0, type: 'portraitPrimary'}, | ||
height, | ||
width: 0, // Leave width unchanged | ||
}); | ||
|
||
// Now that the viewport is taller, give the page some time to fetch new resources that | ||
|
@@ -127,7 +125,7 @@ class FullPageScreenshot extends FRGatherer { | |
|
||
return { | ||
data, | ||
width, | ||
width: deviceMetrics.width, | ||
height, | ||
}; | ||
} | ||
|
@@ -185,29 +183,37 @@ class FullPageScreenshot extends FRGatherer { | |
const session = context.driver.defaultSession; | ||
const executionContext = context.driver.executionContext; | ||
const settings = context.settings; | ||
|
||
// In case some other program is controlling emulation, remember what the device looks | ||
// like now and reset after gatherer is done. | ||
let observedDeviceMetrics; | ||
const lighthouseControlsEmulation = !settings.screenEmulation.disabled; | ||
|
||
/** | ||
* In case some other program is controlling emulation, remember what the device looks like now and reset after gatherer is done. | ||
* If we're gathering with mobile screenEmulation on (overlay scrollbars, etc), continue to use that for this screenshot. | ||
* @type {{width: number, height: number, deviceScaleFactor: number, mobile: boolean}} | ||
*/ | ||
adamraine marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const deviceMetrics = settings.screenEmulation; | ||
if (!lighthouseControlsEmulation) { | ||
observedDeviceMetrics = await executionContext.evaluate(getObservedDeviceMetrics, { | ||
const observedDeviceMetrics = await executionContext.evaluate(getObservedDeviceMetrics, { | ||
args: [], | ||
useIsolation: true, | ||
deps: [kebabCaseToCamelCase], | ||
}); | ||
deviceMetrics.height = observedDeviceMetrics.height; | ||
deviceMetrics.width = observedDeviceMetrics.width; | ||
deviceMetrics.deviceScaleFactor = observedDeviceMetrics.deviceScaleFactor; | ||
// If screen emulation is disabled, use formFactor to determine if we are on mobile. | ||
deviceMetrics.mobile = settings.formFactor === 'mobile'; | ||
} | ||
|
||
try { | ||
return { | ||
screenshot: await this._takeScreenshot(context), | ||
screenshot: await this._takeScreenshot(context, deviceMetrics), | ||
nodes: await this._resolveNodes(context), | ||
}; | ||
} finally { | ||
// Revert resized page. | ||
if (lighthouseControlsEmulation) { | ||
await emulation.emulate(session, settings); | ||
} else if (observedDeviceMetrics) { | ||
} else { | ||
// Best effort to reset emulation to what it was. | ||
// https://github.com/GoogleChrome/lighthouse/pull/10716#discussion_r428970681 | ||
// TODO: seems like this would be brittle. Should at least work for devtools, but what | ||
|
@@ -216,8 +222,10 @@ class FullPageScreenshot extends FRGatherer { | |
// and then just call that to reset? | ||
// https://github.com/GoogleChrome/lighthouse/issues/11122 | ||
await session.sendCommand('Emulation.setDeviceMetricsOverride', { | ||
mobile: settings.formFactor === 'mobile', | ||
...observedDeviceMetrics, | ||
mobile: deviceMetrics.mobile, | ||
deviceScaleFactor: deviceMetrics.deviceScaleFactor, | ||
height: deviceMetrics.height, | ||
width: 0, // Leave width unchanged | ||
}); | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i definitely don't follow how this results in a meaningful number.... but.... i can confirm that it does indeed result in something good. 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
metrics.contentSize.height
represents the desiredmetrics.layoutViewport.clientHeight
for the FPS, and we controlmetrics.layoutViewport.clientHeight
by setting the emulated height over CDP.However, the emulated height (
deviceMetrics.height
) is not necessarily equivalent tometrics.layoutViewport.clientHeight
(because of DPR maybe).So we use the ratio of
metrics.contentSize.height/metrics.layoutViewport.clientHeight
to determine how much we need to scale the emulated height to arrive at the desiredmetrics.layoutViewport.clientHeight
.