summaryrefslogtreecommitdiffstats
path: root/netwerk/test/unit/test_bug767025.js
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--netwerk/test/unit/test_bug767025.js315
1 files changed, 315 insertions, 0 deletions
diff --git a/netwerk/test/unit/test_bug767025.js b/netwerk/test/unit/test_bug767025.js
new file mode 100644
index 0000000000..cc10d85ae2
--- /dev/null
+++ b/netwerk/test/unit/test_bug767025.js
@@ -0,0 +1,315 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+
+"use strict";
+
+const { HttpServer } = ChromeUtils.import("resource://testing-common/httpd.js");
+const { PermissionTestUtils } = ChromeUtils.import(
+ "resource://testing-common/PermissionTestUtils.jsm"
+);
+
+/**
+ * This testcase does the following steps to make sure that bug767025 removes
+ * files as expected.
+ *
+ * STEPS:
+ * - Schedule a offline cache update for app.manifest.
+ * - pages/foo1, pages/foo2, pages/foo3, and pages/foo4 are cached.
+ * - Activate pages/foo1
+ * - Doom pages/foo1, and pages/foo2.
+ * - pages/foo1 should keep alive while pages/foo2 was gone.
+ * - Activate pages/foo3
+ * - Evict all documents.
+ * - all documents except pages/foo1 are gone since pages/foo1 & pages/foo3
+ * are activated.
+ */
+
+const kNS_OFFLINECACHEUPDATESERVICE_CONTRACTID =
+ "@mozilla.org/offlinecacheupdate-service;1";
+const kNS_CACHESTORAGESERVICE_CONTRACTID =
+ "@mozilla.org/netwerk/cache-storage-service;1";
+const kNS_APPLICATIONCACHESERVICE_CONTRACTID =
+ "@mozilla.org/network/application-cache-service;1";
+
+const kManifest =
+ "CACHE MANIFEST\n" +
+ "/pages/foo1\n" +
+ "/pages/foo2\n" +
+ "/pages/foo3\n" +
+ "/pages/foo4\n";
+
+const kDataFileSize = 1024; // file size for each content page
+const kHttpLocation = "http://localhost:4444/";
+
+function manifest_handler(metadata, response) {
+ info("manifest\n");
+ response.setHeader("content-type", "text/cache-manifest");
+
+ response.write(kManifest);
+}
+
+function datafile_handler(metadata, response) {
+ info("datafile_handler\n");
+ let data = "";
+
+ while (data.length < kDataFileSize) {
+ data =
+ data +
+ Math.random()
+ .toString(36)
+ .substring(2, 15);
+ }
+
+ response.setHeader("content-type", "text/plain");
+ response.write(data.substring(0, kDataFileSize));
+}
+
+function app_handler(metadata, response) {
+ info("app_handler\n");
+ response.setHeader("content-type", "text/html");
+
+ response.write("<html></html>");
+}
+
+var httpServer;
+
+function init_profile() {
+ var ps = Cc["@mozilla.org/preferences-service;1"].getService(
+ Ci.nsIPrefBranch
+ );
+ dump(ps.getBoolPref("browser.cache.offline.enable"));
+ ps.setBoolPref("browser.cache.offline.enable", true);
+ ps.setBoolPref("browser.cache.offline.storage.enable", true);
+ ps.setComplexValue(
+ "browser.cache.offline.parent_directory",
+ Ci.nsIFile,
+ do_get_profile()
+ );
+ info("profile " + do_get_profile());
+}
+
+function init_http_server() {
+ httpServer = new HttpServer();
+ httpServer.registerPathHandler("/app.appcache", manifest_handler);
+ httpServer.registerPathHandler("/app", app_handler);
+ for (let i = 1; i <= 4; i++) {
+ httpServer.registerPathHandler("/pages/foo" + i, datafile_handler);
+ }
+ httpServer.start(4444);
+}
+
+function clean_app_cache() {
+ let cache_service = Cc[kNS_CACHESTORAGESERVICE_CONTRACTID].getService(
+ Ci.nsICacheStorageService
+ );
+ let storage = cache_service.appCacheStorage(
+ Services.loadContextInfo.default,
+ null
+ );
+ storage.asyncEvictStorage(null);
+}
+
+function do_app_cache(manifestURL, pageURL) {
+ let update_service = Cc[kNS_OFFLINECACHEUPDATESERVICE_CONTRACTID].getService(
+ Ci.nsIOfflineCacheUpdateService
+ );
+
+ PermissionTestUtils.add(
+ manifestURL,
+ "offline-app",
+ Ci.nsIPermissionManager.ALLOW_ACTION
+ );
+
+ let update = update_service.scheduleUpdate(
+ manifestURL,
+ pageURL,
+ Services.scriptSecurityManager.getSystemPrincipal(),
+ null
+ ); /* no window */
+
+ return update;
+}
+
+function watch_update(update, stateChangeHandler, cacheAvailHandler) {
+ let observer = {
+ QueryInterface: ChromeUtils.generateQI([]),
+
+ updateStateChanged: stateChangeHandler,
+ applicationCacheAvailable: cacheAvailHandler,
+ };
+ ~update.addObserver(observer);
+
+ return update;
+}
+
+function start_and_watch_app_cache(
+ manifestURL,
+ pageURL,
+ stateChangeHandler,
+ cacheAvailHandler
+) {
+ let ioService = Cc["@mozilla.org/network/io-service;1"].getService(
+ Ci.nsIIOService
+ );
+ let update = do_app_cache(
+ ioService.newURI(manifestURL),
+ ioService.newURI(pageURL)
+ );
+ watch_update(update, stateChangeHandler, cacheAvailHandler);
+ return update;
+}
+
+const {
+ STATE_FINISHED: STATE_FINISHED,
+ STATE_CHECKING: STATE_CHECKING,
+ STATE_ERROR: STATE_ERROR,
+} = Ci.nsIOfflineCacheUpdateObserver;
+
+/*
+ * Start caching app1 as a non-pinned app.
+ */
+function start_cache_nonpinned_app() {
+ info("Start non-pinned App1");
+ start_and_watch_app_cache(
+ kHttpLocation + "app.appcache",
+ kHttpLocation + "app",
+ function(update, state) {
+ switch (state) {
+ case STATE_FINISHED:
+ check_bug();
+ break;
+
+ case STATE_ERROR:
+ do_throw("App cache state = " + state);
+ break;
+ }
+ },
+ function(appcache) {
+ info("app avail " + appcache + "\n");
+ }
+ );
+}
+
+var hold_entry_foo1 = null;
+
+function check_bug() {
+ // activate foo1
+ asyncOpenCacheEntry(
+ kHttpLocation + "pages/foo1",
+ "appcache",
+ Ci.nsICacheStorage.OPEN_READONLY,
+ null,
+ function(status, entry, appcache) {
+ let storage = get_cache_service().appCacheStorage(
+ Services.loadContextInfo.default,
+ appcache
+ );
+
+ // Doom foo1 & foo2
+ storage.asyncDoomURI(createURI(kHttpLocation + "pages/foo1"), "", {
+ onCacheEntryDoomed() {
+ storage.asyncDoomURI(createURI(kHttpLocation + "pages/foo2"), "", {
+ onCacheEntryDoomed() {
+ check_evict_cache(appcache);
+ },
+ });
+ },
+ });
+
+ hold_entry_foo1 = entry;
+ }
+ );
+}
+
+function check_evict_cache(appcache) {
+ // Only foo2 should be removed.
+ let file = do_get_profile().clone();
+ file.append("OfflineCache");
+ file.append("5");
+ file.append("9");
+ file.append("8379C6596B8CA4-0");
+ Assert.equal(file.exists(), true);
+
+ file = do_get_profile().clone();
+ file.append("OfflineCache");
+ file.append("C");
+ file.append("2");
+ file.append("5F356A168B5E3B-0");
+ Assert.equal(file.exists(), false);
+
+ // activate foo3
+ asyncOpenCacheEntry(
+ kHttpLocation + "pages/foo3",
+ "appcache",
+ Ci.nsICacheStorage.OPEN_READONLY,
+ null,
+ function(status, entry, appcache) {
+ // evict all documents.
+ let storage = get_cache_service().appCacheStorage(
+ Services.loadContextInfo.default,
+ appcache
+ );
+ storage.asyncEvictStorage(null);
+
+ // All documents are removed except foo1 & foo3.
+ syncWithCacheIOThread(function() {
+ // foo1
+ let file = do_get_profile().clone();
+ file.append("OfflineCache");
+ file.append("5");
+ file.append("9");
+ file.append("8379C6596B8CA4-0");
+ Assert.equal(file.exists(), true);
+
+ file = do_get_profile().clone();
+ file.append("OfflineCache");
+ file.append("0");
+ file.append("0");
+ file.append("61FEE819921D39-0");
+ Assert.equal(file.exists(), false);
+
+ file = do_get_profile().clone();
+ file.append("OfflineCache");
+ file.append("3");
+ file.append("9");
+ file.append("0D8759F1DE5452-0");
+ Assert.equal(file.exists(), false);
+
+ file = do_get_profile().clone();
+ file.append("OfflineCache");
+ file.append("C");
+ file.append("2");
+ file.append("5F356A168B5E3B-0");
+ Assert.equal(file.exists(), false);
+
+ // foo3
+ file = do_get_profile().clone();
+ file.append("OfflineCache");
+ file.append("D");
+ file.append("C");
+ file.append("1ADCCC843B5C00-0");
+ Assert.equal(file.exists(), true);
+
+ file = do_get_profile().clone();
+ file.append("OfflineCache");
+ file.append("F");
+ file.append("0");
+ file.append("FC3E6D6C1164E9-0");
+ Assert.equal(file.exists(), false);
+
+ httpServer.stop(do_test_finished);
+ }, true /* force even with the new cache back end */);
+ },
+ appcache
+ );
+}
+
+function run_test() {
+ if (typeof _XPCSHELL_PROCESS == "undefined" || _XPCSHELL_PROCESS != "child") {
+ init_profile();
+ clean_app_cache();
+ }
+
+ init_http_server();
+ start_cache_nonpinned_app();
+ do_test_pending();
+}