Why my extension sends duplicates on request in geometric progression? - firefox

I've created extension that makes some JSON request & send it to some receiver.
My problem is:
Open popup window
After it closing, extensions sends 1 request
Open it on the same page again, and extension will send 2 requests
Open again, 4 requests
Open again, 8 requests
In each uses of popup, extension will be duplicate outgoing data in geometric progression.
Why that happens?
From the panel I'm send addnewurl to the port:
AddDialog.port.on("addnewurl", function (data) {
{
AddDialog is my popup
here It handle port messages aftre popup is closed(hidded)
}
var http = require("sdk/request").Request;
var req = CreateRequest("add_url", {});
req.params = {...};
var sreq = encodeURIComponent(JSON.stringify(req));
count += 1; //Global counter, u will see it in video
console.log('count = '+count);
var cfg = {
url : getRequestURL(),
contentType : "text/html",
content : sreq,
onComplete : function (response) {
var data = {
code : response.status,
body : response.json
};
AddDialog.port.emit("addnewurldone", data);
}
};
http(cfg).post();
});
For more sense I've created a AVI video record of that. See it here:
https://dl.dropboxusercontent.com/u/86175609/Project002.avi
1.6 MB
How to resolve that?
ADDED by request more info
That function emit addnewurl:
function AddNewURL() {
var node = $("#Tree").dynatree("getActiveNode");
if (node == null) {
$("#ServerStatus").text(LocalizedStr.Status_NoGroupSelected);
$("#ServerStatus").css("color", "red");
return;
};
var nkey = node.data.key;
var aImg = null;
var data = {
ownerId : nkey,
name : $("#LinkTitle").val(),
description : $("#LinkDesc").val(),
url : $("#CurrentURL").val(),
scrcapt:$("#ScrCaptureCB :selected").val()
};
$("#load").css("display", "inline");
$("#ServerStatus").text(LocalizedStr.Status_AddURL);
self.port.emit("addnewurl", data);
};
and it calls by button:
self.port.on("showme", function onShow(data) {
....
document.querySelector('#BtnOk').addEventListener('click', function () {
AddNewURL();
});
...
});
"swomme" goes from here(main.js):
AddDialog.on("show", function () {
count = 0;
AddDialog.port.emit("showme", locTbl);
});
function addToolbarButton() {
var enumerator = mediator.getEnumerator("navigator:browser");
while (enumerator.hasMoreElements()) {
var document = enumerator.getNext().document;
var navBar = document.getElementById('nav-bar');
if (!navBar) {
return;
}
var btn = document.createElement('toolbarbutton');
btn.setAttribute('id', cBtnId);
btn.setAttribute('type', 'button');
btn.setAttribute('class', 'FLAToolButton');
btn.setAttribute('image', data.url('icons/Add.png'));
btn.setAttribute('orient', 'horizontal');
btn.setAttribute('label', loc("Main_ContextMenu"));
btn.addEventListener('click', function () {
AddDialog.show();
}, false)
navBar.appendChild(btn);
}
}

I think the problem is here
document.querySelector('#BtnOk').addEventListener('click', function () {
AddNewURL();
});
If you are running AddDialog.port.emit("showme", locTbl); when you click your toolbar button then you're adding a click listener to #BtnOk every time as well.
On the first toolbar click it will have one click listener, on the second click two, and so on. You should remove the above code from that function and only run it once.

Related

Unable to download file with CasperJS

