我有一个案例
window.open
那么即使选项卡成功打开,
window.open
的返回值为null
。
例如如果
main.py
pip install fastapi
uvicorn main:app --reload --port 8000
和 uvicorn main:app --reload --port 8001
然后会打开一个新选项卡,显示 Google 主页,但我会在原始选项卡的控制台中看到
null
。
from typing import Union
from fastapi import FastAPI, Response
from fastapi.responses import HTMLResponse
app = FastAPI()
@app.get("/", response_class=HTMLResponse)
def read_root(response: Response):
response.headers["Cross-Origin-Opener-Policy"] = "same-origin"
return '''
<iframe src="http://localhost:8001/iframe"></iframe>
'''
@app.get("/iframe", response_class=HTMLResponse)
def read_iframe(response: Response):
response.headers["Cross-Origin-Opener-Policy"] = "same-origin"
return '''
<button id="button">Open</button>
<script>
document.getElementById("button").addEventListener("click", () => {
const w = window.open('https://www.google.com/', "_blank");
console.log(w);
});
</script>
'''
但是,如果我通过转到
http://localhost:8001/iframe
直接访问 iframe 并执行相同的操作,我会在控制台中看到似乎是 Window(/Window 代理?)对象。
或者:如果我使 iframe 与父页面位于同一域中,我还会在控制台中看到一个 Window/Window 代理对象。
或者:如果我将
same-origin
更改为 same-origin-allow-popups
,我还会在控制台中看到一个 Window/Window 代理对象。
为什么在跨源 iframe 且 Cross-Origin-Opener-Policy 设置为同源的情况下
window.open
返回 null
?在 https://developer.mozilla.org/en-US/docs/Web/API/Window/open 它说
如果浏览器无法打开新的浏览上下文,例如因为它被浏览器弹出窗口阻止程序阻止,则返回 null。
但是它确实打开了浏览上下文......
我想了解的原因:我在一个网站上有类似的设置,我正在
Cross-Origin-Opener-Policy: same-site
和 Cross-Origin-Opener-Policy: same-site-allow-popups
之间做出决定。所以,我需要了解它的作用。但是,window.open 的行为。取决于它是否在跨域 iframe 中,这稍微阻碍了这种理解
为什么在 Cross-Origin-Opener-Policy 设置为同源的跨源 iframe 的情况下,window.open 返回 null?
它在规格中。在这种情况下,它会使
window.open
的行为就像您将 noopener
传递给它一样,这反过来又使 window.open 返回 null。
更详细地,来自选择可导航的规则
- 如果 currentDocument 的跨源开启策略的值为“same-origin”或“same-origin-plus-COEP”,并且 currentDocument 的源与 currentDocument 的相关设置对象的顶级源不是同源,则:
- 将 noopener 设置为 true。
- 将名称设置为“_blank”。
- 将 windowType 设置为“new with no opener”。
然后从 7.2.2.1 打开和关闭窗口,当它描述 window.open 的作用时
- 如果 noopener 为 true 或 windowType 为“new with no opener”,则返回 null。
您还可以看到
window.open
与 noopener
的行为方式 - 不涉及 COOP 且不涉及 iframe - 它返回 null,就像本问题的情况一样。
from typing import Union
from fastapi import FastAPI, Response
from fastapi.responses import HTMLResponse
app = FastAPI()
@app.get("/", response_class=HTMLResponse)
def read_root(response: Response):
return '''
<button id="button">Open</button>
<script>
document.getElementById("button").addEventListener("click", () => {
const w = window.open('https://www.google.com/', "_blank", "noopener");
console.log(w);
});
</script>
'''