Bug 1018320 - RequestSync API - patch 5 - mozSetMessageHandlerPromise, r=fabrice

This commit is contained in:
Andrea Marchesini 2015-01-13 09:53:22 +00:00
Родитель f2e48111ed
Коммит d6ae21b741
11 изменённых файлов: 185 добавлений и 12 удалений

Просмотреть файл

@ -1847,6 +1847,33 @@ Navigator::MozHasPendingMessage(const nsAString& aType, ErrorResult& aRv)
return result;
}
void
Navigator::MozSetMessageHandlerPromise(Promise& aPromise,
ErrorResult& aRv)
{
// The WebIDL binding is responsible for the pref check here.
aRv = EnsureMessagesManager();
if (NS_WARN_IF(aRv.Failed())) {
return;
}
bool result = false;
aRv = mMessagesManager->MozIsHandlingMessage(&result);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
if (!result) {
aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
return;
}
aRv = mMessagesManager->MozSetMessageHandlerPromise(&aPromise);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
}
void
Navigator::MozSetMessageHandler(const nsAString& aType,
systemMessageCallback* aCallback,

Просмотреть файл

@ -235,6 +235,8 @@ public:
systemMessageCallback* aCallback,
ErrorResult& aRv);
bool MozHasPendingMessage(const nsAString& aType, ErrorResult& aRv);
void MozSetMessageHandlerPromise(Promise& aPromise, ErrorResult& aRv);
#ifdef MOZ_B2G
already_AddRefed<Promise> GetMobileIdAssertion(const MobileIdOptions& options,
ErrorResult& aRv);

Просмотреть файл

@ -86,7 +86,7 @@ function listener(evt) {
}
function createMedia(type, src, token) {
var tag = getMajorMimeType(test.type);
var tag = getMajorMimeType(type);
var v = document.createElement(tag);
for (var i=0; i<gEventTypes.length; i++) {
v.addEventListener(gEventTypes[i], listener, false);

Просмотреть файл

@ -42,6 +42,10 @@ function SystemMessageManager() {
// Flag to specify if this process has already registered the manifest URL.
this._registerManifestURLReady = false;
// Used to know if the promise has to be accepted or not.
this._isHandling = false;
this._promise = null;
// Flag to determine this process is a parent or child process.
let appInfo = Cc["@mozilla.org/xre/app-info;1"];
this._isParentProcess =
@ -71,6 +75,7 @@ SystemMessageManager.prototype = {
}
aDispatcher.isHandling = true;
this._isHandling = true;
// We get a json blob, but in some cases we want another kind of object
// to be dispatched. To do so, we check if we have a valid contract ID of
@ -94,16 +99,30 @@ SystemMessageManager.prototype = {
.handleMessage(wrapped ? aMessage
: Cu.cloneInto(aMessage, this._window));
// We need to notify the parent one of the system messages has been handled,
// so the parent can release the CPU wake lock it took on our behalf.
cpmm.sendAsyncMessage("SystemMessageManager:HandleMessageDone",
{ type: aType,
manifestURL: this._manifestURL,
pageURL: this._pageURL,
msgID: aMessageID });
this._isHandling = false;
aDispatcher.isHandling = false;
let self = this;
function sendResponse() {
// We need to notify the parent one of the system messages has been
// handled, so the parent can release the CPU wake lock it took on our
// behalf.
cpmm.sendAsyncMessage("SystemMessageManager:HandleMessageDone",
{ type: aType,
manifestURL: self._manifestURL,
pageURL: self._pageURL,
msgID: aMessageID });
}
if (!this._promise) {
debug("No promise set, sending the response immediately.");
sendResponse();
} else {
debug("Using the promise to postpone the response.");
this._promise.then(sendResponse, sendResponse);
this._promise = null;
}
if (aDispatcher.messages.length > 0) {
let msg = aDispatcher.messages.shift();
this._dispatchMessage(aType, aDispatcher, msg.message, msg.messageID);
@ -171,9 +190,29 @@ SystemMessageManager.prototype = {
manifestURL: this._manifestURL })[0];
},
mozIsHandlingMessage: function() {
debug("is handling message: " + this._isHandling);
return this._isHandling;
},
mozSetMessageHandlerPromise: function(aPromise) {
debug("setting a promise");
if (!this._isHandling) {
throw "Not in a handleMessage method";
}
if (this._promise) {
throw "Promise already set";
}
this._promise = aPromise;
},
uninit: function() {
this._dispatchers = null;
this._pendings = null;
this._promise = null;
if (this._isParentProcess) {
Services.obs.removeObserver(this, kSystemMessageInternalReady);

Просмотреть файл

@ -10,10 +10,15 @@ interface nsIDOMSystemMessageCallback : nsISupports
void handleMessage(in jsval message);
};
[scriptable, uuid(091e90dd-0e8b-463d-8cdc-9225d3a6ff90)]
[scriptable, uuid(d04d3c11-26aa-46eb-a981-353af101f9cf)]
interface nsIDOMNavigatorSystemMessages : nsISupports
{
void mozSetMessageHandler(in DOMString type, in nsIDOMSystemMessageCallback callback);
boolean mozHasPendingMessage(in DOMString type);
// the parameter is a promise object.
void mozSetMessageHandlerPromise(in nsISupports promise);
bool mozIsHandlingMessage();
};

Просмотреть файл

@ -587,10 +587,16 @@ this.RequestSyncService = {
timer = null;
}
let timeout = RSYNC_OPERATION_TIMEOUT;
try {
let tmp = Services.prefs.getIntPref("dom.requestSync.maxTaskTimeout");
timeout = tmp;
} catch(e) {}
timer.initWithCallback(function() {
debug("Task is taking too much, let's ignore the promise.");
taskCompleted();
}, RSYNC_OPERATION_TIMEOUT, Ci.nsITimer.TYPE_ONE_SHOT);
}, timeout, Ci.nsITimer.TYPE_ONE_SHOT);
// Sending the message.
let promise =

Просмотреть файл

@ -14,3 +14,4 @@ support-files =
run-if = buildapp != 'b2g'
[test_wakeUp.html]
run-if = buildapp == 'b2g' && toolkit == 'gonk'
[test_promise.html]

Просмотреть файл

@ -72,7 +72,7 @@
SpecialPowers.pushPermissions(
[{ "type": "browser", "allow": 1, "context": document },
{ "type": "embed-apps", "allow": 1, "context": document },
{"type": "requestsync-manager", "allow": 1, "context": document },
{ "type": "requestsync-manager", "allow": 1, "context": document },
{ "type": "webapps-manage", "allow": 1, "context": document }], runTests);
},

Просмотреть файл

@ -0,0 +1,56 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Test for requestSync - promise</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="common_basic.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<div id="container"></div>
<script type="application/javascript;version=1.7">
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["dom.sysmsg.enabled", true]]}, function() {
ok("mozSetMessageHandlerPromise" in navigator, "mozSetMessageHandlerPromise exists");
var status = false;
try {
navigator.mozSetMessageHandlerPromise();
} catch(e) {
status = true;
}
ok(status, "mozSetMessageHandlerPromise wants a promise 1");
status = false;
try {
navigator.mozSetMessageHandlerPromise(42);
} catch(e) {
status = true;
}
ok(status, "mozSetMessageHandlerPromise wants a promise 2");
status = false;
try {
navigator.mozSetMessageHandlerPromise("hello world");
} catch(e) {
status = true;
}
ok(status, "mozSetMessageHandlerPromise wants a promise 3");
status = false;
try {
navigator.mozSetMessageHandlerPromise(new Promise(function(a, b) {}));
} catch(e) {
info(e);
status = true;
}
ok(status, "mozSetMessageHandlerPromise cannot be called outside a messageHandler");
SimpleTest.finish();
});
</script>
</body>
</html>

