chrome.tabs.executeScript only working with an alert before it - google-chrome-extension

I believe this is related to the asynchronous nature of chrome extensions.
This section of my code:
alert(tab.title);
chrome.tabs.executeScript(tab.id, {code:"document.title = 'test'"});
Works fine, but as soon as I remove the alert, it stops working. Is there anything I can do to remove the alert but still have the js injected?
EDIT: More Code
tabs is a global array of tab objects.
chrome.tabs.onSelectionChanged.addListener(function (tabId) {
for (var i = 0; i < tabs.length; i++) {
if (tabs[i].id == tabId) {
var tab = tabs[i];
while (i < tabs.length) {//length-1
tabs[i] = tabs[i+1];
i++;
}
tabs.pop();
alert(tab.title);//WHY IS THIS NEEDED
chrome.tabs.executeScript(tab.id, {code:"document.title = document.title.substring(1)"});
return;
}
}
});
I am very confused. Changing it the following solves the problem:
chrome.tabs.executeScript(tab.id, {code:"setTimeout('document.title = document.title.substring(1)',100)"});
However, as soon as I change the delay to 50, the script doesn't get executed again. I would prefer not to have to have to make this delay. Does anyone know whats going on?

I know this is an old question, but if anyone is looking - wrap the chrome.tabs.executeScript method in a timeout.
setTimeout(function(){chrome.tabs.executeScript(tab.id, {code:"setTimeout('document.title = document.title.substring(1)',100)"});},500);
It's certainly not ideal but it gets the job done.

Sounds like you have a race condition. My best guess would be to change the injected code to execute on onLoad.

Related

VIDEOJS: playing a pre-roll add before each playlist item

I'm using the videojs-playlist plugin along with Google's videojs-ima plugin. Everything works swimmingly except I am only getting a preload ad before the first video. I want one before each video in the playlist.
Basic setup is boilerplate, but for reference:
this.player = videojs('currentvideo', { autoplay : true, fluid : true });
this.player.playlist(this.playlist);
this.player.playlist.autoadvance(5);
const skippable_linear = {google's test ad};
const options = {
id: 'currentvideo',
adTagUrl: skippable_linear,
debug : true
};
this.player.ima(
options
);
this.player.ima.requestAds();
I have tried various ways of manually calling ads from inside an 'ended' event handler, such as calling requestAds again:
const _this = this;
this.player.on( 'ended', function(){
/* some other stuff */
_this.player.ima.requestAds();
});
This does play an ad where I want it, but
this breaks playlist's 'autoadvance' setting (next video doesn't start playing when the ad is finished), and
this puts the player into "ad display" mode (scrubber is unavailable, etc).
Is there a simple way to just say, "play an ad now" programmatically? I've tried, without joy, to use all of the seemingly applicable methods exposed by both the ima plugin and the contrib-ads plugin it relies on. I'll admit here that this is the first time I've ever had to deal with videos that run ads, so I'm kind of a noob.
I am trying to do the same thing. Just like you I failed when calling player.ima.requestAds() on events. I dug deeper and the best I could come up with is what I share bellow.
According to the videojs-ima API you have to use the setContentWithAdTag method instead of whatever you are using to switch the player content. In our case it is the player.playlist.next method.
I combined the code found in the videojs-ima examples with the original playlist.next to write my own next.
Then quite brutally I overrode the original plugin method.
Here's the code:
player.playlist(myPlayilst);
player.playlist.autoadvance(2);
player.playlistUi(); //videojs-playlist-ui
player.ima({
id: 'video5',
adTagUrl: 'thy adserver request'
});
//override playlist.next
player.playlist.next = function(){
var nextIndex = 0,
playlist = this.player_.playlist,
list = this.player_.playlist();
//everything below is copied directly from the original `next` (except for the "//load with ad")
// Repeat
if (playlist.repeat_) {
nextIndex = playlist.currentIndex_ + 1;
if (nextIndex > list.length - 1) {
nextIndex = 0;
}
} else {
// Don't go past the end of the playlist.
nextIndex = Math.min(playlist.currentIndex_ + 1, list.length - 1);
}
// Make the change
if (nextIndex !== playlist.currentIndex_) {
//load with ad
this.player_.playlist.currentItem(nextIndex);
this.player_.ima.setContentWithAdTag(
this.player_.playlist.currentItem(),
null,
true);
this.player_.ima.requestAds();
/////
return list[playlist.currentItem()];
}
}
You will probably need to override other methods that change the current playback, like playlist.previous.
I use videojs-playlist-ui so in my case it was neccessary to change the onclick handler called switchPlaylistItem_. I used some good old brute force to do that like this:
videojs.getComponent('PlaylistMenuItem').prototype.switchPlaylistItem_ = function(e){
this.player_.playlist.currentItem(this.player_.playlist().indexOf(this.item));
this.player_.ima.setContentWithAdTag(
this.player_.playlist.currentItem(),
null,
true);
this.player_.ima.requestAds();
};
PlaylistMenuItem's prototype should be changed before initializing the player.
This solution works, but it feels hacky, so if anyone can come up with something cleaner, please share!
I ended up forking videojs-playlist, and adding the option to override the player.src method. Feel free to use it:
fw-videojs-playlist
Details on how to use it are all in the github readme (including an example with ima.setContentWithAdTag)

