rpmansion
rpmansion

Reputation: 2014

How to prevent chrome extension to reopen the same popup window while it's still open?

I'm working on a chrome extension that has a login popup window. So the idea is for the extension to work it would require user to login so that it could interact with our API and get/post data.

So I override the browserAction to check if the user is logged in or not then if it is not it should show a login popup. My problem is when I click again the extension icon it reopens the same login popup window. How do I prevent that to happen and only one instance of login window should appear if it is open?

background.js

// omitted some codes for brevity
chrome.browserAction.onClicked.addListener(function () {
    // omitted some codes for brevity
    chrome.windows.create({ 
        'url': 'login.html', 
        'type': 'popup',
        'width': width,
        'height': height,
        'left': (screen.width/2) - (width/2),
        'top': (screen.height/2) - (height/2),
        'focused': true
    });
});

Upvotes: 0

Views: 2368

Answers (1)

Makyen
Makyen

Reputation: 33296

There are multiple ways that you can do this.

Use chrome.tabs.query() to detect window is open

You could check for the existence of your popup window by calling chrome.tabs.query():

var popupUrl = chrome.runtime.getURL('/login.html');
chrome.tabs.query({url:popupUrl},function(tabs){
    if(tabs.length > -1){
        //The popup exists
    }
});

In order for the above to work, you have to declare the tabs permission.

However, chrome.tabs.query() will not detect the popup window during the time between the call to chrome.windows.create() and when the window actually opens. Based on testing, this time is long enough for the user to click the browser action button multiple times, opening multiple popup windows.

Keep track of the popup window with a global variable

Given the drawbacks of using chrome.tabs.query() to detect the window, my preference is to use a global variable to hold the current state of the popup window. In the code below, the variable popupWindowId can have three general states:

  • false : Window is not open
  • true : Window is in the process of being opened
  • typeof popupWindowId === 'number' : Popup window is open. The number is the window ID.

If the user clicked the browser action button, then the user wants the popup. While, we don't want to open a new popup, we do want to provide the user with what they want. Thus, if the popup is already open, then the popup window is focused. This will bring it to the top, showing it to the user. A full implementation should also check that the popup window is within the visible bounds of the screen. If it is not visible, then it should be moved to be visible. This later functionality is not implemented here.

To detect when the popup window is closed, a chrome.windows.onRemoved listener is used.

I also like to provide feedback to the user of what is going on, so the title of the popup is changed to "Popup window is already open. Click to focus popup." while the popup is open. When the window is closed, the title is changed back to "Open popup window".

background.js:

var windowNotOpenTitle = 'Open popup window';
var windowIsOpenTitle = 'Popup window is already open. Click to focus popup.';
var popupWindowId = false; //popupWindowId can be true, false, or the popup's window Id.
chrome.browserAction.onClicked.addListener(function () {
    let width= 400;
    let height= 300;
    if(popupWindowId === false){
        popupWindowId = true; //Prevent user pressing pressing the button multiple times.
        chrome.browserAction.setTitle({title:windowIsOpenTitle});
        chrome.windows.create({ 
            'url': 'login.html', 
            'type': 'popup',
            'width': width,
            'height': height,
            'left': (screen.width/2) - (width/2),
            'top': (screen.height/2) - (height/2),
            'focused': true
        },function(win){
            popupWindowId = win.id;
        });
        return;
    }else if(typeof popupWindowId === 'number'){
        //The window is open, and the user clicked the button.
        //  Focus the window.
        chrome.windows.update(popupWindowId,{focused:true});
    }
});
chrome.windows.onRemoved.addListener(function (winId){
    if(popupWindowId === winId){
        //chrome.browserAction.enable();
        chrome.browserAction.setTitle({title:windowNotOpenTitle});
        popupWindowId = false;
    }
});

Upvotes: 5

Related Questions