在使用CefSharp加载时修改远程JavaScript? [英] Modifying remote JavaScripts as they load with CefSharp?

查看:679
本文介绍了在使用CefSharp加载时修改远程JavaScript?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在构建自定义浏览器,作为到远程网站的界面的一部分。他们的GUI很烂,所以我正在做一些JavaScript技巧,以使其看起来更好。

I am building a custom browser as part of an interface to a remote website. Their GUI sucks so I'm doing some JavaScript hacks to make it look better.

当前,要对其UI进行修改,我正在使用以下GreaseMonkey脚本(在Firefox上):

Currently, to make modifications to their UI I am using the following GreaseMonkey script (on Firefox):

// ==UserScript==
// @name        winman-load
// @namespace   winman
// @description stuff to do when winman.js loads
// @include     https://addons.mozilla.org/en-US/firefox/addon/greasemonkey/
// @version     1
// @grant       none
// @run-at document-start
// ==/UserScript==

document.addEventListener("beforescriptexecute", function(e) {
    src = e.target.src;
    content = e.target.text;

    //console.log("src: " + src);

    if (src.search("winman.js") > -1) {

       console.info("============ new winman ===========\n" + src);

        var newContent = "";

        $.ajax({
         async: false,
         type: 'GET',
         url: '/script/winman.js',
         success: function(data) {
           newContent = data.replace('pos += currentPos;', 'pos += currentPos + 100;');
           newContent = newContent.replace('var enable = false;', 'var enable = true;');
           newContent = newContent.replace('var available = true;', 'var available = false;');
         }
        });


        // Stop original script
        e.preventDefault();
        e.stopPropagation();
        unsafeWindow.jQuery(e.target).remove();

        var script = document.createElement('script');

        script.textContent = newContent;

        (document.head || document.documentElement).appendChild(script);
        script.onload = function() {
            this.parentNode.removeChild(this);
        }


    }

});

如果我希望使用CefSharp进行这种操作,我希望能够做些什么,我可以在其中修改脚本

I want to be able to do something if this nature with CefSharp, where I can modify the scripts on-the-fly as the browser loads the page.

推荐答案

好,我知道了这一点。您可以使用以下方法创建RequestHandler:

Ok I figured this out. You create a RequestHandler with a method like this:

    IResponseFilter IRequestHandler.GetResourceResponseFilter(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response) {
        var url = new Uri(request.Url);

        if (request.Url.Equals(scriptToUpdate, StringComparison.OrdinalIgnoreCase)) {

            Dictionary<string, string> dictionary = new Dictionary<string, string>();
            dictionary.Add(search1, replace1);
            dictionary.Add(search2, replace2);

            return new FindReplaceResponseFilter(dictionary);
        }
        return null;
    }

然后为多个搜索/替换创建一个FindReplaceResponseFilter:

And then for the multiple search/replace you make a FindReplaceResponseFilter:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using CefSharp;

namespace CefFilters {
    public class FindReplaceResponseFilter : IResponseFilter {
        private static readonly Encoding encoding = Encoding.UTF8;

        /// <summary>
        ///     The portion of the find string that is currently matching.
        /// </summary>
        private int findMatchOffset;

        /// <summary>
        ///     Overflow from the output buffer.
        /// </summary>
        private readonly List<byte> overflow = new List<byte>();

        /// <summary>
        ///     Number of times the the string was found/replaced.
        /// </summary>
        private int replaceCount;

        private Dictionary<string, string> dictionary;

        public FindReplaceResponseFilter(Dictionary<string, string> dictionary) {
            this.dictionary = dictionary;
        }

        bool IResponseFilter.InitFilter() {
            return true;
        }