I am trying to download a file with CasperJS. If using browser, the download begins when user clicks a button and the response headers look like this:
I have tried these two methods with no luck:
1) https://stackoverflow.com/a/26334034
With this approach, the code block inside the if-statement is never executed. If I remove the condition, a bunch of resources are being saved, such as css files and so on. So the event listener is working, but for some reason not triggering when I use CasperJs click function to click the button that should start the download.
2) https://stackoverflow.com/a/30122021/692695
File.csv is saved but it's the web sites sourcecode, not the csv-file I get when I click the button on the website.
All of my code:
'use strict';
var utils = require('utils');
var casper = require('casper').create({
//verbose: true,
//logLevel: "debug",
clientScripts: ["node_modules/jquery/dist/jquery.min.js"]
});
function writeHtml(filename) {
var fs = require('fs');
var content = casper.getHTML();
fs.write(filename, content, 'w');
}
function getUrl() {
var url;
url = $('.tableofcontent_link:contains("Väestö työmarkkina-aseman, sukupuolen ja iän mukaan")').parent().attr('href');
return url;
}
casper.selectOptionByValue = function(selector, valueToMatch){
this.evaluate(function(selector, valueToMatch){
var select = document.querySelector(selector),
found = false;
Array.prototype.forEach.call(select.children, function(opt, i){
if (!found && opt.value.indexOf(valueToMatch) !== -1) {
select.selectedIndex = i;
found = true;
}
});
// dispatch change event in case there is some kind of validation
var evt = document.createEvent("UIEvents"); // or "HTMLEvents"
evt.initUIEvent("change", true, true);
select.dispatchEvent(evt);
}, selector, valueToMatch);
};
var link;
var url = 'http://pxnet2.stat.fi/PXWeb/pxweb/fi/StatFin/StatFin__tym__tyti/?table';
casper.start(url);
casper.userAgent('Mozilla/5.0 (Macintosh; Intel Mac OS X)');
casper.then(function () {
this.echo("Now at: " + this.getCurrentUrl());
link = 'http://pxnet2.stat.fi' + casper.evaluate(getUrl);
});
casper.then(function () {
this.open(link);
});
casper.then(function() {
this.echo("Now at: " + this.getCurrentUrl());
// Select all data for each item
casper.click('#ctl00_ContentPlaceHolderMain_VariableSelector1_VariableSelector1_VariableSelectorValueSelectRepeater_ctl01_VariableValueSelect_VariableValueSelect_SelectAllButton');
casper.click('#ctl00_ContentPlaceHolderMain_VariableSelector1_VariableSelector1_VariableSelectorValueSelectRepeater_ctl02_VariableValueSelect_VariableValueSelect_SelectAllButton');
casper.click('#ctl00_ContentPlaceHolderMain_VariableSelector1_VariableSelector1_VariableSelectorValueSelectRepeater_ctl03_VariableValueSelect_VariableValueSelect_SelectAllButton');
casper.click('#ctl00_ContentPlaceHolderMain_VariableSelector1_VariableSelector1_VariableSelectorValueSelectRepeater_ctl04_VariableValueSelect_VariableValueSelect_SelectAllButton');
casper.click('#ctl00_ContentPlaceHolderMain_VariableSelector1_VariableSelector1_VariableSelectorValueSelectRepeater_ctl05_VariableValueSelect_VariableValueSelect_SelectAllButton');
});
casper.then(function() {
// casper.selectOptionByValue('#ctl00_ContentPlaceHolderMain_VariableSelector1_VariableSelector1_OutputFormats_OutputFormats_OutputFormatDropDownList',
// 'FileTypeExcelX');
// Select the format of the file from the select option list at the bottom
casper.selectOptionByValue('#ctl00_ContentPlaceHolderMain_VariableSelector1_VariableSelector1_OutputFormats_OutputFormats_OutputFormatDropDownList',
'FileTypeCsvWithHeadingAndSemiColon');
});
casper.then(function () {
// just for debugging
writeHtml('page1.html');
});
casper.then(function() {
//casper.click('#ctl00_ContentPlaceHolderMain_VariableSelector1_VariableSelector1_ButtonViewTable');
});
casper.then(function() {
// FIRST ATTEMPT TO LOAD THE DATA TO a file called file.csv
var formData = casper.evaluate(function(){
return $('form#aspnetForm').serialize();
});
//this.echo("Params: " + formData);
var targetFile = 'file.csv';
casper.download(link, targetFile, 'POST', formData);
});
casper.then(function () {
// just for debugging
writeHtml('page2.html');
});
// SECCOND ATTEMPT TO LOAD THE DATA TO a file called stats.csv
casper.on('resource.received', function (resource) {
if ((resource.url.indexOf('tyti_001') !== -1) ) {
this.echo(resource.url);
var file;
file = "stats.csv";
try {
this.echo("Attempting to download file " + file);
var fs = require('fs');
casper.download(resource.url, fs.workingDirectory + '/' + file);
} catch (e) {
this.echo(e);
}
}
});
casper.run(function () {
this.echo('End').exit();
});
And my package.json:
{
"scripts": {
"test": "dotest"
},
"pre-commit": ["test"],
"dependencies": {
"jquery": "^3.3.1"
},
"devDependencies": {
"pre-commit": "^1.2.2"
}
}
Explanation of the code:
First visit this page: http://pxnet2.stat.fi/PXWeb/pxweb/fi/StatFin/StatFin__tym__tyti/statfin_tyti_pxt_001.px/?rxid=bd4d5dc1-358d-407e-ae47-13266b79bfd0
There, dynamically pick a specified link and move there.
Select all data by clicking the V-shapen icon (look at the attached screenshot) and then select the format of the file.
I've faced this issue earlier with all versions except phantomjs 2.0.0. I also tried the solutions you shared from SO a year ago and they didn't work as well.
I'm going to assume you're using a phantomjs version other than 2.0.0.
Here's the link to download it
https://bitbucket.org/ariya/phantomjs/downloads/
With it, you will have access to onFileDownload method which you can override and use like below
casper.page.onFileDownload = function(status){
console.log('onFileDownload(' + status + ')');
return "newfile.csv";
};
onFileDownload will be called whenever a file is downloaded as a result of clicking a button (ajax) or as a result of sequential get/post requests.
All you have to do is, trigger the click on the button/link that will initiate download.
Note : My solution is assuming that everything else (site is not blocking phantomjs and your request headers/cookies are as expected)

Firefox Addon - Accessing pre-loaded content script from ActionButton

I am attaching content script to every tab on my firefox add-on.
And if user clicks on ActionButton (top right icon on browser) I am trying to access content script handler function, but it does not work.
I am using walkthroughs from Content Scripts but still could not make it work.
Am I doing something wrong?
Please see code below the TODO marked areas are not working;
// main.js
tabs.on('ready', function (tab) {
var worker = tab.attach({
include: "*",
//contentScript: 'window.alert("Page matches ruleset");',
contentStyleFile: [data.url("scripts/myTestContent1.js")]
});
worker.port.on('listener1', function (params) {
// I will listen some messages coming from myTestContent1.js
});
console.log("main.js: tab is ready!");
});
// browser icon typically at top right
var button = buttons.ActionButton({
id: "myActionButton",
label: "My pretty add-on",
icon: {
"16": "./icon-16.png",
"32": "./icon-32.png",
"64": "./icon-64.png"
},
onClick: handleClick
});
// when top right browser icon button is clicked
function handleClick(state) {
var myWorker = tabs.activeTab.attach({
//contentScriptFile: // I do not want to attach anything, just get Active tab!
});
// TODO this code is not handled by active tab's content script
// should be handled by myTestContent1.js but does not work
myWorker.port.emit("initialize", "Message from the add-on");
}
myWorker.port.emit is not calling handler function on my content script.
// myTestContent1.js
// TODO this code is not calling :(
self.port.on("initialize", function () {
alert('self.port.on("initialize")');
});
I fixed the problem by keep tracking tab-worker pairs, so
var TabWorkerPair = function (tabid, worker) {
this.tabid = tabid;
this.worker = worker;
};
tabs.on('close', function (tab) {
for (var i = 0; i < TabWorkerPairList.length; i++) {
var pair = TabWorkerPairList[i];
if (pair.tabid == tab.id) {
// remove object from list
TabWorkerPairList.splice(i, 1);
break;
}
}
console.log("main.js > tabs.on('close') > TabWorkerPairList count: " + TabWorkerPairList.length);
});
tabs.on('ready', function (tab) {
var worker = tab.attach({
include: "*",
contentScriptFile: [data.url("scripts/myTestContent1.js")]
});
// queue workers for tab
var pair = new TabWorkerPair(tab.id, worker);
TabWorkerPairList.push(pair);
console.log("main.js: tab is ready!");
});
and finally I can now emit worker function;
// when top right browser icon button is clicked
function handleClick(state) {
for (var i = 0; i < TabWorkerPairList.length; i++) {
var pair = TabWorkerPairList[i];
if (pair.tabid == tabs.activeTab.id) {
pair.worker.port.emit("initialize", pair.tabid);
break;
}
}
}
main reason: a tab can have multiple workers. So you should manually access the worker you are interested in.

