Was Mark Zuckerberg an AOL add-on developer?

mark_adjusted_350

Facebook founder Mark Zuckerberg’s first website was recently found to still be online at Angelfire, an early free web hosting site. The Internet Archive confirms the site existed in its current form back in 1999, and the page’s source code is noted to be authored by “Mark Zuckerberg”. In addition, the author states they’re 15 (the age Mark was in 1999), and that they live outside of New York City (where Mark lived when he was 15). Motherboard provides further evidence, showing that the primary AOL account for the email listed on the site is a name commonly used by Mark Zuckerberg’s father.

The site screams 1999 web design, and is a very cool piece of internet archaeology. It should also be noted that it’s actually a pretty decent effort for the time for a 15 year old (you only have to see the About section of this blog to see my effort at 16). However, the most interesting aspect of the site is “The Vader Fader”, an AOL add-on application that Zuck was heavily promoting on the site. Did this mean he was apart of the AOL add-on community? Did he use AOL progs? Did he develop in Visual Basic?

vader

I downloaded The Vader Fader, and it is for AOL, and it was indeed written in Visual Basic. I tried firing it up, but got a message box saying I needed to be “online” and then the window on the left popped up. Ugh, I just want to see what this app looks like, I have to have AOL open? So I hunted down a version of AOL 4.0, installed it, and then tried running the app again. This time I got a runtime 6 error – this was most likely caused by Zuck using Integers to store window handles instead of Longs. After Windows 98, window handles started being Longs instead of Integers.

Being persistent, I decided to download Windows Virtual PC and load up Windows 98. After burning AOL 4.0, The Vader Fader, my API Spy, and a hand full of VB dependences to CDs and then loading them up on the OS, I fired up The Vader Fader. This time it didn’t crash, but it still told me I needed to be online. Crap… how was I supposed to do that? I tried signing on, to see if by some fluke AOL was still active and letting random people sign in, but it didn’t work. It then occurred to me – how did progs back in the day determine if someone was signed on? I couldn’t believe I remembered this, but the way it worked was the app would find the main AOL window, and then look for a child window that had a caption that started with “Welcome, “.

I used my API Spy to change the caption of the existing AOL sub-windows to “Welcome, PAT or JK”, and then tried launching The Vader Fader again. This time it worked! Well, sort of. Instead of a message popping up, the caption of the main AOL window changed to “The Vader Fader”, and then nothing happened. I poked around, and the app was running in the background, but there was no main window and it didn’t appear to have done anything else. My best guess is the app worked by augmenting AOL chat rooms and IMs with fading options (why else would it change the main AOL window’s caption?). If that’s the case, there really wouldn’t be much to see, or really any way to see it – given that AOL 4.0 chatrooms and IMs are long defunct.

I was a little sad, but glad I’d at least gotten the app up and running. I also ended up digging through the app’s machine code a little for any other clues on how it was created, but didn’t really find anything interesting (other than the 10 color choices). Since the app used the same online detection mechanism as most other apps at the time, I wonder if Zuck used a common bas file like dos32.bas or genocide.bas – that’d be pretty cool if he did. It’s also kind of neat that the main app he was pushing was a fader, since that was the first app I released on this site. Anyway, I’ve spent way too much time on this. The site is a cool piece of internet archaeology and definitely worth poking around a bit if you have a few extra moments.

Facebook User Identification Bug

Time for Round 2

I decided to take another shot at Facebook’s Security Bug Bounty program. This time I ended up finding a bug that allowed a website to use Facebook to detect if their visitors were particular people. After doing a write-up and submitting it to Facebook’s security team, I was awarded a $1,000 bounty. Below I’ll go into how I came across the issue and how the technique worked. Also, I don’t see myself going full-on bug hunter after this or anything like that, this has mostly just been a random side-adventure that came from me being inspired by some random blogs I read on bug hunting and application security.

How it worked

I noticed that the preview-image for a Facebook Badge was dynamically generated based on a user’s Facebook ID. There were some other configuration parameters, but for simplification, you can imagine the HTML looking something like this:

<img src=”https://facebook.com/badge_edit.php?id=12345″ />

When rendered, the image would look something like Figure 1. Since it could contain a user’s email address, my first instinct was to see if I could load other users’ badge previews and get their email addresses. However, when I tried this, a Facebook logo image loaded instead of the profile image (Figure 2).

Figure 1

Figure 2

