Notification.requestPermission() throwing error on Mozilla - mozilla

I' m trying to get notification for Mozilla. But it continuously throwing this error.
The Notification permission may only be requested from inside a short
running user-generated event handler.
Here is my code. The same code is working fine on Chrome, EDGE and Opera.
Notification.requestPermission().then(function (status) {
if (status === 'denied') {
//
} else if (status === 'granted') {
//
}
});
I found some questions related to this, but none of those is helpful for me.

That message means that your subscription code must be called inside a user generated event, like a click.
Probably you are trying to subscribe the user on page load, but that is not possible on some browsers, like Firefox and Safari, because it is considered an annoyance for the users.
That is one of the reasons why many push services (like OneSignal, Pushpad, etc.) suggest to use a double opt-in: first you display a subscribe prompt or button designed with HTML / CSS and then, after the click on the button, you actually request the permission (your code above).

This piece of code worked for me:
JS
if (Notification.permission === 'granted') {
//do something
}
else if (Notification.permission === 'default') {
$('#allow-push-notification-bar').show();
}
$('#allow-push-notification').click(function () {
$('#allow-push-notification-bar').hide();
Notification.requestPermission().then(function (status) {
if (status === 'denied') {
//do something
} else if (status === 'granted') {
//do something
}
});
});
HTML
<div id="allow-push-notification-bar" class="allow-push-notification-bar">
<div class="content">
<div class="text">
Want to get notification from us?
</div>
<div class="buttons-more">
<button type="button" class="ok-button button-1" id="allow-push-notification">
Yes
</button>
<button type="button" class="ok-button button-1" id="close-push-notification">
No
</button>
</div>
</div>
</div>
This will open a popup after loading the webpage with 2 buttons (Yes/No). Onclick Yes, browser will ask to allow the notification.

That happened to me as well.
If you don't want to use buttons or other element events, you could use a higher-level document click event and request permission from there.
document.addEventListener('click', () => {
Notification.requestPermission().then(function (status) {
if (status === 'denied') {
//
} else if (status === 'granted') {
//
}
});
})

Related

add onClick listener ChromeOS webview

I would like to get the event when the user click on anywhere on the webview.
I tried to add a listener like :
function EnablelistenerClick() {
webview.addEventListener('click', function(e) {
e.preventDefault();
e.stopPropagation();
// DO SOMETHING
});
}
But I catch none of the event. Is it possible to catch event like onClick when the user click on a tag div with onClick="javascript:...." ?
Finally I found a way by using webview.addEventListener('loadstart', function(e) {
console.log("loadstart");
});

Custom chrome extension not launching device list