Youtube API v3 - Select menu to access public channel video data without Oauth

I want to access and view public Youtube videos (simple read only) from any Youtube channel without resorting to Oauth, just with plain API key. I haven't found a decent layman example on how to go about with API v3 ;-(
I have this to juggle with which I cannot get to work. Basically, a Select menu contains options whose values are existing channel IDs. When an option containing a channel ID is selected, it should trigger requestUserUploadsPlaylistId(). Then, when NEXTbutton or PREVIOUSbutton are activated, function requestVideoPlaylist() would kick in. Is there a better way to do this? I get the following error messages in Firebug:
TypeError: response.result is undefined (When I choose an option from SELECTmenu).
TypeError: response.result is undefined (After I click on buttons).
Here is what I am struggling with (am new to API v3 and kinda used to API v2 (sigh)):
<HTML is here>
script>
$('#NEXTbutton').prop('disabled', true).addClass('disabled');
</script>
<script type="text/javascript" src="https://apis.google.com
/js/client.js?onload=onJSClientLoad"></script>
<script>
var dd, playlistId, nextPageToken, prevPageToken;
function onJSClientLoad() {
gapi.client.setApiKey('YOUR-API-KEY');
gapi.client.load('youtube', 'v3', function(){
$('#NEXTbutton').prop('disabled', false).removeClass('disabled');
});
}
// Calling the following function via selected option value of select menu
// I am using "mine: false," since it's an unauthenticated request ??
function requestUserUploadsPlaylistId() {
var dd = $("#SELECTmenu option:selected").val();
var request = gapi.client.youtube.channels.list({
mine: false, // is this legit?
channelId: dd, // Variable is preset chosen value of SELECTmenu options
part: 'contentDetails,id'
});
request.execute(function(response) {
playlistId = response.result.items[0].contentDetails.relatedPlaylists.uploads;
channelId = response.result.items[0].id;
});
}
function requestVideoPlaylist(playlistId, pageToken) {
var requestOptions = {
playlistId: playlistId,
part: 'snippet,id',
maxResults: 5
};
if (pageToken) {
requestOptions.pageToken = pageToken;
}
var request = gapi.client.youtube.playlistItems.list(requestOptions);
request.execute(function(response) {
// Only show the page buttons if there's a next or previous page.
nextPageToken = response.result.nextPageToken;
var nextVis = nextPageToken ? 'visible' : 'hidden';
$('#NEXTbutton').css('visibility', nextVis);
prevPageToken = response.result.prevPageToken
var prevVis = prevPageToken ? 'visible' : 'hidden';
$('#PREVIOUSbutton').css('visibility', prevVis);
var playlistItems = response.result.items;
if (playlistItems) {
$.each(playlistItems, function(index, item) {
displayResult(item.snippet);
});
} else {
$('#CONTAINER').html('Sorry, no uploaded videos available');
}
});
}
function displayResult(videoSnippet) {
for(var i=0;i<response.items.length;i++) {
var channelTitle = response.items[i].snippet.channelTitle
var videoTitle = response.items[i].snippet.title;
var Thumbnail = response.items[i].snippet.thumbnails.medium.url;
var results = '<li><div class="video-result"><img src="'+Thumbnail+'" /></div>
<div class="chantitle">'+channelTitle+'</div>
<div class="vidtitle">'+videoTitle+'</div></li>';
$('#CONTAINER').append(results);
}
}
function nextPage() {
requestVideoPlaylist(playlistId, nextPageToken);
}
function previousPage() {
requestVideoPlaylist(playlistId, prevPageToken);
}
$('#NEXTbutton').on('click', function() { // Display next 5 results
nextPage();
});
$('#PREVIOUSbutton').on('click', function() { // Display previous 5 results
previousPage();
});
$("#SELECTmenu").on("change", function() {
$('#CONTAINER').empty();
if ($("#SELECTmenu option:selected").val().length === 24) { //Channel ID length
requestUserUploadsPlaylistId();
} else {
return false;
}
});
I'm surely missing something here, any pointers will be greatly appreciated.
FINAL UPDATE
A few updates later and I've finally answered my question after playing with the awesome Google APIs Explorer tool. Here is a sample working code allowing access to Youtube channel video-related data from a Select menu for read-only without using OAUTH, just an API key. The Select menu, based on a selected option's value (which contains a channel id), posts a video thumbnail, the thumbnail's channel origin; and the video's title. Should be easy to make the thumbnail clickable so as to load video in iframe embed or redirect to Youtube page. Enjoy!
// Change values and titles accordingly
<select id="SELECTmenu">
<option value="selchan">Select channel ...</option>
<option value="-YOUR-24digit-ChannelID-">Put-channel-title-here</option>
<option value="-YOUR-24digit-ChannelID-">Put-channel-title-here</option>
</select>
<button id="NEXTbutton">NEXT</button>
<button id="PREVIOUSbutton">PREV</button>
<ol id="CONTAINER"></ol> // Loads video data response
<script type="text/javascript"
src="https://apis.google.com/js/client.js?onload=onJSClientLoad">
</script>
var playlistId, nextPageToken, prevPageToken;
function onJSClientLoad() {
gapi.client.setApiKey('INSERT-YOUR-API-KEY'); // Insert your API key
gapi.client.load('youtube', 'v3', function(){
//Add function here if some action required immediately after the API loads
});
}
function requestUserUploadsPlaylistId(pageToken) {
// https://developers.google.com/youtube/v3/docs/channels/list
var selchan = $("#SELECTmenu option:selected").val();
var request = gapi.client.youtube.channels.list({
id: selchan,
part: 'snippet,contentDetails',
filter: 'uploads'
});
request.execute(function(response) {
playlistId = response.result.items[0].contentDetails.relatedPlaylists.uploads;
channelId = response.result.items[0].id;
requestVideoPlaylist(playlistId, pageToken);
});
}
function requestVideoPlaylist(playlistId, pageToken) {
$('#CONTAINER').empty();
var requestOptions = {
playlistId: playlistId,
part: 'snippet,id',
maxResults: 5 // can be changed
};
if (pageToken) {
requestOptions.pageToken = pageToken;
}
var request = gapi.client.youtube.playlistItems.list(requestOptions);
request.execute(function(response) {
// Only show the page buttons if there's a next or previous page.
nextPageToken = response.result.nextPageToken;
var nextVis = nextPageToken ? 'visible' : 'hidden';
$('#NEXTbutton').css('visibility', nextVis);
prevPageToken = response.result.prevPageToken
var prevVis = prevPageToken ? 'visible' : 'hidden';
$('#PREVIOUSbutton').css('visibility', prevVis);
var playlistItems = response.result.items;
if (playlistItems) {
displayResult(playlistItems);
} else {
$('#CONTAINER').html('Sorry, no uploaded videos.');
}
});
}
function displayResult(playlistItems) {
for(var i=0;i<playlistItems.length;i++) {
var channelTitle = playlistItems[i].snippet.channelTitle
var videoTitle = playlistItems[i].snippet.title;
var videoThumbnail = playlistItems[i].snippet.thumbnails.medium.url;
var results = '<li>
<div>'+channelTitle+'</div>
<div><img src="'+videoThumbnail+'" /></div>
<div>'+videoTitle+'</div>
</li>';
$('#CONTAINER').append(results);
}
}
function nextPage() {
$('#CONTAINER').empty(); // This needed here
requestVideoPlaylist(playlistId, nextPageToken);
}
function previousPage() {
$('#CONTAINER').empty(); // This needed here
requestVideoPlaylist(playlistId, prevPageToken);
}
$('#NEXTbutton').on('click', function() { // Display next maxResults
nextPage();
});
$('#PREVIOUSbutton').on('click', function() { // Display previous maxResults
previousPage();
});
// Using as filtering example Select option values which contain channel
// ID length of 24 alphanumerics/symbols to trigger functions just in case
// there are other option values in the menu that do not refer to channel IDs.
$("#SELECTmenu").on("change", function() {
$('#CONTAINER').empty();
if ($("#SELECTmenu option:selected").val().length === 24) {
requestUserUploadsPlaylistId();
return false;
} else {
return false;
}
});
NOTE:
Remember, code sample above is built based on what API v3 provided at the time of this posting.
TIP: It's better to make sure that the buttons be disabled during API call and re-enabled after API has posted the expected results. If you press those buttons while processing, you may get compounded and/or unexpected results. ~ Koolness

