Can the document.location.protocol value be changed in a WinRT webview? - webview

I'm currently having an issue with the WebView control used in a Universal WinRT app (Windows 8.1/Windows Phone 8.1).
I currently load the following piece of JavaScript into the WebView using the NatigateToString method:
<html>
<head>
<base href='MY_BASE_URL'>
</head>
<body>
<script>
var idcomments_acct = 'MY_ACC_ID';
var idcomments_post_id='POST_ID';
var idcomments_post_url='POST_URL';
</script>
<span id='IDCommentsPostTitle' style='display:none'></span>
<script type='text/javascript' src='http://www.intensedebate.com/js/genericCommentWrapperV2.js'></script>
</body>
</html>
This is the piece of code for the IntenseDebate generic install that can be found here.
The issue is with this line of code in the referenced IntenseDebate code:
load_js(document.location.protocol+"//connect.facebook.net/en_US/all.js")
This piece of code fails because document.location.protocol is set to about: in the WebView, leading to a 404 error on this call.
On the Android/iOS webviews simply setting the base URI to a http: or https: based address using their loadDataWithBaseUrl methods worked fine, but the WinRT WebView is missing a similar method. And setting the Base url in the HTML itself (like shown in the piece of code above) does work for resolving image url's and sortlike, but this method doens't change the document.location values.
Since I can't modify the referenced JS file and putting the above piece of HTML on a server isn't an option in this apps usecase, is there any way you can force the document.location.protocol to be a certain value in the WinRT webview? Or is there any other way to get this bit of HTML to work in a webview?

There isn't a direct way to do this. WebView doesn't provide any interface to override the document.location . If branching off of the protocol is a common pattern then this may be a good feature to request on http://wpdev.uservoice.com .
I'm not familiar enough with HTML/JavaScript best practices to say for sure, but most of the references I find searching for document.location.protocol warn against assuming that the protocol will always be http: or https. This may be something that IntenseDebate should fix.
That said, you may be able to get past this by injecting code into your page which finds the problem location in the DOM and changing it live. You can't change just the protocol, but you may be able to find where it is referenced and change that there. I assume it gets loaded into the commentScript.src from genericCommentWrapper2.php referenced in genericCommentWrapper2.cs and then added to the document's head.

Related

Can iframes work in WKWebView with Cordova?