I'm trying to launch the cast api from a chrome extension that i'm writing. When I run this same code in a regular old HTML file on my webserver, it works perfectly. It doesn't work when I use this code in the popup of my extension. The requestSession call doesn't work at all in that case and nothing seems to happen after it's called.
I believe the expected behaviour is that the google cast extension will show the device list popup. Here is my javascript and html. Most of it is copied right out of CastHelloVideo-chrome.
HTML:
<html>
<head>
<title>Popup</title>
<style>
body {
min-width:5px;
overflow-x:hidden;
}
</style>
<script type="text/javascript" src="https://www.gstatic.com/cv/js/sender/v1/cast_sender.js"></script>
</head>
<body>
<button type="button" id="castButton">Cast!</button>
</body>
<script type="text/javascript" src="popup.js"></script>
</html>
Javascript:
//Constants
var applicationID = "<App ID>";
var session;
var currentMediaSession;
///////////////////////////////////////////////////////////////////
//Chromecast API
///////////////////////////////////////////////////////////////////
if (!chrome.cast || !chrome.cast.isAvailable) {
setTimeout(initializeCastApi, 1000);
}
function loadMedia() {
if (!session) {
console.log("no session");
return;
}
var mediaInfo = new chrome.cast.media.MediaInfo('http://commondatastorage.googleapis.com/gtv-videos-bucket/big_buck_bunny_1080p.mp4');
mediaInfo.contentType = 'video/mp4';
var request = new chrome.cast.media.LoadRequest(mediaInfo);
request.autoplay = false;
request.currentTime = 0;
session.loadMedia(request,
onMediaDiscovered.bind(this, 'loadMedia'),
onMediaError);
}
/**
* callback on success for loading media
* #param {Object} e A non-null media object
*/
function onMediaDiscovered(how, mediaSession) {
console.log("new media session ID:" + mediaSession.mediaSessionId);
currentMediaSession = mediaSession;
}
/**
* callback on media loading error
* #param {Object} e A non-null media object
*/
function onMediaError(e) {
console.log("media error");
}
//////////////////////////////////////////////////////////////////
//UI
//////////////////////////////////////////////////////////////////
var castbutton = document.getElementById("castButton");
castButton.onclick=function(){
window.close();
chrome.cast.requestSession(onRequestSessionSuccess, onLaunchError);
// loadMedia();
};
//////////////////////////////////////////////////////////////////
//Helper Functions
//////////////////////////////////////////////////////////////////
function initializeCastApi() {
var sessionRequest = new chrome.cast.SessionRequest(applicationID);
var apiConfig = new chrome.cast.ApiConfig(sessionRequest,
sessionListener,
receiverListener);
chrome.cast.initialize(apiConfig, onInitSuccess, onError);
}
function sessionListener(e) {
console.log('New session ID: ' + e.sessionId);
session = e;
}
function receiverListener(e) {
console.log(e);
}
function onInitSuccess() {
console.log("init success");
}
function onError() {
console.log("error");
}
function onSuccess(message) {
console.log(message);
}
function onRequestSessionSuccess(e) {
session = e;
console.log("session created");
}
function onLaunchError(e) {
console.log(e.description);
}
I think this may be caused because I'm trying to run this out of the popup of my extension. Maybe chrome doesn't allow multiple plugins to show their (the device list is google cast's popup) popup window's at the same time? I've tried closing the popup before executing the requestSession call, but it still doesn't work. Anyone have any ideas?
Invoking requestionSession API call within a Chrome extension is not supported. That's why you cannot get a list of devices.
In any case this method call only works from a regular web page and it triggers the extension to show a pop-up of Cast devices. That's the only current way it's supposed to work.

Can I detect fullscreen in a Chrome extension?

I have a Chrome extension (specifically, a "content script") where I'd like to detect whether the page I am monitoring/changing is in fullscreen state. I have tried several APIs, as well as the "screenfull" library, but no luck so far. Any ideas?
Thanks for your help!
If you want to detect whether the page has used the Fullscreen API to enter fullscreen mode, just check document.webkitIsFullscreen.
If you want a general method to reliably detect full screen mode, the chrome.windows API is your only option. Since this API is unavailable to content scripts, you need to use the message passing API to interact with a background or event page.
Example: content script
function isFullScreen(callback) {
chrome.runtime.sendMessage('getScreenState', function(result) {
callback(result === 'fullscreen');
});
}
// Example: Whenever you want to know the state:
isFullScreen(function(isFullScreen) {
alert('Window is ' + (isFullScreen ? '' : 'not ') + 'in full screen mode.');
});
Example: background / event page
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
if (message === 'getScreenState') {
chrome.windows.get(sender.tab.windowId, function(chromeWindow) {
// "normal", "minimized", "maximized" or "fullscreen"
sendResponse(chromeWindow.state);
});
return true; // Signifies that we want to use sendResponse asynchronously
}
});
You can try something like this:
var isFullScreen = (screen.width == window.outerWidth) && (screen.height == window.outerHeight);
if(isFullScreen) {
// ...
}
The simplest way is to listen for webkitfullscreenchange event, e.g
$(document).on('webkitfullscreenchange',function(){
if (document.webkitIsFullScreen === true) {
console.log('Full screen mode is on");
} else {
console.log('Full screen mode is off");
}
});

$scope.$apply doesn't do anything in a Chrome extension popup

I'm writing a chrome extension that consists of a background process and a popup. The background process continually makes ajax requests to get new data, and the popup displays the info.
In an extremely simplified way, the background.js process looks like this:
var Background = {
data: {},
poll: function() {
$.ajax({
url: 'some_url',
success: function(data) {
this.data = data;
chrome.extension.sendMessage('update');
}.bind(this)
});
},
startPolling: function() {
setInterval(this.poll.bind(this), 10000);
}
};
$(Background.startPolling.bind(Background));
This shoots of an ajax request every 10 seconds, gets some data back, and sets it to Background.data. Again, this is very simplified. You can see the sendMessage call in the success callback.
My popup.js looks something like this, also extremely simplified:
var Background = chrome.extension.getBackgroundPage().Background;
angular.module('App', [])
.controller('PopupCtrl', function PopupCtrl($scope) {
$scope.data = Background.data;
chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
if (request == 'update') {
console.log('update');
$scope.$apply();
}
});
});
And of course, popup.html looks something like:
<html ng-app="App" ng-csp>
<body ng-controller="PopupCtrl">
<p>{{data.title}}</p>
<p>{{data.body}}</p>
<p>{{data.date}}</p>
</body>
</html>
The message is definitely received, because I can see "update" print to the console every 10 second interval. I also know that the data is being updated properly because if I close and reopen the popup, the new data is displayed correctly. So $scope.$apply() is simply not doing anything.
How can I fix this?

window.onbeforeunload not working in chrome

