native messaging host chrome-token-signing - json

I am trying to make an extension that will communicate with a native messaging host chrome-token-signing (https://github.com/open-eid/chrome-token-signing).
I have installed extension , but the EXE is not started. I have message log TEST: {"message":"Invalid argument","result":"invalid_argument"}
Do I need to do Something
I have installed the host in the registry like
HKEY_LOCAL_MACHINE\software\Google\Chrome\NativeMessagingHosts\ee.ria.esteid
and value C:\Users\dev\Desktop\chrome-token-signing\host-windows\ee.ria.esteid.json
The native application manifest.json:
{
"name": "ee.ria.esteid",
"description": "Give signatures with your eID on the web",
"path": "chrome-token-signing.exe",
"type": "stdio",
"allowed_origins": [
"chrome-extension://ckjefchnfjhjfedoccjbhjpbncimppeg/"
]
}
manifest.json of extension
{
"name": "Token signing",
"version": "0.0.24",
"minimum_chrome_version": "40.0",
"manifest_version": 2,
"description": "Use your eID smart card on the web",
"icons": {
"48": "icon48.png",
"128": "icon128.png"
},
"content_scripts": [{
"matches": ["*://*/*", "file:///*"],
"exclude_matches": ["*://www.overdrive.com/*"],
"js": ["content.js"],
"run_at": "document_end",
"all_frames": true
}],
"background": {
"scripts": ["background.js"]
},
"permissions": ["nativeMessaging"],
"applications": {
"gecko": {
"id": "{443830f0-1fff-4f9a-aa1e-444bafbc7319}"
}
}
}
background.js
var NO_NATIVE_URL = "https://open-eid.github.io/chrome-token-signing/missing.html";
var HELLO_URL = "https://open-eid.github.io/chrome-token-signing/hello.html";
var DEVELOPER_URL = "https://github.com/open-eid/chrome-token- signing/wiki/DeveloperTips";
var NATIVE_HOST = "ee.ria.esteid";
var K_SRC = "src";
var K_ORIGIN = "origin";
var K_NONCE = "nonce";
var K_RESULT = "result";
var K_TAB = "tab";
var K_EXTENSION = "extension";
// Stores the longrunning ports per tab
// Used to route all request from a tab to the same host instance
var ports = {};
// Probed to false if host component is OK.
var missing = true;
console.log("Background page activated");
// XXX: probe test, because connectNative() does not allow to check the presence
// of native component for some reason
typeof chrome.runtime.onStartup !== 'undefined' && chrome.runtime.onStartup.addListener(function() {
// Also probed for in onInstalled()
_testNativeComponent().then(function(result) {
if (result === "ok") {
missing = false;
}
});
});
// Force kill of native process
// Becasue Port.disconnect() does not work
function _killPort(tab) {
if (tab in ports) {
console.log("KILL " + tab);
// Force killing with an empty message
ports[tab].postMessage({});
}
}
// Check if native implementation is OK resolves with "ok", "missing" or "forbidden"
function _testNativeComponent() {
return new Promise(function(resolve, reject) {
chrome.runtime.sendNativeMessage(NATIVE_HOST, {}, function(response) {
if (!response) {
console.log("TEST: ERROR " + JSON.stringify(chrome.runtime.lastError));
// Try to be smart and do some string matching
var permissions = "Access to the specified native messaging host is forbidden.";
var missing = "Specified native messaging host not found.";
if (chrome.runtime.lastError.message === permissions) {
resolve("forbidden")
} else if (chrome.runtime.lastError.message === missing) {
resolve("missing");
} else {
resolve("missing");
}
} else {
console.log("TEST: " + JSON.stringify(response));
if (response["result"] === "invalid_argument") {
resolve("ok");
} else {
resolve("missing"); // TODO: something better here
}
}
});
});
}
// When extension is installed, check for native component or direct to helping page
typeof chrome.runtime.onInstalled !== 'undefined' && chrome.runtime.onInstalled.addListener(function(details) {
if (details.reason === "install" || details.reason === "update") {
_testNativeComponent().then(function(result) {
var url = null;
if (result === "ok" && details.reason === "install") {
// Also set the flag, onStartup() shall be called only
// on next startup
missing = false;
// TODO: Add back HELLO page on install
// once there is a nice tutorial
url = HELLO_URL;
} else if (result === "forbidden") {
url = DEVELOPER_URL;
} else if (result === "missing"){
url = NO_NATIVE_URL;
}
if (url) {
chrome.tabs.create({'url': url + "?" + details.reason});
}
});
}
});
// When message is received from page send it to native
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if(sender.id !== chrome.runtime.id && sender.extensionId !== chrome.runtime.id) {
console.log('WARNING: Ignoring message not from our extension');
// Not our extension, do nothing
return;
}
if (sender.tab) {
// Check if page is DONE and close the native component without doing anything else
if (request["type"] === "DONE") {
console.log("DONE " + sender.tab.id);
if (sender.tab.id in ports) {
// FIXME: would want to use Port.disconnect() here
_killPort(sender.tab.id);
}
} else {
request[K_TAB] = sender.tab.id;
if (missing) {
_testNativeComponent().then(function(result) {
if (result === "ok") {
missing = false;
_forward(request);
} else {
return _fail_with (request, "no_implementation");
}
});
} else {
// TODO: Check if the URL is in allowed list or not
// Either way forward to native currently
_forward(request);
}
}
}
});
// Send the message back to the originating tab
function _reply(tab, msg) {
msg[K_SRC] = "background.js";
msg[K_EXTENSION] = chrome.runtime.getManifest().version;
chrome.tabs.sendMessage(tab, msg);
}
// Fail an incoming message if the underlying implementation is not
// present
function _fail_with(msg, result) {
var resp = {};
resp[K_NONCE] = msg[K_NONCE];
resp[K_RESULT] = result;
_reply(msg[K_TAB], resp);
}
// Forward a message to the native component
function _forward(message) {
var tabid = message[K_TAB];
console.log("SEND " + tabid + ": " + JSON.stringify(message));
// Open a port if necessary
if(!ports[tabid]) {
// For some reason there does not seem to be a way to detect missing components from longrunning ports
// So we probe before opening a new port.
console.log("OPEN " + tabid + ": " + NATIVE_HOST);
// create a new port
var port = chrome.runtime.connectNative(NATIVE_HOST);
// XXX: does not indicate anything for some reason.
if (!port) {
console.log("OPEN ERROR: " + JSON.stringify(chrome.runtime.lastError));
}
port.onMessage.addListener(function(response) {
if (response) {
console.log("RECV "+tabid+": " + JSON.stringify(response));
_reply(tabid, response);
} else {
console.log("ERROR "+tabid+": " + JSON.stringify(chrome.runtime.lastError));
_fail_with(message, "technical_error");
}
});
port.onDisconnect.addListener(function() {
console.log("QUIT " + tabid);
delete ports[tabid];
// TODO: reject all pending promises for tab, if any
});
ports[tabid] = port;
ports[tabid].postMessage(message);
} else {
// Port already open
ports[tabid].postMessage(message);
}
}

