在任何文档加载/处理之前插入Javascript
对于我正在进行的项目,我需要在任何网页文档处理开始之前注入javascript。这可以通过WebBrowser组件轻松实现,但我在使用CefSharp时遇到了困难 这里是问题的简化,一个网页需要一个“InjectedObject”来实现功能。在文档顶部调用网页而不进行注入,或在处理文档之前对其进行评估/执行,将导致: ====失败时的html示例输出===== 你在场吗 假的 ===== 当我需要网页显示时,在哪里: ====成功时的html示例输出===== 你在场吗 真的 ===== 然而,我尝试过的所有迭代,甚至使用FrameLoadStart,都会导致在文档开始处理之后插入javascript。是否有任何真正的javascript注入的例子确保它发生在文档处理开始之前。(确保避免出现竞速条件/正时问题) 我希望模仿的WebBrowser组件行为示例如下:在任何文档加载/处理之前插入Javascript,javascript,c#,cefsharp,javascript-injection,Javascript,C#,Cefsharp,Javascript Injection,对于我正在进行的项目,我需要在任何网页文档处理开始之前注入javascript。这可以通过WebBrowser组件轻松实现,但我在使用CefSharp时遇到了困难 这里是问题的简化,一个网页需要一个“InjectedObject”来实现功能。在文档顶部调用网页而不进行注入,或在处理文档之前对其进行评估/执行,将导致: ====失败时的html示例输出===== 你在场吗 假的 ===== 当我需要网页显示时,在哪里: ====成功时的html示例输出===== 你在场吗 真的 ===== 然而,
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;
}
}
}
我非常感谢这些评论和建议。如果我遗漏了什么,请告诉我 终于回到了这个话题。主要基于以下示例: 实现IRequestHandler和IResponseFilter接口: ==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>
<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);
}
}
public partial class MainWindow : Window
{
JavascriptManager jsmanager;
public MainWindow()
{
InitializeComponent();
jsmanager = new JavascriptManager(uiWebView);
}
}
public class JavascriptManager : IRequestHandler
{
string injection = "window.InjectedObject = {};";
public JavascriptManager(ChromiumWebBrowser browser)
{
browser.RequestHandler = this;
// Lets just pretend this is a real url with the example html above.
browser.Address = "https://www.example.com/timingtest.htm"
}
public IResponseFilter GetResourceResponseFilter(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response)
{
if (frame.IsMain && request.ResourceType == ResourceType.MainFrame)
{
return new JavascriptInjectionFilter(injection);
}
return null;
}
}
public class JavascriptInjectionFilter : IResponseFilter
{
/// <summary>
/// Location to insert the javascript
/// </summary>
public enum Locations
{
/// <summary>
/// Insert Javascript at the top of the header element
/// </summary>
head,
/// <summary>
/// Insert Javascript at the top of the body element
/// </summary>
body
}
string injection;
string location;
int offset = 0;
List<byte> overflow = new List<byte>();
/// <summary>
/// Constructor
/// </summary>
/// <param name="injection"></param>
/// <param name="location"></param>
public JavascriptInjectionFilter(string injection, Locations location = Locations.head)
{
this.injection = "<script>" + injection + "</script>";
switch (location)
{
case Locations.head:
this.location = "<head>";
break;
case Locations.body:
this.location = "<body>";
break;
default:
this.location = "<head>";
break;
}
}
/// <summary>
/// Disposal
/// </summary>
public void Dispose()
{
//
}
/// <summary>
/// Filter Processing... handles the injection
/// </summary>
/// <param name="dataIn"></param>
/// <param name="dataInRead"></param>
/// <param name="dataOut"></param>
/// <param name="dataOutWritten"></param>
/// <returns></returns>
public FilterStatus Filter(Stream dataIn, out long dataInRead, Stream dataOut, out long dataOutWritten)
{
dataInRead = dataIn == null ? 0 : dataIn.Length;
dataOutWritten = 0;
if (overflow.Count > 0)
{
var buffersize = Math.Min(overflow.Count, (int)dataOut.Length);
dataOut.Write(overflow.ToArray(), 0, buffersize);
dataOutWritten += buffersize;
if (buffersize < overflow.Count)
{
overflow.RemoveRange(0, buffersize - 1);
}
else
{
overflow.Clear();
}
}
for (var i = 0; i < dataInRead; ++i)
{
var readbyte = (byte)dataIn.ReadByte();
var readchar = Convert.ToChar(readbyte);
var buffersize = dataOut.Length - dataOutWritten;
if (buffersize > 0)
{
dataOut.WriteByte(readbyte);
dataOutWritten++;
}
else
{
overflow.Add(readbyte);
}
if (char.ToLower(readchar) == location[offset])
{
offset++;
if (offset >= location.Length)
{
offset = 0;
buffersize = Math.Min(injection.Length, dataOut.Length - dataOutWritten);
if (buffersize > 0)
{
var data = Encoding.UTF8.GetBytes(injection);
dataOut.Write(data, 0, (int)buffersize);
dataOutWritten += buffersize;
}
if (buffersize < injection.Length)
{
var remaining = injection.Substring((int)buffersize, (int)(injection.Length - buffersize));
overflow.AddRange(Encoding.UTF8.GetBytes(remaining));
}
}
}
else
{
offset = 0;
}
}
if (overflow.Count > 0 || offset > 0)
{
return FilterStatus.NeedMoreData;
}
return FilterStatus.Done;
}
/// <summary>
/// Initialization
/// </summary>
/// <returns></returns>
public bool InitFilter()
{
return true;
}
}
公共部分类主窗口:窗口
{
JavascriptManager和jsmanager;
公共主窗口()
{
初始化组件();
jsmanager=newJavaScriptManager(uiWebView);
}
}
公共类JavascriptManager:IRequestHandler
{
字符串注入=“window.InjectedObject={};”;
公共JavascriptManager(ChromiumWebBrowser浏览器)
{
browser.RequestHandler=this;
//让我们假设这是一个真实的url,上面的例子是html。
浏览器地址=”https://www.example.com/timingtest.htm"
}
公共IResponseFilter GetResourceResponseFilter(IWebBrowser浏览器控件、IBrowser浏览器、IFrame框架、IRequest请求、IResponse响应)
{
if(frame.IsMain&&request.ResourceType==ResourceType.MainFrame)
{
返回新的JavascriptInjectionFilter(注入);
}
返回null;
}
}
公共类JavascriptInjectionFilter:IResponseFilter
{
///
///插入javascript的位置
///
公共枚举位置
{
///
///在header元素的顶部插入Javascript
///
头,,
///
///在body元素的顶部插入Javascript
///
身体
}
管柱注入;
字符串位置;
整数偏移=0;
列表溢出=新列表();
///
///建造师
///
///
///
公共JavascriptInjectionFilter(字符串注入,位置=位置.head)
{
this.injection=“”+injection+”;
开关(位置)
{
案件地点.负责人:
此参数为:location=“”;
打破
案例位置。正文:
此参数为:location=“”;
打破
违约:
此参数为:location=“”;
打破
}
}
///
///处置
///
公共空间处置()
{
//
}
///
///过滤处理…处理注入
///
///
///
///
///
///
公共筛选器Status筛选器(流数据输入、流长数据输入、流数据输出、流长数据输出)
{
dataInRead=dataIn==null?0:dataIn.Length;
dataoutwrited=0;
如果(overflow.Count>0)
{
var buffersize=Math.Min(overflow.Count,(int)dataOut.Length);
写入(overflow.ToArray(),0,buffersize);
DataOutwrited+=缓冲区大小;
if(buffersize0)
{
写字节(读字节);
datawrited++;
}
其他的
{
Add(readbyte);
}
if(char.ToLower(readchar)=位置[offset])
{
offset++;
如果(偏移量>=位置长度)
{
偏移量=0;
buffersize=Math.Min(injection.Length,dataOut.Length-dataoutwrited);
如果(缓冲区大小>0)
{
var data=Encoding.UTF8.GetBytes(注入);
写入(数据,0,(int)buffersize);
DataOutwrited+=缓冲区大小;
}
if(缓冲区大小<注入长度)
{
var剩余=injection.Substring((int)buffersize,(int)(injection.Length-buffersize));
AddRange(Encoding.UTF8.GetBytes(剩余));
}
}
}
其他的
{
偏移量=0;
}
}
如果(overflow.Count>0 | | offset>0)
{
返回FilterStatus.NeedMoreData;
}
返回过滤器状态。完成;
}
///
///初始化
///
///
公共bool InitFilter()
{
返回true;
}
}
谢谢你为我指明了正确的方向,谢谢你
<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>
public partial class MainWindow : Window
{
JavascriptManager jsmanager;
public MainWindow()
{
InitializeComponent();
jsmanager = new JavascriptManager(uiWebView);
}
}
public class JavascriptManager : IRequestHandler
{
string injection = "window.InjectedObject = {};";
public JavascriptManager(ChromiumWebBrowser browser)
{
browser.RequestHandler = this;
// Lets just pretend this is a real url with the example html above.
browser.Address = "https://www.example.com/timingtest.htm"
}
public IResponseFilter GetResourceResponseFilter(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response)
{
if (frame.IsMain && request.ResourceType == ResourceType.MainFrame)
{
return new JavascriptInjectionFilter(injection);
}
return null;
}
}
public class JavascriptInjectionFilter : IResponseFilter
{
/// <summary>
/// Location to insert the javascript
/// </summary>
public enum Locations
{
/// <summary>
/// Insert Javascript at the top of the header element
/// </summary>
head,
/// <summary>
/// Insert Javascript at the top of the body element
/// </summary>
body
}
string injection;
string location;
int offset = 0;
List<byte> overflow = new List<byte>();
/// <summary>
/// Constructor
/// </summary>
/// <param name="injection"></param>
/// <param name="location"></param>
public JavascriptInjectionFilter(string injection, Locations location = Locations.head)
{
this.injection = "<script>" + injection + "</script>";
switch (location)
{
case Locations.head:
this.location = "<head>";
break;
case Locations.body:
this.location = "<body>";
break;
default:
this.location = "<head>";
break;
}
}
/// <summary>
/// Disposal
/// </summary>
public void Dispose()
{
//
}
/// <summary>
/// Filter Processing... handles the injection
/// </summary>
/// <param name="dataIn"></param>
/// <param name="dataInRead"></param>
/// <param name="dataOut"></param>
/// <param name="dataOutWritten"></param>
/// <returns></returns>
public FilterStatus Filter(Stream dataIn, out long dataInRead, Stream dataOut, out long dataOutWritten)
{
dataInRead = dataIn == null ? 0 : dataIn.Length;
dataOutWritten = 0;
if (overflow.Count > 0)
{
var buffersize = Math.Min(overflow.Count, (int)dataOut.Length);
dataOut.Write(overflow.ToArray(), 0, buffersize);
dataOutWritten += buffersize;
if (buffersize < overflow.Count)
{
overflow.RemoveRange(0, buffersize - 1);
}
else
{
overflow.Clear();
}
}
for (var i = 0; i < dataInRead; ++i)
{
var readbyte = (byte)dataIn.ReadByte();
var readchar = Convert.ToChar(readbyte);
var buffersize = dataOut.Length - dataOutWritten;
if (buffersize > 0)
{
dataOut.WriteByte(readbyte);
dataOutWritten++;
}
else
{
overflow.Add(readbyte);
}
if (char.ToLower(readchar) == location[offset])
{
offset++;
if (offset >= location.Length)
{
offset = 0;
buffersize = Math.Min(injection.Length, dataOut.Length - dataOutWritten);
if (buffersize > 0)
{
var data = Encoding.UTF8.GetBytes(injection);
dataOut.Write(data, 0, (int)buffersize);
dataOutWritten += buffersize;
}
if (buffersize < injection.Length)
{
var remaining = injection.Substring((int)buffersize, (int)(injection.Length - buffersize));
overflow.AddRange(Encoding.UTF8.GetBytes(remaining));
}
}
}
else
{
offset = 0;
}
}
if (overflow.Count > 0 || offset > 0)
{
return FilterStatus.NeedMoreData;
}
return FilterStatus.Done;
}
/// <summary>
/// Initialization
/// </summary>
/// <returns></returns>
public bool InitFilter()
{
return true;
}
}
<html><head></head><body><script>window.InjectedObject = {}</script>
<script>
isObjectPresent = typeof InjectedObject == "object";
</script>
<p>isObjectPresent?</p>
<div id="result"></div>
<script>
document.getElementById("result").innerHTML = isObjectPresent;
</script>
</body></html>
public class CustomRequestHandler : DefaultRequestHandler
{
string script = "alert('hello');";
public override IResponseFilter GetResourceResponseFilter(CefSharp.IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response)
{
if (frame.IsMain && request.ResourceType == ResourceType.MainFrame)
{
return new JavascriptInjectionFilter(script);
}
return null;
}
}
CustomRequestHandler customRequestHandler = new CustomRequestHandler();
chromeBrowser.RequestHandler = customRequestHandler ;