Просмотреть файл

@ -49,6 +49,17 @@
is(e.wifiOnly, false, "e.wifiOnly is correct");
++multiShotCounter;
if (multiShotCounter == 1) {
info("Setting a promise object.");
navigator.mozSetMessageHandlerPromise(new Promise(function(a, b) {
setTimeout(a, 0);
}));
} else if (multiShotCounter == 2) {
// The second time we don't reply at all.
navigator.mozSetMessageHandlerPromise(new Promise(function(a, b) {}));
}
maybeDone();
}
@ -84,6 +95,22 @@
}, genericError);
}
function test_unregister_oneShot() {
navigator.sync.unregister('oneShot').then(
function() {
ok(true, "navigator.sync.unregister() oneShot done");
runTests();
}, genericError);
}
function test_unregister_multiShots() {
navigator.sync.unregister('multiShots').then(
function() {
ok(true, "navigator.sync.unregister() multiShots done");
runTests();
}, genericError);
}
function test_wait() {
// nothing to do here.
}
@ -92,6 +119,7 @@
function() {
SpecialPowers.pushPrefEnv({"set": [["dom.requestSync.enabled", true],
["dom.requestSync.minInterval", 1],
["dom.requestSync.maxTaskTimeout", 10000 /* 10 seconds */],
["dom.ignore_webidl_scope_checks", true]]}, runTests);
},
@ -113,6 +141,9 @@
test_register_multiShots,
test_wait,
test_unregister_oneShot,
test_unregister_multiShots,
];
function runTests() {

Просмотреть файл

@ -285,6 +285,12 @@ partial interface Navigator {
void mozSetMessageHandler (DOMString type, systemMessageCallback? callback);
[Throws, Pref="dom.sysmsg.enabled"]
boolean mozHasPendingMessage (DOMString type);
// This method can be called only from the systeMessageCallback function and
// it allows the page to set a promise to keep alive the app until the
// current operation is not fully completed.
[Throws, Pref="dom.sysmsg.enabled"]
void mozSetMessageHandlerPromise (Promise<any> promise);
};
#ifdef MOZ_B2G_RIL