The native app is started and it replies to you that the arguments you give it are invalid.
You need to check with native app documentation and see what arguments are valid for that particular app and use them in the messages you send it from the extension. Your request will look like:
chrome.runtime.sendNativeMessage(NATIVE_HOST, {text: "some_valid_argument"}, function(response){
........

Related

Alexa Skill: Playing Audio results in "Sorry don't know that"

I am coding my very first alexa skill and am very excited! I am trying to make a skill so that when I say "ramranch", alexa will play Sunil Syal. I started this skill using the space fact picker blueprint. I have deleted that code and put in my own. The aws is connected and is working, however when I say "ramranch" in the testing console, Alexa responds with "Sorry, I don't know that". Their is no debug or error message.
/* eslint-disable func-names */
/* eslint-disable no-console */
const Alexa = require('ask-sdk');
const RamRanch = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'LaunchRequest'
|| (request.type === 'IntentRequest'
&& request.intent.name === 'handle');
},
handle(handlerInput) {
this.emit(':tell', "Let's enjoy a world's most beautiful composition, composed by the great, Sunil Syal, <audio src='https://my-apis.000webhostapp.com/audio/Romantic%20Solitude-Instrumental%20(Flute).mp3'/> Wow, That is amazing. Click the link on top right corner to listen to full song.");
}
}
const HelpHandler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'IntentRequest'
&& request.intent.name === 'AMAZON.HelpIntent';
},
handle(handlerInput) {
return handlerInput.responseBuilder
.speak(HELP_MESSAGE)
.reprompt(HELP_REPROMPT)
.getResponse();
},
};
const ExitHandler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'IntentRequest'
&& (request.intent.name === 'AMAZON.CancelIntent'
|| request.intent.name === 'AMAZON.StopIntent');
There is a strong likelihood that when you modified the blueprint skill you may have deleted the node modules. Here is a slightly modified version of your index.js code. Begin a node project npm init. next npm install ask-sdk. your project folder will now have node_modules, package-lock.json, and package.json add this index.js file.
const Alexa = require('ask-sdk-core');
const LaunchRequestHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'LaunchRequest';
},
handle(handlerInput) {
const speechText = 'Welcome to the Alexa Skills Kit, you can say what about ramranch';
return handlerInput.responseBuilder
.speak(speechText)
.reprompt(speechText)
.withSimpleCard('Ramranch', speechText)
.getResponse();
}
};
const RamranchIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'ramranchIntent';
},
handle(handlerInput) {
const speechText = 'Lets enjoy a worlds most beautiful composition, composed by the great, Sunil Syal, <audio src="https://my-apis.000webhostapp.com/audio/Romantic%20Solitude-Instrumental%20(Flute).mp3"/> Wow, That is amazing. Click the link on top right corner to listen to full song.';
return handlerInput.responseBuilder
.speak(speechText)
.withSimpleCard('Ramranch', speechText)
.getResponse();
}
};
const HelpIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'AMAZON.HelpIntent';
},
handle(handlerInput) {
const speechText = 'You can say what about Ramranch!';
return handlerInput.responseBuilder
.speak(speechText)
.reprompt(speechText)
.withSimpleCard('Ramranch', speechText)
.getResponse();
}
};
const CancelAndStopIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& (handlerInput.requestEnvelope.request.intent.name === 'AMAZON.CancelIntent'
|| handlerInput.requestEnvelope.request.intent.name === 'AMAZON.StopIntent');
},
handle(handlerInput) {
const speechText = 'Goodbye!';
return handlerInput.responseBuilder
.speak(speechText)
.withSimpleCard('Ramranch', speechText)
.getResponse();
}
};
const SessionEndedRequestHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'SessionEndedRequest';
},
handle(handlerInput) {
//any cleanup logic goes here
return handlerInput.responseBuilder.getResponse();
}
};
const ErrorHandler = {
canHandle() {
return true;
},
handle(handlerInput, error) {
console.log(`Error handled: ${error.message}`);
return handlerInput.responseBuilder
.speak('Sorry, I can\'t understand the command. Please say again.')
.reprompt('Sorry, I can\'t understand the command. Please say again.')
.getResponse();
},
};
exports.handler = Alexa.SkillBuilders.custom()
.addRequestHandlers(
LaunchRequestHandler,
RamranchIntentHandler,
HelpIntentHandler,
CancelAndStopIntentHandler,
SessionEndedRequestHandler)
.addErrorHandlers(ErrorHandler)
.lambda();
Be sure to modify your Alexa skill developer model to include a ramranchIntent as I have not combined launch and primary intents as in your code. Lastly, zip this with the other previously mentioned files into your lambda function in AWS and add some intent phrases for triggering Ramranch, in my tests I used this skill JSON
{
"interactionModel": {
"languageModel": {
"invocationName": "ramranch player",
"intents": [
{
"name": "AMAZON.FallbackIntent",
"samples": []
},
{
"name": "AMAZON.CancelIntent",
"samples": []
},
{
"name": "AMAZON.HelpIntent",
"samples": []
},
{
"name": "AMAZON.StopIntent",
"samples": []
},
{
"name": "AMAZON.NavigateHomeIntent",
"samples": []
},
{
"name": "ramranchIntent",
"slots": [],
"samples": [
"what about ramranch",
"lets hear ramranch"
]
}
],
"types": []
}
}
}

