XMLHttpRequest in a ContentScript from the Firefox SDK (Cross-Domain) - xmlhttprequest

I am porting a chrome extension to firefox and want to keep as much code as possible. I am working with the sdk and I am new with JavaScript, so please bear with me if it is just a nooby mistake ;)
I need to get some stuff via a couple of XMLHttpRequests in content-scripts.
The "firefox-way" of doing things would be to use the sdk-request-api and work via messages between the main- and the content-script like so. Besides the fact that it would mean a lot of work for me to implement this throughout the whole addon, I also need to get binary data, which seems not to be possible.
The workaround for this is documented here. I would prefer to avoid this, since I think I read somewhere that it is a beta-feature right now and it seems to be pretty "work-aroundy".
Ideally I would like to implement it this way. In the upcoming Firefox 24 it should be possible to allow content scripts to access certain domains. Therefore I am using Firefox Aurora right now. I added the following code to my package.json:
"permissions": {
"cross-domain-content": ["http://mozilla.org"]
}
My main.js creates a panel when a button is clicked and loads the scripts into it:
var testPanel = require("sdk/panel").Panel({
contentURL: data.url("pages/background.html"),
contentScriptFile: [data.url("util/jquery-1.8.2.min.js"), data.url("pages/xhrTest.js")]
})
testPanel.show();
And this is my xhrTest.js:
var xhr = new XMLHttpRequest();
xhr.open("GET","http://mozilla.org",true);
xhr.onerror = function () {
console.log("Error");
};
xhr.onload = function () {
console.log("loaded");
}
xhr.send();
While debugging, it jumps from status 2 to 4 with an empty response and calls the "onerror". The status is 0, statustext is empty and I don't see any other indicators of what went wrong.
Now I don't know if this is still the same-origin-policy blocking me, or if I did something else wrong?
I'd really appreciate any help I can get :)
Thanks in advance,
Fabi

Hrm, I can't really see a glaring error. Here is an example add-on based on the docs that does work, at least it does for me in Firefox 24 Beta:
Main.js:
// main.js
var data = require("sdk/self").data;
var panel = require("sdk/panel").Panel({
height: 250,
contentURL: data.url("panel.html"),
contentScriptFile: data.url("panel-script.js")
});
panel.on("show", function(){
panel.port.emit("show");
});
require("sdk/widget").Widget({
id: "test-widget",
label: "Test-Widget",
contentURL: "http://www.mozilla.org/favicon.ico",
panel: panel
});
Panel.html:
<!doctype HTML>
<html>
<meta charset="utf-8">
<head></head>
<body>
<pre id="forecast_summary"></pre>
</body>
</html>
Content script:
// panel-script.js
var url = "https://hn-test.firebaseio.com/articles/e5b10c82600b51732af584583a7f57c4a7c01bff.json";
self.port.on("show", function () {
var request = new XMLHttpRequest();
request.open("GET", url, true);
request.onload = function () {
var element = document.getElementById("forecast_summary");
// formatting
var pretty = JSON.stringify(JSON.parse(request.responseText), null, ' ');
element.textContent = pretty;
};
request.send();
});
Package.json:
{
"name": "jp-crossdomain-xhr",
"fullName": "jp-crossdomain-xhr",
"id": "jid1-B2RaQxOBKox8wA",
"description": "a basic add-on",
"author": "",
"license": "MPL 2.0",
"version": "0.1",
"permissions": {
"cross-domain-content": ["https://hn-test.firebaseio.com"]
}
}
Github Repo

Related

Show custom error message on passwordless Auth0 page

