зеркало из https://github.com/mozilla/gecko-dev.git
Merge inbound to mozilla-central r=merge a=merge
This commit is contained in:
Коммит
be90f4e875
|
@ -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"> </div><br><div class="test" id="test1d2"> </div>
|
||||
<div class="test" id="test2d1"> </div><br><div class="test" id="test2d2"> </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());
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче