我正在进行的项目需要在网页文档处理之前注入javascript。使用WebBrowser组件可以轻松实现这一点,但是我在使用CefSharp时遇到了困难。
这是问题的一个简化版本,一个网页需要存在“InjectedObject”才能正常运行。如果在文档的最顶部没有发生注入或在文档被处理之前进行评估/执行,将会导致以下html示例输出:
=====html example output on failure=====
isObjectPresent?
false
=====
然而我需要网页显示如下:
=====html example output on success=====
isObjectPresent?
true
=====
<html>
<head>
<script>
isObjectPresent = typeof InjectedObject == "object";
</script>
</head>
<body>
<p>isObjectPresent?</p>
<div id="result"></div>
<script>
document.getElementById("result").innerHTML = isObjectPresent;
</script>
</body>
</html>
查看所有可用的建议,表明我应该使用LoadingStateChanged()或FrameLoadEnd()来注入脚本,即:
观察到所有可用的建议后,我应该使用LoadingStateChanged()或FrameLoadEnd()来注入脚本。
public void OnFrameLoadEnd(object sender, FrameLoadEndEventArgs args) {
if (args.Frame.IsMain) {
args.Frame.ExecuteJavascriptAsync("window.InjectedObject = {};");
}
}
然而,我尝试的所有迭代版本,甚至使用FrameLoadStart,在文档开始处理之后才出现插入的javascript。是否有真正的javascript注入示例可确保在文档处理开始之前发生(确保避免竞争条件/时间问题)。
作为我想要模仿的WebBrowser组件行为的例子:
private void uiWebBrowser_Navigated(object sender, System.Windows.Navigation.NavigationEventArgs e)
{
var browser = (WebBrowser)sender;
var document = browser.Document as HTMLDocument;
var head = document.getElementsByTagName("head").Cast<HTMLHeadElement>().First();
if (head != null)
{
var script = document.createElement("script") as IHTMLScriptElement;
script.text = "window.InjectedObject = {};"
if (head.firstChild != null)
{
head.insertBefore((IHTMLDOMNode)script, head.firstChild);
}
else
{
head.appendChild((IHTMLDOMNode)script;
}
}
}
欢迎提供任何帮助或建议,理想情况下我希望避免通过互联网请求解析和插入下载页面,然后使用loadhtml,因为我预计可能需要为所有影响主框架的导航操作执行此操作,这听起来像是一个hack方法。
根据评论的跟进建议,建议使用javascript V8引擎上下文来实现上述用例。尝试从IRenderProcessMessageHandler接口实现OnContextCreated方法具有相同的结果。
==MainWindow.xaml==
<Window x:Class="ExampleCefSharp001.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:cefSharp="clr-namespace:CefSharp.Wpf;assembly=CefSharp.Wpf"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ExampleCefSharp001"
mc:Ignorable="d"
Title="MainWindow" Height="1000" Width="1100">
<Grid>
<cefSharp:ChromiumWebBrowser x:Name="uiWebView"></cefSharp:ChromiumWebBrowser>
</Grid>
</Window>
==MainWindow.xaml.cs==
public partial class MainWindow : Window
{
JavascriptManager jsmanager;
public MainWindow()
{
InitializeComponent();
jsmanager = new JavascriptManager(uiWebView);
}
}
public class JavascriptManager : ILoadHandler, IRenderProcessMessageHandler
{
string injection = "window.InjectedObject = {};";
public JavascriptManager(ChromiumWebBrowser browser)
{
browser.LoadHandler = this;
browser.RenderProcessMessageHandler = this;
// Lets just pretend this is a real url with the example html above.
browser.Address = "https://www.example.com/timingtest.htm"
}
public void OnContextCreated(IWebBrowser browserControl, IBrowser browser, IFrame frame)
{
frame.ExecuteJavaScriptAsync(injection);
}
}
我非常感谢您的评论和建议。如果有我忽略的地方,请告诉我!