According to the Apache Cordova blog, iframes may not work using WKWebView. (https://cordova.apache.org/news/2018/08/01/future-cordova-ios-webview.html)
I have a Cordova application that is in the App Store that relies quite heavily on iframes. Since UIWebView is likely to be removed in iOS 13, is there a way to get iframes working using WKWebView?
Here's what I've done so far:
I tried using the Ionic WebView plugin (https://github.com/ionic-team/cordova-plugin-ionic-webview), and although it works for parts of my app it does not work on the iframe pages. Specifically, I'm getting Access-Control-Allow-Origin header contains the invalid value 'null'. I don't get this error using UIWebView.
Add this in your config.xml
<allow-navigation href="*" />
Then build your ios platform
I ran into this issue also in my Cordova apps, and have found a workaround. It involves writing content directly to the iframe, rather than giving it a src="...". This way, iframe runs as same-origin as parent.
(Iframes do work in WkWebView; it's just that anything loaded via src="file://..." [e.g. all local app files] are treated as unique-origin, so tends to screw up any cross-frame JavaScript.)
function frameEl_injectHtml(frameEl, injectHtml) {
// frameEl must exist in DOM before its contentWindow is accessible.
if (!frameEl.contentWindow) { alert("frameInjectHtml() but frameEl not (yet or anymore) in DOM."); return; }
frameEl.contentWindow.document.open('text/htmlreplace');
frameEl.contentWindow.document.write(injectHtml);
frameEl.contentWindow.document.close();
}
// Create <frame>, insert into DOM, and inject content.
var frameHtml = "<html><head></head>" +
"<body>" +
"iframe body" +
"<script>window.parent.alert('iframe even same-origin as parent.');</script>" +
"</body></html>";
var frameEl = document.createElement('iframe');
frameEl.src = "about:blank";
document.body.appendChild(frameEl);
frameEl_injectHtml(frameEl, frameHtml);
Add this to your Cordova config.xml
<allow-navigation href="http://*.yourdomain.com/*" />
It will allow your HTML pages, no matter root documents or children in the iframe, to redirect from localhost to a remote URL.

invokescriptasync HRESULT: 0x80020101' script runs fine in chrome and IE

I'm still trying to make the invokescriptasync work. I'm trying the following test on facebook.com and it fails with a HRESULT: 0x80020101' which normally means the script has an error in it, but I tried running the simple javascript in Chrome and IE without any problem.
private async void WebView_OnNavigationCompleted(WebView sender, WebViewNavigationCompletedEventArgs args)
{
await _webView.InvokeScriptAsync("eval", new[]
{
"document.getElementById('blueBarDOMInspector').innerHTML = '';"
});
}
Thanks
I have tested your code and the error is thrown only in case the blueBarDOMInspector is not found. I used the following simple HTML:
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head></head>
<body>
<p id="blueBarDOMInspector"></p>
</body>
</html>
You can confirm that the script works as expected with this HTML. So I suspect the problem is rather on HTML side than on side of UWP.
As for ScriptNotify not working - the website must be HTTPS and be added as trusted to appxmanifest. Better solution is web allowed object. A great example was posted in a question yesterday on SO or here as a sample project. Basically you have to create a Windows Runtime Component with a class marked as [WebAllowed] and then inject it in the WebView using AddWebAllowedObject method.
For your invoking JavaScript code issue,I've checked your code, it's simple, the possible issue might be the 'blueBarDOMInspector' object, please make sure that you could get the 'blueBarDOMInspector' object successfully when the OnNavigationCompleted is fired.
For your second question:
I can invoke the script : "window.external.notify('something');" but it doesn't raise the event ScriptNotify which is another problem :-(
Please check the document:
To enable an external web page to fire the ScriptNotify event when calling window.external.notify, you must include the page's Uniform Resource Identifier (URI) in the ApplicationContentUriRules section of the app manifest.

obtaining a reference to IHTMLCanvasElement

How Can I get a DOM reference to the canvas Handle. I'm using Delphi, IE11 and the corresponding MSMHTML Type library,I suspected it's along the lines of
canvasHandle := (HTMLDoc3.getElementById('canvas') as IHTMLCanvasElement);
the Html:
<canvas id="canvas">
....
</canvas>
however this throws an exception 'Interface not supported'
TWebBrowser control, by default uses IE7 standards/rendering mode.
You need to tell the control to use latest standards.
There are a few ways of doing this.
Here are two of the ways known to me:
Either you specify FEATURE_<some feature> for your application in the registry (.e.g. FEATURE_BROWSER_EMULATION also a nice article here).
Add a "meta http-equiv-'X-UA-Compatible' content= edge" to the <head> block of a webpage to force Windows IE to use the latest standards.
This will enable your HTML5 functionality working without the need for registry tweaks.

Link rel='import' breaks Router

I'm experimenting with dart-polymer apps and have run into a few issues.
Is there a way to inject template declaration of a custom element through code? The docs currently specify the following method:
<link rel="import" href="my_element.html">
I'm trying to use the Route package (specifically 'package:route/client.dart'), and importing an html module via this method seems to break the router, so:
main() {
var router = new Router()
..addHandler(homeUrl, showHome)
..addHandler(signinUrl, showSignin)
..listen();
}
fails to execute the handlers when I navigate to the Url specified. If I remove the html import, the Router works fine.
Any way around this?

"document" in mozilla extension js modules?

I am building Firefox extension, that creates single XMPP chat connection, that can be accessed from all tabs and windows, so I figured, that only way to to this, is to create connection in javascript module and include it on every browser window. Correct me if I am wrong...
EDIT: I am building traditional extension with xul overlays, not using sdk, and talking about those modules: https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules
So I copied Strophe.js into js module. Strophe.js uses code like this:
/*_Private_ function that creates a dummy XML DOM document to serve as
* an element and text node generator.
*/
[---]
if (document.implementation.createDocument === undefined) {
doc = this._getIEXmlDom();
doc.appendChild(doc.createElement('strophe'));
} else {
doc = document.implementation
.createDocument('jabber:client', 'strophe', null);
}
and later uses doc.createElement() to create xml(or html?) nodes.
All worked fine, but in module I got error "Error: ReferenceError: document is not defined".
How to get around this?
(Larger piece of exact code: http://pastebin.com/R64gYiKC )
Use the hiddenDOMwindow
Cu.import("resource://gre/modules/Services.jsm");
var doc = Services.appShell.hiddenDOMWindow.document;
It sounds like you might not be correctly attaching your content script to the worker page. Make sure that you're using something like tabs.attach() to attach one or more content scripts to the worker page (see documentation here).
Otherwise you may need to wait for the DOM to load, waiting for the entire page to load
window.onload = function ()
{
Javascript code goes here
}
Should take at least diagnose that issue (even if the above isn't the best method to use in production). But if I had to wager, I'd say that you're not attaching the content script.

Resources