Search code examples
javascriptc#chromiumchromium-embeddedcefsharp

Reliable way to override javascript globals


I'm trying to mock the date on a CefSharp browser by injecting MockDate and setting it to some fixed date before every other script runs. Every window object, on any frame, at any time, should only have access to the mocked date, so the ideal would be to internally redefine the JavaScript Date object, but I don't think CefSharp or probably even Chromium has this option. I'm also going to mock some other functions like setTimeout and Math.rand, to prevent the browser from having any side effects (this is part of a larger project whose aim is to be able to record/replay browsing activity), so messing with OS's time wouldn't solve it.

I considered using RegisterJsObject since it can actually overwrite existing globals, but I don't think there is a way to pass a JavaScript constructor.

What I've tried so far is to handle the FrameLoadStart event:

private static string Inject = File.ReadAllText("Inject.js");

private void ChromeBrowser_FrameLoadStart(object sender, FrameLoadStartEventArgs e)
{
    e.Frame.ExecuteJavaScriptAsync(Inject);
}

Where "Inject.js" contains the mock date code. But I've noticed that, randomly, sometimes it'll work and sometimes it won't. I guess because the function is async and the javascript context sometimes haven't been created, since according to the documentations you shouldn't run scripts here. The documentation recommends handling OnContextCreated instead, but it only runs for the main frame, which wouldn't let me inject the code on any iframe. So I wonder if I have any alternative.


Solution

  • In case anyone else need this, the solution was to modify the actual C++ CefSharp code by adding a line to the end of CefAppUnmanagedWrapper::OnContextCreated:

    frame->ExecuteJavaScript(CodeToInject, "something://something", 1);
    

    This won't work if injected on the C# side, I believe because these calls are async so you may be injecting it too late, after scripts on the page have already run.