Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Emit message to add-on from content script onbeforeunload?

I have a content script which times how long a user views a page. To do this, I inject a content script into each page, start a timer and then emit a message back to the add-on when the onbeforeunload event is triggered.

The message never seems to get passed to the background script however.

Given that my main.js looks like this:

var pageMod = require('page-mod'),
    self = require("self");

pageMod.PageMod({
  include: "http://*",
  contentScriptFile: [self.data.url('jquery.min.js'),
                      self.data.url('content.js')],
  onAttach: function(worker) {
    worker.port.on('pageView', function(request) {
      console.log("Request received");
    });
  }
});

I can send a message to main.js using the following code no problem.

self.port.emit('pageView', { visitTime: time });

I run into a problem when I try to do it as the user leaves the page however. The message is never received when I do it like this:

$(window).bind('onbeforeunload', function(e) {
  self.port.emit('pageView', { visitTime: time });
  // This should prevent the user from seeing a dialog.
  return undefined;
});

I've tried listening for beforeunload too, that doesn't work either. What could be the problem?

like image 860
David Tuite Avatar asked Aug 23 '12 13:08

David Tuite


2 Answers

The window object that content scripts access in Firefox browser add-ons is a proxy object and can be a little temperamental. Using window.addEventListener will work.

window.addEventListener('beforeunload', function(e) {
  # Do stuff then return undefined so no dialog pops up.
  return undefined
});
like image 50
David Tuite Avatar answered Sep 29 '22 10:09

David Tuite


The onbeforeUnload event is not synchronous, so the browser garbage collects the page before it is finished. Use a synchronous AJAX request:

function Data() 
 {
 var client = new XMLHttpRequest();
 client.open("GET", "/request", false); // third paramater indicates sync xhr
 client.setRequestHeader("Content-Type", "text/plain;charset=UTF-8");
 client.send({ visitTime: time });
 client.onreadystatechange = emitter;
 }

function emitter()
 {
 self.port.emit('pageView', { visitTime: time });
 }

or return a string as an alternative.

like image 25
Paul Sweatte Avatar answered Sep 29 '22 09:09

Paul Sweatte