This meant that only the user themselves could view their profile badge preview. However, even though the logo was put in place to block information from being leaked, I realized that it still leaked information. An external website could use JavaScript to silently load tons of profile badge previews with different user IDs, and then check their height and width. If one of these images loaded and it wasn’t the height and width of the Facebook logo, the website would know that that particular user was viewing their page.

This had a lot of interesting use cases. Someone could:

  • See if a particular acquaintance (boss, ex-girl friend, frenemy) was stalking their Facebook feed or reading their blog.
  • See if someone famous was visiting their site.
  • Track the actions of certain people.
  • Show different content depending on who was visiting.

The one limitation was that someone could only check against a list of certain people, but there are only so many people someone can know, and targeted attacks are for particular people anyway.

Submitting the Bug

It was 1am Monday morning when I found this bug. When I realized what I could do with it, I had a rush of adrenaline and stayed up another 3 hours coding up a proof of concept and submitting a bug report. I really should have just gone to bed and wrote the report the following day (I’m supposed to be in at work by 9am), but it felt sort of like when you’re on the last level of a video game and your mind is buzzing with “holy crap, I’m going to beat the game!”

Similar to my last report, it took around two weeks for a security analyst to get back to me, and similar to last time, I was told it was interesting but that they needed to check with their engineering team. I was a little worried at this response – however, I felt that this time I’d found something that was really cool. Hell, it’s something that I would be tempted to use.

About a week later I noticed the bug was fixed and I received an email asking me to verify the fix. I did a few tests and then let them know that everything checked out. Shortly after this I got an email from the security team letting me know I was eligible for a $1,000 payout and that I needed to fill out a W-9.

Final Thoughts

In addition to Facebook, I also tried the white hat programs of a few other sites, and even ended up making Google’s honorable mention list and earning Reddit’s white hat profile badge. However, even though getting a little bit of recognition and pocket change is fun, I don’t think I’m cut out for bug hunting. I’m glad I did it since I learned a little more about security, but it’s a lot of work for very little return, and after you’ve submitted your find, you’re back to where you started. Even though it was kind of fun, I think my foray into bug hunting is over.

Crafty Tricks for Avoiding XSSI

While looking at the response data from certain AJAX requests in GMail, I noticed that they were prepending their response JSON with either a number, “while(1);”, or “)]}’”. They do this to avoid cross-site inclusion attacks (XSSI), where a malicious site includes a file from another site in order to steal its data. Example:

<-- Code on evil site -->
<script src="http://gmail.google.com/user_email.json"></script>

Even if the data in the JSON object isn’t wrapped in a function or set to anything, it can still possibly be stolen by overriding the Array constructor or defining a setter property on the Object prototype. Most of these holes were plugged up after being discovered, but they still exist in some older browsers, which is why GMail is putting these safe guards in place. Two of the techniques of the mentioned, “while(1);” and “)]}’”, are pretty straight forward. “while(1);” will cause an infinite loop, keeping an attacking site from reaching its payload, and “)]}’” will cause a syntax error, stopping the rest of the script from executing. But the number trick is not so straight forward, and it had me scratching my head. The response data looked something like this:

123
["Email message", 123, "?", 0];

Was this to cause a syntax error? I decided run the code – nope, no syntax error. In fact, it turns out that the above code is valid JavaScript. However, instead of returning the last line, the array, it returns undefined. Wait a second, how could that possibly evaluate to undefined?

To experiment more, I decided to try executing:

123
456;

Which evaluates to 456. And then:

123
"test";

Which evaluates to “test”.

So when the second item is an array, it evaluates to undefined, but when it’s a number or string, it evaluates to the second parameter? WTF JavaScript? After showing the issue to a few co-workers, none of us were able to figure out what was going on, so I took the question to StackOverflow.

Within a few minutes, freakish had the answer. It turns out that JavaScript’s automatic semi-colon insertion was to blame. In the second and third cases, JavaScript realized that “123 456″ and “123 ‘test’” weren’t valid statements, so it inserted a semi-colon at the line breaks. However:

123 ["Email message", 123, "?", 0]

IS a valid statement. What’s happening is that the []‘s cause JavaScript to look for a property value on the number object. The comma statement returns its last parameter, 0, so JavaScript looks for a property named 0 in the number’s prototype chain. When it finds nothing, it returns undefined. This can be tested with the following code:

Number.prototype["0"] = "test";
123["Email message", 123, "?", 0]

