mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 871445 patch 5 - DataStore: onchange, r=ehsan, r=bent
This commit is contained in:
parent
907c386bbd
commit
d4a12c91c0
@ -6,6 +6,7 @@
|
||||
|
||||
Cu.import('resource://gre/modules/ContactService.jsm');
|
||||
Cu.import('resource://gre/modules/SettingsChangeNotifier.jsm');
|
||||
Cu.import('resource://gre/modules/DataStoreChangeNotifier.jsm');
|
||||
Cu.import('resource://gre/modules/AlarmService.jsm');
|
||||
Cu.import('resource://gre/modules/ActivitiesService.jsm');
|
||||
Cu.import('resource://gre/modules/PermissionPromptHelper.jsm');
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
'use strict'
|
||||
|
||||
var EXPORTED_SYMBOLS = ["DataStore", "DataStoreAccess"];
|
||||
this.EXPORTED_SYMBOLS = ["DataStore", "DataStoreAccess"];
|
||||
|
||||
function debug(s) {
|
||||
// dump('DEBUG DataStore: ' + s + '\n');
|
||||
@ -22,6 +22,11 @@ const REVISION_VOID = "void";
|
||||
Cu.import("resource://gre/modules/DataStoreDB.jsm");
|
||||
Cu.import("resource://gre/modules/ObjectWrapper.jsm");
|
||||
Cu.import('resource://gre/modules/Services.jsm');
|
||||
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
|
||||
"@mozilla.org/childprocessmessagemanager;1",
|
||||
"nsIMessageSender");
|
||||
|
||||
/* Helper function */
|
||||
function createDOMError(aWindow, aEvent) {
|
||||
@ -161,13 +166,14 @@ DataStore.prototype = {
|
||||
this.db.addRevision(aRevisionStore, aId, aType,
|
||||
function(aRevisionId) {
|
||||
self.revisionId = aRevisionId;
|
||||
self.sendNotification(aId, aType, aRevisionId);
|
||||
aSuccessCb();
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
retrieveRevisionId: function(aSuccessCb) {
|
||||
if (this.revisionId != null) {
|
||||
retrieveRevisionId: function(aSuccessCb, aForced) {
|
||||
if (this.revisionId != null && !aForced) {
|
||||
aSuccessCb();
|
||||
return;
|
||||
}
|
||||
@ -183,7 +189,12 @@ DataStore.prototype = {
|
||||
let cursor = aEvent.target.result;
|
||||
if (!cursor) {
|
||||
// If the revision doesn't exist, let's create the first one.
|
||||
self.addRevision(aRevisionStore, 0, REVISION_VOID, aSuccessCb);
|
||||
self.addRevision(aRevisionStore, 0, REVISION_VOID,
|
||||
function(aRevisionId) {
|
||||
self.revisionId = aRevisionId;
|
||||
aSuccessCb();
|
||||
}
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -207,6 +218,7 @@ DataStore.prototype = {
|
||||
exposeObject: function(aWindow, aReadOnly) {
|
||||
let self = this;
|
||||
let object = {
|
||||
callbacks: [],
|
||||
|
||||
// Public interface :
|
||||
|
||||
@ -398,8 +410,34 @@ DataStore.prototype = {
|
||||
});
|
||||
},
|
||||
|
||||
set onchange(aCallback) {
|
||||
debug("Set OnChange");
|
||||
this.onchangeCb = aCallback;
|
||||
},
|
||||
|
||||
get onchange() {
|
||||
debug("Get OnChange");
|
||||
return this.onchangeCb;
|
||||
},
|
||||
|
||||
addEventListener: function(aName, aCallback) {
|
||||
debug("addEventListener:" + aName);
|
||||
if (aName != 'change') {
|
||||
return;
|
||||
}
|
||||
|
||||
this.callbacks.push(aCallback);
|
||||
},
|
||||
|
||||
removeEventListener: function(aName, aCallback) {
|
||||
debug('removeEventListener');
|
||||
let pos = this.callbacks.indexOf(aCallback);
|
||||
if (pos != -1) {
|
||||
this.callbacks.splice(pos, 1);
|
||||
}
|
||||
},
|
||||
|
||||
/* TODO:
|
||||
attribute EventHandler onchange;
|
||||
getAll(), getLength()
|
||||
*/
|
||||
|
||||
@ -413,15 +451,79 @@ DataStore.prototype = {
|
||||
remove: 'r',
|
||||
clear: 'r',
|
||||
revisionId: 'r',
|
||||
getChanges: 'r'
|
||||
getChanges: 'r',
|
||||
onchange: 'rw',
|
||||
addEventListener: 'r',
|
||||
removeEventListener: 'r'
|
||||
},
|
||||
|
||||
receiveMessage: function(aMessage) {
|
||||
debug("receiveMessage");
|
||||
|
||||
if (aMessage.name != "DataStore:Changed:Return:OK") {
|
||||
debug("Wrong message: " + aMessage.name);
|
||||
return;
|
||||
}
|
||||
|
||||
self.retrieveRevisionId(
|
||||
function() {
|
||||
if (object.onchangeCb || object.callbacks.length) {
|
||||
let wrappedData = ObjectWrapper.wrap(aMessage.data, aWindow);
|
||||
|
||||
// This array is used to avoid that a callback adds/removes
|
||||
// another eventListener.
|
||||
var cbs = [];
|
||||
if (object.onchangeCb) {
|
||||
cbs.push(object.onchangeCb);
|
||||
}
|
||||
|
||||
for (let i = 0; i < object.callbacks.length; ++i) {
|
||||
cbs.push(object.callbacks[i]);
|
||||
}
|
||||
|
||||
for (let i = 0; i < cbs.length; ++i) {
|
||||
try {
|
||||
cbs[i](wrappedData);
|
||||
} catch(e) {}
|
||||
}
|
||||
}
|
||||
},
|
||||
// Forcing the reading of the revisionId
|
||||
true
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
Services.obs.addObserver(function(aSubject, aTopic, aData) {
|
||||
let wId = aSubject.QueryInterface(Ci.nsISupportsPRUint64).data;
|
||||
if (wId == object.innerWindowID) {
|
||||
cpmm.removeMessageListener("DataStore:Changed:Return:OK", object);
|
||||
}
|
||||
}, "inner-window-destroyed", false);
|
||||
|
||||
let util = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
object.innerWindowID = util.currentInnerWindowID;
|
||||
|
||||
cpmm.addMessageListener("DataStore:Changed:Return:OK", object);
|
||||
cpmm.sendAsyncMessage("DataStore:RegisterForMessages",
|
||||
{ store: this.name, owner: this.owner });
|
||||
|
||||
return object;
|
||||
},
|
||||
|
||||
delete: function() {
|
||||
this.db.delete();
|
||||
},
|
||||
|
||||
sendNotification: function(aId, aOperation, aRevisionId) {
|
||||
debug("SendNotification");
|
||||
if (aOperation != REVISION_VOID) {
|
||||
cpmm.sendAsyncMessage("DataStore:Changed",
|
||||
{ store: this.name, owner: this.owner,
|
||||
message: { revisionId: aRevisionId, id: aId,
|
||||
operation: aOperation } } );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
110
dom/datastore/DataStoreChangeNotifier.jsm
Normal file
110
dom/datastore/DataStoreChangeNotifier.jsm
Normal file
@ -0,0 +1,110 @@
|
||||
/* 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/. */
|
||||
|
||||
"use strict"
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["DataStoreChangeNotifier"];
|
||||
|
||||
function debug(s) {
|
||||
//dump('DEBUG DataStoreChangeNotifier: ' + s + '\n');
|
||||
}
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
const kFromDataStoreChangeNotifier = "fromDataStoreChangeNotifier";
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
|
||||
"@mozilla.org/parentprocessmessagemanager;1",
|
||||
"nsIMessageBroadcaster");
|
||||
|
||||
this.DataStoreChangeNotifier = {
|
||||
children: [],
|
||||
messages: [ "DataStore:Changed", "DataStore:RegisterForMessages",
|
||||
"child-process-shutdown" ],
|
||||
|
||||
init: function() {
|
||||
debug("init");
|
||||
|
||||
this.messages.forEach((function(msgName) {
|
||||
ppmm.addMessageListener(msgName, this);
|
||||
}).bind(this));
|
||||
|
||||
Services.obs.addObserver(this, 'xpcom-shutdown', false);
|
||||
},
|
||||
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
debug("observe");
|
||||
|
||||
switch (aTopic) {
|
||||
case 'xpcom-shutdown':
|
||||
this.messages.forEach((function(msgName) {
|
||||
ppmm.removeMessageListener(msgName, this);
|
||||
}).bind(this));
|
||||
|
||||
Services.obs.removeObserver(this, 'xpcom-shutdown');
|
||||
ppmm = null;
|
||||
break;
|
||||
|
||||
default:
|
||||
debug("Wrong observer topic: " + aTopic);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
broadcastMessage: function broadcastMessage(aMsgName, aData) {
|
||||
debug("Broadast");
|
||||
this.children.forEach(function(obj) {
|
||||
if (obj.store == aData.store && obj.owner == aData.owner) {
|
||||
obj.mm.sendAsyncMessage(aMsgName, aData.message);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
receiveMessage: function(aMessage) {
|
||||
debug("receiveMessage");
|
||||
|
||||
switch (aMessage.name) {
|
||||
case "DataStore:Changed":
|
||||
this.broadcastMessage("DataStore:Changed:Return:OK", aMessage.data);
|
||||
break;
|
||||
|
||||
case "DataStore:RegisterForMessages":
|
||||
debug("Register!");
|
||||
|
||||
for (let i = 0; i < this.children.length; ++i) {
|
||||
if (this.children[i].mm == aMessage.target &&
|
||||
this.children[i].store == aMessage.data.store &&
|
||||
this.children[i].owner == aMessage.data.owner) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.children.push({ mm: aMessage.target,
|
||||
store: aMessage.data.store,
|
||||
owner: aMessage.data.owner });
|
||||
break;
|
||||
|
||||
case "child-process-shutdown":
|
||||
debug("Unregister");
|
||||
|
||||
for (let i = 0; i < this.children.length;) {
|
||||
if (this.children[i].mm == aMessage.target) {
|
||||
debug("Unregister index: " + i);
|
||||
this.children.splice(i, 1);
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
debug("Wrong message: " + aMessage.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DataStoreChangeNotifier.init();
|
@ -137,9 +137,9 @@ DataStoreService.prototype = {
|
||||
resolver.resolve(results);
|
||||
}
|
||||
},
|
||||
function() {
|
||||
resolver.reject();
|
||||
}
|
||||
// if the revision is already known, we don't need to retrieve it
|
||||
// again.
|
||||
false
|
||||
);
|
||||
}
|
||||
});
|
||||
|
@ -21,5 +21,6 @@ EXTRA_COMPONENTS += [
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'DataStore.jsm',
|
||||
'DataStoreChangeNotifier.jsm',
|
||||
'DataStoreDB.jsm',
|
||||
]
|
||||
|
@ -20,10 +20,12 @@ MOCHITEST_FILES = \
|
||||
file_basic.html \
|
||||
test_revision.html \
|
||||
file_revision.html \
|
||||
test_changes.html \
|
||||
file_changes.html \
|
||||
file_changes2.html \
|
||||
file_app.sjs \
|
||||
file_app.template.webapp \
|
||||
file_app2.template.webapp \
|
||||
file_app2.template.webapp^headers^ \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
@ -1,5 +1,4 @@
|
||||
var gBasePath = "tests/dom/datastore/tests/";
|
||||
var gAppTemplatePath = "tests/dom/datastore/tests/file_app.template.webapp";
|
||||
|
||||
function handleRequest(request, response) {
|
||||
var query = getQuery(request);
|
||||
@ -9,7 +8,11 @@ function handleRequest(request, response) {
|
||||
testToken = query.testToken;
|
||||
}
|
||||
|
||||
var template = gBasePath + 'file_app.template.webapp';
|
||||
var template = 'file_app.template.webapp';
|
||||
if ('template' in query) {
|
||||
template = query.template;
|
||||
}
|
||||
var template = gBasePath + template;
|
||||
response.setHeader("Content-Type", "application/x-web-app-manifest+json", false);
|
||||
response.write(readTemplate(template).replace(/TESTTOKEN/g, testToken));
|
||||
}
|
||||
|
@ -6,9 +6,5 @@
|
||||
"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" }
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"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",
|
||||
"launch_path": "/tests/dom/datastore/tests/TESTTOKEN",
|
||||
"icons": { "128": "default_icon" },
|
||||
"datastores-access" : {
|
||||
"foo" : { "readonly": false, "description" : "This store is called foo" },
|
||||
|
@ -1 +0,0 @@
|
||||
Content-Type: application/x-web-app-manifest+json
|
133
dom/datastore/tests/file_changes.html
Normal file
133
dom/datastore/tests/file_changes.html
Normal file
@ -0,0 +1,133 @@
|
||||
<!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 gChangeId = null;
|
||||
var gChangeOperation = null;
|
||||
|
||||
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');
|
||||
|
||||
gStore = stores[0];
|
||||
runTest();
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function testStoreAdd(value, expectedId) {
|
||||
gStore.add(value).then(function(id) {
|
||||
is(id, expectedId, "store.add() is called");
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function testStoreUpdate(id, value) {
|
||||
gStore.update(id, value).then(function(retId) {
|
||||
is(id, retId, "store.update() is called with the right id");
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function testStoreRemove(id, expectedSuccess) {
|
||||
gStore.remove(id).then(function(success) {
|
||||
is(success, expectedSuccess, "store.remove() returns the right value");
|
||||
}, cbError);
|
||||
}
|
||||
|
||||
function eventListener(obj) {
|
||||
ok(obj, "OnChangeListener is called with data");
|
||||
is(obj.id, gChangeId, "OnChangeListener is called with the right ID: " + obj.id);
|
||||
is(obj.operation, gChangeOperation, "OnChangeListener is called with the right operation:" + obj.operation + " " + gChangeOperation);
|
||||
runTest();
|
||||
}
|
||||
|
||||
var tests = [
|
||||
// Test for GetDataStore
|
||||
testGetDataStores,
|
||||
|
||||
// Add onchange = function
|
||||
function() {
|
||||
gStore.onchange = eventListener;
|
||||
runTest();
|
||||
},
|
||||
|
||||
// Add
|
||||
function() { gChangeId = 1; gChangeOperation = 'added';
|
||||
testStoreAdd({ number: 42 }, 1); },
|
||||
|
||||
// Update
|
||||
function() { gChangeId = 1; gChangeOperation = 'updated';
|
||||
testStoreUpdate(1, { number: 43 }); },
|
||||
|
||||
// Remove
|
||||
function() { gChangeId = 1; gChangeOperation = 'removed';
|
||||
testStoreRemove(1, true); },
|
||||
|
||||
// Remove onchange function and replace it with addEventListener
|
||||
function() {
|
||||
gStore.onchange = null;
|
||||
gStore.addEventListener('change', eventListener);
|
||||
runTest();
|
||||
},
|
||||
|
||||
// Add
|
||||
function() { gChangeId = 2; gChangeOperation = 'added';
|
||||
testStoreAdd({ number: 42 }, 2); },
|
||||
|
||||
// Update
|
||||
function() { gChangeId = 2; gChangeOperation = 'updated';
|
||||
testStoreUpdate(2, { number: 43 }); },
|
||||
|
||||
// Remove
|
||||
function() { gChangeId = 2; gChangeOperation = 'removed';
|
||||
testStoreRemove(2, true); },
|
||||
|
||||
// Remove event listener
|
||||
function() {
|
||||
gStore.removeEventListener('change', eventListener);
|
||||
runTest();
|
||||
},
|
||||
];
|
||||
|
||||
function runTest() {
|
||||
if (!tests.length) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
var test = tests.shift();
|
||||
test();
|
||||
}
|
||||
|
||||
runTest();
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
46
dom/datastore/tests/file_changes2.html
Normal file
46
dom/datastore/tests/file_changes2.html
Normal file
@ -0,0 +1,46 @@
|
||||
<!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">
|
||||
|
||||
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 eventListener(obj) {
|
||||
ok(obj, "OnChangeListener is called with data");
|
||||
finish();
|
||||
}
|
||||
|
||||
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');
|
||||
|
||||
stores[0].onchange = eventListener;
|
||||
alert('READY');
|
||||
});
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -10,6 +10,8 @@
|
||||
<div id="container"></div>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
SpecialPowers.Cu.import("resource://gre/modules/DataStoreChangeNotifier.jsm");
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var gBaseURL = 'http://test/tests/dom/datastore/tests/';
|
||||
|
@ -10,8 +10,7 @@
|
||||
<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?testToken=file_basic.html';
|
||||
var gHostedManifestURL = 'http://test/tests/dom/datastore/tests/file_app.sjs?testToken=file_basic.html';
|
||||
var gApp;
|
||||
|
||||
function cbError() {
|
||||
@ -114,6 +113,7 @@
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SpecialPowers.Cu.import("resource://gre/modules/DataStoreChangeNotifier.jsm");
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
runTest();
|
||||
</script>
|
||||
|
177
dom/datastore/tests/test_changes.html
Normal file
177
dom/datastore/tests/test_changes.html
Normal file
@ -0,0 +1,177 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for DataStore - basic operation on a readonly db</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
var gHostedManifestURL = 'http://test/tests/dom/datastore/tests/file_app.sjs?testToken=file_changes.html';
|
||||
var gHostedManifestURL2 = 'http://example.com/tests/dom/datastore/tests/file_app.sjs?testToken=file_changes2.html&template=file_app2.template.webapp';
|
||||
var gApps = [];
|
||||
var gApp2Events = 0;
|
||||
var gStore;
|
||||
|
||||
function cbError() {
|
||||
ok(false, "Error callback invoked");
|
||||
finish();
|
||||
}
|
||||
|
||||
function installApp(aApp) {
|
||||
var request = navigator.mozApps.install(aApp);
|
||||
request.onerror = cbError;
|
||||
request.onsuccess = function() {
|
||||
gApps.push(request.result);
|
||||
runTest();
|
||||
}
|
||||
}
|
||||
|
||||
function uninstallApps() {
|
||||
if (!gApps.length) {
|
||||
ok(true, "All done!");
|
||||
runTest();
|
||||
return;
|
||||
}
|
||||
|
||||
var app = gApps.pop();
|
||||
var request = navigator.mozApps.mgmt.uninstall(app);
|
||||
request.onerror = cbError;
|
||||
request.onsuccess = uninstallApps;
|
||||
}
|
||||
|
||||
function setupApp2() {
|
||||
var ifr = document.createElement('iframe');
|
||||
ifr.setAttribute('mozbrowser', 'true');
|
||||
ifr.setAttribute('mozapp', gApps[1].manifestURL);
|
||||
ifr.setAttribute('src', gApps[1].manifest.launch_path);
|
||||
var domParent = document.getElementById('content');
|
||||
|
||||
// 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 (/READY/.exec(message)) {
|
||||
ok(true, "App2 ready");
|
||||
runTest();
|
||||
} else if (/DONE/.exec(message)) {
|
||||
ok(true, "Messaging from app complete");
|
||||
ifr.removeEventListener('mozbrowsershowmodalprompt', listener);
|
||||
domParent.removeChild(ifr);
|
||||
gApp2Events++;
|
||||
}
|
||||
}
|
||||
|
||||
// This event is triggered when the app calls "alert".
|
||||
ifr.addEventListener('mozbrowsershowmodalprompt', listener, false);
|
||||
domParent.appendChild(ifr);
|
||||
}
|
||||
|
||||
function testApp1() {
|
||||
var ifr = document.createElement('iframe');
|
||||
ifr.setAttribute('mozbrowser', 'true');
|
||||
ifr.setAttribute('mozapp', gApps[0].manifestURL);
|
||||
ifr.setAttribute('src', gApps[0].manifest.launch_path);
|
||||
var domParent = document.getElementById('content');
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
function checkApp2() {
|
||||
ok(gApp2Events, "App2 received events");
|
||||
runTest();
|
||||
}
|
||||
|
||||
var tests = [
|
||||
// Permissions
|
||||
function() {
|
||||
SpecialPowers.pushPermissions(
|
||||
[{ "type": "browser", "allow": 1, "context": document },
|
||||
{ "type": "embed-apps", "allow": 1, "context": document },
|
||||
{ "type": "webapps-manage", "allow": 1, "context": document }], runTest);
|
||||
},
|
||||
|
||||
// Preferences
|
||||
function() {
|
||||
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);
|
||||
},
|
||||
|
||||
// Installing the app1
|
||||
function() { installApp(gHostedManifestURL); },
|
||||
|
||||
// Installing the app2
|
||||
function() { installApp(gHostedManifestURL2); },
|
||||
|
||||
// Setup app2 for receving events
|
||||
setupApp2,
|
||||
|
||||
// Run tests in app
|
||||
testApp1,
|
||||
|
||||
// Check app2
|
||||
checkApp2,
|
||||
|
||||
// Uninstall the apps
|
||||
uninstallApps,
|
||||
];
|
||||
|
||||
function runTest() {
|
||||
if (!tests.length) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
var test = tests.shift();
|
||||
test();
|
||||
}
|
||||
|
||||
function finish() {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SpecialPowers.Cu.import("resource://gre/modules/DataStoreChangeNotifier.jsm");
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
runTest();
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
@ -9,9 +9,8 @@
|
||||
<body>
|
||||
<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?testToken=file_readonly.html';
|
||||
var gHostedManifestURL2 = 'http://example.com/tests/dom/datastore/tests/file_app2.template.webapp';
|
||||
var gHostedManifestURL = 'http://test/tests/dom/datastore/tests/file_app.sjs?testToken=file_readonly.html';
|
||||
var gHostedManifestURL2 = 'http://example.com/tests/dom/datastore/tests/file_app.sjs?testToken=file_readonly.html&template=file_app2.template.webapp';
|
||||
var gGenerator = runTest();
|
||||
|
||||
SpecialPowers.pushPermissions(
|
||||
@ -53,7 +52,7 @@
|
||||
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');
|
||||
ifr.setAttribute('src', app2.manifest.launch_path);
|
||||
var domParent = document.getElementById('container');
|
||||
|
||||
// Set us up to listen for messages from the app.
|
||||
@ -95,6 +94,7 @@
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SpecialPowers.Cu.import("resource://gre/modules/DataStoreChangeNotifier.jsm");
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.promise.enabled", true]]}, runTest);
|
||||
</script>
|
||||
|
@ -122,6 +122,7 @@
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SpecialPowers.Cu.import("resource://gre/modules/DataStoreChangeNotifier.jsm");
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
runTest();
|
||||
</script>
|
||||
|
Loading…
Reference in New Issue
Block a user