4

Is there a way to query the contents of the HTML5 application cache?

I'm writing an iOS application that uses a lot of cached web content. Before loading a given page when the app is offline, I'd like to check whether the page exists in the cache. If it doesn't, I'll notify the user that they have to be online to see that content; if it does, I'll go ahead and load it.

Now, iOS has its own URL caching system, and I initially just assumed that I could check the contents of the cache this way:

if ([[NSURLCache sharedURLCache] cachedResponseForRequest:myRequest] != nil) {
    // go ahead and load the page
}
else {
    // notify the user that the content isn't available
}

Silly me. It seems that iOS's cache and HTML5's cache are unrelated: -cachedResponseForRequest: returns nil for any request, even when I can see that the URL is in the HTML5 application cache (using the Safari web debugger).

So, is there some way that I can query the contents of the HTML5 application cache? It doesn't matter if the answer uses Objective-C code or Javascript, since I can always just execute the relevant JS from Objective-C.

Caleb
  • 124,013
  • 19
  • 183
  • 272
  • HTML5 application cache operations are atomic - if the file is listed in the manifest, and the cache exists, the file is guaranteed to be in the cache. In your situation are you expecting files not listed in the manifest to get added to the appcache? – robertc Jan 20 '13 at 11:01
  • @robertc Thanks for that. I'm not expecting additions to the cache, but the manifest changes from time to time and the cache updates appropriately. – Caleb Jan 20 '13 at 14:38
  • OK, there are some other factors which are worth mentioning, I'll write up a 'proper' answer shortly. – robertc Jan 20 '13 at 15:42

2 Answers2

2

There are two properties of HTML5 AppCache which mean that in normal operation there shouldn't be a need to do so:

  1. AppCache update operations are atomic, either the entire cache is updated, or none of it it
  2. Once an AppCache is created then all files that are in the cache are served from the cache

The end result is that for any given version of the manifest file, any file listed in it that gets loaded into the browser will be consistent with all the other files listed in the manifest. All you should need to check is window.applicationCache.status and check that it is not UNCACHED.

There is another possibility. If you are 'lazily adding' files to the AppCache as described in Dive Into HTML5 then it could be that you're not sure which files are cached. In this case you could adapt one of the approaches for detecting online state, I'm not going to give you a fully tested solution but here is the general idea:

  1. Create a web page containing a unique identifier, something that's unlikely to ever appear normally in a page. The identifier can be in hidden content in an otherwise normal page.
  2. Set this page as the generic FALLBACK in your manifest.
  3. Request pages with AJAX.
  4. Scan the response for the unique identifier, if you find it then you know the page requested is not in the AppCache
Community
  • 1
  • 1
robertc
  • 74,533
  • 18
  • 193
  • 177
  • Thanks for taking the time to answer. This is a hybrid iOS app where the native part is a container that doesn't know much about the content. The web-based content is cached so that the app works even when the device doesn't have network access. I can detect a missing connection just fine, but I'd like to handle certain errors, like 404's from uncached content, by preventing uncached links from even loading in the first place. I'm looking for a way to determine whether or not a given page is in the cache manifest short of downloading and parsing it myself. – Caleb Jan 20 '13 at 18:32
  • @Caleb I didn't describe how to detect a missing connection, I described how to detect a missing file. You don't have to parse the file, just search it for your unique identifier. If you set it up like I suggested you won't get any 404s, just the fallback page. – robertc Jan 20 '13 at 20:19
1

Yes,the cache is stored in the Application.db.

unbuglee
  • 195
  • 1
  • 11