JsonLogOn via https

I've just introduced SSL to my MVC website. I made the whole default AccountContorller use it. It works fine unless I'm currently on http page and try to log on with ajax (the logon action is vredirected to httpS). This popup logon window doesn't even show up.
For the controller a used a custom attribute:
public class RequireSSL : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext.ActionDescriptor.IsDefined(typeof(NoSSL), true) ||
filterContext.ActionDescriptor.IsDefined(typeof(OptionalSSL), true))
{
base.OnActionExecuting(filterContext);
return;
}
HttpRequestBase req = filterContext.HttpContext.Request;
HttpResponseBase res = filterContext.HttpContext.Response;
//Check if we're secure or not and if we're on the local box
if (!req.IsSecureConnection && (!req.IsLocal || Properties.Settings.Default.UseSSLForLocalRequests))
{
var builder = new UriBuilder(req.Url)
{
Scheme = Uri.UriSchemeHttps,
Port = Properties.Settings.Default.HttpsPort,
};
res.Redirect(builder.Uri.ToString());
}
base.OnActionExecuting(filterContext);
}
}
How can I make it work?
EDIT
The whole rest was generated by MVC. (Project with built in authentications)
That's the link.
#Html.ActionLink(#Labels.LogOn, "LogOn", "Account", routeValues: null, htmlAttributes: new { id = "logonLink", data_dialog_title = "Identification" })
JS somehow hooks into that link and performs ajax logon . Probably with this code: (JajaxLogin.js - also out of the box)
/// <reference path="jquery-1.6.2.js" />
/// <reference path="jquery.validate.js" />
$(function () {
// Cache for dialogs
var dialogs = {};
var getValidationSummaryErrors = function ($form) {
// We verify if we created it beforehand
var errorSummary = $form.data('validation-summary-errors');
if (!errorSummary) {
errorSummary = $('<div class="validation-summary-errors"><span>Please correct the errors and try again.</span><ul></ul></div>')
.insertBefore($form);
// Remember that we created it
$form.data('validation-summary-errors', errorSummary);
}
return errorSummary;
};
var formSubmitHandler = function (e) {
var $form = $(this);
// We check if jQuery.validator exists on the form
if (!$form.valid || $form.valid()) {
$.post($form.attr('action'), $form.serializeArray())
.done(function (json) {
json = json || {};
// In case of success, we redirect to the provided URL or the same page.
if (json.success) {
location = json.redirect || location.href;
} else if (json.errors) {
var errorSummary = getValidationSummaryErrors($form);
var items = $.map(json.errors, function (error) {
return '<li>' + error + '</li>';
}).join('');
var ul = errorSummary
.find('ul')
.empty()
.append(items);
}
});
}
// Prevent the normal behavior since we opened the dialog
e.preventDefault();
};
var loadAndShowDialog = function (id, link, url) {
var separator = url.indexOf('?') >= 0 ? '&' : '?';
// Save an empty jQuery in our cache for now.
dialogs[id] = $();
// Load the dialog with the content=1 QueryString in order to get a PartialView
$.get(url + separator + 'content=1')
.done(function (content) {
dialogs[id] = $('<div class="modal-popup">' + content + '</div>')
.hide() // Hide the dialog for now so we prevent flicker
.appendTo(document.body)
.filter('div') // Filter for the div tag only, script tags could surface
.dialog({ // Create the jQuery UI dialog
title: link.data('dialog-title'),
modal: true,
resizable: true,
draggable: true,
width: link.data('dialog-width') || 300
})
.find('form') // Attach logic on forms
.submit(formSubmitHandler)
.end();
});
};
// List of link ids to have an ajax dialog
var links = ['logonLink', 'registerLink'];
$.each(links, function (i, id) {
$('#' + id).click(function (e) {
var link = $(this),
url = link.attr('href');
if (!dialogs[id]) {
loadAndShowDialog(id, link, url);
} else {
dialogs[id].dialog('open');
}
// Prevent the normal behavior since we use a dialog
e.preventDefault();
});
});
});

