Dec 09

Out of the page and into the runtime; Extensions move the Web development model further

Tech, Web Browsing with tags: No Comments »

The Chrome Extensions team had a press event tonight to go over their extensions beta launch that I unfortunately couldn’t make at the last minute. I wanted to be there to see old friends and the good work they have been doing, and support them.

Aaron, Erik, and the team have done a pretty great job with their extension model. They wanted to allow Web developers to develop extensions. Who better to do that than folks who are a) Web developers and b) have written extensions (e.g. Aaron is an old time JS hacker, author of Greasemonkey, and much more since then [Gears etc]).

Of course, over at Mozilla the same idea had been hatched with Jetpack and other equally talented folk are working on that (Aza and Atul and more).

Some of our best Web engineers are on the case, which is great.

Before these new age extension models the world of extensions was tough. On IE you would be mainly a C++ hacker to do anything. Mozilla really raised the bar with its original Add-Ons but even though you could do a lot in JavaScript, there was still a lot of XPCOM and a huge API set since you basically were given the entire Mozilla platform to work with. This was great from a “you can do whatever the crap you want to do” perspective, but it was awfully hard to dive in and get productive.

Thus, most Web developers stayed inside the browser window. We develop applications in our area, and others do the extension thing.

That has changed and we are now breaking out of the browser sandbox in many ways. This is one of them. When we think about delivering experiences to our users we can think of out of the window. What would our users like to be able to do when not on our web site? How can we package our value adds in a way that they can do their thing at any point? How do we interact with the runtime? What can we do if we have more permissions to do interesting things?

We have only just seen the beginning with Jetpack and Chrome Extensions. They are many more APIs to write and for us to then consume. I personally think that Chrome is too restrictive on what you can do in the browser chrome for example. I would love to play around and have my browser morph in interesting ways. If I am on a particular site, new features and functionality could appear if I want them too.

It feels like we are touching the surface on what the Web platform and runtime is versus what a “browser” is as we have envisioned it until now.

2010 will be an exciting year for Web developers as they add extensions to their toolbox in a nice clean way.

Jul 16

When a “Web OS” hits, it will be so much more than a browser launcher!

Tech, Web Browsing with tags: 18 Comments »


original by mwboeckmann

Everyone got in a tizzy over the Google very-early-darn-leaks-pre announcement of Chrome OS. There have been many attempts at a “launch into browser” system, and the timing / marketing hasn’t been right. The journalists have by and large shown that they do not understand any nuance and could only think to write about the external battle of the titans (Chrome OS to destroy Windows!) or the internal battle of the titans (Android vs. Chrome OS).

The news is so early, that it is mainly a no-op right now, other than showing that to get to that point, Chrome will probably be extended quite a bit (access to more native services etc). I am a believer that this has to happen (hence Gears fan), but I also do worry that it will be rushed. We don’t want to fork the Web….. but let’s wait and see.

What I find most interesting though, is that I don’t think that the world needs a computer that boots almost-solely into a browser.

Kent Beck was talking about how he is using Chrome Browser OS right now as a social experiment. Yes. We can all delete every application from our machines and maximize a browser and live in it. That isn’t what will be exciting about a true Web platform.

I have been playing with a Windows laptop, and what has interested me is how much I can get done because my world is available through the browser. Back in the day, if I was at a friends house, I would download putty.exe and telnet/ssh into my world, and it would be ugly text. Now, I can jump on a random computer and access my entire social environment (email, twitter, etc). I can get real work done. One of the reasons that we did Bespin was to extend that to coding too.
This brings me to my benchmark for when I think a web OS will be here.

If I can sidle up to a random computer and have access to everything that I can do on my own laptop, then we have made it

Ironically, I almost used to be able to do just that! In university I could login to any machine on campus and see my screen exactly as I left it. I want X back baybee! ;)

We are getting closer, yet still a ways off. I hate the management that I have to do with iTunes. I want to by the license to play music, and have my collection in the cloud, and sync’d in smart ways. I want to be able to set profiles for what is downloaded and offline-available on my laptop versus the media server vs. the ball and chain’s laptop vs. my phone.

I want my settings to follow me around. Another reason why I am so excited about the future of Weave-like services. Let me login to the browser and get my history, passwords, awesomebar setup for me. Go further, and let me “switch user” on the persons machine and have the login be an identity service like Open ID, Facebook, Weave, or what have you.

