Where is my iframe in the published web application/sidebar?
I've been running into various errors when trying to control the window
in DOM of my published web app and addon sidebar.
-
window.location
returns a vague unknown url liken-rysutduudd.google-usercontent.com
instead of my published web app urlscript.google.com/[SCRIPT_ID]/exec
-
Attempts to redirect my published web-app to a new url fails
window.location.href=www.google.com
-
Forms in web app, when submitted redirects to blank page.
After researching, I figured this is due to the web content being served in a iframe. The documentation doesn't show much except that the webapp is sandboxed in a iframe.
Relevant documentation I've researched:
- https://developers.google.com/apps-script/migration/iframe
- https://developers.google.com/apps-script/guides/html/restrictions
Some of the relevant questions I've looked into:
- window.location.href = window.location.href returning a blank page
- Google script web app goes blank page after submit
- How to stop redirected URL from being masked?
My specific question is: Where exactly is my iframe window in the published web app or my add on sidebar?
PUBLISHED WEB APP
+---------------------------------------------+
| script.google.com |
| |<------- [#0] window.top The top frame
| |
| +---------------------------------+ |
| | *.googleusercontent.com |<----+-------- [#1] Outer Sandboxed Iframe
| | sandboxFrame | |
| | +-----------------------+ | |
| | | /blank | | |
| | | userHtmlFrame | | |
| | | | | |
| | | Where the html |<---+-----+-------- [#2] Inner Sandboxed Iframe
| | | file you created | | |
| | | is loaded | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | +-----------------------+ | |
| | | |
| | | |
| +---------------------------------+ |
| |
| |
| |
+---------------------------------------------+
You're right. Most of the errors are due to the iframe sandboxing done by Google. To answer your question,
-
Your window is located in a iframe with id:
userHtmlFrame
with it'ssrc
set to/blank
. -
This frame is nested inside another frame with
src
:*.googleusercontent.com
and idsandboxFrame
. -
Finally, The
sandboxFrame
is nested inside the main frame:script.google.com
Notes:
-
window
in your published app refers to the inner most frame. -
This inner most frame has it's own cookies, storage and most other attributes unique to a window.
-
Unfortunately, this inner frame cannot be navigated elsewhere.
-
All window navigation must be done on the outermost frame:
script.google.com
. This is why the documentation asks you to setbase
or anchor'starget
to thetop
frame. -
Forms without
action
are submitted to the inner frame/blank
. Therefore, you're redirected to a blank page. The documentation states,
With IFRAME mode however HTML forms are allowed to submit, and if a form element has no action attribute specified it will submit to a blank page. Worse, the inner iframe will redirect to the blank page before the onclick handler has a chance to finish.
-
The origin of your iframe
userHtmlFrame
is inherited fromsandboxFrame
and set to*.googleusercontent.com
. For all intents and purposes(cors, whitelisting origins, fetch requests), this is the effectiveorigin
. -
The
sandboxFrame
currently has the following feature policy:allow
accelerometer *; ambient-light-sensor *; autoplay *; camera *; encrypted-media *; fullscreen *; geolocation *; gyroscope *; magnetometer *; microphone *; midi *; payment *; picture-in-picture *; speaker *; usb *; vibrate *; vr *
- Currently, It has the following sandbox attributes, which limit what you can do to other frames:
allow-downloads allow-forms allow-modals allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-scripts allow-top-navigation-by-user-activation
- The outer windows/other windows can be referenced using
window.top
orwindow.parent
orwindow.opener
from the inner frame. But, There are multiple restrictions imposed due to same origin policy. Cross origin access is limited mostly. Of particular note would be thewindow.postMessage
, which allows communication between frames.
SIDEBAR/MODAL DIALOG
+---------------------------------------------+
| docs.google.com |
| +--------------------------------------+ |<------- [#0] window.top The top frame
| | /macros/.../iframedAppPanel |<--+-------- [#1] Frame1 Same origin
| | +---------------------------------+ | |
| | | *.googleusercontent.com |<|---+-------- [#2] Outer Sandboxed Iframe
| | | sandboxFrame | | |
| | | +-----------------------+ | | |
| | | | /blank | | | |
| | | | userHtmlFrame | | | |
| | | | | | | |
| | | | Where the html |<---+-|---+-------- [#3] Inner Sandboxed Iframe
| | | | file you created | | | |
| | | | is loaded | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | +-----------------------+ | | |
| | | | | |
| | | | | |
| | +---------------------------------+ | |
| | | |
| +--------------------------------------+ |
| |
+---------------------------------------------+
All the above notes for web app stands true also for webcontent published using HtmlService in sidebar or modal dialogs. However,
- There is a extra nested layer of iframe here.
- The
allow-top-navigation
is missing from the sandbox attributes. Therefore, It is not possible to change/navigate the top frame(docs.google.com
) here.
Changelog:
-
Sep 1, 2021:
allow-top-navigation
is removed andallow-top-navigation-by-user-activation
is added instead. Security for the end user is increased at the cost of convenience for the developers.