MozillaZine

Cross-window background code... Ideas/Explanation?

Talk about add-ons and extension development.
asqueella
 
Posts: 4019
Joined: November 16th, 2003, 3:05 am
Location: Russia, Moscow

Post Posted January 30th, 2006, 4:49 am

You could just use the wrappedJSObject trick in that case - interfaces make the code look cleaner, but if you need to just share a JS object across windows, wrappedJSObject may be the way to go (it's certainly easier).

BenBasson
Moderator

User avatar
 
Posts: 13671
Joined: February 13th, 2004, 5:49 am
Location: London, UK

Post Posted January 30th, 2006, 6:11 am

I did think about it, but my components don't seem to register without the IDL. I might have another look at getting that to work though. I'd rather send back arbitrary objects to save time (and save on getter methods), but it's not critical.

TheOneKEA

User avatar
 
Posts: 4864
Joined: October 16th, 2003, 5:47 am
Location: Somewhere in London, riding the Underground

Post Posted January 30th, 2006, 6:45 am

This thread ought to be stickied. I agree with asqueella that good documentation on creating XPCOM components using JavaScript is thin on the ground, and using a sticky to collect information that could make its way into the MozillaZine KB would be invaluable to all extension developers.
Proud user of teh Fox of Fire
Registered Linux User #289618

asqueella
 
Posts: 4019
Joined: November 16th, 2003, 3:05 am
Location: Russia, Moscow

Post Posted January 30th, 2006, 9:47 am

I did think about it, but my components don't seem to register without the IDL.

They should. It works for me.

richwklein
 
Posts: 331
Joined: November 24th, 2002, 8:20 pm
Location: Iowa

Post Posted February 2nd, 2006, 12:20 pm

Cusser wrote:I tried the "any" type, but XPIDL rejected it. I'm not really sure on it's use. I also tried using a struct, but it seems that the syntax requires that a struct is declared inside a module, which I'm not using... I'm declaring the interfaces globally, since doing otherwise appears to break their registration.

Ultimately, I can play with this later, but thanks anyway. For now, I intend to use methods returning arrays or single values, it's easier and I need to get on with the actual implementation :)


You could try using an nsIVariant interface for your data.

XPConnect has magic to transparently convert between nsIVariant and JS types.


so at the top of your idl, you would declare the interfaces used like:

<pre>
interface nsIVariant;
</pre>

then in the interface you are defining you would do something like:

<pre>
nsIVariant getData(in PRUint32 aType);
</pre>
My Extensions:
<a href="http://forecastfox.mozdev.org">Forecastfox</a>
<a href="http://tipbar.mozdev.org">Tip of the Day</a>
<a href="http://urlnav.mozdev.org">Location Navigator</a>
<a href="http://finder.mozdev.org">Finder</a>
<a href="http://rsszilla.mozdev.org">RSSzilla</a>

Daniel_Orner
 
Posts: 118
Joined: May 26th, 2005, 11:06 am

Post Posted February 3rd, 2006, 10:07 am

While we're here... I noticed this:

I've never used IDL to define an XPCOM object


The instructions I'm looking at (Creating XPCOM Components) say that you need both an IDL and a JS file to define an XPCOM object. Can it be done without an IDL file? If so, how?

richwklein
 
Posts: 331
Joined: November 24th, 2002, 8:20 pm
Location: Iowa

Post Posted February 3rd, 2006, 11:59 am

You only need an idl when you define a new interface. If you are using existing interfaces, it isn't needed.
My Extensions:
<a href="http://forecastfox.mozdev.org">Forecastfox</a>
<a href="http://tipbar.mozdev.org">Tip of the Day</a>
<a href="http://urlnav.mozdev.org">Location Navigator</a>
<a href="http://finder.mozdev.org">Finder</a>
<a href="http://rsszilla.mozdev.org">RSSzilla</a>

Daniel_Orner
 
Posts: 118
Joined: May 26th, 2005, 11:06 am

Post Posted February 3rd, 2006, 12:01 pm

How do you access an XPCOM object in JS without an interface? O_o

old zeniko
 
Posts: 0
Joined: December 31st, 1969, 5:00 pm

Post Posted February 3rd, 2006, 12:58 pm

You can't. However for what you apparently want to do, you don't have to use your JS object as an XPCOM object. If you look closely at the <a href="jar:http://mozilla.dorando.at/keyconfig.xpi!/components/keyconfig-service.js">keyconfig component</a>, you'll note how the object is actually injected into each window:
Code: Select all
aSubject.keyconfig = {service: this};

For the domwindowopened notification, aSubject is the newly opened window. So you can access your object inside each window as if it were created in an overlay to browser.xul (i.e. as if you had written var keyconfig = { service: { /* your component here */ } }; in your extensions overlay code).

In fact, you could even write
Code: Select all
aSubject.yourObject = this;

in your component's observe method. That'd be the final equivalent to
Code: Select all
var yourObject = { ... };

in your "normal" code.

Daniel_Orner
 
Posts: 118
Joined: May 26th, 2005, 11:06 am

Post Posted February 5th, 2006, 8:11 am

OK, looks like a great idea! Thanks!

EDIT: As I thought, I'm running into problems. -_- I'm getting "histree is not defined" in my browser windows. I put the following file (which I named "histree-service.js") in the components subdirectory... any idea what's going wrong?
By the way, I tried putting an alert statement in the "initHistree" function, and it didn't fire. Not sure if that's because the function isn't getting called (even though it's right there in the domwindowopened observer) or because the window isn't defined for some reason...?