When we have an open identity system that works, with services that let you take your entire world with you hooked to your identity, then we can talk about how cool the Web platform is as an OS. We will have moved up the services stack from managing the state of windows on the screen, to higher level services.

Marry this to auto syncing of data between all of your devices, and you have a truly new world. Give me that world, not just and autoexec.bat that launches browser.exe :)

Apr 06

Creating custom scrollbars with CSS; How CSS isn’t great for every task

Ajax, Bespin, JavaScript, Web Browsing with tags: , , 22 Comments »

Have you tried to create a nice rich experience and then been fighting the “defaults” to go the extra mile? This reared its head with me recently with Bespin. There are certain commands that pull up divs of content and we need to scroll through it. The problem is that the native scroll bar looks so out of place:

uglyscrollbar

WebKit recently released the ability to style scrollbars in HTML elements (but not the main window, which you have been able to do in IE for donkeys years much to many peoples chagrin).

I decided to take it for a spin and loaded up the examples that show you being able to do every type of scrollbar that you can imagine:

manyscrollbars

So, it shouldn’t be so hard should it. From the blog post I see a few magically ::-webkit-scrollbar CSS properties that I can plugin and be on my way. But looking at the example view source you see many pieces like this:

:not(.none):not(.double-start)::-webkit-scrollbar-track-piece:vertical:end:single-button,
:not(.none):not(.double-start)::-webkit-scrollbar-track-piece:vertical:end:double-button,
.single::-webkit-scrollbar-track-piece:vertical:end,
.double-end::-webkit-scrollbar-track-piece:vertical:end,
.double-both::-webkit-scrollbar-track-piece:vertical:end {
    margin-bottom: -6px;
}

Holy pseudo classes batman! To be fair, this is partly due to the example page having many types of scrollbars in one (hence the not this and not that but the other) but there are still nested classes that you need to grok to get this going.

I quickly built a debug scrollbar where I styled the various pieces with simple colors and borders so I can see which was which. I also went about making the scrollbar have one up arrow on top, and one down arrow on the bottom.

debugscrollbar

The parts and pieces of a scrollbar are quite simple:

  • Thumb: This is the piece that shows you where you are in the scrollbar. This is the chap that you can move around
  • Track: This is the area of the scrollbar that you can move the thumb up and down, or along (depending on the orientation). There is both the area between the top and the thumb, and between the bottom of the thumb and the bottom of the scrollbar
  • Buttons: There may be buttons that you can click to increment or decrement the selection (which moves the thumb). There are various styles (single button, double button, etc)
  • Resizer: This can change the are of the element (e.g. enlarge of shrink)
  • Corner: This area may show up with both horizontal and vertical scrollbars open

The debug scrollbar kinda shows these areas off in a simple visual way. Note how using display: block|none enabled me to setup the single button on top and bottom functionality:

/* Turn on a 13x13 scrollbar */
::-webkit-scrollbar {
    width: 13px;
    height: 13px;
}
 
::-webkit-scrollbar-button:vertical {
    background-color: red;
    border: 1px dashed blue;
}
 
/* Turn on single button up on top, and down on bottom */
::-webkit-scrollbar-button:start:decrement,
::-webkit-scrollbar-button:end:increment {
    display: block;
}
 
/* Turn off the down area up on top, and up area on bottom */
::-webkit-scrollbar-button:vertical:start:increment,
::-webkit-scrollbar-button:vertical:end:decrement {
    display: none;
}
 
/* Place The scroll down button at the bottom */
::-webkit-scrollbar-button:vertical:increment {
    background-color: black;
    border: 1px dashed blue;
}
 
/* Place The scroll up button at the up */
::-webkit-scrollbar-button:vertical:decrement {
    background-color: purple;
    border: 1px dashed blue;
}
 
::-webkit-scrollbar-track:vertical {
    background-color: blue;
    border: 1px dashed pink;
}
 
/* Top area above thumb and below up button */
::-webkit-scrollbar-track-piece:vertical:start {
    border: 1px solid #000;
}
 
/* Bottom area below thumb and down button */
::-webkit-scrollbar-track-piece:vertical:end {
    border: 1px dashed pink;
}
 
/* Track below and above */
::-webkit-scrollbar-track-piece {
    background-color: green;
}
 