This is the code which i used for window.onbeforeunload
<head>
<script>
window.onbeforeunload = func;
function func()
{
var request = new XMLHttpRequest();
request.open("POST", "exit.php", true);
request.onreadystatechange = stateChanged;
request.send(null);
}
function stateChanged()
{
if (request.readyState == 4 || request.readyState == "complete")
alert("Succes!");
}
</script>
</head>
this works with IE and Mozilla but does not work with Chrome..... please help......
thanks in advance.....
It seems that the only thing you can do with onbeforeunload in recent version of Chrome is to set the warning message.
window.onbeforeunload = function () {
return "Are you sure";
};
Will work. Other code in the function seems to be ignored by Chrome
UPDATE: As of Chrome V51, the returned string will be ignored and a default message shown instead.
Know I'm late to this, but was scratching my head why my custom beforeunload message wasn't working in Chrome and was reading this. So in case anyone else does the same, Chrome from Version 51 onwards no longer supports custom messages on beforeunload. Apparently it's because the feature has been misused by various scams. Instead you get a predefined Chrome message which may or may not suit your purposes. More details at:
https://developers.google.com/web/updates/2016/04/chrome-51-deprecations?hl=en#remove-custom-messages-in-onbeforeload-dialogs
Personally do not think the message they've chosen is a great one as it mentions leaving the site and one of the most common legitimate uses for onbeforeunload is for dirty flag processing/checking on a web form so it's not a great wording as a lot of the time the user will still be on your site, just have clicked the cancel or reload button by mistake.
You should try this:
window.onbeforeunload = function(e) {
e.returnValue = 'onbeforeunload';
return 'onbeforeunload';
};
This works on latest Chrome. We had the same issue the e.returnValue with value of onbeforeunload solved my problem.
Your code should be like this:
<head>
<script>
window.onbeforeunload = function(e) {
e.returnValue = 'onbeforeunload';
func();
return ''onbeforeunload'';
};
function func()
{
var request = new XMLHttpRequest();
request.open("POST", "exit.php", true);
request.onreadystatechange = stateChanged;
request.send(null);
}
function stateChanged()
{
if (request.readyState == 4 || request.readyState == "complete")
alert("Succes!");
}
</script>
</head>
Confirmed this behavior on chrome 21.0.1180.79
this seems to work with the same restritions as XSS, if you are refreshing the page or open a page on same domain+port the the script is executed, otherwise it will only be executed if you are returning a string (or similar) and a dialog will be shown asking the user if he wants to leans or stay in the page.
this is an incredible stupid thing to do, because onunload/onbeforeunload are not only used to ask/prevent page changes.
In my case i was using it too save some changes done during page edition and i dont want to prevent the user from changing the page (at least chrome should respect a returning true or change the page without the asking if the return is not a string), script running time restrictions would be enought.
This is specially annoying in chrome because onblur event is not sent to editing elements when unloading a page, chrome simply igores the curent page and jumps to another. So the only change of saving the changes was the unload process and it now can't be done without the STUPID question if the user wants to change it... of course he wants and I didnt want to prevent that...
hope chrome resolves this in a more elegant way soon.
Try this, it worked for me:
window.onbeforeunload = function(event) {
event.returnValue = "Write something clever here..";
};
Try this. I've tried it and it works. Interesting but the Succes message doesn`t need confirmation like the other message.
window.onbeforeunload = function()
{
if ( window.XMLHttpRequest )
{
console.log("before"); //alert("before");
var request = new XMLHttpRequest();
request.open("POST", "exit.php", true);
request.onreadystatechange = function () {
if ( request.readyState == 4 && request.status == 200 )
{
console.log("Succes!"); //alert("Succes!");
}
};
request.send();
}
}
None of the above worked for me. I was sending a message from the content script -> background script in the before unload event function. What did work was when I set persistent to true (in fact you can just remove the line altogether) in the manifest:
"background": {
"scripts": [
"background.js"
],
"persistent": true
},
The logic is explained at this SO question here.
Current versions of Chrome require setting the event's returnValue property. Simply returning a string from the event handler won't trigger the alert.
addEventListener('beforeunload', function(event) {
event.returnValue = 'You have unsaved changes.';
});
I'm running Chrome on MacOS High Sierra and have an Angular 6 project whithin I handle the window.beforeunload an window.onbeforeunload events. You can do that, it's worked for me :
handleUnload(event) {
// Chrome
event.returnValue = true;
}
It show me an error when I try to put a string in event.returnValue, it want a boolean.
Don't know if it allows custom messages to display on the browser.
<script type="text/javascript">
window.addEventListener("beforeunload", function(e) {
e.preventDefault(); // firefox
e.returnValue = ''; // Chrome
});
</script>

Resources