Exposing XPCOM components in JavaScript, part three

Generally speaking, untrusted content (such as a web page) can’t do anything with most XPCOM components, including creating them. There are of course exceptions to this policy – DOM objects, for example, are glorified XPCOM components with clearly defined interfaces for public use. For a web page to use a component, however, including calling on any methods or properties, the component has to explicitly tell Mozilla what is allowable and what is not. The nsISecurityCheckedComponent interface defines how that is done.

If your component doesn’t implement nsISecurityCheckedComponent, the most you’ll be able to do with the component is create instances of it, and that’s only if your component has the DOM_OBJECT flag set on it, as I described in part two of this series. You won’t be able to do anything with those instances, not even access any of its properties. So understanding nsISecurityCheckedComponent is also important.

The rest of this article is in the extended section.

Continue reading Exposing XPCOM components in JavaScript, part three

Verbosio: Basic XBL validation, anyone?

Over the last several days, I’ve been working on getting some basic functionality working in Verbosio again, picking up where I left off several months ago. I realized as I was working on this that I had two separate interfaces, one of them exceedingly minor, that could and should be merged. So now, language packs (which describe a particular XML language) will also be able to do some basic validation of their contents.

As part of that, I started thinking about XBL, which I hope will be the first XML language Verbosio will be able to usefully edit. XBL documents, fundamentally, are a mix of XML and JavaScript. So to make sure a XBL document is “valid” (that is, readable by Gecko products), I can combine well-formedness checking in XML with syntax checking in JS… very, very carefully.

The result is a partially-written, untested JavaScript component which does a whole lot of legwork to handle implementation elements, and will soon do similar legwork on handler elements. One factor of the design (which complicates it, but will make it very cool when I get it working) is to figure out where a JavaScript syntax error is in the XBL document and generate a full error message, complete with source code line and exact line number. I’m fairly certain I can pull it off.

Here’s a sneak peek at my “XBL language pack component“. The function in question here is called “getFirstSyntaxError”. Under normal circumstances (no error at all), it would return null. There are probably a dozen little bugs (and half a dozen big ones) lurking in there, but I think I’ll make it workable in the next few days.

If I do succeed at this, it opens up a whole new avenue for Verbosio, as a proof of concept. XUL, XHTML, and SVG documents can all have inline scripts (though not in as complex a structure as XBL does). By mixing XML well-formedness with JavaScript syntax checking, Verbosio could help page authors fix simple bugs on the fly.

Exposing XPCOM components in JavaScript, part two

Whenever a XPCOM component is exposed to a public web page, the page knows nothing about what that component is, what interfaces it implements. Thus, Mozilla code treats it as if it implements only nsISupports, with the handy-dandy QueryInterface() method… and nothing else.

This means web pages would have to QI for every interface they needed, and they would know nothing about what’s available. However, by implementing one more interface, no more instanceof operators would be needed, and you’d have all the properties and methods of the object that you thought you’d have. That interface is nsIClassInfo.

The rest of this article is in the extended section.

Continue reading Exposing XPCOM components in JavaScript, part two

Exposing XPCOM components in JavaScript, part one

Several months ago, I wrote about my solution for sending messages from content to chrome. Today, I’m starting a three-part follow-up, talking about how component authors can provide their components to web pages. This first part is about letting users touch your component. Part two will focus on nsIClassInfo, which eliminates the need for QueryInterface or the instanceof operator by web pages. Part three will focus on nsISecurityCheckedComponent, which regulates what users can do with your component.

Normally, of course, this isn’t done; most XPCOM components should work behind-the-scenes and not be available to web pages. There are exceptions. For instance, the chromeMessenger above is explicitly for web pages to send messages where it normally wouldn’t be able to (but the application still needs someone to listen for that message). Another is my XPathGenerator code, which I thought had to be C++-based. Fortunately, I discovered earlier this week that isn’t the case.

The rest of this article is in the extended section.

Continue reading Exposing XPCOM components in JavaScript, part one

Getting squirrelly (or “So long, and thanks for all the t-shirts”)

Today, I went and attended the “Attack of the Squirrels” Firefox 2.0 launch party in Sunnyvale, CA, USA. Pretty good group of guys. In exchange for an early ride to Cuesta Park from the San Jose Diridon Caltrain Station, I ended up helping buy food and arrange the layout of goodies.

Thanks, everyone, for showing up and helping George have a great time. Although I have to wonder if the new Firefox 2 shirt I have should only be washed with red clothing… because I don’t have many reds… 🙂

(I just thought of that as I wrote this blog entry.)

Verbosio markup templates: check

