I have a SDK add-on that creates a page worker
events.on(eventTarget, "sandbox", (details, content) => {
var pageWorker = worker.Page({
contentScriptFile: data.url("sandbox.js"),
contentURL: data.url("sandbox.html"),
contentScriptWhen: "end"
});
pageWorker.port.emit("detect-version", content, funcs);
pageWorker.port.on("version-detected", (result) => {
if (result.version) {
events.emit(eventTarget, "result-ready", details, results);
}
});
pageWorker.port.on("done", () => {
pageWorker.destroy();
});
});
As you see on the sandbox event there are some messaging back and forth between the add-on and the page worker
the page worker is created
sends a message: detect-version
listens for version-detected
listens for the done event, calls destroy() on the page worker
I expect the worker.destroy() to remove the object and the background page etc.
This does not seem to happen. If I do a browser session for an hour the browser's memory usage is very high and if I check about:memory in Firefox I see a lot of sandbox.html windows entries which I guess indicates that they are not destroyed.
Does anyone know if this is a bug in 1.14?
or am I doing something wrong here? Other options? I need to have a sandboxed page that can communicate with the add-on and pageworker seems to be the only choice for now.
I see there was a bug fix commited 2013-09-26 in the SDK repo that could relate to this https://github.com/mozilla/addon-sdk/commit/55aeedc69984a2c0df78ddb17cee35a960b1135b
Thank you in advance for any help on this
t.
This still seems to be an issue and I doubt there will be a fix for it. I just came across this and ended up minimizing the side effects by just loading a small static resource at the end of my script:
window.location = "data:text/plain,goodbye";
This way any repeating background requests on the original page will no longer run. Be aware though that this will cause the page worker script to re-evaluate, so you are going to have to check window.location at the top of your script.
Related
This is driving me crazy. I have been trying to implement push notifications for a website and I found a solution (Javacript API notification). The thing is: notifications are not working on mobile devices.
I read about service workers and I have been using this code to ask user for permission and everything, but it is still not working. I am not sure if I am doing something wrong or what. I read about it has to be an https site, but that's does not seem to be the problem. I have also tried the push.js plugin plugin.js, but no succeed so far (even when the demo of that plugin that it's in their website is working on my mobile browser) This is the website >>> https://park-inside.nl/test/
The "Set notification" button is meant to show a notification when the waiting time is below the selected time. So, to test this, just click "Set notification", then select minutes greater than the "Wachttijd" column and refresh page. The notification should appear. It works on desktop browser, but not on mobile. Any idea or suggestion? I would love and appreciate any help.
Note: I am using Chrome 94 on Android 9 (go)
Code that ask for user permission:
Notification.requestPermission(function(result) {
if (result === 'granted') {
navigator.serviceWorker.ready.then(function(registration) {
registration.showNotification('Notification with ServiceWorker');
});
}
});
See the browser support table for Web Notifications: https://caniuse.com/notifications.
They only work in Chrome on Android, not in the stock Android Browser.
Also, be sure to register a service worker, even if it's an empty one, as seen here: https://stackoverflow.com/a/31787926/10551293.
A demo of the notifications is available here: https://serviceworke.rs/push-payload_demo.html.
Google also has a step-by-step codelab available here: https://developers.google.com/codelabs/pwa-training/pwa03--going-offline#0
Apparently, I had to first do this to register a service worker:
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('sw.js');
}
I am not really sure, but I was trying to use a route for the sw.js file, like this: js/sw.js. Once I placed that file in the root of the project, it worked.
Also, I added this code to that file to log some events to the console:
self.addEventListener('install', (event) => {
console.log('Installed');
});
self.addEventListener('activate', (event) => {
console.log('Activated');
});
self.addEventListener('fetch', (event) => {
console.log('Fetch request');
});
Thanks to swift-lynx for the links to some documentation, where I found a solution:
https://developers.google.com/web/ilt/pwa/introduction-to-push-notifications
I have an application (Vanilla JS / Weback + Babel) that uses postMessage to communicate between host page and an iframe (different domains).
I have noticed, that on IOS 12 Chrome browser does send an event that lands in my listener on interactions like button click.
Event data looks like that:
{
"type":"org.chromium.contextMenuMessage",
"requestId":"CC0C490584C989ACE524F0ED69F418DD",
"x":245,
"y":399.5
}
What is it? I couldn't find any resource that could explain that behaviour.
Edit: also, the strangest thing about this event is, that it seems to be present on production environment, but not on localhost.
I'm seeing a very similar thing on my app. I'm receiving messages into a cross-domain iframe from Chrome on iOS v12 and Chrome v76.0.3809. The content of the message I'm receiving is different, more in the form of:
{
iv: e8LCrn94cSbycO3i
payload: daPXeVR5GBg2IffLQ/2fuTmVGzJLnM++z2nC+cjR5kGcG1VhIBHni6tIrw94Gg+KvyMUMVNY3mjfJ9jMhT4g8fcnngZkiLirqoUOqMagVY3gaEzYBCb4ZVgtRelv/paccs7hc/rMi+cDr2eCOSzzKQ6fpHU=
target_frame_id: 419b482d9b6c4565f8dd4e2f470a518
type: org.chromium.encryptedMessage
}
I'm not sure what Chrome is using this data for specifically, it's most likely for communicating with add-ons.
The salient point here is that if you're listening for messages in your iframe using something like:
window.addEventListener('message', callback);
then you will receive all messages sent via postMessage and it's up to you to filter them. Any code on the page, including the browser, has the ability to send message events.
It only triggers a message cross-domain. If the parent and child are on the same domain it doesn't happen. At least that's what I've found and, sadly, I'm stuck with finding more info as well.
I've read up on how to avoid security issues when using window.postMessage() -- particularly the suggestions in this MDN doc.
But given all the preventative tips are all client-side, I'm having trouble understanding how they'd stop bad actors from simply editing changing the code in their developer tools.
Here's the situation I'm dealing with. I have a page that will contain an embedded iframe, and I have control over that iframe (it lives on a separate domain, but the vendor that provides it allows me to put custom JavaScript in the iframe source). The parent window and the iframe will communicate back and forth.
/**
window at https://firstgoodorigin.com
Receives message from iframe to indicate
its contents have loaded.
Once that message has been received,
send a message back to the iframe.
*/
function handleMessage(message) {
if (message.origin === 'https://secondgoodorigin.com') {
// verify and sanitize what's in message.data
// (it'll be something like "loaded")
// if it's good, send a message back
message.source.postMessage('foo', 'https://secondgoodorigin.com');
}
}
window.addEventListener('message', handleMessage, false);
/**
iframe at https://secondgoodorigin.com
Tell parent window it has loaded. Once that happens
it will receive a message from the parent window, for
which we add an event listener.
*/
window.addEventListener('load', () => {
window.parent.postMessage('loaded', https://firstgoodorigin.com);
});
window.addEventListener('message', (message) => {
if (message.origin === 'https://firstgoodorigin.com') {
// verify and sanitize what's in message.data
// do stuff
}
});
Given both the window source and iframe source will be editable inside someone's web inspector, what's to stop them from removing all the validation logic and replacing it with something malicious? What am I missing here?
As mentioned in the comment by Will any code in the browser can be edited by the end user if he or she may want to. The point of the locking down postmessages is to stop a third web site from posting unwanted messages.
If a user is logged into the site in question, and then loads a malicious website, that website could load the web site in question in an iframe or a popup, and then post messages unauthorized to the site.
I'm having some trouble with some inAppBrowser behavior in my cordova app. Here's the code:
var codePass = fooCode;
var executeScriptFunc = function(event) {
ref.executeScript({
code: codePass
}, function (value) {});
ref.removeEventListener('loadstop', executeScriptFunc);
};
var ref = cordova.InAppBrowser.open(fooObject.link, "_blank", "location=yes,enableViewportScale=yes");
ref.addEventListener('loadstop', executeScriptFunc)
The strange thing here is that the code works perfectly every time when emulated. It opens the browser and executes the script no problem. But when I try it on my actual iPhone device, it doesn't always work. The script executes maybe every other time. But it's never even that consistent.
Both the emulator and iPhone are using iOS 9.3.4. Any ideas?
If the site inside the inAppBrowser happens to be served via HTTPS, the callback for executeScript() will not work if the site employs a Content-Security-Policy HTTP response header that does not contain the gap: or gap-iab: schemes for the default-src directive. These are needed because execution of the callback function on iOS relies on an iframe that gets added to the page.
You can check whether this is the root cause for the problem by opening Safari’s Web Inspector for the inAppBrowser—it has a separate Web Inspector instance, independent of the parent application that opened it—and look out for a corresponding error message in the console. Note that you should open the console before executeScript() is run, or otherwise you might not get the error message.
Make sure also that you don't have other event handlers firing at the same time during your polling.
I had multiple pollers all firing every second and that's when I ran into the issue.
After changing the polling time so they all fired at different times, the issue went away.
I have a weird problem where after around 30+ seconds after a local html page has finished loading, calling the google AutocompleteService or PlacesService javascript function does not send out a request to do the lookup. But if less than 30 seconds it works fine. I can even do multiple successful calls if within that time.
Background:
We have a C# dll that is used by a VB6 app that runs as a Windows service. The dll is used to do autocomplete and other places API lookups through the Javascript API.
Due to the asynchronous nature of the google lookups, the WebBrowser control lives in its own thread with its own message loop eg.
thrd = new Thread(new ThreadStart(
delegate
{
Init(false);
System.Windows.Forms.Application.Run(this);
}));
// set thread to STA state before starting
thrd.SetApartmentState(ApartmentState.STA);
thrd.Start();
This is all setup once as part of the startup process of the service.
This dll works fine elsewhere which includes apps running in IIS and on the desktop.
Troubleshooting:
I confirmed that the browser thread stays alive on subsequent lookup calls from the windows service.
Through debugging, i can see that the javascript function (below) is being run (i can see the debug outputs) with no errors thrown. However, the google call, autocomplete.getPlacePredictions, does not send anything out (our network guy was monitoring the traffic while i did the lookup)
Example of the javascript function:
function doAutoComplete(waitKey, searchString, latBias, longBias, radiusBias, components, typesFilter) {
//Removed irrelevant code to keep it brief
//debug output here
autocomplete.getPlacePredictions(options, function (waitKey) {
return (function (predictions, status) {
window.external.setResult(waitKey, status, JSON.stringify(predictions));
});
} (waitKey));
//debug output here
}
The service does not have the issue when installed to a windows 7 machine. So at this stage the issue only happens in a Windows 2012 Server machine.
I have run out of ideas as to what could be causing the google call to not work.
Any help or ideas will be greatly appreciated.
Edit history:
Added #3 to Troubleshooting.
I have sorted it out.
The issue was that the IE enchanced security configuration (IE ESC) was internally blocking/disabling the call to Google. Turning it off prevents the issue from happening but i will look further into tweaking it rather than turning it off.
What is annoying is that it was doing it silently so was hard to track down. I believe the issue only happened when running as a windows service because of the different security levels used for it versus running from the desktop or IIS.