summaryrefslogtreecommitdiffstats
path: root/devtools/shared/platform/CacheEntry.sys.mjs
blob: 761f0d294620945853209c5dbed477315c34920a (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
/* 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/. */

const lazy = {};

ChromeUtils.defineESModuleGetters(lazy, {
  NetworkHelper:
    "resource://devtools/shared/network-observer/NetworkHelper.sys.mjs",
});

/**
 * Global cache session object.
 */
let gCacheSession = null;

/**
 * Get (and create if necessary) a cache session / cache storage session.
 *
 * @param {nsIRequest} request
 */
function getCacheSession(request) {
  if (!gCacheSession) {
    try {
      const cacheService = Services.cache2;
      if (cacheService) {
        let loadContext = lazy.NetworkHelper.getRequestLoadContext(request);
        if (!loadContext) {
          // Get default load context if we can't fetch.
          loadContext = Services.loadContextInfo.default;
        }
        gCacheSession = cacheService.diskCacheStorage(loadContext);
      }
    } catch (e) {
      gCacheSession = null;
    }
  }

  return gCacheSession;
}

/**
 * Parses a cache entry returned from the backend to build a response cache
 * object.
 *
 * @param {nsICacheEntry} cacheEntry
 *     The cache entry from the backend.
 *
 * @returns {Object}
 *     A responseCache object expected by RDP.
 */
function buildResponseCacheObject(cacheEntry) {
  const cacheObject = {};
  try {
    if (cacheEntry.storageDataSize) {
      cacheObject.storageDataSize = cacheEntry.storageDataSize;
    }
  } catch (e) {
    // We just need to handle this in case it's a js file of 0B.
  }
  if (cacheEntry.expirationTime) {
    cacheObject.expirationTime = cacheEntry.expirationTime;
  }
  if (cacheEntry.fetchCount) {
    cacheObject.fetchCount = cacheEntry.fetchCount;
  }
  if (cacheEntry.lastFetched) {
    cacheObject.lastFetched = cacheEntry.lastFetched;
  }
  if (cacheEntry.lastModified) {
    cacheObject.lastModified = cacheEntry.lastModified;
  }
  if (cacheEntry.deviceID) {
    cacheObject.deviceID = cacheEntry.deviceID;
  }
  return cacheObject;
}

/**
 * Does the fetch for the cache entry from the session.
 *
 * @param {nsIRequest} request
 *     The request object.
 *
 * @returns {Promise}
 *     Promise which resolve a response cache object object, or null if none
 *     was available.
 */
export function getResponseCacheObject(request) {
  const cacheSession = getCacheSession(request);
  if (!cacheSession) {
    return null;
  }

  return new Promise(resolve => {
    cacheSession.asyncOpenURI(
      request.URI,
      "",
      Ci.nsICacheStorage.OPEN_SECRETLY,
      {
        onCacheEntryCheck: entry => {
          return Ci.nsICacheEntryOpenCallback.ENTRY_WANTED;
        },
        onCacheEntryAvailable: (cacheEntry, isnew, status) => {
          if (cacheEntry) {
            const cacheObject = buildResponseCacheObject(cacheEntry);
            resolve(cacheObject);
          } else {
            resolve(null);
          }
        },
      }
    );
  });
}