For editing XML, I wanted to have some sort of template system, where XML markup could be abstracted into a simpler system for reusability and flexibility. I didn’t know of any standardized template system like that, so I wrote one.

Designing the mental model proved relatively easy: XBL’s anonymous content design was inspirational with its <xbl:children/> element. I also needed a repetition model, though, so I came up with a repeat element as well (very different from Web Forms 2’s repeat element). I also wanted to separate the UI from the actual output of the templates. Finally, I wanted to provide, in the design, at least, placeholders for custom XML and JavaScript to override what the template normally does.

Making all that work took a lot longer. So long, in fact, that I created an “experimental” section of Verbosio’s CVS repository to work on it in a minimal-code environment, long enough to get the basics working.

I finished the functionality parts of the XBL bindings two days ago. Then, because I knew no one but me would know how the thing worked, I spent several hours documenting it.

Verbosio’s markup language specification, version 0.1.0.

For those of you with XULRunner trunk, and a desire to see some of it in action, read the full article link for details on testing it.

Next on Verbosio’s agenda: creating the XUL wizard for creating markup templates from already-existing XML markup. If you want to edit XUL, XHTML, etc., and you’ve got samples on hand, this tool would guide you through creating templates you and everyone else could use. Good stuff cooking.

Continue reading Verbosio markup templates: check

Cool tip of the day: Node filters in JS as objects

Typically in Mozilla usage, we use tree walkers like this:

const nsIDOMNodeFilter = Components.interfaces.nsIDOMNodeFilter;
function filter(aNode) {
if ((aNode.namespaceURI == "http://verbosio.mozdev.org/namespaces/foo/") && (aNode.localName == "foo")) {
return nsIDOMNodeFilter.FILTER_ACCEPT;
}
return nsIDOMNodeFilter.FILTER_SKIP;
}
var walker = document.createTreeWalker(rootNode, nsIDOMNodeFilter.SHOW_ELEMENT, filter, true);

The NodeFilter we pass in to the tree walker is usually just a JavaScript function. If you read the DOM 2 Traversal spec carefully, though, this isn’t exactly what the spec would indicate. (It makes a special exemption for JavaScript in the ECMAScript bindings.)

According to the spec, node filters are usually objects (not specifically functions) with an acceptNode(Node aNode) method. What this means is, if we shape the filter as an object, we can give special properties to the node filter.

For example, say you want to accept <foo/> and <bar/> elements, but you want to do something different in each case. You could write the filter to have an acceptedType property:

const nsIDOMNodeFilter = Components.interfaces.nsIDOMNodeFilter;
var filter = {
acceptedType: null,
acceptNode: function acceptNode(aNode) {
if (aNode.localName == "foo") {
this.acceptedType = "foo";
return nsIDOMNodeFilter.FILTER_ACCEPT;
}
if (aNode.localName == "bar") {
this.acceptedType = "bar";
return nsIDOMNodeFilter.FILTER_ACCEPT;
}
return nsIDOMNodeFilter.FILTER_SKIP;
}
}
var walker = document.createTreeWalker(rootNode, nsIDOMNodeFilter.SHOW_ELEMENT, filter, true);
while (walker.nextNode()) {
switch (filter.acceptedType) {
case "foo":
// do something
break;
case "bar":
// do something else
break;
default:
throw new Error("Unexpected type");
}
}

Note that this node filter doesn’t modify the document (no good node filter or tree walker should). It modifies itself in such a way that the code using the tree walker and node filter can detect that state change and act according to what the filter is signaling.

Also, don’t forget to prevent leaks by clearing the tree walker when you’re done with it:

walker = null;
filter = null;

Firefox Logo Party Crackers: A Recipe

With the upcoming Firefox 2 Release Parties, I thought I’d recommend a rather silly idea I had for the last Firefox release party series.

Ingredients: Ritz (TM) crackers, cream cheese, blue food coloring

  1. Mix a little food coloring (one or two drops) with cream cheese. Colors do not have to be even.
  2. Spread on crackers, covering approximately 2/3 of the cracker, leaving an uncovered wedge of each cracker in an arc at the edge.
  3. Refrigerate.

Serving size: number of crackers divided by number of people, dogs, cats, cows, firefoxes, thunderbirds, sunbirds, and seamonkeys in attendance. (Note: No amount of crackers will feed or satisfy any big red stomping lizards that happen to visit your city. They don’t like crackers.)

Based on the Firefox 1.0 party I attended in San Francisco, CA.

P.S. Forgive me if your comments take several days to show up. I just moved apartments, and my Internet connection won’t be back on at home until Tuesday.

Alex Vincent's ramblings about Mozilla technology, authoring, and whatever he feels like.