I am trying to use Agora.io. Everything was working as it should. Until I add switching between cameras. I'm trying to switch between cameras thanks to the code below. But the problem is that I get this error: Uncaught TypeError: Cannot read properties of undefined (reading 'deviceId')
The error line is in the changeStreamSource() :
deviceId = devices.cameras[deviceIndex].deviceId;
Can you guide me on this?
function changeStreamSource (deviceIndex, deviceType) {
console.log('Switching stream sources for: ' + deviceType);
var deviceId;
var existingStream = false;
if (deviceType === "video") {
deviceId = devices.cameras[deviceIndex].deviceId;
}
localStreams.camera.stream.switchDevice(deviceType, deviceId, function(){
console.log('successfully switched to new device with id: ' + JSON.stringify(deviceId));
// set the active device ids
if(deviceType === "audio") {
localStreams.camera.micId = deviceId;
} else if (deviceType === "video") {
localStreams.camera.camId = deviceId;
} else {
console.log("unable to determine deviceType: " + deviceType);
}
}, function(){
console.log('failed to switch to new device with id: ' + JSON.stringify(deviceId));
});
}
devices isn't defined in your code. You can get a list of devices using AgoraRTC.getDevices method.
I have a program that will work to start a motion sensor when running the file from the command line, but when I try to call the function from HTML, it recognizes the prototype as 'undefined' and will not execute.
Here is the full code:
var sleep = require('sleep');
var Gpio = require('onoff').Gpio;
var LED = new Gpio(18, 'out');
var sensor = new Gpio(17, 'in', 'both');
sensor.watch(function(err, value){
if (err){
console.log('error');
exit();
}
if(value == 1) {
console.log('Motion Detected');
LED.writeSync(value);
sleep.sleep(3);
}
else if(value == 0) {
console.log('No Motion');
LED.writeSync(value);
sleep.sleep(3);
}
});
function exit() {
LED.unexport();
sensor.unexport();
process.exit();
}
dev tools says 'sensor' is undefined.
How do I run sensor.watch(callback) from html?
Thanks!
I'm trying to setup plupload so that if a file upload fails according to a certain error code, plupload will try to upload it again. Without success.
What I currently have
Here is my piece of code for now :
var attempts = 0; // number of attempts
function init(uploader) {
uploader.bind('Error', function(up, file) {
var code = JSON.parse(file.response).error.code;
console.log(code); //logs the error code
if(code === 503 && attempts > 3) {
up.stop();
file.status = plupload.FAILED;
file.retry = false;
// do stuff...
up.state = plupload.STARTED;
up.trigger("StateChanged");
attempts = 0;
}
else {
console.log("attempt : "+ attempts);
up.stop();
file.status = plupload.QUEUED;
attempts++;
file.retry = true;
up.state = plupload.STARTED;
up.trigger("StateChanged");
up.trigger("QueueChanged"); // ERROR HERE
}
})
}
Where I indicated the "ERROR HERE", my console shows me this :
TypeError: n.getSource is not a function
What am I doing wrong ?
Thanks a lot !
Why don't you add the file again on the queue?
http://www.plupload.com/docs/Uploader#addFile-filefileName-method
addFile(file, [fileName])
From PhantomJS, how do I write to a log instead of to the console?
In the examples https://github.com/ariya/phantomjs/wiki/Examples, it always (in the ones I have looked at) says something like:
console.log('some stuff I wrote');
This is not so useful.
The following can write contents to the file directly by phantomjs:
var fs = require('fs');
try {
fs.write("/home/username/sampleFileName.txt", "Message to be written to the file", 'w');
} catch(e) {
console.log(e);
}
phantom.exit();
The command in the answer by user984003 fails when there is some warning or exceptions occurred. And sometimes does not fall into our specific requirements because in some codebase I am getting the following message always which will also be logged to that file.
Refused to display document because display forbidden by X-Frame-Options.
So I figured it out:
>phantomjs.exe file_to_run.js > my_log.txt
You can override original console.log function, take a look at this :
Object.defineProperty(console, "toFile", {
get : function() {
return console.__file__;
},
set : function(val) {
if (!console.__file__ && val) {
console.__log__ = console.log;
console.log = function() {
var fs = require('fs');
var msg = '';
for (var i = 0; i < arguments.length; i++) {
msg += ((i === 0) ? '' : ' ') + arguments[i];
}
if (msg) {
fs.write(console.__file__, msg + '\r\n', 'a');
}
};
}
else if (console.__file__ && !val) {
console.log = console.__log__;
}
console.__file__ = val;
}
});
Then you can do this:
console.log('this will go to console');
console.toFile = 'test.txt';
console.log('this will go to the test.txt file');
console.toFile = '';
console.log('this will again go to the console');
I'm trying to develop a Firefox extension/add-on that needs access to the SSL Certificate information of the page that is currently loaded. Once I have this information I plan on modifying the contents of the page based on the SSL information. Though, before I get there I first need to get the SSL info.
The approach outlined here makes a separate XMLHTTPRequest to get the security certificate. I would rather not do that if I could avoid it because it presents a security problem.
For example, a malicious site/man-in-the-middle could provide one certificate on the first request for the page (which the browser would verify) and then provide another certificate for the XMLHTTPRequest that my extension would make. This would result in the extension modifying site contents based on inconsistent information. Hence, I'd like to get the SSL Cert information that the browser itself used when verifying the site.
With that in mind I combined the above approach with the method outlined in Altering HTTP Responses in Firefox Extension to intercept all the HTTP responses by adding an observer of the "http-on-examine-response" event. I thought that with this method I could simply grab the cert info as it was being downloaded from the site.
Here is the meat of my code, much of it taken from the above links (the rest is Firefox extension boilerplate):
function dumpSecurityInfo(channel) {
const Cc = Components.classes
const Ci = Components.interfaces;
// Do we have a valid channel argument?
if (! channel instanceof Ci.nsIChannel) {
dump("No channel available\n");
return;
}
var secInfo = channel.securityInfo;
// Print general connection security state
if (secInfo instanceof Ci.nsITransportSecurityInfo) {
dump("name: " + channel.name + "\n");
secInfo.QueryInterface(Ci.nsITransportSecurityInfo);
dump("\tSecurity state: ");
// Check security state flags
if ((secInfo.securityState & Ci.nsIWebProgressListener.STATE_IS_SECURE) == Ci.nsIWebProgressListener.STATE_IS_SECURE)
dump("secure\n");
else if ((secInfo.securityState & Ci.nsIWebProgressListener.STATE_IS_INSECURE) == Ci.nsIWebProgressListener.STATE_IS_INSECURE)
dump("insecure\n");
else if ((secInfo.securityState & Ci.nsIWebProgressListener.STATE_IS_BROKEN) == Ci.nsIWebProgressListener.STATE_IS_BROKEN)
dump("unknown\n");
dump("\tSecurity description: " + secInfo.shortSecurityDescription + "\n");
dump("\tSecurity error message: " + secInfo.errorMessage + "\n");
}
// Print SSL certificate details
if (secInfo instanceof Ci.nsISSLStatusProvider) {
var cert = secInfo.QueryInterface(Ci.nsISSLStatusProvider).
SSLStatus.QueryInterface(Ci.nsISSLStatus).serverCert;
dump("\nCertificate Status:\n");
var verificationResult = cert.verifyForUsage(Ci.nsIX509Cert.CERT_USAGE_SSLServer);
dump("\tVerification: ");
switch (verificationResult) {
case Ci.nsIX509Cert.VERIFIED_OK:
dump("OK");
break;
case Ci.nsIX509Cert.NOT_VERIFIED_UNKNOWN:
dump("not verfied/unknown");
break;
case Ci.nsIX509Cert.CERT_REVOKED:
dump("revoked");
break;
case Ci.nsIX509Cert.CERT_EXPIRED:
dump("expired");
break;
case Ci.nsIX509Cert.CERT_NOT_TRUSTED:
dump("not trusted");
break;
case Ci.nsIX509Cert.ISSUER_NOT_TRUSTED:
dump("issuer not trusted");
break;
case Ci.nsIX509Cert.ISSUER_UNKNOWN:
dump("issuer unknown");
break;
case Ci.nsIX509Cert.INVALID_CA:
dump("invalid CA");
break;
default:
dump("unexpected failure");
break;
}
dump("\n");
dump("\tCommon name (CN) = " + cert.commonName + "\n");
dump("\tOrganisation = " + cert.organization + "\n");
dump("\tIssuer = " + cert.issuerOrganization + "\n");
dump("\tSHA1 fingerprint = " + cert.sha1Fingerprint + "\n");
var validity = cert.validity.QueryInterface(Ci.nsIX509CertValidity);
dump("\tValid from " + validity.notBeforeGMT + "\n");
dump("\tValid until " + validity.notAfterGMT + "\n");
}
}
function TracingListener() {
}
TracingListener.prototype =
{
originalListener: null,
onDataAvailable: function(request, context, inputStream, offset, count) {
try
{
dumpSecurityInfo(request)
this.originalListener.onDataAvailable(request, context, inputStream, offset, count);
} catch (err) {
dump(err);
if (err instanceof Ci.nsIException)
{
request.cancel(e.result);
}
}
},
onStartRequest: function(request, context) {
try
{
dumpSecurityInfo(request)
this.originalListener.onStartRequest(request, context);
} catch (err) {
dump(err);
if (err instanceof Ci.nsIException)
{
request.cancel(e.result);
}
}
},
onStopRequest: function(request, context, statusCode) {
this.originalListener.onStopRequest(request, context, statusCode);
},
QueryInterface: function (aIID) {
const Ci = Components.interfaces;
if ( iid.equals(Ci.nsIObserver) ||
iid.equals(Ci.nsISupportsWeakReference) ||
iid.equals(Ci.nsISupports))
{
return this;
}
throw Components.results.NS_NOINTERFACE;
}
}
var httpRequestObserver =
{
observe: function(aSubject, aTopic, aData)
{
const Ci = Components.interfaces;
if (aTopic == "http-on-examine-response")
{
var newListener = new TracingListener();
aSubject.QueryInterface(Ci.nsITraceableChannel);
newListener.originalListener = aSubject.setNewListener(newListener);
}
},
QueryInterface : function (aIID)
{
const Ci = Components.interfaces;
if (aIID.equals(Ci.nsIObserver) ||
aIID.equals(Ci.nsISupports))
{
return this;
}
throw Components.results.NS_NOINTERFACE;
}
};
var test =
{
run: function() {
const Ci = Components.interfaces;
dump("run");
var observerService = Components.classes["#mozilla.org/observer-service;1"]
.getService(Ci.nsIObserverService);
observerService.addObserver(httpRequestObserver,
"http-on-examine-response", false);
}
};
window.addEventListener("load", function () { test.run(); }, false);
What I found is that this implementation is inconsistent. When I load gmail.com in Firefox I'll sometimes get the certificate information and sometimes I won't. I suspect this is a caching issue as refreshing the page will usually result in the certificate information being downloaded/printed.
For my intended application this behavior is not acceptable. This is for a research project so, if I have to, I would be willing to modify the Firefox source code, but my preference would be to do this using the extension/add-on API.
Is there a better, more consistent way to get the SSL Certificate information?
Building on this answer:
The trick is to register a progress listener and check aState when the onSecurityChange function is called. If the Ci.nsIWebProgressListener.STATE_IS_SECURE flag is set then the page is using an SSL connection. That isn't enough however, the aRequest parameter may not be an instance of Ci.nsIChannel, that should be verified first with if (aRequest instanceof Ci.nsIChannel).
Here is the working code:
function dumpSecurityInfo(channel) {
const Cc = Components.classes
const Ci = Components.interfaces;
// Do we have a valid channel argument?
if (! channel instanceof Ci.nsIChannel) {
dump("No channel available\n");
return;
}
var secInfo = channel.securityInfo;
// Print general connection security state
if (secInfo instanceof Ci.nsITransportSecurityInfo) {
dump("name: " + channel.name + "\n");
secInfo.QueryInterface(Ci.nsITransportSecurityInfo);
dump("\tSecurity state: ");
// Check security state flags
if ((secInfo.securityState & Ci.nsIWebProgressListener.STATE_IS_SECURE) == Ci.nsIWebProgressListener.STATE_IS_SECURE)
dump("secure\n");
else if ((secInfo.securityState & Ci.nsIWebProgressListener.STATE_IS_INSECURE) == Ci.nsIWebProgressListener.STATE_IS_INSECURE)
dump("insecure\n");
else if ((secInfo.securityState & Ci.nsIWebProgressListener.STATE_IS_BROKEN) == Ci.nsIWebProgressListener.STATE_IS_BROKEN)
dump("unknown\n");
dump("\tSecurity description: " + secInfo.shortSecurityDescription + "\n");
dump("\tSecurity error message: " + secInfo.errorMessage + "\n");
}
else {
dump("\tNo security info available for this channel\n");
}
// Print SSL certificate details
if (secInfo instanceof Ci.nsISSLStatusProvider) {
var cert = secInfo.QueryInterface(Ci.nsISSLStatusProvider).
SSLStatus.QueryInterface(Ci.nsISSLStatus).serverCert;
dump("\nCertificate Status:\n");
var verificationResult = cert.verifyForUsage(Ci.nsIX509Cert.CERT_USAGE_SSLServer);
dump("\tVerification: ");
switch (verificationResult) {
case Ci.nsIX509Cert.VERIFIED_OK:
dump("OK");
break;
case Ci.nsIX509Cert.NOT_VERIFIED_UNKNOWN:
dump("not verfied/unknown");
break;
case Ci.nsIX509Cert.CERT_REVOKED:
dump("revoked");
break;
case Ci.nsIX509Cert.CERT_EXPIRED:
dump("expired");
break;
case Ci.nsIX509Cert.CERT_NOT_TRUSTED:
dump("not trusted");
break;
case Ci.nsIX509Cert.ISSUER_NOT_TRUSTED:
dump("issuer not trusted");
break;
case Ci.nsIX509Cert.ISSUER_UNKNOWN:
dump("issuer unknown");
break;
case Ci.nsIX509Cert.INVALID_CA:
dump("invalid CA");
break;
default:
dump("unexpected failure");
break;
}
dump("\n");
dump("\tCommon name (CN) = " + cert.commonName + "\n");
dump("\tOrganisation = " + cert.organization + "\n");
dump("\tIssuer = " + cert.issuerOrganization + "\n");
dump("\tSHA1 fingerprint = " + cert.sha1Fingerprint + "\n");
var validity = cert.validity.QueryInterface(Ci.nsIX509CertValidity);
dump("\tValid from " + validity.notBeforeGMT + "\n");
dump("\tValid until " + validity.notAfterGMT + "\n");
}
}
var myListener =
{
QueryInterface: function(aIID)
{
if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
aIID.equals(Components.interfaces.nsISupports))
return this;
throw Components.results.NS_NOINTERFACE;
},
onStateChange: function(aWebProgress, aRequest, aFlag, aStatus) { },
onLocationChange: function(aProgress, aRequest, aURI) { },
onProgressChange: function(aWebProgress, aRequest, curSelf, maxSelf, curTot, maxTot) { },
onStatusChange: function(aWebProgress, aRequest, aStatus, aMessage) { },
onSecurityChange: function(aWebProgress, aRequest, aState)
{
// check if the state is secure or not
if(aState & Ci.nsIWebProgressListener.STATE_IS_SECURE)
{
// this is a secure page, check if aRequest is a channel,
// since only channels have security information
if (aRequest instanceof Ci.nsIChannel)
{
dumpSecurityInfo(aRequest);
}
}
}
}
var test =
{
run: function() {
dump("run\n");
gBrowser.addProgressListener(myListener);
}
};
window.addEventListener("load", function () { test.run(); }, false);
The way you query the channel to get its security info seems sane. I suspect that your problem is actually timing - you query it at the wrong time. Tracing all requests is really the wrong approach if security info is all you are interested in. It makes far more sense to register a progress listener (there are examples) and to look at the channel whenever onSecurityChange is being called. You are likely to be only interested in requests where aState contains STATE_IS_SECURE flag. Note that aRequest parameter is usually an nsIChannel instance but could also be a plain nsIRequest - instanceof check is required.