feat(chromium): roll Chromium to r722269 (#5289)
This corresponds to Chromium 80.0.3987.0. This roll includes: - Implement support for the new ARIA `generic` role https://chromium-review.googlesource.com/c/chromium/src/+/1872305 - Expose button's children to accessibility tree https://chromium-review.googlesource.com/c/chromium/src/+/1845810 - Remove `Page.handleFileChooser` from CDP https://chromium-review.googlesource.com/c/chromium/src/+/1935410
This commit is contained in:
parent
14b2369650
commit
013a86cf28
@ -182,6 +182,18 @@ class ExecutionContext {
|
|||||||
return createJSHandle(this, response.objects);
|
return createJSHandle(this, response.objects);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Protocol.DOM.BackendNodeId} backendNodeId
|
||||||
|
* @return {Promise<Puppeteer.ElementHandle>}
|
||||||
|
*/
|
||||||
|
async _adoptBackendNodeId(backendNodeId) {
|
||||||
|
const {object} = await this._client.send('DOM.resolveNode', {
|
||||||
|
backendNodeId: backendNodeId,
|
||||||
|
executionContextId: this._contextId,
|
||||||
|
});
|
||||||
|
return /** @type {Puppeteer.ElementHandle}*/(createJSHandle(this, object));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Puppeteer.ElementHandle} elementHandle
|
* @param {Puppeteer.ElementHandle} elementHandle
|
||||||
* @return {Promise<Puppeteer.ElementHandle>}
|
* @return {Promise<Puppeteer.ElementHandle>}
|
||||||
@ -192,11 +204,7 @@ class ExecutionContext {
|
|||||||
const nodeInfo = await this._client.send('DOM.describeNode', {
|
const nodeInfo = await this._client.send('DOM.describeNode', {
|
||||||
objectId: elementHandle._remoteObject.objectId,
|
objectId: elementHandle._remoteObject.objectId,
|
||||||
});
|
});
|
||||||
const {object} = await this._client.send('DOM.resolveNode', {
|
return this._adoptBackendNodeId(nodeInfo.node.backendNodeId);
|
||||||
backendNodeId: nodeInfo.node.backendNodeId,
|
|
||||||
executionContextId: this._contextId,
|
|
||||||
});
|
|
||||||
return /** @type {Puppeteer.ElementHandle}*/(createJSHandle(this, object));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -311,6 +311,8 @@ class ElementHandle extends JSHandle {
|
|||||||
* @param {!Array<string>} filePaths
|
* @param {!Array<string>} filePaths
|
||||||
*/
|
*/
|
||||||
async uploadFile(...filePaths) {
|
async uploadFile(...filePaths) {
|
||||||
|
const isMultiple = await this.evaluate(element => element.multiple);
|
||||||
|
assert(filePaths.length <= 1 || isMultiple, 'Multiple file uploads only work with <input type=file multiple>');
|
||||||
// These imports are only needed for `uploadFile`, so keep them
|
// These imports are only needed for `uploadFile`, so keep them
|
||||||
// scoped here to avoid paying the cost unnecessarily.
|
// scoped here to avoid paying the cost unnecessarily.
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
32
lib/Page.js
32
lib/Page.js
@ -15,7 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
|
||||||
const EventEmitter = require('events');
|
const EventEmitter = require('events');
|
||||||
const mime = require('mime');
|
const mime = require('mime');
|
||||||
const {Events} = require('./Events');
|
const {Events} = require('./Events');
|
||||||
@ -112,7 +111,6 @@ class Page extends EventEmitter {
|
|||||||
networkManager.on(Events.NetworkManager.Response, event => this.emit(Events.Page.Response, event));
|
networkManager.on(Events.NetworkManager.Response, event => this.emit(Events.Page.Response, event));
|
||||||
networkManager.on(Events.NetworkManager.RequestFailed, event => this.emit(Events.Page.RequestFailed, event));
|
networkManager.on(Events.NetworkManager.RequestFailed, event => this.emit(Events.Page.RequestFailed, event));
|
||||||
networkManager.on(Events.NetworkManager.RequestFinished, event => this.emit(Events.Page.RequestFinished, event));
|
networkManager.on(Events.NetworkManager.RequestFinished, event => this.emit(Events.Page.RequestFinished, event));
|
||||||
this._fileChooserInterceptionIsDisabled = false;
|
|
||||||
this._fileChooserInterceptors = new Set();
|
this._fileChooserInterceptors = new Set();
|
||||||
|
|
||||||
client.on('Page.domContentEventFired', event => this.emit(Events.Page.DOMContentLoaded));
|
client.on('Page.domContentEventFired', event => this.emit(Events.Page.DOMContentLoaded));
|
||||||
@ -137,23 +135,22 @@ class Page extends EventEmitter {
|
|||||||
this._client.send('Target.setAutoAttach', {autoAttach: true, waitForDebuggerOnStart: false, flatten: true}),
|
this._client.send('Target.setAutoAttach', {autoAttach: true, waitForDebuggerOnStart: false, flatten: true}),
|
||||||
this._client.send('Performance.enable', {}),
|
this._client.send('Performance.enable', {}),
|
||||||
this._client.send('Log.enable', {}),
|
this._client.send('Log.enable', {}),
|
||||||
this._client.send('Page.setInterceptFileChooserDialog', {enabled: true}).catch(e => {
|
this._client.send('Page.setInterceptFileChooserDialog', {enabled: true}),
|
||||||
this._fileChooserInterceptionIsDisabled = true;
|
|
||||||
}),
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {!Protocol.Page.fileChooserOpenedPayload} event
|
* @param {!Protocol.Page.fileChooserOpenedPayload} event
|
||||||
*/
|
*/
|
||||||
_onFileChooser(event) {
|
async _onFileChooser(event) {
|
||||||
if (!this._fileChooserInterceptors.size) {
|
if (!this._fileChooserInterceptors.size)
|
||||||
this._client.send('Page.handleFileChooser', { action: 'fallback' }).catch(debugError);
|
|
||||||
return;
|
return;
|
||||||
}
|
const frame = this._frameManager.frame(event.frameId);
|
||||||
|
const context = await frame.executionContext();
|
||||||
|
const element = await context._adoptBackendNodeId(event.backendNodeId);
|
||||||
const interceptors = Array.from(this._fileChooserInterceptors);
|
const interceptors = Array.from(this._fileChooserInterceptors);
|
||||||
this._fileChooserInterceptors.clear();
|
this._fileChooserInterceptors.clear();
|
||||||
const fileChooser = new FileChooser(this._client, event);
|
const fileChooser = new FileChooser(this._client, element, event);
|
||||||
for (const interceptor of interceptors)
|
for (const interceptor of interceptors)
|
||||||
interceptor.call(null, fileChooser);
|
interceptor.call(null, fileChooser);
|
||||||
}
|
}
|
||||||
@ -163,8 +160,6 @@ class Page extends EventEmitter {
|
|||||||
* @return !Promise<!FileChooser>}
|
* @return !Promise<!FileChooser>}
|
||||||
*/
|
*/
|
||||||
async waitForFileChooser(options = {}) {
|
async waitForFileChooser(options = {}) {
|
||||||
if (this._fileChooserInterceptionIsDisabled)
|
|
||||||
throw new Error('File chooser handling does not work with multiple connections to the same page');
|
|
||||||
const {
|
const {
|
||||||
timeout = this._timeoutSettings.timeout(),
|
timeout = this._timeoutSettings.timeout(),
|
||||||
} = options;
|
} = options;
|
||||||
@ -1351,10 +1346,12 @@ class ConsoleMessage {
|
|||||||
class FileChooser {
|
class FileChooser {
|
||||||
/**
|
/**
|
||||||
* @param {Puppeteer.CDPSession} client
|
* @param {Puppeteer.CDPSession} client
|
||||||
|
* @param {Puppeteer.ElementHandle} element
|
||||||
* @param {!Protocol.Page.fileChooserOpenedPayload} event
|
* @param {!Protocol.Page.fileChooserOpenedPayload} event
|
||||||
*/
|
*/
|
||||||
constructor(client, event) {
|
constructor(client, element, event) {
|
||||||
this._client = client;
|
this._client = client;
|
||||||
|
this._element = element;
|
||||||
this._multiple = event.mode !== 'selectSingle';
|
this._multiple = event.mode !== 'selectSingle';
|
||||||
this._handled = false;
|
this._handled = false;
|
||||||
}
|
}
|
||||||
@ -1373,11 +1370,7 @@ class FileChooser {
|
|||||||
async accept(filePaths) {
|
async accept(filePaths) {
|
||||||
assert(!this._handled, 'Cannot accept FileChooser which is already handled!');
|
assert(!this._handled, 'Cannot accept FileChooser which is already handled!');
|
||||||
this._handled = true;
|
this._handled = true;
|
||||||
const files = filePaths.map(filePath => path.resolve(filePath));
|
await this._element.uploadFile(...filePaths);
|
||||||
await this._client.send('Page.handleFileChooser', {
|
|
||||||
action: 'accept',
|
|
||||||
files,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1386,9 +1379,6 @@ class FileChooser {
|
|||||||
async cancel() {
|
async cancel() {
|
||||||
assert(!this._handled, 'Cannot cancel FileChooser which is already handled!');
|
assert(!this._handled, 'Cannot cancel FileChooser which is already handled!');
|
||||||
this._handled = true;
|
this._handled = true;
|
||||||
await this._client.send('Page.handleFileChooser', {
|
|
||||||
action: 'cancel',
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
"node": ">=8.16.0"
|
"node": ">=8.16.0"
|
||||||
},
|
},
|
||||||
"puppeteer": {
|
"puppeteer": {
|
||||||
"chromium_revision": "706915"
|
"chromium_revision": "722269"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"unit": "node test/test.js",
|
"unit": "node test/test.js",
|
||||||
|
@ -81,7 +81,7 @@ module.exports.addTests = function({testRunner, expect, FFOX}) {
|
|||||||
expect(await page.accessibility.snapshot()).toEqual(golden);
|
expect(await page.accessibility.snapshot()).toEqual(golden);
|
||||||
});
|
});
|
||||||
it('should report uninteresting nodes', async function({page}) {
|
it('should report uninteresting nodes', async function({page}) {
|
||||||
await page.setContent(`<textarea autofocus>hi</textarea>`);
|
await page.setContent(`<textarea>hi</textarea>`);
|
||||||
await page.focus('textarea');
|
await page.focus('textarea');
|
||||||
const golden = FFOX ? {
|
const golden = FFOX ? {
|
||||||
role: 'entry',
|
role: 'entry',
|
||||||
@ -100,7 +100,7 @@ module.exports.addTests = function({testRunner, expect, FFOX}) {
|
|||||||
focused: true,
|
focused: true,
|
||||||
multiline: true,
|
multiline: true,
|
||||||
children: [{
|
children: [{
|
||||||
role: 'GenericContainer',
|
role: 'generic',
|
||||||
name: '',
|
name: '',
|
||||||
children: [{
|
children: [{
|
||||||
role: 'text', name: 'hi'
|
role: 'text', name: 'hi'
|
||||||
@ -182,7 +182,7 @@ module.exports.addTests = function({testRunner, expect, FFOX}) {
|
|||||||
name: 'my fake image'
|
name: 'my fake image'
|
||||||
}]
|
}]
|
||||||
} : {
|
} : {
|
||||||
role: 'GenericContainer',
|
role: 'generic',
|
||||||
name: '',
|
name: '',
|
||||||
value: 'Edit this image: ',
|
value: 'Edit this image: ',
|
||||||
children: [{
|
children: [{
|
||||||
@ -241,7 +241,7 @@ module.exports.addTests = function({testRunner, expect, FFOX}) {
|
|||||||
<div contenteditable="plaintext-only">Edit this image:<img src="fakeimage.png" alt="my fake image"></div>`);
|
<div contenteditable="plaintext-only">Edit this image:<img src="fakeimage.png" alt="my fake image"></div>`);
|
||||||
const snapshot = await page.accessibility.snapshot();
|
const snapshot = await page.accessibility.snapshot();
|
||||||
expect(snapshot.children[0]).toEqual({
|
expect(snapshot.children[0]).toEqual({
|
||||||
role: 'GenericContainer',
|
role: 'generic',
|
||||||
name: ''
|
name: ''
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -250,7 +250,7 @@ module.exports.addTests = function({testRunner, expect, FFOX}) {
|
|||||||
<div contenteditable="plaintext-only" tabIndex=0>Edit this image:<img src="fakeimage.png" alt="my fake image"></div>`);
|
<div contenteditable="plaintext-only" tabIndex=0>Edit this image:<img src="fakeimage.png" alt="my fake image"></div>`);
|
||||||
const snapshot = await page.accessibility.snapshot();
|
const snapshot = await page.accessibility.snapshot();
|
||||||
expect(snapshot.children[0]).toEqual({
|
expect(snapshot.children[0]).toEqual({
|
||||||
role: 'GenericContainer',
|
role: 'generic',
|
||||||
name: ''
|
name: ''
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -360,10 +360,18 @@ module.exports.addTests = function({testRunner, expect, FFOX}) {
|
|||||||
const div = await page.$('div');
|
const div = await page.$('div');
|
||||||
expect(await page.accessibility.snapshot({root: div})).toEqual(null);
|
expect(await page.accessibility.snapshot({root: div})).toEqual(null);
|
||||||
expect(await page.accessibility.snapshot({root: div, interestingOnly: false})).toEqual({
|
expect(await page.accessibility.snapshot({root: div, interestingOnly: false})).toEqual({
|
||||||
role: 'GenericContainer',
|
role: 'generic',
|
||||||
name: '',
|
name: '',
|
||||||
children: [ { role: 'button', name: 'My Button' } ] }
|
children: [
|
||||||
);
|
{
|
||||||
|
role: 'button',
|
||||||
|
name: 'My Button',
|
||||||
|
children: [
|
||||||
|
{ role: 'text', name: 'My Button' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -94,22 +94,6 @@ module.exports.addLauncherTests = function({testRunner, expect, defaultBrowserOp
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Page.waitForFileChooser', () => {
|
|
||||||
it('should fail gracefully when trying to work with filechoosers within multiple connections', async() => {
|
|
||||||
// 1. Launch a browser and connect to all pages.
|
|
||||||
const originalBrowser = await puppeteer.launch(defaultBrowserOptions);
|
|
||||||
await originalBrowser.pages();
|
|
||||||
// 2. Connect a remote browser and connect to first page.
|
|
||||||
const remoteBrowser = await puppeteer.connect({browserWSEndpoint: originalBrowser.wsEndpoint()});
|
|
||||||
const [page] = await remoteBrowser.pages();
|
|
||||||
// 3. Make sure |page.waitForFileChooser()| does not work with multiclient.
|
|
||||||
let error = null;
|
|
||||||
await page.waitForFileChooser().catch(e => error = e);
|
|
||||||
expect(error.message).toBe('File chooser handling does not work with multiple connections to the same page');
|
|
||||||
originalBrowser.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user