Which evaluates to “test”.

Wow. That is so completely ridiculous. However, it’s also pretty clever on Google’s part. It allows them to have another XSSI-busting technique, and I’m assuming they use a variety of methods in case a hack is discovered which gets around one of the other techniques. Anyway, I found the number trick to be especially interesting, so I figured I’d share it here. And again, freakish deserves the credit for figuring out what was going on.

The Chrome Web Store Effect

It’s been about 5 months since I tried out Chrome’s Web Store for my Snake and Text to ASCII Art apps, and I figured I’d give an update on how putting them in Chrome’s Web Store has effected their usage.

My Snake game has sat around for about 4 years on this site, consistently getting an average of around 30-50 users a day. I originally wrote the game as a nostalgic tribute to my high school days, and it’s only undergone a hand full of updates since its initial inception. Since this site was getting around 6.5k visits a day, 50 visitors means the app was accounting for around 0.077% of the site’s total traffic. After placing the app in Chrome’s Web Store, the daily usage began to steady rise, and the app has recently been getting between 900-1,000 visitors a day on the weekdays:

Snake Stats

Holy crap, the Chrome Web Store is awesome! Even with the bagillion other Snake games listed in the store, traffic has gone through the roof, with daily usage up 2,000%! But what about the TAAG app, has it also seen such a meteoric rise in traffic? Interestingly, even though both the Snake app and TAAG app have a similar number of installs, TAAG hasn’t seen a noticeable rise in traffic:

TAAG Stats

Hrm, this is kind of interesting. My guess is that this discrepancy is caused by the following factors:

  • TAAG is a utility app and isn’t really something that’s used often.
  • There is a high volume of people trying out games in the Web Store (installing them, and then uninstalling them if they don’t like it).

It’s hard to be certain of what’s actually going on, but I found these results to be pretty interesting, so I figured I’d share. I had wondered if the Chrome Web Store would be a positive for web app developers, and so far, from my limited experience, it seems like could potentially be a big plus for web app developers, especially game developers.

Facebook Bug Hunting

Image By laikolosse

Facebook has a neat security bug bounty program where developers, hackers, security researchers, and random Joe’s can submit security flaws to Facebook in exchange for a monetary reward and a place on their White Hat thank you list. Their minimum payout for finding a bug is $500, and that number increases based on the severity of the issue you report. Recently I’d read about amounts as high as $3,000 and $3,500 being paid out, and while this isn’t a ton, it’s definitely a nice amount of pocket change.

Since I was on break with my newborn last month, I decided to take a stab at uncovering an issue myself. Finding bugs is more about being clever than it is about being smart, and I figured the surface area for security issues on Facebook had to be pretty big.

I started out my journey by setting up a couple of test accounts in the Facebook sandbox. At first I tried a number of broad attacks – generic CSRF attacks, generic XSS attacks, faking email headers when sending email to an @facebook.com address, and lots of other really obvious things. Nothing seemed to work, and Facebook seemed to be a more hardened application than I had originally thought.

Original Image By javier.reyesgomez

At this point most people would get bored and move on, but I’m a little more stubborn than most people. I regrouped and realized my current path was fruitless. What I really needed was focus. I needed to look at one feature and see if I could find a hole in it. After surveying the different privacy settings, I decided to see if I could get around the setting that allowed someone to hide their friends list from their friends.

I poked and prodded and looked at everything related to the listing of a user’s friends. Finally I noticed something odd about Facebook’s one of the ajax calls that was being made under the covers. I was able to get it to return an error if a certain user parameter wasn’t a friend or a friend of a friend. Hrm, this was interesting. This meant I could do a check to see if a user was my friend or a friend of one of my friends. I wondered if this check factored in friends that were hidden from me. I rearranged the friend relationships in my test accounts and tried it out. Sure enough, the check didn’t respect hidden friends. This meant I could check if certain people were on the friends list of friends who were hiding their friends from me. If I only had one friend hiding their friends list from me, I could definitively check if certain people were on their friends list.

I ran some more tests, and with the consent of my friend Joel, confirmed the issue on the production version of Facebook. I then wrote up a test case (an attacker friends a victim, the victim accepts the friendship but hides everything from them) and submitted the how-to steps to Facebook’s Security Team.

