SafariDriver 是在 JS 中实现的,因此为了拦截对 、 和 的调用alert
,confirm
必须prompt
覆盖网页上下文中的函数。
将注入的脚本更改为Start
脚本而不是End
脚本注入 - 这意味着一旦加载 DOM,但在解析之前注入脚本(而不是在 onload 事件之后注入):
http://developer.apple.com/library/safari/#documentation/Tools/Conceptual/SafariExtensionGuide/InjectingScripts/InjectingScripts.html#//apple_ref/doc/uid/TP40009977-CH6-SW5
在被测页面的上下文中覆盖全局警报函数,而不是注入的脚本。这类似于 executeScript 命令的要求。因此,我们注入的脚本应该做的第一件事是向 DOM 添加一个脚本标签,用于设置警报覆盖。应将此脚本标记添加为 documentElement 的第一个子项,以确保它在页面中的任何其他标记之前执行。这将确保我们在页面中的任何内容有机会触发警报之前设置警报处理程序。
一旦警报触发,我们必须通知扩展程序有警报,同时阻塞页面中的当前 JS 线程。通常,我们的页面脚本使用 window.postMessage 与注入的脚本进行通信。postMessage 异步触发 MessageEvent。为了保持同步性,我们可以手动触发 MessageEvent:
Use a MessageEvent instead of some other DOM event so we can include a JSON object describing the alert.
var event = document.createEvent('MessageEvent');
event.initMessageEvent('message', false, false, {
type: "alert", // confirm, or prompt
text: "hello"
}, window.location.origin, '0', window, null);
window.dispatchEvent(event);
注入的脚本必须侦听对页面警报消息的响应。要将警报同步发送到扩展程序进行处理,我们可以(ab)使用 Safari 扩展程序的机制来阻止加载内容:
http://developer.apple.com/library/safari/#documentation/Tools/Conceptual/SafariExtensionGuide/MessagesandProxies/MessagesandProxies.html#//apple_ref/doc/uid/TP40009977-CH14-SW9
window.addEventListener('message', function(e) {
// Create a beforeload event, which is required by the canLoad method
var e = document.createEvent('Events');
e.initEvent('beforeload', false, false);
// canLoad sends and waits for a response synchronously. It is the only
// synchronous function in the Safari extension messaging API.
var response = safari.self.tab.canLoad(e, e.data);
// Send the response back to the page using another MessageEvent.
var responseEvent = document.createEvent('MessageEvent');
responseEvent.initMessageEvent('message', false, false, {
accepted: response.accepted,
response: response.value
}, window.location.origin, '0', window, null);
window.dispatchEvent(responseEvent);
}, true);
请注意,扩展程序的警报响应必须使用另一条消息传回页面,因为我们正在跨越上下文边界。唯一的其他选择是将响应存储在 DOM 上以便在另一端读取。
最后一步,这是一个开放式问题,是扩展程序应该如何处理警报。由于我们正在维护警报的阻塞行为,因此无法再让命令执行(即使它们导致未处理的警报错误)。
一种可能性是让 WebDriver 客户端参与警报处理。除了提供 WebSocket 服务器外,WebDriver 客户端还应提供 XHR 端点。当检测到警报时,服务器将向此端点发送同步 POST XHR。客户端应仅在用户接受或解除警报(或从另一个命令引发未处理的警报错误)后响应。当接收到 XHR 响应时,扩展完成链并将响应发送回注入的脚本。
你可以在这里找到更多。