当前位置:  开发笔记 > 编程语言 > 正文

CefSharp在任何文档加载/处理之前注入Javascript

如何解决《CefSharp在任何文档加载/处理之前注入Javascript》经验,为你挑选了1个好方法。

对于我正在处理的项目,我需要在任何网页文档处理开始之前注入javascript.这可以通过WebBrowser组件轻松实现,但我在使用CefSharp时遇到了困难.

这是问题的简化,网页需要"InjectedObject"才能运行.在文档的最顶部调用未注入的网页,或者在处理文档之前进行评估/执行将导致:

===== html示例输出失败=====

isObjectPresent?

=====

我需要在哪里显示网页:

===== html示例输出成功=====

isObjectPresent?

真正

=====


  
    
  
  
    

isObjectPresent?

查看所有可用的建议将表明我应该使用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().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来下载页面,因为我希望我可能必须为影响主框架的所有导航操作做到这一点,这听起来像一个黑客工作.

从评论中得出结论,建议javascript V8引擎上下文足以满足上述用例.尝试从IRenderProcessMessageHandler接口实现OnContextCreated方法具有相同的结果.

== == MainWindow.xaml


  
    
  

== == 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);
  }
}

我非常感谢您的意见和建议.如果有什么我遗失的请告诉我!



1> Glorifundel..:

终于回到了这一点。大量基于以下示例:CefSharp.Example / Filters / FindReplaceResponseFilter.cs

实现IRequestHandler和IResponseFilter接口:

== MainWindow.xaml ==


  
    
  

== MainWindow.xaml.cs ==

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
{
    /// 
    /// Location to insert the javascript
    /// 
    public enum Locations
    {
        /// 
        /// Insert Javascript at the top of the header element
        /// 
        head,
        /// 
        /// Insert Javascript at the top of the body element
        /// 
        body
    }

    string injection;
    string location;
    int offset = 0;
    List overflow = new List();

    /// 
    /// Constructor
    /// 
    /// 
    /// 
    public JavascriptInjectionFilter(string injection, Locations location = Locations.head)
    {
        this.injection = "";
        switch (location)
        {
            case Locations.head:
                this.location = "";
                break;

            case Locations.body:
                this.location = "";
                break;

            default:
                this.location = "";
                break;
        }
    }

    /// 
    /// Disposal
    /// 
    public void Dispose()
    {
        //
    }

    /// 
    /// Filter Processing...  handles the injection
    /// 
    /// 
    /// 
    /// 
    /// 
    /// 
    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;
    }

    /// 
    /// Initialization
    /// 
    /// 
    public bool InitFilter()
    {
        return true;
    }

}

感谢amaitland为我指明了正确的方向,并感谢上述代码的绝大多数基于的示例程序。最终结果:


  
  

isObjectPresent?

这满足了我对文档进行预处理的需求,在标题的顶部带有一些文本,从而确保了在注入代码之前不会运行现有代码的时序问题。

编辑 几个小修正。添加了仅在加载大型机时插入的控制逻辑。

推荐阅读
我我檬檬我我186
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有