I am using qzprint API for printing labels in my open cart extension. Everything was working fine but suddenly it stopped working on FF. In Internet explorer it works fine. If i add alerts in my functions of applet it works fine on firefox as well but not sure why not with out alerts. here is my code.
calling applet functions in my header.tpl
<script type="text/javascript">
deployQZ('<?php echo HTTP_CATALOG ?>');
useDefaultPrinter();
<script>
Applet file containing functions
function deployQZ(path) {
//alert("alert for printing label");
pathApplet = path + 'java/qz-print.jar';
pathJnlp = path + 'java/qz-print_jnlp.jnlp';
var attributes = {id: "qz", code:'qz.PrintApplet.class',
archive: pathApplet, width:1, height:1};
var parameters = {jnlp_href: pathJnlp,
cache_option:'plugin', disable_logging:'false',
initial_focus:'false'};
if (deployJava.versionCheck("1.7+") == true) {}
else if (deployJava.versionCheck("1.6+") == true) {
attributes['archive'] = 'java/jre6/qz-print.jar';
parameters['jnlp_href'] = 'java/jre6/qz-print_jnlp.jnlp';
}
deployJava.runApplet(attributes, parameters, '1.5');
}
/**
* Automatically gets called when applet has loaded.
*/
function qzReady() {
// Setup our global qz object
window["qz"] = document.getElementById('qz');
//var title = document.getElementById("title");
if (qz) {
try {
//title.innerHTML = title.innerHTML + " " + qz.getVersion();
//document.getElementById("content").style.background = "#F0F0F0";
} catch(err) { // LiveConnect error, display a detailed meesage
document.getElementById("content").style.background = "#F5A9A9";
alert("ERROR: \nThe applet did not load correctly. Communication to the " +
"applet has failed, likely caused by Java Security Settings. \n\n" +
"CAUSE: \nJava 7 update 25 and higher block LiveConnect calls " +
"once Oracle has marked that version as outdated, which " +
"is likely the cause. \n\nSOLUTION: \n 1. Update Java to the latest " +
"Java version \n (or)\n 2. Lower the security " +
"settings from the Java Control Panel.");
}
}
}
/**
* Returns is the applet is not loaded properly
*/
function isLoaded() {
if (!qz) {
alert('Error:\n\n\tPrint plugin is NOT loaded!');
return false;
} else {
try {
if (!qz.isActive()) {
alert('Error:\n\n\tPrint plugin is loaded but NOT active!');
return false;
}
} catch (err) {
alert('Error:\n\n\tPrint plugin is NOT loaded properly!');
return false;
}
}
return true;
}
function useDefaultPrinter() {
//alert("alert for printing label");
if (isLoaded()) {
// Searches for default printer
qz.findPrinter();
// Automatically gets called when "qz.findPrinter()" is finished.
window['qzDoneFinding'] = function() {
// Alert the printer name to user
var printer = qz.getPrinter();
//alert(printer !== null ? 'Default printer found: "' + printer + '"':
//'Default printer ' + 'not found');
document.getElementById("name_printer").innerHTML = 'Default printer found: "' + printer + '"';
// Remove reference to this function
window['qzDoneFinding'] = null;
defaultFound = true;
};
}
}
As u can see in my deployqz() and usedefaultprinter() functions i have alert on first line which is in comments if its commented it doesn't work in fire fox and if not commented than it works fine. With comments i get alert message from isLoaded() function "Print plugin is NOT loaded properly!".
Also in my console i get this
An unbalanced tree was written using document.write() causing data from the network to be reparsed. For more information https://developer.mozilla.org/en/Optimizing_Your_Pages_for_Speculative_Parsing
Try this:
If the qzReady is called by the applet when ready, put useDefaultPrinter inside that function.
if isLoaded takes some time, call useDefaultPrinter in there too using setTimeout
Like this
<script type="text/javascript">
deployQZ('<?php echo HTTP_CATALOG ?>');
<script>
Applet file containing functions
var qz;
function deployQZ(path) {
pathApplet = path + 'java/qz-print.jar';
pathJnlp = path + 'java/qz-print_jnlp.jnlp';
var attributes = {id: "qz", code:'qz.PrintApplet.class',
archive: pathApplet, width:1, height:1};
var parameters = {jnlp_href: pathJnlp,
cache_option:'plugin', disable_logging:'false',
initial_focus:'false'};
if (deployJava.versionCheck("1.7+") == true) {}
else if (deployJava.versionCheck("1.6+") == true) {
attributes['archive'] = 'java/jre6/qz-print.jar';
parameters['jnlp_href'] = 'java/jre6/qz-print_jnlp.jnlp';
}
deployJava.runApplet(attributes, parameters, '1.5');
}
/**
* Automatically gets called when applet has loaded.
*/
function qzReady() {
// Setup our global qz object
qz = document.getElementById('qz');
if (qz) {
try {
useDefaultPrinter();
} catch(err) { // LiveConnect error, display a detailed meesage
document.getElementById("content").style.background = "#F5A9A9";
alert("ERROR: \nThe applet did not load correctly. Communication to the " +
"applet has failed, likely caused by Java Security Settings. \n\n" +
"CAUSE: \nJava 7 update 25 and higher block LiveConnect calls " +
"once Oracle has marked that version as outdated, which " +
"is likely the cause. \n\nSOLUTION: \n 1. Update Java to the latest " +
"Java version \n (or)\n 2. Lower the security " +
"settings from the Java Control Panel.");
}
}
else { setTimeout(useDefaultPrinter,300); }
}
/**
* Returns is the applet is not loaded properly
*/
function isLoaded() {
if (!qz) {
alert('Error:\n\n\tPrint plugin is NOT loaded!');
return false;
} else {
try {
if (!qz.isActive()) {
alert('Error:\n\n\tPrint plugin is loaded but NOT active!');
return false;
}
} catch (err) {
alert('Error:\n\n\tPrint plugin is NOT loaded properly!');
return false;
}
}
return true;
}
function useDefaultPrinter() {
//alert("alert for printing label");
if (isLoaded()) {
// Searches for default printer
qz.findPrinter();
// Automatically gets called when "qz.findPrinter()" is finished.
window['qzDoneFinding'] = function() {
// Alert the printer name to user
var printer = qz.getPrinter();
//alert(printer !== null ? 'Default printer found: "' + printer + '"':
//'Default printer ' + 'not found');
document.getElementById("name_printer").innerHTML = 'Default printer found: "' + printer + '"';
// Remove reference to this function
window['qzDoneFinding'] = null;
defaultFound = true;
};
}
else { setTimeout(useDefaultPrinter,300); }
}
Related
Background
I am building a local area network, WebRTC baby monitor with a raspberry pi camera module and USB microphone. The stream is synthesized with GStreamer and im using Janus Gateway to facilitate the WebRTC connection between a web browser and the Pi. The webpage and Javascript is a stripped down version of the streaming demo provided by Meetecho.
This is my first time using many of these technologies and am a bit in over my head with troubleshooting at the moment. I'm having trouble figuring out why the web page works in Chrome and Safari, but does not work in Firefox.
It works fine on Chrome and Safari:
In Firefox, the WebRTC connection seems to be successfully established and maintained (based on comparisons of the network traffic and console output between Chrome and Firefox), but the page seems to get caught up somewhere along the way:
Comparing the consoles
When comparing the console outputs of Chrome and Firefox, they are identical until this point where both consoles report Uncaught (in promise) DOMException: but for possibly different reasons?
Firefox says Uncaught (in promise) DOMException: The fetching process for the media resource was aborted by the user agent at the user's request.
Chrome says Uncaught (in promise) DOMException: The play() request was interrupted by a new load request.
Are these the same errors with different "Hints"? Or are they actually different errors due to some underlying difference between the browsers?
Immediately after this error, Firefox diverges from Chrome by reporting Remote track removed.
Im unsure if I am doing something silly in the JS to cause this or if there is some nuance about Firefox that I am missing.
Other details that might be helpful?
Below is part of the html (index.html) and javascript (janus_stream.js) for the page, the pastebin link contains the whole janus_stream.js.
// We make use of this 'server' variable to provide the address of the
// REST Janus API. By default, in this example we assume that Janus is
// co-located with the web server hosting the HTML pages but listening
// on a different port (8088, the default for HTTP in Janus), which is
// why we make use of the 'window.location.hostname' base address. Since
// Janus can also do HTTPS, and considering we don't really want to make
// use of HTTP for Janus if your demos are served on HTTPS, we also rely
// on the 'window.location.protocol' prefix to build the variable, in
// particular to also change the port used to contact Janus (8088 for
// HTTP and 8089 for HTTPS, if enabled).
// In case you place Janus behind an Apache frontend (as we did on the
// online demos at http://janus.conf.meetecho.com) you can just use a
// relative path for the variable, e.g.:
//
// var server = "/janus";
//
// which will take care of this on its own.
//
//
// If you want to use the WebSockets frontend to Janus, instead, you'll
// have to pass a different kind of address, e.g.:
//
// var server = "ws://" + window.location.hostname + ":8188";
//
// Of course this assumes that support for WebSockets has been built in
// when compiling the server. WebSockets support has not been tested
// as much as the REST API, so handle with care!
//
//
// If you have multiple options available, and want to let the library
// autodetect the best way to contact your server (or pool of servers),
// you can also pass an array of servers, e.g., to provide alternative
// means of access (e.g., try WebSockets first and, if that fails, fall
// back to plain HTTP) or just have failover servers:
//
// var server = [
// "ws://" + window.location.hostname + ":8188",
// "/janus"
// ];
//
// This will tell the library to try connecting to each of the servers
// in the presented order. The first working server will be used for
// the whole session.
//
var server = null;
if(window.location.protocol === 'http:')
server = "http://" + window.location.hostname + ":8088/janus";
else
server = "https://" + window.location.hostname + ":8089/janus";
var janus = null;
var streaming = null;
var opaqueId = "streamingtest-"+Janus.randomString(12);
var bitrateTimer = null;
var spinner = true;
var simulcastStarted = false, svcStarted = false;
var selectedStream = null;
$(document).ready(function() {
// Initialize the library (all console debuggers enabled)
Janus.init({debug: "all", callback: function() {
// Use a button to start the demo
//$('#start').one('click', function() {
//$(this).attr('disabled', true).unbind('click');
// Make sure the browser supports WebRTC
if(!Janus.isWebrtcSupported()) {
bootbox.alert("No WebRTC support... ");
return;
}
// Create session
janus = new Janus(
{
server: server,
success: function() {
// Attach to Streaming plugin
janus.attach(
{
plugin: "janus.plugin.streaming",
opaqueId: opaqueId,
success: function(pluginHandle) {
$('#details').remove();
streaming = pluginHandle;
Janus.log("Plugin attached! (" + streaming.getPlugin() + ", id=" + streaming.getId() + ")");
// Setup streaming session
$('#update-streams').click(updateStreamsList);
updateStreamsList();
$('#start').removeAttr('disabled').html("Stop")
.click(function() {
$(this).attr('disabled', true);
clearInterval(bitrateTimer);
janus.destroy();
$('#streamslist').attr('disabled', true);
$('#watch').attr('disabled', true).unbind('click');
$('#start').attr('disabled', true).html("Bye").unbind('click');
});
},
error: function(error) {
Janus.error(" -- Error attaching plugin... ", error);
bootbox.alert("Error attaching plugin... " + error);
},
iceState: function(state) {
Janus.log("ICE state changed to " + state);
},
webrtcState: function(on) {
Janus.log("Janus says our WebRTC PeerConnection is " + (on ? "up" : "down") + " now");
},
onmessage: function(msg, jsep) {
Janus.debug(" ::: Got a message :::", msg);
var result = msg["result"];
if(result) {
if(result["status"]) {
var status = result["status"];
if(status === 'starting')
$('#status').removeClass('hide').text("Starting, please wait...").show();
else if(status === 'started')
$('#status').removeClass('hide').text("Started").show();
else if(status === 'stopped')
stopStream();
} else if(msg["streaming"] === "event") {
// Is simulcast in place?
var substream = result["substream"];
var temporal = result["temporal"];
if((substream !== null && substream !== undefined) || (temporal !== null && temporal !== undefined)) {
if(!simulcastStarted) {
simulcastStarted = true;
addSimulcastButtons(temporal !== null && temporal !== undefined);
}
// We just received notice that there's been a switch, update the buttons
updateSimulcastButtons(substream, temporal);
}
// Is VP9/SVC in place?
var spatial = result["spatial_layer"];
temporal = result["temporal_layer"];
if((spatial !== null && spatial !== undefined) || (temporal !== null && temporal !== undefined)) {
if(!svcStarted) {
svcStarted = true;
addSvcButtons();
}
// We just received notice that there's been a switch, update the buttons
updateSvcButtons(spatial, temporal);
}
}
} else if(msg["error"]) {
bootbox.alert(msg["error"]);
stopStream();
return;
}
if(jsep) {
Janus.debug("Handling SDP as well...", jsep);
var stereo = (jsep.sdp.indexOf("stereo=1") !== -1);
// Offer from the plugin, let's answer
streaming.createAnswer(
{
jsep: jsep,
// We want recvonly audio/video and, if negotiated, datachannels
media: { audioSend: false, videoSend: false, data: true },
customizeSdp: function(jsep) {
if(stereo && jsep.sdp.indexOf("stereo=1") == -1) {
// Make sure that our offer contains stereo too
jsep.sdp = jsep.sdp.replace("useinbandfec=1", "useinbandfec=1;stereo=1");
}
},
success: function(jsep) {
Janus.debug("Got SDP!", jsep);
var body = { request: "start" };
streaming.send({ message: body, jsep: jsep });
$('#watch').html("Stop").removeAttr('disabled').click(stopStream);
},
error: function(error) {
Janus.error("WebRTC error:", error);
bootbox.alert("WebRTC error... " + error.message);
}
});
}
},
onremotestream: function(stream) {
Janus.debug(" ::: Got a remote stream :::", stream);
var addButtons = false;
if($('#remotevideo').length === 1) {
addButtons = true;
//$('#stream').append('<video class="rounded centered hide" id="remotevideo" width="100%" height="100%" playsinline/>');
$('#remotevideo').get(0).volume = 0;
// Show the stream and hide the spinner when we get a playing event
$("#remotevideo").bind("playing", function () {
$('#waitingvideo').remove();
if(this.videoWidth)
$('#remotevideo').removeClass('hide').show();
if(spinner)
spinner.stop();
spinner = null;
var videoTracks = stream.getVideoTracks();
if(!videoTracks || videoTracks.length === 0)
return;
var width = this.videoWidth;
var height = this.videoHeight;
$('#curres').removeClass('hide').text(width+'x'+height).show();
if(Janus.webRTCAdapter.browserDetails.browser === "firefox") {
// Firefox Stable has a bug: width and height are not immediately available after a playing
setTimeout(function() {
var width = $("#remotevideo").get(0).videoWidth;
var height = $("#remotevideo").get(0).videoHeight;
$('#curres').removeClass('hide').text(width+'x'+height).show();
}, 2000);
}
});
}
Janus.attachMediaStream($('#remotevideo').get(0), stream);
$("#remotevideo").get(0).play();
$("#remotevideo").get(0).volume = 1;
var videoTracks = stream.getVideoTracks();
if(!videoTracks || videoTracks.length === 0) {
// No remote video
$('#remotevideo').hide();
if($('#stream .no-video-container').length === 0) {
$('#stream').append(
'<div class="no-video-container">' +
'<i class="fa fa-video-camera fa-5 no-video-icon"></i>' +
'<span class="no-video-text">No remote video available</span>' +
'</div>');
}
} else {
$('#stream .no-video-container').remove();
$('#remotevideo').removeClass('hide').show();
}
if(!addButtons)
return;
if(videoTracks && videoTracks.length &&
(Janus.webRTCAdapter.browserDetails.browser === "chrome" ||
Janus.webRTCAdapter.browserDetails.browser === "firefox" ||
Janus.webRTCAdapter.browserDetails.browser === "safari")) {
$('#curbitrate').removeClass('hide').show();
bitrateTimer = setInterval(function() {
// Display updated bitrate, if supported
var bitrate = streaming.getBitrate();
$('#curbitrate').text(bitrate);
// Check if the resolution changed too
var width = $("#remotevideo").get(0).videoWidth;
var height = $("#remotevideo").get(0).videoHeight;
if(width > 0 && height > 0)
$('#curres').removeClass('hide').text(width+'x'+height).show();
}, 1000);
}
},
ondataopen: function(data) {
Janus.log("The DataChannel is available!");
$('#waitingvideo').remove();
$('#stream').append(
'<input class="form-control" type="text" id="datarecv" disabled></input>'
);
if(spinner)
spinner.stop();
spinner = null;
},
ondata: function(data) {
Janus.debug("We got data from the DataChannel!", data);
$('#datarecv').val(data);
},
oncleanup: function() {
Janus.log(" ::: Got a cleanup notification :::");
$('#waitingvideo').remove();
$('#remotevideo').remove();
$('#datarecv').remove();
$('.no-video-container').remove();
$('#bitrate').attr('disabled', true);
$('#bitrateset').html('Bandwidth<span class="caret"></span>');
$('#curbitrate').hide();
if(bitrateTimer)
clearInterval(bitrateTimer);
bitrateTimer = null;
$('#curres').hide();
$('#simulcast').remove();
$('#metadata').empty();
$('#info').addClass('hide').hide();
simulcastStarted = false;
}
});
},
error: function(error) {
Janus.error(error);
bootbox.alert(error, function() {
window.location.reload();
});
},
destroyed: function() {
window.location.reload();
}
});
//});
}});
});
function updateStreamsList() {
$('#update-streams').unbind('click').addClass('fa-spin');
var body = { request: "list" };
Janus.debug("Sending message:", body);
streaming.send({ message: body, success: function(result) {
setTimeout(function() {
$('#update-streams').removeClass('fa-spin').click(updateStreamsList);
}, 500);
if(!result) {
bootbox.alert("Got no response to our query for available streams");
return;
}
if(result["list"]) {
$('#streams').removeClass('hide').show();
$('#streamslist').empty();
$('#watch').attr('disabled', true).unbind('click');
var list = result["list"];
Janus.log("Got a list of available streams");
if(list && Array.isArray(list)) {
list.sort(function(a, b) {
if(!a || a.id < (b ? b.id : 0))
return -1;
if(!b || b.id < (a ? a.id : 0))
return 1;
return 0;
});
}
Janus.debug(list);
for(var mp in list) {
Janus.debug(" >> [" + list[mp]["id"] + "] " + list[mp]["description"] + " (" + list[mp]["type"] + ")");
$('#streamslist').append("<li><a href='#' id='" + list[mp]["id"] + "'>" + list[mp]["description"] + " (" + list[mp]["type"] + ")" + "</a></li>");
}
$('#streamslist a').unbind('click').click(function() {
selectedStream = $(this).attr("id");
$('#streamset').html($(this).html()).parent().removeClass('open');
return false;
});
$('#watch').removeAttr('disabled').unbind('click').click(startStream);
}
}});
}
function getStreamInfo() {
$('#metadata').empty();
$('#info').addClass('hide').hide();
if(!selectedStream)
return;
// Send a request for more info on the mountpoint we subscribed to
var body = { request: "info", id: parseInt(selectedStream) || selectedStream };
streaming.send({ message: body, success: function(result) {
if(result && result.info && result.info.metadata) {
$('#metadata').html(result.info.metadata);
$('#info').removeClass('hide').show();
}
}});
}
function startStream() {
selectedStream = "1"
Janus.log("Selected video id #" + selectedStream);
if(!selectedStream) {
bootbox.alert("Select a stream from the list");
return;
}
$('#streamset').attr('disabled', true);
$('#streamslist').attr('disabled', true);
$('#watch').attr('disabled', true).unbind('click');
var body = { request: "watch", id: parseInt(selectedStream) || selectedStream};
streaming.send({ message: body });
// No remote video yet
$('#stream').append('<video class="rounded centered" id="waitingvideo" width="100%" height="100%" />');
if(spinner == null) {
var target = document.getElementById('stream');
spinner = new Spinner({top:100}).spin(target);
} else {
spinner.spin();
}
// Get some more info for the mountpoint to display, if any
getStreamInfo();
}
function stopStream() {
$('#watch').attr('disabled', true).unbind('click');
var body = { request: "stop" };
streaming.send({ message: body });
streaming.hangup();
$('#streamset').removeAttr('disabled');
$('#streamslist').removeAttr('disabled');
$('#watch').html("Watch or Listen").removeAttr('disabled').unbind('click').click(startStream);
$('#status').empty().hide();
$('#bitrate').attr('disabled', true);
$('#bitrateset').html('Bandwidth<span class="caret"></span>');
$('#curbitrate').hide();
if(bitrateTimer)
clearInterval(bitrateTimer);
bitrateTimer = null;
$('#curres').empty().hide();
$('#simulcast').remove();
simulcastStarted = false;
}
.......
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>BabyPi Cam</title>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/7.4.0/adapter.min.js" ></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js" ></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/bootbox.js/5.4.0/bootbox.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/spin.js/2.3.2/spin.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.1.4/toastr.min.js"></script>
<script type="text/javascript" src="janus.js" ></script>
<script type="text/javascript" src="janus_stream.js"></script>
<script>
$(function() {
$(".navbar-static-top").load("navbar.html", function() {
$(".navbar-static-top li.dropdown").addClass("active");
$(".navbar-static-top a[href='streamingtest.html']").parent().addClass("active");
});
$(".footer").load("footer.html");
});
</script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootswatch/3.4.0/cerulean/bootstrap.min.css" type="text/css"/>
<link rel="stylesheet" href="css/demo.css" type="text/css"/>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" type="text/css"/>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.1.4/toastr.min.css"/>
</head>
<body>
<div class="container">
<div class="col-md-12">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">BabyPi Live Stream
<span class="label label-info" id="status"></span>
<span class="label label-primary" id="curres"></span>
<span class="label label-info" id="curbitrate" styple="display:inline;"></span>
</h3>
</div>
<div class="panel-body" id="stream">
<video class="rounded centered" id="remotevideo" width="100%" height="100%" playsinline controls muted></video>
</div>
</div>
</div>
</div>
</body>
</html>
I am also using the janus.js API provided Meetecho
The Questions
What am I doing wrong that prevents this from working in Firefox?
What can the diverging console outputs tell me about what I am doing wrong?
Do you have any suggestions on where to look / what to try to get this working in Firefox?
Any pointers or ideas are greatly appreciated! Please let me know if I can provide other information.
Thank you!
Update: Theory / Possible answer?
In an attempt to address the Uncaught (in promise) DOMException: The fetching process for the media resource was aborted by the user agent at the user's request. error, I changed video.play() to video.load(). This addressed the error, but the same Remote track removed and "No remote video" behavior persists.
In the meantime I may have discovered the more fundamental issue: The video stream from the Pi is H264, and from what I can tell, Firefox does not support this format? Perhaps this is the reason that I am having issues with firefox?
Can any of you confirm or deny this as the true issue?
The issue is related to H264 incompatibility, but after seeing this thread I realized i was a victim of the same issue.
I needed to update one line in my janus.plugin.streaming.jcfg file so that it looks like this:
RPI3: {
type = "rtp"
id = 1
description = "Raspberry Pi 3 Infrared Camera Module stream"
video = true
videoport = 5001
videopt = 96
videortpmap = "H264/90000"
videofmtp = "profile-level-id=42e01f;packetization-mode=1"
audio = true
audioport = 5002
audiopt = 111
audiortpmap = "opus/48000/2"
}
Previously I was using this "incomplete" line which was causing the issue:
...
videofmtp = "packetization-mode=1"
...
Apparently this enables the correct H264 "profile" that can work with Firefox's OpenH264 plugin. Now i am able to view the stream with both chrome and firefox!
I have written code for a small Chrome Extension that scrapes content based on selectors. Once I have the content I need, I push it to my PHP server in order to store it in a database. The code works well except when content is loaded dynamically, I can only see what is visible the source code from the browser.
I thought I could solve the issue by waiting until the page was fully loaded (setInterval) but even when I see that the content is loaded, the source code I'm getting is still the initial one.
I use the following code to create a tab and retrieve the source code:
function CreateTab (createProperties)
{
chrome.tabs.create(createProperties, tab =>
{
if (chrome.runtime.lastError)
{
console.log(chrome.runtime.lastError);
}
else
{
container = "h2";
var i = 0;
var checkClass = setInterval (function()
{
if (i<=3)
{
console.log('Iteration :'+i);
chrome.tabs.executeScript(tab.id,
{
file: 'GetSource.js',
}, async function(results)
{
let e = chrome.runtime.lastError;
if(e !== undefined)
{
console.log(tab.id, e);
}
// GETTING HTML
parser = new DOMParser();
content = parser.parseFromString(results, "text/html");
console.log(content);
// CAPTURE TITLES
try
{
datatable = content.querySelectorAll(container);
}
catch(err)
{
console.log('Iteration '+i+' table not found');
datatable = "";
}
if (datatable.length>0)
{
clearInterval(checkClass);
removeTab(tab.id,3)
// DATA FOUND!
i=10;
}
});
i++;
}
else
{
clearInterval(checkClass);
console.log('Container not found');
removeTab(tab.id,5)
}
},10000);
}
});
}
The script I'm calling to get the source is the following (GetSource.js)
function DOMtoString(document_root) {
var html = '',
node = document_root.firstChild;
while (node) {
switch (node.nodeType) {
case Node.ELEMENT_NODE:
html += node.outerHTML;
break;
case Node.TEXT_NODE:
html += node.nodeValue;
break;
case Node.CDATA_SECTION_NODE:
html += '<![CDATA[' + node.nodeValue + ']]>';
break;
case Node.COMMENT_NODE:
html += '<!--' + node.nodeValue + '-->';
break;
case Node.DOCUMENT_TYPE_NODE:
// (X)HTML documents are identified by public identifiers
html += "<!DOCTYPE " + node.name + (node.publicId ? ' PUBLIC "' + node.publicId + '"' : '') + (!node.publicId && node.systemId ? ' SYSTEM' : '') + (node.systemId ? ' "' + node.systemId + '"' : '') + '>\n';
break;
}
node = node.nextSibling;
}
return html;
}
sourcecode = DOMtoString (document);
sourcecode
How can I make sure that the GetSource.js script is getting the final rendered source code? There are more and more sites using dynamic content loaded after the initial load and with this script I'm stuck on those sites.
There are ready to use scrapers in the Chrome store that can get dynamic content so there must be a solution for my script too. I don't want to use to solutions as I need to retrieve the selectors I want to catch from my server and once the scraping is done pushing them back to the server.
Do you have any idea of how I could achieve this?
Thanks
i am developing an application and loading an hosted application using the inapp browser plugin cordova-plugin-inappbrowser
I have gotten most of the functionalities to work but i am unable to get the part of loading an error message when he url does not load, it dosent just work and shows me an error message of the url where i have hosted my application instead.
Which could be embarrassing.
please i need help on this
This is what am working with below thanks for ur potential responses
// my child browser code, the main source of my app content
function fire(){
var ref = cordova.InAppBrowser.open('http://####################', '_blank', 'location=no,zoom=no,hardwareback=yes,clearsessioncache=yes,clearcache=no');
var myCallback = function(event) { alert(event.url); }
ref.addEventListener('loadstart', inAppBrowserbLoadStart);
ref.addEventListener('loadstop', inAppBrowserbLoadStop);
ref.addEventListener('loaderror', loadErrorCallBack);
ref.addEventListener('exit', inAppBrowserbClose);
}
function loadErrorCallBack(params) {
$('#status-message').text("");
var scriptErrorMesssage =
"alert('Sorry we cannot open that page. Message from the server is : "
+ params.message + "');"
inAppBrowserRef.executeScript({ code: scriptErrorMesssage }, executeScriptCallBack);
inAppBrowserRef.close();
inAppBrowserRef = undefined;
}
function executeScriptCallBack(params) {
if (params[0] == null) {
$('#status-message').text(
"Sorry we couldn't open that page. Message from the server is : '"
+ params.message + "'");
}
}
Your code is generally fine, but you have no control over the title of the alert() function. You can use some other techniques to display the error message. For example, you can use a div:
function loadErrorCallBack(params) {
$('#status-message').text("");
var scriptErrorMesssage = createMsg('Sorry we cannot open that page. Message from the server is: '
+ params.message);
inAppBrowserRef.executeScript({
code: scriptErrorMesssage
}, executeScriptCallBack);
inAppBrowserRef.close();
inAppBrowserRef = undefined;
}
function createMsg(msg) {
return 'var div = document.createElement("div");'
+ 'div.style.position = "absolute";'
+ 'div.style.top = "50%";'
+ 'div.style.left = "50%";'
+ 'div.style.width = "100px";'
+ 'div.style.height = "100px";'
+ 'div.style.color = "#f00";'
+ 'div.innerHTML = "' + msg + '";'
+ 'document.appendChild(div);'
}
I developed a web application and deployed into the server and my security team come up with the below security remidiation issue.
Reflected HTML Parameter Pollution (HPP) is an injection weakness vulnerability that occurs when an attacker can inject a delimiter and change the parameters of a URL generated by an application. The consequences of the attack depend upon the functionality of the application, but may include accessing and potentially exploiting uncontrollable variables, conducting other attacks such as Cross-Site Request Forgery, or altering application behavior in an unintended manner. Recommendations include using strict validation inputs to ensure that the encoded parameter delimiter “%26” is handled properly by the server, and using URL encoding whenever user-supplied content is contained within links or other forms of output generated by the application.
Can any one have the idea about how to prevent HTML parameter pollution in asp.net
here is the script code in the webpage
<script type="text/javascript" language="javascript">
document.onclick = doNavigationCheck ;
var srNumberFinal="";
function OpenDetailsWindow(srNumber)
{
window.open("xxx.aspx?SRNumber="+srNumber+ "","","minimize=no,maximize=no,scrollbars=yes,status=no,toolbar=no,menubar=no,location=no,width=800,directories=no,resizable=yes,titlebar=no");
}
function OpenPrintWindow()
{
var querystrActivityId = "<%=Request.QueryString["activityId"]%>";
if(querystrActivityId != "")
{
var url = "abc.aspx?id=" + "<%=Request.QueryString["id"]%>" + "&activityId=" + querystrActivityId + "";
}
else
{
var hdrActivityId = document.getElementById('<%=uxHdnHdrActivityId.ClientID%>').value;
var url = "PrintServiceRequestDetail.aspx?id=" + "<%=Request.QueryString["id"]%>" + "&activityId=" + hdrActivityId + "";
}
childWinReference=window.open(url, "ChildWin","minimize=yes,maximize=yes,scrollbars=yes,status=yes,toolbar=no,menubar=yes,location=no,directories=no,resizable=yes,copyhistory=no");
childWinReference.focus();
}
function NavigateSRCopy(srNumber)
{
srNumberFinal = srNumber;
if (srNumber != "undefined" && srNumber != null && srNumber != "")
{
new Ajax.Request('<%= (Request.ApplicationPath != "/") ? Request.ApplicationPath : string.Empty %>/xxx/AutoCompleteService.asmx/CheckFormID'
, { method: 'post', postBody: 'srNumber=' + srNumber, onComplete: SearchResponse });
}
}
function SearchResponse(xmlResponse)
{
var xmlDoc;
try //Internet Explorer
{
xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async="false";
xmlDoc.loadXML(xmlResponse.responseText);
}
catch(e)
{
try // Firefox, Mozilla, Opera, etc.
{
parser=new DOMParser();
xmlDoc=parser.parseFromString(xmlResponse.responseText,"text/xml");
}
catch(e)
{
alert(e.message);
return;
}
}
if(xmlDoc.getElementsByTagName("string")[0].childNodes[0] != null)
{
formID = xmlDoc.getElementsByTagName("string")[0].childNodes[0].nodeValue;
}
else
{
formID = null;
}
if(formID != null && formID != "")
{
window.location.href = '/CustomerSupportRequest/CreateServiceRequest.aspx?id=' + formID + '&TemplateSR=' + srNumberFinal + '&Frompage=CopySR';
return true;
}
else
{
alert("This Service Request cannot be copied because it meets at least one of these conditions: \t\t\n\n * It was created prior to 10/15/2008 \n * It was auto generated as part of the Report Requeue Process \n * It was auto generated as part of the ERA Requeue Process \n * It was not created online");
}
}
function UpdateChildCases()
{
var modalPopup = $find('modalParentChildComments');
modalPopup.show();
}
function HideParentChildPopup()
{
var modalPopup = $find('modalParentChildComments');
modalPopup.hide();
return false;
}
function HideErrorSRNumsPopup()
{
var modalPopup = $find('modalParentErrorSRNumDisplay');
modalPopup.hide();
return false;
}
function HideRetrySRNumsPopup()
{
var modalPopup = $find('modalRetrySRNumDisplay');
modalPopup.hide();
return false;
}
function RemoveParent_ChildFlag(type)
{
var childCases = document.getElementById("<%=uxHdnChildCases.ClientID %>");
var msg = "";
var btn;
if(type == "Child")
{
if(childCases.value.indexOf(',') != -1)
msg = "Are you sure you want to remove the Child flag from this Service Request?";
else
msg = "This is the only child associated to the parent case. Removing the child flag will also remove the parent flag from the associated case. Choose OK to remove the flags, or Cancel to close this dialog";
btn = document.getElementById('<%=uxRemoveChildFlag.ClientID%>');
}
else
{
msg = "Removing the parent flag from this case will also remove the child flag from all associated cases. Are you sure you want to remove the Parent flag from this Service Request?";
btn = document.getElementById('<%=uxRemoveParentFlag.ClientID%>');
}
if(btn)
{
if(!confirm(msg))
{
return false;
}
else
{
btn.click();
}
}
}
function limitTextForParentChildComments()
{
var objLblCharCount = document.getElementById('uxLblPCCharCount');
var objTxtComments = document.getElementById('<%=txtParentComment.ClientID%>');
if (objTxtComments.value.length > 1500)
{
objTxtComments.value = objTxtComments.value.substring(0, 1500);
}
else
{
objLblCharCount.innerHTML = 1500 - objTxtComments.value.length + " ";
}
setTimeout("limitTextForParentChildComments()",50);
}
function ValidateInputs()
{
var lblErrorMessage = document.getElementById('<%=lblCommentErrorTxt.ClientID%>');
var objTxtComments = document.getElementById('<%=txtParentComment.ClientID%>');
if(objTxtComments.value.trim() == "")
{
lblErrorMessage.style.display = "block";
return false;
}
}
</script>
As per OWASP Testing for HTTP Parameter pollution, ASP.NET is not vulnerable to HPP because ASP.NET will return all occurrences of a query string value concatenated with a comma (e.g. color=red&color=blue gives color=red,blue).
See here for an example explanation.
That said, your code appears to be vulnerable to XSS instead:
var querystrActivityId = "<%=Request.QueryString["activityId"]%>";
If the query string parameter activityId="; alert('xss');" (URL encoded of course), then an alert box will trigger on your application because this code will be generated in your script tag.
var querystrActivityId = ""; alert('xss');"";
window.onerror = function(type, file, line){
if(type) {
console.log(type);
}
if(file) {
console.log(file);
}
if(line) {
console.log(line);
}
}
this code returns "Script error" when there is an error at some of the .js files. I need the type, file and line of the error. How can I get it?
When window throws error this script works perfect but it is not the same when there is error in the .js file.
I know that these things I can find on the console but imagine that I don't have one and i cannot install.
window.onerror = ErrorLog;
function ErrorLog (msg, url, line) {
console.log("error: " + msg + "\n" + "file: " + url + "\n" + "line: " + line);
return true; // avoid to display an error message in the browser
}
The post of Cryptic "Script Error." reported in Javascript in Chrome and Firefox should answer your "Script Error." problem. Namely it is probably caused by "Same origin policy".
Though I am still looking for why webkit will give me "undefined" file name and "0" line number for uncaught exception.
Here's what I use to capture errors. I have it request an image whose url points to a server side script.
function logJSErrors(errObj) {
if (!errObj || !errObj.lineNumber || errObj.lineNumber == 0) {
return; // can't use it any way.
}
if (window.location && window.location.toString().indexOf('rfhelper32.js') >= 0) {
return; // ignore the stupid Norton/Firefox conflict
}
var img = new Image();
img.src = "/jserror?m=" + encodeURIComponent(errObj.message) +
"&location=" + encodeURIComponent(window.location) +
"&ln=" + encodeURIComponent(errObj.lineNumber) +
"&url=" + encodeURIComponent(errObj.fileName) +
"&browser=" + encodeURIComponent(errObj.browserInfo);
}
window.onerror = function (msg, url, line) {
logJSErrors({ message : msg,
lineNumber : line,
fileName : url,
browserInfo : window.navigator.userAgent
});
// if a jquery ajax call was running, be sure to make the spinning icons go away
if (jQuery) {
try {
jQuery.event.trigger("ajaxStop");
} catch(e) {/* do nothing */
}
}
};