Consecutive calls to chrome.extension.sendMessage() - asynchronous

I am writing an extension, where I want my own cookies store mycookies in background.js which stores domain, path, key and flags. In my background.js, when an HTTP response is received, I call chrome.extension.sendMessage() for each Set-Cookie header of the the response. So each response call this function many times within few m-seconds. After the response, only the last one or two cookies are stored, the rest are lost.
I did the following experiment. I connected a button with the function update_mycookies. A click on button calls the function immediately and displays the content of mycookies after 2500ms. If I read the store after 2500ms, all four cookies are there if I introduce the delays (as below) in update_mycookies but if I remove the delays, only the last one or two cookies are updated, the rest are lost. The chrome.extension.sendMessage is using `chrome.storage.local.set(). I want my store must be updated with all the cookies in response.
function update_mycookies(){
chrome.extension.sendMessage({"cdomain":".google.com", "path":"/", "key":"PREF"});
setTimeout(function() {
chrome.extension.sendMessage({"cdomain":".google.com", "path":"/", "key":"NID"});}, 1000);
setTimeout(function(){
chrome.extension.sendMessage({"cdomain":".google.it", "path":"/", "key":"PREF"}); }, 1500);
setTimeout(function(){
chrome.extension.sendMessage({"cdomain":".google.it", "path":"/", "key":"NID"}); }, 2000);
}
The onMessage listenr is the following:
chrome.extension.onMessage.addListener(
function(request,sender,sendResponse) {
if (request["cdomain"] && request["path"] && request["key"]) {
chrome.storage.local.get("mycookies", function (items) {
if (items["mycookies"]) {
var found = false;
var entries = items["mycookies"].split(";");
entries.forEach (function (entry) {
var dk = entry.split(",");
if (dk[0] == request["cdomain"] && dk[1] == request["path"] && dk[2] == request["key"])
found = true;
});
if (!found)
chrome.storage.local.set({"mycookies": items["mycookies"] + ";" + request["cdomain"] + "," + request["path"] + ","
+ request["key"] });
}
else
chrome.storage.local.set({"mycookies": request["cdomain"] + "," + request["path"] + "," + request["key"] });
});
}
}

Related

How to retreive dataLayer value in GA correctly

I'm facing a problem while retreiving an event for GA. In GA, the eventLabel seems to find any problem with my dataLayer variables, as some of them are read as "undefined":
I've been researching my variables in code, but they seemed to be fine. And suddenly I found this while inspecting my GTM values:
The tag field was written in two lines and apparently "broken"! I supposed it was because of some sort of problem with my viewer, but I'm wondering if maybe that's the reason why my GA values are broken...
I checked length, and, when Iread Google documentation, the "eventLabel" tag can be 500 Bytes long:
And my texts are less than 500 Bytes long... So, what's the problem with my GA values? Is this "broken string" problem the responsible of the incorrect read of values in GA?
EDIT: This is the javascript behind.
The push:
dataLayer.push({
'event':'searchHome',
'eventCategory':'Home',
'eventAction':'search',
'eventLabel': 'route|departureDate|returnDate|category|quantity|variant|people|' + resident + '|' + vehicle,
'eventValue':'0'
});
Javascript to get the resident and vehicle variables (as they are the ones failing):
var vehicle = getTurismoValue($("#search-cars").val(), $("#search-cars option:selected").text(), $("#search-trailer").val());
var resident = getResidenciaValue($("#search-resident").val());
The functions behind:
function getTurismoValue(vehicle, literal, trailer) {
try {
if(vehicle != null && typeof vehicle !== "undefined") {
if (vehicle.trim().length > 0) {
return "Turismo|" + ((trailer.length > 0)?"si":"no");
}
}
return "0";
} catch (err) {
return "0";
}
};
function getResidenciaValue(resident) {
try{
if(resident != null && typeof resident !== "undefined") {
if (resident.trim().length > 0) {
return "peninsula";
}
return "extranjero";
}
return "0";
} catch(err) {
return "0";
}
};
Does anybody see anything weird with this javascript? What's failing?

SignalR causing bad request 400 seen on the server

We are having an issue with signalR. We have an auction site that runs on signalr for real time bidding. We fixed some issues with the browser and everything seemed to be working well. Then we installed new relic on our server and noticed that every minute we are getting http error code 400 on signalr connect, reconnect and abort. Here's a screenshot:
SignalR connect and reconnect are the most time consuming operations of the site according to new relic.
Here is SignalR backend code (We use sql server as signalr backplane):
public class SignalRHub : Hub
{
public void BroadCastMessage(String msg)
{
var hubContext = GlobalHost.ConnectionManager.GetHubContext<SignalRHub>();
hubContext.Clients.All.receiveMessage(msg);
}
}
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
string appString=string.Empty;
//Gets the connection string.
if (System.Configuration.ConfigurationSettings.AppSettings["SignaRScaleoutConn"] != null)
{
appString = System.Configuration.ConfigurationSettings.AppSettings["SignaRScaleoutConn"].ToString();
}
GlobalHost.DependencyResolver.UseSqlServer(appString);
GlobalHost.Configuration.ConnectionTimeout = TimeSpan.FromMinutes(15); //I added this timeout, but it is not required.
app.MapSignalR();
}
}
The javascript client looks like this, it's lengthy, but most of it is jQuery to affect the DOM, I include it all in case something may be wrong inside it.
$(function () {
var chatProxy = $.connection.signalRHub;
$.connection.hub.start();
chatProxy.client.receiveMessage = function (msg) {
var all = $(".soon").map(function () {
var hiddenModelId = $("#hiddenListingId");
if (msg == hiddenModelId.val()) {
$.ajax({
async: "true",
url: "/Listing/AuctionRemainingTime",
type: "POST",
dataType: 'json',
data: '{ "listingID": "' + msg + '"}',
contentType: "application/json; charset=utf-8",
success: function (data) {
if (data != null) {
SoonSettings.HasReloadedThisTick = false;
var element = document.getElementById(msg);
var obj = JSON.parse(data)
// For Clock Counter End Date Time Interval
// Adds 2 minutes to the soon clock when bid is close to finishing.
var hdID = "hdn" + obj.ListingId;
var hdValue = $("#" + hdID);
if (obj.EndDate != hdValue.val()) {
SoonSettings.HasUpdated = false; //Allows clock to change color once it gets under two minutes.
$('#' + hdID).val(obj.EndDate);
Soon.destroy(element);
Soon.create(element, { //Recreates clock with the before 2 minute tick event.
'due': 'in ' + obj.Seconds + ' seconds',
'layout':'group label-uppercase',
'visual':'ring cap-round progressgradient-00fff6_075fff ring-width-custom gap-0',
'face':'text',
'eventTick': 'tick'
});
}
var highbid = obj.HighBidderURL;
// For Date Ends Info.
var ListingEndDate = $("#tdAuctionListingEndDate");
if (obj.EndDate != ListingEndDate.val()) {
$('#' + hdID).val(obj.EndDate);
ListingEndDate.text(obj.EndDate + " Eastern");
ListingEndDate.effect("pulsate", { times: 5 }, 5000);
}
else
{
$(".Bidding_Current_Price").stop(true, true); ///Removes the pulsating effect.
$(".Bidding_Current_Price").removeAttr("style"); //Removes unnecessary attribute from HTML.
}
//Bid div notification.
if (obj.AcceptedActionCount.replace(/[^:]+:*/, "") > 0) {
if (obj.Disposition != '' && obj.Disposition != null) {
if (obj.Disposition == "Neutral") {
$("#spanNeutralBid").show();
$("#divOutbidNotification").hide();
$("#spanPositiveBid").hide();
$("#divProxyBidNotification").hide();
}
else if (obj.Disposition == "Positive") {
$("#spanPositiveBid").show();
$("#divOutbidNotification").hide();
$("#spanNeutralBid").hide();
$("#divProxyBidNotification").hide();
}
else if (obj.Disposition == "Negative") {
$("#divOutbidNotification").show();
$("#spanNeutralBid").hide();
$("#spanPositiveBid").hide();
$("#divProxyBidNotification").hide();
}
else {
$("#divOutbidNotification").hide();
$("#spanNeutralBid").hide();
$("#divProxyBidNotification").hide();
$("#spanPositiveBid").hide();
}
}
}
// For Highlight Current Price when it is Updated
var hdCurrentPrice = $("#hdnCurrentPrice");
if (obj.CurrentPrice != hdCurrentPrice.val()) {
$(".Bidding_Current_Price").text(obj.CurrentPrice);
$(".Bidding_Current_Price").effect("pulsate", { times: 5 }, 5000);
$("#hdnCurrentPrice").val(obj.CurrentPrice);
}
else {
$(".Bidding_Current_Price").stop(true, true);
$(".Bidding_Current_Price").removeAttr("style");
}
// For ReservePrice Status
$("#spanReservePriceStatus").html(obj.ReservePriceStatus);
$("#smallReservePriceStatus").html(obj.ReservePriceStatus);
// For Bid Count
var spanBidCounter = $("#spanBidCount");
$(spanBidCounter).text(obj.AcceptedActionCount);
var stringAppend = "<tr id='trhHighBidder'><td><strong>HighBidder</strong></td>";
stringAppend += "<td>";
if (obj.isAdmin == true) {
stringAppend += "<a id='anchorHighBid' href=" + obj.HighBidderURL + ">";
stringAppend += "<span id='spanHighBidder'>" + obj.CurrentListingActionUserName + "</span>"
stringAppend += "</a>";
}
else {
stringAppend += "<span id='spanHighBidderAnonymous'>" + obj.CurrentListingActionUserName + "</span>";
}
stringAppend += "</td></tr>";
if (obj.AcceptedActionCount.replace(/[^:]+:*/, "") > 0) {
if ($("#tblAuctionDetail").find("#rowHighBidder").length > 0) {
if ($("#tblAuctionDetail").find("#trhHighBidder").length > 0) {
$("#trhHighBidder").remove();
}
}
else {
//add tr to table
if (!$("#tblAuctionDetail").find("#trhHighBidder").length > 0) {
$('#tblAuctionDetail > tbody > tr:eq(6)').after(stringAppend);
}
}
}
// For High Bidder
if (obj.isAdmin) {
var anchorElement = $("#anchorHighBid");
$(anchorElement).attr("href", obj.HighBidderURL);
var spanHighBidder = $("#spanHighBidder");
$(spanHighBidder).text(obj.CurrentListingActionUserName);
}
else {
var spanAdminHighBid = $("#spanHighBidderAnonymous");
$(spanAdminHighBid).text(obj.CurrentListingActionUserName)
}
}
},
error: function (xhr, textStatus, errorThrown) {
}
});
}
});
};
});
Is there anything wrong with the client or the server signalr code that may need to be changed to avoid these errors happening so often? The 400 code has the tendency of showing up almost every minute. I am very new to signalR and know very little of how to make effective code with it.
The real time bidding in the site does work, it's just to find a way to avoid these constant errors. Any help explaining anything of how signalR works is appreciated.
Thanks,
I'd give a try changing the transportation method of SignalR: http://www.asp.net/signalr/overview/guide-to-the-api/hubs-api-guide-javascript-client#transport
and check if problem persists.
If possible to get UserAgent from Bad Request log, try to narrow down which browsers get 400 error. I think, maybe, some browsers are not connecting with correct transport method.

Open multiple links in casperjs

I am trying to scrape all links of special kind (boxscore-links) from this website http://www.basketball-reference.com/teams/GSW/2016_games.html and then visit them one by one, scraping some information from every visited link. For a beginning I want to scrape all links, visit them one by one and get a title of website. The problem is that it always prints the same title and the same current url (initial url) even though it clearly has to be a new one. Seems to me that there is a problem with 'this'-keyword...
(Don't look at limit of links, I took the code from sample on github of casperjs and I left it for console not to be overloaded.)
This is my code:
var casper = require("casper").create({
verbose: true
});
// The base links array
var links = [ "http://www.basketball-reference.com/teams/GSW/2016_games.html" ];
// If we don't set a limit, it could go on forever
var upTo = ~~casper.cli.get(0) || 10;
var currentLink = 0;
// Get the links, and add them to the links array
function addLinks(link) {
this.then(function() {
var found = this.evaluate(searchLinks);
this.echo(found.length + " links found on " + link);
links = links.concat(found);
});
}
// Fetch all <a> elements from the page and return
// the ones which contains a href starting with 'http://'
function searchLinks() {
var links = document.querySelectorAll('#teams_games td:nth-child(5) a');
return Array.prototype.map.call(links, function(e) {
return e.getAttribute('href');
});
}
// Just opens the page and prints the title
function start(link) {
this.start(link, function() {
this.wait(5000, function() {
this.echo('Page title: ' + this.getTitle());
this.echo('Current url: ' + this.getCurrentUrl());
});
});
}
// As long as it has a next link, and is under the maximum limit, will keep running
function check() {
if (links[currentLink] && currentLink < upTo) {
this.echo('--- Link ' + currentLink + ' ---');
start.call(this, links[currentLink]);
addLinks.call(this, links[currentLink]);
currentLink++;
this.run(check);
} else {
this.echo("All done.");
this.exit();
}
}
casper.start().then(function() {
this.echo("Starting");
});
casper.run(check);
Considering an array of URLs, you can iterate over them, visiting each in succession with something like the following:
casper.each(urls, function(self, url) {
self.thenOpen(url, function(){
this.echo('Opening: ' + url);
// Do Whatever
});
});
Obviously this will not find links on a page, but it is a nice way to go over a known set of URLs.

How to get the total count of a Meteor collection with a limit set?

In my meteor app, I'm doing infinite scrolling so I must have a limit set on my subscriptions in order to achieve this, but I also need to show the total count from that same collection and update it if the count changes. How would I achieve that?
I have a partial solution that achieves this but only returns the paginated counts, as follows:
function getTotalCount(system) {
var user = Meteor.user(),
queryObject = getSystemQueryObject(system);
if (queryObject) {
var query = queryObject.find({$and: [
{user: user.username},
{status: {$nin: status_complete}}
]});
var count = 0;
var handle = query.observeChanges({
added: function (id, user) {
$('#' + system + 'Count').text(++count);
$('#' + system + 'Count').addClass("ma-count-badge");
console.log(system + " count incremented: " + count);
},
removed: function () {
$('#' + system + 'Count').text(--count);
$('#' + system + 'Count').addClass("ma-count-badge");
console.log(system + " count decremented: " + count);
}
});
}
else {
return 0;
}
}
The other way is to push this method up to the server as a server method, but then it is not reactive, as follows:
Meteor.call('getSystemsTotalCount', system, function (err, counted) {
if (err) {
throw err;
}
if (counted > 0) {
$('#' + system + 'Count').text(counted);
$('#' + system + 'Count').addClass("ma-count-badge");
}
Session.get('listLimit');
});
}
you can to get the count with following way
var count= queryObject.find({$and: [
{user: user.username},
{status: {$nin: status_complete}}
]}).count();
after that, you can to save in a Session
Session('countCollection',count);
if the collection changes your Session also it will do
So the trick really is to combine both options I have in the question. The first part adds reactivity to adds/deletes and the second part calls out to the server to go get the total count. Now my code looks like:
query.observeChanges({
added: function(id, user) { updateListCount(system);},
removed: function(id) { updateListCount(system);}
});
And I just wrap the Method.call from the second excerpt above with a function called updateListCount invoked by the above. This addresses the issue.

Switch to iframe with phantom.js

I would like to switch to an iframe using pure phantom.js code
Here is my first attempt
var page = new WebPage();
var url = 'http://www.theurltofectch'
page.open(url, function (status) {
if ('success' !== status) {
console.log("Error");
} else {
page.switchToFrame("thenameoftheiframe");
console.log(page.content);
phantom.exit();
}
});
It produces only the source code of the main page. Any idea ?
Notice that the iframe domain is different from the main page domain.
Please give this a try I believe it may be an async issues meaning the iframe is not present when trying to access it. I received the below snippet from another post.
var page = require('webpage').create(),
testindex = 0,
loadInProgress = false;
page.onConsoleMessage = function(msg) {
console.log(msg);
};
page.onLoadStarted = function() {
loadInProgress = true;
console.log("load started");
};
page.onLoadFinished = function() {
loadInProgress = false;
console.log("load finished");
};
/*
page.onNavigationRequested = function(url, type, willNavigate, main) {
console.log('Trying to navigate to: ' + url);
console.log('Caused by: ' + type);
console.log('Will actually navigate: ' + willNavigate);
console.log('Sent from the page\'s main frame: ' + main);
};
*/
/*
The steps array represents a finite set of steps in order to perform the unit test
*/
var steps = [
function() {
//Load Login Page
page.open("https://www.yourpage.com");
},
function() {
//access your iframe here
page.evaluate(function() {
});
},
function() {
//any other step you want
page.evaluate(function() {
});
},
function() {
// Output content of page to stdout after form has been submitted
page.evaluate(function() {
//console.log(document.querySelectorAll('html')[0].outerHTML);
});
//render a test image to see if login passed
page.render('test.png');
}
];
interval = setInterval(function() {
if (!loadInProgress && typeof steps[testindex] === "function") {
console.log("step " + (testindex + 1));
steps[testindex]();
testindex++;
}
if (typeof steps[testindex] !== "function") {
console.log("test complete!");
phantom.exit();
}
}, 50);
replace
console.log(page.content);
with
console.log(page.frameContent);
Should return the contents of the frame phantomjs switched to.
If the iframe is from another domain you may need to add the --web-security=no option like this:
phantomjs --web-security=no myscript.js
As an additional information, what xMythicx said could be true. Some iframes are rendered via Javascript after page finishes loading. If the iframe contents are empty, then you will need to wait for all resources to finish loading, before you start grabbing stuff from the page. But this is another issue, if you need an answer on this, I suggest you ask a new question about it, and I will answer there.
Had the same problem for iframes and
phantomjs --web-security=no
helped in my case :]

Resources