/* The thumb itself */
::-webkit-scrollbar-thumb:vertical {
    height: 50px;
    background-color: yellow;
}
 
/* Corner */
::-webkit-scrollbar-corner:vertical {
    background-color: black;
}
 
/* Resizer */
::-webkit-scrollbar-resizer:vertical {
    background-color: gray;
}

By moving the scrollbar around I could quickly see how this all worked, and it got me to this point which enabled me to plugin the images to make this puppy work for Bespin:

bespinscrollbar

There were a couple of key tweaks needed to make this work:

Getting the buttons working

I used the same trick used in the debug example to turn on the up area above, and the down area below, and then it was just a matter of targeting the correct area for the arrow images:

/* Turn on single button up on top, and down on bottom */
::-webkit-scrollbar-button:start:decrement,
::-webkit-scrollbar-button:end:increment {
    display: block;
}
 
/* Turn off the down area up on top, and up area on bottom */
::-webkit-scrollbar-button:start:increment,
::-webkit-scrollbar-button:end:decrement {
    display: none;
}
 
/* Place The scroll down button at the bottom */
::-webkit-scrollbar-button:end:increment {
    background-image: url(images/scroll_cntrl_dwn.png);
}
 
/* Place The scroll up button at the up */
::-webkit-scrollbar-button:start:decrement {
    background-image: url(images/scroll_cntrl_up.png);
}

Get the track pieces to show

Next up was getting the gutter to show up. As mentioned early on, there is one track, but two areas that can show…. before the thumb and after. You can target these areas via -webkit-scrollbar-track-piece:start || :end and then it is a matter of using the multiple background ability available in new browsers. First we have the top of the gutter, and then a recurring background (and the same for the bottom). This way it just grows with the area that it gets:

/* Top area above thumb and below up button */
::-webkit-scrollbar-track-piece:vertical:start {
    background-image: url(images/scroll_gutter_top.png), url(images/scroll_gutter_mid.png);
    background-repeat: no-repeat, repeat-y;
}
 
/* Bottom area below thumb and down button */
::-webkit-scrollbar-track-piece:vertical:end {
    background-image: url(images/scroll_gutter_btm.png), url(images/scroll_gutter_mid.png);
    background-repeat: no-repeat, repeat-y;
    background-position: bottom left, 0 0;
}

The Thumb

To get the thumb working, I thought I would do the same background image trick with three images (top of thumb, bottom of thumb, and background for the middle). Unfortunately this didn’t seem to work for me as I couldn’t get the middle to not go through the top and bottom. So, instead, I went with another new CSS trick: border-image. Here I splice the top and bottom of a thumb (the top and bottom 8 pixels) and stretch the rest:

/* The thumb itself */
::-webkit-scrollbar-thumb:vertical {
    height: 56px;
    -webkit-border-image: url(images/scroll_thumb.png) 8 0 8 0 stretch stretch;
    border-width: 8 0 8 0;
}

John Resig has a nice readable post on border-image.

And, there you have it. Now we can have nice Bespin-y scrollbars throughout Bespin. This may not be complete though, as we have the ability to also tie in :active and :hover work if we wish (change the color when selecting etc).

Of course, many people had “custom scrollbars”. There are plenty of comments on the original Surfin’ Safari post, and various rants about Flash versions. I agree that we have all seen bizarre Flash versions of scrollbars that don’t look like them at all, and where the designer didn’t bother to put in support for the mousescroll ability etc, but this is a bit different. It let’s you merge in your look and feel, yet with native scrollbar functionality.

And, with Google recreating the button maybe we can feel a little bit better about tweaking the look of common UI elements as long as they are familiar enough to users to still make natural sense.

Now, the CSS declarative way to do scrollbars seems to get pretty ugly to me with all of he pseudo classes and various magic to get the functionality that you would like. I have to admit to liking Kevin’s demo of Flash Catalyst at Web 2.0 Expo and how it lets designers build out a scrollbar. We should be inspired to do tools like this. What if we had an API that wasn’t CSS, but let us say: “I want a Mac style double on the bottom button scrollbar. And, here is a thumb, here is a track, go for it”.

That being said, at least we do have the ability to do this kind of thing now. I hope that other browsers follow WebKit in this instance.

Mar 25

Canvas 3D, standards, and where

Mozila, Open Source, Tech, Web Browsing with tags: , 6 Comments »