Browser push notifications not responding after some time

I'm having a strange problem, and can't seem to find any solution for this. I subscribe users to my web push service and when they receive the notification I track when the notification displays, if its clicked or closed. But when i send notification with require interaction flag or persistent flags and leave it open around 1 min , it becomes disabled.
What I mean by disabled :
cant click on buttons
cant click on notification it self
only can click on X to close it
And then when the user closes notification or system closes it my service worker dose not register close event.
Also one of the problems i ran into on Firefox is that when users click on notification it only focuses on empty tab in Firefox.
Here is my service worker code :
self.addEventListener('push', function(event) {
console.log('[Service Worker] Push Received.');
data = event.data.json();
const title = data.title;
const options = data.options;
event.waitUntil(
self.registration.showNotification(title, options)
.then((notificationEvent)=>{
let payload = {
campaign_id: data.campaign_id,
subscriber_id:data.subscriber_id,
action:'display'
}
sendData(api_url+'touch',payload,'display');
})
);
});
self.addEventListener('notificationclick',function(event){
if(data.url){
console.log('Notification clicked !');
const clickedNotification = event.notification;
let promiseChain = null;
clickedNotification.close();
let payload = {
campaign_id: data.campaign_id,
subscriber_id:data.subscriber_id,
action:'click'
}
if(event.action === 'button1Link')
{
promiseChain = clients.openWindow(data.button1Link);
}else if(event.action === 'button2Link')
{
promiseChain = clients.openWindow(data.button2Link);
}else if(event.action === 'button3Link')
{
promiseChain = clients.openWindow(data.button3Link);
}else if(event.action === 'closeButton')
{
payload.action = 'close';
}else
{
promiseChain = clients.openWindow(data.url);
}
sendData(api_url+'touch',payload).then(()=>console.log('Stat
sent!'));
event.waitUntil(promiseChain);
}
})
self.addEventListener('notificationclose',function(event){
console.log('Notification closed !');
let payload = {
campaign_id: data.campaign_id,
subscriber_id:data.subscriber_id,
action:'close'
}
event.waitUntil(sendData(api_url+'touch',payload,'close'));
})
function sendData(url,payload)
{
let data = new FormData();
Object.keys(payload).map((field)=>{
data.append(field,payload[field]);
});
return fetch(api_url+'touch', {
method: 'POST',
body: data,
mode:'cors'
});
}
I could really use some advice and help, as I looked all over the web for reasons why is this happening and can't seem to find anything useful.
My payload structure looks like this :
array(7) {
["title"]=>
string(25) "Noise reducing headphones"
["url"]=>
string(76) "https://www.bestbuy.com/site/audio/headphones/abcat0204000.c?id=abcat0204000"
["campaign_id"]=>
string(2) "49"
["button1Link"]=>
string(120) "https://cdn.iconscout.com/public/images/icon/premium/png-512/headphones-phones-music-player-3b0242ebbd8df45e-512x512.png"
["button2Link"]=>
string(120) "https://cdn.iconscout.com/public/images/icon/premium/png-512/headphones-phones-music-player-3b0242ebbd8df45e-512x512.png"
["button3Link"]=>
string(120) "https://cdn.iconscout.com/public/images/icon/premium/png-512/headphones-phones-music-player-3b0242ebbd8df45e-512x512.png"
["options"]=>
array(7) {
["actions"]=>
array(3) {
[0]=>
array(2) {
["action"]=>
string(11) "button1Link"
["title"]=>
string(5) "Order"
}
[1]=>
array(2) {
["action"]=>
string(11) "button2Link"
["title"]=>
string(6) "Cancel"
}
[2]=>
array(2) {
["action"]=>
string(11) "button3Link"
["title"]=>
string(17) "Order on facebook"
}
}
["body"]=>
string(40) "Listen to your music without disturbance"
["image"]=>
string(56) "campaignimg1.jpg"
["icon"]=>
string(53) "image2.png"
["vibrate"]=>
array(1) {
[0]=>
string(0) ""
}
["silent"]=>
bool(false)
["requireInteraction"]=>
bool(false)
}
}
So I figured out what was going wrong with my service worker ...
First rebuilt my promises :
notificationclick listener now looks like this :
self.addEventListener('notificationclick',function(event){
const clickedNotification = event.notification;
if(clickedNotification.data.url){
let openWindowEvent = null;
clickedNotification.close();
let payload = {
campaign_id: clickedNotification.data.campaign_id,
subscriber_id:clickedNotification.data.subscriber_id,
action:'click'
}
if(event.action === 'button1Link')
{
openWindowEvent = clients.openWindow(clickedNotification.data.button1Link);
}else if(event.action === 'button2Link')
{
openWindowEvent = clients.openWindow(clickedNotification.data.button2Link);
}else if(event.action === 'button3Link')
{
openWindowEvent = clients.openWindow(clickedNotification.data.button3Link);
}else if(event.action === 'closeButton')
{
payload.action = 'close';
}else
{
openWindowEvent = clients.openWindow(clickedNotification.data.url);
}
payload = prepareData(payload);
const sendStat = fetch(api_url+'touch', {
method: 'POST',
body: payload,
mode:'cors'
});
const promiseChain = Promise.all([
openWindowEvent,
sendStat
]);
event.waitUntil(promiseChain);
}
})
Channing promises helped keep alive service worker long until all the tasks are done .
Also i rebuilt onclose event listener so now it looks like this :
self.addEventListener('notificationclose',function(event){
const closedNotification = event.notification;
console.log('Notification closed !');
let payload = {
campaign_id: closedNotification.data.campaign_id,
subscriber_id: closedNotification.data.subscriber_id,
action:'close'
}
payload = prepareData(payload);
const promiseChain = fetch(api_url+'touch', {
method: 'POST',
body: payload,
mode:'cors'
});
event.waitUntil(promiseChain);
})
And the main problem that disabled my notifications after some time was accessing data. I made a mistake trying to save data that I sent from server when the 'push' event triggered ... This was ok until browser decides to kill the service worker. Then you lose all the data stored in variables.
Solution:
Access data sent from server using variable 'event' passed in to all the event listeners :
self::addEventListener('notificationclick',function(event){});
From there you can access all the data sent with notification and use it as you want. This solved problem of not opening new tab with sent url and registering close event .

How to restrict Google Maps search results to only one country properly?

I am developing an application, in Ionic, where you can plan a trip with a start address and and end address. However I want to limit this feature to only one country. Before writing I have been searching for solutions on the internet, but none of them worked for me.
Have tried these suggestions:
https://stackoverflow.com/a/8282093/8130808
https://stackoverflow.com/a/10170421/8130808
Here is how I have tried to approach it:
//Places markers and displays a route, so the user can accept the current placing
newRoutePlaceMarks(place: any): void {
var googleDiplay = new google.maps.DirectionsRenderer({ draggable: true });
var route = this.directionsDisplay;
//A bit of a hack, sadly Typescript and google maps arent the best of buddies
this.directionsService.route({
origin: this.routeStart,
destination: this.routeEnd,
travelMode: 'DRIVING',
}, function (response, status) {
if (status === 'OK') {
console.log("status is OK trying to put directions up");
//The reason why I've set the addListener before the actual route is so it gets triggered
//on the creation of the route. Had some problem with figuring out how to actually handle
//the data when on the route creation, as this response function is in strict mode, and outside
google.maps.event.addListener(route, "directions_changed", function () {
console.log("Route changed");
this.global = ShareService.getInstance();
this.directions = route.getDirections();
this.metersToDist = this.directions.routes[0].legs[0].distance.value;
this.timeToDist = this.directions.routes[0].legs[0].duration.value;
this.startAddress = this.directions.routes[0].legs[0].start_address;
this.startCord = this.directions.routes[0].legs[0].start_location;
this.endAddress = this.directions.routes[0].legs[0].end_address;
this.endCord = this.directions.routes[0].legs[0].end_location;
this.global.setMetersToDist(this.metersToDist);
this.global.setTimeToDist(this.timeToDist);
this.global.setStartAddress(this.startAddress);
this.global.setStartCord(this.startCord);
this.global.setEndAddress(this.endAddress);
this.global.setEndCord(this.endCord);
var options = {
types: ['geocode'],
componentRestrictions: { country: "dk" }
};
google.maps.places.Autocomplete(this.startAddress, options);
});
//The actual initialiser for the route
route.setDirections(response);
} else {
alert('Could not display route ' + status);
}
});
}
My problem is that the input is HTTPELEMENT, I get the input from an alert dialog
newRouteInput() {
let alert = this.alertCtrl.create({
title: 'New route',
inputs: [
{
name: 'routeStart',
placeholder: 'Start of route'
},
{
name: 'routeEnd',
placeholder: 'End of route'
}
],
buttons: [
{
text: 'Cancel',
role: 'cancel',
handler: data => {
console.log('Cancel clicked');
}
},
{
text: 'Debug start and end',
handler: data => {
if (data.username !== "undefined") {
console.log(data.routeStart + " " + data.routeEnd);
this.routeStart = "Brøndby Strand";
this.routeEnd = "Hvidovre";
this.newRoutePlaceMarks(this.map);
this.routeButton = false;
} else {
return false;
}
}
},
{
text: 'Place route markers',
handler: data => {
if (data.username !== "undefined") {
this.routeStart = data.routeStart;
this.routeEnd = data.routeEnd;
this.newRoutePlaceMarks(this.map);
this.routeButton = false;
} else {
console.log(data.routeStart + " " + data.routeEnd);
return false;
}
}
}
]
});
alert.present();
}
When I run this I get an error because of this.startAddress. It's not null, it contains the start address:
InvalidValueError: not an instance of HTMLInputElement

Determine DRM system supported by browser

I've trying to find out how to determine which DRM system browser is using. And in fact, only chrome say it is use 'com.widevine.alpha' where IE & Safari (Win) throw error on 'requestMediaKeySystemAccess', and firefox do not even try to say it use 'com.adobe.acccess' =]
function isKeySystemSupported(keySystem) {
var dfd = Q.defer();
console.log('check: ', keySystem);
navigator.requestMediaKeySystemAccess(keySystem, [{contentType: 'video/webm; codecs="vp9"'}]).then(function() {
dfd.resolve(true);
}, function() { dfd.resolve(false); } );
return dfd.promise;
}
is there any solution, like Modernizr or similar to get which keySystem I should use?
There are several websites offering such a check, like dash-player.com/browser-capabilities/ After having a closer look at how it is done, one can use something similar to:
// EME Check
var keySystems = {
widevine: ['com.widevine.alpha'],
playready: ['com.microsoft.playready', 'com.youtube.playready'],
clearkey: ['webkit-org.w3.clearkey', 'org.w3.clearkey'],
primetime: ['com.adobe.primetime', 'com.adobe.access'],
fairplay: ['com.apple.fairplay']
};
var keySystemsCount = (function () {
var count = 0;
for (keysys in keySystems) {
if (keySystems.hasOwnProperty(keysys)) {
count += keySystems[keysys].length;
}
}
return count;
})();
var testVideoElement = document.createElement('video');
var supportedSystems = [];
var unsupportedSystems = [];
var supportsEncryptedMediaExtension = function () {
if (!testVideoElement.mediaKeys) {
if (window.navigator.requestMediaKeySystemAccess) {
if (typeof window.navigator.requestMediaKeySystemAccess === 'function') {
console.log('found default EME');
hasEME = true;
var isKeySystemSupported = function (keySystem) {
var config = [{initDataTypes: ['cenc']}];
if (window.navigator.requestMediaKeySystemAccess) {
window.navigator.requestMediaKeySystemAccess(keySystem, config).then(function (keySystemAccess) {
supportedSystems.push(keySystem);
}).catch(function () {
unsupportedSystems.push(keySystem);
});
}
};
var keysys, dummy, i;
for (keysys in keySystems) {
if (keySystems.hasOwnProperty(keysys)) {
for (dummy in keySystems[keysys]) {
isKeySystemSupported(keySystems[keysys][dummy]);
}
}
}
}
} else if (window.MSMediaKeys) {
if (typeof window.MSMediaKeys === 'function') {
console.log('found MS-EME');
hasEME = true;
var keysys, dummy, i;
for (keysys in keySystems) {
if (keySystems.hasOwnProperty(keysys)) {
for (dummy in keySystems[keysys]) {
if (MSMediaKeys.isTypeSupported(keySystems[keysys][dummy])) {
supportedSystems.push(keySystems[keysys][dummy]);
} else {
unsupportedSystems.push(keySystems[keysys][dummy]);
}
}
}
}
}
} else if (testVideoElement.webkitGenerateKeyRequest) {
if (typeof testVideoElement.webkitGenerateKeyRequest === 'function') {
console.log('found WebKit EME');
hasEME = true;
var keysys, dummy, i;
for (keysys in keySystems) {
if (keySystems.hasOwnProperty(keysys)) {
for (dummy in keySystems[keysys]) {
if (testVideoElement.canPlayType('video/mp4', keySystems[keysys][dummy])) {
supportedSystems.push(keySystems[keysys][dummy]);
} else {
unsupportedSystems.push(keySystems[keysys][dummy]);
}
}
}
}
}
} else {
console.log('no supported EME implementation found');
hasEME = false;
}
}
}
Simply run supportsEncryptedMediaExtension() and supportedSystems will be filled with the desired information.
Note that the config object should be extended to include the specific codec claims respective to your particular media. It isn't enough to just detect the key system as codec support sometimes depends on Guest OS dependencies.
var config = [{
"initDataTypes": ["cenc"],
"audioCapabilities": [{
"contentType": "audio/mp4;codecs=\"mp4a.40.2\""
}],
"videoCapabilities": [{
"contentType": "video/mp4;codecs=\"avc1.42E01E\""
}]
}];
In addition to the information listed here, I want to mention that in Chrome, whether you are using https or not will affect the availability of navigator.requestMediaKeySystemAccess function.
In your development environment that probably is running on http, navigator.requestMediaKeySystemAccess will return undefined for Chrome whereas the same code will return a function in Firefox.
In your prod environment that has https, navigator.requestMediaKeySystemAccess will return a function both in Chrome and Firefox.
I had to give videoCapabilities flags to make this work.
function testEME() {
// https://shaka-player-demo.appspot.com/support.html
var keySysConfig = [{
"initDataTypes": ["cenc"]
//,"persistentState": "required" // don't use or MacSafari "not supported"
//,"persistentState": "required", "distinctiveIdentifier": "required"
//,"audioCapabilities": [{
// "contentType": "audio/mp4;codecs=\"mp4a.40.2\""
//}]
,"videoCapabilities": [{
"contentType": "video/mp4;codecs=\"avc1.4D401E\"" // avc1.42E01E = ConstrainedLevel3, 4D401E=MainLevel3
//,"robustness": "3000"
}]
}];
var keySystems = {
playready: ['com.microsoft.playready.recommendation', 'com.microsoft.playready'
, 'com.microsoft.playready.hardware', 'com.youtube.playready'],
clearkey: ['webkit-org.w3.clearkey', 'org.w3.clearkey'],
widevine: ['com.widevine.alpha'],
primetime: ['com.adobe.primetime', 'com.adobe.access'],
fairplay: ['com.apple.fairplay','com.apple.fps'
, 'com.apple.fps.1_0', 'com.apple.fps.2_0', 'com.apple.fps.3_0']
};
for(keyArr in keySystems) {
for(forItemIdx in keySystems[keyArr]) {
let keySys = keySystems[keyArr][forItemIdx];
try {
navigator.requestMediaKeySystemAccess(keySys, keySysConfig).
then(function(mediaKeySystemAccess) {
//let mkConfig = mediaKeySystemAccess.getConfiguration();
//let sFlags = "persistentState="+mkConfig.persistentState
// + ", distinctiveIdentifier="+mkConfig.distinctiveIdentifier;
console.log(keySys + " supported"); //+" ("+sFlags+")");
}).catch(function(ex) {
console.log(keySys+" not supported (" + ex.name+" "+ex.message+")." );
});
} catch (ex) {
console.log(keySys+" not supported (" + ex.name+" "+ex.message+").." );
}
}
}
}

Django ajax unicode error

Hi I have a small javascript function which dynamically filters my form:
// set up a new XMLHttpRequest variable
var request = false;
try {
request = new XMLHttpRequest();
} catch (trymicrosoft) {
try {
request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (othermicrosoft) {
try {
request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (failed) {
request = false;
}
}
}
// if no request then throw up an alert window
if (!request)
alert("Error initializing XMLHttpRequest!");
// this function takes the island group value and sends it to the url as a get variable
function getIslandName(lang) {
var islandGroup = document.getElementById("id_island_group").value;
if (islandGroup == '') {
// if Not Specified re-selected then set data to null and bypass updatePage()
var data = null;
update_select($('select[name=island_name]'), data);
}
else {
var url = "../collections/find_island?island_group=" + escape(islandGroup);
// alert("Ready state is: " + request.readyState);
// alert("url: " + url);
request.open("GET", url, true);
request.onreadystatechange = updatePage;
request.send(null);
}
}
// what to do when http ready state changes
function updatePage() {
if (request.readyState == 4) {
if (request.status == 200) {
// get response array
var data = JSON.parse(request.responseText);
update_select($('select[name=island_name]'), data);
}
// some error checking
else if (request.status == 404) {
alert("Request url does not exist");
}
else {
alert("Error: status code is " + request.status);
}
}
}
function update_select(select, data) {
// find and remove existing options
select.find('option').remove();
var optionText = document.getElementById("lang").innerHTML
select.append($('<option value>' + optionText + '</option>'));
// loop through results and append to select as options
for (var k in data) {
select.append($('<option value="'+data[k]+'">'+data[k]+'</option>'));
}
}
And my forms:
class SearchForm(forms.Form):
...
island_group = forms.ModelChoiceField(
required=False,
label=ugettext_lazy('Island Group'),
initial=None,
queryset=Localityonline.objects.values_list('islandgroup', flat=True).distinct('islandgroup').exclude(islandgroup=None).order_by('islandgroup'),
empty_label=ugettext_lazy("Not Specified"),
widget=forms.Select(attrs={"class":'searchfield', "onChange":'getIslandName()'})
)
island_name = forms.ChoiceField(
required=False,
label=ugettext_lazy('Island Name'),
initial=None,
choices=DEFAULT_CHOICES,
#queryset = Localitymayor.objects.values_list('islandname', flat=True).distinct('islandname').exclude(islandname="n/a").order_by('islandname'),
#empty_label=ugettext_lazy("Not Specified"),
)
...
The problem is, if the value of islandGroup is something like 'Española' (i.e latin characters) I get a status 500 error and the following Django error:
OperationalError: (1267, "Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE) for operation '='")
<WSGIRequest
path:/datazone/collections/find_island/,
GET:<QueryDict: {u'island_group': [u'Espa\ufffd']}>,
POST:<QueryDict: {}>,
COOKIES:{'__utma': '173650102.812455619.1337018914.1337629222.1337641044.38',
'__utmb': '173650102.4.10.1337641044',
'__utmc': '173650102',
'__utmz': '173650102.1337613083.36.2.utmcsr=darwinfoundation.org|utmccn=(referral)|utmcmd=referral|utmcct=/datazone/galapagos-research/search/',
'csrftoken': '7cac07481c8ff5762fac33bf0b3590da',
'sessionid': '4becce44a950091a3cf7d306633427b4'},
META:{'CSRF_COOKIE': '7cac07481c8ff5762fac33bf0b3590da',
'DOCUMENT_ROOT': '/home/darwinfo/public_html',
'GATEWAY_INTERFACE': 'CGI/1.1',
'HTTP_ACCEPT': '*/*',
'HTTP_ACCEPT_CHARSET': 'ISO-8859-1,utf-8;q=0.7,*;q=0.3',
'HTTP_ACCEPT_ENCODING': 'gzip,deflate,sdch',
'HTTP_ACCEPT_LANGUAGE': 'en-US,en;q=0.8',
'HTTP_CONNECTION': 'close',
'HTTP_COOKIE': 'csrftoken=c297f86b353937f52abc36af8b4d595a; csrftoken=7cac07481c8ff5762fac33bf0b3590da; sessionid=4becce44a950091a3cf7d306633427b4; __utma=173650102.812455619.1337018914.1337629222.1337641044.38; __utmb=173650102.4.10.1337641044; __utmc=173650102; __utmz=173650102.1337613083.36.2.utmcsr=darwinfoundation.org|utmccn=
...
'HTTP_USER_AGENT': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.168 Safari/535.19',
'PATH': '/sbin:/usr/sbin:/bin:/usr/bin',
'PATH_INFO': u'/collections/find_island/',
'PATH_TRANSLATED': '/home/darwinfo/public_html/collections/find_island/',
'QUERY_STRING': 'island_group=Espa%F1ola',
'REDIRECT_QUERY_STRING': 'island_group=Espa%F1ola',
'REDIRECT_STATUS': '200',
'REDIRECT_UNIQUE_ID': 'T7rLMjIWL2YAAGS3N#sAAAET',
'REDIRECT_URL': '/datazone/collections/find_island/',
'REMOTE_ADDR': '157.100.37.112',
'REMOTE_PORT': '35245',
'REQUEST_METHOD': 'GET',
'REQUEST_URI': '/datazone/collections/find_island/?island_group=Espa%F1ola',
'SCRIPT_FILENAME': '/home/darwinfo/public_html/datazone/django.fcgi',
'SCRIPT_NAME': u'/datazone',
'SERVER_ADDR': '50.22.47.102',
'SERVER_PORT': '80',
'SERVER_PROTOCOL': 'HTTP/1.1',,
'SERVER_SOFTWARE': 'Apache',
'UNIQUE_ID': 'T7rLMjIWL2YAAGS3N#sAAAET',
'wsgi.errors': <flup.server.fcgi_base.OutputStream object at 0x1707ab90>,
'wsgi.input': <flup.server.fcgi_base.InputStream object at 0x16f2fad0>,
'wsgi.multiprocess': False,
'wsgi.multithread': True,
'wsgi.run_once': False,
'wsgi.url_scheme': 'http',
'wsgi.version': (1, 0)}>
Any help would be much appreciated.
Check the collation type of each table, and make sure that they have the same collation.
After that check also the collation type of each table field that you have use in operation.
I had encountered the same error, and that tricks works .