michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /** michael@0: * This test executes nsIOfflineCacheUpdateService.scheduleAppUpdate API michael@0: * 1. preloads an app with a manifest to a custom sudir in the profile (for simplicity) michael@0: * 2. observes progress and completion of the update michael@0: * 3. checks presence of index.sql and files in the expected location michael@0: */ michael@0: michael@0: Cu.import("resource://testing-common/httpd.js"); michael@0: michael@0: var httpServer = null; michael@0: var cacheUpdateObserver = null; michael@0: michael@0: function make_channel(url, callback, ctx) { michael@0: var ios = Cc["@mozilla.org/network/io-service;1"]. michael@0: getService(Ci.nsIIOService); michael@0: return ios.newChannel(url, "", null); michael@0: } michael@0: michael@0: function make_uri(url) { michael@0: var ios = Cc["@mozilla.org/network/io-service;1"]. michael@0: getService(Ci.nsIIOService); michael@0: return ios.newURI(url, null, null); michael@0: } michael@0: michael@0: // start the test with loading this master entry referencing the manifest michael@0: function masterEntryHandler(metadata, response) michael@0: { michael@0: var masterEntryContent = ""; michael@0: response.setHeader("Content-Type", "text/html"); michael@0: response.bodyOutputStream.write(masterEntryContent, masterEntryContent.length); michael@0: } michael@0: michael@0: // manifest defines fallback namespace from any /redirect path to /content michael@0: function manifestHandler(metadata, response) michael@0: { michael@0: var manifestContent = "CACHE MANIFEST\n"; michael@0: response.setHeader("Content-Type", "text/cache-manifest"); michael@0: response.bodyOutputStream.write(manifestContent, manifestContent.length); michael@0: } michael@0: michael@0: // finally check we got fallback content michael@0: function finish_test(customDir) michael@0: { michael@0: var offlineCacheDir = customDir.clone(); michael@0: offlineCacheDir.append("OfflineCache"); michael@0: michael@0: var indexSqlFile = offlineCacheDir.clone(); michael@0: indexSqlFile.append('index.sqlite'); michael@0: do_check_eq(indexSqlFile.exists(), true); michael@0: michael@0: var file1 = offlineCacheDir.clone(); michael@0: file1.append("2"); michael@0: file1.append("E"); michael@0: file1.append("2C99DE6E7289A5-0"); michael@0: do_check_eq(file1.exists(), true); michael@0: michael@0: var file2 = offlineCacheDir.clone(); michael@0: file2.append("8"); michael@0: file2.append("6"); michael@0: file2.append("0B457F75198B29-0"); michael@0: do_check_eq(file2.exists(), true); michael@0: michael@0: // This must not throw an exception. After the update has finished michael@0: // the index file can be freely removed. This way we check this process michael@0: // is no longer keeping the file open. Check like this will probably michael@0: // work only Windows systems. michael@0: michael@0: // This test could potentially randomaly fail when we start closing michael@0: // the offline cache database off the main thread. Tries in a loop michael@0: // may be a solution then. michael@0: try { michael@0: indexSqlFile.remove(false); michael@0: do_check_true(true); michael@0: } michael@0: catch (ex) { michael@0: do_throw("Could not remove the sqlite.index file, we still keep it open \n" + ex + "\n"); michael@0: } michael@0: michael@0: httpServer.stop(do_test_finished); michael@0: } michael@0: michael@0: function run_test() michael@0: { michael@0: httpServer = new HttpServer(); michael@0: httpServer.registerPathHandler("/masterEntry", masterEntryHandler); michael@0: httpServer.registerPathHandler("/manifest", manifestHandler); michael@0: httpServer.start(4444); michael@0: michael@0: var profileDir = do_get_profile(); michael@0: var customDir = profileDir.clone(); michael@0: customDir.append("customOfflineCacheDir" + Math.random()); michael@0: michael@0: var pm = Cc["@mozilla.org/permissionmanager;1"] michael@0: .getService(Ci.nsIPermissionManager); michael@0: var uri = make_uri("http://localhost:4444"); michael@0: var principal = Cc["@mozilla.org/scriptsecuritymanager;1"] michael@0: .getService(Ci.nsIScriptSecurityManager) michael@0: .getNoAppCodebasePrincipal(uri); michael@0: michael@0: if (pm.testPermissionFromPrincipal(principal, "offline-app") != 0) { michael@0: dump("Previous test failed to clear offline-app permission! Expect failures.\n"); michael@0: } michael@0: pm.addFromPrincipal(principal, "offline-app", Ci.nsIPermissionManager.ALLOW_ACTION); michael@0: michael@0: var ps = Cc["@mozilla.org/preferences-service;1"] michael@0: .getService(Ci.nsIPrefBranch); michael@0: ps.setBoolPref("browser.cache.offline.enable", true); michael@0: // Set this pref to mimic the default browser behavior. michael@0: ps.setComplexValue("browser.cache.offline.parent_directory", Ci.nsILocalFile, profileDir); michael@0: michael@0: var us = Cc["@mozilla.org/offlinecacheupdate-service;1"]. michael@0: getService(Ci.nsIOfflineCacheUpdateService); michael@0: var update = us.scheduleAppUpdate( michael@0: make_uri("http://localhost:4444/manifest"), michael@0: make_uri("http://localhost:4444/masterEntry"), michael@0: 0 /* no AppID */, false /* not in browser*/, michael@0: customDir); michael@0: michael@0: var expectedStates = [ michael@0: Ci.nsIOfflineCacheUpdateObserver.STATE_DOWNLOADING, michael@0: Ci.nsIOfflineCacheUpdateObserver.STATE_ITEMSTARTED, michael@0: Ci.nsIOfflineCacheUpdateObserver.STATE_ITEMPROGRESS, michael@0: Ci.nsIOfflineCacheUpdateObserver.STATE_ITEMCOMPLETED, michael@0: Ci.nsIOfflineCacheUpdateObserver.STATE_FINISHED michael@0: ]; michael@0: michael@0: update.addObserver({ michael@0: updateStateChanged: function(update, state) michael@0: { michael@0: do_check_eq(state, expectedStates.shift()); michael@0: michael@0: if (state == Ci.nsIOfflineCacheUpdateObserver.STATE_FINISHED) michael@0: finish_test(customDir); michael@0: }, michael@0: michael@0: applicationCacheAvailable: function(appCache) michael@0: { michael@0: } michael@0: }, false); michael@0: michael@0: do_test_pending(); michael@0: }