Node.js, For loop

in node.js I am using for loop on server.js but it is not working and cause error
var myEasyrtcApp = function(err, appObj) {
for (i = 0; i < 10; i++) {
appObj.createRoom("room" + i ,null,function(err, roomObj){});
};
}
Please advice how can I use for loop to call appObj.createRoom several time to open different conference room
Sorry, but you almost not give any information... Asuming the last function is a Callback you need to make a Recursive "Loop" something like:
http://pastebin.com/LrKqLgyV
And to use it you can do this:
http://pastebin.com/L1bZZis0
To learn more about this, just google "recursive functions". (I can't post more than 2 links XD)
Hope It works for you ;)

Meteor.setTimeout is not causing delay

I am creating my first Meteor app with the Spheron smart package. I can control he sphero ok and change it's colors but I'm trying to create a delay in between the color change.
Here is my code:
function makePrettyLights(sphero,color){
var colors = [];
colors['red'] = '0xB36305';
colors['green'] = '0xE32017';
colors['blue'] = '0xFFD300';
console.log(color);
var spheroPort = '/dev/tty.Sphero-OBB-RN-SPP';
var timer = 2000;
Meteor.setTimeout(function(){
sphero.on('open', function() {
sphero.setRGB(colors[lineName], false);
});
sphero.open(spheroPort);
},2000);
}
This function is being called from in a loop. I havent included the loop at it involves me parsing some xml and other bits but it works.
if (Meteor.isServer) {
/**** Loop Code Here ****/
makePrettyLights(sphero,color)
/****End Loop Code ****/
}
I have also tried setting the timeout wrapper around the function where it is called instead of inside it.
But basically they all run at the end of my code at the same time.
I20140806-09:49:35.946(1)? set color
I20140806-09:49:35.946(1)? set color
I20140806-09:49:35.946(1)? set color
The problem is most probably in your loop. I assume it's a pretty standard for loop, in which case such behavior is expected. When you call:
for(var i=0; i<5; ++i) {
setTimeout(someFunction, 2000);
}
the setTimeout method will be called 5 times in a row in a single moment. This means that someFunction will be called 5 times in a row after 2000 miliseconds.
Your sphero variable is scoped outside the timeout. So every time a connection is opened the previously added callbacks will fire at the same time since you're just adding on to globally scoped sphero variable.
Try defining sphero (not currently shown with your code above) inside the Meteor.setTimeout callback instead of outside of it.

Chrome extension delay condition

I have created a chrome extension which does something after its button is clicked.
However I dont want it be abused so I need the its code to be executed after some time.
How can I surround this code with a timeout in order to achieve this?
Thank you for reading me!
chrome.tabs.getSelected(null,function(tab) {
var Mp=tab.url.substring(0,23);
if(Mp=='https://www.example.com')
{
onWindowLoad();
chrome.extension.onMessage.addListener(function(request, sender) {
if (request.action == "getSource")
{
...Working here
}
});
}
else
{
message.innerHTML='<span style="color: #f00">This is not a valid page</span>';
}
});
function onWindowLoad()
{
var message = document.querySelector('#message');
chrome.tabs.executeScript(null, {file: "getPagesSource.js"});
}
I had to make a compromise so just after the getSelected I added the following line:
chrome.browserAction.disable(tab.Id);
It disables the action button thus it cant be clicked while the script sends the data to the server, as with this extension I grab the tab url in order to store it in my database.
After the ajax response and adding the following
if(xhr.readyState==4)
{
message.innerHTML=xhr.responseText;
chrome.browserAction.enable(tab.Id); /////<---THAT LINE
}
the button gets ready again to be clicked.
I couldnt find the way to add a specific delay in seconds, this way seems stupid but its working, as the response's delay from my server is enough for switching the 2 states of the action button.
With this, however another problem came up, which Ill write in different question.

How to setTimeout in node.js?

I need to be able to make retries in node.js in the event of failure inside a function. I've setup a while loop as shown below, but I am getting slightly confused about how I should wrap the function call to not make sure that it won't block my whole server.
What should I do?
while(retryCount < 10 && !success){
// Alternative one
while(new Date().getTime() < now + 1000) {
myFunction();
}
// Or:
setTimeout( myFunction(), 1000);
}
You can store number of tryes in function object. It's will be fine for cronjob. If you need same behaviour in request context you must store attempts counter in request scope (not in function object).
var fnc = function() {
console.log('try');
if (true) { // Error condition
// Error here
if (!fnc.tryes) fnc.tryes = 0;
fnc.tryes++;
console.log(fnc.tryes);
if (fnc.tryes <= 10) {
setTimeout(fnc, 1000);
} else {
fnc.tryes = 0;
}
// Something wrong
} else {
// We hame result
}
};
fnc();
I'd say use the setTimeout method, that way the client won't be stuck inside the while loop that checks the time.
That outer while loop is going to block, you'd have to refactor using only setTimeout. However, the fact that you want this sort of thing indicates to me that your code structure is really terrible and needs more reworking. What is it that you are retrying? How are you detecting an error condition? Does doing it 10 times really make the chances of success higher?
I have a gist containing a generic function that will do this sort of thing for you, but I'm reluctant to share if this is an XY problem.

Resources