Why function at AddScriptToExecuteOnDocumentCreatedAsync is called only after source change ?
I have a simple application with WebView2. In my InitializeAsync method, I add 2 scripts via AddScriptToExecuteOnDocumentCreatedAsync.
async void InitializeAsync()
{
await webView.EnsureCoreWebView2Async();
webView.CoreWebView2.WebMessageReceived += RecievedMessage;
webView.CoreWebView2.DOMContentLoaded += delegate
{
IsDOMLoaded = true;
};
await webView.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync("document.addEventListener('mouseup', function(event) { var res = window.getSelection().toString(); var myObj = {action: 'Selection', data: res}; var json = JSON.stringify(myObj); if(res.length > 1) { window.chrome.webview.postMessage(json); } }, false);");
await webView.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync(
"function getTextHTML(){var res = document.body.innerText; var myObj = {action: 'GetHTML', data:res}; var json = JSON.stringify(myObj);window.chrome.webview.postMessage(json);}");
}
Then after button click which should Execute the second script - nothing happens.
private async void ButtonClick(object sender, RoutedEventArgs e)
{
await webView.CoreWebView2.ExecuteScriptAsync("getTextHTML();");
}
But first await webView.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync("document.addEventListener.... works fine at start page. In order to call my second function, I need to reload a page or go to another page.
My question is:
Why it has such behavior and how can I fix it?
Besides, I'd like to know, how I can ensure that script was added? Once, I found my script somewhere after clicking F12 on my browser, but I can't find it again now.
Hey @bodkia22 - I was able to reproduce the issue as you described with simple console.log scripts. I've opened this as a bug on our backlog to take a look.
For now if you'd like to workaround the issue you should be able to combine the 2 scripts into a single script so you're only calling AddScriptToExecuteOnDocumentCreatedAsync once.
@champnic I am hitting this problem now too. I felt the need to add what I have found out just in case it helps.
I am targeting an intRAnet site with a top level document and multiple frames.
- Source has been set to https://mickey.mouse.com/two/ears.jsp
- script added with AddScriptToExecuteOnDocumentCreatedAsync in WebView2InitializationCompleted
- Navigation completes and dom content is ready - the page contains 5 frames.
- Javascript has been loaded for 4 frames which all have a location of about:blank
- The top level document which has a location of https://mickey.mouse.com/two/ears.jsp is ignored.
Then if I use the site (the top level never navigates) instead it creates (and drops) frames and they get the JS as expected into each frame - cool stuff.
If I however put the AddScriptToExecuteOnDocumentCreatedAsync prior to the source being set then it injects into the top level document.
I realize this is similar to the original issue, however, I wanted to highlight that the frames are getting the script it is just the top level document that misses it.
By the way this was an issue a fair while ago, I do hope it is on track to be fixed soon.
@darbid That sounds like it may be By Design. When setting the source, it is both implicitly initializing the page and navigating. By the time the script is being added in InitializationCompleted (async) the top-level page may already have navigated past the point of "DocumentCreated". The InitializationCompleted event is non-blocking - the page will continue to navigate even if stuff is happening in response to the app handling the InitializationCompleted event.
If you want to avoid this, you can explicitly make sure the WebView2 is initialized but hasn't navigated yet by using EnsureCoreWebView2Async(), setting the script, and then navigating to the top-level page.
Thank you @champnic for the explanation. All I had to do was think about what the words in the method name meant :-)
However, to either save some time down the road or alot of dev hair I really think some of these events need to be explained a little better.
For example this one needs to be called prior to DocumentCreation. Where is it explained when DocumentCreation takes place? For example if you look here at Navigation events for WebView2 apps I am not sure I see this event explained. I guess it is someone between event 2 and 3.
To make it further complicated it is async so I guess that means it needs to be called with enough time to spare so that it arrives at its destination prior to this DocumentCreation.
Maybe even AddScriptToExecuteOnDocumentCreatedAsync should say that for it to apply to a url it must be called before calling a navigation to that url. That would be something I understand.
Sorry for being a pain, I do hope my opinion helps.
@darbid Glad it's working! And great callouts - I've opened a bug on our side to improve the clarity of the docs and add DocumentCreated to the navigation events page. Thanks!