Bug 1503070 part 12. Stop using DOMRequest in BrowserElement getCanGoForward/Back APIs. r=ehsan

This commit is contained in:
Boris Zbarsky 2018-11-01 17:37:48 -04:00
parent 322b213beb
commit aede00dddf
6 changed files with 60 additions and 57 deletions

View File

@ -49,18 +49,18 @@ function defineNoReturnMethod(fn) {
};
}
function defineDOMRequestMethod(msgName) {
function definePromiseMethod(msgName) {
return function() {
return this._sendDOMRequest(msgName);
return this._sendAsyncRequest(msgName);
};
}
function BrowserElementParent() {
debug("Creating new BrowserElementParent object");
this._domRequestCounter = 0;
this._promiseCounter = 0;
this._domRequestReady = false;
this._pendingAPICalls = [];
this._pendingDOMRequests = {};
this._pendingPromises = {};
this._pendingDOMFullscreen = false;
Services.obs.addObserver(this, 'oop-frameloader-crashed', /* ownsWeak = */ true);
@ -156,8 +156,8 @@ BrowserElementParent.prototype = {
"error": this._fireEventFromMsg,
"firstpaint": this._fireProfiledEventFromMsg,
"documentfirstpaint": this._fireProfiledEventFromMsg,
"got-can-go-back": this._gotDOMRequestResult,
"got-can-go-forward": this._gotDOMRequestResult,
"got-can-go-back": this._gotAsyncResult,
"got-can-go-forward": this._gotAsyncResult,
"requested-dom-fullscreen": this._requestedDOMFullscreen,
"fullscreen-origin-change": this._fullscreenOriginChange,
"exit-dom-fullscreen": this._exitDomFullscreen,
@ -441,29 +441,33 @@ BrowserElementParent.prototype = {
},
/**
* Kick off a DOMRequest in the child process.
* Kick off an async operation in the child process.
*
* We'll fire an event called |msgName| on the child process, passing along
* We'll send a message called |msgName| to the child process, passing along
* an object with two fields:
*
* - id: the ID of this request.
* - arg: arguments to pass to the child along with this request.
* - id: the ID of this async call.
* - arg: arguments to pass to the child along with this async call.
*
* We expect the child to pass the ID back to us upon completion of the
* request. See _gotDOMRequestResult.
* call. See _gotAsyncResult.
*/
_sendDOMRequest: function(msgName, args) {
let id = 'req_' + this._domRequestCounter++;
let req = Services.DOMRequest.createRequest(this._window);
_sendAsyncRequest: function(msgName, args) {
let id = 'req_' + this._promiseCounter++;
let resolve, reject;
let p = new this._window.Promise((res, rej) => {
resolve = res;
reject = rej;
});
let self = this;
let send = function() {
if (!self._isAlive()) {
return;
}
if (self._sendAsyncMsg(msgName, {id: id, args: args})) {
self._pendingDOMRequests[id] = req;
self._pendingPromises[id] = { p, resolve, reject };
} else {
Services.DOMRequest.fireErrorAsync(req, "fail");
reject(new this._window.DOMException("fail"));
}
};
if (this._domRequestReady) {
@ -472,35 +476,35 @@ BrowserElementParent.prototype = {
// Child haven't been loaded.
this._pendingAPICalls.push(send);
}
return req;
return p;
},
/**
* Called when the child process finishes handling a DOMRequest. data.json
* must have the fields [id, successRv], if the DOMRequest was successful, or
* [id, errorMsg], if the request was not successful.
* Called when the child process finishes handling an async call. data.json
* must have the fields [id, successRv], if the async call was successful, or
* [id, errorMsg], if the call was not successful.
*
* The fields have the following meanings:
*
* - id: the ID of the DOM request (see _sendDOMRequest)
* - successRv: the request's return value, if the request succeeded
* - errorMsg: the message to pass to DOMRequest.fireError(), if the request
* failed.
* - id: the ID of the async call (see _sendAsyncRequest)
* - successRv: the call's return value, if the call succeeded
* - errorMsg: the message to pass to the Promise reject callback, if the
* call failed.
*
*/
_gotDOMRequestResult: function(data) {
let req = this._pendingDOMRequests[data.json.id];
delete this._pendingDOMRequests[data.json.id];
_gotAsyncResult: function(data) {
let p = this._pendingPromises[data.json.id];
delete this._pendingPromises[data.json.id];
if ('successRv' in data.json) {
debug("Successful gotDOMRequestResult.");
debug("Successful gotAsyncResult.");
let clientObj = Cu.cloneInto(data.json.successRv, this._window);
Services.DOMRequest.fireSuccess(req, clientObj);
p.resolve(clientObj);
}
else {
debug("Got error in gotDOMRequestResult.");
Services.DOMRequest.fireErrorAsync(req,
Cu.cloneInto(data.json.errorMsg, this._window));
debug("Got error in gotAsyncResult.");
p.reject(new this._window.DOMException(
Cu.cloneInto(data.json.errorMsg, this._window)));
}
},
@ -532,8 +536,8 @@ BrowserElementParent.prototype = {
});
}),
getCanGoBack: defineDOMRequestMethod('get-can-go-back'),
getCanGoForward: defineDOMRequestMethod('get-can-go-forward'),
getCanGoBack: definePromiseMethod('get-can-go-back'),
getCanGoForward: definePromiseMethod('get-can-go-forward'),
goBack: defineNoReturnMethod(function() {
this._sendAsyncMsg('go-back');

View File

@ -32,20 +32,20 @@ function runTest() {
function checkCanGoBackAndForward(canGoBack, canGoForward, nextTest) {
var seenCanGoBackResult = false;
iframe.getCanGoBack().onsuccess = function(e) {
iframe.getCanGoBack().then(function(result) {
is(seenCanGoBackResult, false, "onsuccess handler shouldn't be called twice.");
seenCanGoBackResult = true;
is(e.target.result, canGoBack);
is(result, canGoBack);
maybeRunNextTest();
};
});
var seenCanGoForwardResult = false;
iframe.getCanGoForward().onsuccess = function(e) {
iframe.getCanGoForward().then(function(result) {
is(seenCanGoForwardResult, false, "onsuccess handler shouldn't be called twice.");
seenCanGoForwardResult = true;
is(e.target.result, canGoForward);
is(result, canGoForward);
maybeRunNextTest();
};
});
function maybeRunNextTest() {
if (seenCanGoBackResult && seenCanGoForwardResult) {

View File

@ -6,7 +6,6 @@
#include "nsISupports.idl"
webidl DOMRequest;
webidl FrameLoader;
%{C++
@ -40,6 +39,6 @@ interface nsIBrowserElementAPI : nsISupports
void goForward();
void reload(in boolean hardReload);
void stop();
DOMRequest getCanGoBack();
DOMRequest getCanGoForward();
Promise getCanGoBack();
Promise getCanGoForward();
};

View File

@ -9,7 +9,7 @@
#include "mozilla/Preferences.h"
#include "mozilla/Services.h"
#include "mozilla/dom/BrowserElementBinding.h"
#include "mozilla/dom/DOMRequest.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/ToJSValue.h"
@ -134,36 +134,36 @@ nsBrowserElement::Stop(ErrorResult& aRv)
}
}
already_AddRefed<DOMRequest>
already_AddRefed<Promise>
nsBrowserElement::GetCanGoBack(ErrorResult& aRv)
{
NS_ENSURE_TRUE(IsBrowserElementOrThrow(aRv), nullptr);
RefPtr<DOMRequest> req;
nsresult rv = mBrowserElementAPI->GetCanGoBack(getter_AddRefs(req));
RefPtr<Promise> p;
nsresult rv = mBrowserElementAPI->GetCanGoBack(getter_AddRefs(p));
if (NS_WARN_IF(NS_FAILED(rv))) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return nullptr;
}
return req.forget();
return p.forget();
}
already_AddRefed<DOMRequest>
already_AddRefed<Promise>
nsBrowserElement::GetCanGoForward(ErrorResult& aRv)
{
NS_ENSURE_TRUE(IsBrowserElementOrThrow(aRv), nullptr);
RefPtr<DOMRequest> req;
nsresult rv = mBrowserElementAPI->GetCanGoForward(getter_AddRefs(req));
RefPtr<Promise> p;
nsresult rv = mBrowserElementAPI->GetCanGoForward(getter_AddRefs(p));
if (NS_WARN_IF(NS_FAILED(rv))) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return nullptr;
}
return req.forget();
return p.forget();
}
} // namespace mozilla

View File

@ -17,7 +17,7 @@ class nsFrameLoader;
namespace mozilla {
namespace dom {
class DOMRequest;
class Promise;
} // namespace dom
class ErrorResult;
@ -43,8 +43,8 @@ public:
void Reload(bool aHardReload, ErrorResult& aRv);
void Stop(ErrorResult& aRv);
already_AddRefed<dom::DOMRequest> GetCanGoBack(ErrorResult& aRv);
already_AddRefed<dom::DOMRequest> GetCanGoForward(ErrorResult& aRv);
already_AddRefed<dom::Promise> GetCanGoBack(ErrorResult& aRv);
already_AddRefed<dom::Promise> GetCanGoForward(ErrorResult& aRv);
protected:
NS_IMETHOD_(already_AddRefed<nsFrameLoader>) GetFrameLoader() = 0;

View File

@ -45,10 +45,10 @@ interface BrowserElementPrivileged {
[Throws,
Pref="dom.mozBrowserFramesEnabled",
ChromeOnly]
DOMRequest getCanGoBack();
Promise<boolean> getCanGoBack();
[Throws,
Pref="dom.mozBrowserFramesEnabled",
ChromeOnly]
DOMRequest getCanGoForward();
Promise<boolean> getCanGoForward();
};