throttling http requests google chrome extension - google-chrome

As it turns out the answer to my prior question does not work. The problem is that I am overloading the server with requests. The process needs a throttle so that subsequent requests incur a little slowdown. Here is the code in question. The important segment of code that needs a timer or setInterval is that prefaced by the alert "Profile Rejected" although it would be acceptable to slow them both down. Any suggestions?
if (greetThisOne==true && !bGreeted)
{
//alert ("Requesting Message Page");
console.log="Message Page Requested";
chrome.extension.sendRequest({cmd: "openMessage", url: messageLink, keyWordsFound: keyWordList, greeted: bGreeted});
}
else
{
//alert("Profile Rejected");
console.log="Profile Rejected";
chrome.extension.sendRequest({cmd: "profileRejected", url: messageLink, keyWordsFound: keyWordList, greeted: bGreeted});
}

You would need to implement some queue in the background page. For example:
var rejectedProfiles = [];
processRejectedProfiles();
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
if(request.cmd == "profileRejected") {
//add to the end of queue
rejectedProfiles.push({url: request.url, other: request.parameters});
}
sendResponse({});
});
function processRejectedProfiles() {
if(rejectedProfiles.length > 0) {
//get the oldest element in queue
var profile = rejectedProfiles.shift();
//process profile
...
}
//process next entry in the queue in 3 seconds
setTimeout(processRejectedProfiles, 3000);
}
This way you will be processing one profile at a time, with a provided delay.

Related

Chrome's webkitSpeechRecognition ends randomly

I'm using the Web Speech API to capture voice commands on my webpage, but the recognizer ends (it stops listening and fires the onend event) after a certain period of time.
Why does this happen? Can I prevent it?
Here is all the code needed to have a voice recognizing page (40 Lines) and reproduce the error. It will alert "end" when the recognizer stops listening.
<h1>Voice Recognizer</h1>
<script>
if (!('webkitSpeechRecognition' in window)) {
alert('Your browser does not support speech recognition.');
} else {
var recognition = new webkitSpeechRecognition();
recognition.continuous = true;
recognition.interimResults = true;
recognition.onstart = function() {
console.log('started');
}
recognition.onresult = function() {
interim_transcript = '';
for (var i = event.resultIndex; i < event.results.length; ++i) {
if (event.results[i].isFinal) {
final_transcript += event.results[i][0].transcript;
} else {
interim_transcript += event.results[i][0].transcript;
}
}
console.log('interim result:', interim_transcript);
console.log('final reuslt:', final_transcript);
}
recognition.onerror = function() { alert('error'); }
recognition.onend = function() { alert('end'); }
function startListening(e){
final_transcript = '';
recognition.start();
}
startListening();
}
</script>
Google tries to limit the amount of processed data because it loads their servers. Restart speech recognition once it is over or use some offline processing like Pocketsphinx.JS
First of all google has given 60 seconds of recording time as of now, and it is very efficient in listening, so i would suggest that you increase your speaking speed. If your speech takes more than 60 secs, then webkit will trigger the onspeechend() function that leads to stopping of your code. either way if you can write your own trigger for onspeechend() and again call your function from within, then it should work for you as it would start a new instance and would continue with your text, unless you clear it.

serviceworkers focus tab: clients is empty on notificationclick

I have a common serviceworker escenario, where I want catch a notification click and focus the tab where the notification has come from. However, clients variable is always empty, its lenght is 0
console.log("sw startup");
self.addEventListener('install', function (event) {
console.log("SW installed");
});
self.addEventListener('activate', function (event) {
console.log("SW activated");
});
self.addEventListener("notificationclick", function (e) {
// Android doesn't automatically close notifications on click
console.log(e);
e.notification.close();
// Focus tab if open
e.waitUntil(clients.matchAll({
type: 'window'
}).then(function (clientList) {
console.log("clients:" + clientList.length);
for (var i = 0; i < clientList.length; ++i) {
var client = clientList[i];
if (client.url === '/' && 'focus' in client) {
return client.focus();
}
}
if (clients.openWindow) {
return clients.openWindow('/');
}
}));
});
And the registration is this one:
this.doNotify = function (notification) {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('sw.js').then(function (reg) {
requestCreateNotification(notification, reg);
}, function (err) {
console.log('sw reg error:' + err);
});
}
...
}
chrome://serviceworker-internals/ output shows that registration and installation are fine. However, when a notification is pushed, clientList is empty. I have tried removing the filter type:'window' but the result is still the same. As clients are empty, a new window is always opened. What am I doing wrong?
The suspicion in your own comment is correct. A page is controlled by a service worker on navigation to an origin that the service worker is registered for. So the original page load that actually initializes the service worker is not itself controlled. That's why the worker only finds your tab once you visit with a new tab or do a refresh.
However (as Jeff Posnick points out in the comments) you can get uncontrolled pages as follows: ServiceWorkerClients.matchAll({includeUncontrolled: true, type: 'window'}).
Try making the service worker immediately claim the page.
E.g.:
self.addEventListener('install', event => event.waitUntil(self.skipWaiting()));
self.addEventListener('activate', event => event.waitUntil(self.clients.claim()));
For a more complex example, see https://serviceworke.rs/immediate-claim.html.

Sending message from popup.js in Chrome extension to background.js

