I have extension with popup.html which has popup.js in it.
I use popup.js to call function located in content script using chrome.tabs.sendMessage -method.
This is working nicely, but..
How do I return the value of the function back to popup.js ? Do I need to set up a listener on the popup.js aswell or what ?
On my popup.js I have:
chrome.tabs.sendMessage(tab.id, {
expiryRequest: 'expiry '
}, function (response) {
if (response.refreshResponse === true) {
console.log('Expiry taken');
} else {
console.log('Expiry NOT taken');
}
});
This part works great..
On my content script I read certain div into a vartiable "result".
At the end of the function on content script I have used.
return result;
or
return true;
None of those returns anything back tuo popup.js.
What do I need to change in order to get my return to work from content script to popup.js ?
You should not return your result, but send it back.
chrome.runtime.onMessage callbacks take 3 parameters: the message, the sender information, and the sendResponse callback.
To pass a response back, sendResponse must be called:
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse){
if(message.ping) sendResponse({pong: true});
});
However, there's an additional trick to it. The event listener should either reply immediately (i.e. synchronously, before it exits) or signal that it will reply later. This is done with the return value:
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse){
if(message.ping) {
chrome.storage.local.get("shouldReply", function(result){
// This is asynchronous: by now the listener returned
if(result.shouldReply) sendResponse({pong: true});
});
}
return true; // Indicate that you will eventually call sendResponse
});
Unless you do this, sendResponse reference is invalidated when the listener exits and an undefined response is sent.
One more caveat: you should call sendResponse no more than once; it will generate an error otherwise.
Related
I'm currently unsuccessfully trying to make my PWA installable. I have registered a SertviceWorker and linked a manifest as well as I am listening on the beforeInstallPromt event.
My ServiceWorker is listening to any fetch event.
My problem is, that the created beforeInstall banner is just being shown on Chrome desktop but on mobile I get a warning in Chrome inspection tab "Application" in the "Manifest" section:
Installability
Service worker does not have the 'fetch' handler
You can check the message on https://dev.testapp.ga/
window.addEventListener('beforeinstallprompt', (e) => {
// Stash the event so it can be triggered later.
deferredPrompt = e;
mtShowInstallButton();
});
manifest.json
{"name":"TestApp","short_name":"TestApp","start_url":"https://testapp.ga/loginCheck","icons":[{"src":"https://testapp.ga/assets/icons/launcher-ldpi.png","sizes":"36x36","density":0.75},{"src":"https://testapp.ga/assets/icons/launcher-mdpi.png","sizes":"48x48","density":1},{"src":"https://testapp.ga/assets/icons/launcher-hdpi.png","sizes":"72x72","density":1.5},{"src":"https://testapp.ga/assets/icons/launcher-xhdpi.png","sizes":"96x96","density":2},{"src":"https://testapp.ga/assets/icons/launcher-xxhdpi.png","sizes":"144x144","density":3},{"src":"https://testapp.ga/assets/icons/launcher-xxxhdpi.png","sizes":"192x192","density":4},{"src":"https://testapp.ga/assets/icons/launcher-web.png","sizes":"512x512","density":10}],"display":"standalone","background_color":"#ffffff","theme_color":"#0288d1","orientation":"any"}
ServiceWorker:
//This array should NEVER contain any file which doesn't exist. Otherwise no single file can be cached.
var preCache=[
'/favicon.png',
'/favicon.ico',
'/assets/Bears/bear-standard.png',
'/assets/jsInclude/mathjax.js',
'/material.js',
'/main.js',
'functions.js',
'/material.css',
'/materialcolors.css',
'/user.css',
'/translations.json',
'/roboto.css',
'/sw.js',
'/'
];
//Please specify the version off your App. For every new version, any files are being refreched.
var appVersion="v0.2.1";
//Please specify all files which sould never be cached
var noCache=[
'/api/'
];
//On installation of app, all files from preCache are being stored automatically.
self.addEventListener('install', function(event) {
event.waitUntil(
caches.open(appVersion+'-offline').then(function(cache) {
return cache.addAll(preCache).then(function(){
console.log('mtSW: Given files were successfully pre-cached')
});
})
);
});
function shouldCache(url) {
//Checking if url is market as noCache
var isNoCache=noCache.includes(url.substr(8).substr(url.substr(8).indexOf("/")))||noCache.includes((url.substr(8).substr(url.substr(8).indexOf("/"))).substr(0,(url.substr(8).substr(url.substr(8).indexOf("/"))).indexOf("?")));
//Checking of hostname of request != current hostname
var isOtherHost=url.substr(8).substr(0,url.substr(8).indexOf("/"))!=location.hostname&&url.substr(7).substr(0,url.substr(7).indexOf("/"))!=location.hostname;
return((url.substr(0,4)=="http"||url.substr(0,3)=="ftp") && isNoCache==false && isOtherHost==false);
}
//If any fetch fails, it will look for the request in the cache and serve it from there first
self.addEventListener('fetch', function(event) {
//Trying to answer with "online" version if fails, using cache.
event.respondWith(
fetch(event.request).then(function (response) {
if(shouldCache(response.url)) {
console.log('mtSW: Adding file to cache: '+response.url);
caches.open(appVersion+'-offline').then(function(cache) {
cache.add(new Request(response.url));
});
}
return(response);
}).catch(function(error) {
console.log( 'mtSW: Error fetching. Serving content from cache: ' + error );
//Check to see if you have it in the cache
//Return response
//If not in the cache, then return error page
return caches.open(appVersion+'-offline').then(function (cache) {
return cache.match(event.request).then(function (matching) {
var report = !matching || matching.status == 404?Promise.reject('no-match'): matching;
return report
});
});
})
);
})
I checked the mtShowInstallButton function. It's fully working on desktop.
What does this mean? On the Desktop, I never got this warning, just when using a handheld device/emulator.
Fetch function is used to fetch JSon manifest file. Try reading google docs again.
For adding PWA in Mobile you need manifest file to be fetched which is fetched using service-worker using fetch function.
Here is the code :
fetch('examples/example.json')
.then(function(response) {
// Do stuff with the response
})
.catch(function(error) {
console.log('Looks like there was a problem: \n', error);
});
for more about fetch and manifest try this.
I would like to present an AdWords interstitial before the user returns to the previous page. How can I do this when the return button is pressed?
I think you can make use of WillPopScope widget. You can pass a callback function which will be called when the view is about pop. Just do whatever tasks to be completed before pop and then return true.
Example:
Future<bool> _willPopCallback() async {
// await showDialog or Show add banners or whatever
// then
return true; // return true if the route to be popped
}
//then pass the callback to WillPopScope
new WillPopScope(child: new Scaffold(), onWillPop: _willPopCallback)
Chrome extension that I'm developing requires users to authenticate with Gmail account.
However, if a user doesn't want to authorize, I've stopped the authorization window from appearing. However, some background scripts seem to be running. How do I make sure that the extension stops functioning completely?
You must initiate your extension in a callback called when the user is authenticated. For example, using oAuth2:
function onAuthorized() {
var url = 'https://www.googleapis.com/oauth2/v1/userinfo';
var request = {
'method': 'GET',
'parameters': {
'alt': 'json'
}
};
// Declare the callback
oauth.sendSignedRequest(url, callback, request);
};
and the callback:
function callback(resp, xhr) {
// ... Process text response ...
}).done(function (data) {
// Your used is authenticated...
// ==>Init your extension HERE
});
}
A background page with "persistent": false will be unloaded after a few seconds of inactivity. Stop doing work and the right thing will happen.
I have written this function in jQuery:
function checkAvailability(value) {
var result = true;
$.getJSON("registration/availability", { username: value }, function(availability) {
if (!availability)
result = false;
alert("in getJSON: " + result);
});
alert(result);
return result;
}
I have got alert from 'getJSON' after this second. Why has it happened this way?
I have Spring MVC project and Controller method which checks username availability. Controller method works properly. But I receive final result too late. How can I synchronize it to return properly value in my function?
EDIT
I am using this function in jQuery validate. I have extracted checkAvailability() function during my test.
$.validator.addMethod("checkAvailability", function(value, element, param) {
var das = checkAvailability(value);
return das;
}, jQuery.format("Someone already has that username. Please try another one."));
And this is my form validate:
$(".form").validate({
rules: {
username: {
checkAvailability: true
},
....
},
messages: {
}
});
EDIT 2
This is my Controller method. It returns boolean value. If username was taken it would return false value.
#RequestMapping(value="/registration/availability", method = RequestMethod.POST)
public #ResponseBody boolean getAvailability(#RequestParam String username) {
List<User> users = getAllUsers();
for (User user : users) {
if (user.getUsername().equals(username)) {
return false;
}
}
return true;
}
Why does this behave this way?
$.getJSON is shorthand for making an AJAX request. The 'A' in ajax stands for asynchronous. Meaning, the javascript engine fires the getJSON call and then immediately executes the next lines, which is alert(result); return result;
The actual value as returned by the web service will be received by your code at a later point in time. The success function that you passed into getJSON will be called once the js engine receives the response from the server. As you can see, it is too late by that point.
Further reading: https://developer.mozilla.org/en/AJAX
What can I do to make this work?
That depends on your situation. Who is calling checkAvailabilty? If you post some code on how this function is being used, I can give examples with my suggestions.
Off the top of my head, you could either make use of jquery deferreds, nice article on the same. Or you could pass in a callback function that is executed from inside your success function.
EDIT:
http://docs.jquery.com/Plugins/Validation/Methods/remote#options
The serverside resource is called via $.ajax (XMLHttpRequest) and gets
a key/value pair, corresponding to the name of the validated element
and its value as a GET parameter. The response is evaluated as JSON
and must be true for valid elements, and can be any false, undefined
or null for invalid elements,
To get a real world idea, check the demo http://jquery.bassistance.de/validate/demo/captcha/
Open Firebug or the developer tools of your choice. Go to the tab that lets you see AJAX requests. Enter the captcha, submit. Check ajax request as listed in the developer tool. Notice the query string parameters. Notice the response. Its a simple 'true' or 'false'.
Not sure if this helps or not but you can use
var result;
$.ajax( {
url : "registration/availability",
data : data,
async : false //syhcrononous ajax request ;)
}).done(function(data) {
result = data;
});
for more info you can refer JQuery AJAX doc
I can set data into the State.data of History.js, like this:
var pushStateData = {};
function RetrieveSearchResults(type, url, searchData) {//, showResetButton,
controlToFocus, navDirection) {
pushStateData = {
SearchType : type,
SearchData : searchData,
};
RetrievePageResults(true, url, pushStateData);
}
function RetrievePageResults(pushNewUrl, url, pushStateData) {
navigationInProgress = true;
if (pushNewUrl) {
if (window.History) {
window.History.pushState(pushStateData, null, url);
}
$.get(url, pushStateData.SearchData, function (reply) {
$("#search-results").html(reply);
navigationInProgress = false;
});
}
If I set a breakpoint on the window.History.pushState statement, in Chrome, I can clearly see pushStateData has the desired values.
However, when I try to retrieve the data:
$(window).bind("statechange", function (e) {
if (!navigationInProgress) {
var State = window.History.getState();
if (window.console && window.console.log) {
console.log("popstate", State, window.location.href);
}
RetrievePageResults(false, State.cleanUrl, State.data);
}
});
When I set a breakpoint on the RetrievePageResults statement,
The State.data object no longer has any of the values I set. State.data is defined, and is not null, but it is an empty object without any apparent values.
Thanks,
Scott
I don't see anything wrong with State.data, when you issue a pushState, make sure you call the History.js method:
History.pushState({state:1}, "State 1", "?state=1");
Where:
First Parameter => The data
Second Parameter => The name
Third Parameter => The url
It seems your not passing the state, and the data will only be present if and only if you call the History.pushState. When your visiting the URL directly (/?state=1) you would have no data in the state, data will only be available when navigating back/forward while pushing state via History.pushState.
side note: Make sure your navigationInProgress variable is fixed, you don't want it to be stalled there. Reset it when the $.get request failed when listening on the error callback. And when your pushNewUrl is false, reset the navigationInProgress attribute.