Search code examples
javascriptgoogle-chromegoogle-chrome-extension

Chrome extension - button listener on notification executes multiple times


I am writing a chrome extension that makes requests to an API and I have noticed that after I create a notification from background script using chrome's notification API, the listeners on the buttons from the notification are executed multiple times. on the first run only once and then increasing. I figured that the listeners just add up on the page but I couldn't find a way to sort of refresh the background page.

This is the function that creates the notification and it's listeners.

var myNotificationID
const displayNotification=(userEmail, password, website,username) =>{
    chrome.notifications.create("", {
        type:    "basic",
        iconUrl: "./icon128.png",
        title:   "PERMISSION",
        requireInteraction: true,
        message: "question",
        buttons: [{
            title: "YES",
        }, {
            title: "NO",
        }]
    }, function(id) {
        myNotificationID = id;
    })

    chrome.notifications.onButtonClicked.addListener(function(notifId, btnIdx) {
        if (notifId === myNotificationID) {
            if (btnIdx === 0) {
                console.log('inserting')
                try{
                    fetch (`http://localhost:8080/users/${userEmail}/accounts`,{      
                    })
                }catch(err){ 
                }
            } else if (btnIdx === 1) {
                console.log('clearing')
                chrome.notifications.clear(myNotificationID)
            }
        }
    });
}

And this is where the function is called

chrome.runtime.onMessage.addListener((message, sender, response)=>{
    if(message.message === 'showNotification'){
        console.log('received insert')
        displayNotification(message.userEmail,message.password, message.currentSite,message.username)
        response({status:"received"})
    }
})

the fetch within the listener is executed multiple times but the log from the onMessage listener is only displayed once, so the listener is the problem here. I tried chrome.notifications.onButtonClicked.removeListener(), but as i mentioned there was no success. Are there any other ways in which i could clean the listeners from the background script once they are used?


Solution

  • Using a notification store:

    const notificationsByID = {};
    
    chrome.notifications.onButtonClicked.addListener((notifId, btnIdx) => {
        // Avoid access to the notification if not registered by displayNotification
        if (!notificationsByID[ notifId ]) { return null; }
        if (btnIdx === 0) {
            console.log('inserting')
            try{
                fetch (`http://localhost:8080/users/${ notificationsByID[ notifId ].userEmail }/accounts`,{ /**/ });
            }catch(err){
                console.log(err);
            }
            delete notificationsByID[ notifId ]; // Cleanup
        } else if (btnIdx === 1) {
            console.log('clearing')
            chrome.notifications.clear(myNotificationID);
            delete notificationsByID[ notifId ]; // Cleanup
        }
    });
    
    chrome.notifications.onClosed.addListener((notifId) => {
        if (notificationsByID[ notifId ]) { delete notificationsByID[ notifId ]; }
    });
    
    const displayNotification=(userEmail, password, website,username) =>{
        chrome.notifications.create("", {
            type:    "basic",
            iconUrl: "./icon128.png",
            title:   "PERMISSION",
            requireInteraction: true,
            message: "question",
            buttons: [{ title: "YES", }, { title: "NO", }]
        }, function(id) {
            // Insertion
            notificationsByID[ id ] = { userEmail, password, website,username };
        })
    }