How to change Chrome's User-Agent string (redux)

As another brief addendum to a different post (the one about changing Chrome's user-agent string), if you use Google Chrome Portable to masquerade as an iPhone then you can have both a fake-iphone-chrome and a normal-chrome. This is handy for when you want to be able to use the non-iPhone versions of various websites while you're testing.

Don't Try to Reminplement HTML in your Rectangle of Joy (redux)

As a brief addendum to my previous post about HTML, I just thought I'd point out that Google's Webmaster Tools work on my phone while Bing's do not.

Obviously, checking on your website from your phone may not be a core use case (after all, the only reason I know it works on my phone is that I've been travelling and just happened to try it out while away from my "real" computer) but phones and other mobile devices are an increasingly important way people use web applications. Consequently, if your web app lives inside a Flash or Silverlight rectangle you're cutting off an entire class of uses.

Don't Try to Reminplement HTML in your Rectangle of Joy

I recently signed up for the Bing Webmaster Tools and it prompted me to install Silverlight. I thought: "That's kind of weird... I'm pretty sure I've got Silverlight... I mean Netflix..." but I installed it, restarted my browser and... it prompted me to install Silverlight again. Okay, Silverlight doesn't work with the Firefox 4 beta, duely noted. It not working with a Firefox beta is legitimate legitimate. Even if someone in the depths of the bat-cave in Redmond has Silverlight binaries that work against the current Firefox betas, I can see not releasing them until it RC's. I get it, but it's still a lame user-experiance.

I switched to Chrome, and then the real page actually rendered. Good. I started pokeing around and land on a page with a scroll bar so I tried to scroll down... and nothing happened. I tried again, nothing. I looked closer. The scroll bars are wrong, text selection doesn't work, neither does Ctrl+Click, and the text is just wrong. It's kind of noisy. At this point that I realize that the whole page is Silverlight rather than just the graphs and fancy bits.

The Take Home Lesson

Don't try to make you're alien rectangle of joy do what HTML does.

The second you notice that you're headed down the road of implementing browser features in JavaScript, Flash, Silverlight or whatever, stop, turn around and start heading back, because here be dragons. Don't try to make this work. You're not going to get it right. Microsoft didn't get it right, and they have way more dudes than you. I'll grant you that HTML+CSS+JS might not be the most powerful client-app toolset ever imagined, I mean even getting certain things to even just line up can be a pain, and the siren song of a single place for documentation/tools must be alluring, but you're not going to get it right. Browsers do so much. They are huge pieces of software that that do all kinds of stuff and you're not going to be able to copy the behaviour people care about in any meaningful way (especially since there are ways that the browsers legitimately differ when it comes to things like "What happens when I right-click on a link?").

Play to the browsers' strengths. Laying out text? Linking pages togther? Use HTML. Save shelling out to your magical rectangle for things that browser's don't already do well (like rendering interactive 3-D environments :-). Even shelling out to Silverlight to draw graphs is kind of boarderline at this point because there are lots of tools for drawing charts with JavaScript+HTML at this point and they will almost certainly give you a better result.

Embrace your platform. Don't try to build around it, lest you end up re-implementing it poorly.

Autotesting QUnit

I was watching a video on performance code kata and I was intrigued by the use of autotest. Basically, it's just a tool that watches the filesystem for changes and re-runs your test-suite when stuff changes. I thought it was a neat idea and wanted to try it out, but I don't really write any Ruby. Instead I turned to the world's most popular dynamic language: JavaScript. I've used QUnit to do some test driven development in JavScript, so tried the simplest thing that could possibly work, a meta-refresh:

<meta http-equiv="refresh" content="5"/>

... and that kind of worked. It was kind of cool, but the constant refreshing gets in the way of of using the JavaScript console to poke at things. Which, when you're writing JavaScript, is kind of an important thing to do. So... meta-refresh with a pause button?

$(function(){
    function startPaused(){
        return location.hash.indexOf("autotest=true") == -1;
    }

    function enable(){
        button.removeAttr("disabled");
        $("body").unbind("mousemove", enable);
    }

    var paused = startPaused();
    var button = $('<input type="button" value="{title}" id="auto-refresh">'.replace("{title}",
        (paused ? "autotest" : "pause")
    ));
    $("body").prepend(button);

    button.click(function(){
        paused = !paused;
        button.attr("value", (paused ? "resume" : "pause"));
        button.attr("disabled", "disabled");

        if(paused){
            location.hash = "";
        }

        $("body").mousemove(enable);
    });


    setInterval(function(){
        if(!paused){
            location.hash = "#autotest=true"
            location.reload(true);
        }
    }, 5000);
});
#auto-refresh {
    float: right;
    background-color: #D2E0E6;
    border: 2px solid #2B81AF;
    color: #2B81AF;
    margin-right: 1em;
    margin-top: 1em;
    border-radius: 5px;
}

#auto-refresh[disabled] {
    opacity: 0.75;
}

There you go. Thirty-odd lines to implement meta-refresh a pause button sigh.

It is actually pretty neat. If I used QUnit more and was in a better position to judge the actually usefulness of such a feature I might try hacking this into core QUnit and seeing if I could get it merged upstream. I mean, there are entire projects built around adding this kind of functionality to other tools, and it's so easy to do in a browser. I'm not planning on it though, because I've only actually used QUnit for fun-zies, and can't really judge how useful this kind of functionality would be on an actual test suite.

May I Bring Your Attention To...

One of the cool things I ended up implementing was Chrome-style disable-enable behaviour for the pause/resume button. Basically, as part of the click handler, it disabled the button and attached a mousemove event handler on the body. The handler then enables the button and unbinds itself when a mousemove event fires. The cool part is that while the button is disabled and your cursor is over it, moving your mouse doesn't fire any mousemove events, but the second your cursor leaves the button, a mousemove event fires and the button gets enabled. You get to safely reuse the pause/resume button without worrying about double clicks doing the wrong thing. Pretty spiffy, huh?

How to change Chrome's User-Agent string

Right now the top result when searching for changing chrome user agent string is terrifyingly bad and advocates editing chrome.dll with a hex editor. Don't do that, maybe it was required in the early days, but current builds support a --user-agent paramater. You can just run:

$ /path/to/chrome --user-agent="Googlebot/2.1 (+http://www.google.com/bot.html)"

... and impersonate any user agent you can think of. I mean yeah, running my browser from the command line isn't something I do a lot either, but it's a whole lot easier, and less likely to fail spectacularly, than editing a shared library with a hex-editor.

Masquerading as the iPhone

I set up a short cut (yes, I do use Windows at work), that put Chrome into pretending-to-be-the-iPhone-mode and gave it the yellow Chrome icon so that I can easily start up an appropriately configured Chrome session (Still easier than modifying a DLL with a hex-editor):

chrome.exe --user-agent="Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+
                         (KHTML, like Gecko) Version/3.0 Mobile/1A543a Safari/419.3"

... look-at-me, I'm the iPhone. Yay!