diff --git a/.eslintrc.js b/.eslintrc.js
index ddb2ec8561bb95..7bc5a0868f09b1 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -71,6 +71,7 @@ module.exports = {
"valid-typeof": 2,
"no-implicit-globals": [2],
"no-unused-expressions": [2, { "allowShortCircuit": true, "allowTernary": true, "allowTaggedTemplates": true}],
+ "no-proto": 2,
// es2015 features
"require-yield": 2,
diff --git a/.gitattributes b/.gitattributes
index 653dde78b55b52..c2515b4ffe5174 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,5 +1,4 @@
# text files must be lf for golden file tests to work
* text=auto eol=lf
-
# make project show as TS on GitHub
*.js linguist-detectable=false
diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md
index 6b212dcc6931be..370d836a4e0a75 100644
--- a/.github/ISSUE_TEMPLATE/bug.md
+++ b/.github/ISSUE_TEMPLATE/bug.md
@@ -7,43 +7,66 @@ assignees: ''
---
-**Context:**
-- Playwright Version: [what Playwright version do you use?]
-- Operating System: [e.g. Windows, Linux or Mac]
-- Node.js version: [e.g. 12.22, 14.6]
-- Browser: [e.g. All, Chromium, Firefox, WebKit]
-- Extra: [any specific details about your environment]
-
-
-
-
-**Code Snippet**
-
-Help us help you! Put down a short code snippet that illustrates your bug and
-that we can run and debug locally. For example:
-
-```javascript
-const {chromium, webkit, firefox} = require('playwright');
-
-(async () => {
- const browser = await chromium.launch();
- const context = await browser.newContext();
- const page = await context.newPage();
-
- // Please include a snippet of HTML that shows an example of the content
- // you are testing.
- await page.setContent(`
-
- …
-
- `);
- // Alternatively, if you are testing a public application, include the URL:
- // await page.goto('https://example.com/')
-
- await page.locator(…);
-})();
+
+
+
+
+
+
+### System info
+- Playwright Version: [v1.XX]
+- Operating System: [All, Windows 11, Ubuntu 20, macOS 13.2, etc.]
+- Browser: [All, Chromium, Firefox, WebKit]
+- Other info:
+
+### Source code
+
+- [ ] I provided exact source code that allows reproducing the issue locally.
+
+
+
+
+
+
+**Link to the GitHub repository with the repro**
+
+[https://github.com/your_profile/playwright_issue_title]
+
+or
+
+**Config file**
+
+```js
+// playwright.config.ts
+import { defineConfig, devices } from '@playwright/test';
+
+export default defineConfig({
+ projects: [
+ {
+ name: 'chromium',
+ use: { ...devices['Desktop Chrome'], },
+ },
+});
+```
+
+**Test file (self-contained)**
+
+```js
+it('should check the box using setChecked', async ({ page }) => {
+ await page.setContent(``);
+ await page.getByRole('checkbox').check();
+ await expect(page.getByRole('checkbox')).toBeChecked();
+});
```
-**Describe the bug**
+**Steps**
+- [Run the test]
+- [...]
+
+**Expected**
+
+[Describe expected behavior]
+
+**Actual**
-Add any other details about the problem here.
+[Describe actual behavior]
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
index ee5b58e0a72458..de718587756aa6 100644
--- a/.github/ISSUE_TEMPLATE/config.yml
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -1,4 +1,4 @@
contact_links:
- - name: Join our GitHub Discussions community
- url: https://github.com/microsoft/playwright/discussions
- about: Ask questions and discuss with other community members
+ - name: Join our Discord Server
+ url: https://aka.ms/playwright/discord
+ about: Ask questions and discuss with other community members
\ No newline at end of file
diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md
deleted file mode 100644
index 55abfc3ec011b6..00000000000000
--- a/.github/ISSUE_TEMPLATE/question.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-name: I have a question
-about: Feel free to ask us your questions!
-title: "[Question]"
-labels: ''
-assignees: ''
-
----
-
-
diff --git a/.github/ISSUE_TEMPLATE/vscode-extension.md b/.github/ISSUE_TEMPLATE/vscode-extension.md
new file mode 100644
index 00000000000000..e623fa9de1ca81
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/vscode-extension.md
@@ -0,0 +1,26 @@
+---
+name: VSCode extension bug
+about: Something doesn't work like it should inside the Visual Studio Code extension or you have a feature request? Tell us!
+title: "[BUG]"
+labels: ''
+assignees: ''
+
+---
+
+**Context:**
+- Playwright Version: [what Playwright version do you use?]
+- Operating System: [e.g. Windows, Linux or Mac]
+- Node.js version: [e.g. 12.22, 14.6]
+- Visual Studio Code version: [e.g. 1.65]
+- Playwright for VSCode extension version: [e.g. 1.2.3]
+- Browser: [e.g. All, Chromium, Firefox, WebKit]
+- Extra: [any specific details about your environment]
+
+**Code Snippet**
+
+Help us help you! Put down a short code snippet that illustrates your bug and
+that we can run and debug locally. For example:
+
+**Describe the bug**
+
+Add any other details about the problem here.
diff --git a/.github/actions/download-artifact/action.yml b/.github/actions/download-artifact/action.yml
new file mode 100644
index 00000000000000..874b202c060ae8
--- /dev/null
+++ b/.github/actions/download-artifact/action.yml
@@ -0,0 +1,40 @@
+name: 'Download blob report'
+description: 'Download blob report from GitHub artifacts'
+inputs:
+ name:
+ description: 'Name of the artifact to download'
+ required: true
+ type: string
+ default: 'blob-report'
+ path:
+ description: 'Directory with downloaded artifacts'
+ required: true
+ type: string
+ default: 'blob-report'
+runs:
+ using: "composite"
+ steps:
+ - name: Download blob report
+ uses: actions/github-script@v6
+ with:
+ script: |
+ console.log(`downloading artifacts for workflow_run: ${context.payload.workflow_run.id}`);
+ console.log(`workflow_run: ${JSON.stringify(context.payload.workflow_run, null, 2)}`);
+ const { data } = await github.rest.actions.listWorkflowRunArtifacts({
+ ...context.repo,
+ run_id: context.payload.workflow_run.id
+ });
+ console.log('total = ', data.total_count);
+ const name = '${{ inputs.name }}';
+ const report = data.artifacts.filter(a => a.name === name)[0];
+ const result = await github.rest.actions.downloadArtifact({
+ ...context.repo,
+ artifact_id: report.id,
+ archive_format: 'zip'
+ });
+ console.log('download result', result);
+ const fs = require('fs');
+ fs.writeFileSync(`${name}.zip`, Buffer.from(result.data));
+ - name: Unzip blob report
+ shell: bash
+ run: unzip ${{ inputs.name }}.zip -d ${{ inputs.path }}
diff --git a/.github/actions/download-blob-report-from-azure/action.yml b/.github/actions/download-blob-report-from-azure/action.yml
new file mode 100644
index 00000000000000..8026de64ea2e50
--- /dev/null
+++ b/.github/actions/download-blob-report-from-azure/action.yml
@@ -0,0 +1,29 @@
+name: 'Download blob report from Azure'
+description: 'Download blob report from Azure blob storage'
+inputs:
+ blob_prefix:
+ description: 'Name of the Azure blob storage directory containing blob report'
+ required: true
+ type: string
+ output_dir:
+ description: 'Output directory where downloaded blobs will be stored'
+ required: true
+ type: string
+ default: 'blob-report'
+ connection_string:
+ description: 'Azure connection string'
+ required: true
+ type: string
+runs:
+ using: "composite"
+ steps:
+ - name: Download Blob Reports from Azure Blob Storage
+ shell: bash
+ run: |
+ OUTPUT_DIR='${{ inputs.output_dir }}'
+ mkdir -p $OUTPUT_DIR
+ LIST=$(az storage blob list -c '$web' --prefix ${{ inputs.blob_prefix }} --connection-string "${{ inputs.connection_string }}")
+ for name in $(echo $LIST | jq --raw-output '.[].name | select(test("report-.*\\.zip$"))');
+ do
+ az storage blob download -c '$web' --name $name -f $OUTPUT_DIR/$(basename $name) --connection-string "${{ inputs.connection_string }}"
+ done
diff --git a/.github/actions/upload-blob-report/action.yml b/.github/actions/upload-blob-report/action.yml
new file mode 100644
index 00000000000000..1747c5f69c26e6
--- /dev/null
+++ b/.github/actions/upload-blob-report/action.yml
@@ -0,0 +1,38 @@
+name: 'Upload blob report'
+description: 'Upload blob to Azure blob storage or to GitHub artifacts (for pull requests)'
+inputs:
+ report_dir:
+ description: 'Directory containing blob report'
+ required: true
+ type: string
+ default: 'test-results/blob-report'
+ connection_string:
+ description: 'Azure connection string'
+ required: true
+ type: string
+runs:
+ using: "composite"
+ steps:
+ - name: Upload blob report to Azure
+ if: always() && github.event_name == 'push'
+ shell: bash
+ run: |
+ REPORT_DIR='run-${{ github.run_id }}-${{ github.run_attempt }}-${{ github.sha }}'
+ az storage blob upload-batch -s "${{ inputs.report_dir }}" -d "\$web/$REPORT_DIR" --connection-string "${{ inputs.connection_string }}"
+ - name: Upload blob report to GitHub
+ if: always() && github.event_name == 'pull_request'
+ uses: actions/upload-artifact@v3
+ with:
+ name: blob-report-${{ github.run_attempt }}
+ path: ${{ inputs.report_dir }}
+ retention-days: 30
+ - name: Write triggering pull request number in a file
+ if: always() && github.event_name == 'pull_request'
+ shell: bash
+ run: echo '${{ github.event.number }}' > pull_request_number.txt;
+ - name: Upload artifact with the pull request number
+ if: always() && github.event_name == 'pull_request'
+ uses: actions/upload-artifact@v3
+ with:
+ name: pull-request
+ path: pull_request_number.txt
diff --git a/.github/workflows/cherry_pick_into_release_branch.yml b/.github/workflows/cherry_pick_into_release_branch.yml
index 30fff595246470..c326509e35b99c 100644
--- a/.github/workflows/cherry_pick_into_release_branch.yml
+++ b/.github/workflows/cherry_pick_into_release_branch.yml
@@ -23,7 +23,7 @@ jobs:
echo "Version is not a two digit semver version"
exit 1
fi
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
with:
ref: release-${{ github.event.inputs.version }}
fetch-depth: 0
@@ -42,27 +42,27 @@ jobs:
console.log(process.argv[1]);
process.exit(0);
}
- console.log(`chery-pick${match[2]}: ${match[1]}`);
+ console.log(`cherry-pick${match[2]}: ${match[1]}`);
' "$COMMIT_MESSAGE")
git commit -m "$COMMIT_MESSAGE"
done
LAST_COMMIT_MESSAGE=$(git show -s --format=%B)
- echo "::set-output name=PR_TITLE::$LAST_COMMIT_MESSAGE"
+ echo "PR_TITLE=$LAST_COMMIT_MESSAGE" >> $GITHUB_OUTPUT
- name: Prepare branch
id: prepare-branch
run: |
BRANCH_NAME="cherry-pick-${{ github.event.inputs.version }}-$(date +%Y-%m-%d-%H-%M-%S)"
- echo "::set-output name=BRANCH_NAME::$BRANCH_NAME"
+ echo "BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_OUTPUT
git checkout -b "$BRANCH_NAME"
git push origin $BRANCH_NAME
- name: Create Pull Request
- uses: actions/github-script@v4
+ uses: actions/github-script@v6
with:
github-token: ${{ secrets.REPOSITORY_DISPATCH_PERSONAL_ACCESS_TOKEN }}
script: |
const readableCommitHashesList = '${{ github.event.inputs.commit_hashes }}'.split(',').map(hash => `- ${hash}`).join('\n');
- const response = await github.pulls.create({
+ const response = await github.rest.pulls.create({
owner: 'microsoft',
repo: 'playwright',
head: 'microsoft:${{ steps.prepare-branch.outputs.BRANCH_NAME }}',
@@ -70,7 +70,7 @@ jobs:
title: '${{ steps.cherry-pick.outputs.PR_TITLE }}',
body: `This PR cherry-picks the following commits:\n\n${readableCommitHashesList}`,
});
- await github.issues.addLabels({
+ await github.rest.issues.addLabels({
owner: 'microsoft',
repo: 'playwright',
issue_number: response.data.number,
diff --git a/.github/workflows/create_test_report.yml b/.github/workflows/create_test_report.yml
new file mode 100644
index 00000000000000..026589613bc672
--- /dev/null
+++ b/.github/workflows/create_test_report.yml
@@ -0,0 +1,127 @@
+name: Publish Test Results
+on:
+ workflow_run:
+ workflows: ["tests 1", "tests 2"]
+ types:
+ - completed
+jobs:
+ merge-reports:
+ permissions:
+ pull-requests: write
+ checks: write
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
+ with:
+ node-version: 16
+
+ - run: npm ci
+ env:
+ DEBUG: pw:install
+ PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
+ - run: npm run build
+
+ - name: Download blob report artifact
+ if: ${{ always() && github.event.workflow_run.event == 'pull_request' }}
+ uses: ./.github/actions/download-artifact
+ with:
+ name: 'blob-report-${{ github.event.workflow_run.run_attempt }}'
+ path: 'blob-report'
+ - name: Download blob report from Azure
+ if: ${{ always() && github.event.workflow_run.event == 'push' }}
+ uses: ./.github/actions/download-blob-report-from-azure
+ with:
+ blob_prefix: 'run-${{ github.event.workflow_run.id }}-${{ github.event.workflow_run.run_attempt }}-${{ github.sha }}'
+ output_dir: 'blob-report'
+ connection_string: '${{ secrets.AZURE_CONNECTION_STRING_FOR_BLOB_REPORT }}'
+
+ - name: Merge reports
+ run: |
+ npx playwright merge-reports --reporter markdown,html --attachments missing blob-report
+
+ - name: Upload HTML report to Azure
+ run: |
+ REPORT_DIR='run-${{ github.event.workflow_run.id }}-${{ github.event.workflow_run.run_attempt }}-${{ github.sha }}'
+ az storage blob upload-batch -s playwright-report -d "\$web/$REPORT_DIR" --connection-string "${{ secrets.AZURE_CONNECTION_STRING_FOR_BLOB_REPORT }}"
+ echo "Report url: https://mspwblobreport.z1.web.core.windows.net/$REPORT_DIR/index.html"
+
+ - name: Upload blob report to Azure
+ if: ${{ github.event.workflow_run.event == 'pull_request' }}
+ run: |
+ REPORT_DIR='run-${{ github.event.workflow_run.id }}-${{ github.event.workflow_run.run_attempt }}-${{ github.sha }}'
+ az storage blob upload-batch -s blob-report -d "\$web/$REPORT_DIR" --connection-string "${{ secrets.AZURE_CONNECTION_STRING_FOR_BLOB_REPORT }}"
+
+ - name: Read pull request number
+ if: ${{ always() && github.event.workflow_run.event == 'pull_request' }}
+ uses: ./.github/actions/download-artifact
+ with:
+ name: 'pull-request'
+ path: './'
+
+ - name: Comment on PR
+ uses: actions/github-script@v6
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ script: |
+ const fs = require('fs');
+ let prNumber;
+ if (context.payload.workflow_run.event === 'pull_request') {
+ const prs = context.payload.workflow_run.pull_requests;
+ if (prs.length) {
+ prNumber = prs[0].number;
+ } else {
+ prNumber = parseInt(fs.readFileSync('pull_request_number.txt').toString());
+ console.log('Read pull request number from file: ' + prNumber);
+ }
+ } else if (context.payload.workflow_run.event === 'push') {
+ const { data } = await github.rest.repos.listPullRequestsAssociatedWithCommit({
+ ...context.repo,
+ commit_sha: context.sha,
+ });
+ if (!data.length) {
+ core.info(`No pull request found for commit ${context.sha}. Not publishing anything.`);
+ return;
+ }
+ prNumber = data[0].number;
+ } else {
+ core.error('Unsupported workflow trigger event: ' + context.payload.workflow_run.event);
+ return;
+ }
+ if (!prNumber) {
+ core.error('No pull request found for commit ' + context.sha + ' and workflow triggered by: ' + context.payload.workflow_run.event);
+ return;
+ }
+ const reportDir = 'run-${{ github.event.workflow_run.id }}-${{ github.event.workflow_run.run_attempt }}-${{ github.sha }}';
+ const reportUrl = `https://mspwblobreport.z1.web.core.windows.net/${reportDir}/index.html#?q=s%3Afailed%20s%3Aflaky`;
+ core.notice('Report url: ' + reportUrl);
+ const mergeWorkflowUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
+ const reportMd = await fs.promises.readFile('report.md', 'utf8');
+ const { data: response } = await github.rest.issues.createComment({
+ ...context.repo,
+ issue_number: prNumber,
+ body: [
+ `### [Test results](${reportUrl}) for "${{ github.event.workflow_run.name }}"`,
+ reportMd,
+ '',
+ `Merge [workflow run](${mergeWorkflowUrl}).`
+ ].join('\n'),
+ });
+ core.info('Posted comment: ' + response.html_url);
+
+ const check = await github.rest.checks.create({
+ ...context.repo,
+ name: 'Merge report (${{ github.event.workflow_run.name }})',
+ head_sha: '${{ github.event.workflow_run.head_sha }}',
+ status: 'completed',
+ conclusion: 'success',
+ details_url: reportUrl,
+ output: {
+ title: 'Test results for "${{ github.event.workflow_run.name }}"',
+ summary: [
+ reportMd,
+ '---',
+ `Full [HTML report](${reportUrl}). Merge [workflow run](${mergeWorkflowUrl}).`
+ ].join('\n'),
+ }
+ });
diff --git a/.github/workflows/infra.yml b/.github/workflows/infra.yml
index 29d3c57386f5c1..7f42f62676acad 100644
--- a/.github/workflows/infra.yml
+++ b/.github/workflows/infra.yml
@@ -10,15 +10,18 @@ on:
- main
- release-*
+env:
+ ELECTRON_SKIP_BINARY_DOWNLOAD: 1
+
jobs:
doc-and-lint:
name: "docs & lint"
runs-on: ubuntu-20.04
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
- node-version: 14
+ node-version: 16
- run: npm i -g npm@8
- run: npm ci
- run: npm run build
diff --git a/.github/workflows/pr_check_client_side_changes.yml b/.github/workflows/pr_check_client_side_changes.yml
index fc8e5cbd1614fd..57c96a60ad6e57 100644
--- a/.github/workflows/pr_check_client_side_changes.yml
+++ b/.github/workflows/pr_check_client_side_changes.yml
@@ -13,11 +13,11 @@ jobs:
if: github.repository == 'microsoft/playwright'
steps:
- name: Create GitHub issue
- uses: actions/github-script@v4
+ uses: actions/github-script@v6
with:
github-token: ${{ secrets.REPOSITORY_DISPATCH_PERSONAL_ACCESS_TOKEN }}
script: |
- const { data } = await github.git.getCommit({
+ const { data } = await github.rest.git.getCommit({
owner: context.repo.owner,
repo: context.repo.repo,
commit_sha: context.sha,
@@ -26,7 +26,7 @@ jobs:
const title = '[Ports]: Backport client side changes';
for (const repo of ['playwright-python', 'playwright-java', 'playwright-dotnet']) {
- const { data: issuesData } = await github.search.issuesAndPullRequests({
+ const { data: issuesData } = await github.rest.search.issuesAndPullRequests({
q: `is:issue is:open repo:microsoft/${repo} in:title "${title}"`
})
let issueNumber = null;
@@ -35,7 +35,7 @@ jobs:
issueNumber = issuesData.items[0].number
issueBody = issuesData.items[0].body
} else {
- const { data: issueCreateData } = await github.issues.create({
+ const { data: issueCreateData } = await github.rest.issues.create({
owner: context.repo.owner,
repo: repo,
title,
@@ -46,7 +46,7 @@ jobs:
}
const newBody = issueBody.trimEnd() + `
- [ ] https://github.com/${context.repo.owner}/${context.repo.repo}/commit/${context.sha} (${commitHeader})`;
- const data = await github.issues.update({
+ const data = await github.rest.issues.update({
owner: context.repo.owner,
repo: repo,
issue_number: issueNumber,
diff --git a/.github/workflows/publish_canary.yml b/.github/workflows/publish_canary.yml
index b390b9ea98a9f5..9fa09f1ef4acd1 100644
--- a/.github/workflows/publish_canary.yml
+++ b/.github/workflows/publish_canary.yml
@@ -8,16 +8,19 @@ on:
branches:
- release-*
+env:
+ ELECTRON_SKIP_BINARY_DOWNLOAD: 1
+
jobs:
publish-canary:
name: "publish canary NPM & Publish canary Docker"
runs-on: ubuntu-20.04
if: github.repository == 'microsoft/playwright'
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
- node-version: 14
+ node-version: 16
registry-url: 'https://registry.npmjs.org'
- run: npm i -g npm@8
- run: npm ci
@@ -58,7 +61,7 @@ jobs:
username: playwright
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Set up Docker QEMU for arm64 docker builds
- uses: docker/setup-qemu-action@v1
+ uses: docker/setup-qemu-action@v2
with:
platforms: arm64
- name: publish docker canary
@@ -69,10 +72,10 @@ jobs:
runs-on: ubuntu-20.04
if: github.repository == 'microsoft/playwright'
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
- node-version: 14
+ node-version: 16
- run: npm i -g npm@8
- name: Deploy Canary
run: bash utils/build/deploy-trace-viewer.sh --canary
diff --git a/.github/workflows/publish_release_docker.yml b/.github/workflows/publish_release_docker.yml
index 6d13fbcd80a504..fe41b5f0bce680 100644
--- a/.github/workflows/publish_release_docker.yml
+++ b/.github/workflows/publish_release_docker.yml
@@ -11,16 +11,19 @@ on:
release:
types: [published]
+env:
+ ELECTRON_SKIP_BINARY_DOWNLOAD: 1
+
jobs:
publish-docker-release:
name: "publish to DockerHub"
runs-on: ubuntu-20.04
if: github.repository == 'microsoft/playwright'
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
- node-version: 14
+ node-version: 16
registry-url: 'https://registry.npmjs.org'
- uses: azure/docker-login@v1
with:
@@ -28,7 +31,7 @@ jobs:
username: playwright
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Set up Docker QEMU for arm64 docker builds
- uses: docker/setup-qemu-action@v1
+ uses: docker/setup-qemu-action@v2
with:
platforms: arm64
- run: npm i -g npm@8
diff --git a/.github/workflows/publish_release_driver.yml b/.github/workflows/publish_release_driver.yml
index bbc7fd60c5acba..f97ce2e884f363 100644
--- a/.github/workflows/publish_release_driver.yml
+++ b/.github/workflows/publish_release_driver.yml
@@ -4,16 +4,19 @@ on:
release:
types: [published]
+env:
+ ELECTRON_SKIP_BINARY_DOWNLOAD: 1
+
jobs:
publish-driver-release:
name: "publish playwright driver to CDN"
runs-on: ubuntu-20.04
if: github.repository == 'microsoft/playwright'
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
- node-version: 14
+ node-version: 16
registry-url: 'https://registry.npmjs.org'
- run: npm i -g npm@8
- run: npm ci
diff --git a/.github/workflows/publish_release_npm.yml b/.github/workflows/publish_release_npm.yml
index 0f71a5d8376297..474157edf1e12c 100644
--- a/.github/workflows/publish_release_npm.yml
+++ b/.github/workflows/publish_release_npm.yml
@@ -4,16 +4,19 @@ on:
release:
types: [published]
+env:
+ ELECTRON_SKIP_BINARY_DOWNLOAD: 1
+
jobs:
publish-npm-release:
name: "publish to NPM"
runs-on: ubuntu-20.04
if: github.repository == 'microsoft/playwright'
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
- node-version: 14
+ node-version: 16
registry-url: 'https://registry.npmjs.org'
- run: npm i -g npm@8
- run: npm ci
diff --git a/.github/workflows/publish_release_traceviewer.yml b/.github/workflows/publish_release_traceviewer.yml
index bb69f98a29da03..5d2de305fcff57 100644
--- a/.github/workflows/publish_release_traceviewer.yml
+++ b/.github/workflows/publish_release_traceviewer.yml
@@ -10,10 +10,10 @@ jobs:
runs-on: ubuntu-20.04
if: github.repository == 'microsoft/playwright'
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
- node-version: 14
+ node-version: 16
- run: npm i -g npm@8
- name: Deploy Stable
run: bash utils/build/deploy-trace-viewer.sh --stable
diff --git a/.github/workflows/roll_browser_into_playwright.yml b/.github/workflows/roll_browser_into_playwright.yml
index 2085178edf8884..53f3244b15a0cb 100644
--- a/.github/workflows/roll_browser_into_playwright.yml
+++ b/.github/workflows/roll_browser_into_playwright.yml
@@ -4,14 +4,17 @@ on:
repository_dispatch:
types: [roll_into_pw]
+env:
+ ELECTRON_SKIP_BINARY_DOWNLOAD: 1
+
jobs:
roll:
runs-on: ubuntu-20.04
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
- node-version: 14
+ node-version: 16
- run: npm i -g npm@8
- run: npm ci
- run: npm run build
@@ -25,7 +28,7 @@ jobs:
id: prepare-branch
run: |
BRANCH_NAME="roll-into-pw-${{ github.event.client_payload.browser }}/${{ github.event.client_payload.revision }}"
- echo "::set-output name=BRANCH_NAME::$BRANCH_NAME"
+ echo "BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_OUTPUT
git config --global user.name github-actions
git config --global user.email 41898282+github-actions[bot]@users.noreply.github.com
git checkout -b "$BRANCH_NAME"
@@ -33,18 +36,18 @@ jobs:
git commit -m "feat(${{ github.event.client_payload.browser }}): roll to r${{ github.event.client_payload.revision }}"
git push origin $BRANCH_NAME
- name: Create Pull Request
- uses: actions/github-script@v4
+ uses: actions/github-script@v6
with:
github-token: ${{ secrets.REPOSITORY_DISPATCH_PERSONAL_ACCESS_TOKEN }}
script: |
- const response = await github.pulls.create({
+ const response = await github.rest.pulls.create({
owner: 'microsoft',
repo: 'playwright',
head: 'microsoft:${{ steps.prepare-branch.outputs.BRANCH_NAME }}',
base: 'main',
title: 'feat(${{ github.event.client_payload.browser }}): roll to r${{ github.event.client_payload.revision }}',
});
- await github.issues.addLabels({
+ await github.rest.issues.addLabels({
owner: 'microsoft',
repo: 'playwright',
issue_number: response.data.number,
diff --git a/.github/workflows/roll_chromium_build.yml b/.github/workflows/roll_chromium_build.yml
deleted file mode 100644
index 9a766e1197b319..00000000000000
--- a/.github/workflows/roll_chromium_build.yml
+++ /dev/null
@@ -1,43 +0,0 @@
-name: "PR: bump chromium/BUILD_NUMBER"
-on:
- workflow_dispatch:
- schedule:
- # At 10:00am UTC (3AM PST) every day to build every new Chromium beta
- - cron: "0 10 * * *"
-jobs:
- trigger-chromium-build:
- name: Trigger Build
- runs-on: ubuntu-20.04
- steps:
- - uses: actions/checkout@v2
- - run: ./browser_patches/chromium/roll_to_current_beta.sh
- - name: Prepare branch
- id: prepare-branch
- run: |
- if [[ "$(git status --porcelain)" == "" ]]; then
- echo "there are no changes";
- exit 0;
- fi
- echo "::set-output name=HAS_CHANGES::1"
- CURRENT_DATE=$(date +%Y-%b-%d)
- BRANCH_NAME="roll-chromium/${CURRENT_DATE}"
- echo "::set-output name=BRANCH_NAME::$BRANCH_NAME"
- echo "::set-output name=CURRENT_DATE::$CURRENT_DATE"
- git config --global user.name github-actions
- git config --global user.email 41898282+github-actions[bot]@users.noreply.github.com
- git checkout -b "$BRANCH_NAME"
- git add .
- git commit -m "browser(chromium): roll to $CURRENT_DATE"
- git push origin $BRANCH_NAME
- - name: Create Pull Request
- if: ${{ steps.prepare-branch.outputs.HAS_CHANGES == '1' }}
- uses: actions/github-script@v4
- with:
- script: |
- await github.pulls.create({
- owner: 'microsoft',
- repo: 'playwright',
- head: 'microsoft:${{ steps.prepare-branch.outputs.BRANCH_NAME }}',
- base: 'main',
- title: 'browser(chromium): roll to ${{ steps.prepare-branch.outputs.CURRENT_DATE }}',
- });
diff --git a/.github/workflows/roll_chromium_tip_of_treebuild.yml b/.github/workflows/roll_chromium_tip_of_treebuild.yml
deleted file mode 100644
index a55d64144415c3..00000000000000
--- a/.github/workflows/roll_chromium_tip_of_treebuild.yml
+++ /dev/null
@@ -1,43 +0,0 @@
-name: "PR: bump chromium-tip-of-tree/BUILD_NUMBER"
-on:
- workflow_dispatch:
- schedule:
- # At 10:00am UTC (3AM PST) every tuesday and thursday to build new Chromium Tip-of-tree
- - cron: "0 10 * * 2,4"
-jobs:
- trigger-chromium-build:
- name: Trigger Build
- runs-on: ubuntu-20.04
- steps:
- - uses: actions/checkout@v2
- - run: ./browser_patches/chromium-tip-of-tree/roll_to_current_tip_of_tree.sh
- - name: Prepare branch
- id: prepare-branch
- run: |
- if [[ "$(git status --porcelain)" == "" ]]; then
- echo "there are no changes";
- exit 0;
- fi
- echo "::set-output name=HAS_CHANGES::1"
- CURRENT_DATE=$(date +%Y-%b-%d)
- BRANCH_NAME="roll-tip-of-tree-chromium/${CURRENT_DATE}"
- echo "::set-output name=BRANCH_NAME::$BRANCH_NAME"
- echo "::set-output name=CURRENT_DATE::$CURRENT_DATE"
- git config --global user.name github-actions
- git config --global user.email 41898282+github-actions[bot]@users.noreply.github.com
- git checkout -b "$BRANCH_NAME"
- git add .
- git commit -m "browser(chromium-tip-of-tree): roll to $CURRENT_DATE"
- git push origin $BRANCH_NAME
- - name: Create Pull Request
- if: ${{ steps.prepare-branch.outputs.HAS_CHANGES == '1' }}
- uses: actions/github-script@v4
- with:
- script: |
- await github.pulls.create({
- owner: 'microsoft',
- repo: 'playwright',
- head: 'microsoft:${{ steps.prepare-branch.outputs.BRANCH_NAME }}',
- base: 'main',
- title: 'browser(chromium-tip-of-tree): roll to ${{ steps.prepare-branch.outputs.CURRENT_DATE }}',
- });
diff --git a/.github/workflows/roll_driver_nodejs.yml b/.github/workflows/roll_driver_nodejs.yml
index 5a2ade5977edbd..bef065ca716efd 100644
--- a/.github/workflows/roll_driver_nodejs.yml
+++ b/.github/workflows/roll_driver_nodejs.yml
@@ -8,11 +8,12 @@ jobs:
trigger-nodejs-roll:
name: Trigger Roll
runs-on: ubuntu-22.04
+ if: github.repository == 'microsoft/playwright'
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
- node-version: 16
+ node-version: 18
- run: node utils/build/update-playwright-driver-version.mjs
- name: Prepare branch
id: prepare-branch
@@ -21,9 +22,9 @@ jobs:
echo "there are no changes";
exit 0;
fi
- echo "::set-output name=HAS_CHANGES::1"
+ echo "HAS_CHANGES=1" >> $GITHUB_OUTPUT
BRANCH_NAME="roll-driver-nodejs/$(date +%Y-%b-%d)"
- echo "::set-output name=BRANCH_NAME::$BRANCH_NAME"
+ echo "BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_OUTPUT
git config --global user.name github-actions
git config --global user.email 41898282+github-actions[bot]@users.noreply.github.com
git checkout -b "$BRANCH_NAME"
@@ -32,10 +33,11 @@ jobs:
git push origin $BRANCH_NAME
- name: Create Pull Request
if: ${{ steps.prepare-branch.outputs.HAS_CHANGES == '1' }}
- uses: actions/github-script@v4
+ uses: actions/github-script@v6
with:
+ github-token: ${{ secrets.REPOSITORY_DISPATCH_PERSONAL_ACCESS_TOKEN }}
script: |
- await github.pulls.create({
+ await github.rest.pulls.create({
owner: 'microsoft',
repo: 'playwright',
head: 'microsoft:${{ steps.prepare-branch.outputs.BRANCH_NAME }}',
diff --git a/.github/workflows/tests_components.yml b/.github/workflows/tests_components.yml
index 7567b5bebc9964..bd1d4396b36793 100644
--- a/.github/workflows/tests_components.yml
+++ b/.github/workflows/tests_components.yml
@@ -15,6 +15,7 @@ on:
env:
FORCE_COLOR: 1
+ ELECTRON_SKIP_BINARY_DOWNLOAD: 1
jobs:
test_components:
@@ -25,10 +26,9 @@ jobs:
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
- # Component tests require Node.js 16+ (they require ESM via TS)
node-version: 16
- run: npm i -g npm@8
- run: npm ci
diff --git a/.github/workflows/tests_electron.yml b/.github/workflows/tests_electron.yml
index c278439322c20d..f11d9b17a5bf2c 100644
--- a/.github/workflows/tests_electron.yml
+++ b/.github/workflows/tests_electron.yml
@@ -28,10 +28,10 @@ jobs:
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
- node-version: 14
+ node-version: 16
- run: npm i -g npm@8
- run: npm ci
env:
@@ -47,8 +47,3 @@ jobs:
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
if: always()
shell: bash
- - uses: actions/upload-artifact@v1
- if: always() && matrix.os == 'ubuntu-latest'
- with:
- name: electron-linux-test-results
- path: test-results
diff --git a/.github/workflows/tests_primary.yml b/.github/workflows/tests_primary.yml
index 9283e931027d06..5d74c721a32a23 100644
--- a/.github/workflows/tests_primary.yml
+++ b/.github/workflows/tests_primary.yml
@@ -23,6 +23,7 @@ env:
# Force terminal colors. @see https://www.npmjs.com/package/colors
FORCE_COLOR: 1
FLAKINESS_CONNECTION_STRING: ${{ secrets.FLAKINESS_CONNECTION_STRING }}
+ ELECTRON_SKIP_BINARY_DOWNLOAD: 1
jobs:
test_linux:
@@ -32,21 +33,20 @@ jobs:
matrix:
browser: [chromium, firefox, webkit]
os: [ubuntu-22.04]
- node-version: [14]
+ node-version: [16]
include:
- os: ubuntu-22.04
- node-version: 16
+ node-version: 18
browser: chromium
- os: ubuntu-22.04
- node-version: 18
+ node-version: 20
browser: chromium
runs-on: ${{ matrix.os }}
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- - run: npm i -g npm@8
- run: npm ci
env:
DEBUG: pw:install
@@ -54,15 +54,18 @@ jobs:
- run: npm run build
- run: npx playwright install --with-deps ${{ matrix.browser }} chromium
- run: xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- npm run test -- --project=${{ matrix.browser }}
+ env:
+ PWTEST_BLOB_SUFFIX: "-${{ matrix.os }}-node${{ matrix.node-version }}"
- run: node tests/config/checkCoverage.js ${{ matrix.browser }}
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
if: always()
shell: bash
- - uses: actions/upload-artifact@v1
+ - name: Upload blob report
if: always()
+ uses: ./.github/actions/upload-blob-report
with:
- name: ${{ matrix.browser }}-${{ matrix.os }}-test-results
- path: test-results
+ report_dir: test-results/blob-report
+ connection_string: '${{ secrets.AZURE_CONNECTION_STRING_FOR_BLOB_REPORT }}'
test_linux_chromium_tot:
name: ${{ matrix.os }} (chromium tip-of-tree)
@@ -72,11 +75,10 @@ jobs:
os: [ubuntu-20.04]
runs-on: ${{ matrix.os }}
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
- node-version: 14
- - run: npm i -g npm@8
+ node-version: 16
- run: npm ci
env:
DEBUG: pw:install
@@ -86,14 +88,10 @@ jobs:
- run: xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- npm run test -- --project=chromium
env:
PWTEST_CHANNEL: chromium-tip-of-tree
+ PWTEST_BLOB_SUFFIX: "-${{ matrix.os }}-chromium-tip-of-tree"
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
if: always()
shell: bash
- - uses: actions/upload-artifact@v1
- if: always()
- with:
- name: ${{ matrix.browser }}-chromium-tip-of-tree-test-results
- path: test-results
test_test_runner:
name: Test Runner
@@ -101,60 +99,97 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
- node-version: [14]
+ node-version: [16]
+ shard: [1/2, 2/2]
include:
- os: ubuntu-latest
- node-version: 16
+ node-version: 18
+ shard: 1/2
- os: ubuntu-latest
node-version: 18
- - os: windows-latest
- node-version: 16
+ shard: 2/2
+ - os: ubuntu-latest
+ node-version: 20
+ shard: 1/2
+ - os: ubuntu-latest
+ node-version: 20
+ shard: 2/2
runs-on: ${{ matrix.os }}
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
node-version: ${{matrix.node-version}}
- - run: npm i -g npm@8
- run: npm ci
env:
DEBUG: pw:install
- run: npm run build
- run: npx playwright install --with-deps
- - run: npm run ttest
+ - run: npm run ttest -- --shard ${{ matrix.shard }}
+ env:
+ PWTEST_BLOB_SUFFIX: "-${{ matrix.os }}-node${{ matrix.node-version }}"
if: matrix.os != 'ubuntu-latest'
- - run: xvfb-run npm run ttest
+ - run: xvfb-run npm run ttest -- --shard ${{ matrix.shard }}
+ env:
+ PWTEST_BLOB_SUFFIX: "-${{ matrix.os }}-node${{ matrix.node-version }}"
if: matrix.os == 'ubuntu-latest'
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
if: always()
shell: bash
+ - name: Upload blob report
+ if: always()
+ uses: ./.github/actions/upload-blob-report
+ with:
+ report_dir: test-results/blob-report
+ connection_string: '${{ secrets.AZURE_CONNECTION_STRING_FOR_BLOB_REPORT }}'
test_web_components:
name: Web Components
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
- # Component tests require Node.js 16+ (they require ESM via TS)
node-version: 16
- - run: npm i -g npm@8
- run: npm ci
env:
DEBUG: pw:install
- run: npm run build
- run: npx playwright install --with-deps
- run: npm run test-html-reporter
- if: always() && matrix.os != 'ubuntu-latest'
- - run: xvfb-run npm run test-html-reporter
- if: always() && matrix.os == 'ubuntu-latest'
- run: npm run test-web
- if: always() && matrix.os != 'ubuntu-latest'
- - run: xvfb-run npm run test-web
- if: always() && matrix.os == 'ubuntu-latest'
+ if: always()
+
+ test_vscode_extension:
+ name: VSCode Extension
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
+ with:
+ node-version: 16
+ - run: npm ci
+ env:
+ DEBUG: pw:install
+ - run: npm run build
+ - run: npx playwright install chromium
+ - name: Checkout extension
+ run: git clone https://github.com/microsoft/playwright-vscode.git
+ - name: Print extension revision
+ run: git rev-parse HEAD
+ working-directory: ./playwright-vscode
+ - name: Remove @playwright/test from extension dependencies
+ run: node -e "const p = require('./package.json'); delete p.devDependencies['@playwright/test']; fs.writeFileSync('./package.json', JSON.stringify(p, null, 2));"
+ working-directory: ./playwright-vscode
+ - name: Build extension
+ run: npm install && npm run build
+ working-directory: ./playwright-vscode
+ - name: Run extension tests
+ run: npm run test -- --workers=1
+ working-directory: ./playwright-vscode
test-package-installations:
- name: "Installation Test ${{ matrix.os }} (${{ matrix.node_version }})"
+ name: "Installation Test ${{ matrix.os }}"
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
@@ -163,15 +198,12 @@ jobs:
- ubuntu-latest
- macos-latest
- windows-latest
- node_version:
- - "^14.1.0" # pre 14.1, zip extraction was broken (https://github.com/microsoft/playwright/issues/1988)
timeout-minutes: 30
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
- node-version: ${{ matrix.node_version }}
- - run: npm i -g npm@8
+ node-version: 16
- run: npm ci
env:
DEBUG: pw:install
diff --git a/.github/workflows/tests_secondary.yml b/.github/workflows/tests_secondary.yml
index be87590123ec40..02b5fbb466c645 100644
--- a/.github/workflows/tests_secondary.yml
+++ b/.github/workflows/tests_secondary.yml
@@ -18,6 +18,7 @@ env:
# Force terminal colors. @see https://www.npmjs.com/package/colors
FORCE_COLOR: 1
FLAKINESS_CONNECTION_STRING: ${{ secrets.FLAKINESS_CONNECTION_STRING }}
+ ELECTRON_SKIP_BINARY_DOWNLOAD: 1
jobs:
test_linux:
@@ -26,14 +27,13 @@ jobs:
fail-fast: false
matrix:
browser: [chromium, firefox, webkit]
- os: [ubuntu-18.04, ubuntu-20.04]
+ os: [ubuntu-20.04, ubuntu-22.04]
runs-on: ${{ matrix.os }}
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
- node-version: 14
- - run: npm i -g npm@8
+ node-version: 16
- run: npm ci
env:
DEBUG: pw:install
@@ -45,26 +45,20 @@ jobs:
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
if: always()
shell: bash
- - uses: actions/upload-artifact@v1
- if: always()
- with:
- name: ${{ matrix.browser }}-${{ matrix.os }}-test-results
- path: test-results
test_mac:
name: ${{ matrix.os }} (${{ matrix.browser }})
strategy:
fail-fast: false
matrix:
- os: [macos-11, macos-12]
+ os: [macos-12, macos-13]
browser: [chromium, firefox, webkit]
runs-on: ${{ matrix.os }}
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
- node-version: 14
- - run: npm i -g npm@8
+ node-version: 16
- run: npm ci
env:
DEBUG: pw:install
@@ -75,11 +69,6 @@ jobs:
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
if: always()
shell: bash
- - uses: actions/upload-artifact@v1
- if: ${{ always() }}
- with:
- name: ${{ matrix.browser }}-${{ matrix.os }}-test-results
- path: test-results
test_win:
name: "Windows"
@@ -89,11 +78,10 @@ jobs:
browser: [chromium, firefox, webkit]
runs-on: windows-latest
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
- node-version: 14
- - run: npm i -g npm@8
+ node-version: 16
- run: npm ci
env:
DEBUG: pw:install
@@ -105,11 +93,6 @@ jobs:
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
if: always()
shell: bash
- - uses: actions/upload-artifact@v1
- if: ${{ always() }}
- with:
- name: ${{ matrix.browser }}-win-test-results
- path: test-results
test-package-installations-other-node-versions:
name: "Installation Test ${{ matrix.os }} (${{ matrix.node_version }})"
@@ -119,16 +102,15 @@ jobs:
matrix:
include:
- os: ubuntu-latest
- node_version: "^18.0.0"
+ node_version: 18
- os: ubuntu-latest
- node_version: "^16.0.0"
+ node_version: 20
timeout-minutes: 30
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node_version }}
- - run: npm i -g npm@8
- run: npm ci
env:
DEBUG: pw:install
@@ -151,11 +133,10 @@ jobs:
os: [ubuntu-20.04, ubuntu-22.04, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
- node-version: 14
- - run: npm i -g npm@8
+ node-version: 16
- run: npm ci
env:
DEBUG: pw:install
@@ -169,11 +150,6 @@ jobs:
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
if: always()
shell: bash
- - uses: actions/upload-artifact@v1
- if: always() && startsWith(matrix.os, 'ubuntu-')
- with:
- name: headful-${{ matrix.browser }}-linux-test-results
- path: test-results
transport_linux:
name: "Transport"
@@ -183,33 +159,22 @@ jobs:
mode: [driver, service]
runs-on: ubuntu-20.04
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
- node-version: 14
- - run: npm i -g npm@8
+ node-version: 16
- run: npm ci
env:
DEBUG: pw:install
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
- run: npm run build
- run: npx playwright install --with-deps chromium
- - run: xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- npm run test -- --project='Chromium page tests'
- if: matrix.mode == 'service'
- env:
- PWTEST_MODE: ${{ matrix.mode }}
- run: xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- npm run ctest
- if: matrix.mode != 'service'
env:
PWTEST_MODE: ${{ matrix.mode }}
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
if: always()
shell: bash
- - uses: actions/upload-artifact@v1
- if: ${{ always() }}
- with:
- name: mode-${{ matrix.mode }}-linux-test-results
- path: test-results
tracing_linux:
name: Tracing ${{ matrix.browser }} ${{ matrix.channel }}
@@ -224,11 +189,10 @@ jobs:
channel: chromium-tip-of-tree
runs-on: ubuntu-20.04
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
- node-version: 14
- - run: npm i -g npm@8
+ node-version: 16
- run: npm ci
env:
DEBUG: pw:install
@@ -239,19 +203,25 @@ jobs:
env:
PWTEST_TRACE: 1
PWTEST_CHANNEL: ${{ matrix.channel }}
+ PWTEST_BLOB_SUFFIX: ${{ (matrix.channel && format('-{0}', matrix.channel)) || '' }}
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
if: always()
shell: bash
+ - name: Upload blob report
+ if: always()
+ uses: ./.github/actions/upload-blob-report
+ with:
+ report_dir: test-results/blob-report
+ connection_string: '${{ secrets.AZURE_CONNECTION_STRING_FOR_BLOB_REPORT }}'
chrome_stable_linux:
name: "Chrome Stable (Linux)"
runs-on: ubuntu-20.04
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
- node-version: 14
- - run: npm i -g npm@8
+ node-version: 16
- run: npm ci
env:
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
@@ -263,21 +233,15 @@ jobs:
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
if: always()
shell: bash
- - uses: actions/upload-artifact@v1
- if: ${{ always() }}
- with:
- name: chrome-stable-linux-test-results
- path: test-results
chrome_stable_win:
name: "Chrome Stable (Win)"
runs-on: windows-latest
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
- node-version: 14
- - run: npm i -g npm@8
+ node-version: 16
- run: npm ci
env:
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
@@ -290,21 +254,15 @@ jobs:
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
if: always()
shell: bash
- - uses: actions/upload-artifact@v1
- if: ${{ always() }}
- with:
- name: chrome-stable-win-test-results
- path: test-results
chrome_stable_mac:
name: "Chrome Stable (Mac)"
runs-on: macos-latest
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
- node-version: 14
- - run: npm i -g npm@8
+ node-version: 16
- run: npm ci
env:
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
@@ -316,11 +274,6 @@ jobs:
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
if: always()
shell: bash
- - uses: actions/upload-artifact@v1
- if: ${{ always() }}
- with:
- name: chrome-stable-mac-test-results
- path: test-results
chromium_tot:
name: Chromium TOT ${{ matrix.os }}
@@ -328,34 +281,28 @@ jobs:
strategy:
fail-fast: false
matrix:
- os: [ubuntu-18.04, macos-12, windows-latest]
+ os: [ubuntu-20.04, macos-12, windows-latest]
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
- node-version: 14
- - run: npm i -g npm@8
+ node-version: 16
- run: npm ci
env:
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
- run: npm run build
- run: npx playwright install --with-deps chromium-tip-of-tree
- run: xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- npm run ctest
- if: matrix.os == 'ubuntu-18.04'
+ if: matrix.os == 'ubuntu-20.04'
env:
PWTEST_CHANNEL: chromium-tip-of-tree
- run: npm run ctest
- if: matrix.os != 'ubuntu-18.04'
+ if: matrix.os != 'ubuntu-20.04'
env:
PWTEST_CHANNEL: chromium-tip-of-tree
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
if: always()
shell: bash
- - uses: actions/upload-artifact@v1
- if: always()
- with:
- name: chromium-tot-${{ matrix.os }}-test-results
- path: test-results
chromium_tot_headed:
name: Chromium TOT headed ${{ matrix.os }}
@@ -365,11 +312,10 @@ jobs:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
- node-version: 14
- - run: npm i -g npm@8
+ node-version: 16
- run: npm ci
env:
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
@@ -386,21 +332,15 @@ jobs:
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
if: always()
shell: bash
- - uses: actions/upload-artifact@v1
- if: always()
- with:
- name: chromium-tot-headed-${{ matrix.os }}-test-results
- path: test-results
firefox_beta_linux:
name: "Firefox Beta (Linux)"
runs-on: ubuntu-20.04
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
- node-version: 14
- - run: npm i -g npm@8
+ node-version: 16
- run: npm ci
env:
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
@@ -412,21 +352,15 @@ jobs:
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
if: always()
shell: bash
- - uses: actions/upload-artifact@v1
- if: ${{ always() }}
- with:
- name: firefox-beta-linux-test-results
- path: test-results
firefox_beta_win:
name: "Firefox Beta (Win)"
runs-on: windows-latest
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
- node-version: 14
- - run: npm i -g npm@8
+ node-version: 16
- run: npm ci
env:
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
@@ -439,21 +373,15 @@ jobs:
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
if: always()
shell: bash
- - uses: actions/upload-artifact@v1
- if: ${{ always() }}
- with:
- name: firefox-beta-win-test-results
- path: test-results
firefox_beta_mac:
name: "Firefox Beta (Mac)"
runs-on: macos-latest
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
- node-version: 14
- - run: npm i -g npm@8
+ node-version: 16
- run: npm ci
env:
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
@@ -465,21 +393,15 @@ jobs:
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
if: always()
shell: bash
- - uses: actions/upload-artifact@v1
- if: ${{ always() }}
- with:
- name: firefox-beta-mac-test-results
- path: test-results
edge_stable_mac:
name: "Edge Stable (Mac)"
runs-on: macos-latest
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
- node-version: 14
- - run: npm i -g npm@8
+ node-version: 16
- run: npm ci
env:
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
@@ -491,22 +413,15 @@ jobs:
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
if: always()
shell: bash
- - uses: actions/upload-artifact@v1
- if: ${{ always() }}
- with:
- name: msedge-stable-mac-test-results
- path: test-results
-
edge_stable_win:
name: "Edge Stable (Win)"
runs-on: windows-latest
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
- node-version: 14
- - run: npm i -g npm@8
+ node-version: 16
- run: npm ci
env:
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
@@ -519,21 +434,15 @@ jobs:
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
if: always()
shell: bash
- - uses: actions/upload-artifact@v1
- if: ${{ always() }}
- with:
- name: edge-stable-win-test-results
- path: test-results
edge_stable_linux:
name: "Edge Stable (Linux)"
runs-on: ubuntu-20.04
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
- node-version: 14
- - run: npm i -g npm@8
+ node-version: 16
- run: npm ci
env:
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
@@ -545,21 +454,15 @@ jobs:
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
if: always()
shell: bash
- - uses: actions/upload-artifact@v1
- if: ${{ always() }}
- with:
- name: edge-stable-linux-test-results
- path: test-results
edge_beta_mac:
name: "Edge Beta (Mac)"
runs-on: macos-latest
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
- node-version: 14
- - run: npm i -g npm@8
+ node-version: 16
- run: npm ci
env:
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
@@ -571,21 +474,15 @@ jobs:
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
if: always()
shell: bash
- - uses: actions/upload-artifact@v1
- if: ${{ always() }}
- with:
- name: msedge-beta-mac-test-results
- path: test-results
edge_beta_win:
name: "Edge Beta (Win)"
runs-on: windows-latest
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
- node-version: 14
- - run: npm i -g npm@8
+ node-version: 16
- run: npm ci
env:
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
@@ -598,21 +495,15 @@ jobs:
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
if: always()
shell: bash
- - uses: actions/upload-artifact@v1
- if: ${{ always() }}
- with:
- name: edge-beta-win-test-results
- path: test-results
edge_beta_linux:
name: "Edge Beta (Linux)"
runs-on: ubuntu-20.04
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
- node-version: 14
- - run: npm i -g npm@8
+ node-version: 16
- run: npm ci
env:
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
@@ -624,21 +515,15 @@ jobs:
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
if: always()
shell: bash
- - uses: actions/upload-artifact@v1
- if: ${{ always() }}
- with:
- name: edge-beta-linux-test-results
- path: test-results
edge_dev_mac:
name: "Edge Dev (Mac)"
runs-on: macos-latest
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
- node-version: 14
- - run: npm i -g npm@8
+ node-version: 16
- run: npm ci
env:
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
@@ -650,21 +535,15 @@ jobs:
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
if: always()
shell: bash
- - uses: actions/upload-artifact@v1
- if: ${{ always() }}
- with:
- name: msedge-dev-mac-test-results
- path: test-results
edge_dev_win:
name: "Edge Dev (Win)"
runs-on: windows-latest
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
- node-version: 14
- - run: npm i -g npm@8
+ node-version: 16
- run: npm ci
env:
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
@@ -677,21 +556,15 @@ jobs:
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
if: always()
shell: bash
- - uses: actions/upload-artifact@v1
- if: ${{ always() }}
- with:
- name: edge-dev-win-test-results
- path: test-results
edge_dev_linux:
name: "Edge Dev (Linux)"
runs-on: ubuntu-20.04
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
- node-version: 14
- - run: npm i -g npm@8
+ node-version: 16
- run: npm ci
env:
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
@@ -703,21 +576,15 @@ jobs:
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
if: always()
shell: bash
- - uses: actions/upload-artifact@v1
- if: ${{ always() }}
- with:
- name: edge-dev-linux-test-results
- path: test-results
chrome_beta_linux:
name: "Chrome Beta (Linux)"
runs-on: ubuntu-20.04
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
- node-version: 14
- - run: npm i -g npm@8
+ node-version: 16
- run: npm ci
env:
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
@@ -729,21 +596,15 @@ jobs:
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
if: always()
shell: bash
- - uses: actions/upload-artifact@v1
- if: ${{ always() }}
- with:
- name: chrome-beta-linux-test-results
- path: test-results
chrome_beta_win:
name: "Chrome Beta (Win)"
runs-on: windows-latest
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
- node-version: 14
- - run: npm i -g npm@8
+ node-version: 16
- run: npm ci
env:
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
@@ -756,21 +617,15 @@ jobs:
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
if: always()
shell: bash
- - uses: actions/upload-artifact@v1
- if: ${{ always() }}
- with:
- name: chrome-beta-win-test-results
- path: test-results
chrome_beta_mac:
name: "Chrome Beta (Mac)"
runs-on: macos-latest
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
- node-version: 14
- - run: npm i -g npm@8
+ node-version: 16
- run: npm ci
env:
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
@@ -782,22 +637,38 @@ jobs:
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
if: always()
shell: bash
- - uses: actions/upload-artifact@v1
- if: ${{ always() }}
- with:
- name: chrome-beta-mac-test-results
- path: test-results
build-playwright-driver:
name: "build-playwright-driver"
runs-on: ubuntu-20.04
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
- node-version: 14
- - run: npm i -g npm@8
+ node-version: 16
- run: npm ci
- run: npm run build
- run: npx playwright install-deps
- run: utils/build/build-playwright-driver.sh
+
+ test_linux_chromium_headless_new:
+ name: Linux Chromium Headless New
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
+ with:
+ node-version: 16
+ - run: npm ci
+ env:
+ DEBUG: pw:install
+ PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
+ - run: npm run build
+ - run: npx playwright install --with-deps chromium
+ - run: xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- npm run test -- --project=chromium
+ env:
+ PLAYWRIGHT_CHROMIUM_USE_HEADLESS_NEW: 1
+ - run: node tests/config/checkCoverage.js chromium
+ - run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
+ if: always()
+ shell: bash
diff --git a/.github/workflows/tests_stress.yml b/.github/workflows/tests_stress.yml
index 8d1c0b0efa5e31..20cd7dff7c5895 100644
--- a/.github/workflows/tests_stress.yml
+++ b/.github/workflows/tests_stress.yml
@@ -16,6 +16,7 @@ on:
env:
FORCE_COLOR: 1
+ ELECTRON_SKIP_BINARY_DOWNLOAD: 1
jobs:
test_components:
@@ -26,8 +27,8 @@ jobs:
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
- run: npm i -g npm@8
- run: npm ci
- run: npm run build
diff --git a/.github/workflows/tests_video.yml b/.github/workflows/tests_video.yml
index a8fbd0d3e338c3..27f1643ef8ed65 100644
--- a/.github/workflows/tests_video.yml
+++ b/.github/workflows/tests_video.yml
@@ -10,6 +10,7 @@ env:
# Force terminal colors. @see https://www.npmjs.com/package/colors
FORCE_COLOR: 1
FLAKINESS_CONNECTION_STRING: ${{ secrets.FLAKINESS_CONNECTION_STRING }}
+ ELECTRON_SKIP_BINARY_DOWNLOAD: 1
jobs:
video_linux:
@@ -21,10 +22,10 @@ jobs:
os: [ubuntu-20.04, ubuntu-22.04]
runs-on: ${{ matrix.os }}
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
with:
- node-version: 14
+ node-version: 16
- run: npm i -g npm@8
- run: npm ci
env:
@@ -38,8 +39,3 @@ jobs:
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
if: always()
shell: bash
- - uses: actions/upload-artifact@v1
- if: ${{ always() }}
- with:
- name: video-${{ matrix.browser }}-linux-test-results
- path: test-results
diff --git a/.github/workflows/tests_webview2.yml b/.github/workflows/tests_webview2.yml
new file mode 100644
index 00000000000000..da0270c2484470
--- /dev/null
+++ b/.github/workflows/tests_webview2.yml
@@ -0,0 +1,45 @@
+name: "WebView2 Tests"
+
+on:
+ push:
+ branches:
+ - main
+ - release-*
+ pull_request:
+ paths-ignore:
+ - 'browser_patches/**'
+ - 'docs/**'
+ types: [ labeled ]
+ branches:
+ - main
+ - release-*
+
+env:
+ # Force terminal colors. @see https://www.npmjs.com/package/colors
+ FORCE_COLOR: 1
+ FLAKINESS_CONNECTION_STRING: ${{ secrets.FLAKINESS_CONNECTION_STRING }}
+ ELECTRON_SKIP_BINARY_DOWNLOAD: 1
+
+jobs:
+ test_webview2:
+ name: WebView2
+ runs-on: windows-2022
+ steps:
+ - uses: actions/checkout@v3
+ - uses: actions/setup-node@v3
+ with:
+ node-version: 18
+ - uses: actions/setup-dotnet@v2
+ with:
+ dotnet-version: '6.0.x'
+ - run: npm i -g npm@8
+ - run: npm ci
+ env:
+ PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
+ - run: npm run build
+ - run: dotnet build
+ working-directory: tests/webview2/webview2-app/
+ - run: npm run webview2test
+ - run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
+ if: always()
+ shell: bash
diff --git a/.github/workflows/trigger_build_chromium.yml b/.github/workflows/trigger_build_chromium.yml
deleted file mode 100644
index e2b2314624402f..00000000000000
--- a/.github/workflows/trigger_build_chromium.yml
+++ /dev/null
@@ -1,31 +0,0 @@
-name: "Trigger: Chromium Builds"
-
-on:
- workflow_dispatch:
- inputs:
- ref:
- description: 'Playwright SHA / ref to build Chromium'
- required: true
- default: 'main'
- push:
- branches:
- - main
- - release-*
- paths:
- - browser_patches/chromium/BUILD_NUMBER
- - .github/workflows/trigger_build_chromium.yml
-
-jobs:
- trigger:
- name: "trigger"
- runs-on: ubuntu-20.04
- steps:
- - run: |
- curl -X POST \
- -H "Accept: application/vnd.github.v3+json" \
- -H "Authorization: token ${GH_TOKEN}" \
- --data "{\"event_type\": \"build_chromium\", \"client_payload\": {\"ref\": \"${GHREF}\"}}" \
- https://api.github.com/repos/microsoft/playwright-internal/dispatches
- env:
- GH_TOKEN: ${{ secrets.REPOSITORY_DISPATCH_PERSONAL_ACCESS_TOKEN }}
- GHREF: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.ref || github.sha }}
diff --git a/.github/workflows/trigger_build_chromium_tip_of_tree.yml b/.github/workflows/trigger_build_chromium_tip_of_tree.yml
deleted file mode 100644
index bdab67cb4de48d..00000000000000
--- a/.github/workflows/trigger_build_chromium_tip_of_tree.yml
+++ /dev/null
@@ -1,31 +0,0 @@
-name: "Trigger: Chromium Tip Of Tree Builds"
-
-on:
- workflow_dispatch:
- inputs:
- ref:
- description: 'Playwright SHA / ref to build Chromium Tip Of Tree'
- required: true
- default: 'main'
- push:
- branches:
- - main
- - release-*
- paths:
- - browser_patches/chromium-tip-of-tree/BUILD_NUMBER
- - .github/workflows/trigger_build_chromium_tip_of_tree.yml
-
-jobs:
- trigger:
- name: "trigger"
- runs-on: ubuntu-20.04
- steps:
- - run: |
- curl -X POST \
- -H "Accept: application/vnd.github.v3+json" \
- -H "Authorization: token ${GH_TOKEN}" \
- --data "{\"event_type\": \"build_chromium_tip_of_tree\", \"client_payload\": {\"ref\": \"${GHREF}\"}}" \
- https://api.github.com/repos/microsoft/playwright-internal/dispatches
- env:
- GH_TOKEN: ${{ secrets.REPOSITORY_DISPATCH_PERSONAL_ACCESS_TOKEN }}
- GHREF: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.ref || github.sha }}
diff --git a/.github/workflows/trigger_build_chromium_with_symbols.yml b/.github/workflows/trigger_build_chromium_with_symbols.yml
index 8fd161a5a72978..b9dfe00fca07c2 100644
--- a/.github/workflows/trigger_build_chromium_with_symbols.yml
+++ b/.github/workflows/trigger_build_chromium_with_symbols.yml
@@ -1,33 +1,30 @@
name: "Trigger: Chromium with Symbols Builds"
-
on:
workflow_dispatch:
- inputs:
- ref:
- description: 'Playwright SHA / ref to build Chromium With Symbols'
- required: true
- default: 'main'
release:
types: [published]
- push:
- branches:
- - release-*
- paths:
- - browser_patches/chromium/BUILD_NUMBER
- - .github/workflows/trigger_build_chromium_with_symbols.yml
jobs:
trigger:
name: "trigger"
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-22.04
steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-node@v2
+ with:
+ node-version: '16'
+ - name: Get Chromium revision
+ id: chromium-version
+ run: |
+ REVISION=$(node -e "console.log(require('./packages/playwright-core/browsers.json').browsers.find(b => b.name === 'chromium-with-symbols').revision)")
+ echo "REVISION=$REVISION" >> $GITHUB_OUTPUT
- run: |
curl -X POST \
-H "Accept: application/vnd.github.v3+json" \
-H "Authorization: token ${GH_TOKEN}" \
- --data "{\"event_type\": \"build_chromium_with_symbols\", \"client_payload\": {\"ref\": \"${GHREF}\"}}" \
- https://api.github.com/repos/microsoft/playwright-internal/dispatches
+ --data "{\"event_type\": \"build_chromium_with_symbols\", \"client_payload\": {\"revision\": \"${CHROMIUM_REVISION}\"}}" \
+ https://api.github.com/repos/microsoft/playwright-browsers/dispatches
env:
GH_TOKEN: ${{ secrets.REPOSITORY_DISPATCH_PERSONAL_ACCESS_TOKEN }}
- GHREF: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.ref || github.sha }}
+ CHROMIUM_REVISION: ${{ steps.chromium-version.outputs.REVISION }}
diff --git a/.github/workflows/trigger_build_ffmpeg.yml b/.github/workflows/trigger_build_ffmpeg.yml
deleted file mode 100644
index 6202c68a16abf8..00000000000000
--- a/.github/workflows/trigger_build_ffmpeg.yml
+++ /dev/null
@@ -1,24 +0,0 @@
-name: "FFMPEG Builder"
-
-on:
- push:
- branches:
- - main
- - release-*
- paths:
- - browser_patches/ffmpeg/BUILD_NUMBER
- - .github/workflows/trigger_build_ffmpeg.yml
-
-jobs:
- trigger:
- name: "trigger"
- runs-on: ubuntu-20.04
- steps:
- - run: |
- curl -X POST \
- -H "Accept: application/vnd.github.v3+json" \
- -H "Authorization: token ${GH_TOKEN}" \
- --data '{"event_type": "build_ffmpeg"}' \
- https://api.github.com/repos/microsoft/playwright-internal/dispatches
- env:
- GH_TOKEN: ${{ secrets.REPOSITORY_DISPATCH_PERSONAL_ACCESS_TOKEN }}
diff --git a/.github/workflows/trigger_build_firefox.yml b/.github/workflows/trigger_build_firefox.yml
deleted file mode 100644
index f0dc3b3daf914e..00000000000000
--- a/.github/workflows/trigger_build_firefox.yml
+++ /dev/null
@@ -1,24 +0,0 @@
-name: "Firefox Builder"
-
-on:
- push:
- branches:
- - main
- - release-*
- paths:
- - browser_patches/firefox/BUILD_NUMBER
- - .github/workflows/trigger_build_firefox.yml
-
-jobs:
- trigger:
- name: "trigger"
- runs-on: ubuntu-20.04
- steps:
- - run: |
- curl -X POST \
- -H "Accept: application/vnd.github.v3+json" \
- -H "Authorization: token ${GH_TOKEN}" \
- --data '{"event_type": "build_firefox"}' \
- https://api.github.com/repos/microsoft/playwright-internal/dispatches
- env:
- GH_TOKEN: ${{ secrets.REPOSITORY_DISPATCH_PERSONAL_ACCESS_TOKEN }}
diff --git a/.github/workflows/trigger_build_firefox_beta.yml b/.github/workflows/trigger_build_firefox_beta.yml
deleted file mode 100644
index 762dd95e184289..00000000000000
--- a/.github/workflows/trigger_build_firefox_beta.yml
+++ /dev/null
@@ -1,24 +0,0 @@
-name: "Firefox Beta Builder"
-
-on:
- push:
- branches:
- - main
- - release-*
- paths:
- - browser_patches/firefox-beta/BUILD_NUMBER
- - .github/workflows/trigger_build_firefox_beta.yml
-
-jobs:
- trigger:
- name: "trigger"
- runs-on: ubuntu-20.04
- steps:
- - run: |
- curl -X POST \
- -H "Accept: application/vnd.github.v3+json" \
- -H "Authorization: token ${GH_TOKEN}" \
- --data '{"event_type": "build_firefox_beta"}' \
- https://api.github.com/repos/microsoft/playwright-internal/dispatches
- env:
- GH_TOKEN: ${{ secrets.REPOSITORY_DISPATCH_PERSONAL_ACCESS_TOKEN }}
diff --git a/.github/workflows/trigger_build_webkit.yml b/.github/workflows/trigger_build_webkit.yml
deleted file mode 100644
index 3dd79da40ca4a9..00000000000000
--- a/.github/workflows/trigger_build_webkit.yml
+++ /dev/null
@@ -1,24 +0,0 @@
-name: "WebKit Builder"
-
-on:
- push:
- branches:
- - main
- - release-*
- paths:
- - browser_patches/webkit/BUILD_NUMBER
- - .github/workflows/trigger_build_webkit.yml
-
-jobs:
- trigger:
- name: "trigger"
- runs-on: ubuntu-20.04
- steps:
- - run: |
- curl -X POST \
- -H "Accept: application/vnd.github.v3+json" \
- -H "Authorization: token ${GH_TOKEN}" \
- --data '{"event_type": "build_webkit"}' \
- https://api.github.com/repos/microsoft/playwright-internal/dispatches
- env:
- GH_TOKEN: ${{ secrets.REPOSITORY_DISPATCH_PERSONAL_ACCESS_TOKEN }}
diff --git a/.github/workflows/trigger_build_winldd.yml b/.github/workflows/trigger_build_winldd.yml
deleted file mode 100644
index dfb2f4bfeb25bf..00000000000000
--- a/.github/workflows/trigger_build_winldd.yml
+++ /dev/null
@@ -1,24 +0,0 @@
-name: "WinLDD Builder"
-
-on:
- push:
- branches:
- - main
- - release-*
- paths:
- - browser_patches/winldd/BUILD_NUMBER
- - .github/workflows/trigger_build_winldd.yml
-
-jobs:
- trigger:
- name: "trigger"
- runs-on: ubuntu-20.04
- steps:
- - run: |
- curl -X POST \
- -H "Accept: application/vnd.github.v3+json" \
- -H "Authorization: token ${GH_TOKEN}" \
- --data '{"event_type": "build_winldd"}' \
- https://api.github.com/repos/microsoft/playwright-internal/dispatches
- env:
- GH_TOKEN: ${{ secrets.REPOSITORY_DISPATCH_PERSONAL_ACCESS_TOKEN }}
diff --git a/.github/workflows/trigger_tests.yml b/.github/workflows/trigger_tests.yml
index 7267c843ba03f2..dcd68dca374400 100644
--- a/.github/workflows/trigger_tests.yml
+++ b/.github/workflows/trigger_tests.yml
@@ -16,6 +16,6 @@ jobs:
-H "Accept: application/vnd.github.v3+json" \
-H "Authorization: token ${GH_TOKEN}" \
--data "{\"event_type\": \"playwright_tests\", \"client_payload\": {\"ref\": \"${GITHUB_SHA}\"}}" \
- https://api.github.com/repos/microsoft/playwright-internal/dispatches
+ https://api.github.com/repos/microsoft/playwright-browsers/dispatches
env:
GH_TOKEN: ${{ secrets.REPOSITORY_DISPATCH_PERSONAL_ACCESS_TOKEN }}
diff --git a/.gitignore b/.gitignore
index deea03bdb9e82f..3d261328095518 100644
--- a/.gitignore
+++ b/.gitignore
@@ -29,3 +29,4 @@ test-results
/tests/installation/output/
/tests/installation/.registry.json
.cache/
+.eslintcache
\ No newline at end of file
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 9e4b58fa5cdb6f..cfc111a1dbc6ac 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -17,6 +17,14 @@
### Getting Code
+Make sure you're running Node.js 16+ and NPM 8+, to verify and upgrade NPM do:
+
+```bash
+node --version
+npm --version
+npm i -g npm@latest
+```
+
1. Clone this repository
```bash
@@ -27,7 +35,7 @@ cd playwright
2. Install dependencies
```bash
-npm install
+npm ci
```
3. Build Playwright
@@ -142,14 +150,24 @@ These are integration tests, making sure public API methods and events work as e
- To run all tests:
```bash
+npx playwright install
npm run test
```
+Be sure to run `npm run build` or let `npm run watch` run before you re-run the
+tests after making your changes to check them.
+
- To run all tests in Chromium
```bash
npm run ctest # also `ftest` for firefox and `wtest` for WebKit
```
+- To run the Playwright test runner tests
+```bash
+npm run ttest
+npm run ttest -- --grep "specific test"
+```
+
- To run a specific test, substitute `it` with `it.only`, or use the `--grep 'My test'` CLI parameter:
```js
diff --git a/README.md b/README.md
index 111b5c7d17ad7e..78fe4814c4c7f4 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# 🎭 Playwright
-[![npm version](https://img.shields.io/npm/v/playwright.svg?style=flat)](https://www.npmjs.com/package/playwright) [![Chromium version](https://img.shields.io/badge/chromium-105.0.5195.28-blue.svg?logo=google-chrome)](https://www.chromium.org/Home) [![Firefox version](https://img.shields.io/badge/firefox-103.0-blue.svg?logo=mozilla-firefox)](https://www.mozilla.org/en-US/firefox/new/) [![WebKit version](https://img.shields.io/badge/webkit-16.0-blue.svg?logo=safari)](https://webkit.org/)
+[![npm version](https://img.shields.io/npm/v/playwright.svg)](https://www.npmjs.com/package/playwright) [![Chromium version](https://img.shields.io/badge/chromium-115.0.5790.98-blue.svg?logo=google-chrome)](https://www.chromium.org/Home) [![Firefox version](https://img.shields.io/badge/firefox-115.0-blue.svg?logo=firefoxbrowser)](https://www.mozilla.org/en-US/firefox/new/) [![WebKit version](https://img.shields.io/badge/webkit-17.0-blue.svg?logo=safari)](https://webkit.org/)
## [Documentation](https://playwright.dev) | [API reference](https://playwright.dev/docs/api/class-playwright)
@@ -8,11 +8,11 @@ Playwright is a framework for Web Testing and Automation. It allows testing [Chr
| | Linux | macOS | Windows |
| :--- | :---: | :---: | :---: |
-| Chromium 105.0.5195.28 | :white_check_mark: | :white_check_mark: | :white_check_mark: |
-| WebKit 16.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: |
-| Firefox 103.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: |
+| Chromium 115.0.5790.98 | :white_check_mark: | :white_check_mark: | :white_check_mark: |
+| WebKit 17.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: |
+| Firefox 115.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: |
-Headless execution is supported for all the browsers on all platforms. Check out [system requirements](https://playwright.dev/docs/library#system-requirements) for details.
+Headless execution is supported for all browsers on all platforms. Check out [system requirements](https://playwright.dev/docs/intro#system-requirements) for details.
Looking for Playwright for [Python](https://playwright.dev/python/docs/intro), [.NET](https://playwright.dev/dotnet/docs/intro), or [Java](https://playwright.dev/java/docs/intro)?
@@ -53,19 +53,19 @@ You can optionally install only selected browsers, see [install browsers](https:
### Resilient • No flaky tests
-**Auto-wait**. Playwright waits for elements to be actionable prior to performing actions. It also has rich set of introspection events. The combination of the two eliminate the need for artificial timeouts - primary cause of flaky tests.
+**Auto-wait**. Playwright waits for elements to be actionable prior to performing actions. It also has a rich set of introspection events. The combination of the two eliminates the need for artificial timeouts - a primary cause of flaky tests.
**Web-first assertions**. Playwright assertions are created specifically for the dynamic web. Checks are automatically retried until the necessary conditions are met.
-**Tracing**. Configure test retry strategy, capture execution trace, videos, screenshots to eliminate flakes.
+**Tracing**. Configure test retry strategy, capture execution trace, videos and screenshots to eliminate flakes.
### No trade-offs • No limits
-Browsers run web content belonging to different origins in different processes. Playwright is aligned with the modern browsers architecture and runs tests out-of-process. This makes Playwright free of the typical in-process test runner limitations.
+Browsers run web content belonging to different origins in different processes. Playwright is aligned with the architecture of the modern browsers and runs tests out-of-process. This makes Playwright free of the typical in-process test runner limitations.
**Multiple everything**. Test scenarios that span multiple tabs, multiple origins and multiple users. Create scenarios with different contexts for different users and run them against your server, all in one test.
-**Trusted events**. Hover elements, interact with dynamic controls, produce trusted events. Playwright uses real browser input pipeline indistinguishable from the real user.
+**Trusted events**. Hover elements, interact with dynamic controls and produce trusted events. Playwright uses real browser input pipeline indistinguishable from the real user.
Test frames, pierce Shadow DOM. Playwright selectors pierce shadow DOM and allow entering frames seamlessly.
@@ -79,7 +79,7 @@ Test frames, pierce Shadow DOM. Playwright selectors pierce shadow DOM and allow
**[Codegen](https://playwright.dev/docs/codegen)**. Generate tests by recording your actions. Save them into any language.
-**[Playwright inspector](https://playwright.dev/docs/inspector)**. Inspect page, generate selectors, step through the test execution, see click points, explore execution logs.
+**[Playwright inspector](https://playwright.dev/docs/inspector)**. Inspect page, generate selectors, step through the test execution, see click points and explore execution logs.
**[Trace Viewer](https://playwright.dev/docs/trace-viewer)**. Capture all the information to investigate the test failure. Playwright trace contains test execution screencast, live DOM snapshots, action explorer, test source and many more.
@@ -91,20 +91,20 @@ To learn how to run these Playwright Test examples, check out our [getting start
#### Page screenshot
-This code snippet navigates to whatsmyuseragent.org and saves a screenshot.
+This code snippet navigates to Playwright homepage and saves a screenshot.
```TypeScript
import { test } from '@playwright/test';
test('Page Screenshot', async ({ page }) => {
- await page.goto('http://whatsmyuseragent.org/');
+ await page.goto('https://playwright.dev/');
await page.screenshot({ path: `example.png` });
});
```
#### Mobile and geolocation
-This snippet emulates Mobile Safari on a device at a given geolocation, navigates to maps.google.com, performs action and takes a screenshot.
+This snippet emulates Mobile Safari on a device at given geolocation, navigates to maps.google.com, performs the action and takes a screenshot.
```TypeScript
import { test, devices } from '@playwright/test';
@@ -118,7 +118,7 @@ test.use({
test('Mobile and geolocation', async ({ page }) => {
await page.goto('https://maps.google.com');
- await page.locator('text="Your location"').click();
+ await page.getByText('Your location').click();
await page.waitForRequest(/.*preview\/pwa/);
await page.screenshot({ path: 'colosseum-iphone.png' });
});
@@ -165,6 +165,5 @@ test('Intercept network requests', async ({ page }) => {
* [Documentation](https://playwright.dev/docs/intro)
* [API reference](https://playwright.dev/docs/api/class-playwright/)
-* [Community showcase](https://playwright.dev/docs/showcase/)
* [Contribution guide](CONTRIBUTING.md)
* [Changelog](https://github.com/microsoft/playwright/releases)
diff --git a/browser_patches/README.md b/browser_patches/README.md
deleted file mode 100644
index e56d6eae3bee4c..00000000000000
--- a/browser_patches/README.md
+++ /dev/null
@@ -1,194 +0,0 @@
-- [Contributing Browser Patches](#Contributing-browser-patches)
- * [1. Setting up local browser checkout](#1-setting-up-local-browser-checkout)
- * [2. Developing a new change](#2-developing-a-new-change)
- * [3. Exporting your change to playwright repo](#3-exporting-your-change-to-playwright-repo)
- * [4. Rolling Playwright to the new browser build](#4-rolling-playwright-to-the-new-browser-build)
-- [Cheatsheet](#cheatsheet)
- * [Firefox](#firefox)
- - [stack trace](#stack-trace)
- - [logging](#logging)
- * [WebKit](#webkit)
- - [Debugging Windows](#degugging-windows)
- - [Enable core dumps on Linux](#enable-core-dumps-on-linux)
-
-# Contributing Browser Patches
-
-Firefox and WebKit have additional patches atop to expose necessary capabilities.
-
-Ideally, all these changes should be upstreamed.
-For the time being, it is possible to setup a browser checkout
-and develop from there.
-
-[WebKit upstream status](webkit/upstream_status.md)
-
-## 1. Setting up local browser checkout
-
-From the `playwright` repo, run the following command:
-
-```bash
-$ ./browser_patches/prepare_checkout.sh firefox
-```
-(you can optionally pass "webkit" for a webkit checkout)
-
-This will create a firefox checkout at `$HOME/firefox`
-
-> **NOTE:** this command downloads GBs of data.
-
-
-This command will:
-- create a `browser_upstream` remote in the checkout
-- create a `playwright-build` branch and apply all playwright-required patches to it.
-
-## 2. Developing a new change
-
-### Creating new branch
-
-You want to create a new branch off the `playwright-build` branch.
-
-Assuming that you're under `$HOME/firefox` checkout:
-
-```bash
-$ git checkout -b my-new-feature playwright-build
-$ # develop my feature on the my-new-feature branch ....
-```
-
-### Building
-
-Each browser has corresponding build script. `--full` options normally takes care of also installing required build dependencies on Linux.
-
-```bash
-./browser_patches/firefox/build.sh --full
-```
-
-### Running tests with local browser build
-
-Playwright test suite may run against local browser build without bundling it.
-```bash
-# Run webkit tests with local webkit build
-WKPATH=./browser_patches/webkit/pw_run.sh npm run wtest
-
-# Run firefox tests with local firefox build on macos
-FFPATH=/tmp/repackaged-firefox/firefox/Nightly.app/Contents/MacOS/firefox npm run ftest
-
-# Run chromium tests with local chromium build on linux
-CRPATH=~/chromium/src/out/Release/chrome npm run ctest
-```
-
-### Flakiness dashboard
-
-You can look at the [flakiness dashboard](http://flaky.aslushnikov.com/) to see recent history of any playwright test.
-
-## 3. Exporting your change to playwright repo
-
-Once you're happy with the work you did in the browser-land, you want to export it to the `playwright` repo.
-
-Assuming that you're in the root of the `playwright` repo and that your browser checkout has your feature branch checked out:
-
-```bash
-$ ./browser_patches/export.sh firefox
-```
-
-This script will:
-- create a new patch and put it to the `./browser_patches/firefox/patches/`
-- update the `./browser_patches/firefox/UPSTREAM_CONFIG.sh` if necessary
-- bump the `./browser_patches/firefox/BUILD_NUMBER` number.
-
-The script will assume Firefox checkout is located at `$HOME/firefox`
-
-Send a PR to the Playwright repo to be reviewed.
-
-## 4. Rolling Playwright to the new browser build
-
-Once the patch has been committed, the build bots will kick in, compile and upload a new browser version to all the platforms. Then you can roll the browser:
-
-```bash
-$ node utils/roll_browser.js chromium 123456
-```
-
-# Cheatsheet
-
-## See browser stdout/stderr
-
-Set the `DEBUG=pw:browser` environment variable to see it.
-
-## Firefox
-
-### Debug build
-
-When compiling set the `FF_DEBUG_BUILD=1` environment variable.
-
-#### Stack trace
-
-In `//mozglue/misc/StackWalk.cpp` add
-
-```c++
-#define MOZ_DEMANGLE_SYMBOLS 1
-```
-
-In native code use
-
-```c++
-#include "mozilla/StackWalk.h"
-// ...
-MozWalkTheStack(stderr);
-```
-
-If the stack trace is still mangled `cat` it to `tools/rb/fix_linux_stack.py`
-
-#### Logging
-
-Upstream documentation: https://firefox-source-docs.mozilla.org/xpcom/logging.html
-
-```bash
-MOZ_LOG=nsHttp:5
-```
-
-Module name is a string passed to the `mozilla::LazyLogModule` of the corresponding component, e.g.:
-
-```c++
-LazyLogModule gHttpLog("nsHttp");
-```
-
-Inside Juggler, you can use `dump('foo\n')`.
-
-## WebKit
-
-#### Logging
-
-Inside Objective-C you can use [NSLog](https://developer.apple.com/documentation/foundation/1395275-nslog).
-
-```
-NSLog(@"Foobar value: %@", value);
-```
-
-#### Debugging windows
-
-In `Source\WTF\wtf\win\DbgHelperWin.cpp` replace
-
-```#if !defined(NDEBUG)``` with ```#if 1```
-
-Then regular `WTFReportBacktrace()` works.
-
-#### Debugging linux
-
-`WTFReportBacktrace()` has been broken since [r283707](https://github.com/WebKit/WebKit/commit/de4ba48c8f229bc45042b543a514f6d88b551a64), see [this comment](https://bugs.webkit.org/show_bug.cgi?id=181916#c96). Revert that change locally to make backtraces work again. Otherwise addr2line -f can still be used to map addresses to function names.
-
-#### Enable core dumps on Linux
-
-```bash
-mkdir -p /tmp/coredumps
-sudo bash -c 'echo "/tmp/coredumps/core-pid_%p.dump" > /proc/sys/kernel/core_pattern'
-ulimit -c unlimited
-```
-
-Then to read stack traces run the following command:
-```bash
-# To find out crashing process name
-file core-pid_29652.dump
-# Point gdb to the local binary of the crashed process and the core file
-gdb $HOME/.cache/ms-playwright/webkit-1292/minibrowser-gtk/WebKitWebProcess core-pid_29652
-# Inside gdb update .so library search path to the local one
-set solib-search-path /home/yurys/.cache/ms-playwright/webkit-1292/minibrowser-gtk
-# Finally print backtrace
-bt
-```
diff --git a/browser_patches/build.sh b/browser_patches/build.sh
deleted file mode 100755
index 509307f9e074a3..00000000000000
--- a/browser_patches/build.sh
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/bin/bash
-set -e
-set +x
-
-trap "cd $(pwd -P)" EXIT
-cd "$(dirname "$0")"
-
-
-if [[ ($1 == '--help') || ($1 == '-h') ]]; then
- echo "usage: build.sh [firefox|webkit|firefox-beta]"
- echo
- exit 0
-fi
-
-if [[ $# == 0 ]]; then
- echo "missing browser: 'firefox' or 'webkit'"
- echo "try './build.sh --help' for more information"
- exit 1
-fi
-
-CMD="$1"
-shift
-if [[ ("$CMD" == "firefox") || ("$CMD" == "firefox/") || ("$CMD" == "ff") ]]; then
- bash ./firefox/build.sh "$@"
-elif [[ ("$CMD" == "firefox-beta") || ("$CMD" == "ff-beta") ]]; then
- bash ./firefox-beta/build.sh "$@"
-elif [[ ("$CMD" == "webkit") || ("$CMD" == "webkit/") || ("$CMD" == "wk") ]]; then
- bash ./webkit/build.sh "$@"
-elif [[ ("$CMD" == "chromium") || ("$CMD" == "chromium/") || ("$CMD" == "cr") ]]; then
- bash ./chromium/build.sh "$@"
-elif [[ ("$CMD" == "winldd") ]]; then
- bash ./winldd/build.sh "$@"
-elif [[ ("$CMD" == "ffmpeg") ]]; then
- bash ./ffmpeg/build.sh "$@"
-else
- echo ERROR: unknown browser to build - "$CMD"
- exit 1
-fi
-
diff --git a/browser_patches/checkout_build_archive_upload.sh b/browser_patches/checkout_build_archive_upload.sh
deleted file mode 100755
index 3d6e6ce179764d..00000000000000
--- a/browser_patches/checkout_build_archive_upload.sh
+++ /dev/null
@@ -1,548 +0,0 @@
-#!/bin/bash
-set -e
-set +x
-set -o pipefail
-
-if [[ ($1 == '--help') || ($1 == '-h') ]]; then
- echo "usage: $(basename "$0") [firefox-linux|firefox-win64|webkit-gtk|webkit-wpe|webkit-gtk-wpe|webkit-win64|webkit-mac-10.15] [-f|--force]"
- echo
- echo "Prepares checkout under browser folder, applies patches, builds, archives, and uploads if build is missing."
- echo "Script will bail out early if the build for the browser version is already present."
- echo
- echo "Pass -f to upload anyway."
- echo
- echo "NOTE: This script is safe to run in a cronjob - it aquires a lock so that it does not run twice."
- exit 0
-fi
-
-if [[ $# == 0 ]]; then
- echo "missing build flavor!"
- echo "try './$(basename "$0") --help' for more information"
- exit 1
-fi
-
-CURRENT_ARCH="$(uname -m)"
-CURRENT_HOST_OS="$(uname)"
-CURRENT_HOST_OS_VERSION=""
-if [[ "$CURRENT_HOST_OS" == "Darwin" ]]; then
- CURRENT_HOST_OS_VERSION=$(sw_vers -productVersion | grep -o '^\d\+.\d\+')
-elif [[ "$CURRENT_HOST_OS" == "Linux" ]]; then
- CURRENT_HOST_OS="$(bash -c 'source /etc/os-release && echo $NAME')"
- CURRENT_HOST_OS_VERSION="$(bash -c 'source /etc/os-release && echo $VERSION_ID')"
-fi
-
-BROWSER_NAME=""
-BROWSER_DISPLAY_NAME=""
-EXTRA_BUILD_ARGS=""
-EXTRA_ARCHIVE_ARGS=""
-BUILD_FLAVOR="$1"
-BUILD_BLOB_NAME=""
-EXPECTED_HOST_OS=""
-EXPECTED_HOST_OS_VERSION=""
-EXPECTED_ARCH="x86_64"
-BUILDS_LIST="EXPECTED_BUILDS"
-
-# ===========================
-# WINLDD COMPILATION
-# ===========================
-if [[ "$BUILD_FLAVOR" == "winldd-win64" ]]; then
- BROWSER_NAME="winldd"
- EXPECTED_HOST_OS="MINGW"
- BUILD_BLOB_NAME="winldd-win64.zip"
-
-
-# ===========================
-# FFMPEG COMPILATION
-# ===========================
-elif [[ "$BUILD_FLAVOR" == "ffmpeg-mac" ]]; then
- BROWSER_NAME="ffmpeg"
- EXTRA_BUILD_ARGS="--mac --full"
- EXPECTED_HOST_OS="Darwin"
- EXPECTED_HOST_OS_VERSION="11.6"
- BUILD_BLOB_NAME="ffmpeg-mac.zip"
-elif [[ "$BUILD_FLAVOR" == "ffmpeg-mac-arm64" ]]; then
- BROWSER_NAME="ffmpeg"
- EXTRA_BUILD_ARGS="--mac --full"
- EXPECTED_HOST_OS="Darwin"
- EXPECTED_HOST_OS_VERSION="11.6"
- EXPECTED_ARCH="arm64"
- BUILD_BLOB_NAME="ffmpeg-mac-arm64.zip"
-elif [[ "$BUILD_FLAVOR" == "ffmpeg-linux" ]]; then
- BROWSER_NAME="ffmpeg"
- EXTRA_BUILD_ARGS="--linux"
- EXPECTED_HOST_OS="Ubuntu"
- EXPECTED_HOST_OS_VERSION="20.04"
- BUILD_BLOB_NAME="ffmpeg-linux.zip"
-elif [[ "$BUILD_FLAVOR" == "ffmpeg-linux-arm64" ]]; then
- BROWSER_NAME="ffmpeg"
- EXTRA_BUILD_ARGS="--cross-compile-linux-arm64"
- EXPECTED_HOST_OS="Ubuntu"
- EXPECTED_HOST_OS_VERSION="20.04"
- BUILD_BLOB_NAME="ffmpeg-linux-arm64.zip"
-elif [[ "$BUILD_FLAVOR" == "ffmpeg-cross-compile-win64" ]]; then
- BROWSER_NAME="ffmpeg"
- EXTRA_BUILD_ARGS="--cross-compile-win64"
- EXPECTED_HOST_OS="Ubuntu"
- EXPECTED_HOST_OS_VERSION="20.04"
- BUILD_BLOB_NAME="ffmpeg-win64.zip"
-
-# ===========================
-# CHROMIUM COMPILATION
-# ===========================
-elif [[ "$BUILD_FLAVOR" == "chromium-win64" ]]; then
- BROWSER_NAME="chromium"
- EXTRA_BUILD_ARGS="--full --goma"
- EXPECTED_HOST_OS="MINGW"
- BUILD_BLOB_NAME="chromium-win64.zip"
-elif [[ "$BUILD_FLAVOR" == "chromium-mac" ]]; then
- BROWSER_NAME="chromium"
- EXTRA_BUILD_ARGS="--full --goma"
- EXPECTED_HOST_OS="Darwin"
- EXPECTED_HOST_OS_VERSION="12.2"
- BUILD_BLOB_NAME="chromium-mac.zip"
-elif [[ "$BUILD_FLAVOR" == "chromium-mac-arm64" ]]; then
- BROWSER_NAME="chromium"
- EXTRA_BUILD_ARGS="--arm64 --full --goma"
- EXPECTED_HOST_OS="Darwin"
- EXPECTED_HOST_OS_VERSION="12.2"
- BUILD_BLOB_NAME="chromium-mac-arm64.zip"
-elif [[ "$BUILD_FLAVOR" == "chromium-linux" ]]; then
- BROWSER_NAME="chromium"
- EXTRA_BUILD_ARGS="--full --goma"
- EXPECTED_HOST_OS="Ubuntu"
- EXPECTED_HOST_OS_VERSION="18.04"
- BUILD_BLOB_NAME="chromium-linux.zip"
-elif [[ "$BUILD_FLAVOR" == "chromium-linux-arm64" ]]; then
- BROWSER_NAME="chromium"
- EXTRA_BUILD_ARGS="--arm64 --full --goma"
- EXPECTED_HOST_OS="Ubuntu"
- EXPECTED_HOST_OS_VERSION="20.04"
- BUILD_BLOB_NAME="chromium-linux-arm64.zip"
-
-# ===========================
-# CHROMIUM-TIP-OF-TREE COMPILATION
-# ===========================
-elif [[ "$BUILD_FLAVOR" == "chromium-tip-of-tree-win64" ]]; then
- BROWSER_NAME="chromium-tip-of-tree"
- EXTRA_BUILD_ARGS="--full --goma"
- EXPECTED_HOST_OS="MINGW"
- BUILD_BLOB_NAME="chromium-tip-of-tree-win64.zip"
-elif [[ "$BUILD_FLAVOR" == "chromium-tip-of-tree-mac" ]]; then
- BROWSER_NAME="chromium-tip-of-tree"
- EXTRA_BUILD_ARGS="--full --goma"
- EXPECTED_HOST_OS="Darwin"
- EXPECTED_HOST_OS_VERSION="12.2"
- BUILD_BLOB_NAME="chromium-tip-of-tree-mac.zip"
-elif [[ "$BUILD_FLAVOR" == "chromium-tip-of-tree-mac-arm64" ]]; then
- BROWSER_NAME="chromium-tip-of-tree"
- EXTRA_BUILD_ARGS="--arm64 --full --goma"
- EXPECTED_HOST_OS="Darwin"
- EXPECTED_HOST_OS_VERSION="12.2"
- BUILD_BLOB_NAME="chromium-tip-of-tree-mac-arm64.zip"
-elif [[ "$BUILD_FLAVOR" == "chromium-tip-of-tree-linux" ]]; then
- BROWSER_NAME="chromium-tip-of-tree"
- EXTRA_BUILD_ARGS="--full --goma"
- EXPECTED_HOST_OS="Ubuntu"
- EXPECTED_HOST_OS_VERSION="18.04"
- BUILD_BLOB_NAME="chromium-tip-of-tree-linux.zip"
-elif [[ "$BUILD_FLAVOR" == "chromium-tip-of-tree-linux-arm64" ]]; then
- BROWSER_NAME="chromium-tip-of-tree"
- EXTRA_BUILD_ARGS="--arm64 --full --goma"
- EXPECTED_HOST_OS="Ubuntu"
- EXPECTED_HOST_OS_VERSION="20.04"
- BUILD_BLOB_NAME="chromium-tip-of-tree-linux-arm64.zip"
-
-# ===========================
-# CHROMIUM-WITH-SYMBOLS COMPILATION
-# ===========================
-elif [[ "$BUILD_FLAVOR" == "chromium-with-symbols-win64" ]]; then
- BROWSER_NAME="chromium"
- BROWSER_DISPLAY_NAME="chromium-with-symbols"
- EXTRA_BUILD_ARGS="--symbols --full --goma"
- EXPECTED_HOST_OS="MINGW"
- BUILD_BLOB_NAME="chromium-with-symbols-win64.zip"
- BUILDS_LIST="EXPECTED_BUILDS_WITH_SYMBOLS"
-elif [[ "$BUILD_FLAVOR" == "chromium-with-symbols-mac" ]]; then
- BROWSER_NAME="chromium"
- BROWSER_DISPLAY_NAME="chromium-with-symbols"
- EXTRA_BUILD_ARGS="--symbols --full --goma"
- EXPECTED_HOST_OS="Darwin"
- EXPECTED_HOST_OS_VERSION="12.2"
- BUILD_BLOB_NAME="chromium-with-symbols-mac.zip"
- BUILDS_LIST="EXPECTED_BUILDS_WITH_SYMBOLS"
-elif [[ "$BUILD_FLAVOR" == "chromium-with-symbols-mac-arm64" ]]; then
- BROWSER_NAME="chromium"
- BROWSER_DISPLAY_NAME="chromium-with-symbols"
- EXTRA_BUILD_ARGS="--arm64 --symbols --full --goma"
- EXPECTED_HOST_OS="Darwin"
- EXPECTED_HOST_OS_VERSION="12.2"
- BUILD_BLOB_NAME="chromium-with-symbols-mac-arm64.zip"
- BUILDS_LIST="EXPECTED_BUILDS_WITH_SYMBOLS"
-elif [[ "$BUILD_FLAVOR" == "chromium-with-symbols-linux" ]]; then
- BROWSER_NAME="chromium"
- BROWSER_DISPLAY_NAME="chromium-with-symbols"
- EXTRA_BUILD_ARGS="--symbols --full --goma"
- EXPECTED_HOST_OS="Ubuntu"
- EXPECTED_HOST_OS_VERSION="18.04"
- BUILD_BLOB_NAME="chromium-with-symbols-linux.zip"
- BUILDS_LIST="EXPECTED_BUILDS_WITH_SYMBOLS"
-elif [[ "$BUILD_FLAVOR" == "chromium-with-symbols-linux-arm64" ]]; then
- BROWSER_NAME="chromium"
- BROWSER_DISPLAY_NAME="chromium-with-symbols-arm64"
- EXTRA_BUILD_ARGS="--arm64 --symbols --full --goma"
- EXPECTED_HOST_OS="Ubuntu"
- EXPECTED_HOST_OS_VERSION="20.04"
- BUILD_BLOB_NAME="chromium-with-symbols-linux-arm64.zip"
- BUILDS_LIST="EXPECTED_BUILDS_WITH_SYMBOLS"
-
-# ===========================
-# FIREFOX COMPILATION
-# ===========================
-elif [[ "$BUILD_FLAVOR" == "firefox-ubuntu-18.04" ]]; then
- BROWSER_NAME="firefox"
- EXTRA_BUILD_ARGS="--full"
- EXPECTED_HOST_OS="Ubuntu"
- EXPECTED_HOST_OS_VERSION="18.04"
- BUILD_BLOB_NAME="firefox-ubuntu-18.04.zip"
-elif [[ "$BUILD_FLAVOR" == "firefox-ubuntu-20.04" ]]; then
- BROWSER_NAME="firefox"
- EXTRA_BUILD_ARGS="--full"
- EXPECTED_HOST_OS="Ubuntu"
- EXPECTED_HOST_OS_VERSION="20.04"
- BUILD_BLOB_NAME="firefox-ubuntu-20.04.zip"
-elif [[ "$BUILD_FLAVOR" == "firefox-ubuntu-20.04-arm64" ]]; then
- BROWSER_NAME="firefox"
- EXTRA_BUILD_ARGS="--full"
- EXPECTED_ARCH="aarch64"
- EXPECTED_HOST_OS="Ubuntu"
- EXPECTED_HOST_OS_VERSION="20.04"
- BUILD_BLOB_NAME="firefox-ubuntu-20.04-arm64.zip"
-elif [[ "$BUILD_FLAVOR" == "firefox-ubuntu-22.04" ]]; then
- BROWSER_NAME="firefox"
- EXTRA_BUILD_ARGS="--full"
- EXPECTED_HOST_OS="Ubuntu"
- EXPECTED_HOST_OS_VERSION="22.04"
- BUILD_BLOB_NAME="firefox-ubuntu-22.04.zip"
-elif [[ "$BUILD_FLAVOR" == "firefox-ubuntu-22.04-arm64" ]]; then
- BROWSER_NAME="firefox"
- EXTRA_BUILD_ARGS="--full"
- EXPECTED_ARCH="aarch64"
- EXPECTED_HOST_OS="Ubuntu"
- EXPECTED_HOST_OS_VERSION="22.04"
- BUILD_BLOB_NAME="firefox-ubuntu-22.04-arm64.zip"
-elif [[ "$BUILD_FLAVOR" == "firefox-debian-11" ]]; then
- BROWSER_NAME="firefox"
- EXTRA_BUILD_ARGS="--full"
- EXPECTED_HOST_OS="Debian"
- EXPECTED_HOST_OS_VERSION="11"
- BUILD_BLOB_NAME="firefox-debian-11.zip"
-elif [[ "$BUILD_FLAVOR" == "firefox-mac-11" ]]; then
- BROWSER_NAME="firefox"
- EXTRA_BUILD_ARGS="--full"
- EXPECTED_HOST_OS="Darwin"
- EXPECTED_HOST_OS_VERSION="11.6"
- EXPECTED_ARCH="x86_64"
- BUILD_BLOB_NAME="firefox-mac-11.zip"
-elif [[ "$BUILD_FLAVOR" == "firefox-mac-11-arm64" ]]; then
- BROWSER_NAME="firefox"
- EXTRA_BUILD_ARGS="--full"
- EXPECTED_HOST_OS="Darwin"
- EXPECTED_HOST_OS_VERSION="11.6"
- EXPECTED_ARCH="arm64"
- BUILD_BLOB_NAME="firefox-mac-11-arm64.zip"
-elif [[ "$BUILD_FLAVOR" == "firefox-win64" ]]; then
- BROWSER_NAME="firefox"
- EXTRA_BUILD_ARGS="--full"
- EXPECTED_HOST_OS="MINGW"
- BUILD_BLOB_NAME="firefox-win64.zip"
- # This is the architecture that is set by mozilla-build bash.
- EXPECTED_ARCH="i686"
-
-
-# ===============================
-# FIREFOX-BETA COMPILATION
-# ===============================
-elif [[ "$BUILD_FLAVOR" == "firefox-beta-ubuntu-18.04" ]]; then
- BROWSER_NAME="firefox-beta"
- EXTRA_BUILD_ARGS="--full"
- EXPECTED_HOST_OS="Ubuntu"
- EXPECTED_HOST_OS_VERSION="18.04"
- BUILD_BLOB_NAME="firefox-beta-ubuntu-18.04.zip"
-elif [[ "$BUILD_FLAVOR" == "firefox-beta-ubuntu-20.04" ]]; then
- BROWSER_NAME="firefox-beta"
- EXTRA_BUILD_ARGS="--full"
- EXPECTED_HOST_OS="Ubuntu"
- EXPECTED_HOST_OS_VERSION="20.04"
- BUILD_BLOB_NAME="firefox-beta-ubuntu-20.04.zip"
-elif [[ "$BUILD_FLAVOR" == "firefox-beta-ubuntu-20.04-arm64" ]]; then
- BROWSER_NAME="firefox-beta"
- EXTRA_BUILD_ARGS="--full"
- EXPECTED_ARCH="aarch64"
- EXPECTED_HOST_OS="Ubuntu"
- EXPECTED_HOST_OS_VERSION="20.04"
- BUILD_BLOB_NAME="firefox-beta-ubuntu-20.04-arm64.zip"
-elif [[ "$BUILD_FLAVOR" == "firefox-beta-ubuntu-22.04" ]]; then
- BROWSER_NAME="firefox-beta"
- EXTRA_BUILD_ARGS="--full"
- EXPECTED_HOST_OS="Ubuntu"
- EXPECTED_HOST_OS_VERSION="22.04"
- BUILD_BLOB_NAME="firefox-beta-ubuntu-22.04.zip"
-elif [[ "$BUILD_FLAVOR" == "firefox-beta-ubuntu-22.04-arm64" ]]; then
- BROWSER_NAME="firefox-beta"
- EXTRA_BUILD_ARGS="--full"
- EXPECTED_ARCH="aarch64"
- EXPECTED_HOST_OS="Ubuntu"
- EXPECTED_HOST_OS_VERSION="22.04"
- BUILD_BLOB_NAME="firefox-beta-ubuntu-22.04-arm64.zip"
-elif [[ "$BUILD_FLAVOR" == "firefox-beta-debian-11" ]]; then
- BROWSER_NAME="firefox-beta"
- EXTRA_BUILD_ARGS="--full"
- EXPECTED_HOST_OS="Debian"
- EXPECTED_HOST_OS_VERSION="11"
- BUILD_BLOB_NAME="firefox-beta-debian-11.zip"
-elif [[ "$BUILD_FLAVOR" == "firefox-beta-mac-11" ]]; then
- BROWSER_NAME="firefox-beta"
- EXTRA_BUILD_ARGS="--full"
- EXPECTED_HOST_OS="Darwin"
- EXPECTED_HOST_OS_VERSION="11.6"
- EXPECTED_ARCH="x86_64"
- BUILD_BLOB_NAME="firefox-beta-mac-11.zip"
-elif [[ "$BUILD_FLAVOR" == "firefox-beta-mac-11-arm64" ]]; then
- BROWSER_NAME="firefox-beta"
- EXTRA_BUILD_ARGS="--full"
- EXPECTED_HOST_OS="Darwin"
- EXPECTED_HOST_OS_VERSION="11.6"
- EXPECTED_ARCH="arm64"
- BUILD_BLOB_NAME="firefox-beta-mac-11-arm64.zip"
-elif [[ "$BUILD_FLAVOR" == "firefox-beta-win64" ]]; then
- BROWSER_NAME="firefox-beta"
- EXTRA_BUILD_ARGS="--full"
- EXPECTED_HOST_OS="MINGW"
- BUILD_BLOB_NAME="firefox-beta-win64.zip"
- # This is the architecture that is set by mozilla-build bash.
- EXPECTED_ARCH="i686"
-
-# ===========================
-# WEBKIT COMPILATION
-# ===========================
-elif [[ "$BUILD_FLAVOR" == "webkit-debian-11" ]]; then
- BROWSER_NAME="webkit"
- EXTRA_BUILD_ARGS="--full"
- EXPECTED_HOST_OS="Debian"
- EXPECTED_HOST_OS_VERSION="11"
- BUILD_BLOB_NAME="webkit-debian-11.zip"
-elif [[ "$BUILD_FLAVOR" == "webkit-ubuntu-18.04" ]]; then
- BROWSER_NAME="webkit"
- EXTRA_BUILD_ARGS="--full"
- EXPECTED_HOST_OS="Ubuntu"
- EXPECTED_HOST_OS_VERSION="18.04"
- BUILD_BLOB_NAME="webkit-ubuntu-18.04.zip"
-elif [[ "$BUILD_FLAVOR" == "webkit-ubuntu-20.04" ]]; then
- BROWSER_NAME="webkit"
- EXTRA_BUILD_ARGS="--full"
- EXPECTED_HOST_OS="Ubuntu"
- EXPECTED_HOST_OS_VERSION="20.04"
- BUILD_BLOB_NAME="webkit-ubuntu-20.04.zip"
-elif [[ "$BUILD_FLAVOR" == "webkit-ubuntu-20.04-arm64" ]]; then
- BROWSER_NAME="webkit"
- EXTRA_BUILD_ARGS="--full"
- EXPECTED_HOST_OS="Ubuntu"
- EXPECTED_HOST_OS_VERSION="20.04"
- EXPECTED_ARCH="aarch64"
- BUILD_BLOB_NAME="webkit-ubuntu-20.04-arm64.zip"
-elif [[ "$BUILD_FLAVOR" == "webkit-ubuntu-22.04" ]]; then
- BROWSER_NAME="webkit"
- EXTRA_BUILD_ARGS="--full"
- EXPECTED_HOST_OS="Ubuntu"
- EXPECTED_HOST_OS_VERSION="22.04"
- BUILD_BLOB_NAME="webkit-ubuntu-22.04.zip"
-elif [[ "$BUILD_FLAVOR" == "webkit-ubuntu-22.04-arm64" ]]; then
- BROWSER_NAME="webkit"
- EXTRA_BUILD_ARGS="--full"
- EXPECTED_HOST_OS="Ubuntu"
- EXPECTED_HOST_OS_VERSION="22.04"
- EXPECTED_ARCH="aarch64"
- BUILD_BLOB_NAME="webkit-ubuntu-22.04-arm64.zip"
-elif [[ "$BUILD_FLAVOR" == "webkit-win64" ]]; then
- BROWSER_NAME="webkit"
- EXPECTED_HOST_OS="MINGW"
- BUILD_BLOB_NAME="webkit-win64.zip"
-elif [[ "$BUILD_FLAVOR" == "webkit-mac-10.15" ]]; then
- BROWSER_NAME="webkit"
- EXPECTED_HOST_OS="Darwin"
- EXPECTED_HOST_OS_VERSION="10.15"
- BUILD_BLOB_NAME="webkit-mac-10.15.zip"
-elif [[ "$BUILD_FLAVOR" == "webkit-mac-12" ]]; then
- BROWSER_NAME="webkit"
- EXPECTED_HOST_OS="Darwin"
- EXPECTED_HOST_OS_VERSION="12.2"
- BUILD_BLOB_NAME="webkit-mac-12.zip"
-elif [[ "$BUILD_FLAVOR" == "webkit-mac-12-arm64" ]]; then
- BROWSER_NAME="webkit"
- EXPECTED_HOST_OS="Darwin"
- EXPECTED_HOST_OS_VERSION="12.2"
- EXPECTED_ARCH="arm64"
- BUILD_BLOB_NAME="webkit-mac-12-arm64.zip"
-elif [[ "$BUILD_FLAVOR" == "webkit-mac-11" ]]; then
- BROWSER_NAME="webkit"
- EXPECTED_HOST_OS="Darwin"
- EXPECTED_HOST_OS_VERSION="11.6"
- BUILD_BLOB_NAME="webkit-mac-11.zip"
-elif [[ "$BUILD_FLAVOR" == "webkit-mac-11-arm64" ]]; then
- BROWSER_NAME="webkit"
- EXPECTED_HOST_OS="Darwin"
- EXPECTED_HOST_OS_VERSION="11.6"
- EXPECTED_ARCH="arm64"
- BUILD_BLOB_NAME="webkit-mac-11-arm64.zip"
-
-
-# ===========================
-# Unknown input
-# ===========================
-else
- echo ERROR: unknown build flavor - "$BUILD_FLAVOR"
- exit 1
-fi
-
-if [[ -z "$BROWSER_DISPLAY_NAME" ]]; then
- BROWSER_DISPLAY_NAME="${BROWSER_NAME}"
-fi
-
-if [[ "$CURRENT_ARCH" != "$EXPECTED_ARCH" ]]; then
- echo "ERROR: cannot build $BUILD_FLAVOR"
- echo " -- expected arch: $EXPECTED_ARCH"
- echo " -- current arch: $CURRENT_ARCH"
- exit 1
-fi
-
-if [[ "$CURRENT_HOST_OS" != $EXPECTED_HOST_OS* ]]; then
- echo "ERROR: cannot build $BUILD_FLAVOR"
- echo " -- expected OS: $EXPECTED_HOST_OS"
- echo " -- current OS: $CURRENT_HOST_OS"
- exit 1
-fi
-
-if [[ "$CURRENT_HOST_OS_VERSION" != "$EXPECTED_HOST_OS_VERSION" ]]; then
- echo "ERROR: cannot build $BUILD_FLAVOR"
- echo " -- expected OS Version: $EXPECTED_HOST_OS_VERSION"
- echo " -- current OS Version: $CURRENT_HOST_OS_VERSION"
- exit 1
-fi
-
-if [[ $(uname) == MINGW* || "$(uname)" == MSYS* ]]; then
- ZIP_PATH="$PWD/archive-$BROWSER_NAME.zip"
- LOG_PATH="$PWD/log-$BROWSER_NAME.zip"
-else
- ZIP_PATH="/tmp/archive-$BROWSER_NAME.zip"
- LOG_PATH="/tmp/log-$BROWSER_NAME.zip"
-fi
-
-if [[ -f "$ZIP_PATH" ]]; then
- echo "Archive $ZIP_PATH already exists - remove and re-run the script."
- exit 1
-fi
-trap "rm -rf ${ZIP_PATH}; rm -rf ${LOG_PATH}; cd $(pwd -P);" INT TERM EXIT
-cd "$(dirname "$0")"
-BUILD_NUMBER=$(head -1 ./$BROWSER_NAME/BUILD_NUMBER)
-BUILD_BLOB_PATH="${BROWSER_NAME}/${BUILD_NUMBER}/${BUILD_BLOB_NAME}"
-LOG_BLOB_NAME="${BUILD_BLOB_NAME%.zip}.log.gz"
-LOG_BLOB_PATH="${BROWSER_NAME}/${BUILD_NUMBER}/${LOG_BLOB_NAME}"
-
-# pull from upstream and check if a new build has to be uploaded.
-if ! [[ ($2 == '-f') || ($2 == '--force') ]]; then
- if ./upload.sh "${BUILD_BLOB_PATH}" --check; then
- echo "Build is already uploaded - no changes."
- exit 0
- fi
-else
- echo "Force-rebuilding the build."
-fi
-
-function generate_and_upload_browser_build {
- echo "-- preparing checkout"
- if ! ./prepare_checkout.sh $BROWSER_NAME; then
- return 20
- fi
-
- echo "-- cleaning"
- if ! ./$BROWSER_NAME/clean.sh; then
- return 21
- fi
-
- echo "-- building"
- if ! ./$BROWSER_NAME/build.sh $EXTRA_BUILD_ARGS; then
- return 22
- fi
-
- echo "-- archiving to $ZIP_PATH"
- if ! ./$BROWSER_NAME/archive.sh "$ZIP_PATH" $EXTRA_ARCHIVE_ARGS; then
- return 23
- fi
-
- echo "-- uploading"
- if ! ./upload.sh "$BUILD_BLOB_PATH" "$ZIP_PATH"; then
- return 24
- fi
- return 0
-}
-
-function create_roll_into_playwright_pr {
- curl -X POST \
- -H "Accept: application/vnd.github.v3+json" \
- -H "Authorization: token ${GH_TOKEN}" \
- --data '{"event_type": "roll_into_pw", "client_payload": {"browser": "'"$1"'", "revision": "'"$2"'"}}' \
- https://api.github.com/repos/microsoft/playwright/dispatches
-}
-
-BUILD_ALIAS="$BUILD_FLAVOR r$BUILD_NUMBER"
-node send_telegram_message.js "$BUILD_ALIAS -- started"
-
-if generate_and_upload_browser_build 2>&1 | ./sanitize_and_compress_log.js $LOG_PATH; then
- # Report successful build. Note: MINGW might not have `du` command.
- UPLOAD_SIZE=""
- if command -v du >/dev/null && command -v awk >/dev/null; then
- UPLOAD_SIZE="$(du -h "$ZIP_PATH" | awk '{print $1}') "
- fi
- node send_telegram_message.js "$BUILD_ALIAS -- ${UPLOAD_SIZE}uploaded"
-
- # Check if we uploaded the last build.
- (
- for i in $(cat "${BROWSER_NAME}/${BUILDS_LIST}"); do
- URL="https://playwright2.blob.core.windows.net/builds/${BROWSER_NAME}/${BUILD_NUMBER}/$i"
- if ! [[ $(curl -s -L -I "$URL" | head -1 | cut -f2 -d' ') == 200 ]]; then
- # Exit subshell
- echo "Missing build at ${URL}"
- exit
- fi
- done;
- LAST_COMMIT_MESSAGE=$(git log --format=%s -n 1 HEAD -- "./${BROWSER_NAME}/BUILD_NUMBER")
- node send_telegram_message.js "${BROWSER_DISPLAY_NAME} r${BUILD_NUMBER} COMPLETE! ✅ ${LAST_COMMIT_MESSAGE}"
- if [[ "${BROWSER_DISPLAY_NAME}" != "chromium-with-symbols" ]]; then
- create_roll_into_playwright_pr $BROWSER_NAME $BUILD_NUMBER
- fi
- )
-else
- RESULT_CODE="$?"
- if (( RESULT_CODE == 10 )); then
- FAILED_STEP="./download_gtk_and_wpe_and_zip_together.sh"
- elif (( RESULT_CODE == 11 )); then
- FAILED_STEP="./upload.sh"
- elif (( RESULT_CODE == 20 )); then
- FAILED_STEP="./prepare_checkout.sh"
- elif (( RESULT_CODE == 21 )); then
- FAILED_STEP="./clean.sh"
- elif (( RESULT_CODE == 22 )); then
- FAILED_STEP="./build.sh"
- elif (( RESULT_CODE == 23 )); then
- FAILED_STEP="./archive.sh"
- elif (( RESULT_CODE == 24 )); then
- FAILED_STEP="./upload.sh"
- else
- FAILED_STEP=""
- fi
- # Upload logs only in case of failure and report failure.
- ./upload.sh "${LOG_BLOB_PATH}" ${LOG_PATH} || true
- node send_telegram_message.js "$BUILD_ALIAS -- ${FAILED_STEP} failed! ❌ ${LOG_BLOB_NAME} -- GitHub Action Logs"
- exit 1
-fi
-
diff --git a/browser_patches/chromium-tip-of-tree/BUILD_NUMBER b/browser_patches/chromium-tip-of-tree/BUILD_NUMBER
deleted file mode 100644
index 95e145d5beb485..00000000000000
--- a/browser_patches/chromium-tip-of-tree/BUILD_NUMBER
+++ /dev/null
@@ -1 +0,0 @@
-1035
diff --git a/browser_patches/chromium-tip-of-tree/EXPECTED_BUILDS b/browser_patches/chromium-tip-of-tree/EXPECTED_BUILDS
deleted file mode 100644
index 2575021ad4c5c3..00000000000000
--- a/browser_patches/chromium-tip-of-tree/EXPECTED_BUILDS
+++ /dev/null
@@ -1,5 +0,0 @@
-chromium-tip-of-tree-mac.zip
-chromium-tip-of-tree-mac-arm64.zip
-chromium-tip-of-tree-linux.zip
-chromium-tip-of-tree-linux-arm64.zip
-chromium-tip-of-tree-win64.zip
diff --git a/browser_patches/chromium-tip-of-tree/UPSTREAM_CONFIG.sh b/browser_patches/chromium-tip-of-tree/UPSTREAM_CONFIG.sh
deleted file mode 100644
index ead22a6954c40e..00000000000000
--- a/browser_patches/chromium-tip-of-tree/UPSTREAM_CONFIG.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-# CURRENT_VERSION: 106.0.5247.0
-# BRANCH_BASE_POSITION: 1036354
-BRANCH_COMMIT="18d7ce4d777fa2c7de03f6a01c026b0f9394037e"
diff --git a/browser_patches/chromium-tip-of-tree/archive.sh b/browser_patches/chromium-tip-of-tree/archive.sh
deleted file mode 100755
index 3e260dfb0af71b..00000000000000
--- a/browser_patches/chromium-tip-of-tree/archive.sh
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/bash
-set -e
-set +x
-
-trap "cd $(pwd -P)" EXIT
-cd "$(dirname "$0")"
-SCRIPT_FOLDER=$(pwd -P)
-
-bash "../chromium/archive.sh" "$@"
diff --git a/browser_patches/chromium-tip-of-tree/build.sh b/browser_patches/chromium-tip-of-tree/build.sh
deleted file mode 100755
index efc6479c616f7a..00000000000000
--- a/browser_patches/chromium-tip-of-tree/build.sh
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/bash
-set -e
-set +x
-
-trap "cd $(pwd -P)" EXIT
-cd "$(dirname "$0")"
-SCRIPT_FOLDER=$(pwd -P)
-
-bash "../chromium/build.sh" "$@"
diff --git a/browser_patches/chromium-tip-of-tree/clean.sh b/browser_patches/chromium-tip-of-tree/clean.sh
deleted file mode 100755
index 3ea4237e9cf70b..00000000000000
--- a/browser_patches/chromium-tip-of-tree/clean.sh
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/bash
-set -e
-set +x
-
-trap "cd $(pwd -P)" EXIT
-cd "$(dirname "$0")"
-SCRIPT_FOLDER=$(pwd -P)
-
-bash "../chromium/clean.sh" "$@"
diff --git a/browser_patches/chromium-tip-of-tree/roll_to_current_tip_of_tree.sh b/browser_patches/chromium-tip-of-tree/roll_to_current_tip_of_tree.sh
deleted file mode 100755
index 4ddf20bf329a3e..00000000000000
--- a/browser_patches/chromium-tip-of-tree/roll_to_current_tip_of_tree.sh
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/bin/bash
-set -e
-set +x
-
-trap "cd $(pwd -P)" EXIT
-cd "$(dirname "$0")"
-SCRIPT_FOLDER=$(pwd -P)
-
-# 1. get current version
-CURRENT_BETA_VERSION=$(curl https://omahaproxy.appspot.com/all | grep "win64,canary," | cut -d ',' -f 3)
-VERSION_INFO_JSON=$(curl "https://omahaproxy.appspot.com/deps.json?version=$CURRENT_BETA_VERSION")
-
-NODE_SCRIPT=$(cat < "${SCRIPT_FOLDER}/UPSTREAM_CONFIG.sh"
-BUILD_NUMBER=$(cat "${SCRIPT_FOLDER}/BUILD_NUMBER")
-echo $(( $BUILD_NUMBER + 1 )) > "${SCRIPT_FOLDER}/BUILD_NUMBER"
diff --git a/browser_patches/chromium/.gitignore b/browser_patches/chromium/.gitignore
deleted file mode 100644
index 2658404cd72839..00000000000000
--- a/browser_patches/chromium/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-/output
-/depot_tools
-/electron-build-tools
diff --git a/browser_patches/chromium/BUILD_NUMBER b/browser_patches/chromium/BUILD_NUMBER
deleted file mode 100644
index 8463e0903ffa40..00000000000000
--- a/browser_patches/chromium/BUILD_NUMBER
+++ /dev/null
@@ -1 +0,0 @@
-1021
diff --git a/browser_patches/chromium/EXPECTED_BUILDS b/browser_patches/chromium/EXPECTED_BUILDS
deleted file mode 100644
index aa0df7e2ef5aa7..00000000000000
--- a/browser_patches/chromium/EXPECTED_BUILDS
+++ /dev/null
@@ -1,5 +0,0 @@
-chromium-mac.zip
-chromium-mac-arm64.zip
-chromium-linux.zip
-chromium-linux-arm64.zip
-chromium-win64.zip
diff --git a/browser_patches/chromium/EXPECTED_BUILDS_WITH_SYMBOLS b/browser_patches/chromium/EXPECTED_BUILDS_WITH_SYMBOLS
deleted file mode 100644
index 36a818ac6f2f7b..00000000000000
--- a/browser_patches/chromium/EXPECTED_BUILDS_WITH_SYMBOLS
+++ /dev/null
@@ -1,5 +0,0 @@
-chromium-with-symbols-mac.zip
-chromium-with-symbols-mac-arm64.zip
-chromium-with-symbols-linux.zip
-chromium-with-symbols-linux-arm64.zip
-chromium-with-symbols-win64.zip
diff --git a/browser_patches/chromium/UPSTREAM_CONFIG.sh b/browser_patches/chromium/UPSTREAM_CONFIG.sh
deleted file mode 100644
index a8d7280576e6df..00000000000000
--- a/browser_patches/chromium/UPSTREAM_CONFIG.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-# CURRENT_VERSION: 105.0.5195.37
-# BRANCH_BASE_POSITION: 1027018
-BRANCH_COMMIT="9f54e061380e11c611d0c695ab77a94fd2a0afa3"
diff --git a/browser_patches/chromium/archive.sh b/browser_patches/chromium/archive.sh
deleted file mode 100755
index c9de58258070c9..00000000000000
--- a/browser_patches/chromium/archive.sh
+++ /dev/null
@@ -1,92 +0,0 @@
-#!/bin/bash
-set -e
-set +x
-
-trap "cd $(pwd -P)" EXIT
-cd "$(dirname "$0")"
-SCRIPT_PATH=$(pwd -P)
-source "${SCRIPT_PATH}/../utils.sh"
-
-if [[ ("$1" == "-h") || ("$1" == "--help") ]]; then
- echo "usage: $(basename "$0") [output-absolute-path]"
- echo
- echo "Generate distributable .zip archive from ./output folder that was previously downloaded."
- echo
- exit 0
-fi
-
-ZIP_PATH=$1
-
-if [[ $ZIP_PATH != /* ]]; then
- echo "ERROR: path $ZIP_PATH is not absolute"
- exit 1
-fi
-if [[ $ZIP_PATH != *.zip ]]; then
- echo "ERROR: path $ZIP_PATH must have .zip extension"
- exit 1
-fi
-if [[ -f $ZIP_PATH ]]; then
- echo "ERROR: path $ZIP_PATH exists; can't do anything."
- exit 1
-fi
-if ! [[ -d $(dirname "$ZIP_PATH") ]]; then
- echo "ERROR: folder for path $($ZIP_PATH) does not exist."
- exit 1
-fi
-
-if [[ -z "${CR_CHECKOUT_PATH}" ]]; then
- CR_CHECKOUT_PATH="$HOME/chromium"
-fi
-if [[ ! -d "${CR_CHECKOUT_PATH}/src" ]]; then
- echo "ERROR: CR_CHECKOUT_PATH does not have src/ subfolder; is this a chromium checkout?"
- exit 1
-fi
-
-CHROMIUM_FOLDER_NAME=""
-CHROMIUM_FILES_TO_ARCHIVE=()
-
-if is_mac; then
- CHROMIUM_FOLDER_NAME="chrome-mac"
- IFS=$'\n' CHROMIUM_FILES_TO_ARCHIVE=($(node "${SCRIPT_PATH}/compute_files_to_archive.js" "${CR_CHECKOUT_PATH}/src/infra/archive_config/mac-archive-rel.json"))
- unset IFS
-elif is_linux; then
- CHROMIUM_FOLDER_NAME="chrome-linux"
- IFS=$'\n' CHROMIUM_FILES_TO_ARCHIVE=($(node "${SCRIPT_PATH}/compute_files_to_archive.js" "${CR_CHECKOUT_PATH}/src/infra/archive_config/linux-archive-rel.json"))
- unset IFS
-elif is_win; then
- CHROMIUM_FOLDER_NAME="chrome-win"
- IFS=$'\n\r' CHROMIUM_FILES_TO_ARCHIVE=($(node "${SCRIPT_PATH}/compute_files_to_archive.js" "${CR_CHECKOUT_PATH}/src/infra/archive_config/win-archive-rel.json"))
- unset IFS
-else
- echo "ERROR: unsupported platform - $(uname)"
- exit 1
-fi
-
-# Prepare resulting archive.
-cd "$SCRIPT_PATH"
-rm -rf output
-mkdir -p "output/${CHROMIUM_FOLDER_NAME}"
-
-# On Mac, use 'ditto' to copy directories instead of 'cp'.
-COPY_COMMAND="cp -R"
-if is_mac; then
- COPY_COMMAND="ditto"
-fi
-
-for ((i = 0; i < ${#CHROMIUM_FILES_TO_ARCHIVE[@]}; i++)) do
- file="${CHROMIUM_FILES_TO_ARCHIVE[$i]}"
- mkdir -p "output/${CHROMIUM_FOLDER_NAME}/$(dirname "${file}")"
- $COPY_COMMAND "${CR_CHECKOUT_PATH}/src/out/Default/${file}" "output/${CHROMIUM_FOLDER_NAME}/${file}"
-done
-
-if is_win; then
- $COPY_COMMAND "${CR_CHECKOUT_PATH}/src/out/Default/"*.manifest "output/${CHROMIUM_FOLDER_NAME}/"
- mkdir -p "output/${CHROMIUM_FOLDER_NAME}/locales"
- $COPY_COMMAND "${CR_CHECKOUT_PATH}/src/out/Default/locales/"*.pak "output/${CHROMIUM_FOLDER_NAME}/locales/"
-fi
-
-cd output
-zip --symlinks -r build.zip "${CHROMIUM_FOLDER_NAME}"
-
-cd "${SCRIPT_PATH}"
-cp output/build.zip "$ZIP_PATH"
diff --git a/browser_patches/chromium/build.sh b/browser_patches/chromium/build.sh
deleted file mode 100755
index 521fb32e702ee9..00000000000000
--- a/browser_patches/chromium/build.sh
+++ /dev/null
@@ -1,130 +0,0 @@
-#!/bin/bash
-set -e
-set +x
-
-trap "cd $(pwd -P)" EXIT
-cd "$(dirname "$0")"
-SCRIPT_FOLDER=$(pwd -P)
-source "${SCRIPT_FOLDER}/../utils.sh"
-
-USAGE=$(cat<
-
- --arm64 cross-compile for arm64
- --symbols compile with symbols
- --full install build dependencies
- --goma use goma when compiling. Make sure to pre-start goma client beforehand with './goma.sh start'.
-
- On Linux & MacOS, it is possible to specify custom compilation targets:
-
- ./build.sh --goma blink_tests
-
-EOF
-)
-
-source "${SCRIPT_FOLDER}/../utils.sh"
-
-if [[ $1 == "--help" || $1 == "-h" ]]; then
- echo "$USAGE"
- exit 0
-fi
-
-args=("$@")
-IS_ARM64=""
-IS_SYMBOLS_BUILD=""
-IS_FULL=""
-USE_GOMA=""
-for ((i="${#args[@]}"-1; i >= 0; --i)); do
- case ${args[i]} in
- --arm64) IS_ARM64="1"; unset args[i]; ;;
- --symbols) IS_SYMBOLS_BUILD="1"; unset args[i]; ;;
- --full) IS_FULL="1"; unset args[i]; ;;
- --goma) USE_GOMA="1"; unset args[i]; ;;
- esac
-done
-
-compile_chromium() {
- if [[ -z "${CR_CHECKOUT_PATH}" ]]; then
- CR_CHECKOUT_PATH="$HOME/chromium"
- fi
-
- if [[ ! -d "${CR_CHECKOUT_PATH}/src" ]]; then
- echo "ERROR: CR_CHECKOUT_PATH does not have src/ subfolder; is this a chromium checkout?"
- exit 1
- fi
-
- source "${SCRIPT_FOLDER}/ensure_depot_tools.sh"
-
- if is_mac; then
- selectXcodeVersionOrDie $(node "${SCRIPT_FOLDER}/../get_xcode_version.js" chromium)
- fi
-
- cd "${CR_CHECKOUT_PATH}/src"
-
- # Prepare build folder.
- mkdir -p "./out/Default"
- echo "is_debug = false" > ./out/Default/args.gn
- echo "dcheck_always_on = false" >> ./out/Default/args.gn
- if [[ -n "${IS_SYMBOLS_BUILD}" ]]; then
- echo "symbol_level = 1" >> ./out/Default/args.gn
- else
- echo "symbol_level = 0" >> ./out/Default/args.gn
- fi
-
- if [[ -n "${IS_ARM64}" ]]; then
- echo 'target_cpu = "arm64"' >> ./out/Default/args.gn
- fi
-
- if [[ ! -z "$USE_GOMA" ]]; then
- "${SCRIPT_FOLDER}/goma.sh" args >> ./out/Default/args.gn
- fi
- echo 'enable_nacl = false' >> ./out/Default/args.gn
-
- echo "===== args.gn ====="
- cat ./out/Default/args.gn
- echo "===== ======= ====="
-
- if [[ -n "$IS_FULL" ]]; then
- if is_linux; then
- ./build/install-build-deps.sh
- if [[ -n "$IS_ARM64" ]]; then
- # Install sysroot image, see https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/linux/chromium_arm.md
- ./build/linux/sysroot_scripts/install-sysroot.py --arch=arm64
- fi
- fi
- fi
-
- TARGETS="${args[@]}"
- if is_win; then
- if [[ -n "$TARGETS" ]]; then
- echo "ERROR: cannot compile custom targets on windows yet."
- echo "Requested to compile chromium targets - ${TARGETS}"
- exit 1
- fi
- if [[ -z "$USE_GOMA" ]]; then
- /c/Windows/System32/cmd.exe "/c $(cygpath -w "${SCRIPT_FOLDER}"/buildwin.bat)"
- else
- /c/Windows/System32/cmd.exe "/c $(cygpath -w "${SCRIPT_FOLDER}"/buildwingoma.bat)"
- fi
- else
- if [[ -z "$TARGETS" ]]; then
- if is_linux; then
- TARGETS="chrome chrome_sandbox clear_key_cdm"
- else
- TARGETS="chrome"
- fi
- fi
- echo
- echo ">> Compiling Targets: $TARGETS"
- echo
-
- gn gen out/Default
- if [[ -z "$USE_GOMA" ]]; then
- autoninja -C out/Default $TARGETS
- else
- ninja -j 200 -C out/Default $TARGETS
- fi
- fi
-}
-
-compile_chromium "${args[@]}"
diff --git a/browser_patches/chromium/buildwin.bat b/browser_patches/chromium/buildwin.bat
deleted file mode 100644
index eec9a5c4129cca..00000000000000
--- a/browser_patches/chromium/buildwin.bat
+++ /dev/null
@@ -1,2 +0,0 @@
-CALL gn gen out/Default
-CALL autoninja -C out/Default chrome eventlog_provider
diff --git a/browser_patches/chromium/buildwingoma.bat b/browser_patches/chromium/buildwingoma.bat
deleted file mode 100644
index d834c5516fa6d7..00000000000000
--- a/browser_patches/chromium/buildwingoma.bat
+++ /dev/null
@@ -1,2 +0,0 @@
-CALL gn gen out/Default
-CALL ninja -j 200 -C out/Default chrome eventlog_provider
diff --git a/browser_patches/chromium/clean.sh b/browser_patches/chromium/clean.sh
deleted file mode 100755
index e03c7df33b76c0..00000000000000
--- a/browser_patches/chromium/clean.sh
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/bash
-set -e
-set +x
-
-trap "cd $(pwd -P)" EXIT
-cd "$(dirname "$0")"
-
-rm -rf output
-if [[ -z "${CR_CHECKOUT_PATH}" ]]; then
- CR_CHECKOUT_PATH="$HOME/chromium"
-fi
-
-if [[ -d "${CR_CHECKOUT_PATH}/src" ]]; then
- rm -rf "${CR_CHECKOUT_PATH}/src/out"
-fi
diff --git a/browser_patches/chromium/compute_files_to_archive.js b/browser_patches/chromium/compute_files_to_archive.js
deleted file mode 100644
index 341837bc1c8737..00000000000000
--- a/browser_patches/chromium/compute_files_to_archive.js
+++ /dev/null
@@ -1,26 +0,0 @@
-// This script is supposed to be run with a path to either of the following configs from chromium checkout:
-// - infra/archive_config/mac-archive-rel.json
-// - infra/archive_config/linux-archive-rel.json
-// - infra/archive_config/win-archive-rel.json
-
-const fs = require('fs');
-
-const configs = JSON.parse(fs.readFileSync(process.argv[2], 'utf8')).archive_datas;
-const config = configs.find(config => config.gcs_path.includes('chrome-linux.zip') || config.gcs_path.includes('chrome-win.zip') || config.gcs_path.includes('chrome-mac.zip'));
-
-const excludeList = new Set([
- // We do not need interactive tests in our archive.
- 'interactive_ui_tests.exe',
- // We no longer compile nacl with Chromium.
- 'nacl_helper_bootstrap',
- 'nacl_helper',
- 'nacl_irt_x86_64.nexe',
-]);
-
-const entries = [
- ...(config.files || []),
- ...(config.dirs || []),
-].filter(entry => !excludeList.has(entry));
-
-for (const entry of entries)
- console.log(entry);
diff --git a/browser_patches/chromium/ensure_depot_tools.sh b/browser_patches/chromium/ensure_depot_tools.sh
deleted file mode 100644
index c746fe53624715..00000000000000
--- a/browser_patches/chromium/ensure_depot_tools.sh
+++ /dev/null
@@ -1,32 +0,0 @@
-# Since this script modifies PATH, it cannot be run in a subshell
-# and must be sourced.
-# Make sure it is sourced.
-sourced=0
-(return 0 2>/dev/null) && sourced=1 || sourced=0
-
-if [[ $sourced == 0 ]]; then
- echo 'ERROR: cannot run this script in a subshell'
- echo 'This file modifies $PATH of the current shell, so it must be sourced instead'
- echo 'Use `source ensure_depot_tool.sh` instead'
- exit 1
-fi
-
-function ensure_depot_tools() {
- # Install depot_tools if they are not in system, and modify $PATH
- # to include depot_tools
- if ! command -v autoninja >/dev/null; then
- if [[ $(uname) == "MINGW"* || "$(uname)" == MSYS* ]]; then
- # NOTE: as of Feb 8, 2021, windows requires manual and separate
- # installation of depot_tools.
- echo "ERROR: cannot automatically install depot_tools on windows. Please, install manually"
- exit 1
- fi
- local SCRIPT_PATH=$(cd "$(dirname "$BASH_SOURCE")"; pwd -P)
- if [[ ! -d "${SCRIPT_PATH}/depot_tools" ]]; then
- git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "${SCRIPT_PATH}/depot_tools"
- fi
- export PATH="${SCRIPT_PATH}/depot_tools:$PATH"
- fi
-}
-
-ensure_depot_tools
diff --git a/browser_patches/chromium/goma.sh b/browser_patches/chromium/goma.sh
deleted file mode 100755
index 8e2ff8649b2264..00000000000000
--- a/browser_patches/chromium/goma.sh
+++ /dev/null
@@ -1,105 +0,0 @@
-#!/bin/bash
-set -e
-set +x
-
-trap "cd $(pwd -P)" EXIT
-cd "$(dirname "$0")"
-SCRIPT_FOLDER=$(pwd -P)
-source "${SCRIPT_FOLDER}/../utils.sh"
-
-ELECTRON_BUILD_TOOLS_REQUIRED_VERSION=2c24fb5c7c938a4e387f355ab64be449604ae5db
-if [[ -d ./electron-build-tools ]]; then
- cd ./electron-build-tools
- # Make sure required commit is part of electron-build-tools.
- if ! git merge-base --is-ancestor "${ELECTRON_BUILD_TOOLS_REQUIRED_VERSION}" HEAD; then
- cd ..
- rm -rf ./electron-build-tools
- echo "Updating electron-build-tools"
- else
- cd ..
- fi
-fi
-
-if [[ ! -d ./electron-build-tools ]]; then
- git clone --single-branch --branch main https://github.com/electron/build-tools/ electron-build-tools
- cd electron-build-tools
- npm install
- mkdir -p third_party
- ./src/e update-goma msftGoma
- cd ..
-fi
-
-if ! is_win; then
- if command -v python >/dev/null; then
- PYTHON=python
- elif command -v python3 >/dev/null; then
- PYTHON=python3
- else
- echo "ERROR: no python or python3 found in PATH"
- exit 1
- fi
-fi
-
-cd electron-build-tools/third_party/goma
-
-export GOMA_START_COMPILER_PROXY=true
-
-function print_gn_args() {
- PLAYWRIGHT_GOMA_PATH="${SCRIPT_FOLDER}/electron-build-tools/third_party/goma"
- if is_win; then
- PLAYWRIGHT_GOMA_PATH=$(cygpath -w "${PLAYWRIGHT_GOMA_PATH}")
- fi
- echo 'use_goma = true'
- echo "goma_dir = \"${PLAYWRIGHT_GOMA_PATH}\""
-}
-
-if [[ $1 == "--help" ]]; then
- echo "$(basename "$0") [login|start|stop|--help]"
- exit 0
-elif [[ $1 == "args" ]]; then
- print_gn_args
-elif [[ $1 == "login" ]]; then
- if is_win; then
- /c/Windows/System32/cmd.exe "/c $(cygpath -w $(pwd)/goma_auth.bat) login"
- else
- $PYTHON ./goma_auth.py login
- fi
- echo
- echo "Congratulation! Goma is logged in!"
- echo "run '$(basename "$0") start' to launch goma client"
-elif [[ $1 == "start" ]]; then
- # We have to prefix ENV with `PLAYWRIGHT` since `GOMA_` env variables
- # have special treatment by goma.
- if [[ ! -z "$PLAYWRIGHT_GOMA_LOGIN_COOKIE" ]]; then
- echo "$PLAYWRIGHT_GOMA_LOGIN_COOKIE" > "$HOME/.goma_oauth2_config"
- fi
- if [[ ! -f "$HOME/.goma_oauth2_config" ]]; then
- echo "ERROR: goma is not logged in!"
- echo "run '$(basename "$0") login'"
- exit 1
- fi
- if is_win; then
- /c/Windows/System32/cmd.exe "/c $(cygpath -w $(pwd)/goma_ctl.bat) ensure_start"
- else
- $PYTHON ./goma_ctl.py ensure_start
- fi
- set +x
- echo
- echo "Congratulatons! Goma is running!"
- echo
- echo "Add the following gn args to use goma:"
- echo
- echo "===== args.gn ====="
- print_gn_args
- echo "===== ======= ====="
-elif [[ $1 == "stop" ]]; then
- if is_win; then
- /c/Windows/System32/cmd.exe "/c $(cygpath -w $(pwd)/goma_ctl.bat) stop"
- else
- $PYTHON ./goma_ctl.py stop
- fi
-else
- echo "ERROR: unknown command - $1"
- echo "Use --help to list all available commands"
- exit 1
-fi
diff --git a/browser_patches/chromium/roll_to_current_beta.sh b/browser_patches/chromium/roll_to_current_beta.sh
deleted file mode 100755
index 7b1c7d6e04ea42..00000000000000
--- a/browser_patches/chromium/roll_to_current_beta.sh
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/bin/bash
-set -e
-set +x
-
-trap "cd $(pwd -P)" EXIT
-cd "$(dirname "$0")"
-SCRIPT_FOLDER=$(pwd -P)
-
-# 1. get current version
-CURRENT_BETA_VERSION=$(curl https://omahaproxy.appspot.com/all | grep "win64,beta" | cut -d ',' -f 3)
-VERSION_INFO_JSON=$(curl "https://omahaproxy.appspot.com/deps.json?version=$CURRENT_BETA_VERSION")
-
-NODE_SCRIPT=$(cat < "${SCRIPT_FOLDER}/UPSTREAM_CONFIG.sh"
-BUILD_NUMBER=$(cat "${SCRIPT_FOLDER}/BUILD_NUMBER")
-echo $(( $BUILD_NUMBER + 1 )) > "${SCRIPT_FOLDER}/BUILD_NUMBER"
diff --git a/browser_patches/clean.sh b/browser_patches/clean.sh
deleted file mode 100755
index b6a2cfe1da8d91..00000000000000
--- a/browser_patches/clean.sh
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/bin/bash
-set -e
-set +x
-
-trap "cd $(pwd -P)" EXIT
-cd "$(dirname "$0")"
-
-
-if [[ ($1 == '--help') || ($1 == '-h') ]]; then
- echo "usage: clean.sh [firefox|webkit|firefox-beta]"
- echo
- exit 0
-fi
-
-if [[ $# == 0 ]]; then
- echo "missing browser: 'firefox' or 'webkit'"
- echo "try './clean.sh --help' for more information"
- exit 1
-fi
-
-CMD="$1"
-shift
-if [[ ("$CMD" == "firefox") || ("$CMD" == "firefox/") || ("$CMD" == "ff") ]]; then
- bash ./firefox/clean.sh "$@"
-elif [[ ("$CMD" == "firefox-beta") || ("$CMD" == "ff-beta") ]]; then
- bash ./firefox-beta/clean.sh "$@"
-elif [[ ("$CMD" == "webkit") || ("$CMD" == "webkit/") || ("$CMD" == "wk") ]]; then
- bash ./webkit/clean.sh "$@"
-elif [[ ("$CMD" == "chromium") || ("$CMD" == "chromium/") || ("$CMD" == "cr") ]]; then
- bash ./chromium/clean.sh "$@"
-elif [[ ("$CMD" == "winldd") ]]; then
- bash ./winldd/clean.sh "$@"
-elif [[ ("$CMD" == "ffmpeg") ]]; then
- bash ./ffmpeg/clean.sh "$@"
-else
- echo ERROR: unknown browser to build - "$CMD"
- exit 1
-fi
-
diff --git a/browser_patches/docker/cli.sh b/browser_patches/docker/cli.sh
deleted file mode 100755
index 1904ebad7e55f9..00000000000000
--- a/browser_patches/docker/cli.sh
+++ /dev/null
@@ -1,98 +0,0 @@
-#!/bin/bash
-# This script is designed to build Firefox & WebKit on various Linux
-# distributions inside docker containers.
-set -e
-set +x
-set -o pipefail
-
-if [[ ($1 == '--help') || ($1 == '-h') ]]; then
- echo "usage: $(basename "$0") [webkit-ubuntu-20.04|firefox-debian-11|...] [build|test|compile|enter|cleanup]"
- echo
- echo "Builds Webkit or Firefox browser inside given Linux distribution"
- exit 0
-fi
-
-trap "cd $(pwd -P)" EXIT
-cd "$(dirname "$0")"
-SCRIPT_FOLDER="$(pwd -P)"
-
-export BUILD_FLAVOR="${1}"
-export BROWSER_NAME=""
-
-DOCKERFILE=""
-
-if [[ "${BUILD_FLAVOR}" == "firefox-beta-"* ]]; then
- DOCKERFILE="${SCRIPT_FOLDER}/firefox-beta/${BUILD_FLAVOR#firefox-beta-}.dockerfile"
- BROWSER_NAME="firefox-beta"
-elif [[ "${BUILD_FLAVOR}" == "firefox-"* ]]; then
- DOCKERFILE="${SCRIPT_FOLDER}/firefox/${BUILD_FLAVOR#firefox-}.dockerfile"
- BROWSER_NAME="firefox"
-elif [[ "${BUILD_FLAVOR}" == "webkit-"* ]]; then
- DOCKERFILE="${SCRIPT_FOLDER}/webkit/${BUILD_FLAVOR#webkit-}.dockerfile"
- BROWSER_NAME="webkit"
-else
- echo "ERROR: unknown build flavor - ${BUILD_FLAVOR}"
- exit 1
-fi
-
-if [[ "${BUILD_FLAVOR}" == *"-arm64" ]]; then
- EXPECTED_ARCH="arm64"
- DOCKER_PLATFORM="linux/arm64"
-else
- EXPECTED_ARCH="x86_64"
- DOCKER_PLATFORM="linux/amd64"
-fi
-
-if [[ $(arch) != "${EXPECTED_ARCH}" ]]; then
- echo "ERROR: host architecture $(arch) does not match expected architecture - ${EXPECTED_ARCH}"
- exit 1
-fi
-
-DOCKER_IMAGE_NAME="${BUILD_FLAVOR}"
-DOCKER_CONTAINER_NAME="${BUILD_FLAVOR}"
-DOCKER_ARGS=$(echo \
- --env CI \
- --env BUILD_FLAVOR \
- --env BROWSER_NAME \
- --env TELEGRAM_BOT_KEY \
- --env AZ_ACCOUNT_NAME \
- --env AZ_ACCOUNT_KEY \
- --env GITHUB_SERVER_URL \
- --env GITHUB_REPOSITORY \
- --env GITHUB_RUN_ID \
- --env GH_TOKEN \
- --env DEBIAN_FRONTEND=noninteractive \
- --env TZ="America/Los_Angeles"
-)
-
-if [[ "$2" == "build" ]]; then
- docker build \
- --build-arg ARG_BUILD_FLAVOR="${BUILD_FLAVOR}" \
- --build-arg ARG_BROWSER_NAME="${BROWSER_NAME}" \
- --no-cache \
- --platform "${DOCKER_PLATFORM}" \
- -t "${DOCKER_IMAGE_NAME}" \
- -f "${DOCKERFILE}" .
-elif [[ "$2" == "test" ]]; then
- docker run --rm ${DOCKER_ARGS} --init --name "${DOCKER_CONTAINER_NAME}" --platform "${DOCKER_PLATFORM}" -it "${DOCKER_IMAGE_NAME}" /bin/bash -c '
- CI=1 ./browser_patches/prepare_checkout.sh "${BROWSER_NAME}"
- ./browser_patches/build.sh "${BROWSER_NAME}" --full
- ./browser_patches/${BROWSER_NAME}/archive.sh $PWD/archive.zip
- '
-elif [[ "$2" == "compile" ]]; then
- docker run --rm ${DOCKER_ARGS} --init --name "${DOCKER_CONTAINER_NAME}" --platform "${DOCKER_PLATFORM}" -t "${DOCKER_IMAGE_NAME}" /bin/bash -c '
- ./browser_patches/checkout_build_archive_upload.sh "${BUILD_FLAVOR}"
- '
-elif [[ "$2" == "enter" ]]; then
- docker run --rm ${DOCKER_ARGS} --init --name "${DOCKER_CONTAINER_NAME}" --platform "${DOCKER_PLATFORM}" -it "${DOCKER_IMAGE_NAME}" /bin/bash
-elif [[ "$2" == "cleanup" ]]; then
- docker kill "${DOCKER_CONTAINER_NAME}" || true
- # Wait for container to stop
- docker wait "${DOCKER_CONTAINER_NAME}" || true
- docker rmi "${DOCKER_IMAGE_NAME}"
- docker system prune -f
-else
- echo "ERROR: unknown command - $2"
- exit 1
-fi
-
diff --git a/browser_patches/docker/firefox-beta/debian-11.dockerfile b/browser_patches/docker/firefox-beta/debian-11.dockerfile
deleted file mode 100644
index 714e0f3860341a..00000000000000
--- a/browser_patches/docker/firefox-beta/debian-11.dockerfile
+++ /dev/null
@@ -1,54 +0,0 @@
-FROM --platform=linux/amd64 debian:11
-
-# Reexport --build-arg as environment variables
-ARG ARG_BUILD_FLAVOR
-ARG ARG_BROWSER_NAME
-ENV BUILD_FLAVOR="${ARG_BUILD_FLAVOR}"
-ENV BROWSER_NAME="${ARG_BROWSER_NAME}"
-
-# These are needed to auto-install tzdata. See https://serverfault.com/questions/949991/how-to-install-tzdata-on-a-ubuntu-docker-image
-ARG DEBIAN_FRONTEND=noninteractive
-ARG TZ=America/Los_Angeles
-
-RUN apt-get update && apt-get install -y curl \
- build-essential \
- git-core \
- zip unzip \
- tzdata \
- sudo
-# Install Python3 with distutils
-RUN apt-get install -y python3 python3-dev python3-pip python3-distutils
-
-# Install Azure CLI
-RUN curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
-
-# Install node16
-RUN curl -sL https://deb.nodesource.com/setup_16.x | bash - && apt-get install -y nodejs
-
-# Create the pwuser and make it passwordless sudoer.
-RUN adduser --disabled-password --gecos "" pwuser && \
- echo "ALL ALL = (ALL) NOPASSWD: ALL" >> /etc/sudoers
-
-# mitigate git clone issues on CI
-# See https://stdworkflow.com/877/error-rpc-failed-curl-56-gnutls-recv-error-54-error-in-the-pull-function
-RUN git config --system user.email "devops@playwright.dev" && \
- git config --system user.name "Playwright DevOps" && \
- git config --system http.postBuffer 524288000 && \
- git config --system http.lowSpeedLimit 0 && \
- git config --system http.lowSpeedTime 999999
-
-# Show welcome message to pwuser
-COPY --chown=pwuser ./pwuser_bashrc /home/pwuser/.bashrc
-
-USER pwuser
-
-# Install Rust
-RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
-ENV PATH="${PATH}:/home/pwuser/.cargo/bin"
-
-RUN mkdir -p /home/pwuser/.mozbuild
-RUN cd /home/pwuser && git clone --depth=1 https://github.com/microsoft/playwright
-
-WORKDIR /home/pwuser/playwright
-
-
diff --git a/browser_patches/docker/firefox-beta/ubuntu-18.04.dockerfile b/browser_patches/docker/firefox-beta/ubuntu-18.04.dockerfile
deleted file mode 100644
index b329797466893c..00000000000000
--- a/browser_patches/docker/firefox-beta/ubuntu-18.04.dockerfile
+++ /dev/null
@@ -1,60 +0,0 @@
-FROM --platform=linux/amd64 ubuntu:18.04
-
-# Reexport --build-arg as environment variables
-ARG ARG_BUILD_FLAVOR
-ARG ARG_BROWSER_NAME
-ENV BUILD_FLAVOR="${ARG_BUILD_FLAVOR}"
-ENV BROWSER_NAME="${ARG_BROWSER_NAME}"
-
-# These are needed to auto-install tzdata. See https://serverfault.com/questions/949991/how-to-install-tzdata-on-a-ubuntu-docker-image
-ARG DEBIAN_FRONTEND=noninteractive
-ARG TZ=America/Los_Angeles
-
-RUN apt-get update && apt-get install -y curl \
- build-essential \
- git-core \
- zip unzip \
- tzdata \
- sudo
-# Install Python3 with distutils
-# Firefox build on Ubuntu 18.04 requires Python3.8 to run its build scripts.
-RUN apt-get install -y python3.8 python3.8-dev python3.8-distutils && \
- # Point python3 to python3.8
- update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.8 2 && \
- curl -sSL https://bootstrap.pypa.io/get-pip.py -o get-pip.py && \
- python3 get-pip.py && \
- rm get-pip.py
-
-# Install Azure CLI
-RUN curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
-
-# Install node16
-RUN curl -sL https://deb.nodesource.com/setup_16.x | bash - && apt-get install -y nodejs
-
-# Create the pwuser and make it passwordless sudoer.
-RUN adduser --disabled-password --gecos "" pwuser && \
- echo "ALL ALL = (ALL) NOPASSWD: ALL" >> /etc/sudoers
-
-# mitigate git clone issues on CI
-# See https://stdworkflow.com/877/error-rpc-failed-curl-56-gnutls-recv-error-54-error-in-the-pull-function
-RUN git config --system user.email "devops@playwright.dev" && \
- git config --system user.name "Playwright DevOps" && \
- git config --system http.postBuffer 524288000 && \
- git config --system http.lowSpeedLimit 0 && \
- git config --system http.lowSpeedTime 999999
-
-# Show welcome message to pwuser
-COPY --chown=pwuser ./pwuser_bashrc /home/pwuser/.bashrc
-
-USER pwuser
-
-# Install Rust
-RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
-ENV PATH="${PATH}:/home/pwuser/.cargo/bin"
-
-RUN mkdir -p /home/pwuser/.mozbuild
-RUN cd /home/pwuser && git clone --depth=1 https://github.com/microsoft/playwright
-
-WORKDIR /home/pwuser/playwright
-
-
diff --git a/browser_patches/docker/firefox-beta/ubuntu-20.04-arm64.dockerfile b/browser_patches/docker/firefox-beta/ubuntu-20.04-arm64.dockerfile
deleted file mode 100644
index 8528f52ac21e09..00000000000000
--- a/browser_patches/docker/firefox-beta/ubuntu-20.04-arm64.dockerfile
+++ /dev/null
@@ -1,62 +0,0 @@
-FROM --platform=linux/arm64 ubuntu:20.04
-
-# Reexport --build-arg as environment variables
-ARG ARG_BUILD_FLAVOR
-ARG ARG_BROWSER_NAME
-ENV BUILD_FLAVOR="${ARG_BUILD_FLAVOR}"
-ENV BROWSER_NAME="${ARG_BROWSER_NAME}"
-
-# These are needed to auto-install tzdata. See https://serverfault.com/questions/949991/how-to-install-tzdata-on-a-ubuntu-docker-image
-ARG DEBIAN_FRONTEND=noninteractive
-ARG TZ=America/Los_Angeles
-
-RUN apt-get update && apt-get install -y curl \
- build-essential \
- git-core \
- zip unzip \
- tzdata \
- sudo
-
-# Ubuntu 20.04 aarch64 specific: default to clang-12.
-RUN apt-get install -y clang-12
-ENV CC=/usr/bin/clang-12
-ENV CXX=/usr/bin/clang++-12
-
-# Install Python3 with distutils
-RUN apt-get install -y python3 python3-dev python3-pip python3-distutils
-
-# Install AZ CLI with Python since they do not ship
-# aarch64 to APT: https://github.com/Azure/azure-cli/issues/7368
-# Pin so future releases do not break us.
-RUN pip3 install azure-cli==2.38.0
-
-# Install node16
-RUN curl -sL https://deb.nodesource.com/setup_16.x | bash - && apt-get install -y nodejs
-
-# Create the pwuser and make it passwordless sudoer.
-RUN adduser --disabled-password --gecos "" pwuser && \
- echo "ALL ALL = (ALL) NOPASSWD: ALL" >> /etc/sudoers
-
-# mitigate git clone issues on CI
-# See https://stdworkflow.com/877/error-rpc-failed-curl-56-gnutls-recv-error-54-error-in-the-pull-function
-RUN git config --system user.email "devops@playwright.dev" && \
- git config --system user.name "Playwright DevOps" && \
- git config --system http.postBuffer 524288000 && \
- git config --system http.lowSpeedLimit 0 && \
- git config --system http.lowSpeedTime 999999
-
-# Show welcome message to pwuser
-COPY --chown=pwuser ./pwuser_bashrc /home/pwuser/.bashrc
-
-USER pwuser
-
-# Install Rust
-RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
-ENV PATH="${PATH}:/home/pwuser/.cargo/bin"
-
-RUN mkdir -p /home/pwuser/.mozbuild
-RUN cd /home/pwuser && git clone --depth=1 https://github.com/microsoft/playwright
-
-WORKDIR /home/pwuser/playwright
-
-
diff --git a/browser_patches/docker/firefox-beta/ubuntu-20.04.dockerfile b/browser_patches/docker/firefox-beta/ubuntu-20.04.dockerfile
deleted file mode 100644
index d6dcbab630bf39..00000000000000
--- a/browser_patches/docker/firefox-beta/ubuntu-20.04.dockerfile
+++ /dev/null
@@ -1,54 +0,0 @@
-FROM --platform=linux/amd64 ubuntu:20.04
-
-# Reexport --build-arg as environment variables
-ARG ARG_BUILD_FLAVOR
-ARG ARG_BROWSER_NAME
-ENV BUILD_FLAVOR="${ARG_BUILD_FLAVOR}"
-ENV BROWSER_NAME="${ARG_BROWSER_NAME}"
-
-# These are needed to auto-install tzdata. See https://serverfault.com/questions/949991/how-to-install-tzdata-on-a-ubuntu-docker-image
-ARG DEBIAN_FRONTEND=noninteractive
-ARG TZ=America/Los_Angeles
-
-RUN apt-get update && apt-get install -y curl \
- build-essential \
- git-core \
- zip unzip \
- tzdata \
- sudo
-# Install Python3 with distutils
-RUN apt-get install -y python3 python3-dev python3-pip python3-distutils
-
-# Install Azure CLI
-RUN curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
-
-# Install node16
-RUN curl -sL https://deb.nodesource.com/setup_16.x | bash - && apt-get install -y nodejs
-
-# Create the pwuser and make it passwordless sudoer.
-RUN adduser --disabled-password --gecos "" pwuser && \
- echo "ALL ALL = (ALL) NOPASSWD: ALL" >> /etc/sudoers
-
-# mitigate git clone issues on CI
-# See https://stdworkflow.com/877/error-rpc-failed-curl-56-gnutls-recv-error-54-error-in-the-pull-function
-RUN git config --system user.email "devops@playwright.dev" && \
- git config --system user.name "Playwright DevOps" && \
- git config --system http.postBuffer 524288000 && \
- git config --system http.lowSpeedLimit 0 && \
- git config --system http.lowSpeedTime 999999
-
-# Show welcome message to pwuser
-COPY --chown=pwuser ./pwuser_bashrc /home/pwuser/.bashrc
-
-USER pwuser
-
-# Install Rust
-RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
-ENV PATH="${PATH}:/home/pwuser/.cargo/bin"
-
-RUN mkdir -p /home/pwuser/.mozbuild
-RUN cd /home/pwuser && git clone --depth=1 https://github.com/microsoft/playwright
-
-WORKDIR /home/pwuser/playwright
-
-
diff --git a/browser_patches/docker/firefox-beta/ubuntu-22.04-arm64.dockerfile b/browser_patches/docker/firefox-beta/ubuntu-22.04-arm64.dockerfile
deleted file mode 100644
index 768e956b0960f7..00000000000000
--- a/browser_patches/docker/firefox-beta/ubuntu-22.04-arm64.dockerfile
+++ /dev/null
@@ -1,62 +0,0 @@
-FROM --platform=linux/arm64 ubuntu:22.04
-
-# Reexport --build-arg as environment variables
-ARG ARG_BUILD_FLAVOR
-ARG ARG_BROWSER_NAME
-ENV BUILD_FLAVOR="${ARG_BUILD_FLAVOR}"
-ENV BROWSER_NAME="${ARG_BROWSER_NAME}"
-
-# These are needed to auto-install tzdata. See https://serverfault.com/questions/949991/how-to-install-tzdata-on-a-ubuntu-docker-image
-ARG DEBIAN_FRONTEND=noninteractive
-ARG TZ=America/Los_Angeles
-
-RUN apt-get update && apt-get install -y curl \
- build-essential \
- git-core \
- zip unzip \
- tzdata \
- sudo
-
-# Ubuntu 22.04 aarch64 specific: default to clang-14.
-RUN apt-get install -y clang-14
-ENV CC=/usr/bin/clang-14
-ENV CXX=/usr/bin/clang++-14
-
-# Install Python3 with distutils
-RUN apt-get install -y python3 python3-dev python3-pip python3-distutils
-
-# Install AZ CLI with Python since they do not ship
-# aarch64 to APT: https://github.com/Azure/azure-cli/issues/7368
-# Pin so future releases do not break us.
-RUN pip3 install azure-cli==2.38.0
-
-# Install node16
-RUN curl -sL https://deb.nodesource.com/setup_16.x | bash - && apt-get install -y nodejs
-
-# Create the pwuser and make it passwordless sudoer.
-RUN adduser --disabled-password --gecos "" pwuser && \
- echo "ALL ALL = (ALL) NOPASSWD: ALL" >> /etc/sudoers
-
-# mitigate git clone issues on CI
-# See https://stdworkflow.com/877/error-rpc-failed-curl-56-gnutls-recv-error-54-error-in-the-pull-function
-RUN git config --system user.email "devops@playwright.dev" && \
- git config --system user.name "Playwright DevOps" && \
- git config --system http.postBuffer 524288000 && \
- git config --system http.lowSpeedLimit 0 && \
- git config --system http.lowSpeedTime 999999
-
-# Show welcome message to pwuser
-COPY --chown=pwuser ./pwuser_bashrc /home/pwuser/.bashrc
-
-USER pwuser
-
-# Install Rust
-RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
-ENV PATH="${PATH}:/home/pwuser/.cargo/bin"
-
-RUN mkdir -p /home/pwuser/.mozbuild
-RUN cd /home/pwuser && git clone --depth=1 https://github.com/microsoft/playwright
-
-WORKDIR /home/pwuser/playwright
-
-
diff --git a/browser_patches/docker/firefox-beta/ubuntu-22.04.dockerfile b/browser_patches/docker/firefox-beta/ubuntu-22.04.dockerfile
deleted file mode 100644
index 348ef04af3e033..00000000000000
--- a/browser_patches/docker/firefox-beta/ubuntu-22.04.dockerfile
+++ /dev/null
@@ -1,54 +0,0 @@
-FROM --platform=linux/amd64 ubuntu:22.04
-
-# Reexport --build-arg as environment variables
-ARG ARG_BUILD_FLAVOR
-ARG ARG_BROWSER_NAME
-ENV BUILD_FLAVOR="${ARG_BUILD_FLAVOR}"
-ENV BROWSER_NAME="${ARG_BROWSER_NAME}"
-
-# These are needed to auto-install tzdata. See https://serverfault.com/questions/949991/how-to-install-tzdata-on-a-ubuntu-docker-image
-ARG DEBIAN_FRONTEND=noninteractive
-ARG TZ=America/Los_Angeles
-
-RUN apt-get update && apt-get install -y curl \
- build-essential \
- git-core \
- zip unzip \
- tzdata \
- sudo
-# Install Python3 with distutils
-RUN apt-get install -y python3 python3-dev python3-pip python3-distutils
-
-# Install Azure CLI
-RUN curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
-
-# Install node16
-RUN curl -sL https://deb.nodesource.com/setup_16.x | bash - && apt-get install -y nodejs
-
-# Create the pwuser and make it passwordless sudoer.
-RUN adduser --disabled-password --gecos "" pwuser && \
- echo "ALL ALL = (ALL) NOPASSWD: ALL" >> /etc/sudoers
-
-# mitigate git clone issues on CI
-# See https://stdworkflow.com/877/error-rpc-failed-curl-56-gnutls-recv-error-54-error-in-the-pull-function
-RUN git config --system user.email "devops@playwright.dev" && \
- git config --system user.name "Playwright DevOps" && \
- git config --system http.postBuffer 524288000 && \
- git config --system http.lowSpeedLimit 0 && \
- git config --system http.lowSpeedTime 999999
-
-# Show welcome message to pwuser
-COPY --chown=pwuser ./pwuser_bashrc /home/pwuser/.bashrc
-
-USER pwuser
-
-# Install Rust
-RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
-ENV PATH="${PATH}:/home/pwuser/.cargo/bin"
-
-RUN mkdir -p /home/pwuser/.mozbuild
-RUN cd /home/pwuser && git clone --depth=1 https://github.com/microsoft/playwright
-
-WORKDIR /home/pwuser/playwright
-
-
diff --git a/browser_patches/docker/firefox/debian-11.dockerfile b/browser_patches/docker/firefox/debian-11.dockerfile
deleted file mode 100644
index 714e0f3860341a..00000000000000
--- a/browser_patches/docker/firefox/debian-11.dockerfile
+++ /dev/null
@@ -1,54 +0,0 @@
-FROM --platform=linux/amd64 debian:11
-
-# Reexport --build-arg as environment variables
-ARG ARG_BUILD_FLAVOR
-ARG ARG_BROWSER_NAME
-ENV BUILD_FLAVOR="${ARG_BUILD_FLAVOR}"
-ENV BROWSER_NAME="${ARG_BROWSER_NAME}"
-
-# These are needed to auto-install tzdata. See https://serverfault.com/questions/949991/how-to-install-tzdata-on-a-ubuntu-docker-image
-ARG DEBIAN_FRONTEND=noninteractive
-ARG TZ=America/Los_Angeles
-
-RUN apt-get update && apt-get install -y curl \
- build-essential \
- git-core \
- zip unzip \
- tzdata \
- sudo
-# Install Python3 with distutils
-RUN apt-get install -y python3 python3-dev python3-pip python3-distutils
-
-# Install Azure CLI
-RUN curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
-
-# Install node16
-RUN curl -sL https://deb.nodesource.com/setup_16.x | bash - && apt-get install -y nodejs
-
-# Create the pwuser and make it passwordless sudoer.
-RUN adduser --disabled-password --gecos "" pwuser && \
- echo "ALL ALL = (ALL) NOPASSWD: ALL" >> /etc/sudoers
-
-# mitigate git clone issues on CI
-# See https://stdworkflow.com/877/error-rpc-failed-curl-56-gnutls-recv-error-54-error-in-the-pull-function
-RUN git config --system user.email "devops@playwright.dev" && \
- git config --system user.name "Playwright DevOps" && \
- git config --system http.postBuffer 524288000 && \
- git config --system http.lowSpeedLimit 0 && \
- git config --system http.lowSpeedTime 999999
-
-# Show welcome message to pwuser
-COPY --chown=pwuser ./pwuser_bashrc /home/pwuser/.bashrc
-
-USER pwuser
-
-# Install Rust
-RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
-ENV PATH="${PATH}:/home/pwuser/.cargo/bin"
-
-RUN mkdir -p /home/pwuser/.mozbuild
-RUN cd /home/pwuser && git clone --depth=1 https://github.com/microsoft/playwright
-
-WORKDIR /home/pwuser/playwright
-
-
diff --git a/browser_patches/docker/firefox/ubuntu-18.04.dockerfile b/browser_patches/docker/firefox/ubuntu-18.04.dockerfile
deleted file mode 100644
index b329797466893c..00000000000000
--- a/browser_patches/docker/firefox/ubuntu-18.04.dockerfile
+++ /dev/null
@@ -1,60 +0,0 @@
-FROM --platform=linux/amd64 ubuntu:18.04
-
-# Reexport --build-arg as environment variables
-ARG ARG_BUILD_FLAVOR
-ARG ARG_BROWSER_NAME
-ENV BUILD_FLAVOR="${ARG_BUILD_FLAVOR}"
-ENV BROWSER_NAME="${ARG_BROWSER_NAME}"
-
-# These are needed to auto-install tzdata. See https://serverfault.com/questions/949991/how-to-install-tzdata-on-a-ubuntu-docker-image
-ARG DEBIAN_FRONTEND=noninteractive
-ARG TZ=America/Los_Angeles
-
-RUN apt-get update && apt-get install -y curl \
- build-essential \
- git-core \
- zip unzip \
- tzdata \
- sudo
-# Install Python3 with distutils
-# Firefox build on Ubuntu 18.04 requires Python3.8 to run its build scripts.
-RUN apt-get install -y python3.8 python3.8-dev python3.8-distutils && \
- # Point python3 to python3.8
- update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.8 2 && \
- curl -sSL https://bootstrap.pypa.io/get-pip.py -o get-pip.py && \
- python3 get-pip.py && \
- rm get-pip.py
-
-# Install Azure CLI
-RUN curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
-
-# Install node16
-RUN curl -sL https://deb.nodesource.com/setup_16.x | bash - && apt-get install -y nodejs
-
-# Create the pwuser and make it passwordless sudoer.
-RUN adduser --disabled-password --gecos "" pwuser && \
- echo "ALL ALL = (ALL) NOPASSWD: ALL" >> /etc/sudoers
-
-# mitigate git clone issues on CI
-# See https://stdworkflow.com/877/error-rpc-failed-curl-56-gnutls-recv-error-54-error-in-the-pull-function
-RUN git config --system user.email "devops@playwright.dev" && \
- git config --system user.name "Playwright DevOps" && \
- git config --system http.postBuffer 524288000 && \
- git config --system http.lowSpeedLimit 0 && \
- git config --system http.lowSpeedTime 999999
-
-# Show welcome message to pwuser
-COPY --chown=pwuser ./pwuser_bashrc /home/pwuser/.bashrc
-
-USER pwuser
-
-# Install Rust
-RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
-ENV PATH="${PATH}:/home/pwuser/.cargo/bin"
-
-RUN mkdir -p /home/pwuser/.mozbuild
-RUN cd /home/pwuser && git clone --depth=1 https://github.com/microsoft/playwright
-
-WORKDIR /home/pwuser/playwright
-
-
diff --git a/browser_patches/docker/firefox/ubuntu-20.04-arm64.dockerfile b/browser_patches/docker/firefox/ubuntu-20.04-arm64.dockerfile
deleted file mode 100644
index 8528f52ac21e09..00000000000000
--- a/browser_patches/docker/firefox/ubuntu-20.04-arm64.dockerfile
+++ /dev/null
@@ -1,62 +0,0 @@
-FROM --platform=linux/arm64 ubuntu:20.04
-
-# Reexport --build-arg as environment variables
-ARG ARG_BUILD_FLAVOR
-ARG ARG_BROWSER_NAME
-ENV BUILD_FLAVOR="${ARG_BUILD_FLAVOR}"
-ENV BROWSER_NAME="${ARG_BROWSER_NAME}"
-
-# These are needed to auto-install tzdata. See https://serverfault.com/questions/949991/how-to-install-tzdata-on-a-ubuntu-docker-image
-ARG DEBIAN_FRONTEND=noninteractive
-ARG TZ=America/Los_Angeles
-
-RUN apt-get update && apt-get install -y curl \
- build-essential \
- git-core \
- zip unzip \
- tzdata \
- sudo
-
-# Ubuntu 20.04 aarch64 specific: default to clang-12.
-RUN apt-get install -y clang-12
-ENV CC=/usr/bin/clang-12
-ENV CXX=/usr/bin/clang++-12
-
-# Install Python3 with distutils
-RUN apt-get install -y python3 python3-dev python3-pip python3-distutils
-
-# Install AZ CLI with Python since they do not ship
-# aarch64 to APT: https://github.com/Azure/azure-cli/issues/7368
-# Pin so future releases do not break us.
-RUN pip3 install azure-cli==2.38.0
-
-# Install node16
-RUN curl -sL https://deb.nodesource.com/setup_16.x | bash - && apt-get install -y nodejs
-
-# Create the pwuser and make it passwordless sudoer.
-RUN adduser --disabled-password --gecos "" pwuser && \
- echo "ALL ALL = (ALL) NOPASSWD: ALL" >> /etc/sudoers
-
-# mitigate git clone issues on CI
-# See https://stdworkflow.com/877/error-rpc-failed-curl-56-gnutls-recv-error-54-error-in-the-pull-function
-RUN git config --system user.email "devops@playwright.dev" && \
- git config --system user.name "Playwright DevOps" && \
- git config --system http.postBuffer 524288000 && \
- git config --system http.lowSpeedLimit 0 && \
- git config --system http.lowSpeedTime 999999
-
-# Show welcome message to pwuser
-COPY --chown=pwuser ./pwuser_bashrc /home/pwuser/.bashrc
-
-USER pwuser
-
-# Install Rust
-RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
-ENV PATH="${PATH}:/home/pwuser/.cargo/bin"
-
-RUN mkdir -p /home/pwuser/.mozbuild
-RUN cd /home/pwuser && git clone --depth=1 https://github.com/microsoft/playwright
-
-WORKDIR /home/pwuser/playwright
-
-
diff --git a/browser_patches/docker/firefox/ubuntu-20.04.dockerfile b/browser_patches/docker/firefox/ubuntu-20.04.dockerfile
deleted file mode 100644
index d6dcbab630bf39..00000000000000
--- a/browser_patches/docker/firefox/ubuntu-20.04.dockerfile
+++ /dev/null
@@ -1,54 +0,0 @@
-FROM --platform=linux/amd64 ubuntu:20.04
-
-# Reexport --build-arg as environment variables
-ARG ARG_BUILD_FLAVOR
-ARG ARG_BROWSER_NAME
-ENV BUILD_FLAVOR="${ARG_BUILD_FLAVOR}"
-ENV BROWSER_NAME="${ARG_BROWSER_NAME}"
-
-# These are needed to auto-install tzdata. See https://serverfault.com/questions/949991/how-to-install-tzdata-on-a-ubuntu-docker-image
-ARG DEBIAN_FRONTEND=noninteractive
-ARG TZ=America/Los_Angeles
-
-RUN apt-get update && apt-get install -y curl \
- build-essential \
- git-core \
- zip unzip \
- tzdata \
- sudo
-# Install Python3 with distutils
-RUN apt-get install -y python3 python3-dev python3-pip python3-distutils
-
-# Install Azure CLI
-RUN curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
-
-# Install node16
-RUN curl -sL https://deb.nodesource.com/setup_16.x | bash - && apt-get install -y nodejs
-
-# Create the pwuser and make it passwordless sudoer.
-RUN adduser --disabled-password --gecos "" pwuser && \
- echo "ALL ALL = (ALL) NOPASSWD: ALL" >> /etc/sudoers
-
-# mitigate git clone issues on CI
-# See https://stdworkflow.com/877/error-rpc-failed-curl-56-gnutls-recv-error-54-error-in-the-pull-function
-RUN git config --system user.email "devops@playwright.dev" && \
- git config --system user.name "Playwright DevOps" && \
- git config --system http.postBuffer 524288000 && \
- git config --system http.lowSpeedLimit 0 && \
- git config --system http.lowSpeedTime 999999
-
-# Show welcome message to pwuser
-COPY --chown=pwuser ./pwuser_bashrc /home/pwuser/.bashrc
-
-USER pwuser
-
-# Install Rust
-RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
-ENV PATH="${PATH}:/home/pwuser/.cargo/bin"
-
-RUN mkdir -p /home/pwuser/.mozbuild
-RUN cd /home/pwuser && git clone --depth=1 https://github.com/microsoft/playwright
-
-WORKDIR /home/pwuser/playwright
-
-
diff --git a/browser_patches/docker/firefox/ubuntu-22.04-arm64.dockerfile b/browser_patches/docker/firefox/ubuntu-22.04-arm64.dockerfile
deleted file mode 100644
index 768e956b0960f7..00000000000000
--- a/browser_patches/docker/firefox/ubuntu-22.04-arm64.dockerfile
+++ /dev/null
@@ -1,62 +0,0 @@
-FROM --platform=linux/arm64 ubuntu:22.04
-
-# Reexport --build-arg as environment variables
-ARG ARG_BUILD_FLAVOR
-ARG ARG_BROWSER_NAME
-ENV BUILD_FLAVOR="${ARG_BUILD_FLAVOR}"
-ENV BROWSER_NAME="${ARG_BROWSER_NAME}"
-
-# These are needed to auto-install tzdata. See https://serverfault.com/questions/949991/how-to-install-tzdata-on-a-ubuntu-docker-image
-ARG DEBIAN_FRONTEND=noninteractive
-ARG TZ=America/Los_Angeles
-
-RUN apt-get update && apt-get install -y curl \
- build-essential \
- git-core \
- zip unzip \
- tzdata \
- sudo
-
-# Ubuntu 22.04 aarch64 specific: default to clang-14.
-RUN apt-get install -y clang-14
-ENV CC=/usr/bin/clang-14
-ENV CXX=/usr/bin/clang++-14
-
-# Install Python3 with distutils
-RUN apt-get install -y python3 python3-dev python3-pip python3-distutils
-
-# Install AZ CLI with Python since they do not ship
-# aarch64 to APT: https://github.com/Azure/azure-cli/issues/7368
-# Pin so future releases do not break us.
-RUN pip3 install azure-cli==2.38.0
-
-# Install node16
-RUN curl -sL https://deb.nodesource.com/setup_16.x | bash - && apt-get install -y nodejs
-
-# Create the pwuser and make it passwordless sudoer.
-RUN adduser --disabled-password --gecos "" pwuser && \
- echo "ALL ALL = (ALL) NOPASSWD: ALL" >> /etc/sudoers
-
-# mitigate git clone issues on CI
-# See https://stdworkflow.com/877/error-rpc-failed-curl-56-gnutls-recv-error-54-error-in-the-pull-function
-RUN git config --system user.email "devops@playwright.dev" && \
- git config --system user.name "Playwright DevOps" && \
- git config --system http.postBuffer 524288000 && \
- git config --system http.lowSpeedLimit 0 && \
- git config --system http.lowSpeedTime 999999
-
-# Show welcome message to pwuser
-COPY --chown=pwuser ./pwuser_bashrc /home/pwuser/.bashrc
-
-USER pwuser
-
-# Install Rust
-RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
-ENV PATH="${PATH}:/home/pwuser/.cargo/bin"
-
-RUN mkdir -p /home/pwuser/.mozbuild
-RUN cd /home/pwuser && git clone --depth=1 https://github.com/microsoft/playwright
-
-WORKDIR /home/pwuser/playwright
-
-
diff --git a/browser_patches/docker/firefox/ubuntu-22.04.dockerfile b/browser_patches/docker/firefox/ubuntu-22.04.dockerfile
deleted file mode 100644
index 348ef04af3e033..00000000000000
--- a/browser_patches/docker/firefox/ubuntu-22.04.dockerfile
+++ /dev/null
@@ -1,54 +0,0 @@
-FROM --platform=linux/amd64 ubuntu:22.04
-
-# Reexport --build-arg as environment variables
-ARG ARG_BUILD_FLAVOR
-ARG ARG_BROWSER_NAME
-ENV BUILD_FLAVOR="${ARG_BUILD_FLAVOR}"
-ENV BROWSER_NAME="${ARG_BROWSER_NAME}"
-
-# These are needed to auto-install tzdata. See https://serverfault.com/questions/949991/how-to-install-tzdata-on-a-ubuntu-docker-image
-ARG DEBIAN_FRONTEND=noninteractive
-ARG TZ=America/Los_Angeles
-
-RUN apt-get update && apt-get install -y curl \
- build-essential \
- git-core \
- zip unzip \
- tzdata \
- sudo
-# Install Python3 with distutils
-RUN apt-get install -y python3 python3-dev python3-pip python3-distutils
-
-# Install Azure CLI
-RUN curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
-
-# Install node16
-RUN curl -sL https://deb.nodesource.com/setup_16.x | bash - && apt-get install -y nodejs
-
-# Create the pwuser and make it passwordless sudoer.
-RUN adduser --disabled-password --gecos "" pwuser && \
- echo "ALL ALL = (ALL) NOPASSWD: ALL" >> /etc/sudoers
-
-# mitigate git clone issues on CI
-# See https://stdworkflow.com/877/error-rpc-failed-curl-56-gnutls-recv-error-54-error-in-the-pull-function
-RUN git config --system user.email "devops@playwright.dev" && \
- git config --system user.name "Playwright DevOps" && \
- git config --system http.postBuffer 524288000 && \
- git config --system http.lowSpeedLimit 0 && \
- git config --system http.lowSpeedTime 999999
-
-# Show welcome message to pwuser
-COPY --chown=pwuser ./pwuser_bashrc /home/pwuser/.bashrc
-
-USER pwuser
-
-# Install Rust
-RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
-ENV PATH="${PATH}:/home/pwuser/.cargo/bin"
-
-RUN mkdir -p /home/pwuser/.mozbuild
-RUN cd /home/pwuser && git clone --depth=1 https://github.com/microsoft/playwright
-
-WORKDIR /home/pwuser/playwright
-
-
diff --git a/browser_patches/docker/pwuser_bashrc b/browser_patches/docker/pwuser_bashrc
deleted file mode 100644
index ed78a6e0534061..00000000000000
--- a/browser_patches/docker/pwuser_bashrc
+++ /dev/null
@@ -1,29 +0,0 @@
-source /etc/os-release
-if [[ -z "${BUILD_FLAVOR}" ]]; then
- BUILD_FLAVOR=''
-fi
-if [[ -z "${BROWSER_NAME}" ]]; then
- BROWSER_NAME=''
-fi
-
-echo "======================================================================"
-echo "Welcome to the ${BUILD_FLAVOR} environment!"
-echo "- distro: ${PRETTY_NAME}"
-echo "- arch: $(arch)"
-
-if [[ -n "${CXX}" ]]; then
- echo "- CXX: ${CXX}"
-fi
-if [[ -n "${CC}" ]]; then
- echo "- CC: ${CC}"
-fi
-
-echo
-echo "NOTE: Playwright clone is shallow (has no git history); to unshallow, run:"
-echo " git fetch --unshallow"
-echo
-echo "To get started, prepare your browser checkout:"
-echo " CI=1 ./browser_patches/prepare_checkout.sh ${BROWSER_NAME}"
-echo
-echo "======================================================================"
-
diff --git a/browser_patches/docker/webkit/debian-11.dockerfile b/browser_patches/docker/webkit/debian-11.dockerfile
deleted file mode 100644
index 34969d74d49fb5..00000000000000
--- a/browser_patches/docker/webkit/debian-11.dockerfile
+++ /dev/null
@@ -1,48 +0,0 @@
-FROM --platform=linux/amd64 debian:11
-
-# Reexport --build-arg as environment variables
-ARG ARG_BUILD_FLAVOR
-ARG ARG_BROWSER_NAME
-ENV BUILD_FLAVOR="${ARG_BUILD_FLAVOR}"
-ENV BROWSER_NAME="${ARG_BROWSER_NAME}"
-
-# These are needed to auto-install tzdata. See https://serverfault.com/questions/949991/how-to-install-tzdata-on-a-ubuntu-docker-image
-ARG DEBIAN_FRONTEND=noninteractive
-ARG TZ=America/Los_Angeles
-
-# Debian 11 specific: add contrib & non-free repositories.
-RUN echo "deb http://ftp.us.debian.org/debian bullseye main contrib non-free" >> /etc/apt/sources.list.d/pwbuild.list
-
-RUN apt-get update && apt-get install -y curl \
- build-essential \
- git-core \
- zip unzip \
- tzdata \
- sudo
-
-# Install Azure CLI
-RUN curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
-
-# Install node16
-RUN curl -sL https://deb.nodesource.com/setup_16.x | bash - && apt-get install -y nodejs
-
-# Create the pwuser and make it passwordless sudoer.
-RUN adduser --disabled-password --gecos "" pwuser && \
- echo "ALL ALL = (ALL) NOPASSWD: ALL" >> /etc/sudoers
-
-# mitigate git clone issues on CI
-# See https://stdworkflow.com/877/error-rpc-failed-curl-56-gnutls-recv-error-54-error-in-the-pull-function
-RUN git config --system user.email "devops@playwright.dev" && \
- git config --system user.name "Playwright DevOps" && \
- git config --system http.postBuffer 524288000 && \
- git config --system http.lowSpeedLimit 0 && \
- git config --system http.lowSpeedTime 999999
-
-# Show welcome message
-COPY ./pwuser_bashrc /home/pwuser/.bashrc
-
-USER pwuser
-RUN cd /home/pwuser && git clone --depth=1 https://github.com/microsoft/playwright
-
-WORKDIR /home/pwuser/playwright
-
diff --git a/browser_patches/docker/webkit/ubuntu-18.04.dockerfile b/browser_patches/docker/webkit/ubuntu-18.04.dockerfile
deleted file mode 100644
index 7cba2be2c832b3..00000000000000
--- a/browser_patches/docker/webkit/ubuntu-18.04.dockerfile
+++ /dev/null
@@ -1,59 +0,0 @@
-FROM --platform=linux/amd64 ubuntu:18.04
-
-# Reexport --build-arg as environment variables
-ARG ARG_BUILD_FLAVOR
-ARG ARG_BROWSER_NAME
-ENV BUILD_FLAVOR="${ARG_BUILD_FLAVOR}"
-ENV BROWSER_NAME="${ARG_BROWSER_NAME}"
-
-# These are needed to auto-install tzdata. See https://serverfault.com/questions/949991/how-to-install-tzdata-on-a-ubuntu-docker-image
-ARG DEBIAN_FRONTEND=noninteractive
-ARG TZ=America/Los_Angeles
-
-RUN apt-get update && apt-get install -y curl \
- build-essential \
- git-core \
- zip unzip \
- tzdata \
- sudo
-
-# Ubuntu 18.04 specific: update CMake. Default CMake on Ubuntu 18.04 is 3.10, whereas WebKit requires 3.12+.
-RUN apt purge --auto-remove cmake && \
- apt-get install -y wget software-properties-common && \
- wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | sudo tee /etc/apt/trusted.gpg.d/kitware.gpg >/dev/null && \
- apt-add-repository "deb https://apt.kitware.com/ubuntu/ bionic main" && \
- apt-get update && apt-get install -y cmake
-
-# Ubuntu 18.04 specific: default to gcc-9.
-RUN add-apt-repository ppa:ubuntu-toolchain-r/test && \
- apt-get update && \
- apt-get install -y gcc-9 g++-9
-ENV CC=/usr/bin/gcc-9
-ENV CXX=/usr/bin/g++-9
-
-# Install Azure CLI
-RUN curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
-
-# Install node16
-RUN curl -sL https://deb.nodesource.com/setup_16.x | bash - && apt-get install -y nodejs
-
-# Create the pwuser and make it passwordless sudoer.
-RUN adduser --disabled-password --gecos "" pwuser && \
- echo "ALL ALL = (ALL) NOPASSWD: ALL" >> /etc/sudoers
-
-# mitigate git clone issues on CI
-# See https://stdworkflow.com/877/error-rpc-failed-curl-56-gnutls-recv-error-54-error-in-the-pull-function
-RUN git config --system user.email "devops@playwright.dev" && \
- git config --system user.name "Playwright DevOps" && \
- git config --system http.postBuffer 524288000 && \
- git config --system http.lowSpeedLimit 0 && \
- git config --system http.lowSpeedTime 999999
-
-# Show welcome message
-COPY ./pwuser_bashrc /home/pwuser/.bashrc
-
-USER pwuser
-RUN cd /home/pwuser && git clone --depth=1 https://github.com/microsoft/playwright
-
-WORKDIR /home/pwuser/playwright
-
diff --git a/browser_patches/docker/webkit/ubuntu-20.04-arm64.dockerfile b/browser_patches/docker/webkit/ubuntu-20.04-arm64.dockerfile
deleted file mode 100644
index 5b30404a562a6f..00000000000000
--- a/browser_patches/docker/webkit/ubuntu-20.04-arm64.dockerfile
+++ /dev/null
@@ -1,56 +0,0 @@
-FROM --platform=linux/arm64 ubuntu:20.04
-
-# Reexport --build-arg as environment variables
-ARG ARG_BUILD_FLAVOR
-ARG ARG_BROWSER_NAME
-ENV BUILD_FLAVOR="${ARG_BUILD_FLAVOR}"
-ENV BROWSER_NAME="${ARG_BROWSER_NAME}"
-
-# These are needed to auto-install tzdata. See https://serverfault.com/questions/949991/how-to-install-tzdata-on-a-ubuntu-docker-image
-ARG DEBIAN_FRONTEND=noninteractive
-ARG TZ=America/Los_Angeles
-
-RUN apt-get update && apt-get install -y curl \
- build-essential \
- git-core \
- zip unzip \
- tzdata \
- sudo
-
-# Ubuntu 20.04 aarch64 specific: default to clang-12.
-RUN apt-get install -y clang-12
-ENV CC=/usr/bin/clang-12
-ENV CXX=/usr/bin/clang++-12
-
-# Install AZ CLI with Python since they do not ship
-# aarch64 to APT: https://github.com/Azure/azure-cli/issues/7368
-# Pin so future releases do not break us.
-RUN apt-get install -y python3 \
- python3-dev \
- python3-pip \
- python3-distutils && \
- pip3 install azure-cli==2.38.0
-
-# Install node16
-RUN curl -sL https://deb.nodesource.com/setup_16.x | bash - && apt-get install -y nodejs
-
-# Create the pwuser and make it passwordless sudoer.
-RUN adduser --disabled-password --gecos "" pwuser && \
- echo "ALL ALL = (ALL) NOPASSWD: ALL" >> /etc/sudoers
-
-# mitigate git clone issues on CI
-# See https://stdworkflow.com/877/error-rpc-failed-curl-56-gnutls-recv-error-54-error-in-the-pull-function
-RUN git config --system user.email "devops@playwright.dev" && \
- git config --system user.name "Playwright DevOps" && \
- git config --system http.postBuffer 524288000 && \
- git config --system http.lowSpeedLimit 0 && \
- git config --system http.lowSpeedTime 999999
-
-# Show welcome message
-COPY ./pwuser_bashrc /home/pwuser/.bashrc
-
-USER pwuser
-RUN cd /home/pwuser && git clone --depth=1 https://github.com/microsoft/playwright
-
-WORKDIR /home/pwuser/playwright
-
diff --git a/browser_patches/docker/webkit/ubuntu-20.04.dockerfile b/browser_patches/docker/webkit/ubuntu-20.04.dockerfile
deleted file mode 100644
index 260954626583b4..00000000000000
--- a/browser_patches/docker/webkit/ubuntu-20.04.dockerfile
+++ /dev/null
@@ -1,45 +0,0 @@
-FROM --platform=linux/amd64 ubuntu:20.04
-
-# Reexport --build-arg as environment variables
-ARG ARG_BUILD_FLAVOR
-ARG ARG_BROWSER_NAME
-ENV BUILD_FLAVOR="${ARG_BUILD_FLAVOR}"
-ENV BROWSER_NAME="${ARG_BROWSER_NAME}"
-
-# These are needed to auto-install tzdata. See https://serverfault.com/questions/949991/how-to-install-tzdata-on-a-ubuntu-docker-image
-ARG DEBIAN_FRONTEND=noninteractive
-ARG TZ=America/Los_Angeles
-
-RUN apt-get update && apt-get install -y curl \
- build-essential \
- git-core \
- zip unzip \
- tzdata \
- sudo
-
-# Install Azure CLI
-RUN curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
-
-# Install node16
-RUN curl -sL https://deb.nodesource.com/setup_16.x | bash - && apt-get install -y nodejs
-
-# Create the pwuser and make it passwordless sudoer.
-RUN adduser --disabled-password --gecos "" pwuser && \
- echo "ALL ALL = (ALL) NOPASSWD: ALL" >> /etc/sudoers
-
-# mitigate git clone issues on CI
-# See https://stdworkflow.com/877/error-rpc-failed-curl-56-gnutls-recv-error-54-error-in-the-pull-function
-RUN git config --system user.email "devops@playwright.dev" && \
- git config --system user.name "Playwright DevOps" && \
- git config --system http.postBuffer 524288000 && \
- git config --system http.lowSpeedLimit 0 && \
- git config --system http.lowSpeedTime 999999
-
-# Show welcome message
-COPY ./pwuser_bashrc /home/pwuser/.bashrc
-
-USER pwuser
-RUN cd /home/pwuser && git clone --depth=1 https://github.com/microsoft/playwright
-
-WORKDIR /home/pwuser/playwright
-
diff --git a/browser_patches/docker/webkit/ubuntu-22.04-arm64.dockerfile b/browser_patches/docker/webkit/ubuntu-22.04-arm64.dockerfile
deleted file mode 100644
index 30e86a1f3e7f57..00000000000000
--- a/browser_patches/docker/webkit/ubuntu-22.04-arm64.dockerfile
+++ /dev/null
@@ -1,56 +0,0 @@
-FROM --platform=linux/arm64 ubuntu:22.04
-
-# Reexport --build-arg as environment variables
-ARG ARG_BUILD_FLAVOR
-ARG ARG_BROWSER_NAME
-ENV BUILD_FLAVOR="${ARG_BUILD_FLAVOR}"
-ENV BROWSER_NAME="${ARG_BROWSER_NAME}"
-
-# These are needed to auto-install tzdata. See https://serverfault.com/questions/949991/how-to-install-tzdata-on-a-ubuntu-docker-image
-ARG DEBIAN_FRONTEND=noninteractive
-ARG TZ=America/Los_Angeles
-
-RUN apt-get update && apt-get install -y curl \
- build-essential \
- git-core \
- zip unzip \
- tzdata \
- sudo
-
-# Ubuntu 22.04 aarch64 specific: default to clang-12.
-RUN apt-get install -y clang-12
-ENV CC=/usr/bin/clang-12
-ENV CXX=/usr/bin/clang++-12
-
-# Install AZ CLI with Python since they do not ship
-# aarch64 to APT: https://github.com/Azure/azure-cli/issues/7368
-# Pin so future releases do not break us.
-RUN apt-get install -y python3 \
- python3-dev \
- python3-pip \
- python3-distutils && \
- pip3 install azure-cli==2.38.0
-
-# Install node16
-RUN curl -sL https://deb.nodesource.com/setup_16.x | bash - && apt-get install -y nodejs
-
-# Create the pwuser and make it passwordless sudoer.
-RUN adduser --disabled-password --gecos "" pwuser && \
- echo "ALL ALL = (ALL) NOPASSWD: ALL" >> /etc/sudoers
-
-# mitigate git clone issues on CI
-# See https://stdworkflow.com/877/error-rpc-failed-curl-56-gnutls-recv-error-54-error-in-the-pull-function
-RUN git config --system user.email "devops@playwright.dev" && \
- git config --system user.name "Playwright DevOps" && \
- git config --system http.postBuffer 524288000 && \
- git config --system http.lowSpeedLimit 0 && \
- git config --system http.lowSpeedTime 999999
-
-# Show welcome message
-COPY ./pwuser_bashrc /home/pwuser/.bashrc
-
-USER pwuser
-RUN cd /home/pwuser && git clone --depth=1 https://github.com/microsoft/playwright
-
-WORKDIR /home/pwuser/playwright
-
diff --git a/browser_patches/docker/webkit/ubuntu-22.04.dockerfile b/browser_patches/docker/webkit/ubuntu-22.04.dockerfile
deleted file mode 100644
index 928874b654a8b0..00000000000000
--- a/browser_patches/docker/webkit/ubuntu-22.04.dockerfile
+++ /dev/null
@@ -1,45 +0,0 @@
-FROM --platform=linux/amd64 ubuntu:22.04
-
-# Reexport --build-arg as environment variables
-ARG ARG_BUILD_FLAVOR
-ARG ARG_BROWSER_NAME
-ENV BUILD_FLAVOR="${ARG_BUILD_FLAVOR}"
-ENV BROWSER_NAME="${ARG_BROWSER_NAME}"
-
-# These are needed to auto-install tzdata. See https://serverfault.com/questions/949991/how-to-install-tzdata-on-a-ubuntu-docker-image
-ARG DEBIAN_FRONTEND=noninteractive
-ARG TZ=America/Los_Angeles
-
-RUN apt-get update && apt-get install -y curl \
- build-essential \
- git-core \
- zip unzip \
- tzdata \
- sudo
-
-# Install Azure CLI
-RUN curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
-
-# Install node16
-RUN curl -sL https://deb.nodesource.com/setup_16.x | bash - && apt-get install -y nodejs
-
-# Create the pwuser and make it passwordless sudoer.
-RUN adduser --disabled-password --gecos "" pwuser && \
- echo "ALL ALL = (ALL) NOPASSWD: ALL" >> /etc/sudoers
-
-# mitigate git clone issues on CI
-# See https://stdworkflow.com/877/error-rpc-failed-curl-56-gnutls-recv-error-54-error-in-the-pull-function
-RUN git config --system user.email "devops@playwright.dev" && \
- git config --system user.name "Playwright DevOps" && \
- git config --system http.postBuffer 524288000 && \
- git config --system http.lowSpeedLimit 0 && \
- git config --system http.lowSpeedTime 999999
-
-# Show welcome message
-COPY ./pwuser_bashrc /home/pwuser/.bashrc
-
-USER pwuser
-RUN cd /home/pwuser && git clone --depth=1 https://github.com/microsoft/playwright
-
-WORKDIR /home/pwuser/playwright
-
diff --git a/browser_patches/export.sh b/browser_patches/export.sh
deleted file mode 100755
index 01139737f05372..00000000000000
--- a/browser_patches/export.sh
+++ /dev/null
@@ -1,177 +0,0 @@
-#!/bin/bash
-set -e
-set +x
-
-trap "cd $(pwd -P)" EXIT
-cd "$(dirname "$0")"
-
-REMOTE_BROWSER_UPSTREAM="browser_upstream"
-BUILD_BRANCH="playwright-build"
-
-# COLORS
-RED=$'\e[1;31m'
-GRN=$'\e[1;32m'
-YEL=$'\e[1;33m'
-END=$'\e[0m'
-
-if [[ ($1 == '--help') || ($1 == '-h') ]]; then
- echo "usage: export.sh [firefox|webkit] [custom_checkout_path]"
- echo
- echo "Exports patch from the current branch of the checkout to browser folder."
- echo "The checkout has to be 'prepared', meaning that 'prepare_checkout.sh' should be"
- echo "run against it first."
- echo
- echo "You can optionally specify custom_checkout_path if you have browser checkout somewhere else"
- echo "and wish to export patches from it."
- echo
- exit 0
-fi
-
-if [[ $# == 0 ]]; then
- echo "missing browser: 'firefox' or 'webkit'"
- echo "try './export.sh --help' for more information"
- exit 1
-fi
-
-# FRIENDLY_CHECKOUT_PATH is used only for logging.
-FRIENDLY_CHECKOUT_PATH="";
-BUILD_NUMBER_UPSTREAM_URL=""
-CHECKOUT_PATH=""
-EXPORT_PATH=""
-EXTRA_FOLDER_PW_PATH=""
-EXTRA_FOLDER_CHECKOUT_RELPATH=""
-if [[ ("$1" == "firefox") || ("$1" == "firefox/") || ("$1" == "ff") ]]; then
- if [[ -z "${FF_CHECKOUT_PATH}" ]]; then
- FRIENDLY_CHECKOUT_PATH='$HOME/firefox';
- CHECKOUT_PATH="$HOME/firefox"
- else
- echo "WARNING: using checkout path from FF_CHECKOUT_PATH env: ${FF_CHECKOUT_PATH}"
- CHECKOUT_PATH="${FF_CHECKOUT_PATH}"
- FRIENDLY_CHECKOUT_PATH=""
- fi
-
- EXTRA_FOLDER_PW_PATH="$PWD/firefox/juggler"
- EXTRA_FOLDER_CHECKOUT_RELPATH="juggler"
- EXPORT_PATH="$PWD/firefox"
- BUILD_NUMBER_UPSTREAM_URL="https://raw.githubusercontent.com/microsoft/playwright/main/browser_patches/firefox/BUILD_NUMBER"
- source "./firefox/UPSTREAM_CONFIG.sh"
-elif [[ ("$1" == "firefox-beta") || ("$1" == "ff-beta") ]]; then
- if [[ -z "${FF_CHECKOUT_PATH}" ]]; then
- FRIENDLY_CHECKOUT_PATH='$HOME/firefox';
- CHECKOUT_PATH="$HOME/firefox"
- else
- echo "WARNING: using checkout path from FF_CHECKOUT_PATH env: ${FF_CHECKOUT_PATH}"
- CHECKOUT_PATH="${FF_CHECKOUT_PATH}"
- FRIENDLY_CHECKOUT_PATH=""
- fi
-
- EXTRA_FOLDER_PW_PATH="$PWD/firefox-beta/juggler"
- EXTRA_FOLDER_CHECKOUT_RELPATH="juggler"
- EXPORT_PATH="$PWD/firefox-beta"
- BUILD_NUMBER_UPSTREAM_URL="https://raw.githubusercontent.com/microsoft/playwright/main/browser_patches/firefox-beta/BUILD_NUMBER"
- source "./firefox-beta/UPSTREAM_CONFIG.sh"
-elif [[ ("$1" == "webkit") || ("$1" == "webkit/") || ("$1" == "wk") ]]; then
- if [[ -z "${WK_CHECKOUT_PATH}" ]]; then
- FRIENDLY_CHECKOUT_PATH='$HOME/webkit';
- CHECKOUT_PATH="$HOME/webkit"
- else
- echo "WARNING: using checkout path from WK_CHECKOUT_PATH env: ${WK_CHECKOUT_PATH}"
- CHECKOUT_PATH="${WK_CHECKOUT_PATH}"
- FRIENDLY_CHECKOUT_PATH=""
- fi
-
- EXTRA_FOLDER_PW_PATH="$PWD/webkit/embedder/Playwright"
- EXTRA_FOLDER_CHECKOUT_RELPATH="Tools/Playwright"
- EXPORT_PATH="$PWD/webkit"
- BUILD_NUMBER_UPSTREAM_URL="https://raw.githubusercontent.com/microsoft/playwright/main/browser_patches/webkit/BUILD_NUMBER"
- source "./webkit/UPSTREAM_CONFIG.sh"
-else
- echo ERROR: unknown browser to export - "$1"
- exit 1
-fi
-
-# we will use this just for beauty.
-if [[ $# == 2 ]]; then
- echo "WARNING: using custom checkout path $2"
- CHECKOUT_PATH=$2
- FRIENDLY_CHECKOUT_PATH=""
-fi
-
-# if there's no checkout folder - bail out.
-if ! [[ -d $CHECKOUT_PATH ]]; then
- echo "ERROR: $FRIENDLY_CHECKOUT_PATH is missing - nothing to export."
- exit 1;
-else
- echo "-- checking $FRIENDLY_CHECKOUT_PATH exists - OK"
-fi
-
-# if folder exists but not a git repository - bail out.
-if ! [[ -d $CHECKOUT_PATH/.git ]]; then
- echo "ERROR: $FRIENDLY_CHECKOUT_PATH is not a git repository! Nothing to export."
- exit 1
-else
- echo "-- checking $FRIENDLY_CHECKOUT_PATH is a git repo - OK"
-fi
-
-# Switch to git repository.
-cd "$CHECKOUT_PATH"
-
-# Setting up |$REMOTE_BROWSER_UPSTREAM| remote and fetch the $BASE_BRANCH
-if git remote get-url $REMOTE_BROWSER_UPSTREAM >/dev/null; then
- if ! [[ $(git config --get remote.$REMOTE_BROWSER_UPSTREAM.url || echo "") == "$REMOTE_URL" ]]; then
- echo "ERROR: remote $REMOTE_BROWSER_UPSTREAM is not pointing to '$REMOTE_URL'! run 'prepare_checkout.sh' first"
- exit 1
- fi
-else
- echo "ERROR: checkout does not have $REMOTE_BROWSER_UPSTREAM; run 'prepare_checkout.sh' first"
- exit 1
-fi
-
-# Check if git repo is dirty.
-if [[ -n $(git status -s --untracked-files=no) ]]; then
- echo "ERROR: $FRIENDLY_CHECKOUT_PATH has dirty GIT state - aborting export."
- exit 1
-else
- echo "-- checking $FRIENDLY_CHECKOUT_PATH is clean - OK"
-fi
-
-PATCH_NAME=$(ls -1 "$EXPORT_PATH"/patches)
-if [[ -z "$PATCH_NAME" ]]; then
- PATCH_NAME="bootstrap.diff"
- OLD_DIFF=""
-else
- OLD_DIFF=$(cat "$EXPORT_PATH"/patches/$PATCH_NAME)
-fi
-
-CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
-NEW_BASE_REVISION=$(git merge-base $REMOTE_BROWSER_UPSTREAM/"$BASE_BRANCH" "$CURRENT_BRANCH")
-NEW_DIFF=$(git diff --diff-algorithm=myers --full-index "$NEW_BASE_REVISION" "$CURRENT_BRANCH" -- . ":!${EXTRA_FOLDER_CHECKOUT_RELPATH}")
-
-# Increment BUILD_NUMBER
-BUILD_NUMBER=$(curl ${BUILD_NUMBER_UPSTREAM_URL} | head -1)
-BUILD_NUMBER=$((BUILD_NUMBER+1))
-
-echo "REMOTE_URL=\"$REMOTE_URL\"
-BASE_BRANCH=\"$BASE_BRANCH\"
-BASE_REVISION=\"$NEW_BASE_REVISION\"" > "$EXPORT_PATH"/UPSTREAM_CONFIG.sh
-echo "$NEW_DIFF" > "$EXPORT_PATH"/patches/$PATCH_NAME
-echo $BUILD_NUMBER > "$EXPORT_PATH"/BUILD_NUMBER
-echo "Changed: $(git config user.email) $(date)" >> "$EXPORT_PATH"/BUILD_NUMBER
-
-echo "-- exporting standalone folder"
-rm -rf "${EXTRA_FOLDER_PW_PATH}"
-mkdir -p $(dirname "${EXTRA_FOLDER_PW_PATH}")
-cp -r "${EXTRA_FOLDER_CHECKOUT_RELPATH}" "${EXTRA_FOLDER_PW_PATH}"
-
-NEW_BASE_REVISION_TEXT="$NEW_BASE_REVISION (not changed)"
-if [[ "$NEW_BASE_REVISION" != "$BASE_REVISION" ]]; then
- NEW_BASE_REVISION_TEXT="$YEL$NEW_BASE_REVISION (changed)$END"
-fi
-
-echo "=============================================================="
-echo " Repository: $FRIENDLY_CHECKOUT_PATH"
-echo " Changes between branches: $REMOTE_BROWSER_UPSTREAM/$BASE_BRANCH..$CURRENT_BRANCH"
-echo " BASE_REVISION: $NEW_BASE_REVISION_TEXT"
-echo " BUILD_NUMBER: $YEL$BUILD_NUMBER (changed)$END"
-echo "=============================================================="
-echo
diff --git a/browser_patches/ffmpeg/.gitignore b/browser_patches/ffmpeg/.gitignore
deleted file mode 100644
index b97a986fa15ea7..00000000000000
--- a/browser_patches/ffmpeg/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-build/
-output/
diff --git a/browser_patches/ffmpeg/BUILD_NUMBER b/browser_patches/ffmpeg/BUILD_NUMBER
deleted file mode 100644
index fb35a14c027168..00000000000000
--- a/browser_patches/ffmpeg/BUILD_NUMBER
+++ /dev/null
@@ -1 +0,0 @@
-1007
diff --git a/browser_patches/ffmpeg/CONFIG.sh b/browser_patches/ffmpeg/CONFIG.sh
deleted file mode 100644
index 2cb8e6f83642ac..00000000000000
--- a/browser_patches/ffmpeg/CONFIG.sh
+++ /dev/null
@@ -1,53 +0,0 @@
-# Copyright (c) Microsoft Corporation.
-#
-# Licensed under the Apache License, Version 2.0 (the 'License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ZLIB_VERSION="v1.2.11"
-ZLIB_CONFIG="--static"
-
-LIBVPX_VERSION="v1.9.0"
-LIBVPX_CONFIG="--enable-static \
- --disable-shared \
- --disable-docs \
- --disable-tools \
- --disable-unit-tests \
- --disable-examples"
-
-FFMPEG_VERSION="n4.3.1"
-FFMPEG_CONFIG="--extra-version=playwright-build-$(cat ./BUILD_NUMBER | head -1) \
- --disable-debug \
- --disable-autodetect \
- --disable-everything \
- --enable-ffmpeg \
- --enable-protocol=pipe \
- --enable-protocol=file \
- --enable-parser=mjpeg \
- --enable-decoder=mjpeg \
- --enable-demuxer=image2pipe \
- --enable-filter=pad \
- --enable-filter=crop \
- --enable-filter=scale \
- --enable-muxer=webm \
- --enable-libvpx \
- --enable-static \
- --enable-encoder=libvpx_vp8 \
- --enable-decoder=libvpx_vp8 \
- --enable-demuxer=matroska \
- --enable-encoder=png \
- --enable-zlib \
- --enable-muxer=image2 \
- --disable-pthreads \
- --disable-iconv \
- --disable-w32threads \
- --disable-bzlib"
-
diff --git a/browser_patches/ffmpeg/EXPECTED_BUILDS b/browser_patches/ffmpeg/EXPECTED_BUILDS
deleted file mode 100644
index ec5ce4f2e01618..00000000000000
--- a/browser_patches/ffmpeg/EXPECTED_BUILDS
+++ /dev/null
@@ -1,6 +0,0 @@
-ffmpeg-mac.zip
-ffmpeg-mac-arm64.zip
-ffmpeg-linux.zip
-ffmpeg-linux-arm64.zip
-ffmpeg-win64.zip
-
diff --git a/browser_patches/ffmpeg/README.md b/browser_patches/ffmpeg/README.md
deleted file mode 100644
index 89ed18d6dc2b9c..00000000000000
--- a/browser_patches/ffmpeg/README.md
+++ /dev/null
@@ -1,57 +0,0 @@
-# Playwright and FFMPEG
-
-Playwright requires FFMPEG to produce screncast and bundles FFMPEG binaries for Mac , Linux and Windows.
-
-## Configuration
-
-We compile `libvpx` and `ffmpeg` only. Their source versions and build
-configurations are defined in [`//browser_patches/ffmpeg/CONFIG.sh`](./CONFIG.sh).
-
-## Building `ffmpeg-linux`
-
-Compilation scripts are based on:
-- https://trac.ffmpeg.org/wiki/CompilationGuide/Generic
-
-Prerequisites:
-- Mac or Linux
-- Docker
-
-Building:
-
-```
-~/playwright$ ./browser_patches/ffmpeg/build.sh --linux
-```
-
-## Building `ffmpeg-mac`
-
-Compilation scripts are based on:
-- https://trac.ffmpeg.org/wiki/CompilationGuide/Generic
-- https://trac.ffmpeg.org/wiki/CompilationGuide/macOS
-
-Prerequisites:
-- Mac
-- xcode command line tools: `xcode-select --install`
-- [homebrew](https://brew.sh/)
-
-Building:
-
-```
-~/playwright$ ./browser_patches/ffmpeg/build.sh --mac
-```
-
-## Building `ffmpeg-win*`
-
-Cross-compilation scripts are based on:
-- https://trac.ffmpeg.org/wiki/CompilationGuide/Generic
-- https://trac.ffmpeg.org/wiki/CompilationGuide/CrossCompilingForWindows
-
-Prerequisites:
-- Mac or Linux
-- [Docker](https://www.docker.com/)
-
-Building:
-
-```
-~/playwright$ ./browser_patches/ffmpeg/build.sh --cross-compile-win64
-```
-
diff --git a/browser_patches/ffmpeg/archive.sh b/browser_patches/ffmpeg/archive.sh
deleted file mode 100755
index ffdf2aba9e0cc0..00000000000000
--- a/browser_patches/ffmpeg/archive.sh
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/bin/bash
-set -e
-set +x
-
-if [[ ("$1" == "-h") || ("$1" == "--help") ]]; then
- echo "usage: $(basename $0) [output-absolute-path]"
- echo
- echo "Generate distributable .zip archive from ./output folder that was previously built."
- echo
- exit 0
-fi
-
-ZIP_PATH=$1
-if [[ $ZIP_PATH != /* ]]; then
- echo "ERROR: path $ZIP_PATH is not absolute"
- exit 1
-fi
-if [[ $ZIP_PATH != *.zip ]]; then
- echo "ERROR: path $ZIP_PATH must have .zip extension"
- exit 1
-fi
-if [[ -f $ZIP_PATH ]]; then
- echo "ERROR: path $ZIP_PATH exists; can't do anything."
- exit 1
-fi
-if ! [[ -d $(dirname $ZIP_PATH) ]]; then
- echo "ERROR: folder for path $($ZIP_PATH) does not exist."
- exit 1
-fi
-
-trap "cd $(pwd -P)" EXIT
-cd "$(dirname $0)"
-
-cp output/ffmpeg.zip $ZIP_PATH
diff --git a/browser_patches/ffmpeg/build-linux.sh b/browser_patches/ffmpeg/build-linux.sh
deleted file mode 100644
index 5514a07e7c7162..00000000000000
--- a/browser_patches/ffmpeg/build-linux.sh
+++ /dev/null
@@ -1,93 +0,0 @@
-#!/bin/bash
-
-# Copyright (c) Microsoft Corporation.
-#
-# Licensed under the Apache License, Version 2.0 (the 'License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-set -ex
-
-function die() { echo "$@"; exit 1; }
-
-
-PREFIX="${HOME}/prefix"
-
-
-if [[ "$(uname)" != "Linux" ]]; then
- echo "ERROR: this script is designed to be run on Linux. Can't run on $(uname)"
- exit 1
-fi
-
-output_path="$1"
-if [[ -z "${output_path}" ]]; then
- die "ERROR: output path is not specified"
-elif [[ "${output_path}" != /* ]]; then
- die "ERROR: output path ${output_path} is not absolute"
-elif ! [[ -d $(dirname "${output_path}") ]]; then
- die "ERROR: folder for output path ${output_path} does not exist."
-fi
-
-function build_zlib {
- cd "${HOME}"
- git clone https://github.com/madler/zlib
- cd zlib
- git checkout "${ZLIB_VERSION}"
- ./configure --prefix="${PREFIX}" ${ZLIB_CONFIG}
- make && make install
-}
-
-function build_libvpx {
- cd "${HOME}"
- git clone https://chromium.googlesource.com/webm/libvpx
- cd libvpx
- git checkout "${LIBVPX_VERSION}"
- # Cross-compiling libvpx according to the docs:
- # - https://chromium.googlesource.com/webm/libvpx/+/main/README
- ./configure --prefix="${PREFIX}" ${LIBVPX_CONFIG}
- make && make install
-}
-
-function build_ffmpeg {
- cd "${HOME}"
- git clone git://source.ffmpeg.org/ffmpeg.git
- cd ffmpeg
- git checkout "${FFMPEG_VERSION}"
- export PKG_CONFIG_PATH="${PREFIX}/lib/pkgconfig"
- # Prohibit pkg-config from using linux system installed libs.
- export PKG_CONFIG_LIBDIR=
-
- ./configure --pkg-config=pkg-config \
- --pkg-config-flags="--static" \
- --extra-cflags="-I/${PREFIX}/include" \
- --extra-ldflags="-L/${PREFIX}/lib -static" \
- --prefix="${PREFIX}" \
- --bindir="${PWD}/bin" \
- ${FFMPEG_CONFIG}
- make && make install
-}
-
-trap "cd $(pwd -P)" EXIT
-cd "$(dirname $0)"
-
-source ./CONFIG.sh
-
-apt-get update
-apt-get install -y git make yasm pkg-config
-
-build_zlib
-build_libvpx
-build_ffmpeg
-
-# put resulting executable where we were asked to
-cp "${HOME}/ffmpeg/bin/ffmpeg" "${output_path}"
-strip "${output_path}"
-
diff --git a/browser_patches/ffmpeg/build-mac.sh b/browser_patches/ffmpeg/build-mac.sh
deleted file mode 100755
index 91ac05f633bb90..00000000000000
--- a/browser_patches/ffmpeg/build-mac.sh
+++ /dev/null
@@ -1,106 +0,0 @@
-#!/bin/bash
-
-# Copyright (c) Microsoft Corporation.
-#
-# Licensed under the Apache License, Version 2.0 (the 'License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-set -e
-
-function die() { echo "$@"; exit 1; }
-
-if [[ "$(uname)" != "Darwin" ]]; then
- die "ERROR: this script is designed to be run on OSX. Can't run on $(uname)"
-fi
-
-trap "cd $(pwd -P)" EXIT
-cd "$(dirname $0)"
-SCRIPT_FOLDER="$(pwd -P)"
-source "${SCRIPT_FOLDER}/../utils.sh"
-
-selectXcodeVersionOrDie $(node "${SCRIPT_FOLDER}/../get_xcode_version.js" ffmpeg)
-
-source ./CONFIG.sh
-
-BUILDDIR="${PWD}/build"
-PREFIX="${BUILDDIR}/osx_prefix"
-OUTPUT_PATH="${PWD}/output/ffmpeg-mac"
-
-function build_zlib {
- cd "${BUILDDIR}"
- git clone https://github.com/madler/zlib
- cd zlib
- git checkout "${ZLIB_VERSION}"
- ./configure --prefix="${PREFIX}" ${ZLIB_CONFIG}
- make && make install
-}
-
-function build_libvpx {
- cd "${BUILDDIR}"
- git clone https://chromium.googlesource.com/webm/libvpx
- cd libvpx
- git checkout "${LIBVPX_VERSION}"
- # Compile libvpx according to the docs:
- # - https://chromium.googlesource.com/webm/libvpx/+/main/README
- ./configure --prefix="${PREFIX}" ${LIBVPX_CONFIG}
- make && make install
-}
-
-function build_ffmpeg {
- cd "${BUILDDIR}"
- git clone git://source.ffmpeg.org/ffmpeg.git
- cd ffmpeg
- git checkout "${FFMPEG_VERSION}"
- export PKG_CONFIG_PATH="${PREFIX}/lib/pkgconfig"
- # Prohibit pkg-config from using system installed libs.
- export PKG_CONFIG_LIBDIR=
-
- ./configure --pkg-config=pkg-config \
- --pkg-config-flags="--static" \
- --extra-cflags="-I/${PREFIX}/include" \
- --extra-ldflags="-L/${PREFIX}/lib" \
- --prefix="${PREFIX}" \
- --bindir="${PWD}/bin" \
- ${FFMPEG_CONFIG}
- make && make install
-}
-
-REQUIERED_BUILD_TOOLS=("git" "make" "yasm" "pkg-config")
-missing_build_tools=()
-
-for dependency in ${REQUIERED_BUILD_TOOLS[@]}; do
- if ! command -v "${dependency}" >/dev/null; then
- missing_build_tools+=("${dependency}")
- fi
-done
-
-if [[ ${#missing_build_tools[@]} != 0 ]]; then
- if [[ "$1" == "--full" ]]; then
- brew install ${missing_build_tools[@]}
- else
- die "ERROR: missing dependencies! Please run: brew install ${missing_build_tools[@]}"
- fi
-fi
-
-# Cleanup
-set -x
-rm -rf "${BUILDDIR}"
-mkdir -p "${BUILDDIR}"
-
-build_zlib
-build_libvpx
-build_ffmpeg
-
-# put resulting executable where we were asked to
-mkdir -p $(dirname "${OUTPUT_PATH}")
-cp "${BUILDDIR}/ffmpeg/bin/ffmpeg" "${OUTPUT_PATH}"
-strip "${OUTPUT_PATH}"
diff --git a/browser_patches/ffmpeg/build.sh b/browser_patches/ffmpeg/build.sh
deleted file mode 100755
index 929f78823481f8..00000000000000
--- a/browser_patches/ffmpeg/build.sh
+++ /dev/null
@@ -1,78 +0,0 @@
-#!/bin/bash
-
-# Copyright (c) Microsoft Corporation.
-#
-# Licensed under the Apache License, Version 2.0 (the 'License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-set -e
-set +x
-
-trap "cd $(pwd -P)" EXIT
-cd "$(dirname $0)"
-
-if [[ ("$1" == "-h") || ("$1" == "--help") ]]; then
- echo "usage: $(basename $0) [--mac|--linux|--cross-compile-win64] [--full]"
- echo
- echo "Build ffmpeg for the given platform"
- echo
- exit 0
-fi
-
-if [[ -z "$1" ]]; then
- echo "ERROR: expected build target. Run with --help for more info"
- exit 1
-fi
-
-LICENSE_FILE="COPYING.LGPLv2.1"
-
-rm -rf ./output
-mkdir -p output
-cp ffmpeg-license/"${LICENSE_FILE}" output
-
-dockerflags="";
-# Use |-it| to run docker to support Ctrl-C if we run the script inside interactive terminal.
-# Otherwise (e.g. cronjob) - do nothing.
-if [[ -t 0 ]]; then
- dockerflags="-it"
-fi
-
-function ensure_docker_or_die() {
- if ! command -v docker >/dev/null; then
- echo "ERROR: docker is required for the script"
- exit 1
- fi
-}
-
-if [[ "$1" == "--mac" ]]; then
- bash ./build-mac.sh $2
- cd output && zip ffmpeg.zip ffmpeg-mac "${LICENSE_FILE}"
-elif [[ "$1" == "--linux" ]]; then
- ensure_docker_or_die
-
- time docker run --init --rm -v"${PWD}":/host ${dockerflags} ubuntu:18.04 bash /host/build-linux.sh /host/output/ffmpeg-linux
- cd output && zip ffmpeg.zip ffmpeg-linux "${LICENSE_FILE}"
-elif [[ "$1" == --cross-compile-win64 ]]; then
- ensure_docker_or_die
-
- time docker run --init --rm -v"${PWD}":/host ${dockerflags} ubuntu:18.04 bash /host/crosscompile-from-linux.sh --win64 /host/output/ffmpeg-win64.exe
- cd output && zip ffmpeg.zip ffmpeg-win64.exe "${LICENSE_FILE}"
-elif [[ "$1" == "--cross-compile-linux-arm64" ]]; then
- ensure_docker_or_die
-
- time docker run --init --rm -v"${PWD}":/host ${dockerflags} ubuntu:18.04 bash /host/crosscompile-from-linux.sh --linux-arm64 /host/output/ffmpeg-linux
- cd output && zip ffmpeg.zip ffmpeg-linux "${LICENSE_FILE}"
-else
- echo "ERROR: unsupported platform - $1"
- exit 1
-fi
-
diff --git a/browser_patches/ffmpeg/clean.sh b/browser_patches/ffmpeg/clean.sh
deleted file mode 100755
index db4d36c08e7bb5..00000000000000
--- a/browser_patches/ffmpeg/clean.sh
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/bash
-set -e
-set +x
-
-trap "cd $(pwd -P)" EXIT
-cd "$(dirname $0)"
-
-rm -rf output
-
diff --git a/browser_patches/ffmpeg/crosscompile-from-linux.sh b/browser_patches/ffmpeg/crosscompile-from-linux.sh
deleted file mode 100644
index caa94843946561..00000000000000
--- a/browser_patches/ffmpeg/crosscompile-from-linux.sh
+++ /dev/null
@@ -1,147 +0,0 @@
-#!/bin/bash
-
-# Copyright (c) Microsoft Corporation.
-#
-# Licensed under the Apache License, Version 2.0 (the 'License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-set -ex
-
-function die() { echo "$@"; exit 1; }
-
-
-PREFIX="${HOME}/prefix"
-TOOLCHAIN_PREFIX_64="/usr/bin/x86_64-w64-mingw32-"
-TOOLCHAIN_PREFIX_ARM64="/usr/bin/aarch64-linux-gnu-"
-
-arch=""
-toolchain_prefix=""
-binary=""
-
-if [[ "$(uname)" != "Linux" ]]; then
- echo "ERROR: this script is designed to be run on Linux. Can't run on $(uname)"
- exit 1
-fi
-
-if [[ "$1" == "--win64" ]]; then
- arch="win64";
- toolchain_prefix="${TOOLCHAIN_PREFIX_64}"
- binary="ffmpeg.exe"
-elif [[ "$1" == "--linux-arm64" ]]; then
- arch="linux-arm64";
- toolchain_prefix="${TOOLCHAIN_PREFIX_ARM64}"
- binary="ffmpeg"
-elif [[ -z "$1" ]]; then
- die "ERROR: expect --win64 or --linux-arm64 as the first argument"
-else
- die "ERROR: unknown arch '$1' - expected --win64 or --linux-arm64"
-fi
-
-output_path="$2"
-if [[ -z "${output_path}" ]]; then
- die "ERROR: output path is not specified"
-elif [[ "${output_path}" != /* ]]; then
- die "ERROR: output path ${output_path} is not absolute"
-elif ! [[ -d $(dirname "${output_path}") ]]; then
- die "ERROR: folder for output path ${output_path} does not exist."
-fi
-
-function build_zlib {
- cd "${HOME}"
- git clone https://github.com/madler/zlib
- cd zlib
- git checkout "${ZLIB_VERSION}"
- ./configure --prefix="${PREFIX}" ${ZLIB_CONFIG}
- make \
- CC="${toolchain_prefix}gcc" \
- CXX="${toolchain_prefix}g++" \
- AR="${toolchain_prefix}ar" \
- PREFIX="$PREFIX" \
- RANLIB="${toolchain_prefix}ranlib" \
- LD="${toolchain_prefix}ld" \
- STRIP="${toolchain_prefix}strip"
- make install
-}
-
-function build_libvpx {
- cd "${HOME}"
- git clone https://chromium.googlesource.com/webm/libvpx
- cd libvpx
- git checkout "${LIBVPX_VERSION}"
- # Cross-compiling libvpx according to the docs:
- # - https://chromium.googlesource.com/webm/libvpx/+/main/README
- local target=""
- if [[ $arch == "win64" ]]; then
- target="x86_64-win64-gcc";
- elif [[ $arch == "linux-arm64" ]]; then
- target="arm64-linux-gcc";
- else
- die "ERROR: unsupported arch to compile libvpx - $arch"
- fi
- CROSS="${toolchain_prefix}" ./configure --prefix="${PREFIX}" --target="${target}" ${LIBVPX_CONFIG}
- CROSS="${toolchain_prefix}" make && make install
-}
-
-function build_ffmpeg {
- cd "${HOME}"
- git clone git://source.ffmpeg.org/ffmpeg.git
- cd ffmpeg
- git checkout "${FFMPEG_VERSION}"
- export PKG_CONFIG_PATH="${PREFIX}/lib/pkgconfig"
- # Prohibit pkg-config from using linux system installed libs.
- export PKG_CONFIG_LIBDIR=
-
- local ffmpeg_arch=""
- local ffmpeg_target_os=""
- if [[ $arch == "win64" ]]; then
- ffmpeg_arch="x86_64";
- ffmpeg_target_os="mingw32"
- elif [[ $arch == "linux-arm64" ]]; then
- ffmpeg_arch="arm64";
- ffmpeg_target_os="linux"
- else
- die "ERROR: unsupported arch to compile ffmpeg - $arch"
- fi
- ./configure --arch="${ffmpeg_arch}" \
- --target-os="${ffmpeg_target_os}" \
- --cross-prefix="${toolchain_prefix}" \
- --disable-doc \
- --pkg-config=pkg-config \
- --pkg-config-flags="--static" \
- --extra-cflags="-I/${PREFIX}/include" \
- --extra-ldflags="-L/${PREFIX}/lib -static" \
- --prefix="${PREFIX}" \
- --bindir="${PWD}/bin" \
- ${FFMPEG_CONFIG}
- make && make install
-}
-
-trap "cd $(pwd -P)" EXIT
-cd "$(dirname $0)"
-
-source ./CONFIG.sh
-
-apt-get update
-apt-get install -y git make yasm pkg-config
-if [[ "${arch}" == "linux-arm64" ]]; then
- apt-get install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
-else
- apt-get install -y mingw-w64
-fi
-
-build_zlib
-build_libvpx
-build_ffmpeg
-
-# put resulting executable where we were asked to
-cp "${HOME}/ffmpeg/bin/${binary}" "${output_path}"
-${toolchain_prefix}strip "${output_path}"
diff --git a/browser_patches/ffmpeg/ffmpeg-license/COPYING.LGPLv2.1 b/browser_patches/ffmpeg/ffmpeg-license/COPYING.LGPLv2.1
deleted file mode 100644
index 58af0d3787aec7..00000000000000
--- a/browser_patches/ffmpeg/ffmpeg-license/COPYING.LGPLv2.1
+++ /dev/null
@@ -1,502 +0,0 @@
- GNU LESSER GENERAL PUBLIC LICENSE
- Version 2.1, February 1999
-
- Copyright (C) 1991, 1999 Free Software Foundation, Inc.
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the Lesser GPL. It also counts
- as the successor of the GNU Library Public License, version 2, hence
- the version number 2.1.]
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
- This license, the Lesser General Public License, applies to some
-specially designated software packages--typically libraries--of the
-Free Software Foundation and other authors who decide to use it. You
-can use it too, but we suggest you first think carefully about whether
-this license or the ordinary General Public License is the better
-strategy to use in any particular case, based on the explanations below.
-
- When we speak of free software, we are referring to freedom of use,
-not price. Our General Public Licenses are designed to make sure that
-you have the freedom to distribute copies of free software (and charge
-for this service if you wish); that you receive source code or can get
-it if you want it; that you can change the software and use pieces of
-it in new free programs; and that you are informed that you can do
-these things.
-
- To protect your rights, we need to make restrictions that forbid
-distributors to deny you these rights or to ask you to surrender these
-rights. These restrictions translate to certain responsibilities for
-you if you distribute copies of the library or if you modify it.
-
- For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you. You must make sure that they, too, receive or can get the source
-code. If you link other code with the library, you must provide
-complete object files to the recipients, so that they can relink them
-with the library after making changes to the library and recompiling
-it. And you must show them these terms so they know their rights.
-
- We protect your rights with a two-step method: (1) we copyright the
-library, and (2) we offer you this license, which gives you legal
-permission to copy, distribute and/or modify the library.
-
- To protect each distributor, we want to make it very clear that
-there is no warranty for the free library. Also, if the library is
-modified by someone else and passed on, the recipients should know
-that what they have is not the original version, so that the original
-author's reputation will not be affected by problems that might be
-introduced by others.
-
- Finally, software patents pose a constant threat to the existence of
-any free program. We wish to make sure that a company cannot
-effectively restrict the users of a free program by obtaining a
-restrictive license from a patent holder. Therefore, we insist that
-any patent license obtained for a version of the library must be
-consistent with the full freedom of use specified in this license.
-
- Most GNU software, including some libraries, is covered by the
-ordinary GNU General Public License. This license, the GNU Lesser
-General Public License, applies to certain designated libraries, and
-is quite different from the ordinary General Public License. We use
-this license for certain libraries in order to permit linking those
-libraries into non-free programs.
-
- When a program is linked with a library, whether statically or using
-a shared library, the combination of the two is legally speaking a
-combined work, a derivative of the original library. The ordinary
-General Public License therefore permits such linking only if the
-entire combination fits its criteria of freedom. The Lesser General
-Public License permits more lax criteria for linking other code with
-the library.
-
- We call this license the "Lesser" General Public License because it
-does Less to protect the user's freedom than the ordinary General
-Public License. It also provides other free software developers Less
-of an advantage over competing non-free programs. These disadvantages
-are the reason we use the ordinary General Public License for many
-libraries. However, the Lesser license provides advantages in certain
-special circumstances.
-
- For example, on rare occasions, there may be a special need to
-encourage the widest possible use of a certain library, so that it becomes
-a de-facto standard. To achieve this, non-free programs must be
-allowed to use the library. A more frequent case is that a free
-library does the same job as widely used non-free libraries. In this
-case, there is little to gain by limiting the free library to free
-software only, so we use the Lesser General Public License.
-
- In other cases, permission to use a particular library in non-free
-programs enables a greater number of people to use a large body of
-free software. For example, permission to use the GNU C Library in
-non-free programs enables many more people to use the whole GNU
-operating system, as well as its variant, the GNU/Linux operating
-system.
-
- Although the Lesser General Public License is Less protective of the
-users' freedom, it does ensure that the user of a program that is
-linked with the Library has the freedom and the wherewithal to run
-that program using a modified version of the Library.
-
- The precise terms and conditions for copying, distribution and
-modification follow. Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library". The
-former contains code derived from the library, whereas the latter must
-be combined with the library in order to run.
-
- GNU LESSER GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License Agreement applies to any software library or other
-program which contains a notice placed by the copyright holder or
-other authorized party saying it may be distributed under the terms of
-this Lesser General Public License (also called "this License").
-Each licensee is addressed as "you".
-
- A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
- The "Library", below, refers to any such software library or work
-which has been distributed under these terms. A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language. (Hereinafter, translation is
-included without limitation in the term "modification".)
-
- "Source code" for a work means the preferred form of the work for
-making modifications to it. For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
- Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it). Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-
- 1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
- You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-
- 2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) The modified work must itself be a software library.
-
- b) You must cause the files modified to carry prominent notices
- stating that you changed the files and the date of any change.
-
- c) You must cause the whole of the work to be licensed at no
- charge to all third parties under the terms of this License.
-
- d) If a facility in the modified Library refers to a function or a
- table of data to be supplied by an application program that uses
- the facility, other than as an argument passed when the facility
- is invoked, then you must make a good faith effort to ensure that,
- in the event an application does not supply such function or
- table, the facility still operates, and performs whatever part of
- its purpose remains meaningful.
-
- (For example, a function in a library to compute square roots has
- a purpose that is entirely well-defined independent of the
- application. Therefore, Subsection 2d requires that any
- application-supplied function or table used by this function must
- be optional: if the application does not supply it, the square
- root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library. To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License. (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.) Do not make any other change in
-these notices.
-
- Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
- This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
- 4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
- If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library". Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
- However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library". The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
- When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library. The
-threshold for this to be true is not precisely defined by law.
-
- If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work. (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
- Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-
- 6. As an exception to the Sections above, you may also combine or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
- You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License. You must supply a copy of this License. If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License. Also, you must do one
-of these things:
-
- a) Accompany the work with the complete corresponding
- machine-readable source code for the Library including whatever
- changes were used in the work (which must be distributed under
- Sections 1 and 2 above); and, if the work is an executable linked
- with the Library, with the complete machine-readable "work that
- uses the Library", as object code and/or source code, so that the
- user can modify the Library and then relink to produce a modified
- executable containing the modified Library. (It is understood
- that the user who changes the contents of definitions files in the
- Library will not necessarily be able to recompile the application
- to use the modified definitions.)
-
- b) Use a suitable shared library mechanism for linking with the
- Library. A suitable mechanism is one that (1) uses at run time a
- copy of the library already present on the user's computer system,
- rather than copying library functions into the executable, and (2)
- will operate properly with a modified version of the library, if
- the user installs one, as long as the modified version is
- interface-compatible with the version that the work was made with.
-
- c) Accompany the work with a written offer, valid for at
- least three years, to give the same user the materials
- specified in Subsection 6a, above, for a charge no more
- than the cost of performing this distribution.
-
- d) If distribution of the work is made by offering access to copy
- from a designated place, offer equivalent access to copy the above
- specified materials from the same place.
-
- e) Verify that the user has already received a copy of these
- materials or that you have already sent this user a copy.
-
- For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it. However, as a special exception,
-the materials to be distributed need not include anything that is
-normally distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
- It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system. Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-
- 7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
- a) Accompany the combined library with a copy of the same work
- based on the Library, uncombined with any other library
- facilities. This must be distributed under the terms of the
- Sections above.
-
- b) Give prominent notice with the combined library of the fact
- that part of it is a work based on the Library, and explaining
- where to find the accompanying uncombined form of the same work.
-
- 8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License. Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License. However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
- 9. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Library or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
- 10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties with
-this License.
-
- 11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all. For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded. In such case, this License incorporates the limitation as if
-written in the body of this License.
-
- 13. The Free Software Foundation may publish revised and/or new
-versions of the Lesser General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation. If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-
- 14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission. For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this. Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
- NO WARRANTY
-
- 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Libraries
-
- If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change. You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
- To apply these terms, attach the following notices to the library. It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
-
- Copyright (C)
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the
- library `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
- , 1 April 1990
- Ty Coon, President of Vice
-
-That's all there is to it!
diff --git a/browser_patches/firefox-beta/.gitignore b/browser_patches/firefox-beta/.gitignore
deleted file mode 100644
index 5e660dc18ee09d..00000000000000
--- a/browser_patches/firefox-beta/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/checkout
diff --git a/browser_patches/firefox-beta/BUILD_NUMBER b/browser_patches/firefox-beta/BUILD_NUMBER
deleted file mode 100644
index 3a5b7616276061..00000000000000
--- a/browser_patches/firefox-beta/BUILD_NUMBER
+++ /dev/null
@@ -1,2 +0,0 @@
-1347
-Changed: aslushnikov@gmail.com Sat Aug 13 14:56:35 MSK 2022
diff --git a/browser_patches/firefox-beta/EXPECTED_BUILDS b/browser_patches/firefox-beta/EXPECTED_BUILDS
deleted file mode 100644
index 1ef87929ac3838..00000000000000
--- a/browser_patches/firefox-beta/EXPECTED_BUILDS
+++ /dev/null
@@ -1,9 +0,0 @@
-firefox-beta-mac-11.zip
-firefox-beta-mac-11-arm64.zip
-firefox-beta-ubuntu-18.04.zip
-firefox-beta-ubuntu-20.04.zip
-firefox-beta-ubuntu-20.04-arm64.zip
-firefox-beta-ubuntu-22.04.zip
-firefox-beta-ubuntu-22.04-arm64.zip
-firefox-beta-debian-11.zip
-firefox-beta-win64.zip
diff --git a/browser_patches/firefox-beta/UPSTREAM_CONFIG.sh b/browser_patches/firefox-beta/UPSTREAM_CONFIG.sh
deleted file mode 100644
index 5f19bdfda533d5..00000000000000
--- a/browser_patches/firefox-beta/UPSTREAM_CONFIG.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-REMOTE_URL="https://github.com/mozilla/gecko-dev"
-BASE_BRANCH="beta"
-BASE_REVISION="762e3edda145d3196066dcd86f2eb8806a66a9c7"
diff --git a/browser_patches/firefox-beta/archive.sh b/browser_patches/firefox-beta/archive.sh
deleted file mode 100755
index 99dd2c31cb21fb..00000000000000
--- a/browser_patches/firefox-beta/archive.sh
+++ /dev/null
@@ -1,61 +0,0 @@
-#!/bin/bash
-set -e
-set +x
-
-if [[ ("$1" == "-h") || ("$1" == "--help") ]]; then
- echo "usage: $(basename "$0") [output-absolute-path]"
- echo
- echo "Generate distributable .zip archive from Firefox checkout folder that was previously built."
- echo
- exit 0
-fi
-
-ZIP_PATH=$1
-if [[ $ZIP_PATH != /* ]]; then
- echo "ERROR: path $ZIP_PATH is not absolute"
- exit 1
-fi
-if [[ $ZIP_PATH != *.zip ]]; then
- echo "ERROR: path $ZIP_PATH must have .zip extension"
- exit 1
-fi
-if [[ -f $ZIP_PATH ]]; then
- echo "ERROR: path $ZIP_PATH exists; can't do anything."
- exit 1
-fi
-if ! [[ -d $(dirname "$ZIP_PATH") ]]; then
- echo "ERROR: folder for path $($ZIP_PATH) does not exist."
- exit 1
-fi
-
-trap "cd $(pwd -P)" EXIT
-cd "$(dirname "$0")"
-SCRIPT_FOLDER="$(pwd -P)"
-source "${SCRIPT_FOLDER}/../utils.sh"
-
-if [[ -z "${FF_CHECKOUT_PATH}" ]]; then
- FF_CHECKOUT_PATH="$HOME/firefox"
-fi
-OBJ_FOLDER="${FF_CHECKOUT_PATH}/obj-build-playwright"
-
-cd "${FF_CHECKOUT_PATH}"
-
-export MH_BRANCH=mozilla-beta
-export MOZ_BUILD_DATE=$(date +%Y%m%d%H%M%S)
-./mach package
-node "${SCRIPT_FOLDER}/install-preferences.js" "${OBJ_FOLDER}/dist/firefox"
-
-if ! [[ -d "$OBJ_FOLDER/dist/firefox" ]]; then
- echo "ERROR: cannot find $OBJ_FOLDER/dist/firefox folder in the firefox checkout. Did you build?"
- exit 1;
-fi
-
-if is_win; then
- # Bundle vcruntime14_1.dll - see https://github.com/microsoft/playwright/issues/9974
- cd "$(printMSVCRedistDir)"
- cp -t "${OBJ_FOLDER}/dist/firefox" vcruntime140_1.dll
-fi
-
-# tar resulting directory and cleanup TMP.
-cd "${OBJ_FOLDER}/dist"
-zip -r "$ZIP_PATH" firefox
diff --git a/browser_patches/firefox-beta/build.sh b/browser_patches/firefox-beta/build.sh
deleted file mode 100755
index 4f2e8c1b54917c..00000000000000
--- a/browser_patches/firefox-beta/build.sh
+++ /dev/null
@@ -1,153 +0,0 @@
-#!/bin/bash
-set -e
-set +x
-
-RUST_VERSION="1.59.0"
-CBINDGEN_VERSION="0.24.3"
-
-trap "cd $(pwd -P)" EXIT
-
-cd "$(dirname "$0")"
-SCRIPT_FOLDER="$(pwd -P)"
-source "${SCRIPT_FOLDER}/../utils.sh"
-
-if [[ ! -z "${FF_CHECKOUT_PATH}" ]]; then
- cd "${FF_CHECKOUT_PATH}"
- echo "WARNING: checkout path from FF_CHECKOUT_PATH env: ${FF_CHECKOUT_PATH}"
-else
- cd "$HOME/firefox"
-fi
-
-args=("$@")
-IS_FULL=""
-IS_JUGGLER=""
-IS_DEBUG=""
-for ((i="${#args[@]}"-1; i >= 0; --i)); do
- case ${args[i]} in
- --full) IS_FULL="1"; unset args[i]; ;;
- --juggler) IS_JUGGLER="1"; unset args[i]; ;;
- --debug) IS_DEBUG="1"; unset args[i]; ;;
- esac
-done
-
-if [[ -n "${IS_JUGGLER}" && -n "${IS_FULL}" ]]; then
- echo "ERROR: either --full or --juggler is allowed"
- exit 1
-fi
-
-echo "== BUILD CONFIGURATION =="
-if [[ -n "${IS_FULL}" ]]; then
- echo "- build type: FULL"
-elif [[ -n "${IS_JUGGLER}" ]]; then
- echo "- build type: JUGGLER"
-else
- echo "- build type: INCREMENTAL"
-fi
-
-if [[ -n "${IS_DEBUG}" ]]; then
- echo "- debug: YES"
-else
- echo "- debug: NO"
-fi
-
-echo "========================="
-
-rm -rf .mozconfig
-
-if is_mac; then
- selectXcodeVersionOrDie $(node "${SCRIPT_FOLDER}/../get_xcode_version.js" firefox)
- echo "-- building on Mac"
-elif is_linux; then
- echo "-- building on Linux"
-elif is_win; then
- echo "ac_add_options --disable-update-agent" >> .mozconfig
- echo "ac_add_options --disable-default-browser-agent" >> .mozconfig
- echo "ac_add_options --disable-maintenance-service" >> .mozconfig
-
- echo "-- building win64 build on MINGW"
- echo "ac_add_options --target=x86_64-pc-mingw32" >> .mozconfig
- echo "ac_add_options --host=x86_64-pc-mingw32" >> .mozconfig
- DLL_FILE=$("C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -find '**\Redist\MSVC\*\x64\**\vcruntime140.dll')
- WIN32_REDIST_DIR=$(dirname "$DLL_FILE" | tail -n 1)
- if ! [[ -d $WIN32_REDIST_DIR ]]; then
- echo "ERROR: cannot find MS VS C++ redistributable $WIN32_REDIST_DIR"
- exit 1;
- fi
-else
- echo "ERROR: cannot upload on this platform!" 1>&2
- exit 1;
-fi
-
-# There's no pre-built wasi sysroot on certain platforms.
-echo "ac_add_options --without-wasm-sandboxed-libraries" >> .mozconfig
-
-OBJ_FOLDER="obj-build-playwright"
-echo "mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/${OBJ_FOLDER}" >> .mozconfig
-echo "ac_add_options --disable-crashreporter" >> .mozconfig
-echo "ac_add_options --disable-backgroundtasks" >> .mozconfig
-
-if [[ -n "${IS_DEBUG}" ]]; then
- echo "ac_add_options --enable-debug" >> .mozconfig
- echo "ac_add_options --enable-debug-symbols" >> .mozconfig
-else
- echo "ac_add_options --enable-release" >> .mozconfig
-fi
-
-if is_mac || is_win; then
- # This options is only available on win and mac.
- echo "ac_add_options --disable-update-agent" >> .mozconfig
-fi
-
-if [[ -z "${IS_JUGGLER}" ]]; then
- # TODO: rustup is not in the PATH on Windows
- if command -v rustup >/dev/null; then
- # We manage Rust version ourselves.
- echo "-- Using rust v${RUST_VERSION}"
- rustup install "${RUST_VERSION}"
- rustup default "${RUST_VERSION}"
- fi
- # Firefox on Linux arm64 host does not ship
- # cbindgen in their default toolchains - install manually.
- if command -v cargo >/dev/null; then
- echo "-- Using cbindgen v${CBINDGEN_VERSION}"
- cargo install cbindgen --version "${CBINDGEN_VERSION}"
- fi
-fi
-
-if [[ -n "${IS_FULL}" ]]; then
- # This is a slow but sure way to get all the necessary toolchains.
- # However, it will not work if tree is dirty.
- # Bail out if git repo is dirty.
- if [[ -n $(git status -s --untracked-files=no) ]]; then
- echo "ERROR: dirty GIT state - commit everything and re-run the script."
- exit 1
- fi
-
- # 1. We have a --single-branch checkout, so we have to add a "master" branch and fetch it
- git remote set-branches --add browser_upstream master
- git fetch --depth 1 browser_upstream master
- # 2. Checkout the master branch and run bootstrap from it.
- git checkout browser_upstream/master
- echo "ac_add_options --enable-bootstrap" >> .mozconfig
- SHELL=/bin/sh ./mach --no-interactive bootstrap --application-choice=browser
- git checkout -
- rm -rf "${OBJ_FOLDER}"
-
- if [[ -n "${WIN32_REDIST_DIR}" ]]; then
- # Having this option in .mozconfig kills incremental compilation.
- echo "export WIN32_REDIST_DIR=\"$WIN32_REDIST_DIR\"" >> .mozconfig
- fi
-fi
-
-if [[ -n "${IS_JUGGLER}" ]]; then
- ./mach build faster
-else
- ./mach build
- if is_mac; then
- FF_DEBUG_BUILD="${IS_DEBUG}" node "${SCRIPT_FOLDER}"/install-preferences.js "$PWD"/${OBJ_FOLDER}/dist
- else
- FF_DEBUG_BUILD="${IS_DEBUG}" node "${SCRIPT_FOLDER}"/install-preferences.js "$PWD"/${OBJ_FOLDER}/dist/bin
- fi
-fi
-
-
diff --git a/browser_patches/firefox-beta/clean.sh b/browser_patches/firefox-beta/clean.sh
deleted file mode 100755
index d94baf33a30d9d..00000000000000
--- a/browser_patches/firefox-beta/clean.sh
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-set -e
-set +x
-
-trap "cd $(pwd -P)" EXIT
-if [[ ! -z "${FF_CHECKOUT_PATH}" ]]; then
- cd "${FF_CHECKOUT_PATH}"
- echo "WARNING: checkout path from FF_CHECKOUT_PATH env: ${FF_CHECKOUT_PATH}"
-else
- cd "$HOME/firefox"
-fi
-
-OBJ_FOLDER="obj-build-playwright"
-if [[ -d $OBJ_FOLDER ]]; then
- rm -rf $OBJ_FOLDER
-fi
-
-if [[ -f "mach" ]]; then
- ./mach clobber || true
-fi
diff --git a/browser_patches/firefox-beta/install-preferences.js b/browser_patches/firefox-beta/install-preferences.js
deleted file mode 100644
index f82f791d54c053..00000000000000
--- a/browser_patches/firefox-beta/install-preferences.js
+++ /dev/null
@@ -1,100 +0,0 @@
-/**
- * Copyright 2018 Google Inc. All rights reserved.
- * Modifications copyright (c) Microsoft Corporation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-const os = require('os');
-const fs = require('fs');
-const path = require('path');
-const util = require('util');
-
-const writeFileAsync = util.promisify(fs.writeFile.bind(fs));
-const mkdirAsync = util.promisify(fs.mkdir.bind(fs));
-
-// Install browser preferences after downloading and unpacking
-// firefox instances.
-// Based on: https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Enterprise_deployment_before_60#Configuration
-async function installFirefoxPreferences(distpath) {
- let executablePath = '';
- if (os.platform() === 'linux')
- executablePath = path.join(distpath, 'firefox');
- else if (os.platform() === 'darwin')
- executablePath = path.join(distpath, (process.env.FF_DEBUG_BUILD ? 'NightlyDebug.app' : 'Nightly.app'), 'Contents', 'MacOS', 'firefox');
- else if (os.platform() === 'win32')
- executablePath = path.join(distpath, 'firefox.exe');
-
- const firefoxFolder = path.dirname(executablePath);
-
- let prefPath = '';
- let configPath = '';
- if (os.platform() === 'darwin') {
- prefPath = path.join(firefoxFolder, '..', 'Resources', 'defaults', 'pref');
- configPath = path.join(firefoxFolder, '..', 'Resources');
- } else if (os.platform() === 'linux') {
- if (!fs.existsSync(path.join(firefoxFolder, 'browser', 'defaults')))
- await mkdirAsync(path.join(firefoxFolder, 'browser', 'defaults'));
- if (!fs.existsSync(path.join(firefoxFolder, 'browser', 'defaults', 'preferences')))
- await mkdirAsync(path.join(firefoxFolder, 'browser', 'defaults', 'preferences'));
- prefPath = path.join(firefoxFolder, 'browser', 'defaults', 'preferences');
- configPath = firefoxFolder;
- } else if (os.platform() === 'win32') {
- prefPath = path.join(firefoxFolder, 'defaults', 'pref');
- configPath = firefoxFolder;
- } else {
- throw new Error('Unsupported platform: ' + os.platform());
- }
-
- await Promise.all([
- copyFile({
- from: path.join(__dirname, 'preferences', '00-playwright-prefs.js'),
- to: path.join(prefPath, '00-playwright-prefs.js'),
- }),
- copyFile({
- from: path.join(__dirname, 'preferences', 'playwright.cfg'),
- to: path.join(configPath, 'playwright.cfg'),
- }),
- ]);
-}
-
-function copyFile({from, to}) {
- const rd = fs.createReadStream(from);
- const wr = fs.createWriteStream(to);
- return new Promise(function(resolve, reject) {
- rd.on('error', reject);
- wr.on('error', reject);
- wr.on('finish', resolve);
- rd.pipe(wr);
- }).catch(function(error) {
- rd.destroy();
- wr.end();
- throw error;
- });
-}
-
-module.exports = { installFirefoxPreferences };
-
-if (require.main === module) {
- if (process.argv.length !== 3) {
- console.log('ERROR: expected a path to the directory with browser build');
- process.exit(1);
- return;
- }
-
- installFirefoxPreferences(process.argv[2]).catch(error => {
- console.error('ERROR: failed to put preferences!');
- console.error(error);
- process.exit(1);
- });
-}
diff --git a/browser_patches/firefox-beta/juggler/Helper.js b/browser_patches/firefox-beta/juggler/Helper.js
deleted file mode 100644
index 70d8aef0d37c43..00000000000000
--- a/browser_patches/firefox-beta/juggler/Helper.js
+++ /dev/null
@@ -1,135 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-const uuidGen = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator);
-const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
-
-class Helper {
-
- addObserver(handler, topic) {
- Services.obs.addObserver(handler, topic);
- return () => Services.obs.removeObserver(handler, topic);
- }
-
- addMessageListener(receiver, eventName, handler) {
- receiver.addMessageListener(eventName, handler);
- return () => receiver.removeMessageListener(eventName, handler);
- }
-
- addEventListener(receiver, eventName, handler) {
- receiver.addEventListener(eventName, handler);
- return () => receiver.removeEventListener(eventName, handler);
- }
-
- awaitEvent(receiver, eventName) {
- return new Promise(resolve => {
- receiver.addEventListener(eventName, function listener() {
- receiver.removeEventListener(eventName, listener);
- resolve();
- });
- });
- }
-
- on(receiver, eventName, handler) {
- // The toolkit/modules/EventEmitter.jsm dispatches event name as a first argument.
- // Fire event listeners without it for convenience.
- const handlerWrapper = (_, ...args) => handler(...args);
- receiver.on(eventName, handlerWrapper);
- return () => receiver.off(eventName, handlerWrapper);
- }
-
- addProgressListener(progress, listener, flags) {
- progress.addProgressListener(listener, flags);
- return () => progress.removeProgressListener(listener);
- }
-
- removeListeners(listeners) {
- for (const tearDown of listeners)
- tearDown.call(null);
- listeners.splice(0, listeners.length);
- }
-
- generateId() {
- const string = uuidGen.generateUUID().toString();
- return string.substring(1, string.length - 1);
- }
-
- getLoadContext(channel) {
- let loadContext = null;
- try {
- if (channel.notificationCallbacks)
- loadContext = channel.notificationCallbacks.getInterface(Ci.nsILoadContext);
- } catch (e) {}
- try {
- if (!loadContext && channel.loadGroup)
- loadContext = channel.loadGroup.notificationCallbacks.getInterface(Ci.nsILoadContext);
- } catch (e) { }
- return loadContext;
- }
-
- getNetworkErrorStatusText(status) {
- if (!status)
- return null;
- for (const key of Object.keys(Cr)) {
- if (Cr[key] === status)
- return key;
- }
- // Security module. The following is taken from
- // https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/How_to_check_the_secruity_state_of_an_XMLHTTPRequest_over_SSL
- if ((status & 0xff0000) === 0x5a0000) {
- // NSS_SEC errors (happen below the base value because of negative vals)
- if ((status & 0xffff) < Math.abs(Ci.nsINSSErrorsService.NSS_SEC_ERROR_BASE)) {
- // The bases are actually negative, so in our positive numeric space, we
- // need to subtract the base off our value.
- const nssErr = Math.abs(Ci.nsINSSErrorsService.NSS_SEC_ERROR_BASE) - (status & 0xffff);
- switch (nssErr) {
- case 11:
- return 'SEC_ERROR_EXPIRED_CERTIFICATE';
- case 12:
- return 'SEC_ERROR_REVOKED_CERTIFICATE';
- case 13:
- return 'SEC_ERROR_UNKNOWN_ISSUER';
- case 20:
- return 'SEC_ERROR_UNTRUSTED_ISSUER';
- case 21:
- return 'SEC_ERROR_UNTRUSTED_CERT';
- case 36:
- return 'SEC_ERROR_CA_CERT_INVALID';
- case 90:
- return 'SEC_ERROR_INADEQUATE_KEY_USAGE';
- case 176:
- return 'SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED';
- default:
- return 'SEC_ERROR_UNKNOWN';
- }
- }
- const sslErr = Math.abs(Ci.nsINSSErrorsService.NSS_SSL_ERROR_BASE) - (status & 0xffff);
- switch (sslErr) {
- case 3:
- return 'SSL_ERROR_NO_CERTIFICATE';
- case 4:
- return 'SSL_ERROR_BAD_CERTIFICATE';
- case 8:
- return 'SSL_ERROR_UNSUPPORTED_CERTIFICATE_TYPE';
- case 9:
- return 'SSL_ERROR_UNSUPPORTED_VERSION';
- case 12:
- return 'SSL_ERROR_BAD_CERT_DOMAIN';
- default:
- return 'SSL_ERROR_UNKNOWN';
- }
- }
- return '';
- }
-
- browsingContextToFrameId(browsingContext) {
- if (!browsingContext)
- return undefined;
- return 'frame-' + browsingContext.id;
- }
-}
-
-var EXPORTED_SYMBOLS = [ "Helper" ];
-this.Helper = Helper;
-
diff --git a/browser_patches/firefox-beta/juggler/NetworkObserver.js b/browser_patches/firefox-beta/juggler/NetworkObserver.js
deleted file mode 100644
index 340f756f6cfef0..00000000000000
--- a/browser_patches/firefox-beta/juggler/NetworkObserver.js
+++ /dev/null
@@ -1,947 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const {EventEmitter} = ChromeUtils.import('resource://gre/modules/EventEmitter.jsm');
-const {Helper} = ChromeUtils.import('chrome://juggler/content/Helper.js');
-const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
-const {NetUtil} = ChromeUtils.import('resource://gre/modules/NetUtil.jsm');
-const { ChannelEventSinkFactory } = ChromeUtils.import("chrome://remote/content/cdp/observers/ChannelEventSink.jsm");
-
-
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const Cu = Components.utils;
-const Cr = Components.results;
-const Cm = Components.manager;
-const CC = Components.Constructor;
-const helper = new Helper();
-
-const UINT32_MAX = Math.pow(2, 32)-1;
-
-const BinaryInputStream = CC('@mozilla.org/binaryinputstream;1', 'nsIBinaryInputStream', 'setInputStream');
-const BinaryOutputStream = CC('@mozilla.org/binaryoutputstream;1', 'nsIBinaryOutputStream', 'setOutputStream');
-const StorageStream = CC('@mozilla.org/storagestream;1', 'nsIStorageStream', 'init');
-
-// Cap response storage with 100Mb per tracked tab.
-const MAX_RESPONSE_STORAGE_SIZE = 100 * 1024 * 1024;
-
-const pageNetworkSymbol = Symbol('PageNetwork');
-
-class PageNetwork {
- static forPageTarget(target) {
- let result = target[pageNetworkSymbol];
- if (!result) {
- result = new PageNetwork(target);
- target[pageNetworkSymbol] = result;
- }
- return result;
- }
-
- constructor(target) {
- EventEmitter.decorate(this);
- this._target = target;
- this._extraHTTPHeaders = null;
- this._responseStorage = new ResponseStorage(MAX_RESPONSE_STORAGE_SIZE, MAX_RESPONSE_STORAGE_SIZE / 10);
- this._requestInterceptionEnabled = false;
- // This is requestId => NetworkRequest map, only contains requests that are
- // awaiting interception action (abort, resume, fulfill) over the protocol.
- this._interceptedRequests = new Map();
- }
-
- setExtraHTTPHeaders(headers) {
- this._extraHTTPHeaders = headers;
- }
-
- combinedExtraHTTPHeaders() {
- return [
- ...(this._target.browserContext().extraHTTPHeaders || []),
- ...(this._extraHTTPHeaders || []),
- ];
- }
-
- enableRequestInterception() {
- this._requestInterceptionEnabled = true;
- }
-
- disableRequestInterception() {
- this._requestInterceptionEnabled = false;
- for (const intercepted of this._interceptedRequests.values())
- intercepted.resume();
- this._interceptedRequests.clear();
- }
-
- resumeInterceptedRequest(requestId, url, method, headers, postData) {
- this._takeIntercepted(requestId).resume(url, method, headers, postData);
- }
-
- fulfillInterceptedRequest(requestId, status, statusText, headers, base64body) {
- this._takeIntercepted(requestId).fulfill(status, statusText, headers, base64body);
- }
-
- abortInterceptedRequest(requestId, errorCode) {
- this._takeIntercepted(requestId).abort(errorCode);
- }
-
- getResponseBody(requestId) {
- if (!this._responseStorage)
- throw new Error('Responses are not tracked for the given browser');
- return this._responseStorage.getBase64EncodedResponse(requestId);
- }
-
- _takeIntercepted(requestId) {
- const intercepted = this._interceptedRequests.get(requestId);
- if (!intercepted)
- throw new Error(`Cannot find request "${requestId}"`);
- this._interceptedRequests.delete(requestId);
- return intercepted;
- }
-}
-
-class NetworkRequest {
- constructor(networkObserver, httpChannel, redirectedFrom) {
- this._networkObserver = networkObserver;
- this.httpChannel = httpChannel;
-
- const loadInfo = this.httpChannel.loadInfo;
- let browsingContext = loadInfo?.frameBrowsingContext || loadInfo?.browsingContext;
- // TODO: Unfortunately, requests from web workers don't have frameBrowsingContext or
- // browsingContext.
- //
- // We fail to attribute them to the original frames on the browser side, but we
- // can use load context top frame to attribute them to the top frame at least.
- if (!browsingContext) {
- const loadContext = helper.getLoadContext(this.httpChannel);
- browsingContext = loadContext?.topFrameElement?.browsingContext;
- }
-
- this._frameId = helper.browsingContextToFrameId(browsingContext);
-
- this.requestId = httpChannel.channelId + '';
- this.navigationId = httpChannel.isMainDocumentChannel ? this.requestId : undefined;
-
- this._redirectedIndex = 0;
- if (redirectedFrom) {
- this.redirectedFromId = redirectedFrom.requestId;
- this._redirectedIndex = redirectedFrom._redirectedIndex + 1;
- this.requestId = this.requestId + '-redirect' + this._redirectedIndex;
- this.navigationId = redirectedFrom.navigationId;
- // Finish previous request now. Since we inherit the listener, we could in theory
- // use onStopRequest, but that will only happen after the last redirect has finished.
- redirectedFrom._sendOnRequestFinished();
- }
- // In case of proxy auth, we get two requests with the same channel:
- // - one is pre-auth
- // - second is with auth header.
- //
- // In this case, we create this NetworkRequest object with a `redirectedFrom`
- // object, and they both share the same httpChannel.
- //
- // Since we want to maintain _channelToRequest map without clashes,
- // we must call `_sendOnRequestFinished` **before** we update it with a new object
- // here.
- if (this._networkObserver._channelToRequest.has(this.httpChannel))
- throw new Error(`Internal Error: invariant is broken for _channelToRequest map`);
- this._networkObserver._channelToRequest.set(this.httpChannel, this);
-
- this._pageNetwork = redirectedFrom ? redirectedFrom._pageNetwork : networkObserver._findPageNetwork(httpChannel);
- this._expectingInterception = false;
- this._expectingResumedRequest = undefined; // { method, headers, postData }
- this._sentOnResponse = false;
-
- if (this._pageNetwork)
- appendExtraHTTPHeaders(httpChannel, this._pageNetwork.combinedExtraHTTPHeaders());
-
- this._responseBodyChunks = [];
-
- httpChannel.QueryInterface(Ci.nsITraceableChannel);
- this._originalListener = httpChannel.setNewListener(this);
- if (redirectedFrom) {
- // Listener is inherited for regular redirects, so we'd like to avoid
- // calling into previous NetworkRequest.
- this._originalListener = redirectedFrom._originalListener;
- }
-
- this._previousCallbacks = httpChannel.notificationCallbacks;
- httpChannel.notificationCallbacks = this;
-
- this.QueryInterface = ChromeUtils.generateQI([
- Ci.nsIAuthPrompt2,
- Ci.nsIAuthPromptProvider,
- Ci.nsIInterfaceRequestor,
- Ci.nsINetworkInterceptController,
- Ci.nsIStreamListener,
- ]);
-
- if (this.redirectedFromId) {
- // Redirects are not interceptable.
- this._sendOnRequest(false);
- }
- }
-
- // Public interception API.
- resume(url, method, headers, postData) {
- this._expectingResumedRequest = { method, headers, postData };
- const newUri = url ? Services.io.newURI(url) : null;
- this._interceptedChannel.resetInterceptionWithURI(newUri);
- this._interceptedChannel = undefined;
- }
-
- // Public interception API.
- abort(errorCode) {
- const error = errorMap[errorCode] || Cr.NS_ERROR_FAILURE;
- this._interceptedChannel.cancelInterception(error);
- this._interceptedChannel = undefined;
- }
-
- // Public interception API.
- fulfill(status, statusText, headers, base64body) {
- this._interceptedChannel.synthesizeStatus(status, statusText);
- for (const header of headers) {
- this._interceptedChannel.synthesizeHeader(header.name, header.value);
- if (header.name.toLowerCase() === 'set-cookie') {
- Services.cookies.QueryInterface(Ci.nsICookieService);
- Services.cookies.setCookieStringFromHttp(this.httpChannel.URI, header.value, this.httpChannel);
- }
- }
- const synthesized = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(Ci.nsIStringInputStream);
- synthesized.data = base64body ? atob(base64body) : '';
- this._interceptedChannel.startSynthesizedResponse(synthesized, null, null, '', false);
- this._interceptedChannel.finishSynthesizedResponse();
- this._interceptedChannel = undefined;
- }
-
- // Instrumentation called by NetworkObserver.
- _onInternalRedirect(newChannel) {
- // Intercepted requests produce "internal redirects" - this is both for our own
- // interception and service workers.
- // An internal redirect has the same channelId, inherits notificationCallbacks and
- // listener, and should be used instead of an old channel.
- this._networkObserver._channelToRequest.delete(this.httpChannel);
- this.httpChannel = newChannel;
- this._networkObserver._channelToRequest.set(this.httpChannel, this);
- }
-
- // Instrumentation called by NetworkObserver.
- _onInternalRedirectReady() {
- // Resumed request is first internally redirected to a new request,
- // and then the new request is ready to be updated.
- if (!this._expectingResumedRequest)
- return;
- const { method, headers, postData } = this._expectingResumedRequest;
- this._expectingResumedRequest = undefined;
-
- if (headers) {
- for (const header of requestHeaders(this.httpChannel))
- this.httpChannel.setRequestHeader(header.name, '', false /* merge */);
- for (const header of headers)
- this.httpChannel.setRequestHeader(header.name, header.value, false /* merge */);
- } else if (this._pageNetwork) {
- appendExtraHTTPHeaders(this.httpChannel, this._pageNetwork.combinedExtraHTTPHeaders());
- }
- if (method)
- this.httpChannel.requestMethod = method;
- if (postData !== undefined)
- setPostData(this.httpChannel, postData, headers);
- }
-
- // nsIInterfaceRequestor
- getInterface(iid) {
- if (iid.equals(Ci.nsIAuthPrompt2) || iid.equals(Ci.nsIAuthPromptProvider) || iid.equals(Ci.nsINetworkInterceptController))
- return this;
- if (iid.equals(Ci.nsIAuthPrompt)) // Block nsIAuthPrompt - we want nsIAuthPrompt2 to be used instead.
- throw Cr.NS_ERROR_NO_INTERFACE;
- if (this._previousCallbacks)
- return this._previousCallbacks.getInterface(iid);
- throw Cr.NS_ERROR_NO_INTERFACE;
- }
-
- // nsIAuthPromptProvider
- getAuthPrompt(aPromptReason, iid) {
- return this;
- }
-
- // nsIAuthPrompt2
- asyncPromptAuth(aChannel, aCallback, aContext, level, authInfo) {
- let canceled = false;
- Promise.resolve().then(() => {
- if (canceled)
- return;
- const hasAuth = this.promptAuth(aChannel, level, authInfo);
- if (hasAuth)
- aCallback.onAuthAvailable(aContext, authInfo);
- else
- aCallback.onAuthCancelled(aContext, true);
- });
- return {
- QueryInterface: ChromeUtils.generateQI([Ci.nsICancelable]),
- cancel: () => {
- aCallback.onAuthCancelled(aContext, false);
- canceled = true;
- }
- };
- }
-
- // nsIAuthPrompt2
- promptAuth(aChannel, level, authInfo) {
- if (authInfo.flags & Ci.nsIAuthInformation.PREVIOUS_FAILED)
- return false;
- const pageNetwork = this._pageNetwork;
- if (!pageNetwork)
- return false;
- let credentials = null;
- if (authInfo.flags & Ci.nsIAuthInformation.AUTH_PROXY) {
- const proxy = this._networkObserver._targetRegistry.getProxyInfo(aChannel);
- credentials = proxy ? {username: proxy.username, password: proxy.password} : null;
- } else {
- credentials = pageNetwork._target.browserContext().httpCredentials;
- }
- if (!credentials)
- return false;
- authInfo.username = credentials.username;
- authInfo.password = credentials.password;
- // This will produce a new request with respective auth header set.
- // It will have the same id as ours. We expect it to arrive as new request and
- // will treat it as our own redirect.
- this._networkObserver._expectRedirect(this.httpChannel.channelId + '', this);
- return true;
- }
-
- // nsINetworkInterceptController
- shouldPrepareForIntercept(aURI, channel) {
- const interceptController = this._fallThroughInterceptController();
- if (interceptController && interceptController.shouldPrepareForIntercept(aURI, channel)) {
- // We assume that interceptController is a service worker if there is one,
- // and yield interception to it. We are not going to intercept ourselves,
- // so we send onRequest now.
- this._sendOnRequest(false);
- return true;
- }
-
- if (channel !== this.httpChannel) {
- // Not our channel? Just in case this happens, don't do anything.
- return false;
- }
-
- // We do not want to intercept any redirects, because we are not able
- // to intercept subresource redirects, and it's unreliable for main requests.
- // We do not sendOnRequest here, because redirects do that in constructor.
- if (this.redirectedFromId)
- return false;
-
- const shouldIntercept = this._shouldIntercept();
- if (!shouldIntercept) {
- // We are not intercepting - ready to issue onRequest.
- this._sendOnRequest(false);
- return false;
- }
-
- this._expectingInterception = true;
- return true;
- }
-
- // nsINetworkInterceptController
- channelIntercepted(intercepted) {
- if (!this._expectingInterception) {
- // We are not intercepting, fall-through.
- const interceptController = this._fallThroughInterceptController();
- if (interceptController)
- interceptController.channelIntercepted(intercepted);
- return;
- }
-
- this._expectingInterception = false;
- this._interceptedChannel = intercepted.QueryInterface(Ci.nsIInterceptedChannel);
-
- const pageNetwork = this._pageNetwork;
- if (!pageNetwork) {
- // Just in case we disabled instrumentation while intercepting, resume and forget.
- this.resume();
- return;
- }
-
- const browserContext = pageNetwork._target.browserContext();
- if (browserContext.settings.onlineOverride === 'offline') {
- // Implement offline.
- this.abort(Cr.NS_ERROR_OFFLINE);
- return;
- }
-
- // Ok, so now we have intercepted the request, let's issue onRequest.
- // If interception has been disabled while we were intercepting, resume and forget.
- const interceptionEnabled = this._shouldIntercept();
- this._sendOnRequest(!!interceptionEnabled);
- if (interceptionEnabled)
- pageNetwork._interceptedRequests.set(this.requestId, this);
- else
- this.resume();
- }
-
- // nsIStreamListener
- onDataAvailable(aRequest, aInputStream, aOffset, aCount) {
- // Turns out webcompat shims might redirect to
- // SimpleChannel, so we get requests from a different channel.
- // See https://github.com/microsoft/playwright/issues/9418#issuecomment-944836244
- if (aRequest !== this.httpChannel)
- return;
- // For requests with internal redirect (e.g. intercepted by Service Worker),
- // we do not get onResponse normally, but we do get nsIStreamListener notifications.
- this._sendOnResponse(false);
-
- const iStream = new BinaryInputStream(aInputStream);
- const sStream = new StorageStream(8192, aCount, null);
- const oStream = new BinaryOutputStream(sStream.getOutputStream(0));
-
- // Copy received data as they come.
- const data = iStream.readBytes(aCount);
- this._responseBodyChunks.push(data);
-
- oStream.writeBytes(data, aCount);
- try {
- this._originalListener.onDataAvailable(aRequest, sStream.newInputStream(0), aOffset, aCount);
- } catch (e) {
- // Be ready to original listener exceptions.
- }
- }
-
- // nsIStreamListener
- onStartRequest(aRequest) {
- // Turns out webcompat shims might redirect to
- // SimpleChannel, so we get requests from a different channel.
- // See https://github.com/microsoft/playwright/issues/9418#issuecomment-944836244
- if (aRequest !== this.httpChannel)
- return;
- try {
- this._originalListener.onStartRequest(aRequest);
- } catch (e) {
- // Be ready to original listener exceptions.
- }
- }
-
- // nsIStreamListener
- onStopRequest(aRequest, aStatusCode) {
- // Turns out webcompat shims might redirect to
- // SimpleChannel, so we get requests from a different channel.
- // See https://github.com/microsoft/playwright/issues/9418#issuecomment-944836244
- if (aRequest !== this.httpChannel)
- return;
- try {
- this._originalListener.onStopRequest(aRequest, aStatusCode);
- } catch (e) {
- // Be ready to original listener exceptions.
- }
-
- if (aStatusCode === 0) {
- // For requests with internal redirect (e.g. intercepted by Service Worker),
- // we do not get onResponse normally, but we do get nsIRequestObserver notifications.
- this._sendOnResponse(false);
- const body = this._responseBodyChunks.join('');
- const pageNetwork = this._pageNetwork;
- if (pageNetwork)
- pageNetwork._responseStorage.addResponseBody(this, body);
- this._sendOnRequestFinished();
- } else {
- this._sendOnRequestFailed(aStatusCode);
- }
-
- delete this._responseBodyChunks;
- }
-
- _shouldIntercept() {
- const pageNetwork = this._pageNetwork;
- if (!pageNetwork)
- return false;
- if (pageNetwork._requestInterceptionEnabled)
- return true;
- const browserContext = pageNetwork._target.browserContext();
- if (browserContext.requestInterceptionEnabled)
- return true;
- if (browserContext.settings.onlineOverride === 'offline')
- return true;
- return false;
- }
-
- _fallThroughInterceptController() {
- if (!this._previousCallbacks || !(this._previousCallbacks instanceof Ci.nsINetworkInterceptController))
- return undefined;
- return this._previousCallbacks.getInterface(Ci.nsINetworkInterceptController);
- }
-
- _sendOnRequest(isIntercepted) {
- // Note: we call _sendOnRequest either after we intercepted the request,
- // or at the first moment we know that we are not going to intercept.
- const pageNetwork = this._pageNetwork;
- if (!pageNetwork)
- return;
- const loadInfo = this.httpChannel.loadInfo;
- const causeType = loadInfo?.externalContentPolicyType || Ci.nsIContentPolicy.TYPE_OTHER;
- const internalCauseType = loadInfo?.internalContentPolicyType || Ci.nsIContentPolicy.TYPE_OTHER;
- pageNetwork.emit(PageNetwork.Events.Request, {
- url: this.httpChannel.URI.spec,
- frameId: this._frameId,
- isIntercepted,
- requestId: this.requestId,
- redirectedFrom: this.redirectedFromId,
- postData: readRequestPostData(this.httpChannel),
- headers: requestHeaders(this.httpChannel),
- method: this.httpChannel.requestMethod,
- navigationId: this.navigationId,
- cause: causeTypeToString(causeType),
- internalCause: causeTypeToString(internalCauseType),
- }, this._frameId);
- }
-
- _sendOnResponse(fromCache, opt_statusCode, opt_statusText) {
- if (this._sentOnResponse) {
- // We can come here twice because of internal redirects, e.g. service workers.
- return;
- }
- this._sentOnResponse = true;
- const pageNetwork = this._pageNetwork;
- if (!pageNetwork)
- return;
-
- this.httpChannel.QueryInterface(Ci.nsIHttpChannelInternal);
- this.httpChannel.QueryInterface(Ci.nsITimedChannel);
- const timing = {
- startTime: this.httpChannel.channelCreationTime,
- domainLookupStart: this.httpChannel.domainLookupStartTime,
- domainLookupEnd: this.httpChannel.domainLookupEndTime,
- connectStart: this.httpChannel.connectStartTime,
- secureConnectionStart: this.httpChannel.secureConnectionStartTime,
- connectEnd: this.httpChannel.connectEndTime,
- requestStart: this.httpChannel.requestStartTime,
- responseStart: this.httpChannel.responseStartTime,
- };
-
- const { status, statusText, headers } = responseHead(this.httpChannel, opt_statusCode, opt_statusText);
- let remoteIPAddress = undefined;
- let remotePort = undefined;
- try {
- remoteIPAddress = this.httpChannel.remoteAddress;
- remotePort = this.httpChannel.remotePort;
- } catch (e) {
- // remoteAddress is not defined for cached requests.
- }
-
- const fromServiceWorker = this._networkObserver._channelIdsFulfilledByServiceWorker.has(this.requestId);
- this._networkObserver._channelIdsFulfilledByServiceWorker.delete(this.requestId);
-
- pageNetwork.emit(PageNetwork.Events.Response, {
- requestId: this.requestId,
- securityDetails: getSecurityDetails(this.httpChannel),
- fromCache,
- headers,
- remoteIPAddress,
- remotePort,
- status,
- statusText,
- timing,
- fromServiceWorker,
- }, this._frameId);
- }
-
- _sendOnRequestFailed(error) {
- const pageNetwork = this._pageNetwork;
- if (pageNetwork) {
- pageNetwork.emit(PageNetwork.Events.RequestFailed, {
- requestId: this.requestId,
- errorCode: helper.getNetworkErrorStatusText(error),
- }, this._frameId);
- }
- this._networkObserver._channelToRequest.delete(this.httpChannel);
- }
-
- _sendOnRequestFinished() {
- const pageNetwork = this._pageNetwork;
- if (pageNetwork) {
- let protocolVersion = undefined;
- try {
- protocolVersion = this.httpChannel.protocolVersion;
- } catch (e) {
- // protocolVersion is unavailable in certain cases.
- };
- pageNetwork.emit(PageNetwork.Events.RequestFinished, {
- requestId: this.requestId,
- responseEndTime: this.httpChannel.responseEndTime,
- transferSize: this.httpChannel.transferSize,
- encodedBodySize: this.httpChannel.encodedBodySize,
- protocolVersion,
- }, this._frameId);
- }
- this._networkObserver._channelToRequest.delete(this.httpChannel);
- }
-}
-
-class NetworkObserver {
- static instance() {
- return NetworkObserver._instance || null;
- }
-
- constructor(targetRegistry) {
- EventEmitter.decorate(this);
- NetworkObserver._instance = this;
-
- this._targetRegistry = targetRegistry;
-
- this._channelToRequest = new Map(); // http channel -> network request
- this._expectedRedirect = new Map(); // expected redirect channel id (string) -> network request
- this._channelIdsFulfilledByServiceWorker = new Set(); // http channel ids that were fulfilled by service worker
-
- const protocolProxyService = Cc['@mozilla.org/network/protocol-proxy-service;1'].getService();
- this._channelProxyFilter = {
- QueryInterface: ChromeUtils.generateQI([Ci.nsIProtocolProxyChannelFilter]),
- applyFilter: (channel, defaultProxyInfo, proxyFilter) => {
- const proxy = this._targetRegistry.getProxyInfo(channel);
- if (!proxy) {
- proxyFilter.onProxyFilterResult(defaultProxyInfo);
- return;
- }
- proxyFilter.onProxyFilterResult(protocolProxyService.newProxyInfo(
- proxy.type,
- proxy.host,
- proxy.port,
- '', /* aProxyAuthorizationHeader */
- '', /* aConnectionIsolationKey */
- Ci.nsIProxyInfo.TRANSPARENT_PROXY_RESOLVES_HOST, /* aFlags */
- UINT32_MAX, /* aFailoverTimeout */
- null, /* failover proxy */
- ));
- },
- };
- protocolProxyService.registerChannelFilter(this._channelProxyFilter, 0 /* position */);
-
- // Register self as ChannelEventSink to track redirects.
- ChannelEventSinkFactory.getService().registerCollector({
- _onChannelRedirect: this._onRedirect.bind(this),
- });
-
- this._eventListeners = [
- helper.addObserver(this._onRequest.bind(this), 'http-on-modify-request'),
- helper.addObserver(this._onResponse.bind(this, false /* fromCache */), 'http-on-examine-response'),
- helper.addObserver(this._onResponse.bind(this, true /* fromCache */), 'http-on-examine-cached-response'),
- helper.addObserver(this._onResponse.bind(this, true /* fromCache */), 'http-on-examine-merged-response'),
- helper.addObserver(this._onServiceWorkerResponse.bind(this), 'service-worker-synthesized-response'),
- ];
- }
-
- _expectRedirect(channelId, previous) {
- this._expectedRedirect.set(channelId, previous);
- }
-
- _onRedirect(oldChannel, newChannel, flags) {
- if (!(oldChannel instanceof Ci.nsIHttpChannel) || !(newChannel instanceof Ci.nsIHttpChannel))
- return;
- const oldHttpChannel = oldChannel.QueryInterface(Ci.nsIHttpChannel);
- const newHttpChannel = newChannel.QueryInterface(Ci.nsIHttpChannel);
- const request = this._channelToRequest.get(oldHttpChannel);
- if (flags & Ci.nsIChannelEventSink.REDIRECT_INTERNAL) {
- if (request)
- request._onInternalRedirect(newHttpChannel);
- } else if (flags & Ci.nsIChannelEventSink.REDIRECT_STS_UPGRADE) {
- if (request) {
- // This is an internal HSTS upgrade. The original http request is canceled, and a new
- // equivalent https request is sent. We forge 307 redirect to follow Chromium here:
- // https://source.chromium.org/chromium/chromium/src/+/main:net/url_request/url_request_http_job.cc;l=211
- request._sendOnResponse(false, 307, 'Temporary Redirect');
- this._expectRedirect(newHttpChannel.channelId + '', request);
- }
- } else {
- if (request)
- this._expectRedirect(newHttpChannel.channelId + '', request);
- }
- }
-
- _findPageNetwork(httpChannel) {
- let loadContext = helper.getLoadContext(httpChannel);
- if (!loadContext)
- return;
- const target = this._targetRegistry.targetForBrowser(loadContext.topFrameElement);
- if (!target)
- return;
- return PageNetwork.forPageTarget(target);
- }
-
- _onRequest(channel, topic) {
- if (!(channel instanceof Ci.nsIHttpChannel))
- return;
- const httpChannel = channel.QueryInterface(Ci.nsIHttpChannel);
- const channelId = httpChannel.channelId + '';
- const redirectedFrom = this._expectedRedirect.get(channelId);
- if (redirectedFrom) {
- this._expectedRedirect.delete(channelId);
- new NetworkRequest(this, httpChannel, redirectedFrom);
- } else {
- const redirectedRequest = this._channelToRequest.get(httpChannel);
- if (redirectedRequest)
- redirectedRequest._onInternalRedirectReady();
- else
- new NetworkRequest(this, httpChannel);
- }
- }
-
- _onResponse(fromCache, httpChannel, topic) {
- const request = this._channelToRequest.get(httpChannel);
- if (request)
- request._sendOnResponse(fromCache);
- }
-
- _onServiceWorkerResponse(channel, topic) {
- if (!(channel instanceof Ci.nsIHttpChannel))
- return;
- const httpChannel = channel.QueryInterface(Ci.nsIHttpChannel);
- const channelId = httpChannel.channelId + '';
- this._channelIdsFulfilledByServiceWorker.add(channelId);
- }
-
- dispose() {
- this._activityDistributor.removeObserver(this);
- ChannelEventSinkFactory.unregister();
- helper.removeListeners(this._eventListeners);
- }
-}
-
-const protocolVersionNames = {
- [Ci.nsITransportSecurityInfo.TLS_VERSION_1]: 'TLS 1',
- [Ci.nsITransportSecurityInfo.TLS_VERSION_1_1]: 'TLS 1.1',
- [Ci.nsITransportSecurityInfo.TLS_VERSION_1_2]: 'TLS 1.2',
- [Ci.nsITransportSecurityInfo.TLS_VERSION_1_3]: 'TLS 1.3',
-};
-
-function getSecurityDetails(httpChannel) {
- const securityInfo = httpChannel.securityInfo;
- if (!securityInfo)
- return null;
- securityInfo.QueryInterface(Ci.nsITransportSecurityInfo);
- if (!securityInfo.serverCert)
- return null;
- return {
- protocol: protocolVersionNames[securityInfo.protocolVersion] || '',
- subjectName: securityInfo.serverCert.commonName,
- issuer: securityInfo.serverCert.issuerCommonName,
- // Convert to seconds.
- validFrom: securityInfo.serverCert.validity.notBefore / 1000 / 1000,
- validTo: securityInfo.serverCert.validity.notAfter / 1000 / 1000,
- };
-}
-
-function readRequestPostData(httpChannel) {
- if (!(httpChannel instanceof Ci.nsIUploadChannel))
- return undefined;
- let iStream = httpChannel.uploadStream;
- if (!iStream)
- return undefined;
- const isSeekableStream = iStream instanceof Ci.nsISeekableStream;
-
- // For some reason, we cannot rewind back big streams,
- // so instead we should clone them.
- const isCloneable = iStream instanceof Ci.nsICloneableInputStream;
- if (isCloneable)
- iStream = iStream.clone();
-
- let prevOffset;
- if (isSeekableStream) {
- prevOffset = iStream.tell();
- iStream.seek(Ci.nsISeekableStream.NS_SEEK_SET, 0);
- }
-
- // Read data from the stream.
- let result = undefined;
- try {
- const maxLen = iStream.available();
- // Cap at 10Mb.
- if (maxLen <= 10 * 1024 * 1024) {
- const buffer = NetUtil.readInputStreamToString(iStream, maxLen);
- result = btoa(buffer);
- }
- } catch (err) {
- }
-
- // Seek locks the file, so seek to the beginning only if necko hasn't
- // read it yet, since necko doesn't seek to 0 before reading (at lest
- // not till 459384 is fixed).
- if (isSeekableStream && prevOffset == 0 && !isCloneable)
- iStream.seek(Ci.nsISeekableStream.NS_SEEK_SET, 0);
- return result;
-}
-
-function requestHeaders(httpChannel) {
- const headers = [];
- httpChannel.visitRequestHeaders({
- visitHeader: (name, value) => headers.push({name, value}),
- });
- return headers;
-}
-
-function causeTypeToString(causeType) {
- for (let key in Ci.nsIContentPolicy) {
- if (Ci.nsIContentPolicy[key] === causeType)
- return key;
- }
- return 'TYPE_OTHER';
-}
-
-function appendExtraHTTPHeaders(httpChannel, headers) {
- if (!headers)
- return;
- for (const header of headers)
- httpChannel.setRequestHeader(header.name, header.value, false /* merge */);
-}
-
-class ResponseStorage {
- constructor(maxTotalSize, maxResponseSize) {
- this._totalSize = 0;
- this._maxResponseSize = maxResponseSize;
- this._maxTotalSize = maxTotalSize;
- this._responses = new Map();
- }
-
- addResponseBody(request, body) {
- if (body.length > this._maxResponseSize) {
- this._responses.set(request.requestId, {
- evicted: true,
- body: '',
- });
- return;
- }
- let encodings = [];
- if ((request.httpChannel instanceof Ci.nsIEncodedChannel) && request.httpChannel.contentEncodings && !request.httpChannel.applyConversion) {
- const encodingHeader = request.httpChannel.getResponseHeader("Content-Encoding");
- encodings = encodingHeader.split(/\s*\t*,\s*\t*/);
- }
- this._responses.set(request.requestId, {body, encodings});
- this._totalSize += body.length;
- if (this._totalSize > this._maxTotalSize) {
- for (let [requestId, response] of this._responses) {
- this._totalSize -= response.body.length;
- response.body = '';
- response.evicted = true;
- if (this._totalSize < this._maxTotalSize)
- break;
- }
- }
- }
-
- getBase64EncodedResponse(requestId) {
- const response = this._responses.get(requestId);
- if (!response)
- throw new Error(`Request "${requestId}" is not found`);
- if (response.evicted)
- return {base64body: '', evicted: true};
- let result = response.body;
- if (response.encodings && response.encodings.length) {
- for (const encoding of response.encodings)
- result = convertString(result, encoding, 'uncompressed');
- }
- return {base64body: btoa(result)};
- }
-}
-
-function responseHead(httpChannel, opt_statusCode, opt_statusText) {
- const headers = [];
- let status = opt_statusCode || 0;
- let statusText = opt_statusText || '';
- try {
- status = httpChannel.responseStatus;
- statusText = httpChannel.responseStatusText;
- httpChannel.visitResponseHeaders({
- visitHeader: (name, value) => headers.push({name, value}),
- });
- } catch (e) {
- // Response headers, status and/or statusText are not available
- // when redirect did not actually hit the network.
- }
- return { status, statusText, headers };
-}
-
-function setPostData(httpChannel, postData, headers) {
- if (!(httpChannel instanceof Ci.nsIUploadChannel2))
- return;
- const synthesized = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(Ci.nsIStringInputStream);
- const body = atob(postData);
- synthesized.setData(body, body.length);
-
- const overriddenHeader = (lowerCaseName, defaultValue) => {
- if (headers) {
- for (const header of headers) {
- if (header.name.toLowerCase() === lowerCaseName) {
- return header.value;
- }
- }
- }
- return defaultValue;
- }
- // Clear content-length, so that upload stream resets it.
- httpChannel.setRequestHeader('content-length', '', false /* merge */);
- httpChannel.explicitSetUploadStream(synthesized, overriddenHeader('content-type', 'application/octet-stream'), -1, httpChannel.requestMethod, false);
-}
-
-function convertString(s, source, dest) {
- const is = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(
- Ci.nsIStringInputStream
- );
- is.setData(s, s.length);
- const listener = Cc["@mozilla.org/network/stream-loader;1"].createInstance(
- Ci.nsIStreamLoader
- );
- let result = [];
- listener.init({
- onStreamComplete: function onStreamComplete(
- loader,
- context,
- status,
- length,
- data
- ) {
- const array = Array.from(data);
- const kChunk = 100000;
- for (let i = 0; i < length; i += kChunk) {
- const len = Math.min(kChunk, length - i);
- const chunk = String.fromCharCode.apply(this, array.slice(i, i + len));
- result.push(chunk);
- }
- },
- });
- const converter = Cc["@mozilla.org/streamConverters;1"].getService(
- Ci.nsIStreamConverterService
- ).asyncConvertData(
- source,
- dest,
- listener,
- null
- );
- converter.onStartRequest(null, null);
- converter.onDataAvailable(null, is, 0, s.length);
- converter.onStopRequest(null, null, null);
- return result.join('');
-}
-
-const errorMap = {
- 'aborted': Cr.NS_ERROR_ABORT,
- 'accessdenied': Cr.NS_ERROR_PORT_ACCESS_NOT_ALLOWED,
- 'addressunreachable': Cr.NS_ERROR_UNKNOWN_HOST,
- 'blockedbyclient': Cr.NS_ERROR_FAILURE,
- 'blockedbyresponse': Cr.NS_ERROR_FAILURE,
- 'connectionaborted': Cr.NS_ERROR_NET_INTERRUPT,
- 'connectionclosed': Cr.NS_ERROR_FAILURE,
- 'connectionfailed': Cr.NS_ERROR_FAILURE,
- 'connectionrefused': Cr.NS_ERROR_CONNECTION_REFUSED,
- 'connectionreset': Cr.NS_ERROR_NET_RESET,
- 'internetdisconnected': Cr.NS_ERROR_OFFLINE,
- 'namenotresolved': Cr.NS_ERROR_UNKNOWN_HOST,
- 'timedout': Cr.NS_ERROR_NET_TIMEOUT,
- 'failed': Cr.NS_ERROR_FAILURE,
-};
-
-PageNetwork.Events = {
- Request: Symbol('PageNetwork.Events.Request'),
- Response: Symbol('PageNetwork.Events.Response'),
- RequestFinished: Symbol('PageNetwork.Events.RequestFinished'),
- RequestFailed: Symbol('PageNetwork.Events.RequestFailed'),
-};
-
-var EXPORTED_SYMBOLS = ['NetworkObserver', 'PageNetwork'];
-this.NetworkObserver = NetworkObserver;
-this.PageNetwork = PageNetwork;
diff --git a/browser_patches/firefox-beta/juggler/SimpleChannel.js b/browser_patches/firefox-beta/juggler/SimpleChannel.js
deleted file mode 100644
index 59b29532ab1fd2..00000000000000
--- a/browser_patches/firefox-beta/juggler/SimpleChannel.js
+++ /dev/null
@@ -1,180 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-// Note: this file should be loadabale with eval() into worker environment.
-// Avoid Components.*, ChromeUtils and global const variables.
-
-const SIMPLE_CHANNEL_MESSAGE_NAME = 'juggler:simplechannel';
-
-class SimpleChannel {
- static createForMessageManager(name, mm) {
- const channel = new SimpleChannel(name);
-
- const messageListener = {
- receiveMessage: message => channel._onMessage(message.data)
- };
- mm.addMessageListener(SIMPLE_CHANNEL_MESSAGE_NAME, messageListener);
-
- channel.setTransport({
- sendMessage: obj => mm.sendAsyncMessage(SIMPLE_CHANNEL_MESSAGE_NAME, obj),
- dispose: () => mm.removeMessageListener(SIMPLE_CHANNEL_MESSAGE_NAME, messageListener),
- });
-
- return channel;
- }
-
- constructor(name) {
- this._name = name;
- this._messageId = 0;
- this._connectorId = 0;
- this._pendingMessages = new Map();
- this._handlers = new Map();
- this._bufferedIncomingMessages = [];
- this._bufferedOutgoingMessages = [];
- this.transport = {
- sendMessage: null,
- dispose: null,
- };
- this._ready = false;
- this._disposed = false;
- }
-
- setTransport(transport) {
- this.transport = transport;
- // connection handshake:
- // 1. There are two channel ends in different processes.
- // 2. Both ends start in the `ready = false` state, meaning that they will
- // not send any messages over transport.
- // 3. Once channel end is created, it sends `READY` message to the other end.
- // 4. Eventually, at least one of the ends receives `READY` message and responds with
- // `READY_ACK`. We assume at least one of the ends will receive "READY" event from the other, since
- // channel ends have a "parent-child" relation, i.e. one end is always created before the other one.
- // 5. Once channel end receives either `READY` or `READY_ACK`, it transitions to `ready` state.
- this.transport.sendMessage('READY');
- }
-
- _markAsReady() {
- if (this._ready)
- return;
- this._ready = true;
- for (const msg of this._bufferedOutgoingMessages)
- this.transport.sendMessage(msg);
- this._bufferedOutgoingMessages = [];
- }
-
- dispose() {
- if (this._disposed)
- return;
- this._disposed = true;
- for (const {resolve, reject, methodName} of this._pendingMessages.values())
- reject(new Error(`Failed "${methodName}": ${this._name} is disposed.`));
- this._pendingMessages.clear();
- this._handlers.clear();
- this.transport.dispose();
- }
-
- _rejectCallbacksFromConnector(connectorId) {
- for (const [messageId, callback] of this._pendingMessages) {
- if (callback.connectorId === connectorId) {
- callback.reject(new Error(`Failed "${callback.methodName}": connector for namespace "${callback.namespace}" in channel "${this._name}" is disposed.`));
- this._pendingMessages.delete(messageId);
- }
- }
- }
-
- connect(namespace) {
- const connectorId = ++this._connectorId;
- return {
- send: (...args) => this._send(namespace, connectorId, ...args),
- emit: (...args) => void this._send(namespace, connectorId, ...args).catch(e => {}),
- dispose: () => this._rejectCallbacksFromConnector(connectorId),
- };
- }
-
- register(namespace, handler) {
- if (this._handlers.has(namespace))
- throw new Error('ERROR: double-register for namespace ' + namespace);
- this._handlers.set(namespace, handler);
- // Try to re-deliver all pending messages.
- const bufferedRequests = this._bufferedIncomingMessages;
- this._bufferedIncomingMessages = [];
- for (const data of bufferedRequests) {
- this._onMessage(data);
- }
- return () => this.unregister(namespace);
- }
-
- unregister(namespace) {
- this._handlers.delete(namespace);
- }
-
- /**
- * @param {string} namespace
- * @param {number} connectorId
- * @param {string} methodName
- * @param {...*} params
- * @return {!Promise<*>}
- */
- async _send(namespace, connectorId, methodName, ...params) {
- if (this._disposed)
- throw new Error(`ERROR: channel ${this._name} is already disposed! Cannot send "${methodName}" to "${namespace}"`);
- const id = ++this._messageId;
- const promise = new Promise((resolve, reject) => {
- this._pendingMessages.set(id, {connectorId, resolve, reject, methodName, namespace});
- });
- const message = {requestId: id, methodName, params, namespace};
- if (this._ready)
- this.transport.sendMessage(message);
- else
- this._bufferedOutgoingMessages.push(message);
- return promise;
- }
-
- async _onMessage(data) {
- if (data === 'READY') {
- this.transport.sendMessage('READY_ACK');
- this._markAsReady();
- return;
- }
- if (data === 'READY_ACK') {
- this._markAsReady();
- return;
- }
- if (data.responseId) {
- const {resolve, reject} = this._pendingMessages.get(data.responseId);
- this._pendingMessages.delete(data.responseId);
- if (data.error)
- reject(new Error(data.error));
- else
- resolve(data.result);
- } else if (data.requestId) {
- const namespace = data.namespace;
- const handler = this._handlers.get(namespace);
- if (!handler) {
- this._bufferedIncomingMessages.push(data);
- return;
- }
- const method = handler[data.methodName];
- if (!method) {
- this.transport.sendMessage({responseId: data.requestId, error: `error in channel "${this._name}": No method "${data.methodName}" in namespace "${namespace}"`});
- return;
- }
- try {
- const result = await method.call(handler, ...data.params);
- this.transport.sendMessage({responseId: data.requestId, result});
- } catch (error) {
- this.transport.sendMessage({responseId: data.requestId, error: `error in channel "${this._name}": exception while running method "${data.methodName}" in namespace "${namespace}": ${error.message} ${error.stack}`});
- return;
- }
- } else {
- dump(`
- ERROR: unknown message in channel "${this._name}": ${JSON.stringify(data)}
- `);
- }
- }
-}
-
-var EXPORTED_SYMBOLS = ['SimpleChannel'];
-this.SimpleChannel = SimpleChannel;
diff --git a/browser_patches/firefox-beta/juggler/TargetRegistry.js b/browser_patches/firefox-beta/juggler/TargetRegistry.js
deleted file mode 100644
index b222ba98bba847..00000000000000
--- a/browser_patches/firefox-beta/juggler/TargetRegistry.js
+++ /dev/null
@@ -1,1065 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-const {EventEmitter} = ChromeUtils.import('resource://gre/modules/EventEmitter.jsm');
-const {Helper} = ChromeUtils.import('chrome://juggler/content/Helper.js');
-const {SimpleChannel} = ChromeUtils.import('chrome://juggler/content/SimpleChannel.js');
-const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
-const {Preferences} = ChromeUtils.import("resource://gre/modules/Preferences.jsm");
-const {ContextualIdentityService} = ChromeUtils.import("resource://gre/modules/ContextualIdentityService.jsm");
-const {NetUtil} = ChromeUtils.import('resource://gre/modules/NetUtil.jsm');
-const {AppConstants} = ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
-const {OS} = ChromeUtils.import("resource://gre/modules/osfile.jsm");
-
-const Cr = Components.results;
-
-const helper = new Helper();
-
-const IDENTITY_NAME = 'JUGGLER ';
-const HUNDRED_YEARS = 60 * 60 * 24 * 365 * 100;
-
-const ALL_PERMISSIONS = [
- 'geo',
- 'desktop-notification',
-];
-
-class DownloadInterceptor {
- constructor(registry) {
- this._registry = registry
- this._handlerToUuid = new Map();
- this._uuidToHandler = new Map();
- }
-
- //
- // nsIDownloadInterceptor implementation.
- //
- interceptDownloadRequest(externalAppHandler, request, browsingContext, outFile) {
- if (!(request instanceof Ci.nsIChannel))
- return false;
- const channel = request.QueryInterface(Ci.nsIChannel);
- let pageTarget = this._registry._browserBrowsingContextToTarget.get(channel.loadInfo.browsingContext.top);
- if (!pageTarget)
- return false;
-
- const browserContext = pageTarget.browserContext();
- const options = browserContext.downloadOptions;
- if (!options)
- return false;
-
- const uuid = helper.generateId();
- let file = null;
- if (options.behavior === 'saveToDisk') {
- file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
- file.initWithPath(options.downloadsDir);
- file.append(uuid);
-
- try {
- file.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600);
- } catch (e) {
- dump(`interceptDownloadRequest failed to create file: ${e}\n`);
- return false;
- }
- }
- outFile.value = file;
- this._handlerToUuid.set(externalAppHandler, uuid);
- this._uuidToHandler.set(uuid, externalAppHandler);
- const downloadInfo = {
- uuid,
- browserContextId: browserContext.browserContextId,
- pageTargetId: pageTarget.id(),
- url: request.name,
- suggestedFileName: externalAppHandler.suggestedFileName,
- };
- this._registry.emit(TargetRegistry.Events.DownloadCreated, downloadInfo);
- return true;
- }
-
- onDownloadComplete(externalAppHandler, canceled, errorName) {
- const uuid = this._handlerToUuid.get(externalAppHandler);
- if (!uuid)
- return;
- this._handlerToUuid.delete(externalAppHandler);
- this._uuidToHandler.delete(uuid);
- const downloadInfo = {
- uuid,
- error: errorName,
- };
- if (canceled === 'NS_BINDING_ABORTED') {
- downloadInfo.canceled = true;
- }
- this._registry.emit(TargetRegistry.Events.DownloadFinished, downloadInfo);
- }
-
- async cancelDownload(uuid) {
- const externalAppHandler = this._uuidToHandler.get(uuid);
- if (!externalAppHandler) {
- return;
- }
- await externalAppHandler.cancel(Cr.NS_BINDING_ABORTED);
- }
-}
-
-const screencastService = Cc['@mozilla.org/juggler/screencast;1'].getService(Ci.nsIScreencastService);
-
-class TargetRegistry {
- constructor() {
- EventEmitter.decorate(this);
-
- this._browserContextIdToBrowserContext = new Map();
- this._userContextIdToBrowserContext = new Map();
- this._browserToTarget = new Map();
- this._browserBrowsingContextToTarget = new Map();
-
- this._browserProxy = null;
-
- // Cleanup containers from previous runs (if any)
- for (const identity of ContextualIdentityService.getPublicIdentities()) {
- if (identity.name && identity.name.startsWith(IDENTITY_NAME)) {
- ContextualIdentityService.remove(identity.userContextId);
- ContextualIdentityService.closeContainerTabs(identity.userContextId);
- }
- }
-
- this._defaultContext = new BrowserContext(this, undefined, undefined);
-
- Services.obs.addObserver({
- observe: (subject, topic, data) => {
- const browser = subject.ownerElement;
- if (!browser)
- return;
- const target = this._browserToTarget.get(browser);
- if (!target)
- return;
- target.emit(PageTarget.Events.Crashed);
- target.dispose();
- }
- }, 'oop-frameloader-crashed');
-
- Services.mm.addMessageListener('juggler:content-ready', {
- receiveMessage: message => {
- const linkedBrowser = message.target;
- const target = this._browserToTarget.get(linkedBrowser);
- if (!target)
- return;
-
- return {
- initScripts: target.browserContext().initScripts,
- bindings: target.browserContext().bindings,
- settings: target.browserContext().settings,
- };
- },
- });
-
- const onTabOpenListener = (appWindow, window, event) => {
- const tab = event.target;
- const userContextId = tab.userContextId;
- const browserContext = this._userContextIdToBrowserContext.get(userContextId);
- const hasExplicitSize = appWindow && (appWindow.chromeFlags & Ci.nsIWebBrowserChrome.JUGGLER_WINDOW_EXPLICIT_SIZE) !== 0;
- const openerContext = tab.linkedBrowser.browsingContext.opener;
- let openerTarget;
- if (openerContext) {
- // Popups usually have opener context. Get top context for the case when opener is
- // an iframe.
- openerTarget = this._browserBrowsingContextToTarget.get(openerContext.top);
- } else if (tab.openerTab) {
- // Noopener popups from the same window have opener tab instead.
- openerTarget = this._browserToTarget.get(tab.openerTab.linkedBrowser);
- }
- if (!browserContext)
- throw new Error(`Internal error: cannot find context for userContextId=${userContextId}`);
- const target = new PageTarget(this, window, tab, browserContext, openerTarget);
- target.updateUserAgent();
- target.updatePlatform();
- target.updateJavaScriptDisabled();
- target.updateTouchOverride();
- target.updateColorSchemeOverride();
- target.updateReducedMotionOverride();
- target.updateForcedColorsOverride();
- if (!hasExplicitSize)
- target.updateViewportSize();
- if (browserContext.videoRecordingOptions)
- target._startVideoRecording(browserContext.videoRecordingOptions);
- };
-
- const onTabCloseListener = event => {
- const tab = event.target;
- const linkedBrowser = tab.linkedBrowser;
- const target = this._browserToTarget.get(linkedBrowser);
- if (target)
- target.dispose();
- };
-
- const domWindowTabListeners = new Map();
-
- const onOpenWindow = async (appWindow) => {
-
- let domWindow;
- if (appWindow instanceof Ci.nsIAppWindow) {
- domWindow = appWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
- } else {
- domWindow = appWindow;
- appWindow = null;
- }
- if (!(domWindow instanceof Ci.nsIDOMChromeWindow))
- return;
- // In persistent mode, window might be opened long ago and might be
- // already initialized.
- //
- // In this case, we want to keep this callback synchronous so that we will call
- // `onTabOpenListener` synchronously and before the sync IPc message `juggler:content-ready`.
- if (domWindow.document.readyState === 'uninitialized' || domWindow.document.readyState === 'loading') {
- // For non-initialized windows, DOMContentLoaded initializes gBrowser
- // and starts tab loading (see //browser/base/content/browser.js), so we
- // are guaranteed to call `onTabOpenListener` before the sync IPC message
- // `juggler:content-ready`.
- await helper.awaitEvent(domWindow, 'DOMContentLoaded');
- }
-
- if (!domWindow.gBrowser)
- return;
- const tabContainer = domWindow.gBrowser.tabContainer;
- domWindowTabListeners.set(domWindow, [
- helper.addEventListener(tabContainer, 'TabOpen', event => onTabOpenListener(appWindow, domWindow, event)),
- helper.addEventListener(tabContainer, 'TabClose', onTabCloseListener),
- ]);
- for (const tab of domWindow.gBrowser.tabs)
- onTabOpenListener(appWindow, domWindow, { target: tab });
- };
-
- const onCloseWindow = window => {
- const domWindow = window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
- if (!(domWindow instanceof Ci.nsIDOMChromeWindow))
- return;
- if (!domWindow.gBrowser)
- return;
-
- const listeners = domWindowTabListeners.get(domWindow) || [];
- domWindowTabListeners.delete(domWindow);
- helper.removeListeners(listeners);
- for (const tab of domWindow.gBrowser.tabs)
- onTabCloseListener({ target: tab });
- };
-
- const extHelperAppSvc = Cc["@mozilla.org/uriloader/external-helper-app-service;1"].getService(Ci.nsIExternalHelperAppService);
- this._downloadInterceptor = new DownloadInterceptor(this);
- extHelperAppSvc.setDownloadInterceptor(this._downloadInterceptor);
-
- Services.wm.addListener({ onOpenWindow, onCloseWindow });
- for (const win of Services.wm.getEnumerator(null))
- onOpenWindow(win);
- }
-
- async cancelDownload(options) {
- this._downloadInterceptor.cancelDownload(options.uuid);
- }
-
- setBrowserProxy(proxy) {
- this._browserProxy = proxy;
- }
-
- getProxyInfo(channel) {
- const originAttributes = channel.loadInfo && channel.loadInfo.originAttributes;
- const browserContext = originAttributes ? this.browserContextForUserContextId(originAttributes.userContextId) : null;
- // Prefer context proxy and fallback to browser-level proxy.
- const proxyInfo = (browserContext && browserContext._proxy) || this._browserProxy;
- if (!proxyInfo || proxyInfo.bypass.some(domainSuffix => channel.URI.host.endsWith(domainSuffix)))
- return null;
- return proxyInfo;
- }
-
- defaultContext() {
- return this._defaultContext;
- }
-
- createBrowserContext(removeOnDetach) {
- return new BrowserContext(this, helper.generateId(), removeOnDetach);
- }
-
- browserContextForId(browserContextId) {
- return this._browserContextIdToBrowserContext.get(browserContextId);
- }
-
- browserContextForUserContextId(userContextId) {
- return this._userContextIdToBrowserContext.get(userContextId);
- }
-
- async newPage({browserContextId}) {
- const browserContext = this.browserContextForId(browserContextId);
- const features = "chrome,dialog=no,all";
- // See _callWithURIToLoad in browser.js for the structure of window.arguments
- // window.arguments[1]: unused (bug 871161)
- // [2]: referrerInfo (nsIReferrerInfo)
- // [3]: postData (nsIInputStream)
- // [4]: allowThirdPartyFixup (bool)
- // [5]: userContextId (int)
- // [6]: originPrincipal (nsIPrincipal)
- // [7]: originStoragePrincipal (nsIPrincipal)
- // [8]: triggeringPrincipal (nsIPrincipal)
- // [9]: allowInheritPrincipal (bool)
- // [10]: csp (nsIContentSecurityPolicy)
- // [11]: nsOpenWindowInfo
- const args = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
- const urlSupports = Cc["@mozilla.org/supports-string;1"].createInstance(
- Ci.nsISupportsString
- );
- urlSupports.data = 'about:blank';
- args.appendElement(urlSupports); // 0
- args.appendElement(undefined); // 1
- args.appendElement(undefined); // 2
- args.appendElement(undefined); // 3
- args.appendElement(undefined); // 4
- const userContextIdSupports = Cc[
- "@mozilla.org/supports-PRUint32;1"
- ].createInstance(Ci.nsISupportsPRUint32);
- userContextIdSupports.data = browserContext.userContextId;
- args.appendElement(userContextIdSupports); // 5
- args.appendElement(undefined); // 6
- args.appendElement(undefined); // 7
- args.appendElement(Services.scriptSecurityManager.getSystemPrincipal()); // 8
-
- const window = Services.ww.openWindow(null, AppConstants.BROWSER_CHROME_URL, '_blank', features, args);
- await waitForWindowReady(window);
- if (window.gBrowser.browsers.length !== 1)
- throw new Error(`Unexpected number of tabs in the new window: ${window.gBrowser.browsers.length}`);
- const browser = window.gBrowser.browsers[0];
- let target = this._browserToTarget.get(browser);
- while (!target) {
- await helper.awaitEvent(this, TargetRegistry.Events.TargetCreated);
- target = this._browserToTarget.get(browser);
- }
- browser.focus();
- if (browserContext.settings.timezoneId) {
- if (await target.hasFailedToOverrideTimezone())
- throw new Error('Failed to override timezone');
- }
- return target.id();
- }
-
- targets() {
- return Array.from(this._browserToTarget.values());
- }
-
- targetForBrowser(browser) {
- return this._browserToTarget.get(browser);
- }
-}
-
-class PageTarget {
- constructor(registry, win, tab, browserContext, opener) {
- EventEmitter.decorate(this);
-
- this._targetId = helper.generateId();
- this._registry = registry;
- this._window = win;
- this._gBrowser = win.gBrowser;
- this._tab = tab;
- this._linkedBrowser = tab.linkedBrowser;
- this._browserContext = browserContext;
- this._viewportSize = undefined;
- this._initialDPPX = this._linkedBrowser.browsingContext.overrideDPPX;
- this._url = 'about:blank';
- this._openerId = opener ? opener.id() : undefined;
- this._channel = SimpleChannel.createForMessageManager(`browser::page[${this._targetId}]`, this._linkedBrowser.messageManager);
- this._videoRecordingInfo = undefined;
- this._screencastRecordingInfo = undefined;
- this._dialogs = new Map();
- this.forcedColors = 'no-override';
- this._pageInitScripts = [];
-
- const navigationListener = {
- QueryInterface: ChromeUtils.generateQI([Ci.nsIWebProgressListener, Ci.nsISupportsWeakReference]),
- onLocationChange: (aWebProgress, aRequest, aLocation) => this._onNavigated(aLocation),
- };
- this._eventListeners = [
- helper.addObserver(this._updateModalDialogs.bind(this), 'tabmodal-dialog-loaded'),
- helper.addProgressListener(tab.linkedBrowser, navigationListener, Ci.nsIWebProgress.NOTIFY_LOCATION),
- helper.addEventListener(this._linkedBrowser, 'DOMModalDialogClosed', event => this._updateModalDialogs()),
- ];
-
- this._disposed = false;
- browserContext.pages.add(this);
- this._registry._browserToTarget.set(this._linkedBrowser, this);
- this._registry._browserBrowsingContextToTarget.set(this._linkedBrowser.browsingContext, this);
-
- this._registry.emit(TargetRegistry.Events.TargetCreated, this);
- }
-
- dialog(dialogId) {
- return this._dialogs.get(dialogId);
- }
-
- dialogs() {
- return [...this._dialogs.values()];
- }
-
- async windowReady() {
- await waitForWindowReady(this._window);
- }
-
- linkedBrowser() {
- return this._linkedBrowser;
- }
-
- browserContext() {
- return this._browserContext;
- }
-
- updateTouchOverride() {
- this._linkedBrowser.browsingContext.touchEventsOverride = this._browserContext.touchOverride ? 'enabled' : 'none';
- }
-
- updateUserAgent() {
- this._linkedBrowser.browsingContext.customUserAgent = this._browserContext.defaultUserAgent;
- }
-
- updatePlatform() {
- this._linkedBrowser.browsingContext.customPlatform = this._browserContext.defaultPlatform;
- }
-
- updateJavaScriptDisabled() {
- this._linkedBrowser.browsingContext.allowJavascript = !this._browserContext.javaScriptDisabled;
- }
-
- _updateModalDialogs() {
- const prompts = new Set(this._linkedBrowser.tabModalPromptBox ? this._linkedBrowser.tabModalPromptBox.listPrompts() : []);
- for (const dialog of this._dialogs.values()) {
- if (!prompts.has(dialog.prompt())) {
- this._dialogs.delete(dialog.id());
- this.emit(PageTarget.Events.DialogClosed, dialog);
- } else {
- prompts.delete(dialog.prompt());
- }
- }
- for (const prompt of prompts) {
- const dialog = Dialog.createIfSupported(prompt);
- if (!dialog)
- continue;
- this._dialogs.set(dialog.id(), dialog);
- this.emit(PageTarget.Events.DialogOpened, dialog);
- }
- }
-
- async updateViewportSize() {
- // Viewport size is defined by three arguments:
- // 1. default size. Could be explicit if set as part of `window.open` call, e.g.
- // `window.open(url, title, 'width=400,height=400')`
- // 2. page viewport size
- // 3. browserContext viewport size
- //
- // The "default size" (1) is only respected when the page is opened.
- // Otherwise, explicitly set page viewport prevales over browser context
- // default viewport.
- const viewportSize = this._viewportSize || this._browserContext.defaultViewportSize;
- const actualSize = await setViewportSizeForBrowser(viewportSize, this._linkedBrowser, this._window);
- this._linkedBrowser.browsingContext.overrideDPPX = this._browserContext.deviceScaleFactor || this._initialDPPX;
- await this._channel.connect('').send('awaitViewportDimensions', {
- width: actualSize.width,
- height: actualSize.height,
- deviceSizeIsPageSize: !!this._browserContext.deviceScaleFactor,
- });
- }
-
- setEmulatedMedia(mediumOverride) {
- this._linkedBrowser.browsingContext.mediumOverride = mediumOverride || '';
- }
-
- setColorScheme(colorScheme) {
- this.colorScheme = fromProtocolColorScheme(colorScheme);
- this.updateColorSchemeOverride();
- }
-
- updateColorSchemeOverride() {
- this._linkedBrowser.browsingContext.prefersColorSchemeOverride = this.colorScheme || this._browserContext.colorScheme || 'none';
- }
-
- setReducedMotion(reducedMotion) {
- this.reducedMotion = fromProtocolReducedMotion(reducedMotion);
- this.updateReducedMotionOverride();
- }
-
- updateReducedMotionOverride() {
- this._linkedBrowser.browsingContext.prefersReducedMotionOverride = this.reducedMotion || this._browserContext.reducedMotion || 'none';
- }
-
- setForcedColors(forcedColors) {
- this.forcedColors = fromProtocolForcedColors(forcedColors);
- this.updateForcedColorsOverride();
- }
-
- updateForcedColorsOverride() {
- this._linkedBrowser.browsingContext.forcedColorsOverride = (this.forcedColors !== 'no-override' ? this.forcedColors : this._browserContext.forcedColors) || 'no-override';
- }
-
- async setViewportSize(viewportSize) {
- this._viewportSize = viewportSize;
- await this.updateViewportSize();
- }
-
- close(runBeforeUnload = false) {
- this._gBrowser.removeTab(this._tab, {
- skipPermitUnload: !runBeforeUnload,
- });
- }
-
- channel() {
- return this._channel;
- }
-
- id() {
- return this._targetId;
- }
-
- info() {
- return {
- targetId: this.id(),
- type: 'page',
- browserContextId: this._browserContext.browserContextId,
- openerId: this._openerId,
- };
- }
-
- _onNavigated(aLocation) {
- this._url = aLocation.spec;
- this._browserContext.grantPermissionsToOrigin(this._url);
- }
-
- async ensurePermissions() {
- await this._channel.connect('').send('ensurePermissions', {}).catch(e => void e);
- }
-
- async setInitScripts(scripts) {
- this._pageInitScripts = scripts;
- await this.pushInitScripts();
- }
-
- async pushInitScripts() {
- await this._channel.connect('').send('setInitScripts', [...this._browserContext.initScripts, ...this._pageInitScripts]).catch(e => void e);
- }
-
- async addBinding(worldName, name, script) {
- await this._channel.connect('').send('addBinding', { worldName, name, script }).catch(e => void e);
- }
-
- async applyContextSetting(name, value) {
- 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
- // to be initialized and visible.
- await this.windowReady();
- const file = OS.Path.join(dir, helper.generateId() + '.webm');
- if (width < 10 || width > 10000 || height < 10 || height > 10000)
- throw new Error("Invalid size");
-
- const docShell = this._gBrowser.ownerGlobal.docShell;
- // Exclude address bar and navigation control from the video.
- const rect = this.linkedBrowser().getBoundingClientRect();
- const devicePixelRatio = this._window.devicePixelRatio;
- let sessionId;
- const registry = this._registry;
- const screencastClient = {
- QueryInterface: ChromeUtils.generateQI([Ci.nsIScreencastServiceClient]),
- screencastFrame(data, deviceWidth, deviceHeight) {
- },
- screencastStopped() {
- registry.emit(TargetRegistry.Events.ScreencastStopped, sessionId);
- },
- };
- const viewport = this._viewportSize || this._browserContext.defaultViewportSize || { width: 0, height: 0 };
- sessionId = screencastService.startVideoRecording(screencastClient, docShell, true, file, width, height, 0, viewport.width, viewport.height, devicePixelRatio * rect.top);
- this._videoRecordingInfo = { sessionId, file };
- this.emit(PageTarget.Events.ScreencastStarted);
- }
-
- _stopVideoRecording() {
- if (!this._videoRecordingInfo)
- throw new Error('No video recording in progress');
- const videoRecordingInfo = this._videoRecordingInfo;
- this._videoRecordingInfo = undefined;
- screencastService.stopVideoRecording(videoRecordingInfo.sessionId);
- }
-
- videoRecordingInfo() {
- return this._videoRecordingInfo;
- }
-
- async startScreencast({ width, height, quality }) {
- // 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
- // to be initialized and visible.
- await this.windowReady();
- if (width < 10 || width > 10000 || height < 10 || height > 10000)
- throw new Error("Invalid size");
-
- const docShell = this._gBrowser.ownerGlobal.docShell;
- // Exclude address bar and navigation control from the video.
- const rect = this.linkedBrowser().getBoundingClientRect();
- const devicePixelRatio = this._window.devicePixelRatio;
-
- const self = this;
- const screencastClient = {
- QueryInterface: ChromeUtils.generateQI([Ci.nsIScreencastServiceClient]),
- screencastFrame(data, deviceWidth, deviceHeight) {
- if (self._screencastRecordingInfo)
- self.emit(PageTarget.Events.ScreencastFrame, { data, deviceWidth, deviceHeight });
- },
- screencastStopped() {
- },
- };
- const viewport = this._viewportSize || this._browserContext.defaultViewportSize || { width: 0, height: 0 };
- const screencastId = screencastService.startVideoRecording(screencastClient, docShell, false, '', width, height, quality || 90, viewport.width, viewport.height, devicePixelRatio * rect.top);
- this._screencastRecordingInfo = { screencastId };
- return { screencastId };
- }
-
- screencastFrameAck({ screencastId }) {
- if (!this._screencastRecordingInfo || this._screencastRecordingInfo.screencastId !== screencastId)
- return;
- screencastService.screencastFrameAck(screencastId);
- }
-
- stopScreencast() {
- if (!this._screencastRecordingInfo)
- throw new Error('No screencast in progress');
- const { screencastId } = this._screencastRecordingInfo;
- this._screencastRecordingInfo = undefined;
- screencastService.stopVideoRecording(screencastId);
- }
-
- dispose() {
- this._disposed = true;
- if (this._videoRecordingInfo)
- this._stopVideoRecording();
- if (this._screencastRecordingInfo)
- this.stopScreencast();
- this._browserContext.pages.delete(this);
- this._registry._browserToTarget.delete(this._linkedBrowser);
- this._registry._browserBrowsingContextToTarget.delete(this._linkedBrowser.browsingContext);
- try {
- helper.removeListeners(this._eventListeners);
- } catch (e) {
- // In some cases, removing listeners from this._linkedBrowser fails
- // because it is already half-destroyed.
- if (e)
- dump(e.message + '\n' + e.stack + '\n');
- }
- this._registry.emit(TargetRegistry.Events.TargetDestroyed, this);
- }
-}
-
-PageTarget.Events = {
- ScreencastStarted: Symbol('PageTarget.ScreencastStarted'),
- ScreencastFrame: Symbol('PageTarget.ScreencastFrame'),
- Crashed: Symbol('PageTarget.Crashed'),
- DialogOpened: Symbol('PageTarget.DialogOpened'),
- DialogClosed: Symbol('PageTarget.DialogClosed'),
-};
-
-function fromProtocolColorScheme(colorScheme) {
- if (colorScheme === 'light' || colorScheme === 'dark')
- return colorScheme;
- if (colorScheme === null || colorScheme === 'no-preference')
- return undefined;
- throw new Error('Unknown color scheme: ' + colorScheme);
-}
-
-function fromProtocolReducedMotion(reducedMotion) {
- if (reducedMotion === 'reduce' || reducedMotion === 'no-preference')
- return reducedMotion;
- if (reducedMotion === null)
- return undefined;
- throw new Error('Unknown reduced motion: ' + reducedMotion);
-}
-
-function fromProtocolForcedColors(forcedColors) {
- if (forcedColors === 'active' || forcedColors === 'none')
- return forcedColors;
- if (forcedColors === null)
- return undefined;
- throw new Error('Unknown forced colors: ' + forcedColors);
-}
-
-class BrowserContext {
- constructor(registry, browserContextId, removeOnDetach) {
- this._registry = registry;
- this.browserContextId = browserContextId;
- // Default context has userContextId === 0, but we pass undefined to many APIs just in case.
- this.userContextId = 0;
- if (browserContextId !== undefined) {
- const identity = ContextualIdentityService.create(IDENTITY_NAME + browserContextId);
- this.userContextId = identity.userContextId;
- }
- this._principals = [];
- // Maps origins to the permission lists.
- this._permissions = new Map();
- this._registry._browserContextIdToBrowserContext.set(this.browserContextId, this);
- this._registry._userContextIdToBrowserContext.set(this.userContextId, this);
- this._proxy = null;
- this.removeOnDetach = removeOnDetach;
- this.extraHTTPHeaders = undefined;
- this.httpCredentials = undefined;
- this.requestInterceptionEnabled = undefined;
- this.ignoreHTTPSErrors = undefined;
- this.downloadOptions = undefined;
- this.defaultViewportSize = undefined;
- this.deviceScaleFactor = undefined;
- this.defaultUserAgent = null;
- this.defaultPlatform = null;
- this.javaScriptDisabled = false;
- this.touchOverride = false;
- this.colorScheme = 'none';
- this.forcedColors = 'no-override';
- this.reducedMotion = 'none';
- this.videoRecordingOptions = undefined;
- this.initScripts = [];
- this.bindings = [];
- this.settings = {};
- this.pages = new Set();
- }
-
- setColorScheme(colorScheme) {
- this.colorScheme = fromProtocolColorScheme(colorScheme);
- for (const page of this.pages)
- page.updateColorSchemeOverride();
- }
-
- setReducedMotion(reducedMotion) {
- this.reducedMotion = fromProtocolReducedMotion(reducedMotion);
- for (const page of this.pages)
- page.updateReducedMotionOverride();
- }
-
- setForcedColors(forcedColors) {
- this.forcedColors = fromProtocolForcedColors(forcedColors);
- for (const page of this.pages)
- page.updateForcedColorsOverride();
- }
-
- async destroy() {
- if (this.userContextId !== 0) {
- ContextualIdentityService.remove(this.userContextId);
- for (const page of this.pages)
- page.close();
- if (this.pages.size) {
- await new Promise(f => {
- const listener = helper.on(this._registry, TargetRegistry.Events.TargetDestroyed, () => {
- if (!this.pages.size) {
- helper.removeListeners([listener]);
- f();
- }
- });
- });
- }
- }
- this._registry._browserContextIdToBrowserContext.delete(this.browserContextId);
- this._registry._userContextIdToBrowserContext.delete(this.userContextId);
- }
-
- setProxy(proxy) {
- // Clear AuthCache.
- Services.obs.notifyObservers(null, "net:clear-active-logins");
- this._proxy = proxy;
- }
-
- setIgnoreHTTPSErrors(ignoreHTTPSErrors) {
- if (this.ignoreHTTPSErrors === ignoreHTTPSErrors)
- return;
- this.ignoreHTTPSErrors = ignoreHTTPSErrors;
- const certOverrideService = Cc[
- "@mozilla.org/security/certoverride;1"
- ].getService(Ci.nsICertOverrideService);
- if (ignoreHTTPSErrors) {
- Preferences.set("network.stricttransportsecurity.preloadlist", false);
- Preferences.set("security.cert_pinning.enforcement_level", 0);
- certOverrideService.setDisableAllSecurityChecksAndLetAttackersInterceptMyData(true, this.userContextId);
- } else {
- certOverrideService.setDisableAllSecurityChecksAndLetAttackersInterceptMyData(false, this.userContextId);
- }
- }
-
- setDefaultUserAgent(userAgent) {
- this.defaultUserAgent = userAgent;
- for (const page of this.pages)
- page.updateUserAgent();
- }
-
- setDefaultPlatform(platform) {
- this.defaultPlatform = platform;
- for (const page of this.pages)
- page.updatePlatform();
- }
-
- setJavaScriptDisabled(javaScriptDisabled) {
- this.javaScriptDisabled = javaScriptDisabled;
- for (const page of this.pages)
- page.updateJavaScriptDisabled();
- }
-
- setTouchOverride(touchOverride) {
- this.touchOverride = touchOverride;
- for (const page of this.pages)
- page.updateTouchOverride();
- }
-
- async setDefaultViewport(viewport) {
- this.defaultViewportSize = viewport ? viewport.viewportSize : undefined;
- this.deviceScaleFactor = viewport ? viewport.deviceScaleFactor : undefined;
- await Promise.all(Array.from(this.pages).map(page => page.updateViewportSize()));
- }
-
- async setInitScripts(scripts) {
- this.initScripts = scripts;
- await Promise.all(Array.from(this.pages).map(page => page.pushInitScripts()));
- }
-
- async addBinding(worldName, name, script) {
- this.bindings.push({ worldName, name, script });
- await Promise.all(Array.from(this.pages).map(page => page.addBinding(worldName, name, script)));
- }
-
- async applySetting(name, value) {
- this.settings[name] = value;
- await Promise.all(Array.from(this.pages).map(page => page.applyContextSetting(name, value)));
- }
-
- async grantPermissions(origin, permissions) {
- this._permissions.set(origin, permissions);
- const promises = [];
- for (const page of this.pages) {
- if (origin === '*' || page._url.startsWith(origin)) {
- this.grantPermissionsToOrigin(page._url);
- promises.push(page.ensurePermissions());
- }
- }
- await Promise.all(promises);
- }
-
- resetPermissions() {
- for (const principal of this._principals) {
- for (const permission of ALL_PERMISSIONS)
- Services.perms.removeFromPrincipal(principal, permission);
- }
- this._principals = [];
- this._permissions.clear();
- }
-
- grantPermissionsToOrigin(url) {
- let origin = Array.from(this._permissions.keys()).find(key => url.startsWith(key));
- if (!origin)
- origin = '*';
-
- const permissions = this._permissions.get(origin);
- if (!permissions)
- return;
-
- const attrs = { userContextId: this.userContextId || undefined };
- const principal = Services.scriptSecurityManager.createContentPrincipal(NetUtil.newURI(url), attrs);
- this._principals.push(principal);
- for (const permission of ALL_PERMISSIONS) {
- const action = permissions.includes(permission) ? Ci.nsIPermissionManager.ALLOW_ACTION : Ci.nsIPermissionManager.DENY_ACTION;
- Services.perms.addFromPrincipal(principal, permission, action, Ci.nsIPermissionManager.EXPIRE_NEVER, 0 /* expireTime */);
- }
- }
-
- setCookies(cookies) {
- const protocolToSameSite = {
- [undefined]: Ci.nsICookie.SAMESITE_NONE,
- 'Lax': Ci.nsICookie.SAMESITE_LAX,
- 'Strict': Ci.nsICookie.SAMESITE_STRICT,
- };
- for (const cookie of cookies) {
- const uri = cookie.url ? NetUtil.newURI(cookie.url) : null;
- let domain = cookie.domain;
- if (!domain) {
- if (!uri)
- throw new Error('At least one of the url and domain needs to be specified');
- domain = uri.host;
- }
- let path = cookie.path;
- if (!path)
- path = uri ? dirPath(uri.filePath) : '/';
- let secure = false;
- if (cookie.secure !== undefined)
- secure = cookie.secure;
- else if (uri && uri.scheme === 'https')
- secure = true;
- Services.cookies.add(
- domain,
- path,
- cookie.name,
- cookie.value,
- secure,
- cookie.httpOnly || false,
- cookie.expires === undefined || cookie.expires === -1 /* isSession */,
- cookie.expires === undefined ? Date.now() + HUNDRED_YEARS : cookie.expires,
- { userContextId: this.userContextId || undefined } /* originAttributes */,
- protocolToSameSite[cookie.sameSite],
- Ci.nsICookie.SCHEME_UNSET
- );
- }
- }
-
- clearCookies() {
- Services.cookies.removeCookiesWithOriginAttributes(JSON.stringify({ userContextId: this.userContextId || undefined }));
- }
-
- getCookies() {
- const result = [];
- const sameSiteToProtocol = {
- [Ci.nsICookie.SAMESITE_NONE]: 'None',
- [Ci.nsICookie.SAMESITE_LAX]: 'Lax',
- [Ci.nsICookie.SAMESITE_STRICT]: 'Strict',
- };
- for (let cookie of Services.cookies.cookies) {
- if (cookie.originAttributes.userContextId !== this.userContextId)
- continue;
- if (cookie.host === 'addons.mozilla.org')
- continue;
- result.push({
- name: cookie.name,
- value: cookie.value,
- domain: cookie.host,
- path: cookie.path,
- expires: cookie.isSession ? -1 : cookie.expiry,
- size: cookie.name.length + cookie.value.length,
- httpOnly: cookie.isHttpOnly,
- secure: cookie.isSecure,
- session: cookie.isSession,
- sameSite: sameSiteToProtocol[cookie.sameSite],
- });
- }
- return result;
- }
-
- async setVideoRecordingOptions(options) {
- this.videoRecordingOptions = options;
- const promises = [];
- for (const page of this.pages) {
- if (options)
- promises.push(page._startVideoRecording(options));
- else if (page._videoRecordingInfo)
- promises.push(page._stopVideoRecording());
- }
- await Promise.all(promises);
- }
-}
-
-class Dialog {
- static createIfSupported(prompt) {
- const type = prompt.args.promptType;
- switch (type) {
- case 'alert':
- case 'alertCheck':
- return new Dialog(prompt, 'alert');
- case 'prompt':
- return new Dialog(prompt, 'prompt');
- case 'confirm':
- case 'confirmCheck':
- return new Dialog(prompt, 'confirm');
- case 'confirmEx':
- return new Dialog(prompt, 'beforeunload');
- default:
- return null;
- };
- }
-
- constructor(prompt, type) {
- this._id = helper.generateId();
- this._type = type;
- this._prompt = prompt;
- }
-
- id() {
- return this._id;
- }
-
- message() {
- return this._prompt.ui.infoBody.textContent;
- }
-
- type() {
- return this._type;
- }
-
- prompt() {
- return this._prompt;
- }
-
- dismiss() {
- if (this._prompt.ui.button1)
- this._prompt.ui.button1.click();
- else
- this._prompt.ui.button0.click();
- }
-
- defaultValue() {
- return this._prompt.ui.loginTextbox.value;
- }
-
- accept(promptValue) {
- if (typeof promptValue === 'string' && this._type === 'prompt')
- this._prompt.ui.loginTextbox.value = promptValue;
- this._prompt.ui.button0.click();
- }
-}
-
-
-function dirPath(path) {
- return path.substring(0, path.lastIndexOf('/') + 1);
-}
-
-async function waitForWindowReady(window) {
- if (window.delayedStartupPromise) {
- await window.delayedStartupPromise;
- } else {
- await new Promise((resolve => {
- Services.obs.addObserver(function observer(aSubject, aTopic) {
- if (window == aSubject) {
- Services.obs.removeObserver(observer, aTopic);
- resolve();
- }
- }, "browser-delayed-startup-finished");
- }));
- }
- if (window.document.readyState !== 'complete')
- await helper.awaitEvent(window, 'load');
-}
-
-async function setViewportSizeForBrowser(viewportSize, browser, window) {
- await waitForWindowReady(window);
- if (viewportSize) {
- const {width, height} = viewportSize;
- const rect = browser.getBoundingClientRect();
- window.resizeBy(width - rect.width, height - rect.height);
- browser.style.setProperty('min-width', width + 'px');
- browser.style.setProperty('min-height', height + 'px');
- browser.style.setProperty('max-width', width + 'px');
- browser.style.setProperty('max-height', height + 'px');
- } else {
- browser.style.removeProperty('min-width');
- browser.style.removeProperty('min-height');
- browser.style.removeProperty('max-width');
- browser.style.removeProperty('max-height');
- }
- const rect = browser.getBoundingClientRect();
- return { width: rect.width, height: rect.height };
-}
-
-TargetRegistry.Events = {
- TargetCreated: Symbol('TargetRegistry.Events.TargetCreated'),
- TargetDestroyed: Symbol('TargetRegistry.Events.TargetDestroyed'),
- DownloadCreated: Symbol('TargetRegistry.Events.DownloadCreated'),
- DownloadFinished: Symbol('TargetRegistry.Events.DownloadFinished'),
- ScreencastStopped: Symbol('TargetRegistry.ScreencastStopped'),
-};
-
-var EXPORTED_SYMBOLS = ['TargetRegistry', 'PageTarget'];
-this.TargetRegistry = TargetRegistry;
-this.PageTarget = PageTarget;
diff --git a/browser_patches/firefox-beta/juggler/components/moz.build b/browser_patches/firefox-beta/juggler/components/moz.build
deleted file mode 100644
index bab81f83fcb290..00000000000000
--- a/browser_patches/firefox-beta/juggler/components/moz.build
+++ /dev/null
@@ -1,6 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-XPCOM_MANIFESTS += ["components.conf"]
-
diff --git a/browser_patches/firefox-beta/juggler/content/FrameTree.js b/browser_patches/firefox-beta/juggler/content/FrameTree.js
deleted file mode 100644
index 61ff889e755fb9..00000000000000
--- a/browser_patches/firefox-beta/juggler/content/FrameTree.js
+++ /dev/null
@@ -1,634 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-const Ci = Components.interfaces;
-const Cr = Components.results;
-const Cu = Components.utils;
-
-const {Helper} = ChromeUtils.import('chrome://juggler/content/Helper.js');
-const {SimpleChannel} = ChromeUtils.import('chrome://juggler/content/SimpleChannel.js');
-const {EventEmitter} = ChromeUtils.import('resource://gre/modules/EventEmitter.jsm');
-const {Runtime} = ChromeUtils.import('chrome://juggler/content/content/Runtime.js');
-
-const helper = new Helper();
-
-class FrameTree {
- constructor(rootDocShell) {
- EventEmitter.decorate(this);
-
- this._browsingContextGroup = rootDocShell.browsingContext.group;
- if (!this._browsingContextGroup.__jugglerFrameTrees)
- this._browsingContextGroup.__jugglerFrameTrees = new Set();
- this._browsingContextGroup.__jugglerFrameTrees.add(this);
- this._isolatedWorlds = new Map();
-
- this._webSocketEventService = Cc[
- "@mozilla.org/websocketevent/service;1"
- ].getService(Ci.nsIWebSocketEventService);
-
- this._runtime = new Runtime(false /* isWorker */);
- this._workers = new Map();
- this._docShellToFrame = new Map();
- this._frameIdToFrame = new Map();
- this._pageReady = false;
- this._mainFrame = this._createFrame(rootDocShell);
- const webProgress = rootDocShell.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebProgress);
- this.QueryInterface = ChromeUtils.generateQI([
- Ci.nsIWebProgressListener,
- Ci.nsIWebProgressListener2,
- Ci.nsISupportsWeakReference,
- ]);
-
- this._addedScrollbarsStylesheetSymbol = Symbol('_addedScrollbarsStylesheetSymbol');
-
- this._wdm = Cc["@mozilla.org/dom/workers/workerdebuggermanager;1"].createInstance(Ci.nsIWorkerDebuggerManager);
- this._wdmListener = {
- QueryInterface: ChromeUtils.generateQI([Ci.nsIWorkerDebuggerManagerListener]),
- onRegister: this._onWorkerCreated.bind(this),
- onUnregister: this._onWorkerDestroyed.bind(this),
- };
- this._wdm.addListener(this._wdmListener);
- for (const workerDebugger of this._wdm.getWorkerDebuggerEnumerator())
- this._onWorkerCreated(workerDebugger);
-
- const flags = Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT |
- Ci.nsIWebProgress.NOTIFY_LOCATION;
- this._eventListeners = [
- helper.addObserver(this._onDOMWindowCreated.bind(this), 'content-document-global-created'),
- helper.addObserver(this._onDOMWindowCreated.bind(this), 'juggler-dom-window-reused'),
- helper.addObserver(subject => this._onDocShellCreated(subject.QueryInterface(Ci.nsIDocShell)), 'webnavigation-create'),
- helper.addObserver(subject => this._onDocShellDestroyed(subject.QueryInterface(Ci.nsIDocShell)), 'webnavigation-destroy'),
- helper.addProgressListener(webProgress, this, flags),
- ];
- }
-
- workers() {
- return [...this._workers.values()];
- }
-
- runtime() {
- return this._runtime;
- }
-
- setInitScripts(scripts) {
- for (const world of this._isolatedWorlds.values())
- world._scriptsToEvaluateOnNewDocument = [];
-
- for (let { worldName, script } of scripts) {
- worldName = worldName || '';
- const existing = this._isolatedWorlds.has(worldName);
- const world = this._ensureWorld(worldName);
- world._scriptsToEvaluateOnNewDocument.push(script);
- // FIXME: 'should inherit http credentials from browser context' fails without this
- if (worldName && !existing) {
- for (const frame of this.frames())
- frame._createIsolatedContext(worldName);
- }
- }
- }
-
- _ensureWorld(worldName) {
- worldName = worldName || '';
- let world = this._isolatedWorlds.get(worldName);
- if (!world) {
- world = new IsolatedWorld(worldName);
- this._isolatedWorlds.set(worldName, world);
- }
- return world;
- }
-
- _frameForWorker(workerDebugger) {
- if (workerDebugger.type !== Ci.nsIWorkerDebugger.TYPE_DEDICATED)
- return null;
- if (!workerDebugger.window)
- return null;
- const docShell = workerDebugger.window.docShell;
- return this._docShellToFrame.get(docShell) || null;
- }
-
- _onDOMWindowCreated(window) {
- if (!window[this._addedScrollbarsStylesheetSymbol] && this.scrollbarsHidden) {
- const styleSheetService = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Components.interfaces.nsIStyleSheetService);
- const ioService = Cc["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService);
- const uri = ioService.newURI('chrome://juggler/content/content/hidden-scrollbars.css', null, null);
- const sheet = styleSheetService.preloadSheet(uri, styleSheetService.AGENT_SHEET);
- window.windowUtils.addSheet(sheet, styleSheetService.AGENT_SHEET);
- window[this._addedScrollbarsStylesheetSymbol] = true;
- }
- const frame = this._docShellToFrame.get(window.docShell) || null;
- if (!frame)
- return;
- frame._onGlobalObjectCleared();
- }
-
- setScrollbarsHidden(hidden) {
- this.scrollbarsHidden = hidden;
- }
-
- _onWorkerCreated(workerDebugger) {
- // Note: we do not interoperate with firefox devtools.
- if (workerDebugger.isInitialized)
- return;
- const frame = this._frameForWorker(workerDebugger);
- if (!frame)
- return;
- const worker = new Worker(frame, workerDebugger);
- this._workers.set(workerDebugger, worker);
- this.emit(FrameTree.Events.WorkerCreated, worker);
- }
-
- _onWorkerDestroyed(workerDebugger) {
- const worker = this._workers.get(workerDebugger);
- if (!worker)
- return;
- worker.dispose();
- this._workers.delete(workerDebugger);
- this.emit(FrameTree.Events.WorkerDestroyed, worker);
- }
-
- allFramesInBrowsingContextGroup(group) {
- const frames = [];
- for (const frameTree of (group.__jugglerFrameTrees || []))
- frames.push(...frameTree.frames());
- return frames;
- }
-
- isPageReady() {
- return this._pageReady;
- }
-
- forcePageReady() {
- if (this._pageReady)
- return false;
- this._pageReady = true;
- this.emit(FrameTree.Events.PageReady);
- return true;
- }
-
- addBinding(worldName, name, script) {
- worldName = worldName || '';
- const world = this._ensureWorld(worldName);
- world._bindings.set(name, script);
- for (const frame of this.frames())
- frame._addBinding(worldName, name, script);
- }
-
- frameForDocShell(docShell) {
- return this._docShellToFrame.get(docShell) || null;
- }
-
- frame(frameId) {
- return this._frameIdToFrame.get(frameId) || null;
- }
-
- frames() {
- let result = [];
- collect(this._mainFrame);
- return result;
-
- function collect(frame) {
- result.push(frame);
- for (const subframe of frame._children)
- collect(subframe);
- }
- }
-
- mainFrame() {
- return this._mainFrame;
- }
-
- dispose() {
- this._browsingContextGroup.__jugglerFrameTrees.delete(this);
- this._wdm.removeListener(this._wdmListener);
- this._runtime.dispose();
- helper.removeListeners(this._eventListeners);
- }
-
- onStateChange(progress, request, flag, status) {
- if (!(request instanceof Ci.nsIChannel))
- return;
- const channel = request.QueryInterface(Ci.nsIChannel);
- const docShell = progress.DOMWindow.docShell;
- const frame = this._docShellToFrame.get(docShell);
- if (!frame) {
- dump(`ERROR: got a state changed event for un-tracked docshell!\n`);
- return;
- }
-
- if (!channel.isDocument) {
- // Somehow, we can get worker requests here,
- // while we are only interested in frame documents.
- return;
- }
-
- const isStart = flag & Ci.nsIWebProgressListener.STATE_START;
- const isTransferring = flag & Ci.nsIWebProgressListener.STATE_TRANSFERRING;
- const isStop = flag & Ci.nsIWebProgressListener.STATE_STOP;
- const isDocument = flag & Ci.nsIWebProgressListener.STATE_IS_DOCUMENT;
-
- if (isStart) {
- // Starting a new navigation.
- frame._pendingNavigationId = channelId(channel);
- frame._pendingNavigationURL = channel.URI.spec;
- this.emit(FrameTree.Events.NavigationStarted, frame);
- } else if (isTransferring || (isStop && frame._pendingNavigationId && !status)) {
- // Navigation is committed.
- for (const subframe of frame._children)
- this._detachFrame(subframe);
- const navigationId = frame._pendingNavigationId;
- frame._pendingNavigationId = null;
- frame._pendingNavigationURL = null;
- frame._lastCommittedNavigationId = navigationId;
- frame._url = channel.URI.spec;
- this.emit(FrameTree.Events.NavigationCommitted, frame);
- if (frame === this._mainFrame)
- this.forcePageReady();
- } else if (isStop && frame._pendingNavigationId && status) {
- // Navigation is aborted.
- const navigationId = frame._pendingNavigationId;
- frame._pendingNavigationId = null;
- frame._pendingNavigationURL = null;
- // Always report download navigation as failure to match other browsers.
- const errorText = helper.getNetworkErrorStatusText(status);
- this.emit(FrameTree.Events.NavigationAborted, frame, navigationId, errorText);
- if (frame === this._mainFrame && status !== Cr.NS_BINDING_ABORTED)
- this.forcePageReady();
- }
-
- if (isStop && isDocument)
- this.emit(FrameTree.Events.Load, frame);
- }
-
- onLocationChange(progress, request, location, flags) {
- const docShell = progress.DOMWindow.docShell;
- const frame = this._docShellToFrame.get(docShell);
- const sameDocumentNavigation = !!(flags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT);
- if (frame && sameDocumentNavigation) {
- frame._url = location.spec;
- this.emit(FrameTree.Events.SameDocumentNavigation, frame);
- }
- }
-
- _onDocShellCreated(docShell) {
- // Bug 1142752: sometimes, the docshell appears to be immediately
- // destroyed, bailout early to prevent random exceptions.
- if (docShell.isBeingDestroyed())
- return;
- // If this docShell doesn't belong to our frame tree - do nothing.
- let root = docShell;
- while (root.parent)
- root = root.parent;
- if (root === this._mainFrame._docShell)
- this._createFrame(docShell);
- }
-
- _createFrame(docShell) {
- const parentFrame = this._docShellToFrame.get(docShell.parent) || null;
- const frame = new Frame(this, this._runtime, docShell, parentFrame);
- this._docShellToFrame.set(docShell, frame);
- this._frameIdToFrame.set(frame.id(), frame);
- this.emit(FrameTree.Events.FrameAttached, frame);
- // Create execution context **after** reporting frame.
- // This is our protocol contract.
- if (frame.domWindow())
- frame._onGlobalObjectCleared();
- return frame;
- }
-
- _onDocShellDestroyed(docShell) {
- const frame = this._docShellToFrame.get(docShell);
- if (frame)
- this._detachFrame(frame);
- }
-
- _detachFrame(frame) {
- // Detach all children first
- for (const subframe of frame._children)
- this._detachFrame(subframe);
- this._docShellToFrame.delete(frame._docShell);
- this._frameIdToFrame.delete(frame.id());
- if (frame._parentFrame)
- frame._parentFrame._children.delete(frame);
- frame._parentFrame = null;
- frame.dispose();
- this.emit(FrameTree.Events.FrameDetached, frame);
- }
-}
-
-FrameTree.Events = {
- FrameAttached: 'frameattached',
- FrameDetached: 'framedetached',
- WorkerCreated: 'workercreated',
- WorkerDestroyed: 'workerdestroyed',
- WebSocketCreated: 'websocketcreated',
- WebSocketOpened: 'websocketopened',
- WebSocketClosed: 'websocketclosed',
- WebSocketFrameReceived: 'websocketframereceived',
- WebSocketFrameSent: 'websocketframesent',
- NavigationStarted: 'navigationstarted',
- NavigationCommitted: 'navigationcommitted',
- NavigationAborted: 'navigationaborted',
- SameDocumentNavigation: 'samedocumentnavigation',
- PageReady: 'pageready',
- Load: 'load',
-};
-
-class IsolatedWorld {
- constructor(name) {
- this._name = name;
- this._scriptsToEvaluateOnNewDocument = [];
- this._bindings = new Map();
- }
-}
-
-class Frame {
- constructor(frameTree, runtime, docShell, parentFrame) {
- this._frameTree = frameTree;
- this._runtime = runtime;
- this._docShell = docShell;
- this._children = new Set();
- this._frameId = helper.browsingContextToFrameId(this._docShell.browsingContext);
- this._parentFrame = null;
- this._url = '';
- if (docShell.domWindow && docShell.domWindow.location)
- this._url = docShell.domWindow.location.href;
- if (parentFrame) {
- this._parentFrame = parentFrame;
- parentFrame._children.add(this);
- }
-
- this._lastCommittedNavigationId = null;
- this._pendingNavigationId = null;
- this._pendingNavigationURL = null;
-
- this._textInputProcessor = null;
-
- this._worldNameToContext = new Map();
- this._initialNavigationDone = false;
-
- this._webSocketListenerInnerWindowId = 0;
- // WebSocketListener calls frameReceived event before webSocketOpened.
- // To avoid this, serialize event reporting.
- this._webSocketInfos = new Map();
-
- const dispatchWebSocketFrameReceived = (webSocketSerialID, frame) => this._frameTree.emit(FrameTree.Events.WebSocketFrameReceived, {
- frameId: this._frameId,
- wsid: webSocketSerialID + '',
- opcode: frame.opCode,
- data: frame.opCode !== 1 ? btoa(frame.payload) : frame.payload,
- });
- this._webSocketListener = {
- QueryInterface: ChromeUtils.generateQI([Ci.nsIWebSocketEventListener, ]),
-
- webSocketCreated: (webSocketSerialID, uri, protocols) => {
- this._frameTree.emit(FrameTree.Events.WebSocketCreated, {
- frameId: this._frameId,
- wsid: webSocketSerialID + '',
- requestURL: uri,
- });
- this._webSocketInfos.set(webSocketSerialID, {
- opened: false,
- pendingIncomingFrames: [],
- });
- },
-
- webSocketOpened: (webSocketSerialID, effectiveURI, protocols, extensions, httpChannelId) => {
- this._frameTree.emit(FrameTree.Events.WebSocketOpened, {
- frameId: this._frameId,
- requestId: httpChannelId + '',
- wsid: webSocketSerialID + '',
- effectiveURL: effectiveURI,
- });
- const info = this._webSocketInfos.get(webSocketSerialID);
- info.opened = true;
- for (const frame of info.pendingIncomingFrames)
- dispatchWebSocketFrameReceived(webSocketSerialID, frame);
- },
-
- webSocketMessageAvailable: (webSocketSerialID, data, messageType) => {
- // We don't use this event.
- },
-
- webSocketClosed: (webSocketSerialID, wasClean, code, reason) => {
- this._webSocketInfos.delete(webSocketSerialID);
- let error = '';
- if (!wasClean) {
- const keys = Object.keys(Ci.nsIWebSocketChannel);
- for (const key of keys) {
- if (Ci.nsIWebSocketChannel[key] === code)
- error = key;
- }
- }
- this._frameTree.emit(FrameTree.Events.WebSocketClosed, {
- frameId: this._frameId,
- wsid: webSocketSerialID + '',
- error,
- });
- },
-
- frameReceived: (webSocketSerialID, frame) => {
- // Report only text and binary frames.
- if (frame.opCode !== 1 && frame.opCode !== 2)
- return;
- const info = this._webSocketInfos.get(webSocketSerialID);
- if (info.opened)
- dispatchWebSocketFrameReceived(webSocketSerialID, frame);
- else
- info.pendingIncomingFrames.push(frame);
- },
-
- frameSent: (webSocketSerialID, frame) => {
- // Report only text and binary frames.
- if (frame.opCode !== 1 && frame.opCode !== 2)
- return;
- this._frameTree.emit(FrameTree.Events.WebSocketFrameSent, {
- frameId: this._frameId,
- wsid: webSocketSerialID + '',
- opcode: frame.opCode,
- data: frame.opCode !== 1 ? btoa(frame.payload) : frame.payload,
- });
- },
- };
- }
-
- _createIsolatedContext(name) {
- const principal = [this.domWindow()]; // extended principal
- const sandbox = Cu.Sandbox(principal, {
- sandboxPrototype: this.domWindow(),
- wantComponents: false,
- wantExportHelpers: false,
- wantXrays: true,
- });
- const world = this._runtime.createExecutionContext(this.domWindow(), sandbox, {
- frameId: this.id(),
- name,
- });
- this._worldNameToContext.set(name, world);
- return world;
- }
-
- unsafeObject(objectId) {
- for (const context of this._worldNameToContext.values()) {
- const result = context.unsafeObject(objectId);
- if (result)
- return result.object;
- }
- throw new Error('Cannot find object with id = ' + objectId);
- }
-
- dispose() {
- for (const context of this._worldNameToContext.values())
- this._runtime.destroyExecutionContext(context);
- this._worldNameToContext.clear();
- }
-
- _addBinding(worldName, name, script) {
- let executionContext = this._worldNameToContext.get(worldName);
- if (worldName && !executionContext)
- executionContext = this._createIsolatedContext(worldName);
- if (executionContext)
- executionContext.addBinding(name, script);
- }
-
- _onGlobalObjectCleared() {
- const webSocketService = this._frameTree._webSocketEventService;
- if (this._webSocketListenerInnerWindowId)
- webSocketService.removeListener(this._webSocketListenerInnerWindowId, this._webSocketListener);
- this._webSocketListenerInnerWindowId = this.domWindow().windowGlobalChild.innerWindowId;
- webSocketService.addListener(this._webSocketListenerInnerWindowId, this._webSocketListener);
-
- for (const context of this._worldNameToContext.values())
- this._runtime.destroyExecutionContext(context);
- this._worldNameToContext.clear();
-
- this._worldNameToContext.set('', this._runtime.createExecutionContext(this.domWindow(), this.domWindow(), {
- frameId: this._frameId,
- name: '',
- }));
- for (const [name, world] of this._frameTree._isolatedWorlds) {
- if (name)
- this._createIsolatedContext(name);
- const executionContext = this._worldNameToContext.get(name);
- // Add bindings before evaluating scripts.
- for (const [name, script] of world._bindings)
- executionContext.addBinding(name, script);
- for (const script of world._scriptsToEvaluateOnNewDocument)
- executionContext.evaluateScriptSafely(script);
- }
- }
-
- mainExecutionContext() {
- return this._worldNameToContext.get('');
- }
-
- textInputProcessor() {
- if (!this._textInputProcessor) {
- this._textInputProcessor = Cc["@mozilla.org/text-input-processor;1"].createInstance(Ci.nsITextInputProcessor);
- }
- this._textInputProcessor.beginInputTransactionForTests(this._docShell.DOMWindow);
- return this._textInputProcessor;
- }
-
- pendingNavigationId() {
- return this._pendingNavigationId;
- }
-
- pendingNavigationURL() {
- return this._pendingNavigationURL;
- }
-
- lastCommittedNavigationId() {
- return this._lastCommittedNavigationId;
- }
-
- docShell() {
- return this._docShell;
- }
-
- domWindow() {
- return this._docShell.domWindow;
- }
-
- name() {
- const frameElement = this._docShell.domWindow.frameElement;
- let name = '';
- if (frameElement)
- name = frameElement.getAttribute('name') || frameElement.getAttribute('id') || '';
- return name;
- }
-
- parentFrame() {
- return this._parentFrame;
- }
-
- id() {
- return this._frameId;
- }
-
- url() {
- return this._url;
- }
-
-}
-
-class Worker {
- constructor(frame, workerDebugger) {
- this._frame = frame;
- this._workerId = helper.generateId();
- this._workerDebugger = workerDebugger;
-
- workerDebugger.initialize('chrome://juggler/content/content/WorkerMain.js');
-
- this._channel = new SimpleChannel(`content::worker[${this._workerId}]`);
- this._channel.setTransport({
- sendMessage: obj => workerDebugger.postMessage(JSON.stringify(obj)),
- dispose: () => {},
- });
- this._workerDebuggerListener = {
- QueryInterface: ChromeUtils.generateQI([Ci.nsIWorkerDebuggerListener]),
- onMessage: msg => void this._channel._onMessage(JSON.parse(msg)),
- onClose: () => void this._channel.dispose(),
- onError: (filename, lineno, message) => {
- dump(`Error in worker: ${message} @${filename}:${lineno}\n`);
- },
- };
- workerDebugger.addListener(this._workerDebuggerListener);
- }
-
- channel() {
- return this._channel;
- }
-
- frame() {
- return this._frame;
- }
-
- id() {
- return this._workerId;
- }
-
- url() {
- return this._workerDebugger.url;
- }
-
- dispose() {
- this._channel.dispose();
- this._workerDebugger.removeListener(this._workerDebuggerListener);
- }
-}
-
-function channelId(channel) {
- if (channel instanceof Ci.nsIIdentChannel) {
- const identChannel = channel.QueryInterface(Ci.nsIIdentChannel);
- return String(identChannel.channelId);
- }
- return helper.generateId();
-}
-
-
-var EXPORTED_SYMBOLS = ['FrameTree'];
-this.FrameTree = FrameTree;
-
diff --git a/browser_patches/firefox-beta/juggler/content/PageAgent.js b/browser_patches/firefox-beta/juggler/content/PageAgent.js
deleted file mode 100644
index 63a1807e4db1c8..00000000000000
--- a/browser_patches/firefox-beta/juggler/content/PageAgent.js
+++ /dev/null
@@ -1,894 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
-const Ci = Components.interfaces;
-const Cr = Components.results;
-const Cu = Components.utils;
-
-const {Helper} = ChromeUtils.import('chrome://juggler/content/Helper.js');
-const {NetUtil} = ChromeUtils.import('resource://gre/modules/NetUtil.jsm');
-const dragService = Cc["@mozilla.org/widget/dragservice;1"].getService(
- Ci.nsIDragService
-);
-const obs = Cc["@mozilla.org/observer-service;1"].getService(
- Ci.nsIObserverService
-);
-
-const helper = new Helper();
-
-class WorkerData {
- constructor(pageAgent, browserChannel, worker) {
- this._workerRuntime = worker.channel().connect('runtime');
- this._browserWorker = browserChannel.connect(worker.id());
- this._worker = worker;
- const emit = name => {
- return (...args) => this._browserWorker.emit(name, ...args);
- };
- this._eventListeners = [
- worker.channel().register('runtime', {
- runtimeConsole: emit('runtimeConsole'),
- runtimeExecutionContextCreated: emit('runtimeExecutionContextCreated'),
- runtimeExecutionContextDestroyed: emit('runtimeExecutionContextDestroyed'),
- }),
- browserChannel.register(worker.id(), {
- evaluate: (options) => this._workerRuntime.send('evaluate', options),
- callFunction: (options) => this._workerRuntime.send('callFunction', options),
- getObjectProperties: (options) => this._workerRuntime.send('getObjectProperties', options),
- disposeObject: (options) => this._workerRuntime.send('disposeObject', options),
- }),
- ];
- }
-
- dispose() {
- this._workerRuntime.dispose();
- this._browserWorker.dispose();
- helper.removeListeners(this._eventListeners);
- }
-}
-
-class PageAgent {
- constructor(messageManager, browserChannel, frameTree) {
- this._messageManager = messageManager;
- this._browserChannel = browserChannel;
- this._browserPage = browserChannel.connect('page');
- this._frameTree = frameTree;
- this._runtime = frameTree.runtime();
-
- this._workerData = new Map();
-
- const docShell = frameTree.mainFrame().docShell();
- this._docShell = docShell;
- this._initialDPPX = docShell.contentViewer.overrideDPPX;
- this._dragging = false;
-
- // Dispatch frameAttached events for all initial frames
- for (const frame of this._frameTree.frames()) {
- this._onFrameAttached(frame);
- if (frame.url())
- this._onNavigationCommitted(frame);
- if (frame.pendingNavigationId())
- this._onNavigationStarted(frame);
- }
-
- // Report created workers.
- for (const worker of this._frameTree.workers())
- this._onWorkerCreated(worker);
-
- // Report execution contexts.
- for (const context of this._runtime.executionContexts())
- this._onExecutionContextCreated(context);
-
- if (this._frameTree.isPageReady()) {
- this._browserPage.emit('pageReady', {});
- const mainFrame = this._frameTree.mainFrame();
- const domWindow = mainFrame.domWindow();
- const document = domWindow ? domWindow.document : null;
- const readyState = document ? document.readyState : null;
- // Sometimes we initialize later than the first about:blank page is opened.
- // In this case, the page might've been loaded already, and we need to issue
- // the `DOMContentLoaded` and `load` events.
- if (mainFrame.url() === 'about:blank' && readyState === 'complete')
- this._emitAllEvents(this._frameTree.mainFrame());
- }
-
- this._eventListeners = [
- helper.addObserver(this._linkClicked.bind(this, false), 'juggler-link-click'),
- helper.addObserver(this._linkClicked.bind(this, true), 'juggler-link-click-sync'),
- helper.addObserver(this._onWindowOpenInNewContext.bind(this), 'juggler-window-open-in-new-context'),
- helper.addObserver(this._filePickerShown.bind(this), 'juggler-file-picker-shown'),
- helper.addEventListener(this._messageManager, 'DOMContentLoaded', this._onDOMContentLoaded.bind(this)),
- helper.addObserver(this._onDocumentOpenLoad.bind(this), 'juggler-document-open-loaded'),
- helper.on(this._frameTree, 'load', this._onLoad.bind(this)),
- helper.on(this._frameTree, 'frameattached', this._onFrameAttached.bind(this)),
- helper.on(this._frameTree, 'framedetached', this._onFrameDetached.bind(this)),
- helper.on(this._frameTree, 'navigationstarted', this._onNavigationStarted.bind(this)),
- helper.on(this._frameTree, 'navigationcommitted', this._onNavigationCommitted.bind(this)),
- helper.on(this._frameTree, 'navigationaborted', this._onNavigationAborted.bind(this)),
- helper.on(this._frameTree, 'samedocumentnavigation', this._onSameDocumentNavigation.bind(this)),
- helper.on(this._frameTree, 'pageready', () => this._browserPage.emit('pageReady', {})),
- helper.on(this._frameTree, 'workercreated', this._onWorkerCreated.bind(this)),
- helper.on(this._frameTree, 'workerdestroyed', this._onWorkerDestroyed.bind(this)),
- helper.on(this._frameTree, 'websocketcreated', event => this._browserPage.emit('webSocketCreated', event)),
- helper.on(this._frameTree, 'websocketopened', event => this._browserPage.emit('webSocketOpened', event)),
- helper.on(this._frameTree, 'websocketframesent', event => this._browserPage.emit('webSocketFrameSent', event)),
- helper.on(this._frameTree, 'websocketframereceived', event => this._browserPage.emit('webSocketFrameReceived', event)),
- helper.on(this._frameTree, 'websocketclosed', event => this._browserPage.emit('webSocketClosed', event)),
- helper.addObserver(this._onWindowOpen.bind(this), 'webNavigation-createdNavigationTarget-from-js'),
- this._runtime.events.onErrorFromWorker((domWindow, message, stack) => {
- const frame = this._frameTree.frameForDocShell(domWindow.docShell);
- if (!frame)
- return;
- this._browserPage.emit('pageUncaughtError', {
- frameId: frame.id(),
- message,
- stack,
- });
- }),
- this._runtime.events.onConsoleMessage(msg => this._browserPage.emit('runtimeConsole', msg)),
- this._runtime.events.onRuntimeError(this._onRuntimeError.bind(this)),
- this._runtime.events.onExecutionContextCreated(this._onExecutionContextCreated.bind(this)),
- this._runtime.events.onExecutionContextDestroyed(this._onExecutionContextDestroyed.bind(this)),
- this._runtime.events.onBindingCalled(this._onBindingCalled.bind(this)),
- browserChannel.register('page', {
- addBinding: ({ worldName, name, script }) => this._frameTree.addBinding(worldName, name, script),
- adoptNode: this._adoptNode.bind(this),
- crash: this._crash.bind(this),
- describeNode: this._describeNode.bind(this),
- dispatchKeyEvent: this._dispatchKeyEvent.bind(this),
- dispatchMouseEvent: this._dispatchMouseEvent.bind(this),
- dispatchTouchEvent: this._dispatchTouchEvent.bind(this),
- dispatchTapEvent: this._dispatchTapEvent.bind(this),
- getContentQuads: this._getContentQuads.bind(this),
- getFullAXTree: this._getFullAXTree.bind(this),
- goBack: this._goBack.bind(this),
- goForward: this._goForward.bind(this),
- insertText: this._insertText.bind(this),
- navigate: this._navigate.bind(this),
- reload: this._reload.bind(this),
- scrollIntoViewIfNeeded: this._scrollIntoViewIfNeeded.bind(this),
- setCacheDisabled: this._setCacheDisabled.bind(this),
- setFileInputFiles: this._setFileInputFiles.bind(this),
- setInterceptFileChooserDialog: this._setInterceptFileChooserDialog.bind(this),
- evaluate: this._runtime.evaluate.bind(this._runtime),
- callFunction: this._runtime.callFunction.bind(this._runtime),
- getObjectProperties: this._runtime.getObjectProperties.bind(this._runtime),
- disposeObject: this._runtime.disposeObject.bind(this._runtime),
- }),
- ];
- }
-
- _setCacheDisabled({cacheDisabled}) {
- const enable = Ci.nsIRequest.LOAD_NORMAL;
- const disable = Ci.nsIRequest.LOAD_BYPASS_CACHE |
- Ci.nsIRequest.INHIBIT_CACHING;
-
- const docShell = this._frameTree.mainFrame().docShell();
- docShell.defaultLoadFlags = cacheDisabled ? disable : enable;
- }
-
- _emitAllEvents(frame) {
- this._browserPage.emit('pageEventFired', {
- frameId: frame.id(),
- name: 'DOMContentLoaded',
- });
- this._browserPage.emit('pageEventFired', {
- frameId: frame.id(),
- name: 'load',
- });
- }
-
- _onExecutionContextCreated(executionContext) {
- this._browserPage.emit('runtimeExecutionContextCreated', {
- executionContextId: executionContext.id(),
- auxData: executionContext.auxData(),
- });
- }
-
- _onExecutionContextDestroyed(executionContext) {
- this._browserPage.emit('runtimeExecutionContextDestroyed', {
- executionContextId: executionContext.id(),
- });
- }
-
- _onWorkerCreated(worker) {
- const workerData = new WorkerData(this, this._browserChannel, worker);
- this._workerData.set(worker.id(), workerData);
- this._browserPage.emit('pageWorkerCreated', {
- workerId: worker.id(),
- frameId: worker.frame().id(),
- url: worker.url(),
- });
- }
-
- _onWorkerDestroyed(worker) {
- const workerData = this._workerData.get(worker.id());
- if (!workerData)
- return;
- this._workerData.delete(worker.id());
- workerData.dispose();
- this._browserPage.emit('pageWorkerDestroyed', {
- workerId: worker.id(),
- });
- }
-
- _onWindowOpen(subject) {
- if (!(subject instanceof Ci.nsIPropertyBag2))
- return;
- const props = subject.QueryInterface(Ci.nsIPropertyBag2);
- const hasUrl = props.hasKey('url');
- const createdDocShell = props.getPropertyAsInterface('createdTabDocShell', Ci.nsIDocShell);
- if (!hasUrl && createdDocShell === this._docShell && this._frameTree.forcePageReady())
- this._emitAllEvents(this._frameTree.mainFrame());
- }
-
- _setInterceptFileChooserDialog({enabled}) {
- this._docShell.fileInputInterceptionEnabled = !!enabled;
- }
-
- _linkClicked(sync, anchorElement) {
- if (anchorElement.ownerGlobal.docShell !== this._docShell)
- return;
- this._browserPage.emit('pageLinkClicked', { phase: sync ? 'after' : 'before' });
- }
-
- _onWindowOpenInNewContext(docShell) {
- // TODO: unify this with _onWindowOpen if possible.
- const frame = this._frameTree.frameForDocShell(docShell);
- if (!frame)
- return;
- this._browserPage.emit('pageWillOpenNewWindowAsynchronously');
- }
-
- _filePickerShown(inputElement) {
- const frame = this._findFrameForNode(inputElement);
- if (!frame)
- return;
- this._browserPage.emit('pageFileChooserOpened', {
- executionContextId: frame.mainExecutionContext().id(),
- element: frame.mainExecutionContext().rawValueToRemoteObject(inputElement)
- });
- }
-
- _findFrameForNode(node) {
- return this._frameTree.frames().find(frame => {
- const doc = frame.domWindow().document;
- return node === doc || node.ownerDocument === doc;
- });
- }
-
- _onDOMContentLoaded(event) {
- if (!event.target.ownerGlobal)
- return;
- const docShell = event.target.ownerGlobal.docShell;
- const frame = this._frameTree.frameForDocShell(docShell);
- if (!frame)
- return;
- this._browserPage.emit('pageEventFired', {
- frameId: frame.id(),
- name: 'DOMContentLoaded',
- });
- }
-
- _onRuntimeError({ executionContext, message, stack }) {
- this._browserPage.emit('pageUncaughtError', {
- frameId: executionContext.auxData().frameId,
- message: message.toString(),
- stack: stack.toString(),
- });
- }
-
- _onDocumentOpenLoad(document) {
- const docShell = document.ownerGlobal.docShell;
- const frame = this._frameTree.frameForDocShell(docShell);
- if (!frame)
- return;
- this._browserPage.emit('pageEventFired', {
- frameId: frame.id(),
- name: 'load'
- });
- }
-
- _onLoad(frame) {
- this._browserPage.emit('pageEventFired', {
- frameId: frame.id(),
- name: 'load'
- });
- }
-
- _onNavigationStarted(frame) {
- this._browserPage.emit('pageNavigationStarted', {
- frameId: frame.id(),
- navigationId: frame.pendingNavigationId(),
- url: frame.pendingNavigationURL(),
- });
- }
-
- _onNavigationAborted(frame, navigationId, errorText) {
- this._browserPage.emit('pageNavigationAborted', {
- frameId: frame.id(),
- navigationId,
- errorText,
- });
- if (!frame._initialNavigationDone && frame !== this._frameTree.mainFrame())
- this._emitAllEvents(frame);
- frame._initialNavigationDone = true;
- }
-
- _onSameDocumentNavigation(frame) {
- this._browserPage.emit('pageSameDocumentNavigation', {
- frameId: frame.id(),
- url: frame.url(),
- });
- }
-
- _onNavigationCommitted(frame) {
- this._browserPage.emit('pageNavigationCommitted', {
- frameId: frame.id(),
- navigationId: frame.lastCommittedNavigationId() || undefined,
- url: frame.url(),
- name: frame.name(),
- });
- frame._initialNavigationDone = true;
- }
-
- _onFrameAttached(frame) {
- this._browserPage.emit('pageFrameAttached', {
- frameId: frame.id(),
- parentFrameId: frame.parentFrame() ? frame.parentFrame().id() : undefined,
- });
- }
-
- _onFrameDetached(frame) {
- this._browserPage.emit('pageFrameDetached', {
- frameId: frame.id(),
- });
- }
-
- _onBindingCalled({executionContextId, name, payload}) {
- this._browserPage.emit('pageBindingCalled', {
- executionContextId,
- name,
- payload
- });
- }
-
- dispose() {
- for (const workerData of this._workerData.values())
- workerData.dispose();
- this._workerData.clear();
- helper.removeListeners(this._eventListeners);
- }
-
- async _navigate({frameId, url, referer}) {
- try {
- const uri = NetUtil.newURI(url);
- } catch (e) {
- throw new Error(`Invalid url: "${url}"`);
- }
- let referrerURI = null;
- let referrerInfo = null;
- if (referer) {
- try {
- referrerURI = NetUtil.newURI(referer);
- const ReferrerInfo = Components.Constructor(
- '@mozilla.org/referrer-info;1',
- 'nsIReferrerInfo',
- 'init'
- );
- referrerInfo = new ReferrerInfo(Ci.nsIHttpChannel.REFERRER_POLICY_UNSET, true, referrerURI);
- } catch (e) {
- throw new Error(`Invalid referer: "${referer}"`);
- }
- }
- const frame = this._frameTree.frame(frameId);
- const docShell = frame.docShell().QueryInterface(Ci.nsIWebNavigation);
- docShell.loadURI(url, {
- triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
- flags: Ci.nsIWebNavigation.LOAD_FLAGS_NONE,
- referrerInfo,
- postData: null,
- headers: null,
- });
- return {navigationId: frame.pendingNavigationId(), navigationURL: frame.pendingNavigationURL()};
- }
-
- async _reload({frameId, url}) {
- const frame = this._frameTree.frame(frameId);
- const docShell = frame.docShell().QueryInterface(Ci.nsIWebNavigation);
- docShell.reload(Ci.nsIWebNavigation.LOAD_FLAGS_NONE);
- }
-
- async _goBack({frameId, url}) {
- const frame = this._frameTree.frame(frameId);
- const docShell = frame.docShell();
- if (!docShell.canGoBack)
- return {success: false};
- docShell.goBack();
- return {success: true};
- }
-
- async _goForward({frameId, url}) {
- const frame = this._frameTree.frame(frameId);
- const docShell = frame.docShell();
- if (!docShell.canGoForward)
- return {success: false};
- docShell.goForward();
- return {success: true};
- }
-
- async _adoptNode({frameId, objectId, executionContextId}) {
- const frame = this._frameTree.frame(frameId);
- if (!frame)
- throw new Error('Failed to find frame with id = ' + frameId);
- const unsafeObject = frame.unsafeObject(objectId);
- const context = this._runtime.findExecutionContext(executionContextId);
- const fromPrincipal = unsafeObject.nodePrincipal;
- const toFrame = this._frameTree.frame(context.auxData().frameId);
- const toPrincipal = toFrame.domWindow().document.nodePrincipal;
- if (!toPrincipal.subsumes(fromPrincipal))
- return { remoteObject: null };
- return { remoteObject: context.rawValueToRemoteObject(unsafeObject) };
- }
-
- async _setFileInputFiles({objectId, frameId, files}) {
- const frame = this._frameTree.frame(frameId);
- if (!frame)
- throw new Error('Failed to find frame with id = ' + frameId);
- const unsafeObject = frame.unsafeObject(objectId);
- if (!unsafeObject)
- throw new Error('Object is not input!');
- const nsFiles = await Promise.all(files.map(filePath => File.createFromFileName(filePath)));
- unsafeObject.mozSetFileArray(nsFiles);
- }
-
- _getContentQuads({objectId, frameId}) {
- const frame = this._frameTree.frame(frameId);
- if (!frame)
- throw new Error('Failed to find frame with id = ' + frameId);
- const unsafeObject = frame.unsafeObject(objectId);
- if (!unsafeObject.getBoxQuads)
- throw new Error('RemoteObject is not a node');
- const quads = unsafeObject.getBoxQuads({relativeTo: this._frameTree.mainFrame().domWindow().document, recurseWhenNoFrame: true}).map(quad => {
- return {
- p1: {x: quad.p1.x, y: quad.p1.y},
- p2: {x: quad.p2.x, y: quad.p2.y},
- p3: {x: quad.p3.x, y: quad.p3.y},
- p4: {x: quad.p4.x, y: quad.p4.y},
- };
- });
- return {quads};
- }
-
- _describeNode({objectId, frameId}) {
- const frame = this._frameTree.frame(frameId);
- if (!frame)
- throw new Error('Failed to find frame with id = ' + frameId);
- const unsafeObject = frame.unsafeObject(objectId);
- const browsingContextGroup = frame.docShell().browsingContext.group;
- const frames = this._frameTree.allFramesInBrowsingContextGroup(browsingContextGroup);
- let contentFrame;
- let ownerFrame;
- for (const frame of frames) {
- if (unsafeObject.contentWindow && frame.docShell() === unsafeObject.contentWindow.docShell)
- contentFrame = frame;
- const document = frame.domWindow().document;
- if (unsafeObject === document || unsafeObject.ownerDocument === document)
- ownerFrame = frame;
- }
- return {
- contentFrameId: contentFrame ? contentFrame.id() : undefined,
- ownerFrameId: ownerFrame ? ownerFrame.id() : undefined,
- };
- }
-
- async _scrollIntoViewIfNeeded({objectId, frameId, rect}) {
- const frame = this._frameTree.frame(frameId);
- if (!frame)
- throw new Error('Failed to find frame with id = ' + frameId);
- const unsafeObject = frame.unsafeObject(objectId);
- if (!unsafeObject.isConnected)
- throw new Error('Node is detached from document');
- if (!rect)
- rect = { x: -1, y: -1, width: -1, height: -1};
- if (unsafeObject.scrollRectIntoViewIfNeeded)
- unsafeObject.scrollRectIntoViewIfNeeded(rect.x, rect.y, rect.width, rect.height);
- else
- throw new Error('Node does not have a layout object');
- }
-
- _getNodeBoundingBox(unsafeObject) {
- if (!unsafeObject.getBoxQuads)
- throw new Error('RemoteObject is not a node');
- const quads = unsafeObject.getBoxQuads({relativeTo: this._frameTree.mainFrame().domWindow().document});
- if (!quads.length)
- return;
- let x1 = Infinity;
- let y1 = Infinity;
- let x2 = -Infinity;
- let y2 = -Infinity;
- for (const quad of quads) {
- const boundingBox = quad.getBounds();
- x1 = Math.min(boundingBox.x, x1);
- y1 = Math.min(boundingBox.y, y1);
- x2 = Math.max(boundingBox.x + boundingBox.width, x2);
- y2 = Math.max(boundingBox.y + boundingBox.height, y2);
- }
- return {x: x1, y: y1, width: x2 - x1, height: y2 - y1};
- }
-
- async _dispatchKeyEvent({type, keyCode, code, key, repeat, location, text}) {
- // key events don't fire if we are dragging.
- if (this._dragging) {
- if (type === 'keydown' && key === 'Escape')
- this._cancelDragIfNeeded();
- return;
- }
- const frame = this._frameTree.mainFrame();
- const tip = frame.textInputProcessor();
- if (key === 'Meta' && Services.appinfo.OS !== 'Darwin')
- key = 'OS';
- else if (key === 'OS' && Services.appinfo.OS === 'Darwin')
- key = 'Meta';
- let keyEvent = new (frame.domWindow().KeyboardEvent)("", {
- key,
- code,
- location,
- repeat,
- keyCode
- });
- if (type === 'keydown') {
- if (text && text !== key) {
- tip.commitCompositionWith(text, keyEvent);
- } else {
- const flags = 0;
- tip.keydown(keyEvent, flags);
- }
- } else if (type === 'keyup') {
- if (text)
- throw new Error(`keyup does not support text option`);
- const flags = 0;
- tip.keyup(keyEvent, flags);
- } else {
- throw new Error(`Unknown type ${type}`);
- }
- }
-
- async _dispatchTouchEvent({type, touchPoints, modifiers}) {
- const frame = this._frameTree.mainFrame();
- const defaultPrevented = frame.domWindow().windowUtils.sendTouchEvent(
- type.toLowerCase(),
- touchPoints.map((point, id) => id),
- touchPoints.map(point => point.x),
- touchPoints.map(point => point.y),
- touchPoints.map(point => point.radiusX === undefined ? 1.0 : point.radiusX),
- touchPoints.map(point => point.radiusY === undefined ? 1.0 : point.radiusY),
- touchPoints.map(point => point.rotationAngle === undefined ? 0.0 : point.rotationAngle),
- touchPoints.map(point => point.force === undefined ? 1.0 : point.force),
- touchPoints.length,
- modifiers);
- return {defaultPrevented};
- }
-
- async _dispatchTapEvent({x, y, modifiers}) {
- // Force a layout at the point in question, because touch events
- // do not seem to trigger one like mouse events.
- this._frameTree.mainFrame().domWindow().windowUtils.elementFromPoint(
- x,
- y,
- false /* aIgnoreRootScrollFrame */,
- true /* aFlushLayout */);
-
- const {defaultPrevented: startPrevented} = await this._dispatchTouchEvent({
- type: 'touchstart',
- modifiers,
- touchPoints: [{x, y}]
- });
- const {defaultPrevented: endPrevented} = await this._dispatchTouchEvent({
- type: 'touchend',
- modifiers,
- touchPoints: [{x, y}]
- });
- if (startPrevented || endPrevented)
- return;
-
- const frame = this._frameTree.mainFrame();
- frame.domWindow().windowUtils.sendMouseEvent(
- 'mousemove',
- x,
- y,
- 0 /*button*/,
- 0 /*clickCount*/,
- modifiers,
- false /*aIgnoreRootScrollFrame*/,
- undefined /*pressure*/,
- 5 /*inputSource*/,
- undefined /*isDOMEventSynthesized*/,
- false /*isWidgetEventSynthesized*/,
- 0 /*buttons*/,
- undefined /*pointerIdentifier*/,
- true /*disablePointerEvent*/);
-
- frame.domWindow().windowUtils.sendMouseEvent(
- 'mousedown',
- x,
- y,
- 0 /*button*/,
- 1 /*clickCount*/,
- modifiers,
- false /*aIgnoreRootScrollFrame*/,
- undefined /*pressure*/,
- 5 /*inputSource*/,
- undefined /*isDOMEventSynthesized*/,
- false /*isWidgetEventSynthesized*/,
- 1 /*buttons*/,
- undefined /*pointerIdentifier*/,
- true /*disablePointerEvent*/);
-
- frame.domWindow().windowUtils.sendMouseEvent(
- 'mouseup',
- x,
- y,
- 0 /*button*/,
- 1 /*clickCount*/,
- modifiers,
- false /*aIgnoreRootScrollFrame*/,
- undefined /*pressure*/,
- 5 /*inputSource*/,
- undefined /*isDOMEventSynthesized*/,
- false /*isWidgetEventSynthesized*/,
- 0 /*buttons*/,
- undefined /*pointerIdentifier*/,
- true /*disablePointerEvent*/);
- }
-
- _startDragSessionIfNeeded() {
- const sess = dragService.getCurrentSession();
- if (sess) return;
- dragService.startDragSessionForTests(
- Ci.nsIDragService.DRAGDROP_ACTION_MOVE |
- Ci.nsIDragService.DRAGDROP_ACTION_COPY |
- Ci.nsIDragService.DRAGDROP_ACTION_LINK
- );
- }
-
- _simulateDragEvent(type, x, y, modifiers) {
- const window = this._frameTree.mainFrame().domWindow();
- const element = window.windowUtils.elementFromPoint(x, y, false, false);
- const event = window.document.createEvent('DragEvent');
-
- event.initDragEvent(
- type,
- true /* bubble */,
- true /* cancelable */,
- window,
- 0 /* clickCount */,
- window.mozInnerScreenX + x,
- window.mozInnerScreenY + y,
- x,
- y,
- modifiers & 2 /* ctrlkey */,
- modifiers & 1 /* altKey */,
- modifiers & 4 /* shiftKey */,
- modifiers & 8 /* metaKey */,
- 0 /* button */, // firefox always has the button as 0 on drops, regardless of which was pressed
- null /* relatedTarget */,
- null,
- );
- if (type !== 'drop' || dragService.dragAction)
- window.windowUtils.dispatchDOMEventViaPresShellForTesting(element, event);
- if (type === 'drop')
- this._cancelDragIfNeeded();
- }
-
- _cancelDragIfNeeded() {
- this._dragging = false;
- const sess = dragService.getCurrentSession();
- if (sess)
- dragService.endDragSession(true);
- }
-
- async _dispatchMouseEvent({type, x, y, button, clickCount, modifiers, buttons}) {
- this._startDragSessionIfNeeded();
- const trapDrag = subject => {
- this._dragging = true;
- }
-
- // Don't send mouse events if there is an active drag
- if (!this._dragging) {
- const frame = this._frameTree.mainFrame();
-
- obs.addObserver(trapDrag, 'on-datatransfer-available');
- frame.domWindow().windowUtils.sendMouseEvent(
- type,
- x,
- y,
- button,
- clickCount,
- modifiers,
- false /*aIgnoreRootScrollFrame*/,
- undefined /*pressure*/,
- undefined /*inputSource*/,
- true /*isDOMEventSynthesized*/,
- false /*isWidgetEventSynthesized*/,
- buttons);
- obs.removeObserver(trapDrag, 'on-datatransfer-available');
-
- if (type === 'mousedown' && button === 2) {
- frame.domWindow().windowUtils.sendMouseEvent(
- 'contextmenu',
- x,
- y,
- button,
- clickCount,
- modifiers,
- false /*aIgnoreRootScrollFrame*/,
- undefined /*pressure*/,
- undefined /*inputSource*/,
- undefined /*isDOMEventSynthesized*/,
- undefined /*isWidgetEventSynthesized*/,
- buttons);
- }
- }
-
- // update drag state
- if (this._dragging) {
- if (type === 'mousemove')
- this._simulateDragEvent('dragover', x, y, modifiers);
- else if (type === 'mouseup') // firefox will do drops when any mouse button is released
- this._simulateDragEvent('drop', x, y, modifiers);
- } else {
- this._cancelDragIfNeeded();
- }
- }
-
- async _insertText({text}) {
- const frame = this._frameTree.mainFrame();
- frame.textInputProcessor().commitCompositionWith(text);
- }
-
- async _crash() {
- dump(`Crashing intentionally\n`);
- // This is to intentionally crash the frame.
- // We crash by using js-ctypes and dereferencing
- // a bad pointer. The crash should happen immediately
- // upon loading this frame script.
- const { ctypes } = ChromeUtils.import('resource://gre/modules/ctypes.jsm');
- ChromeUtils.privateNoteIntentionalCrash();
- const zero = new ctypes.intptr_t(8);
- 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)
- };
- }
-}
-
-var EXPORTED_SYMBOLS = ['PageAgent'];
-this.PageAgent = PageAgent;
-
diff --git a/browser_patches/firefox-beta/juggler/content/Runtime.js b/browser_patches/firefox-beta/juggler/content/Runtime.js
deleted file mode 100644
index 20c046a1dbd36c..00000000000000
--- a/browser_patches/firefox-beta/juggler/content/Runtime.js
+++ /dev/null
@@ -1,596 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-// Note: this file should be loadabale with eval() into worker environment.
-// Avoid Components.*, ChromeUtils and global const variables.
-
-if (!this.Debugger) {
- // Worker has a Debugger defined already.
- const {addDebuggerToGlobal} = ChromeUtils.import("resource://gre/modules/jsdebugger.jsm", {});
- addDebuggerToGlobal(Components.utils.getGlobalForObject(this));
-}
-
-let lastId = 0;
-function generateId() {
- return 'id-' + (++lastId);
-}
-
-const consoleLevelToProtocolType = {
- 'dir': 'dir',
- 'log': 'log',
- 'debug': 'debug',
- 'info': 'info',
- 'error': 'error',
- 'warn': 'warning',
- 'dirxml': 'dirxml',
- 'table': 'table',
- 'trace': 'trace',
- 'clear': 'clear',
- 'group': 'startGroup',
- 'groupCollapsed': 'startGroupCollapsed',
- 'groupEnd': 'endGroup',
- 'assert': 'assert',
- 'profile': 'profile',
- 'profileEnd': 'profileEnd',
- 'count': 'count',
- 'countReset': 'countReset',
- 'time': null,
- 'timeLog': 'timeLog',
- 'timeEnd': 'timeEnd',
- 'timeStamp': 'timeStamp',
-};
-
-const disallowedMessageCategories = new Set([
- 'XPConnect JavaScript',
- 'component javascript',
- 'chrome javascript',
- 'chrome registration',
- 'XBL',
- 'XBL Prototype Handler',
- 'XBL Content Sink',
- 'xbl javascript',
-]);
-
-class Runtime {
- constructor(isWorker = false) {
- this._debugger = new Debugger();
- this._pendingPromises = new Map();
- this._executionContexts = new Map();
- this._windowToExecutionContext = new Map();
- this._eventListeners = [];
- if (isWorker) {
- this._registerWorkerConsoleHandler();
- } else {
- const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
- this._registerConsoleServiceListener(Services);
- this._registerConsoleAPIListener(Services);
- }
- // We can't use event listener here to be compatible with Worker Global Context.
- // Use plain callbacks instead.
- this.events = {
- onConsoleMessage: createEvent(),
- onRuntimeError: createEvent(),
- onErrorFromWorker: createEvent(),
- onExecutionContextCreated: createEvent(),
- onExecutionContextDestroyed: createEvent(),
- onBindingCalled: createEvent(),
- };
- }
-
- executionContexts() {
- return [...this._executionContexts.values()];
- }
-
- async evaluate({executionContextId, expression, returnByValue}) {
- const executionContext = this.findExecutionContext(executionContextId);
- if (!executionContext)
- throw new Error('Failed to find execution context with id = ' + executionContextId);
- const exceptionDetails = {};
- let result = await executionContext.evaluateScript(expression, exceptionDetails);
- if (!result)
- return {exceptionDetails};
- if (returnByValue)
- result = executionContext.ensureSerializedToValue(result);
- return {result};
- }
-
- async callFunction({executionContextId, functionDeclaration, args, returnByValue}) {
- const executionContext = this.findExecutionContext(executionContextId);
- if (!executionContext)
- throw new Error('Failed to find execution context with id = ' + executionContextId);
- const exceptionDetails = {};
- let result = await executionContext.evaluateFunction(functionDeclaration, args, exceptionDetails);
- if (!result)
- return {exceptionDetails};
- if (returnByValue)
- result = executionContext.ensureSerializedToValue(result);
- return {result};
- }
-
- async getObjectProperties({executionContextId, objectId}) {
- const executionContext = this.findExecutionContext(executionContextId);
- if (!executionContext)
- throw new Error('Failed to find execution context with id = ' + executionContextId);
- return {properties: executionContext.getObjectProperties(objectId)};
- }
-
- async disposeObject({executionContextId, objectId}) {
- const executionContext = this.findExecutionContext(executionContextId);
- if (!executionContext)
- throw new Error('Failed to find execution context with id = ' + executionContextId);
- return executionContext.disposeObject(objectId);
- }
-
- _registerConsoleServiceListener(Services) {
- const Ci = Components.interfaces;
- const consoleServiceListener = {
- QueryInterface: ChromeUtils.generateQI([Ci.nsIConsoleListener]),
-
- observe: message => {
- if (!(message instanceof Ci.nsIScriptError) || !message.outerWindowID ||
- !message.category || disallowedMessageCategories.has(message.category)) {
- return;
- }
- const errorWindow = Services.wm.getOuterWindowWithId(message.outerWindowID);
- if (message.category === 'Web Worker' && message.logLevel === Ci.nsIConsoleMessage.error) {
- emitEvent(this.events.onErrorFromWorker, errorWindow, message.message, '' + message.stack);
- return;
- }
- const executionContext = this._windowToExecutionContext.get(errorWindow);
- if (!executionContext) {
- return;
- }
- const typeNames = {
- [Ci.nsIConsoleMessage.debug]: 'debug',
- [Ci.nsIConsoleMessage.info]: 'info',
- [Ci.nsIConsoleMessage.warn]: 'warn',
- [Ci.nsIConsoleMessage.error]: 'error',
- };
- if (!message.hasException) {
- emitEvent(this.events.onConsoleMessage, {
- args: [{
- value: message.message,
- }],
- type: typeNames[message.logLevel],
- executionContextId: executionContext.id(),
- location: {
- lineNumber: message.lineNumber,
- columnNumber: message.columnNumber,
- url: message.sourceName,
- },
- });
- } else {
- emitEvent(this.events.onRuntimeError, {
- executionContext,
- message: message.errorMessage,
- stack: message.stack.toString(),
- });
- }
- },
- };
- Services.console.registerListener(consoleServiceListener);
- this._eventListeners.push(() => Services.console.unregisterListener(consoleServiceListener));
- }
-
- _registerConsoleAPIListener(Services) {
- const Ci = Components.interfaces;
- const Cc = Components.classes;
- const ConsoleAPIStorage = Cc["@mozilla.org/consoleAPI-storage;1"].getService(Ci.nsIConsoleAPIStorage);
- const onMessage = ({ wrappedJSObject }) => {
- const executionContext = Array.from(this._executionContexts.values()).find(context => {
- // There is no easy way to determine isolated world context and we normally don't write
- // objects to console from utility worlds so we always return main world context here.
- if (context._isIsolatedWorldContext())
- return false;
- const domWindow = context._domWindow;
- return domWindow && domWindow.windowGlobalChild.innerWindowId === wrappedJSObject.innerID;
- });
- if (!executionContext)
- return;
- this._onConsoleMessage(executionContext, wrappedJSObject);
- }
- ConsoleAPIStorage.addLogEventListener(
- onMessage,
- Cc["@mozilla.org/systemprincipal;1"].createInstance(Ci.nsIPrincipal)
- );
- this._eventListeners.push(() => ConsoleAPIStorage.removeLogEventListener(onMessage));
- }
-
- _registerWorkerConsoleHandler() {
- setConsoleEventHandler(message => {
- const executionContext = Array.from(this._executionContexts.values())[0];
- this._onConsoleMessage(executionContext, message);
- });
- this._eventListeners.push(() => setConsoleEventHandler(null));
- }
-
- _onConsoleMessage(executionContext, message) {
- const type = consoleLevelToProtocolType[message.level];
- if (!type)
- return;
- const args = message.arguments.map(arg => executionContext.rawValueToRemoteObject(arg));
- emitEvent(this.events.onConsoleMessage, {
- args,
- type,
- executionContextId: executionContext.id(),
- location: {
- lineNumber: message.lineNumber - 1,
- columnNumber: message.columnNumber - 1,
- url: message.filename,
- },
- });
- }
-
- dispose() {
- for (const tearDown of this._eventListeners)
- tearDown.call(null);
- this._eventListeners = [];
- }
-
- async _awaitPromise(executionContext, obj, exceptionDetails = {}) {
- if (obj.promiseState === 'fulfilled')
- return {success: true, obj: obj.promiseValue};
- if (obj.promiseState === 'rejected') {
- const debuggee = executionContext._debuggee;
- exceptionDetails.text = debuggee.executeInGlobalWithBindings('e.message', {e: obj.promiseReason}).return;
- exceptionDetails.stack = debuggee.executeInGlobalWithBindings('e.stack', {e: obj.promiseReason}).return;
- return {success: false, obj: null};
- }
- let resolve, reject;
- const promise = new Promise((a, b) => {
- resolve = a;
- reject = b;
- });
- this._pendingPromises.set(obj.promiseID, {resolve, reject, executionContext, exceptionDetails});
- if (this._pendingPromises.size === 1)
- this._debugger.onPromiseSettled = this._onPromiseSettled.bind(this);
- return await promise;
- }
-
- _onPromiseSettled(obj) {
- const pendingPromise = this._pendingPromises.get(obj.promiseID);
- if (!pendingPromise)
- return;
- this._pendingPromises.delete(obj.promiseID);
- if (!this._pendingPromises.size)
- this._debugger.onPromiseSettled = undefined;
-
- if (obj.promiseState === 'fulfilled') {
- pendingPromise.resolve({success: true, obj: obj.promiseValue});
- return;
- };
- const debuggee = pendingPromise.executionContext._debuggee;
- pendingPromise.exceptionDetails.text = debuggee.executeInGlobalWithBindings('e.message', {e: obj.promiseReason}).return;
- pendingPromise.exceptionDetails.stack = debuggee.executeInGlobalWithBindings('e.stack', {e: obj.promiseReason}).return;
- pendingPromise.resolve({success: false, obj: null});
- }
-
- createExecutionContext(domWindow, contextGlobal, auxData) {
- // Note: domWindow is null for workers.
- const context = new ExecutionContext(this, domWindow, contextGlobal, auxData);
- this._executionContexts.set(context._id, context);
- if (domWindow)
- this._windowToExecutionContext.set(domWindow, context);
- emitEvent(this.events.onExecutionContextCreated, context);
- return context;
- }
-
- findExecutionContext(executionContextId) {
- const executionContext = this._executionContexts.get(executionContextId);
- if (!executionContext)
- throw new Error('Failed to find execution context with id = ' + executionContextId);
- return executionContext;
- }
-
- destroyExecutionContext(destroyedContext) {
- for (const [promiseID, {reject, executionContext}] of this._pendingPromises) {
- if (executionContext === destroyedContext) {
- reject(new Error('Execution context was destroyed!'));
- this._pendingPromises.delete(promiseID);
- }
- }
- if (!this._pendingPromises.size)
- this._debugger.onPromiseSettled = undefined;
- this._debugger.removeDebuggee(destroyedContext._contextGlobal);
- this._executionContexts.delete(destroyedContext._id);
- if (destroyedContext._domWindow)
- this._windowToExecutionContext.delete(destroyedContext._domWindow);
- emitEvent(this.events.onExecutionContextDestroyed, destroyedContext);
- }
-}
-
-class ExecutionContext {
- constructor(runtime, domWindow, contextGlobal, auxData) {
- this._runtime = runtime;
- this._domWindow = domWindow;
- this._contextGlobal = contextGlobal;
- this._debuggee = runtime._debugger.addDebuggee(contextGlobal);
- this._remoteObjects = new Map();
- this._id = generateId();
- this._auxData = auxData;
- this._jsonStringifyObject = this._debuggee.executeInGlobal(`((stringify, object) => {
- const oldToJSON = Date.prototype.toJSON;
- Date.prototype.toJSON = undefined;
- const oldArrayToJSON = Array.prototype.toJSON;
- const oldArrayHadToJSON = Array.prototype.hasOwnProperty('toJSON');
- if (oldArrayHadToJSON)
- Array.prototype.toJSON = undefined;
-
- let hasSymbol = false;
- const result = stringify(object, (key, value) => {
- if (typeof value === 'symbol')
- hasSymbol = true;
- return value;
- });
-
- Date.prototype.toJSON = oldToJSON;
- if (oldArrayHadToJSON)
- Array.prototype.toJSON = oldArrayToJSON;
-
- return hasSymbol ? undefined : result;
- }).bind(null, JSON.stringify.bind(JSON))`).return;
- }
-
- id() {
- return this._id;
- }
-
- auxData() {
- return this._auxData;
- }
-
- _isIsolatedWorldContext() {
- return !!this._auxData.name;
- }
-
- async evaluateScript(script, exceptionDetails = {}) {
- const userInputHelper = this._domWindow ? this._domWindow.windowUtils.setHandlingUserInput(true) : null;
- if (this._domWindow && this._domWindow.document)
- this._domWindow.document.notifyUserGestureActivation();
-
- let {success, obj} = this._getResult(this._debuggee.executeInGlobal(script), exceptionDetails);
- userInputHelper && userInputHelper.destruct();
- if (!success)
- return null;
- if (obj && obj.isPromise) {
- const awaitResult = await this._runtime._awaitPromise(this, obj, exceptionDetails);
- if (!awaitResult.success)
- return null;
- obj = awaitResult.obj;
- }
- return this._createRemoteObject(obj);
- }
-
- evaluateScriptSafely(script) {
- try {
- this._debuggee.executeInGlobal(script);
- } catch (e) {
- dump(`ERROR: ${e.message}\n${e.stack}\n`);
- }
- }
-
- async evaluateFunction(functionText, args, exceptionDetails = {}) {
- const funEvaluation = this._getResult(this._debuggee.executeInGlobal('(' + functionText + ')'), exceptionDetails);
- if (!funEvaluation.success)
- return null;
- if (!funEvaluation.obj.callable)
- throw new Error('functionText does not evaluate to a function!');
- args = args.map(arg => {
- if (arg.objectId) {
- if (!this._remoteObjects.has(arg.objectId))
- throw new Error('Cannot find object with id = ' + arg.objectId);
- return this._remoteObjects.get(arg.objectId);
- }
- switch (arg.unserializableValue) {
- case 'Infinity': return Infinity;
- case '-Infinity': return -Infinity;
- case '-0': return -0;
- case 'NaN': return NaN;
- default: return this._toDebugger(arg.value);
- }
- });
- const userInputHelper = this._domWindow ? this._domWindow.windowUtils.setHandlingUserInput(true) : null;
- if (this._domWindow && this._domWindow.document)
- this._domWindow.document.notifyUserGestureActivation();
- let {success, obj} = this._getResult(funEvaluation.obj.apply(null, args), exceptionDetails);
- userInputHelper && userInputHelper.destruct();
- if (!success)
- return null;
- if (obj && obj.isPromise) {
- const awaitResult = await this._runtime._awaitPromise(this, obj, exceptionDetails);
- if (!awaitResult.success)
- return null;
- obj = awaitResult.obj;
- }
- return this._createRemoteObject(obj);
- }
-
- addBinding(name, script) {
- Cu.exportFunction((...args) => {
- emitEvent(this._runtime.events.onBindingCalled, {
- executionContextId: this._id,
- name,
- payload: args[0],
- });
- }, this._contextGlobal, {
- defineAs: name,
- });
- this.evaluateScriptSafely(script);
- }
-
- unsafeObject(objectId) {
- if (!this._remoteObjects.has(objectId))
- return;
- return { object: this._remoteObjects.get(objectId).unsafeDereference() };
- }
-
- rawValueToRemoteObject(rawValue) {
- const debuggerObj = this._debuggee.makeDebuggeeValue(rawValue);
- return this._createRemoteObject(debuggerObj);
- }
-
- _instanceOf(debuggerObj, rawObj, className) {
- if (this._domWindow)
- return rawObj instanceof this._domWindow[className];
- return this._debuggee.executeInGlobalWithBindings('o instanceof this[className]', {o: debuggerObj, className: this._debuggee.makeDebuggeeValue(className)}).return;
- }
-
- _createRemoteObject(debuggerObj) {
- if (debuggerObj instanceof Debugger.Object) {
- const objectId = generateId();
- this._remoteObjects.set(objectId, debuggerObj);
- const rawObj = debuggerObj.unsafeDereference();
- const type = typeof rawObj;
- let subtype = undefined;
- if (debuggerObj.isProxy)
- subtype = 'proxy';
- else if (Array.isArray(rawObj))
- subtype = 'array';
- else if (Object.is(rawObj, null))
- subtype = 'null';
- else if (this._instanceOf(debuggerObj, rawObj, 'Node'))
- subtype = 'node';
- else if (this._instanceOf(debuggerObj, rawObj, 'RegExp'))
- subtype = 'regexp';
- else if (this._instanceOf(debuggerObj, rawObj, 'Date'))
- subtype = 'date';
- else if (this._instanceOf(debuggerObj, rawObj, 'Map'))
- subtype = 'map';
- else if (this._instanceOf(debuggerObj, rawObj, 'Set'))
- subtype = 'set';
- else if (this._instanceOf(debuggerObj, rawObj, 'WeakMap'))
- subtype = 'weakmap';
- else if (this._instanceOf(debuggerObj, rawObj, 'WeakSet'))
- subtype = 'weakset';
- else if (this._instanceOf(debuggerObj, rawObj, 'Error'))
- subtype = 'error';
- else if (this._instanceOf(debuggerObj, rawObj, 'Promise'))
- subtype = 'promise';
- else if ((this._instanceOf(debuggerObj, rawObj, 'Int8Array')) || (this._instanceOf(debuggerObj, rawObj, 'Uint8Array')) ||
- (this._instanceOf(debuggerObj, rawObj, 'Uint8ClampedArray')) || (this._instanceOf(debuggerObj, rawObj, 'Int16Array')) ||
- (this._instanceOf(debuggerObj, rawObj, 'Uint16Array')) || (this._instanceOf(debuggerObj, rawObj, 'Int32Array')) ||
- (this._instanceOf(debuggerObj, rawObj, 'Uint32Array')) || (this._instanceOf(debuggerObj, rawObj, 'Float32Array')) ||
- (this._instanceOf(debuggerObj, rawObj, 'Float64Array'))) {
- subtype = 'typedarray';
- }
- return {objectId, type, subtype};
- }
- if (typeof debuggerObj === 'symbol') {
- const objectId = generateId();
- this._remoteObjects.set(objectId, debuggerObj);
- return {objectId, type: 'symbol'};
- }
-
- let unserializableValue = undefined;
- if (Object.is(debuggerObj, NaN))
- unserializableValue = 'NaN';
- else if (Object.is(debuggerObj, -0))
- unserializableValue = '-0';
- else if (Object.is(debuggerObj, Infinity))
- unserializableValue = 'Infinity';
- else if (Object.is(debuggerObj, -Infinity))
- unserializableValue = '-Infinity';
- return unserializableValue ? {unserializableValue} : {value: debuggerObj};
- }
-
- ensureSerializedToValue(protocolObject) {
- if (!protocolObject.objectId)
- return protocolObject;
- const obj = this._remoteObjects.get(protocolObject.objectId);
- this._remoteObjects.delete(protocolObject.objectId);
- return {value: this._serialize(obj)};
- }
-
- _toDebugger(obj) {
- if (typeof obj !== 'object')
- return obj;
- if (obj === null)
- return obj;
- const properties = {};
- for (let [key, value] of Object.entries(obj)) {
- properties[key] = {
- configurable: true,
- writable: true,
- enumerable: true,
- value: this._toDebugger(value),
- };
- }
- const baseObject = Array.isArray(obj) ? '([])' : '({})';
- const debuggerObj = this._debuggee.executeInGlobal(baseObject).return;
- debuggerObj.defineProperties(properties);
- return debuggerObj;
- }
-
- _serialize(obj) {
- const result = this._debuggee.executeInGlobalWithBindings('stringify(e)', {e: obj, stringify: this._jsonStringifyObject});
- if (result.throw)
- throw new Error('Object is not serializable');
- return result.return === undefined ? undefined : JSON.parse(result.return);
- }
-
- disposeObject(objectId) {
- this._remoteObjects.delete(objectId);
- }
-
- getObjectProperties(objectId) {
- if (!this._remoteObjects.has(objectId))
- throw new Error('Cannot find object with id = ' + arg.objectId);
- const result = [];
- for (let obj = this._remoteObjects.get(objectId); obj; obj = obj.proto) {
- for (const propertyName of obj.getOwnPropertyNames()) {
- const descriptor = obj.getOwnPropertyDescriptor(propertyName);
- if (!descriptor.enumerable)
- continue;
- result.push({
- name: propertyName,
- value: this._createRemoteObject(descriptor.value),
- });
- }
- }
- return result;
- }
-
- _getResult(completionValue, exceptionDetails = {}) {
- if (!completionValue) {
- exceptionDetails.text = 'Evaluation terminated!';
- exceptionDetails.stack = '';
- return {success: false, obj: null};
- }
- if (completionValue.throw) {
- if (this._debuggee.executeInGlobalWithBindings('e instanceof Error', {e: completionValue.throw}).return) {
- exceptionDetails.text = this._debuggee.executeInGlobalWithBindings('e.message', {e: completionValue.throw}).return;
- exceptionDetails.stack = this._debuggee.executeInGlobalWithBindings('e.stack', {e: completionValue.throw}).return;
- } else {
- exceptionDetails.value = this._serialize(completionValue.throw);
- }
- return {success: false, obj: null};
- }
- return {success: true, obj: completionValue.return};
- }
-}
-
-const listenersSymbol = Symbol('listeners');
-
-function createEvent() {
- const listeners = new Set();
- const subscribeFunction = listener => {
- listeners.add(listener);
- return () => listeners.delete(listener);
- }
- subscribeFunction[listenersSymbol] = listeners;
- return subscribeFunction;
-}
-
-function emitEvent(event, ...args) {
- let listeners = event[listenersSymbol];
- if (!listeners || !listeners.size)
- return;
- listeners = new Set(listeners);
- for (const listener of listeners)
- listener.call(null, ...args);
-}
-
-var EXPORTED_SYMBOLS = ['Runtime'];
-this.Runtime = Runtime;
diff --git a/browser_patches/firefox-beta/juggler/content/WorkerMain.js b/browser_patches/firefox-beta/juggler/content/WorkerMain.js
deleted file mode 100644
index 3d0c1168cb8915..00000000000000
--- a/browser_patches/firefox-beta/juggler/content/WorkerMain.js
+++ /dev/null
@@ -1,76 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-loadSubScript('chrome://juggler/content/content/Runtime.js');
-loadSubScript('chrome://juggler/content/SimpleChannel.js');
-
-const channel = new SimpleChannel('worker::worker');
-const eventListener = event => channel._onMessage(JSON.parse(event.data));
-this.addEventListener('message', eventListener);
-channel.setTransport({
- sendMessage: msg => postMessage(JSON.stringify(msg)),
- dispose: () => this.removeEventListener('message', eventListener),
-});
-
-const runtime = new Runtime(true /* isWorker */);
-
-(() => {
- // Create execution context in the runtime only when the script
- // source was actually evaluated in it.
- const dbg = new Debugger(global);
- if (dbg.findScripts({global}).length) {
- runtime.createExecutionContext(null /* domWindow */, global, {});
- } else {
- dbg.onNewScript = function(s) {
- dbg.onNewScript = undefined;
- dbg.removeAllDebuggees();
- runtime.createExecutionContext(null /* domWindow */, global, {});
- };
- }
-})();
-
-class RuntimeAgent {
- constructor(runtime, channel) {
- this._runtime = runtime;
- this._browserRuntime = channel.connect('runtime');
-
- for (const context of this._runtime.executionContexts())
- this._onExecutionContextCreated(context);
-
- this._eventListeners = [
- this._runtime.events.onConsoleMessage(msg => this._browserRuntime.emit('runtimeConsole', msg)),
- this._runtime.events.onExecutionContextCreated(this._onExecutionContextCreated.bind(this)),
- this._runtime.events.onExecutionContextDestroyed(this._onExecutionContextDestroyed.bind(this)),
- channel.register('runtime', {
- evaluate: this._runtime.evaluate.bind(this._runtime),
- callFunction: this._runtime.callFunction.bind(this._runtime),
- getObjectProperties: this._runtime.getObjectProperties.bind(this._runtime),
- disposeObject: this._runtime.disposeObject.bind(this._runtime),
- }),
- ];
- }
-
- _onExecutionContextCreated(executionContext) {
- this._browserRuntime.emit('runtimeExecutionContextCreated', {
- executionContextId: executionContext.id(),
- auxData: executionContext.auxData(),
- });
- }
-
- _onExecutionContextDestroyed(executionContext) {
- this._browserRuntime.emit('runtimeExecutionContextDestroyed', {
- executionContextId: executionContext.id(),
- });
- }
-
- dispose() {
- for (const disposer of this._eventListeners)
- disposer();
- this._eventListeners = [];
- }
-}
-
-new RuntimeAgent(runtime, channel);
-
diff --git a/browser_patches/firefox-beta/juggler/content/hidden-scrollbars.css b/browser_patches/firefox-beta/juggler/content/hidden-scrollbars.css
deleted file mode 100644
index 26fc0db7680db4..00000000000000
--- a/browser_patches/firefox-beta/juggler/content/hidden-scrollbars.css
+++ /dev/null
@@ -1,7 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-* {
- scrollbar-width: none !important;
-}
diff --git a/browser_patches/firefox-beta/juggler/content/main.js b/browser_patches/firefox-beta/juggler/content/main.js
deleted file mode 100644
index d471ab955327d3..00000000000000
--- a/browser_patches/firefox-beta/juggler/content/main.js
+++ /dev/null
@@ -1,155 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
-const {Helper} = ChromeUtils.import('chrome://juggler/content/Helper.js');
-const {FrameTree} = ChromeUtils.import('chrome://juggler/content/content/FrameTree.js');
-const {SimpleChannel} = ChromeUtils.import('chrome://juggler/content/SimpleChannel.js');
-const {PageAgent} = ChromeUtils.import('chrome://juggler/content/content/PageAgent.js');
-
-let frameTree;
-const helper = new Helper();
-const messageManager = this;
-
-let pageAgent;
-
-let failedToOverrideTimezone = false;
-
-const applySetting = {
- geolocation: (geolocation) => {
- if (geolocation) {
- docShell.setGeolocationOverride({
- coords: {
- latitude: geolocation.latitude,
- longitude: geolocation.longitude,
- accuracy: geolocation.accuracy,
- altitude: NaN,
- altitudeAccuracy: NaN,
- heading: NaN,
- speed: NaN,
- },
- address: null,
- timestamp: Date.now()
- });
- } else {
- docShell.setGeolocationOverride(null);
- }
- },
-
- onlineOverride: (onlineOverride) => {
- if (!onlineOverride) {
- docShell.onlineOverride = Ci.nsIDocShell.ONLINE_OVERRIDE_NONE;
- return;
- }
- docShell.onlineOverride = onlineOverride === 'online' ?
- Ci.nsIDocShell.ONLINE_OVERRIDE_ONLINE : Ci.nsIDocShell.ONLINE_OVERRIDE_OFFLINE;
- },
-
- bypassCSP: (bypassCSP) => {
- docShell.bypassCSPEnabled = bypassCSP;
- },
-
- timezoneId: (timezoneId) => {
- failedToOverrideTimezone = !docShell.overrideTimezone(timezoneId);
- },
-
- locale: (locale) => {
- docShell.languageOverride = locale;
- },
-
- scrollbarsHidden: (hidden) => {
- frameTree.setScrollbarsHidden(hidden);
- },
-
- colorScheme: (colorScheme) => {
- frameTree.setColorScheme(colorScheme);
- },
-
- reducedMotion: (reducedMotion) => {
- frameTree.setReducedMotion(reducedMotion);
- },
-
- forcedColors: (forcedColors) => {
- frameTree.setForcedColors(forcedColors);
- },
-};
-
-const channel = SimpleChannel.createForMessageManager('content::page', messageManager);
-
-function initialize() {
- const response = sendSyncMessage('juggler:content-ready')[0];
- // If we didn't get a response, then we don't want to do anything
- // as a part of this frame script.
- if (!response)
- return;
- const {
- initScripts = [],
- bindings = [],
- settings = {}
- } = response || {};
- // Enforce focused state for all top level documents.
- docShell.overrideHasFocus = true;
- docShell.forceActiveState = true;
- frameTree = new FrameTree(docShell);
- for (const [name, value] of Object.entries(settings)) {
- if (value !== undefined)
- applySetting[name](value);
- }
- for (const { worldName, name, script } of bindings)
- frameTree.addBinding(worldName, name, script);
- frameTree.setInitScripts(initScripts);
-
- pageAgent = new PageAgent(messageManager, channel, frameTree);
-
- channel.register('', {
- setInitScripts(scripts) {
- frameTree.setInitScripts(scripts);
- },
-
- addBinding({worldName, name, script}) {
- frameTree.addBinding(worldName, name, script);
- },
-
- applyContextSetting({name, value}) {
- applySetting[name](value);
- },
-
- ensurePermissions() {
- // noop, just a rountrip.
- },
-
- hasFailedToOverrideTimezone() {
- return failedToOverrideTimezone;
- },
-
- async awaitViewportDimensions({width, height, deviceSizeIsPageSize}) {
- docShell.deviceSizeIsPageSize = deviceSizeIsPageSize;
- const win = docShell.domWindow;
- if (win.innerWidth === width && win.innerHeight === height)
- return;
- await new Promise(resolve => {
- const listener = helper.addEventListener(win, 'resize', () => {
- if (win.innerWidth === width && win.innerHeight === height) {
- helper.removeListeners([listener]);
- resolve();
- }
- });
- });
- },
-
- dispose() {
- },
- });
-
- const gListeners = [
- helper.addEventListener(messageManager, 'unload', msg => {
- helper.removeListeners(gListeners);
- pageAgent.dispose();
- frameTree.dispose();
- channel.dispose();
- }),
- ];
-}
-
-initialize();
diff --git a/browser_patches/firefox-beta/juggler/jar.mn b/browser_patches/firefox-beta/juggler/jar.mn
deleted file mode 100644
index 8b3d3922c14ab3..00000000000000
--- a/browser_patches/firefox-beta/juggler/jar.mn
+++ /dev/null
@@ -1,25 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-juggler.jar:
-% content juggler %content/
-
- content/components/Juggler.js (components/Juggler.js)
-
- content/Helper.js (Helper.js)
- content/NetworkObserver.js (NetworkObserver.js)
- content/TargetRegistry.js (TargetRegistry.js)
- content/SimpleChannel.js (SimpleChannel.js)
- content/protocol/PrimitiveTypes.js (protocol/PrimitiveTypes.js)
- content/protocol/Protocol.js (protocol/Protocol.js)
- content/protocol/Dispatcher.js (protocol/Dispatcher.js)
- content/protocol/PageHandler.js (protocol/PageHandler.js)
- content/protocol/BrowserHandler.js (protocol/BrowserHandler.js)
- content/content/main.js (content/main.js)
- content/content/FrameTree.js (content/FrameTree.js)
- content/content/PageAgent.js (content/PageAgent.js)
- content/content/Runtime.js (content/Runtime.js)
- content/content/WorkerMain.js (content/WorkerMain.js)
- content/content/hidden-scrollbars.css (content/hidden-scrollbars.css)
-
diff --git a/browser_patches/firefox-beta/juggler/moz.build b/browser_patches/firefox-beta/juggler/moz.build
deleted file mode 100644
index 905c20cc3139ef..00000000000000
--- a/browser_patches/firefox-beta/juggler/moz.build
+++ /dev/null
@@ -1,10 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-DIRS += ["components", "screencast", "pipe"]
-
-JAR_MANIFESTS += ["jar.mn"]
-with Files("**"):
- BUG_COMPONENT = ("Testing", "Juggler")
-
diff --git a/browser_patches/firefox-beta/juggler/pipe/components.conf b/browser_patches/firefox-beta/juggler/pipe/components.conf
deleted file mode 100644
index db13a00ba7c979..00000000000000
--- a/browser_patches/firefox-beta/juggler/pipe/components.conf
+++ /dev/null
@@ -1,15 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-Classes = [
- {
- 'cid': '{d69ecefe-3df7-4d11-9dc7-f604edb96da2}',
- 'contract_ids': ['@mozilla.org/juggler/remotedebuggingpipe;1'],
- 'type': 'nsIRemoteDebuggingPipe',
- 'constructor': 'mozilla::nsRemoteDebuggingPipe::GetSingleton',
- 'headers': ['/juggler/pipe/nsRemoteDebuggingPipe.h'],
- },
-]
diff --git a/browser_patches/firefox-beta/juggler/pipe/moz.build b/browser_patches/firefox-beta/juggler/pipe/moz.build
deleted file mode 100644
index b56c697881173f..00000000000000
--- a/browser_patches/firefox-beta/juggler/pipe/moz.build
+++ /dev/null
@@ -1,24 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-XPIDL_SOURCES += [
- 'nsIRemoteDebuggingPipe.idl',
-]
-
-XPIDL_MODULE = 'jugglerpipe'
-
-SOURCES += [
- 'nsRemoteDebuggingPipe.cpp',
-]
-
-XPCOM_MANIFESTS += [
- 'components.conf',
-]
-
-LOCAL_INCLUDES += [
-]
-
-FINAL_LIBRARY = 'xul'
diff --git a/browser_patches/firefox-beta/juggler/pipe/nsIRemoteDebuggingPipe.idl b/browser_patches/firefox-beta/juggler/pipe/nsIRemoteDebuggingPipe.idl
deleted file mode 100644
index ac91b636155a3e..00000000000000
--- a/browser_patches/firefox-beta/juggler/pipe/nsIRemoteDebuggingPipe.idl
+++ /dev/null
@@ -1,20 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-[scriptable, uuid(7910c231-971a-4653-abdc-a8599a986c4c)]
-interface nsIRemoteDebuggingPipeClient : nsISupports
-{
- void receiveMessage(in AString message);
- void disconnected();
-};
-
-[scriptable, uuid(b7bfb66b-fd46-4aa2-b4ad-396177186d94)]
-interface nsIRemoteDebuggingPipe : nsISupports
-{
- void init(in nsIRemoteDebuggingPipeClient client);
- void sendMessage(in AString message);
- void stop();
-};
diff --git a/browser_patches/firefox-beta/juggler/pipe/nsRemoteDebuggingPipe.cpp b/browser_patches/firefox-beta/juggler/pipe/nsRemoteDebuggingPipe.cpp
deleted file mode 100644
index abcb0a758fac13..00000000000000
--- a/browser_patches/firefox-beta/juggler/pipe/nsRemoteDebuggingPipe.cpp
+++ /dev/null
@@ -1,223 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsRemoteDebuggingPipe.h"
-
-#include
-#if defined(_WIN32)
-#include
-#include
-#else
-#include
-#include
-#include
-#endif
-
-#include "mozilla/StaticPtr.h"
-#include "nsISupportsPrimitives.h"
-#include "nsThreadUtils.h"
-
-namespace mozilla {
-
-NS_IMPL_ISUPPORTS(nsRemoteDebuggingPipe, nsIRemoteDebuggingPipe)
-
-namespace {
-
-StaticRefPtr gPipe;
-
-const size_t kWritePacketSize = 1 << 16;
-
-#if defined(_WIN32)
-HANDLE readHandle;
-HANDLE writeHandle;
-#else
-const int readFD = 3;
-const int writeFD = 4;
-#endif
-
-size_t ReadBytes(void* buffer, size_t size, bool exact_size)
-{
- size_t bytesRead = 0;
- while (bytesRead < size) {
-#if defined(_WIN32)
- DWORD sizeRead = 0;
- bool hadError = !ReadFile(readHandle, static_cast(buffer) + bytesRead,
- size - bytesRead, &sizeRead, nullptr);
-#else
- int sizeRead = read(readFD, static_cast(buffer) + bytesRead,
- size - bytesRead);
- if (sizeRead < 0 && errno == EINTR)
- continue;
- bool hadError = sizeRead <= 0;
-#endif
- if (hadError) {
- return 0;
- }
- bytesRead += sizeRead;
- if (!exact_size)
- break;
- }
- return bytesRead;
-}
-
-void WriteBytes(const char* bytes, size_t size)
-{
- size_t totalWritten = 0;
- while (totalWritten < size) {
- size_t length = size - totalWritten;
- if (length > kWritePacketSize)
- length = kWritePacketSize;
-#if defined(_WIN32)
- DWORD bytesWritten = 0;
- bool hadError = !WriteFile(writeHandle, bytes + totalWritten, static_cast(length), &bytesWritten, nullptr);
-#else
- int bytesWritten = write(writeFD, bytes + totalWritten, length);
- if (bytesWritten < 0 && errno == EINTR)
- continue;
- bool hadError = bytesWritten <= 0;
-#endif
- if (hadError)
- return;
- totalWritten += bytesWritten;
- }
-}
-
-} // namespace
-
-// static
-already_AddRefed nsRemoteDebuggingPipe::GetSingleton() {
- if (!gPipe) {
- gPipe = new nsRemoteDebuggingPipe();
- }
- return do_AddRef(gPipe);
-}
-
-nsRemoteDebuggingPipe::nsRemoteDebuggingPipe() = default;
-
-nsRemoteDebuggingPipe::~nsRemoteDebuggingPipe() = default;
-
-nsresult nsRemoteDebuggingPipe::Init(nsIRemoteDebuggingPipeClient* aClient) {
- MOZ_RELEASE_ASSERT(NS_IsMainThread(), "Remote debugging pipe must be used on the Main thread.");
- if (mClient) {
- return NS_ERROR_FAILURE;
- }
- mClient = aClient;
-
- MOZ_ALWAYS_SUCCEEDS(NS_NewNamedThread("Pipe Reader", getter_AddRefs(mReaderThread)));
- MOZ_ALWAYS_SUCCEEDS(NS_NewNamedThread("Pipe Writer", getter_AddRefs(mWriterThread)));
-
-#if defined(_WIN32)
- CHAR pipeReadStr[20];
- CHAR pipeWriteStr[20];
- GetEnvironmentVariableA("PW_PIPE_READ", pipeReadStr, 20);
- GetEnvironmentVariableA("PW_PIPE_WRITE", pipeWriteStr, 20);
- readHandle = reinterpret_cast(atoi(pipeReadStr));
- writeHandle = reinterpret_cast(atoi(pipeWriteStr));
-#endif
-
- MOZ_ALWAYS_SUCCEEDS(mReaderThread->Dispatch(NewRunnableMethod(
- "nsRemoteDebuggingPipe::ReaderLoop",
- this, &nsRemoteDebuggingPipe::ReaderLoop), nsIThread::DISPATCH_NORMAL));
- return NS_OK;
-}
-
-nsresult nsRemoteDebuggingPipe::Stop() {
- MOZ_RELEASE_ASSERT(NS_IsMainThread(), "Remote debugging pipe must be used on the Main thread.");
- if (!mClient) {
- return NS_ERROR_FAILURE;
- }
- m_terminated = true;
- mClient = nullptr;
- // Cancel pending synchronous read.
-#if defined(_WIN32)
- CancelIoEx(readHandle, nullptr);
- CloseHandle(readHandle);
- CloseHandle(writeHandle);
-#else
- shutdown(readFD, SHUT_RDWR);
- shutdown(writeFD, SHUT_RDWR);
-#endif
- mReaderThread->Shutdown();
- mReaderThread = nullptr;
- mWriterThread->Shutdown();
- mWriterThread = nullptr;
- return NS_OK;
-}
-
-void nsRemoteDebuggingPipe::ReaderLoop() {
- const size_t bufSize = 256 * 1024;
- std::vector buffer;
- buffer.resize(bufSize);
- std::vector line;
- while (!m_terminated) {
- size_t size = ReadBytes(buffer.data(), bufSize, false);
- if (!size) {
- nsCOMPtr runnable = NewRunnableMethod<>(
- "nsRemoteDebuggingPipe::Disconnected",
- this, &nsRemoteDebuggingPipe::Disconnected);
- NS_DispatchToMainThread(runnable.forget());
- break;
- }
- size_t start = 0;
- size_t end = line.size();
- line.insert(line.end(), buffer.begin(), buffer.begin() + size);
- while (true) {
- for (; end < line.size(); ++end) {
- if (line[end] == '\0') {
- break;
- }
- }
- if (end == line.size()) {
- break;
- }
- if (end > start) {
- nsCString message;
- message.Append(line.data() + start, end - start);
- nsCOMPtr runnable = NewRunnableMethod(
- "nsRemoteDebuggingPipe::ReceiveMessage",
- this, &nsRemoteDebuggingPipe::ReceiveMessage, std::move(message));
- NS_DispatchToMainThread(runnable.forget());
- }
- ++end;
- start = end;
- }
- if (start != 0 && start < line.size()) {
- memmove(line.data(), line.data() + start, line.size() - start);
- }
- line.resize(line.size() - start);
- }
-}
-
-void nsRemoteDebuggingPipe::ReceiveMessage(const nsCString& aMessage) {
- MOZ_RELEASE_ASSERT(NS_IsMainThread(), "Remote debugging pipe must be used on the Main thread.");
- if (mClient) {
- NS_ConvertUTF8toUTF16 utf16(aMessage);
- mClient->ReceiveMessage(utf16);
- }
-}
-
-void nsRemoteDebuggingPipe::Disconnected() {
- MOZ_RELEASE_ASSERT(NS_IsMainThread(), "Remote debugging pipe must be used on the Main thread.");
- if (mClient)
- mClient->Disconnected();
-}
-
-nsresult nsRemoteDebuggingPipe::SendMessage(const nsAString& aMessage) {
- MOZ_RELEASE_ASSERT(NS_IsMainThread(), "Remote debugging pipe must be used on the Main thread.");
- if (!mClient) {
- return NS_ERROR_FAILURE;
- }
- NS_ConvertUTF16toUTF8 utf8(aMessage);
- nsCOMPtr runnable = NS_NewRunnableFunction(
- "nsRemoteDebuggingPipe::SendMessage",
- [message = std::move(utf8)] {
- const nsCString& flat = PromiseFlatCString(message);
- WriteBytes(flat.Data(), flat.Length());
- WriteBytes("\0", 1);
- });
- MOZ_ALWAYS_SUCCEEDS(mWriterThread->Dispatch(runnable.forget(), nsIThread::DISPATCH_NORMAL));
- return NS_OK;
-}
-
-} // namespace mozilla
diff --git a/browser_patches/firefox-beta/juggler/pipe/nsRemoteDebuggingPipe.h b/browser_patches/firefox-beta/juggler/pipe/nsRemoteDebuggingPipe.h
deleted file mode 100644
index be4cb2675e7810..00000000000000
--- a/browser_patches/firefox-beta/juggler/pipe/nsRemoteDebuggingPipe.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#pragma once
-
-#include
-#include "nsCOMPtr.h"
-#include "nsIRemoteDebuggingPipe.h"
-#include "nsThread.h"
-
-namespace mozilla {
-
-class nsRemoteDebuggingPipe final : public nsIRemoteDebuggingPipe {
- public:
- NS_DECL_THREADSAFE_ISUPPORTS
- NS_DECL_NSIREMOTEDEBUGGINGPIPE
-
- static already_AddRefed GetSingleton();
- nsRemoteDebuggingPipe();
-
- private:
- void ReaderLoop();
- void ReceiveMessage(const nsCString& aMessage);
- void Disconnected();
- ~nsRemoteDebuggingPipe();
-
- RefPtr mClient;
- nsCOMPtr mReaderThread;
- nsCOMPtr mWriterThread;
- std::atomic m_terminated { false };
-};
-
-} // namespace mozilla
diff --git a/browser_patches/firefox-beta/juggler/protocol/BrowserHandler.js b/browser_patches/firefox-beta/juggler/protocol/BrowserHandler.js
deleted file mode 100644
index 623f9cc3312689..00000000000000
--- a/browser_patches/firefox-beta/juggler/protocol/BrowserHandler.js
+++ /dev/null
@@ -1,296 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const {AddonManager} = ChromeUtils.import("resource://gre/modules/AddonManager.jsm");
-const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
-const {TargetRegistry} = ChromeUtils.import("chrome://juggler/content/TargetRegistry.js");
-const {Helper} = ChromeUtils.import('chrome://juggler/content/Helper.js');
-const {PageHandler} = ChromeUtils.import("chrome://juggler/content/protocol/PageHandler.js");
-const {AppConstants} = ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
-
-const helper = new Helper();
-
-class BrowserHandler {
- constructor(session, dispatcher, targetRegistry, onclose, onstart) {
- this._session = session;
- this._dispatcher = dispatcher;
- this._targetRegistry = targetRegistry;
- this._enabled = false;
- this._attachToDefaultContext = false;
- this._eventListeners = [];
- this._createdBrowserContextIds = new Set();
- this._attachedSessions = new Map();
- this._onclose = onclose;
- this._onstart = onstart;
- }
-
- async ['Browser.enable']({attachToDefaultContext}) {
- if (this._enabled)
- return;
- await this._onstart();
- this._enabled = true;
- this._attachToDefaultContext = attachToDefaultContext;
-
- this._eventListeners = [
- helper.on(this._targetRegistry, TargetRegistry.Events.TargetCreated, this._onTargetCreated.bind(this)),
- helper.on(this._targetRegistry, TargetRegistry.Events.TargetDestroyed, this._onTargetDestroyed.bind(this)),
- helper.on(this._targetRegistry, TargetRegistry.Events.DownloadCreated, this._onDownloadCreated.bind(this)),
- helper.on(this._targetRegistry, TargetRegistry.Events.DownloadFinished, this._onDownloadFinished.bind(this)),
- helper.on(this._targetRegistry, TargetRegistry.Events.ScreencastStopped, sessionId => {
- this._session.emitEvent('Browser.videoRecordingFinished', {screencastId: '' + sessionId});
- })
- ];
-
- for (const target of this._targetRegistry.targets())
- this._onTargetCreated(target);
- }
-
- async ['Browser.createBrowserContext']({removeOnDetach}) {
- if (!this._enabled)
- throw new Error('Browser domain is not enabled');
- const browserContext = this._targetRegistry.createBrowserContext(removeOnDetach);
- this._createdBrowserContextIds.add(browserContext.browserContextId);
- return {browserContextId: browserContext.browserContextId};
- }
-
- async ['Browser.removeBrowserContext']({browserContextId}) {
- if (!this._enabled)
- throw new Error('Browser domain is not enabled');
- await this._targetRegistry.browserContextForId(browserContextId).destroy();
- this._createdBrowserContextIds.delete(browserContextId);
- }
-
- dispose() {
- helper.removeListeners(this._eventListeners);
- for (const [target, session] of this._attachedSessions)
- this._dispatcher.destroySession(session);
- this._attachedSessions.clear();
- for (const browserContextId of this._createdBrowserContextIds) {
- const browserContext = this._targetRegistry.browserContextForId(browserContextId);
- if (browserContext.removeOnDetach)
- browserContext.destroy();
- }
- this._createdBrowserContextIds.clear();
- }
-
- _shouldAttachToTarget(target) {
- if (this._createdBrowserContextIds.has(target._browserContext.browserContextId))
- return true;
- return this._attachToDefaultContext && target._browserContext === this._targetRegistry.defaultContext();
- }
-
- _onTargetCreated(target) {
- if (!this._shouldAttachToTarget(target))
- return;
- const channel = target.channel();
- const session = this._dispatcher.createSession();
- this._attachedSessions.set(target, session);
- this._session.emitEvent('Browser.attachedToTarget', {
- sessionId: session.sessionId(),
- targetInfo: target.info()
- });
- session.setHandler(new PageHandler(target, session, channel));
- }
-
- _onTargetDestroyed(target) {
- const session = this._attachedSessions.get(target);
- if (!session)
- return;
- this._attachedSessions.delete(target);
- this._dispatcher.destroySession(session);
- this._session.emitEvent('Browser.detachedFromTarget', {
- sessionId: session.sessionId(),
- targetId: target.id(),
- });
- }
-
- _onDownloadCreated(downloadInfo) {
- this._session.emitEvent('Browser.downloadCreated', downloadInfo);
- }
-
- _onDownloadFinished(downloadInfo) {
- this._session.emitEvent('Browser.downloadFinished', downloadInfo);
- }
-
- async ['Browser.cancelDownload']({uuid}) {
- await this._targetRegistry.cancelDownload({uuid});
- }
-
- async ['Browser.newPage']({browserContextId}) {
- const targetId = await this._targetRegistry.newPage({browserContextId});
- return {targetId};
- }
-
- async ['Browser.close']() {
- let browserWindow = Services.wm.getMostRecentWindow(
- "navigator:browser"
- );
- if (browserWindow && browserWindow.gBrowserInit) {
- // idleTasksFinishedPromise does not resolve when the window
- // is closed early enough, so we race against window closure.
- await Promise.race([
- browserWindow.gBrowserInit.idleTasksFinishedPromise,
- waitForWindowClosed(browserWindow),
- ]);
- }
- this._onclose();
- Services.startup.quit(Ci.nsIAppStartup.eForceQuit);
- }
-
- async ['Browser.grantPermissions']({browserContextId, origin, permissions}) {
- await this._targetRegistry.browserContextForId(browserContextId).grantPermissions(origin, permissions);
- }
-
- async ['Browser.resetPermissions']({browserContextId}) {
- this._targetRegistry.browserContextForId(browserContextId).resetPermissions();
- }
-
- ['Browser.setExtraHTTPHeaders']({browserContextId, headers}) {
- this._targetRegistry.browserContextForId(browserContextId).extraHTTPHeaders = headers;
- }
-
- ['Browser.setHTTPCredentials']({browserContextId, credentials}) {
- this._targetRegistry.browserContextForId(browserContextId).httpCredentials = nullToUndefined(credentials);
- }
-
- async ['Browser.setBrowserProxy']({type, host, port, bypass, username, password}) {
- this._targetRegistry.setBrowserProxy({ type, host, port, bypass, username, password});
- }
-
- async ['Browser.setContextProxy']({browserContextId, type, host, port, bypass, username, password}) {
- const browserContext = this._targetRegistry.browserContextForId(browserContextId);
- browserContext.setProxy({ type, host, port, bypass, username, password });
- }
-
- ['Browser.setRequestInterception']({browserContextId, enabled}) {
- this._targetRegistry.browserContextForId(browserContextId).requestInterceptionEnabled = enabled;
- }
-
- ['Browser.setIgnoreHTTPSErrors']({browserContextId, ignoreHTTPSErrors}) {
- this._targetRegistry.browserContextForId(browserContextId).setIgnoreHTTPSErrors(nullToUndefined(ignoreHTTPSErrors));
- }
-
- ['Browser.setDownloadOptions']({browserContextId, downloadOptions}) {
- this._targetRegistry.browserContextForId(browserContextId).downloadOptions = nullToUndefined(downloadOptions);
- }
-
- async ['Browser.setGeolocationOverride']({browserContextId, geolocation}) {
- await this._targetRegistry.browserContextForId(browserContextId).applySetting('geolocation', nullToUndefined(geolocation));
- }
-
- async ['Browser.setOnlineOverride']({browserContextId, override}) {
- await this._targetRegistry.browserContextForId(browserContextId).applySetting('onlineOverride', nullToUndefined(override));
- }
-
- async ['Browser.setColorScheme']({browserContextId, colorScheme}) {
- await this._targetRegistry.browserContextForId(browserContextId).setColorScheme(nullToUndefined(colorScheme));
- }
-
- async ['Browser.setReducedMotion']({browserContextId, reducedMotion}) {
- await this._targetRegistry.browserContextForId(browserContextId).setReducedMotion(nullToUndefined(reducedMotion));
- }
-
- async ['Browser.setForcedColors']({browserContextId, forcedColors}) {
- await this._targetRegistry.browserContextForId(browserContextId).setForcedColors(nullToUndefined(forcedColors));
- }
-
- async ['Browser.setVideoRecordingOptions']({browserContextId, options}) {
- await this._targetRegistry.browserContextForId(browserContextId).setVideoRecordingOptions(options);
- }
-
- async ['Browser.setUserAgentOverride']({browserContextId, userAgent}) {
- await this._targetRegistry.browserContextForId(browserContextId).setDefaultUserAgent(userAgent);
- }
-
- async ['Browser.setPlatformOverride']({browserContextId, platform}) {
- await this._targetRegistry.browserContextForId(browserContextId).setDefaultPlatform(platform);
- }
-
- async ['Browser.setBypassCSP']({browserContextId, bypassCSP}) {
- await this._targetRegistry.browserContextForId(browserContextId).applySetting('bypassCSP', nullToUndefined(bypassCSP));
- }
-
- async ['Browser.setJavaScriptDisabled']({browserContextId, javaScriptDisabled}) {
- await this._targetRegistry.browserContextForId(browserContextId).setJavaScriptDisabled(javaScriptDisabled);
- }
-
- async ['Browser.setLocaleOverride']({browserContextId, locale}) {
- await this._targetRegistry.browserContextForId(browserContextId).applySetting('locale', nullToUndefined(locale));
- }
-
- async ['Browser.setTimezoneOverride']({browserContextId, timezoneId}) {
- await this._targetRegistry.browserContextForId(browserContextId).applySetting('timezoneId', nullToUndefined(timezoneId));
- }
-
- async ['Browser.setTouchOverride']({browserContextId, hasTouch}) {
- await this._targetRegistry.browserContextForId(browserContextId).setTouchOverride(nullToUndefined(hasTouch));
- }
-
- async ['Browser.setDefaultViewport']({browserContextId, viewport}) {
- await this._targetRegistry.browserContextForId(browserContextId).setDefaultViewport(nullToUndefined(viewport));
- }
-
- async ['Browser.setScrollbarsHidden']({browserContextId, hidden}) {
- await this._targetRegistry.browserContextForId(browserContextId).applySetting('scrollbarsHidden', nullToUndefined(hidden));
- }
-
- async ['Browser.setInitScripts']({browserContextId, scripts}) {
- await this._targetRegistry.browserContextForId(browserContextId).setInitScripts(scripts);
- }
-
- async ['Browser.addBinding']({browserContextId, worldName, name, script}) {
- await this._targetRegistry.browserContextForId(browserContextId).addBinding(worldName, name, script);
- }
-
- ['Browser.setCookies']({browserContextId, cookies}) {
- this._targetRegistry.browserContextForId(browserContextId).setCookies(cookies);
- }
-
- ['Browser.clearCookies']({browserContextId}) {
- this._targetRegistry.browserContextForId(browserContextId).clearCookies();
- }
-
- ['Browser.getCookies']({browserContextId}) {
- const cookies = this._targetRegistry.browserContextForId(browserContextId).getCookies();
- return {cookies};
- }
-
- async ['Browser.getInfo']() {
- const version = AppConstants.MOZ_APP_VERSION_DISPLAY;
- const userAgent = Components.classes["@mozilla.org/network/protocol;1?name=http"]
- .getService(Components.interfaces.nsIHttpProtocolHandler)
- .userAgent;
- return {version: 'Firefox/' + version, userAgent};
- }
-}
-
-async function waitForWindowClosed(browserWindow) {
- if (browserWindow.closed)
- return;
- await new Promise((resolve => {
- const listener = {
- onCloseWindow: window => {
- let domWindow;
- if (window instanceof Ci.nsIAppWindow)
- domWindow = window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
- else
- domWindow = window;
- if (domWindow === browserWindow) {
- Services.wm.removeListener(listener);
- resolve();
- }
- },
- };
- Services.wm.addListener(listener);
- }));
-}
-
-function nullToUndefined(value) {
- return value === null ? undefined : value;
-}
-
-var EXPORTED_SYMBOLS = ['BrowserHandler'];
-this.BrowserHandler = BrowserHandler;
diff --git a/browser_patches/firefox-beta/juggler/protocol/Dispatcher.js b/browser_patches/firefox-beta/juggler/protocol/Dispatcher.js
deleted file mode 100644
index af72f307ac4953..00000000000000
--- a/browser_patches/firefox-beta/juggler/protocol/Dispatcher.js
+++ /dev/null
@@ -1,135 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-const {protocol, checkScheme} = ChromeUtils.import("chrome://juggler/content/protocol/Protocol.js");
-const {Helper} = ChromeUtils.import('chrome://juggler/content/Helper.js');
-
-const helper = new Helper();
-
-class Dispatcher {
- /**
- * @param {Connection} connection
- */
- constructor(connection) {
- this._connection = connection;
- this._connection.onmessage = this._dispatch.bind(this);
- this._connection.onclose = this._dispose.bind(this);
- this._sessions = new Map();
- this._rootSession = new ProtocolSession(this, undefined);
- }
-
- rootSession() {
- return this._rootSession;
- }
-
- createSession() {
- const session = new ProtocolSession(this, helper.generateId());
- this._sessions.set(session.sessionId(), session);
- return session;
- }
-
- destroySession(session) {
- this._sessions.delete(session.sessionId());
- session._dispose();
- }
-
- _dispose() {
- this._connection.onmessage = null;
- this._connection.onclose = null;
- this._rootSession._dispose();
- this._rootSession = null;
- this._sessions.clear();
- }
-
- async _dispatch(event) {
- const data = JSON.parse(event.data);
- const id = data.id;
- const sessionId = data.sessionId;
- delete data.sessionId;
- try {
- const session = sessionId ? this._sessions.get(sessionId) : this._rootSession;
- if (!session)
- throw new Error(`ERROR: cannot find session with id "${sessionId}"`);
- const method = data.method;
- const params = data.params || {};
- if (!id)
- throw new Error(`ERROR: every message must have an 'id' parameter`);
- if (!method)
- throw new Error(`ERROR: every message must have a 'method' parameter`);
-
- const [domain, methodName] = method.split('.');
- const descriptor = protocol.domains[domain] ? protocol.domains[domain].methods[methodName] : null;
- if (!descriptor)
- throw new Error(`ERROR: method '${method}' is not supported`);
- let details = {};
- if (!checkScheme(descriptor.params || {}, params, details))
- throw new Error(`ERROR: failed to call method '${method}' with parameters ${JSON.stringify(params, null, 2)}\n${details.error}`);
-
- const result = await session.dispatch(method, params);
-
- details = {};
- if ((descriptor.returns || result) && !checkScheme(descriptor.returns, result, details))
- throw new Error(`ERROR: failed to dispatch method '${method}' result ${JSON.stringify(result, null, 2)}\n${details.error}`);
-
- this._connection.send(JSON.stringify({id, sessionId, result}));
- } catch (e) {
- this._connection.send(JSON.stringify({id, sessionId, error: {
- message: e.message,
- data: e.stack
- }}));
- }
- }
-
- _emitEvent(sessionId, eventName, params) {
- const [domain, eName] = eventName.split('.');
- const scheme = protocol.domains[domain] ? protocol.domains[domain].events[eName] : null;
- if (!scheme)
- throw new Error(`ERROR: event '${eventName}' is not supported`);
- const details = {};
- if (!checkScheme(scheme, params || {}, details))
- throw new Error(`ERROR: failed to emit event '${eventName}' ${JSON.stringify(params, null, 2)}\n${details.error}`);
- this._connection.send(JSON.stringify({method: eventName, params, sessionId}));
- }
-}
-
-class ProtocolSession {
- constructor(dispatcher, sessionId) {
- this._sessionId = sessionId;
- this._dispatcher = dispatcher;
- this._handler = null;
- }
-
- sessionId() {
- return this._sessionId;
- }
-
- setHandler(handler) {
- this._handler = handler;
- }
-
- _dispose() {
- if (this._handler)
- this._handler.dispose();
- this._handler = null;
- this._dispatcher = null;
- }
-
- emitEvent(eventName, params) {
- if (!this._dispatcher)
- throw new Error(`Session has been disposed.`);
- this._dispatcher._emitEvent(this._sessionId, eventName, params);
- }
-
- async dispatch(method, params) {
- if (!this._handler)
- throw new Error(`Session does not have a handler!`);
- if (!this._handler[method])
- throw new Error(`Handler for does not implement method "${method}"`);
- return await this._handler[method](params);
- }
-}
-
-this.EXPORTED_SYMBOLS = ['Dispatcher'];
-this.Dispatcher = Dispatcher;
-
diff --git a/browser_patches/firefox-beta/juggler/protocol/PageHandler.js b/browser_patches/firefox-beta/juggler/protocol/PageHandler.js
deleted file mode 100644
index 415f395aaf048f..00000000000000
--- a/browser_patches/firefox-beta/juggler/protocol/PageHandler.js
+++ /dev/null
@@ -1,466 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const {Helper} = ChromeUtils.import('chrome://juggler/content/Helper.js');
-const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
-const {NetworkObserver, PageNetwork} = ChromeUtils.import('chrome://juggler/content/NetworkObserver.js');
-const {PageTarget} = ChromeUtils.import('chrome://juggler/content/TargetRegistry.js');
-const {setTimeout} = ChromeUtils.import('resource://gre/modules/Timer.jsm');
-
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const Cu = Components.utils;
-const XUL_NS = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul';
-const helper = new Helper();
-
-function hashConsoleMessage(params) {
- return params.location.lineNumber + ':' + params.location.columnNumber + ':' + params.location.url;
-}
-
-class WorkerHandler {
- constructor(session, contentChannel, workerId) {
- this._session = session;
- this._contentWorker = contentChannel.connect(workerId);
- this._workerConsoleMessages = new Set();
- this._workerId = workerId;
-
- const emitWrappedProtocolEvent = eventName => {
- return params => {
- this._session.emitEvent('Page.dispatchMessageFromWorker', {
- workerId,
- message: JSON.stringify({method: eventName, params}),
- });
- }
- }
-
- this._eventListeners = [
- contentChannel.register(workerId, {
- runtimeConsole: (params) => {
- this._workerConsoleMessages.add(hashConsoleMessage(params));
- emitWrappedProtocolEvent('Runtime.console')(params);
- },
- runtimeExecutionContextCreated: emitWrappedProtocolEvent('Runtime.executionContextCreated'),
- runtimeExecutionContextDestroyed: emitWrappedProtocolEvent('Runtime.executionContextDestroyed'),
- }),
- ];
- }
-
- async sendMessage(message) {
- const [domain, method] = message.method.split('.');
- if (domain !== 'Runtime')
- throw new Error('ERROR: can only dispatch to Runtime domain inside worker');
- const result = await this._contentWorker.send(method, message.params);
- this._session.emitEvent('Page.dispatchMessageFromWorker', {
- workerId: this._workerId,
- message: JSON.stringify({result, id: message.id}),
- });
- }
-
- dispose() {
- this._contentWorker.dispose();
- helper.removeListeners(this._eventListeners);
- }
-}
-
-class PageHandler {
- constructor(target, session, contentChannel) {
- this._session = session;
- this._contentChannel = contentChannel;
- this._contentPage = contentChannel.connect('page');
- this._workers = new Map();
-
- this._pageTarget = target;
- this._pageNetwork = PageNetwork.forPageTarget(target);
-
- const emitProtocolEvent = eventName => {
- return (...args) => this._session.emitEvent(eventName, ...args);
- }
-
- this._reportedFrameIds = new Set();
- this._networkEventsForUnreportedFrameIds = new Map();
-
- // `Page.ready` protocol event is emitted whenever page has completed initialization, e.g.
- // finished all the transient navigations to the `about:blank`.
- //
- // We'd like to avoid reporting meaningful events before the `Page.ready` since they are likely
- // to be ignored by the protocol clients.
- this._isPageReady = false;
-
- if (this._pageTarget.videoRecordingInfo())
- this._onVideoRecordingStarted();
-
- this._eventListeners = [
- helper.on(this._pageTarget, PageTarget.Events.DialogOpened, this._onDialogOpened.bind(this)),
- helper.on(this._pageTarget, PageTarget.Events.DialogClosed, this._onDialogClosed.bind(this)),
- helper.on(this._pageTarget, PageTarget.Events.Crashed, () => {
- this._session.emitEvent('Page.crashed', {});
- }),
- helper.on(this._pageTarget, PageTarget.Events.ScreencastStarted, this._onVideoRecordingStarted.bind(this)),
- helper.on(this._pageTarget, PageTarget.Events.ScreencastFrame, this._onScreencastFrame.bind(this)),
- helper.on(this._pageNetwork, PageNetwork.Events.Request, this._handleNetworkEvent.bind(this, 'Network.requestWillBeSent')),
- helper.on(this._pageNetwork, PageNetwork.Events.Response, this._handleNetworkEvent.bind(this, 'Network.responseReceived')),
- helper.on(this._pageNetwork, PageNetwork.Events.RequestFinished, this._handleNetworkEvent.bind(this, 'Network.requestFinished')),
- helper.on(this._pageNetwork, PageNetwork.Events.RequestFailed, this._handleNetworkEvent.bind(this, 'Network.requestFailed')),
- contentChannel.register('page', {
- pageBindingCalled: emitProtocolEvent('Page.bindingCalled'),
- pageDispatchMessageFromWorker: emitProtocolEvent('Page.dispatchMessageFromWorker'),
- pageEventFired: emitProtocolEvent('Page.eventFired'),
- pageFileChooserOpened: emitProtocolEvent('Page.fileChooserOpened'),
- pageFrameAttached: this._onFrameAttached.bind(this),
- pageFrameDetached: emitProtocolEvent('Page.frameDetached'),
- pageLinkClicked: emitProtocolEvent('Page.linkClicked'),
- pageWillOpenNewWindowAsynchronously: emitProtocolEvent('Page.willOpenNewWindowAsynchronously'),
- pageNavigationAborted: emitProtocolEvent('Page.navigationAborted'),
- pageNavigationCommitted: emitProtocolEvent('Page.navigationCommitted'),
- pageNavigationStarted: emitProtocolEvent('Page.navigationStarted'),
- pageReady: this._onPageReady.bind(this),
- pageSameDocumentNavigation: emitProtocolEvent('Page.sameDocumentNavigation'),
- pageUncaughtError: emitProtocolEvent('Page.uncaughtError'),
- pageWorkerCreated: this._onWorkerCreated.bind(this),
- pageWorkerDestroyed: this._onWorkerDestroyed.bind(this),
- runtimeConsole: params => {
- const consoleMessageHash = hashConsoleMessage(params);
- for (const worker of this._workers.values()) {
- if (worker._workerConsoleMessages.has(consoleMessageHash)) {
- worker._workerConsoleMessages.delete(consoleMessageHash);
- return;
- }
- }
- emitProtocolEvent('Runtime.console')(params);
- },
- runtimeExecutionContextCreated: emitProtocolEvent('Runtime.executionContextCreated'),
- runtimeExecutionContextDestroyed: emitProtocolEvent('Runtime.executionContextDestroyed'),
-
- webSocketCreated: emitProtocolEvent('Page.webSocketCreated'),
- webSocketOpened: emitProtocolEvent('Page.webSocketOpened'),
- webSocketClosed: emitProtocolEvent('Page.webSocketClosed'),
- webSocketFrameReceived: emitProtocolEvent('Page.webSocketFrameReceived'),
- webSocketFrameSent: emitProtocolEvent('Page.webSocketFrameSent'),
- }),
- ];
- }
-
- async dispose() {
- this._contentPage.dispose();
- helper.removeListeners(this._eventListeners);
- }
-
- _onVideoRecordingStarted() {
- const info = this._pageTarget.videoRecordingInfo();
- this._session.emitEvent('Page.videoRecordingStarted', { screencastId: info.sessionId, file: info.file });
- }
-
- _onScreencastFrame(params) {
- this._session.emitEvent('Page.screencastFrame', params);
- }
-
- _onPageReady(event) {
- this._isPageReady = true;
- this._session.emitEvent('Page.ready');
- for (const dialog of this._pageTarget.dialogs())
- this._onDialogOpened(dialog);
- }
-
- _onDialogOpened(dialog) {
- if (!this._isPageReady)
- return;
- this._session.emitEvent('Page.dialogOpened', {
- dialogId: dialog.id(),
- type: dialog.type(),
- message: dialog.message(),
- defaultValue: dialog.defaultValue(),
- });
- }
-
- _onDialogClosed(dialog) {
- if (!this._isPageReady)
- return;
- this._session.emitEvent('Page.dialogClosed', { dialogId: dialog.id(), });
- }
-
- _onWorkerCreated({workerId, frameId, url}) {
- const worker = new WorkerHandler(this._session, this._contentChannel, workerId);
- this._workers.set(workerId, worker);
- this._session.emitEvent('Page.workerCreated', {workerId, frameId, url});
- }
-
- _onWorkerDestroyed({workerId}) {
- const worker = this._workers.get(workerId);
- if (!worker)
- return;
- this._workers.delete(workerId);
- worker.dispose();
- this._session.emitEvent('Page.workerDestroyed', {workerId});
- }
-
- _handleNetworkEvent(protocolEventName, eventDetails, frameId) {
- if (!this._reportedFrameIds.has(frameId)) {
- let events = this._networkEventsForUnreportedFrameIds.get(frameId);
- if (!events) {
- events = [];
- this._networkEventsForUnreportedFrameIds.set(frameId, events);
- }
- events.push({eventName: protocolEventName, eventDetails});
- } else {
- this._session.emitEvent(protocolEventName, eventDetails);
- }
- }
-
- _onFrameAttached({frameId, parentFrameId}) {
- this._session.emitEvent('Page.frameAttached', {frameId, parentFrameId});
- this._reportedFrameIds.add(frameId);
- const events = this._networkEventsForUnreportedFrameIds.get(frameId) || [];
- this._networkEventsForUnreportedFrameIds.delete(frameId);
- for (const {eventName, eventDetails} of events)
- this._session.emitEvent(eventName, eventDetails);
- }
-
- async ['Page.close']({runBeforeUnload}) {
- // Postpone target close to deliver response in session.
- Services.tm.dispatchToMainThread(() => {
- this._pageTarget.close(runBeforeUnload);
- });
- }
-
- async ['Page.setViewportSize']({viewportSize}) {
- await this._pageTarget.setViewportSize(viewportSize === null ? undefined : viewportSize);
- }
-
- async ['Runtime.evaluate'](options) {
- return await this._contentPage.send('evaluate', options);
- }
-
- async ['Runtime.callFunction'](options) {
- return await this._contentPage.send('callFunction', options);
- }
-
- async ['Runtime.getObjectProperties'](options) {
- return await this._contentPage.send('getObjectProperties', options);
- }
-
- async ['Runtime.disposeObject'](options) {
- return await this._contentPage.send('disposeObject', options);
- }
-
- async ['Network.getResponseBody']({requestId}) {
- return this._pageNetwork.getResponseBody(requestId);
- }
-
- async ['Network.setExtraHTTPHeaders']({headers}) {
- this._pageNetwork.setExtraHTTPHeaders(headers);
- }
-
- async ['Network.setRequestInterception']({enabled}) {
- if (enabled)
- this._pageNetwork.enableRequestInterception();
- else
- this._pageNetwork.disableRequestInterception();
- }
-
- async ['Network.resumeInterceptedRequest']({requestId, url, method, headers, postData}) {
- this._pageNetwork.resumeInterceptedRequest(requestId, url, method, headers, postData);
- }
-
- async ['Network.abortInterceptedRequest']({requestId, errorCode}) {
- this._pageNetwork.abortInterceptedRequest(requestId, errorCode);
- }
-
- async ['Network.fulfillInterceptedRequest']({requestId, status, statusText, headers, base64body}) {
- this._pageNetwork.fulfillInterceptedRequest(requestId, status, statusText, headers, base64body);
- }
-
- async ['Accessibility.getFullAXTree'](params) {
- return await this._contentPage.send('getFullAXTree', params);
- }
-
- async ['Page.setFileInputFiles'](options) {
- return await this._contentPage.send('setFileInputFiles', options);
- }
-
- async ['Page.setEmulatedMedia']({colorScheme, type, reducedMotion, forcedColors}) {
- this._pageTarget.setColorScheme(colorScheme || null);
- this._pageTarget.setReducedMotion(reducedMotion || null);
- this._pageTarget.setForcedColors(forcedColors || null);
- this._pageTarget.setEmulatedMedia(type);
- }
-
- async ['Page.bringToFront'](options) {
- this._pageTarget._window.focus();
- }
-
- async ['Page.setCacheDisabled'](options) {
- return await this._contentPage.send('setCacheDisabled', options);
- }
-
- async ['Page.addBinding'](options) {
- return await this._contentPage.send('addBinding', options);
- }
-
- async ['Page.adoptNode'](options) {
- return await this._contentPage.send('adoptNode', options);
- }
-
- async ['Page.screenshot']({ mimeType, clip, omitDeviceScaleFactor }) {
- const rect = new DOMRect(clip.x, clip.y, clip.width, clip.height);
-
- const browsingContext = this._pageTarget.linkedBrowser().browsingContext;
- // `win.devicePixelRatio` returns a non-overriden value to priveleged code.
- // See https://bugzilla.mozilla.org/show_bug.cgi?id=1761032
- // See https://phabricator.services.mozilla.com/D141323
- const devicePixelRatio = browsingContext.overrideDPPX || this._pageTarget._window.devicePixelRatio;
- const scale = omitDeviceScaleFactor ? 1 : devicePixelRatio;
- const canvasWidth = rect.width * scale;
- const canvasHeight = rect.height * scale;
-
- const MAX_CANVAS_DIMENSIONS = 32767;
- const MAX_CANVAS_AREA = 472907776;
- if (canvasWidth > MAX_CANVAS_DIMENSIONS || canvasHeight > MAX_CANVAS_DIMENSIONS)
- throw new Error('Cannot take screenshot larger than ' + MAX_CANVAS_DIMENSIONS);
- if (canvasWidth * canvasHeight > MAX_CANVAS_AREA)
- throw new Error('Cannot take screenshot with more than ' + MAX_CANVAS_AREA + ' pixels');
-
- let snapshot;
- while (!snapshot) {
- try {
- //TODO(fission): browsingContext will change in case of cross-group navigation.
- snapshot = await browsingContext.currentWindowGlobal.drawSnapshot(
- rect,
- scale,
- "rgb(255,255,255)"
- );
- } catch (e) {
- // The currentWindowGlobal.drawSnapshot might throw
- // NS_ERROR_LOSS_OF_SIGNIFICANT_DATA if called during navigation.
- // wait a little and re-try.
- await new Promise(x => setTimeout(x, 50));
- }
- }
-
- const win = browsingContext.topChromeWindow.ownerGlobal;
- const canvas = win.document.createElementNS('http://www.w3.org/1999/xhtml', 'canvas');
- canvas.width = canvasWidth;
- canvas.height = canvasHeight;
- let ctx = canvas.getContext('2d');
- ctx.drawImage(snapshot, 0, 0);
- snapshot.close();
- const dataURL = canvas.toDataURL(mimeType);
- return { data: dataURL.substring(dataURL.indexOf(',') + 1) };
- }
-
- async ['Page.getContentQuads'](options) {
- return await this._contentPage.send('getContentQuads', options);
- }
-
- async ['Page.navigate'](options) {
- return await this._contentPage.send('navigate', options);
- }
-
- async ['Page.goBack'](options) {
- return await this._contentPage.send('goBack', options);
- }
-
- async ['Page.goForward'](options) {
- return await this._contentPage.send('goForward', options);
- }
-
- async ['Page.reload'](options) {
- return await this._contentPage.send('reload', options);
- }
-
- async ['Page.describeNode'](options) {
- return await this._contentPage.send('describeNode', options);
- }
-
- async ['Page.scrollIntoViewIfNeeded'](options) {
- return await this._contentPage.send('scrollIntoViewIfNeeded', options);
- }
-
- async ['Page.setInitScripts']({ scripts }) {
- return await this._pageTarget.setInitScripts(scripts);
- }
-
- async ['Page.dispatchKeyEvent'](options) {
- return await this._contentPage.send('dispatchKeyEvent', options);
- }
-
- async ['Page.dispatchTouchEvent'](options) {
- return await this._contentPage.send('dispatchTouchEvent', options);
- }
-
- async ['Page.dispatchTapEvent'](options) {
- return await this._contentPage.send('dispatchTapEvent', options);
- }
-
- async ['Page.dispatchMouseEvent'](options) {
- return await this._contentPage.send('dispatchMouseEvent', options);
- }
-
- async ['Page.dispatchWheelEvent']({x, y, button, deltaX, deltaY, deltaZ, modifiers }) {
- const boundingBox = this._pageTarget._linkedBrowser.getBoundingClientRect();
- x += boundingBox.left;
- y += boundingBox.top;
- const deltaMode = 0; // WheelEvent.DOM_DELTA_PIXEL
- const lineOrPageDeltaX = deltaX > 0 ? Math.floor(deltaX) : Math.ceil(deltaX);
- const lineOrPageDeltaY = deltaY > 0 ? Math.floor(deltaY) : Math.ceil(deltaY);
-
- const win = this._pageTarget._window;
- win.windowUtils.sendWheelEvent(
- x,
- y,
- deltaX,
- deltaY,
- deltaZ,
- deltaMode,
- modifiers,
- lineOrPageDeltaX,
- lineOrPageDeltaY,
- 0 /* options */);
- }
-
- async ['Page.insertText'](options) {
- return await this._contentPage.send('insertText', options);
- }
-
- async ['Page.crash'](options) {
- return await this._contentPage.send('crash', options);
- }
-
- async ['Page.handleDialog']({dialogId, accept, promptText}) {
- const dialog = this._pageTarget.dialog(dialogId);
- if (!dialog)
- throw new Error('Failed to find dialog with id = ' + dialogId);
- if (accept)
- dialog.accept(promptText);
- else
- dialog.dismiss();
- }
-
- async ['Page.setInterceptFileChooserDialog'](options) {
- return await this._contentPage.send('setInterceptFileChooserDialog', options);
- }
-
- async ['Page.startScreencast'](options) {
- return await this._pageTarget.startScreencast(options);
- }
-
- async ['Page.screencastFrameAck'](options) {
- await this._pageTarget.screencastFrameAck(options);
- }
-
- async ['Page.stopScreencast'](options) {
- await this._pageTarget.stopScreencast(options);
- }
-
- async ['Page.sendMessageToWorker']({workerId, message}) {
- const worker = this._workers.get(workerId);
- if (!worker)
- throw new Error('ERROR: cannot find worker with id ' + workerId);
- return await worker.sendMessage(JSON.parse(message));
- }
-}
-
-var EXPORTED_SYMBOLS = ['PageHandler'];
-this.PageHandler = PageHandler;
diff --git a/browser_patches/firefox-beta/juggler/protocol/PrimitiveTypes.js b/browser_patches/firefox-beta/juggler/protocol/PrimitiveTypes.js
deleted file mode 100644
index 5799038f19cbca..00000000000000
--- a/browser_patches/firefox-beta/juggler/protocol/PrimitiveTypes.js
+++ /dev/null
@@ -1,147 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-const t = {};
-
-t.String = function(x, details = {}, path = ['']) {
- if (typeof x === 'string' || typeof x === 'String')
- return true;
- details.error = `Expected "${path.join('.')}" to be |string|; found |${typeof x}| \`${JSON.stringify(x)}\` instead.`;
- return false;
-}
-
-t.Number = function(x, details = {}, path = ['']) {
- if (typeof x === 'number')
- return true;
- details.error = `Expected "${path.join('.')}" to be |number|; found |${typeof x}| \`${JSON.stringify(x)}\` instead.`;
- return false;
-}
-
-t.Boolean = function(x, details = {}, path = ['']) {
- if (typeof x === 'boolean')
- return true;
- details.error = `Expected "${path.join('.')}" to be |boolean|; found |${typeof x}| \`${JSON.stringify(x)}\` instead.`;
- return false;
-}
-
-t.Null = function(x, details = {}, path = ['']) {
- if (Object.is(x, null))
- return true;
- details.error = `Expected "${path.join('.')}" to be \`null\`; found \`${JSON.stringify(x)}\` instead.`;
- return false;
-}
-
-t.Undefined = function(x, details = {}, path = ['']) {
- if (Object.is(x, undefined))
- return true;
- details.error = `Expected "${path.join('.')}" to be \`undefined\`; found \`${JSON.stringify(x)}\` instead.`;
- return false;
-}
-
-t.Any = x => true,
-
-t.Enum = function(values) {
- return function(x, details = {}, path = ['']) {
- if (values.indexOf(x) !== -1)
- return true;
- details.error = `Expected "${path.join('.')}" to be one of [${values.join(', ')}]; found \`${JSON.stringify(x)}\` (${typeof x}) instead.`;
- return false;
- }
-}
-
-t.Nullable = function(scheme) {
- return function(x, details = {}, path = ['']) {
- if (Object.is(x, null))
- return true;
- return checkScheme(scheme, x, details, path);
- }
-}
-
-t.Optional = function(scheme) {
- return function(x, details = {}, path = ['']) {
- if (Object.is(x, undefined))
- return true;
- return checkScheme(scheme, x, details, path);
- }
-}
-
-t.Array = function(scheme) {
- return function(x, details = {}, path = ['']) {
- if (!Array.isArray(x)) {
- details.error = `Expected "${path.join('.')}" to be an array; found \`${JSON.stringify(x)}\` (${typeof x}) instead.`;
- return false;
- }
- const lastPathElement = path[path.length - 1];
- for (let i = 0; i < x.length; ++i) {
- path[path.length - 1] = lastPathElement + `[${i}]`;
- if (!checkScheme(scheme, x[i], details, path))
- return false;
- }
- path[path.length - 1] = lastPathElement;
- return true;
- }
-}
-
-t.Recursive = function(types, schemeName) {
- return function(x, details = {}, path = ['']) {
- const scheme = types[schemeName];
- return checkScheme(scheme, x, details, path);
- }
-}
-
-function beauty(path, obj) {
- if (path.length === 1)
- return `object ${JSON.stringify(obj, null, 2)}`;
- return `property "${path.join('.')}" - ${JSON.stringify(obj, null, 2)}`;
-}
-
-function checkScheme(scheme, x, details = {}, path = ['']) {
- if (!scheme)
- throw new Error(`ILLDEFINED SCHEME: ${path.join('.')}`);
- if (typeof scheme === 'object') {
- if (!x) {
- details.error = `Object "${path.join('.')}" is undefined, but has some scheme`;
- return false;
- }
- for (const [propertyName, aScheme] of Object.entries(scheme)) {
- path.push(propertyName);
- const result = checkScheme(aScheme, x[propertyName], details, path);
- path.pop();
- if (!result)
- return false;
- }
- for (const propertyName of Object.keys(x)) {
- if (!scheme[propertyName]) {
- path.push(propertyName);
- details.error = `Found ${beauty(path, x[propertyName])} which is not described in this scheme`;
- return false;
- }
- }
- return true;
- }
- return scheme(x, details, path);
-}
-
-/*
-
-function test(scheme, obj) {
- const details = {};
- if (!checkScheme(scheme, obj, details)) {
- dump(`FAILED: ${JSON.stringify(obj)}
- details.error: ${details.error}
- `);
- } else {
- dump(`SUCCESS: ${JSON.stringify(obj)}
-`);
- }
-}
-
-test(t.Array(t.String), ['a', 'b', 2, 'c']);
-test(t.Either(t.String, t.Number), {});
-
-*/
-
-this.t = t;
-this.checkScheme = checkScheme;
-this.EXPORTED_SYMBOLS = ['t', 'checkScheme'];
diff --git a/browser_patches/firefox-beta/juggler/protocol/Protocol.js b/browser_patches/firefox-beta/juggler/protocol/Protocol.js
deleted file mode 100644
index be0f15af0d5a74..00000000000000
--- a/browser_patches/firefox-beta/juggler/protocol/Protocol.js
+++ /dev/null
@@ -1,993 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-const {t, checkScheme} = ChromeUtils.import('chrome://juggler/content/protocol/PrimitiveTypes.js');
-
-// Protocol-specific types.
-const browserTypes = {};
-
-browserTypes.TargetInfo = {
- type: t.Enum(['page']),
- targetId: t.String,
- browserContextId: t.Optional(t.String),
- // PageId of parent tab, if any.
- openerId: t.Optional(t.String),
-};
-
-browserTypes.CookieOptions = {
- name: t.String,
- value: t.String,
- url: t.Optional(t.String),
- domain: t.Optional(t.String),
- path: t.Optional(t.String),
- secure: t.Optional(t.Boolean),
- httpOnly: t.Optional(t.Boolean),
- sameSite: t.Optional(t.Enum(['Strict', 'Lax', 'None'])),
- expires: t.Optional(t.Number),
-};
-
-browserTypes.Cookie = {
- name: t.String,
- domain: t.String,
- path: t.String,
- value: t.String,
- expires: t.Number,
- size: t.Number,
- httpOnly: t.Boolean,
- secure: t.Boolean,
- session: t.Boolean,
- sameSite: t.Enum(['Strict', 'Lax', 'None']),
-};
-
-browserTypes.Geolocation = {
- latitude: t.Number,
- longitude: t.Number,
- accuracy: t.Optional(t.Number),
-};
-
-browserTypes.DownloadOptions = {
- behavior: t.Optional(t.Enum(['saveToDisk', 'cancel'])),
- downloadsDir: t.Optional(t.String),
-};
-
-const pageTypes = {};
-pageTypes.DOMPoint = {
- x: t.Number,
- y: t.Number,
-};
-
-pageTypes.Rect = {
- x: t.Number,
- y: t.Number,
- width: t.Number,
- height: t.Number,
-};
-
-pageTypes.Size = {
- width: t.Number,
- height: t.Number,
-};
-
-pageTypes.Viewport = {
- viewportSize: pageTypes.Size,
- deviceScaleFactor: t.Optional(t.Number),
-};
-
-pageTypes.DOMQuad = {
- p1: pageTypes.DOMPoint,
- p2: pageTypes.DOMPoint,
- p3: pageTypes.DOMPoint,
- p4: pageTypes.DOMPoint,
-};
-
-pageTypes.TouchPoint = {
- x: t.Number,
- y: t.Number,
- radiusX: t.Optional(t.Number),
- radiusY: t.Optional(t.Number),
- rotationAngle: t.Optional(t.Number),
- force: t.Optional(t.Number),
-};
-
-pageTypes.Clip = {
- x: t.Number,
- y: t.Number,
- width: t.Number,
- height: t.Number,
-};
-
-pageTypes.InitScript = {
- script: t.String,
- worldName: t.Optional(t.String),
-};
-
-const runtimeTypes = {};
-runtimeTypes.RemoteObject = {
- type: t.Optional(t.Enum(['object', 'function', 'undefined', 'string', 'number', 'boolean', 'symbol', 'bigint'])),
- subtype: t.Optional(t.Enum(['array', 'null', 'node', 'regexp', 'date', 'map', 'set', 'weakmap', 'weakset', 'error', 'proxy', 'promise', 'typedarray'])),
- objectId: t.Optional(t.String),
- unserializableValue: t.Optional(t.Enum(['Infinity', '-Infinity', '-0', 'NaN'])),
- value: t.Any
-};
-
-runtimeTypes.ObjectProperty = {
- name: t.String,
- value: runtimeTypes.RemoteObject,
-};
-
-runtimeTypes.ScriptLocation = {
- columnNumber: t.Number,
- lineNumber: t.Number,
- url: t.String,
-};
-
-runtimeTypes.ExceptionDetails = {
- text: t.Optional(t.String),
- stack: t.Optional(t.String),
- value: t.Optional(t.Any),
-};
-
-runtimeTypes.CallFunctionArgument = {
- objectId: t.Optional(t.String),
- unserializableValue: t.Optional(t.Enum(['Infinity', '-Infinity', '-0', 'NaN'])),
- value: t.Any,
-};
-
-runtimeTypes.AuxData = {
- frameId: t.Optional(t.String),
- name: t.Optional(t.String),
-};
-
-const axTypes = {};
-axTypes.AXTree = {
- role: t.String,
- name: t.String,
- children: t.Optional(t.Array(t.Recursive(axTypes, 'AXTree'))),
-
- selected: t.Optional(t.Boolean),
- focused: t.Optional(t.Boolean),
- pressed: t.Optional(t.Boolean),
- focusable: t.Optional(t.Boolean),
- haspopup: t.Optional(t.String),
- required: t.Optional(t.Boolean),
- invalid: t.Optional(t.Boolean),
- modal: t.Optional(t.Boolean),
- editable: t.Optional(t.Boolean),
- busy: t.Optional(t.Boolean),
- multiline: t.Optional(t.Boolean),
- readonly: t.Optional(t.Boolean),
- checked: t.Optional(t.Enum(['mixed', true])),
- expanded: t.Optional(t.Boolean),
- disabled: t.Optional(t.Boolean),
- multiselectable: t.Optional(t.Boolean),
-
- value: t.Optional(t.String),
- description: t.Optional(t.String),
-
- roledescription: t.Optional(t.String),
- valuetext: t.Optional(t.String),
- orientation: t.Optional(t.String),
- autocomplete: t.Optional(t.String),
- keyshortcuts: t.Optional(t.String),
-
- level: t.Optional(t.Number),
-
- tag: t.Optional(t.String),
-
- foundObject: t.Optional(t.Boolean),
-}
-
-const networkTypes = {};
-
-networkTypes.HTTPHeader = {
- name: t.String,
- value: t.String,
-};
-
-networkTypes.HTTPCredentials = {
- username: t.String,
- password: t.String,
-};
-
-networkTypes.SecurityDetails = {
- protocol: t.String,
- subjectName: t.String,
- issuer: t.String,
- validFrom: t.Number,
- validTo: t.Number,
-};
-
-networkTypes.ResourceTiming = {
- startTime: t.Number,
- domainLookupStart: t.Number,
- domainLookupEnd: t.Number,
- connectStart: t.Number,
- secureConnectionStart: t.Number,
- connectEnd: t.Number,
- requestStart: t.Number,
- responseStart: t.Number,
-};
-
-const Browser = {
- targets: ['browser'],
-
- types: browserTypes,
-
- events: {
- 'attachedToTarget': {
- sessionId: t.String,
- targetInfo: browserTypes.TargetInfo,
- },
- 'detachedFromTarget': {
- sessionId: t.String,
- targetId: t.String,
- },
- 'downloadCreated': {
- uuid: t.String,
- browserContextId: t.Optional(t.String),
- pageTargetId: t.String,
- url: t.String,
- suggestedFileName: t.String,
- },
- 'downloadFinished': {
- uuid: t.String,
- canceled: t.Optional(t.Boolean),
- error: t.Optional(t.String),
- },
- 'videoRecordingFinished': {
- screencastId: t.String,
- },
- },
-
- methods: {
- 'enable': {
- params: {
- attachToDefaultContext: t.Boolean,
- },
- },
- 'createBrowserContext': {
- params: {
- removeOnDetach: t.Optional(t.Boolean),
- },
- returns: {
- browserContextId: t.String,
- },
- },
- 'removeBrowserContext': {
- params: {
- browserContextId: t.String,
- },
- },
- 'newPage': {
- params: {
- browserContextId: t.Optional(t.String),
- },
- returns: {
- targetId: t.String,
- }
- },
- 'close': {},
- 'getInfo': {
- returns: {
- userAgent: t.String,
- version: t.String,
- },
- },
- 'setExtraHTTPHeaders': {
- params: {
- browserContextId: t.Optional(t.String),
- headers: t.Array(networkTypes.HTTPHeader),
- },
- },
- 'setBrowserProxy': {
- params: {
- type: t.Enum(['http', 'https', 'socks', 'socks4']),
- bypass: t.Array(t.String),
- host: t.String,
- port: t.Number,
- username: t.Optional(t.String),
- password: t.Optional(t.String),
- },
- },
- 'setContextProxy': {
- params: {
- browserContextId: t.Optional(t.String),
- type: t.Enum(['http', 'https', 'socks', 'socks4']),
- bypass: t.Array(t.String),
- host: t.String,
- port: t.Number,
- username: t.Optional(t.String),
- password: t.Optional(t.String),
- },
- },
- 'setHTTPCredentials': {
- params: {
- browserContextId: t.Optional(t.String),
- credentials: t.Nullable(networkTypes.HTTPCredentials),
- },
- },
- 'setRequestInterception': {
- params: {
- browserContextId: t.Optional(t.String),
- enabled: t.Boolean,
- },
- },
- 'setGeolocationOverride': {
- params: {
- browserContextId: t.Optional(t.String),
- geolocation: t.Nullable(browserTypes.Geolocation),
- }
- },
- 'setUserAgentOverride': {
- params: {
- browserContextId: t.Optional(t.String),
- userAgent: t.Nullable(t.String),
- }
- },
- 'setPlatformOverride': {
- params: {
- browserContextId: t.Optional(t.String),
- platform: t.Nullable(t.String),
- }
- },
- 'setBypassCSP': {
- params: {
- browserContextId: t.Optional(t.String),
- bypassCSP: t.Nullable(t.Boolean),
- }
- },
- 'setIgnoreHTTPSErrors': {
- params: {
- browserContextId: t.Optional(t.String),
- ignoreHTTPSErrors: t.Nullable(t.Boolean),
- }
- },
- 'setJavaScriptDisabled': {
- params: {
- browserContextId: t.Optional(t.String),
- javaScriptDisabled: t.Boolean,
- }
- },
- 'setLocaleOverride': {
- params: {
- browserContextId: t.Optional(t.String),
- locale: t.Nullable(t.String),
- }
- },
- 'setTimezoneOverride': {
- params: {
- browserContextId: t.Optional(t.String),
- timezoneId: t.Nullable(t.String),
- }
- },
- 'setDownloadOptions': {
- params: {
- browserContextId: t.Optional(t.String),
- downloadOptions: t.Nullable(browserTypes.DownloadOptions),
- }
- },
- 'setTouchOverride': {
- params: {
- browserContextId: t.Optional(t.String),
- hasTouch: t.Nullable(t.Boolean),
- }
- },
- 'setDefaultViewport': {
- params: {
- browserContextId: t.Optional(t.String),
- viewport: t.Nullable(pageTypes.Viewport),
- }
- },
- 'setScrollbarsHidden': {
- params: {
- browserContextId: t.Optional(t.String),
- hidden: t.Boolean,
- }
- },
- 'setInitScripts': {
- params: {
- browserContextId: t.Optional(t.String),
- scripts: t.Array(pageTypes.InitScript),
- }
- },
- 'addBinding': {
- params: {
- browserContextId: t.Optional(t.String),
- worldName: t.Optional(t.String),
- name: t.String,
- script: t.String,
- },
- },
- 'grantPermissions': {
- params: {
- origin: t.String,
- browserContextId: t.Optional(t.String),
- permissions: t.Array(t.String),
- },
- },
- 'resetPermissions': {
- params: {
- browserContextId: t.Optional(t.String),
- }
- },
- 'setCookies': {
- params: {
- browserContextId: t.Optional(t.String),
- cookies: t.Array(browserTypes.CookieOptions),
- }
- },
- 'clearCookies': {
- params: {
- browserContextId: t.Optional(t.String),
- }
- },
- 'getCookies': {
- params: {
- browserContextId: t.Optional(t.String)
- },
- returns: {
- cookies: t.Array(browserTypes.Cookie),
- },
- },
- 'setOnlineOverride': {
- params: {
- browserContextId: t.Optional(t.String),
- override: t.Nullable(t.Enum(['online', 'offline'])),
- }
- },
- 'setColorScheme': {
- params: {
- browserContextId: t.Optional(t.String),
- colorScheme: t.Nullable(t.Enum(['dark', 'light', 'no-preference'])),
- },
- },
- 'setReducedMotion': {
- params: {
- browserContextId: t.Optional(t.String),
- reducedMotion: t.Nullable(t.Enum(['reduce', 'no-preference'])),
- },
- },
- 'setForcedColors': {
- params: {
- browserContextId: t.Optional(t.String),
- forcedColors: t.Nullable(t.Enum(['active', 'none'])),
- },
- },
- 'setVideoRecordingOptions': {
- params: {
- browserContextId: t.Optional(t.String),
- options: t.Optional({
- dir: t.String,
- width: t.Number,
- height: t.Number,
- }),
- },
- },
- 'cancelDownload': {
- params: {
- uuid: t.Optional(t.String),
- }
- }
- },
-};
-
-const Network = {
- targets: ['page'],
- types: networkTypes,
- events: {
- 'requestWillBeSent': {
- // frameId may be absent for redirected requests.
- frameId: t.Optional(t.String),
- requestId: t.String,
- // RequestID of redirected request.
- redirectedFrom: t.Optional(t.String),
- postData: t.Optional(t.String),
- headers: t.Array(networkTypes.HTTPHeader),
- isIntercepted: t.Boolean,
- url: t.String,
- method: t.String,
- navigationId: t.Optional(t.String),
- cause: t.String,
- internalCause: t.String,
- },
- 'responseReceived': {
- securityDetails: t.Nullable(networkTypes.SecurityDetails),
- requestId: t.String,
- fromCache: t.Boolean,
- remoteIPAddress: t.Optional(t.String),
- remotePort: t.Optional(t.Number),
- status: t.Number,
- statusText: t.String,
- headers: t.Array(networkTypes.HTTPHeader),
- timing: networkTypes.ResourceTiming,
- fromServiceWorker: t.Boolean,
- },
- 'requestFinished': {
- requestId: t.String,
- responseEndTime: t.Number,
- transferSize: t.Number,
- encodedBodySize: t.Number,
- protocolVersion: t.Optional(t.String),
- },
- 'requestFailed': {
- requestId: t.String,
- errorCode: t.String,
- },
- },
- methods: {
- 'setRequestInterception': {
- params: {
- enabled: t.Boolean,
- },
- },
- 'setExtraHTTPHeaders': {
- params: {
- headers: t.Array(networkTypes.HTTPHeader),
- },
- },
- 'abortInterceptedRequest': {
- params: {
- requestId: t.String,
- errorCode: t.String,
- },
- },
- 'resumeInterceptedRequest': {
- params: {
- requestId: t.String,
- url: t.Optional(t.String),
- method: t.Optional(t.String),
- headers: t.Optional(t.Array(networkTypes.HTTPHeader)),
- postData: t.Optional(t.String),
- },
- },
- 'fulfillInterceptedRequest': {
- params: {
- requestId: t.String,
- status: t.Number,
- statusText: t.String,
- headers: t.Array(networkTypes.HTTPHeader),
- base64body: t.Optional(t.String), // base64-encoded
- },
- },
- 'getResponseBody': {
- params: {
- requestId: t.String,
- },
- returns: {
- base64body: t.String,
- evicted: t.Optional(t.Boolean),
- },
- },
- },
-};
-
-const Runtime = {
- targets: ['page'],
- types: runtimeTypes,
- events: {
- 'executionContextCreated': {
- executionContextId: t.String,
- auxData: runtimeTypes.AuxData,
- },
- 'executionContextDestroyed': {
- executionContextId: t.String,
- },
- 'console': {
- executionContextId: t.String,
- args: t.Array(runtimeTypes.RemoteObject),
- type: t.String,
- location: runtimeTypes.ScriptLocation,
- },
- },
- methods: {
- 'evaluate': {
- params: {
- // Pass frameId here.
- executionContextId: t.String,
- expression: t.String,
- returnByValue: t.Optional(t.Boolean),
- },
-
- returns: {
- result: t.Optional(runtimeTypes.RemoteObject),
- exceptionDetails: t.Optional(runtimeTypes.ExceptionDetails),
- }
- },
- 'callFunction': {
- params: {
- // Pass frameId here.
- executionContextId: t.String,
- functionDeclaration: t.String,
- returnByValue: t.Optional(t.Boolean),
- args: t.Array(runtimeTypes.CallFunctionArgument),
- },
-
- returns: {
- result: t.Optional(runtimeTypes.RemoteObject),
- exceptionDetails: t.Optional(runtimeTypes.ExceptionDetails),
- }
- },
- 'disposeObject': {
- params: {
- executionContextId: t.String,
- objectId: t.String,
- },
- },
-
- 'getObjectProperties': {
- params: {
- executionContextId: t.String,
- objectId: t.String,
- },
-
- returns: {
- properties: t.Array(runtimeTypes.ObjectProperty),
- }
- },
- },
-};
-
-const Page = {
- targets: ['page'],
-
- types: pageTypes,
- events: {
- 'ready': {
- },
- 'crashed': {
- },
- 'eventFired': {
- frameId: t.String,
- name: t.Enum(['load', 'DOMContentLoaded']),
- },
- 'uncaughtError': {
- frameId: t.String,
- message: t.String,
- stack: t.String,
- },
- 'frameAttached': {
- frameId: t.String,
- parentFrameId: t.Optional(t.String),
- },
- 'frameDetached': {
- frameId: t.String,
- },
- 'navigationStarted': {
- frameId: t.String,
- navigationId: t.String,
- url: t.String,
- },
- 'navigationCommitted': {
- frameId: t.String,
- // |navigationId| can only be null in response to enable.
- navigationId: t.Optional(t.String),
- url: t.String,
- // frame.id or frame.name
- name: t.String,
- },
- 'navigationAborted': {
- frameId: t.String,
- navigationId: t.String,
- errorText: t.String,
- },
- 'sameDocumentNavigation': {
- frameId: t.String,
- url: t.String,
- },
- 'dialogOpened': {
- dialogId: t.String,
- type: t.Enum(['prompt', 'alert', 'confirm', 'beforeunload']),
- message: t.String,
- defaultValue: t.Optional(t.String),
- },
- 'dialogClosed': {
- dialogId: t.String,
- },
- 'bindingCalled': {
- executionContextId: t.String,
- name: t.String,
- payload: t.Any,
- },
- 'linkClicked': {
- phase: t.Enum(['before', 'after']),
- },
- 'willOpenNewWindowAsynchronously': {},
- 'fileChooserOpened': {
- executionContextId: t.String,
- element: runtimeTypes.RemoteObject
- },
- 'workerCreated': {
- workerId: t.String,
- frameId: t.String,
- url: t.String,
- },
- 'workerDestroyed': {
- workerId: t.String,
- },
- 'dispatchMessageFromWorker': {
- workerId: t.String,
- message: t.String,
- },
- 'videoRecordingStarted': {
- screencastId: t.String,
- file: t.String,
- },
- 'webSocketCreated': {
- frameId: t.String,
- wsid: t.String,
- requestURL: t.String,
- },
- 'webSocketOpened': {
- frameId: t.String,
- requestId: t.String,
- wsid: t.String,
- effectiveURL: t.String,
- },
- 'webSocketClosed': {
- frameId: t.String,
- wsid: t.String,
- error: t.String,
- },
- 'webSocketFrameSent': {
- frameId: t.String,
- wsid: t.String,
- opcode: t.Number,
- data: t.String,
- },
- 'webSocketFrameReceived': {
- frameId: t.String,
- wsid: t.String,
- opcode: t.Number,
- data: t.String,
- },
- 'screencastFrame': {
- data: t.String,
- deviceWidth: t.Number,
- deviceHeight: t.Number,
- },
- },
-
- methods: {
- 'close': {
- params: {
- runBeforeUnload: t.Optional(t.Boolean),
- },
- },
- 'setFileInputFiles': {
- params: {
- frameId: t.String,
- objectId: t.String,
- files: t.Array(t.String),
- },
- },
- 'addBinding': {
- params: {
- worldName: t.Optional(t.String),
- name: t.String,
- script: t.String,
- },
- },
- 'setViewportSize': {
- params: {
- viewportSize: t.Nullable(pageTypes.Size),
- },
- },
- 'bringToFront': {
- params: {
- },
- },
- 'setEmulatedMedia': {
- params: {
- type: t.Optional(t.Enum(['screen', 'print', ''])),
- colorScheme: t.Optional(t.Enum(['dark', 'light', 'no-preference'])),
- reducedMotion: t.Optional(t.Enum(['reduce', 'no-preference'])),
- forcedColors: t.Optional(t.Enum(['active', 'none'])),
- },
- },
- 'setCacheDisabled': {
- params: {
- cacheDisabled: t.Boolean,
- },
- },
- 'describeNode': {
- params: {
- frameId: t.String,
- objectId: t.String,
- },
- returns: {
- contentFrameId: t.Optional(t.String),
- ownerFrameId: t.Optional(t.String),
- },
- },
- 'scrollIntoViewIfNeeded': {
- params: {
- frameId: t.String,
- objectId: t.String,
- rect: t.Optional(pageTypes.Rect),
- },
- },
- 'setInitScripts': {
- params: {
- scripts: t.Array(pageTypes.InitScript)
- }
- },
- 'navigate': {
- params: {
- frameId: t.String,
- url: t.String,
- referer: t.Optional(t.String),
- },
- returns: {
- navigationId: t.Nullable(t.String),
- navigationURL: t.Nullable(t.String),
- }
- },
- 'goBack': {
- params: {
- frameId: t.String,
- },
- returns: {
- success: t.Boolean,
- },
- },
- 'goForward': {
- params: {
- frameId: t.String,
- },
- returns: {
- success: t.Boolean,
- },
- },
- 'reload': {
- params: {
- frameId: t.String,
- },
- },
- 'adoptNode': {
- params: {
- frameId: t.String,
- objectId: t.String,
- executionContextId: t.String,
- },
- returns: {
- remoteObject: t.Nullable(runtimeTypes.RemoteObject),
- },
- },
- 'screenshot': {
- params: {
- mimeType: t.Enum(['image/png', 'image/jpeg']),
- clip: pageTypes.Clip,
- omitDeviceScaleFactor: t.Optional(t.Boolean),
- },
- returns: {
- data: t.String,
- }
- },
- 'getContentQuads': {
- params: {
- frameId: t.String,
- objectId: t.String,
- },
- returns: {
- quads: t.Array(pageTypes.DOMQuad),
- },
- },
- 'dispatchKeyEvent': {
- params: {
- type: t.String,
- key: t.String,
- keyCode: t.Number,
- location: t.Number,
- code: t.String,
- repeat: t.Boolean,
- text: t.Optional(t.String),
- }
- },
- 'dispatchTouchEvent': {
- params: {
- type: t.Enum(['touchStart', 'touchEnd', 'touchMove', 'touchCancel']),
- touchPoints: t.Array(pageTypes.TouchPoint),
- modifiers: t.Number,
- },
- returns: {
- defaultPrevented: t.Boolean,
- }
- },
- 'dispatchTapEvent': {
- params: {
- x: t.Number,
- y: t.Number,
- modifiers: t.Number,
- }
- },
- 'dispatchMouseEvent': {
- params: {
- type: t.String,
- button: t.Number,
- x: t.Number,
- y: t.Number,
- modifiers: t.Number,
- clickCount: t.Optional(t.Number),
- buttons: t.Number,
- }
- },
- 'dispatchWheelEvent': {
- params: {
- x: t.Number,
- y: t.Number,
- deltaX: t.Number,
- deltaY: t.Number,
- deltaZ: t.Number,
- modifiers: t.Number,
- }
- },
- 'insertText': {
- params: {
- text: t.String,
- }
- },
- 'crash': {
- params: {}
- },
- 'handleDialog': {
- params: {
- dialogId: t.String,
- accept: t.Boolean,
- promptText: t.Optional(t.String),
- },
- },
- 'setInterceptFileChooserDialog': {
- params: {
- enabled: t.Boolean,
- },
- },
- 'sendMessageToWorker': {
- params: {
- frameId: t.String,
- workerId: t.String,
- message: t.String,
- },
- },
- 'startScreencast': {
- params: {
- width: t.Number,
- height: t.Number,
- quality: t.Number,
- },
- returns: {
- screencastId: t.String,
- },
- },
- 'screencastFrameAck': {
- params: {
- screencastId: t.String,
- },
- },
- 'stopScreencast': {
- },
- },
-};
-
-
-const Accessibility = {
- targets: ['page'],
- types: axTypes,
- events: {},
- methods: {
- 'getFullAXTree': {
- params: {
- objectId: t.Optional(t.String),
- },
- returns: {
- tree: axTypes.AXTree
- },
- }
- }
-}
-
-this.protocol = {
- domains: {Browser, Page, Runtime, Network, Accessibility},
-};
-this.checkScheme = checkScheme;
-this.EXPORTED_SYMBOLS = ['protocol', 'checkScheme'];
diff --git a/browser_patches/firefox-beta/juggler/screencast/HeadlessWindowCapturer.cpp b/browser_patches/firefox-beta/juggler/screencast/HeadlessWindowCapturer.cpp
deleted file mode 100644
index 88d1791dde449b..00000000000000
--- a/browser_patches/firefox-beta/juggler/screencast/HeadlessWindowCapturer.cpp
+++ /dev/null
@@ -1,144 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "HeadlessWindowCapturer.h"
-
-#include "api/video/i420_buffer.h"
-#include "HeadlessWidget.h"
-#include "libyuv.h"
-#include "mozilla/EndianUtils.h"
-#include "mozilla/gfx/DataSurfaceHelpers.h"
-#include "rtc_base/ref_counted_object.h"
-#include "rtc_base/time_utils.h"
-#include "api/scoped_refptr.h"
-
-using namespace mozilla::widget;
-using namespace webrtc;
-
-namespace mozilla {
-
-rtc::scoped_refptr HeadlessWindowCapturer::Create(HeadlessWidget* headlessWindow) {
- return new rtc::RefCountedObject(headlessWindow);
-}
-
-HeadlessWindowCapturer::HeadlessWindowCapturer(mozilla::widget::HeadlessWidget* window)
- : mWindow(window) {
-}
-HeadlessWindowCapturer::~HeadlessWindowCapturer() {
- StopCapture();
-}
-
-
-void HeadlessWindowCapturer::RegisterCaptureDataCallback(rtc::VideoSinkInterface* dataCallback) {
- rtc::CritScope lock2(&_callBackCs);
- _dataCallBacks.insert(dataCallback);
-}
-void HeadlessWindowCapturer::DeRegisterCaptureDataCallback(rtc::VideoSinkInterface* dataCallback) {
- rtc::CritScope lock2(&_callBackCs);
- auto it = _dataCallBacks.find(dataCallback);
- if (it != _dataCallBacks.end()) {
- _dataCallBacks.erase(it);
- }
-}
-
-void HeadlessWindowCapturer::RegisterRawFrameCallback(webrtc::RawFrameCallback* rawFrameCallback) {
- rtc::CritScope lock2(&_callBackCs);
- _rawFrameCallbacks.insert(rawFrameCallback);
-}
-
-void HeadlessWindowCapturer::DeRegisterRawFrameCallback(webrtc::RawFrameCallback* rawFrameCallback) {
- rtc::CritScope lock2(&_callBackCs);
- auto it = _rawFrameCallbacks.find(rawFrameCallback);
- if (it != _rawFrameCallbacks.end()) {
- _rawFrameCallbacks.erase(it);
- }
-}
-
-void HeadlessWindowCapturer::NotifyFrameCaptured(const webrtc::VideoFrame& frame) {
- rtc::CritScope lock2(&_callBackCs);
- for (auto dataCallBack : _dataCallBacks)
- dataCallBack->OnFrame(frame);
-}
-
-int32_t HeadlessWindowCapturer::StopCaptureIfAllClientsClose() {
- if (_dataCallBacks.empty()) {
- return StopCapture();
- } else {
- return 0;
- }
-}
-
-int32_t HeadlessWindowCapturer::StartCapture(const webrtc::VideoCaptureCapability& capability) {
- mWindow->SetSnapshotListener([this] (RefPtr&& dataSurface){
- if (!NS_IsInCompositorThread()) {
- fprintf(stderr, "SnapshotListener is called not on the Compositor thread!\n");
- return;
- }
-
- if (dataSurface->GetFormat() != gfx::SurfaceFormat::B8G8R8A8) {
- fprintf(stderr, "Unexpected snapshot surface format: %hhd\n", dataSurface->GetFormat());
- return;
- }
-
- webrtc::VideoCaptureCapability frameInfo;
- frameInfo.width = dataSurface->GetSize().width;
- frameInfo.height = dataSurface->GetSize().height;
-#if MOZ_LITTLE_ENDIAN()
- frameInfo.videoType = VideoType::kARGB;
-#else
- frameInfo.videoType = VideoType::kBGRA;
-#endif
-
- {
- rtc::CritScope lock2(&_callBackCs);
- for (auto rawFrameCallback : _rawFrameCallbacks) {
- rawFrameCallback->OnRawFrame(dataSurface->GetData(), dataSurface->Stride(), frameInfo);
- }
- if (!_dataCallBacks.size())
- return;
- }
-
- int width = dataSurface->GetSize().width;
- int height = dataSurface->GetSize().height;
- rtc::scoped_refptr buffer = I420Buffer::Create(width, height);
-
- gfx::DataSourceSurface::ScopedMap map(dataSurface.get(), gfx::DataSourceSurface::MapType::READ);
- if (!map.IsMapped()) {
- fprintf(stderr, "Failed to map snapshot bytes!\n");
- return;
- }
-
-#if MOZ_LITTLE_ENDIAN()
- const int conversionResult = libyuv::ARGBToI420(
-#else
- const int conversionResult = libyuv::BGRAToI420(
-#endif
- map.GetData(), map.GetStride(),
- buffer->MutableDataY(), buffer->StrideY(),
- buffer->MutableDataU(), buffer->StrideU(),
- buffer->MutableDataV(), buffer->StrideV(),
- width, height);
- if (conversionResult != 0) {
- fprintf(stderr, "Failed to convert capture frame to I420: %d\n", conversionResult);
- return;
- }
-
- VideoFrame captureFrame(buffer, 0, rtc::TimeMillis(), kVideoRotation_0);
- NotifyFrameCaptured(captureFrame);
- });
- return 0;
-}
-
-int32_t HeadlessWindowCapturer::StopCapture() {
- if (!CaptureStarted())
- return 0;
- mWindow->SetSnapshotListener(nullptr);
- return 0;
-}
-
-bool HeadlessWindowCapturer::CaptureStarted() {
- return true;
-}
-
-} // namespace mozilla
diff --git a/browser_patches/firefox-beta/juggler/screencast/HeadlessWindowCapturer.h b/browser_patches/firefox-beta/juggler/screencast/HeadlessWindowCapturer.h
deleted file mode 100644
index 9f67565c04d418..00000000000000
--- a/browser_patches/firefox-beta/juggler/screencast/HeadlessWindowCapturer.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#pragma once
-
-#include
-#include
-#include "api/video/video_frame.h"
-#include "api/video/video_sink_interface.h"
-#include "modules/video_capture/video_capture.h"
-#include "rtc_base/deprecated/recursive_critical_section.h"
-#include "video_engine/desktop_capture_impl.h"
-
-class nsIWidget;
-
-namespace mozilla {
-
-namespace widget {
-class HeadlessWidget;
-}
-
-class HeadlessWindowCapturer : public webrtc::VideoCaptureModuleEx {
- public:
- static rtc::scoped_refptr Create(mozilla::widget::HeadlessWidget*);
-
- void RegisterCaptureDataCallback(
- rtc::VideoSinkInterface* dataCallback) override;
- void DeRegisterCaptureDataCallback(
- rtc::VideoSinkInterface* dataCallback) override;
- int32_t StopCaptureIfAllClientsClose() override;
-
- void RegisterRawFrameCallback(webrtc::RawFrameCallback* rawFrameCallback) override;
- void DeRegisterRawFrameCallback(webrtc::RawFrameCallback* rawFrameCallback) override;
-
- int32_t SetCaptureRotation(webrtc::VideoRotation) override { return -1; }
- bool SetApplyRotation(bool) override { return false; }
- bool GetApplyRotation() override { return true; }
-
- const char* CurrentDeviceName() const override { return "Headless window"; }
-
- // Platform dependent
- int32_t StartCapture(const webrtc::VideoCaptureCapability& capability) override;
- bool FocusOnSelectedSource() override { return false; }
- int32_t StopCapture() override;
- bool CaptureStarted() override;
- int32_t CaptureSettings(webrtc::VideoCaptureCapability& settings) override {
- return -1;
- }
-
- protected:
- HeadlessWindowCapturer(mozilla::widget::HeadlessWidget*);
- ~HeadlessWindowCapturer() override;
-
- private:
- void NotifyFrameCaptured(const webrtc::VideoFrame& frame);
-
- RefPtr mWindow;
- rtc::RecursiveCriticalSection _callBackCs;
- std::set*> _dataCallBacks;
- std::set _rawFrameCallbacks;
-};
-
-} // namespace mozilla
diff --git a/browser_patches/firefox-beta/juggler/screencast/ScreencastEncoder.cpp b/browser_patches/firefox-beta/juggler/screencast/ScreencastEncoder.cpp
deleted file mode 100644
index 5891953392bb56..00000000000000
--- a/browser_patches/firefox-beta/juggler/screencast/ScreencastEncoder.cpp
+++ /dev/null
@@ -1,382 +0,0 @@
-/*
- * Copyright (c) 2010, The WebM Project authors. All rights reserved.
- * Copyright (c) 2013 The Chromium Authors. All rights reserved.
- * Copyright (C) 2020 Microsoft Corporation.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "ScreencastEncoder.h"
-
-#include
-#include
-#include
-#include
-#include
-#include "nsIThread.h"
-#include "nsThreadUtils.h"
-#include "WebMFileWriter.h"
-#include "api/video/video_frame.h"
-
-namespace mozilla {
-
-namespace {
-
-struct VpxCodecDeleter {
- void operator()(vpx_codec_ctx_t* codec) {
- if (codec) {
- vpx_codec_err_t ret = vpx_codec_destroy(codec);
- if (ret != VPX_CODEC_OK)
- fprintf(stderr, "Failed to destroy codec: %s\n", vpx_codec_error(codec));
- }
- }
-};
-
-using ScopedVpxCodec = std::unique_ptr;
-
-// Number of timebase unints per one frame.
-constexpr int timeScale = 1000;
-
-// Defines the dimension of a macro block. This is used to compute the active
-// map for the encoder.
-const int kMacroBlockSize = 16;
-
-void createImage(unsigned int width, unsigned int height,
- std::unique_ptr& out_image,
- std::unique_ptr& out_image_buffer,
- int& out_buffer_size) {
- std::unique_ptr image(new vpx_image_t());
- memset(image.get(), 0, sizeof(vpx_image_t));
-
- // libvpx seems to require both to be assigned.
- image->d_w = width;
- image->w = width;
- image->d_h = height;
- image->h = height;
-
- // I420
- image->fmt = VPX_IMG_FMT_YV12;
- image->x_chroma_shift = 1;
- image->y_chroma_shift = 1;
-
- // libyuv's fast-path requires 16-byte aligned pointers and strides, so pad
- // the Y, U and V planes' strides to multiples of 16 bytes.
- const int y_stride = ((image->w - 1) & ~15) + 16;
- const int uv_unaligned_stride = y_stride >> image->x_chroma_shift;
- const int uv_stride = ((uv_unaligned_stride - 1) & ~15) + 16;
-
- // libvpx accesses the source image in macro blocks, and will over-read
- // if the image is not padded out to the next macroblock: crbug.com/119633.
- // Pad the Y, U and V planes' height out to compensate.
- // Assuming macroblocks are 16x16, aligning the planes' strides above also
- // macroblock aligned them.
- static_assert(kMacroBlockSize == 16, "macroblock_size_not_16");
- const int y_rows = ((image->h - 1) & ~(kMacroBlockSize-1)) + kMacroBlockSize;
- const int uv_rows = y_rows >> image->y_chroma_shift;
-
- // Allocate a YUV buffer large enough for the aligned data & padding.
- out_buffer_size = y_stride * y_rows + 2*uv_stride * uv_rows;
- std::unique_ptr image_buffer(new uint8_t[out_buffer_size]);
-
- // Reset image value to 128 so we just need to fill in the y plane.
- memset(image_buffer.get(), 128, out_buffer_size);
-
- // Fill in the information for |image_|.
- unsigned char* uchar_buffer =
- reinterpret_cast(image_buffer.get());
- image->planes[0] = uchar_buffer;
- image->planes[1] = image->planes[0] + y_stride * y_rows;
- image->planes[2] = image->planes[1] + uv_stride * uv_rows;
- image->stride[0] = y_stride;
- image->stride[1] = uv_stride;
- image->stride[2] = uv_stride;
-
- out_image = std::move(image);
- out_image_buffer = std::move(image_buffer);
-}
-
-} // namespace
-
-class ScreencastEncoder::VPXFrame {
-public:
- VPXFrame(rtc::scoped_refptr&& buffer, const gfx::IntMargin& margin)
- : m_frameBuffer(std::move(buffer))
- , m_margin(margin)
- { }
-
- void setDuration(TimeDuration duration) { m_duration = duration; }
- TimeDuration duration() const { return m_duration; }
-
- void convertToVpxImage(vpx_image_t* image)
- {
- if (m_frameBuffer->type() != webrtc::VideoFrameBuffer::Type::kI420) {
- fprintf(stderr, "convertToVpxImage unexpected frame buffer type: %d\n", m_frameBuffer->type());
- return;
- }
-
- auto src = m_frameBuffer->GetI420();
- const int y_stride = image->stride[VPX_PLANE_Y];
- MOZ_ASSERT(image->stride[VPX_PLANE_U] == image->stride[VPX_PLANE_V]);
- const int uv_stride = image->stride[1];
- uint8_t* y_data = image->planes[VPX_PLANE_Y];
- uint8_t* u_data = image->planes[VPX_PLANE_U];
- uint8_t* v_data = image->planes[VPX_PLANE_V];
-
- double src_width = src->width() - m_margin.LeftRight();
- double src_height = src->height() - m_margin.top;
- // YUV offsets must be even.
- int yuvTopOffset = m_margin.top & 1 ? m_margin.top + 1 : m_margin.top;
- int yuvLeftOffset = m_margin.left & 1 ? m_margin.left + 1 : m_margin.left;
-
- if (src_width > image->w || src_height > image->h) {
- double scale = std::min(image->w / src_width, image->h / src_height);
- double dst_width = src_width * scale;
- if (dst_width > image->w) {
- src_width *= image->w / dst_width;
- dst_width = image->w;
- }
- double dst_height = src_height * scale;
- if (dst_height > image->h) {
- src_height *= image->h / dst_height;
- dst_height = image->h;
- }
- libyuv::I420Scale(src->DataY() + yuvTopOffset * src->StrideY() + yuvLeftOffset, src->StrideY(),
- src->DataU() + (yuvTopOffset * src->StrideU() + yuvLeftOffset) / 2, src->StrideU(),
- src->DataV() + (yuvTopOffset * src->StrideV() + yuvLeftOffset) / 2, src->StrideV(),
- src_width, src_height,
- y_data, y_stride,
- u_data, uv_stride,
- v_data, uv_stride,
- dst_width, dst_height,
- libyuv::kFilterBilinear);
- } else {
- int width = std::min(image->w, src_width);
- int height = std::min(image->h, src_height);
-
- libyuv::I420Copy(src->DataY() + yuvTopOffset * src->StrideY() + yuvLeftOffset, src->StrideY(),
- src->DataU() + (yuvTopOffset * src->StrideU() + yuvLeftOffset) / 2, src->StrideU(),
- src->DataV() + (yuvTopOffset * src->StrideV() + yuvLeftOffset) / 2, src->StrideV(),
- y_data, y_stride,
- u_data, uv_stride,
- v_data, uv_stride,
- width, height);
- }
- }
-
-private:
- rtc::scoped_refptr m_frameBuffer;
- gfx::IntMargin m_margin;
- TimeDuration m_duration;
-};
-
-
-class ScreencastEncoder::VPXCodec {
-public:
- VPXCodec(ScopedVpxCodec codec, vpx_codec_enc_cfg_t cfg, FILE* file)
- : m_codec(std::move(codec))
- , m_cfg(cfg)
- , m_file(file)
- , m_writer(new WebMFileWriter(file, &m_cfg))
- {
- nsresult rv = NS_NewNamedThread("Screencast enc", getter_AddRefs(m_encoderQueue));
- if (rv != NS_OK) {
- fprintf(stderr, "ScreencastEncoder::VPXCodec failed to spawn thread %d\n", rv);
- return;
- }
-
- createImage(cfg.g_w, cfg.g_h, m_image, m_imageBuffer, m_imageBufferSize);
- }
-
- ~VPXCodec() {
- m_encoderQueue->Shutdown();
- m_encoderQueue = nullptr;
- }
-
- void encodeFrameAsync(std::unique_ptr&& frame)
- {
- m_encoderQueue->Dispatch(NS_NewRunnableFunction("VPXCodec::encodeFrameAsync", [this, frame = std::move(frame)] {
- memset(m_imageBuffer.get(), 128, m_imageBufferSize);
- frame->convertToVpxImage(m_image.get());
-
- double frameCount = frame->duration().ToSeconds() * fps;
- // For long duration repeat frame at 1 fps to ensure last frame duration is short enough.
- // TODO: figure out why simply passing duration doesn't work well.
- for (;frameCount > 1.5; frameCount -= 1) {
- encodeFrame(m_image.get(), timeScale);
- }
- encodeFrame(m_image.get(), std::max(1, frameCount * timeScale));
- }));
- }
-
- void finishAsync(std::function&& callback)
- {
- m_encoderQueue->Dispatch(NS_NewRunnableFunction("VPXCodec::finishAsync", [this, callback = std::move(callback)] {
- finish();
- callback();
- }));
- }
-
-private:
- bool encodeFrame(vpx_image_t *img, int duration)
- {
- vpx_codec_iter_t iter = nullptr;
- const vpx_codec_cx_pkt_t *pkt = nullptr;
- int flags = 0;
- const vpx_codec_err_t res = vpx_codec_encode(m_codec.get(), img, m_pts, duration, flags, VPX_DL_REALTIME);
- if (res != VPX_CODEC_OK) {
- fprintf(stderr, "Failed to encode frame: %s\n", vpx_codec_error(m_codec.get()));
- return false;
- }
-
- bool gotPkts = false;
- while ((pkt = vpx_codec_get_cx_data(m_codec.get(), &iter)) != nullptr) {
- gotPkts = true;
-
- if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) {
- m_writer->writeFrame(pkt);
- ++m_frameCount;
- // fprintf(stderr, " #%03d %spts=%" PRId64 " sz=%zd\n", m_frameCount, (pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0 ? "[K] " : "", pkt->data.frame.pts, pkt->data.frame.sz);
- m_pts += pkt->data.frame.duration;
- }
- }
-
- return gotPkts;
- }
-
- void finish()
- {
- // Flush encoder.
- while (encodeFrame(nullptr, 1))
- ++m_frameCount;
-
- m_writer->finish();
- fclose(m_file);
- // fprintf(stderr, "ScreencastEncoder::finish %d frames\n", m_frameCount);
- }
-
- RefPtr m_encoderQueue;
- ScopedVpxCodec m_codec;
- vpx_codec_enc_cfg_t m_cfg;
- FILE* m_file { nullptr };
- std::unique_ptr m_writer;
- int m_frameCount { 0 };
- int64_t m_pts { 0 };
- std::unique_ptr m_imageBuffer;
- int m_imageBufferSize { 0 };
- std::unique_ptr m_image;
-};
-
-ScreencastEncoder::ScreencastEncoder(std::unique_ptr vpxCodec, const gfx::IntMargin& margin)
- : m_vpxCodec(std::move(vpxCodec))
- , m_margin(margin)
-{
-}
-
-ScreencastEncoder::~ScreencastEncoder()
-{
-}
-
-std::unique_ptr ScreencastEncoder::create(nsCString& errorString, const nsCString& filePath, int width, int height, const gfx::IntMargin& margin)
-{
- vpx_codec_iface_t* codec_interface = vpx_codec_vp8_cx();
- if (!codec_interface) {
- errorString = "Codec not found.";
- return nullptr;
- }
-
- if (width <= 0 || height <= 0 || (width % 2) != 0 || (height % 2) != 0) {
- errorString.AppendPrintf("Invalid frame size: %dx%d", width, height);
- return nullptr;
- }
-
- vpx_codec_enc_cfg_t cfg;
- memset(&cfg, 0, sizeof(cfg));
- vpx_codec_err_t error = vpx_codec_enc_config_default(codec_interface, &cfg, 0);
- if (error) {
- errorString.AppendPrintf("Failed to get default codec config: %s", vpx_codec_err_to_string(error));
- return nullptr;
- }
-
- cfg.g_w = width;
- cfg.g_h = height;
- cfg.g_timebase.num = 1;
- cfg.g_timebase.den = fps * timeScale;
- cfg.g_error_resilient = VPX_ERROR_RESILIENT_DEFAULT;
-
- ScopedVpxCodec codec(new vpx_codec_ctx_t);
- if (vpx_codec_enc_init(codec.get(), codec_interface, &cfg, 0)) {
- errorString.AppendPrintf("Failed to initialize encoder: %s", vpx_codec_error(codec.get()));
- return nullptr;
- }
-
- FILE* file = fopen(filePath.get(), "wb");
- if (!file) {
- errorString.AppendPrintf("Failed to open file '%s' for writing: %s", filePath.get(), strerror(errno));
- return nullptr;
- }
-
- std::unique_ptr vpxCodec(new VPXCodec(std::move(codec), cfg, file));
- // fprintf(stderr, "ScreencastEncoder initialized with: %s\n", vpx_codec_iface_name(codec_interface));
- return std::make_unique(std::move(vpxCodec), margin);
-}
-
-void ScreencastEncoder::flushLastFrame()
-{
- TimeStamp now = TimeStamp::Now();
- if (m_lastFrameTimestamp) {
- // If previous frame encoding failed for some rason leave the timestampt intact.
- if (!m_lastFrame)
- return;
-
- m_lastFrame->setDuration(now - m_lastFrameTimestamp);
- m_vpxCodec->encodeFrameAsync(std::move(m_lastFrame));
- }
- m_lastFrameTimestamp = now;
-}
-
-void ScreencastEncoder::encodeFrame(const webrtc::VideoFrame& videoFrame)
-{
- // fprintf(stderr, "ScreencastEncoder::encodeFrame\n");
- flushLastFrame();
-
- m_lastFrame = std::make_unique(videoFrame.video_frame_buffer(), m_margin);
-}
-
-void ScreencastEncoder::finish(std::function&& callback)
-{
- if (!m_vpxCodec) {
- callback();
- return;
- }
-
- flushLastFrame();
- m_vpxCodec->finishAsync([callback = std::move(callback)] () mutable {
- NS_DispatchToMainThread(NS_NewRunnableFunction("ScreencastEncoder::finish callback", std::move(callback)));
- });
-}
-
-
-} // namespace mozilla
diff --git a/browser_patches/firefox-beta/juggler/screencast/ScreencastEncoder.h b/browser_patches/firefox-beta/juggler/screencast/ScreencastEncoder.h
deleted file mode 100644
index 883ad01011cf6d..00000000000000
--- a/browser_patches/firefox-beta/juggler/screencast/ScreencastEncoder.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#pragma once
-
-#include
-#include
-#include "mozilla/gfx/Rect.h"
-#include "mozilla/Maybe.h"
-#include "mozilla/TimeStamp.h"
-#include "nsISupportsImpl.h"
-#include "nsStringFwd.h"
-
-namespace webrtc {
-class VideoFrame;
-}
-
-namespace mozilla {
-
-class ScreencastEncoder {
-public:
- static constexpr int fps = 25;
-
- static std::unique_ptr create(nsCString& errorString, const nsCString& filePath, int width, int height, const gfx::IntMargin& margin);
-
- class VPXCodec;
- ScreencastEncoder(std::unique_ptr, const gfx::IntMargin& margin);
- ~ScreencastEncoder();
-
- void encodeFrame(const webrtc::VideoFrame& videoFrame);
-
- void finish(std::function&& callback);
-
-private:
- void flushLastFrame();
-
- std::unique_ptr m_vpxCodec;
- gfx::IntMargin m_margin;
- TimeStamp m_lastFrameTimestamp;
- class VPXFrame;
- std::unique_ptr m_lastFrame;
-};
-
-} // namespace mozilla
diff --git a/browser_patches/firefox-beta/juggler/screencast/WebMFileWriter.cpp b/browser_patches/firefox-beta/juggler/screencast/WebMFileWriter.cpp
deleted file mode 100644
index f720b300f25187..00000000000000
--- a/browser_patches/firefox-beta/juggler/screencast/WebMFileWriter.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2014 The WebM project authors. All Rights Reserved.
- */
-
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "WebMFileWriter.h"
-
-#include
-#include "mkvmuxer/mkvmuxerutil.h"
-
-namespace mozilla {
-
-WebMFileWriter::WebMFileWriter(FILE* file, vpx_codec_enc_cfg_t* cfg)
- : m_cfg(cfg)
- , m_writer(new mkvmuxer::MkvWriter(file))
- , m_segment(new mkvmuxer::Segment()) {
- m_segment->Init(m_writer.get());
- m_segment->set_mode(mkvmuxer::Segment::kFile);
- m_segment->OutputCues(true);
-
- mkvmuxer::SegmentInfo* info = m_segment->GetSegmentInfo();
- std::string version = "Playwright " + std::string(vpx_codec_version_str());
- info->set_writing_app(version.c_str());
-
- // Add vp8 track.
- m_videoTrackId = m_segment->AddVideoTrack(
- static_cast(m_cfg->g_w), static_cast(m_cfg->g_h), 0);
- if (!m_videoTrackId) {
- fprintf(stderr, "Failed to add video track\n");
- }
-}
-
-WebMFileWriter::~WebMFileWriter() {}
-
-void WebMFileWriter::writeFrame(const vpx_codec_cx_pkt_t* pkt) {
- int64_t pts_ns = pkt->data.frame.pts * 1000000000ll * m_cfg->g_timebase.num /
- m_cfg->g_timebase.den;
- m_segment->AddFrame(static_cast(pkt->data.frame.buf),
- pkt->data.frame.sz, m_videoTrackId, pts_ns,
- pkt->data.frame.flags & VPX_FRAME_IS_KEY);
-}
-
-void WebMFileWriter::finish() {
- m_segment->Finalize();
-}
-
-} // namespace mozilla
diff --git a/browser_patches/firefox-beta/juggler/screencast/WebMFileWriter.h b/browser_patches/firefox-beta/juggler/screencast/WebMFileWriter.h
deleted file mode 100644
index 4a7fd06e6c3e74..00000000000000
--- a/browser_patches/firefox-beta/juggler/screencast/WebMFileWriter.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#pragma once
-
-#include
-#include
-#include
-#include "vpx/vpx_encoder.h"
-
-#include "mkvmuxer/mkvmuxer.h"
-#include "mkvmuxer/mkvwriter.h"
-
-namespace mozilla {
-
-class WebMFileWriter {
-public:
- WebMFileWriter(FILE*, vpx_codec_enc_cfg_t* cfg);
- ~WebMFileWriter();
-
- void writeFrame(const vpx_codec_cx_pkt_t* pkt);
- void finish();
-
-private:
- vpx_codec_enc_cfg_t* m_cfg = nullptr;
- std::unique_ptr m_writer;
- std::unique_ptr m_segment;
- uint64_t m_videoTrackId = 0;
-};
-
-} // namespace mozilla
diff --git a/browser_patches/firefox-beta/juggler/screencast/components.conf b/browser_patches/firefox-beta/juggler/screencast/components.conf
deleted file mode 100644
index 6298739122ea57..00000000000000
--- a/browser_patches/firefox-beta/juggler/screencast/components.conf
+++ /dev/null
@@ -1,15 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-Classes = [
- {
- 'cid': '{d8c4d9e0-9462-445e-9e43-68d3872ad1de}',
- 'contract_ids': ['@mozilla.org/juggler/screencast;1'],
- 'type': 'nsIScreencastService',
- 'constructor': 'mozilla::nsScreencastService::GetSingleton',
- 'headers': ['/juggler/screencast/nsScreencastService.h'],
- },
-]
diff --git a/browser_patches/firefox-beta/juggler/screencast/moz.build b/browser_patches/firefox-beta/juggler/screencast/moz.build
deleted file mode 100644
index e21b177c3965ce..00000000000000
--- a/browser_patches/firefox-beta/juggler/screencast/moz.build
+++ /dev/null
@@ -1,49 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-XPIDL_SOURCES += [
- 'nsIScreencastService.idl',
-]
-
-XPIDL_MODULE = 'jugglerscreencast'
-
-SOURCES += [
- 'HeadlessWindowCapturer.cpp',
- 'nsScreencastService.cpp',
- 'ScreencastEncoder.cpp',
-]
-
-XPCOM_MANIFESTS += [
- 'components.conf',
-]
-
-LOCAL_INCLUDES += [
- '/dom/media/systemservices',
- '/media/libyuv/libyuv/include',
- '/third_party/libwebrtc',
- '/third_party/libwebrtc/third_party/abseil-cpp',
-]
-
-LOCAL_INCLUDES += [
- '/widget',
- '/widget/headless',
-]
-
-LOCAL_INCLUDES += [
- '/third_party/aom/third_party/libwebm',
-]
-
-SOURCES += [
- '/third_party/aom/third_party/libwebm/mkvmuxer/mkvmuxer.cc',
- '/third_party/aom/third_party/libwebm/mkvmuxer/mkvmuxerutil.cc',
- '/third_party/aom/third_party/libwebm/mkvmuxer/mkvwriter.cc',
- 'WebMFileWriter.cpp',
-]
-
-include('/dom/media/webrtc/third_party_build/webrtc.mozbuild')
-include('/ipc/chromium/chromium-config.mozbuild')
-
-FINAL_LIBRARY = 'xul'
diff --git a/browser_patches/firefox-beta/juggler/screencast/nsIScreencastService.idl b/browser_patches/firefox-beta/juggler/screencast/nsIScreencastService.idl
deleted file mode 100644
index 16c94371ba1c53..00000000000000
--- a/browser_patches/firefox-beta/juggler/screencast/nsIScreencastService.idl
+++ /dev/null
@@ -1,31 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-interface nsIDocShell;
-
-[scriptable, uuid(0b5d32c4-aeeb-11eb-8529-0242ac130003)]
-interface nsIScreencastServiceClient : nsISupports
-{
- void screencastFrame(in AString frame, in uint32_t deviceWidth, in uint32_t deviceHeight);
-
- void screencastStopped();
-};
-
-/**
- * Service for recording window video.
- */
-[scriptable, uuid(d8c4d9e0-9462-445e-9e43-68d3872ad1de)]
-interface nsIScreencastService : nsISupports
-{
- AString startVideoRecording(in nsIScreencastServiceClient client, in nsIDocShell docShell, in boolean isVideo, in ACString fileName, in uint32_t width, in uint32_t height, in uint32_t quality, in uint32_t viewportWidth, in uint32_t viewportHeight, in uint32_t offset_top);
-
- /**
- * Will emit 'juggler-screencast-stopped' when the video file is saved.
- */
- void stopVideoRecording(in AString sessionId);
-
- void screencastFrameAck(in AString sessionId);
-};
diff --git a/browser_patches/firefox-beta/juggler/screencast/nsScreencastService.cpp b/browser_patches/firefox-beta/juggler/screencast/nsScreencastService.cpp
deleted file mode 100644
index 20a766dc3735de..00000000000000
--- a/browser_patches/firefox-beta/juggler/screencast/nsScreencastService.cpp
+++ /dev/null
@@ -1,378 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsScreencastService.h"
-
-#include "ScreencastEncoder.h"
-#include "HeadlessWidget.h"
-#include "HeadlessWindowCapturer.h"
-#include "mozilla/Base64.h"
-#include "mozilla/ClearOnShutdown.h"
-#include "mozilla/PresShell.h"
-#include "mozilla/StaticPtr.h"
-#include "nsIDocShell.h"
-#include "nsIObserverService.h"
-#include "nsIRandomGenerator.h"
-#include "nsISupportsPrimitives.h"
-#include "nsThreadManager.h"
-#include "nsView.h"
-#include "nsViewManager.h"
-#include "modules/desktop_capture/desktop_capturer.h"
-#include "modules/desktop_capture/desktop_capture_options.h"
-#include "modules/desktop_capture/desktop_frame.h"
-#include "modules/video_capture/video_capture.h"
-#include "mozilla/widget/PlatformWidgetTypes.h"
-#include "video_engine/desktop_capture_impl.h"
-extern "C" {
-#include "jpeglib.h"
-}
-#include
-
-using namespace mozilla::widget;
-
-namespace mozilla {
-
-NS_IMPL_ISUPPORTS(nsScreencastService, nsIScreencastService)
-
-namespace {
-
-const int kMaxFramesInFlight = 1;
-
-StaticRefPtr gScreencastService;
-
-rtc::scoped_refptr CreateWindowCapturer(nsIWidget* widget) {
- if (gfxPlatform::IsHeadless()) {
- HeadlessWidget* headlessWidget = static_cast(widget);
- return HeadlessWindowCapturer::Create(headlessWidget);
- }
- uintptr_t rawWindowId = reinterpret_cast(widget->GetNativeData(NS_NATIVE_WINDOW_WEBRTC_DEVICE_ID));
- if (!rawWindowId) {
- fprintf(stderr, "Failed to get native window id\n");
- return nullptr;
- }
- nsCString windowId;
- windowId.AppendPrintf("%" PRIuPTR, rawWindowId);
- bool captureCursor = false;
- static int moduleId = 0;
- return webrtc::DesktopCaptureImpl::Create(++moduleId, windowId.get(), CaptureDeviceType::Window, captureCursor);
-}
-
-nsresult generateUid(nsString& uid) {
- nsresult rv = NS_OK;
- nsCOMPtr rg = do_GetService("@mozilla.org/security/random-generator;1", &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- uint8_t* buffer;
- const int kLen = 16;
- rv = rg->GenerateRandomBytes(kLen, &buffer);
- NS_ENSURE_SUCCESS(rv, rv);
-
- for (int i = 0; i < kLen; i++) {
- uid.AppendPrintf("%02x", buffer[i]);
- }
- free(buffer);
- return rv;
-}
-}
-
-class nsScreencastService::Session : public rtc::VideoSinkInterface,
- public webrtc::RawFrameCallback {
- Session(
- nsIScreencastServiceClient* client,
- rtc::scoped_refptr&& capturer,
- std::unique_ptr encoder,
- int width, int height,
- int viewportWidth, int viewportHeight,
- gfx::IntMargin margin,
- uint32_t jpegQuality)
- : mClient(client)
- , mCaptureModule(std::move(capturer))
- , mEncoder(std::move(encoder))
- , mJpegQuality(jpegQuality)
- , mWidth(width)
- , mHeight(height)
- , mViewportWidth(viewportWidth)
- , mViewportHeight(viewportHeight)
- , mMargin(margin) {
- }
- ~Session() override = default;
-
- public:
- NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Session)
- static RefPtr Create(
- nsIScreencastServiceClient* client,
- rtc::scoped_refptr&& capturer,
- std::unique_ptr encoder,
- int width, int height,
- int viewportWidth, int viewportHeight,
- gfx::IntMargin margin,
- uint32_t jpegQuality) {
- return do_AddRef(new Session(client, std::move(capturer), std::move(encoder), width, height, viewportWidth, viewportHeight, margin, jpegQuality));
- }
-
- bool Start() {
- webrtc::VideoCaptureCapability capability;
- // The size is ignored in fact.
- capability.width = 1280;
- capability.height = 960;
- capability.maxFPS = ScreencastEncoder::fps;
- capability.videoType = webrtc::VideoType::kI420;
- int error = mCaptureModule->StartCapture(capability);
- if (error) {
- fprintf(stderr, "StartCapture error %d\n", error);
- return false;
- }
-
- if (mEncoder)
- mCaptureModule->RegisterCaptureDataCallback(this);
- else
- mCaptureModule->RegisterRawFrameCallback(this);
- return true;
- }
-
- void Stop() {
- if (mStopped) {
- fprintf(stderr, "Screencast session has already been stopped\n");
- return;
- }
- mStopped = true;
- if (mEncoder)
- mCaptureModule->DeRegisterCaptureDataCallback(this);
- else
- mCaptureModule->DeRegisterRawFrameCallback(this);
- int error = mCaptureModule->StopCapture();
- if (error) {
- fprintf(stderr, "StopCapture error %d\n", error);
- }
- if (mEncoder) {
- mEncoder->finish([this, protect = RefPtr{this}] {
- NS_DispatchToMainThread(NS_NewRunnableFunction(
- "NotifyScreencastStopped", [this, protect = std::move(protect)]() -> void {
- mClient->ScreencastStopped();
- }));
- });
- } else {
- mClient->ScreencastStopped();
- }
- }
-
- void ScreencastFrameAck() {
- if (mFramesInFlight.load() == 0) {
- fprintf(stderr, "ScreencastFrameAck is called while there are no inflight frames\n");
- return;
- }
- mFramesInFlight.fetch_sub(1);
- }
-
- // These callbacks end up running on the VideoCapture thread.
- void OnFrame(const webrtc::VideoFrame& videoFrame) override {
- if (!mEncoder)
- return;
- mEncoder->encodeFrame(videoFrame);
- }
-
- // These callbacks end up running on the VideoCapture thread.
- void OnRawFrame(uint8_t* videoFrame, size_t videoFrameStride, const webrtc::VideoCaptureCapability& frameInfo) override {
- int pageWidth = frameInfo.width - mMargin.LeftRight();
- int pageHeight = frameInfo.height - mMargin.TopBottom();
- // Frame size is 1x1 when browser window is minimized.
- if (pageWidth <= 1 || pageHeight <= 1)
- return;
- // Headed Firefox brings sizes in sync slowly.
- if (mViewportWidth && pageWidth > mViewportWidth)
- pageWidth = mViewportWidth;
- if (mViewportHeight && pageHeight > mViewportHeight)
- pageHeight = mViewportHeight;
-
- if (mFramesInFlight.load() >= kMaxFramesInFlight)
- return;
-
- int screenshotWidth = pageWidth;
- int screenshotHeight = pageHeight;
- int screenshotTopMargin = mMargin.TopBottom();
- std::unique_ptr canvas;
- uint8_t* canvasPtr = videoFrame;
- int canvasStride = videoFrameStride;
-
- if (mWidth < pageWidth || mHeight < pageHeight) {
- double scale = std::min(1., std::min((double)mWidth / pageWidth, (double)mHeight / pageHeight));
- int canvasWidth = frameInfo.width * scale;
- int canvasHeight = frameInfo.height * scale;
- canvasStride = canvasWidth * 4;
-
- screenshotWidth *= scale;
- screenshotHeight *= scale;
- screenshotTopMargin *= scale;
-
- canvas.reset(new uint8_t[canvasWidth * canvasHeight * 4]);
- canvasPtr = canvas.get();
- libyuv::ARGBScale(videoFrame,
- videoFrameStride,
- frameInfo.width,
- frameInfo.height,
- canvasPtr,
- canvasStride,
- canvasWidth,
- canvasHeight,
- libyuv::kFilterBilinear);
- }
-
- jpeg_compress_struct info;
- jpeg_error_mgr error;
- info.err = jpeg_std_error(&error);
- jpeg_create_compress(&info);
-
- unsigned char* bufferPtr = nullptr;
- unsigned long bufferSize;
- jpeg_mem_dest(&info, &bufferPtr, &bufferSize);
-
- info.image_width = screenshotWidth;
- info.image_height = screenshotHeight;
-
-#if MOZ_LITTLE_ENDIAN()
- if (frameInfo.videoType == webrtc::VideoType::kARGB)
- info.in_color_space = JCS_EXT_BGRA;
- if (frameInfo.videoType == webrtc::VideoType::kBGRA)
- info.in_color_space = JCS_EXT_ARGB;
-#else
- if (frameInfo.videoType == webrtc::VideoType::kARGB)
- info.in_color_space = JCS_EXT_ARGB;
- if (frameInfo.videoType == webrtc::VideoType::kBGRA)
- info.in_color_space = JCS_EXT_BGRA;
-#endif
-
- // # of color components in input image
- info.input_components = 4;
-
- jpeg_set_defaults(&info);
- jpeg_set_quality(&info, mJpegQuality, true);
-
- jpeg_start_compress(&info, true);
- while (info.next_scanline < info.image_height) {
- JSAMPROW row = canvasPtr + (screenshotTopMargin + info.next_scanline) * canvasStride;
- if (jpeg_write_scanlines(&info, &row, 1) != 1) {
- fprintf(stderr, "JPEG library failed to encode line\n");
- break;
- }
- }
-
- jpeg_finish_compress(&info);
- jpeg_destroy_compress(&info);
-
- nsCString base64;
- nsresult rv = mozilla::Base64Encode(reinterpret_cast(bufferPtr), bufferSize, base64);
- free(bufferPtr);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return;
- }
-
- mFramesInFlight.fetch_add(1);
- NS_DispatchToMainThread(NS_NewRunnableFunction(
- "NotifyScreencastFrame", [this, protect = RefPtr{this}, base64, pageWidth, pageHeight]() -> void {
- if (mStopped)
- return;
- NS_ConvertUTF8toUTF16 utf16(base64);
- mClient->ScreencastFrame(utf16, pageWidth, pageHeight);
- }));
- }
-
- private:
- RefPtr mClient;
- rtc::scoped_refptr mCaptureModule;
- std::unique_ptr mEncoder;
- uint32_t mJpegQuality;
- bool mStopped = false;
- std::atomic mFramesInFlight = 0;
- int mWidth;
- int mHeight;
- int mViewportWidth;
- int mViewportHeight;
- gfx::IntMargin mMargin;
-};
-
-
-// static
-already_AddRefed nsScreencastService::GetSingleton() {
- if (gScreencastService) {
- return do_AddRef(gScreencastService);
- }
-
- gScreencastService = new nsScreencastService();
- // ClearOnShutdown(&gScreencastService);
- return do_AddRef(gScreencastService);
-}
-
-nsScreencastService::nsScreencastService() = default;
-
-nsScreencastService::~nsScreencastService() {
-}
-
-nsresult nsScreencastService::StartVideoRecording(nsIScreencastServiceClient* aClient, nsIDocShell* aDocShell, bool isVideo, const nsACString& aVideoFileName, uint32_t width, uint32_t height, uint32_t quality, uint32_t viewportWidth, uint32_t viewportHeight, uint32_t offsetTop, nsAString& sessionId) {
- MOZ_RELEASE_ASSERT(NS_IsMainThread(), "Screencast service must be started on the Main thread.");
-
- PresShell* presShell = aDocShell->GetPresShell();
- if (!presShell)
- return NS_ERROR_UNEXPECTED;
- nsViewManager* viewManager = presShell->GetViewManager();
- if (!viewManager)
- return NS_ERROR_UNEXPECTED;
- nsView* view = viewManager->GetRootView();
- if (!view)
- return NS_ERROR_UNEXPECTED;
- nsIWidget* widget = view->GetWidget();
-
- rtc::scoped_refptr capturer = CreateWindowCapturer(widget);
- if (!capturer)
- return NS_ERROR_FAILURE;
-
- gfx::IntMargin margin;
- auto bounds = widget->GetScreenBounds().ToUnknownRect();
- auto clientBounds = widget->GetClientBounds().ToUnknownRect();
- // Crop the image to exclude frame (if any).
- margin = bounds - clientBounds;
- // Crop the image to exclude controls.
- margin.top += offsetTop;
-
- nsCString error;
- std::unique_ptr encoder;
- if (isVideo) {
- encoder = ScreencastEncoder::create(error, PromiseFlatCString(aVideoFileName), width, height, margin);
- if (!encoder) {
- fprintf(stderr, "Failed to create ScreencastEncoder: %s\n", error.get());
- return NS_ERROR_FAILURE;
- }
- }
-
- nsString uid;
- nsresult rv = generateUid(uid);
- NS_ENSURE_SUCCESS(rv, rv);
- sessionId = uid;
-
- auto session = Session::Create(aClient, std::move(capturer), std::move(encoder), width, height, viewportWidth, viewportHeight, margin, isVideo ? 0 : quality);
- if (!session->Start())
- return NS_ERROR_FAILURE;
- mIdToSession.emplace(sessionId, std::move(session));
- return NS_OK;
-}
-
-nsresult nsScreencastService::StopVideoRecording(const nsAString& aSessionId) {
- nsString sessionId(aSessionId);
- auto it = mIdToSession.find(sessionId);
- if (it == mIdToSession.end())
- return NS_ERROR_INVALID_ARG;
- it->second->Stop();
- mIdToSession.erase(it);
- return NS_OK;
-}
-
-nsresult nsScreencastService::ScreencastFrameAck(const nsAString& aSessionId) {
- nsString sessionId(aSessionId);
- auto it = mIdToSession.find(sessionId);
- if (it == mIdToSession.end())
- return NS_ERROR_INVALID_ARG;
- it->second->ScreencastFrameAck();
- return NS_OK;
-}
-
-} // namespace mozilla
diff --git a/browser_patches/firefox-beta/juggler/screencast/nsScreencastService.h b/browser_patches/firefox-beta/juggler/screencast/nsScreencastService.h
deleted file mode 100644
index 419603e0e69b0a..00000000000000
--- a/browser_patches/firefox-beta/juggler/screencast/nsScreencastService.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#pragma once
-
-#include
-#include