And then I waited. Two and a half weeks came and went. I began to think my submission had been ignored when a message popped into my inbox from Facebook’s Security Team. They apologized for the delay, were very polite, and told me they thought the trick was pretty interesting. However, they wanted to double check with their Privacy Team to confirm how certain behavior was supposed to work and then they’d get back to me. They also mentioned they were going through a large backlog of issues. This made me curious as to how many submissions they get a day. Interestingly, around the time of this email I saw another individual go public with a bug they’d found due to not hearing back about a report quickly enough.

I was hopeful after the first email. The trick allowed someone to obtain information about their friends that was supposed to be hidden. It wasn’t the greatest find, but it was a neat little trick. However, the following week they emailed me saying that while they thought it was a cool trick, they felt it was an acceptable risk and that planned updates they were rolling out would eliminate it anyway.

The wind came out of my sails, and I felt like the achievement had slipped through my fingers. I still applaud them for setting up such a system, and being able to work in a sandboxed version of Facebook to try out different techniques is really cool. However, I’m left with mix feelings. Though then again, if you’re bored and just want to try and hack Facebook, it’s a fun way to spend a few hours.

Update 2013/27/02: I got confirmation a few days ago of a 1k reward on another bug I submitted. I may do another post on it, or may just make a short update here.

2012 Comes to a Close

I’ve had a lot of false starts with writing posts lately. Writers blocks seems to have gotten the best of me, but I figured I’d do a post to reflect on the past 12 months.

The hand of a fellow runner
Photo By fejsez

This year I turned 30, which makes me feel a little strange. I’m no longer the young guy. Up until 2 years ago I was always the youngest guy on the team I worked on at work, now I’m the oldest guy (though in fairness, the team I’m currently on is only 3 people).

I also became a dad this year (2012-12-09), which is pretty cool. I wont bore you with any mushy revelations or talk about how it’s changed me – I honestly still feel like the same person. However, it is amazing to look over at the little guy and know that he’s got half my DNA. It’s also fun to wonder what kind of person he’ll be. Hopefully I can steer him in the right direction and help him become the best person that he can be.

PHP

I learned a lot about web development this year. Both on my own, by experimenting with new HTML5 APIs and browser tools, and at work. To speak in general terms, at work I’m a developer on two web applications – one based in Java Spring and one based in PHP. Working with the two side by side, I’ve slowly grown to hate Java web development – it’s slow for iterating changes, lends itself to gigantic class hierarchies, and seems to make trivial tasks harder than they should be. Even though it has its flaws, PHP is actually pretty fun to develop in. It also has great documentation and it seems like there is a blog post or forum question on anything you’d possibly want to do with it.

I still prefer the front-end though, and I’m still not sure I want to rely on PHP every time I do something on the back-end. One of my goals for next year is to take a serious look at Node.js, Python, and Ruby, and to do a for-fun project in each. I’ve actually started this already, but got a little side tracked when the baby showed up.

Internet Archive Fund Raiser

The Internet Archive is doing a donation drive with a 3-to-1 match. The archive was of great help to this site a few years ago when I underwent the one-two punch of my hard drive crashing and then my old web host deleting my site. Thanks to their Way Back Machine, I was able to recover a lot of files (in fact, it’s the reason the VB sections to this site are still up). I threw a couple of bucks their way out of appreciation, and I figured I’d pass on the link to anyone else who was interested in helping them out. They’re almost at their goal of raising 150k.

Book Review: “JavaScript: The Definitive Guide”

I felt a little nerdy asking for this for Christmas, but it was worth while read

The web apps I write for this site are written in JavaScript, and after landing a web developer job two years ago, I’ve focused more on getting better at everything web related – through reading blogs, writing apps, and reading books.

As far as books were concerned, there had been one which had consistently caught my eye, but which I’d kept resisting due to its size. I have a short attention span and I was worried I wouldn’t finish it. I also tried to foolishly convince myself that I probably already knew most of what it covered – after finishing JavaScript: The Good Parts and a couple other short books, I felt I had a pretty good handle on the language. What else could there really be to know? But temptation got the best of me, and I’m glad it did, because it’s a great book and I learned a ton.

JavaScript: The Definitive Guide, by David Flanagan, is 1078 pages* of densely packed information on the JavaScript programming language. It’s not filled with fluff and it covers an amazing amount of ground. In truth, it’s really 3 books in one: a book on the core JavaScript language, a book on client-side JavaScript development, and a reference book for client-side and core development. It’s written for people familiar with programming who want to gain an in-depth understanding of everything they can do with JavaScript.

An experiment in retaining information

I didn’t want to read this book and then 6 months later not remember anything I’d read. I had a friend who’d read it and not gotten much out of it, but I believed that may have been because of information overload. Leisurely reading technical books can be fun, but the information isn’t going to stick unless you use it or discuss it. So I decided to try an experiment – after each chapter, I was going to write up a set of notes on what I found interesting in that chapter. That would force me to go back over the information and help me document what I may want to go back to later on.

I did this on the wordpress blog Reading the Rhino JS Book. It’s really just a collection of notes, but it’s a great way for me to go back and go “oh yeah, this is what I found interesting in this chapter”. In the beginning I was really excited and felt it was a great way to read a technical book – if you’re going to invest the time in reading a large book, you might as well invest the time to try and retain the information. However, I’d be lying if I didn’t say I got tired of writing up notes on each chapter. So my feelings are mixed. I do believe it helped in organizing what I learned and found interesting, but it was also a bit of a pain towards the end. I haven’t yet decided if I’ll take notes on each chapter of the next programming book I read, but I can say it was useful to do so in this case.

Who should read this Book?

I would not recommend this book for people who are new to JavaScript. It does contain almost everything you need to know, but it’s not really written for the newbie. When you’re new you want to get up and running quickly, and you want a brief introduction to the tool set you have at hand. For that, JavaScript: The Good Parts is probably the better choice.

If you do front-end web development professionally, or you just really like writing web apps, this book is worth picking up. It’s written to be readable and thoroughly covers the current set of web technologies you have at your finger tips with JavaScript. Even if you feel like you have a good handle on things, this book does a good job at filling in the gaps. As an example, I knew JavaScript did automatic semicolon insertion if you forgot to include semicolons**, but I wasn’t sure how this worked. It turns out that the ECMAScript spec has a clearly defined algorithm for this, and knowing how it works gives some insight into using the language.

Final Thoughts

This is probably now my favorite book on JavaScript. A couple weeks ago I was openly pondering where I wanted to go web development wise, and I think, for now, I’m going to focus on client-side development. This doesn’t mean I’m going to ignore back-end stuff, I do a lot of PHP at work and there’s other back-end technologies like Ruby, Python, and Node which look interesting, but the client-side looks like it has the most utility for app developers. It’s nice to be able to quickly write a single page app, upload it, and have anyone be able to use it.

* 716 pages if you don’t include the reference sections.
** Technically the interpreter doesn’t insert semicolons, it just treats a line break as the end of a statement in certain situations. Thus it’s sort of simulating semicolon insertion.

Trying out Chrome’s App Store for the Web after falling down the W3C Widget Rabbit Hole

In my last post I discussed offline storage for web apps, and that I wasn’t sure how users were supposed to know that certain apps worked offline. Google Chrome has come up with a neat solution for this that allows users to “install” web apps via their Chrome Web Store. I’d played around with its previous incarnation, when it was the Chrome Extension Gallery, but I hadn’t really been back since it opened up to web apps and changed its name.

Installed App

The Chrome Web Store is interesting because you can submit both packaged apps and hosted apps. A hosted apps is simply a zip file of a metadata file and some icons. The metadata file explains general information like the URL for the app and if it works online or not.

Installing a hosted app is sort of a fancy way of bookmarking it, but the fact Chrome tells you whether it works offline or not is a big plus. This solves the issue of letting users know that an app’s URL will work even when they don’t have an internet connection.

This is exactly the kind of thing I was looking for! To try it out, I decided to create hosted apps of my Text to ASCII Art Generator and JavaScript Snake Game:

Both work offline, and I plan to create hosted apps of some of my other programs too, but for now I’m just testing the waters. FireFox will also soon launch a web app store called The Mozilla Marketplace. It’s setup will be similar to chrome’s, though it’ll be slightly more feature rich, allowing you to run web apps like Desktop programs. This feature is similar to the idea behind W3C Widgets, though W3C Widgets seem to have fallen out of favor.

As an aside, before I ended up at Chrome’s Web Store, I took a detour through the world of W3C Widgets. I hadn’t heard of them before, and unless the tides change, I may not hear much about them again. However, I figured I’d write up what I learned, since they seem to be one of the least popular pieces in the HTML5 puzzle.

W3C Widgets?

