use localStorage to cache homepage/category API responses (bug 980081)

This is a working implementation of [bug 980081](https://bugzilla.mozilla.org/show_bug.cgi?id=980081) but using `localStorage` as a proof of concept instead of `IndexedDB` ([localForage](https://github.com/mozilla/localForage)). The goal is to improve the second-run experience (launching the app for any subsequent time after the first time the app is launched). I'd encourage people to read my [exhaustive proposal](https://bugzilla.mozilla.org/show_bug.cgi?id=980081#c1) in the bug if they're curious.

I'd love to have lots of eyes on this and get people's feedback. @dethe and I will be working on this, and if anyone else is interested in helping out here, holler at us.

- [x] persist request cache
- [x] persist model cache
- [x] do asynchronous cache refreshing (such that even on cache hits, we update the cache in the background by letting each XHR still go through after the template has been rendered from the cached data from the *persistent* cache [never from the local, in-memory cache] and updating the local, in-memory cache when the request)
- [x] upon log out, remove all cached responses (persisted and local, in-memory ones) containing for signed URLs (those containing `?_user=` tokens that may or may not contain user data)
- [x] allow local setting (`offline_cache_enabled`) and query-string parameter (`?cache=false`) to disable caching
- [x] allow cache to be disabled, reenabled, and cleared from the debug page
- [x] use a whitelist for only relevant API endpoints (i.e., not search results, ratings, etc.)
- [x] use an LRU cache (allowing each whitelisted API URL to have a different TTL)
- [x] figure out a way to expire model cache (consider whitelisting + LRU cache like we're doing for request cache; because the model cache gets rewritten whenever the request cache gets updated, this is not a huge concern but if there are models in the persisted model cache that we never end up using [e.g., a featured app gets removed from the homepage], then we're wasting space [albeit not a huge ton])
- [ ] use localForage instead of localStorage
- [x] add tests
- [ ] enhancement for later: move background XHRs to a web worker