зеркало из https://github.com/mozilla/gecko-dev.git
Bug 871445 - patch 4 - DatAStore: permissions, owned/access, r=mounir, r=ehsan
--HG-- rename : dom/datastore/tests/file_app.template.webapp => dom/datastore/tests/file_app2.template.webapp rename : dom/datastore/tests/test_revision.html => dom/datastore/tests/file_revision.html
This commit is contained in:
Родитель
fc124929c3
Коммит
343c0f10b9
|
@ -541,16 +541,26 @@ this.DOMApplicationRegistry = {
|
|||
},
|
||||
|
||||
updateDataStore: function(aId, aManifestURL, aManifest) {
|
||||
if (!("datastores" in aManifest)) {
|
||||
return;
|
||||
if ('datastores-owned' in aManifest) {
|
||||
for (let name in aManifest['datastores-owned']) {
|
||||
let readonly = "access" in aManifest['datastores-owned'][name]
|
||||
? aManifest['datastores-owned'][name].access == 'readonly'
|
||||
: false;
|
||||
|
||||
dataStoreService.installDataStore(aId, name, aManifestURL, readonly);
|
||||
}
|
||||
}
|
||||
|
||||
for (let name in aManifest.datastores) {
|
||||
let readonly = ("readonly" in aManifest.datastores[name]) &&
|
||||
!aManifest.datastores[name].readonly
|
||||
? false : true;
|
||||
if ('datastores-access' in aManifest) {
|
||||
for (let name in aManifest['datastores-access']) {
|
||||
let readonly = ("readonly" in aManifest['datastores-access'][name]) &&
|
||||
!aManifest['datastores-access'][name].readonly
|
||||
? false : true;
|
||||
|
||||
dataStoreService.installDataStore(aId, name, aManifestURL, readonly);
|
||||
// The first release is always in readonly mode.
|
||||
dataStoreService.installAccessDataStore(aId, name, aManifestURL,
|
||||
/* readonly */ true);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
'use strict'
|
||||
|
||||
var EXPORTED_SYMBOLS = ["DataStore"];
|
||||
var EXPORTED_SYMBOLS = ["DataStore", "DataStoreAccess"];
|
||||
|
||||
function debug(s) {
|
||||
// dump('DEBUG DataStore: ' + s + '\n');
|
||||
|
@ -204,7 +204,7 @@ DataStore.prototype = {
|
|||
new aWindow.DOMError("ReadOnlyError", "DataStore in readonly mode"));
|
||||
},
|
||||
|
||||
exposeObject: function(aWindow) {
|
||||
exposeObject: function(aWindow, aReadOnly) {
|
||||
let self = this;
|
||||
let object = {
|
||||
|
||||
|
@ -219,7 +219,7 @@ DataStore.prototype = {
|
|||
},
|
||||
|
||||
get readOnly() {
|
||||
return self.readOnly;
|
||||
return aReadOnly;
|
||||
},
|
||||
|
||||
get: function DS_get(aId) {
|
||||
|
@ -242,7 +242,7 @@ DataStore.prototype = {
|
|||
return self.throwInvalidArg(aWindow);
|
||||
}
|
||||
|
||||
if (self.readOnly) {
|
||||
if (aReadOnly) {
|
||||
return self.throwReadOnly(aWindow);
|
||||
}
|
||||
|
||||
|
@ -255,7 +255,7 @@ DataStore.prototype = {
|
|||
},
|
||||
|
||||
add: function DS_add(aObj) {
|
||||
if (self.readOnly) {
|
||||
if (aReadOnly) {
|
||||
return self.throwReadOnly(aWindow);
|
||||
}
|
||||
|
||||
|
@ -273,7 +273,7 @@ DataStore.prototype = {
|
|||
return self.throwInvalidArg(aWindow);
|
||||
}
|
||||
|
||||
if (self.readOnly) {
|
||||
if (aReadOnly) {
|
||||
return self.throwReadOnly(aWindow);
|
||||
}
|
||||
|
||||
|
@ -286,7 +286,7 @@ DataStore.prototype = {
|
|||
},
|
||||
|
||||
clear: function DS_clear() {
|
||||
if (self.readOnly) {
|
||||
if (aReadOnly) {
|
||||
return self.throwReadOnly(aWindow);
|
||||
}
|
||||
|
||||
|
@ -424,3 +424,15 @@ DataStore.prototype = {
|
|||
this.db.delete();
|
||||
}
|
||||
};
|
||||
|
||||
/* DataStoreAccess */
|
||||
|
||||
function DataStoreAccess(aAppId, aName, aOrigin, aReadOnly) {
|
||||
this.appId = aAppId;
|
||||
this.name = aName;
|
||||
this.origin = aOrigin;
|
||||
this.readOnly = aReadOnly;
|
||||
}
|
||||
|
||||
DataStoreAccess.prototype = {};
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@ function DataStoreService() {
|
|||
DataStoreService.prototype = {
|
||||
// Hash of DataStores
|
||||
stores: {},
|
||||
accessStores: {},
|
||||
|
||||
installDataStore: function(aAppId, aName, aOwner, aReadOnly) {
|
||||
debug('installDataStore - appId: ' + aAppId + ', aName: ' +
|
||||
|
@ -67,15 +68,52 @@ DataStoreService.prototype = {
|
|||
this.stores[aName][aAppId] = store;
|
||||
},
|
||||
|
||||
installAccessDataStore: function(aAppId, aName, aOwner, aReadOnly) {
|
||||
debug('installDataStore - appId: ' + aAppId + ', aName: ' +
|
||||
aName + ', aOwner:' + aOwner + ', aReadOnly: ' +
|
||||
aReadOnly);
|
||||
|
||||
if (aName in this.accessStores && aAppId in this.accessStores[aName]) {
|
||||
debug('This should not happen');
|
||||
return;
|
||||
}
|
||||
|
||||
let accessStore = new DataStoreAccess(aAppId, aName, aOwner, aReadOnly);
|
||||
|
||||
if (!(aName in this.accessStores)) {
|
||||
this.accessStores[aName] = {};
|
||||
}
|
||||
|
||||
this.accessStores[aName][aAppId] = accessStore;
|
||||
},
|
||||
|
||||
getDataStores: function(aWindow, aName) {
|
||||
debug('getDataStores - aName: ' + aName);
|
||||
let appId = aWindow.document.nodePrincipal.appId;
|
||||
|
||||
let self = this;
|
||||
return new aWindow.Promise(function(resolver) {
|
||||
let matchingStores = [];
|
||||
|
||||
if (aName in self.stores) {
|
||||
for (let appId in self.stores[aName]) {
|
||||
matchingStores.push(self.stores[aName][appId]);
|
||||
if (appId in self.stores[aName]) {
|
||||
matchingStores.push({ store: self.stores[aName][appId],
|
||||
readonly: false });
|
||||
}
|
||||
|
||||
for (var i in self.stores[aName]) {
|
||||
if (i == appId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let access = self.getDataStoreAccess(self.stores[aName][i], appId);
|
||||
if (!access) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let readOnly = self.stores[aName][i].readOnly || access.readOnly;
|
||||
matchingStores.push({ store: self.stores[aName][i],
|
||||
readonly: readOnly });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -88,10 +126,11 @@ DataStoreService.prototype = {
|
|||
}
|
||||
|
||||
for (let i = 0; i < matchingStores.length; ++i) {
|
||||
let obj = matchingStores[i].exposeObject(aWindow);
|
||||
let obj = matchingStores[i].store.exposeObject(aWindow,
|
||||
matchingStores[i].readonly);
|
||||
results.push(obj);
|
||||
|
||||
matchingStores[i].retrieveRevisionId(
|
||||
matchingStores[i].store.retrieveRevisionId(
|
||||
function() {
|
||||
--callbackPending;
|
||||
if (!callbackPending) {
|
||||
|
@ -106,6 +145,15 @@ DataStoreService.prototype = {
|
|||
});
|
||||
},
|
||||
|
||||
getDataStoreAccess: function(aStore, aAppId) {
|
||||
if (!(aStore.name in this.accessStores) ||
|
||||
!(aAppId in this.accessStores[aStore.name])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.accessStores[aStore.name][aAppId];
|
||||
},
|
||||
|
||||
observe: function observe(aSubject, aTopic, aData) {
|
||||
debug('getDataStores - aTopic: ' + aTopic);
|
||||
if (aTopic != 'webapps-clear-data') {
|
||||
|
|
|
@ -15,6 +15,11 @@ interface nsIDataStoreService : nsISupports
|
|||
in DOMString manifestURL,
|
||||
in boolean readOnly);
|
||||
|
||||
void installAccessDataStore(in unsigned long appId,
|
||||
in DOMString name,
|
||||
in DOMString manifestURL,
|
||||
in boolean readOnly);
|
||||
|
||||
nsISupports getDataStores(in nsIDOMWindow window,
|
||||
in DOMString name);
|
||||
};
|
||||
|
|
|
@ -13,11 +13,17 @@ include $(DEPTH)/config/autoconf.mk
|
|||
|
||||
MOCHITEST_FILES = \
|
||||
test_app_install.html \
|
||||
file_app_install.html \
|
||||
test_readonly.html \
|
||||
file_readonly.html \
|
||||
test_basic.html \
|
||||
file_basic.html \
|
||||
test_revision.html \
|
||||
file_revision.html \
|
||||
file_app.sjs \
|
||||
file_app.template.webapp \
|
||||
file_app2.template.webapp \
|
||||
file_app2.template.webapp^headers^ \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -2,9 +2,16 @@ var gBasePath = "tests/dom/datastore/tests/";
|
|||
var gAppTemplatePath = "tests/dom/datastore/tests/file_app.template.webapp";
|
||||
|
||||
function handleRequest(request, response) {
|
||||
var query = getQuery(request);
|
||||
|
||||
var testToken = '';
|
||||
if ('testToken' in query) {
|
||||
testToken = query.testToken;
|
||||
}
|
||||
|
||||
var template = gBasePath + 'file_app.template.webapp';
|
||||
response.setHeader("Content-Type", "application/x-web-app-manifest+json", false);
|
||||
response.write(readTemplate(template));
|
||||
response.write(readTemplate(template).replace(/TESTTOKEN/g, testToken));
|
||||
}
|
||||
|
||||
// Copy-pasted incantations. There ought to be a better way to synchronously read
|
||||
|
@ -35,3 +42,12 @@ function readTemplate(path) {
|
|||
cis.close();
|
||||
return data;
|
||||
}
|
||||
|
||||
function getQuery(request) {
|
||||
var query = {};
|
||||
request.queryString.split('&').forEach(function (val) {
|
||||
var [name, value] = val.split('=');
|
||||
query[name] = unescape(value);
|
||||
});
|
||||
return query;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
{
|
||||
"name": "Really Rapid Release (hosted)",
|
||||
"description": "Updated even faster than <a href='http://mozilla.org'>Firefox</a>, just to annoy slashdotters.",
|
||||
"launch_path": "/tests/dom/datastore/tests/file_app.sjs",
|
||||
"launch_path": "/tests/dom/datastore/tests/TESTTOKEN",
|
||||
"icons": { "128": "default_icon" },
|
||||
"datastores" : {
|
||||
"datastores-owned" : {
|
||||
"foo" : { "access": "readwrite", "description" : "This store is called foo" },
|
||||
"bar" : { "access": "readonly", "description" : "This store is called bar" }
|
||||
},
|
||||
"datastores-access" : {
|
||||
"foo" : { "readonly": false, "description" : "This store is called foo" },
|
||||
"bar" : { "readonly": true, "description" : "This store is called bar" }
|
||||
}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"name": "Really Rapid Release (hosted) - app 2",
|
||||
"description": "Updated even faster than <a href='http://mozilla.org'>Firefox</a>, just to annoy slashdotters.",
|
||||
"launch_path": "/tests/dom/datastore/tests/file_readonly.html",
|
||||
"icons": { "128": "default_icon" },
|
||||
"datastores-access" : {
|
||||
"foo" : { "readonly": false, "description" : "This store is called foo" },
|
||||
"bar" : { "readonly": true, "description" : "This store is called bar" }
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
Content-Type: application/x-web-app-manifest+json
|
|
@ -0,0 +1,40 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for DataStore - install/uninstall apps</title>
|
||||
<body>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
function is(a, b, msg) {
|
||||
alert((a === b ? 'OK' : 'KO') + ' ' + msg)
|
||||
}
|
||||
|
||||
function ok(a, msg) {
|
||||
alert((a ? 'OK' : 'KO')+ ' ' + msg)
|
||||
}
|
||||
|
||||
function cbError() {
|
||||
alert('KO error');
|
||||
}
|
||||
|
||||
function finish() {
|
||||
alert('DONE');
|
||||
}
|
||||
|
||||
navigator.getDataStores('foo').then(function(stores) {
|
||||
is(stores.length, 1, "getDataStores('foo') returns 1 element");
|
||||
is(stores[0].name, 'foo', 'The dataStore.name is foo');
|
||||
ok(stores[0].owner, 'The dataStore.owner exists');
|
||||
is(stores[0].readOnly, false, 'The dataStore foo is not in readonly');
|
||||
|
||||
navigator.getDataStores('bar').then(function(stores) {
|
||||
is(stores.length, 1, "getDataStores('bar') returns 1 element");
|
||||
is(stores[0].name, 'bar', 'The dataStore.name is bar');
|
||||
ok(stores[0].owner, 'The dataStore.owner exists');
|
||||
is(stores[0].readOnly, false, 'The dataStore bar is in readonly');
|
||||
finish();
|
||||
}, cbError);
|
||||
}, cbError);
|
||||
</script>
|
||||
</html>
|
|
@ -0,0 +1,185 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for DataStore - basic operation on a readonly db</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="container"></div>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
var gStore;
|
||||
|
||||
function is(a, b, msg) {
|
||||
alert((a === b ? 'OK' : 'KO') + ' ' + msg)
|
||||
}
|
||||
|
||||
function ok(a, msg) {
|
||||
alert((a ? 'OK' : 'KO')+ ' ' + msg)
|
||||
}
|
||||
|
||||
function cbError() {
|
||||
alert('KO error');
|
||||
}
|
||||
|
||||
function finish() {
|
||||
alert('DONE');
|
||||
}
|
||||
|
||||
function testGetDataStores() {
|
||||
navigator.getDataStores('foo').then(function(stores) {
|
||||
is(stores.length, 1, "getDataStores('foo') returns 1 element");
|
||||
is(stores[0].name, 'foo', 'The dataStore.name is foo');
|
||||
is(stores[0].readOnly, false, 'The dataStore foo is not in readonly');
|
||||
|
||||
var store = stores[0];
|
||||
ok("get" in store, "store.get exists");
|
||||
ok("update" in store, "store.update exists");
|
||||
ok("add" in store, "store.add exists");
|
||||
ok("remove" in store, "store.remove exists");
|
||||
ok("clear" in store, "store.clear exists");
|
||||
|
||||
gStore = stores[0];
|
||||
|
||||
runTest();
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function testStoreErrorGet(id) {
|
||||
gStore.get(id).then(function(what) {
|
||||
ok(false, "store.get(" + id + ") retrieves data");
|
||||
}, function(error) {
|
||||
ok(true, "store.get() failed properly because the id is non-valid");
|
||||
ok(error instanceof DOMError, "error is a DOMError");
|
||||
is(error.name, "SyntaxError", "Error is a syntax error");
|
||||
}).then(runTest, cbError);
|
||||
}
|
||||
|
||||
function testStoreErrorUpdate(id) {
|
||||
gStore.update(id, "foo").then(function(what) {
|
||||
ok(false, "store.update(" + id + ") retrieves data");
|
||||
}, function(error) {
|
||||
ok(true, "store.update() failed properly because the id is non-valid");
|
||||
ok(error instanceof DOMError, "error is a DOMError");
|
||||
is(error.name, "SyntaxError", "Error is a syntax error");
|
||||
}).then(runTest, cbError);
|
||||
}
|
||||
|
||||
function testStoreErrorRemove(id) {
|
||||
gStore.remove(id).then(function(what) {
|
||||
ok(false, "store.remove(" + id + ") retrieves data");
|
||||
}, function(error) {
|
||||
ok(true, "store.remove() failed properly because the id is non-valid");
|
||||
ok(error instanceof DOMError, "error is a DOMError");
|
||||
is(error.name, "SyntaxError", "Error is a syntax error");
|
||||
}).then(runTest, cbError);
|
||||
}
|
||||
|
||||
function testStoreGet(id, value) {
|
||||
gStore.get(id).then(function(what) {
|
||||
ok(true, "store.get() retrieves data");
|
||||
is(what, value, "store.get(" + id + ") returns " + value);
|
||||
}, function() {
|
||||
ok(false, "store.get(" + id + ") retrieves data");
|
||||
}).then(runTest, cbError);
|
||||
}
|
||||
|
||||
function testStoreAdd(value) {
|
||||
return gStore.add(value).then(function(what) {
|
||||
ok(true, "store.add() is called");
|
||||
ok(what > 0, "store.add() returns something");
|
||||
return what;
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function testStoreUpdate(id, value) {
|
||||
return gStore.update(id, value).then(function() {
|
||||
ok(true, "store.update() is called");
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function testStoreRemove(id) {
|
||||
return gStore.remove(id).then(function() {
|
||||
ok(true, "store.remove() is called");
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function testStoreClear() {
|
||||
return gStore.clear().then(function() {
|
||||
ok(true, "store.clear() is called");
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
var tests = [
|
||||
// Test for GetDataStore
|
||||
testGetDataStores,
|
||||
|
||||
// Broken ID
|
||||
function() { testStoreErrorGet('hello world'); },
|
||||
function() { testStoreErrorGet(true); },
|
||||
function() { testStoreErrorGet(null); },
|
||||
|
||||
// Unknown ID
|
||||
function() { testStoreGet(42, undefined); },
|
||||
function() { testStoreGet(42, undefined); }, // twice
|
||||
|
||||
// Add + Get - number
|
||||
function() { testStoreAdd(42).then(function(id) {
|
||||
gId = id; runTest(); }, cbError); },
|
||||
function() { testStoreGet(gId, 42); },
|
||||
function() { testStoreGet(gId + "", 42); },
|
||||
|
||||
// Add + Get - boolean
|
||||
function() { testStoreAdd(true).then(function(id) {
|
||||
gId = id; runTest(); }, cbError); },
|
||||
function() { testStoreGet(gId, true); },
|
||||
|
||||
// Add + Get - string
|
||||
function() { testStoreAdd("hello world").then(function(id) {
|
||||
gId = id; runTest(); }, cbError); },
|
||||
function() { testStoreGet(gId, "hello world"); },
|
||||
|
||||
// Broken update
|
||||
function() { testStoreErrorUpdate('hello world'); },
|
||||
function() { testStoreErrorUpdate(true); },
|
||||
function() { testStoreErrorUpdate(null); },
|
||||
|
||||
// Update + Get - string
|
||||
function() { testStoreUpdate(gId, "hello world 2").then(function() {
|
||||
runTest(); }, cbError); },
|
||||
function() { testStoreGet(gId, "hello world 2"); },
|
||||
|
||||
// Broken remove
|
||||
function() { testStoreErrorRemove('hello world'); },
|
||||
function() { testStoreErrorRemove(true); },
|
||||
function() { testStoreErrorRemove(null); },
|
||||
|
||||
// Remove
|
||||
function() { testStoreRemove(gId).then(function(what) {
|
||||
runTest(); }, cbError); },
|
||||
function() { testStoreGet(gId).catch(function() {
|
||||
runTest(); }); },
|
||||
|
||||
// Remove - wrong ID
|
||||
function() { testStoreRemove(gId).then(function(what) {
|
||||
runTest(); }, cbError); },
|
||||
|
||||
// Clear
|
||||
function() { testStoreClear().then(function(what) {
|
||||
runTest(); }, cbError); },
|
||||
];
|
||||
|
||||
function runTest() {
|
||||
if (!tests.length) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
var test = tests.shift();
|
||||
test();
|
||||
}
|
||||
|
||||
runTest();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,72 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for DataStore - basic operation on a readonly db</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="container"></div>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
function is(a, b, msg) {
|
||||
dump((a === b ? 'OK' : 'KO') + ' ' + msg + "\n")
|
||||
alert((a === b ? 'OK' : 'KO') + ' ' + msg)
|
||||
}
|
||||
|
||||
function ok(a, msg) {
|
||||
alert((a ? 'OK' : 'KO')+ ' ' + msg)
|
||||
}
|
||||
|
||||
function cbError() {
|
||||
alert('KO error');
|
||||
}
|
||||
|
||||
function finish() {
|
||||
alert('DONE');
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
navigator.getDataStores('bar').then(function(stores) {
|
||||
is(stores.length, 1, "getDataStores('bar') returns 1 element");
|
||||
is(stores[0].name, 'bar', 'The dataStore.name is bar');
|
||||
is(stores[0].readOnly, true, 'The dataStore bar is eadonly');
|
||||
|
||||
var store = stores[0];
|
||||
ok("get" in store, "store.get exists");
|
||||
ok("update" in store, "store.update exists");
|
||||
ok("add" in store, "store.add exists");
|
||||
ok("remove" in store, "store.remove exists");
|
||||
ok("clear" in store, "store.clear exists");
|
||||
|
||||
var f = store.clear();
|
||||
f = f.then(cbError, function() {
|
||||
ok(true, "store.clear() fails because the db is readonly");
|
||||
return store.remove(123);
|
||||
});
|
||||
|
||||
f = f.then(cbError, function() {
|
||||
ok(true, "store.remove() fails because the db is readonly");
|
||||
return store.add(123, true);
|
||||
});
|
||||
|
||||
f = f.then(cbError, function() {
|
||||
ok(true, "store.add() fails because the db is readonly");
|
||||
return store.update(123, {});
|
||||
})
|
||||
|
||||
f = f.then(cbError, function() {
|
||||
ok(true, "store.update() fails because the db is readonly");
|
||||
})
|
||||
|
||||
f.then(function() {
|
||||
// All done.
|
||||
ok(true, "All done");
|
||||
finish();
|
||||
});
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
runTest();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,196 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for DataStore - basic operation on a readonly db</title>
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
var gStore;
|
||||
var gPreviousRevisionId = '';
|
||||
|
||||
function is(a, b, msg) {
|
||||
alert((a === b ? 'OK' : 'KO') + ' ' + msg)
|
||||
}
|
||||
|
||||
function isnot(a, b, msg) {
|
||||
alert((a !== b ? 'OK' : 'KO') + ' ' + msg)
|
||||
}
|
||||
|
||||
function ok(a, msg) {
|
||||
alert((a ? 'OK' : 'KO')+ ' ' + msg)
|
||||
}
|
||||
|
||||
function cbError() {
|
||||
alert('KO error');
|
||||
}
|
||||
|
||||
function finish() {
|
||||
alert('DONE');
|
||||
}
|
||||
|
||||
function testGetDataStores() {
|
||||
navigator.getDataStores('foo').then(function(stores) {
|
||||
is(stores.length, 1, "getDataStores('foo') returns 1 element");
|
||||
is(stores[0].name, 'foo', 'The dataStore.name is foo');
|
||||
is(stores[0].readOnly, false, 'The dataStore foo is not in readonly');
|
||||
|
||||
gStore = stores[0];
|
||||
|
||||
runTest();
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function testStoreAdd(value, expectedId) {
|
||||
return gStore.add(value).then(function(id) {
|
||||
is(id, expectedId, "store.add() is called");
|
||||
runTest();
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function testStoreUpdate(id, value) {
|
||||
return gStore.update(id, value).then(function(retId) {
|
||||
is(id, retId, "store.update() is called with the right id");
|
||||
runTest();
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function testStoreRemove(id, expectedSuccess) {
|
||||
return gStore.remove(id).then(function(success) {
|
||||
is(success, expectedSuccess, "store.remove() returns the right value");
|
||||
runTest();
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function testStoreRevisionId() {
|
||||
is(/[0-9a-zA-Z]{8}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{12}/.test(gStore.revisionId), true, "store.revisionId returns something");
|
||||
runTest();
|
||||
}
|
||||
|
||||
function testStoreWrongRevisions(id) {
|
||||
return gStore.getChanges(id).then(
|
||||
function(what) {
|
||||
is(what, undefined, "Wrong revisionId == undefined object");
|
||||
runTest();
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function testStoreRevisions(id, changes) {
|
||||
return gStore.getChanges(id).then(function(what) {
|
||||
is(JSON.stringify(changes.addedIds),
|
||||
JSON.stringify(what.addedIds), "store.revisions - addedIds: " +
|
||||
JSON.stringify(what.addedIds) + " | " + JSON.stringify(changes.addedIds));
|
||||
is(JSON.stringify(changes.updatedIds),
|
||||
JSON.stringify(what.updatedIds), "store.revisions - updatedIds: " +
|
||||
JSON.stringify(what.updatedIds) + " | " + JSON.stringify(changes.updatedIds));
|
||||
is(JSON.stringify(changes.removedIds),
|
||||
JSON.stringify(what.removedIds), "store.revisions - removedIds: " +
|
||||
JSON.stringify(what.removedIds) + " | " + JSON.stringify(changes.removedIds));
|
||||
runTest();
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function testStoreRevisionIdChanged() {
|
||||
isnot(gStore.revisionId, gPreviousRevisionId, "Revision changed");
|
||||
gPreviousRevisionId = gStore.revisionId;
|
||||
runTest();
|
||||
}
|
||||
|
||||
function testStoreRevisionIdNotChanged() {
|
||||
is(gStore.revisionId, gPreviousRevisionId, "Revision changed");
|
||||
runTest();
|
||||
}
|
||||
|
||||
var revisions = [];
|
||||
|
||||
var tests = [
|
||||
// Test for GetDataStore
|
||||
testGetDataStores,
|
||||
|
||||
// The first revision is not empty
|
||||
testStoreRevisionIdChanged,
|
||||
|
||||
// wrong revision ID
|
||||
function() { testStoreWrongRevisions('foobar'); },
|
||||
|
||||
// Add
|
||||
function() { testStoreAdd({ number: 42 }, 1); },
|
||||
function() { revisions.push(gStore.revisionId); testStoreRevisionId(); },
|
||||
testStoreRevisionIdChanged,
|
||||
function() { testStoreRevisions(revisions[0], { addedIds: [], updatedIds: [], removedIds: [] }); },
|
||||
|
||||
// Add
|
||||
function() { testStoreAdd({ number: 42 }, 2); },
|
||||
function() { revisions.push(gStore.revisionId); runTest(); },
|
||||
testStoreRevisionIdChanged,
|
||||
function() { testStoreRevisions(revisions[0], { addedIds: [2], updatedIds: [], removedIds: [] }); },
|
||||
function() { testStoreRevisions(revisions[1], { addedIds: [], updatedIds: [], removedIds: [] }); },
|
||||
|
||||
// Add
|
||||
function() { testStoreAdd({ number: 42 }, 3); },
|
||||
function() { revisions.push(gStore.revisionId); runTest(); },
|
||||
testStoreRevisionIdChanged,
|
||||
function() { testStoreRevisions(revisions[0], { addedIds: [2,3], updatedIds: [], removedIds: [] }); },
|
||||
function() { testStoreRevisions(revisions[1], { addedIds: [3], updatedIds: [], removedIds: [] }); },
|
||||
function() { testStoreRevisions(revisions[2], { addedIds: [], updatedIds: [], removedIds: [] }); },
|
||||
|
||||
// Update
|
||||
function() { testStoreUpdate(3, { number: 43 }); },
|
||||
function() { revisions.push(gStore.revisionId); runTest(); },
|
||||
testStoreRevisionIdChanged,
|
||||
function() { testStoreRevisions(revisions[0], { addedIds: [2,3], updatedIds: [], removedIds: [] }); },
|
||||
function() { testStoreRevisions(revisions[1], { addedIds: [3], updatedIds: [], removedIds: [] }); },
|
||||
function() { testStoreRevisions(revisions[2], { addedIds: [], updatedIds: [3], removedIds: [] }); },
|
||||
function() { testStoreRevisions(revisions[3], { addedIds: [], updatedIds: [], removedIds: [] }); },
|
||||
|
||||
// Update
|
||||
function() { testStoreUpdate(3, { number: 42 }); },
|
||||
function() { revisions.push(gStore.revisionId); runTest(); },
|
||||
testStoreRevisionIdChanged,
|
||||
function() { testStoreRevisions(revisions[0], { addedIds: [2,3], updatedIds: [], removedIds: [] }); },
|
||||
function() { testStoreRevisions(revisions[1], { addedIds: [3], updatedIds: [], removedIds: [] }); },
|
||||
function() { testStoreRevisions(revisions[2], { addedIds: [], updatedIds: [3], removedIds: [] }); },
|
||||
function() { testStoreRevisions(revisions[3], { addedIds: [], updatedIds: [3], removedIds: [] }); },
|
||||
function() { testStoreRevisions(revisions[4], { addedIds: [], updatedIds: [], removedIds: [] }); },
|
||||
|
||||
// Remove
|
||||
function() { testStoreRemove(3, true); },
|
||||
function() { revisions.push(gStore.revisionId); runTest(); },
|
||||
testStoreRevisionIdChanged,
|
||||
function() { testStoreRevisions(revisions[0], { addedIds: [2], updatedIds: [], removedIds: [] }); },
|
||||
function() { testStoreRevisions(revisions[1], { addedIds: [], updatedIds: [], removedIds: [] }); },
|
||||
function() { testStoreRevisions(revisions[2], { addedIds: [], updatedIds: [], removedIds: [3] }); },
|
||||
function() { testStoreRevisions(revisions[3], { addedIds: [], updatedIds: [], removedIds: [3] }); },
|
||||
function() { testStoreRevisions(revisions[4], { addedIds: [], updatedIds: [], removedIds: [3] }); },
|
||||
function() { testStoreRevisions(revisions[5], { addedIds: [], updatedIds: [], removedIds: [] }); },
|
||||
|
||||
function() { testStoreRemove(3, false); },
|
||||
testStoreRevisionIdNotChanged,
|
||||
|
||||
// Remove
|
||||
function() { testStoreRemove(42, false); },
|
||||
testStoreRevisionIdNotChanged,
|
||||
];
|
||||
|
||||
function runTest() {
|
||||
if (!tests.length) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
var test = tests.shift();
|
||||
test();
|
||||
}
|
||||
|
||||
runTest();
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var gBaseURL = 'http://test/tests/dom/datastore/tests/';
|
||||
var gHostedManifestURL = gBaseURL + 'file_app.sjs';
|
||||
var gHostedManifestURL = gBaseURL + 'file_app.sjs?testToken=file_app_install.html';
|
||||
var gGenerator = runTest();
|
||||
|
||||
SpecialPowers.pushPermissions(
|
||||
|
@ -23,7 +23,8 @@
|
|||
function() { gGenerator.next() });
|
||||
|
||||
function continueTest() {
|
||||
gGenerator.next();
|
||||
try { gGenerator.next(); }
|
||||
catch(e) { dump("Got exception: " + e + "\n"); }
|
||||
}
|
||||
|
||||
function cbError() {
|
||||
|
@ -40,6 +41,8 @@
|
|||
}, cbError);
|
||||
yield undefined;
|
||||
|
||||
SpecialPowers.setBoolPref("dom.mozBrowserFramesEnabled", true);
|
||||
|
||||
SpecialPowers.autoConfirmAppInstall(continueTest);
|
||||
yield undefined;
|
||||
|
||||
|
@ -53,42 +56,43 @@
|
|||
is(app.manifest.description, "Updated even faster than Firefox, just to annoy slashdotters.",
|
||||
"Manifest is HTML-sanitized");
|
||||
|
||||
navigator.getDataStores('foo').then(function(stores) {
|
||||
is(stores.length, 1, "getDataStores('foo') returns 1 element");
|
||||
is(stores[0].name, 'foo', 'The dataStore.name is foo');
|
||||
is(stores[0].owner, 'http://test/tests/dom/datastore/tests/file_app.sjs', 'The dataStore.owner exists');
|
||||
is(stores[0].readOnly, false, 'The dataStore foo is not in readonly');
|
||||
continueTest();
|
||||
}, cbError);
|
||||
yield undefined;
|
||||
var ifr = document.createElement('iframe');
|
||||
ifr.setAttribute('mozbrowser', 'true');
|
||||
ifr.setAttribute('mozapp', app.manifestURL);
|
||||
ifr.setAttribute('src', app.manifest.launch_path);
|
||||
var domParent = document.getElementById('container');
|
||||
|
||||
navigator.getDataStores('bar').then(function(stores) {
|
||||
is(stores.length, 1, "getDataStores('bar') returns 1 element");
|
||||
is(stores[0].name, 'bar', 'The dataStore.name is bar');
|
||||
is(stores[0].owner, 'http://test/tests/dom/datastore/tests/file_app.sjs', 'The dataStore.owner exists');
|
||||
is(stores[0].readOnly, true, 'The dataStore bar is in readonly');
|
||||
continueTest();
|
||||
}, cbError);
|
||||
yield undefined;
|
||||
// Set us up to listen for messages from the app.
|
||||
var listener = function(e) {
|
||||
var message = e.detail.message;
|
||||
if (/^OK/.exec(message)) {
|
||||
ok(true, "Message from app: " + message);
|
||||
} else if (/KO/.exec(message)) {
|
||||
ok(false, "Message from app: " + message);
|
||||
} else if (/DONE/.exec(message)) {
|
||||
ok(true, "Messaging from app complete");
|
||||
ifr.removeEventListener('mozbrowsershowmodalprompt', listener);
|
||||
domParent.removeChild(ifr);
|
||||
|
||||
// Uninstall the app.
|
||||
request = navigator.mozApps.mgmt.uninstall(app);
|
||||
request.onerror = cbError;
|
||||
request.onsuccess = continueTest;
|
||||
yield undefined;
|
||||
// Uninstall the app.
|
||||
request = navigator.mozApps.mgmt.uninstall(app);
|
||||
request.onerror = cbError;
|
||||
request.onsuccess = function() {
|
||||
// All done.
|
||||
ok(true, "All done");
|
||||
finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
navigator.getDataStores('foo').then(function(stores) {
|
||||
is(stores.length, 0, "getDataStores('foo') returns 0 elements");
|
||||
continueTest();
|
||||
}, cbError);
|
||||
yield undefined;
|
||||
// This event is triggered when the app calls "alert".
|
||||
ifr.addEventListener('mozbrowsershowmodalprompt', listener, false);
|
||||
|
||||
// All done.
|
||||
info("All done");
|
||||
finish();
|
||||
domParent.appendChild(ifr);
|
||||
}
|
||||
|
||||
function finish() {
|
||||
SpecialPowers.clearUserPref("dom.mozBrowserFramesEnabled");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
|
|
|
@ -11,9 +11,8 @@
|
|||
<script type="application/javascript;version=1.7">
|
||||
|
||||
var gBaseURL = 'http://test/tests/dom/datastore/tests/';
|
||||
var gHostedManifestURL = gBaseURL + 'file_app.sjs';
|
||||
var gHostedManifestURL = gBaseURL + 'file_app.sjs?testToken=file_basic.html';
|
||||
var gApp;
|
||||
var gStore;
|
||||
|
||||
function cbError() {
|
||||
ok(false, "Error callback invoked");
|
||||
|
@ -29,94 +28,9 @@
|
|||
}
|
||||
}
|
||||
|
||||
function testGetDataStores() {
|
||||
navigator.getDataStores('foo').then(function(stores) {
|
||||
is(stores.length, 1, "getDataStores('foo') returns 1 element");
|
||||
is(stores[0].name, 'foo', 'The dataStore.name is foo');
|
||||
is(stores[0].readOnly, false, 'The dataStore foo is not in readonly');
|
||||
|
||||
var store = stores[0];
|
||||
ok("get" in store, "store.get exists");
|
||||
ok("update" in store, "store.update exists");
|
||||
ok("add" in store, "store.add exists");
|
||||
ok("remove" in store, "store.remove exists");
|
||||
ok("clear" in store, "store.clear exists");
|
||||
|
||||
gStore = stores[0];
|
||||
|
||||
runTest();
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function testStoreErrorGet(id) {
|
||||
gStore.get(id).then(function(what) {
|
||||
ok(false, "store.get(" + id + ") retrieves data");
|
||||
}, function(error) {
|
||||
ok(true, "store.get() failed properly because the id is non-valid");
|
||||
ok(error instanceof DOMError, "error is a DOMError");
|
||||
is(error.name, "SyntaxError", "Error is a syntax error");
|
||||
}).then(runTest, cbError);
|
||||
}
|
||||
|
||||
function testStoreErrorUpdate(id) {
|
||||
gStore.update(id, "foo").then(function(what) {
|
||||
ok(false, "store.update(" + id + ") retrieves data");
|
||||
}, function(error) {
|
||||
ok(true, "store.update() failed properly because the id is non-valid");
|
||||
ok(error instanceof DOMError, "error is a DOMError");
|
||||
is(error.name, "SyntaxError", "Error is a syntax error");
|
||||
}).then(runTest, cbError);
|
||||
}
|
||||
|
||||
function testStoreErrorRemove(id) {
|
||||
gStore.remove(id).then(function(what) {
|
||||
ok(false, "store.remove(" + id + ") retrieves data");
|
||||
}, function(error) {
|
||||
ok(true, "store.remove() failed properly because the id is non-valid");
|
||||
ok(error instanceof DOMError, "error is a DOMError");
|
||||
is(error.name, "SyntaxError", "Error is a syntax error");
|
||||
}).then(runTest, cbError);
|
||||
}
|
||||
|
||||
function testStoreGet(id, value) {
|
||||
gStore.get(id).then(function(what) {
|
||||
ok(true, "store.get() retrieves data");
|
||||
is(what, value, "store.get(" + id + ") returns " + value);
|
||||
}, function() {
|
||||
ok(false, "store.get(" + id + ") retrieves data");
|
||||
}).then(runTest, cbError);
|
||||
}
|
||||
|
||||
function testStoreAdd(value) {
|
||||
return gStore.add(value).then(function(what) {
|
||||
ok(true, "store.add() is called");
|
||||
ok(what > 0, "store.add() returns something");
|
||||
return what;
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function testStoreUpdate(id, value) {
|
||||
return gStore.update(id, value).then(function(what) {
|
||||
ok(true, "store.update() is called");
|
||||
is(id, what, "store.update(" + id + ") updates the correct id");
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function testStoreRemove(id) {
|
||||
return gStore.remove(id).then(function() {
|
||||
ok(true, "store.remove() is called");
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function testStoreClear() {
|
||||
return gStore.clear().then(function() {
|
||||
ok(true, "store.clear() is called");
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function uninstallApp() {
|
||||
// Uninstall the app.
|
||||
request = navigator.mozApps.mgmt.uninstall(gApp);
|
||||
var request = navigator.mozApps.mgmt.uninstall(gApp);
|
||||
request.onerror = cbError;
|
||||
request.onsuccess = function() {
|
||||
// All done.
|
||||
|
@ -125,6 +39,33 @@
|
|||
}
|
||||
}
|
||||
|
||||
function testApp() {
|
||||
var ifr = document.createElement('iframe');
|
||||
ifr.setAttribute('mozbrowser', 'true');
|
||||
ifr.setAttribute('mozapp', gApp.manifestURL);
|
||||
ifr.setAttribute('src', gApp.manifest.launch_path);
|
||||
var domParent = document.getElementById('container');
|
||||
|
||||
// Set us up to listen for messages from the app.
|
||||
var listener = function(e) {
|
||||
var message = e.detail.message;
|
||||
if (/^OK/.exec(message)) {
|
||||
ok(true, "Message from app: " + message);
|
||||
} else if (/KO/.exec(message)) {
|
||||
ok(false, "Message from app: " + message);
|
||||
} else if (/DONE/.exec(message)) {
|
||||
ok(true, "Messaging from app complete");
|
||||
ifr.removeEventListener('mozbrowsershowmodalprompt', listener);
|
||||
domParent.removeChild(ifr);
|
||||
runTest();
|
||||
}
|
||||
}
|
||||
|
||||
// This event is triggered when the app calls "alert".
|
||||
ifr.addEventListener('mozbrowsershowmodalprompt', listener, false);
|
||||
domParent.appendChild(ifr);
|
||||
}
|
||||
|
||||
var tests = [
|
||||
// Permissions
|
||||
function() {
|
||||
|
@ -139,6 +80,11 @@
|
|||
SpecialPowers.pushPrefEnv({"set": [["dom.promise.enabled", true]]}, runTest);
|
||||
},
|
||||
|
||||
function() {
|
||||
SpecialPowers.setBoolPref("dom.mozBrowserFramesEnabled", true);
|
||||
runTest();
|
||||
},
|
||||
|
||||
// No confirmation needed when an app is installed
|
||||
function() {
|
||||
SpecialPowers.autoConfirmAppInstall(runTest);
|
||||
|
@ -147,62 +93,8 @@
|
|||
// Installing the app
|
||||
installApp,
|
||||
|
||||
// Test for GetDataStore
|
||||
testGetDataStores,
|
||||
|
||||
// Broken ID
|
||||
function() { testStoreErrorGet('hello world'); },
|
||||
function() { testStoreErrorGet(true); },
|
||||
function() { testStoreErrorGet(null); },
|
||||
|
||||
// Unknown ID
|
||||
function() { testStoreGet(42, undefined); },
|
||||
function() { testStoreGet(42, undefined); }, // twice
|
||||
|
||||
// Add + Get - number
|
||||
function() { testStoreAdd(42).then(function(id) {
|
||||
gId = id; runTest(); }, cbError); },
|
||||
function() { testStoreGet(gId, 42); },
|
||||
function() { testStoreGet(gId+"", 42); },
|
||||
|
||||
// Add + Get - boolean
|
||||
function() { testStoreAdd(true).then(function(id) {
|
||||
gId = id; runTest(); }, cbError); },
|
||||
function() { testStoreGet(gId, true); },
|
||||
|
||||
// Add + Get - string
|
||||
function() { testStoreAdd("hello world").then(function(id) {
|
||||
gId = id; runTest(); }, cbError); },
|
||||
function() { testStoreGet(gId, "hello world"); },
|
||||
|
||||
// Broken update
|
||||
function() { testStoreErrorUpdate('hello world'); },
|
||||
function() { testStoreErrorUpdate(true); },
|
||||
function() { testStoreErrorUpdate(null); },
|
||||
|
||||
// Update + Get - string
|
||||
function() { testStoreUpdate(gId, "hello world 2").then(function() {
|
||||
runTest(); }, cbError); },
|
||||
function() { testStoreGet(gId, "hello world 2"); },
|
||||
|
||||
// Broken remove
|
||||
function() { testStoreErrorRemove('hello world'); },
|
||||
function() { testStoreErrorRemove(true); },
|
||||
function() { testStoreErrorRemove(null); },
|
||||
|
||||
// Remove
|
||||
function() { testStoreRemove(gId).then(function(what) {
|
||||
runTest(); }, cbError); },
|
||||
function() { testStoreGet(gId).catch(function() {
|
||||
runTest(); }); },
|
||||
|
||||
// Remove - wrong ID
|
||||
function() { testStoreRemove(gId).then(function(what) {
|
||||
runTest(); }, cbError); },
|
||||
|
||||
// Clear
|
||||
function() { testStoreClear().then(function(what) {
|
||||
runTest(); }, cbError); },
|
||||
// Run tests in app
|
||||
testApp,
|
||||
|
||||
// Uninstall the app
|
||||
uninstallApp
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
<div id="container"></div>
|
||||
<script type="application/javascript;version=1.7">
|
||||
var gBaseURL = 'http://test/tests/dom/datastore/tests/';
|
||||
var gHostedManifestURL = gBaseURL + 'file_app.sjs';
|
||||
var gHostedManifestURL = gBaseURL + 'file_app.sjs?testToken=file_readonly.html';
|
||||
var gHostedManifestURL2 = 'http://example.com/tests/dom/datastore/tests/file_app2.template.webapp';
|
||||
var gGenerator = runTest();
|
||||
|
||||
SpecialPowers.pushPermissions(
|
||||
|
@ -30,6 +31,8 @@
|
|||
}
|
||||
|
||||
function runTest() {
|
||||
SpecialPowers.setBoolPref("dom.mozBrowserFramesEnabled", true);
|
||||
|
||||
SpecialPowers.autoConfirmAppInstall(continueTest);
|
||||
yield undefined;
|
||||
|
||||
|
@ -40,52 +43,55 @@
|
|||
|
||||
var app = request.result;
|
||||
|
||||
navigator.getDataStores('bar').then(function(stores) {
|
||||
is(stores.length, 1, "getDataStores('bar') returns 1 element");
|
||||
is(stores[0].name, 'bar', 'The dataStore.name is bar');
|
||||
is(stores[0].readOnly, true, 'The dataStore bar is readonly');
|
||||
request = navigator.mozApps.install(gHostedManifestURL2);
|
||||
request.onerror = cbError;
|
||||
request.onsuccess = continueTest;
|
||||
yield undefined;
|
||||
|
||||
var store = stores[0];
|
||||
ok("get" in store, "store.get exists");
|
||||
ok("update" in store, "store.update exists");
|
||||
ok("add" in store, "store.add exists");
|
||||
ok("remove" in store, "store.remove exists");
|
||||
ok("clear" in store, "store.clear exists");
|
||||
var app2 = request.result;
|
||||
|
||||
var f = store.clear();
|
||||
f = f.then(cbError, function() {
|
||||
ok(true, "store.clear() fails because the db is readonly");
|
||||
return store.remove(123);
|
||||
});
|
||||
var ifr = document.createElement('iframe');
|
||||
ifr.setAttribute('mozbrowser', 'true');
|
||||
ifr.setAttribute('mozapp', app2.manifestURL);
|
||||
ifr.setAttribute('src', 'http://example.com/tests/dom/datastore/tests/file_readonly.html');
|
||||
var domParent = document.getElementById('container');
|
||||
|
||||
f = f.then(cbError, function() {
|
||||
ok(true, "store.remove() fails because the db is readonly");
|
||||
return store.add(123, true);
|
||||
});
|
||||
// Set us up to listen for messages from the app.
|
||||
var listener = function(e) {
|
||||
var message = e.detail.message;
|
||||
if (/^OK/.exec(message)) {
|
||||
ok(true, "Message from app: " + message);
|
||||
} else if (/KO/.exec(message)) {
|
||||
ok(false, "Message from app: " + message);
|
||||
} else if (/DONE/.exec(message)) {
|
||||
ok(true, "Messaging from app complete");
|
||||
ifr.removeEventListener('mozbrowsershowmodalprompt', listener);
|
||||
domParent.removeChild(ifr);
|
||||
|
||||
f = f.then(cbError, function() {
|
||||
ok(true, "store.add() fails because the db is readonly");
|
||||
return store.update(123, {});
|
||||
})
|
||||
|
||||
f = f.then(cbError, function() {
|
||||
ok(true, "store.update() fails because the db is readonly");
|
||||
})
|
||||
|
||||
f.then(function() {
|
||||
// Uninstall the app.
|
||||
request = navigator.mozApps.mgmt.uninstall(app);
|
||||
request.onerror = cbError;
|
||||
request.onsuccess = function() {
|
||||
// All done.
|
||||
info("All done");
|
||||
finish();
|
||||
// Uninstall app2
|
||||
request = navigator.mozApps.mgmt.uninstall(app2);
|
||||
request.onerror = cbError;
|
||||
request.onsuccess = function() {
|
||||
// All done.
|
||||
info("All done");
|
||||
finish();
|
||||
}
|
||||
}
|
||||
});
|
||||
}, cbError);
|
||||
}
|
||||
}
|
||||
|
||||
// This event is triggered when the app calls "alert".
|
||||
ifr.addEventListener('mozbrowsershowmodalprompt', listener, false);
|
||||
|
||||
domParent.appendChild(ifr);
|
||||
}
|
||||
|
||||
function finish() {
|
||||
SpecialPowers.clearUserPref("dom.mozBrowserFramesEnabled");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<script type="application/javascript;version=1.7">
|
||||
|
||||
var gBaseURL = 'http://test/tests/dom/datastore/tests/';
|
||||
var gHostedManifestURL = gBaseURL + 'file_app.sjs';
|
||||
var gHostedManifestURL = gBaseURL + 'file_app.sjs?testToken=file_revision.html';
|
||||
var gApp;
|
||||
var gStore;
|
||||
var gPreviousRevisionId = '';
|
||||
|
@ -34,70 +34,9 @@
|
|||
}
|
||||
}
|
||||
|
||||
function testGetDataStores() {
|
||||
navigator.getDataStores('foo').then(function(stores) {
|
||||
is(stores.length, 1, "getDataStores('foo') returns 1 element");
|
||||
is(stores[0].name, 'foo', 'The dataStore.name is foo');
|
||||
is(stores[0].readOnly, false, 'The dataStore foo is not in readonly');
|
||||
|
||||
gStore = stores[0];
|
||||
|
||||
runTest();
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function testStoreAdd(value, expectedId) {
|
||||
return gStore.add(value).then(function(id) {
|
||||
is(id, expectedId, "store.add() is called");
|
||||
runTest();
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function testStoreUpdate(id, value) {
|
||||
return gStore.update(id, value).then(function(retId) {
|
||||
is(id, retId, "store.update() is called with the right id");
|
||||
runTest();
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function testStoreRemove(id, expectedSuccess) {
|
||||
return gStore.remove(id).then(function(success) {
|
||||
is(success, expectedSuccess, "store.remove() returns the right value");
|
||||
runTest();
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function testStoreRevisionId() {
|
||||
is(/[0-9a-zA-Z]{8}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{12}/.test(gStore.revisionId), true, "store.revisionId returns something");
|
||||
runTest();
|
||||
}
|
||||
|
||||
function testStoreWrongRevisions(id) {
|
||||
return gStore.getChanges(id).then(
|
||||
function(what) {
|
||||
is(what, undefined, "Wrong revisionId == undefined object");
|
||||
runTest();
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function testStoreRevisions(id, changes) {
|
||||
return gStore.getChanges(id).then(function(what) {
|
||||
is(JSON.stringify(changes.addedIds),
|
||||
JSON.stringify(what.addedIds), "store.revisions - addedIds: " +
|
||||
JSON.stringify(what.addedIds) + " | " + JSON.stringify(changes.addedIds));
|
||||
is(JSON.stringify(changes.updatedIds),
|
||||
JSON.stringify(what.updatedIds), "store.revisions - updatedIds: " +
|
||||
JSON.stringify(what.updatedIds) + " | " + JSON.stringify(changes.updatedIds));
|
||||
is(JSON.stringify(changes.removedIds),
|
||||
JSON.stringify(what.removedIds), "store.revisions - removedIds: " +
|
||||
JSON.stringify(what.removedIds) + " | " + JSON.stringify(changes.removedIds));
|
||||
runTest();
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function uninstallApp() {
|
||||
// Uninstall the app.
|
||||
request = navigator.mozApps.mgmt.uninstall(gApp);
|
||||
var request = navigator.mozApps.mgmt.uninstall(gApp);
|
||||
request.onerror = cbError;
|
||||
request.onsuccess = function() {
|
||||
// All done.
|
||||
|
@ -106,15 +45,31 @@
|
|||
}
|
||||
}
|
||||
|
||||
function testStoreRevisionIdChanged() {
|
||||
isnot(gStore.revisionId, gPreviousRevisionId, "Revision changed");
|
||||
gPreviousRevisionId = gStore.revisionId;
|
||||
runTest();
|
||||
}
|
||||
function testApp() {
|
||||
var ifr = document.createElement('iframe');
|
||||
ifr.setAttribute('mozbrowser', 'true');
|
||||
ifr.setAttribute('mozapp', gApp.manifestURL);
|
||||
ifr.setAttribute('src', gApp.manifest.launch_path);
|
||||
var domParent = document.getElementById('content');
|
||||
|
||||
function testStoreRevisionIdNotChanged() {
|
||||
is(gStore.revisionId, gPreviousRevisionId, "Revision changed");
|
||||
runTest();
|
||||
// Set us up to listen for messages from the app.
|
||||
var listener = function(e) {
|
||||
var message = e.detail.message;
|
||||
if (/^OK/.exec(message)) {
|
||||
ok(true, "Message from app: " + message);
|
||||
} else if (/KO/.exec(message)) {
|
||||
ok(false, "Message from app: " + message);
|
||||
} else if (/DONE/.exec(message)) {
|
||||
ok(true, "Messaging from app complete");
|
||||
ifr.removeEventListener('mozbrowsershowmodalprompt', listener);
|
||||
domParent.removeChild(ifr);
|
||||
runTest();
|
||||
}
|
||||
}
|
||||
|
||||
// This event is triggered when the app calls "alert".
|
||||
ifr.addEventListener('mozbrowsershowmodalprompt', listener, false);
|
||||
domParent.appendChild(ifr);
|
||||
}
|
||||
|
||||
var revisions = [];
|
||||
|
@ -133,6 +88,11 @@
|
|||
SpecialPowers.pushPrefEnv({"set": [["dom.promise.enabled", true]]}, runTest);
|
||||
},
|
||||
|
||||
// Enabling mozBrowser
|
||||
function() {
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.mozBrowserFramesEnabled", true]]}, runTest);
|
||||
},
|
||||
|
||||
// No confirmation needed when an app is installed
|
||||
function() {
|
||||
SpecialPowers.autoConfirmAppInstall(runTest);
|
||||
|
@ -141,72 +101,8 @@
|
|||
// Installing the app
|
||||
installApp,
|
||||
|
||||
// Test for GetDataStore
|
||||
testGetDataStores,
|
||||
|
||||
// The first revision is not empty
|
||||
testStoreRevisionIdChanged,
|
||||
|
||||
// wrong revision ID
|
||||
function() { testStoreWrongRevisions('foobar'); },
|
||||
|
||||
// Add
|
||||
function() { testStoreAdd({ number: 42 }, 1); },
|
||||
function() { revisions.push(gStore.revisionId); testStoreRevisionId(); },
|
||||
testStoreRevisionIdChanged,
|
||||
function() { testStoreRevisions(revisions[0], { addedIds: [], updatedIds: [], removedIds: [] }); },
|
||||
|
||||
// Add
|
||||
function() { testStoreAdd({ number: 42 }, 2); },
|
||||
function() { revisions.push(gStore.revisionId); runTest(); },
|
||||
testStoreRevisionIdChanged,
|
||||
function() { testStoreRevisions(revisions[0], { addedIds: [2], updatedIds: [], removedIds: [] }); },
|
||||
function() { testStoreRevisions(revisions[1], { addedIds: [], updatedIds: [], removedIds: [] }); },
|
||||
|
||||
// Add
|
||||
function() { testStoreAdd({ number: 42 }, 3); },
|
||||
function() { revisions.push(gStore.revisionId); runTest(); },
|
||||
testStoreRevisionIdChanged,
|
||||
function() { testStoreRevisions(revisions[0], { addedIds: [2,3], updatedIds: [], removedIds: [] }); },
|
||||
function() { testStoreRevisions(revisions[1], { addedIds: [3], updatedIds: [], removedIds: [] }); },
|
||||
function() { testStoreRevisions(revisions[2], { addedIds: [], updatedIds: [], removedIds: [] }); },
|
||||
|
||||
// Update
|
||||
function() { testStoreUpdate(3, { number: 43 }); },
|
||||
function() { revisions.push(gStore.revisionId); runTest(); },
|
||||
testStoreRevisionIdChanged,
|
||||
function() { testStoreRevisions(revisions[0], { addedIds: [2,3], updatedIds: [], removedIds: [] }); },
|
||||
function() { testStoreRevisions(revisions[1], { addedIds: [3], updatedIds: [], removedIds: [] }); },
|
||||
function() { testStoreRevisions(revisions[2], { addedIds: [], updatedIds: [3], removedIds: [] }); },
|
||||
function() { testStoreRevisions(revisions[3], { addedIds: [], updatedIds: [], removedIds: [] }); },
|
||||
|
||||
// Update
|
||||
function() { testStoreUpdate(3, { number: 42 }); },
|
||||
function() { revisions.push(gStore.revisionId); runTest(); },
|
||||
testStoreRevisionIdChanged,
|
||||
function() { testStoreRevisions(revisions[0], { addedIds: [2,3], updatedIds: [], removedIds: [] }); },
|
||||
function() { testStoreRevisions(revisions[1], { addedIds: [3], updatedIds: [], removedIds: [] }); },
|
||||
function() { testStoreRevisions(revisions[2], { addedIds: [], updatedIds: [3], removedIds: [] }); },
|
||||
function() { testStoreRevisions(revisions[3], { addedIds: [], updatedIds: [3], removedIds: [] }); },
|
||||
function() { testStoreRevisions(revisions[4], { addedIds: [], updatedIds: [], removedIds: [] }); },
|
||||
|
||||
// Remove
|
||||
function() { testStoreRemove(3, true); },
|
||||
function() { revisions.push(gStore.revisionId); runTest(); },
|
||||
testStoreRevisionIdChanged,
|
||||
function() { testStoreRevisions(revisions[0], { addedIds: [2], updatedIds: [], removedIds: [] }); },
|
||||
function() { testStoreRevisions(revisions[1], { addedIds: [], updatedIds: [], removedIds: [] }); },
|
||||
function() { testStoreRevisions(revisions[2], { addedIds: [], updatedIds: [], removedIds: [3] }); },
|
||||
function() { testStoreRevisions(revisions[3], { addedIds: [], updatedIds: [], removedIds: [3] }); },
|
||||
function() { testStoreRevisions(revisions[4], { addedIds: [], updatedIds: [], removedIds: [3] }); },
|
||||
function() { testStoreRevisions(revisions[5], { addedIds: [], updatedIds: [], removedIds: [] }); },
|
||||
|
||||
function() { testStoreRemove(3, false); },
|
||||
testStoreRevisionIdNotChanged,
|
||||
|
||||
// Remove
|
||||
function() { testStoreRemove(42, false); },
|
||||
testStoreRevisionIdNotChanged,
|
||||
// Run tests in app
|
||||
testApp,
|
||||
|
||||
// Uninstall the app
|
||||
uninstallApp
|
||||
|
|
Загрузка…
Ссылка в новой задаче