I have a javascript function like below.
var object;
$(document).ready(function () {
$("#buttonA").click(function (e) {
object.doWork(); //triggers a method in Silverlight
});
});
Method in Silverlight
private void doWork()
{
SaveFileDialog dialog = new SaveFileDialog();
dialog.ShowDialog(); //throws error "Dialogs must be user-initiated"
}
Any ideas why the error is thrown. I do not have any break points set in the doWork method in silverlight. The button click event in javascript seems to be user initiated event. Please suggest a solution to this problem.
Thanks,
Dialogs must be user-initiated in the sense that they have to occur due to a user interaction event (click, button press etc) within the Silverlight component. (In fact "due to" is really a restriction of having to occur within a certain period after the interaction, rather than some strict restriction such as relating to the call stack)
From the perspective of the Silverlight security restriction, this is just an arbitrary javascript method calling into Silverlight, and so this will not be possible (for good reason). You would need to open the dialog from a real Silverlight button.
If you really need to raise some kind of dialogs from a Silverlight control called via javascript, you may need to actually call back out to open a dialog in JavaScript/HTML (or some kind of popover in either environment).
Related
Situation
In our Android app (Xamarin), we open a web page using an ActionView intent. The code looks like this:
Intent intent = new Intent((string)Intent.ActionView, Android.Net.Uri.Parse(args.url));
intent.AddFlags(ActivityFlags.NewTask);
The opened page at some point does a JS redirect, with a line like this:
window.location = '...';
We tried many different variations of that line, including window.location.href = '...', window.location.assign('...'); and some more. All show the same behavior.
Problem
This has worked fine for years now, in all browsers - but now we ran into a problem, when the browser on the android device is the Edge browser:
When the browser tab is initially opened by the intent, the window.location = '...' line in Javascript is just ignored by the browser. No error message - just ignored.
However, if that same browser tab with exactly the same URL is opened manually (either by reloading or by copying and pasting the URL), the JS redirect is executed just fine.
Question
How do we fix this, how do we make the JS redirect reliably work?
My guess is that we are running into a security feature, which prevents JS redirects in browser tabs that the user has never interacted with.
Is there something (maybe an intent flag?) to circumvent this? We already tried the flag GrantWriteUriPermission, but it did not help.
Possible duplicates
Android Browser Facebook Redirect Does Not Always Trigger Intent for URL :
The proposed situation of setting the URL on a link and faking a click on it did not work.
Microsoft Edge security
Microsoft Edge recently fixed an issue regarding XSS Targeting Non-Script Elements (June 24, 2021).
The vulnerability was found by two researcher when they visited a website in another language via the Microsoft Edge browser and attempted to translate the page. The goal of the recent fix by Microsoft is to avoid vulnerability regarding accessing dynamically to a content from a third party application and specifically in the case of browser redirection. They need to act quickly because the vulnerability is quite huge.
In order to mitigate a large class of potential cross-site scripting issues, the Microsoft Edge Extension system has incorporated the general concept of Content Security Policy (CSP)
Ok, but ... is there any solution?
Maybe you can find a solution to solve your issue here, in particular the part concerning the <button onclick="...">.
Inline code is considered harmful in concept of CSP and microsoft recommend some good practices :
1 - The clickHandler definition must be moved into an external JavaScript
2 - The inline event handler definitions must be rewritten in terms of addEventListener and extracted into your external js file. If you are currently starting your program using code like <body onload="main();">, consider replacing it by hooking into the DOMContentLoaded event of the document, or the load event of the window, depending on your requirements. Use the former, since it generally triggers more quickly.
3 - Function inside onclick call must be rewritten to avoid converting the string of function into JavaScript for running.
The code exemple of the external .js file cited in the documentation look like this :
function awesome() {
// Do something awesome!
}
function totallyAwesome() {
// do something TOTALLY awesome!
}
function awesomeTask() {
awesome();
totallyAwesome();
}
function clickHandler(e) {
setTimeout(awesomeTask, 1000);
}
function main() {
// Initialization work goes here.
}
// Add event listeners once the DOM has fully loaded by listening for the
// `DOMContentLoaded` event on the document, and adding your listeners to
// specific elements when it triggers.
document.addEventListener('DOMContentLoaded', function () {
document.querySelector('button').addEventListener('click',
clickHandler);
main();
});
Hope it's helps
Background information: We have a platform which runs on https://system.example.com. This platform consists of 10 separate web applications (all written in PHP and JS). Each application has historically been in a sub-directory within the same subdomain:
https://system.example.com/app1/
https://system.example.com/app2/
...
https://system.example.com/app10/
We are in the process of rebuilding one of the applications, app2, and have decided to host this on a new separate subdomain, https://app2.example.com.
Part of the app2 application uses JavaScript to open a pop-up window for app10. Most functionality inside this popup works as expected. However, when attempting to use a "Save" button inside the popup my browser console was showing:
Uncaught DOMException: Blocked a frame with origin "https://app2.example.com" from accessing a cross-origin frame.
at https://system.example.com/app10/manage.php:1:334
I have read both SecurityError: Blocked a frame with origin from accessing a cross-origin frame and https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage but still unclear as to how to fix this.
The code and process I have is as follows:
The popup is opened from https://app2.example.com by a button which has an onclick event handler:
<button onclick="postToPopUp('https://system.example.com/app10/manage.php', 'fileManage', 'width=800px,height=600px', ['f_id', '123'], 'app2', 'filesCallbackManage')">Open app10</button>
The postToPopup() function is used to pass POST data from app2 into https://system.example.com/app10/manage.php based on Javascript window.open pass values using POST - this works fine.
The problem occurs when I click a "Save" button inside the popup which renders the following markup within the popup window:
<!doctype HTML><html><head><title>upload</title>
<script type="text/javascript" language="javascript" charset="utf-8">
var fileObject = {"files":{"0":{"f_id":"1784","f_title":"test07.pdf"},"f_id":123}};
window.opener.filesCallbackManage(fileObject);
window.close();
</script><body></body></html>
What this did originally - when everything was under the same subdomain - was called a js function filesCallbackManage() which resided in the code for https://system.example.com/app2. The function itself was passed an object, fileObject, which updated various parts of the UI inside app2. The popup was closed after clicking the Save button due to window.close();
Although I've read about using postMessage I don't understand how this fits in or whether this is even the correct solution to my problem? The data is being posted from the subdomain https://app2.example.com to https://system.example.com/app10 correctly. The problem is that filesCallbackManage() won't fire because of the cross origin restriction. Inside my code for https://app2.example.com I have a simple statement to see if it's firing:
function filesCallbackManage(data)
{
console.log('filesCallbackManage has fired');
}
This never fires because of the problem I have. I get the console error mentioned previously and a blank popup window (technically this is correct since there is nothing in the <body> tag in the above markup) but the window doesn't close and the callback isn't fired.
The example given on the Mozilla website isn't extensive enough to understand how it can be adapted to this type of scenario. Please can someone elaborate? Furthermore, the linked Stack Overflow post is four years old so I want to be sure anything I put on this is secure and up-to-date.
The postToPopup() function is used to pass POST data
Submitting a form across origins is fine. So you can do this.
The problem occurs when I click a "Save" button inside the popup
You're trying to access the DOM of the window across origins. This is forbidden.
Although I've read about using postMessage I don't understand how this fits in or whether this is even the correct solution to my problem?
postMessage is as close as you can get to accessing the DOM of a window across origins.
You can't do this.
var fileObject = {"files":{"0":{"f_id":"1784","f_title":"test07.pdf"},"f_id":123}};
window.opener.filesCallbackManage(fileObject);
Instead you have to send a message:
window.opener.postMessage(fileObject, "https://system.example.com");
And have code which listens for it:
addEventListener("message", receiveMessage);
function receiveMessage(event) {
if (event.origin !== "http://app2.example.com") { return false; }
filesCallbackManage(event.data);
}
We're coding an app for Android. It's a WebView that contains Html5 pages. We're using loadUrl() webview's method, in order to push some native OS variables to html, such as:
webview.loadUrl("javascript:myJavascriptFunc('" + myAndroidOSVar + "');");
It works pretty fine. But if we are typing on an input from page while loadUrl() is called, we lose focus of our input fields, even if javascript function called just changes a flag on cache.
Do you know other way to call a Javascript function from WebView instead of loadUrl()?
This is the closest you can get to avoiding the issue: WebView hides soft keyboard during loadUrl(), which means a keyboard cannot stay open while calling javascript
Basically you are avoiding the loadUrl call by queuing up commands on the native side and at an interval letting the JS bridge get the commands and execute using JS eval() or something.
I'm not sure exactly how it will respond if you have multiple fields in the webview, but I came up with a workaround to keep the keyboard shown: https://stackoverflow.com/a/18776064/513038. It may be worth trying.
yes, there is a way by adding a JavaScriptInterface to your WebView , refer this tutorial for more explanation and details
I have a Flash game that I'm trying to save the state of when the user closes the browser tab. It is using the following jquery code:
//Called from Flash when window closes
function sendRequest(url, params) {
$.ajax({
type: "POST",
async: false,
url: url,
data: params
})
}
$(window).unload(function() {
//Make Flash attempt to save the game when the window closes.
//Flash gets the necessary data and calls sendRequest()
document["flashGame"].saveBeforeUnload();
});
Firefox: Works correctly
Chrome: Works correctly when reloading but not when closing tabs or closing the browser
IE (all versions): Does not work at all
I want it to work in all browsers correctly, but most important is Chrome (not many of our users have IE).
Flash is correctly calling sendRequest (in all browsers, tested with an alert), so I don't believe the problems come from Flash, but it might.
The short answer is that you can't.
The onbeforeunload event was initially introduced by Microsoft to allow a standard confirmation dialog. It is now supported in the original form by most browsers and in most case a short, non interactive, function is allowed to execute (for example you may log your state in the localStorage). But, as described in the cross-browser jQuery API, this is unreliable :
The exact handling of the unload event has varied from version to
version of browsers. For example, some versions of Firefox trigger the
event when a link is followed, but not when the window is closed. In
practical usage, behavior should be tested on all supported browsers,
and contrasted with the proprietary beforeunload event.
As there are many potential security problems related to the execution of a task when the user asked to end the page (and thus the script), this will probably be unreliable until (and if) a serious normalization effort is done to precise what exactly can be done in a onbeforeunload callback.
For the predictable future, it's recommended to not depend on onbeforeunload but to use other schemes, for example constant background saving or a big "save" button.
Try window.onbeforeunload. I found this in the jQueryBug Tracker as a possible solution:
window.onbeforeunload = function() { return "text"; }
I'm trying to call a function in a Silverlight 4 component to open a file dialog and upload a file to the server. Everything works well within Silverlight but I'd like to call the component from JavaScript. So I call the button click handler from a C#-function which is [ScriptableMember]. I get the following error when calling the function:
System.Security.SecurityException: Dialogs must be user-initiated.
at System.Windows.Browser.ManagedObjectInfo.Invoke(ManagedObject obj, InvokeType
invokeType, String memberName, ScriptParam[] args) at
System.Windows.Hosting.ManagedHost.InvokeScriptableMember(IntPtr pHandle, Int32 nMemberID,
Int32 nInvokeType, Int32 nArgCount, ScriptParam[] pArgs, ScriptParam& pResult,
ExceptionInfo& pExcepInfo)
I based my code on the tutorial by Tim Heuer that can be found here: http://www.silverlight.net/learn/videos/silverlight-videos/openfiledialog-and-file-upload/
I understand why the error is thrown, sort of, the 'click' from the user is done in JavaScript and probably is not going through to Silverlight. For Silverlight this is merely a function call.
Is this new policy from Silverlight 4? Is it still possible to only use Silverlight behind to screens to upload a file? Any help is appreciated.
I believe in Silverlight 2 this may have been permitted, but ever since it has not. This was a breaking behavior change, requiring the action to be "user initiated" through a user action -in- Silverlight: something like a key press or mouse click on a button with a click event handler.
There isn't a way to pop up and open the file dialog any other way.