void FileInputType::HandleDOMActivateEvent(Event& event) {
// ...
if (!LocalFrame::HasTransientUserActivation(document.GetFrame())) {
String message =
"File chooser dialog can only be shown with a user activation.";
document.AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
mojom::ConsoleMessageSource::kJavaScript,
mojom::ConsoleMessageLevel::kWarning, message));
return;
}
// ...
}
日前,做需求过程碰到了这么一个问题:File chooser dialog can only be shown with a user activation,从描述看是在没有用户激活页面的情况下尝试去调起文件选择器,被浏览器拒绝了。
需求背景:页面加载时,通过代码触发
file input
的click
事件,达到调起文件选择器的目的。大致如下:猜想这是浏览器考虑安全因素做的限制,确实也是。试想一下用户打开一个未知网页,不断调起文件选择器(或者新建窗口操作),用户的设备将直接被卡死。
但还是想探究验证一下浏览器内核是如何做限制的。chromium源码位置
可以看出,浏览器在响应dom事件时会先判断是否有
短暂的
用户激活行为。但,短暂
是多久?浏览器用
user_activation_state_
维护了用户激活的状态,其中IsActive
最终是通过IsActiveInternal
实现的,里面维护了一个transient_state_expiry_time_
变量,这就是浏览器用来标识短暂的
用户激活的变量。浏览器每收到用户的交互行为时(单纯地移动鼠标可不算,浏览器应该维护了一套属于用户激活行为的事件白名单)
ActivateTransientState
,这里会更新激活态的过期时间,在kActivationLifespan
时间后就会过期,也就是5s。搞清楚了原理,我们用demo来验证一下!
纯加载网页,无用户激活行为,期望不调起:
加载后,用户在3s内点击网页,期望调起:
加载并且用户点击网页,5s后执行
autoClick
,期望不调起:总结一下:在用户激活页面(点击,选中等)的5s内,自动执行的脚本有响应,否则浏览器无响应。