Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/tests_primary.yml
Original file line number Diff line number Diff line change
Expand Up @@ -139,14 +139,15 @@ jobs:
- uses: ./.github/actions/run-test
with:
node-version: ${{matrix.node-version}}
command: npm run ttest -- --shard ${{ matrix.shardIndex }}/${{ matrix.shardTotal }} --shard-weights=${{ matrix.shardWeights }}
command: npm run ttest -- --shard ${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
bot-name: "${{ matrix.os }}-node${{ matrix.node-version }}"
shard-index: ${{ matrix.shardIndex }}
flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }}
flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }}
flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }}
env:
PWTEST_CHANNEL: firefox-beta
PWTEST_SHARD_WEIGHTS: ${{ matrix.shardWeights }}

test_vscode_extension:
name: VSCode Extension
Expand Down
2 changes: 1 addition & 1 deletion browser_patches/firefox/UPSTREAM_CONFIG.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
REMOTE_URL="https://github.com/mozilla-firefox/firefox"
BASE_BRANCH="release"
BASE_REVISION="e0df3d598dba47de812bb5144cbc187557377095"
BASE_REVISION="d0f4d17d5aefe7ca5aa97afbcafcdc641cbd9f93"
50 changes: 0 additions & 50 deletions browser_patches/firefox/juggler/NetworkObserver.js
Original file line number Diff line number Diff line change
Expand Up @@ -810,56 +810,6 @@ function overrideRequestHeaders(httpChannel, headers) {
appendExtraHTTPHeaders(httpChannel, headers);
}

// Forbidden request headers according to https://developer.mozilla.org/en-US/docs/Glossary/Forbidden_request_header
// These headers cannot be set or modified programmatically.
const FORBIDDEN_HEADER_NAMES = new Set([
'accept-charset',
'accept-encoding',
'access-control-request-headers',
'access-control-request-method',
'connection',
'content-length',
'cookie',
'date',
'dnt',
'expect',
'host',
'keep-alive',
'origin',
'referer',
'set-cookie',
'te',
'trailer',
'transfer-encoding',
'upgrade',
'via',
]);

// Forbidden method names for X-HTTP-Method-* headers
const FORBIDDEN_METHODS = new Set(['CONNECT', 'TRACE', 'TRACK']);

function isForbiddenHeader(name, value) {
const lowerName = name.toLowerCase();

if (FORBIDDEN_HEADER_NAMES.has(lowerName))
return true;

if (lowerName.startsWith('proxy-'))
return true;

if (lowerName.startsWith('sec-'))
return true;

if (lowerName === 'x-http-method' ||
lowerName === 'x-http-method-override' ||
lowerName === 'x-method-override') {
if (value && FORBIDDEN_METHODS.has(value.toUpperCase()))
return true;
}

return false;
}

const redirectStatus = [301, 302, 303, 307, 308];

