I am uploading a file through chrome extension as a form data and my code follows below. The problem here is that the file browsing window opens for just a second and then disappears.
The issue appears in Mac OS only.
manifest.json:
"background": { "scripts": ["jszip.js", "background.js"] },
background.js:
chrome.runtime.onMessage.addListener(function (msg) { if (msg.action === 'browse') { var myForm=document.createElement("FORM"); var myFile=document.createElement("INPUT"); myFile.type="file"; myFile.id="selectFile"; //myFile.onclick="openDialog()"; myForm.appendChild(myFile); var myButton=document.createElement("INPUT"); myButton.name="submit"; myButton.type="submit"; myButton.value="Submit"; myForm.appendChild(myButton); document.body.appendChild(myForm); } });
popup.js:
window.onload = function () { chrome.runtime.sendMessage({ action: 'browse' }); }
Starting next year, Chrome extensions will show what data they collect from users. Google will add a "Privacy practices" section on each Chrome extension's Web Store page listing what data they collect from users and what the developer plans to do with it.
You want to let the user choose and upload a file from your popup. But in OSX, as soon as the file-chooser dialog opens, the popup loses focus and closes, causing its JS context to get destroyed as well. Thus, the dialog opens and closes immediately.
This is a known bug on MAC for quite some time.
You can move the dialog opening logic to the background-page, which is not affected by loss of focus. From the popup, you can send a message to the background-page, requesting to initiate the browse-and-upload process (see sample code below).
manifest.json
{ ... "background": { "persistent": false, "scripts": ["background.js"] }, "browser_action": { "default_title": "Test Extension", // "default_icon": { // "19": "img/icon19.png", // "38": "img/icon38.png" // }, "default_popup": "popup.html" }, "permissions": [ "https://www.example.com/uploads" // The above permission is needed for cross-domain XHR ] }
popup.html
... <script src="popup.js"></script> </head> <body> <input type="button" id="button" value="Browse and Upload" /> ...
popup.js
document.addEventListener('DOMContentLoaded', function () { document.getElementById('button').addEventListener('click', function () { chrome.runtime.sendMessage({ action: 'browseAndUpload' }); window.close(); }); });
background.js
var uploadUrl = 'https://www.example.com/uploads'; /* Creates an `input[type="file]` */ var fileChooser = document.createElement('input'); fileChooser.type = 'file'; fileChooser.addEventListener('change', function () { var file = fileChooser.files[0]; var formData = new FormData(); formData.append(file.name, file); var xhr = new XMLHttpRequest(); xhr.open('POST', uploadUrl, true); xhr.addEventListener('readystatechange', function (evt) { console.log('ReadyState: ' + xhr.readyState, 'Status: ' + xhr.status); }); xhr.send(formData); form.reset(); // <-- Resets the input so we do get a `change` event, // even if the user chooses the same file }); /* Wrap it in a form for resetting */ var form = document.createElement('form'); form.appendChild(fileChooser); /* Listen for messages from popup */ chrome.runtime.onMessage.addListener(function (msg) { if (msg.action === 'browseAndUpload') { fileChooser.click(); } });
Heads up:
As a security precaution, Chrome will execute fileChooser.click()
only if it is a result of user interaction.
In the above example, the user clicks the button in the popup, which sends a message to the background-page, which calls fileChooser.click();
. If you try to call it programmatically it won't work. (E.g. calling it on document load won't have any effect.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With