What is the proper way to send a message (and get a response) to background.js from popup.js in a Chrome extension? Every method I try ends up with an error that:
"Port: Could not establish connection. Receiving end does not exist."
I would prefer to use chrome.extension.sendMessage() over chrome.extension.connect() with port.postMessage(), but neither method seems to have worked.
What I am trying to do is wire a button in the popup.html to call into some javascript in popup.js which calls back to background.js in an effort to get info about the currentTab() that was topMost (ie:to get the current URL string to show in the popup.html)
Right now in popup.js (wired to the action of the button) I have:
function getURL()
{
chrome.extension.sendMessage({greeting: "GetURL"},
function(response) { tabURL = response.navURL });
$("#tabURL").text(tabURL);
}
In background.js I have:
chrome.extension.onMessage.addListener( function(request,sender,sendResponse)
{
if( request.greeting == "GetURL" )
{
var tabURL = "Not set yet";
chrome.tabs.getCurrent(function(tab){
tabURL = tab.url;
});
sendResponse( {navURL:tabURL} );
}
}
Any ideas?
Just to clarify, we talking about communication between popup page from browserAction and background script?
Anyway you have quite a few errors in your code.
First your totally ignore the fact that all callbacks in chrome api are asynchronous.
In background page
var tabURL = "Not set yet";
chrome.tabs.getCurrent(function(tab){
tabURL = tab.url;
}); //this will be invoked somewhere in the future
sendResponse( {navURL:tabURL} );
//navUrl will be always Not set yet because callback of getCurrent hasn't been called yet
Same in popup.js
chrome.runtime.sendMessage({greeting: "GetURL"},
function(response) { tabURL = response.navURL });//callback will be invoked somewhere in the future
$("#tabURL").text(tabURL)//tabURL will display something totally different from what you have been expected
Second error is that chrome.tabs.getCurrent doesn't give you the current tab selected by user in main window. The docs says:
Gets the tab that this script call is being made from. May be
undefined if called from a non-tab context (for example: a background
page or popup view).
So you will get undefined for all of your requests, because you call it in background page. What you need to do is to use method chrome.tabs.query to obtain currently active tabs.
So after fixing all problems new code should look something like this:
background.js
chrome.runtime.onMessage.addListener( function(request,sender,sendResponse)
{
if( request.greeting === "GetURL" )
{
var tabURL = "Not set yet";
chrome.tabs.query({active:true},function(tabs){
if(tabs.length === 0) {
sendResponse({});
return;
}
tabURL = tabs[0].url;
sendResponse( {navURL:tabURL} );
});
}
}
popup.js
function getURL() {
chrome.runtime.sendMessage({greeting: "GetURL"},
function (response) {
tabURL = response.navURL;
$("#tabURL").text(tabURL);
});
}

Chrome extension to monitor a kiosk and reload if needed

I have a kiosk that processes portraits of people. It is running in chrome.
One out of 200 people who use the kiosk end up with it freezing during the process. When it freezes, I never get the "ah snap" and the page just kinda hangs.
I was wondering if it is possible to make an extension to monitor the page and check for a heartbeat - If it is not seen after 30 seconds reload the window.
Any help would be great.
Have a content script in the kiosk page send a message every X seconds back to the background page
In the content script:
var port = chrome.extension.connect({ name: "keep-alive" });
port.postMessage('is-alive', { alive: true });
setInterval(function () {
port.postMessage('is-alive', { alive: true });
}, 1000 * 15);
If the background page detects the message hasn't come back after a certain time then reload the tab
In the background page:
var last = Date.now();
var interval = 1000 * 15;
chrome.extension.onConnect.addListener(function (port) {
if (port.name === 'keep-alive') {
port.onMessage.addListener(function (data) {
if (data.type === 'is-alive' && data.payload.alive === true) {
last = Date.now();
}
});
}
});
setInterval(function () {
if (Date.now() - last > interval) {
// Reload the tab...
}
}, interval);
For information about reloading the tab, see the chrome.tabs documentation. You will need to add tabs to your permission list in the manifest.
If you'd like to know more about message passing, see the Messaging docs.

Repeat jQuery JSON request until condition is met

I am trying to repeat a JSON request in jQuery to check the status of a video encoding job until it is completed. "Processing" would be displayed until the job is finished, at which point the video will be displayed.
Would a loop, checking every x seconds to see if "status" equals "finished," be the best solution for this? If so, how would I break free from this loop when the job is finished?
The JSON response while the job is in progress will be nothing more than "processing," when it is finished it will contain things such as the job ID, width, and height.
Any help would be appreciated, thanks!
UPDATE
Here's my final solution thanks to Felix:
var checkStatus = function() {
$.getJSON('json-data.php', function(data) {
if (data.status != 'finished') {
setTimeout(checkStatus, 2000);
} else {
//Sample code to run when finished
$("#statusText").text("Job Complete");
$("#dimensions").text(data.width + 'x' + data.height);
}
});
};
checkStatus();
A loop won't work as the Ajax request is asynchronous.
One way would be to make same kind of recursive call and trigger the Ajax function again from the success callback (maybe after some timeout), if the condition is not met.
Something like (pseudo code):
function check_condition() {
$.getJSON(<url>, function(result) {
if(!result.finished) {
setTimeout(check_condition, 2000);
}
// do something else
}
}
var checkStatusInterval = 30 * 10000; // 30 seconds
var checkStatusFunc = function(){
$.getJSON('getMovieStatus', function(data){
if (data.Incompleted){ // or however you check
checkStatusTimer = setTimeout(checkStatusFunc, checkStatusInterval);
}
});
};
var checkStatusTimer = setTimeout(checkStatusFunc,checkStatusInterval );
To stop:
<input type="button" id="stopchecking" value="Stop Checking..." />
$('#stopchecking').click(function(e){
clearTimeout(checkStatusTimer);
});