SendAsyncMessage Document Object Sending

Talk about add-ons and extension development.
Post Reply
Sebastien Parisia
Posts: 4
Joined: May 15th, 2016, 7:31 pm

SendAsyncMessage Document Object Sending

Post by Sebastien Parisia »

Hi,

Is it possible to send document object from content script to index.js for add-on sdk? Firefox Develoepers throws it is not cloneable error.

Thanks in advance
lithopsian
Posts: 3664
Joined: September 15th, 2010, 9:03 am

Re: SendAsyncMessage Document Object Sending

Post by lithopsian »

This is from a frame script, right? You can send any object, but it sounds like you are trying to send it as data instead of as an object. The second parameter to sendAsyncMessage is an object which is cloned and passed to the receiver. A document cannot be cloned. The *third* parameter is optional and is an object each of whose properties can also be an object. These are *wrapped* and passed without being cloned. This is how you would pass a document. The message receiver can treat the document largely as if it was an actual document object, but it is actually a cross-process object wrapper (CPOW).

CPOWs automatically generate inter-process messages when you access them, which means you now have synchronous access to the content process. That can simplify your code and is almost essential in some situations such as working in a popupshowing handler, but it comes with its own set of problems. First, it is slow, orders of magnitudes slower than a normal javascript object access. This may be acceptable for one or two accesses in a non-critical path but would be a problem for multiple accesses that occur regularly. Second, the object may not exist any more, oops! So your code may throw. Potentially, accessing CPOWs can also cause deadlocks and crashes. Except in very specific situations it isn't possible to guarantee that it is safe to use a CPOW, although it is quite rare for anything bad to happen except just being very slow. Lastly, you cannot pass a CPOW to many Firefox functions that expect the underlying object.
Noitidart
Posts: 1168
Joined: September 16th, 2007, 8:01 am

Re: SendAsyncMessage Document Object Sending

Post by Noitidart »

Try to find some other way. You shouldn't have to send a document from one process to another. You should just be needing small bits of data. If you need the whole document, you should strongly consider reworking your code, instaed of going with the CPOW.

I origianlly started with CPOWs but saw the perf was much less. I reworked everything, and for sure I was able to get it down to just small serializable bits of data. In the end result, it was the best thing I could have done, definitely worth the time spent.
Sebastien Parisia
Posts: 4
Joined: May 15th, 2016, 7:31 pm

Re: SendAsyncMessage Document Object Sending

Post by Sebastien Parisia »

Guys thanks but I need document object because I want to save web page by toolbar button click.

It is like Save Page As context menu but by toolbar button.

I looked into dource code from nsContextMenu.js.

Right click menu uses saveDocument method availabkle for main Window.

I decided I could call

window.saveDcoument(document,true);

by toolbar button of Add-on SDK add-on.

It is simple and works for Firefox 46.

But Firefox 47 is electrolysis and I can not get document object no matter what.

I get CPOW error.

Then I thought I can pass window object to content script, or document object to index.js

Both did not help.

Does this mean Electrolysis prevents low level add-on stuff and Frefox can not be extendede anymore like it used to be?
Sebastien Parisia
Posts: 4
Joined: May 15th, 2016, 7:31 pm

Re: SendAsyncMessage Document Object Sending

Post by Sebastien Parisia »

Code: Select all

var code = `
    addMessageListener("to-child", function(message) {
      message.target.sendAsyncMessage("finish", message.data);
    });
`;

  var tab = gBrowser.addTab();
  var browser = tab.linkedBrowser;

  browser.messageManager.loadFrameScript('data:,' + code, false);

  browser.messageManager.sendAsyncMessage("to-child", {
    set: new Set([1, 2, 3]),
    logins: []
  });

  browser.messageManager.addMessageListener("finish", (msg) => {
    console.log(msg);
    console.log(msg.data.set instanceof Set, "received a set");
    console.log(msg.data.set.has(1), "has 1");
    console.log(!msg.data.set.has(4), "no 4");
    gBrowser.removeTab(tab);
  });
This works.
Sebastien Parisia
Posts: 4
Joined: May 15th, 2016, 7:31 pm

Re: SendAsyncMessage Document Object Sending

Post by Sebastien Parisia »

Code: Select all

var code = `
    addMessageListener("to-child", function(message) {
      message.target.sendAsyncMessage("finish", message.data);
    });
`;

  let tab = gBrowser.addTab();
  let browser = tab.linkedBrowser;

  browser.messageManager.loadFrameScript('data:,' + code, false);

  let login = Cc["@mozilla.org/login-manager/loginInfo;1"].
    createInstance(Ci.nsILoginInfo);
  login.init("", "", "", "", "", "", "");

  browser.messageManager.sendAsyncMessage("to-child", {
    set: new Set([1, 2, 3]),
    logins: [login]
  });

  browser.messageManager.addMessageListener("finish", (msg) => {
    console.log(msg);
    console.log(msg.data.set instanceof Set, "received a set");
    console.log(msg.data.set.has(1), "has 1");
    console.log(!msg.data.set.has(4), "no 4");
    gBrowser.removeTab(tab);
  });
This does not work because nsiLoginInfo is passed. Same like document, it throws error. This reaaly prevents low level stuff.
Noitidart
Posts: 1168
Joined: September 16th, 2007, 8:01 am

Re: SendAsyncMessage Document Object Sending

Post by Noitidart »

Sebastien Parisia wrote:Guys thanks but I need document object because I want to save web page by toolbar button click.

It is like Save Page As context menu but by toolbar button.

I looked into dource code from nsContextMenu.js.

Right click menu uses saveDocument method availabkle for main Window.

I decided I could call

window.saveDcoument(document,true);

by toolbar button of Add-on SDK add-on.

It is simple and works for Firefox 46.

But Firefox 47 is electrolysis and I can not get document object no matter what.

I get CPOW error.

Then I thought I can pass window object to content script, or document object to index.js

Both did not help.

Does this mean Electrolysis prevents low level add-on stuff and Frefox can not be extendede anymore like it used to be?
Can't you do the save from the framescript? I think the current way uses CPOWs but that is absolutely bad. Try to find a framescript way :)
Post Reply