netwerk/test/unit/test_pinned_app_cache.js

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/netwerk/test/unit/test_pinned_app_cache.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,276 @@
     1.4 +/* -*- Mode: Javasript; indent-tab-mode: nil; js-indent-level: 2 -*- */
     1.5 +/*
     1.6 + * This testcase performs 3 requests against the offline cache.  They
     1.7 + * are
     1.8 + *
     1.9 + *  - start_cache_nonpinned_app1()
    1.10 + *
    1.11 + *    - Request nsOfflineCacheService to skip pages (4) of app1 on
    1.12 + *      the cache storage.
    1.13 + *
    1.14 + *    - The offline cache storage is empty at this monent.
    1.15 + *
    1.16 + *  - start_cache_nonpinned_app2_for_partial()
    1.17 + *
    1.18 + *     - Request nsOfflineCacheService to skip pages of app2 on the
    1.19 + *       cache storage.
    1.20 + *
    1.21 + *     - The offline cache storage has only enough space for one more
    1.22 + *       additional page.  Only first of pages is really in the cache.
    1.23 + *
    1.24 + *  - start_cache_pinned_app2_for_success()
    1.25 + *
    1.26 + *     - Request nsOfflineCacheService to skip pages of app2 on the
    1.27 + *       cache storage.
    1.28 + *
    1.29 + *     - The offline cache storage has only enough space for one
    1.30 + *       additional page.  But, this is a pinned request,
    1.31 + *       nsOfflineCacheService will make more space for this request
    1.32 + *       by discarding app1 (non-pinned)
    1.33 + *
    1.34 + */
    1.35 +
    1.36 +Cu.import("resource://testing-common/httpd.js");
    1.37 +
    1.38 +// const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
    1.39 +
    1.40 +Cu.import("resource://gre/modules/Services.jsm");
    1.41 +
    1.42 +const kNS_OFFLINECACHEUPDATESERVICE_CONTRACTID =
    1.43 +  "@mozilla.org/offlinecacheupdate-service;1";
    1.44 +
    1.45 +const kManifest1 = "CACHE MANIFEST\n" +
    1.46 +  "/pages/foo1\n" +
    1.47 +  "/pages/foo2\n" +
    1.48 +  "/pages/foo3\n" +
    1.49 +  "/pages/foo4\n";
    1.50 +const kManifest2 = "CACHE MANIFEST\n" +
    1.51 +  "/pages/foo5\n" +
    1.52 +  "/pages/foo6\n" +
    1.53 +  "/pages/foo7\n" +
    1.54 +  "/pages/foo8\n";
    1.55 +
    1.56 +const kDataFileSize = 1024;	// file size for each content page
    1.57 +const kCacheSize = kDataFileSize * 5; // total space for offline cache storage
    1.58 +
    1.59 +XPCOMUtils.defineLazyGetter(this, "kHttpLocation", function() {
    1.60 +  return "http://localhost:" + httpServer.identity.primaryPort + "/";
    1.61 +});
    1.62 +
    1.63 +XPCOMUtils.defineLazyGetter(this, "kHttpLocation_ip", function() {
    1.64 +  return "http://127.0.0.1:" + httpServer.identity.primaryPort + "/";
    1.65 +});
    1.66 +
    1.67 +function manifest1_handler(metadata, response) {
    1.68 +  do_print("manifest1\n");
    1.69 +  response.setHeader("content-type", "text/cache-manifest");
    1.70 +
    1.71 +  response.write(kManifest1);
    1.72 +}
    1.73 +
    1.74 +function manifest2_handler(metadata, response) {
    1.75 +  do_print("manifest2\n");
    1.76 +  response.setHeader("content-type", "text/cache-manifest");
    1.77 +
    1.78 +  response.write(kManifest2);
    1.79 +}
    1.80 +
    1.81 +function app_handler(metadata, response) {
    1.82 +  do_print("app_handler\n");
    1.83 +  response.setHeader("content-type", "text/html");
    1.84 +
    1.85 +  response.write("<html></html>");
    1.86 +}
    1.87 +
    1.88 +function datafile_handler(metadata, response) {
    1.89 +  do_print("datafile_handler\n");
    1.90 +  let data = "";
    1.91 +
    1.92 +  while(data.length < kDataFileSize) {
    1.93 +    data = data + Math.random().toString(36).substring(2, 15);
    1.94 +  }
    1.95 +
    1.96 +  response.setHeader("content-type", "text/plain");
    1.97 +  response.write(data.substring(0, kDataFileSize));
    1.98 +}
    1.99 +
   1.100 +var httpServer;
   1.101 +
   1.102 +function init_profile() {
   1.103 +  var ps = Cc["@mozilla.org/preferences-service;1"]
   1.104 +    .getService(Ci.nsIPrefBranch);
   1.105 +  dump(ps.getBoolPref("browser.cache.offline.enable"));
   1.106 +  ps.setBoolPref("browser.cache.offline.enable", true);
   1.107 +  ps.setComplexValue("browser.cache.offline.parent_directory",
   1.108 +		     Ci.nsILocalFile, do_get_profile());
   1.109 +}
   1.110 +
   1.111 +function init_http_server() {
   1.112 +  httpServer = new HttpServer();
   1.113 +  httpServer.registerPathHandler("/app1", app_handler);
   1.114 +  httpServer.registerPathHandler("/app2", app_handler);
   1.115 +  httpServer.registerPathHandler("/app1.appcache", manifest1_handler);
   1.116 +  httpServer.registerPathHandler("/app2.appcache", manifest2_handler);
   1.117 +  for (i = 1; i <= 8; i++) {
   1.118 +    httpServer.registerPathHandler("/pages/foo" + i, datafile_handler);
   1.119 +  }
   1.120 +  httpServer.start(-1);
   1.121 +}
   1.122 +
   1.123 +function init_cache_capacity() {
   1.124 +  let prefs = Cc["@mozilla.org/preferences-service;1"]
   1.125 +    .getService(Components.interfaces.nsIPrefBranch);
   1.126 +  prefs.setIntPref("browser.cache.offline.capacity", kCacheSize / 1024);
   1.127 +}
   1.128 +
   1.129 +function clean_app_cache() {
   1.130 +  evict_cache_entries("appcache");
   1.131 +}
   1.132 +
   1.133 +function do_app_cache(manifestURL, pageURL, pinned) {
   1.134 +  let update_service = Cc[kNS_OFFLINECACHEUPDATESERVICE_CONTRACTID].
   1.135 +    getService(Ci.nsIOfflineCacheUpdateService);
   1.136 +
   1.137 +  Services.perms.add(manifestURL,
   1.138 +		     "pin-app",
   1.139 +                     pinned ?
   1.140 +                     Ci.nsIPermissionManager.ALLOW_ACTION :
   1.141 +                     Ci.nsIPermissionManager.DENY_ACTION);
   1.142 +
   1.143 +  let update =
   1.144 +    update_service.scheduleUpdate(manifestURL,
   1.145 +                                  pageURL,
   1.146 +                                  null); /* no window */
   1.147 +
   1.148 +  return update;
   1.149 +}
   1.150 +
   1.151 +function watch_update(update, stateChangeHandler, cacheAvailHandler) {
   1.152 +  let observer = {
   1.153 +    QueryInterface: function QueryInterface(iftype) {
   1.154 +      return this;
   1.155 +    },
   1.156 +
   1.157 +    updateStateChanged: stateChangeHandler,
   1.158 +    applicationCacheAvailable: cacheAvailHandler
   1.159 +  };
   1.160 +  update.addObserver(observer, false);
   1.161 +
   1.162 +  return update;
   1.163 +}
   1.164 +
   1.165 +function start_and_watch_app_cache(manifestURL,
   1.166 +                                 pageURL,
   1.167 +                                 pinned,
   1.168 +                                 stateChangeHandler,
   1.169 +                                 cacheAvailHandler) {
   1.170 +  let ioService = Cc["@mozilla.org/network/io-service;1"].
   1.171 +    getService(Ci.nsIIOService);
   1.172 +  let update = do_app_cache(ioService.newURI(manifestURL, null, null),
   1.173 +                            ioService.newURI(pageURL, null, null),
   1.174 +                            pinned);
   1.175 +  watch_update(update, stateChangeHandler, cacheAvailHandler);
   1.176 +  return update;
   1.177 +}
   1.178 +
   1.179 +const {STATE_FINISHED: STATE_FINISHED,
   1.180 +       STATE_CHECKING: STATE_CHECKING,
   1.181 +       STATE_ERROR: STATE_ERROR } = Ci.nsIOfflineCacheUpdateObserver;
   1.182 +
   1.183 +/*
   1.184 + * Start caching app1 as a non-pinned app.
   1.185 + */
   1.186 +function start_cache_nonpinned_app() {
   1.187 +  do_print("Start non-pinned App1");
   1.188 +  start_and_watch_app_cache(kHttpLocation + "app1.appcache",
   1.189 +                          kHttpLocation + "app1",
   1.190 +                          false,
   1.191 +                          function (update, state) {
   1.192 +                            switch(state) {
   1.193 +                            case STATE_FINISHED:
   1.194 +                              start_cache_nonpinned_app2_for_partial();
   1.195 +                              break;
   1.196 +
   1.197 +                            case STATE_ERROR:
   1.198 +                              do_throw("App1 cache state = " + state);
   1.199 +                              break;
   1.200 +                            }
   1.201 +                          },
   1.202 +                          function (appcahe) {
   1.203 +                            do_print("app1 avail " + appcache + "\n");
   1.204 +                          });
   1.205 +}
   1.206 +
   1.207 +/*
   1.208 + * Start caching app2 as a non-pinned app.
   1.209 + *
   1.210 + * This cache request is supposed to be saved partially in the cache
   1.211 + * storage for running out of the cache storage.  The offline cache
   1.212 + * storage can hold 5 files at most.  (kDataFileSize bytes for each
   1.213 + * file)
   1.214 + */
   1.215 +function start_cache_nonpinned_app2_for_partial() {
   1.216 +  let error_count = [0];
   1.217 +  do_print("Start non-pinned App2 for partial\n");
   1.218 +  start_and_watch_app_cache(kHttpLocation_ip + "app2.appcache",
   1.219 +                            kHttpLocation_ip + "app2",
   1.220 +                            false,
   1.221 +                            function (update, state) {
   1.222 +                              switch(state) {
   1.223 +                              case STATE_FINISHED:
   1.224 +				start_cache_pinned_app2_for_success();
   1.225 +				break;
   1.226 +
   1.227 +                              case STATE_ERROR:
   1.228 +				do_throw("App2 cache state = " + state);
   1.229 +				break;
   1.230 +                              }
   1.231 +                            },
   1.232 +                            function (appcahe) {
   1.233 +                            });
   1.234 +}
   1.235 +
   1.236 +/*
   1.237 + * Start caching app2 as a pinned app.
   1.238 + *
   1.239 + * This request use IP address (127.0.0.1) as the host name instead of
   1.240 + * the one used by app1.  Because, app1 is also pinned when app2 is
   1.241 + * pinned if they have the same host name (localhost).
   1.242 + */
   1.243 +function start_cache_pinned_app2_for_success() {
   1.244 +  let error_count = [0];
   1.245 +  do_print("Start pinned App2 for success\n");
   1.246 +  start_and_watch_app_cache(kHttpLocation_ip + "app2.appcache",
   1.247 +                            kHttpLocation_ip + "app2",
   1.248 +                            true,
   1.249 +                            function (update, state) {
   1.250 +                              switch(state) {
   1.251 +                              case STATE_FINISHED:
   1.252 +				do_check_true(error_count[0] == 0,
   1.253 +                                              "Do not discard app1?");
   1.254 +				httpServer.stop(do_test_finished);
   1.255 +				break;
   1.256 +
   1.257 +                              case STATE_ERROR:
   1.258 +				do_print("STATE_ERROR\n");
   1.259 +				error_count[0]++;
   1.260 +				break;
   1.261 +                              }
   1.262 +                            },
   1.263 +                            function (appcahe) {
   1.264 +                              do_print("app2 avail " + appcache + "\n");
   1.265 +                            });
   1.266 +}
   1.267 +
   1.268 +function run_test() {
   1.269 +  if (typeof _XPCSHELL_PROCESS == "undefined" ||
   1.270 +      _XPCSHELL_PROCESS != "child") {
   1.271 +    init_profile();
   1.272 +    init_cache_capacity();
   1.273 +    clean_app_cache();
   1.274 +  }
   1.275 +
   1.276 +  init_http_server();
   1.277 +  start_cache_nonpinned_app();
   1.278 +  do_test_pending();
   1.279 +}

mercurial