Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

# 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/.
import os
import sys
from pathlib import Path
sys.path.append(os.fspath(Path(__file__).parents[3] / "quota/test/marionette"))
from quota_test_case import QuotaTestCase
QM_ENCRYPTION_PREF = "dom.quotaManager.encryption.enabled"
QM_TESTING_PREF = "dom.quotaManager.testing"
class CacheAPIEncryptionPersistence(QuotaTestCase):
"""
Verify that encrypted Cache API data persists across a browser restart.
The lockstore keystore lives in the profile, so the same DEKs should be
available after restart and cached responses should be readable.
"""
def setUp(self):
super().setUp()
# QuotaManager reads encryption.enabled once at startup, so write it to
# the profile and restart before touching storage.
self.marionette.instance.profile.set_preferences({
QM_ENCRYPTION_PREF: True,
QM_TESTING_PREF: True,
})
self.marionette.restart(in_app=False)
self.cacheName = "PersistCache"
self.cacheRequestURL = "https://example.com/persist-test"
self.cacheResponseBody = "persist_cache_value_lockstore"
def test_cache_survives_restart(self):
url = self.marionette.absolute_url("empty.html")
self.marionette.navigate(url)
self.marionette.execute_async_script(
"""
const [cacheName, requestURL, responseBody, resolve] = arguments;
caches.open(cacheName).then(cache => {
const request = new Request(requestURL);
const response = new Response(responseBody);
return cache.put(request, response);
}).then(() => resolve("written"))
.catch(e => resolve("write_error: " + e));
""",
script_args=(
self.cacheName,
self.cacheRequestURL,
self.cacheResponseBody,
),
)
self.assertEqual(
self.readBack(),
self.cacheResponseBody,
"Pre-restart cache read-back failed",
)
self.marionette.restart(in_app=True)
self.marionette.navigate(url)
self.assertEqual(
self.readBack(),
self.cacheResponseBody,
"Encrypted cache data did not survive browser restart",
)
# Origins encrypted earlier must stay readable after the pref is
# turned off.
self.marionette.instance.profile.set_preferences({QM_ENCRYPTION_PREF: False})
self.marionette.restart(in_app=False)
self.marionette.navigate(url)
self.assertEqual(
self.readBack(),
self.cacheResponseBody,
"Encrypted cache data unreadable after disabling encryption",
)
def readBack(self):
return self.marionette.execute_async_script(
"""
const [cacheName, requestURL, resolve] = arguments;
caches.open(cacheName).then(cache => {
return cache.match(requestURL);
}).then(response => {
if (!response) { resolve(null); return; }
return response.text();
}).then(text => resolve(text))
.catch(e => resolve(null));
""",
script_args=(self.cacheName, self.cacheRequestURL),
)