        FilterStatus IResponseFilter.Filter(Stream dataIn, out long dataInRead, Stream dataOut, out long dataOutWritten) {
            // All data will be read.
            dataInRead = dataIn == null ? 0 : dataIn.Length;
            dataOutWritten = 0;

            // Write overflow then reset
            if (overflow.Count > 0) {
                // Write the overflow from last time.
                WriteOverflow(dataOut, ref dataOutWritten);
            }

            // Evaluate each character in the input buffer. Track how many characters in
            // a row match findString. If findString is completely matched then write
            // replacement. Otherwise, write the input characters as-is.
            for (var i = 0; i < dataInRead; ++i) {
                var readByte = (byte) dataIn.ReadByte();
                var charForComparison = Convert.ToChar(readByte);

                if (replaceCount < dictionary.Count) { 
                    var replace = dictionary.ElementAt(replaceCount);
                    if (charForComparison == replace.Key[findMatchOffset]) {
                        //We have a match, increment the counter
                        findMatchOffset++;

                        // If all characters match the string specified
                        if (findMatchOffset == replace.Key.Length) {
                            // Complete match of the find string. Write the replace string.
                            WriteString(replace.Value, replace.Value.Length, dataOut, ref dataOutWritten);


                            // Start over looking for a match.
                            findMatchOffset = 0;
                            replaceCount++;
                        }
                        continue;
                    }
                    // Character did not match the find string.
                    if (findMatchOffset > 0) {
                        // Write the portion of the find string that has matched so far.
                        WriteString(replace.Key, findMatchOffset, dataOut, ref dataOutWritten);

                        // Start over looking for a match.
                        findMatchOffset = 0;
                    }
                }

                // Write the current character.
                WriteSingleByte(readByte, dataOut, ref dataOutWritten);
            }

            if (overflow.Count > 0) {
                //If we end up with overflow data then we'll need to return NeedMoreData
                // On the next pass the data will be written, then the next batch will be processed.
                return FilterStatus.NeedMoreData;
            }

            // If a match is currently in-progress we need more data. Otherwise, we're
            // done.
            return findMatchOffset > 0 ? FilterStatus.NeedMoreData : FilterStatus.Done;
        }

        private void WriteOverflow(Stream dataOut, ref long dataOutWritten) {
            // Number of bytes remaining in the output buffer.
            var remainingSpace = dataOut.Length - dataOutWritten;
            // Maximum number of bytes we can write into the output buffer.
            var maxWrite = Math.Min(overflow.Count, remainingSpace);

            // Write the maximum portion that fits in the output buffer.
            if (maxWrite > 0) {
                dataOut.Write(overflow.ToArray(), 0, (int) maxWrite);
                dataOutWritten += maxWrite;
            }

            if (maxWrite < overflow.Count) {
                // Need to write more bytes than will fit in the output buffer. 
                // Remove the bytes that were written already
                overflow.RemoveRange(0, (int) (maxWrite - 1));
            }
            else {
                overflow.Clear();
            }
        }

        private void WriteString(string str, int stringSize, Stream dataOut, ref long dataOutWritten) {
            // Number of bytes remaining in the output buffer.
            var remainingSpace = dataOut.Length - dataOutWritten;
            // Maximum number of bytes we can write into the output buffer.
            var maxWrite = Math.Min(stringSize, remainingSpace);

            // Write the maximum portion that fits in the output buffer.
            if (maxWrite > 0) {
                var bytes = encoding.GetBytes(str);
                dataOut.Write(bytes, 0, (int) maxWrite);
                dataOutWritten += maxWrite;
            }

            if (maxWrite < stringSize) {
                // Need to write more bytes than will fit in the output buffer. Store the
                // remainder in the overflow buffer.
                overflow.AddRange(encoding.GetBytes(str.Substring((int) maxWrite, (int) (stringSize - maxWrite))));
            }
        }

        private void WriteSingleByte(byte data, Stream dataOut, ref long dataOutWritten) {
            // Number of bytes remaining in the output buffer.
            var remainingSpace = dataOut.Length - dataOutWritten;

            // Write the byte to the buffer or add it to the overflow
            if (remainingSpace > 0) {
                dataOut.WriteByte(data);
                dataOutWritten += 1;
            }
            else {
                // Need to write more bytes than will fit in the output buffer. Store the
                // remainder in the overflow buffer.
                overflow.Add(data);
            }
        }

        public void Dispose() {}
    }
}

请记住,这会从左到右,从上到下进行迭代,因此请确保您的搜索和替换顺序正确。

Keep in mind that this iterates through left to right, top to bottom, so make sure your search and replaces are in the right order.

这篇关于在使用CefSharp加载时修改远程JavaScript?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