Enabling Knockout.js to work across iframes

If you haven’t checked out Knockout yet, I highly recommend it.

Knockout allows you to create declarative bindings in your HTML that map to your underlying model’s properties. The nice thing about the bindings being in HTML is that you and your designer team can work in real HTML.

But Knockout’s real magic comes from its dependency tracking. When bound model properties change, Knockout magically updates the bound parts of the HTML that need it. It’s an approach I have used many times that gives you the real benefits of MVC by allowing the view to bind to the model rather than the other way around.

We wrote something similar in Digitalk Smalltalk back in the 90s, and then VisualWorks Smalltalk introduced Aspect Adaptors baked right in. In Knockout these model property trackers are called Observers. It also has something called a Dependency Observer that tracks any model properties accessed during a function call (for example getting the list of users), it then automatically creates observers on those properties. Very cool.

One problem with the current version of Knockout is that there are still a few hurdles preventing it from working across frames or windows: it uses a global state to do its Dependency Observer magic, it does identify class checking (which fails across frames), and it does some things relative to the window the code was loaded into rather than the current element’s window. I have written a couple of patches that cover most of these cases and have submitted a pull request to Steve Sanderson.

Update 3/21/12

After many tweaks and discussions my cross-frame changes have been accepted into Knockout 2.10. See issue 405 for details.

Using IntelliJ IDEA to debug Firefox Extensions

I have been a fan of JetBrains’ IntelliJ IDEA as an IDE for many years, and with WebStorm/PhpStorm (or IntelliJ with the JavaScript plugin) JetBrain really is on their way to having a great JavaScript IDE. What is particularly impressive is how WebStorm/PhpStorm is able to parse out meaning from untyped JS and have knowledge of many of the core JS libraries.

But one problem is that they don’t debug Firefox extensions. I often use ChromeBug for this, but sometimes it’s nice to debug right in the IDE. With a little bit of hacking I found a way to update their debugger so that it can also debug Firefox extensions.

You can get the code on GitHub at WebStorm-Firefox-Connector. I plan to update it with each update of the WebStorm Firefox extension until JetBrains adds this functionality themselves. I’ve submitted the changes to JetBrains as an issue in the hope that they will incorporate my changes into the main product.

To debug extensions with WebStorm/IntelliJ, do the following:

  • Install WebStorm and let it install the Firefox debugger extension
  • Determine what version of the Firefox debugger extension you are using (look in the Add-Ons tab)
  • Download the correct branch from GitHub for your version to replace the contents of the firefox-connector@jetbrains.com directory.
  • Edit the file extensions\firefox-connector@jetbrains.com\chrome\chromeFiles\content\scripts.js to add your chrome URL root to the variable enabledChromeComponents. For example, this allows me to debug an extension named myext:
    • ·         enabledChromeComponents: ["myext"]

 

Most folks won’t care, but it’s worth pointing out that you can’t use WebStorm to debug Firebug itself since they both use JSD, which only supports one debugger client at a time. JSD2 is supposed to fix this, but sometimes I wonder if JSD2 will ever really happen.

I do some work on Firebug, and I have looked a bit into creating a multi-layer-client wrapper for JSD, but haven’t had the time to get it actually working. Besides, the JSD layer is a bit tricky. Let’s just say I’ve gotten used to wishing JSD2 were on the horizon and knowing that it probably isn’t.

 

Update 2/14/11

They have updated the debugger extension (0.4.3) with a good chunk of my changes, but unfortunately not all of them. Looks like I’ll be updating the patched version of the debug extensions for at least a while longer. You can still find the any updates at GitHub.

I was awarded a Firefox Security Bug Bounty Award!

I just received an email from the head of the Mozilla security team that I have been awarded a Security Bug Bounty Award for an sg:critical bug I found in Firefox. For those that don’t know, sg:critical is the highest level of severity and indicates the bug is an “exploitable vulnerability which can lead to the widespread compromise of many users.” That sounds pretty scary, but on the bright side sg:critical means I get the maximum bounty of $3000 (and a t-shirt :). Very cool :).

I don’t want to share more since the vulnerability hasn’t been fixed yet, but as soon as it is I’ll give a full explanation.

Update 9/27/11

The bug is (finally) fixed and has been announced as Mozilla Foundation Security Advisory 2011-43 (CVE-2011-3004), which means I can finally talk about it. The bug deals with the guts of how Firefox wraps unsecure JavaScript objects so the details are a bit complicated. People who are interested in the gritty details should follow the above link. Since the full explanation is a bit much for a blog post I’m just going to summarize it here.

In Firefox the loadSubScript function loads code into the current security context, and since it’s called from an extension the code is loaded in the secure security context. In Firefox 3.6 (and now again in Firefox 11+) any unsecure objects passed in the loadSubScript context are correctly wrapped in a XrayWrapper (XPCNWrapper in Firefox 3.6).

