Merge inbound to mozilla-central r=merge a=merge

This commit is contained in:
Gurzau Raul 2017-12-06 11:53:55 +02:00
Родитель c2096f8bee 6dc1932292
Коммит f5f1c3f294
292 изменённых файлов: 6006 добавлений и 1365 удалений

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

@ -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()
}
}
// 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)
{
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,7 +437,7 @@ U2F::Register(const nsAString& aAppId,
}
void
U2F::FinishRegister(const uint64_t& aTransactionId,
U2F::FinishMakeCredential(const uint64_t& aTransactionId,
nsTArray<uint8_t>& aRegBuffer)
{
MOZ_ASSERT(NS_IsMainThread());
@ -566,7 +566,7 @@ U2F::Sign(const nsAString& aAppId,
}
void
U2F::FinishSign(const uint64_t& aTransactionId,
U2F::FinishGetAssertion(const uint64_t& aTransactionId,
nsTArray<uint8_t>& aCredentialId,
nsTArray<uint8_t>& aSigBuffer)
{
@ -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,
FinishMakeCredential(const uint64_t& aTransactionId,
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();
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,13 +38,14 @@
function startTest() {
promise_test((test) => {
listenControllerEvents();
return VRSimulationDriver.AttachWebVRDisplay().then(() => {
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();
});
});
}, "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,6 +36,7 @@
var img = document.createElement('img');
img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACw=";
return VRSimulationDriver.AttachWebVRDisplay().then(() => {
return navigator.getVRDisplays().then((displays) => {
assert_equals(displays.length, 1, "displays.length must be one after attach.");
vrDisplay = displays[0];
@ -43,6 +45,7 @@
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 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 VRSimulationDriver.AttachWebVRDisplay().then(() => {
return 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.")
}, "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();
// 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;

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

@ -17,7 +17,7 @@ interface HTMLMediaElement : HTMLElement {
readonly attribute MediaError? error;
// network state
[CEReactions, NeedsSubjectPrincipal, SetterThrows]
[CEReactions, SetterNeedsSubjectPrincipal, SetterThrows]
attribute DOMString src;
readonly attribute DOMString currentSrc;

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше