Detect if another Chrome app is running - javascript

I've got a Chrome extension and a Chrome app, which can communicate with each other over messaging. There are certain actions I want the extension to take only when the Chrome app isn't running. Given the Chrome app's Id, how can I detect from the Chrome extension if it is running?
I've tried using closed and suspend lifecycle events from the chrome app to assist, but that route isn't seeming possible due to various reasons. Is there any other way to detect?

Well, you are already using Messaging, so presumably App's event page will wake up to answer if you call it, even if the app is not launched.
You define "running" as having windows open. From the event page, you can check that:
chrome.runtime.onMessageExternal.addListener(function(message, sender, sendResponse) {
/* ... */
if (chrome.app.window.getAll().length) {
// Launched
} else {
// Not launched
}
});

Something like:
chrome.management.get(appId,function(theapp){
if(theapp.enabled){
// it is running
} else {
// it is not running
}
});

Related

Problem with service worker JavaScript on mobile browsers

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

How to check if a Firefox WebExtension is installed or not with page JavaScript?

I have developed a WebExtension for Firefox and my website works with the extension as a prerequisite. I need to check programmatically whether the extension is installed or not and if not ask the user to install it.
I am not able to find a way how to check this operation of whether my extension is already installed in the user's browser.
Editor note: Methods available in Firefox differ from those available in Chrome, so this question is not a duplicate.
Important note to begin with: A page can't query if an extension is installed without explicit help from the extension. This is done to prevent browser fingerprinting and/or preventing sites from denying content if certain extensions are installed.
WebExtensions are largely built upon the same principles as Chrome extensions. As such, this question is relevant: Check whether user has a Chrome extension installed.
However, some of the best methods available in Chrome are currently unavailable in Firefox:
You can't use external messaging from a webpage (through externally_connectable) as it's not available in FF.
You can't use web-accessible resources for checking presence since Firefox intentionally shields them from fingerprinting:
The files will then be available using a URL like:
moz-extension://<random-UUID>/<path/to/resource>
This UUID is randomly generated for every browser instance and is not your extension's ID. This prevents websites from fingerprinting the extensions a user has installed.
As such, what are your options? The page can't talk directly to the extension context (background), and the background can't directly affect the page; you need a Content script to interact with the page content.
How can page code and a content script communicate? They are isolated from each other unless content script does something about it.
First off, generic tricks that work in both FF and Chrome:
You can create or modify a DOM element on the page from a content script and look for those modifications in the page.
// Content script
let beacon = document.createElement("div");
beacon.classname = browser.runtime.id;
document.body.appendChild(beacon);
// Page script
// Make sure this runs after the extension code
if (document.getElementsByClassName("expected-extension-id").length) {
// Installed
} else {
// Not installed
}
You can use postMessage to communicate between contexts, though it's clunky to use as a bidirectional channel.
Here's documentation and sample WebExtension.
// Content script code
window.postMessage({
direction: "from-content-script",
message: "Message from extension"
}, "*");
// Page code
window.addEventListener("message", function(event) {
if (event.source == window &&
event.data.direction &&
event.data.direction == "from-content-script") {
// Assume extension is now installed
}
});
You can use custom DOM events in a similar way.
There are interesting Firefox-specific approaches as well:
You can share code with the page using exportFunction or cloneInto:
// Content script
function usefulFunction() {
/* ... */
}
const extensionInterface = {
usefulFunction
}
window.wrappedJSObject.extensionInterface =
cloneInto(extensionInterface, window, {cloneFunctions: true});
// Page code
if (typeof window.extensionInterface !== "undefined") {
// Installed
window.extensionInterface.usefulFunction();
} else {
// Not installed
}

setUninstallURL - in Safari and Firefox?

We created extensions for Chrome, Firefox and Safari. We want to open a new tab when uninstalling our extension. I found this code for Chrome, but is it possible to do it in Safari and Firefox?
switch (platform) {
case 'chrome':
try {
chrome.runtime.setUninstallURL(uninstall_url);
} catch(e) {
console.error(e);
}
break;
}
In place of manifest.json Safari extensions use Info.plist which is typically generated with ExtensionBuilder. As you can see from the provided screenshot, no 'uninstallURL' is available. I suggest testing a beforeUnload listener in the global page but this will probably also be triggered during other events like updates, browser closing etc.
As for Firefox, it all depends on the actual API your add-on is based on. You maybe out of luck if you have used the Addon SDK or created a legacy XUL overlay extension. However, Restartless bootstrapped extensions use low-level APIs and the uninstall function in bootstrap.js receives a reason parameter:
function uninstall(data, reason) {
if (reason === ADDON_UNINSTALL) {
let win = Services.wm.getMostRecentWindow('navigator:browser');
win.gBrowser.selectedTab = win.gBrowser.addTab(url);
}
}
Good news is a new WebExtensions API is coming to Firefox. It is basically identical to the Chrome API. See the relevant bug
From addon sdk you would use this https://developer.mozilla.org/en-US/Add-ons/SDK/Tutorials/Listening_for_load_and_unload
That shows you how to listen for load and unload and detect the reason for load/unload solution is from here - https://stackoverflow.com/a/31497334/1828637

Is it possible to terminate a process from Chrome packaged application onSuspend or onClose?

I'm trying to debug an packaged app which is based on Chrome App Sample WebSocket Server. First time I'm working with Chrome Apps so be kind.
When I run the app from Google Dev Editor I can open and close the application as I like. However, when installing it from the Chrome App Store, re-opening the app crashes my Chromebook = screen goes black for a few seconds, then comes back with all programs closed.
I'm not really sure where to start debugging this and as my extension is pretty much all copied from the app samples, it may also be a bug. I did find out, that if I terminate the process which remains in the shift+esc task manager by hand, I can restart the app without crashing.
I looked a little into ways to run things on closing of the app. I think I cannot use:
chrome.runtime.onSuspend.addListener(function() {
// kill process here
});
but maybe:
chrome.app.window.onClosed.addListener(function (){
// kill process here
});
would be usable, provided I have access to the processes and know the process id. I did find this blog post and gist on the topic, suggesting this would be possibe:
var tab_id;
var processes = (chrome.processes !== undefined) ? chrome.processes : chrome.experimental.processes;
chrome.browserAction.onClicked.addListener(function (tab) {
tab_id = tab.id;
processes.getProcessIdForTab(tab.id, function (processId) {
if (!isNaN(parseFloat(processId)) && isFinite(processId)) {
processes.terminate(processId);
}
});
});
processes.onExited.addListener(function (id, exitType, exitCode) {
if (exitType == 2 && exitCode == 15) {
chrome.tabs.reload(tab_id);
}
});
but I'm not able to access the processes as shown in the code (guess it's too old).
Question:
Is it at all possible to access the processes running from a Chrome App to try and terminate a process? If not how best tackle this then?
Thanks!

Page Worker - destroy() does not seems to remove the window object

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.

Categories