Firefox, Mozilla validator error

I am getting this one error when I use the Mozilla validator:
This is the JS file:
const STATE_START = Components.interfaces.nsIWebProgressListener.STATE_START;
const STATE_STOP = Components.interfaces.nsIWebProgressListener.STATE_STOP;
// Version changes:
// It used to get the lists from a PHP file, but that was putting too much of a strain on the servers
// now it uses xml files.
// Randomizes the servers to load balance
// Mozilla editor suggested no synchronous file gets, so changed it to asynchronous
// Added one more server to help with the updates (Ilovemafiaafire.net)
// Edited some redirect code that some idiots were spreading FUD about.
var xmlDoc = null;
var quickFilter_100_count_redirect_url='http://www.mafiaafire.com/help_us.php';
var countXmlUrl = 0;
//var xmlUrl = 'http://elxotica.com/xml-update/xml-list.php';
var xmlUrl = new Array(4);
xmlUrl[0] = 'http://mafiaafire.com/xml-update/mf_xml_list.xml';
xmlUrl[1] = 'http://ifucksexygirls.com/xml-update/mf_xml_list.xml';
xmlUrl[2] = 'http://ezee.se/xml-update/mf_xml_list.xml';
xmlUrl[3] = 'http://ilovemafiaafire.net/mf_xml_list.xml';
xmlUrl.sort(function() {return 0.5 - Math.random()})
var realXmlUrl = xmlUrl[countXmlUrl];
var notificationUrl = 'http://mafiaafire.com/xml-update/click_here_for_details.php';
var root_node = null;
var second_node = null;
var timervar = null;
var mafiaafireFilterUrl = '';
//Calling the interface for preferences
var prefManager = Components.classes["#mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
var quickfilter_mafiaafire =
{
// get the domain name from the current url
get_domain_name:function()
{
var urlbar = window.content.location.href;
domain_name_parts = urlbar.match(/:\/\/(.[^/]+)/)[1].split('.');
if(domain_name_parts.length >= 3){
domain_name_parts[0] = '';
}
var dn = domain_name_parts.join('.');
if(dn.indexOf('.') == 0)
return dn.substr(1);
else
return dn;
},
// send ajax request to server for loading the xml
request_xml:function ()
{
//alert(countXmlUrl);
http_request = false;
http_request = new XMLHttpRequest();
if (http_request.overrideMimeType) {
http_request.overrideMimeType('text/xml');
}
if (!http_request)
{
return false;
}
http_request.onreadystatechange = this.response_xml;
http_request.open('GET', realXmlUrl, true);
http_request.send(null);
xmlDoc = http_request.responseXML;
},
// receive the ajax response
response_xml:function ()
{
if (http_request.readyState == 4)
{
if(http_request.status == 404 && countXmlUrl<=3)
{
countXmlUrl++;
//alert(xmlUrl[countXmlUrl]);
realXmlUrl = xmlUrl[countXmlUrl];
quickfilter_mafiaafire.request_xml();
}
if (http_request.status == 200)
{
xmlDoc = http_request.responseXML;
}
}
},
filterUrl:function()
{
var urlBar = window.content.location.href;
//check if url bar is blank or empty
if (urlBar == 'about:blank' || urlBar == '' || urlBar.indexOf('http')<0)
return false;
//1. get domain
processing_domain = this.get_domain_name();
//alert(processing_domain);
//Couldn't fetch the XML config, so returning gracefully
if(xmlDoc == null)
return false;
try
{
root_node = '';
// Parsing the xml
root_node = xmlDoc.getElementsByTagName('filter');
for(i=0;i<=root_node.length;i++)
{
second_node = '';
second_node = root_node[i];
if(second_node.getElementsByTagName('realdomain')[0].firstChild.nodeValue == processing_domain)
{
this.notificationBox();
mafiaafireFilterUrl = '';
mafiaafireFilterUrl = second_node.getElementsByTagName('filterdomain')[0].firstChild.nodeValue;
timervar = setTimeout("quickfilter_mafiaafire.redirectToAnotherUrl()",1500);
//window.content.location.href = second_node.getElementsByTagName('filterdomain')[0].firstChild.nodeValue;
//this.redirectToAnotherUrl(this.filterUrl);
//timervar = setInterval("quickfilter_mafiaafire.redirectToAnotherUrl(quickfilter_mafiaafire.filterUrl)",1000);
}
}
}
catch(e){
//alert(e.toString());
}
},
// This function is called for showing the notification
notificationBox:function()
{
try{
// Firefox default notification interface
var notificationBox = gBrowser.getNotificationBox();
notificationBox.removeAllNotifications(false);
notificationBox.appendNotification('You are being redirected', "", "chrome://quickfilter/content/filter.png", notificationBox.PRIORITY_INFO_HIGH, [{
accessKey: '',
label: ' click here for details',
callback: function() {
// Showing the notification Bar
window.content.location.href = notificationUrl;
}
}]);
}catch(e){}
},
redirectToAnotherUrl:function()
{
var qucikFilterRedirectCount = '';
//Read the value from preferrences
qucikFilterRedirectCount = prefManager.getCharPref("extensions.quickfilter_redirect_count");
//alert(qucikFilterRedirectCount);
if(qucikFilterRedirectCount % 15 == 0)
{
// Disable for now, can comment this entire section but this is the easier fix incase we decide to enable it later
//window.content.location.href = quickFilter_100_count_redirect_url+"?d="+mafiaafireFilterUrl;
window.content.location.href = mafiaafireFilterUrl;
}
else
{
window.content.location.href = mafiaafireFilterUrl;
}
qucikFilterRedirectCount = parseInt(qucikFilterRedirectCount)+1;
prefManager.setCharPref("extensions.quickfilter_redirect_count",qucikFilterRedirectCount);
}
}
var quickfilter_urlBarListener = {
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;
},
//Called when the location of the window being watched changes
onLocationChange: function(aProgress, aRequest, aURI)
{
// This fires when the location bar changes; that is load event is confirmed
// or when the user switches tabs. If you use myListener for more than one tab/window,
// use aProgress.DOMWindow to obtain the tab/window which triggered the change.
quickfilter_mafiaafire.filterUrl();
},
//Notification indicating the state has changed for one of the requests associated with aWebProgress.
onStateChange: function(aProgress, aRequest, aFlag, aStatus)
{
if(aFlag & STATE_START)
{
// This fires when the load event is initiated
}
if(aFlag & STATE_STOP)
{
// This fires when the load finishes
}
},
//Notification that the progress has changed for one of the requests associated with aWebProgress
onProgressChange: function() {},
//Notification that the status of a request has changed. The status message is intended to be displayed to the user.
onStatusChange: function() {},
//Notification called for security progress
onSecurityChange: function() {},
onLinkIconAvailable: function() {}
};
var quickfilter_extension = {
init: function()
{
//Initiating the progressListerner
gBrowser.addProgressListener(quickfilter_urlBarListener, Components.interfaces.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
//Load the block list xml form server
quickfilter_mafiaafire.request_xml();
},
uninit: function()
{
// Remove the progressListerner
gBrowser.removeProgressListener(quickfilter_urlBarListener);
}
};
// window.addEventListener("load", function () { TheGreatTest1.onFirefoxLoad(); }, false);
// this function is Called on window Onload event
window.addEventListener("load", function(e) {
quickfilter_extension.init();
}, false);
window.addEventListener("unload", function(e) {
quickfilter_extension.uninit();
}, false);
Can you tell me how to squash that error please?
It looks like the offending line is setTimeout("quickfilter_mafiaafire.redirectToAnotherUrl()",1500);
The setTimeout function can take a string (which then essentially gets eval'd) or a function (which gets called). Using a string is not recommended, for all the same reasons that using eval is not recommended. See https://developer.mozilla.org/en/DOM/window.setTimeout
In this case, the simplest fix would be to change it to setTimeout(function() { quickfilter_mafiaafire.redirectToAnotherUrl(); },1500);

Resources