Commit 60dcff42 authored by Martin Sramek's avatar Martin Sramek Committed by Commit Bot

Verify that various backends are deleted with the "storage" datatype

- Local Storage
- Indexed DB
- Filesystems
- Service workers
- WebSQL

Bug: 607897
Change-Id: I7fd82d08c651fb8f41dbde9c6af1b723679c621c
Reviewed-on: https://chromium-review.googlesource.com/596088Reviewed-by: default avatarMike West <mkwst@chromium.org>
Commit-Queue: Martin Šrámek <msramek@chromium.org>
Cr-Commit-Position: refs/heads/master@{#491993}
parent 996de39b
<!DOCTYPE html>
<html>
<head>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="support/test_utils.sub.js"></script>
</head>
<body>
<script>
/** @property{Datatype} The storage datatype. */
var storage = TestUtils.DATATYPES.filter(function(datatype) {
return datatype.name == "storage";
})[0];
// The tests are set up asynchronously.
setup({"explicit_done": true});
// There must be at least one test added synchronously, otherwise
// testharness will complain.
// TODO(@msramek): Find a way to avoid this dummy test.
test(function() {}, "Populate backends.");
TestUtils.populateStorage()
.then(function() {
// Navigate to a resource with a Clear-Site-Data header in
// an iframe, then verify that all backends of the "storage"
// datatype have been deleted.
return new Promise(function(resolve, reject) {
window.addEventListener("message", resolve);
var iframe = document.createElement("iframe");
iframe.src = TestUtils.getClearSiteDataUrl([storage]);
document.body.appendChild(iframe);
}).then(function() {
TestUtils.STORAGE.forEach(function(backend) {
var test_name =
"Clear backend when 'storage' is deleted: " + backend.name;
promise_test(function() {
return backend.isEmpty().then(function(isEmpty) {
assert_true(
isEmpty,
backend.name + " should have been cleared.");
});
}, test_name);
});
done();
});
});
</script>
</body>
</html>
......@@ -11,6 +11,8 @@ var TestUtils = (function() {
* @typedef Datatype
* @type{object}
* @property{string} name Name of the datatype.
* @property{function():boolean} supported
* Whether this datatype is supported by this user agent.
* @method{function():Void} add A function to add an instance of the datatype.
* @method{function():boolean} isEmpty A function that tests whether
* the datatype's storage backend is empty.
......@@ -20,39 +22,174 @@ var TestUtils = (function() {
var TestUtils = {};
/**
* All datatypes supported by Clear-Site-Data.
* Various storage backends that are part of the 'storage' datatype.
* @param{Array.<Datatype>}
*/
TestUtils.DATATYPES = [
TestUtils.STORAGE = [
{
"name": "cookies",
"name": "local storage",
"supported": function() { !!window.localStorage; },
"add": function() {
return new Promise(function(resolve, reject) {
document.cookie = randomString() + "=" + randomString();
localStorage.setItem(randomString(), randomString());
resolve();
});
},
"isEmpty": function() {
return new Promise(function(resolve, reject) {
resolve(!document.cookie);
resolve(!localStorage.length);
});
}
},
{
"name": "storage",
"name": "Indexed DB",
"supported": function() { return !!window.indexedDB; },
"add": function() {
return new Promise(function(resolve, reject) {
localStorage.setItem(randomString(), randomString());
var request = window.indexedDB.open("database");
request.onupgradeneeded = function() {
request.result.createObjectStore("store");
};
request.onsuccess = function() {
request.result.close();
resolve();
}
});
},
"isEmpty": function() {
return new Promise(function(resolve, reject) {
var request = window.indexedDB.open("database");
request.onsuccess = function() {
var database = request.result;
try {
var transaction = database.transaction(["store"]);
resolve(false);
} catch(error) {
// The database is empty. However, by testing that, we have also
// created it, which means that |onupgradeneeded| in the "add"
// method will not run the next time. Delete the database before
// reporting that it was empty.
var deletion = window.indexedDB.deleteDatabase("database");
deletion.onsuccess = resolve.bind(this, true);
} finally {
database.close();
}
};
});
}
},
{
// TODO(@msramek): We should also test the PERSISTENT filesystem, however,
// that might require storage permissions.
"name": "filesystems",
"supported": function() {
return window.requestFileSystem || window.webkitRequestFileSystem;
},
"add": function() {
return new Promise(function(resolve, reject) {
var onSuccess = function(fileSystem) {
fileSystem.root.getFile('file', {"create": true}, resolve, resolve);
}
var onFailure = resolve;
var requestFileSystem =
window.requestFileSystem || window.webkitRequestFileSystem;
requestFileSystem(window.TEMPORARY, 1 /* 1B */,
onSuccess, onFailure);
});
},
"isEmpty": function() {
return new Promise(function(resolve, reject) {
var onSuccess = function(fileSystem) {
fileSystem.root.getFile(
'file', {},
resolve.bind(this, false) /* opened successfully */,
resolve.bind(this, true) /* failed to open */);
}
var onFailure = resolve.bind(this, true);
var requestFileSystem =
window.requestFileSystem || window.webkitRequestFileSystem;
requestFileSystem(window.TEMPORARY, 1 /* 1B */,
onSuccess, onFailure);
});
}
},
{
"name": "service workers",
"supported": function() { return !!navigator.serviceWorker; },
"add": function() {
return navigator.serviceWorker.register(
"support/service_worker.js",
{ scope: "support/scope-that-does-not-contain-this-test/"});
},
"isEmpty": function() {
return new Promise(function(resolve, reject) {
navigator.serviceWorker.getRegistrations()
.then(function(registrations) {
resolve(!registrations.length);
});
});
}
},
{
"name": "WebSQL",
"supported": function() { return !!window.openDatabase; },
"add": function() {
return new Promise(function(resolve, reject) {
var database = window.openDatabase(
"database", "1.0", "database", 1024 /* 1 kB */);
database.transaction(function(context) {
context.executeSql("CREATE TABLE IF NOT EXISTS data (column)");
context.executeSql(
"INSERT INTO data (column) VALUES (1)", [], resolve);
});
});
},
"isEmpty": function() {
return new Promise(function(resolve, reject) {
var database = window.openDatabase(
"database", "1.0", "database", 1024 /* 1 kB */);
database.transaction(function(context) {
context.executeSql("CREATE TABLE IF NOT EXISTS data (column)");
context.executeSql(
"SELECT * FROM data", [],
function(transaction, result) {
resolve(!result.rows.length);
});
});
});
}
}
].filter(function(backend) { return backend.supported(); });
/**
* All datatypes supported by Clear-Site-Data.
* @param{Array.<Datatype>}
*/
TestUtils.DATATYPES = [
{
"name": "cookies",
"supported": function() { return typeof document.cookie == "string"; },
"add": function() {
return new Promise(function(resolve, reject) {
document.cookie = randomString() + "=" + randomString();
resolve();
});
},
"isEmpty": function() {
return new Promise(function(resolve, reject) {
resolve(!localStorage.length);
resolve(!document.cookie);
});
}
},
{
"name": "storage",
"supported": TestUtils.STORAGE[0].supported,
"add": TestUtils.STORAGE[0].add,
"isEmpty": TestUtils.STORAGE[0].isEmpty,
}
];
].filter(function(datatype) { return datatype.supported(); });
/**
* All possible combinations of datatypes.
......@@ -75,11 +212,13 @@ var TestUtils = (function() {
})();
/**
* Ensures that all datatypes are nonempty. Should be called in the test
* setup phase.
* Populates |datatypes| by calling the "add" method on each of them,
* and verifies that they are nonempty.
* @param {Array.<Datatype>} datatypes to be populated.
* @private
*/
TestUtils.populateDatatypes = function() {
return Promise.all(TestUtils.DATATYPES.map(function(datatype) {
function populate(datatypes) {
return Promise.all(datatypes.map(function(datatype) {
return new Promise(function(resolve, reject) {
datatype.add().then(function() {
datatype.isEmpty().then(function(isEmpty) {
......@@ -94,6 +233,18 @@ var TestUtils = (function() {
}));
};
/**
* Ensures that all datatypes are nonempty. Should be called in the test
* setup phase.
*/
TestUtils.populateDatatypes = populate.bind(this, TestUtils.DATATYPES);
/**
* Ensures that all backends of the "storage" datatype are nonempty. Should
* be called in the test setup phase.
*/
TestUtils.populateStorage = populate.bind(this, TestUtils.STORAGE);
/**
* Get the support server URL that returns a Clear-Site-Data header
* to clear |datatypes|.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment