How to close parent window in an Apps Script Web App? - google-apps-script

I have a web app in Google Apps Script and I need that when I have click in a Button, the browser tab closes. I tried with different solutions but it does not work as I require it.
This is my HTML code.
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<h1>Demo Close tab</h1>
<p>When you click the button, you must close this tab.</p>
<button>Close</button>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script>
window.onload = function() {
$("button").click(function() {
// window.close();
// window.top.close();
// window.open("","_top","").close();
});
}
</script>
</body>
</html>
And this is my GS code
function doGet() {
var template = HtmlService.createTemplateFromFile("Index");
return template.evaluate()
.setSandboxMode(HtmlService.SandboxMode.IFRAME)
.addMetaTag("viewport", "width=device-width, initial-scale=1")
.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL)
.setTitle("Demo Google Analytics");
}

As stated in the docs HTML Service: Restrictions:
The setSandboxMode method now has no effect when called.
Your Google Apps Script runs in an iframe by default, regardless of any attempts to change the sandbox mode. I strongly suspect the sandbox settings will prevent you accessing the parent window, but you might try window.parent.window.

According to Javascript Documention: Window.close()
This method is only allowed to be called for windows that were opened by a script using the window.open() method. If the window was not opened by a script, an error similar to this one appears in the console: Scripts may not close windows that were not opened by script.

Web Apps are usually standalone script projects that, as per the documentation on restrictions applied in the IFRAME sandbox mode (which is, as of 2021, the only mode available), has the following sandbox flags (corresponding to the sandbox attribute) set on the HTMLIFrameElement Web Apps are served in:
Flag
allow-same-origin
allow-forms
allow-scripts
allow-popups
allow-downloads
allow-modals
allow-popups-to-escape-sandbox
allow-top-navigation-by-user-activation
Note the last flag - this is the reason for being able to initiate navigation when a user clicks on an element but not when calling methods like window.top.close(), window.location.reload(), or window.location.replace(<url>).
This seemed to not be strictly enforced for bound script projects up until September 2021, but it is now. As of now, there are several open issues on the Issue Tracker reporting that the auto-closing Web App windows stopped working - please follow them if you want to get updates on whether or not Google will reconsider enforcing the flag:
https://issuetracker.google.com/issues/198071205
https://issuetracker.google.com/issues/198323022
https://issuetracker.google.com/issues/198073648 (status "Won't fix" but open for a feature-request)

Related

Google Script App Fails in Incognito Mode

I have a simple Google Script published as a web app with anonymous access. The code is available here and the web app is available here.
code.gs
function doGet() {
return HtmlService.createHtmlOutputFromFile("index").setTitle("Google Script")
}
index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<p>Hello</p>
</body>
</html>
The script web app works in normal Chrome mode but returns a 500 error when the page is viewed in the incognito mode of Chrome or Firefox.
The script fails with a 500 error in both V8 and DEPRECATED_ES5 runtime.
See screenshot.
Yes it is consistently reproducible in a new project.
I have the same problem... It is related to the HtmlService
The app script was workng for about a year, but yesterday started to return the error "Google Docs encountered an error".
return HtmlService.createHtmlOutput("<p>Hello World</p>");
If I login it works, however the script is meant to return dynamic list as html when people visit my website, hence why it is needed to run as "as anyone, even anonymous".
Partial Workaround:
Some of my scripts are API's returning just strings, the workaround for these is to use ContentService instead of HtmlService.
return ContentService.createTextOutput("Hello World");
Thank you for looking into this issue.
It looks like a problem at Google's end and they have acknowledged the bug as well. We'll have to wait until they issue fix.
Update: Looks like Google has rolled out an update and the issue is automatically resolved. The web app is now working as before.

Google Apps Script doGet(e) createHtmlOutput returning broken Google Drive error page on Safari [duplicate]

I have a simple Google Script published as a web app with anonymous access. The code is available here and the web app is available here.
code.gs
function doGet() {
return HtmlService.createHtmlOutputFromFile("index").setTitle("Google Script")
}
index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<p>Hello</p>
</body>
</html>
The script web app works in normal Chrome mode but returns a 500 error when the page is viewed in the incognito mode of Chrome or Firefox.
The script fails with a 500 error in both V8 and DEPRECATED_ES5 runtime.
See screenshot.
Yes it is consistently reproducible in a new project.
I have the same problem... It is related to the HtmlService
The app script was workng for about a year, but yesterday started to return the error "Google Docs encountered an error".
return HtmlService.createHtmlOutput("<p>Hello World</p>");
If I login it works, however the script is meant to return dynamic list as html when people visit my website, hence why it is needed to run as "as anyone, even anonymous".
Partial Workaround:
Some of my scripts are API's returning just strings, the workaround for these is to use ContentService instead of HtmlService.
return ContentService.createTextOutput("Hello World");
Thank you for looking into this issue.
It looks like a problem at Google's end and they have acknowledged the bug as well. We'll have to wait until they issue fix.
Update: Looks like Google has rolled out an update and the issue is automatically resolved. The web app is now working as before.

How to tell if script/asset is loaded by Asynchronous or Deferred in Chrome Network Tools

Is there any way to tell if a script/asset is loaded asynchronously or loaded deferred from the Google Chrome Browser Network Tools tab?
Unfortunately, you can't see dependencies in the critical rendering path in the network tab of Google Chrome.
What you can do is look at the priority of requests (you might have to enable this tab in the network windows -> right click on the tabs). An async request should have a low priority (just like images which are loaded async). Chromes appears to do just that (https://bugs.chromium.org/p/chromium/issues/detail?id=408229), it's not super accurate, but might help you.
a script can be loaded inline in HTML or dynamically via a function call.
To know whether a script was inline or not:
Disable javascript (dev tools settings -> disable javascript)
Look for that script in the source code (right click -> view page source) of the page, if it's not there then it's loaded asynchronously by default.
If it's included in the source code then look for the async tag:
<script type="text/javascript" async="" src="https://www.google-analytics.com/analytics.js"></script>
if the async attribute is present, then the script will be fetched in parallel to parsing and evaluated as soon as it is available.
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-async

Linking to another html page in Google Apps Script Not working in sandbox 'IFRAME'

In Google Apps Script: Using NATIVE sandbox mode:
Linking to another HTML page in Google Apps Script is working fine.
But when using IFRAME sandbox mode:
Unable to get links working in Google Apps Script when using sandbox mode of "IFRAME"
As per the above SO post I tried using target="_blank". As expected, when the link is clicked the page opens in a new window.
However -
Using target="_parent" in Chrome opens a new window each time, but Firefox is not working. According to https://developers.google.com/apps-script/guides/html/restrictions target="_parent" is not supported by HTML Service — this is probably why it behaves like target="_blank".
Using target="_self" in both Chrome and Firefox results in the first click opening in the same window but subsequent clicks bring up a blank page.
I want the page to load in the same window as my Apps script, as would occur when using target="_self" in an anchor on an unrestricted web page.
plz help me.
When using IFRAME sandbox mode, for <a>nchors to open in the same tab or window, target="_top" must be specified. Support for this was added to Google Apps Script in the latter half of 2015. Before this time unexpected behaviour resulted. From a Google Apps Script developer blog:
We have been working hard to improve IFRAME sandbox mode and have
added many features since then, including: Firefox support, file
uploads, top navigation support, and improved Google Picker API
support.
It's a doc error needs to fix with Google when using "SandBoxMode=IFRAME" currently. See Can't call a server function with a form with input type="file" when using SandBoxMode=IFRAME.
I've tested it works now by setting the HtmlService.SandboxMode.NATIVE
instead of working when HtmlService.SandboxMode is set to Iframe. Also reference to this related issue here.

Multi-Window Chrome Packaged App?

Hello I'm new to chrome packaged apps.
How would I create a button image, that when clicked launches
a new chrome packaged app window displaying a local html page.
In your first html page, just add the button. Also, that page will need to reference a Javascript file to add the event handlers:
<button id="thebutton">Open a New Window</button>
<script src="script.js"></script>
Then you add an event handler to the button in script.js (or whatever you name your script page):
document.querySelector('#thebutton').addEventListener('click', function() {
chrome.app.window.create('new.html', {"width":300, "height": 200});
});
If you need for that window to be sandboxed (e.g., not use the default content security policy), you need to specify that the page is sandboxed in manifest.json:
"sandbox": {
"pages": ["new.html"]
}
When new.html is loaded, it will be loaded in its own origin which doesn't have access to the opening window or to the advanced API's. If you need the sandboxed page to do something with the advanced API's, you can use postMessage and receive messages to communicate with a window that's still in the CSP.