While researching offline web storage, I was bothered by the fact that normal users would have no idea that certain URLs still worked when they were offline. With this concern, I ended up emailing the W3C’s fixing-appcache mailing list because I could only find a small bit of discussion on the topic, and that discussion didn’t come to a consensus about what to do. The response I got was pretty interesting, and made me realize there were areas to the HTML5 world that I hadn’t seen:

This is essentially what the Widgets spec is supposed to achieve.  See
here for an example of a widget configuration:

http://www.w3.org/TR/widgets/#example-configuration-document

It makes sense to split packaging a website from providing offline
storage/caching technologies, since the two are different solutions to
different problems.  It's true that there is some crossover,
especially if a widget includes content in its package.  But the
widgets spec has its own problems, not least of which is a terrible
name.

Letting users know that your site will work when offline doesn't seem
like a terribly difficult problem to solve at the application level,
to be honest. I think as a developer I'd rather browser vendors spend
their time on other stuff :-).  But it's certainly a fair point, and
does need to be considered as part of the UX of your app.

After thinking about it, he was right about separating out the packaging of an app from its offline storage capability. However, what was this widgets spec he mentioned? I’d never heard of W3C Widgets, so I decided to some research.

W3C Widgets are essentially packaged web apps. In fact, at one point, ppk proposed that they be put under the buzz word “HTML5 apps”. The W3C Widget spec discusses a format similar to Chrome extensions. You have a zip file of a directory structure containing HTML, CSS and JavaScirpt files, with a config.xml file that explains the basic metadata of the widget. Widgets can be embedded within a webpage or run from a user’s desktop. Not exactly what I was looking for, but it sounds kind of neat. Why had I never heard of this before? I did some more googling and the vast majority of the blogs and news regarding W3C Widgets seemed to be from 2009 or 2010. I could find nothing on Chrome, FireFox or IE implementing the spec – even though as of September 27, 2011, it became an official W3C recommendation.

I did, however, find a hand full of projects that used the spec. While there wasn’t a lot of buzz around W3C Widgets, there appeared to be enough going on with them that they weren’t in danger of falling into the abyss, at least not yet. Below is a list of the projects I found with some notes I made on them.

  • Opera’s Web Browser – Opera appears to have fully embraced W3C Widgets and is using the spec for Opera extensions. They’ve also set the browser up so that it will run widgets that you launch from your desktop. So its basically allowing you to create native-ish HTML5 apps. I find it peculiar that no other vendor has embraced W3C Widgets like Opera has.
  • Apache Wookie – This appears to be a widget environment and it reminds me of the OZone Widget Framework. Though Apache Wookie runs W3C widgets while OZone runs OZone widgets.
  • Phonegap – This framework allows developers to create HTML5 apps that can be distributed in mobile phone app stores. Its app configuration is based on the W3C Widget spec.
  • Wholesale Applications Community (WAC) – “An allegiance of telecommunications firms and others working together to create a common mobile platform” [ref]. W3C Widgets are apart of what they’re doing. However, according to this article, they ended up failing.

So each of these projects is kind of cool, but none of them addressed the original problem I had – how the hell are users supposed to know they have web apps installed on their computers that will work when they’re offline? And if W3C Widgets are the answer, why aren’t the major vendors adopting them? Eventually I had some nice people direct me towards the Chrome Web Store, and it was also nice to find out that FireFox will soon have its own web store too. Hopefully IE10 will do something similar when it comes out.

Even though I didn’t find them useful, it was interesting to learn about the existence of W3C Widgets. I’m not sure why they seem to have failed, as they’re essentially a way of packaging HTML5 apps. Though then again, I do think Chrome’s manifest is a lot nicer than the config.xml that the W3C Widget spec detailed.

Notes on Offline Web Storage for TAAG

After you’ve visited it at least once, the Text to ASCII Art Generator (TAAG) will now work even when you don’t have an internet connection. I had a user request this, so I figured I’d add it in for them and anyone else out there who may want to use the app offline.

Offline web applications are one of the new capabilities being introduced with HTML5. An offline web application has its files downloaded and permanently installed in a web browser’s application cache. This allows users to go to an app’s URL and have it work even when they aren’t online. It’s a smart idea, but it has some interesting pros and cons. In this entry I’ll detail what I did to set TAAG up to work offline, detail some issues I ran into, and provide some notes for anyone looking create an offline app.

