Summary: | ApplicationCache: feature request - scriptable APIs to manage the set of appcaches created by a site. | ||
---|---|---|---|
Product: | WebKit | Reporter: | Michael Nordman <michaeln> |
Component: | WebCore Misc. | Assignee: | Michael Nordman <michaeln> |
Status: | RESOLVED WONTFIX | ||
Severity: | Normal | CC: | annevk, ap, dgrogan, ian, me, peter |
Priority: | P2 | ||
Version: | 528+ (Nightly build) | ||
Hardware: | Unspecified | ||
OS: | Unspecified |
Description
Michael Nordman
2011-08-29 10:18:56 PDT
We have similar desirements to enumerate other object types like indexedDBs and sqlDBs, and related desirements to delete these other object types. We could introduce a top level object in the window/worker namespace that contains methods to perform these things. window.<something>.enumerateApplicationCaches(...) window.<something>.enumerateIndexedDatabases(...) window.<something>.enumerateSqlDatabases(...) window.<something>.deleteApplicationCache(manifestUrl); window.<something>.deleteIndexedDatabase(name); window.<something>.deleteSqlDatabase(name); > We could introduce a top level object in the window/worker namespace that contains methods to perform these things.
> window.<something>.enumerateApplicationCaches(...)
Looks like window.storageInfo could work for this.
window.storageInfo.enumerateApplicationCaches(ApplicationCacheEnumerationCallback callback);
window.storageInfo.getApplicationCacheInfo(String manifestUrl, ApplicationCacheInfoCallback callback) raises(DOMException);
interface ApplicationCacheEnumerationCallback {
void handleEvent(in ApplicationCacheInfoArray cacheInfos);
}
interface ApplicationCacheInfoCallback {
void handleEvent(in ApplicationCacheInfo cacheInfo);
}
interface ApplicationCacheInfo : public DOMApplicationCache {
// meta data accessors
readonly attribute String manifestUrl;
readonly attribute number size;
readonly attribute DateTime creationTime;
readonly attribute DateTime lastCheckTime; // The last time a manifest was checked for a newer version
readonly attribute DateTime lastUpdateTime; // The last time a manifest fetch caused an actual update
readonly attribute DateTime lastAccessTime; // The last time the cache actually bound to a browsing context
// ability to delete an appcache
void delete() raises(DOMException);
// Other stuff is inherited from DOMApplicationCache
}
(In reply to comment #2) > > We could introduce a top level object in the window/worker namespace that contains methods to perform these things. > > window.<something>.enumerateApplicationCaches(...) > > Looks like window.storageInfo could work for this. For this to work, storageInfo should also be available in WorkerContext.idl. I think to proceed with this, it'd be good to put it behind a new ENABLE(APPLICATION_CACHE_INFO) flag until its fully ready to go. Some notes on our latest thoughts. StorageInfo { // Support for listing, creating, updating, deleting, and monitoring the status of appcaches. void getApplicationCaches(ApplicationCachesCallback callback); void deleteApplicationCache(String manifestUrl); void getApplicationCacheInfo(String manifestUrl, ApplicationCacheInfoCallback callback); // Support for listing and deleting sql databases. void getSqlDatabases(SqlDatabasesCallback callback); void deleteSqlDatabase(String databaseName); } interface ApplicationCacheInfo { readonly attribute String manifestUrl; readonly attribute number sizeInBytes; readonly attribute DateTime lastAccessTime; // The last time the cache was bound to a browsing context void createOrUpdate(); readonly attribute unsigned short status; // UNCACHED,IDLE,CHECKING,DOWNLOADING,OBSOLETE attribute EventListener onchecking; attribute EventListener onerror; attribute EventListener onnoupdate; attribute EventListener ondownloading; attribute EventListener onprogress; attribute EventListener oncached; attribute EventListener onobsolete; } interface ApplicationCachesCallback { void handleEvent(in ApplicationCacheInfo[] info); } interface ApplicationCacheInfoCallback { void handleEvent(in ApplicationCacheInfo cache); } interface SqlDatabaseInfo { readonly attribute String name; readonly attribute number sizeInBytes; readonly attribute DateTime lastAccessTime; // The last time the database was opened } interface SqlDatabasesCallback { void handleEvent(in SqlDatabaseInfo[] info); } Seems mostly reasonable. Any particular reason for using a separate interface than ApplicationCache to represent the cache? Most of this object seems to duplicate the existing interface. The name "createOrUpdate()" is a bit ugly, I'd go with the less precise but cleaner "update()", personally. Why have deleteApplicationCache() as a separate method rather than a method on the ApplicationCache object? Don't forget to vendor-prefix the API since it's not specced yet. (pinch me... some feedback/discussion that doesn't start and end with "whats your use case" :) > Any particular reason for using a separate interface than ApplicationCache to represent the cache? Most of this object seems to duplicate the existing interface. The existing DOMApplicationCache and the new 'info' interfaces overlap quite alot, particularly the event handlers and status accessor, but not entirely. The swapCache() method doesn't apply to the info object, and a status value of UPDATE_READY doesn't make sense either. There is no 'create' capability with DOMApplicationCache. I see them as different object types. The DOMApplicationCache is that which is bound to your document. Info objects are a new object type, not bound to your document or frame in anyway. I'd be more in favor of adding a 'manifestUrl' attribute to the DOMApplicationCache interface than merging them together. Given the attr callers could easily lookup the 'info' for that manifestUrl as needed for management purposes. > The name "createOrUpdate()" is a bit ugly, I'd go with the less precise but cleaner "update()", personally. Wanted to be clear that this gave a means of creating it. > Why have deleteApplicationCache() as a separate method rather than a method on the ApplicationCache object? A usecase I've seen would be streamlined by not having to first 'get' and then 'delete'. Here's what they do now. <iframe style='display: none;' src='unwantedManifest1'></iframe> <iframe style='display: none;' src='unwantedManifest2'></iframe> Also symmetry with the deleteSqlDatabase() function. In some cases we're seeing a need to delete databases because they cant be opened. > Don't forget to vendor-prefix the API since it's not specced yet. Yup, the 'storageInfo' object is itself prefixed since that is not yet specced. I'm not sure of these additions need additional prefixing. webkitStorageInfo.getApplicationCaches(...); vs webkitStorageInfo.webkitGetApplicationCaches(...) (In reply to comment #7) > (pinch me... some feedback/discussion that doesn't start and end with "whats your use case" :) I'm assuming your use cases are "a big site with many applications would like to be able to provide a page that deletes all the cached applications on that site", and "a big site with many applications would like to be able to install or update multiple applications at once". Regarding the objects: I think it would be unfortunate to use an entirely separate interface. IMHO we should either use the same objects (my preference), in particular having the navigator.applicationCache object === the object in the enumeration, if the current page is cached, or, if there's really good reasons not to do that, we should at least have the Info objects inherit from an AbstractApplicationCache interface that hosts all the common bits. Having two almost entirely duplicate interfaces seems like poor design. > swapCache() It can just throw an exception in the case where the cache isn't the current one (InvalidStateError). > status value of UPDATE_READY doesn't make sense That's no big deal. The attribute would just never take that value. > no 'create' capability with DOMApplicationCache. We can just update() creates instead of throwing an exception. Regarding deleting, it's not like it's going to happen so often that saving a few keystrokes is going to matter: window.storageInfo.getApplicationCacheInfo(manifestURL, function (o) { o.delete(); }); ...vs: window.storageInfo.deleteApplicationCacheInfo(manifestURL); I mean, you could just as easily suggest that we add an "updateApplicationCacheInfo(manifestURL)" method so that you don't have to get the object to update it, or even a "getApplicationCacheStatus(manifestURL)" method... Why is deletion special? > Also symmetry with the deleteSqlDatabase() function. Since WebSQLDatabase is a vestigial feature only implemented in certain UAs, and not part of the Web platform proper, I don't think that's a great goal. Soon enough the SQL things will disappear and being consistent with it would be pointless. Having said that, though, I'd move the consistency the other way: just put delete() into SqlDatabaseInfo. > > Don't forget to vendor-prefix the API since it's not specced yet. > > Yup, the 'storageInfo' object is itself prefixed since that is not yet specced. LGTM. Thnx for taking the time hixie! (In reply to comment #8) > I'm assuming your use cases are "a big site with many applications would like to be able to provide a page that deletes all the cached applications on that site", and "a big site with many applications would like to be able to install or update multiple applications at once". Yup, of course. > Regarding the objects: I think it would be unfortunate to use an entirely separate interface. IMHO we should either use the same objects (my preference), in particular having the navigator.applicationCache object === the object in the enumeration, if the current page is cached, or, if there's really good reasons not to do that, we should at least have the Info objects inherit from an AbstractApplicationCache interface that hosts all the common bits. Having two almost entirely duplicate interfaces seems like poor design. Interesting, an earlier draft employed interface inheritance. Other feedback told me that was misleading since it didn't employ object inheritance. I can see reusing the same interface or deriving from a common interface to compose two different ones. But i maintain that there are two different object types, associatedCache vs cacheInfo In particular, having window.applicationCache === oneParticularInfoInstance is troublesome. That particular info object would behave subtlety differently than the rest if your page happened to be bound to manifest (it would enter the UPDATE_READY state, .swapCache() would have meaning, you would not be able to see latest 'info' about the current version w/o calling swapCache()). Also, its mysteriously tied to a particular Document. When that document goes away, it would break (or mysteriously revert to being an 'unassociated' instance)... all that is wonky. > > swapCache() > It can just throw an exception in the case where the cache isn't the current one (InvalidStateError). > > status value of UPDATE_READY doesn't make sense > That's no big deal. The attribute would just never take that value. > > no 'create' capability with DOMApplicationCache. > We can just update() creates instead of throwing an exception. Sure, it could be that way, if we reuse the same interface. > Regarding deleting, it's not like it's going to happen so often that saving a few keystrokes is going to matter: > window.storageInfo.getApplicationCacheInfo(manifestURL, function (o) { o.delete(); }); > I mean, you could just as easily suggest that we add an "updateApplicationCacheInfo(manifestURL)" method so that you don't have to get the object to update it, or even a "getApplicationCacheStatus(manifestURL)" method... Why is deletion special? Good point, symmetry with IndexedDB which has a delete() method is more desirable anyway. > Since WebSQLDatabase is a vestigial feature only implemented in certain UAs, and not part of the Web platform proper, I don't think that's a great goal. Soon enough the SQL things will disappear and being consistent with it would be pointless. Having said that, though, I'd move the consistency the other way: just put delete() into SqlDatabaseInfo. A delete() method on the db object actually doesn't work in some cases. There are difficult cases where open() can fail to produce an instance and throws an exception instead (the sync nature + version checking semantics built into open() are problematic). This new vestige wants to be a standalone method. (In reply to comment #9) > Thnx for taking the time hixie! My pleasure. I'm likely to end up having to spec this anyway one day. ;-) Regarding window.applicationCache === oneParticularInfoInstance, you raise some very valid points. Let's not do that. Having a common interface may be the way to go. Having almost duplicate interface definitions really raises some red flags for me. We're very likely to end up with subtle differences in the APIs if we go that route, e.g. someone typos it in one of the definitions, or the copy/paste is done slightly wrong, or whatnot. Better to clearly indicate that they're supposed to be identical right up front by having just one copy of the definitions (and ideally sharing as much implementation code as possible too). > A delete() method on the db object actually doesn't work in some cases. Not on the db object, on the SqlDatabaseInfo object. > My pleasure. I'm likely to end up having to spec this anyway one day. ;-) nice! > Regarding window.applicationCache === oneParticularInfoInstance, you raise some very valid points. Let's not do that. > > Having a common interface may be the way to go. Having almost duplicate interface definitions really raises some red flags for me. We're very likely to end up with subtle differences in the APIs if we go that route, e.g. someone typos it in one of the definitions, or the copy/paste is done slightly wrong, or whatnot. Better to clearly indicate that they're supposed to be identical right up front by having just one copy of the definitions (and ideally sharing as much implementation code as possible too). Sgtm. All of the additional members on the 'info' object in comment #5 (plus a delete method) could also be provided directly on the window.applicationCache object. My plan for delete is to have the group asyncly enter the OBSOLETE state and raise events accordingly. > Not on the db object, on the SqlDatabaseInfo object. yes, that works for me I'll run these refinements by some would be internal customers for this. I'm not sure we really need the datetime values, i'll see about dropping those too. Did any of this end up getting implemented? (In reply to comment #12) > Did any of this end up getting implemented? Nope. Ok, I've started spec work on this (based on the comments above) at: https://www.w3.org/Bugs/Public/show_bug.cgi?id=18609 This is a feature we've disabled/removed. |