clients.openWindow not opening standalone app - javascript

I want to open a standalone web app added to home screen from a received push notification. Almost everything is working fine, except that when I click the notification when the stand-alone app or a browser is not open, it gives me a random list of other irrelevant apps [screenshot attached].
>
Here is my code on Service Worker where I try to open the app.
self.addEventListener('notificationclick', function(event){
var data = event.notification.data;
event.notification.close();
event.waitUntil(clients.matchAll({
type: 'window'
})
.then(function(clientList) {
for (var i = 0; i < clientList.length; i++) {
var client = clientList[i];
if (client.url.split('#')[0] == 'https://account.info.lk/' && 'focus' in client){
client.navigate(data.url);
return client.focus();
}
}
if (clients.openWindow)
return clients.openWindow(data.url);
}));
});
Please help me get the standalone app (or at least on a browser window open when a push notification is clicked.

Related

Why web push not work from iframe in chrome with both load through https?

Web push works fine from iframe in local but when i uploaded to cloud server then it does not work in only chrome or chromium browser.
I have developed a webpush micro-service that serve from a Iframe. That works fine in local but when i uploaded to cloud server then it does not work in only chrome or chromium browser. You can check from https:alemran.me (click ^ icon from bot).
Web Worker:
self.addEventListener('push', function (event) {
if (!(self.Notification && self.Notification.permission === 'granted')) {
return;
}
const sendNotification = (title, body ) => {
return self.registration.showNotification(title,
body
);
};
if (event.data) {
const message = JSON.parse(event.data.text());
event.waitUntil(sendNotification(message.title,message.message));
}
});
There is no error show in console
You can open a new window with a url and get permission from user....
Like :
let win = window.open("your url", "_blank");
let winInterval = window.setInterval(function() {
if (win.closed !== false) {
window.clearInterval(winInterval );
//check your api for user subscription status
}
}, 200);

Console.log double logging from web workers

My intention is for one message to be passed to the worker after it is created, and for that message to be logged by the worker and a reply to be sent back. What happens is that the message sent to the web worker is logged twice, and only one reply is sent. If you refresh the page or pause execution using developer tools, the message is correctly logged once.
I created a miniature extension to demonstrate this. There is a background script listening for a click on the browser action button. When it is clicked, a new tab is opened, and this tab generates 2 web workers. These workers listen for messages and log them, and send a reply stating that the message was recieved. The newly opened tab then sends the message, and logs the reply.
Google drive with all of the files needed to run this as a chrome extension
Image demonstrating the double logging of the message
Some references:
general web worker
use
.postMessage to
worker
chrome browser action
chrome tabs API
I have been working on my extension for a while now and have run into all sorts of fun bugs, particularly with async code. In the end I was always able to either debug them myself or find a reference that explained the problem. Thank you for any help you can give!
background.js
const tabUrl = chrome.extension.getURL("tab.html");
function browserActionCallback(tab) {
function createResultsTab() {
chrome.tabs.create({
"url": tabUrl,
"index": tab.index + 1
}, function() {
console.log("Tab created");
});
}
(function tabHandler() {
chrome.tabs.query({"url":tabUrl}, (tabQueryResults) => {
if (tabQueryResults.length > 0) {
chrome.tabs.remove(tabQueryResults[0].id, () => {
createResultsTab();
});
} else {
createResultsTab();
}
});
})();
}
chrome.browserAction.onClicked.addListener((tab) => {
browserActionCallback(tab);
});
tab.js
function createWorkers(num) {
/*in original extension I intended to let the user change number of workers in options*/
var workers = new Array(num);
for (let i = 0; i < num; i++) {
workers[i] = new Worker("worker.js");
}
return workers;
}
function messageWorkers(workers) {
let len = workers.length
for (let i = 0; i < len; i++) {
let message = "Connection " + i + " started";
workers[i].postMessage(message);
workers[i].onmessage = function(e) {
console.log(e.data);
}
}
}
var numWorkers = 2;
const WORKERS = createWorkers(numWorkers);
console.log("Before");
messageWorkers(WORKERS);
console.log("After");
worker.js
onmessage = function(msg) {
console.log(msg.data);
postMessage("Worker reply- " + msg.data);
}
EDIT 1: changing the tab.js messageWorkers function's for loop such that onmessage is set before postMessage does not change the results. Sending multiple messages also doesn't change results. If I have a console.log statement at the start of worker's onmessage function which logs that the function has begun, it too logs twice. To reiterate, this only happens when this tab is created by the background script and not when the page is refreshed or debugger is used.
EDIT 2: in the devtools console, there is a drop down menu to choose between top and workers. Checking the option 'selected context only' makes the repeated logging disappear, however this view is a little narrower than I would like
I can confirm this issue. Sample code to reproduce it:
index.js
function worker() {
console.log('this logged twice');
}
const workerBlob = new Blob(
[worker.toString().match(/function[^{]+\{([\s\S]*)\}$/)[1]],
{type: 'text/javascript'}
);
const workerBlobUrl = URL.createObjectURL(workerBlob);
new Worker(workerBlobUrl);
Use index.js as a Chrome extension background script and "this logged twice" will be logged twice when loading the extension or re-launching Chrome.

Service Worker onClick event - How to open url in window withing sw scope?

I have service worker which handles push notification click event:
self.addEventListener('notificationclick', function (e) {
e.notification.close();
e.waitUntil(
clients.openWindow(e.notification.data.url)
);
});
When notification comes it takes url from data and displays it in new window.
The code works, however, I want different behavior. When User clicks on the link, then it should check if there is any opened window within service worker scope. If yes, then it should focus on the window and navigate to the given url.
I have checked this answer but it is not exactly what I want.
Any idea how it can be done?
P.S. I wrote this code but it still doesn't work. The first two messages are however shown in the log.
self.addEventListener('notificationclick', function (e) {
e.notification.close();
var redirectUrl = e.notification.data.redirect_url.toString();
var scopeUrl = e.notification.data.scope_url.toString();
console.log(redirectUrl);
console.log(scopeUrl);
e.waitUntil(
clients.matchAll({type: 'window'}).then(function(clients) {
for (i = 0; i < clients.length; i++) {
console.log(clients[i].url);
if (clients[i].url.toString().indexOf(scopeUrl) !== -1) {
// Scope url is the part of main url
clients[i].navigate(givenUrl);
clients[i].focus();
break;
}
}
})
);
});
Ok, here is the piece of code which works as expected. Notice that I am passing scope_url together with redirect_url into the web notification. After that I am checking if scope_url is part of sw location. Only after that I navigate to redirect_url.
self.addEventListener('notificationclick', function (e) {
e.notification.close();
var redirectUrl = e.notification.data.redirect_url;
var scopeUrl = e.notification.data.scope_url;
e.waitUntil(
clients.matchAll({includeUncontrolled: true, type: 'window'}).then(function(clients) {
for (i = 0; i < clients.length; i++) {
if (clients[i].url.indexOf(scopeUrl) !== -1) {
// Scope url is the part of main url
clients[i].navigate(redirectUrl);
clients[i].focus();
break;
}
}
})
);
});
If I understand you correctly, most of the code you linked to works here.
First retrieve all the clients
If there are more than one, choose one of them
Navigate that to somewhere and focus
Else open a new window
Right?
event.waitUntil(
clients.matchAll({type: 'window'})
.then(clients => {
// clients is an array with all the clients
if (clients.length > 0) {
// if you have multiple clients, decide
// choose one of the clients here
const someClient = clients[..someindex..]
return someClient.navigate(navigationUrl)
.then(client => client.focus());
} else {
// if you don't have any clients
return clients.openWindow(navigationUrl);
}
})
);

Detect multiple chrome tabs opened of the same app in javascript

Is there a way to detect if multiple browser tabs are opened of the same application.
Let's say i have www.test.com and i open 4 tabs of this website.
Is there a way to detect that multiple tabs are opened in JavaScript?
You can use my sysend.js library, it use localStorage to send messages between open tabs/windows. All to do is this code:
sysend.on('notification', function() {
sysend.broadcast('multiple');
});
sysend.on('multiple', function() {
// this will fire n-1 times if there are n tabs open if n > 1
alert('multiple pages');
});
sysend.broadcast('notification');
JSFIDDLE
There is, but it's not guaranteed to always be correct:
window.onload = function() {
var applicationCount = localStorage.getItem("applicationCount");
if (!applicationCount) {
applicationCount = 0;
}
localStorage.setItem("applicationCount", ++applicationCount);
}
window.onbeforeunload = function(e) {
var applicationCount = localStorage.getItem("applicationCount");
if (!applicationCount) {
applicationCount = 1;
}
localStorage.setItem("applicationCount", --applicationCount);
};
It uses the localStorage which is shared among the tabs. But note that if the browser crashes, the value is still saved.

Differences in Chrome on various OS

I'm developing a chrome extension and i've met a very strange bug - my code works well on Mac OS, but doesn't work on Windows and Linux versions of Chrome. Versions are the same.
function captureAllScreen() {
chrome.windows.getCurrent(function(w) {
chrome.tabs.captureVisibleTab(w.id, {"format":"png"}, function(response) {
var image = response;
var url;
chrome.tabs.getSelected(w.id, function(response) {
url = response.url;
});
var viewTabUrl = [chrome.extension.getURL('app.html'),
'?id=', id++].join('');
chrome.tabs.create({url: viewTabUrl}, function(tab) {
var targetId = tab.id;
var addSnapshotImageToTab = function(tabId, changedProps, tab) {
if (tabId != targetId || changedProps.status != "complete") {
return;
};
chrome.tabs.onUpdated.removeListener(addSnapshotImageToTab);
var views = chrome.extension.getViews();
for (var i = 0; i < views.length; i++) {
var view = views[i];
if (view.location.href == viewTabUrl) {
view.twm_Draw.sendScreen(image, url); //Application-specific method
break;
}
}
window.close();
};
chrome.tabs.onUpdated.addListener(addSnapshotImageToTab);
});
});
});
};
Update:
What i want to do with this code - is to take a screenshot and tab url and send it to my extension's page. When user clicks on my extension's icon - it opens a popup with two buttons, one of it fires this function.
In Mac Os everything works - this code takes a screenshot, tab url, opens new tab with my application and sends the data there. On Linux & Windows versions of chrome it doesn't send the data, after clicking the icon in the popup you just get a blank tab opened.
I think this part might be causing problems:
var url;
chrome.tabs.getSelected(w.id, function(response) {
url = response.url;
});
//using url
The rest of the code should be wrapped into callback function, otherwise order of execution is not guaranteed.
I'm guess it's only supported on Mac, whatever it does:
view.twm_Draw.sendScreen(image, url); //Application-specific method
I don't know about Unix but on Windows you can only get a screenshot using a NPAPI plugin like the Google extension for screen capture.

Categories

Resources