4
votes

For my chrome extension, I want to perform an action when the browserAction popup window closes. I understand that there no built-in events are triggered when this happens. I found this suggestion to open a connection with the background script, and then use the connection's port.onDisconnect event to detect that the popup window is closing.

However, when the popup window closes, I see the following error in the Developer Console for the background script:

(BLESSED_EXTENSION context for glkehflnlfekdijfhacccflbffbjhgbd) extensions::messaging:102: Uncaught TypeError: Cannot read property 'destroy_' of undefined{TypeError: Cannot read property 'destroy_' of undefined
   at PortImpl.destroy_ (extensions::messaging:102:37)
   at dispatchOnDisconnect (extensions::messaging:322:29)}

The scripts that I use are detailed below.

Can you see where I am going wrong?


manifest.json

{ "manifest_version": 2

, "name": "Detect when popup closes"
, "version": "0.1"

, "browser_action": {
    "default_icon": "popup.png"
  , "default_popup": "popup.html"
  }

, "background": {
    "scripts": [
      "background.js"
    ]
  }
}

popup.html

<!DOCTYPE html>
<body>
  <h1>Test</h1>

  <script src="popup.js"></script>  
</body>
</html>

popup.js

var port = chrome.runtime.connect()

background.js

chrome.runtime.onConnect.addListener(function (externalPort) {
  externalPort.onDisconnect = function () {
    try { 
      var ignoreError = chrome.runtime.lastError
    } catch (error) {
      console.log("onDisconnect")
    }
  }
)
2
The suggestion was to detect the event in background script. The port is disconnected because the popup was destroyed so there are no event listeners left to be invoked on port disconnection. - wOxxOm
@wOxxOm I've rewritten my bare-bones extension to use port.onDisconnect in the background script, as you suggest. However, this merely displaces the error to the moment when the popup window closes. - James Newton
The error in this case is documented and may be ignored by simple assignment var ignoreError = chrome.runtime.lastError. The important thing is that the disconnect listener will actually fire. - wOxxOm
@wOxxOm I've added the assignment that you suggested, but I doubt that I have put it in the right place. Perhaps the disconnect listener fires, but the error prevents me from getting it to do anything useful. - James Newton
@JamesNewton I rolled back your "SOLVED" edit; in future, please post your own solution (if it's appropriate) as a separate answer - self-answering is absolutely okay, but mixing answers into questions is not. Also, there's no need to tag your question as solved in the title (the fact that there is an accepted answer is enough). - Xan

2 Answers

11
votes

For reference, here's the working version of the background.js script:

chrome.runtime.onConnect.addListener(function (externalPort) {
  externalPort.onDisconnect.addListener(function () {
    console.log("onDisconnect")
    // Do stuff that should happen when popup window closes here
  })

  console.log("onConnect")
})
6
votes

onDisconnect is not an assignable property.
It's an object that provides addListener method to register a callback:

externalPort.onDisconnect.addListener(function() {
    var ignoreError = chrome.runtime.lastError;
    console.log("onDisconnect");
});