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

Unable to intercept FileChooser when invoked from window.chooseFileSystemEntries #5210

Closed
agnivade opened this issue Nov 30, 2019 · 20 comments
Closed

Comments

@agnivade
Copy link

This is both an issue with puppeteer and Chromium. I am raising an issue here in the hope that it gets more eyes than in the Chromium issue tracker.

Steps to reproduce

Tell us about your environment:

  • Puppeteer version:2.0.0
  • Chromium: 78.0.3904.70 and 80.0.3982.0
  • Platform / OS version:Ubuntu 4.15.0-45
  • URLs (if applicable):
  • Node.js version:10.16.3

Basically, I am calling window.chooseFileSystemEntries which is a new functionality introduced in Chrome 78 to access the native filesystem. (https://web.dev/native-file-system/). And then I want to intercept the opening of the file dialog, and pass a file path to it.

Unfortunately, the event does not get intercepted. Whereas, it clearly does, when I manually invoke a file opener dialog from an input[type="file"].

I think since this is a bleeding edge feature, perhaps this follows a different code path from inside Chrome, due to which the event handler is unable to intercept it.

What steps will reproduce the problem?

Please include code that reproduces the issue.

HTML file:

<!doctype html>
<html>

<head>
	<meta charset="utf-8">
	<title>File access</title>
</head>

<body>
	<input type="file" name="ff" id="open2">
	<button id="openFile">Open file</button>
	<script>
	document.getElementById("openFile").addEventListener('click', async (e) => {
  	const fileHandle = await window.chooseFileSystemEntries();
  	const file = await fileHandle.getFile();
  	const contents = await file.text();
  	console.log(contents);
	});
	</script>
</body>
</html>

Serve this HTML file using any local web server.

JS Code

const puppeteer = require('puppeteer-core');

(async () => {
  const browser = await puppeteer.launch({
  	headless: false, 
  	executablePath: '/path/to/chromium_tip',
  	args: [
  		'--flag-switches-begin',
  		'--enable-features=NativeFileSystemAPI',
  		'--flag-switches-end',
  	]
  });
  const page = await browser.newPage();
  await page.goto('http://localhost:8080/file.html');

  const [fileChooser] = await Promise.all([
	  page.waitForFileChooser(),
	  page.click('#openFile'), // trying to #open2 works
	]);
	// await fileChooser.accept(['/home/agniva/Desktop/sticky_note.txt']);
	console.log(fileChooser);
	await page.waitFor(1000);
  await browser.close();
})();

What is the expected result?

There are couple of issues here.

When I click #openFile, the filechooser dialog does not get intercepted at all. I can see the dialog, and after 30 secs, it times out with:

(node:11168) UnhandledPromiseRejectionWarning: TimeoutError: waiting for waiting for file chooser failed: timeout 30000ms exceeded

But if I change it to click #open2, everything works perfectly fine. And fileChooser gets logged properly.

This is a problem with Chromium.

The page.handleFileChooser API is removed from Chromium 80 at chromium/chromium@41361e4. So therefore, using fileChooser.accept with Chromium 80 raises an error. This is something to be fixed at puppeteer. The API needs to use the new fields at https://chromedevtools.github.io/devtools-protocol/tot/Page#event-fileChooserOpened to call the https://chromedevtools.github.io/devtools-protocol/tot/DOM#method-setFileInputFiles method.

The commit also moved the dialog interception from browser-side to blink-side. I hoped that it will make a difference in intercepting dialogs invoked from window.chooseFileSystemEntries but it does not. The same failure to interception occurs with Chrome 78 too.

/cc @pavelfeldman who made the commit.

For further context: I work on WebAssembly with the Go team. Not being able to read/write files has prevented us from running the Go test suite inside the browser, which has failed to catch several bugs. Currently, we run tests inside Node. But resolving this issue will allow us to run the test suite inside the browser too.

@DJ-Glock
Copy link

Same issue.

@agnivade did you develop any workaround for this?

@agnivade
Copy link
Author

Nope, still waiting on the Chrome/puppeteer team to come back with something.

@DJ-Glock
Copy link

@agnivade am I right thinking that waitForFileChooser does not work with Chromium 80+ at all? In my case it doesn't. But I did not see any errors.

@DJ-Glock
Copy link

#5363

@alansyue1020
Copy link

@DJ-Glock I try to downgrade Chromium version, and it works!

@agnivade
Copy link
Author

agnivade commented Feb 4, 2020

Hey all, the original issue was about FileChooser not being intercepted if invoked from window.chooseFileSystemEntries. FileChooser not working at all is a regression in puppeteer which got fixed at tip recently. Let's keep this thread on track :)

@agnivade
Copy link
Author

Bumping some important people again in the hope someone takes a look at this: @mathiasbynens @pavelfeldman @dmitshur

@koresar
Copy link

koresar commented Mar 16, 2020

Which version of puppeteer I should downgrade to if I want this working asap?

@mvdan
Copy link

mvdan commented Mar 16, 2020

@koresar as far as we know, window.chooseFileSystemEntries has never worked with Chrome DevTools (puppeteer, chromedp, etc) since it's a fairly new and unstable API.

@DJ-Glock
Copy link

DJ-Glock commented Mar 16, 2020

@koresar fileChooser works fine for me with puppeteer 2.0.0 with HeadlessChrome/79.0.3945.0 (wich is part of puppeteer)

@koresar
Copy link

koresar commented Mar 16, 2020

Thank you people. Sound like I have an error of a different kind. Weird, but this code does networking, I think.

const [fileChooser] = await Promise.all([
  page.waitForFileChooser(),
  page.click(".upload-indicator button") // some button that triggers file selection
]);
await fileChooser.accept([`${__dirname}/file.txt`]);

But I need, well, to just choose a file.

@DJ-Glock
Copy link

@koresar what error do you get finally? What is the puppeteer / chromium version?

@koresar
Copy link

koresar commented Mar 17, 2020

I'm getting

Error: Evaluation failed: TypeError: Failed to fetch
at __puppeteer_evaluation_script__:4:32

somewhere within JSHandle.js.

I assume it tries to upload file. However, the Angular app I'm trying to automate with puppeteer does not do that.

@koresar
Copy link

koresar commented Mar 18, 2020

Ok. Here is my bug.
#5503
Looks unrelated to this issue.

@stale
Copy link

stale bot commented Jun 26, 2022

We're marking this issue as unconfirmed because it has not had recent activity and we weren't able to confirm it yet. It will be closed if no further activity occurs within the next 30 days.

@stale stale bot added the unconfirmed label Jun 26, 2022
@stale
Copy link

stale bot commented Jul 26, 2022

We are closing this issue. If the issue still persists in the latest version of Puppeteer, please reopen the issue and update the description. We will try our best to accomodate it!

@stale stale bot closed this as completed Jul 26, 2022
@Mohsen7s
Copy link

This issue still exist and the only fix to this is downgrading to 4 years old chrome ver 78. Please re-open and start investigation to solve

@osuvorova
Copy link

Same problem for me.

@pondorasti
Copy link

Running into the same problem....:/

@LMeiraba
Copy link

same here :(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants