Search code examples
google-chrome-extensiongoogle-nativeclient

How to persist PNaCl process within a Chrome Extension


My team and I have created a Chrome Extension which bundles a PNaCl application to handle multimedia encoding & muxing which is adapted from the Pepper SDK (version 39) examples and the online SDK tutorial. The application's purpose to capture content from the user's desktop, tab, and webcam in order to create multimedia files.

The extension works as expected while it's visible but the PNaCl process is stopped/unloaded when the extension is hidden. I need to know what is the best strategy to persist a PNaCl process when the Chrome Extension is no longer visible.

The PNaCl app is embedded in my primary UI code (in my case this is set to index.html). The extension contains Background Pages which continues to process requests when hidden so I'm confident the manifest.json permissions and process work as expected. Additionally there are no exceptions.

So far I've attempted:

  • Make a background JavaScript page the interface to the PNaCl application so it's reference is stored in the background page which should persist.
  • Create a Chrome Window in order to persist PNaCl application and present a live-preview of the captured stream while the extension is hidden.
  • (Ongoing) Embed the PNaCl container a background HTML page rather primary HTML page which represents the extension UI.

So far none of them have persisted the PNaCl process.

The relevant parts of my manifest.json:

{
    "manifest_version": 2,
    "minimum_chrome_version": "39.0.0.0",

    "offline_enabled": true,

    "permissions":[
        "desktopCapture",
        "tabCapture",
        "tabs",
        "unlimitedStorage"
    ],

    "browser_action":{
        "default_popup": "index.html"
    },

    "background":{
        "scripts": ["helpers.js", "background.js", "capture_state.js"],
        "persistent": true
    }
}

If I'm able to resolve before I get a response I'll respond with a solution.


Solution

  • We've resolved the issue despite the lack of documentation.

    Here are the primary issues:

    Issue #1 - Listener ID in front-end extension code.

    We had our id="listener" inside of our front-end extension code (which is unloaded when the extension is hidden) and manually specifying a background.html page doesn't allow us to use background JavaScript files (a requirement of our application).

    Resolution: We dynamically added the id="listener" and altered the common.js file using document.addElement to the generated background page (which is automatically created when the extension is loaded).

    Issue #2 - getUserMedia method invoked in front-end extension code.

    Our application requires that the streams returned from getUserMedia persist so that we can capture from the mic, webcam, and desktop in the background even if the extension is hidden.

    Since we requested these in the front-end extension code (to create a live-preview) we thought we could simply pass them into the generated background page and they would persist.

    What we found is that when the extension is hidden reading from the streams halts immediately without error. We found this out by digging through our code and monitoring the Chrome Task Manager to see that when the extension was hidden it's CPU usage goes to 0 but it's memory stays elevated (much like phenomena you'd expect when a thread deadlocks or is blocking).

    Resolution: Moving the getUserMedia invocation to one of the background scripts and using the streams it returns resolves this.