Wrapper ensures that secure code can’t accidently pass an unsecure object to a secure object that can be used as a privilege upgrade attack. There are surprising number ways of doing this in JavaScript without this wrapper protection.

In Firefox 4 a bug was introduced that missed adding these wrappers for loadSubScript. So the secure loaded code was handed unsecure, unwrapped objects.  If a target window (any web page) anticipated this bug they could check for the vulnerability in each user’s browser, and if they found it they could use it to do anything a Firefox extension could do (essentially gaining full access to the user’s system, files … practically everything).

See [post: Inserting JavaScript/CSS…] for one possible use case for loadSubScript (now that it is no longer a security hole).

Inserting JavaScript/CSS in a target page from a Firefox Extension

When you’re working with Firefox extensions you often want to act on the target page, accessing elements or even changing HTML, but JavaScript libraries and jQuery plugins assume that they are always working on the current scope’s global objects.

So every time you find yourself wanting to act on variables like window, document and jQuery you run into a problem.  You could insert the module into the target window using a script tag, but that may conflict with the target window’s JS.

A better solution is to load another instance of these libraries in your own scope tied to the target window’s global variables. One approach is to eval the window inside a context that has remapped the window and document element.

The following code demonstrates this given a passed target window.


createTargetScripts: function(targetWindow) {
   // Create the scripts we will use on the target window, we create them in a closure so they will
   // have the target window and document (but our privilege, and the target objects they use will actually be wrappers).

   (function() {
      var window = targetWindow;
      var document = targetWindow.document;
      eval(evalStringForURL('libs/jquery.js'));
      var jQuery = targetWindow.jQuery;          // Add jQuery to local scope for jQuery plugins
      eval(evalStringForURL('libs/jquery.tmpl-master0405.js'));
      eval(evalStringForURL('libs/jquery.qtip.js'));

   })();

   // Even though the jQuery is on the wrapper, that wrapper may be used by other extensions
   targetWindow.targetJQ = targetWindow.jQuery.noConflict(true);

   } ,
   readURLSync: function(url) {
      var data = myExtensionJQ.ajax({
         url: url,
         async: false,
         dataType: "text",
         mimeType: 'text/plain; charset=x-user-defined'
         }).responseText;
      return data;
   },

   // Add sourceURL so debuggers will know what source file to use
   evalStringForURL: function(url) {
      var evalStr = this.readURLSync(url);
      var sourceURLStr = "//@ sourceURL=" + url;
      return evalStr + sourceURLStr;
   },

For CSS you can do even better. Instead of inserting the CSS into the target page you can load it as a “user sheet,” making it available in all pages. If you want to override existing styles in the target page you just use a “!” in your style. Here is the code:


var sss = Components.classes["@mozilla.org/content/style-sheet-service;1"]
   .getService(Components.interfaces.nsIStyleSheetService);
var ios = Components.classes["@mozilla.org/network/io-service;1"]
   .getService(Components.interfaces.nsIIOService);
var uri = ios.newURI(url, null, null);
   sss.loadAndRegisterSheet(uri, sss.USER_SHEET);

FYI, Another Firefox-specific approach for loading the JS libraries with a different context is to use loadSubScript, but a bug in Firefox 4 broke this. I’ve documented the bug at https://bugzilla.mozilla.org/show_bug.cgi?id=653926. Unfortunately, you can’t actually view the bug report – it was restricted because it exposes a potential Firefox security vulnerability.

Update 6/15/11

Apparently the bug I mentioned above exposes a severe security vulnerability since I was awarded a Firefox Security Bug Bounty Award. See [post: Firefox Security Bug Bounty…].

Adding a little jQuery/Sizzle to FirePath for Firebug

FirePath is a very cool Firebug plugin that adds the ability to search the HTML tree using XPath or CSS Selectors. It filters the actual Firebug DOM tree so you can then act on that element in all the normal Firebug ways (view DOM, inspect, etc).

Here is a screenshot:

Unfortunately FirePath only supports native CSS Selectors, and most of the world (including me) actually uses jQuery’s Sizzle which gives us some really key additions like :not, :contains, and :first.

So I did a little extension hacking and added Sizzle support to FirePath. You can find the patch for it where I submitted it to the FirePath author at http://code.google.com/p/firepath/issues/detail?id=22.

Update 3/22/2011

I guess I’m not the only one who wanted to use jQuery/Sizzle. The patch was accepted and FirePath with jQuery/Sizzle is now available in Version 0.9.6.1!

Logging QUnit results

I’ve mentioned QUnit in other posts [POST: CUSTOM QUNIT TEST TYPES] and how much stock I put into unit testing in general, so I thought I’d share some more tips for people who don’t have much experience with QUnit. This will probably be a recurring theme on this blog.

One of the advantages of QUnit is that it has built-in hooks for testing automation tools. I use these hooks to do basic console logging so I can see what test is running next to my own log messages. I also log the amount of time each test takes.

