I am trying to make a call to a meteor method, to insert a document before redirecting the user to the relevant url (using the generated document _id).
The code currently works on chromium but not on firefox, where on firefox it appears to just get redirected right away without actually inserting anything.
I've attached my code at the bottom. Can anyone tell me what went wrong and what can I do to fix it? Why will chrome and firefox behave differently in this situation?
Any help provided is greatly appreciated!
client.js
newDoc(){
Meteor.call('addDoc',{
// some parameters
})
}
clientandserver.js (Meteor method)
'addDoc'(obj){
console.log(obj); // does not output anything on firefox
DocumentData.insert({
//some parameters
},function(err,documentID){
if (Meteor.isClient){
window.location = '/docs/' + documentID;
// redirection happens before insertion on firefox
}
});
}
Bring window.location to the client side. Like:
newDoc(){
Meteor.call('addDoc', data, function(error, result){
if(result){
window.location = '/docs/' + documentID;
}
})
}
And put only the insertion in server side, like:
'addDoc'(obj){
return DocumentData.insert({
//some parameters
});
}
I've used this structure and it works for me in both Firefox & Chrome.
Related
The problem:
A chrome extension I am working on needs a location spoofer. It works, however I cannot 'unset' it.
What I have so far:
Let's examine the relevant code. This is a part of a content script.
let cachedGeoLocFunc = navigator.geolocation.getCurrentPosition
let geoSpoofCode = conf => `
(function() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition = function(success) { return success(${conf}); }
} else {
console.error('Geolocation is not supported in this browser');
}
})()
`
browser.runtime
.sendMessage({ type: 'request-spoofed-coords' })
.then(curCoords => {
//json from state, contains current spoofed locale
if (curCoords) {
let script = document.createElement('script')
script.textContent = geoSpoofCode(curCoords)
document.documentElement.appendChild(script)
script.remove()
} else {
//revert to default behavior
let unSetScript = document.createElement('script')
unSetScript.textContent = `
(function() {
navigator.geolocation.getCurrentPosition = ${cachedGeoLocFunc};
})()`
document.documentElement.appendChild(unSetScript)
unSetScript.remove()
}
})
As you can see, I am overriding the chrome native function and providing my own value. This works fine for spoofing a location.
Unexpected behaviour:
Conceptually I imagined this would work. I am caching the native chrome function so I can later reset it (see the else). In practice I get this error when this content script gets injected into a page.
Uncaught SyntaxError: Unexpected identifier
And it breaks here (as per the chrome inspector)
Screen shot of error
My questions!
So, it just injects [ native code ] instead of the actual function (at-least that is what it looks like).
Does anyone know how I can un-override this function. Is there an elegant way to do this?
How does caching in chrome work, is there ever a way to view this native code
Anyways help would be appreciated. Hope you all have a great day!
Ok, this was a misunderstanding as #wOxxOm pointed out. Please refer to their response. Content scripts do not affect or truly 'override' api functions.
I have a method in JavaScript that looks as follows:
function onAction() {
getValue1();
getValue2();
getValue3();
}
When I call onAction() I see two different behaviors between Mobile Safari and Android Chrome. In Safari, I get the values for all three methods. On Android Chrome, I only get the value of the last method. It doesn't matter which one is last. I suspected it may be an execution timing issue and attempted the following:
function onAction() {
new Promise(function(resolve,reject) {
resolve(1);
})
.then(function() {
getValue1();
})
.then(function() {
getValue2();
})
.then(function() {
getValue3();
});
}
Again, it works fine in Mobile Safari, but not Android Chrome.
I'm sure I'm missing something obvious, but it's eluding me. If it matters, the getValue* functions are used to get values via each platform's mechanism for Native Code->JavaScript bridging.
Any help is appreciated. Please let me know if I can supply any more information.
Regards,
Rob
**Additional Info **
The getValueX functions don't return any values. They trigger values to be pushed over to the native wrapper:
function getReaderSDKVersion() {
var message = {'action' : MPDataEnum.SDKVersion};
raiseMessage(message);
}
function raiseMessage(message) {
if (isPlatformiOS()) {
window.webkit.messageHandlers.interOp.postMessage(message);
} else {
var url = "mpcard://runMethod#" + JSON.stringify(message);
window.location.href = url;
}
}
The issue is answered here:
Triggering shouldStartLoadWithRequest with multiple window.location.href calls
Whereas this was an issue in most browsers, it doesn't appear to affect Mobile Safari now.
I am integrating my project with facebook auth login, and I want to support Chrome on IOS. I noticed that I have to handle both authWithOAuthPopup and authWithRedirect (firebase user-auth) in this case. However Chrome IOS did not support Popup auth currently.
I simplify my code and shows the case how it won't work in Chrome on IOS
var rootRef = new Firebase('https://docs-sandbox.firebaseio.com/web/uauth');
rootRef.onAuth( function(authData){
alert('getAuth');
alert(authData);
console.log(authData);
});
$('#login').on('click', function(e){
rootRef.authWithOAuthPopup("facebook", function(err, authData){
if(err && err.code === 'TRANSPORT_UNAVAILABLE'){
rootRef.authWithOAuthRedirect("facebook", function(err, authData){
if(authData){
alert('redirect');
alert(authData);
}
})
}
})
});
Link here http://jsfiddle.net/blackbing/zjunuzec/5/ for more detail.
It works on Safari IOS. If login success, it will alert [object], but it shows null in Chrome on IOS.
any idea?
I think that I figure out what the problem is.
First of all, it is said getAuth is synchronized in document, but It is not reliable synchronized on authWithOAuthRedirect. So when the page redirect to the original page. I can't get authData so that I can't decide if user is signin. (but actually user is signed in).
Second, since callback in "authWithOAuthRedirect" is not possible to be called, the callback function can't get authData anyway. It just could be called if occur error, right? I suggest to notice this behavior that in document.
Anyway: I think the snippet in document have to correct :
https://www.firebase.com/docs/web/guide/user-auth.html#section-popups
the callback in authWithFunction is for handling error, not suggested to deal with authData, onAuth is a better way to get authData. I update a snippet on my gist [https://gist.github.com/blackbing/f77d04cbed4b0059af2e]
var ref = new Firebase("https://<your-firebase>.firebaseio.com");
rootRef.onAuth( function(authData){
//It is a better way to get authData instead of get from auth callback function
console.log(authData);
});
// prefer pop-ups, so we don't navigate away from the page
// auth callback is to handle if occur error
ref.authWithOAuthPopup("google", function(err) {
if (err) {
if (err.code === "TRANSPORT_UNAVAILABLE") {
// fall-back to browser redirects, and pick up the session
// automatically when we come back to the origin page
ref.authWithOAuthRedirect("google", function(err) { ... });
}
}
});
BTW, I found a similar question https://stackoverflow.com/a/26416696/797411, the workaround is not good but I think we met the same problem.
I tried to do a simple AJAX request on http://localhost:8080/ and I get an error right away when using IE 11. I don't think IE is even trying to send anything.
Did somebody meet this issue?
Here is a fiddle showing this behavior,
html:
<button id='btn1'>launch</button>
onLoad:
var xhr,btn=document.getElementById('btn1');
btn.onclick=onButton;
var onReadyState=function(){
console.log('ready state:'+_xhr.readyState);
if(xhr.readyState===4){
console.log('status:'+_xhr.status);
}
}
function onButton(){
xhr=new window.XMLHttpRequest();
xhr.onreadystatechange=onReadyState;
xhr.open('POST','http://localhost:8080/ScanAPI/v1/client');
xhr.send();
}
You will need to launch the IE F12 developer tool, before trying and you will see IE catching the exception.
Any help on this would be greatly appreciated.
Thanks!
It doesn't work because you are referencing an object named _xhr that does not exist within the scope of the onReadyState function.
You should be using this instead :
var onReadyState = function() {
if (this.readyState === 4) {
console.log('status :' + this.status);
}
};
That's because the XMLHttpRequest object will call back onReadyState with its own context, which is accessible through this in your function.
Also note that the onReadyState function misses a semi-colon at the end of its definition, didn't notice it at first sight.
EDIT : I also noticed that IE10 (and IE11) does interpret some HTTP response code as network errors (such as with a 401 response code), if it is your case, then it makes sense that IE fails at retrieving your resource.
I forked your fiddle and wrote a simple page that works well with IE11.
I need to redirect in a javascript file to a given URI specified by the user.
So a quick example how I do this:
function redirect(uri) {
if(navigator.userAgent.match(/Android/i)) {
document.location.href=uri;
}
window.location.replace(uri);
}
This works fine for everything except Android devices. iOS and all modern Webbrowsers support window.location.replace(...), however Android devices don't do that.
But if I now try to redirect using this function, lets say to "http://www.google.com" the android devices fail to actually redirect to the given url.
Now is it just me being stupid here right now or is there another problem?
Sincerly
p.s. the redirect function is called as an callback from an XML request sent, but that should not be an issue at all.
Android supports document.location without the href property
Try to use:
function redirect(uri) {
if(navigator.userAgent.match(/Android/i))
document.location=uri;
else
window.location.replace(uri);
}
I think it should be window.location.href, not document.location.href.
I would suggest :
location.assign('someUrl');
It's a better solution as it keeps history of the original document, so you can navigate to the previous webpage using back-button or history.back() as explained here.
You can use match and replace in iOS but apparently not in Android. In my experience this is what works for redirects in Android:
<script type="text/javascript"> // <![CDATA[
if ( (navigator.userAgent.indexOf('Android') != -1) ) {
document.location = "http://www.your URL/your HTML file.html";
} // ]]>
</script>
You can just use: window.location = "http://example.com";