The first step in creating an offline web application is to create a manifest file which tells the browser which files it should store in its application cache, which files should try getting from the network, and if offline, which files it should use in place of certain standard files. Any HTML files that reference this manifest will be implicitly added to the CACHE section of the manifest and after a user’s first visit, all cached data will come from the application cache, even if a user F5′s the page. The application cache is only ever updated when the manifest file is updated, and even then, it will take 2 visits for a user to see any updates. This is because when a user visits the app’s URL, the application will be read from the cache, it will then see the manifest has been updated, and it will then update the application cache for the user’s next visit. These idiosyncrasies are a bit to take in, but once you know what’s going on its not that bad. Here’s what a sample manifest file would look like:

CACHE MANIFEST
# This is a comment.
# The cache is only ever refreshed when changed.
# Last updated: 2012.08.18

# The CACHE section indicates what we want cached.
# The HTML file linking to this manifest to auto-added to this list.
CACHE:
one.jpg
two.jpg
jquery.js?12345

# The NETWORK section indicates which non-cached files should be 
# obtained from the network. This will almost always be "*".
NETWORK:
*

# The fallback section allows us to setup "fallback" pages to use 
# when offline.
FALLBACK:
page2.htm page2-is-offline.htm

An HTML file linking to this manifest might look like this:

<html manifest="my.appcache">
<head><title>Test</title><meta charset="utf-8"></head>
<body>
<div>Some text</div>
<img src="one.jpg"/>
<img src="two.jpg"/>
<script src="jquery.js?12345"></script>
</body>
</html>

And one last gotcha – to keep the manifest file from being cached by the browser, and to ensure the manifest is served with the correct mime type (an incorrect mime type will keep the manifest from being recognized), we need to update the web server’s configuration. For Apache, we’d add the following rules to our .htaccess file:

AddType text/cache-manifest .appcache

<Files *.appcache>
    ExpiresActive On
    ExpiresDefault "access"
</Files>

That should do it! With this technique your users will now be able to use your apps even when they don’t have an internet connection. I find this cool because it makes web apps more useful and puts them a step closer to supplanting Desktop apps. However, there are unfortunately a number of issues that have held offline web apps back, and they’re worth mentioning.

Issues with application caching

A lot of people aren’t happy with how application caching currently works. The W3C has set up a working group that’s discussing possible improvements, though hopefully the main components of the current spec will continue to work. However, I also feel like they need to make some changes too. Below I’ll list my biggest concerns.

  • How would users know that certain URLs still work when they’re offline?

    I don’t understand how this isn’t the most important issue for offline applications. Without someone manually telling you that you can use a particular application while offline, I don’t see how someone would think they could browse to example.com/webapp and expect it to work when they didn’t have an internet connection. In their current form, I only see offline applications as useful to techies or people in the know.

    It’d be nice if offline applications could provide an icon, name, and description, and then browsers could show users which offline applications they had installed. It could be argued that this is a browser feature, but bookmarks are a browser feature too, and all browsers allow webpages to provide a favicon for bookmarking purposes. Whatever the case, there should be a way to let users know certain web pages/apps work offline.

    I’ve only seen this discussed once, and the people involved didn’t come to any conclusions, so I’m not too hopeful on this one. However, I think it’s probably the most important point, since no users = no usage.

    2012.09.01 Edit: Someone alerted me that there is a Widgets spec that’s currently in the works that supposed to solve this issue. I haven’t taken a good look through it yet, but it’s good to know there are attempts to solve this problem currently in the works.

  • Fresh updates aren’t served immediately / F5 doesn’t break the cache / the page that links to the manifest has to be cached.

    This seems to be the most popular feature request, though after reading spec author Hixie’s take on the issue, I sort of agree that many of the use-cases for using the application cache in this way are very similar to straight up HTTP caching. Though it would be nice if an app used the HTTP cache while online and this cache synced with the application cache, which would then be used when a user was offline.

    Around two months ago, a new feature was added to spec in an attempt to address this. It takes the form of a new setting that gets added to the manifest:

    SETTINGS:
    prefer-online
    

    It’s explained here, though there’s some debate on if its the right solution, and I was unable to get it to work in Chrome or the nightly FireFox build, so I’m not sure how it works or if it actually solves the problem.

