Skip to content
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

[WIP] feat(chromium): roll Chromium to r722269 #5289

Merged
merged 2 commits into from Jan 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 13 additions & 5 deletions lib/ExecutionContext.js
Expand Up @@ -182,6 +182,18 @@ class ExecutionContext {
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
* @return {Promise<Puppeteer.ElementHandle>}
Expand All @@ -192,11 +204,7 @@ class ExecutionContext {
const nodeInfo = await this._client.send('DOM.describeNode', {
objectId: elementHandle._remoteObject.objectId,
});
const {object} = await this._client.send('DOM.resolveNode', {
backendNodeId: nodeInfo.node.backendNodeId,
executionContextId: this._contextId,
});
return /** @type {Puppeteer.ElementHandle}*/(createJSHandle(this, object));
return this._adoptBackendNodeId(nodeInfo.node.backendNodeId);
}
}

Expand Down
2 changes: 2 additions & 0 deletions lib/JSHandle.js
Expand Up @@ -311,6 +311,8 @@ class ElementHandle extends JSHandle {
* @param {!Array<string>} 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
// scoped here to avoid paying the cost unnecessarily.
const path = require('path');
Expand Down
32 changes: 11 additions & 21 deletions lib/Page.js
Expand Up @@ -15,7 +15,6 @@
*/

const fs = require('fs');
const path = require('path');
const EventEmitter = require('events');
const mime = require('mime');
const {Events} = require('./Events');
Expand Down Expand Up @@ -112,7 +111,6 @@ class Page extends EventEmitter {
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.RequestFinished, event => this.emit(Events.Page.RequestFinished, event));
this._fileChooserInterceptionIsDisabled = false;
this._fileChooserInterceptors = new Set();

client.on('Page.domContentEventFired', event => this.emit(Events.Page.DOMContentLoaded));
Expand All @@ -137,23 +135,22 @@ class Page extends EventEmitter {
this._client.send('Target.setAutoAttach', {autoAttach: true, waitForDebuggerOnStart: false, flatten: true}),
this._client.send('Performance.enable', {}),
this._client.send('Log.enable', {}),
this._client.send('Page.setInterceptFileChooserDialog', {enabled: true}).catch(e => {
this._fileChooserInterceptionIsDisabled = true;
}),
this._client.send('Page.setInterceptFileChooserDialog', {enabled: true}),
]);
}

/**
* @param {!Protocol.Page.fileChooserOpenedPayload} event
*/
_onFileChooser(event) {
if (!this._fileChooserInterceptors.size) {
this._client.send('Page.handleFileChooser', { action: 'fallback' }).catch(debugError);
async _onFileChooser(event) {
if (!this._fileChooserInterceptors.size)
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);
this._fileChooserInterceptors.clear();
const fileChooser = new FileChooser(this._client, event);
const fileChooser = new FileChooser(this._client, element, event);
for (const interceptor of interceptors)
interceptor.call(null, fileChooser);
}
Expand All @@ -163,8 +160,6 @@ class Page extends EventEmitter {
* @return !Promise<!FileChooser>}
*/
async waitForFileChooser(options = {}) {
if (this._fileChooserInterceptionIsDisabled)
throw new Error('File chooser handling does not work with multiple connections to the same page');
const {
timeout = this._timeoutSettings.timeout(),
} = options;
Expand Down Expand Up @@ -1351,10 +1346,12 @@ class ConsoleMessage {
class FileChooser {
/**
* @param {Puppeteer.CDPSession} client
* @param {Puppeteer.ElementHandle} element
* @param {!Protocol.Page.fileChooserOpenedPayload} event
*/
constructor(client, event) {
constructor(client, element, event) {
this._client = client;
this._element = element;
this._multiple = event.mode !== 'selectSingle';
this._handled = false;
}
Expand All @@ -1373,11 +1370,7 @@ class FileChooser {
async accept(filePaths) {
assert(!this._handled, 'Cannot accept FileChooser which is already handled!');
this._handled = true;
const files = filePaths.map(filePath => path.resolve(filePath));
await this._client.send('Page.handleFileChooser', {
action: 'accept',
files,
});
await this._element.uploadFile(...filePaths);
}

/**
Expand All @@ -1386,9 +1379,6 @@ class FileChooser {
async cancel() {
mathiasbynens marked this conversation as resolved.
Show resolved Hide resolved
assert(!this._handled, 'Cannot cancel FileChooser which is already handled!');
this._handled = true;
await this._client.send('Page.handleFileChooser', {
action: 'cancel',
});
}
}

Expand Down
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -8,7 +8,7 @@
"node": ">=8.16.0"
},
"puppeteer": {
"chromium_revision": "706915"
"chromium_revision": "722269"
},
"scripts": {
"unit": "node test/test.js",
Expand Down
24 changes: 16 additions & 8 deletions test/accessibility.spec.js
Expand Up @@ -81,7 +81,7 @@ module.exports.addTests = function({testRunner, expect, FFOX}) {
expect(await page.accessibility.snapshot()).toEqual(golden);
});
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');
const golden = FFOX ? {
role: 'entry',
Expand All @@ -100,7 +100,7 @@ module.exports.addTests = function({testRunner, expect, FFOX}) {
focused: true,
multiline: true,
children: [{
role: 'GenericContainer',
role: 'generic',
name: '',
children: [{
role: 'text', name: 'hi'
Expand Down Expand Up @@ -182,7 +182,7 @@ module.exports.addTests = function({testRunner, expect, FFOX}) {
name: 'my fake image'
}]
} : {
role: 'GenericContainer',
role: 'generic',
name: '',
value: 'Edit this image: ',
children: [{
Expand Down Expand Up @@ -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>`);
const snapshot = await page.accessibility.snapshot();
expect(snapshot.children[0]).toEqual({
role: 'GenericContainer',
role: 'generic',
name: ''
});
});
Expand All @@ -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>`);
const snapshot = await page.accessibility.snapshot();
expect(snapshot.children[0]).toEqual({
role: 'GenericContainer',
role: 'generic',
name: ''
});
});
Expand Down Expand Up @@ -360,10 +360,18 @@ module.exports.addTests = function({testRunner, expect, FFOX}) {
const div = await page.$('div');
expect(await page.accessibility.snapshot({root: div})).toEqual(null);
expect(await page.accessibility.snapshot({root: div, interestingOnly: false})).toEqual({
role: 'GenericContainer',
role: 'generic',
name: '',
children: [ { role: 'button', name: 'My Button' } ] }
);
children: [
{
role: 'button',
name: 'My Button',
children: [
{ role: 'text', name: 'My Button' },
],
},
],
});
});
});
});
Expand Down
16 changes: 0 additions & 16 deletions test/chromiumonly.spec.js
Expand Up @@ -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();
});

});
});
};

Expand Down