I would like to only allow certain phone numbers when patients sign up to my application through a passwordless Auth0 page.
For this I added a custom Auth0 action to the Pre User Registration flow.
My custom action checks the phone prefix:
/**
* Handler that will be called during the execution of a PreUserRegistration flow.
*
* #param {Event} event - Details about the context and user that is attempting to register.
* #param {PreUserRegistrationAPI} api - Interface whose methods can be used to change the behavior of the signup.
*/
exports.onExecutePreUserRegistration = async (event, api) => {
if (!isAllowedPhoneNumber(event.user.phone_number)) {
api.access.deny('my_custom_identifier', 'My Custom Message');
}
};
const allowedPhonePrefixes = ["+43", "+32", "+420", "+45"];
const isAllowedPhoneNumber = (phoneNumber) =>
allowedPhonePrefixes.some((prefix) => phoneNumber.startsWith(prefix));
However, "My Custom Message" doesn't show up when I try a phone number outside those allowed. Instead, I see the default "We're sorry, something went wrong".
I then tried to edit the HTML code of my custom Auth0 login page adding this:
languageDictionary = {
...languageDictionary,
passwordless: {
"lock.fallback": "My Custom Message",
"no_signups_from_outside_schengen_area": "My Custom Message 2",
}
};
So the HTML code of my page now looks like this:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Sign In with Auth0</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<!--[if IE 8]>
<script src="//cdnjs.cloudflare.com/ajax/libs/ie8/0.2.5/ie8.js"></script>
<![endif]-->
<!--[if lte IE 9]>
<script src="https://cdn.auth0.com/js/base64.js"></script>
<script src="https://cdn.auth0.com/js/es5-shim.min.js"></script>
<![endif]-->
<script src="https://cdn.auth0.com/js/lock/11.30/lock.min.js"></script>
<script>
// Decode utf8 characters properly
var config = JSON.parse(decodeURIComponent(escape(window.atob('##config##'))));
config.extraParams = config.extraParams || {};
var connection = config.connection;
var prompt = config.prompt;
var languageDictionary;
var language;
if (config.dict && config.dict.signin && config.dict.signin.title) {
languageDictionary = { title: config.dict.signin.title };
} else if (typeof config.dict === 'string') {
language = config.dict;
}
var loginHint = config.extraParams.login_hint;
languageDictionary = {
...languageDictionary,
passwordless: {
"lock.fallback": "My Custom Message",
"no_signups_from_outside_schengen_area": "My Custom Message 2",
}
};
var lock = new Auth0LockPasswordless(config.clientID, config.auth0Domain, {
auth: {
redirectUrl: config.callbackURL,
responseType: (config.internalOptions || {}).response_type ||
(config.callbackOnLocationHash ? 'token' : 'code'),
params: config.internalOptions
},
configurationBaseUrl: config.clientConfigurationBaseUrl,
overrides: {
__tenant: config.auth0Tenant,
__token_issuer: config.authorizationServer.issuer
},
assetsUrl: config.assetsUrl,
allowedConnections: connection ? [connection] : null,
rememberLastLogin: !prompt,
language: language,
languageBaseUrl: config.languageBaseUrl,
languageDictionary: languageDictionary,
theme: {
logo: 'https://link-to-my-logo.something',
primaryColor: '#429db3'
},
closable: false,
showTerms: false
});
lock.show();
</script>
</body>
</html>
... but still neither "My Custom Message" nor "My Custom Message 2" show up. I still see "We're sorry, something went wrong".
How can I show a custom error message to users who enter a phone number from outside the list of allowed countries?
Note: I am pretty sure that the custom Auth0 action works, as I am able to prevent sign-ups for certain phone prefixes. What is probably wrong is the way I'm changing the code of the HTML page shown above, I suppose.
There is a partial solution that allows to show a custom message for all extensibility errors. (I haven't found a way to show different custom messages for different extensibility errors.)
This partial solution involves changing the structure in which the languageDictorionary variable above is structured:
languageDictionary = {
...languageDictionary,
error: {
passwordless: {
extensibility_error: "My Custom Message for all extensibility errors"
}
}
};
This way, any call to api.access.deny in the Pre User Registration flow will show "My Custom Message for all extensibility errors", no matter what identifier or message is passed to api.access.deny.

URL.createObjectURL(mediaSource) - play back video from URL - MOOV atom - Elastic Transcoder

I am trying to play back a video (currently hosted on S3 with public access) by creating a blob URL.
I have used Elastic Transcoder to encode the video since it is supposed to set the MOOV atom to the top (beginning).
I am unable to get the code to work but also found a working example: link here
Here is my code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
</head>
<body>
<video controls></video>
<script>
var video = document.querySelector('video');
var assetURL = 'https://ovation-blob-url-test.s3.amazonaws.com/AdobeStock_116640093_Video_WM_NEW.mp4';
// Need to be specific for Blink regarding codecs
// ./mp4info frag_bunny.mp4 | grep Codec
var mimeCodec = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"';
if ('MediaSource' in window && MediaSource.isTypeSupported(mimeCodec)) {
var mediaSource = new MediaSource;
//console.log(mediaSource.readyState); // closed
video.src = URL.createObjectURL(mediaSource);
mediaSource.addEventListener('sourceopen', sourceOpen);
} else {
console.error('Unsupported MIME type or codec: ', mimeCodec);
}
function sourceOpen (_) {
//console.log(this.readyState); // open
var mediaSource = this;
var sourceBuffer = mediaSource.addSourceBuffer(mimeCodec);
fetchAB(assetURL, function (buf) {
sourceBuffer.addEventListener('updateend', function (_) {
mediaSource.endOfStream();
video.play();
//console.log(mediaSource.readyState); // ended
});
sourceBuffer.appendBuffer(buf);
});
};
function fetchAB (url, cb) {
console.log(url);
var xhr = new XMLHttpRequest;
xhr.open('get', url);
xhr.responseType = 'arraybuffer';
xhr.onload = function () {
cb(xhr.response);
};
xhr.send();
};
</script>
</body>
</html>
What am I doing wrong? I looked at tools ie.e MP4Box or QT-FastStart but they seem to be kind of old school. I would also be willing to change from MP4 to M3U8 playlist but then I don't know what MIME types to use.
At the ned of the day I am trying to play back a video/stream and hide the URL (origin) potentially using blob.
Thank you guys!
So, first, even though this code seems to be taken from mozilla documentation site, there are a few issues - you are not checking the readyState before calling endOfStream thus the error you get is valid, secondly, the play() call is blocked by the autoplay policy changes. If you add an error handler, you will actually see that the appendBuffer fails. Here is the updated snippet:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
</head>
<body>
<video controls></video>
<script>
var video = document.querySelector('video');
var assetURL = 'https://ovation-blob-url-test.s3.amazonaws.com/AdobeStock_116640093_Video_WM_NEW.mp4';
// Need to be specific for Blink regarding codecs
// ./mp4info frag_bunny.mp4 | grep Codec
var mimeCodec = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"';
if ('MediaSource' in window && MediaSource.isTypeSupported(mimeCodec)) {
var mediaSource = new MediaSource;
//console.log(mediaSource.readyState); // closed
video.src = URL.createObjectURL(mediaSource);
mediaSource.addEventListener('sourceopen', sourceOpen);
} else {
console.error('Unsupported MIME type or codec: ', mimeCodec);
}
function sourceOpen (_) {
//console.log(this.readyState); // open
var mediaSource = this;
var sourceBuffer = mediaSource.addSourceBuffer(mimeCodec);
fetchAB(assetURL, function (buf) {
sourceBuffer.addEventListener('updateend', function (_) {
// console.log(mediaSource.readyState); // ended
if (mediaSource.readyState === "open") {
mediaSource.endOfStream();
video.play();
}
});
sourceBuffer.addEventListener('error', function (event) {
console.log('an error encountered while trying to append buffer');
});
sourceBuffer.appendBuffer(buf);
});
};
function fetchAB (url, cb) {
console.log(url);
var xhr = new XMLHttpRequest;
xhr.open('get', url);
xhr.responseType = 'arraybuffer';
xhr.onload = function () {
cb(xhr.response);
};
xhr.send();
};
</script>
</body>
</html>
So lets advance to next issue - the actual error. So, using chrome://media-internals/ we can see that the video actually fails to load do to incompatibility with the ISOBMFF format:
I am not familiar with Elastic Transcoder, but it seems that is it not producing an mp4 file suitable for live streaming. Also, if using mse, putting moov at the beginning is not enough, the video actually has to meet all of the ISOBMFF requirements - see chapters 3. and 4.
The working sample you mentioned is not a valid comparison since it uses the blob for the src, where the ISOBMFF rules do not apply. If it is fine for you to go that way, don't use MSE and put the blob directly in the src. If you need MSE, you have to mux it correctly.
Ok, so I got the original code example to work by encoding my MP4 videos with ffmpeg:
ffmpeg -i input.mp4 -vf scale=1920:1080,setsar=1:1 -c:v libx264 -preset medium -c:a aac -movflags empty_moov+default_base_moof+frag_keyframe output.mp4 -hide_banner
Important is: -movflags empty_moov+default_base_moof+frag_keyframe
This setup also scales the video to 1920x1080 (disregarding any aspect ratio of the input video)
However, based on the comments of the original post, I do believe there might be a more efficient way to generate the blob url and ingest into a video tag. This example was copied straight from https://developer.mozilla.org.
If anyone comes up with a better script (not over-engineered), please post it here.
Thank you #Rudolfs Bundulis for all your help!

Google Maps API Grey background

I have problem with Google Maps on my site.
Maps and code works locally but when i publish map it shows only gray background.
I have Joomla site.
Please could someone help me.
This is my code:
<head>
<script src='http://code.jquery.com/jquery.min.js' type='text/javascript'></script>
</head>
<body>
<script src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>
<script src="/maps/westcampus.js"></script>
<script>
var infowindow;
function initialize() {
var map = new google.maps.Map(document.getElementById('map_canvas'), {
center: new google.maps.LatLng(37.42362457157549, -122.0921247138165),
mapTypeId: google.maps.MapTypeId.ROADMAP,
zoom: 10
});
for (var x in westcampus) {
var building = westcampus[x];
var location = new google.maps.LatLng(building.lat,building.lng);
addMarker(map, building.name, location);
}
}
var bounds = new google.maps.LatLngBounds ();
function addMarker(map, name, location) {
var marker= new google.maps.Marker({
position: location,
map: map
});
bounds.extend (location);
google.maps.event.addListener(marker, 'click', function() {
if (typeof infowindow != 'undefined') infowindow.close();
infowindow = new google.maps.InfoWindow({
content: name
});
infowindow.open(map,marker);
});
map.fitBounds (bounds);
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
<div id="map_canvas" style="width: 100%; height: 400px;"></div>
</body>
</html>
and DB
var westcampus = [{'name':'Google West Campus 1','lat':37.423901,'lng':-122.091497,'ost': "Ostatak!"},
{'name':'Google West Campus 2','lat':37.424194,'lng':-122.092699,'ost': "Ostatak!"},
{'name':'Google West Campus 3','lat':37.423901,'lng':-122.092456,'ost': "Ostatak!"}];
thanks
There seems to be nothing wrong with the code you're using.
So the problem is with the server, and where it's requesting the map from.
Are you running SSL, and trying to request the JavaScript via HTTP ? Maybe remote to the server and see if you can run the page locally there. Investigate the network with chrome of fiddler. Might be returning 403 somewhere or something along those lines.
Or a load timing issue. Sometimes google maps need the resize event called once the map triggers the idle event. So it recalculates the bounds of the map tiles.
Can't really suggest anything else. Good luck.

Auto-Redirecting after BigVideo.js video ends

I'm having trouble auto-redirecting after my video has ended using BigVideo.js. Not sure what's wrong here. Not only does this not redirect it completely breaks the player and the video does not play.
<script type="text/javascript">
var BV;
$(function() {
// initialize BigVideo
BV = new $.BigVideo();
BV.init();
BV.show('vids/video.mp4');
BV.getPlayer().on("ended", function() {
window.location = "http://www.google.com";
})
});
</script>
I tested your code locally and the redirection worked without any problems.
I guess it depends on the browser type/version or other environment factor.
Try to properly unload the video element by:
BV.getPlayer().on("ended", function () {
this.pause();
delete(this);
window.location = "http://www.google.com";
});
reference:
How to properly unload/destroy a VIDEO element
hope that will do the trick :)

Push notifications using Node.js socket.io on apache web-server

I am trying to understand how this all push notifications works. I tried to do some test of push technology but so far i failed.
The base assumptions are:
1) use Apache web-server as the main application web-server (mandatory since all our code is using that)
2) Cross-Browser push notification server in node.js Technology (offered socket.io since it is crossed browser).
So far i failed and here is my code (p1.html):
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>P1</title>
</head>
<body>
<h1>P1</h1>
<section id="content"></section>
<script src="/socket.io.js"></script> <!--socket.io-->
<script src="/socket.js"></script> <!--socket.io-client-->
<script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
<script>
var socket = io.connect('http://localhost:8080');
socket.on('notification', function (data) {
$('#content').append(data.message + '<br>')
});
</script>
</body>
</html>
and my server script (p1.js):
var app = require('http').createServer(handler)
, io = require('socket.io').listen(app)
, url = require('url')
app.listen(8080);
console.log("creating a connection");
io.sockets.on( 'connection', function ( socket ) {
console.log("runing time");
sendTimeMessage(socket);
});
function sendTimeMessage(socket){
console.log("in time");
var time= new Date().getTime();
console.log(time);
socket.volatile.emit( 'notification' , time );
setTimeout(sendTimeMessage, 5000);
}
function handler (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end("");
}
function sendMessage(message) {
io.sockets.emit('notification', {'message': message});
}
i changed the IPs to local host for the example so i hope there is no mistake on the syntax.
when i run, the Apache web-server is the one that display the data and the idea is for the socket-io to update few fields.
current state:
1. If i don't add the socket.io-client js file i get reference error for socket.io-client
2. If i do add socket.io-client i get "ReferenceError: require is not defined
[Break On This Error] 'undefined' != typeof io ? io : module.exports
i can really need help understanding it, and making it work. i am also open minded to alternative solutions
i can really need help getting this done.
Working example, of what you want to achieve. First mistake is wrong javascript path on client-side, the right one is /socket.io/socket.io.js. Second mistake is use of socket.volatile which doesn't exist.
var app = require('http').createServer(handler)
, io = require('socket.io').listen(app)
, url = require('url')
console.log("creating a connection");
io.sockets.on( 'connection', function ( socket ) {
console.log("runing time");
sendTimeMessage(socket);
});
function sendTimeMessage(socket){
console.log("in time");
var now= new Date().getTime();
socket.emit('notification', {'message': now});
setTimeout(function() {
socket.emit('notification', {'message': "after 5s"});
},5000);
}
function handler (req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.end("<html><script src=\"/socket.io/socket.io.js\"></script> <!--socket.io--><script>io.connect().on('notification', function (data) {console.log(data)});</script></html>");
}
app.listen(8080);
Ok, i partially solved the with a huge help from the guys on IRC i created an:
1) HTML over Apache on port 80
2) live notification service update my HTML over port 8080
(there might still have code issue in the values arrived from the functions cause its not fully debuged)
p1.html (client)
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<section id="content"></section>
<script src="/node_modules/socket.io-client/dist/socket.io.js"></script>
<script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
<script>
var socket = io.connect('http://10.10.10.1:8080');
socket.on('notification', function (from,msg) {
$('#content').append(msg.message + '<br>')
});
</script>
</body>
</html>
p1.js (service)
var io = require('socket.io').listen(8080)
console.log("creating a connection");
io.sockets.on( 'connection', function ( socket ) {
console.log("runing time");
var oldtime= new Date().getTime();
while (1){
var newtime= new Date().getTime();
if (newtime%5323==0 && newtime != oldtime){
oldtime = newtime;
console.log(newtime);
socket.emit( 'notification' , {'message': "the time is - " + newtime} );
}
}
});
enjoy
Thanks #yanger
I was helped by your code.
I want to add a comment.
But I can't use comment yet.
In my case, I want to make a real time alarm.
and I use 80 port web server and 81 port alarm server.
So I just use this code. (Client.js)
var socket = io.connect(':81');
It's totally working.
I wish someone would read this article and get help.