Other Notes

  • Chrome was easier to work with than FireFox

    Chrome will print to the console as its loading the application into the cache, so you know instantly if there’s a problem or not. FireFox didn’t do this and that made it a bit more annoying to work with.

  • Listing installed applications

    • For Chrome, browse to the URL “chrome://appcache-internals/”
    • For FireFox, in the menu, go to: “Tools>Options>Advanced>Network” and see the section on “Offline Web Content and User Data”.


  • In the manifest, URLs need to be URL encoded and query strings needed to be included

    Kind of obvious, but worth mentioning.

  • The popular iframe trick doesn’t work in FireFox

    There is a popular trick that aims to allow an HTML page to use the application cache while not being cached itself. It attempts this by having the page include an iframe with an HTML tag that links to the manifest. From my own tests, this trick works in Chrome but not in FireFox.

    2012.09.10 Update: After updating to FireFox 15, it seems to work now.

  • JavaScript API

    I didn’t go into it here, but there’s also a JavaScript API for the application cache. See the “Additional Resources” section below for more information.

  • What would happen if every website wanted to work offline?

    The space on a user’s computer is finite. I’m not sure how offline storage will work if offline apps end up becoming very popular in the future. Maybe the solution is to focus on installable apps which have the option of working offline – and users can pick and choose what they want installed?

Additional Resources

Tone Playing Experiment with HTML5′s Web Audio API

tl;dr: Tone Player (works in Google Chrome and Safari 6+ only)

One of my favorite parts of the QBasic class I had in high school was discovering how to play sounds. It introduced a whole new layer on which to experiment with.

Until recently, adding custom sounds to a web application has not been a simple task. Thankfully, the W3C is working on a new high level audio specification called the Web Audio API that allows you to easily create and play sounds. Webkit based browsers have pushed out an implementation of this spec (Chrome and Safari 6+), and hopefully other browsers will follow suit soon. Previously, Mozilla had been working on a more lower level audio API called the Audio Data API, but it is now deprecated.

After seeing a few fancy demos of the Web Audio API, I decided to do some digging to see what all it could do. Sadly, there aren’t a lot of great up-to-date tutorials on how to use it. A couple of exceptions I found to this were the getting started tutorial at creativejs.com and a hand full of nice blog posts by Stuart Memo. However, I was also surprised to find that the Web Audio WC3 specification is actually very readable.

So with this fancy new API, how hard is it to create and play a simple tone? It’s pretty easy actually. The below code gives one example.

var context = new webkitAudioContext(),//webkit browsers only
    oscillator = context.createOscillator();

oscillator.type = 0; // sine wave
oscillator.frequency.value = 2000;
oscillator.connect(context.destination);
oscillator.noteOn && oscillator.noteOn(0);

You can also play more than one frequency at once. However, I found that playing too many tones together can crash the browser, so this is something you have to be careful about, and there may be a better way to do this.

var context = new webkitAudioContext(),
    oscillators = [], num = 5, ii;

for (ii = 0; ii < num; ii++) {
    oscillators[ii] = context.createOscillator();
    oscillators[ii].type = 0;
    oscillators[ii].frequency.value = 2000 + ii * 200;
}

var connectIt = function(ii) {
    oscillators[ii].connect(context.destination);
    oscillators[ii].noteOn && oscillators[ii].noteOn(0);
    ii++;
    if (ii < num) {
        setTimeout(function() {connectIt(ii);}, 1000);
    } else {
        setTimeout(function() {
            for (var jj = 0; jj < num; jj++) {
                oscillators[jj].disconnect();
            }
        }, 1000);
    }
}

connectIt(0);

Oh, and you'll notice I check for the noteOn property before trying to use it. The spec says you need to use it, while Chrome tells me it doesn't exist. This appears to be a possible bug in Chrome's implementation.

With the basics down, I decided to create a simple Tone Player. It doesn't add much to what I've already showed you, but it has a few extra features. And in all honestly, it was actually made more to serve as a hearing test for myself. A couple years ago I had a hearing test done which indicated I had hearing issues, especially in my left ear. Since then I've been trying to take care of my hearing as best as possible. This tone generator is fascinating for me because I actually found that I can't hear certain frequencies (near 12000Hz), unless I really jack up the volume, but I can hear others fine all the way up to the 20k's. Hrm, probably time to schedule another appointment.

Anyway, enough about my hearing issues. Even though the API currently only works in a couple of browsers, it's a lot of fun, and I've hardly even dared to scratch the surface with this entry. I recommend checking it out if you have a few moments. If you're looking for a less experimental, more cross-browser way to play sound, I'd recommend checking out one of the many JavaScript libraries that have popped up to play audio. I'll link a few below for those who are interested.