summaryrefslogtreecommitdiffstats
path: root/netwerk/test/unit/test_offlinecache_custom-directory.js
blob: 44e7957dc7ec84729dd92271d0859563511b115b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

/**
 * This test executes nsIOfflineCacheUpdateService.scheduleAppUpdate API
 * 1. preloads an app with a manifest to a custom sudir in the profile (for simplicity)
 * 2. observes progress and completion of the update
 * 3. checks presence of index.sql and files in the expected location
 */

Cu.import("resource://testing-common/httpd.js");
Cu.import('resource://gre/modules/Services.jsm');
Cu.import("resource://gre/modules/NetUtil.jsm");


var httpServer = null;
var cacheUpdateObserver = null;
var systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal();

function make_channel(url, callback, ctx) {
  return NetUtil.newChannel({
    uri: url,
    loadUsingSystemPrincipal: true
  });
}

function make_uri(url) {
  var ios = Cc["@mozilla.org/network/io-service;1"].
            getService(Ci.nsIIOService);
  return ios.newURI(url, null, null);
}

// start the test with loading this master entry referencing the manifest
function masterEntryHandler(metadata, response)
{
  var masterEntryContent = "<html manifest='/manifest'></html>";
  response.setHeader("Content-Type", "text/html");
  response.bodyOutputStream.write(masterEntryContent, masterEntryContent.length);
}

// manifest defines fallback namespace from any /redirect path to /content
function manifestHandler(metadata, response)
{
  var manifestContent = "CACHE MANIFEST\n";
  response.setHeader("Content-Type", "text/cache-manifest");
  response.bodyOutputStream.write(manifestContent, manifestContent.length);
}

// finally check we got fallback content
function finish_test(customDir)
{
  var offlineCacheDir = customDir.clone();
  offlineCacheDir.append("OfflineCache");

  var indexSqlFile = offlineCacheDir.clone();
  indexSqlFile.append('index.sqlite');
  do_check_eq(indexSqlFile.exists(), true);

  var file1 = offlineCacheDir.clone();
  file1.append("2");
  file1.append("E");
  file1.append("2C99DE6E7289A5-0");
  do_check_eq(file1.exists(), true);

  var file2 = offlineCacheDir.clone();
  file2.append("8");
  file2.append("6");
  file2.append("0B457F75198B29-0");
  do_check_eq(file2.exists(), true);

  // This must not throw an exception.  After the update has finished
  // the index file can be freely removed.  This way we check this process
  // is no longer keeping the file open.  Check like this will probably
  // work only Windows systems.

  // This test could potentially randomaly fail when we start closing
  // the offline cache database off the main thread.  Tries in a loop
  // may be a solution then.
  try {
    indexSqlFile.remove(false);
    do_check_true(true);
  }
  catch (ex) {
    do_throw("Could not remove the sqlite.index file, we still keep it open \n" + ex + "\n");
  }

  httpServer.stop(do_test_finished);
}

function run_test()
{
  httpServer = new HttpServer();
  httpServer.registerPathHandler("/masterEntry", masterEntryHandler);
  httpServer.registerPathHandler("/manifest", manifestHandler);
  httpServer.start(4444);

  var profileDir = do_get_profile();
  var customDir = profileDir.clone();
  customDir.append("customOfflineCacheDir" + Math.random());

  var pm = Cc["@mozilla.org/permissionmanager;1"]
    .getService(Ci.nsIPermissionManager);
  var ssm = Cc["@mozilla.org/scriptsecuritymanager;1"]
              .getService(Ci.nsIScriptSecurityManager);
  var uri = make_uri("http://localhost:4444");
  var principal = ssm.createCodebasePrincipal(uri, {});

  if (pm.testPermissionFromPrincipal(principal, "offline-app") != 0) {
    dump("Previous test failed to clear offline-app permission!  Expect failures.\n");
  }
  pm.addFromPrincipal(principal, "offline-app", Ci.nsIPermissionManager.ALLOW_ACTION);

  var ps = Cc["@mozilla.org/preferences-service;1"]
    .getService(Ci.nsIPrefBranch);
  ps.setBoolPref("browser.cache.offline.enable", true);
  // Set this pref to mimic the default browser behavior.
  ps.setComplexValue("browser.cache.offline.parent_directory", Ci.nsILocalFile, profileDir);

  var us = Cc["@mozilla.org/offlinecacheupdate-service;1"].
           getService(Ci.nsIOfflineCacheUpdateService);
  var update = us.scheduleAppUpdate(
      make_uri("http://localhost:4444/manifest"),
      make_uri("http://localhost:4444/masterEntry"),
      systemPrincipal,
      customDir);

  var expectedStates = [
      Ci.nsIOfflineCacheUpdateObserver.STATE_DOWNLOADING,
      Ci.nsIOfflineCacheUpdateObserver.STATE_ITEMSTARTED,
      Ci.nsIOfflineCacheUpdateObserver.STATE_ITEMPROGRESS,
      Ci.nsIOfflineCacheUpdateObserver.STATE_ITEMCOMPLETED,
      Ci.nsIOfflineCacheUpdateObserver.STATE_FINISHED
  ];

  update.addObserver({
    updateStateChanged: function(update, state)
    {
      do_check_eq(state, expectedStates.shift());

      if (state == Ci.nsIOfflineCacheUpdateObserver.STATE_FINISHED)
          finish_test(customDir);
    },

    applicationCacheAvailable: function(appCache)
    {
    }
  }, false);

  do_test_pending();
}