I was excited to hear about the Canvas 3D effort that Mozilla, Google, and Khronos are engaged in (and others can too of course).

Khronos is the group being OpenGL, and thus a good set of folks to be involved in the Canvas 3D approach that is in the mould of “OpenGL ES like for the Web” in that it is a low level API that others can build on top of. Others have played with higher level “Games” APIs, or virtual worlds, and this is not the same. It is a primitive that will enable people to do interesting things that sit on top.

I noted Ryan Stewart (friend and great chap) weighing in:

So it’s unfortunate to see that even the browser vendors have given up on moving the open web forward through standards. Whether it’s the WHATWG versus the W3C or the trials and tribulations of actually implementing HTML5, things are very broken and everyone is moving on regardless. I don’t blame any of them, but it doesn’t seem like it’s good for web developers.

Then, I saw John Dowdell, also of Adobe, talking about standards.

I already talked about how many of the leaps on the Web haven’t started in the W3C (and rarely start inside standards orgs first) and rather come out in browser implementations that are then shared. Think XMLHttpRequest. Think Canvas itself from Apple! Do something well, see people use it and get excited about it, and then get multiple implementations and standards. Everyone wins.

John’s wording is interesting:

“But Mozilla’s proposal relies upon further proprietary extensions to the experimental CANVAS tag”

“And you’d lose the moral fulsomeness of the ‘Web Standards for The Open Web!’ pitch when focusing on your own proprietary alternatives to existing standards.”

Look at how browsers have done some things recently. Take some of the new CSS work that Apple started out. When the Mozilla community liked what they saw, and had developers demanding, they went and implemented it too. When you see WebKit and Gecko doing this kind of work it is particularly Open because the projects are open source and you can check them out (well, if you are allowed ;) How great is that, to iterate nicely in the open…. and then when ready we can drive into the standards bodies.

Back to the Canvas 3D work. Having Mozilla, Google, and Khronos work on this in the open seems pretty darn good to me. This won’t be hidden behind a proprietary binary that no-one can see. There will be some work in marrying the world of OpenGL ES and JavaScript as nicely as possible, and there will be plenty of room for the jQuery/Dojo/Prototype/YUI/…. of the world to do nice abstractions on top, but this is good stuff. This is more than just throwing out an API on top of a proprietary system, and I can’t wait to see what comes of it all. Want to get involved? You can in this world.

Feb 09

Will the real WebKit please standup

Comic, Tech, Web Browsing 6 Comments »

webkits

I recently heard a conversation in Palo Alto which had the following in part of it:

  • Chap A: Are you testing in WebKit?
  • Chap B: Which WebKit?

I have heard this before. I am running into this issue myself right now. Something that our team is playing with uses some bleeding edge standards, and some recently were added to WebKit nightly. Unfortunately, that doesn’t mean that they are in Chrome, AIR, Mobile Safari (in this case it is), or the other people who use and fork WebKit (from Nokia to Titanium).

On the one hand companies are highly leveraging each others work when they choose WebKit. Forking isn’t necessarily an evil thing anymore, especially if everyone is giving back to the cause as much as possible. The WebKit team implements CSS Animations, and you hope that it will be placed in browsers that use WebKit in the future. Watching the WebKit community deal with the many large companies will be interesting indeed in the coming couple of years. Luckily, the core team is top notch, and continue to push forward.

Jan 02

Loving Ubiquity; Extending the Web in 2009

Ajax, Tech, Web Browsing 4 Comments »

I have a project that deals with JavaScript commands that anyone can author, so I decided it would be smart to take more time looking and integrating with Ubiquity which recently got another beautiful upgrade.

Ubiquity really is the “other” command line of the Web (the URL bar being the first one). It gives me Quicksilver like access, but also has huge improvements: Writing plugins is simple JavaScript, and you can subscribe to commands from other people. This is huge. A social command-line!

There is a built in tinyurl command, but I use tr.im one these days, so I quickly wrote one:

CmdUtils.CreateCommand({
  name: "trimurl",
  homepage: "http://almaer.com/firefox/commands/",
  author: { name: "Dion Almaer", email: "dion@almaer.com"},
  license: "ASL",
  description: "Sends your URL to tr.im instead of tiny url",
  help: "Just type in the URL!",
  takes: {"url to shorten": noun_arb_text},
  modifiers: {"as": noun_arb_text},
 
  preview: "Replaces the inputted URL with a Tr.im URL.",
  execute: function(urlToShorten, mods) {
    var baseUrl = "http://tr.im/api/trim_url.json";
    var params = "?url=" + urlToShorten.text;
 
    var custom  = mods["as"].text;
    if (custom) {
      params += "&custom=" + custom;
    }
    jQuery.getJSON(baseUrl + params, function(data) {
      CmdUtils.copyToClipboard(data.url);
    })
  }
});

This chap uses modifiers to allow me to pass in a custom url.

The following said that there will be a url following, and you can optionally say “as customname”:

  takes: {"url to shorten": noun_arb_text},
  modifiers: {"as": noun_arb_text},

I couldn’t find a way to just add to the takes hash, as it would be nice to say:

  takes: {"url to shorten": noun_arb_text, custom: noun_optional_text },

After using Ubiquity for some time now, I am really impressed with how the team is accelerating, and I see this as a great way to extend the Web, and Firefox in 2009.

I find myself in a funny place with the key combos for bringing up Ubiquity and Quicksilver in my mind. I am using Quicksilver less and less (e.g. won’t use it to search the Web or do anything with email) and Ubiquity more and more. As the Open Web takes over the desktop (another prediction;) then Ubiquity will gain usage for me.

Atul has released a preview of Ubiquity 0.2 which has a new architecture and a new Locked-Down Feed Plugin (LDFP).

Dec 31

window.resize firing frequency in browsers

Ajax, Tech, Web Browsing 11 Comments »

I was playing with a Web application that did interesting redrawing of the layout (e.g. needed to do JavaScript magic in the onresize event).

I noticed that in Firefox the event took a fair time to fire. Joel Webber (of GWT fame) has also found this and said:

“Firefox and Opera do this wierd thing where they only fire resize events when you let go of the mouse button, or every second or so while dragging. It’s really irritating because there’s no way to get a “real” resize event, and it makes your ui look crappy when it goes through intermediate wrong-sized states.

I’ve always assumed this was to cover up layout performance issues. WebKit and IE fire resize events immediately.”

I wonder if the layout issue is correct, and if so, it would be nice to be able to somehow say to the browser “yup, I am in control of layout so please fire faster” or maybe by defining onresize you are saying that.

With decorators/annotations you would say:

@FireFrequency(ms=10) window.onresize = function() {
  // ....
}

Turns out that Ben was being a good citizen and in going to file a bug, found a couple out there.

Dec 09

App Discover: An add-on that shows me when apps or user scripts are available for a site

Mozila, Tech, Web Browsing with tags: , 10 Comments »

Greasemonkey and Fluid userscripts. AIR and the new Titanium apps. Browser add-ons. When you go to a website do you know if you are getting the best experience for you? You could search for script on userscripts, or Google for apps, but what if the developers of the sites had a way of pointing out that there were enhanced experiences for you?

This is where App Discover comes in. It is a Firefox add-on that notifies you of these very items. All the developer has to do is add a simple link tag to their page, and the add-on will find it for you.

For example, if Twitter added the following tag, you would be notified of TweetDeck:

<link rel="application" 
  type="application/vnd.adobe.air-application-installer-package+zip" 
  title="TweetDeck Adobe AIR Twitter App" 
  href="http://www.tweetdeck.com/beta/TweetDeck_0_20.air" />

That line would mean you would see this in the browser:

Twitter App Discover Example

The type is a mime-type of course, and these are mapped into custom verbiage, but if you come up with something new… as long as the href is good, you should be golden.

I just added support for Appcelerator Titanium for example:

<link rel="application" 
  type="application/vnd.appcelerator-titanium-app-package+zip" 
  title="Tweetanium Appcelerator Titanium Twitter App" 
  href="http://tweetanium.com/tweetanium.zip" />

This is just a simple beginning of course. Where would we really want to go from here?

  • The current limitation is that it only really works well with one link tag (items get replaced)
  • I want to add preferences so the user can let the add-on know what they want to be alerted about (e.g. yes to Titanium apps and Greasemonkey scripts only!)
  • Be smart based on installation: E.g. if you don’t have Fluid (and especially if not on a Mac), don’t show it
  • Get social: “You have three friends who have installed TweetDeck”. This requires the browser being smarter about your social graph, which I think is a natural progression.
  • It should be smarter and not bug you when you go back to the same page. That can be fixed via the AnnotationService.

That leads me to XUL. I tweeted how it can feel a little strange to look up XUL docs and see dates in the lower 2000s. You have this nagging feeling of “has something really not changed since them? Is there an new better way of doing this?” As @mfinkle pointed out, “XUL is stable.”

I have to say thanks to the Ubiquity team who had done the lifting for me, which meant that this add-on took an hour to write!

Dec 01

Application trust models; Expanding Web applications out of the sandbox

Security, Tech, Web Browsing with tags: 5 Comments »

Winter

A few years back Web developers were celebrating the glimpse of a beautiful Winter as some of our best hacked our way out of the prehistoric ages to give us Ajax.

Ajax Universe

Fast forward to Hope year and we have seen the Web platform explode. We have gone from Web hack to the mobile phone and even the desktop.

With technology such as Prism, Fluid, Gears, and AIR we get to use our Web skills to build desktop applications. If you play the numbers game and realise how many people understand how to hack on the Web versus write native applications you can see how if harnessed correctly, the Web could be a dominant platform far beyond the browser as we know it.

However, how do we break out of the Web sandbox? We gain a great deal of this “secure” (don’t say that to Crockford) place for us to build applications and we can’t just break out willy-nilly.

The problem is, that if we don’t come up with something you will always end up saying “I can’t prompt my users for every little thing, so I guess I will just write a native application.”

This of course doesn’t actually help make life secure for the end users. Instead, they hit OK on the “Sure, I know I downloaded that from the Internet” dialog and now native code is doing whatever it wants too!

ASIDE: I would love to know how many people: a) download something from the Web, b) run it, c) see that dialog and then d) say “oh, OK no.” I know what I am willing to bet on ;)

What if we took the weakness of the current Web sandbox and make it a strength. If our platform is able to intercept what is going on, imagine if we could have metrics that show us exactly what an application is doing. Chrome does one small thing here, showing you the memory that a tab is using. This is a great start. What if we go further and you think of iStatMenu being somewhere in the browser:

Browser Metrics

Now for every browser application you can see not only its memory footprint, but you can see if it is using your location, how it uses the network, the local database, and even the file system. Instead of asking once “is it ok for this app to do anything” we can ask a more nuanced question, but also give a lot of feedback after the fact, way after you have forgotten what you said would be OK.

We could also have power user modes that allow you to visually see the heap, allowing you to navigate it as you debug your application. Detailed networking views. And, more.

Of course, the best way of doing this work is through implicit interfaces. Having a Google Search with a “[x] near my location” checkbox is the obvious example.

This is a delicate issue, but I believe that the Web needs to move in a broad direction, and we need to work through these problems. What do you think?

Nov 17

View Source Improving: From Linkification to Discovery

Tech, Web Browsing 5 Comments »

Linkified View Source

Curtis Bartley fixed a Firefox bug which has now enabled live links within view source. As you can see above, links are now underlined and you can navigate away through the source. Very nice indeed, thanks Curtis!

Ben and I were talking about this, as well as bringing other features into the world of view source. Some small things such as popping up the actual color when you see a #xxxxxx, or a thumbnail on an img or url().

Of course, this normally leads to Firebug-land. In fact, after talking to some Mozillans, I am excited about improving discoverability.

For example, would it be cool to:

a) Show a top info drop down saying “You seem to be interested in the underpinnings of the Web and development. If so, __check out Firebug__” when a user runs their third View Source. Ditto for other develop-y actions (grabbing the Web Developer toolbar etc).

b) Allowing sites to link to their add-ons. This one should be cross browser. If you are a company such as LinkedIn, and you have developed a cool add-on or extension for your site, how are users to know? They may no be hanging on on AMO looking for one :)

You can imagine something like:

<link rel='browser-addon' browser='firefox' href='https://addons.mozilla.org/en-US/firefox/addon/1512' type='application/addon' />

to point to a Firefox add-on in this case. You could also follow the same pattern to get info on site specific browser info, Greasemonkey scripts, or specific apps (e.g. AIR apps).

<link rel='browser-userscript' title='Cool Video Script' href='http://userscripts.org/scripts/show/9789' />
 
<link rel='browser-app' title='eBay Air' href='http://desktop.ebay.com/' />

What do you think?