The code to add these hooks is straightforward:

var startTime = null;
var currentTest = null;
QUnit.testStart = function(details) {
   currentTest = details.name;
   startTime = new Date().getTime();
   console.warn("QUnit starting " + currentTest);
};

QUnit.testDone = function(details) {
   console.assert(currentTest);
   cm.console.warn("QUnit finished " + currentTest + " (" + (new Date().getTime() - startTime).toString() + " ms)");
   currentTest = null;
};

QUnit.begin = function(details) {
   cm.console.log("QUnit starting");
};

QUnit.done = function(details) {
   cm.console.log("QUnit finished");
};

If you use modules then there are hooks at that level also:

QUnit.moduleStart = function(details) {
};
QUnit.moduleDone = function(details) {
};

The same approach can be used to do other things like send notifications (email/tweet) or generate a timing summary. You can read more about the QUnit integration hooks at:
http://docs.jquery.com/Qunit#Integration_into_Browser_Automation_Tools.

IntelliJ IDEA Code Completion for Knockout data-bind attributes

I’m a fan of Knockout. Among other awesome features, it allows you to create custom data bindings right inside your HTML using a data-bind attribute. The value of this attribute is actually a piece of JavaScript code that is executed each time the bindings are evaluated. These bindings can be simple or quite complex. Here is a simple example:

</pre>
<div data-bind="css: { profitWarning: currentProfit() < 0 }">Profit Information</div>
<pre>

Unfortunately, if you’re working with IntelliJ IDEA (WebStorm/RubyMine) you won’t get all of its JavaScript magic for the data-bind value because it thinks it’s looking at an HTML attribute string, so no code completion, etc.

But there is a way to fix this. IntelliJ supports something called Language Injection (originally called IntelliLang) to detect code fragments within another language, such as JavaScript code inside an HTML script element. Even better, IntelliJ lets you define your own Language Injections. So let’s create one for the Knockout data-bind attribute. It’s pretty straightforward to do, here are the steps…

  • In your project settings (even though Language Injections are global, they are defined in the project settings) select Language Injections
  • Click New then XML Attribute Injection
  • Then fill it out the dialog as follows (see screenshot below)
    • ID is the language type (JavaScript in our case)
    • Prefix/Suffix are used to make the data-bind string valid JavaScript code
    • Local Name indicates the attribute name where the Language Injection applies.

And now you will get all the IntelliJ goodness you love when editing your Knockout data-bindings like code completion, syntax/error highlighting, docs, and navigation!

You don’t have to stop with Knockout of course. You can also create more complicated injection rules using XPath or IntelliJ internal “Program Structure Interface Patterns,” which allow you map to the language structure itself.

I’ve created a few for other cases as well, which I’d be happy to share in another blog post if there’s enough interest. Just let me know in the comments.

Speaking on Cities Unwired panel for Digital Capital Week

I’ll be participating in a panel discussion this Saturday at the inaugural Digital Capital Week put on by iStrategyLabs. The panel will also include Karla Ballard, VP of Social Innovations, One-Economy; Tegene Baharu, Director, DC-Net, and Peter Corbett will be moderating. We’re going to be discussing Cities Unwired, focusing on “the new kinds of services developers, startups, and governments [will] be able to deliver to their citizens,” now that CLEAR is providing mobile broadband across DC.

There will be plenty of time for people to ask questions. Come for the interesting discussion, stay for the DCWeek after party :).

An iPhone and Android visual dictionary for Crisis Camp Haiti

I’m attending the 2nd Crisis Camp for Haiti this weekend. It’s amazing how many more people are planning to show up and help out from across the country and the world.

In prep for the weekend I’ve written a prototype for a visual dictionary mobile application that runs on iPhone and Android phones. Haiti has a large mix of languages and a high percentage of people with limited reading and writing skills, but relief workers still desperately need to communicate on a variety of subjects. Good visual dictionaries can be great for this since they allow communication through well recognized images and symbols, but the existing approaches are paper based which limits the vocabulary. Physical dictionaries also need to be printed and then distributed to the aid workers (a hard task in a crisis).

By using a mobile application we hope to work around these issues.

Here are some screenshots of the prototype. It’s not pretty, but it works on both iPhone and Android and I think it’s a solid starting point. I developed it in Appcelerator Titanium because that is what one of the existing teams is using for their mobile applications. It allows us deploy the app to any Android or IOS device. And it’s great for prototyping and testing since you can do that using normal web development tools.

You can expand the dictionary on the server and the client downloads the updates next time it’s connected. I think we may add a way to share dictionaries directly between phones as well, (not surprisingly, internet access in Haiti is intermittent at best). In time my hope is that we can even crowdsource the images and translations into an open source repository to have an ever-growing vocabulary for this and other image-based translation apps.

%d bloggers like this: