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

This commit is contained in:
Csoregi Natalia 2017-12-14 00:01:37 +02:00
Родитель 4ab6deca48 49929d098e
Коммит be90f4e875
47 изменённых файлов: 903 добавлений и 679 удалений

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

@ -1,3 +1,4 @@
{
"phabricator.uri" : "https://phabricator.services.mozilla.com/"
"phabricator.uri" : "https://phabricator.services.mozilla.com/",
"repository.callsign": "MOZILLACENTRAL"
}

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

@ -12,4 +12,5 @@ skip-if = os == 'win' # Bug 1411118
[browser_notification_remove_permission.js]
skip-if = os == 'win' # Bug 1411118
[browser_notification_replace.js]
skip-if = os == 'win' # Bug 1422928
[browser_notification_tab_switching.js]

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

@ -81,7 +81,6 @@ pref("devtools.gridinspector.gridOutlineMaxRows", 50);
pref("devtools.gridinspector.showGridAreas", false);
pref("devtools.gridinspector.showGridLineNumbers", false);
pref("devtools.gridinspector.showInfiniteLines", false);
pref("devtools.gridinspector.showNegativeLineNumbers", false);
// Whether or not the box model panel is opened in the computed view
pref("devtools.computed.boxmodel.opened", true);

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

@ -4,7 +4,6 @@
"use strict";
const Services = require("Services");
const { AutoRefreshHighlighter } = require("./auto-refresh");
const {
CANVAS_SIZE,
@ -38,8 +37,6 @@ const { LocalizationHelper } = require("devtools/shared/l10n");
const LAYOUT_STRINGS_URI = "devtools/client/locales/layout.properties";
const LAYOUT_L10N = new LocalizationHelper(LAYOUT_STRINGS_URI);
const NEGATIVE_LINE_NUMBERS_PREF = "devtools.gridinspector.showNegativeLineNumbers";
const COLUMNS = "cols";
const ROWS = "rows";
@ -743,13 +740,10 @@ class CssGridHighlighter extends AutoRefreshHighlighter {
if (this.options.showGridLineNumbers) {
this.renderLineNumbers(fragment.cols, COLUMNS, this.getFirstRowLinePos(fragment));
this.renderLineNumbers(fragment.rows, ROWS, this.getFirstColLinePos(fragment));
if (Services.prefs.getBoolPref(NEGATIVE_LINE_NUMBERS_PREF)) {
this.renderNegativeLineNumbers(fragment.cols, COLUMNS,
this.getLastRowLinePos(fragment));
this.renderNegativeLineNumbers(fragment.rows, ROWS,
this.getLastColLinePos(fragment));
}
this.renderNegativeLineNumbers(fragment.cols, COLUMNS,
this.getLastRowLinePos(fragment));
this.renderNegativeLineNumbers(fragment.rows, ROWS,
this.getLastColLinePos(fragment));
}
}

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

@ -774,156 +774,6 @@ nsDOMWindowUtils::SendMouseEventCommon(const nsAString& aType,
aIsDOMEventSynthesized, aIsWidgetEventSynthesized);
}
NS_IMETHODIMP
nsDOMWindowUtils::SendPointerEventCommon(const nsAString& aType,
float aX,
float aY,
int32_t aButton,
int32_t aClickCount,
int32_t aModifiers,
bool aIgnoreRootScrollFrame,
float aPressure,
unsigned short aInputSourceArg,
int32_t aPointerId,
int32_t aWidth,
int32_t aHeight,
int32_t aTiltX,
int32_t aTiltY,
bool aIsPrimary,
bool aIsSynthesized,
uint8_t aOptionalArgCount,
bool aToWindow,
bool* aPreventDefault)
{
// get the widget to send the event to
nsPoint offset;
nsCOMPtr<nsIWidget> widget = GetWidget(&offset);
if (!widget) {
return NS_ERROR_FAILURE;
}
EventMessage msg;
if (aType.EqualsLiteral("pointerdown")) {
msg = ePointerDown;
} else if (aType.EqualsLiteral("pointerup")) {
msg = ePointerUp;
} else if (aType.EqualsLiteral("pointermove")) {
msg = ePointerMove;
} else if (aType.EqualsLiteral("pointerover")) {
msg = ePointerOver;
} else if (aType.EqualsLiteral("pointerout")) {
msg = ePointerOut;
} else {
return NS_ERROR_FAILURE;
}
if (aInputSourceArg == nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN) {
aInputSourceArg = nsIDOMMouseEvent::MOZ_SOURCE_MOUSE;
}
WidgetPointerEvent event(true, msg, widget);
event.mModifiers = nsContentUtils::GetWidgetModifiers(aModifiers);
event.button = aButton;
event.buttons = nsContentUtils::GetButtonsFlagForButton(aButton);
event.pressure = aPressure;
event.inputSource = aInputSourceArg;
event.pointerId = aPointerId;
event.mWidth = aWidth;
event.mHeight = aHeight;
event.tiltX = aTiltX;
event.tiltY = aTiltY;
event.mIsPrimary =
(nsIDOMMouseEvent::MOZ_SOURCE_MOUSE == aInputSourceArg) ? true : aIsPrimary;
event.mClickCount = aClickCount;
event.mTime = PR_IntervalNow();
event.mFlags.mIsSynthesizedForTests = aOptionalArgCount >= 10 ? aIsSynthesized : true;
nsPresContext* presContext = GetPresContext();
if (!presContext) {
return NS_ERROR_FAILURE;
}
event.mRefPoint =
nsContentUtils::ToWidgetPoint(CSSPoint(aX, aY), offset, presContext);
event.mIgnoreRootScrollFrame = aIgnoreRootScrollFrame;
nsEventStatus status;
if (aToWindow) {
nsCOMPtr<nsIPresShell> presShell;
nsView* view = nsContentUtils::GetViewToDispatchEvent(presContext, getter_AddRefs(presShell));
if (!presShell || !view) {
return NS_ERROR_FAILURE;
}
status = nsEventStatus_eIgnore;
return presShell->HandleEvent(view->GetFrame(), &event, false, &status);
}
nsresult rv = widget->DispatchEvent(&event, status);
if (aPreventDefault) {
*aPreventDefault = (status == nsEventStatus_eConsumeNoDefault);
}
return rv;
}
NS_IMETHODIMP
nsDOMWindowUtils::SendPointerEvent(const nsAString& aType,
float aX,
float aY,
int32_t aButton,
int32_t aClickCount,
int32_t aModifiers,
bool aIgnoreRootScrollFrame,
float aPressure,
unsigned short aInputSourceArg,
int32_t aPointerId,
int32_t aWidth,
int32_t aHeight,
int32_t aTiltX,
int32_t aTiltY,
bool aIsPrimary,
bool aIsSynthesized,
uint8_t aOptionalArgCount,
bool* aPreventDefault)
{
AUTO_PROFILER_LABEL("nsDOMWindowUtils::SendPointerEvent", EVENTS);
return SendPointerEventCommon(aType, aX, aY, aButton, aClickCount,
aModifiers, aIgnoreRootScrollFrame,
aPressure, aInputSourceArg, aPointerId,
aWidth, aHeight, aTiltX, aTiltY,
aIsPrimary, aIsSynthesized,
aOptionalArgCount, false, aPreventDefault);
}
NS_IMETHODIMP
nsDOMWindowUtils::SendPointerEventToWindow(const nsAString& aType,
float aX,
float aY,
int32_t aButton,
int32_t aClickCount,
int32_t aModifiers,
bool aIgnoreRootScrollFrame,
float aPressure,
unsigned short aInputSourceArg,
int32_t aPointerId,
int32_t aWidth,
int32_t aHeight,
int32_t aTiltX,
int32_t aTiltY,
bool aIsPrimary,
bool aIsSynthesized,
uint8_t aOptionalArgCount)
{
AUTO_PROFILER_LABEL("nsDOMWindowUtils::SendPointerEventToWindow", EVENTS);
return SendPointerEventCommon(aType, aX, aY, aButton, aClickCount,
aModifiers, aIgnoreRootScrollFrame,
aPressure, aInputSourceArg, aPointerId,
aWidth, aHeight, aTiltX, aTiltY,
aIsPrimary, aIsSynthesized,
aOptionalArgCount, true, nullptr);
}
NS_IMETHODIMP
nsDOMWindowUtils::SendWheelEvent(float aX,
float aY,

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

@ -100,26 +100,6 @@ protected:
bool aIsWidgetEventSynthesized,
int32_t aButtons);
NS_IMETHOD SendPointerEventCommon(const nsAString& aType,
float aX,
float aY,
int32_t aButton,
int32_t aClickCount,
int32_t aModifiers,
bool aIgnoreRootScrollFrame,
float aPressure,
unsigned short aInputSourceArg,
int32_t aPointerId,
int32_t aWidth,
int32_t aHeight,
int32_t aTiltX,
int32_t aTiltY,
bool aIsPrimary,
bool aIsSynthesized,
uint8_t aOptionalArgCount,
bool aToWindow,
bool* aPreventDefault);
NS_IMETHOD SendTouchEventCommon(const nsAString& aType,
uint32_t* aIdentifiers,
int32_t* aXs,

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

@ -43,9 +43,9 @@ var pointerleavecount = 0;
var pointerovercount = 0;
var pointeroutcount = 0;
function sendPointerEvent(t, elem) {
function sendMouseEventToElement(t, elem) {
var r = elem.getBoundingClientRect();
synthesizePointer(elem, r.width / 2, r.height / 2, {type: t});
synthesizeMouse(elem, r.width / 2, r.height / 2, {type: t});
}
var expectedPointerEnterTargets = [];
@ -68,7 +68,7 @@ function runTests() {
iframe.addEventListener("pointerover", pover);
// Make sure ESM thinks pointer is outside the test elements.
sendPointerEvent("pointermove", outside);
sendMouseEventToElement("mousemove", outside);
pointerentercount = 0;
pointerleavecount = 0;
@ -78,7 +78,7 @@ function runTests() {
expectedRelatedEnter = outside;
expectedRelatedLeave = inner;
expectedPointerEnterTargets = ["outertest", "middletest", "innertest"];
sendPointerEvent("pointermove", inner);
sendMouseEventToElement("mousemove", inner);
is(pointerentercount, 3, "Unexpected pointerenter event count!");
is(pointerovercount, 1, "Unexpected pointerover event count!");
is(pointeroutcount, 0, "Unexpected pointerout event count!");
@ -86,7 +86,7 @@ function runTests() {
expectedRelatedEnter = inner;
expectedRelatedLeave = outside;
expectedPointerLeaveTargets = ["innertest", "middletest", "outertest"];
sendPointerEvent("pointermove", outside);
sendMouseEventToElement("mousemove", outside);
is(pointerentercount, 3, "Unexpected pointerenter event count!");
is(pointerovercount, 1, "Unexpected pointerover event count!");
is(pointeroutcount, 1, "Unexpected pointerout event count!");
@ -96,14 +96,14 @@ function runTests() {
var r = file.getBoundingClientRect();
expectedRelatedEnter = outside;
expectedRelatedLeave = file;
synthesizePointer(file, r.width / 6, r.height / 2, {type: "pointermove"});
synthesizeMouse(file, r.width / 6, r.height / 2, {type: "mousemove"});
is(pointerentercount, 4, "Unexpected pointerenter event count!");
is(pointerovercount, 2, "Unexpected pointerover event count!");
is(pointeroutcount, 1, "Unexpected pointerout event count!");
is(pointerleavecount, 3, "Unexpected pointerleave event count!");
// Moving pointer over type="file" shouldn't cause pointerover/out/enter/leave events
synthesizePointer(file, r.width - (r.width / 6), r.height / 2, {type: "pointermove"});
synthesizeMouse(file, r.width - (r.width / 6), r.height / 2, {type: "mousemove"});
is(pointerentercount, 4, "Unexpected pointerenter event count!");
is(pointerovercount, 2, "Unexpected pointerover event count!");
is(pointeroutcount, 1, "Unexpected pointerout event count!");
@ -111,7 +111,7 @@ function runTests() {
expectedRelatedEnter = file;
expectedRelatedLeave = outside;
sendPointerEvent("pointermove", outside);
sendMouseEventToElement("mousemove", outside);
is(pointerentercount, 4, "Unexpected pointerenter event count!");
is(pointerovercount, 2, "Unexpected pointerover event count!");
is(pointeroutcount, 2, "Unexpected pointerout event count!");
@ -135,17 +135,17 @@ function runTests() {
expectedRelatedEnter = outside;
expectedRelatedLeave = iframe;
// Move pointer inside the iframe.
synthesizePointer(iframe.contentDocument.body, r.width / 2, r.height / 4, {type: "pointermove"},
iframe.contentWindow);
synthesizeMouse(iframe.contentDocument.body, r.width / 2, r.height / 4, {type: "mousemove"},
iframe.contentWindow);
is(pointerentercount, 6, "Unexpected pointerenter event count!");
is(pointerleavecount, 4, "Unexpected pointerleave event count!");
synthesizePointer(iframe.contentDocument.body, r.width / 2, r.height - (r.height / 4), {type: "pointermove"},
iframe.contentWindow);
synthesizeMouse(iframe.contentDocument.body, r.width / 2, r.height - (r.height / 4), {type: "mousemove"},
iframe.contentWindow);
is(pointerentercount, 7, "Unexpected pointerenter event count!");
is(pointerleavecount, 5, "Unexpected pointerleave event count!");
expectedRelatedEnter = iframe;
expectedRelatedLeave = outside;
sendPointerEvent("pointermove", outside);
sendMouseEventToElement("mousemove", outside);
is(pointerentercount, 7, "Unexpected pointerenter event count!");
is(pointerleavecount, 7, "Unexpected pointerleave event count!");
@ -153,19 +153,19 @@ function runTests() {
expectedRelatedEnter = outside;
expectedRelatedLeave = iframe;
// Move pointer inside the iframe.
synthesizePointer(iframe.contentDocument.body, r.width / 2, r.height / 4, {type: "pointerdown"},
iframe.contentWindow);
synthesizePointer(iframe.contentDocument.body, r.width / 2, r.height - (r.height / 4), {type: "pointerdown"},
iframe.contentWindow);
synthesizeMouse(iframe.contentDocument.body, r.width / 2, r.height / 4, {type: "mousedown"},
iframe.contentWindow);
synthesizeMouse(iframe.contentDocument.body, r.width / 2, r.height - (r.height / 4), {type: "mousedown"},
iframe.contentWindow);
is(pointerentercount, 10, "Unexpected pointerenter event count!");
// pointerdown + pointermove must produce single pointerenter event
expectedRelatedEnter = outside;
expectedRelatedLeave = iframe;
synthesizePointer(iframe.contentDocument.body, r.width / 2, r.height / 4, {type: "pointerdown"},
iframe.contentWindow);
synthesizePointer(iframe.contentDocument.body, r.width / 2 + 1, r.height / 4 + 1, {type: "pointermove"},
iframe.contentWindow);
synthesizeMouse(iframe.contentDocument.body, r.width / 2, r.height / 4, {type: "mousedown"},
iframe.contentWindow);
synthesizeMouse(iframe.contentDocument.body, r.width / 2 + 1, r.height / 4 + 1, {type: "mousemove"},
iframe.contentWindow);
is(pointerentercount, 11, "Unexpected pointerenter event count!");
Array.from(document.querySelectorAll('*'))

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

@ -30,6 +30,10 @@ script.addMessageListener("emptyfile.opened", message => {
then(() => checkContent("begin", [message.file, "Hello world!"])).
then(() => checkContent("end", ["Hello world!", message.file])).
then(() => checkContent("random", [message.file, message.file, "Hello world!", message.file])).
then(() => checkContent("random 2", [message.file, message.file, "Hello ",
message.file, "world", message.file,
message.file, "!", message.file, "",
message.file, message.file])).
then(SimpleTest.finish);
});

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

@ -342,73 +342,6 @@ interface nsIDOMWindowUtils : nsISupports {
[optional] in long aButtons,
[optional] in unsigned long aIdentifier);
/** Synthesize a pointer event. The event types supported are:
* pointerdown, pointerup, pointermove, pointerover, pointerout
*
* Events are sent in coordinates offset by aX and aY from the window.
*
* Note that additional events may be fired as a result of this call. For
* instance, typically a click event will be fired as a result of a
* mousedown and mouseup in sequence.
*
* Normally at this level of events, the pointerover and pointerout events are
* only fired when the window is entered or exited. For inter-element
* pointerover and pointerout events, a movemove event fired on the new element
* should be sufficient to generate the correct over and out events as well.
*
* Cannot be accessed from unprivileged context (not content-accessible)
* Will throw a DOM security error if called without chrome privileges.
*
* The event is dispatched via the toplevel window, so it could go to any
* window under the toplevel window, in some cases it could never reach this
* window at all.
*
* @param aType event type
* @param aX x offset in CSS pixels
* @param aY y offset in CSS pixels
* @param aButton button to synthesize
* @param aClickCount number of clicks that have been performed
* @param aModifiers modifiers pressed, using constants defined as MODIFIER_*
* @param aIgnoreRootScrollFrame whether the event should ignore viewport bounds
* during dispatch
* @param aPressure touch input pressure: 0.0 -> 1.0
* @param aInputSourceArg input source, see nsIDOMMouseEvent for values,
* defaults to mouse input.
* @param aPointerId A unique identifier for the pointer causing the event,
* defaulting to nsIDOMWindowUtils::DEFAULT_MOUSE_POINTER_ID.
* @param aWidth The width (magnitude on the X axis), default is 0
* @param aHeight The height (magnitude on the Y axis), default is 0
* @param aTilt The plane angle between the Y-Z plane
* and the plane containing both the transducer (e.g. pen stylus) axis and the Y axis. default is 0
* @param aTiltX The plane angle between the X-Z plane
* and the plane containing both the transducer (e.g. pen stylus) axis and the X axis. default is 0
* @param aIsPrimary Indicates if the pointer represents the primary pointer of this pointer type.
* @param aIsSynthesized controls nsIDOMEvent.isSynthesized value
* that helps identifying test related events,
* defaults to true
*
* returns true if the page called prevent default on this event
*/
[optional_argc]
boolean sendPointerEvent(in AString aType,
in float aX,
in float aY,
in long aButton,
in long aClickCount,
in long aModifiers,
[optional] in boolean aIgnoreRootScrollFrame,
[optional] in float aPressure,
[optional] in unsigned short aInputSourceArg,
[optional] in long aPointerId,
[optional] in long aWidth,
[optional] in long aHeight,
[optional] in long aTiltX,
[optional] in long aTiltY,
[optional] in boolean aIsPrimary,
[optional] in boolean aIsSynthesized);
/** Synthesize a touch event. The event types supported are:
* touchstart, touchend, touchmove, and touchcancel
*
@ -465,27 +398,6 @@ interface nsIDOMWindowUtils : nsISupports {
[optional] in long aButtons,
[optional] in unsigned long aIdentifier);
/** The same as sendPointerEvent but ensures that the event
* is dispatched to this DOM window or one of its children.
*/
[optional_argc]
void sendPointerEventToWindow(in AString aType,
in float aX,
in float aY,
in long aButton,
in long aClickCount,
in long aModifiers,
[optional] in boolean aIgnoreRootScrollFrame,
[optional] in float aPressure,
[optional] in unsigned short aInputSourceArg,
[optional] in long aPointerId,
[optional] in long aWidth,
[optional] in long aHeight,
[optional] in long aTiltX,
[optional] in long aTiltY,
[optional] in boolean aIsPrimary,
[optional] in boolean aIsSynthesized);
/** The same as sendTouchEvent but ensures that the event is dispatched to
* this DOM window or one of its children.
*/

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

@ -15,6 +15,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(AuthenticatorAssertionResponse,
AuthenticatorResponse)
tmp->mAuthenticatorDataCachedObj = nullptr;
tmp->mSignatureCachedObj = nullptr;
tmp->mUserHandleCachedObj = nullptr;
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(AuthenticatorAssertionResponse,
@ -22,6 +23,7 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(AuthenticatorAssertionResponse,
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mAuthenticatorDataCachedObj)
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mSignatureCachedObj)
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mUserHandleCachedObj)
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(AuthenticatorAssertionResponse,
@ -38,6 +40,7 @@ AuthenticatorAssertionResponse::AuthenticatorAssertionResponse(nsPIDOMWindowInne
: AuthenticatorResponse(aParent)
, mAuthenticatorDataCachedObj(nullptr)
, mSignatureCachedObj(nullptr)
, mUserHandleCachedObj(nullptr)
{
mozilla::HoldJSObjects(this);
}
@ -93,17 +96,21 @@ AuthenticatorAssertionResponse::SetSignature(CryptoBuffer& aBuffer)
}
void
AuthenticatorAssertionResponse::GetUserId(DOMString& aRetVal)
AuthenticatorAssertionResponse::GetUserHandle(JSContext* aCx,
JS::MutableHandle<JSObject*> aRetVal)
{
// This requires mUserId to not be re-set for the life of the caller's in-var.
aRetVal.SetOwnedString(mUserId);
if (!mUserHandleCachedObj) {
mUserHandleCachedObj = mUserHandle.ToArrayBuffer(aCx);
}
aRetVal.set(mUserHandleCachedObj);
}
nsresult
AuthenticatorAssertionResponse::SetUserId(const nsAString& aUserId)
AuthenticatorAssertionResponse::SetUserHandle(CryptoBuffer& aBuffer)
{
MOZ_ASSERT(mUserId.IsEmpty(), "We already have a UserID?");
mUserId.Assign(aUserId);
if (NS_WARN_IF(!mUserHandle.Assign(aBuffer))) {
return NS_ERROR_OUT_OF_MEMORY;
}
return NS_OK;
}

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

@ -48,17 +48,18 @@ public:
SetSignature(CryptoBuffer& aBuffer);
void
GetUserId(DOMString& aRetVal);
GetUserHandle(JSContext* aCx, JS::MutableHandle<JSObject*> aRetVal);
nsresult
SetUserId(const nsAString& aUserId);
SetUserHandle(CryptoBuffer& aUserHandle);
private:
CryptoBuffer mAuthenticatorData;
JS::Heap<JSObject*> mAuthenticatorDataCachedObj;
CryptoBuffer mSignature;
JS::Heap<JSObject*> mSignatureCachedObj;
nsString mUserId;
CryptoBuffer mUserHandle;
JS::Heap<JSObject*> mUserHandleCachedObj;
};
} // namespace dom

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

@ -225,12 +225,12 @@ WebAuthnManager::MakeCredential(const MakePublicKeyCredentialOptions& aOptions,
return promise.forget();
}
// Enforce 4.4.3 User Account Parameters for Credential Generation
if (aOptions.mUser.mId.WasPassed()) {
// When we add UX, we'll want to do more with this value, but for now
// we just have to verify its correctness.
// Enforce 5.4.3 User Account Parameters for Credential Generation
// When we add UX, we'll want to do more with this value, but for now
// we just have to verify its correctness.
{
CryptoBuffer userId;
userId.Assign(aOptions.mUser.mId.Value());
userId.Assign(aOptions.mUser.mId);
if (userId.Length() > 64) {
promise->MaybeReject(NS_ERROR_DOM_TYPE_ERR);
return promise.forget();

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

@ -107,8 +107,12 @@ function() {
is(aAssertion.id, bytesToBase64UrlSafe(new Uint8Array(aAssertion.rawId)), "Encoded Key ID and Raw Key ID match");
ok(aAssertion.response.authenticatorData === aAssertion.response.authenticatorData, "AuthenticatorAssertionResponse.AuthenticatorData is SameObject");
ok(aAssertion.response.authenticatorData instanceof ArrayBuffer, "AuthenticatorAssertionResponse.AuthenticatorData is an ArrayBuffer");
ok(aAssertion.response.signature === aAssertion.response.signature, "AuthenticatorAssertionResponse.Signature is SameObject");
isnot(aAssertion.response.userId, undefined, "AuthenticatorAssertionResponse.UserId is defined")
ok(aAssertion.response.signature instanceof ArrayBuffer, "AuthenticatorAssertionResponse.Signature is an ArrayBuffer");
ok(aAssertion.response.userHandle === aAssertion.response.userHandle, "AuthenticatorAssertionResponse.UserHandle is SameObject");
ok(aAssertion.response.userHandle instanceof ArrayBuffer, "AuthenticatorAssertionResponse.UserHandle is an ArrayBuffer");
is(aAssertion.response.userHandle.byteLength, 0, "AuthenticatorAssertionResponse.UserHandle is emtpy");
ok(aAssertion.response.authenticatorData.byteLength > 0, "Authenticator data exists");
let clientData = JSON.parse(buffer2string(aAssertion.response.clientDataJSON));
@ -137,7 +141,7 @@ function() {
function testMakeCredential() {
let rp = {id: document.domain, name: "none", icon: "none"};
let user = {name: "none", icon: "none", displayName: "none"};
let user = {id: new Uint8Array(), name: "none", icon: "none", displayName: "none"};
let param = {type: "public-key", alg: cose_alg_ECDSA_w_SHA256};
let makeCredentialOptions = {
rp: rp,
@ -156,7 +160,7 @@ function() {
function testMakeDuplicate(aCredInfo) {
let rp = {id: document.domain, name: "none", icon: "none"};
let user = {name: "none", icon: "none", displayName: "none"};
let user = {id: new Uint8Array(), name: "none", icon: "none", displayName: "none"};
let param = {type: "public-key", alg: cose_alg_ECDSA_w_SHA256};
let makeCredentialOptions = {
rp: rp,

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

@ -87,6 +87,61 @@
.catch(expectTypeError);
},
// Test without rp.name
function() {
let rp = {id: document.domain, icon: "none"};
let makeCredentialOptions = {
rp: rp, user: user, challenge: gCredentialChallenge, pubKeyCredParams: [param]
};
return credm.create({publicKey: makeCredentialOptions})
.then(arrivingHereIsBad)
.catch(expectTypeError);
},
// Test without user.id
function() {
let user = {name: "none", icon: "none", displayName: "none"};
let makeCredentialOptions = {
rp: rp, user: user, challenge: gCredentialChallenge, pubKeyCredParams: [param]
};
return credm.create({publicKey: makeCredentialOptions})
.then(arrivingHereIsBad)
.catch(expectTypeError);
},
// Test without user.name
function() {
let user = {id: new Uint8Array(64), icon: "none", displayName: "none"};
let makeCredentialOptions = {
rp: rp, user: user, challenge: gCredentialChallenge, pubKeyCredParams: [param]
};
return credm.create({publicKey: makeCredentialOptions})
.then(arrivingHereIsBad)
.catch(expectTypeError);
},
// Test without user.displayName
function() {
let user = {id: new Uint8Array(64), name: "none", icon: "none"};
let makeCredentialOptions = {
rp: rp, user: user, challenge: gCredentialChallenge, pubKeyCredParams: [param]
};
return credm.create({publicKey: makeCredentialOptions})
.then(arrivingHereIsBad)
.catch(expectTypeError);
},
// Test with a user handle that exceeds the max length
function() {
let user = {id: new Uint8Array(65), name: "none", icon: "none", displayName: "none"};
let makeCredentialOptions = {
rp: rp, user: user, challenge: gCredentialChallenge, pubKeyCredParams: [param]
};
return credm.create({publicKey: makeCredentialOptions})
.then(arrivingHereIsBad)
.catch(expectTypeError);
},
// Test without any parameters; this is acceptable meaning the RP ID is
// happy to take any credential type
function() {

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

@ -44,7 +44,7 @@ function() {
function testMakeCredential() {
let rp = {id: document.domain, name: "none", icon: "none"};
let user = {name: "none", icon: "none", displayName: "none"};
let user = {id: new Uint8Array(), name: "none", icon: "none", displayName: "none"};
let param = {type: "public-key", alg: cose_alg_ECDSA_w_SHA256};
let makeCredentialOptions = {
rp: rp, user: user, challenge: credentialChallenge, pubKeyCredParams: [param]

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

@ -25,17 +25,18 @@
function arrivingHereIsGood(aResult) {
ok(true, "Good result! Received a: " + aResult);
return Promise.resolve();
}
function arrivingHereIsBad(aResult) {
ok(false, "Bad result! Received a: " + aResult);
return Promise.resolve();
}
function expectSecurityError(aResult) {
ok(aResult.toString().startsWith("SecurityError"), "Expecting a SecurityError");
return Promise.resolve();
}
function expectTypeError(aResult) {
ok(aResult.toString().startsWith("TypeError"), "Expecting a TypeError");
}
function keepThisPublicKeyCredential(aIdentifier) {
@ -66,7 +67,7 @@
var testFuncs = [
function() {
// Test basic good call
let rp = {id: document.domain};
let rp = {id: document.domain, name: "none"};
let makeCredentialOptions = {
rp: rp, user: user, challenge: chall, pubKeyCredParams: [param]
};
@ -78,15 +79,24 @@
function() {
// Test rp.id being unset
let makeCredentialOptions = {
rp: {}, user: user, challenge: chall, pubKeyCredParams: [param]
rp: {name: "none"}, user: user, challenge: chall, pubKeyCredParams: [param]
};
return credm.create({publicKey: makeCredentialOptions})
.then(arrivingHereIsGood)
.catch(arrivingHereIsBad);
},
function() {
// Test rp.name being unset
let makeCredentialOptions = {
rp: {id: document.domain}, user: user, challenge: chall, pubKeyCredParams: [param]
};
return credm.create({publicKey: makeCredentialOptions})
.then(arrivingHereIsBad)
.catch(expectTypeError);
},
function() {
// Test this origin with optional fields
let rp = {id: "user:pass@" + document.domain + ":8888"};
let rp = {id: "user:pass@" + document.domain + ":8888", name: "none"};
let makeCredentialOptions = {
rp: rp, user: user, challenge: chall, pubKeyCredParams: [param]
};
@ -96,7 +106,7 @@
},
function() {
// Test blank rp.id
let rp = {id: ""};
let rp = {id: "", name: "none"};
let makeCredentialOptions = {
rp: rp, user: user, challenge: chall, pubKeyCredParams: [param]
};
@ -106,7 +116,7 @@
},
function() {
// Test subdomain of this origin
let rp = {id: "subdomain." + document.domain};
let rp = {id: "subdomain." + document.domain, name: "none"};
let makeCredentialOptions = {
rp: rp, user: user, challenge: chall, pubKeyCredParams: [param]
};
@ -116,7 +126,7 @@
},
function() {
// Test the same origin
let rp = {id: "example.com"};
let rp = {id: "example.com", name: "none"};
let makeCredentialOptions = {
rp: rp, user: user, challenge: chall, pubKeyCredParams: [param]
};
@ -126,7 +136,7 @@
},
function() {
// Test the eTLD
let rp = {id: "com"};
let rp = {id: "com", name: "none"};
let makeCredentialOptions = {
rp: rp, user: user, challenge: chall, pubKeyCredParams: [param]
};
@ -136,7 +146,7 @@
},
function () {
// Test a different domain within the same TLD
let rp = {id: "alt.test"};
let rp = {id: "alt.test", name: "none"};
let makeCredentialOptions = {
rp: rp, user: user, challenge: chall, pubKeyCredParams: [param]
};
@ -233,7 +243,7 @@
},
function () {
// Test basic good Create call but using an origin (Bug 1380421)
let rp = {id: window.origin};
let rp = {id: window.origin, name: "none"};
let makeCredentialOptions = {
rp: rp, user: user, challenge: chall, pubKeyCredParams: [param]
};

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

@ -36,7 +36,7 @@ interface AuthenticatorAttestationResponse : AuthenticatorResponse {
interface AuthenticatorAssertionResponse : AuthenticatorResponse {
[SameObject] readonly attribute ArrayBuffer authenticatorData;
[SameObject] readonly attribute ArrayBuffer signature;
readonly attribute DOMString userId;
[SameObject] readonly attribute ArrayBuffer userHandle;
};
dictionary PublicKeyCredentialParameters {
@ -59,8 +59,8 @@ dictionary MakePublicKeyCredentialOptions {
};
dictionary PublicKeyCredentialEntity {
DOMString name;
USVString icon;
required DOMString name;
USVString icon;
};
dictionary PublicKeyCredentialRpEntity : PublicKeyCredentialEntity {
@ -68,8 +68,8 @@ dictionary PublicKeyCredentialRpEntity : PublicKeyCredentialEntity {
};
dictionary PublicKeyCredentialUserEntity : PublicKeyCredentialEntity {
BufferSource id;
DOMString displayName;
required BufferSource id;
required DOMString displayName;
};
dictionary AuthenticatorSelectionCriteria {
@ -115,9 +115,9 @@ enum PublicKeyCredentialType {
};
dictionary PublicKeyCredentialDescriptor {
required PublicKeyCredentialType type;
required BufferSource id;
sequence<AuthenticatorTransport> transports;
required PublicKeyCredentialType type;
required BufferSource id;
sequence<AuthenticatorTransport> transports;
};
enum AuthenticatorTransport {

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

@ -1,16 +1,29 @@
let clientId;
addEventListener('fetch', function(event) {
if (event.request.url.includes('getClients')) {
// Excepted to fail since the storage access is not allowed.
self.clients.matchAll();
} else if (event.request.url.includes('getClient-stage1')) {
self.clients.matchAll().then(function(clients) {
event.respondWith(async function() {
if (event.request.url.includes('getClients')) {
// Expected to fail since the storage access is not allowed.
try {
await self.clients.matchAll();
} catch (e) {
// expected failure
}
} else if (event.request.url.includes('getClient-stage1')) {
let clients = await self.clients.matchAll();
clientId = clients[0].id;
});
} else if (event.request.url.includes('getClient-stage2')) {
// Excepted to fail since the storage access is not allowed.
self.clients.get(clientId);
}
} else if (event.request.url.includes('getClient-stage2')) {
// Expected to fail since the storage access is not allowed.
try {
await self.clients.get(clientId);
} catch(e) {
// expected failure
}
}
// Pass through the network request once our various Clients API
// promises have completed.
return await fetch(event.request);
}());
});
addEventListener('message', function(event) {

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

@ -730,6 +730,8 @@ static inline wr::WrFilterOpType ToWrFilterOpType(uint32_t type) {
return wr::WrFilterOpType::Saturate;
case NS_STYLE_FILTER_SEPIA:
return wr::WrFilterOpType::Sepia;
case NS_STYLE_FILTER_DROP_SHADOW:
return wr::WrFilterOpType::DropShadow;
}
MOZ_ASSERT_UNREACHABLE("Tried to convert unknown filter type.");
return wr::WrFilterOpType::Grayscale;

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

@ -359,13 +359,16 @@ pub enum WrFilterOpType {
Opacity = 6,
Saturate = 7,
Sepia = 8,
DropShadow = 9,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct WrFilterOp {
filter_type: WrFilterOpType,
argument: c_float,
argument: c_float, // holds radius for DropShadow; value for other filters
offset: LayoutVector2D, // only used for DropShadow
color: ColorF, // only used for DropShadow
}
/// cbindgen:derive-eq=false
@ -1293,6 +1296,9 @@ pub extern "C" fn wr_dp_push_stacking_context(state: &mut WrState,
WrFilterOpType::Opacity => FilterOp::Opacity(PropertyBinding::Value(c_filter.argument), c_filter.argument),
WrFilterOpType::Saturate => FilterOp::Saturate(c_filter.argument),
WrFilterOpType::Sepia => FilterOp::Sepia(c_filter.argument),
WrFilterOpType::DropShadow => FilterOp::DropShadow(c_filter.offset,
c_filter.argument,
c_filter.color),
}
}).collect();

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

@ -225,6 +225,7 @@ enum class WrFilterOpType : uint32_t {
Opacity = 6,
Saturate = 7,
Sepia = 8,
DropShadow = 9,
Sentinel /* this must be last for serialization purposes. */
};
@ -691,10 +692,14 @@ struct WrAnimationProperty {
struct WrFilterOp {
WrFilterOpType filter_type;
float argument;
LayoutVector2D offset;
ColorF color;
bool operator==(const WrFilterOp& aOther) const {
return filter_type == aOther.filter_type &&
argument == aOther.argument;
argument == aOther.argument &&
offset == aOther.offset &&
color == aOther.color;
}
};

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

@ -74,14 +74,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1078327
var rect_t = target.getBoundingClientRect();
var rect_m = mediator.getBoundingClientRect();
var rect_l = listener.getBoundingClientRect();
synthesizePointer(target, rect_t.width/2, rect_t.height/20, {type: "pointerdown"});
synthesizePointer(target, rect_t.width/2, rect_t.height/20, {type: "pointermove"});
synthesizePointer(mediator, rect_m.width/2, rect_m.height/20, {type: "pointermove"});
synthesizePointer(listener, rect_l.width/2, rect_l.height/20, {type: "pointermove"});
synthesizePointer(mediator, rect_m.width/2, rect_m.height/20, {type: "pointermove"});
synthesizePointer(target, rect_t.width/2, rect_t.height/20, {type: "pointermove"});
synthesizePointer(target, rect_t.width/2, rect_t.height/20, {type: "pointerup"});
synthesizePointer(target, rect_t.width/2, rect_t.height/20, {type: "pointermove"});
synthesizeMouse(target, rect_t.width/2, rect_t.height/20, {type: "mousedown"});
synthesizeMouse(target, rect_t.width/2, rect_t.height/20, {type: "mousemove"});
synthesizeMouse(mediator, rect_m.width/2, rect_m.height/20, {type: "mousemove"});
synthesizeMouse(listener, rect_l.width/2, rect_l.height/20, {type: "mousemove"});
synthesizeMouse(mediator, rect_m.width/2, rect_m.height/20, {type: "mousemove"});
synthesizeMouse(target, rect_t.width/2, rect_t.height/20, {type: "mousemove"});
synthesizeMouse(target, rect_t.width/2, rect_t.height/20, {type: "mouseup"});
synthesizeMouse(target, rect_t.width/2, rect_t.height/20, {type: "mousemove"});
finishTest();
}
function finishTest() {

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

@ -59,9 +59,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1080360
listener.addEventListener("lostpointercapture", ListenerHandler);
document.addEventListener("lostpointercapture", DocumentHandler);
var rect = target.getBoundingClientRect();
synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointerdown"});
synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointermove"});
synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointerup"});
synthesizeMouse(target, rect.width/2, rect.height/2, {type: "mousedown"});
synthesizeMouse(target, rect.width/2, rect.height/2, {type: "mousemove"});
synthesizeMouse(target, rect.width/2, rect.height/2, {type: "mouseup"});
finishTest();
}
function finishTest() {

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

@ -83,9 +83,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1080361
target.addEventListener("pointerup", TargetUpHandler);
listener.addEventListener("gotpointercapture", ListenerHandler);
var rect = target.getBoundingClientRect();
synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointerdown"});
synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointermove"});
synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointerup"});
synthesizeMouse(target, rect.width/2, rect.height/2, {type: "mousedown"});
synthesizeMouse(target, rect.width/2, rect.height/2, {type: "mousemove"});
synthesizeMouse(target, rect.width/2, rect.height/2, {type: "mouseup"});
finishTest();
}
function finishTest() {

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

@ -46,12 +46,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1153130
target.addEventListener("gotpointercapture", TargetHandler);
target.addEventListener("pointermove", TargetHandler);
var rect = target.getBoundingClientRect();
synthesizePointer(target, rect.width/5, rect.height/5, {type: "pointermove"});
synthesizePointer(target, rect.width/5, rect.height/5, {type: "pointerdown"});
synthesizePointer(target, rect.width/4, rect.height/4, {type: "pointermove"});
synthesizePointer(target, rect.width/3, rect.height/3, {type: "pointermove"});
synthesizePointer(target, rect.width/3, rect.height/3, {type: "pointerup"});
synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointermove"});
synthesizeMouse(target, rect.width/5, rect.height/5, {type: "mousemove"});
synthesizeMouse(target, rect.width/5, rect.height/5, {type: "mousedown"});
synthesizeMouse(target, rect.width/4, rect.height/4, {type: "mousemove"});
synthesizeMouse(target, rect.width/3, rect.height/3, {type: "mousemove"});
synthesizeMouse(target, rect.width/3, rect.height/3, {type: "mouseup"});
synthesizeMouse(target, rect.width/2, rect.height/2, {type: "mousemove"});
test_success = true;
finishTest();
}

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

@ -100,13 +100,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1162990
setEventHandlers();
var rectCd = child.getBoundingClientRect();
var rectLr = listener.getBoundingClientRect();
synthesizePointer(listener, rectLr.width/3, rectLr.height/2, {type: "pointerdown"});
synthesizePointer(child, rectCd.width/3, rectCd.height/2, {type: "pointermove"});
synthesizePointer(listener, rectLr.width/3, rectLr.height/2, {type: "pointermove"});
synthesizePointer(child, rectCd.width/3, rectCd.height/2, {type: "pointermove"});
synthesizePointer(listener, rectLr.width/3, rectLr.height/2, {type: "pointermove"});
synthesizePointer(listener, rectLr.width/3, rectLr.height/2, {type: "pointerup"});
synthesizePointer(listener, rectLr.width/3, rectLr.height/3, {type: "pointermove"});
synthesizeMouse(listener, rectLr.width/3, rectLr.height/2, {type: "mousedown"});
synthesizeMouse(child, rectCd.width/3, rectCd.height/2, {type: "mousemove"});
synthesizeMouse(listener, rectLr.width/3, rectLr.height/2, {type: "mousemove"});
synthesizeMouse(child, rectCd.width/3, rectCd.height/2, {type: "mousemove"});
synthesizeMouse(listener, rectLr.width/3, rectLr.height/2, {type: "mousemove"});
synthesizeMouse(listener, rectLr.width/3, rectLr.height/2, {type: "mouseup"});
synthesizeMouse(listener, rectLr.width/3, rectLr.height/3, {type: "mousemove"});
finishTest();
}

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

@ -101,13 +101,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1162990
var rectTg = target.getBoundingClientRect();
var rectCd = child.getBoundingClientRect();
var rectLr = listener.getBoundingClientRect();
synthesizePointer(target, rectTg.width/3, rectTg.height/7, {type: "pointerdown"});
synthesizePointer(child, rectCd.width/3, rectCd.height/2, {type: "pointermove"});
synthesizePointer(listener, rectLr.width/3, rectLr.height/2, {type: "pointermove"});
synthesizePointer(child, rectCd.width/3, rectCd.height/2, {type: "pointermove"});
synthesizePointer(target, rectTg.width/3, rectTg.height/7, {type: "pointermove"});
synthesizePointer(target, rectTg.width/3, rectTg.height/7, {type: "pointerup"});
synthesizePointer(target, rectTg.width/3, rectTg.height/9, {type: "pointermove"});
synthesizeMouse(target, rectTg.width/3, rectTg.height/7, {type: "mousedown"});
synthesizeMouse(child, rectCd.width/3, rectCd.height/2, {type: "mousemove"});
synthesizeMouse(listener, rectLr.width/3, rectLr.height/2, {type: "mousemove"});
synthesizeMouse(child, rectCd.width/3, rectCd.height/2, {type: "mousemove"});
synthesizeMouse(target, rectTg.width/3, rectTg.height/7, {type: "mousemove"});
synthesizeMouse(target, rectTg.width/3, rectTg.height/7, {type: "mouseup"});
synthesizeMouse(target, rectTg.width/3, rectTg.height/9, {type: "mousemove"});
finishTest();
}

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

@ -56,57 +56,57 @@ var test2d1pointergotcapture = 0;
var test2d2pointergotcapture = 0;
var test1PointerId = 1;
var test2PointerId = 2;
function sendPointerMove(el, id) {
var rect = el.getBoundingClientRect();
var utils = SpecialPowers.getDOMWindowUtils(window);
utils.sendPointerEvent('pointermove', rect.left + 5, rect.top + 5, 0, 0, 0, false, 0, SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH, id);
}
function sendPointerDown(el, id) {
var rect = el.getBoundingClientRect();
var utils = SpecialPowers.getDOMWindowUtils(window);
utils.sendPointerEvent('pointerdown', rect.left + 5, rect.top + 5, 0, 1, 0, false, 0, SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH, id);
}
function sendPointerUp(el, id) {
var rect = el.getBoundingClientRect();
var utils = SpecialPowers.getDOMWindowUtils(window);
utils.sendPointerEvent('pointerup', rect.left + 5, rect.top + 5, 0, 1, 0, false, 0, SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH, id);
}
var rx = 1;
var ry = 1;
var angle = 0;
var force = 1;
var modifiers = 0;
var utils = SpecialPowers.getDOMWindowUtils(window);
function log(s) {
document.getElementById("l").textContent += s + "\n";
}
function test1d2Listener(e) {
function test1d1IncreasePointerMoveCount(e) {
log(e.type + ", " + e.target.id);
is(e.target, test1d2, "test1d2 should have got pointermove.");
is(e.target, test1d1, "check target is 1d1.");
++test1d1pointermovecount;
}
function test1d2IncreasePointerMoveCount(e) {
log(e.type + ", " + e.target.id);
is(e.target, test1d2, "check target is 1d2.");
++test1d2pointermovecount;
}
function test2d2Listener(e) {
function test2d1IncreasePointerMoveCount(e) {
log(e.type + ", " + e.target.id);
is(e.target, test2d2, "test2d2 should have got pointermove.");
is(e.target, test2d1, "check target is 2d1.");
++test2d1pointermovecount;
}
function test2d2IncreasePointerMoveCount(e) {
log(e.type + ", " + e.target.id);
is(e.target, test2d2, "check target is 2d2.");
++test2d2pointermovecount;
}
function test1d1DownListener(e) {
function test1d1CapturePointer(e) {
log(e.type + ", " + e.target.id);
test1d1.setPointerCapture(e.pointerId);
}
function test1d1MoveListener(e) {
function test1d2CapturePointer(e) {
log(e.type + ", " + e.target.id);
test1d2.setPointerCapture(e.pointerId);
}
function test2d1DownListener(e) {
function test2d1CapturePointer(e) {
log(e.type + ", " + e.target.id);
test2d1.setPointerCapture(e.pointerId);
}
function test2d1MoveListener(e) {
function test2d2CapturePointer(e) {
log(e.type + ", " + e.target.id);
test2d2.setPointerCapture(e.pointerId);
}
@ -151,24 +151,30 @@ function test2d2PointerLostCapture(e) {
++test2d2pointerlostcapture;
}
function test1d1PointerMoveListener(e) {
log(e.type + ", " + e.target.id);
++test1d1pointermovecount;
}
function test2d1PointerMoveListener(e) {
log(e.type + ", " + e.target.id);
++test2d1pointermovecount;
}
function runTests() {
test1d1 = document.getElementById("test1d1");
test1d2 = document.getElementById("test1d2");
test2d1 = document.getElementById("test2d1");
test2d2 = document.getElementById("test2d2");
test1d2.addEventListener("pointermove", test1d2Listener, true);
test2d2.addEventListener("pointermove", test2d2Listener, true);
var rect1d1 = test1d1.getBoundingClientRect();
var rect1d2 = test1d2.getBoundingClientRect();
var rect2d1 = test2d1.getBoundingClientRect();
var rect2d2 = test2d2.getBoundingClientRect();
var left1d1 = rect1d1.left + 5;
var top1d1 = rect1d1.top + 5;
var left1d2 = rect1d2.left + 5;
var top1d2 = rect1d2.top + 5;
var left2d1 = rect2d1.left + 5;
var top2d1 = rect2d1.top + 5;
var left2d2 = rect2d2.left + 5;
var top2d2 = rect2d2.top + 5;
test1d1.addEventListener("pointermove", test1d1IncreasePointerMoveCount, true);
test1d2.addEventListener("pointermove", test1d2IncreasePointerMoveCount, true);
test2d1.addEventListener("pointermove", test2d1IncreasePointerMoveCount, true);
test2d2.addEventListener("pointermove", test2d2IncreasePointerMoveCount, true);
test1d1.addEventListener("gotpointercapture", test1d1PointerGotCapture, true);
test1d1.addEventListener("lostpointercapture", test1d1PointerLostCapture, true);
@ -183,86 +189,91 @@ function runTests() {
test2d2.addEventListener("lostpointercapture", test2d2PointerLostCapture, true);
document.body.offsetLeft;
sendPointerMove(test1d2, test1PointerId);
sendPointerMove(test2d2, test2PointerId);
is(test1d2pointermovecount, 1, "Should have got pointermove");
is(test2d2pointermovecount, 1, "Should have got pointermove");
// This shouldn't enable capturing, since we're not in a right kind of
// event listener.
sendPointerDown(test1d1, test1PointerId);
sendPointerDown(test2d1, test2PointerId);
utils.sendTouchEvent('touchstart', [test1PointerId, test2PointerId],
[left1d1, left2d1], [top1d1, top2d1], [rx, rx], [ry, ry],
[angle, angle], [force, force], 2, modifiers);
sendPointerMove(test1d2, test1PointerId);
sendPointerMove(test2d2, test2PointerId);
utils.sendTouchEvent('touchmove', [test1PointerId, test2PointerId],
[left1d2, left2d2], [top1d2, top2d2], [rx, rx], [ry, ry],
[angle, angle], [force, force], 2, modifiers);
sendPointerUp(test1d1, test1PointerId);
sendPointerUp(test2d1, test2PointerId);
utils.sendTouchEvent('touchend', [test1PointerId, test2PointerId],
[left1d1, left2d1], [top1d1, top2d1], [rx, rx], [ry, ry],
[angle, angle], [force, force], 2, modifiers);
is(test1d2pointermovecount, 2, "Should have got pointermove");
is(test2d2pointermovecount, 2, "Should have got pointermove");
// No implicitly / explicitly pointer capture. pointermove should be
// dispatched to 1d2, 2d2
is(test1d1pointermovecount, 0, "1d1 shouldn't have got pointermove");
is(test2d1pointermovecount, 0, "2d1 shouldn't have got pointermove");
is(test1d2pointermovecount, 1, "1d2 should have got pointermove");
is(test2d2pointermovecount, 1, "2d2 should have got pointermove");
test1d1.addEventListener("pointerdown", test1d1DownListener, true);
test1d1.addEventListener("pointermove", test1d1PointerMoveListener, true);
test2d1.addEventListener("pointerdown", test2d1DownListener, true);
test2d1.addEventListener("pointermove", test2d1PointerMoveListener, true);
// Explicitly capture pointer to 1d1, 2d1
test1d1.addEventListener("pointerdown", test1d1CapturePointer, {capture: true, once: true});
test2d1.addEventListener("pointerdown", test2d1CapturePointer, {capture: true, once: true});
sendPointerDown(test1d1, test1PointerId);
sendPointerDown(test2d1, test2PointerId);
sendPointerMove(test1d2, test1PointerId);
sendPointerMove(test2d2, test2PointerId);
is(test1d2pointermovecount, 2, "Shouldn't have got pointermove");
is(test1d1pointermovecount, 1, "Should have got pointermove");
is(test1d1pointergotcapture, 1, "Should have got pointergotcapture");
utils.sendTouchEvent('touchstart', [test1PointerId, test2PointerId],
[left1d1, left2d1], [top1d1, top2d1], [rx, rx], [ry, ry],
[angle, angle], [force, force], 2, modifiers);
is(test2d2pointermovecount, 2, "Shouldn't have got pointermove");
is(test2d1pointermovecount, 1, "Should have got pointermove");
is(test2d1pointergotcapture, 1, "Should have got pointergotcapture");
utils.sendTouchEvent('touchmove', [test1PointerId, test2PointerId],
[left1d2, left2d2], [top1d2, top2d2], [rx, rx], [ry, ry],
[angle, angle], [force, force], 2, modifiers);
sendPointerUp(test1d1, test1PointerId);
sendPointerUp(test2d1, test2PointerId);
test1d1.removeEventListener("pointerdown", test1d1DownListener, true);
test1d1.removeEventListener("pointermove", test1d1PointerMoveListener, true);
test2d1.removeEventListener("pointerdown", test2d1DownListener, true);
test2d1.removeEventListener("pointermove", test2d1PointerMoveListener, true);
// Explicitly capture pointer to 1d1, 2d1. pointermove, gotpointercapture
// should be dispatched to 1d1, 2d1
is(test1d1pointermovecount, 1, "1d1 should have got pointermove");
is(test1d1pointergotcapture, 1, "1d1 should have got pointergotcapture");
is(test1d2pointermovecount, 1, "1d2 shouldn't have got pointermove");
is(test1d2pointergotcapture, 0, "1d2 shouldn't have got pointergotcapture");
// Nothing should be capturing the event.
sendPointerMove(test1d2, test1PointerId);
sendPointerMove(test2d2, test2PointerId);
is(test2d1pointermovecount, 1, "2d1 should have got pointermove");
is(test2d1pointergotcapture, 1, "2d1 should have got pointergotcapture");
is(test2d2pointermovecount, 1, "2d2 shouldn't have got pointermove");
is(test2d2pointergotcapture, 0, "2d2 shouldn't have got pointergotcapture");
is(test1d2pointermovecount, 3, "Should have got pointermove");
is(test1d1pointerlostcapture, 1, "Should have got pointerlostcapture");
is(test2d2pointermovecount, 3, "Should have got pointermove");
is(test2d1pointerlostcapture, 1, "Should have got pointerlostcapture");
utils.sendTouchEvent('touchend', [test1PointerId, test2PointerId],
[left1d1, left2d1], [top1d1, top2d1], [rx, rx], [ry, ry],
[angle, angle], [force, force], 2, modifiers);
test1d1.addEventListener("pointermove", test1d1MoveListener, true);
test2d1.addEventListener("pointermove", test2d1MoveListener, true);
// Explicitly capture pointer to 1d1, 2d1 when pointerdown
test1d1.addEventListener("pointerdown", test1d1CapturePointer, {capture: true, once: true});
test2d1.addEventListener("pointerdown", test2d1CapturePointer, {capture: true, once: true});
sendPointerDown(test1d1, test1PointerId);
sendPointerDown(test2d1, test2PointerId);
// Explicitly capture pointer to 1d2, 2d2 when pointermove
test1d1.addEventListener("pointermove", test1d2CapturePointer, {capture: true, once: true});
test2d1.addEventListener("pointermove", test2d2CapturePointer, {capture: true, once: true});
sendPointerMove(test1d1, test1PointerId); // This should call setPointerCapture to test1d2!
sendPointerMove(test2d1, test2PointerId); // This should call setPointerCapture to test2d2!
utils.sendTouchEvent('touchstart', [test1PointerId, test2PointerId],
[left1d1, left2d1], [top1d1, top2d1], [rx, rx], [ry, ry],
[angle, angle], [force, force], 2, modifiers);
test1d1.removeEventListener("pointermove", test1d1MoveListener, true);
test1d1.addEventListener("pointermove", test1d1PointerMoveListener, true);
// This should send pointer event to test1d1, test2d1.
utils.sendTouchEvent('touchmove', [test1PointerId, test2PointerId],
[left1d1, left2d1], [top1d1, top2d1], [rx, rx], [ry, ry],
[angle, angle], [force, force], 2, modifiers);
test2d1.removeEventListener("pointermove", test2d1MoveListener, true);
test2d1.addEventListener("pointermove", test2d1PointerMoveListener, true);
// This should send pointer event to test1d2, test2d2.
utils.sendTouchEvent('touchmove', [test1PointerId, test2PointerId],
[left1d1, left2d1], [top1d1, top2d1], [rx, rx], [ry, ry],
[angle, angle], [force, force], 2, modifiers);
sendPointerMove(test1d1, test1PointerId); // This should send pointer event to test1d2.
sendPointerMove(test2d1, test2PointerId); // This should send pointer event to test2d2.
is(test1d1pointermovecount, 2, "1d1 should have got pointermove");
is(test1d1pointergotcapture, 2, "1d1 should have got pointergotcapture");
is(test1d2pointermovecount, 2, "1d2 should have got pointermove");
is(test1d2pointergotcapture, 1, "1d2 should have got pointergotcapture");
is(test1d1pointermovecount, 1, "Shouldn't have got pointermove");
is(test1d2pointermovecount, 4, "Should have got pointermove");
is(test1d2pointergotcapture, 1, "Should have got pointergotcapture");
is(test2d1pointermovecount, 2, "2d1 should have got pointermove");
is(test2d1pointergotcapture, 2, "2d1 should have got pointergotcapture");
is(test2d2pointermovecount, 2, "2d2 should have got pointermove");
is(test2d2pointergotcapture, 1, "2d2 should have got pointergotcapture");
is(test2d1pointermovecount, 1, "Shouldn't have got pointermove");
is(test2d2pointermovecount, 4, "Should have got pointermove");
is(test2d2pointergotcapture, 1, "Should have got pointergotcapture");
sendPointerUp(test1d1, test1PointerId);
sendPointerUp(test2d1, test2PointerId);
utils.sendTouchEvent('touchend', [test1PointerId, test2PointerId],
[left1d1, left2d1], [top1d1, top2d1], [rx, rx], [ry, ry],
[angle, angle], [force, force], 2, modifiers);
finishTest();
}
@ -271,7 +282,7 @@ function finishTest() {
// Let window.onerror have a chance to fire
setTimeout(function() {
setTimeout(function() {
window.parent.postMessage("SimpleTest.finish();", "*");
window.parent.postMessage("run next", "*");
}, 0);
}, 0);
}
@ -280,6 +291,7 @@ window.onload = function () {
SpecialPowers.pushPrefEnv({
"set": [
["dom.w3c_pointer_events.enabled", true],
["dom.w3c_pointer_events.implicit_capture", false]
]
}, runTests);
}

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

@ -0,0 +1,306 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=968148
-->
<head>
<title>Test for Bug 968148</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<style>
.test {
width: 20px;
height: 20px;
border: 1px solid black;
-moz-user-select: none;
}
</style>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=968148">Mozilla Bug 968148</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/**
* Test for Bug 968148, test orignally copied from test_bug582771.html.
* Mouse functionality converted to pointer and all steps duplicated in order to run them in parallel for two different pointer Id's
**/
function ok(condition, msg) {
parent.ok(condition, msg);
}
function is(a, b, msg) {
parent.is(a, b, msg);
}
var test1d1;
var test1d2;
var test2d1;
var test2d2;
var test1d1pointermovecount = 0;
var test1d2pointermovecount = 0;
var test2d1pointermovecount = 0;
var test2d2pointermovecount = 0;
var test1d1pointerlostcapture = 0;
var test1d2pointerlostcapture = 0;
var test2d1pointerlostcapture = 0;
var test2d2pointerlostcapture = 0;
var test1d1pointergotcapture = 0;
var test1d2pointergotcapture = 0;
var test2d1pointergotcapture = 0;
var test2d2pointergotcapture = 0;
var test1PointerId = 1;
var test2PointerId = 2;
var rx = 1;
var ry = 1;
var angle = 0;
var force = 1;
var modifiers = 0;
var utils = SpecialPowers.getDOMWindowUtils(window);
function log(s) {
document.getElementById("l").textContent += s + "\n";
}
function test1d1IncreasePointerMoveCount(e) {
log(e.type + ", " + e.target.id);
is(e.target, test1d1, "check target is 1d1.");
++test1d1pointermovecount;
}
function test1d2IncreasePointerMoveCount(e) {
log(e.type + ", " + e.target.id);
is(e.target, test1d2, "check target is 1d2.");
++test1d2pointermovecount;
}
function test2d1IncreasePointerMoveCount(e) {
log(e.type + ", " + e.target.id);
is(e.target, test2d1, "check target is 2d1.");
++test2d1pointermovecount;
}
function test2d2IncreasePointerMoveCount(e) {
log(e.type + ", " + e.target.id);
is(e.target, test2d2, "check target is 2d2.");
++test2d2pointermovecount;
}
function test1d1CapturePointer(e) {
log(e.type + ", " + e.target.id);
test1d1.setPointerCapture(e.pointerId);
}
function test1d2CapturePointer(e) {
log(e.type + ", " + e.target.id);
test1d2.setPointerCapture(e.pointerId);
}
function test2d1CapturePointer(e) {
log(e.type + ", " + e.target.id);
test2d1.setPointerCapture(e.pointerId);
}
function test2d2CapturePointer(e) {
log(e.type + ", " + e.target.id);
test2d2.setPointerCapture(e.pointerId);
}
function test1d1PointerGotCapture(e) {
log(e.type + ", " + e.target.id);
++test1d1pointergotcapture;
}
function test1d1PointerLostCapture(e) {
log(e.type + ", " + e.target.id);
++test1d1pointerlostcapture;
}
function test2d1PointerGotCapture(e) {
log(e.type + ", " + e.target.id);
++test2d1pointergotcapture;
}
function test2d1PointerLostCapture(e) {
log(e.type + ", " + e.target.id);
++test2d1pointerlostcapture;
}
function test1d2PointerGotCapture(e) {
log(e.type + ", " + e.target.id);
++test1d2pointergotcapture;
}
function test1d2PointerLostCapture(e) {
log(e.type + ", " + e.target.id);
++test1d2pointerlostcapture;
}
function test2d2PointerGotCapture(e) {
log(e.type + ", " + e.target.id);
++test2d2pointergotcapture;
}
function test2d2PointerLostCapture(e) {
log(e.type + ", " + e.target.id);
++test2d2pointerlostcapture;
}
function runTests() {
test1d1 = document.getElementById("test1d1");
test1d2 = document.getElementById("test1d2");
test2d1 = document.getElementById("test2d1");
test2d2 = document.getElementById("test2d2");
var rect1d1 = test1d1.getBoundingClientRect();
var rect1d2 = test1d2.getBoundingClientRect();
var rect2d1 = test2d1.getBoundingClientRect();
var rect2d2 = test2d2.getBoundingClientRect();
var left1d1 = rect1d1.left + 5;
var top1d1 = rect1d1.top + 5;
var left1d2 = rect1d2.left + 5;
var top1d2 = rect1d2.top + 5;
var left2d1 = rect2d1.left + 5;
var top2d1 = rect2d1.top + 5;
var left2d2 = rect2d2.left + 5;
var top2d2 = rect2d2.top + 5;
test1d1.addEventListener("pointermove", test1d1IncreasePointerMoveCount, true);
test1d2.addEventListener("pointermove", test1d2IncreasePointerMoveCount, true);
test2d1.addEventListener("pointermove", test2d1IncreasePointerMoveCount, true);
test2d2.addEventListener("pointermove", test2d2IncreasePointerMoveCount, true);
test1d1.addEventListener("gotpointercapture", test1d1PointerGotCapture, true);
test1d1.addEventListener("lostpointercapture", test1d1PointerLostCapture, true);
test2d1.addEventListener("gotpointercapture", test2d1PointerGotCapture, true);
test2d1.addEventListener("lostpointercapture", test2d1PointerLostCapture, true);
test1d2.addEventListener("gotpointercapture", test1d2PointerGotCapture, true);
test1d2.addEventListener("lostpointercapture", test1d2PointerLostCapture, true);
test2d2.addEventListener("gotpointercapture", test2d2PointerGotCapture, true);
test2d2.addEventListener("lostpointercapture", test2d2PointerLostCapture, true);
document.body.offsetLeft;
// This shouldn't enable capturing, since we're not in a right kind of
// event listener.
utils.sendTouchEvent('touchstart', [test1PointerId, test2PointerId],
[left1d1, left2d1], [top1d1, top2d1], [rx, rx], [ry, ry],
[angle, angle], [force, force], 2, modifiers);
utils.sendTouchEvent('touchmove', [test1PointerId, test2PointerId],
[left1d2, left2d2], [top1d2, top2d2], [rx, rx], [ry, ry],
[angle, angle], [force, force], 2, modifiers);
utils.sendTouchEvent('touchend', [test1PointerId, test2PointerId],
[left1d1, left2d1], [top1d1, top2d1], [rx, rx], [ry, ry],
[angle, angle], [force, force], 2, modifiers);
// Implicitly pointer capture. pointermove should be dispatched to 1d1, 2d1
is(test1d1pointermovecount, 1, "1d1 should have got pointermove");
is(test2d1pointermovecount, 1, "2d1 should have got pointermove");
is(test1d2pointermovecount, 0, "1d2 shouldn't have got pointermove");
is(test2d2pointermovecount, 0, "2d2 shouldn't have got pointermove");
// Explicitly capture pointer to 1d1, 2d1
test1d1.addEventListener("pointerdown", test1d1CapturePointer, {capture: true, once: true});
test2d1.addEventListener("pointerdown", test2d1CapturePointer, {capture: true, once: true});
utils.sendTouchEvent('touchstart', [test1PointerId, test2PointerId],
[left1d1, left2d1], [top1d1, top2d1], [rx, rx], [ry, ry],
[angle, angle], [force, force], 2, modifiers);
utils.sendTouchEvent('touchmove', [test1PointerId, test2PointerId],
[left1d2, left2d2], [top1d2, top2d2], [rx, rx], [ry, ry],
[angle, angle], [force, force], 2, modifiers);
// Explicitly capture pointer to 1d1, 2d1. pointermove, gotpointercapture
// should be dispatched to 1d1, 2d1
is(test1d1pointermovecount, 2, "1d1 should have got pointermove");
is(test1d1pointergotcapture, 2, "1d1 should have got pointergotcapture");
is(test1d2pointermovecount, 0, "1d2 shouldn't have got pointermove");
is(test1d2pointergotcapture, 0, "1d2 shouldn't have got pointergotcapture");
is(test2d1pointermovecount, 2, "2d1 should have got pointermove");
is(test2d1pointergotcapture, 2, "2d1 should have got pointergotcapture");
is(test2d2pointermovecount, 0, "2d2 shouldn't have got pointermove");
is(test2d2pointergotcapture, 0, "2d2 shouldn't have got pointergotcapture");
utils.sendTouchEvent('touchend', [test1PointerId, test2PointerId],
[left1d1, left2d1], [top1d1, top2d1], [rx, rx], [ry, ry],
[angle, angle], [force, force], 2, modifiers);
// Explicitly capture pointer to 1d1, 2d1 when pointerdown
test1d1.addEventListener("pointerdown", test1d1CapturePointer, {capture: true, once: true});
test2d1.addEventListener("pointerdown", test2d1CapturePointer, {capture: true, once: true});
// Explicitly capture pointer to 1d2, 2d2 when pointermove
test1d1.addEventListener("pointermove", test1d2CapturePointer, {capture: true, once: true});
test2d1.addEventListener("pointermove", test2d2CapturePointer, {capture: true, once: true});
utils.sendTouchEvent('touchstart', [test1PointerId, test2PointerId],
[left1d1, left2d1], [top1d1, top2d1], [rx, rx], [ry, ry],
[angle, angle], [force, force], 2, modifiers);
// This should send pointer event to test1d1, test2d1.
utils.sendTouchEvent('touchmove', [test1PointerId, test2PointerId],
[left1d1, left2d1], [top1d1, top2d1], [rx, rx], [ry, ry],
[angle, angle], [force, force], 2, modifiers);
// This should send pointer event to test1d2, test2d2.
utils.sendTouchEvent('touchmove', [test1PointerId, test2PointerId],
[left1d1, left2d1], [top1d1, top2d1], [rx, rx], [ry, ry],
[angle, angle], [force, force], 2, modifiers);
is(test1d1pointermovecount, 3, "1d1 shouldn't have got pointermove");
is(test1d1pointergotcapture, 3, "1d1 should have got pointergotcapture");
is(test1d2pointermovecount, 1, "1d2 should have got pointermove");
is(test1d2pointergotcapture, 1, "1d2 should have got pointergotcapture");
is(test2d1pointermovecount, 3, "2d1 shouldn't have got pointermove");
is(test2d1pointergotcapture, 3, "2d1 should have got pointergotcapture");
is(test2d2pointermovecount, 1, "2d2 should have got pointermove");
is(test2d2pointergotcapture, 1, "2d2 should have got pointergotcapture");
utils.sendTouchEvent('touchend', [test1PointerId, test2PointerId],
[left1d1, left2d1], [top1d1, top2d1], [rx, rx], [ry, ry],
[angle, angle], [force, force], 2, modifiers);
finishTest();
}
function finishTest() {
// Let window.onerror have a chance to fire
setTimeout(function() {
setTimeout(function() {
window.parent.postMessage("finishTest", "*");
}, 0);
}, 0);
}
window.onload = function () {
SpecialPowers.pushPrefEnv({
"set": [
["dom.w3c_pointer_events.enabled", true],
["dom.w3c_pointer_events.implicit_capture", true]
]
}, runTests);
}
SimpleTest.waitForExplicitFinish();
</script>
</pre>
<div class="test" id="test1d1">&nbsp;</div><br><div class="test" id="test1d2">&nbsp;</div>
<div class="test" id="test2d1">&nbsp;</div><br><div class="test" id="test2d2">&nbsp;</div>
<pre id="l"></pre>
</body>
</html>

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

@ -68,8 +68,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1098139
target.addEventListener("gotpointercapture", GotPCHandler);
target.addEventListener("lostpointercapture", LostPCHandler);
var rect = target.getBoundingClientRect();
synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointerdown"});
synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointerup"});
synthesizeMouse(target, rect.width/2, rect.height/2, {type: "mousedown"});
synthesizeMouse(target, rect.width/2, rect.height/2, {type: "mouseup"});
finishTest();
}
function finishTest() {

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

@ -50,8 +50,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=977003
listener.addEventListener("gotpointercapture", ListenerHandler);
listener.addEventListener("lostpointercapture", ListenerHandler);
var rect = target.getBoundingClientRect();
synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointerdown"});
synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointerup"});
synthesizeMouse(target, rect.width/2, rect.height/2, {type: "mousedown"});
synthesizeMouse(target, rect.width/2, rect.height/2, {type: "mouseup"});
finishTest();
}
function finishTest() {

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

@ -66,9 +66,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=977003
listener.addEventListener("gotpointercapture", ListenerHandler);
listener.addEventListener("lostpointercapture", ListenerHandler);
var rect = target.getBoundingClientRect();
synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointerdown"});
synthesizePointer(target, rect.width/3, rect.height/3, {type: "pointermove"});
synthesizePointer(target, rect.width/4, rect.height/4, {type: "pointermove"});
synthesizeMouse(target, rect.width/2, rect.height/2, {type: "mousedown"});
synthesizeMouse(target, rect.width/3, rect.height/3, {type: "mousemove"});
synthesizeMouse(target, rect.width/4, rect.height/4, {type: "mousemove"});
finishTest();
}
function finishTest() {

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

@ -69,10 +69,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=977003
listener.addEventListener("gotpointercapture", ListenerGotHandler);
listener.addEventListener("lostpointercapture", ListenerLostHandler);
var rect = target.getBoundingClientRect();
synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointerdown"});
synthesizePointer(target, rect.width/3, rect.height/3, {type: "pointermove"});
synthesizePointer(target, rect.width/4, rect.height/4, {type: "pointermove"});
synthesizePointer(target, rect.width/4, rect.height/4, {type: "pointerup"});
synthesizeMouse(target, rect.width/2, rect.height/2, {type: "mousedown"});
synthesizeMouse(target, rect.width/3, rect.height/3, {type: "mousemove"});
synthesizeMouse(target, rect.width/4, rect.height/4, {type: "mousemove"});
synthesizeMouse(target, rect.width/4, rect.height/4, {type: "mouseup"});
finishTest();
}
function finishTest() {

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

@ -84,9 +84,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1098139
listener.addEventListener("pointerup", ListenerHandler);
listener.addEventListener("pointerout", ListenerHandler);
var rect = target.getBoundingClientRect();
synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointerdown", isPrimary: true, inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH});
synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointermove", isPrimary: true, inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH});
synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointerup", isPrimary: true, inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH});
synthesizeMouse(target, rect.width/2, rect.height/2, {type: "mousedown", isPrimary: true, inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH});
synthesizeMouse(target, rect.width/2, rect.height/2, {type: "mousemove", isPrimary: true, inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH});
synthesizeMouse(target, rect.width/2, rect.height/2, {type: "mouseup", isPrimary: true, inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH});
finishTest();
}
function finishTest() {

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

@ -74,9 +74,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1073563
listener.addEventListener("pointerout", ListenerHandler);
listener.addEventListener("lostpointercapture", ListenerHandler);
var rect = target.getBoundingClientRect();
synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointerdown"});
synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointermove"});
synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointerup"});
synthesizeMouse(target, rect.width/2, rect.height/2, {type: "mousedown"});
synthesizeMouse(target, rect.width/2, rect.height/2, {type: "mousemove"});
synthesizeMouse(target, rect.width/2, rect.height/2, {type: "mouseup"});
finishTest();
}
function finishTest() {

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

@ -100,11 +100,14 @@ skip-if = toolkit == 'android' # Bug 1355821
skip-if = toolkit == 'android' # Bug 1355822
[test_bug968148.html]
skip-if = toolkit == 'android' # Bug 1355829
support-files = bug968148_inner.html
support-files =
bug968148_inner.html
bug968148_inner2.html
[test_bug970964.html]
skip-if = toolkit == 'android' # Bug 1355829
support-files = bug970964_inner.html
[test_bug977003.html]
skip-if = toolkit == 'android' # We don't support pointer event on android
support-files =
bug977003_inner_1.html
bug977003_inner_2.html
@ -115,18 +118,23 @@ support-files =
[test_bug990340.html]
[test_bug993936.html]
[test_bug1078327.html]
skip-if = toolkit == 'android' # We don't support pointer event on android
support-files = bug1078327_inner.html
[test_bug1080360.html]
skip-if = toolkit == 'android' # We don't support pointer event on android
support-files = bug1080360_inner.html
[test_bug1080361.html]
skip-if = toolkit == 'android' # We don't support pointer event on android
support-files = bug1080361_inner.html
[test_bug1093686.html]
support-files = bug1093686_inner.html
[test_bug1120705.html]
skip-if = toolkit == 'android' || os == 'mac' || toolkit == 'gtk3' # android does not have clickable scrollbars, mac does not have scrollbar down and up buttons, gtk may or may not have scrollbar buttons depending on theme
[test_bug1153130.html]
skip-if = toolkit == 'android' # We don't support pointer event on android
support-files = bug1153130_inner.html
[test_bug1162990.html]
skip-if = toolkit == 'android' # We don't support pointer event on android
support-files =
bug1162990_inner_1.html
bug1162990_inner_2.html

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

@ -8,25 +8,37 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=968148
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript">
function setRemoteFrame() {
function testWithoutImplicitPointerCapture() {
var iframe = document.getElementById("testFrame");
iframe.src = "bug968148_inner.html";
}
function messageListener(event) {
eval(event.data);
}
window.addEventListener("message", messageListener);
function testWithImplicitPointerCapture() {
var iframe = document.getElementById("testFrame");
iframe.src = "bug968148_inner2.html";
}
function runTest() {
SimpleTest.waitForExplicitFinish();
window.addEventListener("message", (event) => {
if (event.data == "finishTest") {
SimpleTest.finish();
} else if (event.data == "run next") {
SpecialPowers.pushPrefEnv({
"set": [
["dom.w3c_pointer_events.enabled", true],
["dom.w3c_pointer_events.implicit_capture", true]
]
}, testWithImplicitPointerCapture);
}
});
SpecialPowers.pushPrefEnv({
"set": [
["dom.w3c_pointer_events.enabled", true]
["dom.w3c_pointer_events.enabled", true],
["dom.w3c_pointer_events.implicit_capture", false]
]
}, setRemoteFrame);
}, testWithoutImplicitPointerCapture);
}
</script>
</head>

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

@ -9972,6 +9972,38 @@ nsDisplayFilter::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuild
wrFilters.AppendElement(filterOp);
break;
}
case NS_STYLE_FILTER_DROP_SHADOW: {
float appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
nsCSSShadowArray* shadows = filter.GetDropShadow();
if (!shadows || shadows->Length() != 1) {
NS_NOTREACHED("Exactly one drop shadow should have been parsed.");
return false;
}
nsCSSShadowItem* shadow = shadows->ShadowAt(0);
nscolor color = shadow->mColor;
if (!shadow->mHasColor) {
color = mFrame->StyleColor()->mColor;
}
mozilla::wr::WrFilterOp filterOp = {
wr::ToWrFilterOpType(filter.GetType()),
NSAppUnitsToFloatPixels(shadow->mRadius, appUnitsPerDevPixel),
{
NSAppUnitsToFloatPixels(shadow->mXOffset, appUnitsPerDevPixel),
NSAppUnitsToFloatPixels(shadow->mYOffset, appUnitsPerDevPixel),
},
{
NS_GET_R(color) / 255.0f,
NS_GET_G(color) / 255.0f,
NS_GET_B(color) / 255.0f,
NS_GET_A(color) / 255.0f,
}
};
wrFilters.AppendElement(filterOp);
break;
}
default:
return false;
}

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

@ -4,6 +4,6 @@
default-preferences pref(layout.css.filters.enabled,true)
# Some platforms render this complex filter chain a little differently, and that's ok.
fuzzy(5,13000) fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)&&layersGPUAccelerated,35,13057) == long-chain.html long-chain-ref.html # Win10: Bug 1258241
fuzzy(5,13000) fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)&&layersGPUAccelerated,35,13057) fails-if(webrender) == long-chain.html long-chain-ref.html # Win10: Bug 1258241
== moz-element.html moz-element-ref.html
fuzzy-if(webrender,15-15,8262-8262) == same-filter.html same-filter-ref.html

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

@ -26,9 +26,9 @@ fuzzy-if(webrender,6-6,21308-21308) == blur-zoomed-page.html blur-zoomed-page-re
== contrast-percent.html contrast-percent-ref.html
== contrast-reduce.html contrast-reduce-ref.html
== contrast-zero.html contrast-zero-ref.html
== drop-shadow.html drop-shadow-ref.html
== drop-shadow-default-color.html drop-shadow-default-color-ref.html
== drop-shadow-negative-offset.html drop-shadow-negative-offset-ref.html
fuzzy-if(webrender,9-9,2625-2625) == drop-shadow.html drop-shadow-ref.html
fuzzy-if(webrender,9-9,2625-2625) == drop-shadow-default-color.html drop-shadow-default-color-ref.html
fuzzy-if(webrender,9-9,2625-2625) == drop-shadow-negative-offset.html drop-shadow-negative-offset-ref.html
== filter-on-huge-bbox.html pass.svg
== filter-on-outer-svg.html pass.svg
fuzzy-if(webrender,1,10000) fuzzy-if(d2d,1,10000) == grayscale.html grayscale-ref.html

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

@ -37,6 +37,26 @@ PartiallySeekableInputStream::PartiallySeekableInputStream(already_AddRefed<nsII
, mBufferSize(aBufferSize)
, mPos(0)
, mClosed(false)
{
Init();
}
PartiallySeekableInputStream::PartiallySeekableInputStream(already_AddRefed<nsIInputStream> aClonedBaseStream,
PartiallySeekableInputStream* aClonedFrom)
: mInputStream(Move(aClonedBaseStream))
, mWeakCloneableInputStream(nullptr)
, mWeakIPCSerializableInputStream(nullptr)
, mWeakAsyncInputStream(nullptr)
, mCachedBuffer(aClonedFrom->mCachedBuffer)
, mBufferSize(aClonedFrom->mBufferSize)
, mPos(aClonedFrom->mPos)
, mClosed(aClonedFrom->mClosed)
{
Init();
}
void
PartiallySeekableInputStream::Init()
{
MOZ_ASSERT(mInputStream);
@ -65,9 +85,6 @@ PartiallySeekableInputStream::PartiallySeekableInputStream(already_AddRefed<nsII
}
}
PartiallySeekableInputStream::~PartiallySeekableInputStream()
{}
NS_IMETHODIMP
PartiallySeekableInputStream::Close()
{
@ -167,8 +184,7 @@ PartiallySeekableInputStream::GetCloneable(bool* aCloneable)
{
NS_ENSURE_STATE(mWeakCloneableInputStream);
*aCloneable = true;
return NS_OK;
return mWeakCloneableInputStream->GetCloneable(aCloneable);
}
NS_IMETHODIMP
@ -183,7 +199,7 @@ PartiallySeekableInputStream::Clone(nsIInputStream** aResult)
}
nsCOMPtr<nsIInputStream> stream =
new PartiallySeekableInputStream(clonedStream.forget(), mBufferSize);
new PartiallySeekableInputStream(clonedStream.forget(), this);
stream.forget(aResult);
return NS_OK;
@ -252,6 +268,7 @@ PartiallySeekableInputStream::Serialize(mozilla::ipc::InputStreamParams& aParams
FileDescriptorArray& aFileDescriptors)
{
MOZ_ASSERT(mWeakIPCSerializableInputStream);
MOZ_DIAGNOSTIC_ASSERT(mCachedBuffer.IsEmpty());
mozilla::ipc::InputStreamHelper::SerializeInputStream(mInputStream, aParams,
aFileDescriptors);
}

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

@ -38,7 +38,13 @@ public:
uint64_t aBufferSize = 4096);
private:
~PartiallySeekableInputStream();
PartiallySeekableInputStream(already_AddRefed<nsIInputStream> aClonedBaseStream,
PartiallySeekableInputStream* aClonedFrom);
~PartiallySeekableInputStream() = default;
void
Init();
nsCOMPtr<nsIInputStream> mInputStream;

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

@ -10,7 +10,6 @@
* sendWheelAndPaintNoFlush
* synthesizeMouse
* synthesizeMouseAtCenter
* synthesizePointer
* synthesizeWheel
* synthesizeWheelAtPoint
* synthesizeKey
@ -363,12 +362,6 @@ function synthesizeTouch(aTarget, aOffsetX, aOffsetY, aEvent, aWindow)
synthesizeTouchAtPoint(rect.left + aOffsetX, rect.top + aOffsetY,
aEvent, aWindow);
}
function synthesizePointer(aTarget, aOffsetX, aOffsetY, aEvent, aWindow)
{
var rect = aTarget.getBoundingClientRect();
return synthesizePointerAtPoint(rect.left + aOffsetX, rect.top + aOffsetY,
aEvent, aWindow);
}
/*
* Synthesize a mouse event at a particular point in aWindow.
@ -454,35 +447,6 @@ function synthesizeTouchAtPoint(left, top, aEvent, aWindow = window)
}
}
function synthesizePointerAtPoint(left, top, aEvent, aWindow = window)
{
var utils = _getDOMWindowUtils(aWindow);
var defaultPrevented = false;
if (utils) {
var button = computeButton(aEvent);
var clickCount = aEvent.clickCount || 1;
var modifiers = _parseModifiers(aEvent, aWindow);
var pressure = ("pressure" in aEvent) ? aEvent.pressure : 0;
var inputSource = ("inputSource" in aEvent) ? aEvent.inputSource : 0;
var synthesized = ("isSynthesized" in aEvent) ? aEvent.isSynthesized : true;
var isPrimary = ("isPrimary" in aEvent) ? aEvent.isPrimary : false;
if (("type" in aEvent) && aEvent.type) {
defaultPrevented = utils.sendPointerEventToWindow(aEvent.type, left, top, button,
clickCount, modifiers, false,
pressure, inputSource,
synthesized, 0, 0, 0, 0, isPrimary);
}
else {
utils.sendPointerEventToWindow("pointerdown", left, top, button, clickCount, modifiers, false, pressure, inputSource);
utils.sendPointerEventToWindow("pointerup", left, top, button, clickCount, modifiers, false, pressure, inputSource);
}
}
return defaultPrevented;
}
// Call synthesizeMouse with coordinates at the center of aTarget.
function synthesizeMouseAtCenter(aTarget, aEvent, aWindow)
{

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

@ -0,0 +1,3 @@
[border-image-slice-percentage.html]
type: reftest
disabled: if (os == "linux") and debug: https://bugzilla.mozilla.org/show_bug.cgi?id=1383061

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

@ -623,12 +623,12 @@ const kTests = [
todoMismatch: [],
},
{ description: "PointerEvent (pointerdown)",
targetID: "pointer-target", eventType: "pointerdown",
targetID: "pointer-target", eventType: "mousedown",
dispatchEvent: function () {
var elem = document.getElementById(this.targetID);
var rect = elem.getBoundingClientRect();
synthesizePointer(elem, rect.width/2, rect.height/2,
{ type: this.eventType, button: 1, clickCount: 1, inputSource: 2, pressure: 0.25, isPrimary: true });
synthesizeMouse(elem, rect.width/2, rect.height/2,
{ type: this.eventType, button: 1, clickCount: 1, inputSource: 2, pressure: 0.25, isPrimary: true });
},
canRun: function () {
return true;
@ -636,12 +636,12 @@ const kTests = [
todoMismatch: [],
},
{ description: "PointerEvent (pointerup)",
targetID: "pointer-target", eventType: "pointerup",
targetID: "pointer-target", eventType: "mouseup",
dispatchEvent: function () {
var elem = document.getElementById(this.targetID);
var rect = elem.getBoundingClientRect();
synthesizePointer(elem, rect.width/2, rect.height/2,
{ type: this.eventType, button: -1, ctrlKey: true, shiftKey: true, altKey: true, isSynthesized: false });
synthesizeMouse(elem, rect.width/2, rect.height/2,
{ type: this.eventType, button: -1, ctrlKey: true, shiftKey: true, altKey: true, isSynthesized: false });
},
canRun: function () {
return true;

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

@ -41,6 +41,7 @@ class nsMultiplexInputStream final
, public nsIIPCSerializableInputStream
, public nsICloneableInputStream
, public nsIAsyncInputStream
, public nsIInputStreamCallback
{
public:
nsMultiplexInputStream();
@ -52,6 +53,7 @@ public:
NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
NS_DECL_NSICLONEABLEINPUTSTREAM
NS_DECL_NSIASYNCINPUTSTREAM
NS_DECL_NSIINPUTSTREAMCALLBACK
void AsyncWaitCompleted();
@ -77,6 +79,9 @@ private:
{
}
nsresult
AsyncWaitInternal();
// This method updates mSeekableStreams, mIPCSerializableStreams,
// mCloneableStreams and mAsyncInputStreams values.
void UpdateQIMap(StreamData& aStream, int32_t aCount);
@ -107,6 +112,9 @@ private:
bool mStartedReadingCurrent;
nsresult mStatus;
nsCOMPtr<nsIInputStreamCallback> mAsyncWaitCallback;
uint32_t mAsyncWaitFlags;
uint32_t mAsyncWaitRequestedCount;
nsCOMPtr<nsIEventTarget> mAsyncWaitEventTarget;
uint32_t mSeekableStreams;
uint32_t mIPCSerializableStreams;
@ -130,6 +138,8 @@ NS_INTERFACE_MAP_BEGIN(nsMultiplexInputStream)
IsCloneable())
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAsyncInputStream,
IsAsyncInputStream())
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIInputStreamCallback,
IsAsyncInputStream())
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIMultiplexInputStream)
NS_IMPL_QUERY_CLASSINFO(nsMultiplexInputStream)
NS_INTERFACE_MAP_END
@ -182,6 +192,8 @@ nsMultiplexInputStream::nsMultiplexInputStream()
, mCurrentStream(0)
, mStartedReadingCurrent(false)
, mStatus(NS_OK)
, mAsyncWaitFlags(0)
, mAsyncWaitRequestedCount(0)
, mSeekableStreams(0)
, mIPCSerializableStreams(0)
, mCloneableStreams(0)
@ -281,14 +293,25 @@ nsMultiplexInputStream::GetStream(uint32_t aIndex, nsIInputStream** aResult)
NS_IMETHODIMP
nsMultiplexInputStream::Close()
{
MutexAutoLock lock(mLock);
mStatus = NS_BASE_STREAM_CLOSED;
nsTArray<nsCOMPtr<nsIInputStream>> streams;
// Let's take a copy of the streams becuase, calling close() it could trigger
// a nsIInputStreamCallback immediately and we don't want to create a deadlock
// with mutex.
{
MutexAutoLock lock(mLock);
uint32_t len = mStreams.Length();
for (uint32_t i = 0; i < len; ++i) {
streams.AppendElement(mStreams[i].mStream);
}
mStatus = NS_BASE_STREAM_CLOSED;
}
nsresult rv = NS_OK;
uint32_t len = mStreams.Length();
uint32_t len = streams.Length();
for (uint32_t i = 0; i < len; ++i) {
nsresult rv2 = mStreams[i].mStream->Close();
nsresult rv2 = streams[i]->Close();
// We still want to close all streams, but we should return an error
if (NS_FAILED(rv2)) {
rv = rv2;
@ -317,6 +340,11 @@ nsMultiplexInputStream::Available(uint64_t* aResult)
rv = AvailableMaybeSeek(mStreams[i], &streamAvail);
if (rv == NS_BASE_STREAM_CLOSED) {
// If a stream is closed, we continue with the next one.
// If this is the current stream we move to the following stream.
if (mCurrentStream == i) {
++mCurrentStream;
}
// If this is the last stream, we want to return this error code.
continue;
}
@ -792,11 +820,15 @@ class AsyncWaitRunnable final : public CancelableRunnable
RefPtr<nsMultiplexInputStream> mStream;
public:
explicit AsyncWaitRunnable(nsMultiplexInputStream* aStream)
: CancelableRunnable("AsyncWaitRunnable")
, mStream(aStream)
static void
Create(nsMultiplexInputStream* aStream, nsIEventTarget* aEventTarget)
{
MOZ_ASSERT(aStream);
RefPtr<AsyncWaitRunnable> runnable = new AsyncWaitRunnable(aStream);
if (aEventTarget) {
aEventTarget->Dispatch(runnable.forget(), NS_DISPATCH_NORMAL);
} else {
runnable->Run();
}
}
NS_IMETHOD
@ -805,141 +837,136 @@ public:
mStream->AsyncWaitCompleted();
return NS_OK;
}
};
// This helper class processes an array of nsIAsyncInputStreams, calling
// AsyncWait() for each one of them. When all of them have answered, this helper
// dispatches a AsyncWaitRunnable object. If there is an error calling
// AsyncWait(), AsyncWaitRunnable is not dispatched.
class AsyncStreamHelper final : public nsIInputStreamCallback
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
static nsresult
Process(nsMultiplexInputStream* aStream,
nsTArray<nsCOMPtr<nsIAsyncInputStream>>& aAsyncStreams,
uint32_t aFlags, uint32_t aRequestedCount,
nsIEventTarget* aEventTarget)
{
MOZ_ASSERT(aStream);
MOZ_ASSERT(!aAsyncStreams.IsEmpty());
MOZ_ASSERT(aEventTarget);
RefPtr<AsyncStreamHelper> helper =
new AsyncStreamHelper(aStream, aAsyncStreams, aEventTarget);
return helper->Run(aFlags, aRequestedCount);
}
private:
AsyncStreamHelper(nsMultiplexInputStream* aStream,
nsTArray<nsCOMPtr<nsIAsyncInputStream>>& aAsyncStreams,
nsIEventTarget* aEventTarget)
: mMutex("AsyncStreamHelper::mMutex")
explicit AsyncWaitRunnable(nsMultiplexInputStream* aStream)
: CancelableRunnable("AsyncWaitRunnable")
, mStream(aStream)
, mEventTarget(aEventTarget)
, mValid(true)
{
mPendingStreams.SwapElements(aAsyncStreams);
MOZ_ASSERT(aStream);
}
~AsyncStreamHelper() = default;
nsresult
Run(uint32_t aFlags, uint32_t aRequestedCount)
{
MutexAutoLock lock(mMutex);
for (uint32_t i = 0; i < mPendingStreams.Length(); ++i) {
nsresult rv =
mPendingStreams[i]->AsyncWait(this, aFlags, aRequestedCount,
mEventTarget);
if (NS_WARN_IF(NS_FAILED(rv))) {
mValid = false;
return rv;
}
}
return NS_OK;
}
NS_IMETHOD
OnInputStreamReady(nsIAsyncInputStream* aStream) override
{
MOZ_ASSERT(aStream, "This cannot be one of ours.");
MutexAutoLock lock(mMutex);
// We failed during the Run().
if (!mValid) {
return NS_OK;
}
MOZ_ASSERT(mPendingStreams.Contains(aStream));
mPendingStreams.RemoveElement(aStream);
// The last asyncStream answered. We can inform nsMultiplexInputStream.
if (mPendingStreams.IsEmpty()) {
RefPtr<AsyncWaitRunnable> runnable = new AsyncWaitRunnable(mStream);
return mEventTarget->Dispatch(runnable.forget(), NS_DISPATCH_NORMAL);
}
return NS_OK;
}
Mutex mMutex;
RefPtr<nsMultiplexInputStream> mStream;
nsTArray<nsCOMPtr<nsIAsyncInputStream>> mPendingStreams;
nsCOMPtr<nsIEventTarget> mEventTarget;
bool mValid;
};
NS_IMPL_ISUPPORTS(AsyncStreamHelper, nsIInputStreamCallback)
NS_IMETHODIMP
nsMultiplexInputStream::AsyncWait(nsIInputStreamCallback* aCallback,
uint32_t aFlags,
uint32_t aRequestedCount,
nsIEventTarget* aEventTarget)
{
// When AsyncWait() is called, it's better to call AsyncWait() to any sub
// stream if they are valid nsIAsyncInputStream instances. In this way, when
// they all call OnInputStreamReady(), we can proceed with the Read().
{
MutexAutoLock lock(mLock);
MutexAutoLock lock(mLock);
// We must execute the callback also when the stream is closed.
if (NS_FAILED(mStatus) && mStatus != NS_BASE_STREAM_CLOSED) {
return mStatus;
}
if (NS_FAILED(mStatus)) {
return mStatus;
}
if (mAsyncWaitCallback && aCallback) {
return NS_ERROR_FAILURE;
}
if (mAsyncWaitCallback && aCallback) {
return NS_ERROR_FAILURE;
}
mAsyncWaitCallback = aCallback;
mAsyncWaitFlags = aFlags;
mAsyncWaitRequestedCount = aRequestedCount;
mAsyncWaitEventTarget = aEventTarget;
mAsyncWaitCallback = aCallback;
if (!mAsyncWaitCallback) {
return NS_OK;
}
nsTArray<nsCOMPtr<nsIAsyncInputStream>> asyncStreams;
for (uint32_t i = mCurrentStream; i < mStreams.Length(); ++i) {
if (mStreams[i].mAsyncStream) {
asyncStreams.AppendElement(mStreams[i].mAsyncStream);
if (!mAsyncWaitCallback) {
return NS_OK;
}
}
if (!aEventTarget) {
aEventTarget = SystemGroup::EventTargetFor(TaskCategory::Other);
return AsyncWaitInternal();
}
nsresult
nsMultiplexInputStream::AsyncWaitInternal()
{
nsCOMPtr<nsIAsyncInputStream> stream;
uint32_t asyncWaitFlags = 0;
uint32_t asyncWaitRequestedCount = 0;
nsCOMPtr<nsIEventTarget> asyncWaitEventTarget;
{
MutexAutoLock lock(mLock);
// Let's take the first async stream if we are not already closed, and if
// it has data to read or if it async.
if (mStatus != NS_BASE_STREAM_CLOSED) {
for (; mCurrentStream < mStreams.Length(); ++mCurrentStream) {
stream = mStreams[mCurrentStream].mAsyncStream;
if (stream) {
break;
}
uint64_t avail = 0;
nsresult rv = AvailableMaybeSeek(mStreams[mCurrentStream], &avail);
if (rv == NS_BASE_STREAM_CLOSED || (NS_SUCCEEDED(rv) && avail == 0)) {
// Nothing to read here. Let's move on.
continue;
}
if (NS_FAILED(rv)) {
return rv;
}
break;
}
}
asyncWaitFlags = mAsyncWaitFlags;
asyncWaitRequestedCount = mAsyncWaitRequestedCount;
asyncWaitEventTarget = mAsyncWaitEventTarget;
}
if (asyncStreams.IsEmpty()) {
RefPtr<AsyncWaitRunnable> runnable = new AsyncWaitRunnable(this);
return aEventTarget->Dispatch(runnable.forget(), NS_DISPATCH_NORMAL);
MOZ_ASSERT_IF(stream, NS_SUCCEEDED(mStatus));
// If we are here it's because we are already closed, or if the current stream
// is not async. In both case we have to execute the callback.
if (!stream) {
AsyncWaitRunnable::Create(this, asyncWaitEventTarget);
return NS_OK;
}
return AsyncStreamHelper::Process(this, asyncStreams, aFlags, aRequestedCount,
aEventTarget);
return stream->AsyncWait(this, asyncWaitFlags, asyncWaitRequestedCount,
asyncWaitEventTarget);
}
NS_IMETHODIMP
nsMultiplexInputStream::OnInputStreamReady(nsIAsyncInputStream* aStream)
{
nsCOMPtr<nsIInputStreamCallback> callback;
// When OnInputStreamReady is called, we could be in 2 scenarios:
// a. there is something to read;
// b. the stream is closed.
// But if the stream is closed and it was not the last one, we must proceed
// with the following stream in order to have something to read by the callee.
{
MutexAutoLock lock(mLock);
// The callback has been nullified in the meantime.
if (!mAsyncWaitCallback) {
return NS_OK;
}
if (NS_SUCCEEDED(mStatus)) {
uint64_t avail = 0;
nsresult rv = aStream->Available(&avail);
if (rv == NS_BASE_STREAM_CLOSED || avail == 0) {
// This stream is closed or empty, let's move to the following one.
++mCurrentStream;
MutexAutoUnlock unlock(mLock);
return AsyncWaitInternal();
}
}
mAsyncWaitCallback.swap(callback);
mAsyncWaitEventTarget = nullptr;
}
return callback->OnInputStreamReady(this);
}
void
@ -956,6 +983,7 @@ nsMultiplexInputStream::AsyncWaitCompleted()
}
mAsyncWaitCallback.swap(callback);
mAsyncWaitEventTarget = nullptr;
}
callback->OnInputStreamReady(this);

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

@ -142,10 +142,6 @@ TEST(TestMultiplexInputStream, AsyncWait_withoutEventTarget) {
new testing::InputStreamCallback();
ASSERT_EQ(NS_OK, ais->AsyncWait(cb, 0, 0, nullptr));
ASSERT_FALSE(cb->Called());
// Eventually it is called.
MOZ_ALWAYS_TRUE(mozilla::SpinEventLoopUntil([&]() { return cb->Called(); }));
ASSERT_TRUE(cb->Called());
}
@ -184,10 +180,6 @@ TEST(TestMultiplexInputStream, AsyncWait_withoutEventTarget_closureOnly) {
ASSERT_FALSE(cb->Called());
ais->CloseWithStatus(NS_ERROR_FAILURE);
ASSERT_FALSE(cb->Called());
// Eventually it is called.
MOZ_ALWAYS_TRUE(mozilla::SpinEventLoopUntil([&]() { return cb->Called(); }));
ASSERT_TRUE(cb->Called());
}