function filterHeadersForRedirect(headers, requestMethod, status) {
Expand Down
34 changes: 21 additions & 13 deletions browser_patches/firefox/juggler/TargetRegistry.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ const Cr = Components.results;
const helper = new Helper();

const IDENTITY_NAME = 'JUGGLER ';
const HUNDRED_YEARS = 60 * 60 * 24 * 365 * 100;

const ALL_PERMISSIONS = [
'geo',
Expand Down Expand Up @@ -364,10 +363,6 @@ export class TargetRegistry {
target = this._browserToTarget.get(browser);
}
browser.focus();
if (browserContext.crossProcessCookie.settings.timezoneId) {
if (await target.hasFailedToOverrideTimezone())
throw new Error('Failed to override timezone');
}
didCreateFirstPage = true;
return target.id();
}
Expand Down Expand Up @@ -508,6 +503,7 @@ export class PageTarget {
updateOverridesForBrowsingContext(browsingContext = undefined) {
this.updateTouchOverride(browsingContext);
this.updateUserAgent(browsingContext);
this.updateTimezoneOverride(browsingContext);
this.updatePlatform(browsingContext);
this.updateDPPXOverride(browsingContext);
this.updateZoom(browsingContext);
Expand Down Expand Up @@ -545,6 +541,10 @@ export class PageTarget {
(browsingContext || this._linkedBrowser.browsingContext).customUserAgent = this._browserContext.defaultUserAgent;
}

updateTimezoneOverride(browsingContext = undefined) {
(browsingContext || this._linkedBrowser.browsingContext).timezoneOverride = this._browserContext.timezoneOverride;
}

updatePlatform(browsingContext = undefined) {
(browsingContext || this._linkedBrowser.browsingContext).customPlatform = this._browserContext.defaultPlatform;
}
Expand Down Expand Up @@ -749,10 +749,6 @@ export class PageTarget {
await this._channel.connect('').send('applyContextSetting', { name, value }).catch(e => void e);
}

async hasFailedToOverrideTimezone() {
return await this._channel.connect('').send('hasFailedToOverrideTimezone').catch(e => true);
}

async _startVideoRecording({width, height, dir}) {
// On Mac the window may not yet be visible when TargetCreated and its
// NSWindow.windowNumber may be -1, so we wait until the window is known
Expand All @@ -770,7 +766,7 @@ export class PageTarget {
const registry = this._registry;
const screencastClient = {
QueryInterface: ChromeUtils.generateQI([Ci.nsIScreencastServiceClient]),
screencastFrame(data, deviceWidth, deviceHeight) {
screencastFrame(data, deviceWidth, deviceHeight, timestamp) {
},
screencastStopped() {
registry.emit(TargetRegistry.Events.ScreencastStopped, sessionId);
Expand Down Expand Up @@ -810,9 +806,9 @@ export class PageTarget {
const self = this;
const screencastClient = {
QueryInterface: ChromeUtils.generateQI([Ci.nsIScreencastServiceClient]),
screencastFrame(data, deviceWidth, deviceHeight) {
screencastFrame(data, deviceWidth, deviceHeight, timestamp) {
if (self._screencastRecordingInfo)
self.emit(PageTarget.Events.ScreencastFrame, { data, deviceWidth, deviceHeight });
self.emit(PageTarget.Events.ScreencastFrame, { data, deviceWidth, deviceHeight, timestamp });
},
screencastStopped() {
},
Expand Down Expand Up @@ -939,6 +935,7 @@ class BrowserContext {
this.defaultViewportSize = undefined;
this.deviceScaleFactor = undefined;
this.defaultUserAgent = null;
this.timezoneOverride = undefined;
this.defaultPlatform = null;
this.touchOverride = false;
this.forceOffline = false;
Expand Down Expand Up @@ -1035,6 +1032,14 @@ class BrowserContext {
page.updateUserAgent();
}

setTimezoneOverride(timezoneId) {
if (!Intl.supportedValuesOf("timeZone").includes(timezoneId))
throw new Error(`Invalid timezone ID: ${timezoneId}`);
this.timezoneOverride = timezoneId;
for (const page of this.pages)
page.updateTimezoneOverride();
}

setDefaultPlatform(platform) {
this.defaultPlatform = platform;
for (const page of this.pages)
Expand Down Expand Up @@ -1153,7 +1158,10 @@ class BrowserContext {
secure,
cookie.httpOnly || false,
cookie.expires === undefined || cookie.expires === -1 /* isSession */,
cookie.expires === undefined ? Date.now() + HUNDRED_YEARS : cookie.expires * 1000,
// The XPCOM interface requires the expiry field even for session cookies.
// The expiry value must be passed in milliseconds and is capped at 400
// days.
cookie.expires === undefined ? Number.MAX_SAFE_INTEGER : Services.cookies.maybeCapExpiry(cookie.expires * 1000),
{ userContextId: this.userContextId || undefined } /* originAttributes */,
protocolToSameSite[cookie.sameSite],
Ci.nsICookie.SCHEME_UNSET
Expand Down
8 changes: 1 addition & 7 deletions browser_patches/firefox/juggler/content/FrameTree.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,6 @@ export class FrameTree {
helper.addObserver((browsingContext, topic, why) => {
this._onBrowsingContextDetached(browsingContext);
}, 'browsing-context-discarded'),
helper.addObserver((subject, topic, eventInfo) => {
const [type, jugglerEventId] = eventInfo.split(' ');
this.emit(FrameTree.Events.InputEvent, { type, jugglerEventId: +(jugglerEventId ?? '0') });
}, 'juggler-mouse-event-hit-renderer'),
helper.addProgressListener(webProgress, this, flags),
];

Expand Down Expand Up @@ -261,9 +257,7 @@ export class FrameTree {
mozSystemGroup: true,
capture: true,
};
const emitInputEvent = (event) => this.emit(FrameTree.Events.InputEvent, { type: event.type, jugglerEventId: 0 });
// Drag events are dispatched from content process, so these we don't see in the
// `juggler-mouse-event-hit-renderer` instrumentation.
const emitInputEvent = (event) => this.emit(FrameTree.Events.InputEvent, { type: event.type });
this._dragEventListeners = [
helper.addEventListener(chromeEventHandler, 'dragstart', emitInputEvent, options),
helper.addEventListener(chromeEventHandler, 'dragover', emitInputEvent, options),
Expand Down
153 changes: 14 additions & 139 deletions browser_patches/firefox/juggler/content/PageAgent.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,6 @@ export class PageAgent {
dispatchTouchEvent: this._dispatchTouchEvent.bind(this),
dispatchTapEvent: this._dispatchTapEvent.bind(this),
getContentQuads: this._getContentQuads.bind(this),
getFullAXTree: this._getFullAXTree.bind(this),
insertText: this._insertText.bind(this),
scrollIntoViewIfNeeded: this._scrollIntoViewIfNeeded.bind(this),
setFileInputFiles: this._setFileInputFiles.bind(this),
Expand Down Expand Up @@ -539,21 +538,23 @@ export class PageAgent {

if ((type === 'drop' && dropEffect !== 'none') || type === 'dragover') {
const win = this._frameTree.mainFrame().domWindow();
win.windowUtils.jugglerSendMouseEvent(
win.synthesizeMouseEvent(
type,
x,
y,
0, /*button*/
0, /*clickCount*/
modifiers,
false /*aIgnoreRootScrollFrame*/,
0.0 /*pressure*/,
0 /*inputSource*/,
true /*isDOMEventSynthesized*/,
false /*isWidgetEventSynthesized*/,
0 /*buttons*/,
win.windowUtils.DEFAULT_MOUSE_POINTER_ID /* pointerIdentifier */,
false /*disablePointerEvent*/,
{
button: 0,
buttons: 0,
clickCount: 0,
modifiers,
pressure: 0.0,
inputSource: MouseEvent.MOZ_SOURCE_MOUSE,
},
{
ignoreRootScrollFrame: false,
isDOMEventSynthesized: true,
isWidgetEventSynthesized: false,
}
);
return;
}
Expand Down Expand Up @@ -581,131 +582,5 @@ export class PageAgent {
const badptr = ctypes.cast(zero, ctypes.PointerType(ctypes.int32_t));
badptr.contents;
}

async _getFullAXTree({objectId}) {
let unsafeObject = null;
if (objectId) {
unsafeObject = this._frameTree.mainFrame().unsafeObject(objectId);
if (!unsafeObject)
throw new Error(`No object found for id "${objectId}"`);
}

const service = Cc["@mozilla.org/accessibilityService;1"]
.getService(Ci.nsIAccessibilityService);
const document = this._frameTree.mainFrame().domWindow().document;
const docAcc = service.getAccessibleFor(document);

while (docAcc.document.isUpdatePendingForJugglerAccessibility)
await new Promise(x => this._frameTree.mainFrame().domWindow().requestAnimationFrame(x));

async function waitForQuiet() {
let state = {};
docAcc.getState(state, {});
if ((state.value & Ci.nsIAccessibleStates.STATE_BUSY) == 0)
return;
let resolve, reject;
const promise = new Promise((x, y) => {resolve = x, reject = y});
let eventObserver = {
observe(subject, topic) {
if (topic !== "accessible-event") {
return;
}

// If event type does not match expected type, skip the event.
let event = subject.QueryInterface(Ci.nsIAccessibleEvent);
if (event.eventType !== Ci.nsIAccessibleEvent.EVENT_STATE_CHANGE) {
return;
}

// If event's accessible does not match expected accessible,
// skip the event.
if (event.accessible !== docAcc) {
return;
}

Services.obs.removeObserver(this, "accessible-event");
resolve();
},
};
Services.obs.addObserver(eventObserver, "accessible-event");
return promise;
}
function buildNode(accElement) {
let a = {}, b = {};
accElement.getState(a, b);
const tree = {
role: service.getStringRole(accElement.role),
name: accElement.name || '',
};
if (unsafeObject && unsafeObject === accElement.DOMNode)
tree.foundObject = true;
for (const userStringProperty of [
'value',
'description'
]) {
tree[userStringProperty] = accElement[userStringProperty] || undefined;
}

const states = {};
for (const name of service.getStringStates(a.value, b.value))
states[name] = true;
for (const name of ['selected',
'focused',
'pressed',
'focusable',
'required',
'invalid',
'modal',
'editable',
'busy',
'checked',
'multiselectable']) {
if (states[name])
tree[name] = true;
}

if (states['multi line'])
tree['multiline'] = true;
if (states['editable'] && states['readonly'])
tree['readonly'] = true;
if (states['checked'])
tree['checked'] = true;
if (states['mixed'])
tree['checked'] = 'mixed';
if (states['expanded'])
tree['expanded'] = true;
else if (states['collapsed'])
tree['expanded'] = false;
if (!states['enabled'])
tree['disabled'] = true;

const attributes = {};
if (accElement.attributes) {
for (const { key, value } of accElement.attributes.enumerate()) {
attributes[key] = value;
}
}
for (const numericalProperty of ['level']) {
if (numericalProperty in attributes)
tree[numericalProperty] = parseFloat(attributes[numericalProperty]);
}
for (const stringProperty of ['tag', 'roledescription', 'valuetext', 'orientation', 'autocomplete', 'keyshortcuts', 'haspopup']) {
if (stringProperty in attributes)
tree[stringProperty] = attributes[stringProperty];
}
const children = [];

for (let child = accElement.firstChild; child; child = child.nextSibling) {
children.push(buildNode(child));
}
if (children.length)
tree.children = children;
return tree;
}
await waitForQuiet();
return {
tree: buildNode(docAcc)
};
}
}

2 changes: 1 addition & 1 deletion browser_patches/firefox/juggler/content/Runtime.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ class Runtime {
emitEvent(this.events.onRuntimeError, {
executionContext,
message: message.errorMessage,
stack: message.stack.toString(),
stack: message.stack ? message.stack.toString() : '',
});
}
},
Expand Down
Loading
Loading