зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to mozilla-autoland. r=merge a=merge
--HG-- extra : rebase_source : b704804c0529b605cda321eb65c867121107ce21
This commit is contained in:
Коммит
1880c5e16b
|
@ -45,7 +45,7 @@ skip-if = buildapp == "mulet"
|
|||
[test_select.html]
|
||||
[test_tabbox.xul]
|
||||
[test_tabbrowser.xul]
|
||||
skip-if = os == 'linux' && debug # Bug 1389365
|
||||
skip-if = (os == 'linux' && debug) || (os == 'win' && ccov) # Bug 1389365 || bug 1423218
|
||||
[test_table.html]
|
||||
[test_tree.xul]
|
||||
[test_txtcntr.html]
|
||||
|
|
|
@ -13,6 +13,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1378010
|
|||
Components.utils.import("resource://gre/modules/Subprocess.jsm");
|
||||
Components.utils.import("resource://gre/modules/osfile.jsm");
|
||||
|
||||
SimpleTest.requestLongerTimeout(2);
|
||||
|
||||
const screenshotPath = OS.Path.join(OS.Constants.Path.tmpDir, "headless_test_screenshot.png");
|
||||
|
||||
async function runFirefox(args) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
This is the PDF.js project output, https://github.com/mozilla/pdf.js
|
||||
|
||||
Current extension version is: 2.0.173
|
||||
Current extension version is: 2.0.185
|
||||
|
||||
Taken from upstream commit: fffd5cb8
|
||||
Taken from upstream commit: f2994736
|
||||
|
|
|
@ -1960,7 +1960,7 @@ function _fetchDocument(worker, source, pdfDataRangeTransport, docId) {
|
|||
if (worker.destroyed) {
|
||||
return Promise.reject(new Error('Worker was destroyed'));
|
||||
}
|
||||
let apiVersion = '2.0.173';
|
||||
let apiVersion = '2.0.185';
|
||||
source.disableRange = (0, _dom_utils.getDefaultSetting)('disableRange');
|
||||
source.disableAutoFetch = (0, _dom_utils.getDefaultSetting)('disableAutoFetch');
|
||||
source.disableStream = (0, _dom_utils.getDefaultSetting)('disableStream');
|
||||
|
@ -3253,8 +3253,8 @@ var InternalRenderTask = function InternalRenderTaskClosure() {
|
|||
}();
|
||||
var version, build;
|
||||
{
|
||||
exports.version = version = '2.0.173';
|
||||
exports.build = build = 'fffd5cb8';
|
||||
exports.version = version = '2.0.185';
|
||||
exports.build = build = 'f2994736';
|
||||
}
|
||||
exports.getDocument = getDocument;
|
||||
exports.LoopbackPort = LoopbackPort;
|
||||
|
@ -4627,8 +4627,8 @@ exports.SVGGraphics = SVGGraphics;
|
|||
"use strict";
|
||||
|
||||
|
||||
var pdfjsVersion = '2.0.173';
|
||||
var pdfjsBuild = 'fffd5cb8';
|
||||
var pdfjsVersion = '2.0.185';
|
||||
var pdfjsBuild = 'f2994736';
|
||||
var pdfjsSharedUtil = __w_pdfjs_require__(0);
|
||||
var pdfjsDisplayGlobal = __w_pdfjs_require__(12);
|
||||
var pdfjsDisplayAPI = __w_pdfjs_require__(3);
|
||||
|
@ -7752,8 +7752,8 @@ if (!_global_scope2.default.PDFJS) {
|
|||
}
|
||||
var PDFJS = _global_scope2.default.PDFJS;
|
||||
{
|
||||
PDFJS.version = '2.0.173';
|
||||
PDFJS.build = 'fffd5cb8';
|
||||
PDFJS.version = '2.0.185';
|
||||
PDFJS.build = 'f2994736';
|
||||
}
|
||||
PDFJS.pdfBug = false;
|
||||
if (PDFJS.verbosity !== undefined) {
|
||||
|
|
|
@ -20728,8 +20728,8 @@ exports.PostScriptCompiler = PostScriptCompiler;
|
|||
"use strict";
|
||||
|
||||
|
||||
var pdfjsVersion = '2.0.173';
|
||||
var pdfjsBuild = 'fffd5cb8';
|
||||
var pdfjsVersion = '2.0.185';
|
||||
var pdfjsBuild = 'f2994736';
|
||||
var pdfjsCoreWorker = __w_pdfjs_require__(19);
|
||||
exports.WorkerMessageHandler = pdfjsCoreWorker.WorkerMessageHandler;
|
||||
|
||||
|
@ -20924,7 +20924,7 @@ var WorkerMessageHandler = {
|
|||
var cancelXHRs = null;
|
||||
var WorkerTasks = [];
|
||||
let apiVersion = docParams.apiVersion;
|
||||
let workerVersion = '2.0.173';
|
||||
let workerVersion = '2.0.185';
|
||||
if (apiVersion !== null && apiVersion !== workerVersion) {
|
||||
throw new Error(`The API version "${apiVersion}" does not match ` + `the Worker version "${workerVersion}".`);
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@ var _pdfjsLib = __webpack_require__(1);
|
|||
const CSS_UNITS = 96.0 / 72.0;
|
||||
const DEFAULT_SCALE_VALUE = 'auto';
|
||||
const DEFAULT_SCALE = 1.0;
|
||||
const MIN_SCALE = 0.25;
|
||||
const MIN_SCALE = 0.10;
|
||||
const MAX_SCALE = 10.0;
|
||||
const UNKNOWN_SCALE = 0;
|
||||
const MAX_AUTO_SCALE = 1.25;
|
||||
|
@ -5299,6 +5299,9 @@ class PDFSidebarResizer {
|
|||
_boundEvents.mouseMove = this._mouseMove.bind(this);
|
||||
_boundEvents.mouseUp = this._mouseUp.bind(this);
|
||||
this.resizer.addEventListener('mousedown', evt => {
|
||||
if (evt.button !== 0) {
|
||||
return;
|
||||
}
|
||||
this.outerContainer.classList.add(SIDEBAR_RESIZING_CLASS);
|
||||
window.addEventListener('mousemove', _boundEvents.mouseMove);
|
||||
window.addEventListener('mouseup', _boundEvents.mouseUp);
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -55,6 +55,7 @@ mozilla.pth:third_party/python/mock-1.0.0
|
|||
mozilla.pth:xpcom/typelib/xpt/tools
|
||||
mozilla.pth:tools/docs
|
||||
mozilla.pth:media/webrtc/trunk/tools/gyp/pylib
|
||||
mozilla.pth:third_party/python/cbor2
|
||||
mozilla.pth:third_party/python/pyasn1
|
||||
mozilla.pth:third_party/python/pyasn1-modules
|
||||
mozilla.pth:third_party/python/rsa
|
||||
|
|
|
@ -3442,11 +3442,40 @@ nsDocShell::MaybeCreateInitialClientSource(nsIPrincipal* aPrincipal)
|
|||
ClientManager::CreateSource(ClientType::Window,
|
||||
win->EventTargetFor(TaskCategory::Other),
|
||||
principal);
|
||||
if (NS_WARN_IF(!mInitialClientSource)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Mark the initial client as execution ready, but owned by the docshell.
|
||||
// If the client is actually used this will cause ClientSource to force
|
||||
// the creation of the initial about:blank by calling nsDocShell::GetDocument().
|
||||
mInitialClientSource->DocShellExecutionReady(this);
|
||||
|
||||
// Next, check to see if the parent is controlled.
|
||||
nsCOMPtr<nsIDocShell> parent = GetParentDocshell();
|
||||
nsPIDOMWindowOuter* parentOuter = parent ? parent->GetWindow() : nullptr;
|
||||
nsPIDOMWindowInner* parentInner =
|
||||
parentOuter ? parentOuter->GetCurrentInnerWindow() : nullptr;
|
||||
if (!parentInner) {
|
||||
return;
|
||||
}
|
||||
|
||||
Maybe<ServiceWorkerDescriptor> controller(parentInner->GetController());
|
||||
if (controller.isNothing()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the parent is controlled then propagate that controller to the
|
||||
// initial about:blank client as well. This will set the controller
|
||||
// in the ClientManagerService in the parent.
|
||||
RefPtr<ClientHandle> handle =
|
||||
ClientManager::CreateHandle(mInitialClientSource->Info(),
|
||||
parentInner->EventTargetFor(TaskCategory::Other));
|
||||
handle->Control(controller.ref());
|
||||
|
||||
// Also mark the ClientSource as controlled directly in case script
|
||||
// immediately accesses navigator.serviceWorker.controller.
|
||||
mInitialClientSource->SetController(controller.ref());
|
||||
}
|
||||
|
||||
Maybe<ClientInfo>
|
||||
|
|
|
@ -87,10 +87,7 @@ public:
|
|||
|
||||
// XPCOM GetName() is OK
|
||||
|
||||
void GetValue(nsString& val, nsIPrincipal&)
|
||||
{
|
||||
GetValue(val);
|
||||
}
|
||||
// XPCOM GetValue() is OK
|
||||
|
||||
void SetValue(const nsAString& aValue, nsIPrincipal* aTriggeringPrincipal, ErrorResult& aRv);
|
||||
|
||||
|
|
|
@ -1121,8 +1121,8 @@ public:
|
|||
already_AddRefed<Attr> SetAttributeNodeNS(Attr& aNewAttr,
|
||||
ErrorResult& aError);
|
||||
|
||||
already_AddRefed<DOMRectList> GetClientRects();
|
||||
already_AddRefed<DOMRect> GetBoundingClientRect();
|
||||
MOZ_CAN_RUN_SCRIPT already_AddRefed<DOMRectList> GetClientRects();
|
||||
MOZ_CAN_RUN_SCRIPT already_AddRefed<DOMRect> GetBoundingClientRect();
|
||||
|
||||
// Shadow DOM v1
|
||||
already_AddRefed<ShadowRoot> AttachShadow(const ShadowRootInit& aInit,
|
||||
|
@ -1145,60 +1145,60 @@ private:
|
|||
void ScrollIntoView(const ScrollIntoViewOptions &aOptions);
|
||||
public:
|
||||
void ScrollIntoView(const BooleanOrScrollIntoViewOptions& aObject);
|
||||
void Scroll(double aXScroll, double aYScroll);
|
||||
void Scroll(const ScrollToOptions& aOptions);
|
||||
void ScrollTo(double aXScroll, double aYScroll);
|
||||
void ScrollTo(const ScrollToOptions& aOptions);
|
||||
void ScrollBy(double aXScrollDif, double aYScrollDif);
|
||||
void ScrollBy(const ScrollToOptions& aOptions);
|
||||
MOZ_CAN_RUN_SCRIPT void Scroll(double aXScroll, double aYScroll);
|
||||
MOZ_CAN_RUN_SCRIPT void Scroll(const ScrollToOptions& aOptions);
|
||||
MOZ_CAN_RUN_SCRIPT void ScrollTo(double aXScroll, double aYScroll);
|
||||
MOZ_CAN_RUN_SCRIPT void ScrollTo(const ScrollToOptions& aOptions);
|
||||
MOZ_CAN_RUN_SCRIPT void ScrollBy(double aXScrollDif, double aYScrollDif);
|
||||
MOZ_CAN_RUN_SCRIPT void ScrollBy(const ScrollToOptions& aOptions);
|
||||
/* Scrolls without flushing the layout.
|
||||
* aDx is the x offset, aDy the y offset in CSS pixels.
|
||||
* Returns true if we actually scrolled.
|
||||
*/
|
||||
bool ScrollByNoFlush(int32_t aDx, int32_t aDy);
|
||||
int32_t ScrollTop();
|
||||
void SetScrollTop(int32_t aScrollTop);
|
||||
int32_t ScrollLeft();
|
||||
void SetScrollLeft(int32_t aScrollLeft);
|
||||
int32_t ScrollWidth();
|
||||
int32_t ScrollHeight();
|
||||
void MozScrollSnap();
|
||||
int32_t ClientTop()
|
||||
MOZ_CAN_RUN_SCRIPT bool ScrollByNoFlush(int32_t aDx, int32_t aDy);
|
||||
MOZ_CAN_RUN_SCRIPT int32_t ScrollTop();
|
||||
MOZ_CAN_RUN_SCRIPT void SetScrollTop(int32_t aScrollTop);
|
||||
MOZ_CAN_RUN_SCRIPT int32_t ScrollLeft();
|
||||
MOZ_CAN_RUN_SCRIPT void SetScrollLeft(int32_t aScrollLeft);
|
||||
MOZ_CAN_RUN_SCRIPT int32_t ScrollWidth();
|
||||
MOZ_CAN_RUN_SCRIPT int32_t ScrollHeight();
|
||||
MOZ_CAN_RUN_SCRIPT void MozScrollSnap();
|
||||
MOZ_CAN_RUN_SCRIPT int32_t ClientTop()
|
||||
{
|
||||
return nsPresContext::AppUnitsToIntCSSPixels(GetClientAreaRect().y);
|
||||
}
|
||||
int32_t ClientLeft()
|
||||
MOZ_CAN_RUN_SCRIPT int32_t ClientLeft()
|
||||
{
|
||||
return nsPresContext::AppUnitsToIntCSSPixels(GetClientAreaRect().x);
|
||||
}
|
||||
int32_t ClientWidth()
|
||||
MOZ_CAN_RUN_SCRIPT int32_t ClientWidth()
|
||||
{
|
||||
return nsPresContext::AppUnitsToIntCSSPixels(GetClientAreaRect().Width());
|
||||
}
|
||||
int32_t ClientHeight()
|
||||
MOZ_CAN_RUN_SCRIPT int32_t ClientHeight()
|
||||
{
|
||||
return nsPresContext::AppUnitsToIntCSSPixels(GetClientAreaRect().Height());
|
||||
}
|
||||
int32_t ScrollTopMin()
|
||||
MOZ_CAN_RUN_SCRIPT int32_t ScrollTopMin()
|
||||
{
|
||||
nsIScrollableFrame* sf = GetScrollFrame();
|
||||
return sf ?
|
||||
nsPresContext::AppUnitsToIntCSSPixels(sf->GetScrollRange().y) : 0;
|
||||
}
|
||||
int32_t ScrollTopMax()
|
||||
MOZ_CAN_RUN_SCRIPT int32_t ScrollTopMax()
|
||||
{
|
||||
nsIScrollableFrame* sf = GetScrollFrame();
|
||||
return sf ?
|
||||
nsPresContext::AppUnitsToIntCSSPixels(sf->GetScrollRange().YMost()) :
|
||||
0;
|
||||
}
|
||||
int32_t ScrollLeftMin()
|
||||
MOZ_CAN_RUN_SCRIPT int32_t ScrollLeftMin()
|
||||
{
|
||||
nsIScrollableFrame* sf = GetScrollFrame();
|
||||
return sf ?
|
||||
nsPresContext::AppUnitsToIntCSSPixels(sf->GetScrollRange().x) : 0;
|
||||
}
|
||||
int32_t ScrollLeftMax()
|
||||
MOZ_CAN_RUN_SCRIPT int32_t ScrollLeftMax()
|
||||
{
|
||||
nsIScrollableFrame* sf = GetScrollFrame();
|
||||
return sf ?
|
||||
|
@ -1237,10 +1237,6 @@ public:
|
|||
nsTArray<RefPtr<Animation>>& aAnimations);
|
||||
|
||||
NS_IMETHOD GetInnerHTML(nsAString& aInnerHTML);
|
||||
void GetInnerHTML(nsAString& aInnerHTML, nsIPrincipal& aSubjectPrincipal)
|
||||
{
|
||||
GetInnerHTML(aInnerHTML);
|
||||
}
|
||||
virtual void SetInnerHTML(const nsAString& aInnerHTML, nsIPrincipal& aSubjectPrincipal, ErrorResult& aError);
|
||||
void GetOuterHTML(nsAString& aOuterHTML);
|
||||
void SetOuterHTML(const nsAString& aOuterHTML, ErrorResult& aError);
|
||||
|
@ -1589,6 +1585,7 @@ protected:
|
|||
* @param aScroll Destination of scroll, in CSS pixels
|
||||
* @param aOptions Dictionary of options to be evaluated
|
||||
*/
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
void Scroll(const CSSIntPoint& aScroll, const ScrollOptions& aOptions);
|
||||
|
||||
/**
|
||||
|
@ -1829,8 +1826,9 @@ private:
|
|||
* Get this element's client area rect in app units.
|
||||
* @return the frame's client area
|
||||
*/
|
||||
nsRect GetClientAreaRect();
|
||||
MOZ_CAN_RUN_SCRIPT nsRect GetClientAreaRect();
|
||||
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
nsIScrollableFrame* GetScrollFrame(nsIFrame **aStyledFrame = nullptr,
|
||||
FlushType aFlushType = FlushType::Layout);
|
||||
|
||||
|
|
|
@ -440,7 +440,6 @@ Location::GetHref(nsAString& aHref)
|
|||
|
||||
void
|
||||
Location::SetHref(const nsAString& aHref,
|
||||
nsIPrincipal& aSubjectPrincipal,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
JSContext *cx = nsContentUtils::GetCurrentJSContext();
|
||||
|
|
|
@ -69,7 +69,6 @@ public:
|
|||
}
|
||||
|
||||
void SetHref(const nsAString& aHref,
|
||||
nsIPrincipal& aSubjectPrincipal,
|
||||
ErrorResult& aError);
|
||||
|
||||
void GetOrigin(nsAString& aOrigin,
|
||||
|
|
|
@ -49,7 +49,6 @@
|
|||
#include "mozilla/dom/workers/RuntimeService.h"
|
||||
#include "mozilla/Hal.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "mozilla/SSE.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "Connection.h"
|
||||
#include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent()
|
||||
|
@ -722,12 +721,6 @@ Navigator::HardwareConcurrency()
|
|||
return rts->ClampedHardwareConcurrency();
|
||||
}
|
||||
|
||||
bool
|
||||
Navigator::CpuHasSSE2()
|
||||
{
|
||||
return mozilla::supports_sse2();
|
||||
}
|
||||
|
||||
void
|
||||
Navigator::RefreshMIMEArray()
|
||||
{
|
||||
|
|
|
@ -171,7 +171,6 @@ public:
|
|||
ErrorResult& aRv) const;
|
||||
bool JavaEnabled(CallerType aCallerType, ErrorResult& aRv);
|
||||
uint64_t HardwareConcurrency();
|
||||
bool CpuHasSSE2();
|
||||
bool TaintEnabled()
|
||||
{
|
||||
return false;
|
||||
|
|
|
@ -1790,6 +1790,13 @@ nsGlobalWindowInner::EnsureClientSource()
|
|||
// the client in the docshell. This mainly occurs in situations where
|
||||
// the principal is not clearly inherited from the parent; e.g. sandboxed
|
||||
// iframes, window.open(), etc.
|
||||
// TODO: We may not be marking initial about:blank documents created
|
||||
// this way as controlled by a service worker properly. The
|
||||
// controller should be coming from the same place as the inheritted
|
||||
// principal. We do this in docshell, but as mentioned we aren't
|
||||
// smart enough to handle all cases yet. For example, a
|
||||
// window.open() with new URL should inherit the controller from
|
||||
// the opener, but we probably don't handle that yet.
|
||||
if (!mClientSource) {
|
||||
mClientSource = ClientManager::CreateSource(ClientType::Window,
|
||||
EventTargetFor(TaskCategory::Other),
|
||||
|
@ -1800,6 +1807,39 @@ nsGlobalWindowInner::EnsureClientSource()
|
|||
newClientSource = true;
|
||||
}
|
||||
|
||||
// The load may have started controlling the Client as well. If
|
||||
// so, mark it as controlled immediately here. The actor may
|
||||
// or may not have been notified by the parent side about being
|
||||
// controlled yet.
|
||||
if (loadInfo) {
|
||||
const Maybe<ServiceWorkerDescriptor> controller = loadInfo->GetController();
|
||||
if (controller.isSome()) {
|
||||
mClientSource->SetController(controller.ref());
|
||||
}
|
||||
|
||||
// We also have to handle the case where te initial about:blank is
|
||||
// controlled due to inheritting the service worker from its parent,
|
||||
// but the actual nsIChannel load is not covered by any service worker.
|
||||
// In this case we want the final page to be uncontrolled. There is
|
||||
// an open spec issue about how exactly this should be handled, but for
|
||||
// now we just force creation of a new ClientSource to clear the
|
||||
// controller.
|
||||
//
|
||||
// https://github.com/w3c/ServiceWorker/issues/1232
|
||||
//
|
||||
else if (mClientSource->GetController().isSome()) {
|
||||
mClientSource.reset();
|
||||
mClientSource =
|
||||
ClientManager::CreateSource(ClientType::Window,
|
||||
EventTargetFor(TaskCategory::Other),
|
||||
mDoc->NodePrincipal());
|
||||
if (NS_WARN_IF(!mClientSource)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
newClientSource = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Its possible that we got a client just after being frozen in
|
||||
// the bfcache. In that case freeze the client immediately.
|
||||
if (newClientSource && IsFrozen()) {
|
||||
|
@ -2282,6 +2322,12 @@ nsPIDOMWindowInner::GetClientInfo() const
|
|||
return Move(nsGlobalWindowInner::Cast(this)->GetClientInfo());
|
||||
}
|
||||
|
||||
Maybe<ServiceWorkerDescriptor>
|
||||
nsPIDOMWindowInner::GetController() const
|
||||
{
|
||||
return Move(nsGlobalWindowInner::Cast(this)->GetController());
|
||||
}
|
||||
|
||||
void
|
||||
nsGlobalWindowInner::UpdateTopInnerWindow()
|
||||
{
|
||||
|
@ -6118,6 +6164,17 @@ nsGlobalWindowInner::GetClientInfo() const
|
|||
return Move(clientInfo);
|
||||
}
|
||||
|
||||
Maybe<ServiceWorkerDescriptor>
|
||||
nsGlobalWindowInner::GetController() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
Maybe<ServiceWorkerDescriptor> controller;
|
||||
if (mClientSource) {
|
||||
controller = mClientSource->GetController();
|
||||
}
|
||||
return Move(controller);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGlobalWindowInner::FireDelayedDOMEvents()
|
||||
{
|
||||
|
|
|
@ -349,6 +349,7 @@ public:
|
|||
void SyncStateFromParentWindow();
|
||||
|
||||
mozilla::Maybe<mozilla::dom::ClientInfo> GetClientInfo() const;
|
||||
mozilla::Maybe<mozilla::dom::ServiceWorkerDescriptor> GetController() const;
|
||||
|
||||
virtual nsresult FireDelayedDOMEvents() override;
|
||||
|
||||
|
|
|
@ -1340,12 +1340,6 @@ public:
|
|||
// way to ask an element whether it's an HTMLContentElement.
|
||||
virtual bool IsHTMLContentElement() const { return false; }
|
||||
|
||||
void GetTextContent(nsAString& aTextContent,
|
||||
nsIPrincipal& aSubjectPrincipal,
|
||||
mozilla::OOMReporter& aError)
|
||||
{
|
||||
GetTextContentInternal(aTextContent, aError);
|
||||
}
|
||||
void GetTextContent(nsAString& aTextContent,
|
||||
mozilla::OOMReporter& aError)
|
||||
{
|
||||
|
|
|
@ -51,6 +51,7 @@ class DocGroup;
|
|||
class TabGroup;
|
||||
class Element;
|
||||
class Performance;
|
||||
class ServiceWorkerDescriptor;
|
||||
class ServiceWorkerRegistration;
|
||||
class Timeout;
|
||||
class TimeoutManager;
|
||||
|
@ -326,6 +327,7 @@ public:
|
|||
bool HasOpenWebSockets() const;
|
||||
|
||||
mozilla::Maybe<mozilla::dom::ClientInfo> GetClientInfo() const;
|
||||
mozilla::Maybe<mozilla::dom::ServiceWorkerDescriptor> GetController() const;
|
||||
|
||||
mozilla::dom::TabGroup* TabGroup();
|
||||
|
||||
|
|
|
@ -7293,9 +7293,6 @@ class CGCallGenerator(CGThing):
|
|||
A class to generate an actual call to a C++ object. Assumes that the C++
|
||||
object is stored in a variable whose name is given by the |object| argument.
|
||||
|
||||
needsSubjectPrincipal is a boolean indicating whether the call should
|
||||
receive the subject nsIPrincipal as argument.
|
||||
|
||||
needsCallerType is a boolean indicating whether the call should receive
|
||||
a PrincipalType for the caller.
|
||||
|
||||
|
@ -7306,8 +7303,7 @@ class CGCallGenerator(CGThing):
|
|||
declaring the result variable. If the caller doesn't care about the result
|
||||
value, resultVar can be omitted.
|
||||
"""
|
||||
def __init__(self, isFallible, needsSubjectPrincipal, needsCallerType,
|
||||
isChromeOnly,
|
||||
def __init__(self, isFallible, needsCallerType, isChromeOnly,
|
||||
arguments, argsPre, returnType, extendedAttributes, descriptor,
|
||||
nativeMethodName, static, object="self", argsPost=[],
|
||||
resultVar=None):
|
||||
|
@ -7369,6 +7365,7 @@ class CGCallGenerator(CGThing):
|
|||
assert resultOutParam == "ptr"
|
||||
args.append(CGGeneric("&" + resultVar))
|
||||
|
||||
needsSubjectPrincipal = "needsSubjectPrincipal" in extendedAttributes
|
||||
if needsSubjectPrincipal:
|
||||
args.append(CGGeneric("subjectPrincipal"))
|
||||
|
||||
|
@ -7886,7 +7883,6 @@ class CGPerSignatureCall(CGThing):
|
|||
else:
|
||||
cgThings.append(CGCallGenerator(
|
||||
self.isFallible(),
|
||||
idlNode.getExtendedAttribute('NeedsSubjectPrincipal'),
|
||||
needsCallerType(idlNode),
|
||||
isChromeOnly(idlNode),
|
||||
self.getArguments(), argsPre, returnType,
|
||||
|
@ -9437,7 +9433,8 @@ class CGSpecializedSetter(CGAbstractStaticMethod):
|
|||
Argument('JS::Handle<JSObject*>', 'obj'),
|
||||
Argument('%s*' % descriptor.nativeType, 'self'),
|
||||
Argument('JSJitSetterCallArgs', 'args')]
|
||||
CGAbstractStaticMethod.__init__(self, descriptor, name, "bool", args)
|
||||
CGAbstractStaticMethod.__init__(self, descriptor, name, "bool", args,
|
||||
canRunScript=True)
|
||||
|
||||
def definition_body(self):
|
||||
nativeName = CGSpecializedSetter.makeNativeName(self.descriptor,
|
||||
|
@ -14700,7 +14697,7 @@ class CGNativeMember(ClassMethod):
|
|||
args.append(Argument("JS::MutableHandle<JSObject*>", "aRetVal"))
|
||||
|
||||
# And the nsIPrincipal
|
||||
if self.member.getExtendedAttribute('NeedsSubjectPrincipal'):
|
||||
if 'needsSubjectPrincipal' in self.extendedAttrs:
|
||||
# Cheat and assume self.descriptorProvider is a descriptor
|
||||
if self.descriptorProvider.interface.isExposedInAnyWorker():
|
||||
args.append(Argument("Maybe<nsIPrincipal*>", "aSubjectPrincipal"))
|
||||
|
|
|
@ -600,6 +600,9 @@ class Descriptor(DescriptorProvider):
|
|||
def ensureValidCanOOMExtendedAttribute(attr):
|
||||
ensureValidBoolExtendedAttribute(attr, "CanOOM")
|
||||
|
||||
def ensureValidNeedsSubjectPrincipalExtendedAttribute(attr):
|
||||
ensureValidBoolExtendedAttribute(attr, "NeedsSubjectPrincipal")
|
||||
|
||||
def maybeAppendInfallibleToAttrs(attrs, throws):
|
||||
ensureValidThrowsExtendedAttribute(throws)
|
||||
if throws is None:
|
||||
|
@ -610,9 +613,15 @@ class Descriptor(DescriptorProvider):
|
|||
if canOOM is not None:
|
||||
attrs.append("canOOM")
|
||||
|
||||
def maybeAppendNeedsSubjectPrincipalToAttrs(attrs, needsSubjectPrincipal):
|
||||
ensureValidNeedsSubjectPrincipalExtendedAttribute(needsSubjectPrincipal)
|
||||
if needsSubjectPrincipal is not None:
|
||||
attrs.append("needsSubjectPrincipal")
|
||||
|
||||
name = member.identifier.name
|
||||
throws = self.interface.isJSImplemented() or member.getExtendedAttribute("Throws")
|
||||
canOOM = member.getExtendedAttribute("CanOOM")
|
||||
needsSubjectPrincipal = member.getExtendedAttribute("NeedsSubjectPrincipal")
|
||||
if member.isMethod():
|
||||
# JSObject-returning [NewObject] methods must be fallible,
|
||||
# since they have to (fallibly) allocate the new JSObject.
|
||||
|
@ -622,6 +631,8 @@ class Descriptor(DescriptorProvider):
|
|||
attrs = self.extendedAttributes['all'].get(name, [])
|
||||
maybeAppendInfallibleToAttrs(attrs, throws)
|
||||
maybeAppendCanOOMToAttrs(attrs, canOOM)
|
||||
maybeAppendNeedsSubjectPrincipalToAttrs(attrs,
|
||||
needsSubjectPrincipal)
|
||||
return attrs
|
||||
|
||||
assert member.isAttr()
|
||||
|
@ -636,6 +647,12 @@ class Descriptor(DescriptorProvider):
|
|||
canOOMAttr = "GetterCanOOM" if getter else "SetterCanOOM"
|
||||
canOOM = member.getExtendedAttribute(canOOMAttr)
|
||||
maybeAppendCanOOMToAttrs(attrs, canOOM)
|
||||
if needsSubjectPrincipal is None:
|
||||
needsSubjectPrincipalAttr = (
|
||||
"GetterNeedsSubjectPrincipal" if getter else "SetterNeedsSubjectPrincipal")
|
||||
needsSubjectPrincipal = member.getExtendedAttribute(
|
||||
needsSubjectPrincipalAttr)
|
||||
maybeAppendNeedsSubjectPrincipalToAttrs(attrs, needsSubjectPrincipal)
|
||||
return attrs
|
||||
|
||||
def supportsIndexedProperties(self):
|
||||
|
|
|
@ -29,7 +29,7 @@ def generate(output, idlFilename, preprocessorHeader):
|
|||
# Unfortunately, even some of the getters here are fallible
|
||||
# (e.g. on nsComputedDOMStyle).
|
||||
extendedAttrs = ["Throws", "TreatNullAs=EmptyString",
|
||||
"NeedsSubjectPrincipal"]
|
||||
"SetterNeedsSubjectPrincipal"]
|
||||
if pref is not "":
|
||||
extendedAttrs.append('Pref="%s"' % pref)
|
||||
|
||||
|
|
|
@ -4150,7 +4150,8 @@ class IDLAttribute(IDLInterfaceMember):
|
|||
|
||||
def handleExtendedAttribute(self, attr):
|
||||
identifier = attr.identifier()
|
||||
if ((identifier == "SetterThrows" or identifier == "SetterCanOOM")
|
||||
if ((identifier == "SetterThrows" or identifier == "SetterCanOOM" or
|
||||
identifier == "SetterNeedsSubjectPrincipal")
|
||||
and self.readonly):
|
||||
raise WebIDLError("Readonly attributes must not be flagged as "
|
||||
"[%s]" % identifier,
|
||||
|
@ -4352,6 +4353,8 @@ class IDLAttribute(IDLInterfaceMember):
|
|||
identifier == "NewObject" or
|
||||
identifier == "UnsafeInPrerendering" or
|
||||
identifier == "NeedsSubjectPrincipal" or
|
||||
identifier == "SetterNeedsSubjectPrincipal" or
|
||||
identifier == "GetterNeedsSubjectPrincipal" or
|
||||
identifier == "NeedsCallerType" or
|
||||
identifier == "ReturnValueNeedsContainsHack" or
|
||||
identifier == "BinaryName" or
|
||||
|
@ -4988,7 +4991,9 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
|||
if (identifier == "GetterThrows" or
|
||||
identifier == "SetterThrows" or
|
||||
identifier == "GetterCanOOM" or
|
||||
identifier == "SetterCanOOM"):
|
||||
identifier == "SetterCanOOM" or
|
||||
identifier == "SetterNeedsSubjectPrincipal" or
|
||||
identifier == "GetterNeedsSubjectPrincipal"):
|
||||
raise WebIDLError("Methods must not be flagged as "
|
||||
"[%s]" % identifier,
|
||||
[attr.location, self.location])
|
||||
|
|
|
@ -101,16 +101,6 @@ class ClientChannelHelper final : public nsIInterfaceRequestor
|
|||
newLoadInfo->SetInitialClientInfo(initialClientInfo.ref());
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure we keep the service worker controller on same-origin
|
||||
// internal redirects.
|
||||
if (oldLoadInfo != newLoadInfo &&
|
||||
aFlags & nsIChannelEventSink::REDIRECT_INTERNAL) {
|
||||
const Maybe<ServiceWorkerDescriptor>& controller = oldLoadInfo->GetController();
|
||||
if (controller.isSome()) {
|
||||
newLoadInfo->SetController(controller.ref());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If it's a cross-origin redirect then we discard the old reserved client
|
||||
|
@ -134,6 +124,20 @@ class ClientChannelHelper final : public nsIInterfaceRequestor
|
|||
newLoadInfo->GiveReservedClientSource(Move(reservedClient));
|
||||
}
|
||||
|
||||
// Normally we keep the controller across channel redirects, but we must
|
||||
// clear it when a non-subresource load redirects. Only do this for real
|
||||
// redirects, however.
|
||||
//
|
||||
// There is an open spec question about what to do in this case for
|
||||
// worker script redirects. For now we clear the controller as that
|
||||
// seems most sane. See:
|
||||
//
|
||||
// https://github.com/w3c/ServiceWorker/issues/1239
|
||||
//
|
||||
if (!(aFlags & nsIChannelEventSink::REDIRECT_INTERNAL)) {
|
||||
newLoadInfo->ClearController();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIChannelEventSink> outerSink = do_GetInterface(mOuter);
|
||||
if (outerSink) {
|
||||
return outerSink->AsyncOnChannelRedirect(aOldChannel, aNewChannel, aFlags,
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "ClientHandleOpChild.h"
|
||||
#include "ClientManager.h"
|
||||
#include "mozilla/dom/PClientManagerChild.h"
|
||||
#include "mozilla/dom/ServiceWorkerDescriptor.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -101,5 +102,25 @@ ClientHandle::Info() const
|
|||
return mClientInfo;
|
||||
}
|
||||
|
||||
RefPtr<GenericPromise>
|
||||
ClientHandle::Control(const ServiceWorkerDescriptor& aServiceWorker)
|
||||
{
|
||||
RefPtr<GenericPromise::Private> outerPromise =
|
||||
new GenericPromise::Private(__func__);
|
||||
|
||||
RefPtr<ClientOpPromise> innerPromise =
|
||||
StartOp(ClientControlledArgs(aServiceWorker.ToIPC()));
|
||||
|
||||
innerPromise->Then(mSerialEventTarget, __func__,
|
||||
[outerPromise](const ClientOpResult& aResult) {
|
||||
outerPromise->Resolve(true, __func__);
|
||||
},
|
||||
[outerPromise](const ClientOpResult& aResult) {
|
||||
outerPromise->Reject(aResult.get_nsresult(), __func__);
|
||||
});
|
||||
|
||||
return outerPromise.forget();
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "mozilla/dom/ClientInfo.h"
|
||||
#include "mozilla/dom/ClientOpPromise.h"
|
||||
#include "mozilla/dom/ClientThing.h"
|
||||
#include "mozilla/MozPromise.h"
|
||||
|
||||
#ifdef XP_WIN
|
||||
#undef PostMessage
|
||||
|
@ -22,6 +23,7 @@ class ClientManager;
|
|||
class ClientHandleChild;
|
||||
class ClientOpConstructorArgs;
|
||||
class PClientManagerChild;
|
||||
class ServiceWorkerDescriptor;
|
||||
|
||||
// The ClientHandle allows code to take a simple ClientInfo struct and
|
||||
// convert it into a live actor-backed object attached to a particular
|
||||
|
@ -62,6 +64,12 @@ public:
|
|||
const ClientInfo&
|
||||
Info() const;
|
||||
|
||||
// Mark the ClientSource attached to this handle as controlled by the
|
||||
// given service worker. The promise will resolve true if the ClientSource
|
||||
// is successfully marked or reject if the operation could not be completed.
|
||||
RefPtr<GenericPromise>
|
||||
Control(const ServiceWorkerDescriptor& aServiceWorker);
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(ClientHandle);
|
||||
};
|
||||
|
||||
|
|
|
@ -6,17 +6,48 @@
|
|||
|
||||
#include "ClientHandleOpParent.h"
|
||||
|
||||
#include "ClientHandleParent.h"
|
||||
#include "ClientSourceParent.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
ClientSourceParent*
|
||||
ClientHandleOpParent::GetSource() const
|
||||
{
|
||||
auto handle = static_cast<ClientHandleParent*>(Manager());
|
||||
return handle->GetSource();
|
||||
}
|
||||
|
||||
void
|
||||
ClientHandleOpParent::ActorDestroy(ActorDestroyReason aReason)
|
||||
{
|
||||
mPromiseRequestHolder.DisconnectIfExists();
|
||||
}
|
||||
|
||||
void
|
||||
ClientHandleOpParent::Init(const ClientOpConstructorArgs& aArgs)
|
||||
{
|
||||
ClientSourceParent* source = GetSource();
|
||||
if (!source) {
|
||||
Unused << PClientHandleOpParent::Send__delete__(this, NS_ERROR_DOM_ABORT_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<ClientOpPromise> p = source->StartOp(aArgs);
|
||||
|
||||
// Capturing 'this' is safe here because we disconnect the promise in
|
||||
// ActorDestroy() which ensures neither lambda is called if the actor
|
||||
// is destroyed before the source operation completes.
|
||||
p->Then(GetCurrentThreadSerialEventTarget(), __func__,
|
||||
[this] (const ClientOpResult& aResult) {
|
||||
mPromiseRequestHolder.Complete();
|
||||
Unused << PClientHandleOpParent::Send__delete__(this, aResult);
|
||||
},
|
||||
[this] (nsresult aRv) {
|
||||
mPromiseRequestHolder.Complete();
|
||||
Unused << PClientHandleOpParent::Send__delete__(this, aRv);
|
||||
})->Track(mPromiseRequestHolder);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -6,13 +6,21 @@
|
|||
#ifndef _mozilla_dom_ClientHandleOpParent_h
|
||||
#define _mozilla_dom_ClientHandleOpParent_h
|
||||
|
||||
#include "ClientOpPromise.h"
|
||||
#include "mozilla/dom/PClientHandleOpParent.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class ClientSourceParent;
|
||||
|
||||
class ClientHandleOpParent final : public PClientHandleOpParent
|
||||
{
|
||||
MozPromiseRequestHolder<ClientOpPromise> mPromiseRequestHolder;
|
||||
|
||||
ClientSourceParent*
|
||||
GetSource() const;
|
||||
|
||||
// PClientHandleOpParent interface
|
||||
void
|
||||
ActorDestroy(ActorDestroyReason aReason) override;
|
||||
|
|
|
@ -50,18 +50,37 @@ union IPCClientState
|
|||
IPCClientWorkerState;
|
||||
};
|
||||
|
||||
struct ClientInfoAndState
|
||||
{
|
||||
IPCClientInfo info;
|
||||
IPCClientState state;
|
||||
};
|
||||
|
||||
struct ClientSourceExecutionReadyArgs
|
||||
{
|
||||
nsCString url;
|
||||
FrameType frameType;
|
||||
};
|
||||
|
||||
struct ClientControlledArgs
|
||||
{
|
||||
IPCServiceWorkerDescriptor serviceWorker;
|
||||
};
|
||||
|
||||
struct ClientGetInfoAndStateArgs
|
||||
{
|
||||
nsID id;
|
||||
PrincipalInfo principalInfo;
|
||||
};
|
||||
|
||||
struct ClientOpenWindowArgs
|
||||
{
|
||||
};
|
||||
|
||||
struct ClientOpConstructorArgs
|
||||
union ClientOpConstructorArgs
|
||||
{
|
||||
ClientControlledArgs;
|
||||
ClientGetInfoAndStateArgs;
|
||||
};
|
||||
|
||||
struct ClientNavigateOpConstructorArgs
|
||||
|
@ -71,6 +90,7 @@ struct ClientNavigateOpConstructorArgs
|
|||
union ClientOpResult
|
||||
{
|
||||
nsresult;
|
||||
ClientInfoAndState;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -245,5 +245,14 @@ ClientManager::CreateHandle(const ClientInfo& aClientInfo,
|
|||
return mgr->CreateHandleInternal(aClientInfo, aSerialEventTarget);
|
||||
}
|
||||
|
||||
// static
|
||||
RefPtr<ClientOpPromise>
|
||||
ClientManager::GetInfoAndState(const ClientGetInfoAndStateArgs& aArgs,
|
||||
nsISerialEventTarget* aSerialEventTarget)
|
||||
{
|
||||
RefPtr<ClientManager> mgr = GetOrCreateForCurrentThread();
|
||||
return mgr->StartOp(aArgs, aSerialEventTarget);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -18,6 +18,7 @@ class PrincipalInfo;
|
|||
} // namespace ipc
|
||||
namespace dom {
|
||||
|
||||
class ClientGetInfoAndStateArgs;
|
||||
class ClientHandle;
|
||||
class ClientInfo;
|
||||
class ClientManagerChild;
|
||||
|
@ -37,6 +38,7 @@ class WorkerPrivate;
|
|||
class ClientManager final : public ClientThing<ClientManagerChild>
|
||||
{
|
||||
friend class ClientManagerChild;
|
||||
friend class ClientSource;
|
||||
|
||||
ClientManager();
|
||||
~ClientManager();
|
||||
|
@ -92,6 +94,10 @@ public:
|
|||
CreateHandle(const ClientInfo& aClientInfo,
|
||||
nsISerialEventTarget* aSerialEventTarget);
|
||||
|
||||
static RefPtr<ClientOpPromise>
|
||||
GetInfoAndState(const ClientGetInfoAndStateArgs& aArgs,
|
||||
nsISerialEventTarget* aSerialEventTarget);
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(mozilla::dom::ClientManager)
|
||||
};
|
||||
|
||||
|
|
|
@ -11,9 +11,31 @@
|
|||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
template <typename Method, typename... Args>
|
||||
void
|
||||
ClientManagerOpParent::DoServiceOp(Method aMethod, Args&&... aArgs)
|
||||
{
|
||||
// Note, we need perfect forarding of the template type in order
|
||||
// to allow already_AddRefed<> to be passed as an arg.
|
||||
RefPtr<ClientOpPromise> p = (mService->*aMethod)(Forward<Args>(aArgs)...);
|
||||
|
||||
// Capturing `this` is safe here because we disconnect the promise in
|
||||
// ActorDestroy() which ensures neither lambda is called if the actor
|
||||
// is destroyed before the source operation completes.
|
||||
p->Then(GetCurrentThreadSerialEventTarget(), __func__,
|
||||
[this] (const mozilla::dom::ClientOpResult& aResult) {
|
||||
mPromiseRequestHolder.Complete();
|
||||
Unused << PClientManagerOpParent::Send__delete__(this, aResult);
|
||||
}, [this] (nsresult aRv) {
|
||||
mPromiseRequestHolder.Complete();
|
||||
Unused << PClientManagerOpParent::Send__delete__(this, aRv);
|
||||
})->Track(mPromiseRequestHolder);
|
||||
}
|
||||
|
||||
void
|
||||
ClientManagerOpParent::ActorDestroy(ActorDestroyReason aReason)
|
||||
{
|
||||
mPromiseRequestHolder.DisconnectIfExists();
|
||||
}
|
||||
|
||||
ClientManagerOpParent::ClientManagerOpParent(ClientManagerService* aService)
|
||||
|
@ -25,6 +47,19 @@ ClientManagerOpParent::ClientManagerOpParent(ClientManagerService* aService)
|
|||
void
|
||||
ClientManagerOpParent::Init(const ClientOpConstructorArgs& aArgs)
|
||||
{
|
||||
switch (aArgs.type()) {
|
||||
case ClientOpConstructorArgs::TClientGetInfoAndStateArgs:
|
||||
{
|
||||
DoServiceOp(&ClientManagerService::GetInfoAndState,
|
||||
aArgs.get_ClientGetInfoAndStateArgs());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
MOZ_ASSERT_UNREACHABLE("Unknown Client operation!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#define _mozilla_dom_ClientManagerOpParent_h
|
||||
|
||||
#include "mozilla/dom/PClientManagerOpParent.h"
|
||||
#include "ClientOpPromise.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -16,6 +17,11 @@ class ClientManagerService;
|
|||
class ClientManagerOpParent final : public PClientManagerOpParent
|
||||
{
|
||||
RefPtr<ClientManagerService> mService;
|
||||
MozPromiseRequestHolder<ClientOpPromise> mPromiseRequestHolder;
|
||||
|
||||
template <typename Method, typename... Args>
|
||||
void
|
||||
DoServiceOp(Method aMethod, Args&&... aArgs);
|
||||
|
||||
// PClientManagerOpParent interface
|
||||
void
|
||||
|
|
|
@ -290,5 +290,19 @@ ClientManagerService::RemoveManager(ClientManagerParent* aManager)
|
|||
MOZ_ASSERT(removed);
|
||||
}
|
||||
|
||||
RefPtr<ClientOpPromise>
|
||||
ClientManagerService::GetInfoAndState(const ClientGetInfoAndStateArgs& aArgs)
|
||||
{
|
||||
RefPtr<ClientOpPromise> ref;
|
||||
|
||||
ClientSourceParent* source = FindSource(aArgs.id(), aArgs.principalInfo());
|
||||
if (!source || !source->ExecutionReady()) {
|
||||
ref = ClientOpPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
return source->StartOp(aArgs);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -6,8 +6,7 @@
|
|||
#ifndef _mozilla_dom_ClientManagerService_h
|
||||
#define _mozilla_dom_ClientManagerService_h
|
||||
|
||||
#include "mozilla/ipc/PBackgroundSharedTypes.h"
|
||||
#include "mozilla/MozPromise.h"
|
||||
#include "ClientOpPromise.h"
|
||||
#include "nsDataHashtable.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -60,6 +59,9 @@ public:
|
|||
void
|
||||
RemoveManager(ClientManagerParent* aManager);
|
||||
|
||||
RefPtr<ClientOpPromise>
|
||||
GetInfoAndState(const ClientGetInfoAndStateArgs& aArgs);
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(mozilla::dom::ClientManagerService)
|
||||
};
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "ClientManager.h"
|
||||
#include "ClientManagerChild.h"
|
||||
#include "ClientSourceChild.h"
|
||||
#include "ClientState.h"
|
||||
#include "ClientValidation.h"
|
||||
#include "mozilla/dom/ClientIPCTypes.h"
|
||||
#include "mozilla/dom/WorkerPrivate.h"
|
||||
|
@ -54,6 +55,37 @@ ClientSource::ExecutionReady(const ClientSourceExecutionReadyArgs& aArgs)
|
|||
});
|
||||
}
|
||||
|
||||
nsresult
|
||||
ClientSource::SnapshotWindowState(ClientState* aStateOut)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsPIDOMWindowInner* window = GetInnerWindow();
|
||||
if (!window || !window->IsCurrentInnerWindow() ||
|
||||
!window->HasActiveDocument()) {
|
||||
*aStateOut = ClientState(ClientWindowState(VisibilityState::Hidden,
|
||||
TimeStamp(), false));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIDocument* doc = window->GetExtantDoc();
|
||||
if (NS_WARN_IF(!doc)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
ErrorResult rv;
|
||||
bool focused = doc->HasFocus(rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
rv.SuppressException();
|
||||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
*aStateOut = ClientState(ClientWindowState(doc->VisibilityState(),
|
||||
doc->LastFocusTime(), focused));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
WorkerPrivate*
|
||||
ClientSource::GetWorkerPrivate() const
|
||||
{
|
||||
|
@ -74,6 +106,18 @@ ClientSource::GetDocShell() const
|
|||
return mOwner.as<nsCOMPtr<nsIDocShell>>();
|
||||
}
|
||||
|
||||
void
|
||||
ClientSource::MaybeCreateInitialDocument()
|
||||
{
|
||||
nsIDocShell* docshell = GetDocShell();
|
||||
if (docshell) {
|
||||
// Force the create of the initial document if it does not exist yet.
|
||||
Unused << docshell->GetDocument();
|
||||
|
||||
MOZ_DIAGNOSTIC_ASSERT(GetInnerWindow());
|
||||
}
|
||||
}
|
||||
|
||||
ClientSource::ClientSource(ClientManager* aManager,
|
||||
nsISerialEventTarget* aEventTarget,
|
||||
const ClientSourceConstructorArgs& aArgs)
|
||||
|
@ -257,6 +301,84 @@ ClientSource::Info() const
|
|||
return mClientInfo;
|
||||
}
|
||||
|
||||
void
|
||||
ClientSource::WorkerSyncPing(WorkerPrivate* aWorkerPrivate)
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(ClientSource);
|
||||
MOZ_DIAGNOSTIC_ASSERT(aWorkerPrivate);
|
||||
MOZ_DIAGNOSTIC_ASSERT(aWorkerPrivate == mManager->GetWorkerPrivate());
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
MOZ_DIAGNOSTIC_ASSERT(GetActor());
|
||||
GetActor()->SendWorkerSyncPing();
|
||||
}
|
||||
|
||||
void
|
||||
ClientSource::SetController(const ServiceWorkerDescriptor& aServiceWorker)
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(ClientSource);
|
||||
|
||||
if (mController.isSome() && mController.ref() == aServiceWorker) {
|
||||
return;
|
||||
}
|
||||
|
||||
mController.reset();
|
||||
mController.emplace(aServiceWorker);
|
||||
}
|
||||
|
||||
RefPtr<ClientOpPromise>
|
||||
ClientSource::Control(const ClientControlledArgs& aArgs)
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(ClientSource);
|
||||
|
||||
SetController(ServiceWorkerDescriptor(aArgs.serviceWorker()));
|
||||
|
||||
RefPtr<ClientOpPromise> ref =
|
||||
ClientOpPromise::CreateAndResolve(NS_OK, __func__);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
const Maybe<ServiceWorkerDescriptor>&
|
||||
ClientSource::GetController() const
|
||||
{
|
||||
return mController;
|
||||
}
|
||||
|
||||
RefPtr<ClientOpPromise>
|
||||
ClientSource::GetInfoAndState(const ClientGetInfoAndStateArgs& aArgs)
|
||||
{
|
||||
RefPtr<ClientOpPromise> ref;
|
||||
|
||||
ClientState state;
|
||||
nsresult rv = SnapshotState(&state);
|
||||
if (NS_FAILED(rv)) {
|
||||
ref = ClientOpPromise::CreateAndReject(rv, __func__);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
ref = ClientOpPromise::CreateAndResolve(ClientInfoAndState(mClientInfo.ToIPC(),
|
||||
state.ToIPC()), __func__);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
nsresult
|
||||
ClientSource::SnapshotState(ClientState* aStateOut)
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(ClientSource);
|
||||
MOZ_DIAGNOSTIC_ASSERT(aStateOut);
|
||||
|
||||
if (mClientInfo.Type() == ClientType::Window) {
|
||||
MaybeCreateInitialDocument();
|
||||
nsresult rv = SnapshotWindowState(aStateOut);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
*aStateOut = ClientState(ClientWorkerState());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsISerialEventTarget*
|
||||
ClientSource::EventTarget() const
|
||||
{
|
||||
|
|
|
@ -7,14 +7,19 @@
|
|||
#define _mozilla_dom_ClientSource_h
|
||||
|
||||
#include "mozilla/dom/ClientInfo.h"
|
||||
#include "mozilla/dom/ClientOpPromise.h"
|
||||
#include "mozilla/dom/ClientThing.h"
|
||||
#include "mozilla/dom/ServiceWorkerDescriptor.h"
|
||||
#include "mozilla/Variant.h"
|
||||
|
||||
class nsIDocShell;
|
||||
class nsISerialEventTarget;
|
||||
class nsPIDOMWindowInner;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class ClientControlledArgs;
|
||||
class ClientManager;
|
||||
class ClientSourceChild;
|
||||
class ClientSourceConstructorArgs;
|
||||
|
@ -46,6 +51,7 @@ class ClientSource final : public ClientThing<ClientSourceChild>
|
|||
mozilla::dom::workers::WorkerPrivate*> mOwner;
|
||||
|
||||
ClientInfo mClientInfo;
|
||||
Maybe<ServiceWorkerDescriptor> mController;
|
||||
|
||||
void
|
||||
Shutdown();
|
||||
|
@ -59,6 +65,12 @@ class ClientSource final : public ClientThing<ClientSourceChild>
|
|||
nsIDocShell*
|
||||
GetDocShell() const;
|
||||
|
||||
void
|
||||
MaybeCreateInitialDocument();
|
||||
|
||||
nsresult
|
||||
SnapshotWindowState(ClientState* aStateOut);
|
||||
|
||||
// Private methods called by ClientManager
|
||||
ClientSource(ClientManager* aManager,
|
||||
nsISerialEventTarget* aEventTarget,
|
||||
|
@ -91,6 +103,40 @@ public:
|
|||
const ClientInfo&
|
||||
Info() const;
|
||||
|
||||
// Trigger a synchronous IPC ping to the parent process to confirm that
|
||||
// the ClientSource actor has been created. This should only be used
|
||||
// by the WorkerPrivate startup code to deal with a ClientHandle::Control()
|
||||
// call racing on the main thread. Do not call this in other circumstances!
|
||||
void
|
||||
WorkerSyncPing(mozilla::dom::workers::WorkerPrivate* aWorkerPrivate);
|
||||
|
||||
// Synchronously mark the ClientSource as controlled by the given service
|
||||
// worker. This can happen as a result of a remote operation or directly
|
||||
// by local code. For example, if a client's initial network load is
|
||||
// intercepted by a controlling service worker then this should be called
|
||||
// immediately.
|
||||
//
|
||||
// Note, there is no way to clear the controlling service worker because
|
||||
// the specification does not allow that operation.
|
||||
void
|
||||
SetController(const ServiceWorkerDescriptor& aServiceWorker);
|
||||
|
||||
// Mark the ClientSource as controlled using the remote operation arguments.
|
||||
// This will in turn call SetController().
|
||||
RefPtr<ClientOpPromise>
|
||||
Control(const ClientControlledArgs& aArgs);
|
||||
|
||||
// Get the ClientSource's current controlling service worker, if one has
|
||||
// been set.
|
||||
const Maybe<ServiceWorkerDescriptor>&
|
||||
GetController() const;
|
||||
|
||||
RefPtr<ClientOpPromise>
|
||||
GetInfoAndState(const ClientGetInfoAndStateArgs& aArgs);
|
||||
|
||||
nsresult
|
||||
SnapshotState(ClientState* aStateOut);
|
||||
|
||||
nsISerialEventTarget*
|
||||
EventTarget() const;
|
||||
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
#include "ClientSourceChild.h"
|
||||
|
||||
#include "ClientSource.h"
|
||||
#include "ClientSourceOpChild.h"
|
||||
#include "ClientThing.h"
|
||||
#include "mozilla/dom/ClientIPCTypes.h"
|
||||
#include "mozilla/Unused.h"
|
||||
|
||||
|
@ -61,17 +61,23 @@ ClientSourceChild::SetOwner(ClientThing<ClientSourceChild>* aThing)
|
|||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(aThing);
|
||||
MOZ_DIAGNOSTIC_ASSERT(!mSource);
|
||||
mSource = aThing;
|
||||
mSource = static_cast<ClientSource*>(aThing);
|
||||
}
|
||||
|
||||
void
|
||||
ClientSourceChild::RevokeOwner(ClientThing<ClientSourceChild>* aThing)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(mSource);
|
||||
MOZ_DIAGNOSTIC_ASSERT(mSource == aThing);
|
||||
MOZ_DIAGNOSTIC_ASSERT(mSource == static_cast<ClientSource*>(aThing));
|
||||
mSource = nullptr;
|
||||
}
|
||||
|
||||
ClientSource*
|
||||
ClientSourceChild::GetSource() const
|
||||
{
|
||||
return mSource;
|
||||
}
|
||||
|
||||
void
|
||||
ClientSourceChild::MaybeStartTeardown()
|
||||
{
|
||||
|
|
|
@ -11,12 +11,13 @@
|
|||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class ClientSource;
|
||||
class ClientSourceConstructorArgs;
|
||||
template <typename ActorType> class ClientThing;
|
||||
|
||||
class ClientSourceChild final : public PClientSourceChild
|
||||
{
|
||||
ClientThing<ClientSourceChild>* mSource;
|
||||
ClientSource* mSource;
|
||||
bool mTeardownStarted;
|
||||
|
||||
// PClientSourceChild interface
|
||||
|
@ -42,6 +43,9 @@ public:
|
|||
void
|
||||
RevokeOwner(ClientThing<ClientSourceChild>* aThing);
|
||||
|
||||
ClientSource*
|
||||
GetSource() const;
|
||||
|
||||
void
|
||||
MaybeStartTeardown();
|
||||
};
|
||||
|
|
|
@ -6,17 +6,91 @@
|
|||
|
||||
#include "ClientSourceOpChild.h"
|
||||
|
||||
#include "ClientSource.h"
|
||||
#include "ClientSourceChild.h"
|
||||
#include "mozilla/Unused.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
ClientSource*
|
||||
ClientSourceOpChild::GetSource() const
|
||||
{
|
||||
auto actor = static_cast<ClientSourceChild*>(Manager());
|
||||
return actor->GetSource();
|
||||
}
|
||||
|
||||
template<typename Method, typename Args>
|
||||
void
|
||||
ClientSourceOpChild::DoSourceOp(Method aMethod, const Args& aArgs)
|
||||
{
|
||||
RefPtr<ClientOpPromise> promise;
|
||||
nsCOMPtr<nsISerialEventTarget> target;
|
||||
|
||||
// Some ClientSource operations can cause the ClientSource to be destroyed.
|
||||
// This means we should reference the ClientSource pointer for the minimum
|
||||
// possible to start the operation. Use an extra block scope here to help
|
||||
// enforce this and prevent accidental usage later in the method.
|
||||
{
|
||||
ClientSource* source = GetSource();
|
||||
if (!source) {
|
||||
Unused << PClientSourceOpChild::Send__delete__(this, NS_ERROR_DOM_ABORT_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
target = source->EventTarget();
|
||||
|
||||
// This may cause the ClientSource object to be destroyed. Do not
|
||||
// use the source variable after this call.
|
||||
promise = (source->*aMethod)(aArgs);
|
||||
}
|
||||
|
||||
// The ClientSource methods are required to always return a promise. If
|
||||
// they encounter an error they should just immediately resolve or reject
|
||||
// the promise as appropriate.
|
||||
MOZ_DIAGNOSTIC_ASSERT(promise);
|
||||
|
||||
// Capture 'this' is safe here because we disconnect the promise
|
||||
// ActorDestroy() which ensures nethier lambda is called if the
|
||||
// actor is destroyed before the source operation completes.
|
||||
promise->Then(target, __func__,
|
||||
[this, aArgs] (const mozilla::dom::ClientOpResult& aResult) {
|
||||
mPromiseRequestHolder.Complete();
|
||||
Unused << PClientSourceOpChild::Send__delete__(this, aResult);
|
||||
},
|
||||
[this] (nsresult aRv) {
|
||||
mPromiseRequestHolder.Complete();
|
||||
Unused << PClientSourceOpChild::Send__delete__(this, aRv);
|
||||
})->Track(mPromiseRequestHolder);
|
||||
}
|
||||
|
||||
void
|
||||
ClientSourceOpChild::ActorDestroy(ActorDestroyReason aReason)
|
||||
{
|
||||
mPromiseRequestHolder.DisconnectIfExists();
|
||||
}
|
||||
|
||||
void
|
||||
ClientSourceOpChild::Init(const ClientOpConstructorArgs& aArgs)
|
||||
{
|
||||
switch (aArgs.type()) {
|
||||
case ClientOpConstructorArgs::TClientControlledArgs:
|
||||
{
|
||||
DoSourceOp(&ClientSource::Control, aArgs.get_ClientControlledArgs());
|
||||
break;
|
||||
}
|
||||
case ClientOpConstructorArgs::TClientGetInfoAndStateArgs:
|
||||
{
|
||||
DoSourceOp(&ClientSource::GetInfoAndState,
|
||||
aArgs.get_ClientGetInfoAndStateArgs());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
MOZ_ASSERT_UNREACHABLE("unknown client operation!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -12,8 +12,19 @@
|
|||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class ClientSource;
|
||||
|
||||
class ClientSourceOpChild final : public PClientSourceOpChild
|
||||
{
|
||||
MozPromiseRequestHolder<ClientOpPromise> mPromiseRequestHolder;
|
||||
|
||||
ClientSource*
|
||||
GetSource() const;
|
||||
|
||||
template <typename Method, typename Args>
|
||||
void
|
||||
DoSourceOp(Method aMethod, const Args& aArgs);
|
||||
|
||||
// PClientSourceOpChild interface
|
||||
void
|
||||
ActorDestroy(ActorDestroyReason aReason) override;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
using mozilla::ipc::AssertIsOnBackgroundThread;
|
||||
using mozilla::ipc::BackgroundParent;
|
||||
using mozilla::ipc::IPCResult;
|
||||
using mozilla::ipc::PrincipalInfo;
|
||||
|
@ -82,6 +83,15 @@ ClientSourceParent::KillInvalidChild()
|
|||
MOZ_ALWAYS_SUCCEEDS(SystemGroup::Dispatch(TaskCategory::Other, r.forget()));
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
ClientSourceParent::RecvWorkerSyncPing()
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
// Do nothing here. This is purely a sync message allowing the child to
|
||||
// confirm that the actor has been created on the parent process.
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
IPCResult
|
||||
ClientSourceParent::RecvTeardown()
|
||||
{
|
||||
|
@ -209,6 +219,12 @@ ClientSourceParent::IsFrozen() const
|
|||
return mFrozen;
|
||||
}
|
||||
|
||||
bool
|
||||
ClientSourceParent::ExecutionReady() const
|
||||
{
|
||||
return mExecutionReady;
|
||||
}
|
||||
|
||||
void
|
||||
ClientSourceParent::AttachHandle(ClientHandleParent* aClientHandle)
|
||||
{
|
||||
|
@ -226,5 +242,25 @@ ClientSourceParent::DetachHandle(ClientHandleParent* aClientHandle)
|
|||
mHandleList.RemoveElement(aClientHandle);
|
||||
}
|
||||
|
||||
RefPtr<ClientOpPromise>
|
||||
ClientSourceParent::StartOp(const ClientOpConstructorArgs& aArgs)
|
||||
{
|
||||
RefPtr<ClientOpPromise::Private> promise =
|
||||
new ClientOpPromise::Private(__func__);
|
||||
|
||||
// If we are being controlled, remember that data before propagating
|
||||
// on to the ClientSource.
|
||||
if (aArgs.type() == ClientOpConstructorArgs::TClientControlledArgs) {
|
||||
mController.reset();
|
||||
mController.emplace(aArgs.get_ClientControlledArgs().serviceWorker());
|
||||
}
|
||||
|
||||
// Constructor failure will reject the promise via ActorDestroy().
|
||||
ClientSourceOpParent* actor = new ClientSourceOpParent(aArgs, promise);
|
||||
Unused << SendPClientSourceOpConstructor(actor, aArgs);
|
||||
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -7,7 +7,9 @@
|
|||
#define _mozilla_dom_ClientSourceParent_h
|
||||
|
||||
#include "ClientInfo.h"
|
||||
#include "ClientOpPromise.h"
|
||||
#include "mozilla/dom/PClientSourceParent.h"
|
||||
#include "mozilla/dom/ServiceWorkerDescriptor.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -18,6 +20,7 @@ class ClientManagerService;
|
|||
class ClientSourceParent final : public PClientSourceParent
|
||||
{
|
||||
ClientInfo mClientInfo;
|
||||
Maybe<ServiceWorkerDescriptor> mController;
|
||||
RefPtr<ClientManagerService> mService;
|
||||
nsTArray<ClientHandleParent*> mHandleList;
|
||||
bool mExecutionReady;
|
||||
|
@ -27,6 +30,9 @@ class ClientSourceParent final : public PClientSourceParent
|
|||
KillInvalidChild();
|
||||
|
||||
// PClientSourceParent
|
||||
mozilla::ipc::IPCResult
|
||||
RecvWorkerSyncPing() override;
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RecvTeardown() override;
|
||||
|
||||
|
@ -61,11 +67,17 @@ public:
|
|||
bool
|
||||
IsFrozen() const;
|
||||
|
||||
bool
|
||||
ExecutionReady() const;
|
||||
|
||||
void
|
||||
AttachHandle(ClientHandleParent* aClientSource);
|
||||
|
||||
void
|
||||
DetachHandle(ClientHandleParent* aClientSource);
|
||||
|
||||
RefPtr<ClientOpPromise>
|
||||
StartOp(const ClientOpConstructorArgs& aArgs);
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -20,6 +20,7 @@ sync protocol PClientSource
|
|||
manages PClientSourceOp;
|
||||
|
||||
parent:
|
||||
sync WorkerSyncPing();
|
||||
async Teardown();
|
||||
async ExecutionReady(ClientSourceExecutionReadyArgs aArgs);
|
||||
async Freeze();
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(CredentialsContainer, mParent)
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(CredentialsContainer, mParent, mManager)
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(CredentialsContainer)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(CredentialsContainer)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CredentialsContainer)
|
||||
|
@ -28,6 +28,16 @@ CredentialsContainer::CredentialsContainer(nsPIDOMWindowInner* aParent) :
|
|||
CredentialsContainer::~CredentialsContainer()
|
||||
{}
|
||||
|
||||
void
|
||||
CredentialsContainer::EnsureWebAuthnManager()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (!mManager) {
|
||||
mManager = new WebAuthnManager(mParent);
|
||||
}
|
||||
}
|
||||
|
||||
JSObject*
|
||||
CredentialsContainer::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
|
@ -37,22 +47,22 @@ CredentialsContainer::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenPro
|
|||
already_AddRefed<Promise>
|
||||
CredentialsContainer::Get(const CredentialRequestOptions& aOptions)
|
||||
{
|
||||
RefPtr<WebAuthnManager> mgr = WebAuthnManager::GetOrCreate();
|
||||
return mgr->GetAssertion(mParent, aOptions.mPublicKey, aOptions.mSignal);
|
||||
EnsureWebAuthnManager();
|
||||
return mManager->GetAssertion(aOptions.mPublicKey, aOptions.mSignal);
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
CredentialsContainer::Create(const CredentialCreationOptions& aOptions)
|
||||
{
|
||||
RefPtr<WebAuthnManager> mgr = WebAuthnManager::GetOrCreate();
|
||||
return mgr->MakeCredential(mParent, aOptions.mPublicKey, aOptions.mSignal);
|
||||
EnsureWebAuthnManager();
|
||||
return mManager->MakeCredential(aOptions.mPublicKey, aOptions.mSignal);
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
CredentialsContainer::Store(const Credential& aCredential)
|
||||
{
|
||||
RefPtr<WebAuthnManager> mgr = WebAuthnManager::GetOrCreate();
|
||||
return mgr->Store(mParent, aCredential);
|
||||
EnsureWebAuthnManager();
|
||||
return mManager->Store(aCredential);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class WebAuthnManager;
|
||||
|
||||
class CredentialsContainer final : public nsISupports
|
||||
, public nsWrapperCache
|
||||
{
|
||||
|
@ -32,15 +34,20 @@ public:
|
|||
|
||||
already_AddRefed<Promise>
|
||||
Get(const CredentialRequestOptions& aOptions);
|
||||
|
||||
already_AddRefed<Promise>
|
||||
Create(const CredentialCreationOptions& aOptions);
|
||||
|
||||
already_AddRefed<Promise>
|
||||
Store(const Credential& aCredential);
|
||||
|
||||
private:
|
||||
~CredentialsContainer();
|
||||
|
||||
void EnsureWebAuthnManager();
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowInner> mParent;
|
||||
RefPtr<WebAuthnManager> mManager;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "nsHostObjectProtocolHandler.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "nsProxyRelease.h"
|
||||
#include "nsStreamUtils.h"
|
||||
#include "nsStringStream.h"
|
||||
#include "nsHttpChannel.h"
|
||||
|
@ -58,6 +59,268 @@ ShouldCheckSRI(const InternalRequest* const aRequest,
|
|||
|
||||
} // anonymous namespace
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// AlternativeDataStreamListener
|
||||
//-----------------------------------------------------------------------------
|
||||
class AlternativeDataStreamListener final : public nsIStreamListener,
|
||||
public nsIThreadRetargetableStreamListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIREQUESTOBSERVER
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
|
||||
|
||||
// The status of AlternativeDataStreamListener
|
||||
// LOADING: is the initial status, loading the alternative data
|
||||
// COMPLETED: Alternative data loading is completed
|
||||
// CANCELED: Alternative data loading is canceled, this would make
|
||||
// AlternativeDataStreamListener ignore all channel callbacks
|
||||
// FALLBACK: fallback the channel callbacks to FetchDriver
|
||||
// Depends on different situaions, the status transition could be followings
|
||||
// 1. LOADING->COMPLETED
|
||||
// This is the normal status transition for alternative data loading
|
||||
//
|
||||
// 2. LOADING->CANCELED
|
||||
// LOADING->COMPLETED->CANCELED
|
||||
// Alternative data loading could be canceled when cacheId from alternative
|
||||
// data channel does not match with from main data channel(The cacheID
|
||||
// checking is in FetchDriver::OnStartRequest).
|
||||
// Notice the alternative data loading could finish before the cacheID
|
||||
// checking, so the statust transition could be LOADING->COMPLETED->CANCELED
|
||||
//
|
||||
// 3. LOADING->FALLBACK
|
||||
// For the case that alternative data loading could not be initialized, i.e.
|
||||
// alternative data does not exist or no preferred alternative data type is
|
||||
// requested. Once the status becomes FALLBACK, AlternativeDataStreamListener
|
||||
// transits the channel callback request to FetchDriver, and the status
|
||||
// should not go back to LOADING, COMPLETED, or CANCELED anymore.
|
||||
enum eStatus {
|
||||
LOADING = 0,
|
||||
COMPLETED,
|
||||
CANCELED,
|
||||
FALLBACK
|
||||
};
|
||||
|
||||
AlternativeDataStreamListener(FetchDriver* aFetchDriver,
|
||||
nsIChannel* aChannel,
|
||||
const nsACString& aAlternativeDataType);
|
||||
eStatus Status();
|
||||
void Cancel();
|
||||
uint64_t GetAlternativeDataCacheEntryId();
|
||||
const nsACString& GetAlternativeDataType() const;
|
||||
already_AddRefed<nsICacheInfoChannel> GetCacheInfoChannel();
|
||||
already_AddRefed<nsIInputStream> GetAlternativeInputStream();
|
||||
|
||||
private:
|
||||
~AlternativeDataStreamListener() = default;
|
||||
|
||||
// This creates a strong reference cycle with FetchDriver and its
|
||||
// mAltDataListener. We need to clear at least one reference of them once the
|
||||
// data loading finishes.
|
||||
RefPtr<FetchDriver> mFetchDriver;
|
||||
nsCString mAlternativeDataType;
|
||||
nsCOMPtr<nsIInputStream> mPipeAlternativeInputStream;
|
||||
nsCOMPtr<nsIOutputStream> mPipeAlternativeOutputStream;
|
||||
uint64_t mAlternativeDataCacheEntryId;
|
||||
nsCOMPtr<nsICacheInfoChannel> mCacheInfoChannel;
|
||||
nsCOMPtr<nsIChannel> mChannel;
|
||||
Atomic<eStatus> mStatus;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(AlternativeDataStreamListener,
|
||||
nsIStreamListener,
|
||||
nsIThreadRetargetableStreamListener)
|
||||
|
||||
AlternativeDataStreamListener::AlternativeDataStreamListener(FetchDriver* aFetchDriver,
|
||||
nsIChannel* aChannel,
|
||||
const nsACString& aAlternativeDataType)
|
||||
: mFetchDriver(aFetchDriver)
|
||||
, mAlternativeDataType(aAlternativeDataType)
|
||||
, mAlternativeDataCacheEntryId(0)
|
||||
, mChannel(aChannel)
|
||||
, mStatus(AlternativeDataStreamListener::LOADING)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(mFetchDriver);
|
||||
MOZ_DIAGNOSTIC_ASSERT(mChannel);
|
||||
}
|
||||
|
||||
AlternativeDataStreamListener::eStatus
|
||||
AlternativeDataStreamListener::Status()
|
||||
{
|
||||
return mStatus;
|
||||
}
|
||||
|
||||
void
|
||||
AlternativeDataStreamListener::Cancel()
|
||||
{
|
||||
mAlternativeDataCacheEntryId = 0;
|
||||
mCacheInfoChannel = nullptr;
|
||||
mPipeAlternativeOutputStream = nullptr;
|
||||
mPipeAlternativeInputStream = nullptr;
|
||||
if (mChannel && mStatus != AlternativeDataStreamListener::FALLBACK) {
|
||||
// if mStatus is fallback, we need to keep channel to forward request back to
|
||||
// FetchDriver
|
||||
mChannel->Cancel(NS_BINDING_ABORTED);
|
||||
mChannel = nullptr;
|
||||
}
|
||||
mStatus = AlternativeDataStreamListener::CANCELED;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
AlternativeDataStreamListener::GetAlternativeDataCacheEntryId()
|
||||
{
|
||||
return mAlternativeDataCacheEntryId;
|
||||
}
|
||||
|
||||
const nsACString&
|
||||
AlternativeDataStreamListener::GetAlternativeDataType() const
|
||||
{
|
||||
return mAlternativeDataType;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIInputStream>
|
||||
AlternativeDataStreamListener::GetAlternativeInputStream()
|
||||
{
|
||||
nsCOMPtr<nsIInputStream> inputStream = mPipeAlternativeInputStream;
|
||||
return inputStream.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<nsICacheInfoChannel>
|
||||
AlternativeDataStreamListener::GetCacheInfoChannel()
|
||||
{
|
||||
nsCOMPtr<nsICacheInfoChannel> channel = mCacheInfoChannel;
|
||||
return channel.forget();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
AlternativeDataStreamListener::OnStartRequest(nsIRequest* aRequest,
|
||||
nsISupports* aContext)
|
||||
{
|
||||
workers::AssertIsOnMainThread();
|
||||
MOZ_ASSERT(!mAlternativeDataType.IsEmpty());
|
||||
// Checking the alternative data type is the same between we asked and the
|
||||
// saved in the channel.
|
||||
nsAutoCString alternativeDataType;
|
||||
nsCOMPtr<nsICacheInfoChannel> cic = do_QueryInterface(aRequest);
|
||||
mStatus = AlternativeDataStreamListener::LOADING;
|
||||
if (cic &&
|
||||
NS_SUCCEEDED(cic->GetAlternativeDataType(alternativeDataType)) &&
|
||||
mAlternativeDataType.Equals(alternativeDataType) &&
|
||||
NS_SUCCEEDED(cic->GetCacheEntryId(&mAlternativeDataCacheEntryId))) {
|
||||
|
||||
MOZ_DIAGNOSTIC_ASSERT(!mPipeAlternativeInputStream);
|
||||
MOZ_DIAGNOSTIC_ASSERT(!mPipeAlternativeOutputStream);
|
||||
nsresult rv = NS_NewPipe(
|
||||
getter_AddRefs(mPipeAlternativeInputStream),
|
||||
getter_AddRefs(mPipeAlternativeOutputStream),
|
||||
0 /* default segment size */,
|
||||
UINT32_MAX /* infinite pipe */,
|
||||
true /* non-blocking input, otherwise you deadlock */,
|
||||
false /* blocking output, since the pipe is 'in'finite */);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
mFetchDriver->FailWithNetworkError(rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
MOZ_DIAGNOSTIC_ASSERT(!mCacheInfoChannel);
|
||||
mCacheInfoChannel = cic;
|
||||
|
||||
// call FetchDriver::HttpFetch to load main body
|
||||
MOZ_ASSERT(mFetchDriver);
|
||||
return mFetchDriver->HttpFetch();
|
||||
|
||||
} else {
|
||||
// Needn't load alternative data, since alternative data does not exist.
|
||||
// Set status to FALLBACK to reuse the opened channel to load main body, then
|
||||
// call FetchDriver::OnStartRequest to continue the work.
|
||||
// Unfortunately can't change the stream listener to mFetchDriver, need to
|
||||
// keep AlternativeDataStreamListener alive to redirect OnDataAvailable and
|
||||
// OnStopRequest to mFetchDriver.
|
||||
MOZ_ASSERT(alternativeDataType.IsEmpty());
|
||||
mStatus = AlternativeDataStreamListener::FALLBACK;
|
||||
mAlternativeDataCacheEntryId = 0;
|
||||
MOZ_ASSERT(mFetchDriver);
|
||||
return mFetchDriver->OnStartRequest(aRequest, aContext);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
AlternativeDataStreamListener::OnDataAvailable(nsIRequest* aRequest,
|
||||
nsISupports* aContext,
|
||||
nsIInputStream* aInputStream,
|
||||
uint64_t aOffset,
|
||||
uint32_t aCount)
|
||||
{
|
||||
if (mStatus == AlternativeDataStreamListener::LOADING) {
|
||||
MOZ_ASSERT(mPipeAlternativeOutputStream);
|
||||
uint32_t read;
|
||||
return aInputStream->ReadSegments(NS_CopySegmentToStream,
|
||||
mPipeAlternativeOutputStream,
|
||||
aCount, &read);
|
||||
}
|
||||
if (mStatus == AlternativeDataStreamListener::FALLBACK) {
|
||||
MOZ_ASSERT(mFetchDriver);
|
||||
return mFetchDriver->OnDataAvailable(aRequest, aContext, aInputStream, aOffset, aCount);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
AlternativeDataStreamListener::OnStopRequest(nsIRequest* aRequest,
|
||||
nsISupports* aContext,
|
||||
nsresult aStatusCode)
|
||||
{
|
||||
workers::AssertIsOnMainThread();
|
||||
|
||||
// Alternative data loading is going to finish, breaking the reference cycle
|
||||
// here by taking the ownership to a loacl variable.
|
||||
RefPtr<FetchDriver> fetchDriver = mFetchDriver.forget();
|
||||
|
||||
if (mStatus == AlternativeDataStreamListener::CANCELED) {
|
||||
// do nothing
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mStatus == AlternativeDataStreamListener::FALLBACK) {
|
||||
MOZ_ASSERT(fetchDriver);
|
||||
return fetchDriver->OnStopRequest(aRequest, aContext, aStatusCode);
|
||||
}
|
||||
|
||||
MOZ_DIAGNOSTIC_ASSERT(mStatus == AlternativeDataStreamListener::LOADING);
|
||||
|
||||
MOZ_ASSERT(!mAlternativeDataType.IsEmpty() &&
|
||||
mPipeAlternativeOutputStream &&
|
||||
mPipeAlternativeInputStream);
|
||||
|
||||
mPipeAlternativeOutputStream->Close();
|
||||
mPipeAlternativeOutputStream = nullptr;
|
||||
|
||||
// Cleanup the states for alternative data if needed.
|
||||
if (NS_FAILED(aStatusCode)) {
|
||||
mAlternativeDataCacheEntryId = 0;
|
||||
mCacheInfoChannel = nullptr;
|
||||
mPipeAlternativeInputStream = nullptr;
|
||||
}
|
||||
mStatus = AlternativeDataStreamListener::COMPLETED;
|
||||
// alternative data loading finish, call FetchDriver::FinishOnStopRequest to
|
||||
// continue the final step for the case FetchDriver::OnStopRequest is called
|
||||
// earlier than AlternativeDataStreamListener::OnStopRequest
|
||||
MOZ_ASSERT(fetchDriver);
|
||||
return fetchDriver->FinishOnStopRequest(this);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
AlternativeDataStreamListener::CheckListenerChain()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// FetchDriver
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
NS_IMPL_ISUPPORTS(FetchDriver,
|
||||
nsIStreamListener, nsIChannelEventSink, nsIInterfaceRequestor,
|
||||
nsIThreadRetargetableStreamListener)
|
||||
|
@ -131,7 +394,7 @@ FetchDriver::Fetch(AbortSignal* aSignal, FetchDriverObserver* aObserver)
|
|||
Follow(aSignal);
|
||||
}
|
||||
|
||||
rv = HttpFetch();
|
||||
rv = HttpFetch(mRequest->GetPreferredAlternativeDataType());
|
||||
if (NS_FAILED(rv)) {
|
||||
FailWithNetworkError(rv);
|
||||
}
|
||||
|
@ -144,12 +407,13 @@ FetchDriver::Fetch(AbortSignal* aSignal, FetchDriverObserver* aObserver)
|
|||
// Functionality is often split between here, the CORS listener proxy and the
|
||||
// Necko HTTP implementation.
|
||||
nsresult
|
||||
FetchDriver::HttpFetch()
|
||||
FetchDriver::HttpFetch(const nsACString& aPreferredAlternativeDataType)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// Step 1. "Let response be null."
|
||||
mResponse = nullptr;
|
||||
mOnStopRequestCalled = false;
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIIOService> ios = do_GetIOService(&rv);
|
||||
|
@ -269,8 +533,6 @@ FetchDriver::HttpFetch()
|
|||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mLoadGroup = nullptr;
|
||||
|
||||
// Insert ourselves into the notification callbacks chain so we can set
|
||||
// headers on redirects.
|
||||
#ifdef DEBUG
|
||||
|
@ -414,7 +676,23 @@ FetchDriver::HttpFetch()
|
|||
}
|
||||
}
|
||||
|
||||
rv = chan->AsyncOpen2(this);
|
||||
// if the preferred alternative data type in InternalRequest is not empty, set
|
||||
// the data type on the created channel and also create a AlternativeDataStreamListener
|
||||
// to be the stream listener of the channel.
|
||||
if (!aPreferredAlternativeDataType.IsEmpty()) {
|
||||
nsCOMPtr<nsICacheInfoChannel> cic = do_QueryInterface(chan);
|
||||
if (cic) {
|
||||
cic->PreferAlternativeDataType(aPreferredAlternativeDataType);
|
||||
MOZ_ASSERT(!mAltDataListener);
|
||||
mAltDataListener =
|
||||
new AlternativeDataStreamListener(this, chan, aPreferredAlternativeDataType);
|
||||
rv = chan->AsyncOpen2(mAltDataListener);
|
||||
} else {
|
||||
rv = chan->AsyncOpen2(this);
|
||||
}
|
||||
} else {
|
||||
rv = chan->AsyncOpen2(this);
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Step 4 onwards of "HTTP Fetch" is handled internally by Necko.
|
||||
|
@ -580,6 +858,44 @@ FetchDriver::OnStartRequest(nsIRequest* aRequest,
|
|||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsICacheInfoChannel> cic = do_QueryInterface(aRequest);
|
||||
if (cic && mAltDataListener) {
|
||||
// Skip the case that mAltDataListener->Status() equals to FALLBACK, that means
|
||||
// the opened channel for alternative data loading is reused for loading the
|
||||
// main data.
|
||||
if (mAltDataListener->Status() != AlternativeDataStreamListener::FALLBACK) {
|
||||
// Verify the cache ID is the same with from alternative data cache.
|
||||
// If the cache ID is different, droping the alternative data loading,
|
||||
// otherwise setup the response's alternative body and cacheInfoChannel.
|
||||
uint64_t cacheEntryId = 0;
|
||||
if (NS_SUCCEEDED(cic->GetCacheEntryId(&cacheEntryId)) &&
|
||||
cacheEntryId != mAltDataListener->GetAlternativeDataCacheEntryId()) {
|
||||
mAltDataListener->Cancel();
|
||||
} else {
|
||||
// AlternativeDataStreamListener::OnStartRequest had already been called,
|
||||
// the alternative data input stream and cacheInfo channel must be created.
|
||||
nsCOMPtr<nsICacheInfoChannel> cacheInfo = mAltDataListener->GetCacheInfoChannel();
|
||||
nsCOMPtr<nsIInputStream> altInputStream = mAltDataListener->GetAlternativeInputStream();
|
||||
MOZ_ASSERT(altInputStream && cacheInfo);
|
||||
response->SetAlternativeBody(altInputStream);
|
||||
nsMainThreadPtrHandle<nsICacheInfoChannel> handle(
|
||||
new nsMainThreadPtrHolder<nsICacheInfoChannel>("nsICacheInfoChannel",
|
||||
cacheInfo,
|
||||
false));
|
||||
response->SetCacheInfoChannel(handle);
|
||||
}
|
||||
} else if (!mAltDataListener->GetAlternativeDataType().IsEmpty()) {
|
||||
// If the status is FALLBACK and the mAltDataListener::mAlternativeDataType
|
||||
// is not empty, that means the data need to be saved into cache, setup the
|
||||
// response's nsICacheInfoChannel for caching the data after loading.
|
||||
nsMainThreadPtrHandle<nsICacheInfoChannel> handle(
|
||||
new nsMainThreadPtrHolder<nsICacheInfoChannel>("nsICacheInfoChannel",
|
||||
cic,
|
||||
false));
|
||||
response->SetCacheInfoChannel(handle);
|
||||
}
|
||||
}
|
||||
|
||||
// We open a pipe so that we can immediately set the pipe's read end as the
|
||||
// response's body. Setting the segment size to UINT32_MAX means that the
|
||||
// pipe has infinite space. The nsIChannel will continue to buffer data in
|
||||
|
@ -800,6 +1116,12 @@ FetchDriver::OnStopRequest(nsIRequest* aRequest,
|
|||
{
|
||||
workers::AssertIsOnMainThread();
|
||||
|
||||
MOZ_DIAGNOSTIC_ASSERT(!mOnStopRequestCalled);
|
||||
mOnStopRequestCalled = true;
|
||||
|
||||
// main data loading is going to finish, breaking the reference cycle.
|
||||
RefPtr<AlternativeDataStreamListener> altDataListener = mAltDataListener.forget();
|
||||
|
||||
// We need to check mObserver, which is nulled by FailWithNetworkError(),
|
||||
// because in the case of "error" redirect mode, aStatusCode may be NS_OK but
|
||||
// mResponse will definitely be null so we must not take the else branch.
|
||||
|
@ -808,6 +1130,9 @@ FetchDriver::OnStopRequest(nsIRequest* aRequest,
|
|||
if (outputStream) {
|
||||
outputStream->CloseWithStatus(NS_BINDING_FAILED);
|
||||
}
|
||||
if (altDataListener) {
|
||||
altDataListener->Cancel();
|
||||
}
|
||||
|
||||
// We proceed as usual here, since we've already created a successful response
|
||||
// from OnStartRequest.
|
||||
|
@ -835,6 +1160,9 @@ FetchDriver::OnStopRequest(nsIRequest* aRequest,
|
|||
nsresult rv = mSRIDataVerifier->Verify(mSRIMetadata, channel, sourceUri,
|
||||
reporter);
|
||||
if (NS_FAILED(rv)) {
|
||||
if (altDataListener) {
|
||||
altDataListener->Cancel();
|
||||
}
|
||||
FailWithNetworkError(rv);
|
||||
// Cancel request.
|
||||
return rv;
|
||||
|
@ -846,6 +1174,28 @@ FetchDriver::OnStopRequest(nsIRequest* aRequest,
|
|||
}
|
||||
}
|
||||
|
||||
return FinishOnStopRequest(altDataListener);
|
||||
}
|
||||
|
||||
nsresult
|
||||
FetchDriver::FinishOnStopRequest(AlternativeDataStreamListener* aAltDataListener)
|
||||
{
|
||||
workers::AssertIsOnMainThread();
|
||||
// OnStopRequest is not called from channel, that means the main data loading
|
||||
// does not finish yet. Reaching here since alternative data loading finishes.
|
||||
if (!mOnStopRequestCalled) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
MOZ_DIAGNOSTIC_ASSERT(!mAltDataListener);
|
||||
// Wait for alternative data loading finish if we needed it.
|
||||
if (aAltDataListener &&
|
||||
aAltDataListener->Status() == AlternativeDataStreamListener::LOADING) {
|
||||
// For LOADING case, channel holds the reference of altDataListener, no need
|
||||
// to restore it to mAltDataListener.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mObserver) {
|
||||
// From "Main Fetch" step 19.1, 19.2: Process response.
|
||||
if (ShouldCheckSRI(mRequest, mResponse)) {
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#define mozilla_dom_FetchDriver_h
|
||||
|
||||
#include "nsIChannelEventSink.h"
|
||||
#include "nsICacheInfoChannel.h"
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIThreadRetargetableStreamListener.h"
|
||||
|
@ -88,6 +89,8 @@ private:
|
|||
bool mGotResponseAvailable;
|
||||
};
|
||||
|
||||
class AlternativeDataStreamListener;
|
||||
|
||||
class FetchDriver final : public nsIStreamListener,
|
||||
public nsIChannelEventSink,
|
||||
public nsIInterfaceRequestor,
|
||||
|
@ -146,17 +149,23 @@ private:
|
|||
|
||||
bool mIsTrackingFetch;
|
||||
|
||||
RefPtr<AlternativeDataStreamListener> mAltDataListener;
|
||||
bool mOnStopRequestCalled;
|
||||
|
||||
#ifdef DEBUG
|
||||
bool mResponseAvailableCalled;
|
||||
bool mFetchCalled;
|
||||
#endif
|
||||
|
||||
friend class AlternativeDataStreamListener;
|
||||
|
||||
FetchDriver() = delete;
|
||||
FetchDriver(const FetchDriver&) = delete;
|
||||
FetchDriver& operator=(const FetchDriver&) = delete;
|
||||
~FetchDriver();
|
||||
|
||||
nsresult HttpFetch();
|
||||
|
||||
nsresult HttpFetch(const nsACString& aPreferredAlternativeDataType = EmptyCString());
|
||||
// Returns the filtered response sent to the observer.
|
||||
already_AddRefed<InternalResponse>
|
||||
BeginAndGetFilteredResponse(InternalResponse* aResponse,
|
||||
|
@ -166,6 +175,8 @@ private:
|
|||
void FailWithNetworkError(nsresult rv);
|
||||
|
||||
void SetRequestHeaders(nsIHttpChannel* aChannel) const;
|
||||
|
||||
nsresult FinishOnStopRequest(AlternativeDataStreamListener* aAltDataListener);
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -52,6 +52,8 @@ InternalRequest::GetRequestConstructorCopy(nsIGlobalObject* aGlobal, ErrorResult
|
|||
copy->mRedirectMode = mRedirectMode;
|
||||
copy->mCreatedByFetchEvent = mCreatedByFetchEvent;
|
||||
copy->mContentPolicyTypeOverridden = mContentPolicyTypeOverridden;
|
||||
|
||||
copy->mPreferredAlternativeDataType = mPreferredAlternativeDataType;
|
||||
return copy.forget();
|
||||
}
|
||||
|
||||
|
|
|
@ -552,6 +552,18 @@ public:
|
|||
return mPrincipalInfo;
|
||||
}
|
||||
|
||||
const nsCString&
|
||||
GetPreferredAlternativeDataType() const
|
||||
{
|
||||
return mPreferredAlternativeDataType;
|
||||
}
|
||||
|
||||
void
|
||||
SetPreferredAlternativeDataType(const nsACString& aDataType)
|
||||
{
|
||||
mPreferredAlternativeDataType = aDataType;
|
||||
}
|
||||
|
||||
private:
|
||||
// Does not copy mBodyStream. Use fallible Clone() for complete copy.
|
||||
explicit InternalRequest(const InternalRequest& aOther);
|
||||
|
@ -574,6 +586,8 @@ private:
|
|||
nsCOMPtr<nsIInputStream> mBodyStream;
|
||||
int64_t mBodyLength;
|
||||
|
||||
nsCString mPreferredAlternativeDataType;
|
||||
|
||||
nsContentPolicyType mContentPolicyType;
|
||||
|
||||
// Empty string: no-referrer
|
||||
|
|
|
@ -8,7 +8,9 @@
|
|||
#define mozilla_dom_InternalResponse_h
|
||||
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsICacheInfoChannel.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsProxyRelease.h"
|
||||
|
||||
#include "mozilla/dom/InternalHeaders.h"
|
||||
#include "mozilla/dom/ResponseBinding.h"
|
||||
|
@ -247,6 +249,57 @@ public:
|
|||
void
|
||||
SetPaddingSize(int64_t aPaddingSize);
|
||||
|
||||
void
|
||||
SetAlternativeBody(nsIInputStream* aAlternativeBody)
|
||||
{
|
||||
if (mWrappedResponse) {
|
||||
return mWrappedResponse->SetAlternativeBody(aAlternativeBody);
|
||||
}
|
||||
// A request's body may not be reset once set.
|
||||
MOZ_DIAGNOSTIC_ASSERT(!mAlternativeBody);
|
||||
|
||||
mAlternativeBody = aAlternativeBody;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIInputStream>
|
||||
TakeAlternativeBody()
|
||||
{
|
||||
if (mWrappedResponse) {
|
||||
return mWrappedResponse->TakeAlternativeBody();
|
||||
}
|
||||
|
||||
if (!mAlternativeBody) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// cleanup the non-alternative body here.
|
||||
// Once alternative data is used, the real body is no need anymore.
|
||||
mBody = nullptr;
|
||||
mBodySize = UNKNOWN_BODY_SIZE;
|
||||
return mAlternativeBody.forget();
|
||||
}
|
||||
|
||||
void
|
||||
SetCacheInfoChannel(const nsMainThreadPtrHandle<nsICacheInfoChannel>& aCacheInfoChannel)
|
||||
{
|
||||
if (mWrappedResponse) {
|
||||
return mWrappedResponse->SetCacheInfoChannel(aCacheInfoChannel);
|
||||
}
|
||||
MOZ_ASSERT(!mCacheInfoChannel);
|
||||
mCacheInfoChannel = aCacheInfoChannel;
|
||||
}
|
||||
|
||||
nsMainThreadPtrHandle<nsICacheInfoChannel>
|
||||
TakeCacheInfoChannel()
|
||||
{
|
||||
if (mWrappedResponse) {
|
||||
return mWrappedResponse->TakeCacheInfoChannel();
|
||||
}
|
||||
nsMainThreadPtrHandle<nsICacheInfoChannel> rtn = mCacheInfoChannel;
|
||||
mCacheInfoChannel = nullptr;
|
||||
return rtn;
|
||||
}
|
||||
|
||||
void
|
||||
InitChannelInfo(nsIChannel* aChannel)
|
||||
{
|
||||
|
@ -326,6 +379,11 @@ private:
|
|||
Maybe<uint32_t> mPaddingInfo;
|
||||
int64_t mPaddingSize;
|
||||
nsresult mErrorCode;
|
||||
|
||||
// For alternative data such as JS Bytecode cached in the HTTP cache.
|
||||
nsCOMPtr<nsIInputStream> mAlternativeBody;
|
||||
nsMainThreadPtrHandle<nsICacheInfoChannel> mCacheInfoChannel;
|
||||
|
||||
public:
|
||||
static const int64_t UNKNOWN_BODY_SIZE = -1;
|
||||
static const int64_t UNKNOWN_PADDING_SIZE = -1;
|
||||
|
|
|
@ -100,7 +100,7 @@ public:
|
|||
SetHTMLAttr(nsGkAtoms::scrolling, aScrolling, aError);
|
||||
}
|
||||
|
||||
void GetSrc(nsString& aSrc, nsIPrincipal&)
|
||||
void GetSrc(nsString& aSrc)
|
||||
{
|
||||
GetURIAttr(nsGkAtoms::src, nullptr, aSrc);
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ public:
|
|||
uint32_t GetSandboxFlags();
|
||||
|
||||
// Web IDL binding methods
|
||||
void GetSrc(nsString& aSrc, nsIPrincipal&) const
|
||||
void GetSrc(nsString& aSrc) const
|
||||
{
|
||||
GetURIAttr(nsGkAtoms::src, nullptr, aSrc);
|
||||
}
|
||||
|
|
|
@ -98,7 +98,7 @@ public:
|
|||
{
|
||||
SetHTMLBoolAttr(nsGkAtoms::ismap, aIsMap, aError);
|
||||
}
|
||||
uint32_t Width()
|
||||
MOZ_CAN_RUN_SCRIPT uint32_t Width()
|
||||
{
|
||||
return GetWidthHeightForImage(mCurrentRequest).width;
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ public:
|
|||
{
|
||||
SetUnsignedIntAttr(nsGkAtoms::width, aWidth, 0, aError);
|
||||
}
|
||||
uint32_t Height()
|
||||
MOZ_CAN_RUN_SCRIPT uint32_t Height()
|
||||
{
|
||||
return GetWidthHeightForImage(mCurrentRequest).height;
|
||||
}
|
||||
|
@ -142,10 +142,6 @@ public:
|
|||
{
|
||||
SetHTMLAttr(nsGkAtoms::alt, aAlt, aError);
|
||||
}
|
||||
void GetSrc(nsAString& aSrc, nsIPrincipal&)
|
||||
{
|
||||
GetSrc(aSrc);
|
||||
}
|
||||
void GetSrc(nsAString& aSrc)
|
||||
{
|
||||
GetURIAttr(nsGkAtoms::src, nullptr, aSrc);
|
||||
|
@ -158,7 +154,7 @@ public:
|
|||
{
|
||||
SetHTMLAttr(nsGkAtoms::src, aSrc, aTriggeringPrincipal, aError);
|
||||
}
|
||||
void GetSrcset(nsAString& aSrcset, nsIPrincipal&)
|
||||
void GetSrcset(nsAString& aSrcset)
|
||||
{
|
||||
GetHTMLAttr(nsGkAtoms::srcset, aSrcset);
|
||||
}
|
||||
|
@ -241,8 +237,8 @@ public:
|
|||
return GetReferrerPolicyAsEnum();
|
||||
}
|
||||
|
||||
int32_t X();
|
||||
int32_t Y();
|
||||
MOZ_CAN_RUN_SCRIPT int32_t X();
|
||||
MOZ_CAN_RUN_SCRIPT int32_t Y();
|
||||
void GetLowsrc(nsAString& aLowsrc)
|
||||
{
|
||||
GetURIAttr(nsGkAtoms::lowsrc, nullptr, aLowsrc);
|
||||
|
@ -376,7 +372,7 @@ protected:
|
|||
// only that it is valid.
|
||||
bool TryCreateResponsiveSelector(nsIContent *aSourceNode);
|
||||
|
||||
CSSIntPoint GetXY();
|
||||
MOZ_CAN_RUN_SCRIPT CSSIntPoint GetXY();
|
||||
virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
void UpdateFormOwner();
|
||||
|
||||
|
|
|
@ -568,7 +568,7 @@ public:
|
|||
SetHTMLAttr(nsGkAtoms::formtarget, aValue, aRv);
|
||||
}
|
||||
|
||||
uint32_t Height();
|
||||
MOZ_CAN_RUN_SCRIPT uint32_t Height();
|
||||
|
||||
void SetHeight(uint32_t aValue, ErrorResult& aRv)
|
||||
{
|
||||
|
@ -714,7 +714,7 @@ public:
|
|||
SetUnsignedIntAttr(nsGkAtoms::size, aValue, DEFAULT_COLS, aRv);
|
||||
}
|
||||
|
||||
void GetSrc(nsAString& aValue, nsIPrincipal&)
|
||||
void GetSrc(nsAString& aValue)
|
||||
{
|
||||
GetURIAttr(nsGkAtoms::src, nullptr, aValue);
|
||||
}
|
||||
|
|
|
@ -88,10 +88,6 @@ public:
|
|||
{
|
||||
GetURIAttr(nsGkAtoms::href, nullptr, aValue);
|
||||
}
|
||||
void GetHref(nsString& aValue, nsIPrincipal&)
|
||||
{
|
||||
GetHref(aValue);
|
||||
}
|
||||
void SetHref(const nsAString& aHref, nsIPrincipal& aTriggeringPrincipal, ErrorResult& aRv)
|
||||
{
|
||||
SetHTMLAttr(nsGkAtoms::href, aHref, aTriggeringPrincipal, aRv);
|
||||
|
|
|
@ -442,10 +442,6 @@ public:
|
|||
|
||||
MediaError* GetError() const;
|
||||
|
||||
void GetSrc(nsString& aSrc, nsIPrincipal&)
|
||||
{
|
||||
GetSrc(aSrc);
|
||||
}
|
||||
void SetSrc(const nsAString& aSrc, nsIPrincipal& aTriggeringPrincipal, ErrorResult& aRv)
|
||||
{
|
||||
SetHTMLAttr(nsGkAtoms::src, aSrc, aTriggeringPrincipal, aRv);
|
||||
|
|
|
@ -54,7 +54,7 @@ public:
|
|||
MediaSource* GetSrcMediaSource() { return mSrcMediaSource; };
|
||||
|
||||
// WebIDL
|
||||
void GetSrc(nsString& aSrc, nsIPrincipal&)
|
||||
void GetSrc(nsString& aSrc)
|
||||
{
|
||||
GetURIAttr(nsGkAtoms::src, nullptr, aSrc);
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ public:
|
|||
SetHTMLAttr(nsGkAtoms::type, aType, rv);
|
||||
}
|
||||
|
||||
void GetSrcset(DOMString& aSrcset, nsIPrincipal&)
|
||||
void GetSrcset(DOMString& aSrcset)
|
||||
{
|
||||
GetHTMLAttr(nsGkAtoms::srcset, aSrcset);
|
||||
}
|
||||
|
|
|
@ -65,7 +65,9 @@ public:
|
|||
return mImageIsResized;
|
||||
}
|
||||
already_AddRefed<imgIRequest> GetImageRequest(ErrorResult& aRv);
|
||||
void ShrinkToFit();
|
||||
// ShrinkToFit is called from xpidl methods and we don't have a good
|
||||
// way to mark those MOZ_CAN_RUN_SCRIPT yet.
|
||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY void ShrinkToFit();
|
||||
void RestoreImage();
|
||||
void RestoreImageTo(int32_t aX, int32_t aY)
|
||||
{
|
||||
|
|
|
@ -176,6 +176,7 @@ public:
|
|||
aError);
|
||||
}
|
||||
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
void GetInnerText(mozilla::dom::DOMString& aValue, mozilla::ErrorResult& aError);
|
||||
void SetInnerText(const nsAString& aValue);
|
||||
|
||||
|
@ -265,6 +266,7 @@ public:
|
|||
* Pass a reference to the image request, since the method may change the
|
||||
* value and we want to use the updated value.
|
||||
*/
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
nsSize GetWidthHeightForImage(RefPtr<imgRequestProxy>& aImageRequest);
|
||||
|
||||
// XPIDL methods
|
||||
|
|
|
@ -209,11 +209,7 @@ public:
|
|||
mozilla::ErrorResult& rv);
|
||||
void Writeln(JSContext* cx, const mozilla::dom::Sequence<nsString>& aText,
|
||||
mozilla::ErrorResult& rv);
|
||||
void GetDesignMode(nsAString& aDesignMode,
|
||||
nsIPrincipal& aSubjectPrincipal)
|
||||
{
|
||||
GetDesignMode(aDesignMode);
|
||||
}
|
||||
// XPCOM GetDesignMode is fine.
|
||||
void SetDesignMode(const nsAString& aDesignMode,
|
||||
nsIPrincipal& aSubjectPrincipal,
|
||||
mozilla::ErrorResult& rv);
|
||||
|
|
|
@ -918,7 +918,7 @@ MediaDecoder::GetCompositor()
|
|||
ownerDoc ? nsContentUtils::LayerManagerForDocument(ownerDoc) : nullptr;
|
||||
RefPtr<KnowsCompositor> knows =
|
||||
layerManager ? layerManager->AsKnowsCompositor() : nullptr;
|
||||
return knows.forget();
|
||||
return knows ? knows->GetForMedia().forget() : nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -123,7 +123,10 @@ private:
|
|||
void Set(VideoFrameRate aRate) { mRate = aRate; }
|
||||
void Set(layers::KnowsCompositor* aKnowsCompositor)
|
||||
{
|
||||
mKnowsCompositor = aKnowsCompositor;
|
||||
if (aKnowsCompositor) {
|
||||
mKnowsCompositor = aKnowsCompositor;
|
||||
MOZ_ASSERT(aKnowsCompositor->IsThreadSafe());
|
||||
}
|
||||
}
|
||||
void Set(TrackInfo::TrackType aType)
|
||||
{
|
||||
|
|
|
@ -473,6 +473,7 @@ typedef enum {
|
|||
, NPNVsupportsCompositingCoreAnimationPluginsBool = 74656 /* TRUE if the browser supports
|
||||
CA model compositing */
|
||||
#endif
|
||||
, NPNVLast
|
||||
} NPNVariable;
|
||||
|
||||
typedef enum {
|
||||
|
|
|
@ -373,30 +373,11 @@ struct ParamTraits<NPRect>
|
|||
};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<NPWindowType>
|
||||
{
|
||||
typedef NPWindowType paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam)
|
||||
{
|
||||
aMsg->WriteInt16(int16_t(aParam));
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
|
||||
{
|
||||
int16_t result;
|
||||
if (aMsg->ReadInt16(aIter, &result)) {
|
||||
*aResult = paramType(result);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void Log(const paramType& aParam, std::wstring* aLog)
|
||||
{
|
||||
aLog->append(StringPrintf(L"%d", int16_t(aParam)));
|
||||
}
|
||||
};
|
||||
struct ParamTraits<NPWindowType> :
|
||||
public ContiguousEnumSerializerInclusive<NPWindowType,
|
||||
NPWindowType::NPWindowTypeWindow,
|
||||
NPWindowType::NPWindowTypeDrawable>
|
||||
{};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::plugins::NPRemoteWindow>
|
||||
|
@ -670,76 +651,26 @@ struct ParamTraits<mozilla::plugins::IPCByteRange>
|
|||
};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<NPNVariable>
|
||||
{
|
||||
typedef NPNVariable paramType;
|
||||
struct ParamTraits<NPNVariable> :
|
||||
public ContiguousEnumSerializer<NPNVariable,
|
||||
NPNVariable::NPNVxDisplay,
|
||||
NPNVariable::NPNVLast>
|
||||
{};
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam)
|
||||
{
|
||||
WriteParam(aMsg, int(aParam));
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
|
||||
{
|
||||
int intval;
|
||||
if (ReadParam(aMsg, aIter, &intval)) {
|
||||
*aResult = paramType(intval);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
// The only accepted value is NPNURLVariable::NPNURLVProxy
|
||||
template<>
|
||||
struct ParamTraits<NPNURLVariable> :
|
||||
public ContiguousEnumSerializerInclusive<NPNURLVariable,
|
||||
NPNURLVariable::NPNURLVProxy,
|
||||
NPNURLVariable::NPNURLVProxy>
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct ParamTraits<NPNURLVariable>
|
||||
{
|
||||
typedef NPNURLVariable paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam)
|
||||
{
|
||||
WriteParam(aMsg, int(aParam));
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
|
||||
{
|
||||
int intval;
|
||||
if (ReadParam(aMsg, aIter, &intval) &&
|
||||
intval == NPNURLVProxy) {
|
||||
*aResult = paramType(intval);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<>
|
||||
struct ParamTraits<NPCoordinateSpace>
|
||||
{
|
||||
typedef NPCoordinateSpace paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam)
|
||||
{
|
||||
WriteParam(aMsg, int32_t(aParam));
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
|
||||
{
|
||||
int32_t intval;
|
||||
if (ReadParam(aMsg, aIter, &intval)) {
|
||||
switch (intval) {
|
||||
case NPCoordinateSpacePlugin:
|
||||
case NPCoordinateSpaceWindow:
|
||||
case NPCoordinateSpaceFlippedWindow:
|
||||
case NPCoordinateSpaceScreen:
|
||||
case NPCoordinateSpaceFlippedScreen:
|
||||
*aResult = paramType(intval);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
struct ParamTraits<NPCoordinateSpace> :
|
||||
public ContiguousEnumSerializerInclusive<NPCoordinateSpace,
|
||||
NPCoordinateSpace::NPCoordinateSpacePlugin,
|
||||
NPCoordinateSpace::NPCoordinateSpaceFlippedScreen>
|
||||
{};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::plugins::NPAudioDeviceChangeDetailsIPC>
|
||||
|
|
|
@ -9,13 +9,13 @@
|
|||
#include "mozilla/dom/WebCryptoCommon.h"
|
||||
#include "mozilla/ipc/PBackgroundChild.h"
|
||||
#include "mozilla/ipc/BackgroundChild.h"
|
||||
#include "mozilla/dom/WebAuthnTransactionChild.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsICryptoHash.h"
|
||||
#include "nsIEffectiveTLDService.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsURLParsers.h"
|
||||
#include "U2FTransactionChild.h"
|
||||
#include "U2FUtil.h"
|
||||
#include "hasht.h"
|
||||
|
||||
|
@ -293,9 +293,9 @@ U2F::~U2F()
|
|||
}
|
||||
|
||||
if (mChild) {
|
||||
RefPtr<U2FTransactionChild> c;
|
||||
RefPtr<WebAuthnTransactionChild> c;
|
||||
mChild.swap(c);
|
||||
c->Send__delete__(c);
|
||||
c->Disconnect();
|
||||
}
|
||||
|
||||
mRegisterCallback.reset();
|
||||
|
@ -437,8 +437,8 @@ U2F::Register(const nsAString& aAppId,
|
|||
}
|
||||
|
||||
void
|
||||
U2F::FinishRegister(const uint64_t& aTransactionId,
|
||||
nsTArray<uint8_t>& aRegBuffer)
|
||||
U2F::FinishMakeCredential(const uint64_t& aTransactionId,
|
||||
nsTArray<uint8_t>& aRegBuffer)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
|
@ -566,9 +566,9 @@ U2F::Sign(const nsAString& aAppId,
|
|||
}
|
||||
|
||||
void
|
||||
U2F::FinishSign(const uint64_t& aTransactionId,
|
||||
nsTArray<uint8_t>& aCredentialId,
|
||||
nsTArray<uint8_t>& aSigBuffer)
|
||||
U2F::FinishGetAssertion(const uint64_t& aTransactionId,
|
||||
nsTArray<uint8_t>& aCredentialId,
|
||||
nsTArray<uint8_t>& aSigBuffer)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
|
@ -749,7 +749,7 @@ U2F::MaybeCreateBackgroundActor()
|
|||
return false;
|
||||
}
|
||||
|
||||
RefPtr<U2FTransactionChild> mgr(new U2FTransactionChild(this));
|
||||
RefPtr<WebAuthnTransactionChild> mgr(new WebAuthnTransactionChild(this));
|
||||
PWebAuthnTransactionChild* constructedMgr =
|
||||
actorChild->SendPWebAuthnTransactionConstructor(mgr);
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "mozilla/dom/Nullable.h"
|
||||
#include "mozilla/dom/U2FBinding.h"
|
||||
#include "mozilla/dom/WebAuthnManagerBase.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/MozPromise.h"
|
||||
#include "nsProxyRelease.h"
|
||||
|
@ -24,7 +25,7 @@ class nsISerialEventTarget;
|
|||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class U2FTransactionChild;
|
||||
class WebAuthnTransactionChild;
|
||||
class U2FRegisterCallback;
|
||||
class U2FSignCallback;
|
||||
|
||||
|
@ -59,6 +60,7 @@ private:
|
|||
};
|
||||
|
||||
class U2F final : public nsIDOMEventListener
|
||||
, public WebAuthnManagerBase
|
||||
, public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
|
@ -97,18 +99,22 @@ public:
|
|||
const Optional<Nullable<int32_t>>& opt_aTimeoutSeconds,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void
|
||||
FinishRegister(const uint64_t& aTransactionId, nsTArray<uint8_t>& aRegBuffer);
|
||||
// WebAuthnManagerBase
|
||||
|
||||
void
|
||||
FinishSign(const uint64_t& aTransactionId,
|
||||
nsTArray<uint8_t>& aCredentialId,
|
||||
nsTArray<uint8_t>& aSigBuffer);
|
||||
FinishMakeCredential(const uint64_t& aTransactionId,
|
||||
nsTArray<uint8_t>& aRegBuffer) override;
|
||||
|
||||
void
|
||||
RequestAborted(const uint64_t& aTransactionId, const nsresult& aError);
|
||||
FinishGetAssertion(const uint64_t& aTransactionId,
|
||||
nsTArray<uint8_t>& aCredentialId,
|
||||
nsTArray<uint8_t>& aSigBuffer) override;
|
||||
|
||||
void ActorDestroyed();
|
||||
void
|
||||
RequestAborted(const uint64_t& aTransactionId,
|
||||
const nsresult& aError) override;
|
||||
|
||||
void ActorDestroyed() override;
|
||||
|
||||
private:
|
||||
~U2F();
|
||||
|
@ -135,7 +141,7 @@ private:
|
|||
Maybe<nsMainThreadPtrHandle<U2FSignCallback>> mSignCallback;
|
||||
|
||||
// IPC Channel to the parent process.
|
||||
RefPtr<U2FTransactionChild> mChild;
|
||||
RefPtr<WebAuthnTransactionChild> mChild;
|
||||
|
||||
// The current transaction, if any.
|
||||
Maybe<U2FTransaction> mTransaction;
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#include "U2FTransactionChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
U2FTransactionChild::RecvConfirmRegister(const uint64_t& aTransactionId,
|
||||
nsTArray<uint8_t>&& aRegBuffer)
|
||||
{
|
||||
mU2F->FinishRegister(aTransactionId, aRegBuffer);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
U2FTransactionChild::RecvConfirmSign(const uint64_t& aTransactionId,
|
||||
nsTArray<uint8_t>&& aCredentialId,
|
||||
nsTArray<uint8_t>&& aBuffer)
|
||||
{
|
||||
mU2F->FinishSign(aTransactionId, aCredentialId, aBuffer);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
U2FTransactionChild::RecvAbort(const uint64_t& aTransactionId,
|
||||
const nsresult& aError)
|
||||
{
|
||||
mU2F->RequestAborted(aTransactionId, aError);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
void
|
||||
U2FTransactionChild::ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
mU2F->ActorDestroyed();
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -1,50 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_dom_U2FTransactionChild_h
|
||||
#define mozilla_dom_U2FTransactionChild_h
|
||||
|
||||
#include "mozilla/dom/WebAuthnTransactionChildBase.h"
|
||||
|
||||
/*
|
||||
* Child process IPC implementation for U2F API. Receives results of U2F
|
||||
* transactions from the parent process, and sends them to the U2FManager
|
||||
* to either cancel the transaction, or be formatted and relayed to content.
|
||||
*/
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class U2FTransactionChild final : public WebAuthnTransactionChildBase
|
||||
{
|
||||
public:
|
||||
explicit U2FTransactionChild(U2F* aU2F) : mU2F(aU2F) {
|
||||
MOZ_ASSERT(mU2F);
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RecvConfirmRegister(const uint64_t& aTransactionId,
|
||||
nsTArray<uint8_t>&& aRegBuffer) override;
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RecvConfirmSign(const uint64_t& aTransactionId,
|
||||
nsTArray<uint8_t>&& aCredentialId,
|
||||
nsTArray<uint8_t>&& aBuffer) override;
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RecvAbort(const uint64_t& aTransactionId, const nsresult& aError) override;
|
||||
|
||||
void ActorDestroy(ActorDestroyReason why) override;
|
||||
|
||||
private:
|
||||
// ~U2F() will destroy child actors.
|
||||
U2F* mU2F;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif //mozilla_dom_U2FTransactionChild_h
|
|
@ -1,52 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#include "U2FTransactionParent.h"
|
||||
#include "mozilla/dom/U2FTokenManager.h"
|
||||
#include "mozilla/ipc/BackgroundParent.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
U2FTransactionParent::RecvRequestRegister(const uint64_t& aTransactionId,
|
||||
const WebAuthnMakeCredentialInfo& aTransactionInfo)
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
U2FTokenManager* mgr = U2FTokenManager::Get();
|
||||
mgr->Register(this, aTransactionId, aTransactionInfo);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
U2FTransactionParent::RecvRequestSign(const uint64_t& aTransactionId,
|
||||
const WebAuthnGetAssertionInfo& aTransactionInfo)
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
U2FTokenManager* mgr = U2FTokenManager::Get();
|
||||
mgr->Sign(this, aTransactionId, aTransactionInfo);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
U2FTransactionParent::RecvRequestCancel(const uint64_t& aTransactionId)
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
U2FTokenManager* mgr = U2FTokenManager::Get();
|
||||
mgr->Cancel(this, aTransactionId);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
void
|
||||
U2FTransactionParent::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
U2FTokenManager* mgr = U2FTokenManager::Get();
|
||||
mgr->MaybeClearTransaction(this);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -1,47 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_dom_U2FTransactionParent_h
|
||||
#define mozilla_dom_U2FTransactionParent_h
|
||||
|
||||
#include "mozilla/dom/PWebAuthnTransactionParent.h"
|
||||
|
||||
/*
|
||||
* Parent process IPC implementation for WebAuthn and U2F API. Receives
|
||||
* authentication data to be either registered or signed by a key, passes
|
||||
* information to U2FTokenManager.
|
||||
*/
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class U2FTransactionParent final : public PWebAuthnTransactionParent
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING(U2FTransactionParent);
|
||||
U2FTransactionParent() = default;
|
||||
|
||||
virtual mozilla::ipc::IPCResult
|
||||
RecvRequestRegister(const uint64_t& aTransactionId,
|
||||
const WebAuthnMakeCredentialInfo& aTransactionInfo) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult
|
||||
RecvRequestSign(const uint64_t& aTransactionId,
|
||||
const WebAuthnGetAssertionInfo& aTransactionInfo) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult
|
||||
RecvRequestCancel(const uint64_t& aTransactionId) override;
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
|
||||
private:
|
||||
~U2FTransactionParent() = default;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif //mozilla_dom_U2FTransactionParent_h
|
|
@ -15,8 +15,6 @@ EXPORTS.mozilla.dom += [
|
|||
|
||||
UNIFIED_SOURCES += [
|
||||
'U2F.cpp',
|
||||
'U2FTransactionChild.cpp',
|
||||
'U2FTransactionParent.cpp',
|
||||
]
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
|
|
@ -6,6 +6,10 @@ var VRSimulationDriver = (function() {
|
|||
"use strict";
|
||||
|
||||
var AttachWebVRDisplay = function() {
|
||||
if (vrMockDisplay) {
|
||||
// Avoid creating multiple displays
|
||||
return Promise.resolve(vrMockDisplay);
|
||||
}
|
||||
var promise = VRServiceTest.attachVRDisplay("VRDisplayTest");
|
||||
promise.then(function (display) {
|
||||
assert_true(display != null, "AttachWebVRDisplay should success.");
|
||||
|
|
|
@ -14,7 +14,8 @@ skip-if = (os != "win" && release_or_beta) # Enable Linux after Bug 1310655
|
|||
[test_vrDisplay_exitPresent.html]
|
||||
skip-if = (os != "win" && release_or_beta) # Enable Linux after Bug 1310655
|
||||
[test_vrDisplay_getFrameData.html]
|
||||
skip-if = (os != "win" && release_or_beta) # Enable Linux after Bug 1310655
|
||||
# Enable Linux after Bug 1310655, enable Android after Bug 1348246
|
||||
skip-if = (os != "win" && release_or_beta) || (os == "android")
|
||||
[test_vrDisplay_onvrdisplaydeactivate_crosscontent.html]
|
||||
skip-if = true
|
||||
[test_vrDisplay_requestPresent.html]
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
function runVRTest(callback) {
|
||||
SpecialPowers.pushPrefEnv({"set" : [["dom.vr.puppet.enabled", true],
|
||||
["dom.vr.require-gesture", false],
|
||||
["dom.vr.test.enabled", true]]},
|
||||
["dom.vr.test.enabled", true],
|
||||
["dom.vr.display.enumerate.interval", 0],
|
||||
["dom.vr.controller.enumerate.interval", 0]]},
|
||||
() => {
|
||||
VRServiceTest = navigator.requestVRServiceTest();
|
||||
callback();
|
||||
|
|
|
@ -38,12 +38,13 @@
|
|||
function startTest() {
|
||||
promise_test((test) => {
|
||||
listenControllerEvents();
|
||||
return navigator.getVRDisplays().then((displays) => {
|
||||
vrDisplay = displays[0];
|
||||
assert_equals(displays.length, 1, "displays.length must be one after attach.");
|
||||
assert_equals(displays[0].displayId, 1, "displayId must be one.");
|
||||
addController();
|
||||
addController();
|
||||
return VRSimulationDriver.AttachWebVRDisplay().then(() => {
|
||||
return navigator.getVRDisplays().then((displays) => {
|
||||
vrDisplay = displays[0];
|
||||
assert_equals(displays.length, 1, "displays.length must be one after attach.");
|
||||
addController();
|
||||
addController();
|
||||
});
|
||||
});
|
||||
}, "Finish to add VRDisplay.");
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="VRSimulationDriver.js"></script>
|
||||
<script src="runVRTest.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -35,12 +36,14 @@
|
|||
var img = document.createElement('img');
|
||||
img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACw=";
|
||||
|
||||
return navigator.getVRDisplays().then((displays) => {
|
||||
assert_equals(displays.length, 1, "displays.length must be one after attach.");
|
||||
vrDisplay = displays[0];
|
||||
var frameData = new VRFrameData();
|
||||
return vrDisplay.requestPresent([{source: canvas}]).then(() => {
|
||||
requestPresentTest();
|
||||
return VRSimulationDriver.AttachWebVRDisplay().then(() => {
|
||||
return navigator.getVRDisplays().then((displays) => {
|
||||
assert_equals(displays.length, 1, "displays.length must be one after attach.");
|
||||
vrDisplay = displays[0];
|
||||
var frameData = new VRFrameData();
|
||||
return vrDisplay.requestPresent([{source: canvas}]).then(() => {
|
||||
requestPresentTest();
|
||||
});
|
||||
});
|
||||
});
|
||||
}, "Finish running WebVR Canvas2D test.");
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="VRSimulationDriver.js"></script>
|
||||
<script src="runVRTest.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -17,23 +18,29 @@
|
|||
});
|
||||
}
|
||||
var initVRPresentation = function(content) {
|
||||
return content.navigator.getVRDisplays().then((displays) => {
|
||||
return VRSimulationDriver.AttachWebVRDisplay().then(() => {
|
||||
return content.navigator.getVRDisplays().then((displays) => {
|
||||
content.vrDisplay = displays[0];
|
||||
content.canvas = content.document.createElement("canvas");
|
||||
content.canvas.id = "vrCanvas";
|
||||
return content.vrDisplay.requestPresent([{source:content.canvas}]);
|
||||
});
|
||||
});
|
||||
}
|
||||
function startTest() {
|
||||
var ifr1 = document.getElementById("iframe1");
|
||||
var ifr2 = document.getElementById("iframe2");
|
||||
var frame1 = ifr1.contentWindow;
|
||||
var frame2 = ifr2.contentWindow;
|
||||
initVRPresentation(frame1).then(() => {
|
||||
promise_test((test) => {
|
||||
return promise_rejects(test, null, testExitPresentOnOtherIframe(frame2));
|
||||
}, "We cannot exist VR presentation established by another content, this promise is expected to be rejected.")
|
||||
});
|
||||
promise_test((test) => {
|
||||
return VRSimulationDriver.AttachWebVRDisplay().then(() => {
|
||||
return initVRPresentation(frame1).then(() => {
|
||||
promise_test((test) => {
|
||||
return promise_rejects(test, null, testExitPresentOnOtherIframe(frame2));
|
||||
}, "We cannot exit VR presentation established by another content, this promise is expected to be rejected.")
|
||||
});
|
||||
});
|
||||
}, "Finish running WebVR exitPresent test.");
|
||||
}
|
||||
runVRTest(startTest);
|
||||
</script>
|
||||
|
|
|
@ -6,6 +6,10 @@ var VRSimulationDriver = (function() {
|
|||
"use strict";
|
||||
|
||||
var AttachWebVRDisplay = function() {
|
||||
if (vrMockDisplay) {
|
||||
// Avoid creating multiple displays
|
||||
return Promise.resolve(vrMockDisplay);
|
||||
}
|
||||
var promise = VRServiceTest.attachVRDisplay("VRDisplayTest");
|
||||
promise.then(function (display) {
|
||||
vrMockDisplay = display;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# WebVR Reftests
|
||||
# Please confirm there is no other VR display connected. Otherwise, VRPuppetDisplay can't be attached.
|
||||
default-preferences pref(dom.vr.puppet.enabled,true) pref(dom.vr.test.enabled,true) pref(dom.vr.require-gesture,false) pref(dom.vr.puppet.submitframe,1) pref(dom.vr.display.rafMaxDuration,200)
|
||||
default-preferences pref(dom.vr.puppet.enabled,true) pref(dom.vr.test.enabled,true) pref(dom.vr.require-gesture,false) pref(dom.vr.puppet.submitframe,1) pref(dom.vr.display.rafMaxDuration,200) pref(dom.vr.display.enumerate.interval,0) pref(dom.vr.controller.enumerate.interval,0)
|
||||
|
||||
# VR SubmitFrame is only implemented for D3D11.1 and MacOSX now.
|
||||
# Our Windows 7 test machines don't support D3D11.1, so we run these tests on Windows 8+ only.
|
||||
|
|
|
@ -52,12 +52,15 @@ struct WebAuthnGetAssertionInfo {
|
|||
|
||||
async protocol PWebAuthnTransaction {
|
||||
manager PBackground;
|
||||
|
||||
parent:
|
||||
async __delete__();
|
||||
async RequestRegister(uint64_t aTransactionId, WebAuthnMakeCredentialInfo aTransactionInfo);
|
||||
async RequestSign(uint64_t aTransactionId, WebAuthnGetAssertionInfo aTransactionInfo);
|
||||
async RequestCancel(uint64_t aTransactionId);
|
||||
async DestroyMe();
|
||||
|
||||
child:
|
||||
async __delete__();
|
||||
async ConfirmRegister(uint64_t aTransactionId, uint8_t[] RegBuffer);
|
||||
async ConfirmSign(uint64_t aTransactionId, uint8_t[] CredentialID, uint8_t[] ReplyBuffer);
|
||||
async Abort(uint64_t aTransactionId, nsresult Error);
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#include "nsNetCID.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "WebAuthnCoseIdentifiers.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "mozilla/dom/AuthenticatorAttestationResponse.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/PWebAuthnTransaction.h"
|
||||
|
@ -40,7 +39,6 @@ const uint8_t FLAG_UV = 0x04; // User was Verified (biometrics, etc.); this
|
|||
**********************************************************************/
|
||||
|
||||
namespace {
|
||||
StaticRefPtr<WebAuthnManager> gWebAuthnManager;
|
||||
static mozilla::LazyLogModule gWebAuthnManagerLog("webauthnmanager");
|
||||
}
|
||||
|
||||
|
@ -147,37 +145,29 @@ RelaxSameOrigin(nsPIDOMWindowInner* aParent,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
ListenForVisibilityEvents(nsPIDOMWindowInner* aParent,
|
||||
WebAuthnManager* aListener)
|
||||
void
|
||||
WebAuthnManager::ListenForVisibilityEvents()
|
||||
{
|
||||
MOZ_ASSERT(aParent);
|
||||
MOZ_ASSERT(aListener);
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = aParent->GetExtantDoc();
|
||||
nsCOMPtr<nsIDocument> doc = mParent->GetExtantDoc();
|
||||
if (NS_WARN_IF(!doc)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsresult rv = doc->AddSystemEventListener(kVisibilityChange, aListener,
|
||||
nsresult rv = doc->AddSystemEventListener(kVisibilityChange, this,
|
||||
/* use capture */ true,
|
||||
/* wants untrusted */ false);
|
||||
Unused << NS_WARN_IF(NS_FAILED(rv));
|
||||
}
|
||||
|
||||
static void
|
||||
StopListeningForVisibilityEvents(nsPIDOMWindowInner* aParent,
|
||||
WebAuthnManager* aListener)
|
||||
void
|
||||
WebAuthnManager::StopListeningForVisibilityEvents()
|
||||
{
|
||||
MOZ_ASSERT(aParent);
|
||||
MOZ_ASSERT(aListener);
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = aParent->GetExtantDoc();
|
||||
nsCOMPtr<nsIDocument> doc = mParent->GetExtantDoc();
|
||||
if (NS_WARN_IF(!doc)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsresult rv = doc->RemoveSystemEventListener(kVisibilityChange, aListener,
|
||||
nsresult rv = doc->RemoveSystemEventListener(kVisibilityChange, this,
|
||||
/* use capture */ true);
|
||||
Unused << NS_WARN_IF(NS_FAILED(rv));
|
||||
}
|
||||
|
@ -186,16 +176,18 @@ StopListeningForVisibilityEvents(nsPIDOMWindowInner* aParent,
|
|||
* WebAuthnManager Implementation
|
||||
**********************************************************************/
|
||||
|
||||
WebAuthnManager::WebAuthnManager()
|
||||
WebAuthnManager::WebAuthnManager(nsPIDOMWindowInner* aParent)
|
||||
: mParent(aParent)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aParent);
|
||||
}
|
||||
|
||||
void
|
||||
WebAuthnManager::ClearTransaction()
|
||||
{
|
||||
if (!NS_WARN_IF(mTransaction.isNothing())) {
|
||||
StopListeningForVisibilityEvents(mTransaction.ref().mParent, this);
|
||||
StopListeningForVisibilityEvents();
|
||||
}
|
||||
|
||||
mTransaction.reset();
|
||||
|
@ -233,7 +225,7 @@ WebAuthnManager::~WebAuthnManager()
|
|||
if (mChild) {
|
||||
RefPtr<WebAuthnTransactionChild> c;
|
||||
mChild.swap(c);
|
||||
c->Send__delete__(c);
|
||||
c->Disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -251,7 +243,7 @@ WebAuthnManager::MaybeCreateBackgroundActor()
|
|||
return false;
|
||||
}
|
||||
|
||||
RefPtr<WebAuthnTransactionChild> mgr(new WebAuthnTransactionChild());
|
||||
RefPtr<WebAuthnTransactionChild> mgr(new WebAuthnTransactionChild(this));
|
||||
PWebAuthnTransactionChild* constructedMgr =
|
||||
actor->SendPWebAuthnTransactionConstructor(mgr);
|
||||
|
||||
|
@ -265,42 +257,17 @@ WebAuthnManager::MaybeCreateBackgroundActor()
|
|||
return true;
|
||||
}
|
||||
|
||||
//static
|
||||
WebAuthnManager*
|
||||
WebAuthnManager::GetOrCreate()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (gWebAuthnManager) {
|
||||
return gWebAuthnManager;
|
||||
}
|
||||
|
||||
gWebAuthnManager = new WebAuthnManager();
|
||||
ClearOnShutdown(&gWebAuthnManager);
|
||||
return gWebAuthnManager;
|
||||
}
|
||||
|
||||
//static
|
||||
WebAuthnManager*
|
||||
WebAuthnManager::Get()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
return gWebAuthnManager;
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
WebAuthnManager::MakeCredential(nsPIDOMWindowInner* aParent,
|
||||
const MakePublicKeyCredentialOptions& aOptions,
|
||||
WebAuthnManager::MakeCredential(const MakePublicKeyCredentialOptions& aOptions,
|
||||
const Optional<OwningNonNull<AbortSignal>>& aSignal)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aParent);
|
||||
|
||||
if (mTransaction.isSome()) {
|
||||
CancelTransaction(NS_ERROR_ABORT);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aParent);
|
||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(mParent);
|
||||
|
||||
ErrorResult rv;
|
||||
RefPtr<Promise> promise = Promise::Create(global, rv);
|
||||
|
@ -316,7 +283,7 @@ WebAuthnManager::MakeCredential(nsPIDOMWindowInner* aParent,
|
|||
|
||||
nsString origin;
|
||||
nsCString rpId;
|
||||
rv = GetOrigin(aParent, origin, rpId);
|
||||
rv = GetOrigin(mParent, origin, rpId);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
promise->MaybeReject(rv);
|
||||
return promise.forget();
|
||||
|
@ -354,7 +321,7 @@ WebAuthnManager::MakeCredential(nsPIDOMWindowInner* aParent,
|
|||
// Otherwise, reject promise with a DOMException whose name is
|
||||
// "SecurityError", and terminate this algorithm.
|
||||
|
||||
if (NS_FAILED(RelaxSameOrigin(aParent, aOptions.mRp.mId.Value(), rpId))) {
|
||||
if (NS_FAILED(RelaxSameOrigin(mParent, aOptions.mRp.mId.Value(), rpId))) {
|
||||
promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return promise.forget();
|
||||
}
|
||||
|
@ -498,7 +465,7 @@ WebAuthnManager::MakeCredential(nsPIDOMWindowInner* aParent,
|
|||
extensions,
|
||||
authSelection);
|
||||
|
||||
ListenForVisibilityEvents(aParent, this);
|
||||
ListenForVisibilityEvents();
|
||||
|
||||
AbortSignal* signal = nullptr;
|
||||
if (aSignal.WasPassed()) {
|
||||
|
@ -507,8 +474,7 @@ WebAuthnManager::MakeCredential(nsPIDOMWindowInner* aParent,
|
|||
}
|
||||
|
||||
MOZ_ASSERT(mTransaction.isNothing());
|
||||
mTransaction = Some(WebAuthnTransaction(aParent,
|
||||
promise,
|
||||
mTransaction = Some(WebAuthnTransaction(promise,
|
||||
rpIdHash,
|
||||
clientDataJSON,
|
||||
signal));
|
||||
|
@ -518,18 +484,16 @@ WebAuthnManager::MakeCredential(nsPIDOMWindowInner* aParent,
|
|||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
WebAuthnManager::GetAssertion(nsPIDOMWindowInner* aParent,
|
||||
const PublicKeyCredentialRequestOptions& aOptions,
|
||||
WebAuthnManager::GetAssertion(const PublicKeyCredentialRequestOptions& aOptions,
|
||||
const Optional<OwningNonNull<AbortSignal>>& aSignal)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aParent);
|
||||
|
||||
if (mTransaction.isSome()) {
|
||||
CancelTransaction(NS_ERROR_ABORT);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aParent);
|
||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(mParent);
|
||||
|
||||
ErrorResult rv;
|
||||
RefPtr<Promise> promise = Promise::Create(global, rv);
|
||||
|
@ -545,7 +509,7 @@ WebAuthnManager::GetAssertion(nsPIDOMWindowInner* aParent,
|
|||
|
||||
nsString origin;
|
||||
nsCString rpId;
|
||||
rv = GetOrigin(aParent, origin, rpId);
|
||||
rv = GetOrigin(mParent, origin, rpId);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
promise->MaybeReject(rv);
|
||||
return promise.forget();
|
||||
|
@ -571,7 +535,7 @@ WebAuthnManager::GetAssertion(nsPIDOMWindowInner* aParent,
|
|||
// Otherwise, reject promise with a DOMException whose name is
|
||||
// "SecurityError", and terminate this algorithm.
|
||||
|
||||
if (NS_FAILED(RelaxSameOrigin(aParent, aOptions.mRpId.Value(), rpId))) {
|
||||
if (NS_FAILED(RelaxSameOrigin(mParent, aOptions.mRpId.Value(), rpId))) {
|
||||
promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return promise.forget();
|
||||
}
|
||||
|
@ -661,7 +625,7 @@ WebAuthnManager::GetAssertion(nsPIDOMWindowInner* aParent,
|
|||
allowList,
|
||||
extensions);
|
||||
|
||||
ListenForVisibilityEvents(aParent, this);
|
||||
ListenForVisibilityEvents();
|
||||
|
||||
AbortSignal* signal = nullptr;
|
||||
if (aSignal.WasPassed()) {
|
||||
|
@ -670,8 +634,7 @@ WebAuthnManager::GetAssertion(nsPIDOMWindowInner* aParent,
|
|||
}
|
||||
|
||||
MOZ_ASSERT(mTransaction.isNothing());
|
||||
mTransaction = Some(WebAuthnTransaction(aParent,
|
||||
promise,
|
||||
mTransaction = Some(WebAuthnTransaction(promise,
|
||||
rpIdHash,
|
||||
clientDataJSON,
|
||||
signal));
|
||||
|
@ -681,17 +644,15 @@ WebAuthnManager::GetAssertion(nsPIDOMWindowInner* aParent,
|
|||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
WebAuthnManager::Store(nsPIDOMWindowInner* aParent,
|
||||
const Credential& aCredential)
|
||||
WebAuthnManager::Store(const Credential& aCredential)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aParent);
|
||||
|
||||
if (mTransaction.isSome()) {
|
||||
CancelTransaction(NS_ERROR_ABORT);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aParent);
|
||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(mParent);
|
||||
|
||||
ErrorResult rv;
|
||||
RefPtr<Promise> promise = Promise::Create(global, rv);
|
||||
|
@ -816,12 +777,12 @@ WebAuthnManager::FinishMakeCredential(const uint64_t& aTransactionId,
|
|||
// values returned from the authenticator as well as the clientDataJSON
|
||||
// computed earlier.
|
||||
RefPtr<AuthenticatorAttestationResponse> attestation =
|
||||
new AuthenticatorAttestationResponse(mTransaction.ref().mParent);
|
||||
new AuthenticatorAttestationResponse(mParent);
|
||||
attestation->SetClientDataJSON(clientDataBuf);
|
||||
attestation->SetAttestationObject(attObj);
|
||||
|
||||
RefPtr<PublicKeyCredential> credential =
|
||||
new PublicKeyCredential(mTransaction.ref().mParent);
|
||||
new PublicKeyCredential(mParent);
|
||||
credential->SetId(keyHandleBase64Url);
|
||||
credential->SetType(NS_LITERAL_STRING("public-key"));
|
||||
credential->SetRawId(keyHandleBuf);
|
||||
|
@ -901,13 +862,12 @@ WebAuthnManager::FinishGetAssertion(const uint64_t& aTransactionId,
|
|||
// with the values returned from the authenticator as well as the
|
||||
// clientDataJSON computed earlier.
|
||||
RefPtr<AuthenticatorAssertionResponse> assertion =
|
||||
new AuthenticatorAssertionResponse(mTransaction.ref().mParent);
|
||||
new AuthenticatorAssertionResponse(mParent);
|
||||
assertion->SetClientDataJSON(clientDataBuf);
|
||||
assertion->SetAuthenticatorData(authenticatorDataBuf);
|
||||
assertion->SetSignature(signatureBuf);
|
||||
|
||||
RefPtr<PublicKeyCredential> credential =
|
||||
new PublicKeyCredential(mTransaction.ref().mParent);
|
||||
RefPtr<PublicKeyCredential> credential = new PublicKeyCredential(mParent);
|
||||
credential->SetId(credentialBase64Url);
|
||||
credential->SetType(NS_LITERAL_STRING("public-key"));
|
||||
credential->SetRawId(credentialBuf);
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "mozilla/MozPromise.h"
|
||||
#include "mozilla/dom/Event.h"
|
||||
#include "mozilla/dom/PWebAuthnTransaction.h"
|
||||
#include "mozilla/dom/WebAuthnManagerBase.h"
|
||||
#include "nsIDOMEventListener.h"
|
||||
|
||||
/*
|
||||
|
@ -63,13 +64,11 @@ class WebAuthnTransactionChild;
|
|||
class WebAuthnTransaction
|
||||
{
|
||||
public:
|
||||
WebAuthnTransaction(nsPIDOMWindowInner* aParent,
|
||||
const RefPtr<Promise>& aPromise,
|
||||
WebAuthnTransaction(const RefPtr<Promise>& aPromise,
|
||||
const nsTArray<uint8_t>& aRpIdHash,
|
||||
const nsCString& aClientData,
|
||||
AbortSignal* aSignal)
|
||||
: mParent(aParent)
|
||||
, mPromise(aPromise)
|
||||
: mPromise(aPromise)
|
||||
, mRpIdHash(aRpIdHash)
|
||||
, mClientData(aClientData)
|
||||
, mSignal(aSignal)
|
||||
|
@ -78,9 +77,6 @@ public:
|
|||
MOZ_ASSERT(mId > 0);
|
||||
}
|
||||
|
||||
// Parent of the context we're running the transaction in.
|
||||
nsCOMPtr<nsPIDOMWindowInner> mParent;
|
||||
|
||||
// JS Promise representing the transaction status.
|
||||
RefPtr<Promise> mPromise;
|
||||
|
||||
|
@ -106,49 +102,55 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
class WebAuthnManager final : public nsIDOMEventListener
|
||||
class WebAuthnManager final : public WebAuthnManagerBase
|
||||
, public nsIDOMEventListener
|
||||
, public AbortFollower
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDOMEVENTLISTENER
|
||||
|
||||
static WebAuthnManager* GetOrCreate();
|
||||
static WebAuthnManager* Get();
|
||||
explicit WebAuthnManager(nsPIDOMWindowInner* aParent);
|
||||
|
||||
already_AddRefed<Promise>
|
||||
MakeCredential(nsPIDOMWindowInner* aParent,
|
||||
const MakePublicKeyCredentialOptions& aOptions,
|
||||
MakeCredential(const MakePublicKeyCredentialOptions& aOptions,
|
||||
const Optional<OwningNonNull<AbortSignal>>& aSignal);
|
||||
|
||||
already_AddRefed<Promise>
|
||||
GetAssertion(nsPIDOMWindowInner* aParent,
|
||||
const PublicKeyCredentialRequestOptions& aOptions,
|
||||
GetAssertion(const PublicKeyCredentialRequestOptions& aOptions,
|
||||
const Optional<OwningNonNull<AbortSignal>>& aSignal);
|
||||
|
||||
already_AddRefed<Promise>
|
||||
Store(nsPIDOMWindowInner* aParent, const Credential& aCredential);
|
||||
Store(const Credential& aCredential);
|
||||
|
||||
// WebAuthnManagerBase
|
||||
|
||||
void
|
||||
FinishMakeCredential(const uint64_t& aTransactionId,
|
||||
nsTArray<uint8_t>& aRegBuffer);
|
||||
nsTArray<uint8_t>& aRegBuffer) override;
|
||||
|
||||
void
|
||||
FinishGetAssertion(const uint64_t& aTransactionId,
|
||||
nsTArray<uint8_t>& aCredentialId,
|
||||
nsTArray<uint8_t>& aSigBuffer);
|
||||
nsTArray<uint8_t>& aSigBuffer) override;
|
||||
|
||||
void
|
||||
RequestAborted(const uint64_t& aTransactionId, const nsresult& aError);
|
||||
RequestAborted(const uint64_t& aTransactionId,
|
||||
const nsresult& aError) override;
|
||||
|
||||
void ActorDestroyed() override;
|
||||
|
||||
// AbortFollower
|
||||
|
||||
void Abort() override;
|
||||
|
||||
void ActorDestroyed();
|
||||
|
||||
private:
|
||||
WebAuthnManager();
|
||||
virtual ~WebAuthnManager();
|
||||
|
||||
// Visibility event handling.
|
||||
void ListenForVisibilityEvents();
|
||||
void StopListeningForVisibilityEvents();
|
||||
|
||||
// Clears all information we have about the current transaction.
|
||||
void ClearTransaction();
|
||||
// Rejects the current transaction and calls ClearTransaction().
|
||||
|
@ -159,6 +161,9 @@ private:
|
|||
|
||||
bool MaybeCreateBackgroundActor();
|
||||
|
||||
// The parent window.
|
||||
nsCOMPtr<nsPIDOMWindowInner> mParent;
|
||||
|
||||
// IPC Channel to the parent process.
|
||||
RefPtr<WebAuthnTransactionChild> mChild;
|
||||
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_dom_WebAuthnManagerBase_h
|
||||
#define mozilla_dom_WebAuthnManagerBase_h
|
||||
|
||||
/*
|
||||
* A base class used by WebAuthn and U2F implementations, providing shared
|
||||
* functionality and requiring an interface used by the IPC child actors.
|
||||
*/
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class WebAuthnManagerBase
|
||||
{
|
||||
public:
|
||||
virtual void
|
||||
FinishMakeCredential(const uint64_t& aTransactionId,
|
||||
nsTArray<uint8_t>& aRegBuffer) = 0;
|
||||
|
||||
virtual void
|
||||
FinishGetAssertion(const uint64_t& aTransactionId,
|
||||
nsTArray<uint8_t>& aCredentialId,
|
||||
nsTArray<uint8_t>& aSigBuffer) = 0;
|
||||
|
||||
virtual void
|
||||
RequestAborted(const uint64_t& aTransactionId,
|
||||
const nsresult& aError) = 0;
|
||||
|
||||
virtual void ActorDestroyed() = 0;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif //mozilla_dom_WebAuthnManagerBase_h
|
|
@ -9,13 +9,26 @@
|
|||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
WebAuthnTransactionChild::WebAuthnTransactionChild(WebAuthnManagerBase* aManager)
|
||||
: mManager(aManager)
|
||||
{
|
||||
MOZ_ASSERT(aManager);
|
||||
|
||||
// Retain a reference so the task object isn't deleted without IPDL's
|
||||
// knowledge. The reference will be released by
|
||||
// mozilla::ipc::BackgroundChildImpl::DeallocPWebAuthnTransactionChild.
|
||||
NS_ADDREF_THIS();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
WebAuthnTransactionChild::RecvConfirmRegister(const uint64_t& aTransactionId,
|
||||
nsTArray<uint8_t>&& aRegBuffer)
|
||||
{
|
||||
RefPtr<WebAuthnManager> mgr = WebAuthnManager::Get();
|
||||
MOZ_ASSERT(mgr);
|
||||
mgr->FinishMakeCredential(aTransactionId, aRegBuffer);
|
||||
if (NS_WARN_IF(!mManager)) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
|
||||
mManager->FinishMakeCredential(aTransactionId, aRegBuffer);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
|
@ -24,9 +37,11 @@ WebAuthnTransactionChild::RecvConfirmSign(const uint64_t& aTransactionId,
|
|||
nsTArray<uint8_t>&& aCredentialId,
|
||||
nsTArray<uint8_t>&& aBuffer)
|
||||
{
|
||||
RefPtr<WebAuthnManager> mgr = WebAuthnManager::Get();
|
||||
MOZ_ASSERT(mgr);
|
||||
mgr->FinishGetAssertion(aTransactionId, aCredentialId, aBuffer);
|
||||
if (NS_WARN_IF(!mManager)) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
|
||||
mManager->FinishGetAssertion(aTransactionId, aCredentialId, aBuffer);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
|
@ -34,21 +49,36 @@ mozilla::ipc::IPCResult
|
|||
WebAuthnTransactionChild::RecvAbort(const uint64_t& aTransactionId,
|
||||
const nsresult& aError)
|
||||
{
|
||||
RefPtr<WebAuthnManager> mgr = WebAuthnManager::Get();
|
||||
MOZ_ASSERT(mgr);
|
||||
mgr->RequestAborted(aTransactionId, aError);
|
||||
if (NS_WARN_IF(!mManager)) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
|
||||
mManager->RequestAborted(aTransactionId, aError);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
void
|
||||
WebAuthnTransactionChild::ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
RefPtr<WebAuthnManager> mgr = WebAuthnManager::Get();
|
||||
// This could happen after the WebAuthnManager has been shut down.
|
||||
if (mgr) {
|
||||
mgr->ActorDestroyed();
|
||||
// Called by either a __delete__ message from the parent, or when the
|
||||
// channel disconnects. Clear out the child actor reference to be sure.
|
||||
if (mManager) {
|
||||
mManager->ActorDestroyed();
|
||||
mManager = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WebAuthnTransactionChild::Disconnect()
|
||||
{
|
||||
mManager = nullptr;
|
||||
|
||||
// The WebAuthnManager released us, but we're going to be held alive by the
|
||||
// IPC layer. The parent will explicitly destroy us via Send__delete__(),
|
||||
// after receiving the DestroyMe message.
|
||||
|
||||
SendDestroyMe();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
#ifndef mozilla_dom_WebAuthnTransactionChild_h
|
||||
#define mozilla_dom_WebAuthnTransactionChild_h
|
||||
|
||||
#include "mozilla/dom/WebAuthnTransactionChildBase.h"
|
||||
#include "mozilla/dom/PWebAuthnTransactionChild.h"
|
||||
#include "mozilla/dom/WebAuthnManagerBase.h"
|
||||
|
||||
/*
|
||||
* Child process IPC implementation for WebAuthn API. Receives results of
|
||||
|
@ -19,22 +20,33 @@
|
|||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class WebAuthnTransactionChild final : public WebAuthnTransactionChildBase
|
||||
class WebAuthnTransactionChild final : public PWebAuthnTransactionChild
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING(WebAuthnTransactionChild);
|
||||
explicit WebAuthnTransactionChild(WebAuthnManagerBase* aManager);
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RecvConfirmRegister(const uint64_t& aTransactionId,
|
||||
nsTArray<uint8_t>&& aRegBuffer) override;
|
||||
nsTArray<uint8_t>&& aRegBuffer);
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RecvConfirmSign(const uint64_t& aTransactionId,
|
||||
nsTArray<uint8_t>&& aCredentialId,
|
||||
nsTArray<uint8_t>&& aBuffer) override;
|
||||
nsTArray<uint8_t>&& aBuffer);
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RecvAbort(const uint64_t& aTransactionId, const nsresult& aError) override;
|
||||
RecvAbort(const uint64_t& aTransactionId, const nsresult& aError);
|
||||
|
||||
void ActorDestroy(ActorDestroyReason why) override;
|
||||
void ActorDestroy(ActorDestroyReason why);
|
||||
|
||||
void Disconnect();
|
||||
|
||||
private:
|
||||
~WebAuthnTransactionChild() = default;
|
||||
|
||||
// Nulled by ~WebAuthnManager() when disconnecting.
|
||||
WebAuthnManagerBase* mManager;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#include "mozilla/dom/WebAuthnTransactionChildBase.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
WebAuthnTransactionChildBase::WebAuthnTransactionChildBase()
|
||||
{
|
||||
// Retain a reference so the task object isn't deleted without IPDL's
|
||||
// knowledge. The reference will be released by
|
||||
// mozilla::ipc::BackgroundChildImpl::DeallocPWebAuthnTransactionChild.
|
||||
NS_ADDREF_THIS();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_dom_WebAuthnTransactionChildBase_h
|
||||
#define mozilla_dom_WebAuthnTransactionChildBase_h
|
||||
|
||||
#include "mozilla/dom/PWebAuthnTransactionChild.h"
|
||||
|
||||
/*
|
||||
* A base class to be used by child process IPC implementations for WebAuthn
|
||||
* and U2F. This mostly handles refcounting so we can properly dereference
|
||||
* in mozilla::ipc::BackgroundChildImpl::DeallocPWebAuthnTransactionChild(),
|
||||
* a function that doesn't know which of the two implementations is passed.
|
||||
*/
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class WebAuthnTransactionChildBase : public PWebAuthnTransactionChild
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING(WebAuthnTransactionChildBase);
|
||||
WebAuthnTransactionChildBase();
|
||||
|
||||
protected:
|
||||
~WebAuthnTransactionChildBase() = default;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif //mozilla_dom_WebAuthnTransactionChildBase_h
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "mozilla/dom/WebAuthnTransactionParent.h"
|
||||
#include "mozilla/dom/U2FTokenManager.h"
|
||||
#include "mozilla/ipc/PBackgroundParent.h"
|
||||
#include "mozilla/ipc/BackgroundParent.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -40,12 +41,40 @@ WebAuthnTransactionParent::RecvRequestCancel(const uint64_t& aTransactionId)
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
WebAuthnTransactionParent::RecvDestroyMe()
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
// The child was disconnected from the WebAuthnManager instance and will send
|
||||
// no further messages. It is kept alive until we delete it explicitly.
|
||||
|
||||
// The child should have cancelled any active transaction. This means
|
||||
// we expect no more messages to the child. We'll crash otherwise.
|
||||
|
||||
// The IPC roundtrip is complete. No more messages, hopefully.
|
||||
IProtocol* mgr = Manager();
|
||||
if (!Send__delete__(this)) {
|
||||
return IPC_FAIL_NO_REASON(mgr);
|
||||
}
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
void
|
||||
WebAuthnTransactionParent::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
// Called either by Send__delete__() in RecvDestroyMe() above, or when
|
||||
// the channel disconnects. Ensure the token manager forgets about us.
|
||||
U2FTokenManager* mgr = U2FTokenManager::Get();
|
||||
mgr->MaybeClearTransaction(this);
|
||||
}
|
||||
|
||||
// The manager could probably be null on shutdown?
|
||||
if (mgr) {
|
||||
mgr->MaybeClearTransaction(this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,6 +35,9 @@ public:
|
|||
virtual mozilla::ipc::IPCResult
|
||||
RecvRequestCancel(const uint64_t& aTransactionId) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult
|
||||
RecvDestroyMe() override;
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
|
||||
private:
|
||||
|
|
|
@ -22,8 +22,8 @@ EXPORTS.mozilla.dom += [
|
|||
'U2FTokenTransport.h',
|
||||
'WebAuthnCBORUtil.h',
|
||||
'WebAuthnManager.h',
|
||||
'WebAuthnManagerBase.h',
|
||||
'WebAuthnTransactionChild.h',
|
||||
'WebAuthnTransactionChildBase.h',
|
||||
'WebAuthnTransactionParent.h',
|
||||
'WebAuthnUtil.h',
|
||||
]
|
||||
|
@ -41,7 +41,6 @@ UNIFIED_SOURCES += [
|
|||
'WebAuthnCBORUtil.cpp',
|
||||
'WebAuthnManager.cpp',
|
||||
'WebAuthnTransactionChild.cpp',
|
||||
'WebAuthnTransactionChildBase.cpp',
|
||||
'WebAuthnTransactionParent.cpp',
|
||||
'WebAuthnUtil.cpp',
|
||||
]
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
interface Attr : Node {
|
||||
readonly attribute DOMString localName;
|
||||
[CEReactions, NeedsSubjectPrincipal, SetterThrows]
|
||||
[CEReactions, SetterNeedsSubjectPrincipal, SetterThrows]
|
||||
attribute DOMString value;
|
||||
|
||||
[Constant]
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
*/
|
||||
|
||||
interface CSSStyleDeclaration {
|
||||
[CEReactions, NeedsSubjectPrincipal, SetterThrows]
|
||||
[CEReactions, SetterNeedsSubjectPrincipal, SetterThrows]
|
||||
attribute DOMString cssText;
|
||||
|
||||
readonly attribute unsigned long length;
|
||||
|
|
|
@ -221,7 +221,7 @@ partial interface Element {
|
|||
|
||||
// http://domparsing.spec.whatwg.org/#extensions-to-the-element-interface
|
||||
partial interface Element {
|
||||
[CEReactions, NeedsSubjectPrincipal, Pure,SetterThrows,TreatNullAs=EmptyString]
|
||||
[CEReactions, SetterNeedsSubjectPrincipal, Pure, SetterThrows, TreatNullAs=EmptyString]
|
||||
attribute DOMString innerHTML;
|
||||
[CEReactions, Pure,SetterThrows,TreatNullAs=EmptyString]
|
||||
attribute DOMString outerHTML;
|
||||
|
|
|
@ -42,7 +42,7 @@ interface HTMLDocument : Document {
|
|||
[CEReactions, Throws]
|
||||
void writeln(DOMString... text);
|
||||
|
||||
[CEReactions, SetterThrows, NeedsSubjectPrincipal]
|
||||
[CEReactions, SetterThrows, SetterNeedsSubjectPrincipal]
|
||||
attribute DOMString designMode;
|
||||
[CEReactions, Throws, NeedsSubjectPrincipal]
|
||||
boolean execCommand(DOMString commandId, optional boolean showUI = false,
|
||||
|
|
|
@ -17,7 +17,7 @@ interface HTMLFrameElement : HTMLElement {
|
|||
attribute DOMString name;
|
||||
[CEReactions, SetterThrows]
|
||||
attribute DOMString scrolling;
|
||||
[CEReactions, NeedsSubjectPrincipal, SetterThrows]
|
||||
[CEReactions, SetterNeedsSubjectPrincipal, SetterThrows]
|
||||
attribute DOMString src;
|
||||
[CEReactions, SetterThrows]
|
||||
attribute DOMString frameBorder;
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
[HTMLConstructor]
|
||||
interface HTMLIFrameElement : HTMLElement {
|
||||
[CEReactions, NeedsSubjectPrincipal, SetterThrows, Pure]
|
||||
[CEReactions, SetterNeedsSubjectPrincipal, SetterThrows, Pure]
|
||||
attribute DOMString src;
|
||||
[CEReactions, SetterThrows, Pure]
|
||||
attribute DOMString srcdoc;
|
||||
|
|
|
@ -21,9 +21,9 @@ interface nsIStreamListener;
|
|||
interface HTMLImageElement : HTMLElement {
|
||||
[CEReactions, SetterThrows]
|
||||
attribute DOMString alt;
|
||||
[CEReactions, NeedsSubjectPrincipal, SetterThrows]
|
||||
[CEReactions, SetterNeedsSubjectPrincipal, SetterThrows]
|
||||
attribute DOMString src;
|
||||
[CEReactions, NeedsSubjectPrincipal, SetterThrows]
|
||||
[CEReactions, SetterNeedsSubjectPrincipal, SetterThrows]
|
||||
attribute DOMString srcset;
|
||||
[CEReactions, SetterThrows]
|
||||
attribute DOMString? crossOrigin;
|
||||
|
|
|
@ -81,7 +81,7 @@ interface HTMLInputElement : HTMLElement {
|
|||
attribute boolean required;
|
||||
[CEReactions, Pure, SetterThrows]
|
||||
attribute unsigned long size;
|
||||
[CEReactions, Pure, NeedsSubjectPrincipal, SetterThrows]
|
||||
[CEReactions, Pure, SetterNeedsSubjectPrincipal, SetterThrows]
|
||||
attribute DOMString src;
|
||||
[CEReactions, Pure, SetterThrows]
|
||||
attribute DOMString step;
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
interface HTMLLinkElement : HTMLElement {
|
||||
[Pure]
|
||||
attribute boolean disabled;
|
||||
[CEReactions, NeedsSubjectPrincipal, SetterThrows, Pure]
|
||||
[CEReactions, SetterNeedsSubjectPrincipal, SetterThrows, Pure]
|
||||
attribute DOMString href;
|
||||
[CEReactions, SetterThrows, Pure]
|
||||
attribute DOMString? crossOrigin;
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче