I'm working on a standalone script that will eventually be published as an add-on. It will have a sidebar users interact with and from there they can launch the Google File Picker to upload a report for processing. I previously was looking for a way for the sidebar to know that the file picker was done. I replicated this answer successfully and got the File picker dialog to send a message back to the sidebar indicating it was finished. However, the console is full of some errors and warnings that I'm wondering if I should be concerned about. The errors are:
Unsafe attempt to initiate navigation for frame with origin 'https://docs.google.com' from frame with URL 'https://***.googleusercontent.com/userCodeAppPanel'. The frame attempting navigation of the top-level window is sandboxed, but the flag of 'allow-top-navigation' or 'allow-top-navigation-by-user-activation' is not set.
DOMException: Blocked a frame with origin "https://###.googleusercontent.com" from accessing a cross-origin frame. at findSideBar (https://###.googleusercontent.com/userCodeAppPanel:80:18) at w0.pickerCallback [as Fb] (https://###.googleusercontent.com/userCodeAppPanel:98:11) at w0._.h.iV (https://apis.google.com/_/scs/apps-static/_/js/k=oz.gapi.en.uAzDleg2hnU.O/m=picker/rt=j/sv=1/d=1/ed=1/am=AQ/rs=AGLTcCMT6b3QcRI88QolvkcdUjC8YnoTvA/cb=gapi.loaded_0:740:393) at d (https://apis.google.com/_/scs/apps-static/_/js/k=oz.gapi.en.uAzDleg2hnU.O/m=picker/rt=j/sv=1/d=1/ed=1/am=AQ/rs=AGLTcCMT6b3QcRI88QolvkcdUjC8YnoTvA/cb=gapi.loaded_0:215:143) at b (https://apis.google.com/_/scs/apps-static/_/js/k=oz.gapi.en.uAzDleg2hnU.O/m=picker/rt=j/sv=1/d=1/ed=1/am=AQ/rs=AGLTcCMT6b3QcRI88QolvkcdUjC8YnoTvA/cb=gapi.loaded_0:210:1)
Refused to get unsafe header "X-HTTP-Status-Code-Override"
The first error I have seen before, however, the second is new and relevant to sending the message from the file picker dialog back to the sidebar.
It's worth mentioning that everything still works. My question is primarily are these errors I should be worried about, will they cause problems when the add-on is being reviewed before being published, and how can I correct them?
I've included below my code for the sidebar creation, picker creation, and the relevant code for sending the message from the picker to the sidebar.
Sidebar Creation:
function buildSidebar(type) {
hideColumns();
hideRows();
hideSheets();
if(type == 'setup' || checkSetup()) {
var html = HtmlService.createTemplateFromFile('SidebarSetupHTML')
.evaluate()
.setTitle('Test');
} else {
var html = HtmlService.createTemplateFromFile('SidebarMainHTML')
.evaluate()
.setTitle('Test');
}
SpreadsheetApp.getUi().showSidebar(html);
}
Picker Creation:
function showPicker() {
var html = HtmlService.createHtmlOutputFromFile('PickerHTML.html')
.setWidth(600)
.setHeight(425)
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
SpreadsheetApp.getUi().showModalDialog(html, 'Select Report(s)');
}
Picker Message Code:
function pickerCallback(data) {
var action = data[google.picker.Response.ACTION];
if (action == google.picker.Action.PICKED) {
(function findSideBar(limit) {
let f = window.top.frames;
for (let i = 0; i < limit; ++i) {
try {
if (
f[i] /*/iframedAppPanel*/ &&
f[i].length &&
f[i][0] && //#sandboxFrame
f[i][0][0] && //#userHtmlFrame
window !== f[i][0][0] //!== self
) {
console.info('Sidebar found');
var sidebar = f[i][0][0];
sidebar.modalDone('PICKED'); //Modal has finished
console.log('Message sent');
google.script.host.close();
}
} catch (e) {
console.error(e);
continue;
}
}
})(10);
}
}
Sidebar launch picker and receive message:
function testPicker() {
google.script.run.withSuccessHandler(pickerResponse).showPicker();
}
function pickerResponse(e) {
(async () => {
let receiver = new Promise((res, rej) => {
window.modalDone = res;
});
var message = await receiver;
console.log('message received');
if(message == 'PICKED' || message == "NOT_PICKED") {
console.log(message);
}
//Do what you want here
})();
}
When I saw your script, I thought that the reason for your issue might be the loop after the if statement was true
. So for example, when the if statement is true
, how about putting break
in the last line? So, how about the following modification?
if (
f[i] /*/iframedAppPanel*/ &&
f[i].length &&
f[i][0] && //#sandboxFrame
f[i][0][0] && //#userHtmlFrame
window !== f[i][0][0] //!== self
) {
console.info('Sidebar found');
var sidebar = f[i][0][0];
sidebar.modalDone('PICKED'); //Modal has finished
console.log('Message sent');
google.script.host.close();
}
if (
f[i] /*/iframedAppPanel*/ &&
f[i].length &&
f[i][0] && //#sandboxFrame
f[i][0][0] && //#userHtmlFrame
window !== f[i][0][0] //!== self
) {
console.info('Sidebar found');
var sidebar = f[i][0][0];
sidebar.modalDone('PICKED'); //Modal has finished
console.log('Message sent');
google.script.host.close();
break; // <--- Added
}
When I tested a following sample script for a custom dialog on Google Docs (For example, it's Google Spreadsheet),
<script>
google.script.host.close();
alert("ok");
</script>
I confirmed that the alert window is opened and also, the dialog is closed. So I thought that google.script.host.close()
might work with the asynchronous process.
For example, when google.script.run
with the high process cost is used as follows,
<script>
google.script.host.close();
google.script.run.withSuccessHandler(_ => alert("ok2")).myFunction();
alert("ok1");
</script>
it seems that myFunction()
and alert("ok2")
are not run because the dialog is closed before run myFunction()
, while alert("ok1")
is run. On the other hand, when the process cost is low, it seems that the script after google.script.host.close()
is run.
From these situation, as an attempt, I have proposed to add break
after google.script.host.close()
for OP's issue.