Code: Select all
function NSGetModule(compMgr, fileSpec) { return histreeModule; }

var histreeModule = {
  CID: Components.ID("{4a4bb6c4-94e4-11da-956a-00e08161165f}"),
  contractID : "@mozilla.org/histree;1",
  className  : "histreeService",

  registerSelf: function (aComponentManager, aFileSpec, aLocation, aType)
  {
    aComponentManager = aComponentManager.QueryInterface(Components.interfaces.nsIComponentRegistrar);

    aComponentManager.registerFactoryLocation(this.CID, this.className, this.contractID, aFileSpec, aLocation, aType);

    var CategoryManager = Components.classes["@mozilla.org/categorymanager;1"]
                                    .getService(Components.interfaces.nsICategoryManager);
    CategoryManager.addCategoryEntry("app-startup", this.className, "service," + this.contractID, true, true, null);
  },
 
  getClassObject: function (aComponentManager, aCID, aIID)
  {
    if (!aIID.equals(Components.interfaces.nsIFactory)) throw Components.results.NS_ERROR_NOT_IMPLEMENTED;

    if (aCID.equals(this.CID)) return this.factory;
   
    throw Components.results.NS_ERROR_NO_INTERFACE;
  },

  factory: {
    createInstance: function (aOuter, aIID)
    {
      if (aOuter != null) throw Components.results.NS_ERROR_NO_AGGREGATION;

      return new histreeService();
    }
  },
 
  canUnload: function () { return true; }
};

function histreeService() { }

histreeService.prototype = {
  observe: function (aSubject, aTopic, aData)
  {
     var os = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
    if(aTopic == "app-startup")
     {   os.addObserver(this,"domwindowopened",false);
      os.addObserver(this, "domwindowclosed", false);
     }
    else if(aTopic == "domwindowopened")
    {
      aSubject.histree = this;
     aSubject.histree.initHistree();
     aSubject.addEventListener("load", histree.newWindow, false);
    }
   else if (aTopic == "domwindowclosed")
   {
      for (var i = 0; i < aSubject.histree.windows.length; i++)
      {   if (aSubject.histree.windows[i].window == aSubject)
         {   aSubject.histree.windows.splice(i, 1);
            return;
         }
      }
   }
  },
//////more attributes/functions which were copied and pasted from my original object
}

asqueella
 
Posts: 4019
Joined: November 16th, 2003, 3:05 am
Location: Russia, Moscow

Post Posted February 5th, 2006, 10:50 am

How do you access an XPCOM object in JS without an interface? O_o

via wrappedJSObject, see above.

Daniel_Orner
 
Posts: 118
Joined: May 26th, 2005, 11:06 am

Post Posted February 5th, 2006, 10:51 am

Nowhere in this thread does it actually explain what the "wrappedJSObject trick" is, though everyone's referencing it all the time. -_-

asqueella
 
Posts: 4019
Joined: November 16th, 2003, 3:05 am
Location: Russia, Moscow

Post Posted February 5th, 2006, 10:55 am

It was mentioned in the previous thread on this topic: http://forums.mozillazine.org/viewtopic ... 74#1863874

[edit]
basically:
Code: Select all
// in the component code you set the magical property wrappedJSObject on the component instance in constructor:
function MyComponentImpl {
  this.wrappedJSObject = this; // or any other JS object
}
MyComponentImpl.prototype = {
  l: 1,
 // ...
};

// then in the caller you can access that object easily:
var o = Components.classes[mycontractid].getService/createInstance().wrappedJSObject;
alert(o.l); // alerts 1

Daniel_Orner
 
Posts: 118
Joined: May 26th, 2005, 11:06 am

Post Posted February 5th, 2006, 12:24 pm

OK... I'm slowly getting there. But I've got this very weird error that just popped up.

Part of my component code:
Code: Select all
//Called on startup.
initHistree: function(aWindow)
{ /*...*/
   aWindow.addEventListener("load", this.newWindow, false);
}

/**... stuff... **/

//Called when a window is created.
newWindow: function(aEvent)
{   aEvent.currentTarget.removeEventListener("load", this.newWindow, false);   
   var win = aEvent.currentTarget.top;
   if (!win.getBrowser) return; //not a browser window
   this.addWindowListeners(win);
},
/*** More stuff... ***/
addWindowListeners: function(aWindow)
{ /**...**/
}


The weird thing is that the term "this" inside newWindow suddenly seems to be referring to the ChromeWindow object, not my component object! So addWindowListeners isn't defined any more. I can't use a reference to the object itself (as defined in my overlay code) since it doesn't know about it yet. -_- I tried replacing "this" with histreeService.prototype (histreeService being my component object), but I then simply get two "uncaught exception: null" in the JS console.

I am STUMPED.

asqueella
 
Posts: 4019
Joined: November 16th, 2003, 3:05 am
Location: Russia, Moscow

Post Posted February 5th, 2006, 2:03 pm


Return to Extension Development


Who is online

Users browsing this forum: No registered users and 1 guest