gecko/dom/tests/mochitest/ajax/offline/offlineTests.js

285 lines
7.4 KiB
JavaScript

// Utility functions for offline tests.
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var Cc = Components.classes;
var Ci = Components.interfaces;
const kNetBase = 2152398848; // 0x804B0000
var NS_ERROR_CACHE_KEY_NOT_FOUND = kNetBase + 61;
var NS_ERROR_CACHE_KEY_WAIT_FOR_VALIDATION = kNetBase + 64;
// Reading the contents of multiple cache entries asynchronously
function OfflineCacheContents(urls) {
this.urls = urls;
this.contents = {};
}
OfflineCacheContents.prototype = {
QueryInterface: function(iid) {
if (!iid.equals(Ci.nsISupports) &&
!iid.equals(Ci.nsICacheListener)) {
throw Cr.NS_ERROR_NO_INTERFACE;
}
return this;
},
onCacheEntryAvailable: function(desc, accessGranted, status) {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
if (!desc) {
this.fetch(this.callback);
return;
}
var stream = desc.QueryInterface(Ci.nsICacheEntryDescriptor).openInputStream(0);
var sstream = Components.classes["@mozilla.org/scriptableinputstream;1"]
.createInstance(Components.interfaces.nsIScriptableInputStream);
sstream.init(stream);
this.contents[desc.key] = sstream.read(sstream.available());
sstream.close();
desc.close();
this.fetch(this.callback);
},
fetch: function(callback)
{
this.callback = callback;
if (this.urls.length == 0) {
callback(this.contents);
return;
}
var url = this.urls.shift();
var self = this;
var cacheSession = OfflineTest.getActiveSession();
cacheSession.asyncOpenCacheEntry(url, Ci.nsICache.ACCESS_READ, this);
}
};
var OfflineTest = {
_slaveWindow: null,
// The window where test results should be sent.
_masterWindow: null,
setupChild: function()
{
if (window.parent.OfflineTest.hasSlave()) {
return false;
}
this._slaveWindow = null;
this._masterWindow = window.top;
return true;
},
// Setup the tests. This will reload the current page in a new window
// if necessary.
setup: function()
{
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
if (!window.opener || !window.opener.OfflineTest ||
!window.opener.OfflineTest._isMaster) {
// Offline applications must be toplevel windows and have the
// offline-app permission. Because we were loaded without the
// offline-app permission and (probably) in an iframe, we need to
// enable the pref and spawn a new window to perform the actual
// tests. It will use this window to report successes and
// failures.
var pm = Cc["@mozilla.org/permissionmanager;1"]
.getService(Ci.nsIPermissionManager);
var uri = Cc["@mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService)
.newURI(window.location.href, null, null);
pm.add(uri, "offline-app", Ci.nsIPermissionManager.ALLOW_ACTION);
// Tests must run as toplevel windows. Open a slave window to run
// the test.
this._isMaster = true;
this._slaveWindow = window.open(window.location, "offlinetest");
this._slaveWindow._OfflineSlaveWindow = true;
return false;
}
this._masterWindow = window.opener;
return true;
},
teardown: function()
{
// Remove the offline-app permission we gave ourselves.
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var pm = Cc["@mozilla.org/permissionmanager;1"]
.getService(Ci.nsIPermissionManager);
var uri = Cc["@mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService)
.newURI(window.location.href, null, null);
pm.remove(uri.host, "offline-app");
this.clear();
},
finish: function()
{
SimpleTest.finish();
if (this._masterWindow) {
this._masterWindow.OfflineTest.finish();
window.close();
}
},
hasSlave: function()
{
return (this._slaveWindow != null);
},
//
// Mochitest wrappers - These forward tests to the proper mochitest window.
//
ok: function(condition, name, diag)
{
return this._masterWindow.SimpleTest.ok(condition, name, diag);
},
is: function(a, b, name)
{
return this._masterWindow.SimpleTest.is(a, b, name);
},
isnot: function(a, b, name)
{
return this._masterWindow.SimpleTest.isnot(a, b, name);
},
clear: function()
{
// XXX: maybe we should just wipe out the entire disk cache.
var appCacheService = Cc["@mozilla.org/network/application-cache-service;1"]
.getService(Ci.nsIApplicationCacheService);
var applicationCache = this.getActiveCache();
if (applicationCache) {
applicationCache.discard();
}
},
failEvent: function(e)
{
OfflineTest.ok(false, "Unexpected event: " + e.type);
},
// The offline API as specified has no way to watch the load of a resource
// added with applicationCache.add().
waitForAdd: function(url, onFinished) {
// Check every half second for ten seconds.
var numChecks = 20;
var waitFunc = function() {
var cacheSession = OfflineTest.getActiveSession();
var entry;
try {
var entry = cacheSession.openCacheEntry(url, Ci.nsICache.ACCESS_READ, true);
} catch (e) {
}
if (entry) {
entry.close();
onFinished();
return;
}
if (--numChecks == 0) {
onFinished();
return;
}
setTimeout(OfflineTest.priv(waitFunc), 500);
}
setTimeout(this.priv(waitFunc), 500);
},
getManifestUrl: function()
{
return window.top.document.documentElement.getAttribute("manifest");
},
getActiveCache: function()
{
// Note that this is the current active cache in the cache stack, not the
// one associated with this window.
var serv = Cc["@mozilla.org/network/application-cache-service;1"]
.getService(Ci.nsIApplicationCacheService);
return serv.getActiveCache(this.getManifestUrl());
},
getActiveSession: function()
{
var cache = this.getActiveCache();
if (!cache) return null;
var cacheService = Cc["@mozilla.org/network/cache-service;1"]
.getService(Ci.nsICacheService);
return cacheService.createSession(cache.clientID,
Ci.nsICache.STORE_OFFLINE,
true);
},
priv: function(func)
{
var self = this;
return function() {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
func(arguments);
}
},
checkCache: function(url, expectEntry)
{
var cacheSession = this.getActiveSession();
if (!cacheSession) {
if (expectEntry) {
this.ok(false, url + " should exist in the offline cache");
} else {
this.ok(true, url + " should not exist in the offline cache");
}
return;
}
try {
var entry = cacheSession.openCacheEntry(url, Ci.nsICache.ACCESS_READ, false);
if (expectEntry) {
this.ok(true, url + " should exist in the offline cache");
} else {
this.ok(false, url + " should not exist in the offline cache");
}
entry.close();
} catch (e) {
if (e.result == NS_ERROR_CACHE_KEY_NOT_FOUND) {
if (expectEntry) {
this.ok(false, url + " should exist in the offline cache");
} else {
this.ok(true, url + " should not exist in the offline cache");
}
} else if (e.result == NS_ERROR_CACHE_KEY_WAIT_FOR_VALIDATION) {
// There was a cache key that we couldn't access yet, that's good enough.
if (expectEntry) {
this.ok(true, url + " should exist in the offline cache");
} else {
this.ok(false, url + " should not exist in the offline cache");
}
} else {
throw e;
}
}
}
};