diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json deleted file mode 100644 index b6524c2c49caf..0000000000000 --- a/.devcontainer/devcontainer.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "name": "Playwright", - "image": "mcr.microsoft.com/playwright:next", - "postCreateCommand": "npm install && npm run build && apt-get update && apt-get install -y software-properties-common && curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - && add-apt-repository \"deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable\" && apt-get install -y docker-ce-cli", - "settings": { - "terminal.integrated.shell.linux": "/bin/bash" - }, - "runArgs": [ - "-v", "/var/run/docker.sock:/var/run/docker.sock" - ] -} \ No newline at end of file diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 60b8fd360fcb9..0000000000000 --- a/.eslintignore +++ /dev/null @@ -1,21 +0,0 @@ -test/assets/modernizr.js -/tests/third_party/ -/packages/*/lib/ -*.js -/packages/playwright-core/src/generated/* -/packages/playwright-core/src/third_party/ -/packages/playwright-core/types/* -/packages/playwright-ct-core/src/generated/* -/index.d.ts -node_modules/ -browser_patches/*/checkout/ -browser_patches/chromium/output/ -**/*.d.ts -output/ -test-results/ -tests/components/ -tests/installation/fixture-scripts/ -examples/ -DEPS -.cache/ -utils/ diff --git a/.eslintrc-with-ts-config.js b/.eslintrc-with-ts-config.js deleted file mode 100644 index b06ec001951bc..0000000000000 --- a/.eslintrc-with-ts-config.js +++ /dev/null @@ -1,15 +0,0 @@ -module.exports = { - extends: "./.eslintrc.js", - parserOptions: { - ecmaVersion: 9, - sourceType: "module", - project: "./tsconfig.json", - }, - rules: { - "@typescript-eslint/no-base-to-string": "error", - "@typescript-eslint/no-unnecessary-boolean-literal-compare": 2, - }, - parserOptions: { - project: "./tsconfig.json" - }, -}; diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index bb351a8c5640d..0000000000000 --- a/.eslintrc.js +++ /dev/null @@ -1,128 +0,0 @@ -module.exports = { - parser: "@typescript-eslint/parser", - plugins: ["@typescript-eslint", "notice"], - parserOptions: { - ecmaVersion: 9, - sourceType: "module", - }, - extends: [ - "plugin:react-hooks/recommended" - ], - - /** - * ESLint rules - * - * All available rules: http://eslint.org/docs/rules/ - * - * Rules take the following form: - * "rule-name", [severity, { opts }] - * Severity: 2 == error, 1 == warning, 0 == off. - */ - rules: { - "@typescript-eslint/no-unused-vars": [2, {args: "none"}], - "@typescript-eslint/consistent-type-imports": [2, {disallowTypeAnnotations: false}], - /** - * Enforced rules - */ - // syntax preferences - "object-curly-spacing": ["error", "always"], - "quotes": [2, "single", { - "avoidEscape": true, - "allowTemplateLiterals": true - }], - "jsx-quotes": [2, "prefer-single"], - "no-extra-semi": 2, - "@typescript-eslint/semi": [2], - "comma-style": [2, "last"], - "wrap-iife": [2, "inside"], - "spaced-comment": [2, "always", { - "markers": ["*"] - }], - "eqeqeq": [2], - "accessor-pairs": [2, { - "getWithoutSet": false, - "setWithoutGet": false - }], - "brace-style": [2, "1tbs", {"allowSingleLine": true}], - "curly": [2, "multi-or-nest", "consistent"], - "new-parens": 2, - "arrow-parens": [2, "as-needed"], - "prefer-const": 2, - "quote-props": [2, "consistent"], - "nonblock-statement-body-position": [2, "below"], - - // anti-patterns - "no-var": 2, - "no-with": 2, - "no-multi-str": 2, - "no-caller": 2, - "no-implied-eval": 2, - "no-labels": 2, - "no-new-object": 2, - "no-octal-escape": 2, - "no-self-compare": 2, - "no-shadow-restricted-names": 2, - "no-cond-assign": 2, - "no-debugger": 2, - "no-dupe-keys": 2, - "no-duplicate-case": 2, - "no-empty-character-class": 2, - "no-unreachable": 2, - "no-unsafe-negation": 2, - "radix": 2, - "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, - "template-curly-spacing": [2, "never"], - - // spacing details - "space-infix-ops": 2, - "space-in-parens": [2, "never"], - "array-bracket-spacing": [2, "never"], - "comma-spacing": [2, { "before": false, "after": true }], - "keyword-spacing": [2, "always"], - "space-before-function-paren": [2, { - "anonymous": "never", - "named": "never", - "asyncArrow": "always" - }], - "no-whitespace-before-property": 2, - "keyword-spacing": [2, { - "overrides": { - "if": {"after": true}, - "else": {"after": true}, - "for": {"after": true}, - "while": {"after": true}, - "do": {"after": true}, - "switch": {"after": true}, - "return": {"after": true} - } - }], - "arrow-spacing": [2, { - "after": true, - "before": true - }], - "@typescript-eslint/func-call-spacing": 2, - "@typescript-eslint/type-annotation-spacing": 2, - - // file whitespace - "no-multiple-empty-lines": [2, {"max": 2}], - "no-mixed-spaces-and-tabs": 2, - "no-trailing-spaces": 2, - "linebreak-style": [ process.platform === "win32" ? 0 : 2, "unix" ], - "indent": [2, 2, { "SwitchCase": 1, "CallExpression": {"arguments": 2}, "MemberExpression": 2 }], - "key-spacing": [2, { - "beforeColon": false - }], - - // copyright - "notice/notice": [2, { - "mustMatch": "Copyright", - "templateFile": require("path").join(__dirname, "utils", "copyright.js"), - }], - } -}; diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index 062d7c7e742d1..60fea176c8f0c 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -24,6 +24,7 @@ body: ## Make a minimal reproduction To file the report, you will need a GitHub repository with a minimal (but complete) example and simple/clear steps on how to reproduce the bug. The simpler you can make it, the more likely we are to successfully verify and fix the bug. You can create a new project with `npm init playwright@latest new-project` and then add the test code there. + Please make sure you only include the code and the dependencies absolutely necessary for your repro. Due to the security considerations, we can only run the code we trust. Major web frameworks are Ok to use, but smaller convenience libraries are not. - type: markdown attributes: value: | diff --git a/.github/ISSUE_TEMPLATE/question.yml b/.github/ISSUE_TEMPLATE/question.yml index 9615afdc8a2ec..b64936798031e 100644 --- a/.github/ISSUE_TEMPLATE/question.yml +++ b/.github/ISSUE_TEMPLATE/question.yml @@ -23,5 +23,5 @@ body: > [!IMPORTANT] > This issue will be closed. options: - - label: I understand + - label: I understand that this issue will be closed required: true diff --git a/.github/ISSUE_TEMPLATE/regression.yml b/.github/ISSUE_TEMPLATE/regression.yml index bc0a101502a6f..632c67104b19b 100644 --- a/.github/ISSUE_TEMPLATE/regression.yml +++ b/.github/ISSUE_TEMPLATE/regression.yml @@ -1,7 +1,6 @@ name: Report regression description: Functionality that used to work and does not any more title: "[Regression]: " - body: - type: markdown attributes: diff --git a/.github/actions/enable-microphone-access/action.yml b/.github/actions/enable-microphone-access/action.yml index b94f48064711f..76ca24eebfc6d 100644 --- a/.github/actions/enable-microphone-access/action.yml +++ b/.github/actions/enable-microphone-access/action.yml @@ -14,12 +14,12 @@ runs: fi echo "Allowing microphone access to all apps" version=$(sw_vers -productVersion | cut -d. -f1) - if [[ "$version" == "14" ]]; then + if [[ "$version" == "14" || "$version" == "15" ]]; then sqlite3 $HOME/Library/Application\ Support/com.apple.TCC/TCC.db "INSERT OR IGNORE INTO access VALUES ('kTCCServiceMicrophone','/usr/local/opt/runner/provisioner/provisioner',1,2,4,1,NULL,NULL,0,'UNUSED',NULL,0,1687786159,NULL,NULL,'UNUSED',1687786159);" elif [[ "$version" == "12" || "$version" == "13" ]]; then sqlite3 $HOME/Library/Application\ Support/com.apple.TCC/TCC.db "INSERT OR REPLACE INTO access VALUES('kTCCServiceMicrophone','/usr/local/opt/runner/provisioner/provisioner',1,2,4,1,NULL,NULL,0,'UNUSED',NULL,0,1687786159);" else - echo "macOS version is unsupported. Version is $version, exiting" - exit 1 + echo "Skipping unsupported macOS version $version" + exit 0 fi echo "Successfully allowed microphone access" diff --git a/.github/actions/run-test/action.yml b/.github/actions/run-test/action.yml index c193515c4501d..3f458b8b6247f 100644 --- a/.github/actions/run-test/action.yml +++ b/.github/actions/run-test/action.yml @@ -41,9 +41,6 @@ runs: npm ci echo "::endgroup::" shell: bash - env: - DEBUG: pw:install - PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: '1' - run: | echo "::group::npm run build" npm run build diff --git a/.github/actions/upload-blob-report/action.yml b/.github/actions/upload-blob-report/action.yml index 72a084142a77f..e407e67573928 100644 --- a/.github/actions/upload-blob-report/action.yml +++ b/.github/actions/upload-blob-report/action.yml @@ -22,13 +22,3 @@ runs: name: blob-report-${{ inputs.job_name }} path: ${{ inputs.report_dir }}/** retention-days: 7 - - name: Write triggering pull request number in a file - if: ${{ !cancelled() && 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: ${{ !cancelled() && github.event_name == 'pull_request' }} - uses: actions/upload-artifact@v4 - with: - name: pull-request-${{ inputs.job_name }} - path: pull_request_number.txt \ No newline at end of file diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000000000..84a45f6df4322 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,14 @@ +version: 2 +updates: + - package-ecosystem: "pip" + directory: "/" + schedule: + interval: "weekly" + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + groups: + actions: + patterns: + - "*" diff --git a/.github/workflows/cherry_pick_into_release_branch.yml b/.github/workflows/cherry_pick_into_release_branch.yml index 08c5562f35f03..b0f635a69b199 100644 --- a/.github/workflows/cherry_pick_into_release_branch.yml +++ b/.github/workflows/cherry_pick_into_release_branch.yml @@ -33,8 +33,8 @@ jobs: - name: Cherry-pick commits id: cherry-pick run: | - git config --global user.name github-actions - git config --global user.email 41898282+github-actions[bot]@users.noreply.github.com + git config --global user.name microsoft-playwright-automation[bot] + git config --global user.email 203992400+microsoft-playwright-automation[bot]@users.noreply.github.com for COMMIT_HASH in $(echo "${{ github.event.inputs.commit_hashes }}" | tr "," "\n"); do git cherry-pick --no-commit "$COMMIT_HASH" @@ -59,10 +59,15 @@ jobs: echo "BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_OUTPUT git checkout -b "$BRANCH_NAME" git push origin $BRANCH_NAME + - uses: actions/create-github-app-token@v2 + id: app-token + with: + app-id: ${{ vars.PLAYWRIGHT_APP_ID }} + private-key: ${{ secrets.PLAYWRIGHT_PRIVATE_KEY }} - name: Create Pull Request uses: actions/github-script@v7 with: - github-token: ${{ secrets.REPOSITORY_DISPATCH_PERSONAL_ACCESS_TOKEN }} + github-token: ${{ steps.app-token.outputs.token }} script: | const readableCommitHashesList = '${{ github.event.inputs.commit_hashes }}'.split(',').map(hash => `- ${hash}`).join('\n'); const response = await github.rest.pulls.create({ diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml new file mode 100644 index 0000000000000..54cf652ae21b6 --- /dev/null +++ b/.github/workflows/copilot-setup-steps.yml @@ -0,0 +1,17 @@ +name: "Copilot Setup Steps" +on: workflow_dispatch +jobs: + copilot-setup-steps: + runs-on: ubuntu-latest + + permissions: + contents: read + + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: "22" + - run: npm ci + - run: npm run build + - run: npx playwright install --with-deps diff --git a/.github/workflows/create_test_report.yml b/.github/workflows/create_test_report.yml index 9d382f1ee632e..6758556deff7e 100644 --- a/.github/workflows/create_test_report.yml +++ b/.github/workflows/create_test_report.yml @@ -20,8 +20,7 @@ jobs: node-version: 18 - run: npm ci env: - DEBUG: pw:install - PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 + ELECTRON_SKIP_BINARY_DOWNLOAD: 1 - run: npm run build - name: Download blob report artifact @@ -34,7 +33,9 @@ jobs: run: | npx playwright merge-reports --config .github/workflows/merge.config.ts ./all-blob-reports env: - NODE_OPTIONS: --max-old-space-size=4096 + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NODE_OPTIONS: --max-old-space-size=8192 + HTML_REPORT_URL: 'https://mspwblobreport.z1.web.core.windows.net/run-${{ github.event.workflow_run.id }}-${{ github.event.workflow_run.run_attempt }}-${{ github.sha }}/index.html' - name: Azure Login uses: azure/login@v2 @@ -50,91 +51,3 @@ jobs: echo "Report url: https://mspwblobreport.z1.web.core.windows.net/$REPORT_DIR/index.html" env: AZCOPY_AUTO_LOGIN_TYPE: AZCLI - - - name: Read pull request number - uses: ./.github/actions/download-artifact - with: - namePrefix: 'pull-request' - path: '.' - - - name: Comment on PR - uses: actions/github-script@v7 - 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 { - 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; - } - { - // Mark previous comments as outdated by minimizing them. - const { data: comments } = await github.rest.issues.listComments({ - ...context.repo, - issue_number: prNumber, - }); - for (const comment of comments) { - if (comment.user.login === 'github-actions[bot]' && /\[Test results\]\(https:\/\/.+?\) for "${{ github.event.workflow_run.name }}"/.test(comment.body)) { - await github.graphql(` - mutation { - minimizeComment(input: {subjectId: "${comment.node_id}", classifier: OUTDATED}) { - clientMutationId - } - } - `); - } - } - } - 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'); - function formatComment(lines) { - let body = lines.join('\n'); - if (body.length > 65535) - body = body.substring(0, 65000) + `... ${body.length - 65000} more characters`; - return body; - } - const { data: response } = await github.rest.issues.createComment({ - ...context.repo, - issue_number: prNumber, - body: formatComment([ - `### [Test results](${reportUrl}) for "${{ github.event.workflow_run.name }}"`, - reportMd, - '', - `Merge [workflow run](${mergeWorkflowUrl}).` - ]), - }); - 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 3580ecc97ad8d..0a03f10f1338a 100644 --- a/.github/workflows/infra.yml +++ b/.github/workflows/infra.yml @@ -16,7 +16,7 @@ env: jobs: doc-and-lint: name: "docs & lint" - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -24,8 +24,7 @@ jobs: node-version: 18 - run: npm ci - run: npm run build - - run: npx playwright install-deps - - run: npx playwright install + - run: npx playwright install --with-deps - run: npm run lint - name: Verify clean tree run: | @@ -35,21 +34,28 @@ jobs: exit 1 fi - name: Audit prod NPM dependencies - run: npm audit --omit dev + run: node utils/check_audit.js + continue-on-error: true lint-snippets: name: "Lint snippets" - runs-on: ubuntu-22.04 + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 18 - - uses: actions/setup-python@v4 + - uses: actions/setup-python@v5 with: python-version: '3.11' - - uses: actions/setup-dotnet@v3 + - uses: actions/setup-dotnet@v4 with: dotnet-version: 8.0.x + - uses: actions/setup-java@v4 + with: + distribution: 'zulu' + java-version: '21' - run: npm ci - run: pip install -r utils/doclint/linting-code-snippets/python/requirements.txt + - run: mvn package + working-directory: utils/doclint/linting-code-snippets/java - run: node utils/doclint/linting-code-snippets/cli.js diff --git a/.github/workflows/merge.config.ts b/.github/workflows/merge.config.ts index b39944bc809c1..222b728f7c134 100644 --- a/.github/workflows/merge.config.ts +++ b/.github/workflows/merge.config.ts @@ -1,4 +1,4 @@ export default { testDir: '../../tests', - reporter: [['markdown'], ['html']] + reporter: [[require.resolve('../../tests/config/ghaMarkdownReporter')], ['html']] }; \ No newline at end of file diff --git a/.github/workflows/pr_check_client_side_changes.yml b/.github/workflows/pr_check_client_side_changes.yml index 7748b5d514af3..12b7e5dff9131 100644 --- a/.github/workflows/pr_check_client_side_changes.yml +++ b/.github/workflows/pr_check_client_side_changes.yml @@ -12,14 +12,24 @@ on: jobs: check: name: Check - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 if: github.repository == 'microsoft/playwright' steps: - uses: actions/checkout@v4 + - uses: actions/create-github-app-token@v2 + id: app-token + with: + app-id: ${{ vars.PLAYWRIGHT_APP_ID }} + private-key: ${{ secrets.PLAYWRIGHT_PRIVATE_KEY }} + repositories: | + playwright + playwright-python + playwright-java + playwright-dotnet - name: Create GitHub issue uses: actions/github-script@v7 with: - github-token: ${{ secrets.REPOSITORY_DISPATCH_PERSONAL_ACCESS_TOKEN }} + github-token: ${{ steps.app-token.outputs.token }} script: | const currentPlaywrightVersion = require('./package.json').version.match(/\d+\.\d+/)[0]; const { data } = await github.rest.git.getCommit({ @@ -28,11 +38,15 @@ jobs: commit_sha: context.sha, }); const commitHeader = data.message.split('\n')[0]; + const prMatch = commitHeader.match(/#(\d+)/); + const formattedCommit = prMatch + ? `https://github.com/microsoft/playwright/pull/${prMatch[1]}` + : `https://github.com/${context.repo.owner}/${context.repo.repo}/commit/${context.sha} (${commitHeader})`; const title = '[Ports]: Backport client side changes for ' + currentPlaywrightVersion; for (const repo of ['playwright-python', 'playwright-java', 'playwright-dotnet']) { const { data: issuesData } = await github.rest.search.issuesAndPullRequests({ - q: `is:issue is:open repo:microsoft/${repo} in:title "${title}" author:playwrightmachine` + q: `is:issue is:open repo:microsoft/${repo} in:title "${title}"` }) let issueNumber = null; let issueBody = ''; @@ -50,7 +64,7 @@ jobs: issueBody = issueCreateData.body; } const newBody = issueBody.trimEnd() + ` - - [ ] https://github.com/${context.repo.owner}/${context.repo.repo}/commit/${context.sha} (${commitHeader})`; + - [ ] ${formattedCommit}`; const data = await github.rest.issues.update({ owner: context.repo.owner, repo: repo, diff --git a/.github/workflows/publish_canary.yml b/.github/workflows/publish_canary.yml index 50a156475529a..87ebcf27b3a5e 100644 --- a/.github/workflows/publish_canary.yml +++ b/.github/workflows/publish_canary.yml @@ -3,7 +3,7 @@ name: "publish canary" on: workflow_dispatch: schedule: - - cron: "10 0 * * *" + - cron: "10 5 * * *" push: branches: - release-* @@ -14,7 +14,7 @@ env: jobs: publish-canary: name: "publish canary NPM" - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 if: github.repository == 'microsoft/playwright' permissions: id-token: write # This is required for OIDC login (azure/login) to succeed @@ -28,7 +28,6 @@ jobs: registry-url: 'https://registry.npmjs.org' - run: npm ci - run: npm run build - - run: npx playwright install-deps - name: "@next: publish with commit timestamp (triggered manually)" if: contains(github.ref, 'main') && github.event_name == 'workflow_dispatch' run: | @@ -65,20 +64,26 @@ jobs: publish-trace-viewer: name: "publish Trace Viewer to trace.playwright.dev" - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 if: github.repository == 'microsoft/playwright' steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 18 + - uses: actions/create-github-app-token@v2 + id: app-token + with: + app-id: ${{ vars.PLAYWRIGHT_APP_ID }} + private-key: ${{ secrets.PLAYWRIGHT_PRIVATE_KEY }} + repositories: trace.playwright.dev - name: Deploy Canary run: bash utils/build/deploy-trace-viewer.sh --canary if: contains(github.ref, 'main') env: - GH_SERVICE_ACCOUNT_TOKEN: ${{ secrets.REPOSITORY_DISPATCH_PERSONAL_ACCESS_TOKEN }} + GH_SERVICE_ACCOUNT_TOKEN: ${{ steps.app-token.outputs.token }} - name: Deploy BETA run: bash utils/build/deploy-trace-viewer.sh --beta if: contains(github.ref, 'release') env: - GH_SERVICE_ACCOUNT_TOKEN: ${{ secrets.REPOSITORY_DISPATCH_PERSONAL_ACCESS_TOKEN }} + GH_SERVICE_ACCOUNT_TOKEN: ${{ steps.app-token.outputs.token }} diff --git a/.github/workflows/publish_release_docker.yml b/.github/workflows/publish_release_docker.yml index 6a9e6d85ae05e..c9603bffcdf21 100644 --- a/.github/workflows/publish_release_docker.yml +++ b/.github/workflows/publish_release_docker.yml @@ -2,12 +2,6 @@ name: "publish release - Docker" on: workflow_dispatch: - inputs: - is_release: - required: true - type: boolean - description: "Is this a release image?" - release: types: [published] @@ -35,7 +29,6 @@ jobs: platforms: arm64 - run: npm ci - run: npm run build - - run: npx playwright install-deps - name: Azure Login uses: azure/login@v2 with: @@ -45,6 +38,3 @@ jobs: - name: Login to ACR via OIDC run: az acr login --name playwright - run: ./utils/docker/publish_docker.sh stable - if: (github.event_name != 'workflow_dispatch' && !github.event.release.prerelease) || (github.event_name == 'workflow_dispatch' && github.event.inputs.is_release == 'true') - - run: ./utils/docker/publish_docker.sh canary - if: (github.event_name != 'workflow_dispatch' && github.event.release.prerelease) || (github.event_name == 'workflow_dispatch' && github.event.inputs.is_release != 'true') diff --git a/.github/workflows/publish_release_driver.yml b/.github/workflows/publish_release_driver.yml index 8ad1a4184a185..328deaf01cb7a 100644 --- a/.github/workflows/publish_release_driver.yml +++ b/.github/workflows/publish_release_driver.yml @@ -10,7 +10,7 @@ env: jobs: publish-driver-release: name: "publish playwright driver to CDN" - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 if: github.repository == 'microsoft/playwright' permissions: id-token: write # This is required for OIDC login (azure/login) to succeed @@ -24,7 +24,6 @@ jobs: registry-url: 'https://registry.npmjs.org' - run: npm ci - run: npm run build - - run: npx playwright install-deps - run: utils/build/build-playwright-driver.sh - name: Azure Login uses: azure/login@v2 diff --git a/.github/workflows/publish_release_npm.yml b/.github/workflows/publish_release_npm.yml index 46b58168345dc..cab5e13596467 100644 --- a/.github/workflows/publish_release_npm.yml +++ b/.github/workflows/publish_release_npm.yml @@ -10,7 +10,7 @@ env: jobs: publish-npm-release: name: "publish to NPM" - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 if: github.repository == 'microsoft/playwright' permissions: contents: read @@ -23,7 +23,6 @@ jobs: registry-url: 'https://registry.npmjs.org' - run: npm ci - run: npm run build - - run: npx playwright install-deps - run: utils/publish_all_packages.sh --release-candidate if: ${{ github.event.release.prerelease }} env: diff --git a/.github/workflows/publish_release_traceviewer.yml b/.github/workflows/publish_release_traceviewer.yml index 60af5442e95b2..b497f5290cdcc 100644 --- a/.github/workflows/publish_release_traceviewer.yml +++ b/.github/workflows/publish_release_traceviewer.yml @@ -7,14 +7,20 @@ on: jobs: publish-trace-viewer: name: "publish Trace Viewer to trace.playwright.dev" - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 if: github.repository == 'microsoft/playwright' steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 18 + - uses: actions/create-github-app-token@v2 + id: app-token + with: + app-id: ${{ vars.PLAYWRIGHT_APP_ID }} + private-key: ${{ secrets.PLAYWRIGHT_PRIVATE_KEY }} + repositories: trace.playwright.dev - name: Deploy Stable run: bash utils/build/deploy-trace-viewer.sh --stable env: - GH_SERVICE_ACCOUNT_TOKEN: ${{ secrets.REPOSITORY_DISPATCH_PERSONAL_ACCESS_TOKEN }} + GH_SERVICE_ACCOUNT_TOKEN: ${{ steps.app-token.outputs.token }} diff --git a/.github/workflows/roll_browser_into_playwright.yml b/.github/workflows/roll_browser_into_playwright.yml index da905131603e6..3dc822638e361 100644 --- a/.github/workflows/roll_browser_into_playwright.yml +++ b/.github/workflows/roll_browser_into_playwright.yml @@ -6,13 +6,18 @@ on: env: ELECTRON_SKIP_BINARY_DOWNLOAD: 1 + BROWSER: ${{ github.event.client_payload.browser }} + REVISION: ${{ github.event.client_payload.revision }} permissions: contents: write +concurrency: + group: 'roll-browser-into-playwright-${{ github.event.client_payload.browser }}-${{ github.event.client_payload.revision }}' + jobs: roll: - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -24,30 +29,45 @@ jobs: run: npx playwright install-deps - name: Roll to new revision run: | - ./utils/roll_browser.js ${{ github.event.client_payload.browser }} ${{ github.event.client_payload.revision }} + ./utils/roll_browser.js $BROWSER $REVISION npm run build - name: Prepare branch id: prepare-branch run: | - BRANCH_NAME="roll-into-pw-${{ github.event.client_payload.browser }}/${{ github.event.client_payload.revision }}" + BRANCH_NAME="roll-into-pw-${BROWSER}/${REVISION}" 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 fetch origin $BRANCH_NAME:$BRANCH_NAME || true + if git show-ref --verify --quiet refs/heads/$BRANCH_NAME; then + echo "exists=1" >> $GITHUB_OUTPUT + echo "branch $BRANCH_NAME already exists, exiting" + exit 0 + fi + echo "exists=0" >> $GITHUB_OUTPUT + + git config --global user.name microsoft-playwright-automation[bot] + git config --global user.email 203992400+microsoft-playwright-automation[bot]@users.noreply.github.com git checkout -b "$BRANCH_NAME" git add . - git commit -m "feat(${{ github.event.client_payload.browser }}): roll to r${{ github.event.client_payload.revision }}" - git push origin $BRANCH_NAME + git commit -m "feat(${BROWSER}): roll to r${REVISION}" + git push origin $BRANCH_NAME --force + - uses: actions/create-github-app-token@v2 + id: app-token + with: + app-id: ${{ vars.PLAYWRIGHT_APP_ID }} + private-key: ${{ secrets.PLAYWRIGHT_PRIVATE_KEY }} - name: Create Pull Request uses: actions/github-script@v7 + if: ${{ steps.prepare-branch.outputs.exists == '0' }} with: - github-token: ${{ secrets.REPOSITORY_DISPATCH_PERSONAL_ACCESS_TOKEN }} + github-token: ${{ steps.app-token.outputs.token }} script: | 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 }}', + title: 'feat(${{ env.BROWSER }}): roll to r${{ env.REVISION }}', }); await github.rest.issues.addLabels({ owner: 'microsoft', diff --git a/.github/workflows/roll_driver_nodejs.yml b/.github/workflows/roll_driver_nodejs.yml index ee0d3d262ce36..ee993f980f12d 100644 --- a/.github/workflows/roll_driver_nodejs.yml +++ b/.github/workflows/roll_driver_nodejs.yml @@ -27,17 +27,22 @@ jobs: echo "HAS_CHANGES=1" >> $GITHUB_OUTPUT BRANCH_NAME="roll-driver-nodejs/$(date +%Y-%b-%d)" 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 config --global user.name microsoft-playwright-automation[bot] + git config --global user.email 203992400+microsoft-playwright-automation[bot]@users.noreply.github.com git checkout -b "$BRANCH_NAME" git add . git commit -m "chore(driver): roll driver to recent Node.js LTS version" git push origin $BRANCH_NAME + - uses: actions/create-github-app-token@v2 + id: app-token + with: + app-id: ${{ vars.PLAYWRIGHT_APP_ID }} + private-key: ${{ secrets.PLAYWRIGHT_PRIVATE_KEY }} - name: Create Pull Request if: ${{ steps.prepare-branch.outputs.HAS_CHANGES == '1' }} uses: actions/github-script@v7 with: - github-token: ${{ secrets.REPOSITORY_DISPATCH_PERSONAL_ACCESS_TOKEN }} + github-token: ${{ steps.app-token.outputs.token }} script: | await github.rest.pulls.create({ owner: 'microsoft', diff --git a/.github/workflows/roll_stable_test_runner.yml b/.github/workflows/roll_stable_test_runner.yml new file mode 100644 index 0000000000000..2c908520444d8 --- /dev/null +++ b/.github/workflows/roll_stable_test_runner.yml @@ -0,0 +1,58 @@ +name: "PR: bump stable-test-runner" +on: + workflow_dispatch: + schedule: + # At 10:00am UTC (3AM PST) every Monday + - cron: "0 10 * * 1" +jobs: + trigger-roll: + name: Trigger Roll + runs-on: ubuntu-24.04 + if: github.repository == 'microsoft/playwright' + permissions: + contents: write + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 22 + - run: | + npm install @playwright/test@next + VERSION=$(node -e "console.log(require('./package.json').dependencies['@playwright/test'].replace('^', ''))") + echo "VERSION=$VERSION" >> $GITHUB_OUTPUT + working-directory: tests/playwright-test/stable-test-runner/ + id: bump + - name: Prepare branch + id: prepare-branch + run: | + if [[ "$(git status --porcelain)" == "" ]]; then + echo "there are no changes"; + exit 0; + fi + echo "HAS_CHANGES=1" >> $GITHUB_OUTPUT + BRANCH_NAME="roll-stable-test-runner/$(date +%Y-%b-%d)" + echo "BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_OUTPUT + git config --global user.name microsoft-playwright-automation[bot] + git config --global user.email 203992400+microsoft-playwright-automation[bot]@users.noreply.github.com + git checkout -b "$BRANCH_NAME" + git add . + git commit -m "test: roll stable-test-runner to ${{ steps.bump.outputs.VERSION }}" + git push origin $BRANCH_NAME + - uses: actions/create-github-app-token@v2 + id: app-token + with: + app-id: ${{ vars.PLAYWRIGHT_APP_ID }} + private-key: ${{ secrets.PLAYWRIGHT_PRIVATE_KEY }} + - name: Create Pull Request + if: ${{ steps.prepare-branch.outputs.HAS_CHANGES == '1' }} + uses: actions/github-script@v7 + with: + github-token: ${{ steps.app-token.outputs.token }} + script: | + await github.rest.pulls.create({ + owner: 'microsoft', + repo: 'playwright', + head: 'microsoft:${{ steps.prepare-branch.outputs.BRANCH_NAME }}', + base: 'main', + title: 'test: roll stable-test-runner to ${{ steps.bump.outputs.VERSION }}', + }); diff --git a/.github/workflows/tests_bidi.yml b/.github/workflows/tests_bidi.yml new file mode 100644 index 0000000000000..4d6dc437325ce --- /dev/null +++ b/.github/workflows/tests_bidi.yml @@ -0,0 +1,80 @@ +name: tests BiDi + +on: + workflow_dispatch: + inputs: + ref: + description: Playwright SHA / ref to test. Use 'refs/pull/PULL_REQUEST_ID/head' to test a PR. Defaults to the current branch. + required: false + default: '' + pull_request: + branches: + - main + paths: + - .github/workflows/tests_bidi.yml + - packages/playwright-core/src/server/bidi/** + - tests/bidi/** + schedule: + # Run every day at midnight + - cron: '0 0 * * *' + +env: + FORCE_COLOR: 1 + +jobs: + test_bidi: + name: BiDi + environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }} + runs-on: ubuntu-24.04 + permissions: + id-token: write # This is required for OIDC login (azure/login) to succeed + contents: read # This is required for actions/checkout to succeed + strategy: + fail-fast: false + matrix: + channel: [bidi-chromium, moz-firefox-nightly] + steps: + - uses: actions/checkout@v4 + if: github.event_name != 'workflow_dispatch' + - uses: actions/checkout@v4 + if: github.event_name == 'workflow_dispatch' + with: + ref: ${{ github.event.inputs.ref }} + - uses: actions/setup-node@v4 + with: + node-version: 20 + - run: npm ci + - run: npm run build + - run: npx playwright install --with-deps chromium + if: matrix.channel == 'bidi-chromium' + - if: matrix.channel == 'moz-firefox-nightly' + run: | + echo "BIDI_FFPATH=$(npx -y @puppeteer/browsers install firefox@nightly | tail -n1 | sed 's/^[^ ]* *//')" >> "$GITHUB_ENV" + - name: Run tests + run: xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- npm run biditest -- --project=${{ matrix.channel }}* + env: + PWTEST_USE_BIDI_EXPECTATIONS: '1' + - name: Upload csv report to GitHub + if: ${{ !cancelled() }} + uses: actions/upload-artifact@v4 + with: + name: csv-report-${{ matrix.channel }} + path: test-results/report.csv + retention-days: 7 + + - name: Azure Login + if: ${{ !cancelled() && github.ref == 'refs/heads/main' }} + uses: azure/login@v2 + with: + client-id: ${{ secrets.AZURE_BLOB_REPORTS_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_BLOB_REPORTS_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_BLOB_REPORTS_SUBSCRIPTION_ID }} + + - name: Upload report.csv to Azure + if: ${{ !cancelled() && github.ref == 'refs/heads/main' }} + run: | + REPORT_DIR='bidi-reports' + azcopy cp "./test-results/report.csv" "https://mspwblobreport.blob.core.windows.net/\$web/$REPORT_DIR/${{ matrix.channel }}.csv" + echo "Report url: https://mspwblobreport.z1.web.core.windows.net/$REPORT_DIR/${{ matrix.channel }}.csv" + env: + AZCOPY_AUTO_LOGIN_TYPE: AZCLI diff --git a/.github/workflows/tests_others.yml b/.github/workflows/tests_others.yml index 783f3fe2ff800..ed18e1541c635 100644 --- a/.github/workflows/tests_others.yml +++ b/.github/workflows/tests_others.yml @@ -24,9 +24,7 @@ jobs: strategy: fail-fast: false matrix: - # Stick with macos-latest-large for now which is Intel-based until - # https://github.com/microsoft/playwright/issues/30705 is fixed. - os: [ubuntu-latest, macos-latest-large, windows-latest] + os: [ubuntu-latest, macos-latest, windows-latest] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 @@ -66,7 +64,7 @@ jobs: contents: read # This is required for actions/checkout to succeed steps: - uses: actions/checkout@v4 - - uses: actions/setup-dotnet@v3 + - uses: actions/setup-dotnet@v4 with: dotnet-version: '8.0.x' - run: dotnet build @@ -149,6 +147,13 @@ jobs: runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 + - name: Setup Ubuntu Binary Installation # TODO: Remove when https://github.com/electron/electron/issues/42510 is fixed + if: ${{ runner.os == 'Linux' }} + run: | + if grep -q "Ubuntu 24" /etc/os-release; then + sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 + fi + shell: bash - uses: ./.github/actions/run-test with: browsers-to-install: chromium diff --git a/.github/workflows/tests_primary.yml b/.github/workflows/tests_primary.yml index 02847957c4fd7..ec575d808e798 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 ELECTRON_SKIP_BINARY_DOWNLOAD: 1 + DEBUG_GIT_COMMIT_INFO: 1 jobs: test_linux: @@ -41,6 +42,9 @@ jobs: - os: ubuntu-22.04 node-version: 22 browser: chromium + - os: ubuntu-22.04 + node-version: 24 + browser: chromium runs-on: ${{ matrix.os }} permissions: id-token: write # This is required for OIDC login (azure/login) to succeed @@ -63,7 +67,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-20.04] + os: [ubuntu-22.04] runs-on: ${{ matrix.os }} permissions: id-token: write # This is required for OIDC login (azure/login) to succeed @@ -108,6 +112,14 @@ jobs: node-version: 22 shardIndex: 2 shardTotal: 2 + - os: ubuntu-latest + node-version: 24 + shardIndex: 1 + shardTotal: 2 + - os: ubuntu-latest + node-version: 24 + shardIndex: 2 + shardTotal: 2 runs-on: ${{ matrix.os }} permissions: id-token: write # This is required for OIDC login (azure/login) to succeed @@ -134,8 +146,6 @@ jobs: with: node-version: 18 - run: npm ci - env: - DEBUG: pw:install - run: npm run build - run: npx playwright install --with-deps @@ -165,6 +175,7 @@ jobs: runs-on: ubuntu-latest env: PWTEST_BOT_NAME: "vscode-extension" + DEBUG_GIT_COMMIT_INFO: "" steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -184,7 +195,7 @@ jobs: 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 + run: npm ci && npm run build working-directory: ./playwright-vscode - name: Run extension tests run: npm run test -- --workers=1 @@ -215,6 +226,13 @@ jobs: - uses: actions/checkout@v4 - run: npm install -g yarn@1 - run: npm install -g pnpm@8 + - name: Setup Ubuntu Binary Installation # TODO: Remove when https://github.com/electron/electron/issues/42510 is fixed + if: ${{ runner.os == 'Linux' }} + run: | + if grep -q "Ubuntu 24" /etc/os-release; then + sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 + fi + shell: bash - uses: ./.github/actions/run-test with: command: npm run itest diff --git a/.github/workflows/tests_secondary.yml b/.github/workflows/tests_secondary.yml index fd5458fb89f04..eafe68cd60f3e 100644 --- a/.github/workflows/tests_secondary.yml +++ b/.github/workflows/tests_secondary.yml @@ -31,7 +31,7 @@ jobs: fail-fast: false matrix: browser: [chromium, firefox, webkit] - os: [ubuntu-20.04, ubuntu-24.04] + os: [ubuntu-24.04] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 @@ -50,8 +50,15 @@ jobs: strategy: fail-fast: false matrix: - os: [macos-12, macos-13, macos-14] + # Intel: *-large + # Arm64: *-xlarge + os: [macos-13-large, macos-13-xlarge, macos-14-large, macos-14-xlarge] browser: [chromium, firefox, webkit] + include: + - os: macos-15-large + browser: webkit + - os: macos-15-xlarge + browser: webkit runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 @@ -95,11 +102,20 @@ jobs: node_version: 20 - os: ubuntu-latest node_version: 22 + - os: ubuntu-latest + node_version: 24 timeout-minutes: 30 steps: - uses: actions/checkout@v4 - run: npm install -g yarn@1 - run: npm install -g pnpm@8 + - name: Setup Ubuntu Binary Installation # TODO: Remove when https://github.com/electron/electron/issues/42510 is fixed + if: ${{ runner.os == 'Linux' }} + run: | + if grep -q "Ubuntu 24" /etc/os-release; then + sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 + fi + shell: bash - uses: ./.github/actions/run-test with: node-version: ${{ matrix.node_version }} @@ -116,7 +132,11 @@ jobs: fail-fast: false matrix: browser: [chromium, firefox, webkit] - os: [ubuntu-20.04, ubuntu-22.04, ubuntu-24.04, macos-14, windows-latest] + os: [ubuntu-24.04, macos-14-xlarge, windows-latest] + include: + # We have different binaries per Ubuntu version for WebKit. + - browser: webkit + os: ubuntu-22.04 runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 @@ -136,7 +156,7 @@ jobs: fail-fast: false matrix: mode: [driver, service] - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - uses: ./.github/actions/run-test @@ -158,11 +178,16 @@ jobs: matrix: include: - browser: chromium + runs-on: ubuntu-22.04 - browser: firefox + runs-on: ubuntu-22.04 + # See https://github.com/microsoft/playwright/issues/35586 - browser: webkit + runs-on: ubuntu-24.04 - browser: chromium + runs-on: ubuntu-22.04 channel: chromium-tip-of-tree - runs-on: ubuntu-20.04 + runs-on: ${{ matrix.runs-on }} steps: - uses: actions/checkout@v4 - uses: ./.github/actions/run-test @@ -177,359 +202,99 @@ jobs: PWTEST_TRACE: 1 PWTEST_CHANNEL: ${{ matrix.channel }} - chrome_stable_linux: - name: "Chrome Stable (Linux)" - environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }} - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v4 - - uses: ./.github/actions/run-test - with: - browsers-to-install: chrome - command: npm run ctest - bot-name: "chrome-stable-linux" - flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }} - flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }} - flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }} - env: - PWTEST_CHANNEL: chrome - - chrome_stable_win: - name: "Chrome Stable (Win)" + test_chromium_channels: + name: Test ${{ matrix.channel }} on ${{ matrix.runs-on }} environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }} - runs-on: windows-latest - steps: - - uses: actions/checkout@v4 - - uses: ./.github/actions/run-test - with: - browsers-to-install: chrome - command: npm run ctest - bot-name: "chrome-stable-windows" - flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }} - flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }} - flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }} - env: - PWTEST_CHANNEL: chrome - - chrome_stable_mac: - name: "Chrome Stable (Mac)" - environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }} - runs-on: macos-latest + runs-on: ${{ matrix.runs-on }} + strategy: + fail-fast: false + matrix: + channel: [chrome, chrome-beta, msedge, msedge-beta, msedge-dev] + runs-on: [ubuntu-22.04, macos-latest, windows-latest] steps: - uses: actions/checkout@v4 - uses: ./.github/actions/run-test with: - browsers-to-install: chrome + browsers-to-install: ${{ matrix.channel }} command: npm run ctest - bot-name: "chrome-stable-mac" + bot-name: ${{ matrix.channel }}-${{ matrix.runs-on }} flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }} flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }} flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }} env: - PWTEST_CHANNEL: chrome + PWTEST_CHANNEL: ${{ matrix.channel }} chromium_tot: - name: Chromium tip-of-tree ${{ matrix.os }} + name: Chromium tip-of-tree ${{ matrix.os }}${{ matrix.headed }} environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }} runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - os: [ubuntu-20.04, macos-12, windows-latest] + os: [ubuntu-22.04, macos-13, windows-latest] + headed: ['--headed', ''] + exclude: + # Tested in tests_primary.yml already + - os: ubuntu-22.04 + headed: '' steps: - uses: actions/checkout@v4 - uses: ./.github/actions/run-test with: browsers-to-install: chromium-tip-of-tree - command: npm run ctest - bot-name: "tip-of-tree-${{ matrix.os }}" + command: npm run ctest -- ${{ matrix.headed }} + bot-name: "chromium-tip-of-tree-${{ matrix.os }}${{ matrix.headed }}" flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }} flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }} flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }} env: PWTEST_CHANNEL: chromium-tip-of-tree - chromium_tot_headed: - name: Chromium tip-of-tree headed ${{ matrix.os }} + chromium_tot_headless_shell: + name: Chromium tip-of-tree headless-shell-${{ matrix.os }} environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }} runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - os: [ubuntu-latest, macos-latest, windows-latest] - steps: - - uses: actions/checkout@v4 - - uses: ./.github/actions/run-test - with: - browsers-to-install: chromium-tip-of-tree - command: npm run ctest -- --headed - bot-name: "tip-of-tree-headed-${{ matrix.os }}" - flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }} - flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }} - flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }} - env: - PWTEST_CHANNEL: chromium-tip-of-tree - - firefox_beta_linux: - name: "Firefox Beta (Linux)" - environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }} - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v4 - - uses: ./.github/actions/run-test - with: - browsers-to-install: firefox-beta chromium - command: npm run ftest - bot-name: "firefox-beta-linux" - flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }} - flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }} - flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }} - env: - PWTEST_CHANNEL: firefox-beta - - firefox_beta_win: - name: "Firefox Beta (Win)" - environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }} - runs-on: windows-latest + os: [ubuntu-22.04] steps: - uses: actions/checkout@v4 - uses: ./.github/actions/run-test with: - browsers-to-install: firefox-beta chromium - command: npm run ftest -- --workers=1 - bot-name: "firefox-beta-windows" + browsers-to-install: chromium-tip-of-tree-headless-shell + command: npm run ctest + bot-name: "chromium-tip-of-tree-headless-shell-${{ matrix.os }}" flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }} flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }} flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }} env: - PWTEST_CHANNEL: firefox-beta + PWTEST_CHANNEL: chromium-tip-of-tree-headless-shell - firefox_beta_mac: - name: "Firefox Beta (Mac)" + firefox_beta: + name: Firefox Beta ${{ matrix.os }} environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }} - # Stick with macos-latest-large for now which is Intel-based until - # https://github.com/microsoft/playwright/issues/30705 is fixed. - runs-on: macos-latest-large + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-22.04, windows-latest, macos-latest] steps: - uses: actions/checkout@v4 - uses: ./.github/actions/run-test with: browsers-to-install: firefox-beta chromium command: npm run ftest - bot-name: "firefox-beta-mac" + bot-name: "firefox-beta-${{ matrix.os }}" flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }} flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }} flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }} env: PWTEST_CHANNEL: firefox-beta - edge_stable_mac: - name: "Edge Stable (Mac)" - environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }} - runs-on: macos-latest - steps: - - uses: actions/checkout@v4 - - uses: ./.github/actions/run-test - with: - browsers-to-install: msedge - command: npm run ctest - bot-name: "edge-stable-mac" - flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }} - flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }} - flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }} - env: - PWTEST_CHANNEL: msedge - - edge_stable_win: - name: "Edge Stable (Win)" - environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }} - runs-on: windows-latest - steps: - - uses: actions/checkout@v4 - - uses: ./.github/actions/run-test - with: - browsers-to-install: msedge - command: npm run ctest - bot-name: "edge-stable-windows" - flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }} - flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }} - flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }} - env: - PWTEST_CHANNEL: msedge - - edge_stable_linux: - name: "Edge Stable (Linux)" - environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }} - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v4 - - uses: ./.github/actions/run-test - with: - browsers-to-install: msedge - command: npm run ctest - bot-name: "edge-stable-linux" - flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }} - flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }} - flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }} - env: - PWTEST_CHANNEL: msedge - - edge_beta_mac: - name: "Edge Beta (Mac)" - environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }} - runs-on: macos-latest - steps: - - uses: actions/checkout@v4 - - uses: ./.github/actions/run-test - with: - browsers-to-install: msedge-beta - command: npm run ctest - bot-name: "edge-beta-mac" - flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }} - flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }} - flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }} - env: - PWTEST_CHANNEL: msedge-beta - - edge_beta_win: - name: "Edge Beta (Win)" - environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }} - runs-on: windows-latest - steps: - - uses: actions/checkout@v4 - - uses: ./.github/actions/run-test - with: - browsers-to-install: msedge-beta - command: npm run ctest - bot-name: "edge-beta-windows" - flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }} - flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }} - flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }} - env: - PWTEST_CHANNEL: msedge-beta - - edge_beta_linux: - name: "Edge Beta (Linux)" - environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }} - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v4 - - uses: ./.github/actions/run-test - with: - browsers-to-install: msedge-beta - command: npm run ctest - bot-name: "edge-beta-linux" - flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }} - flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }} - flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }} - env: - PWTEST_CHANNEL: msedge-beta - - edge_dev_mac: - name: "Edge Dev (Mac)" - environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }} - runs-on: macos-latest - steps: - - uses: actions/checkout@v4 - - uses: ./.github/actions/run-test - with: - browsers-to-install: msedge-dev - command: npm run ctest - bot-name: "edge-dev-mac" - flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }} - flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }} - flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }} - env: - PWTEST_CHANNEL: msedge-dev - - edge_dev_win: - name: "Edge Dev (Win)" - environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }} - runs-on: windows-latest - steps: - - uses: actions/checkout@v4 - - uses: ./.github/actions/run-test - with: - browsers-to-install: msedge-dev - command: npm run ctest - bot-name: "edge-dev-windows" - flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }} - flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }} - flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }} - env: - PWTEST_CHANNEL: msedge-dev - - edge_dev_linux: - name: "Edge Dev (Linux)" - environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }} - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v4 - - uses: ./.github/actions/run-test - with: - browsers-to-install: msedge-dev - command: npm run ctest - bot-name: "edge-dev-linux" - flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }} - flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }} - flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }} - env: - PWTEST_CHANNEL: msedge-dev - - chrome_beta_linux: - name: "Chrome Beta (Linux)" - environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }} - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v4 - - uses: ./.github/actions/run-test - with: - browsers-to-install: chrome-beta - command: npm run ctest - bot-name: "chrome-beta-linux" - flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }} - flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }} - flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }} - env: - PWTEST_CHANNEL: chrome-beta - - chrome_beta_win: - name: "Chrome Beta (Win)" - environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }} - runs-on: windows-latest - steps: - - uses: actions/checkout@v4 - - uses: ./.github/actions/run-test - with: - browsers-to-install: chrome-beta - command: npm run ctest - bot-name: "chrome-beta-windows" - flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }} - flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }} - flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }} - env: - PWTEST_CHANNEL: chrome-beta - - chrome_beta_mac: - name: "Chrome Beta (Mac)" - environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }} - runs-on: macos-latest - steps: - - uses: actions/checkout@v4 - - uses: ./.github/actions/run-test - with: - browsers-to-install: chrome-beta - command: npm run ctest - bot-name: "chrome-beta-mac" - flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }} - flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }} - flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }} - env: - PWTEST_CHANNEL: chrome-beta - build-playwright-driver: name: "build-playwright-driver" - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -537,22 +302,27 @@ jobs: node-version: 18 - 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 + test_channel_chromium: + name: Test channel=chromium environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }} - runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + runs-on: [ubuntu-latest, windows-latest, macos-latest] + runs-on: ${{ matrix.runs-on }} steps: - uses: actions/checkout@v4 - uses: ./.github/actions/run-test with: + # TODO: this should pass --no-shell. + # However, codegen tests do not inherit the channel and try to launch headless shell. browsers-to-install: chromium command: npm run ctest - bot-name: "headless-new" + bot-name: "channel-chromium-${{ matrix.runs-on }}" flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }} flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }} flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }} env: - PLAYWRIGHT_CHROMIUM_USE_HEADLESS_NEW: 1 + PWTEST_CHANNEL: chromium diff --git a/.github/workflows/tests_service.yml b/.github/workflows/tests_service.yml deleted file mode 100644 index 2739680712d66..0000000000000 --- a/.github/workflows/tests_service.yml +++ /dev/null @@ -1,70 +0,0 @@ -name: "tests service" - -on: - workflow_dispatch: - -env: - FORCE_COLOR: 1 - ELECTRON_SKIP_BINARY_DOWNLOAD: 1 - -jobs: - test: - name: "Service" - strategy: - fail-fast: false - matrix: - service-os: [linux, windows] - browser: [chromium, firefox, webkit] - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - - run: npm ci - env: - PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 - - run: npm run build - - run: xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- npm run test -- --project=${{ matrix.browser }}-* --workers=10 --retries=0 - env: - PWTEST_MODE: service2 - PWTEST_TRACE: 1 - PWTEST_BOT_NAME: "${{ matrix.browser }}-${{ matrix.service-os }}-service" - PLAYWRIGHT_SERVICE_ACCESS_KEY: ${{ secrets.PLAYWRIGHT_SERVICE_ACCESS_KEY }} - PLAYWRIGHT_SERVICE_URL: ${{ secrets.PLAYWRIGHT_SERVICE_URL }} - PLAYWRIGHT_SERVICE_OS: ${{ matrix.service-os }} - PLAYWRIGHT_SERVICE_RUN_ID: ${{ github.run_id }}-${{ github.run_attempt }}-${{ github.sha }} - - name: Upload blob report to GitHub - if: ${{ !cancelled() }} - uses: actions/upload-artifact@v3 - with: - name: all-blob-reports - path: blob-report - retention-days: 2 - - merge_reports: - name: "Merge reports" - needs: [test] - if: ${{ !cancelled() }} - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - - run: npm ci - env: - PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 - - run: npm run build - - name: Download blob report artifact - uses: actions/download-artifact@v3 - with: - name: all-blob-reports - path: all-blob-reports - - run: npx playwright merge-reports --reporter markdown,html ./all-blob-reports - - name: Upload HTML report to Azure - run: | - REPORT_DIR='run-service-${{ github.run_id }}-${{ github.run_attempt }}-${{ github.sha }}' - azcopy cp --recursive "./playwright-report/*" "https://mspwblobreport.blob.core.windows.net/\$web/$REPORT_DIR" - echo "Report url: https://mspwblobreport.z1.web.core.windows.net/$REPORT_DIR/index.html#?q=s:failed" - env: - AZCOPY_AUTO_LOGIN_TYPE: SPN - AZCOPY_SPA_APPLICATION_ID: '${{ secrets.AZCOPY_SPA_APPLICATION_ID }}' - AZCOPY_SPA_CLIENT_SECRET: '${{ secrets.AZCOPY_SPA_CLIENT_SECRET }}' - AZCOPY_TENANT_ID: '${{ secrets.AZCOPY_TENANT_ID }}' diff --git a/.github/workflows/tests_video.yml b/.github/workflows/tests_video.yml index 0733b082a0818..cc303d79c5aae 100644 --- a/.github/workflows/tests_video.yml +++ b/.github/workflows/tests_video.yml @@ -19,7 +19,7 @@ jobs: fail-fast: false matrix: browser: [chromium, firefox, webkit] - os: [ubuntu-20.04, ubuntu-22.04] + os: [ubuntu-22.04, ubuntu-24.04] permissions: id-token: write # This is required for OIDC login (azure/login) to succeed contents: read # This is required for actions/checkout to succeed diff --git a/.github/workflows/trigger_tests.yml b/.github/workflows/trigger_tests.yml index dcd68dca37440..69a3d5f21b4e7 100644 --- a/.github/workflows/trigger_tests.yml +++ b/.github/workflows/trigger_tests.yml @@ -9,8 +9,14 @@ on: jobs: trigger: name: "trigger" - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 steps: + - uses: actions/create-github-app-token@v2 + id: app-token + with: + app-id: ${{ vars.PLAYWRIGHT_APP_ID }} + private-key: ${{ secrets.PLAYWRIGHT_PRIVATE_KEY }} + repositories: playwright-browsers - run: | curl -X POST \ -H "Accept: application/vnd.github.v3+json" \ @@ -18,4 +24,4 @@ jobs: --data "{\"event_type\": \"playwright_tests\", \"client_payload\": {\"ref\": \"${GITHUB_SHA}\"}}" \ https://api.github.com/repos/microsoft/playwright-browsers/dispatches env: - GH_TOKEN: ${{ secrets.REPOSITORY_DISPATCH_PERSONAL_ACCESS_TOKEN }} + GH_TOKEN: ${{ steps.app-token.outputs.token }} diff --git a/.gitignore b/.gitignore index 69d85e4975adc..8e41e318108ae 100644 --- a/.gitignore +++ b/.gitignore @@ -33,4 +33,6 @@ test-results /tests/installation/output/ /tests/installation/.registry.json .cache/ -.eslintcache \ No newline at end of file +.eslintcache +playwright.env +/firefox/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 30e89e6beef6f..a945d57263589 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,92 +1,92 @@ # Contributing -- [How to Contribute](#how-to-contribute) - * [Getting Code](#getting-code) - * [Code reviews](#code-reviews) - * [Code Style](#code-style) - * [API guidelines](#api-guidelines) - * [Commit Messages](#commit-messages) - * [Writing Documentation](#writing-documentation) - * [Adding New Dependencies](#adding-new-dependencies) - * [Running & Writing Tests](#running--writing-tests) - * [Public API Coverage](#public-api-coverage) -- [Contributor License Agreement](#contributor-license-agreement) - * [Code of Conduct](#code-of-conduct) +## Choose an issue -## How to Contribute +Playwright **requires an issue** for every contribution, except for minor documentation updates. We strongly recommend +to pick an issue +labeled [open-to-a-pull-request](https://github.com/microsoft/playwright/issues?q=is%3Aissue%20state%3Aopen%20label%3Aopen-to-a-pull-request) +for your first contribution to the project. -We strongly recommend that you open an issue before beginning any code modifications. This is particularly important if the changes involve complex logic or if the existing code isn't immediately clear. By doing so, we can discuss and agree upon the best approach to address a bug or implement a feature, ensuring that our efforts are aligned. +If you are passionate about a bug/feature, but cannot find an issue describing it, **file an issue first**. This will +facilitate the discussion, and you might get some early feedback from project maintainers before spending your time on +creating a pull request. -### Getting Code - -Make sure you're running Node.js 20 to verify and upgrade NPM do: +## Make a change +Make sure you're running Node.js 20 or later. ```bash node --version -npm --version -npm i -g npm@latest ``` -1. Clone this repository - +Clone the repository. If you plan to send a pull request, it might be better to [fork the repository](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/fork-a-repo) first. ```bash git clone https://github.com/microsoft/playwright cd playwright ``` -2. Install dependencies - +Install dependencies and run the build in watch mode. ```bash npm ci +npm run watch +npx playwright install ``` -3. Build Playwright +**Experimental dev mode with Hot Module Replacement for recorder/trace-viewer/UI Mode** -```bash -npm run build +``` +PW_HMR=1 npm run watch +PW_HMR=1 npx playwright show-trace +PW_HMR=1 npm run ctest -- --ui +PW_HMR=1 npx playwright codegen +PW_HMR=1 npx playwright show-report ``` -4. Run tests +Playwright is a multi-package repository that uses npm workspaces. For browser APIs, look at [`packages/playwright-core`](https://github.com/microsoft/playwright/blob/main/packages/playwright-core). For test runner, see [`packages/playwright`](https://github.com/microsoft/playwright/blob/main/packages/playwright). -This will run a test on line `23` in `page-fill.spec.ts`: +Note that some files are generated by the build, so the watch process might override your changes if done in the wrong file. For example, TypeScript types for the API are generated from the [`docs/src`](https://github.com/microsoft/playwright/blob/main/docs/src). -```bash -npm run ctest -- page-fill:23 -``` +Coding style is fully defined in [eslint.config.mjs](https://github.com/microsoft/playwright/blob/main/eslint.config.mjs). Before creating a pull request, or at any moment during development, run linter to check all kinds of things: + ```bash + npm run lint + ``` -See [here](#running--writing-tests) for more information about running and writing tests. +Comments should have an explicit purpose and should improve readability rather than hinder it. If the code would not be understood without comments, consider re-writing the code to make it self-explanatory. -### Code reviews +### Write documentation -All submissions, including submissions by project members, require review. We -use GitHub pull requests for this purpose. Consult -[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more -information on using pull requests. +Every part of the public API should be documented in [`docs/src`](https://github.com/microsoft/playwright/blob/main/docs/src), in the same change that adds/changes the API. We use markdown files with custom structure to specify the API. Take a look around for an example. -### Code Style +Various other files are generated from the API specification. If you are running `npm run watch`, these will be re-generated automatically. -- Coding style is fully defined in [.eslintrc](https://github.com/microsoft/playwright/blob/main/.eslintrc.js) -- Comments should be generally avoided. If the code would not be understood without comments, consider re-writing the code to make it self-explanatory. +Larger changes will require updates to the documentation guides as well. This will be made clear during the code review. -To run code linter, use: +## Add a test -```bash -npm run eslint -``` +Playwright requires a test for almost any new or modified functionality. An exception would be a pure refactoring, but chances are you are doing more than that. + +There are multiple [test suites](https://github.com/microsoft/playwright/blob/main/tests) in Playwright that will be executed on the CI. The two most important that you need to run locally are: -### API guidelines +- Library tests cover APIs not related to the test runner. + ```bash + # fast path runs all tests in Chromium + npm run ctest -When authoring new API methods, consider the following: + # slow path runs all tests in three browsers + npm run test + ``` -- Expose as little information as needed. When in doubt, don’t expose new information. -- Methods are used in favor of getters/setters. - - The only exception is namespaces, e.g. `page.keyboard` and `page.coverage` -- All string literals must be lowercase. This includes event names and option values. -- Avoid adding "sugar" API (API that is trivially implementable in user-space) unless they're **very** common. +- Test runner tests. + ```bash + npm run ttest + ``` -### Commit Messages +Since Playwright tests are using Playwright under the hood, everything from our documentation applies, for example [this guide on running and debugging tests](https://playwright.dev/docs/running-tests#running-tests). -Commit messages should follow the Semantic Commit Messages format: +Note that tests should be *hermetic*, and not depend on external services. Tests should work on all three platforms: macOS, Linux and Windows. + +## Write a commit message + +Commit messages should follow the [Semantic Commit Messages](https://www.conventionalcommits.org/en/v1.0.0/) format: ``` label(namespace): title @@ -97,129 +97,59 @@ footer ``` 1. *label* is one of the following: - - `fix` - playwright bug fixes. - - `feat` - playwright features. - - `docs` - changes to docs, e.g. `docs(api): ..` to change documentation. - - `test` - changes to playwright tests infrastructure. - - `devops` - build-related work, e.g. CI related patches and general changes to the browser build infrastructure + - `fix` - bug fixes + - `feat` - new features + - `docs` - documentation-only changes + - `test` - test-only changes + - `devops` - changes to the CI or build - `chore` - everything that doesn't fall under previous categories -2. *namespace* is put in parenthesis after label and is optional. Must be lowercase. +2. *namespace* is put in parentheses after label and is optional. Must be lowercase. 3. *title* is a brief summary of changes. 4. *description* is **optional**, new-line separated from title and is in present tense. -5. *footer* is **optional**, new-line separated from *description* and contains "fixes" / "references" attribution to github issues. +5. *footer* is **optional**, new-line separated from *description* and contains "fixes" / "references" attribution to GitHub issues. Example: ``` -fix(firefox): make sure session cookies work - -This patch fixes session cookies in the firefox browser. - -Fixes #123, fixes #234 -``` - -### Writing Documentation - -All API classes, methods, and events should have a description in [`docs/src`](https://github.com/microsoft/playwright/blob/main/docs/src). There's a [documentation linter](https://github.com/microsoft/playwright/tree/main/utils/doclint) which makes sure documentation is aligned with the codebase. - -To run the documentation linter, use: - -```bash -npm run doc -``` - -To build the documentation site locally and test how your changes will look in practice: - -1. Clone the [microsoft/playwright.dev](https://github.com/microsoft/playwright.dev) repo -1. Follow [the playwright.dev README instructions to "roll docs"](https://github.com/microsoft/playwright.dev/#roll-docs) against your local `playwright` repo with your changes in progress -1. Follow [the playwright.dev README instructions to "run dev server"](https://github.com/microsoft/playwright.dev/#run-dev-server) to view your changes - -### Adding New Dependencies - -For all dependencies (both installation and development): -- **Do not add** a dependency if the desired functionality is easily implementable. -- If adding a dependency, it should be well-maintained and trustworthy. - -A barrier for introducing new installation dependencies is especially high: -- **Do not add** installation dependency unless it's critical to project success. - -### Running & Writing Tests - -- Every feature should be accompanied by a test. -- Every public api event/method should be accompanied by a test. -- Tests should be *hermetic*. Tests should not depend on external services. -- Tests should work on all three platforms: Mac, Linux and Win. This is especially important for screenshot tests. - -Playwright tests are located in [`tests`](https://github.com/microsoft/playwright/blob/main/tests) and use `@playwright/test` test runner. -These are integration tests, making sure public API methods and events work as expected. - -- To run all tests: - -```bash -npx playwright install -npm run test -``` +feat(trace viewer): network panel filtering -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. +This patch adds a filtering toolbar to the network panel. + -- To run tests in Chromium -```bash -npm run ctest # also `ftest` for firefox and `wtest` for WebKit -npm run ctest -- page-fill:23 # runs line 23 of page-fill.spec.ts +Fixes #123, references #234. ``` -To run tests in WebKit / Firefox, use `wtest` or `ftest`. +## Send a pull request -- To run the Playwright test runner tests -```bash -npm run ttest -npm run ttest -- --grep "specific test" -``` +All submissions, including submissions by project members, require review. We use GitHub pull requests for this purpose. +Make sure to keep your PR (diff) small and readable. If necessary, split your contribution into multiple PRs. +Consult [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more information on using pull requests. -- To run a specific test, substitute `it` with `it.only`, or use the `--grep 'My test'` CLI parameter: - -```js -... -// Using "it.only" to run a specific test -it.only('should work', async ({server, page}) => { - const response = await page.goto(server.EMPTY_PAGE); - expect(response.ok).toBe(true); -}); -// or -playwright test --config=xxx --grep 'should work' -``` +After a successful code review, one of the maintainers will merge your pull request. Congratulations! -- To disable a specific test, substitute `it` with `it.skip`: +## More details -```js -... -// Using "it.skip" to skip a specific test -it.skip('should work', async ({server, page}) => { - const response = await page.goto(server.EMPTY_PAGE); - expect(response.ok).toBe(true); -}); -``` +**No new dependencies** -- To run tests in non-headless (headed) mode: +There is a very high bar for new dependencies, including updating to a new version of an existing dependency. We recommend to explicitly discuss this in an issue and get a green light from a maintainer, before creating a pull request that updates dependencies. -```bash -npm run ctest -- --headed -``` - -- To run tests with custom browser executable, specify `CRPATH`, `WKPATH` or `FFPATH` env variable that points to browser executable: +**Custom browser build** +To run tests with custom browser executable, specify `CRPATH`, `WKPATH` or `FFPATH` env variable that points to browser executable: ```bash CRPATH= npm run ctest ``` -- When should a test be marked with `skip` or `fixme`? +You will also find `DEBUG=pw:browser` useful for debugging custom-builds. + +**Building documentation site** - - **`skip(condition)`**: This test *should ***never*** work* for `condition` - where `condition` is usually something like: `test.skip(browserName === 'chromium', 'This does not work because of ...')`. +The [playwright.dev](https://playwright.dev/) documentation site lives in a separate repository, and documentation from [`docs/src`](https://github.com/microsoft/playwright/blob/main/docs/src) is frequently rolled there. - - **`fixme(condition)`**: This test *should ***eventually*** work* for `condition` - where `condition` is usually something like: `test.fixme(browserName === 'chromium', 'We are waiting for version x')`. +Most of the time this should not concern you. However, if you are doing something unusual in the docs, you can build locally and test how your changes will look in practice: +1. Clone the [microsoft/playwright.dev](https://github.com/microsoft/playwright.dev) repo. +1. Follow [the playwright.dev README instructions to "roll docs"](https://github.com/microsoft/playwright.dev/#roll-docs) against your local `playwright` repo with your changes in progress. +1. Follow [the playwright.dev README instructions to "run dev server"](https://github.com/microsoft/playwright.dev/#run-dev-server) to view your changes. ## Contributor License Agreement diff --git a/FILING_ISSUES.md b/FILING_ISSUES.md new file mode 100644 index 0000000000000..b699cd2e50440 --- /dev/null +++ b/FILING_ISSUES.md @@ -0,0 +1,35 @@ +# How to File a Bug Report That Actually Gets Resolved + +Make sure you’re on the latest Playwright release before filing. Check existing GitHub issues to avoid duplicates. + +## Use the Template + +Follow the **Bug Report** template. It guides you step-by-step: + +- Fill it out thoroughly. +- Clearly list the steps needed to reproduce the bug. +- Provide what you expected to see versus what happened in reality. +- Include system info from `npx envinfo --preset playwright`. + +## Keep Your Repro Minimal + +We can't parse your entire code base. Reduce it down to the absolute essentials: + +- Start a fresh project (`npm init playwright@latest new-project`). +- Add only the code/DOM needed to show the problem. +- Only use major frameworks if necessary (React, Angular, static HTTP server, etc.). +- Avoid adding extra libraries unless absolutely necessary. Note that we won't install any suspect dependencies. + +## Why This Matters +- Most issues that lack a repro turn out to be misconfigurations or usage errors. +- We can't fix problems if we can’t reproduce them ourselves. +- We can’t debug entire private projects or handle sensitive credentials. +- Each confirmed bug will have a test in our repo, so your repro must be as clean as possible. + +## More Help + +- [Stack Overflow’s Minimal Reproducible Example Guide](https://stackoverflow.com/help/minimal-reproducible-example) +- [Playwright Debugging Tools](https://playwright.dev/docs/debug) + +## Bottom Line +A well-isolated bug speeds up verification and resolution. Minimal, public repro or it’s unlikely we can assist. diff --git a/README.md b/README.md index 3e2add10dcaeb..445b4613e4944 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # 🎭 Playwright -[![npm version](https://img.shields.io/npm/v/playwright.svg)](https://www.npmjs.com/package/playwright) [![Chromium version](https://img.shields.io/badge/chromium-128.0.6613.7-blue.svg?logo=google-chrome)](https://www.chromium.org/Home) [![Firefox version](https://img.shields.io/badge/firefox-128.0-blue.svg?logo=firefoxbrowser)](https://www.mozilla.org/en-US/firefox/new/) [![WebKit version](https://img.shields.io/badge/webkit-18.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-140.0.7339.186-blue.svg?logo=google-chrome)](https://www.chromium.org/Home) [![Firefox version](https://img.shields.io/badge/firefox-141.0-blue.svg?logo=firefoxbrowser)](https://www.mozilla.org/en-US/firefox/new/) [![WebKit version](https://img.shields.io/badge/webkit-26.0-blue.svg?logo=safari)](https://webkit.org/) [![Join Discord](https://img.shields.io/badge/join-discord-informational)](https://aka.ms/playwright/discord) ## [Documentation](https://playwright.dev) | [API reference](https://playwright.dev/docs/api/class-playwright) @@ -8,9 +8,9 @@ Playwright is a framework for Web Testing and Automation. It allows testing [Chr | | Linux | macOS | Windows | | :--- | :---: | :---: | :---: | -| Chromium 128.0.6613.7 | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| WebKit 18.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| Firefox 128.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| Chromium 140.0.7339.186 | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| WebKit 26.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| Firefox 141.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: | Headless execution is supported for all browsers on all platforms. Check out [system requirements](https://playwright.dev/docs/intro#system-requirements) for details. @@ -46,7 +46,6 @@ npx playwright install You can optionally install only selected browsers, see [install browsers](https://playwright.dev/docs/cli#install-browsers) for more details. Or you can install no browsers at all and use existing [browser channels](https://playwright.dev/docs/browsers). * [Getting started](https://playwright.dev/docs/intro) -* [Installation configuration](https://playwright.dev/docs/installation) * [API reference](https://playwright.dev/docs/api/class-playwright) ## Capabilities @@ -163,7 +162,7 @@ test('Intercept network requests', async ({ page }) => { ## Resources -* [Documentation](https://playwright.dev/docs/intro) +* [Documentation](https://playwright.dev) * [API reference](https://playwright.dev/docs/api/class-playwright/) * [Contribution guide](CONTRIBUTING.md) * [Changelog](https://github.com/microsoft/playwright/releases) diff --git a/SUPPORT.md b/SUPPORT.md new file mode 100644 index 0000000000000..78cb929fb1bd4 --- /dev/null +++ b/SUPPORT.md @@ -0,0 +1,17 @@ +# Support + +## How to file issues and get help + +This project uses GitHub issues to track bugs and feature requests. Please search the [existing issues][gh-issues] before filing new ones to avoid duplicates. For new issues, file your bug or feature request as a new issue using corresponding template. + +For help and questions about using this project, please see the [docs site for Playwright][docs]. + +Join our community [Discord Server][discord-server] to connect with other developers using Playwright and ask questions in our 'help-playwright' forum. + +## Microsoft Support Policy + +Support for Playwright is limited to the resources listed above. + +[gh-issues]: https://github.com/microsoft/playwright/issues/ +[docs]: https://playwright.dev/ +[discord-server]: https://aka.ms/playwright/discord diff --git a/babel.config.json b/babel.config.json deleted file mode 100644 index 3e345f427474a..0000000000000 --- a/babel.config.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "assumptions": { - "setPublicClassFields": true - }, - "plugins": [ - ["@babel/plugin-transform-typescript", { "allowDeclareFields": true } ], - "@babel/plugin-transform-export-namespace-from", - "@babel/plugin-transform-class-properties", - "@babel/plugin-transform-logical-assignment-operators", - "@babel/plugin-transform-nullish-coalescing-operator", - "@babel/plugin-transform-optional-chaining", - "@babel/plugin-transform-modules-commonjs" - ], - "ignore": [ - "**/*.d.ts" - ] -} diff --git a/browser_patches/firefox/UPSTREAM_CONFIG.sh b/browser_patches/firefox/UPSTREAM_CONFIG.sh index 10889141a731d..0513b8920832a 100644 --- a/browser_patches/firefox/UPSTREAM_CONFIG.sh +++ b/browser_patches/firefox/UPSTREAM_CONFIG.sh @@ -1,3 +1,3 @@ -REMOTE_URL="https://github.com/mozilla/gecko-dev" +REMOTE_URL="https://github.com/mozilla-firefox/firefox" BASE_BRANCH="release" -BASE_REVISION="bd7e0ac24a6fb1cddde3e45ea191b7abcc90cf56" +BASE_REVISION="00656c9425c51ee035578ca6ebebe13c755b0375" diff --git a/browser_patches/firefox/juggler/Helper.js b/browser_patches/firefox/juggler/Helper.js index f5a64d6c8bc33..875dd5ac2e8b3 100644 --- a/browser_patches/firefox/juggler/Helper.js +++ b/browser_patches/firefox/juggler/Helper.js @@ -4,9 +4,9 @@ const uuidGen = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator); -class Helper { +export class Helper { decorateAsEventEmitter(objectToDecorate) { - const { EventEmitter } = ChromeUtils.import('resource://gre/modules/EventEmitter.jsm'); + const { EventEmitter } = ChromeUtils.importESModule('resource://gre/modules/EventEmitter.sys.mjs'); const emitter = new EventEmitter(); objectToDecorate.on = emitter.on.bind(emitter); objectToDecorate.addEventListener = emitter.on.bind(emitter); @@ -172,7 +172,7 @@ class Helper { const helper = new Helper(); -class EventWatcher { +export class EventWatcher { constructor(receiver, eventNames, pendingEventWatchers = new Set()) { this._pendingEventWatchers = pendingEventWatchers; this._pendingEventWatchers.add(this); @@ -233,7 +233,3 @@ class EventWatcher { } } -var EXPORTED_SYMBOLS = [ "Helper", "EventWatcher" ]; -this.Helper = Helper; -this.EventWatcher = EventWatcher; - diff --git a/browser_patches/firefox/juggler/JugglerFrameParent.jsm b/browser_patches/firefox/juggler/JugglerFrameParent.jsm index e621fab240680..9c3b58898955e 100644 --- a/browser_patches/firefox/juggler/JugglerFrameParent.jsm +++ b/browser_patches/firefox/juggler/JugglerFrameParent.jsm @@ -1,13 +1,11 @@ "use strict"; -const { TargetRegistry } = ChromeUtils.import('chrome://juggler/content/TargetRegistry.js'); -const { Helper } = ChromeUtils.import('chrome://juggler/content/Helper.js'); +const { TargetRegistry } = ChromeUtils.importESModule('chrome://juggler/content/TargetRegistry.js'); +const { Helper } = ChromeUtils.importESModule('chrome://juggler/content/Helper.js'); const helper = new Helper(); -var EXPORTED_SYMBOLS = ['JugglerFrameParent']; - -class JugglerFrameParent extends JSWindowActorParent { +export class JugglerFrameParent extends JSWindowActorParent { constructor() { super(); } diff --git a/browser_patches/firefox/juggler/NetworkObserver.js b/browser_patches/firefox/juggler/NetworkObserver.js index 8eb69d813360e..c063e0484d71b 100644 --- a/browser_patches/firefox/juggler/NetworkObserver.js +++ b/browser_patches/firefox/juggler/NetworkObserver.js @@ -4,9 +4,9 @@ "use strict"; -const {Helper} = ChromeUtils.import('chrome://juggler/content/Helper.js'); -const {NetUtil} = ChromeUtils.import('resource://gre/modules/NetUtil.jsm'); -const { ChannelEventSinkFactory } = ChromeUtils.import("chrome://remote/content/cdp/observers/ChannelEventSink.jsm"); +const {Helper} = ChromeUtils.importESModule('chrome://juggler/content/Helper.js'); +const {NetUtil} = ChromeUtils.importESModule('resource://gre/modules/NetUtil.sys.mjs'); +const { ChannelEventSinkFactory } = ChromeUtils.importESModule("chrome://remote/content/cdp/observers/ChannelEventSink.sys.mjs"); const Cc = Components.classes; @@ -28,7 +28,7 @@ const MAX_RESPONSE_STORAGE_SIZE = 100 * 1024 * 1024; const pageNetworkSymbol = Symbol('PageNetwork'); -class PageNetwork { +export class PageNetwork { static forPageTarget(target) { if (!target) return undefined; @@ -143,12 +143,16 @@ class NetworkRequest { const target = this._networkObserver._targetRegistry.targetForBrowserId(browsingContext.browserId); this._pageNetwork = PageNetwork.forPageTarget(target); } - this._expectingInterception = false; + this._shouldYieldInterceptionToServiceWorker = false; this._expectingResumedRequest = undefined; // { method, headers, postData } + this._overriddenHeadersForRedirect = redirectedFrom?._overriddenHeadersForRedirect; + this._sentOnRequest = false; this._sentOnResponse = false; this._fulfilled = false; - if (this._pageNetwork) + if (this._overriddenHeadersForRedirect) + overrideRequestHeaders(httpChannel, this._overriddenHeadersForRedirect); + else if (this._pageNetwork) appendExtraHTTPHeaders(httpChannel, this._pageNetwork.combinedExtraHTTPHeaders()); this._responseBodyChunks = []; @@ -201,11 +205,13 @@ class NetworkRequest { 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); + for (const cookieString of header.value.split('\n')) + Services.cookies.setCookieStringFromHttp(this.httpChannel.URI, cookieString, this.httpChannel); } } const synthesized = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(Ci.nsIStringInputStream); - synthesized.data = base64body ? atob(base64body) : ''; + if (base64body) + synthesized.setByteStringData(atob(base64body)); this._interceptedChannel.startSynthesizedResponse(synthesized, null, null, '', false); this._interceptedChannel.finishSynthesizedResponse(); this._interceptedChannel = undefined; @@ -230,20 +236,13 @@ class NetworkRequest { if (!this._expectingResumedRequest) return; const { method, headers, postData } = this._expectingResumedRequest; + this._overriddenHeadersForRedirect = headers; this._expectingResumedRequest = undefined; - if (headers) { - for (const header of requestHeaders(this.httpChannel)) { - // We cannot remove the "host" header. - if (header.name.toLowerCase() === 'host') - continue; - 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) { + if (headers) + overrideRequestHeaders(this.httpChannel, headers); + else if (this._pageNetwork) appendExtraHTTPHeaders(this.httpChannel, this._pageNetwork.combinedExtraHTTPHeaders()); - } if (method) this.httpChannel.requestMethod = method; if (postData !== undefined) @@ -320,9 +319,8 @@ class NetworkRequest { 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); + // and yield interception to it. + this._shouldYieldInterceptionToServiceWorker = true; return true; } @@ -331,12 +329,6 @@ class NetworkRequest { 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. @@ -344,21 +336,24 @@ class NetworkRequest { 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); + // Yield to a service worker if determined so in shouldPrepareForIntercept(). + const serviceWorker = this._shouldYieldInterceptionToServiceWorker ? this._fallThroughInterceptController() : undefined; + // Clear the flag to avoid an infinite loop. After service worker, we should intercept ourselves. + this._shouldYieldInterceptionToServiceWorker = false; + + if (serviceWorker) { + const interceptedChannel = intercepted.QueryInterface(Ci.nsIInterceptedChannel); + // If service worker will not actually intercept the request, we want to be called again. + interceptedChannel.interceptAfterServiceWorkerResets(); + serviceWorker.channelIntercepted(intercepted); return; } - this._expectingInterception = false; this._interceptedChannel = intercepted.QueryInterface(Ci.nsIInterceptedChannel); const pageNetwork = this._pageNetwork; @@ -412,6 +407,7 @@ class NetworkRequest { // See https://github.com/microsoft/playwright/issues/9418#issuecomment-944836244 if (aRequest !== this.httpChannel) return; + this._sendOnRequest(false); try { this._originalListener.onStartRequest(aRequest); } catch (e) { @@ -449,6 +445,10 @@ class NetworkRequest { } _shouldIntercept() { + // We do not want to intercept any redirects, because we are not able + // to intercept subresource redirects, and it's unreliable for main requests. + if (this.redirectedFromId) + return false; const pageNetwork = this._pageNetwork; if (!pageNetwork) return false; @@ -469,8 +469,15 @@ class NetworkRequest { } _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. + if (this._sentOnRequest) { + // We can come here twice because: + // - Redirects call _sendOnRequest in the constructor and from inside interception. + // - All other requests might call _sendOnRequest from onStartRequest and from inside interception. + // - All requests call _sendOnRequest from _sendOnResponse to avoid responses without requests. + return; + } + this._sentOnRequest = true; + const pageNetwork = this._pageNetwork; if (!pageNetwork) return; @@ -493,11 +500,21 @@ class NetworkRequest { } _sendOnResponse(fromCache, opt_statusCode, opt_statusText) { + // For internal redirects, and perhaps something else that we lack test coverage for, + // we can arrive here before onStartRequest has fired. Make sure we + // notify about the request first. + this._sendOnRequest(false); + if (this._sentOnResponse) { - // We can come here twice because of internal redirects, e.g. service workers. + // We can come here twice because of an internal redirect, for example: + // - request was intercepted by a service worker; + // - HSTS redirect; + // - CORS preflight; + // - who knows what else? return; } this._sentOnResponse = true; + const pageNetwork = this._pageNetwork; if (!pageNetwork) return; @@ -516,6 +533,8 @@ class NetworkRequest { }; const { status, statusText, headers } = responseHead(this.httpChannel, opt_statusCode, opt_statusText); + if (redirectStatus.includes(status) && this._overriddenHeadersForRedirect) + this._overriddenHeadersForRedirect = filterHeadersForRedirect(this._overriddenHeadersForRedirect, this.httpChannel.requestMethod, status); let remoteIPAddress = undefined; let remotePort = undefined; try { @@ -578,7 +597,7 @@ class NetworkRequest { } } -class NetworkObserver { +export class NetworkObserver { static instance() { return NetworkObserver._instance || null; } @@ -602,6 +621,8 @@ class NetworkObserver { proxyFilter.onProxyFilterResult(defaultProxyInfo); return; } + if (this._targetRegistry.shouldBustHTTPAuthCacheForProxy(proxy)) + Services.obs.notifyObservers(null, "net:clear-active-logins"); proxyFilter.onProxyFilterResult(protocolProxyService.newProxyInfo( proxy.type, proxy.host, @@ -771,6 +792,36 @@ function requestHeaders(httpChannel) { return headers; } +function clearRequestHeaders(httpChannel) { + for (const header of requestHeaders(httpChannel)) { + // We cannot remove the "host" header. + if (header.name.toLowerCase() === 'host') + continue; + // Keep the "cookie" header. If there is an override, it will be set anyway. + // Otherwise, we may delete a cookie that was set for a redirect. + if (header.name.toLowerCase() === 'cookie') + continue; + httpChannel.setRequestHeader(header.name, '', false /* merge */); + } +} + +function overrideRequestHeaders(httpChannel, headers) { + clearRequestHeaders(httpChannel); + appendExtraHTTPHeaders(httpChannel, headers); +} + +const redirectStatus = [301, 302, 303, 307, 308]; + +function filterHeadersForRedirect(headers, requestMethod, status) { + // HTTP-redirect fetch step 13 (https://fetch.spec.whatwg.org/#http-redirect-fetch) + if ((status === 301 || status === 302) && requestMethod === 'POST' || + status === 303 && !['GET', 'HEAD'].includes(requestMethod)) { + const requestBodyHeaders = ['content-encoding', 'content-language', 'content-length', 'content-location', 'content-type']; + return headers.filter(header => !requestBodyHeaders.includes(header.name.toLowerCase())); + } + return headers; +} + function causeTypeToString(causeType) { for (let key in Ci.nsIContentPolicy) { if (Ci.nsIContentPolicy[key] === causeType) @@ -858,7 +909,7 @@ function setPostData(httpChannel, postData, headers) { return; const synthesized = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(Ci.nsIStringInputStream); const body = atob(postData); - synthesized.setData(body, body.length); + synthesized.setByteStringData(body); const overriddenHeader = (lowerCaseName) => { if (headers) { @@ -890,7 +941,7 @@ function convertString(s, source, dest) { const is = Cc["@mozilla.org/io/string-input-stream;1"].createInstance( Ci.nsIStringInputStream ); - is.setData(s, s.length); + is.setByteStringData(s); const listener = Cc["@mozilla.org/network/stream-loader;1"].createInstance( Ci.nsIStreamLoader ); @@ -950,6 +1001,3 @@ PageNetwork.Events = { RequestFailed: Symbol('PageNetwork.Events.RequestFailed'), }; -var EXPORTED_SYMBOLS = ['NetworkObserver', 'PageNetwork']; -this.NetworkObserver = NetworkObserver; -this.PageNetwork = PageNetwork; diff --git a/browser_patches/firefox/juggler/SimpleChannel.js b/browser_patches/firefox/juggler/SimpleChannel.js index a4e1b19df4c6d..cc555451cdd49 100644 --- a/browser_patches/firefox/juggler/SimpleChannel.js +++ b/browser_patches/firefox/juggler/SimpleChannel.js @@ -79,7 +79,7 @@ class SimpleChannel { _setTimeout(cb, timeout) { // Lazy load on first call. - this._setTimeout = ChromeUtils.import('resource://gre/modules/Timer.jsm').setTimeout; + this._setTimeout = ChromeUtils.importESModule('resource://gre/modules/Timer.sys.mjs').setTimeout; this._setTimeout(cb, timeout); } @@ -251,6 +251,3 @@ class SimpleChannel { } } } - -var EXPORTED_SYMBOLS = ['SimpleChannel']; -this.SimpleChannel = SimpleChannel; diff --git a/browser_patches/firefox/juggler/TargetRegistry.js b/browser_patches/firefox/juggler/TargetRegistry.js index ea7b2afa4d734..4bdf162ab64f7 100644 --- a/browser_patches/firefox/juggler/TargetRegistry.js +++ b/browser_patches/firefox/juggler/TargetRegistry.js @@ -2,12 +2,11 @@ * 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 {Helper} = ChromeUtils.import('chrome://juggler/content/Helper.js'); -const {SimpleChannel} = ChromeUtils.import('chrome://juggler/content/SimpleChannel.js'); -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 {Helper} = ChromeUtils.importESModule('chrome://juggler/content/Helper.js'); +const {Preferences} = ChromeUtils.importESModule("resource://gre/modules/Preferences.sys.mjs"); +const {ContextualIdentityService} = ChromeUtils.importESModule("resource://gre/modules/ContextualIdentityService.sys.mjs"); +const {NetUtil} = ChromeUtils.importESModule('resource://gre/modules/NetUtil.sys.mjs'); +const {AppConstants} = ChromeUtils.importESModule("resource://gre/modules/AppConstants.sys.mjs"); const Cr = Components.results; @@ -22,6 +21,9 @@ const ALL_PERMISSIONS = [ ]; let globalTabAndWindowActivationChain = Promise.resolve(); +// This is a workaround for https://github.com/microsoft/playwright/issues/34586 +let didCreateFirstPage = false; +let globalNewPageChain = Promise.resolve(); class DownloadInterceptor { constructor(registry) { @@ -102,7 +104,7 @@ class DownloadInterceptor { const screencastService = Cc['@mozilla.org/juggler/screencast;1'].getService(Ci.nsIScreencastService); -class TargetRegistry { +export class TargetRegistry { static instance() { return TargetRegistry._instance || null; } @@ -116,6 +118,7 @@ class TargetRegistry { this._browserToTarget = new Map(); this._browserIdToTarget = new Map(); + this._proxiesWithClashingAuthCacheKeys = new Set(); this._browserProxy = null; // Cleanup containers from previous runs (if any) @@ -234,12 +237,50 @@ class TargetRegistry { onOpenWindow(win); } + // Firefox uses nsHttpAuthCache to cache authentication to the proxy. + // If we're provided with a single proxy with a multiple different authentications, then + // we should clear the nsHttpAuthCache on every request. + shouldBustHTTPAuthCacheForProxy(proxy) { + return this._proxiesWithClashingAuthCacheKeys.has(proxy); + } + + _updateProxiesWithSameAuthCacheAndDifferentCredentials() { + const proxyIdToCredentials = new Map(); + const allProxies = [...this._browserContextIdToBrowserContext.values()].map(bc => bc._proxy).filter(Boolean); + if (this._browserProxy) + allProxies.push(this._browserProxy); + const proxyAuthCacheKeyAndProxy = allProxies.map(proxy => [ + JSON.stringify({ + type: proxy.type, + host: proxy.host, + port: proxy.port, + }), + proxy, + ]); + this._proxiesWithClashingAuthCacheKeys.clear(); + + proxyAuthCacheKeyAndProxy.sort(([cacheKey1], [cacheKey2]) => cacheKey1 < cacheKey2 ? -1 : 1); + for (let i = 0; i < proxyAuthCacheKeyAndProxy.length - 1; ++i) { + const [cacheKey1, proxy1] = proxyAuthCacheKeyAndProxy[i]; + const [cacheKey2, proxy2] = proxyAuthCacheKeyAndProxy[i + 1]; + if (cacheKey1 !== cacheKey2) + continue; + if (proxy1.username === proxy2.username && proxy1.password === proxy2.password) + continue; + // `proxy1` and `proxy2` have the same caching key, but serve different credentials. + // We have to bust HTTP Auth Cache everytime there's a request that will use either of the proxies. + this._proxiesWithClashingAuthCacheKeys.add(proxy1); + this._proxiesWithClashingAuthCacheKeys.add(proxy2); + } + } + async cancelDownload(options) { this._downloadInterceptor.cancelDownload(options.uuid); } setBrowserProxy(proxy) { this._browserProxy = proxy; + this._updateProxiesWithSameAuthCacheAndDifferentCredentials(); } getProxyInfo(channel) { @@ -269,6 +310,16 @@ class TargetRegistry { } async newPage({browserContextId}) { + // When creating the very first page, we cannot create multiple in parallel. + // See https://github.com/microsoft/playwright/issues/34586. + if (didCreateFirstPage) + return this._newPageInternal({browserContextId}); + const result = globalNewPageChain.then(() => this._newPageInternal({browserContextId})); + globalNewPageChain = result.catch(error => { /* swallow errors to keep chain running */ }); + return result; + } + + async _newPageInternal({browserContextId}) { const browserContext = this.browserContextForId(browserContextId); const features = "chrome,dialog=no,all"; // See _callWithURIToLoad in browser.js for the structure of window.arguments @@ -317,6 +368,7 @@ class TargetRegistry { if (await target.hasFailedToOverrideTimezone()) throw new Error('Failed to override timezone'); } + didCreateFirstPage = true; return target.id(); } @@ -333,7 +385,7 @@ class TargetRegistry { } } -class PageTarget { +export class PageTarget { constructor(registry, win, tab, browserContext, opener) { helper.decorateAsEventEmitter(this); @@ -345,6 +397,7 @@ class PageTarget { this._linkedBrowser = tab.linkedBrowser; this._browserContext = browserContext; this._viewportSize = undefined; + this._zoom = 1; this._initialDPPX = this._linkedBrowser.browsingContext.overrideDPPX; this._url = 'about:blank'; this._openerId = opener ? opener.id() : undefined; @@ -354,7 +407,7 @@ class PageTarget { this._videoRecordingInfo = undefined; this._screencastRecordingInfo = undefined; this._dialogs = new Map(); - this.forcedColors = 'no-override'; + this.forcedColors = 'none'; this.disableCache = false; this.mediumOverride = ''; this.crossProcessCookie = { @@ -368,7 +421,7 @@ class PageTarget { onLocationChange: (aWebProgress, aRequest, aLocation) => this._onNavigated(aLocation), }; this._eventListeners = [ - helper.addObserver(this._updateModalDialogs.bind(this), 'tabmodal-dialog-loaded'), + helper.addObserver(this._updateModalDialogs.bind(this), 'common-dialog-loaded'), helper.addProgressListener(tab.linkedBrowser, navigationListener, Ci.nsIWebProgress.NOTIFY_LOCATION), helper.addEventListener(this._linkedBrowser, 'DOMModalDialogClosed', event => this._updateModalDialogs()), helper.addEventListener(this._linkedBrowser, 'WillChangeBrowserRemoteness', event => this._willChangeBrowserRemoteness()), @@ -457,9 +510,11 @@ class PageTarget { this.updateUserAgent(browsingContext); this.updatePlatform(browsingContext); this.updateDPPXOverride(browsingContext); + this.updateZoom(browsingContext); this.updateEmulatedMedia(browsingContext); this.updateColorSchemeOverride(browsingContext); this.updateReducedMotionOverride(browsingContext); + this.updateContrastOverride(browsingContext); this.updateForcedColorsOverride(browsingContext); this.updateForceOffline(browsingContext); this.updateCacheDisabled(browsingContext); @@ -495,11 +550,20 @@ class PageTarget { } updateDPPXOverride(browsingContext = undefined) { - (browsingContext || this._linkedBrowser.browsingContext).overrideDPPX = this._browserContext.deviceScaleFactor || this._initialDPPX; + browsingContext ||= this._linkedBrowser.browsingContext; + const dppx = this._zoom * (this._browserContext.deviceScaleFactor || this._initialDPPX); + browsingContext.overrideDPPX = dppx; + } + + async updateZoom(browsingContext = undefined) { + browsingContext ||= this._linkedBrowser.browsingContext; + // Update dpr first, and then UI zoom. + this.updateDPPXOverride(browsingContext); + browsingContext.fullZoom = this._zoom; } _updateModalDialogs() { - const prompts = new Set(this._linkedBrowser.tabModalPromptBox ? this._linkedBrowser.tabModalPromptBox.listPrompts() : []); + const prompts = new Set(this._linkedBrowser.tabDialogBox.getContentDialogManager().dialogs.map(dialog => dialog.frameContentWindow.Dialog)); for (const dialog of this._dialogs.values()) { if (!prompts.has(dialog.prompt())) { this._dialogs.delete(dialog.id()); @@ -545,7 +609,7 @@ class PageTarget { const toolbarTop = stackRect.y; this._window.resizeBy(width - this._window.innerWidth, height + toolbarTop - this._window.innerHeight); - await this._channel.connect('').send('awaitViewportDimensions', { width, height }); + await this._channel.connect('').send('awaitViewportDimensions', { width: width / this._zoom, height: height / this._zoom }); } else { this._linkedBrowser.style.removeProperty('width'); this._linkedBrowser.style.removeProperty('height'); @@ -557,8 +621,8 @@ class PageTarget { const actualSize = this._linkedBrowser.getBoundingClientRect(); await this._channel.connect('').send('awaitViewportDimensions', { - width: actualSize.width, - height: actualSize.height, + width: actualSize.width / this._zoom, + height: actualSize.height / this._zoom, }); } } @@ -590,13 +654,23 @@ class PageTarget { (browsingContext || this._linkedBrowser.browsingContext).prefersReducedMotionOverride = this.reducedMotion || this._browserContext.reducedMotion || 'none'; } + setContrast(contrast) { + this.contrast = fromProtocolContrast(contrast); + this.updateContrastOverride(); + } + + updateContrastOverride(browsingContext = undefined) { + (browsingContext || this._linkedBrowser.browsingContext).prefersContrastOverride = this.contrast || this._browserContext.contrast || 'none'; + } + setForcedColors(forcedColors) { this.forcedColors = fromProtocolForcedColors(forcedColors); this.updateForcedColorsOverride(); } updateForcedColorsOverride(browsingContext = undefined) { - (browsingContext || this._linkedBrowser.browsingContext).forcedColorsOverride = (this.forcedColors !== 'no-override' ? this.forcedColors : this._browserContext.forcedColors) || 'no-override'; + const isActive = this.forcedColors === 'active' || this._browserContext.forcedColors === 'active'; + (browsingContext || this._linkedBrowser.browsingContext).forcedColorsOverride = isActive ? 'active' : 'none'; } async setInterceptFileChooserDialog(enabled) { @@ -610,6 +684,14 @@ class PageTarget { await this.updateViewportSize(); } + async setZoom(zoom) { + // This is default range from the ZoomManager. + if (zoom < 0.3 || zoom > 5) + throw new Error('Invalid zoom value, must be between 0.3 and 5'); + this._zoom = zoom; + await this.updateZoom(); + } + close(runBeforeUnload = false) { this._gBrowser.removeTab(this._tab, { skipPermitUnload: !runBeforeUnload, @@ -816,11 +898,19 @@ function fromProtocolReducedMotion(reducedMotion) { throw new Error('Unknown reduced motion: ' + reducedMotion); } +function fromProtocolContrast(contrast) { + if (contrast === 'more' || contrast === 'less' || contrast === 'custom' || contrast === 'no-preference') + return contrast; + if (contrast === null) + return undefined; + throw new Error('Unknown contrast: ' + contrast); +} + function fromProtocolForcedColors(forcedColors) { if (forcedColors === 'active' || forcedColors === 'none') return forcedColors; - if (forcedColors === null) - return undefined; + if (!forcedColors) + return 'none'; throw new Error('Unknown forced colors: ' + forcedColors); } @@ -854,8 +944,9 @@ class BrowserContext { this.forceOffline = false; this.disableCache = false; this.colorScheme = 'none'; - this.forcedColors = 'no-override'; + this.forcedColors = 'none'; this.reducedMotion = 'none'; + this.contrast = 'none'; this.videoRecordingOptions = undefined; this.crossProcessCookie = { initScripts: [], @@ -882,6 +973,12 @@ class BrowserContext { page.updateReducedMotionOverride(); } + setContrast(contrast) { + this.contrast = fromProtocolContrast(contrast); + for (const page of this.pages) + page.updateContrastOverride(); + } + setForcedColors(forcedColors) { this.forcedColors = fromProtocolForcedColors(forcedColors); for (const page of this.pages) @@ -906,12 +1003,14 @@ class BrowserContext { } this._registry._browserContextIdToBrowserContext.delete(this.browserContextId); this._registry._userContextIdToBrowserContext.delete(this.userContextId); + this._registry._updateProxiesWithSameAuthCacheAndDifferentCredentials(); } setProxy(proxy) { // Clear AuthCache. Services.obs.notifyObservers(null, "net:clear-active-logins"); this._proxy = proxy; + this._registry._updateProxiesWithSameAuthCacheAndDifferentCredentials(); } setIgnoreHTTPSErrors(ignoreHTTPSErrors) { @@ -1194,7 +1293,3 @@ TargetRegistry.Events = { 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/juggler/components/Juggler.js b/browser_patches/firefox/juggler/components/Juggler.js index d919935fb50ac..6121c4d3928bc 100644 --- a/browser_patches/firefox/juggler/components/Juggler.js +++ b/browser_patches/firefox/juggler/components/Juggler.js @@ -2,16 +2,17 @@ * 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/. */ -var EXPORTED_SYMBOLS = ["Juggler", "JugglerFactory"]; - -const {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm"); -const {ComponentUtils} = ChromeUtils.import("resource://gre/modules/ComponentUtils.jsm"); -const {Dispatcher} = ChromeUtils.import("chrome://juggler/content/protocol/Dispatcher.js"); -const {BrowserHandler} = ChromeUtils.import("chrome://juggler/content/protocol/BrowserHandler.js"); -const {NetworkObserver} = ChromeUtils.import("chrome://juggler/content/NetworkObserver.js"); -const {TargetRegistry} = ChromeUtils.import("chrome://juggler/content/TargetRegistry.js"); -const {Helper} = ChromeUtils.import('chrome://juggler/content/Helper.js'); -const {ActorManagerParent} = ChromeUtils.import('resource://gre/modules/ActorManagerParent.jsm'); +// Load SimpleChannel in browser-process global. +Services.scriptloader.loadSubScript('chrome://juggler/content/SimpleChannel.js'); + +const {XPCOMUtils} = ChromeUtils.importESModule("resource://gre/modules/XPCOMUtils.sys.mjs"); +const {ComponentUtils} = ChromeUtils.importESModule("resource://gre/modules/ComponentUtils.sys.mjs"); +const {Dispatcher} = ChromeUtils.importESModule("chrome://juggler/content/protocol/Dispatcher.js"); +const {BrowserHandler} = ChromeUtils.importESModule("chrome://juggler/content/protocol/BrowserHandler.js"); +const {NetworkObserver} = ChromeUtils.importESModule("chrome://juggler/content/NetworkObserver.js"); +const {TargetRegistry} = ChromeUtils.importESModule("chrome://juggler/content/TargetRegistry.js"); +const {Helper} = ChromeUtils.importESModule('chrome://juggler/content/Helper.js'); +const {ActorManagerParent} = ChromeUtils.importESModule('resource://gre/modules/ActorManagerParent.sys.mjs'); const helper = new Helper(); const Cc = Components.classes; @@ -21,10 +22,10 @@ const Ci = Components.interfaces; ActorManagerParent.addJSWindowActors({ JugglerFrame: { parent: { - moduleURI: 'chrome://juggler/content/JugglerFrameParent.jsm', + esModuleURI: 'chrome://juggler/content/JugglerFrameParent.jsm', }, child: { - moduleURI: 'chrome://juggler/content/content/JugglerFrameChild.jsm', + esModuleURI: 'chrome://juggler/content/content/JugglerFrameChild.jsm', events: { // Normally, we instantiate an actor when a new window is created. DOMWindowCreated: {}, @@ -45,7 +46,7 @@ ActorManagerParent.addJSWindowActors({ let browserStartupFinishedCallback; let browserStartupFinishedPromise = new Promise(x => browserStartupFinishedCallback = x); -class Juggler { +export class Juggler { get classDescription() { return "Sample command-line handler"; } get classID() { return Components.ID('{f7a74a33-e2ab-422d-b022-4fb213dd2639}'); } get contractID() { return "@mozilla.org/remote/juggler;1" } @@ -105,7 +106,10 @@ class Juggler { }; // Force create hidden window here, otherwise its creation later closes the web socket! - Services.appShell.hiddenDOMWindow; + // Since https://phabricator.services.mozilla.com/D219834, hiddenDOMWindow is only available on MacOS. + if (Services.appShell.hasHiddenWindow) { + Services.appShell.hiddenDOMWindow; + } let pipeStopped = false; let browserHandler; @@ -151,7 +155,7 @@ class Juggler { const jugglerInstance = new Juggler(); // This is used by the XPCOM codepath which expects a constructor -var JugglerFactory = function() { +export var JugglerFactory = function() { return jugglerInstance; }; diff --git a/browser_patches/firefox/juggler/components/components.conf b/browser_patches/firefox/juggler/components/components.conf index e5bc6523b10cd..955b38ab9ccec 100644 --- a/browser_patches/firefox/juggler/components/components.conf +++ b/browser_patches/firefox/juggler/components/components.conf @@ -11,7 +11,7 @@ Classes = [ "command-line-handler": "m-remote", "profile-after-change": "Juggler", }, - "jsm": "chrome://juggler/content/components/Juggler.js", + "esModule": "chrome://juggler/content/components/Juggler.js", "constructor": "JugglerFactory", }, ] diff --git a/browser_patches/firefox/juggler/content/FrameTree.js b/browser_patches/firefox/juggler/content/FrameTree.js index 2d59b3c43aa23..09a95b3548df9 100644 --- a/browser_patches/firefox/juggler/content/FrameTree.js +++ b/browser_patches/firefox/juggler/content/FrameTree.js @@ -7,13 +7,11 @@ 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 {Runtime} = ChromeUtils.import('chrome://juggler/content/content/Runtime.js'); +const {Helper} = ChromeUtils.importESModule('chrome://juggler/content/Helper.js'); const helper = new Helper(); -class FrameTree { +export class FrameTree { constructor(rootBrowsingContext) { helper.decorateAsEventEmitter(this); @@ -46,8 +44,6 @@ class FrameTree { 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]), @@ -130,24 +126,12 @@ class FrameTree { } _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.frameForDocShell(window.docShell); if (!frame) return; frame._onGlobalObjectCleared(); } - setScrollbarsHidden(hidden) { - this.scrollbarsHidden = hidden; - } - setJavaScriptDisabled(javaScriptDisabled) { this._javaScriptDisabled = javaScriptDisabled; for (const frame of this.frames()) @@ -704,6 +688,3 @@ function channelId(channel) { } -var EXPORTED_SYMBOLS = ['FrameTree']; -this.FrameTree = FrameTree; - diff --git a/browser_patches/firefox/juggler/content/JugglerFrameChild.jsm b/browser_patches/firefox/juggler/content/JugglerFrameChild.jsm index 529f6d3b5898e..af060c57aac90 100644 --- a/browser_patches/firefox/juggler/content/JugglerFrameChild.jsm +++ b/browser_patches/firefox/juggler/content/JugglerFrameChild.jsm @@ -1,14 +1,16 @@ "use strict"; -const { Helper } = ChromeUtils.import('chrome://juggler/content/Helper.js'); -const { initialize } = ChromeUtils.import('chrome://juggler/content/content/main.js'); +const { Helper } = ChromeUtils.importESModule('chrome://juggler/content/Helper.js'); +const { initialize } = ChromeUtils.importESModule('chrome://juggler/content/content/main.js'); const Ci = Components.interfaces; const helper = new Helper(); let sameProcessInstanceNumber = 0; -class JugglerFrameChild extends JSWindowActorChild { +const topBrowingContextToAgents = new Map(); + +export class JugglerFrameChild extends JSWindowActorChild { constructor() { super(); @@ -16,49 +18,68 @@ class JugglerFrameChild extends JSWindowActorChild { } handleEvent(aEvent) { - if (this._agents && aEvent.type === 'DOMWillOpenModalDialog') { - this._agents.channel.pause(); + const agents = this._agents(); + if (!agents) + return; + if (aEvent.type === 'DOMWillOpenModalDialog') { + agents.channel.pause(); return; } - if (this._agents && aEvent.type === 'DOMModalDialogClosed') { - this._agents.channel.resumeSoon(); + if (aEvent.type === 'DOMModalDialogClosed') { + agents.channel.resumeSoon(); return; } - if (this._agents && aEvent.target === this.document) - this._agents.pageAgent.onWindowEvent(aEvent); - if (this._agents && aEvent.target === this.document) - this._agents.frameTree.onWindowEvent(aEvent); + if (aEvent.target === this.document) { + agents.pageAgent.onWindowEvent(aEvent); + agents.frameTree.onWindowEvent(aEvent); + } + } + + _agents() { + return topBrowingContextToAgents.get(this.browsingContext.top); } actorCreated() { this.actorName = `content::${this.browsingContext.browserId}/${this.browsingContext.id}/${++sameProcessInstanceNumber}`; this._eventListeners.push(helper.addEventListener(this.contentWindow, 'load', event => { - this._agents?.pageAgent.onWindowEvent(event); + this._agents()?.pageAgent.onWindowEvent(event); })); if (this.document.documentURI.startsWith('moz-extension://')) return; - this._agents = initialize(this.browsingContext, this.docShell, this); - } - _dispose() { - helper.removeListeners(this._eventListeners); - // We do not cleanup since agents are shared for all frames in the process. - - // TODO: restore the cleanup. - // Reset transport so that all messages will be pending and will not throw any errors. - // this._channel.resetTransport(); - // this._agents.pageAgent.dispose(); - // this._agents.frameTree.dispose(); - // this._agents = undefined; + // Child frame events will be forwarded to related top-level agents. + if (this.browsingContext.parent) + return; + + let agents = topBrowingContextToAgents.get(this.browsingContext); + if (!agents) { + agents = initialize(this.browsingContext, this.docShell); + topBrowingContextToAgents.set(this.browsingContext, agents); + } + agents.channel.bindToActor(this); + agents.actor = this; } didDestroy() { - this._dispose(); + helper.removeListeners(this._eventListeners); + + if (this.browsingContext.parent) + return; + + const agents = topBrowingContextToAgents.get(this.browsingContext); + // The agents are already re-bound to a new actor. + if (agents?.actor !== this) + return; + + topBrowingContextToAgents.delete(this.browsingContext); + + agents.channel.resetTransport(); + agents.pageAgent.dispose(); + agents.frameTree.dispose(); } receiveMessage() { } } -var EXPORTED_SYMBOLS = ['JugglerFrameChild']; diff --git a/browser_patches/firefox/juggler/content/PageAgent.js b/browser_patches/firefox/juggler/content/PageAgent.js index 6aee921e87779..2ff5e6b922b55 100644 --- a/browser_patches/firefox/juggler/content/PageAgent.js +++ b/browser_patches/firefox/juggler/content/PageAgent.js @@ -8,9 +8,9 @@ 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 {setTimeout} = ChromeUtils.import('resource://gre/modules/Timer.jsm'); +const {Helper} = ChromeUtils.importESModule('chrome://juggler/content/Helper.js'); +const {NetUtil} = ChromeUtils.importESModule('resource://gre/modules/NetUtil.sys.mjs'); +const {setTimeout} = ChromeUtils.importESModule('resource://gre/modules/Timer.sys.mjs'); const dragService = Cc["@mozilla.org/widget/dragservice;1"].getService( Ci.nsIDragService @@ -51,7 +51,7 @@ class WorkerData { } } -class PageAgent { +export class PageAgent { constructor(browserChannel, frameTree) { this._browserChannel = browserChannel; this._browserPage = browserChannel.connect('page'); @@ -120,7 +120,8 @@ class PageAgent { // After the dragStart event is dispatched and handled by Web, // it might or might not create a new drag session, depending on its preventing default. setTimeout(() => { - this._browserPage.emit('pageInputEvent', { type: 'juggler-drag-finalized', dragSessionStarted: !!dragService.getCurrentSession() }); + const session = this._getCurrentDragSession(); + this._browserPage.emit('pageInputEvent', { type: 'juggler-drag-finalized', dragSessionStarted: !!session }); }, 0); } }), @@ -370,7 +371,12 @@ class PageAgent { 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))); + let nsFiles; + if (unsafeObject.webkitdirectory) { + nsFiles = await new Directory(files[0]).getFiles(true); + } else { + nsFiles = await Promise.all(files.map(filePath => File.createFromFileName(filePath))); + } unsafeObject.mozSetFileArray(nsFiles); const events = [ new (frame.domWindow().Event)('input', { bubbles: true, cancelable: true, composed: true }), @@ -521,8 +527,14 @@ class PageAgent { }); } + _getCurrentDragSession() { + const frame = this._frameTree.mainFrame(); + const domWindow = frame?.domWindow(); + return domWindow ? dragService.getCurrentSession(domWindow) : undefined; + } + async _dispatchDragEvent({type, x, y, modifiers}) { - const session = dragService.getCurrentSession(); + const session = this._getCurrentDragSession(); const dropEffect = session.dataTransfer.dropEffect; if ((type === 'drop' && dropEffect !== 'none') || type === 'dragover') { @@ -546,9 +558,8 @@ class PageAgent { return; } if (type === 'dragend') { - const session = dragService.getCurrentSession(); - if (session) - dragService.endDragSession(true); + const session = this._getCurrentDragSession(); + session?.endDragSession(true); return; } } @@ -564,7 +575,7 @@ class PageAgent { // 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'); + const { ctypes } = ChromeUtils.importESModule('resource://gre/modules/ctypes.sys.mjs'); ChromeUtils.privateNoteIntentionalCrash(); const zero = new ctypes.intptr_t(8); const badptr = ctypes.cast(zero, ctypes.PointerType(ctypes.int32_t)); @@ -698,6 +709,3 @@ class PageAgent { } } -var EXPORTED_SYMBOLS = ['PageAgent']; -this.PageAgent = PageAgent; - diff --git a/browser_patches/firefox/juggler/content/Runtime.js b/browser_patches/firefox/juggler/content/Runtime.js index a5fa7a03dd343..ad8720a1d3e36 100644 --- a/browser_patches/firefox/juggler/content/Runtime.js +++ b/browser_patches/firefox/juggler/content/Runtime.js @@ -8,8 +8,8 @@ if (!this.Debugger) { // Worker has a Debugger defined already. - const {addDebuggerToGlobal} = ChromeUtils.import("resource://gre/modules/jsdebugger.jsm", {}); - addDebuggerToGlobal(Components.utils.getGlobalForObject(this)); + const {addDebuggerToGlobal} = ChromeUtils.importESModule("resource://gre/modules/jsdebugger.sys.mjs"); + addDebuggerToGlobal(Components.utils.getGlobalForObject(globalThis)); } let lastId = 0; @@ -596,5 +596,5 @@ function emitEvent(event, ...args) { listener.call(null, ...args); } -var EXPORTED_SYMBOLS = ['Runtime']; -this.Runtime = Runtime; +// Export Runtime to global. +globalThis.Runtime = Runtime; diff --git a/browser_patches/firefox/juggler/content/main.js b/browser_patches/firefox/juggler/content/main.js index 022b1e3a5e87c..68fb364eadb4e 100644 --- a/browser_patches/firefox/juggler/content/main.js +++ b/browser_patches/firefox/juggler/content/main.js @@ -2,29 +2,21 @@ * 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 {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'); +// Load SimpleChannel and Runtime in content process's global. +// NOTE: since these have to exist in both Worker and main threads, and we do +// not know a way to load ES Modules in worker threads, we have to use the loadSubScript +// utility instead. +Services.scriptloader.loadSubScript('chrome://juggler/content/SimpleChannel.js'); +Services.scriptloader.loadSubScript('chrome://juggler/content/content/Runtime.js'); -const browsingContextToAgents = new Map(); -const helper = new Helper(); - -function initialize(browsingContext, docShell, actor) { - if (browsingContext.parent) { - // For child frames, return agents from the main frame. - return browsingContextToAgents.get(browsingContext.top); - } +const {Helper} = ChromeUtils.importESModule('chrome://juggler/content/Helper.js'); +const {FrameTree} = ChromeUtils.importESModule('chrome://juggler/content/content/FrameTree.js'); +const {PageAgent} = ChromeUtils.importESModule('chrome://juggler/content/content/PageAgent.js'); - let data = browsingContextToAgents.get(browsingContext); - if (data) { - // Rebind from one main frame actor to another one. - data.channel.bindToActor(actor); - return data; - } +const helper = new Helper(); - data = { channel: undefined, pageAgent: undefined, frameTree: undefined, failedToOverrideTimezone: false }; - browsingContextToAgents.set(browsingContext, data); +export function initialize(browsingContext, docShell) { + const data = { channel: undefined, pageAgent: undefined, frameTree: undefined, failedToOverrideTimezone: false }; const applySetting = { geolocation: (geolocation) => { @@ -59,10 +51,6 @@ function initialize(browsingContext, docShell, actor) { docShell.languageOverride = locale; }, - scrollbarsHidden: (hidden) => { - data.frameTree.setScrollbarsHidden(hidden); - }, - javaScriptDisabled: (javaScriptDisabled) => { data.frameTree.setJavaScriptDisabled(javaScriptDisabled); }, @@ -84,7 +72,6 @@ function initialize(browsingContext, docShell, actor) { data.frameTree.addBinding(worldName, name, script); data.frameTree.setInitScripts([...contextCrossProcessCookie.initScripts, ...pageCrossProcessCookie.initScripts]); data.channel = new SimpleChannel('', 'process-' + Services.appinfo.processID); - data.channel.bindToActor(actor); data.pageAgent = new PageAgent(data.channel, data.frameTree); docShell.fileInputInterceptionEnabled = !!pageCrossProcessCookie.interceptFileChooserDialog; @@ -133,6 +120,3 @@ function initialize(browsingContext, docShell, actor) { return data; } - -var EXPORTED_SYMBOLS = ['initialize']; -this.initialize = initialize; diff --git a/browser_patches/firefox/juggler/protocol/BrowserHandler.js b/browser_patches/firefox/juggler/protocol/BrowserHandler.js index 7de276d017b26..035a53bb688c9 100644 --- a/browser_patches/firefox/juggler/protocol/BrowserHandler.js +++ b/browser_patches/firefox/juggler/protocol/BrowserHandler.js @@ -4,15 +4,15 @@ "use strict"; -const {AddonManager} = ChromeUtils.import("resource://gre/modules/AddonManager.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 {AddonManager} = ChromeUtils.importESModule("resource://gre/modules/AddonManager.sys.mjs"); +const {TargetRegistry} = ChromeUtils.importESModule("chrome://juggler/content/TargetRegistry.js"); +const {Helper} = ChromeUtils.importESModule('chrome://juggler/content/Helper.js'); +const {PageHandler} = ChromeUtils.importESModule("chrome://juggler/content/protocol/PageHandler.js"); +const {AppConstants} = ChromeUtils.importESModule("resource://gre/modules/AppConstants.sys.mjs"); const helper = new Helper(); -class BrowserHandler { +export class BrowserHandler { constructor(session, dispatcher, targetRegistry, startCompletePromise, onclose) { this._session = session; this._dispatcher = dispatcher; @@ -219,6 +219,10 @@ class BrowserHandler { await this._targetRegistry.browserContextForId(browserContextId).setForcedColors(nullToUndefined(forcedColors)); } + async ['Browser.setContrast']({browserContextId, contrast}) { + await this._targetRegistry.browserContextForId(browserContextId).setContrast(nullToUndefined(contrast)); + } + async ['Browser.setVideoRecordingOptions']({browserContextId, options}) { await this._targetRegistry.browserContextForId(browserContextId).setVideoRecordingOptions(options); } @@ -255,10 +259,6 @@ class BrowserHandler { 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); } @@ -313,6 +313,3 @@ async function waitForWindowClosed(browserWindow) { function nullToUndefined(value) { return value === null ? undefined : value; } - -var EXPORTED_SYMBOLS = ['BrowserHandler']; -this.BrowserHandler = BrowserHandler; diff --git a/browser_patches/firefox/juggler/protocol/Dispatcher.js b/browser_patches/firefox/juggler/protocol/Dispatcher.js index 8542461d529eb..7a65d0a1170c1 100644 --- a/browser_patches/firefox/juggler/protocol/Dispatcher.js +++ b/browser_patches/firefox/juggler/protocol/Dispatcher.js @@ -2,12 +2,13 @@ * 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 {protocol} = ChromeUtils.importESModule("chrome://juggler/content/protocol/Protocol.js"); +const {checkScheme} = ChromeUtils.importESModule("chrome://juggler/content/protocol/PrimitiveTypes.js"); +const {Helper} = ChromeUtils.importESModule('chrome://juggler/content/Helper.js'); const helper = new Helper(); -class Dispatcher { +export class Dispatcher { /** * @param {Connection} connection */ @@ -132,7 +133,3 @@ class ProtocolSession { return await this._handler[method](params); } } - -this.EXPORTED_SYMBOLS = ['Dispatcher']; -this.Dispatcher = Dispatcher; - diff --git a/browser_patches/firefox/juggler/protocol/PageHandler.js b/browser_patches/firefox/juggler/protocol/PageHandler.js index 8fa9a06361b71..1dab7d8803782 100644 --- a/browser_patches/firefox/juggler/protocol/PageHandler.js +++ b/browser_patches/firefox/juggler/protocol/PageHandler.js @@ -4,11 +4,11 @@ "use strict"; -const {Helper, EventWatcher} = ChromeUtils.import('chrome://juggler/content/Helper.js'); -const {NetUtil} = ChromeUtils.import('resource://gre/modules/NetUtil.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 {Helper, EventWatcher} = ChromeUtils.importESModule('chrome://juggler/content/Helper.js'); +const {NetUtil} = ChromeUtils.importESModule('resource://gre/modules/NetUtil.sys.mjs'); +const {NetworkObserver, PageNetwork} = ChromeUtils.importESModule('chrome://juggler/content/NetworkObserver.js'); +const {PageTarget} = ChromeUtils.importESModule('chrome://juggler/content/TargetRegistry.js'); +const {setTimeout} = ChromeUtils.importESModule('resource://gre/modules/Timer.sys.mjs'); const Cc = Components.classes; const Ci = Components.interfaces; @@ -65,7 +65,7 @@ class WorkerHandler { } } -class PageHandler { +export class PageHandler { constructor(target, session, contentChannel) { this._session = session; this._contentChannel = contentChannel; @@ -240,6 +240,10 @@ class PageHandler { await this._pageTarget.setViewportSize(viewportSize === null ? undefined : viewportSize); } + async ['Page.setZoom']({zoom}) { + await this._pageTarget.setZoom(zoom); + } + async ['Runtime.evaluate'](options) { return await this._contentPage.send('evaluate', options); } @@ -256,6 +260,13 @@ class PageHandler { return await this._contentPage.send('disposeObject', options); } + async ['Heap.collectGarbage']() { + Services.obs.notifyObservers(null, "child-gc-request"); + Cu.forceGC(); + Services.obs.notifyObservers(null, "child-cc-request"); + Cu.forceCC(); + } + async ['Network.getResponseBody']({requestId}) { return this._pageNetwork.getResponseBody(requestId); } @@ -291,10 +302,11 @@ class PageHandler { return await this._contentPage.send('setFileInputFiles', options); } - async ['Page.setEmulatedMedia']({colorScheme, type, reducedMotion, forcedColors}) { + async ['Page.setEmulatedMedia']({colorScheme, type, reducedMotion, forcedColors, contrast}) { this._pageTarget.setColorScheme(colorScheme || null); this._pageTarget.setReducedMotion(reducedMotion || null); this._pageTarget.setForcedColors(forcedColors || null); + this._pageTarget.setContrast(contrast || null); this._pageTarget.setEmulatedMedia(type); } @@ -679,6 +691,3 @@ class PageHandler { return await worker.sendMessage(JSON.parse(message)); } } - -var EXPORTED_SYMBOLS = ['PageHandler']; -this.PageHandler = PageHandler; diff --git a/browser_patches/firefox/juggler/protocol/PrimitiveTypes.js b/browser_patches/firefox/juggler/protocol/PrimitiveTypes.js index 5799038f19cbc..ca6d1ec4f60f2 100644 --- a/browser_patches/firefox/juggler/protocol/PrimitiveTypes.js +++ b/browser_patches/firefox/juggler/protocol/PrimitiveTypes.js @@ -2,7 +2,7 @@ * 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 = {}; +export const t = {}; t.String = function(x, details = {}, path = ['']) { if (typeof x === 'string' || typeof x === 'String') @@ -96,7 +96,7 @@ function beauty(path, obj) { return `property "${path.join('.')}" - ${JSON.stringify(obj, null, 2)}`; } -function checkScheme(scheme, x, details = {}, path = ['']) { +export function checkScheme(scheme, x, details = {}, path = ['']) { if (!scheme) throw new Error(`ILLDEFINED SCHEME: ${path.join('.')}`); if (typeof scheme === 'object') { @@ -142,6 +142,3 @@ test(t.Either(t.String, t.Number), {}); */ -this.t = t; -this.checkScheme = checkScheme; -this.EXPORTED_SYMBOLS = ['t', 'checkScheme']; diff --git a/browser_patches/firefox/juggler/protocol/Protocol.js b/browser_patches/firefox/juggler/protocol/Protocol.js index 6c9b700f05fec..4cb44d679ce0b 100644 --- a/browser_patches/firefox/juggler/protocol/Protocol.js +++ b/browser_patches/firefox/juggler/protocol/Protocol.js @@ -2,7 +2,7 @@ * 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'); +const {t} = ChromeUtils.importESModule('chrome://juggler/content/protocol/PrimitiveTypes.js'); // Protocol-specific types. const browserTypes = {}; @@ -394,12 +394,6 @@ const Browser = { viewport: t.Nullable(pageTypes.Viewport), } }, - 'setScrollbarsHidden': { - params: { - browserContextId: t.Optional(t.String), - hidden: t.Boolean, - } - }, 'setInitScripts': { params: { browserContextId: t.Optional(t.String), @@ -469,6 +463,12 @@ const Browser = { forcedColors: t.Nullable(t.Enum(['active', 'none'])), }, }, + 'setContrast': { + params: { + browserContextId: t.Optional(t.String), + contrast: t.Nullable(t.Enum(['less', 'more', 'custom', 'no-preference'])), + }, + }, 'setVideoRecordingOptions': { params: { browserContextId: t.Optional(t.String), @@ -487,6 +487,17 @@ const Browser = { }, }; +const Heap = { + targets: ['page'], + types: {}, + events: {}, + methods: { + 'collectGarbage': { + params: {}, + }, + }, +}; + const Network = { targets: ['page'], types: networkTypes, @@ -789,6 +800,11 @@ const Page = { viewportSize: t.Nullable(pageTypes.Size), }, }, + 'setZoom': { + params: { + zoom: t.Number, + }, + }, 'bringToFront': { params: { }, @@ -799,6 +815,7 @@ const Page = { colorScheme: t.Optional(t.Enum(['dark', 'light', 'no-preference'])), reducedMotion: t.Optional(t.Enum(['reduce', 'no-preference'])), forcedColors: t.Optional(t.Enum(['active', 'none'])), + contrast: t.Optional(t.Enum(['less', 'more', 'custom', 'no-preference'])), }, }, 'setCacheDisabled': { @@ -1001,8 +1018,6 @@ const Accessibility = { } } -this.protocol = { - domains: {Browser, Page, Runtime, Network, Accessibility}, +export const protocol = { + domains: {Browser, Heap, Page, Runtime, Network, Accessibility}, }; -this.checkScheme = checkScheme; -this.EXPORTED_SYMBOLS = ['protocol', 'checkScheme']; diff --git a/browser_patches/firefox/juggler/screencast/moz.build b/browser_patches/firefox/juggler/screencast/moz.build index e21b177c3965c..f89c54e037e39 100644 --- a/browser_patches/firefox/juggler/screencast/moz.build +++ b/browser_patches/firefox/juggler/screencast/moz.build @@ -23,8 +23,8 @@ XPCOM_MANIFESTS += [ LOCAL_INCLUDES += [ '/dom/media/systemservices', '/media/libyuv/libyuv/include', + '/third_party/abseil-cpp', '/third_party/libwebrtc', - '/third_party/libwebrtc/third_party/abseil-cpp', ] LOCAL_INCLUDES += [ diff --git a/browser_patches/firefox/juggler/screencast/nsScreencastService.cpp b/browser_patches/firefox/juggler/screencast/nsScreencastService.cpp index 25f6171801414..7256c8c8ea416 100644 --- a/browser_patches/firefox/juggler/screencast/nsScreencastService.cpp +++ b/browser_patches/firefox/juggler/screencast/nsScreencastService.cpp @@ -129,7 +129,7 @@ class nsScreencastService::Session : public rtc::VideoSinkInterfaceStartCapture(capability); + int error = mCaptureModule->StartCaptureCounted(capability); if (error) { fprintf(stderr, "StartCapture error %d\n", error); return false; @@ -152,7 +152,7 @@ class nsScreencastService::Session : public rtc::VideoSinkInterfaceDeRegisterCaptureDataCallback(this); else mCaptureModule->DeRegisterRawFrameCallback(this); - mCaptureModule->StopCapture(); + mCaptureModule->StopCaptureCounted(); if (mEncoder) { mEncoder->finish([this, protect = RefPtr{this}] { NS_DispatchToMainThread(NS_NewRunnableFunction( @@ -343,10 +343,17 @@ nsresult nsScreencastService::StartVideoRecording(nsIScreencastServiceClient* aC return NS_ERROR_FAILURE; gfx::IntMargin margin; - auto bounds = widget->GetScreenBounds().ToUnknownRect(); + // Screen bounds is the widget location on screen. + auto screenBounds = widget->GetScreenBounds().ToUnknownRect(); + // Client bounds is the content location, in terms of parent widget. + // To use it, we need to translate it to screen coordinates first. auto clientBounds = widget->GetClientBounds().ToUnknownRect(); + for (auto parent = widget->GetParent(); parent != nullptr; parent = parent->GetParent()) { + auto pb = parent->GetClientBounds().ToUnknownRect(); + clientBounds.MoveBy(pb.X(), pb.Y()); + } // Crop the image to exclude frame (if any). - margin = bounds - clientBounds; + margin = screenBounds - clientBounds; // Crop the image to exclude controls. margin.top += offsetTop; diff --git a/browser_patches/firefox/patches/bootstrap.diff b/browser_patches/firefox/patches/bootstrap.diff index 6291e775e6a7f..6f70b0342c8ec 100644 --- a/browser_patches/firefox/patches/bootstrap.diff +++ b/browser_patches/firefox/patches/bootstrap.diff @@ -1,5 +1,5 @@ diff --git a/accessible/base/NotificationController.h b/accessible/base/NotificationController.h -index 137963f1170927ae0262e0dc26ef721d496376f4..41fa27bc4a3da41814a7f326792990df3424e81f 100644 +index 1bcd464d3bd6b8465f78c62b074b0d57dbc6a082..f878ac9db2d800542dabcc2f48e8ae4727ec4b9a 100644 --- a/accessible/base/NotificationController.h +++ b/accessible/base/NotificationController.h @@ -244,6 +244,8 @@ class NotificationController final : public EventQueue, @@ -57,10 +57,10 @@ index 8e9bf2b413585b5a3db9370eee5d57fb6c6716ed..5a3b194b54e3813c89989f13a214c989 * Return XPCOM wrapper for the internal accessible. */ diff --git a/browser/app/winlauncher/LauncherProcessWin.cpp b/browser/app/winlauncher/LauncherProcessWin.cpp -index 81d4ee91e9383693d794dbf68184a80b49b582c6..1a07e3511f73199fe0b248412d01d7b8a3744a66 100644 +index 8167d2b81c918e02ce757f7f448f22e07c29d140..3ae798880acfd8aa965ae08051f2f81855133711 100644 --- a/browser/app/winlauncher/LauncherProcessWin.cpp +++ b/browser/app/winlauncher/LauncherProcessWin.cpp -@@ -22,6 +22,7 @@ +@@ -23,6 +23,7 @@ #include "mozilla/WinHeaderOnlyUtils.h" #include "nsWindowsHelpers.h" @@ -68,7 +68,7 @@ index 81d4ee91e9383693d794dbf68184a80b49b582c6..1a07e3511f73199fe0b248412d01d7b8 #include #include -@@ -425,8 +426,18 @@ Maybe LauncherMain(int& argc, wchar_t* argv[], +@@ -422,8 +423,18 @@ Maybe LauncherMain(int& argc, wchar_t* argv[], HANDLE stdHandles[] = {::GetStdHandle(STD_INPUT_HANDLE), ::GetStdHandle(STD_OUTPUT_HANDLE), ::GetStdHandle(STD_ERROR_HANDLE)}; @@ -89,10 +89,10 @@ index 81d4ee91e9383693d794dbf68184a80b49b582c6..1a07e3511f73199fe0b248412d01d7b8 DWORD creationFlags = CREATE_SUSPENDED | CREATE_UNICODE_ENVIRONMENT; diff --git a/browser/installer/allowed-dupes.mn b/browser/installer/allowed-dupes.mn -index f6d425f36a965f03ac82dbe3ab6cde06f12751ac..d60999ab2658b1e1e5f07a8aee530451c44f2957 100644 +index a097c2c56a665204ff7b5593c7faf836366801cf..235a4e224e08c22870c6913e335f0b6020b3e7da 100644 --- a/browser/installer/allowed-dupes.mn +++ b/browser/installer/allowed-dupes.mn -@@ -73,6 +73,12 @@ browser/features/webcompat@mozilla.org/shims/empty-shim.txt +@@ -67,6 +67,12 @@ browser/features/webcompat@mozilla.org/shims/empty-shim.txt removed-files #endif @@ -102,14 +102,14 @@ index f6d425f36a965f03ac82dbe3ab6cde06f12751ac..d60999ab2658b1e1e5f07a8aee530451 +chrome/juggler/content/server/stream-utils.js +chrome/marionette/content/stream-utils.js + - # Bug 1496075 - Switch searchplugins to Web Extensions - browser/chrome/browser/search-extensions/amazon/favicon.ico - browser/chrome/browser/search-extensions/amazondotcn/favicon.ico + # Bug 1606928 - There's no reliable way to connect Top Sites favicons with the favicons in the Search Service + browser/chrome/browser/content/activity-stream/data/content/tippytop/favicons/allegro-pl.ico + browser/defaults/settings/main/search-config-icons/96327a73-c433-5eb4-a16d-b090cadfb80b diff --git a/browser/installer/package-manifest.in b/browser/installer/package-manifest.in -index 1b87a9ab4aec939acac1da54a2b6670cc581fe86..a638dbe8e2f260d8be550fa8eb5bf6f6c2c31080 100644 +index 89cff6b562a82bd3a9a5d268abd4373199b31fac..e58dbf0ab0b06e84f6dac64698d11c6268091204 100644 --- a/browser/installer/package-manifest.in +++ b/browser/installer/package-manifest.in -@@ -185,6 +185,9 @@ +@@ -196,6 +196,9 @@ @RESPATH@/chrome/remote.manifest #endif @@ -167,10 +167,10 @@ index d49c6fbf1bf83b832795fa674f6b41f223eef812..7ea3540947ff5f61b15f27fbf4b95564 const transportProvider = { setListener(upgradeListener) { diff --git a/docshell/base/BrowsingContext.cpp b/docshell/base/BrowsingContext.cpp -index 6e1a1b689398fa6c3c73f2f243ae02c67a4476c8..9dcf71ce753cf11f295d83eb7653e940065c8e2c 100644 +index 2425779a7767e9350ee2afc4aea111a090c7f909..393eb86bf2d9a8f778bfce560a9fb3bf528ba558 100644 --- a/docshell/base/BrowsingContext.cpp +++ b/docshell/base/BrowsingContext.cpp -@@ -106,8 +106,15 @@ struct ParamTraits +@@ -108,8 +108,15 @@ struct ParamTraits template <> struct ParamTraits @@ -183,36 +183,28 @@ index 6e1a1b689398fa6c3c73f2f243ae02c67a4476c8..9dcf71ce753cf11f295d83eb7653e940 + : public mozilla::dom::WebIDLEnumSerializer {}; + +template <> -+struct ParamTraits -+ : public mozilla::dom::WebIDLEnumSerializer {}; ++struct ParamTraits ++ : public mozilla::dom::WebIDLEnumSerializer {}; template <> - struct ParamTraits -@@ -2804,6 +2811,40 @@ void BrowsingContext::DidSet(FieldIndex, + struct ParamTraits +@@ -2891,6 +2898,32 @@ void BrowsingContext::DidSet(FieldIndex, PresContextAffectingFieldChanged(); } -+void BrowsingContext::DidSet(FieldIndex, -+ dom::PrefersReducedMotionOverride aOldValue) { ++void BrowsingContext::DidSet(FieldIndex, ++ dom::PrefersContrastOverride aOldValue) { + MOZ_ASSERT(IsTop()); -+ if (PrefersReducedMotionOverride() == aOldValue) { ++ if (PrefersContrastOverride() == aOldValue) { + return; + } -+ PreOrderWalk([&](BrowsingContext* aContext) { -+ if (nsIDocShell* shell = aContext->GetDocShell()) { -+ if (nsPresContext* pc = shell->GetPresContext()) { -+ pc->MediaFeatureValuesChanged( -+ {MediaFeatureChangeReason::SystemMetricsChange}, -+ MediaFeatureChangePropagation::JustThisDocument); -+ } -+ } -+ }); ++ PresContextAffectingFieldChanged(); +} + -+void BrowsingContext::DidSet(FieldIndex, -+ dom::ForcedColorsOverride aOldValue) { ++void BrowsingContext::DidSet(FieldIndex, ++ dom::PrefersReducedMotionOverride aOldValue) { + MOZ_ASSERT(IsTop()); -+ if (ForcedColorsOverride() == aOldValue) { ++ if (PrefersReducedMotionOverride() == aOldValue) { + return; + } + PreOrderWalk([&](BrowsingContext* aContext) { @@ -230,10 +222,10 @@ index 6e1a1b689398fa6c3c73f2f243ae02c67a4476c8..9dcf71ce753cf11f295d83eb7653e940 nsString&& aOldValue) { MOZ_ASSERT(IsTop()); diff --git a/docshell/base/BrowsingContext.h b/docshell/base/BrowsingContext.h -index 5ec95a61e4d3af265cbe7dd9d83f6535da1d103e..f8acafe6d58c429af27a38363e06ad546dfbfddd 100644 +index eb183cb5c0751e43ea674f9e52441a5a82f186e0..79c5d8110faa89779dd0c16ba00620e7e65d06f5 100644 --- a/docshell/base/BrowsingContext.h +++ b/docshell/base/BrowsingContext.h -@@ -199,10 +199,10 @@ struct EmbedderColorSchemes { +@@ -203,10 +203,10 @@ struct EmbedderColorSchemes { FIELD(GVInaudibleAutoplayRequestStatus, GVAutoplayRequestStatus) \ /* ScreenOrientation-related APIs */ \ FIELD(CurrentOrientationAngle, float) \ @@ -246,33 +238,51 @@ index 5ec95a61e4d3af265cbe7dd9d83f6535da1d103e..f8acafe6d58c429af27a38363e06ad54 FIELD(EmbedderElementType, Maybe) \ FIELD(MessageManagerGroup, nsString) \ FIELD(MaxTouchPointsOverride, uint8_t) \ -@@ -240,6 +240,10 @@ struct EmbedderColorSchemes { +@@ -246,6 +246,9 @@ struct EmbedderColorSchemes { * embedder element. */ \ FIELD(EmbedderColorSchemes, EmbedderColorSchemes) \ FIELD(DisplayMode, dom::DisplayMode) \ + /* playwright addition */ \ + FIELD(PrefersReducedMotionOverride, dom::PrefersReducedMotionOverride) \ -+ /* playwright addition */ \ -+ FIELD(ForcedColorsOverride, dom::ForcedColorsOverride) \ ++ FIELD(PrefersContrastOverride, dom::PrefersContrastOverride) \ /* The number of entries added to the session history because of this \ * browsing context. */ \ FIELD(HistoryEntryCount, uint32_t) \ -@@ -926,6 +930,14 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache { - return GetPrefersColorSchemeOverride(); +@@ -950,6 +953,14 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache { + return GetForcedColorsOverride(); } + dom::PrefersReducedMotionOverride PrefersReducedMotionOverride() const { + return GetPrefersReducedMotionOverride(); + } + -+ dom::ForcedColorsOverride ForcedColorsOverride() const { -+ return GetForcedColorsOverride(); ++ dom::PrefersContrastOverride PrefersContrastOverride() const { ++ return GetPrefersContrastOverride(); + } + bool IsInBFCache() const; bool AllowJavascript() const { return GetAllowJavascript(); } -@@ -1090,6 +1102,23 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache { +@@ -1112,6 +1123,11 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache { + return IsTop(); + } + ++ bool CanSet(FieldIndex, ++ dom::PrefersContrastOverride, ContentParent*) { ++ return IsTop(); ++ } ++ + bool CanSet(FieldIndex, dom::ForcedColorsOverride, + ContentParent*) { + return IsTop(); +@@ -1130,10 +1146,22 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache { + void DidSet(FieldIndex, + dom::ForcedColorsOverride aOldValue); + ++ void DidSet(FieldIndex, ++ dom::PrefersContrastOverride aOldValue); ++ + template void WalkPresContexts(Callback&&); void PresContextAffectingFieldChanged(); @@ -284,23 +294,24 @@ index 5ec95a61e4d3af265cbe7dd9d83f6535da1d103e..f8acafe6d58c429af27a38363e06ad54 + void DidSet(FieldIndex, + dom::PrefersReducedMotionOverride aOldValue); + -+ -+ bool CanSet(FieldIndex, -+ dom::ForcedColorsOverride, ContentParent*) { -+ return IsTop(); -+ } -+ -+ void DidSet(FieldIndex, -+ dom::ForcedColorsOverride aOldValue); + void DidSet(FieldIndex, nsString&& aOldValue); bool CanSet(FieldIndex, bool, ContentParent*) { diff --git a/docshell/base/CanonicalBrowsingContext.cpp b/docshell/base/CanonicalBrowsingContext.cpp -index 84f2d2960a3fa642754e0c909f92d96865e39984..e91fc85fc7a7966d2d536839fab823ae88d1b4bd 100644 +index bef42c91d6f88922c8c101f3675325d828872aaf..8eb68c441fbef8ecbe5e90c118ccc00813564577 100644 --- a/docshell/base/CanonicalBrowsingContext.cpp +++ b/docshell/base/CanonicalBrowsingContext.cpp -@@ -1477,6 +1477,12 @@ void CanonicalBrowsingContext::LoadURI(nsIURI* aURI, +@@ -324,6 +324,8 @@ void CanonicalBrowsingContext::ReplacedBy( + txn.SetShouldDelayMediaFromStart(GetShouldDelayMediaFromStart()); + txn.SetForceOffline(GetForceOffline()); + txn.SetTopInnerSizeForRFP(GetTopInnerSizeForRFP()); ++ txn.SetPrefersReducedMotionOverride(GetPrefersReducedMotionOverride()); ++ txn.SetForcedColorsOverride(GetForcedColorsOverride()); + + // Propagate some settings on BrowsingContext replacement so they're not lost + // on bfcached navigations. These are important for GeckoView (see bug +@@ -1635,6 +1637,12 @@ void CanonicalBrowsingContext::LoadURI(nsIURI* aURI, return; } @@ -314,7 +325,7 @@ index 84f2d2960a3fa642754e0c909f92d96865e39984..e91fc85fc7a7966d2d536839fab823ae } diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp -index 3404597343e0d21c42c5adc2f2849888869cf75a..558f03f30672b9f0fdb68ba8d23a0d878d33643d 100644 +index 32c537d6be90247af8d778048c6d27f3800d4b02..b72196b0694828489f8ad27c209f49f0d41c43cb 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -15,6 +15,12 @@ @@ -330,23 +341,23 @@ index 3404597343e0d21c42c5adc2f2849888869cf75a..558f03f30672b9f0fdb68ba8d23a0d87 #include "mozilla/ArrayUtils.h" #include "mozilla/Attributes.h" #include "mozilla/AutoRestore.h" -@@ -64,6 +70,7 @@ - #include "mozilla/dom/ContentFrameMessageManager.h" +@@ -66,6 +72,7 @@ #include "mozilla/dom/DocGroup.h" #include "mozilla/dom/Element.h" + #include "mozilla/dom/FragmentDirective.h" +#include "mozilla/dom/Geolocation.h" #include "mozilla/dom/HTMLAnchorElement.h" #include "mozilla/dom/HTMLIFrameElement.h" - #include "mozilla/dom/PerformanceNavigation.h" -@@ -88,6 +95,7 @@ - #include "mozilla/dom/JSWindowActorChild.h" + #include "mozilla/dom/Navigation.h" +@@ -94,6 +101,7 @@ #include "mozilla/dom/DocumentBinding.h" + #include "mozilla/glean/DocshellMetrics.h" #include "mozilla/ipc/ProtocolUtils.h" +#include "mozilla/dom/WorkerCommon.h" #include "mozilla/net/DocumentChannel.h" #include "mozilla/net/DocumentChannelChild.h" #include "mozilla/net/ParentChannelWrapper.h" -@@ -111,6 +119,7 @@ +@@ -117,6 +125,7 @@ #include "nsIDocumentViewer.h" #include "mozilla/dom/Document.h" #include "nsHTMLDocument.h" @@ -354,7 +365,7 @@ index 3404597343e0d21c42c5adc2f2849888869cf75a..558f03f30672b9f0fdb68ba8d23a0d87 #include "nsIDocumentLoaderFactory.h" #include "nsIDOMWindow.h" #include "nsIEditingSession.h" -@@ -206,6 +215,7 @@ +@@ -211,6 +220,7 @@ #include "nsGlobalWindowInner.h" #include "nsGlobalWindowOuter.h" #include "nsJSEnvironment.h" @@ -362,7 +373,7 @@ index 3404597343e0d21c42c5adc2f2849888869cf75a..558f03f30672b9f0fdb68ba8d23a0d87 #include "nsNetCID.h" #include "nsNetUtil.h" #include "nsObjectLoadingContent.h" -@@ -346,6 +356,13 @@ nsDocShell::nsDocShell(BrowsingContext* aBrowsingContext, +@@ -352,6 +362,14 @@ nsDocShell::nsDocShell(BrowsingContext* aBrowsingContext, mAllowDNSPrefetch(true), mAllowWindowControl(true), mCSSErrorReportingEnabled(false), @@ -373,10 +384,11 @@ index 3404597343e0d21c42c5adc2f2849888869cf75a..558f03f30672b9f0fdb68ba8d23a0d87 + mDisallowBFCache(false), + mReducedMotionOverride(REDUCED_MOTION_OVERRIDE_NONE), + mForcedColorsOverride(FORCED_COLORS_OVERRIDE_NO_OVERRIDE), ++ mContrastOverride(CONTRAST_OVERRIDE_NONE), mAllowAuth(mItemType == typeContent), mAllowKeywordFixup(false), mDisableMetaRefreshWhenInactive(false), -@@ -3101,6 +3118,214 @@ nsDocShell::GetMessageManager(ContentFrameMessageManager** aMessageManager) { +@@ -3024,6 +3042,232 @@ nsDocShell::GetMessageManager(ContentFrameMessageManager** aMessageManager) { return NS_OK; } @@ -586,12 +598,30 @@ index 3404597343e0d21c42c5adc2f2849888869cf75a..558f03f30672b9f0fdb68ba8d23a0d87 + return NS_OK; +} + ++NS_IMETHODIMP ++nsDocShell::GetContrastOverride(ContrastOverride* aContrastOverride) { ++ *aContrastOverride = GetRootDocShell()->mContrastOverride; ++ return NS_OK; ++} ++ ++NS_IMETHODIMP ++nsDocShell::SetContrastOverride(ContrastOverride aContrastOverride) { ++ mContrastOverride = aContrastOverride; ++ RefPtr presContext = GetPresContext(); ++ if (presContext) { ++ presContext->MediaFeatureValuesChanged( ++ {MediaFeatureChangeReason::SystemMetricsChange}, ++ MediaFeatureChangePropagation::JustThisDocument); ++ } ++ return NS_OK; ++} ++ +// =============== Juggler End ======================= + NS_IMETHODIMP nsDocShell::GetIsNavigating(bool* aOut) { *aOut = mIsNavigating; -@@ -4789,7 +5014,7 @@ nsDocShell::GetVisibility(bool* aVisibility) { +@@ -4731,7 +4975,7 @@ nsDocShell::GetVisibility(bool* aVisibility) { } void nsDocShell::ActivenessMaybeChanged() { @@ -600,7 +630,7 @@ index 3404597343e0d21c42c5adc2f2849888869cf75a..558f03f30672b9f0fdb68ba8d23a0d87 if (RefPtr presShell = GetPresShell()) { presShell->ActivenessMaybeChanged(); } -@@ -6711,6 +6936,10 @@ bool nsDocShell::CanSavePresentation(uint32_t aLoadType, +@@ -6658,6 +6902,10 @@ bool nsDocShell::CanSavePresentation(uint32_t aLoadType, return false; // no entry to save into } @@ -611,7 +641,7 @@ index 3404597343e0d21c42c5adc2f2849888869cf75a..558f03f30672b9f0fdb68ba8d23a0d87 MOZ_ASSERT(!mozilla::SessionHistoryInParent(), "mOSHE cannot be non-null with SHIP"); nsCOMPtr viewer = mOSHE->GetDocumentViewer(); -@@ -8443,6 +8672,12 @@ nsresult nsDocShell::PerformRetargeting(nsDocShellLoadState* aLoadState) { +@@ -8399,6 +8647,12 @@ nsresult nsDocShell::PerformRetargeting(nsDocShellLoadState* aLoadState) { true, // aForceNoOpener getter_AddRefs(newBC)); MOZ_ASSERT(!newBC); @@ -624,7 +654,7 @@ index 3404597343e0d21c42c5adc2f2849888869cf75a..558f03f30672b9f0fdb68ba8d23a0d87 return rv; } -@@ -9569,6 +9804,16 @@ nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState, +@@ -9572,6 +9826,16 @@ nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState, nsINetworkPredictor::PREDICT_LOAD, attrs, nullptr); nsCOMPtr req; @@ -641,7 +671,7 @@ index 3404597343e0d21c42c5adc2f2849888869cf75a..558f03f30672b9f0fdb68ba8d23a0d87 rv = DoURILoad(aLoadState, aCacheKey, getter_AddRefs(req)); if (NS_SUCCEEDED(rv)) { -@@ -12732,6 +12977,9 @@ class OnLinkClickEvent : public Runnable { +@@ -12791,6 +13055,9 @@ class OnLinkClickEvent : public Runnable { mHandler->OnLinkClickSync(mContent, mLoadState, mNoOpenerImplied, mTriggeringPrincipal); } @@ -651,17 +681,17 @@ index 3404597343e0d21c42c5adc2f2849888869cf75a..558f03f30672b9f0fdb68ba8d23a0d87 return NS_OK; } -@@ -12816,6 +13064,8 @@ nsresult nsDocShell::OnLinkClick( - nsCOMPtr ev = - new OnLinkClickEvent(this, aContent, loadState, noOpenerImplied, - aIsTrusted, aTriggeringPrincipal); +@@ -12877,6 +13144,8 @@ nsresult nsDocShell::OnLinkClick( + + nsCOMPtr ev = new OnLinkClickEvent( + this, aContent, loadState, noOpenerImplied, aTriggeringPrincipal); + nsCOMPtr observerService = mozilla::services::GetObserverService(); + observerService->NotifyObservers(ToSupports(aContent), "juggler-link-click", nullptr); return Dispatch(ev.forget()); } diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h -index 82ac6c9ab9dbc102a429ab0fe6cb24b8fcdf477f..f6328c25349cf39fcce973adcf908782e8721447 100644 +index f22a333733322ad17f097d7edd46af21a687906c..6bcf8ca9f9cd64dc9f5695d00e0a3e6a97978f02 100644 --- a/docshell/base/nsDocShell.h +++ b/docshell/base/nsDocShell.h @@ -15,6 +15,7 @@ @@ -672,7 +702,7 @@ index 82ac6c9ab9dbc102a429ab0fe6cb24b8fcdf477f..f6328c25349cf39fcce973adcf908782 #include "mozilla/dom/WindowProxyHolder.h" #include "nsCOMPtr.h" #include "nsCharsetSource.h" -@@ -76,6 +77,7 @@ class nsCommandManager; +@@ -77,6 +78,7 @@ class nsCommandManager; class nsDocShellEditorData; class nsDOMNavigationTiming; class nsDSURIContentListener; @@ -680,7 +710,7 @@ index 82ac6c9ab9dbc102a429ab0fe6cb24b8fcdf477f..f6328c25349cf39fcce973adcf908782 class nsGlobalWindowOuter; class FramingChecker; -@@ -401,6 +403,15 @@ class nsDocShell final : public nsDocLoader, +@@ -403,6 +405,15 @@ class nsDocShell final : public nsDocLoader, void SetWillChangeProcess() { mWillChangeProcess = true; } bool WillChangeProcess() { return mWillChangeProcess; } @@ -696,7 +726,7 @@ index 82ac6c9ab9dbc102a429ab0fe6cb24b8fcdf477f..f6328c25349cf39fcce973adcf908782 // Create a content viewer within this nsDocShell for the given // `WindowGlobalChild` actor. nsresult CreateDocumentViewerForActor( -@@ -1004,6 +1015,8 @@ class nsDocShell final : public nsDocLoader, +@@ -1006,6 +1017,8 @@ class nsDocShell final : public nsDocLoader, bool CSSErrorReportingEnabled() const { return mCSSErrorReportingEnabled; } @@ -705,7 +735,7 @@ index 82ac6c9ab9dbc102a429ab0fe6cb24b8fcdf477f..f6328c25349cf39fcce973adcf908782 // Handles retrieval of subframe session history for nsDocShell::LoadURI. If a // load is requested in a subframe of the current DocShell, the subframe // loadType may need to reflect the loadType of the parent document, or in -@@ -1295,6 +1308,16 @@ class nsDocShell final : public nsDocLoader, +@@ -1285,6 +1298,17 @@ class nsDocShell final : public nsDocLoader, bool mAllowDNSPrefetch : 1; bool mAllowWindowControl : 1; bool mCSSErrorReportingEnabled : 1; @@ -718,12 +748,13 @@ index 82ac6c9ab9dbc102a429ab0fe6cb24b8fcdf477f..f6328c25349cf39fcce973adcf908782 + RefPtr mGeolocationServiceOverride; + ReducedMotionOverride mReducedMotionOverride; + ForcedColorsOverride mForcedColorsOverride; ++ ContrastOverride mContrastOverride; + bool mAllowAuth : 1; bool mAllowKeywordFixup : 1; bool mDisableMetaRefreshWhenInactive : 1; diff --git a/docshell/base/nsIDocShell.idl b/docshell/base/nsIDocShell.idl -index 21f09a517e91644f81f5bb823f556c15cd06e51f..a68d30e0a60f03a0942ac1cd8a1f83804fdfd3e0 100644 +index 84e821e33e8164829dfee4f05340784e189b90ee..aa690eb747cb73bc6bff40a62546037c2e64c485 100644 --- a/docshell/base/nsIDocShell.idl +++ b/docshell/base/nsIDocShell.idl @@ -44,6 +44,7 @@ interface nsIURI; @@ -734,7 +765,7 @@ index 21f09a517e91644f81f5bb823f556c15cd06e51f..a68d30e0a60f03a0942ac1cd8a1f8380 interface nsIEditor; interface nsIEditingSession; interface nsIInputStream; -@@ -754,6 +755,36 @@ interface nsIDocShell : nsIDocShellTreeItem +@@ -719,6 +720,45 @@ interface nsIDocShell : nsIDocShellTreeItem */ void synchronizeLayoutHistoryState(); @@ -766,16 +797,25 @@ index 21f09a517e91644f81f5bb823f556c15cd06e51f..a68d30e0a60f03a0942ac1cd8a1f8380 + }; + [infallible] attribute nsIDocShell_ForcedColorsOverride forcedColorsOverride; + ++ cenum ContrastOverride : 8 { ++ CONTRAST_OVERRIDE_LESS, ++ CONTRAST_OVERRIDE_MORE, ++ CONTRAST_OVERRIDE_CUSTOM, ++ CONTRAST_OVERRIDE_NO_PREFERENCE, ++ CONTRAST_OVERRIDE_NONE, /* This clears the override. */ ++ }; ++ [infallible] attribute nsIDocShell_ContrastOverride contrastOverride; ++ + void setGeolocationOverride(in nsIDOMGeoPosition position); + /** * This attempts to save any applicable layout history state (like * scroll position) in the nsISHEntry. This is normally done diff --git a/dom/base/Document.cpp b/dom/base/Document.cpp -index 4e9286a91e3b0f1114aa0a7aa6ff81dde615a73d..941a0c3dac71008ca760024a1e828f75f6af5182 100644 +index fd2d0be5f7755e64fc134515ea138c4ed0d28daf..ae48159ddbfb98d03e538d077a33260c639a74ac 100644 --- a/dom/base/Document.cpp +++ b/dom/base/Document.cpp -@@ -3676,6 +3676,9 @@ void Document::SendToConsole(nsCOMArray& aMessages) { +@@ -3752,6 +3752,9 @@ void Document::SendToConsole(nsCOMArray& aMessages) { } void Document::ApplySettingsFromCSP(bool aSpeculative) { @@ -785,7 +825,7 @@ index 4e9286a91e3b0f1114aa0a7aa6ff81dde615a73d..941a0c3dac71008ca760024a1e828f75 nsresult rv = NS_OK; if (!aSpeculative) { // 1) apply settings from regular CSP -@@ -3733,6 +3736,11 @@ nsresult Document::InitCSP(nsIChannel* aChannel) { +@@ -3809,6 +3812,11 @@ nsresult Document::InitCSP(nsIChannel* aChannel) { MOZ_ASSERT(!mScriptGlobalObject, "CSP must be initialized before mScriptGlobalObject is set!"); @@ -797,7 +837,7 @@ index 4e9286a91e3b0f1114aa0a7aa6ff81dde615a73d..941a0c3dac71008ca760024a1e828f75 // If this is a data document - no need to set CSP. if (mLoadedAsData) { return NS_OK; -@@ -4500,6 +4508,10 @@ bool Document::HasFocus(ErrorResult& rv) const { +@@ -4617,6 +4625,10 @@ bool Document::HasFocus(ErrorResult& rv) const { return false; } @@ -808,7 +848,7 @@ index 4e9286a91e3b0f1114aa0a7aa6ff81dde615a73d..941a0c3dac71008ca760024a1e828f75 if (!fm->IsInActiveWindow(bc)) { return false; } -@@ -18849,6 +18861,66 @@ ColorScheme Document::PreferredColorScheme(IgnoreRFP aIgnoreRFP) const { +@@ -19688,6 +19700,35 @@ ColorScheme Document::PreferredColorScheme(IgnoreRFP aIgnoreRFP) const { return PreferenceSheet::PrefsFor(*this).mColorScheme; } @@ -840,60 +880,28 @@ index 4e9286a91e3b0f1114aa0a7aa6ff81dde615a73d..941a0c3dac71008ca760024a1e828f75 + + return LookAndFeel::GetInt(LookAndFeel::IntID::PrefersReducedMotion, 0) == 1; +} -+ -+bool Document::ForcedColors() const { -+ auto* docShell = static_cast(GetDocShell()); -+ nsIDocShell::ForcedColorsOverride forcedColors; -+ if (docShell && docShell->GetForcedColorsOverride(&forcedColors) == NS_OK) { -+ switch (forcedColors) { -+ case nsIDocShell::FORCED_COLORS_OVERRIDE_ACTIVE: -+ return true; -+ case nsIDocShell::FORCED_COLORS_OVERRIDE_NONE: -+ return false; -+ case nsIDocShell::FORCED_COLORS_OVERRIDE_NO_OVERRIDE: -+ break; -+ }; -+ } -+ -+ if (auto* bc = GetBrowsingContext()) { -+ switch (bc->Top()->ForcedColorsOverride()) { -+ case dom::ForcedColorsOverride::Active: -+ return true; -+ case dom::ForcedColorsOverride::None: -+ return false; -+ case dom::ForcedColorsOverride::No_override: -+ break; -+ } -+ } -+ -+ if (mIsBeingUsedAsImage) { -+ return false; -+ } -+ return !PreferenceSheet::PrefsFor(*this).mUseDocumentColors; -+} + bool Document::HasRecentlyStartedForegroundLoads() { if (!sLoadingForegroundTopLevelContentDocument) { return false; diff --git a/dom/base/Document.h b/dom/base/Document.h -index a52c61addffc4a2344fa06cb0bceebe6a7ca9075..b0f8d65e5341bf277e48bef3b88cb4cc384fbc49 100644 +index 622f54e369d324a4cc2800dd4b331bd628339bed..2ef6ed20cf35febeff75b22dfa5bb2fbb4e295fe 100644 --- a/dom/base/Document.h +++ b/dom/base/Document.h -@@ -4044,6 +4044,9 @@ class Document : public nsINode, +@@ -4140,6 +4140,8 @@ class Document : public nsINode, // color-scheme meta tag. ColorScheme DefaultColorScheme() const; + bool PrefersReducedMotion() const; -+ bool ForcedColors() const; + static bool HasRecentlyStartedForegroundLoads(); static bool AutomaticStorageAccessPermissionCanBeGranted( diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp -index 14a00b8ed85f69312a89990acbb5e0f9755bd832..4b07c28615920a95a2ba59247f8575515cac4235 100644 +index a13cae5b990fb2f750e62f5117ad63aa981d787f..bc0f2d674aadd8eba867f56e873595a8885d1798 100644 --- a/dom/base/Navigator.cpp +++ b/dom/base/Navigator.cpp -@@ -338,14 +338,18 @@ void Navigator::GetAppName(nsAString& aAppName) const { +@@ -344,14 +344,18 @@ void Navigator::GetAppName(nsAString& aAppName) const { * for more detail. */ /* static */ @@ -914,7 +922,7 @@ index 14a00b8ed85f69312a89990acbb5e0f9755bd832..4b07c28615920a95a2ba59247f857551 // Split values on commas. for (nsDependentSubstring lang : -@@ -397,7 +401,13 @@ void Navigator::GetLanguage(nsAString& aLanguage) { +@@ -403,7 +407,13 @@ void Navigator::GetLanguage(nsAString& aLanguage) { } void Navigator::GetLanguages(nsTArray& aLanguages) { @@ -929,11 +937,21 @@ index 14a00b8ed85f69312a89990acbb5e0f9755bd832..4b07c28615920a95a2ba59247f857551 // The returned value is cached by the binding code. The window listens to the // accept languages change and will clear the cache when needed. It has to +@@ -2298,7 +2308,8 @@ bool Navigator::Webdriver() { + } + #endif + +- return false; ++ // Playwright is automating the browser, so we should pretend to be a webdriver ++ return true; + } + + AutoplayPolicy Navigator::GetAutoplayPolicy(AutoplayPolicyMediaType aType) { diff --git a/dom/base/Navigator.h b/dom/base/Navigator.h -index e559dc4d6aef61b7012a27f3d6c3186a12a15319..9798a50789ce972c4d9e94419e20a5cde4cd552a 100644 +index 6abf6cef230c97815f17f6b7abf9f1b1de274a6f..46ead1f32e0d710b5b32e61dff72a4f772d5421e 100644 --- a/dom/base/Navigator.h +++ b/dom/base/Navigator.h -@@ -215,7 +215,7 @@ class Navigator final : public nsISupports, public nsWrapperCache { +@@ -218,7 +218,7 @@ class Navigator final : public nsISupports, public nsWrapperCache { StorageManager* Storage(); @@ -943,94 +961,95 @@ index e559dc4d6aef61b7012a27f3d6c3186a12a15319..9798a50789ce972c4d9e94419e20a5cd dom::MediaCapabilities* MediaCapabilities(); dom::MediaSession* MediaSession(); diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp -index c6f1687f73df6b1849a191ff8722dc9fc26fc3eb..9fdface27d5c9bd0c61b8af229a31be2356c46b5 100644 +index f362a444a0f5ed247582646754dffd54d0b4540a..bbd72dab7ff4fbac8c247961e530764cb5c68d11 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp -@@ -8711,7 +8711,8 @@ nsresult nsContentUtils::SendMouseEvent( - bool aIgnoreRootScrollFrame, float aPressure, - unsigned short aInputSourceArg, uint32_t aIdentifier, bool aToWindow, - PreventDefaultResult* aPreventDefault, bool aIsDOMEventSynthesized, +@@ -9151,11 +9151,13 @@ nsresult nsContentUtils::SendMouseEvent( + int32_t aClickCount, int32_t aModifiers, bool aIgnoreRootScrollFrame, + float aPressure, unsigned short aInputSourceArg, uint32_t aIdentifier, + bool aToWindow, bool* aPreventDefault, bool aIsDOMEventSynthesized, - bool aIsWidgetEventSynthesized) { + bool aIsWidgetEventSynthesized, + bool convertToPointer, uint32_t aJugglerEventId) { - nsPoint offset; - nsCOMPtr widget = GetWidget(aPresShell, &offset); - if (!widget) return NS_ERROR_FAILURE; -@@ -8719,6 +8720,7 @@ nsresult nsContentUtils::SendMouseEvent( + MOZ_ASSERT(aWidget); EventMessage msg; Maybe exitFrom; bool contextMenuKey = false; -+ bool isDragEvent = false; ++ bool isPWDragEventMessage = false; if (aType.EqualsLiteral("mousedown")) { msg = eMouseDown; } else if (aType.EqualsLiteral("mouseup")) { -@@ -8743,6 +8745,12 @@ nsresult nsContentUtils::SendMouseEvent( +@@ -9181,6 +9183,12 @@ nsresult nsContentUtils::SendMouseEvent( msg = eMouseHitTest; } else if (aType.EqualsLiteral("MozMouseExploreByTouch")) { msg = eMouseExploreByTouch; + } else if (aType.EqualsLiteral("dragover")) { + msg = eDragOver; -+ isDragEvent = true; ++ isPWDragEventMessage = true; + } else if (aType.EqualsLiteral("drop")) { + msg = eDrop; -+ isDragEvent = true; ++ isPWDragEventMessage = true; } else { return NS_ERROR_FAILURE; } -@@ -8751,12 +8759,21 @@ nsresult nsContentUtils::SendMouseEvent( - aInputSourceArg = MouseEvent_Binding::MOZ_SOURCE_MOUSE; - } +@@ -9191,7 +9199,14 @@ nsresult nsContentUtils::SendMouseEvent( -- WidgetMouseEvent event(true, msg, widget, -+ std::unique_ptr eventOwner; -+ if (isDragEvent) { -+ eventOwner.reset(new WidgetDragEvent(true, msg, widget)); -+ eventOwner->mReason = aIsWidgetEventSynthesized + Maybe pointerEvent; + Maybe mouseEvent; +- if (IsPointerEventMessage(msg)) { ++ Maybe pwDragEvent; ++ ++ if (isPWDragEventMessage) { ++ pwDragEvent.emplace(true, msg, aWidget); ++ pwDragEvent->mReason = aIsWidgetEventSynthesized + ? WidgetMouseEvent::eSynthesized + : WidgetMouseEvent::eReal; -+ } else { -+ eventOwner.reset(new WidgetMouseEvent(true, msg, widget, - aIsWidgetEventSynthesized - ? WidgetMouseEvent::eSynthesized - : WidgetMouseEvent::eReal, - contextMenuKey ? WidgetMouseEvent::eContextMenuKey -- : WidgetMouseEvent::eNormal); -+ : WidgetMouseEvent::eNormal)); -+ } -+ WidgetMouseEvent& event = *eventOwner.get(); - event.pointerId = aIdentifier; - event.mModifiers = GetWidgetModifiers(aModifiers); - event.mButton = aButton; -@@ -8767,8 +8784,10 @@ nsresult nsContentUtils::SendMouseEvent( - event.mPressure = aPressure; - event.mInputSource = aInputSourceArg; - event.mClickCount = aClickCount; -+ event.mJugglerEventId = aJugglerEventId; - event.mFlags.mIsSynthesizedForTests = aIsDOMEventSynthesized; - event.mExitFrom = exitFrom; -+ event.convertToPointer = convertToPointer; ++ } else if (IsPointerEventMessage(msg)) { + MOZ_ASSERT(!aIsWidgetEventSynthesized, + "The event shouldn't be dispatched as a synthesized event"); + if (MOZ_UNLIKELY(aIsWidgetEventSynthesized)) { +@@ -9210,8 +9225,11 @@ nsresult nsContentUtils::SendMouseEvent( + contextMenuKey ? WidgetMouseEvent::eContextMenuKey + : WidgetMouseEvent::eNormal); + } ++ + WidgetMouseEvent& mouseOrPointerEvent = ++ pwDragEvent.isSome() ? pwDragEvent.ref() : + pointerEvent.isSome() ? pointerEvent.ref() : mouseEvent.ref(); ++ + mouseOrPointerEvent.pointerId = aIdentifier; + mouseOrPointerEvent.mModifiers = GetWidgetModifiers(aModifiers); + mouseOrPointerEvent.mButton = aButton; +@@ -9224,6 +9242,8 @@ nsresult nsContentUtils::SendMouseEvent( + mouseOrPointerEvent.mClickCount = aClickCount; + mouseOrPointerEvent.mFlags.mIsSynthesizedForTests = aIsDOMEventSynthesized; + mouseOrPointerEvent.mExitFrom = exitFrom; ++ mouseOrPointerEvent.mJugglerEventId = aJugglerEventId; ++ mouseOrPointerEvent.convertToPointer = convertToPointer; nsPresContext* presContext = aPresShell->GetPresContext(); if (!presContext) return NS_ERROR_FAILURE; diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h -index 338fc097dede02a538f240ba4cc66307086c7f56..8345e47237bc40490bd17019a053cce4c3d74a91 100644 +index 779cd9e544bfb2d135f12c3558c0ca8164b37029..041eba4bcbf40f51fc40ce7609ea81408e6a788d 100644 --- a/dom/base/nsContentUtils.h +++ b/dom/base/nsContentUtils.h -@@ -3055,7 +3055,8 @@ class nsContentUtils { +@@ -3015,8 +3015,9 @@ class nsContentUtils { + int32_t aButton, int32_t aButtons, int32_t aClickCount, int32_t aModifiers, bool aIgnoreRootScrollFrame, float aPressure, unsigned short aInputSourceArg, uint32_t aIdentifier, bool aToWindow, - mozilla::PreventDefaultResult* aPreventDefault, -- bool aIsDOMEventSynthesized, bool aIsWidgetEventSynthesized); +- bool* aPreventDefault, bool aIsDOMEventSynthesized, +- bool aIsWidgetEventSynthesized); ++ bool* aPreventDefault, + bool aIsDOMEventSynthesized, bool aIsWidgetEventSynthesized, + bool convertToPointer = true, uint32_t aJugglerEventId = 0); static void FirePageShowEventForFrameLoaderSwap( nsIDocShellTreeItem* aItem, diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp -index 9bc8340b9009717e0feecd5c14ff02be07a03daf..70ea04c7f11e6ccfadf72a82ec1741fac10ef5fd 100644 +index 15fe1db8a28ed2592b61aaf2006ddaa656f12389..2642c18bebcdfdd467be557171ba4ee204fcabde 100644 --- a/dom/base/nsDOMWindowUtils.cpp +++ b/dom/base/nsDOMWindowUtils.cpp -@@ -685,6 +685,26 @@ nsDOMWindowUtils::GetPresShellId(uint32_t* aPresShellId) { +@@ -710,6 +710,26 @@ nsDOMWindowUtils::GetPresShellId(uint32_t* aPresShellId) { return NS_ERROR_FAILURE; } @@ -1057,7 +1076,7 @@ index 9bc8340b9009717e0feecd5c14ff02be07a03daf..70ea04c7f11e6ccfadf72a82ec1741fa NS_IMETHODIMP nsDOMWindowUtils::SendMouseEvent( const nsAString& aType, float aX, float aY, int32_t aButton, -@@ -699,7 +719,7 @@ nsDOMWindowUtils::SendMouseEvent( +@@ -724,7 +744,7 @@ nsDOMWindowUtils::SendMouseEvent( aOptionalArgCount >= 7 ? aIdentifier : DEFAULT_MOUSE_POINTER_ID, false, aPreventDefault, aOptionalArgCount >= 4 ? aIsDOMEventSynthesized : true, aOptionalArgCount >= 5 ? aIsWidgetEventSynthesized : false, @@ -1066,7 +1085,7 @@ index 9bc8340b9009717e0feecd5c14ff02be07a03daf..70ea04c7f11e6ccfadf72a82ec1741fa } NS_IMETHODIMP -@@ -717,7 +737,7 @@ nsDOMWindowUtils::SendMouseEventToWindow( +@@ -742,7 +762,7 @@ nsDOMWindowUtils::SendMouseEventToWindow( aOptionalArgCount >= 7 ? aIdentifier : DEFAULT_MOUSE_POINTER_ID, true, nullptr, aOptionalArgCount >= 4 ? aIsDOMEventSynthesized : true, aOptionalArgCount >= 5 ? aIsWidgetEventSynthesized : false, @@ -1075,27 +1094,29 @@ index 9bc8340b9009717e0feecd5c14ff02be07a03daf..70ea04c7f11e6ccfadf72a82ec1741fa } NS_IMETHODIMP -@@ -726,13 +746,13 @@ nsDOMWindowUtils::SendMouseEventCommon( +@@ -751,7 +771,7 @@ nsDOMWindowUtils::SendMouseEventCommon( int32_t aClickCount, int32_t aModifiers, bool aIgnoreRootScrollFrame, float aPressure, unsigned short aInputSourceArg, uint32_t aPointerId, bool aToWindow, bool* aPreventDefault, bool aIsDOMEventSynthesized, - bool aIsWidgetEventSynthesized, int32_t aButtons) { + bool aIsWidgetEventSynthesized, int32_t aButtons, bool aConvertToPointer, uint32_t aJugglerEventId) { RefPtr presShell = GetPresShell(); - PreventDefaultResult preventDefaultResult; - nsresult rv = nsContentUtils::SendMouseEvent( - presShell, aType, aX, aY, aButton, aButtons, aClickCount, aModifiers, - aIgnoreRootScrollFrame, aPressure, aInputSourceArg, aPointerId, aToWindow, -- &preventDefaultResult, aIsDOMEventSynthesized, aIsWidgetEventSynthesized); -+ &preventDefaultResult, aIsDOMEventSynthesized, aIsWidgetEventSynthesized, aConvertToPointer, aJugglerEventId); - - if (aPreventDefault) { - *aPreventDefault = preventDefaultResult != PreventDefaultResult::No; + if (!presShell) { + return NS_ERROR_FAILURE; +@@ -768,7 +788,7 @@ nsDOMWindowUtils::SendMouseEventCommon( + presShell, widget, aType, refPoint, aButton, aButtons, aClickCount, + aModifiers, aIgnoreRootScrollFrame, aPressure, aInputSourceArg, + aPointerId, aToWindow, aPreventDefault, aIsDOMEventSynthesized, +- aIsWidgetEventSynthesized); ++ aIsWidgetEventSynthesized, aConvertToPointer, aJugglerEventId); + } + + NS_IMETHODIMP diff --git a/dom/base/nsDOMWindowUtils.h b/dom/base/nsDOMWindowUtils.h -index 63968c9b7a4e418e4c0de6e7a75fa215a36a9105..decf3ea3833ccdffd49a7aded2d600f9416e8306 100644 +index a8a48d28fc4ef612f8234bc2490a41672f1704f5..f702b0c9a0783ec547a41bbefd68e18a27a239fe 100644 --- a/dom/base/nsDOMWindowUtils.h +++ b/dom/base/nsDOMWindowUtils.h -@@ -93,7 +93,7 @@ class nsDOMWindowUtils final : public nsIDOMWindowUtils, +@@ -94,7 +94,7 @@ class nsDOMWindowUtils final : public nsIDOMWindowUtils, int32_t aClickCount, int32_t aModifiers, bool aIgnoreRootScrollFrame, float aPressure, unsigned short aInputSourceArg, uint32_t aIdentifier, bool aToWindow, bool* aPreventDefault, bool aIsDOMEventSynthesized, @@ -1105,10 +1126,10 @@ index 63968c9b7a4e418e4c0de6e7a75fa215a36a9105..decf3ea3833ccdffd49a7aded2d600f9 MOZ_CAN_RUN_SCRIPT nsresult SendTouchEventCommon( diff --git a/dom/base/nsFocusManager.cpp b/dom/base/nsFocusManager.cpp -index 5a4cf78d65eee0adcbeca33787706113eca19de7..7c8016e422ccc9e86563eaa83c9acc1dad0e5967 100644 +index 555a08b4b3fcd0d0c7986014d2e3516c6e5991c0..74a39e000b0e68042f1f51f6fafbc39ac9b42e51 100644 --- a/dom/base/nsFocusManager.cpp +++ b/dom/base/nsFocusManager.cpp -@@ -1675,6 +1675,10 @@ Maybe nsFocusManager::SetFocusInner(Element* aNewContent, +@@ -1720,6 +1720,10 @@ Maybe nsFocusManager::SetFocusInner(Element* aNewContent, (GetActiveBrowsingContext() == newRootBrowsingContext); } @@ -1119,7 +1140,7 @@ index 5a4cf78d65eee0adcbeca33787706113eca19de7..7c8016e422ccc9e86563eaa83c9acc1d // Exit fullscreen if a website focuses another window if (StaticPrefs::full_screen_api_exit_on_windowRaise() && !isElementInActiveWindow && (aFlags & FLAG_RAISE)) { -@@ -2242,6 +2246,7 @@ bool nsFocusManager::BlurImpl(BrowsingContext* aBrowsingContextToClear, +@@ -2306,6 +2310,7 @@ bool nsFocusManager::BlurImpl(BrowsingContext* aBrowsingContextToClear, bool aIsLeavingDocument, bool aAdjustWidget, bool aRemainActive, Element* aElementToFocus, uint64_t aActionId) { @@ -1127,7 +1148,7 @@ index 5a4cf78d65eee0adcbeca33787706113eca19de7..7c8016e422ccc9e86563eaa83c9acc1d LOGFOCUS(("<>", aActionId)); // hold a reference to the focused content, which may be null -@@ -2288,6 +2293,11 @@ bool nsFocusManager::BlurImpl(BrowsingContext* aBrowsingContextToClear, +@@ -2352,6 +2357,11 @@ bool nsFocusManager::BlurImpl(BrowsingContext* aBrowsingContextToClear, return true; } @@ -1139,7 +1160,7 @@ index 5a4cf78d65eee0adcbeca33787706113eca19de7..7c8016e422ccc9e86563eaa83c9acc1d // Keep a ref to presShell since dispatching the DOM event may cause // the document to be destroyed. RefPtr presShell = docShell->GetPresShell(); -@@ -2947,7 +2957,9 @@ void nsFocusManager::RaiseWindow(nsPIDOMWindowOuter* aWindow, +@@ -3066,7 +3076,9 @@ void nsFocusManager::RaiseWindow(nsPIDOMWindowOuter* aWindow, } } @@ -1151,10 +1172,10 @@ index 5a4cf78d65eee0adcbeca33787706113eca19de7..7c8016e422ccc9e86563eaa83c9acc1d // care of lowering the present active window. This happens in // a separate runnable to avoid touching multiple windows in diff --git a/dom/base/nsGlobalWindowOuter.cpp b/dom/base/nsGlobalWindowOuter.cpp -index e28dcdb092b23558702377af32eece5d273d4cf3..a37ae9d6ccd978d5e84562450e7039d6a75d517b 100644 +index 99a5049a3aff2efb208895d60622fd9c8d7f337a..9a9b039a46f1294a8b4af0613fb4f4173ac6a8a0 100644 --- a/dom/base/nsGlobalWindowOuter.cpp +++ b/dom/base/nsGlobalWindowOuter.cpp -@@ -2509,10 +2509,16 @@ nsresult nsGlobalWindowOuter::SetNewDocument(Document* aDocument, +@@ -2512,10 +2512,16 @@ nsresult nsGlobalWindowOuter::SetNewDocument(Document* aDocument, }(); if (!isContentAboutBlankInChromeDocshell) { @@ -1175,7 +1196,7 @@ index e28dcdb092b23558702377af32eece5d273d4cf3..a37ae9d6ccd978d5e84562450e7039d6 } } -@@ -2632,6 +2638,19 @@ void nsGlobalWindowOuter::DispatchDOMWindowCreated() { +@@ -2635,6 +2641,19 @@ void nsGlobalWindowOuter::DispatchDOMWindowCreated() { } } @@ -1196,10 +1217,10 @@ index e28dcdb092b23558702377af32eece5d273d4cf3..a37ae9d6ccd978d5e84562450e7039d6 void nsGlobalWindowOuter::SetDocShell(nsDocShell* aDocShell) { diff --git a/dom/base/nsGlobalWindowOuter.h b/dom/base/nsGlobalWindowOuter.h -index 8337a7353fb8e97372f0b57bd0fd867506a9129f..e7dedd6d26125e481e1145337a0be6ab864c1e1b 100644 +index 0453a18ec10c1434d1692f10b1b4acee754e6b7e..ee7bad691515bb51f6b4345e88944b02ad173180 100644 --- a/dom/base/nsGlobalWindowOuter.h +++ b/dom/base/nsGlobalWindowOuter.h -@@ -315,6 +315,7 @@ class nsGlobalWindowOuter final : public mozilla::dom::EventTarget, +@@ -320,6 +320,7 @@ class nsGlobalWindowOuter final : public mozilla::dom::EventTarget, // Outer windows only. void DispatchDOMWindowCreated(); @@ -1208,10 +1229,10 @@ index 8337a7353fb8e97372f0b57bd0fd867506a9129f..e7dedd6d26125e481e1145337a0be6ab // Outer windows only. virtual void EnsureSizeAndPositionUpToDate() override; diff --git a/dom/base/nsINode.cpp b/dom/base/nsINode.cpp -index d5455e559639aee9328905b50f02c52e94db950b..3fbd1e0459e5391066fc6b3a4e30a841594b31bf 100644 +index 8e2bbed21c13f23745e2eaad4ded831106ebd930..a17b0c7b9730737f178c05703b08d0f5f6d9ecd1 100644 --- a/dom/base/nsINode.cpp +++ b/dom/base/nsINode.cpp -@@ -1365,6 +1365,61 @@ void nsINode::GetBoxQuadsFromWindowOrigin(const BoxQuadOptions& aOptions, +@@ -1449,6 +1449,61 @@ void nsINode::GetBoxQuadsFromWindowOrigin(const BoxQuadOptions& aOptions, mozilla::GetBoxQuadsFromWindowOrigin(this, aOptions, aResult, aRv); } @@ -1274,10 +1295,10 @@ index d5455e559639aee9328905b50f02c52e94db950b..3fbd1e0459e5391066fc6b3a4e30a841 DOMQuad& aQuad, const GeometryNode& aFrom, const ConvertCoordinateOptions& aOptions, CallerType aCallerType, diff --git a/dom/base/nsINode.h b/dom/base/nsINode.h -index 3a47992cc89176fe9500f7b1d5b74e4422cb9625..27e6da8498af5e4a3c37407a3a8ab592e28dc372 100644 +index eb75f281630f8ca1b901686207c9fc97336d675f..e607f0ae454d52fc2bfe19046b492352a84b4ebd 100644 --- a/dom/base/nsINode.h +++ b/dom/base/nsINode.h -@@ -2248,6 +2248,10 @@ class nsINode : public mozilla::dom::EventTarget { +@@ -2397,6 +2397,10 @@ class nsINode : public mozilla::dom::EventTarget { nsTArray>& aResult, ErrorResult& aRv); @@ -1289,10 +1310,10 @@ index 3a47992cc89176fe9500f7b1d5b74e4422cb9625..27e6da8498af5e4a3c37407a3a8ab592 DOMQuad& aQuad, const TextOrElementOrDocument& aFrom, const ConvertCoordinateOptions& aOptions, CallerType aCallerType, diff --git a/dom/base/nsJSUtils.cpp b/dom/base/nsJSUtils.cpp -index cf8037cd580013efe5eb578c43f45c0d21946c6a..583460796fdef633e8075013597f7c315ce4ab06 100644 +index bf7eb34da03c0958de688deecb53b407d430f645..a2ec3b1b7e86f72bee38d890c0834abfe4be8637 100644 --- a/dom/base/nsJSUtils.cpp +++ b/dom/base/nsJSUtils.cpp -@@ -177,6 +177,11 @@ bool nsJSUtils::GetScopeChainForElement( +@@ -149,6 +149,11 @@ bool nsJSUtils::GetEnvironmentChainForElement(JSContext* aCx, Element* aElement, return true; } @@ -1305,23 +1326,23 @@ index cf8037cd580013efe5eb578c43f45c0d21946c6a..583460796fdef633e8075013597f7c31 void nsJSUtils::ResetTimeZone() { JS::ResetTimeZone(); } diff --git a/dom/base/nsJSUtils.h b/dom/base/nsJSUtils.h -index cceb725d393d5e5f83c8f87491089c3fa1d57cc3..e906a7fb7c3fd72554613f640dcc272e6984d929 100644 +index f32e21752d5013bf143eb45391ab9218debab08e..83763d2354dade2f8d2b7930ba18ae91c55133ad 100644 --- a/dom/base/nsJSUtils.h +++ b/dom/base/nsJSUtils.h -@@ -79,6 +79,7 @@ class nsJSUtils { - JSContext* aCx, mozilla::dom::Element* aElement, - JS::MutableHandleVector aScopeChain); +@@ -75,6 +75,7 @@ class nsJSUtils { + mozilla::dom::Element* aElement, + JS::EnvironmentChain& aEnvChain); + static bool SetTimeZoneOverride(const char* timezoneId); static void ResetTimeZone(); static bool DumpEnabled(); diff --git a/dom/chrome-webidl/BrowsingContext.webidl b/dom/chrome-webidl/BrowsingContext.webidl -index d70f3e18cc8e8f749e5057297161206129871453..2f2be2a6539203d1957bfe580a06ab70a512c053 100644 +index 6ec88536141126c97c9b599e3237bb5670d42ce8..41c6cc56738bdaf711adf2cf5b00c7fad5d71ba8 100644 --- a/dom/chrome-webidl/BrowsingContext.webidl +++ b/dom/chrome-webidl/BrowsingContext.webidl -@@ -53,6 +53,24 @@ enum PrefersColorSchemeOverride { - "dark", +@@ -61,6 +61,26 @@ enum ForcedColorsOverride { + "active", }; +/** @@ -1334,35 +1355,73 @@ index d70f3e18cc8e8f749e5057297161206129871453..2f2be2a6539203d1957bfe580a06ab70 +}; + +/** -+ * CSS forced-colors values. ++ * CSS prefers-contrast values. + */ -+enum ForcedColorsOverride { ++enum PrefersContrastOverride { + "none", -+ "active", -+ "no-override", /* This clears the override. */ ++ "no-preference", ++ "more", ++ "less", ++ "custom", +}; + /** * Allowed overrides of platform/pref default behaviour for touch events. */ -@@ -209,6 +227,12 @@ interface BrowsingContext { - // Color-scheme simulation, for DevTools. - [SetterThrows] attribute PrefersColorSchemeOverride prefersColorSchemeOverride; +@@ -220,6 +240,12 @@ interface BrowsingContext { + // Forced-colors simulation, for DevTools + [SetterThrows] attribute ForcedColorsOverride forcedColorsOverride; + // Reduced-Motion simulation, for DevTools. + [SetterThrows] attribute PrefersReducedMotionOverride prefersReducedMotionOverride; + -+ // Forced-Colors simulation, for DevTools. -+ [SetterThrows] attribute ForcedColorsOverride forcedColorsOverride; ++ // Contrast simulation, for DevTools. ++ [SetterThrows] attribute PrefersContrastOverride prefersContrastOverride; + /** * A unique identifier for the browser element that is hosting this * BrowsingContext tree. Every BrowsingContext in the element's tree will +diff --git a/dom/fetch/Fetch.cpp b/dom/fetch/Fetch.cpp +index 0bd219694282347309680fc9b53b945e1fd0ad92..c5c2e2d32a380ec72379b05a8b84f187431f7309 100644 +--- a/dom/fetch/Fetch.cpp ++++ b/dom/fetch/Fetch.cpp +@@ -701,6 +701,12 @@ already_AddRefed FetchRequest(nsIGlobalObject* aGlobal, + ipcArgs.hasCSPEventListener() = false; + ipcArgs.isWorkerRequest() = false; + ++ /* --> Playwright: associate keep-alive fetch with the window */ ++ BrowsingContext* bc = window ? window->GetBrowsingContext() : nullptr; ++ if (bc) ++ ipcArgs.associatedBrowsingContextID() = bc->Id(); ++ /* <-- Playwright */ ++ + actor->DoFetchOp(ipcArgs); + + mozilla::glean::networking::fetch_keepalive_request_count.Get("main"_ns) +diff --git a/dom/fetch/FetchService.cpp b/dom/fetch/FetchService.cpp +index b5e60bbd27fbb2f033d233e9ae2ebc728f442512..0adc568ece34d2c0f35eeacd81e2db9125b7c327 100644 +--- a/dom/fetch/FetchService.cpp ++++ b/dom/fetch/FetchService.cpp +@@ -268,6 +268,14 @@ RefPtr FetchService::FetchInstance::Fetch() { + false // IsTrackingFetch + ); + ++ /* --> Playwright: associate keep-alive fetch with the window */ ++ if (mArgsType == FetchArgsType::MainThreadFetch) { ++ auto& args = mArgs.as(); ++ mFetchDriver->SetAssociatedBrowsingContextID( ++ args.mAssociatedBrowsingContextID); ++ } ++ /* <-- Playwright */ ++ + if (mArgsType == FetchArgsType::WorkerFetch) { + auto& args = mArgs.as(); + mFetchDriver->SetWorkerScript(args.mWorkerScript); diff --git a/dom/geolocation/Geolocation.cpp b/dom/geolocation/Geolocation.cpp -index cb9107deb1acfc6f9f3efe87144fcd9bbccd9231..5034c066db8e13dbd01b9bbe79ac2447135f3360 100644 +index 7c653fe131dc34d35ffdc030950071adb31a9fc9..b23442a42ba8ee270e8e38930e59ae15c2a29039 100644 --- a/dom/geolocation/Geolocation.cpp +++ b/dom/geolocation/Geolocation.cpp -@@ -23,6 +23,7 @@ +@@ -28,6 +28,7 @@ #include "nsComponentManagerUtils.h" #include "nsContentPermissionHelper.h" #include "nsContentUtils.h" @@ -1370,7 +1429,7 @@ index cb9107deb1acfc6f9f3efe87144fcd9bbccd9231..5034c066db8e13dbd01b9bbe79ac2447 #include "nsGlobalWindowInner.h" #include "mozilla/dom/Document.h" #include "nsINamed.h" -@@ -256,10 +257,8 @@ nsGeolocationRequest::Allow(JS::Handle aChoices) { +@@ -428,10 +429,8 @@ nsGeolocationRequest::Allow(JS::Handle aChoices) { return NS_OK; } @@ -1383,7 +1442,7 @@ index cb9107deb1acfc6f9f3efe87144fcd9bbccd9231..5034c066db8e13dbd01b9bbe79ac2447 CachedPositionAndAccuracy lastPosition = gs->GetCachedPosition(); if (lastPosition.position) { EpochTimeStamp cachedPositionTime_ms; -@@ -437,8 +436,7 @@ void nsGeolocationRequest::Shutdown() { +@@ -639,8 +638,7 @@ void nsGeolocationRequest::Shutdown() { // If there are no other high accuracy requests, the geolocation service will // notify the provider to switch to the default accuracy. if (mOptions && mOptions->mEnableHighAccuracy) { @@ -1393,7 +1452,7 @@ index cb9107deb1acfc6f9f3efe87144fcd9bbccd9231..5034c066db8e13dbd01b9bbe79ac2447 if (gs) { gs->UpdateAccuracy(); } -@@ -727,8 +725,14 @@ void nsGeolocationService::StopDevice() { +@@ -957,8 +955,14 @@ void nsGeolocationService::StopDevice() { StaticRefPtr nsGeolocationService::sService; already_AddRefed @@ -1409,7 +1468,7 @@ index cb9107deb1acfc6f9f3efe87144fcd9bbccd9231..5034c066db8e13dbd01b9bbe79ac2447 if (nsGeolocationService::sService) { result = nsGeolocationService::sService; -@@ -820,7 +824,9 @@ nsresult Geolocation::Init(nsPIDOMWindowInner* aContentDom) { +@@ -1050,7 +1054,9 @@ nsresult Geolocation::Init(nsPIDOMWindowInner* aContentDom) { // If no aContentDom was passed into us, we are being used // by chrome/c++ and have no mOwner, no mPrincipal, and no need // to prompt. @@ -1421,7 +1480,7 @@ index cb9107deb1acfc6f9f3efe87144fcd9bbccd9231..5034c066db8e13dbd01b9bbe79ac2447 mService->AddLocator(this); } diff --git a/dom/geolocation/Geolocation.h b/dom/geolocation/Geolocation.h -index 7e1af00d05fbafa2d828e2c7e4dcc5c82d115f5b..e85af9718d064e4d2865bc944e9d4ba1efb9a5d7 100644 +index 992de29b5d2d09c19e55ebb2502215ec9d05a171..cdc20567b693283b0fd5a5923f7ea54210bd1712 100644 --- a/dom/geolocation/Geolocation.h +++ b/dom/geolocation/Geolocation.h @@ -31,6 +31,7 @@ @@ -1432,7 +1491,7 @@ index 7e1af00d05fbafa2d828e2c7e4dcc5c82d115f5b..e85af9718d064e4d2865bc944e9d4ba1 class nsGeolocationService; class nsGeolocationRequest; -@@ -48,13 +49,14 @@ struct CachedPositionAndAccuracy { +@@ -51,13 +52,14 @@ struct CachedPositionAndAccuracy { bool isHighAccuracy; }; @@ -1448,9 +1507,9 @@ index 7e1af00d05fbafa2d828e2c7e4dcc5c82d115f5b..e85af9718d064e4d2865bc944e9d4ba1 static mozilla::StaticRefPtr sService; NS_DECL_THREADSAFE_ISUPPORTS -@@ -179,6 +181,8 @@ class Geolocation final : public nsIGeolocationUpdate, public nsWrapperCache { - // null. - static already_AddRefed NonWindowSingleton(); +@@ -189,6 +191,8 @@ class Geolocation final : public nsIGeolocationUpdate, public nsWrapperCache { + BrowsingContext* aBrowsingContext, + geolocation::ParentRequestResolver&& aResolver); + nsGeolocationService* GetGeolocationService() { return mService; }; + @@ -1458,18 +1517,18 @@ index 7e1af00d05fbafa2d828e2c7e4dcc5c82d115f5b..e85af9718d064e4d2865bc944e9d4ba1 ~Geolocation(); diff --git a/dom/html/HTMLInputElement.cpp b/dom/html/HTMLInputElement.cpp -index d5a65a17555b7764611803f7fb298712b2c60fd7..fdee7deaf0b14e01702b902f8b73256c281e76b8 100644 +index c3e7de8f41e06e11155620b75c4d8a830d908b37..39eb9d31258693dce3a26c3227f28d92bccdb019 100644 --- a/dom/html/HTMLInputElement.cpp +++ b/dom/html/HTMLInputElement.cpp -@@ -57,6 +57,7 @@ +@@ -64,6 +64,7 @@ #include "mozilla/dom/Document.h" #include "mozilla/dom/HTMLDataListElement.h" #include "mozilla/dom/HTMLOptionElement.h" +#include "nsDocShell.h" - #include "nsIFormControlFrame.h" - #include "nsITextControlFrame.h" #include "nsIFrame.h" -@@ -783,6 +784,13 @@ nsresult HTMLInputElement::InitFilePicker(FilePickerType aType) { + #include "nsRangeFrame.h" + #include "nsError.h" +@@ -790,6 +791,13 @@ nsresult HTMLInputElement::InitFilePicker(FilePickerType aType) { return NS_ERROR_FAILURE; } @@ -1480,14 +1539,14 @@ index d5a65a17555b7764611803f7fb298712b2c60fd7..fdee7deaf0b14e01702b902f8b73256c + return NS_OK; + } + - if (IsPopupBlocked(doc)) { + if (IsPickerBlocked(doc)) { return NS_OK; } diff --git a/dom/interfaces/base/nsIDOMWindowUtils.idl b/dom/interfaces/base/nsIDOMWindowUtils.idl -index 6a0df1b435cee9cea3b7d7ca30d0aff0e31f8ac0..c17b24823dd873c025e407fcc635b7c678dfd8ed 100644 +index 5e417145c4f21d8f2aa65088611477b681c9c327..bc84c509659c7556077e69c652e5b19639eb88bb 100644 --- a/dom/interfaces/base/nsIDOMWindowUtils.idl +++ b/dom/interfaces/base/nsIDOMWindowUtils.idl -@@ -373,6 +373,26 @@ interface nsIDOMWindowUtils : nsISupports { +@@ -374,6 +374,26 @@ interface nsIDOMWindowUtils : nsISupports { [optional] in long aButtons, [optional] in unsigned long aIdentifier); @@ -1515,10 +1574,10 @@ index 6a0df1b435cee9cea3b7d7ca30d0aff0e31f8ac0..c17b24823dd873c025e407fcc635b7c6 * touchstart, touchend, touchmove, and touchcancel * diff --git a/dom/ipc/BrowserChild.cpp b/dom/ipc/BrowserChild.cpp -index bdd10fdcb285e43778b55907ac05bfa973207e5e..d98808918ff8eccd6c51b4fbce1cce5e3745206a 100644 +index 93f20a36acef74947d5377df5ff916546218d8b8..22b706b985d22a8c0c278a12ab4944e26ded51a4 100644 --- a/dom/ipc/BrowserChild.cpp +++ b/dom/ipc/BrowserChild.cpp -@@ -1652,6 +1652,21 @@ void BrowserChild::HandleRealMouseButtonEvent(const WidgetMouseEvent& aEvent, +@@ -1676,6 +1676,21 @@ void BrowserChild::HandleRealMouseButtonEvent(const WidgetMouseEvent& aEvent, if (postLayerization) { postLayerization->Register(); } @@ -1555,15 +1614,12 @@ index 5aa445d2e0a6169e57c44569974d557b3baf7064..671f71979b407f0ca17c66f13805e851 } diff --git a/dom/media/systemservices/video_engine/desktop_capture_impl.cc b/dom/media/systemservices/video_engine/desktop_capture_impl.cc -index a966ff06d4a52e2ff70ce71df3a6a607a67e3eda..eb6bb16413df43217ddd85048c02d41d15e8431f 100644 +index c43a1b3b245101c974742c5e50f54857e538bbfb..c07a568da3342cbf2af07471fa6959cb242b9a4e 100644 --- a/dom/media/systemservices/video_engine/desktop_capture_impl.cc +++ b/dom/media/systemservices/video_engine/desktop_capture_impl.cc -@@ -135,11 +135,12 @@ int32_t ScreenDeviceInfoImpl::GetOrientation(const char* aDeviceUniqueIdUTF8, - return 0; - } +@@ -52,9 +52,10 @@ namespace webrtc { --VideoCaptureModule* DesktopCaptureImpl::Create(const int32_t aModuleId, -+VideoCaptureModuleEx* DesktopCaptureImpl::Create(const int32_t aModuleId, + DesktopCaptureImpl* DesktopCaptureImpl::Create(const int32_t aModuleId, const char* aUniqueId, - const CaptureDeviceType aType) { + const CaptureDeviceType aType, @@ -1573,30 +1629,20 @@ index a966ff06d4a52e2ff70ce71df3a6a607a67e3eda..eb6bb16413df43217ddd85048c02d41d + aType, aCaptureCursor); } - int32_t WindowDeviceInfoImpl::Init() { -@@ -412,7 +413,7 @@ static bool UsePipewire() { + static DesktopCaptureOptions CreateDesktopCaptureOptions() { +@@ -155,8 +156,10 @@ static std::unique_ptr CreateTabCapturer( static std::unique_ptr CreateDesktopCapturerAndThread( CaptureDeviceType aDeviceType, DesktopCapturer::SourceId aSourceId, - nsIThread** aOutThread) { + nsIThread** aOutThread, bool aCaptureCursor) { DesktopCaptureOptions options = CreateDesktopCaptureOptions(); - std::unique_ptr capturer; - -@@ -462,8 +463,10 @@ static std::unique_ptr CreateDesktopCapturerAndThread( - - capturer->SelectSource(aSourceId); - -- capturer = std::make_unique(std::move(capturer), -- options); -+ if (aCaptureCursor) { -+ capturer = std::make_unique( -+ std::move(capturer), options); -+ } - } else if (aDeviceType == CaptureDeviceType::Browser) { - // XXX We don't capture cursors, so avoid the extra indirection layer. We - // could also pass null for the pMouseCursorMonitor. -@@ -480,7 +483,8 @@ static std::unique_ptr CreateDesktopCapturerAndThread( ++ if (aCaptureCursor) ++ options.set_prefer_cursor_embedded(aCaptureCursor); + auto ensureThread = [&]() { + if (*aOutThread) { + return *aOutThread; +@@ -253,7 +256,8 @@ static std::unique_ptr CreateDesktopCapturerAndThread( } DesktopCaptureImpl::DesktopCaptureImpl(const int32_t aId, const char* aUniqueId, @@ -1606,7 +1652,7 @@ index a966ff06d4a52e2ff70ce71df3a6a607a67e3eda..eb6bb16413df43217ddd85048c02d41d : mModuleId(aId), mTrackingId(mozilla::TrackingId(CaptureEngineToTrackingSourceStr([&] { switch (aType) { -@@ -497,6 +501,7 @@ DesktopCaptureImpl::DesktopCaptureImpl(const int32_t aId, const char* aUniqueId, +@@ -270,6 +274,7 @@ DesktopCaptureImpl::DesktopCaptureImpl(const int32_t aId, const char* aUniqueId, aId)), mDeviceUniqueId(aUniqueId), mDeviceType(aType), @@ -1614,7 +1660,7 @@ index a966ff06d4a52e2ff70ce71df3a6a607a67e3eda..eb6bb16413df43217ddd85048c02d41d mControlThread(mozilla::GetCurrentSerialEventTarget()), mNextFrameMinimumTime(Timestamp::Zero()), mCallbacks("DesktopCaptureImpl::mCallbacks") {} -@@ -521,6 +526,19 @@ void DesktopCaptureImpl::DeRegisterCaptureDataCallback( +@@ -294,6 +299,19 @@ void DesktopCaptureImpl::DeRegisterCaptureDataCallback( } } @@ -1634,7 +1680,7 @@ index a966ff06d4a52e2ff70ce71df3a6a607a67e3eda..eb6bb16413df43217ddd85048c02d41d int32_t DesktopCaptureImpl::StopCaptureIfAllClientsClose() { { auto callbacks = mCallbacks.Lock(); -@@ -553,7 +571,7 @@ int32_t DesktopCaptureImpl::StartCapture( +@@ -333,7 +351,7 @@ int32_t DesktopCaptureImpl::StartCapture( DesktopCapturer::SourceId sourceId = std::stoi(mDeviceUniqueId); std::unique_ptr capturer = CreateDesktopCapturerAndThread( @@ -1643,7 +1689,7 @@ index a966ff06d4a52e2ff70ce71df3a6a607a67e3eda..eb6bb16413df43217ddd85048c02d41d MOZ_ASSERT(!capturer == !mCaptureThread); if (!capturer) { -@@ -654,6 +672,15 @@ void DesktopCaptureImpl::OnCaptureResult(DesktopCapturer::Result aResult, +@@ -441,6 +459,15 @@ void DesktopCaptureImpl::OnCaptureResult(DesktopCapturer::Result aResult, frameInfo.height = aFrame->size().height(); frameInfo.videoType = VideoType::kARGB; @@ -1660,18 +1706,18 @@ index a966ff06d4a52e2ff70ce71df3a6a607a67e3eda..eb6bb16413df43217ddd85048c02d41d frameInfo.width * frameInfo.height * DesktopFrame::kBytesPerPixel; diff --git a/dom/media/systemservices/video_engine/desktop_capture_impl.h b/dom/media/systemservices/video_engine/desktop_capture_impl.h -index 7292f6c8a70298d4bf103080804843fa9bba1d15..7a50fee0d2fcaad475302d010892800a6e3c4e75 100644 +index a76b7de569db1cb42728a5514fb80e5c46e0344e..3d61ad8d3aa4a7eaf96957dcd680e1e1ee8abdf4 100644 --- a/dom/media/systemservices/video_engine/desktop_capture_impl.h +++ b/dom/media/systemservices/video_engine/desktop_capture_impl.h -@@ -24,6 +24,7 @@ +@@ -26,6 +26,7 @@ #include "api/video/video_sink_interface.h" #include "modules/desktop_capture/desktop_capturer.h" #include "modules/video_capture/video_capture.h" +#include "rtc_base/deprecated/recursive_critical_section.h" - - #include "desktop_device_info.h" #include "mozilla/DataMutex.h" -@@ -43,6 +44,21 @@ namespace webrtc { + #include "mozilla/Maybe.h" + #include "mozilla/TimeStamp.h" +@@ -42,17 +43,44 @@ namespace webrtc { class VideoCaptureEncodeInterface; @@ -1688,12 +1734,21 @@ index 7292f6c8a70298d4bf103080804843fa9bba1d15..7a50fee0d2fcaad475302d010892800a + + virtual void RegisterRawFrameCallback(RawFrameCallback* rawFrameCallback) = 0; + virtual void DeRegisterRawFrameCallback(RawFrameCallback* rawFrameCallback) = 0; ++ int32_t StartCaptureCounted(const VideoCaptureCapability& aCapability) { ++ ++capture_counter_; ++ return capture_counter_ == 1 ? StartCapture(aCapability) : 0; ++ } ++ ++ int32_t StopCaptureCounted() { ++ --capture_counter_; ++ return capture_counter_ == 0 ? StopCapture() : 0; ++ } ++ ++ private: ++ int32_t capture_counter_ = 0; +}; + - // simulate deviceInfo interface for video engine, bridge screen/application and - // real screen/application device info - -@@ -158,13 +174,13 @@ class BrowserDeviceInfoImpl : public VideoCaptureModule::DeviceInfo { + // Reuses the video engine pipeline for screen sharing. // As with video, DesktopCaptureImpl is a proxy for screen sharing // and follows the video pipeline design class DesktopCaptureImpl : public DesktopCapturer::Callback, @@ -1702,15 +1757,14 @@ index 7292f6c8a70298d4bf103080804843fa9bba1d15..7a50fee0d2fcaad475302d010892800a public: /* Create a screen capture modules object */ -- static VideoCaptureModule* Create( -+ static VideoCaptureModuleEx* Create( + static DesktopCaptureImpl* Create( const int32_t aModuleId, const char* aUniqueId, - const mozilla::camera::CaptureDeviceType aType); + const mozilla::camera::CaptureDeviceType aType, bool aCaptureCursor = true); [[nodiscard]] static std::shared_ptr CreateDeviceInfo(const int32_t aId, -@@ -178,6 +194,8 @@ class DesktopCaptureImpl : public DesktopCapturer::Callback, +@@ -66,6 +94,8 @@ class DesktopCaptureImpl : public DesktopCapturer::Callback, void DeRegisterCaptureDataCallback( rtc::VideoSinkInterface* aCallback) override; int32_t StopCaptureIfAllClientsClose() override; @@ -1719,7 +1773,7 @@ index 7292f6c8a70298d4bf103080804843fa9bba1d15..7a50fee0d2fcaad475302d010892800a int32_t SetCaptureRotation(VideoRotation aRotation) override; bool SetApplyRotation(bool aEnable) override; -@@ -200,7 +218,8 @@ class DesktopCaptureImpl : public DesktopCapturer::Callback, +@@ -89,7 +119,8 @@ class DesktopCaptureImpl : public DesktopCapturer::Callback, protected: DesktopCaptureImpl(const int32_t aId, const char* aUniqueId, @@ -1729,9 +1783,9 @@ index 7292f6c8a70298d4bf103080804843fa9bba1d15..7a50fee0d2fcaad475302d010892800a virtual ~DesktopCaptureImpl(); private: -@@ -208,6 +227,9 @@ class DesktopCaptureImpl : public DesktopCapturer::Callback, - static constexpr uint32_t kMaxDesktopCaptureCpuUsage = 50; +@@ -98,6 +129,9 @@ class DesktopCaptureImpl : public DesktopCapturer::Callback, void InitOnThread(std::unique_ptr aCapturer, int aFramerate); + void UpdateOnThread(int aFramerate); void ShutdownOnThread(); + + rtc::RecursiveCriticalSection mApiCs; @@ -1739,7 +1793,7 @@ index 7292f6c8a70298d4bf103080804843fa9bba1d15..7a50fee0d2fcaad475302d010892800a // DesktopCapturer::Callback interface. void OnCaptureResult(DesktopCapturer::Result aResult, std::unique_ptr aFrame) override; -@@ -215,6 +237,8 @@ class DesktopCaptureImpl : public DesktopCapturer::Callback, +@@ -105,6 +139,8 @@ class DesktopCaptureImpl : public DesktopCapturer::Callback, // Notifies all mCallbacks of OnFrame(). mCaptureThread only. void NotifyOnFrame(const VideoFrame& aFrame); @@ -1793,18 +1847,18 @@ index 3b39538e51840cd9b1685b2efd2ff2e9ec83608a..c7bf4f2d53b58bbacb22b3ebebf6f3fc return aGlobalOrNull; diff --git a/dom/security/nsCSPUtils.cpp b/dom/security/nsCSPUtils.cpp -index 11d09909f73fee425fd0f50b384c396a52e02a36..b0e668881bcd3b850de709ebf2557ae8391b8fe8 100644 +index 5ec21c1c7f975a372399748e8bab2b21ce347f20..ed16831e549afa3d6623398d35eb61e26ab5f2b0 100644 --- a/dom/security/nsCSPUtils.cpp +++ b/dom/security/nsCSPUtils.cpp -@@ -22,6 +22,7 @@ +@@ -23,6 +23,7 @@ #include "nsSandboxFlags.h" #include "nsServiceManagerUtils.h" #include "nsWhitespaceTokenizer.h" +#include "nsDocShell.h" + #include "mozilla/Assertions.h" #include "mozilla/Components.h" - #include "mozilla/dom/CSPDictionariesBinding.h" -@@ -132,6 +133,11 @@ void CSP_ApplyMetaCSPToDoc(mozilla::dom::Document& aDoc, +@@ -135,6 +136,11 @@ void CSP_ApplyMetaCSPToDoc(mozilla::dom::Document& aDoc, return; } @@ -1817,19 +1871,19 @@ index 11d09909f73fee425fd0f50b384c396a52e02a36..b0e668881bcd3b850de709ebf2557ae8 nsContentUtils::TrimWhitespace( aPolicyStr)); diff --git a/dom/webidl/GeometryUtils.webidl b/dom/webidl/GeometryUtils.webidl -index 2f71b284ee5f7e11f117c447834b48355784448c..2640bd57123c2b03bf4b06a2419cd020ba95f155 100644 +index aee376e971ae01ac1e512c3920b115bfaf06afa8..1701311534bf77e6cd9bafc0e3a283610476aa8f 100644 --- a/dom/webidl/GeometryUtils.webidl +++ b/dom/webidl/GeometryUtils.webidl -@@ -16,6 +16,8 @@ dictionary BoxQuadOptions { - GeometryNode relativeTo; - [ChromeOnly] +@@ -17,6 +17,8 @@ dictionary GeometryUtilsOptions { boolean createFramesForSuppressedWhitespace = true; + [ChromeOnly] + boolean flush = true; + [ChromeOnly] + boolean recurseWhenNoFrame = false; }; - dictionary ConvertCoordinateOptions { -@@ -27,6 +29,9 @@ interface mixin GeometryUtils { + dictionary BoxQuadOptions : GeometryUtilsOptions { +@@ -35,6 +37,9 @@ interface mixin GeometryUtils { [Throws, Func="nsINode::HasBoxQuadsSupport", NeedsCallerType] sequence getBoxQuads(optional BoxQuadOptions options = {}); @@ -1840,10 +1894,10 @@ index 2f71b284ee5f7e11f117c447834b48355784448c..2640bd57123c2b03bf4b06a2419cd020 * returned quads are further translated relative to the window * origin -- which is not the layout origin. Further translation diff --git a/dom/workers/RuntimeService.cpp b/dom/workers/RuntimeService.cpp -index 02efb1205382850b41c38d5f6ee47092adcdc63e..28c8d05d0b5cc415f3d13a4588248f3844faf4f2 100644 +index a23637c4a887b66a1b4c709a648762b84151bf01..d8da9063261482f1da3257e3f95a8a49d94325f8 100644 --- a/dom/workers/RuntimeService.cpp +++ b/dom/workers/RuntimeService.cpp -@@ -995,7 +995,7 @@ void PrefLanguagesChanged(const char* /* aPrefName */, void* /* aClosure */) { +@@ -1026,7 +1026,7 @@ void PrefLanguagesChanged(const char* /* aPrefName */, void* /* aClosure */) { AssertIsOnMainThread(); nsTArray languages; @@ -1852,7 +1906,7 @@ index 02efb1205382850b41c38d5f6ee47092adcdc63e..28c8d05d0b5cc415f3d13a4588248f38 RuntimeService* runtime = RuntimeService::GetService(); if (runtime) { -@@ -1182,8 +1182,7 @@ bool RuntimeService::RegisterWorker(WorkerPrivate& aWorkerPrivate) { +@@ -1214,8 +1214,7 @@ bool RuntimeService::RegisterWorker(WorkerPrivate& aWorkerPrivate) { } // The navigator overridden properties should have already been read. @@ -1862,7 +1916,7 @@ index 02efb1205382850b41c38d5f6ee47092adcdc63e..28c8d05d0b5cc415f3d13a4588248f38 mNavigatorPropertiesLoaded = true; } -@@ -1789,6 +1788,13 @@ void RuntimeService::PropagateStorageAccessPermissionGranted( +@@ -1836,6 +1835,13 @@ void RuntimeService::PropagateStorageAccessPermissionGranted( } } @@ -1876,7 +1930,7 @@ index 02efb1205382850b41c38d5f6ee47092adcdc63e..28c8d05d0b5cc415f3d13a4588248f38 template void RuntimeService::BroadcastAllWorkers(const Func& aFunc) { AssertIsOnMainThread(); -@@ -2304,6 +2310,14 @@ void PropagateStorageAccessPermissionGrantedToWorkers( +@@ -2361,6 +2367,14 @@ void PropagateStorageAccessPermissionGrantedToWorkers( } } @@ -1892,10 +1946,10 @@ index 02efb1205382850b41c38d5f6ee47092adcdc63e..28c8d05d0b5cc415f3d13a4588248f38 MOZ_ASSERT(!NS_IsMainThread()); MOZ_ASSERT(aCx); diff --git a/dom/workers/RuntimeService.h b/dom/workers/RuntimeService.h -index f51076ac1480794989999d00577bc9cf1566d5f9..fe15b2e00dc8f0bf203f2af9aad86e16c996d43d 100644 +index 534bbe9ec4f0261189eb3322c1229c1eb5d8802e..6aa99b64fdbbff3704602e944b129879fbdf8c15 100644 --- a/dom/workers/RuntimeService.h +++ b/dom/workers/RuntimeService.h -@@ -109,6 +109,8 @@ class RuntimeService final : public nsIObserver { +@@ -112,6 +112,8 @@ class RuntimeService final : public nsIObserver { void PropagateStorageAccessPermissionGranted( const nsPIDOMWindowInner& aWindow); @@ -1905,10 +1959,10 @@ index f51076ac1480794989999d00577bc9cf1566d5f9..fe15b2e00dc8f0bf203f2af9aad86e16 return mNavigatorProperties; } diff --git a/dom/workers/WorkerCommon.h b/dom/workers/WorkerCommon.h -index d10dabb5c5ff8e17851edf2bd2efc08e74584d8e..53c4070c5fde43b27fb8fbfdcf4c23d8af57fba3 100644 +index 58894a8361c7ef1dddd481ca5877a209a8b8ff5c..c481d40d79b6397b7f1d571bd9f6ae5c0a946217 100644 --- a/dom/workers/WorkerCommon.h +++ b/dom/workers/WorkerCommon.h -@@ -44,6 +44,8 @@ void ResumeWorkersForWindow(const nsPIDOMWindowInner& aWindow); +@@ -47,6 +47,8 @@ void ResumeWorkersForWindow(const nsPIDOMWindowInner& aWindow); void PropagateStorageAccessPermissionGrantedToWorkers( const nsPIDOMWindowInner& aWindow); @@ -1918,17 +1972,17 @@ index d10dabb5c5ff8e17851edf2bd2efc08e74584d8e..53c4070c5fde43b27fb8fbfdcf4c23d8 bool IsWorkerGlobal(JSObject* global); diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp -index a8643981aa966e9324a5dbdb09b4fe57210dc581..5120df2607584a7cd50ea03aa997ef5ade5c8ee2 100644 +index 5d918a82708a26125f7322e43f6436d7eafaa812..b230baead02e05d87a211c276066ec7939ea8251 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp -@@ -682,6 +682,18 @@ class UpdateContextOptionsRunnable final : public WorkerControlRunnable { +@@ -736,6 +736,18 @@ class UpdateContextOptionsRunnable final : public WorkerControlRunnable { } }; +class ResetDefaultLocaleRunnable final : public WorkerControlRunnable { + public: + explicit ResetDefaultLocaleRunnable(WorkerPrivate* aWorkerPrivate) -+ : WorkerControlRunnable(aWorkerPrivate, "ResetDefaultLocaleRunnable", WorkerThread) {} ++ : WorkerControlRunnable("ResetDefaultLocaleRunnable") {} + + virtual bool WorkerRun(JSContext* aCx, + WorkerPrivate* aWorkerPrivate) override { @@ -1937,10 +1991,10 @@ index a8643981aa966e9324a5dbdb09b4fe57210dc581..5120df2607584a7cd50ea03aa997ef5a + } +}; + - class UpdateLanguagesRunnable final : public WorkerRunnable { + class UpdateLanguagesRunnable final : public WorkerThreadRunnable { nsTArray mLanguages; -@@ -1993,6 +2005,16 @@ void WorkerPrivate::UpdateContextOptions( +@@ -2159,6 +2171,16 @@ void WorkerPrivate::UpdateContextOptions( } } @@ -1949,7 +2003,7 @@ index a8643981aa966e9324a5dbdb09b4fe57210dc581..5120df2607584a7cd50ea03aa997ef5a + + RefPtr runnable = + new ResetDefaultLocaleRunnable(this); -+ if (!runnable->Dispatch()) { ++ if (!runnable->Dispatch(this)) { + NS_WARNING("Failed to reset default locale in worker!"); + } +} @@ -1957,7 +2011,7 @@ index a8643981aa966e9324a5dbdb09b4fe57210dc581..5120df2607584a7cd50ea03aa997ef5a void WorkerPrivate::UpdateLanguages(const nsTArray& aLanguages) { AssertIsOnParentThread(); -@@ -5489,6 +5511,15 @@ void WorkerPrivate::UpdateContextOptionsInternal( +@@ -5946,6 +5968,15 @@ void WorkerPrivate::UpdateContextOptionsInternal( } } @@ -1974,10 +2028,10 @@ index a8643981aa966e9324a5dbdb09b4fe57210dc581..5120df2607584a7cd50ea03aa997ef5a const nsTArray& aLanguages) { WorkerGlobalScope* globalScope = GlobalScope(); diff --git a/dom/workers/WorkerPrivate.h b/dom/workers/WorkerPrivate.h -index a670d009759d101cf9574cde3c2481b8aa2737f6..ac87b7f27dfcc060adb52387b146c45eed996fa7 100644 +index 7bccdc8c0c2cd53f7aa7a6d9a74435344dd27980..86bba2128a7c0f4e5efa4bfbc939937aec146695 100644 --- a/dom/workers/WorkerPrivate.h +++ b/dom/workers/WorkerPrivate.h -@@ -417,6 +417,8 @@ class WorkerPrivate final +@@ -443,6 +443,8 @@ class WorkerPrivate final void UpdateContextOptionsInternal(JSContext* aCx, const JS::ContextOptions& aContextOptions); @@ -1986,7 +2040,7 @@ index a670d009759d101cf9574cde3c2481b8aa2737f6..ac87b7f27dfcc060adb52387b146c45e void UpdateLanguagesInternal(const nsTArray& aLanguages); void UpdateJSWorkerMemoryParameterInternal(JSContext* aCx, JSGCParamKey key, -@@ -1036,6 +1038,8 @@ class WorkerPrivate final +@@ -1091,6 +1093,8 @@ class WorkerPrivate final void UpdateContextOptions(const JS::ContextOptions& aContextOptions); @@ -2022,10 +2076,10 @@ index 7a069ef0c59895cf1f8dc35d612f1494c9c9f1ef..5b09dfdcc5323def65c35b0696141b44 Span aTimeZone) { #if MOZ_INTL_USE_ICU_CPP_TIMEZONE diff --git a/intl/components/src/TimeZone.h b/intl/components/src/TimeZone.h -index 9d0423ef13958d5c443cc3531269603c4801c338..f0c4ba7c528d2be466e0f7669a1e37e876f9091e 100644 +index 89770839ae108b5f3462a7f20684fdb72c4ab2fb..a7e40d6b7c33c234b41e586eac573ba4ce3a7d18 100644 --- a/intl/components/src/TimeZone.h +++ b/intl/components/src/TimeZone.h -@@ -190,6 +190,8 @@ class TimeZone final { +@@ -191,6 +191,8 @@ class TimeZone final { return FillBufferWithICUCall(aBuffer, ucal_getHostTimeZone); } @@ -2048,10 +2102,10 @@ index 523e84c8c93f4221701f90f2e8ee146ec8e1adbd..98d5b1176e5378431b859a2dbd4d4e77 inline ClippedTime TimeClip(double time); diff --git a/js/src/debugger/Object.cpp b/js/src/debugger/Object.cpp -index 17528b0fd99ce8274e702746ff5674de4c3d4f2d..37fa52ae07381bec3504136b9bec0aa1ca110d6b 100644 +index b7ea4b6f66d14db0324397cdc1b0ed8c5ea167e2..1c59e328079e7e43b65f7cb7bc31636a48a93263 100644 --- a/js/src/debugger/Object.cpp +++ b/js/src/debugger/Object.cpp -@@ -2468,7 +2468,11 @@ Maybe DebuggerObject::call(JSContext* cx, +@@ -2484,7 +2484,11 @@ Maybe DebuggerObject::call(JSContext* cx, invokeArgs[i].set(args2[i]); } @@ -2064,10 +2118,10 @@ index 17528b0fd99ce8274e702746ff5674de4c3d4f2d..37fa52ae07381bec3504136b9bec0aa1 } diff --git a/js/src/vm/DateTime.cpp b/js/src/vm/DateTime.cpp -index 21ecc2e9f50a16357ace3320335d31a4929fc146..c4b1444ce53b20a700d2ff9f18521bd67623e7d2 100644 +index a57b8fefa104f966393a99f5a81876b9a95f9743..adc42dd227e52643b06fb101170aeafb490c0acc 100644 --- a/js/src/vm/DateTime.cpp +++ b/js/src/vm/DateTime.cpp -@@ -186,6 +186,11 @@ void js::DateTimeInfo::internalResetTimeZone(ResetTimeZoneMode mode) { +@@ -185,6 +185,11 @@ void js::DateTimeInfo::internalResetTimeZone(ResetTimeZoneMode mode) { } } @@ -2079,7 +2133,7 @@ index 21ecc2e9f50a16357ace3320335d31a4929fc146..c4b1444ce53b20a700d2ff9f18521bd6 void js::DateTimeInfo::updateTimeZone() { MOZ_ASSERT(timeZoneStatus_ != TimeZoneStatus::Valid); -@@ -527,10 +532,24 @@ void js::ResetTimeZoneInternal(ResetTimeZoneMode mode) { +@@ -528,10 +533,24 @@ void js::ResetTimeZoneInternal(ResetTimeZoneMode mode) { js::DateTimeInfo::resetTimeZone(mode); } @@ -2104,7 +2158,7 @@ index 21ecc2e9f50a16357ace3320335d31a4929fc146..c4b1444ce53b20a700d2ff9f18521bd6 #if JS_HAS_INTL_API # if defined(XP_WIN) static bool IsOlsonCompatibleWindowsTimeZoneId(std::string_view tz) { -@@ -748,6 +767,15 @@ static bool ReadTimeZoneLink(std::string_view tz, +@@ -749,6 +768,15 @@ static bool ReadTimeZoneLink(std::string_view tz, void js::DateTimeInfo::internalResyncICUDefaultTimeZone() { #if JS_HAS_INTL_API @@ -2120,7 +2174,7 @@ index 21ecc2e9f50a16357ace3320335d31a4929fc146..c4b1444ce53b20a700d2ff9f18521bd6 // In the future we should not be setting a default ICU time zone at all, // instead all accesses should go through the appropriate DateTimeInfo // instance depending on the resist fingerprinting status. For now we return -@@ -759,7 +787,6 @@ void js::DateTimeInfo::internalResyncICUDefaultTimeZone() { +@@ -760,7 +788,6 @@ void js::DateTimeInfo::internalResyncICUDefaultTimeZone() { if (const char* tzenv = std::getenv("TZ")) { std::string_view tz(tzenv); @@ -2129,7 +2183,7 @@ index 21ecc2e9f50a16357ace3320335d31a4929fc146..c4b1444ce53b20a700d2ff9f18521bd6 # if defined(XP_WIN) diff --git a/js/src/vm/DateTime.h b/js/src/vm/DateTime.h -index fd6d7ae078b8f6b3cc46a4a993a1e044a7128c90..4743094e489122dd9ee8ab9a7a175dd7e928859d 100644 +index e3cf82daa3749664aa8ced7e6553b8c6434dfec8..b45b49c4f3bbf12853c4afb12de21d99ac88d77b 100644 --- a/js/src/vm/DateTime.h +++ b/js/src/vm/DateTime.h @@ -65,6 +65,8 @@ enum class ResetTimeZoneMode : bool { @@ -2141,7 +2195,7 @@ index fd6d7ae078b8f6b3cc46a4a993a1e044a7128c90..4743094e489122dd9ee8ab9a7a175dd7 /** * Stores date/time information, particularly concerning the current local * time zone, and implements a small cache for daylight saving time offset -@@ -225,6 +227,7 @@ class DateTimeInfo { +@@ -253,6 +255,7 @@ class DateTimeInfo { private: // The method below should only be called via js::ResetTimeZoneInternal(). friend void js::ResetTimeZoneInternal(ResetTimeZoneMode); @@ -2149,7 +2203,7 @@ index fd6d7ae078b8f6b3cc46a4a993a1e044a7128c90..4743094e489122dd9ee8ab9a7a175dd7 static void resetTimeZone(ResetTimeZoneMode mode) { { -@@ -321,6 +324,8 @@ class DateTimeInfo { +@@ -352,6 +355,8 @@ class DateTimeInfo { JS::UniqueChars locale_; JS::UniqueTwoByteChars standardName_; JS::UniqueTwoByteChars daylightSavingsName_; @@ -2158,7 +2212,7 @@ index fd6d7ae078b8f6b3cc46a4a993a1e044a7128c90..4743094e489122dd9ee8ab9a7a175dd7 #else // Restrict the data-time range to the minimum required time_t range as // specified in POSIX. Most operating systems support 64-bit time_t -@@ -336,6 +341,8 @@ class DateTimeInfo { +@@ -367,6 +372,8 @@ class DateTimeInfo { void internalResetTimeZone(ResetTimeZoneMode mode); @@ -2168,7 +2222,7 @@ index fd6d7ae078b8f6b3cc46a4a993a1e044a7128c90..4743094e489122dd9ee8ab9a7a175dd7 void internalResyncICUDefaultTimeZone(); diff --git a/layout/base/GeometryUtils.cpp b/layout/base/GeometryUtils.cpp -index dac899f7558b26d6848da8b98ed8a93555c8751a..2a07d67fa1c2840b25085566e84dc3b2d9b789cf 100644 +index 4bfd336ddcbee8004ac538ca7b7d8216d04a61c3..cd22351c4aeacea8afc9828972222aca1b3063bf 100644 --- a/layout/base/GeometryUtils.cpp +++ b/layout/base/GeometryUtils.cpp @@ -23,6 +23,7 @@ @@ -2179,18 +2233,18 @@ index dac899f7558b26d6848da8b98ed8a93555c8751a..2a07d67fa1c2840b25085566e84dc3b2 using namespace mozilla; using namespace mozilla::dom; -@@ -261,11 +262,27 @@ static bool CheckFramesInSameTopLevelBrowsingContext(nsIFrame* aFrame1, +@@ -265,10 +266,27 @@ static bool CheckFramesInSameTopLevelBrowsingContext(nsIFrame* aFrame1, return false; } -+static nsIFrame* GetFrameForNode(nsINode* aNode, -+ bool aCreateFramesForSuppressedWhitespace, ++static nsIFrame* GetFrameForNodeRecursive(nsINode* aNode, ++ const GeometryUtilsOptions& aOptions, + bool aRecurseWhenNoFrame) { -+ nsIFrame* frame = GetFrameForNode(aNode, aCreateFramesForSuppressedWhitespace); ++ nsIFrame* frame = GetFrameForNode(aNode, aOptions); + if (!frame && aRecurseWhenNoFrame && aNode->IsContent()) { + dom::FlattenedChildIterator iter(aNode->AsContent()); + for (nsIContent* child = iter.GetNextChild(); child; child = iter.GetNextChild()) { -+ frame = GetFrameForNode(child, aCreateFramesForSuppressedWhitespace, aRecurseWhenNoFrame); ++ frame = GetFrameForNodeRecursive(child, aOptions, aRecurseWhenNoFrame); + if (frame) { + break; + } @@ -2200,28 +2254,29 @@ index dac899f7558b26d6848da8b98ed8a93555c8751a..2a07d67fa1c2840b25085566e84dc3b2 +} + void GetBoxQuads(nsINode* aNode, const dom::BoxQuadOptions& aOptions, - nsTArray >& aResult, CallerType aCallerType, + nsTArray>& aResult, CallerType aCallerType, ErrorResult& aRv) { - nsIFrame* frame = -- GetFrameForNode(aNode, aOptions.mCreateFramesForSuppressedWhitespace); -+ GetFrameForNode(aNode, aOptions.mCreateFramesForSuppressedWhitespace, aOptions.mRecurseWhenNoFrame); +- nsIFrame* frame = GetFrameForNode(aNode, aOptions); ++ nsIFrame* frame = ++ GetFrameForNodeRecursive(aNode, aOptions, aOptions.mRecurseWhenNoFrame); if (!frame) { // No boxes to return return; -@@ -280,7 +297,7 @@ void GetBoxQuads(nsINode* aNode, const dom::BoxQuadOptions& aOptions, +@@ -281,7 +299,8 @@ void GetBoxQuads(nsINode* aNode, const dom::BoxQuadOptions& aOptions, + // EnsureFrameForTextNode call. We need to get the first frame again // when that happens and re-check it. if (!weakFrame.IsAlive()) { - frame = -- GetFrameForNode(aNode, aOptions.mCreateFramesForSuppressedWhitespace); -+ GetFrameForNode(aNode, aOptions.mCreateFramesForSuppressedWhitespace, aOptions.mRecurseWhenNoFrame); +- frame = GetFrameForNode(aNode, aOptions); ++ frame = ++ GetFrameForNodeRecursive(aNode, aOptions, aOptions.mRecurseWhenNoFrame); if (!frame) { // No boxes to return return; diff --git a/layout/base/PresShell.cpp b/layout/base/PresShell.cpp -index 31c21c337786b76306029149a925293a44c45c28..7aa4eb0b4980bb8ecdc4e10c91b1cd70e5d0ad08 100644 +index e8fb3a8304b27814e6e84355f24410c820667f9d..211c86fe55b8b650e40275a427b30a1ee8a9a3d7 100644 --- a/layout/base/PresShell.cpp +++ b/layout/base/PresShell.cpp -@@ -11127,7 +11127,9 @@ bool PresShell::ComputeActiveness() const { +@@ -11512,7 +11512,9 @@ bool PresShell::ComputeActiveness() const { if (!browserChild->IsVisible()) { MOZ_LOG(gLog, LogLevel::Debug, (" > BrowserChild %p is not visible", browserChild)); @@ -2232,11 +2287,36 @@ index 31c21c337786b76306029149a925293a44c45c28..7aa4eb0b4980bb8ecdc4e10c91b1cd70 } // If the browser is visible but just due to be preserving layers +diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp +index 315d532eab56dab13b6c8bc2380a5cda2a17ffc1..7c4552137149e8c7fc9ac08a09bd4242952b53b6 100644 +--- a/layout/base/nsLayoutUtils.cpp ++++ b/layout/base/nsLayoutUtils.cpp +@@ -708,6 +708,10 @@ bool nsLayoutUtils::AllowZoomingForDocument( + !aDocument->GetPresShell()->AsyncPanZoomEnabled()) { + return false; + } ++ ++ /* Playwright: disable zooming as we don't support meta viewport tag */ ++ if (1 == 1) return false; ++ + // True if we allow zooming for all documents on this platform, or if we are + // in RDM. + BrowsingContext* bc = aDocument->GetBrowsingContext(); +@@ -9770,6 +9774,9 @@ void nsLayoutUtils::ComputeSystemFont(nsFont* aSystemFont, + + /* static */ + bool nsLayoutUtils::ShouldHandleMetaViewport(const Document* aDocument) { ++ /* Playwright: disable meta viewport handling since we don't require one */ ++ if (1 == 1) return false; ++ + BrowsingContext* bc = aDocument->GetBrowsingContext(); + return StaticPrefs::dom_meta_viewport_enabled() || (bc && bc->InRDMPane()); + } diff --git a/layout/style/GeckoBindings.h b/layout/style/GeckoBindings.h -index 7bb839ae18835d128dc9285b7f9dc5b5e06335af..09e3979d07447522ace740daf2b818a6c551ceba 100644 +index c7cf59c2661c7e203384c9b82789879f756b44b7..21e32dab4e60112c073bdd5070a308da2b4e0373 100644 --- a/layout/style/GeckoBindings.h +++ b/layout/style/GeckoBindings.h -@@ -625,6 +625,7 @@ float Gecko_MediaFeatures_GetResolution(const mozilla::dom::Document*); +@@ -596,6 +596,7 @@ float Gecko_MediaFeatures_GetResolution(const mozilla::dom::Document*); bool Gecko_MediaFeatures_PrefersReducedMotion(const mozilla::dom::Document*); bool Gecko_MediaFeatures_PrefersReducedTransparency( const mozilla::dom::Document*); @@ -2245,10 +2325,10 @@ index 7bb839ae18835d128dc9285b7f9dc5b5e06335af..09e3979d07447522ace740daf2b818a6 const mozilla::dom::Document*); mozilla::StylePrefersColorScheme Gecko_MediaFeatures_PrefersColorScheme( diff --git a/layout/style/nsMediaFeatures.cpp b/layout/style/nsMediaFeatures.cpp -index f888c127d4423336a8f51e2011fc42eaf6c33f11..51d6e069f4a81c42b4bf270ba44ae4f82b8df592 100644 +index ca382a3cfba8ce5839890d6e4cb3cf9789287e3b..5800fc23dc77ee5764beddd6fa48a7fd701d2939 100644 --- a/layout/style/nsMediaFeatures.cpp +++ b/layout/style/nsMediaFeatures.cpp -@@ -260,11 +260,11 @@ bool Gecko_MediaFeatures_MatchesPlatform(StylePlatform aPlatform) { +@@ -264,11 +264,7 @@ bool Gecko_MediaFeatures_MatchesPlatform(StylePlatform aPlatform) { } bool Gecko_MediaFeatures_PrefersReducedMotion(const Document* aDocument) { @@ -2258,28 +2338,45 @@ index f888c127d4423336a8f51e2011fc42eaf6c33f11..51d6e069f4a81c42b4bf270ba44ae4f8 - } - return LookAndFeel::GetInt(LookAndFeel::IntID::PrefersReducedMotion, 0) == 1; + return aDocument->PrefersReducedMotion(); -+} -+ -+bool Gecko_MediaFeatures_ForcedColors(const Document* aDocument) { -+ return aDocument->ForcedColors(); } bool Gecko_MediaFeatures_PrefersReducedTransparency(const Document* aDocument) { +@@ -293,6 +289,20 @@ StylePrefersColorScheme Gecko_MediaFeatures_PrefersColorScheme( + // as a signal. + StylePrefersContrast Gecko_MediaFeatures_PrefersContrast( + const Document* aDocument) { ++ if (auto* bc = aDocument->GetBrowsingContext()) { ++ switch (bc->Top()->PrefersContrastOverride()) { ++ case dom::PrefersContrastOverride::No_preference: ++ return StylePrefersContrast::NoPreference; ++ case dom::PrefersContrastOverride::Less: ++ return StylePrefersContrast::Less; ++ case dom::PrefersContrastOverride::More: ++ return StylePrefersContrast::More; ++ case dom::PrefersContrastOverride::Custom: ++ return StylePrefersContrast::Custom; ++ } ++ } ++ ++ + if (aDocument->ShouldResistFingerprinting(RFPTarget::CSSPrefersContrast)) { + return StylePrefersContrast::NoPreference; + } diff --git a/netwerk/base/LoadInfo.cpp b/netwerk/base/LoadInfo.cpp -index eb90324c37ce515e5a0fcf75412605ae57ead9ee..6733dd6c99d77399529945386caa3926960e4176 100644 +index 1ec2c64193206d31702e22e5c4783f084b1cff31..fb463eb12ee39cd1e448369f3b47fbcfbb2473b9 100644 --- a/netwerk/base/LoadInfo.cpp +++ b/netwerk/base/LoadInfo.cpp -@@ -653,7 +653,8 @@ LoadInfo::LoadInfo(const LoadInfo& rhs) - mInterceptionInfo(rhs.mInterceptionInfo), - mHasInjectedCookieForCookieBannerHandling( +@@ -696,7 +696,8 @@ LoadInfo::LoadInfo(const LoadInfo& rhs) rhs.mHasInjectedCookieForCookieBannerHandling), -- mWasSchemelessInput(rhs.mWasSchemelessInput) { -+ mWasSchemelessInput(rhs.mWasSchemelessInput), + mSchemelessInput(rhs.mSchemelessInput), + mHttpsUpgradeTelemetry(rhs.mHttpsUpgradeTelemetry), +- mIsNewWindowTarget(rhs.mIsNewWindowTarget) { ++ mIsNewWindowTarget(rhs.mIsNewWindowTarget), + mJugglerLoadIdentifier(rhs.mJugglerLoadIdentifier) { } LoadInfo::LoadInfo( -@@ -2369,4 +2370,16 @@ LoadInfo::SetWasSchemelessInput(bool aWasSchemelessInput) { +@@ -2534,4 +2535,16 @@ LoadInfo::SetSkipHTTPSUpgrade(bool aSkipHTTPSUpgrade) { return NS_OK; } @@ -2297,23 +2394,23 @@ index eb90324c37ce515e5a0fcf75412605ae57ead9ee..6733dd6c99d77399529945386caa3926 + } // namespace mozilla::net diff --git a/netwerk/base/LoadInfo.h b/netwerk/base/LoadInfo.h -index a8631b09b26708ca10f683f1a9dd6b8467d3fe8e..a0bd72113e3539d815d32382946581ee62f39b6c 100644 +index 93cc8d3630f7029303240555ae72d41b68047375..8a09863af399e25ba3f01caff2f6b3af1260e8b8 100644 --- a/netwerk/base/LoadInfo.h +++ b/netwerk/base/LoadInfo.h -@@ -401,6 +401,8 @@ class LoadInfo final : public nsILoadInfo { +@@ -426,6 +426,8 @@ class LoadInfo final : public nsILoadInfo { - bool mHasInjectedCookieForCookieBannerHandling = false; - bool mWasSchemelessInput = false; + bool mIsNewWindowTarget = false; + bool mSkipHTTPSUpgrade = false; + + uint64_t mJugglerLoadIdentifier = 0; }; // This is exposed solely for testing purposes and should not be used outside of diff --git a/netwerk/base/TRRLoadInfo.cpp b/netwerk/base/TRRLoadInfo.cpp -index 920e7623a7f912296fc23361f66ab35a30c35f1e..dfea0d0f7a72da9699615d7ff778e429e7ae40fb 100644 +index d1650595f8cf28a704f94a99c1f6bfe1deb9cc77..2072a3990ff6f4496626dcebb277291ad845cac3 100644 --- a/netwerk/base/TRRLoadInfo.cpp +++ b/netwerk/base/TRRLoadInfo.cpp -@@ -861,5 +861,15 @@ TRRLoadInfo::SetWasSchemelessInput(bool aWasSchemelessInput) { +@@ -950,5 +950,15 @@ TRRLoadInfo::GetFetchDestination(nsACString& aDestination) { return NS_ERROR_NOT_IMPLEMENTED; } @@ -2330,48 +2427,63 @@ index 920e7623a7f912296fc23361f66ab35a30c35f1e..dfea0d0f7a72da9699615d7ff778e429 } // namespace net } // namespace mozilla diff --git a/netwerk/base/nsILoadInfo.idl b/netwerk/base/nsILoadInfo.idl -index ddfcb223e6126c943b58e9d198f0e2fa767c3de1..4280b836c55e5778ad4c94226ea537facb19c436 100644 +index 774ec045c0b18310e8cb86e8a9d6b1788d028435..cbf303a0ed872c27d580b4b6615f3dd9c76a8a19 100644 --- a/netwerk/base/nsILoadInfo.idl +++ b/netwerk/base/nsILoadInfo.idl -@@ -1532,4 +1532,6 @@ interface nsILoadInfo : nsISupports - * Whether the load has gone through the URL bar, where the fixup had to add * the protocol scheme. - */ - [infallible] attribute boolean wasSchemelessInput; +@@ -1626,4 +1626,6 @@ interface nsILoadInfo : nsISupports + return static_cast(userNavigationInvolvement); + } + %} + + [infallible] attribute unsigned long long jugglerLoadIdentifier; }; diff --git a/netwerk/base/nsINetworkInterceptController.idl b/netwerk/base/nsINetworkInterceptController.idl -index 155daa5cd52c4e93e1cc4559875868f4faf2c37e..02e8a2614a27a4cc9e1de760d4c48617eba25d4d 100644 +index 7f91d2df6f8bb4020c75c132dc8f6bf26625fa1e..aaa5541a17039d6b13ad83ab176fdaaf79edb2a0 100644 --- a/netwerk/base/nsINetworkInterceptController.idl +++ b/netwerk/base/nsINetworkInterceptController.idl -@@ -59,6 +59,7 @@ interface nsIInterceptedChannel : nsISupports - * results in the resulting client not being controlled. +@@ -60,6 +60,16 @@ interface nsIInterceptedChannel : nsISupports */ void resetInterception(in boolean bypass); -+ void resetInterceptionWithURI(in nsIURI aURI); ++ // ----- Playwright begin ----- ++ ++ // Same as resetInterception, but updates the URI. ++ void resetInterceptionWithURI(in nsIURI aURI); ++ ++ // After resetInterception is called, this request will be intercepted again. ++ void interceptAfterServiceWorkerResets(); ++ ++ // ----- Playwright end ------- ++ /** * Set the status and reason for the forthcoming synthesized response. + * Multiple calls overwrite existing values. diff --git a/netwerk/ipc/DocumentLoadListener.cpp b/netwerk/ipc/DocumentLoadListener.cpp -index d849eab7507f0665a8a79a1b11759afa3481f1ad..3a95d5201a1c1f2161a95e15beae86f2833a875f 100644 +index 771ae1fbe3d54aa25443eea675cf3abd26a21ce9..a916cb49c16dc6c7809ccbb7c8d4172446a5ac07 100644 --- a/netwerk/ipc/DocumentLoadListener.cpp +++ b/netwerk/ipc/DocumentLoadListener.cpp -@@ -167,6 +167,7 @@ static auto CreateDocumentLoadInfo(CanonicalBrowsingContext* aBrowsingContext, - loadInfo->SetHasValidUserGestureActivation( - aLoadState->HasValidUserGestureActivation()); +@@ -177,6 +177,7 @@ static auto CreateDocumentLoadInfo(CanonicalBrowsingContext* aBrowsingContext, + loadInfo->SetTextDirectiveUserActivation( + aLoadState->GetTextDirectiveUserActivation()); loadInfo->SetIsMetaRefresh(aLoadState->IsMetaRefresh()); + loadInfo->SetJugglerLoadIdentifier(aLoadState->GetLoadIdentifier()); return loadInfo.forget(); } diff --git a/netwerk/protocol/http/InterceptedHttpChannel.cpp b/netwerk/protocol/http/InterceptedHttpChannel.cpp -index c58fbc96391f8dcb585bd00b5ae8cba9088abd82..c121c891b61c9d60df770020c4ad09521d2bbfe6 100644 +index fbf4bdf1e24d1102df113984be6c8dc3a7d0d810..787bf014d3bf0b8537f99bf5eb4074e100c78c18 100644 --- a/netwerk/protocol/http/InterceptedHttpChannel.cpp +++ b/netwerk/protocol/http/InterceptedHttpChannel.cpp -@@ -727,6 +727,14 @@ NS_IMPL_ISUPPORTS(ResetInterceptionHeaderVisitor, nsIHttpHeaderVisitor) +@@ -728,10 +728,33 @@ NS_IMPL_ISUPPORTS(ResetInterceptionHeaderVisitor, nsIHttpHeaderVisitor) } // anonymous namespace ++NS_IMETHODIMP ++InterceptedHttpChannel::InterceptAfterServiceWorkerResets() { ++ mInterceptAfterServiceWorkerResets = true; ++ return NS_OK; ++} ++ +NS_IMETHODIMP +InterceptedHttpChannel::ResetInterceptionWithURI(nsIURI* aURI) { + if (aURI) { @@ -2383,7 +2495,20 @@ index c58fbc96391f8dcb585bd00b5ae8cba9088abd82..c121c891b61c9d60df770020c4ad0952 NS_IMETHODIMP InterceptedHttpChannel::ResetInterception(bool aBypass) { INTERCEPTED_LOG(("InterceptedHttpChannel::ResetInterception [%p] bypass: %s", -@@ -1140,11 +1148,18 @@ InterceptedHttpChannel::OnStartRequest(nsIRequest* aRequest) { + this, aBypass ? "true" : "false")); ++ if (mInterceptAfterServiceWorkerResets) { ++ mInterceptAfterServiceWorkerResets = false; ++ nsCOMPtr controller; ++ GetCallback(controller); ++ if (!controller) ++ return NS_ERROR_DOM_INVALID_STATE_ERR; ++ return controller->ChannelIntercepted(this); ++ } ++ + if (mCanceled) { + return mStatus; + } +@@ -1146,11 +1169,18 @@ InterceptedHttpChannel::OnStartRequest(nsIRequest* aRequest) { GetCallback(mProgressSink); } @@ -2402,11 +2527,151 @@ index c58fbc96391f8dcb585bd00b5ae8cba9088abd82..c121c891b61c9d60df770020c4ad0952 if (mPump && mLoadFlags & LOAD_CALL_CONTENT_SNIFFERS) { mPump->PeekStream(CallTypeSniffers, static_cast(this)); +diff --git a/netwerk/protocol/http/InterceptedHttpChannel.h b/netwerk/protocol/http/InterceptedHttpChannel.h +index 704404c9f094640ad63b685d64bd5a396e733e4b..92bdc21b4d6a015cc2f2bb22781ec6750c7789ec 100644 +--- a/netwerk/protocol/http/InterceptedHttpChannel.h ++++ b/netwerk/protocol/http/InterceptedHttpChannel.h +@@ -90,6 +90,11 @@ class InterceptedHttpChannel final + Atomic mCallingStatusAndProgress; + bool mInterceptionReset{false}; + ++ // ----- Playwright begin ----- ++ // After resetInterception is called, this request will call into interceptors again. ++ bool mInterceptAfterServiceWorkerResets{false}; ++ // ----- Playwright end ------- ++ + /** + * InterceptionTimeStamps is used to record the time stamps of the + * interception. +diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp +index e4479400a4c574f652befbee7d83bd664aa2b840..2761dce9477f7f1622a82fe1da6472597ae82534 100644 +--- a/netwerk/protocol/http/nsHttpChannel.cpp ++++ b/netwerk/protocol/http/nsHttpChannel.cpp +@@ -688,11 +688,9 @@ nsresult nsHttpChannel::OnBeforeConnect() { + // SecurityInfo.sys.mjs + mLoadInfo->SetHstsStatus(isSecureURI); + +- RefPtr bc; +- mLoadInfo->GetBrowsingContext(getter_AddRefs(bc)); + // If bypassing the cache and we're forced offline + // we can just return the error here. +- if (bc && bc->Top()->GetForceOffline() && ++ if (IsForcedOffline() && + BYPASS_LOCAL_CACHE(mLoadFlags, LoadPreferCacheLoadOverBypass())) { + return NS_ERROR_OFFLINE; + } +@@ -805,9 +803,7 @@ nsresult nsHttpChannel::MaybeUseHTTPSRRForUpgrade(bool aShouldUpgrade, + return aStatus; + } + +- RefPtr bc; +- mLoadInfo->GetBrowsingContext(getter_AddRefs(bc)); +- bool forceOffline = bc && bc->Top()->GetForceOffline(); ++ bool forceOffline = IsForcedOffline(); + + if (mURI->SchemeIs("https") || aShouldUpgrade || !LoadUseHTTPSSVC() || + forceOffline) { +@@ -1266,15 +1262,14 @@ nsresult nsHttpChannel::ContinueConnect() { + "CORS preflight must have been finished by the time we " + "do the rest of ContinueConnect"); + +- RefPtr bc; +- mLoadInfo->GetBrowsingContext(getter_AddRefs(bc)); ++ bool isForcedOffline = IsForcedOffline(); + + // we may or may not have a cache entry at this point + if (mCacheEntry) { + // read straight from the cache if possible... + if (CachedContentIsValid()) { + // If we're forced offline, and set to bypass the cache, return offline. +- if (bc && bc->Top()->GetForceOffline() && ++ if (isForcedOffline && + BYPASS_LOCAL_CACHE(mLoadFlags, LoadPreferCacheLoadOverBypass())) { + return NS_ERROR_OFFLINE; + } +@@ -1316,7 +1311,7 @@ nsresult nsHttpChannel::ContinueConnect() { + } + + // We're about to hit the network. Don't if we're forced offline. +- if (bc && bc->Top()->GetForceOffline()) { ++ if (isForcedOffline) { + return NS_ERROR_OFFLINE; + } + +@@ -1421,12 +1416,9 @@ void nsHttpChannel::SpeculativeConnect() { + // don't speculate if we are offline, when doing http upgrade (i.e. + // websockets bootstrap), or if we can't do keep-alive (because then we + // couldn't reuse the speculative connection anyhow). +- RefPtr bc; +- mLoadInfo->GetBrowsingContext(getter_AddRefs(bc)); +- + if (gIOService->IsOffline() || mUpgradeProtocolCallback || + !(mCaps & NS_HTTP_ALLOW_KEEPALIVE) || +- (bc && bc->Top()->GetForceOffline())) { ++ IsForcedOffline()) { + return; + } + +@@ -4214,9 +4206,6 @@ nsresult nsHttpChannel::OpenCacheEntryInternal(bool isHttps) { + uint32_t cacheEntryOpenFlags; + bool offline = gIOService->IsOffline(); + +- RefPtr bc; +- mLoadInfo->GetBrowsingContext(getter_AddRefs(bc)); +- + bool maybeRCWN = false; + + nsAutoCString cacheControlRequestHeader; +@@ -4227,7 +4216,7 @@ nsresult nsHttpChannel::OpenCacheEntryInternal(bool isHttps) { + return NS_OK; + } + +- bool forceOffline = bc && bc->Top()->GetForceOffline(); ++ bool forceOffline = IsForcedOffline(); + if (offline || (mLoadFlags & INHIBIT_CACHING) || forceOffline) { + if (BYPASS_LOCAL_CACHE(mLoadFlags, LoadPreferCacheLoadOverBypass()) && + !offline && !forceOffline) { +@@ -7300,6 +7289,20 @@ void nsHttpChannel::MaybeStartDNSPrefetch() { + } + } + ++bool nsHttpChannel::IsForcedOffline() { ++ RefPtr bc; ++ mLoadInfo->GetBrowsingContext(getter_AddRefs(bc)); ++ if (bc && bc->Top()->GetForceOffline()) ++ return true; ++ ++ RefPtr wbc; ++ mLoadInfo->GetWorkerAssociatedBrowsingContext(getter_AddRefs(wbc)); ++ if (wbc && wbc->Top()->GetForceOffline()) ++ return true; ++ ++ return false; ++} ++ + NS_IMETHODIMP + nsHttpChannel::GetEncodedBodySize(uint64_t* aEncodedBodySize) { + if (mCacheEntry && !LoadCacheEntryIsWriteOnly()) { +diff --git a/netwerk/protocol/http/nsHttpChannel.h b/netwerk/protocol/http/nsHttpChannel.h +index cb8b8b7406411edceb30aa53c9b9007a38058f84..ebdc5384ca20feda399b70532a3036174f1a7431 100644 +--- a/netwerk/protocol/http/nsHttpChannel.h ++++ b/netwerk/protocol/http/nsHttpChannel.h +@@ -307,6 +307,10 @@ class nsHttpChannel final : public HttpBaseChannel, + void MaybeResolveProxyAndBeginConnect(); + void MaybeStartDNSPrefetch(); + ++ // ---- Playwright begin ++ bool IsForcedOffline(); ++ // ---- Playwright end ++ + // Based on the proxy configuration determine the strategy for resolving the + // end server host name. + ProxyDNSStrategy GetProxyDNSStrategy(); diff --git a/parser/html/nsHtml5TreeOpExecutor.cpp b/parser/html/nsHtml5TreeOpExecutor.cpp -index f2c47c42a6b6448ede3a6fef1510a3982336d5af..9e35df57102c93238de2e4d548bbe1205d227f3b 100644 +index d3b44cc62d3df49bbf842356cbdb153c82c3163c..23cf9bc83fb1faaf1c7406331b78e522b307cbf0 100644 --- a/parser/html/nsHtml5TreeOpExecutor.cpp +++ b/parser/html/nsHtml5TreeOpExecutor.cpp -@@ -1382,6 +1382,10 @@ void nsHtml5TreeOpExecutor::UpdateReferrerInfoFromMeta( +@@ -1349,6 +1349,10 @@ void nsHtml5TreeOpExecutor::UpdateReferrerInfoFromMeta( void nsHtml5TreeOpExecutor::AddSpeculationCSP(const nsAString& aCSP) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); @@ -2418,10 +2683,10 @@ index f2c47c42a6b6448ede3a6fef1510a3982336d5af..9e35df57102c93238de2e4d548bbe120 nsCOMPtr preloadCsp = mDocument->GetPreloadCsp(); if (!preloadCsp) { diff --git a/security/manager/ssl/nsCertOverrideService.cpp b/security/manager/ssl/nsCertOverrideService.cpp -index b8d0bbc3a12f74c19284b26eadada361abeb7946..a50379c57158748684e2ea5065550af81c1e9b86 100644 +index 8413eb5916f1f857e18972a14292d14f32684aee..66a3c7b01fdc56c29d789ff786aa91d8b0f02cd6 100644 --- a/security/manager/ssl/nsCertOverrideService.cpp +++ b/security/manager/ssl/nsCertOverrideService.cpp -@@ -438,7 +438,12 @@ nsCertOverrideService::HasMatchingOverride( +@@ -433,7 +433,12 @@ nsCertOverrideService::HasMatchingOverride( bool disableAllSecurityCheck = false; { MutexAutoLock lock(mMutex); @@ -2435,7 +2700,7 @@ index b8d0bbc3a12f74c19284b26eadada361abeb7946..a50379c57158748684e2ea5065550af8 } if (disableAllSecurityCheck) { *aIsTemporary = false; -@@ -650,14 +655,24 @@ static bool IsDebugger() { +@@ -645,14 +650,24 @@ static bool IsDebugger() { NS_IMETHODIMP nsCertOverrideService:: @@ -2491,10 +2756,10 @@ index 6dfd07d6b676a99993408921de8dea9d561f201d..e3c6794363cd6336effbeac83a179f37 readonly attribute boolean securityCheckDisabled; }; diff --git a/services/settings/Utils.sys.mjs b/services/settings/Utils.sys.mjs -index 73c83e526be1a3a252f995d0718e3975d50bffa7..db5977c54221e19e107a8325a0834302c2e84546 100644 +index d3643aedf21a26594268a47bc0f6ac53e3977f75..795c6f3b28278b9f65a596799d4e424880fcffa7 100644 --- a/services/settings/Utils.sys.mjs +++ b/services/settings/Utils.sys.mjs -@@ -95,7 +95,7 @@ function _isUndefined(value) { +@@ -97,7 +97,7 @@ const _cdnURLs = {}; export var Utils = { get SERVER_URL() { @@ -2503,7 +2768,7 @@ index 73c83e526be1a3a252f995d0718e3975d50bffa7..db5977c54221e19e107a8325a0834302 ? lazy.gServerURL : AppConstants.REMOTE_SETTINGS_SERVER_URL; }, -@@ -108,6 +108,9 @@ export var Utils = { +@@ -110,6 +110,9 @@ export var Utils = { log, get shouldSkipRemoteActivityDueToTests() { @@ -2513,31 +2778,8 @@ index 73c83e526be1a3a252f995d0718e3975d50bffa7..db5977c54221e19e107a8325a0834302 return ( (lazy.isRunningTests || Cu.isInAutomation) && this.SERVER_URL == "data:,#remote-settings-dummy/v1" -diff --git a/servo/components/style/gecko/media_features.rs b/servo/components/style/gecko/media_features.rs -index 8de45d95c2b942f069c898c93702bc7db2219369..be72e9678c3de31b1eaa72cfcb2c8be886f4a80f 100644 ---- a/servo/components/style/gecko/media_features.rs -+++ b/servo/components/style/gecko/media_features.rs -@@ -292,10 +292,15 @@ pub enum ForcedColors { - - /// https://drafts.csswg.org/mediaqueries-5/#forced-colors - fn eval_forced_colors(context: &Context, query_value: Option) -> bool { -- let forced = !context.device().use_document_colors(); -+ let prefers_forced_colors = -+ unsafe { bindings::Gecko_MediaFeatures_ForcedColors(context.device().document()) }; -+ let query_value = match query_value { -+ Some(v) => v, -+ None => return prefers_forced_colors, -+ }; - match query_value { -- Some(query_value) => forced == (query_value == ForcedColors::Active), -- None => forced, -+ ForcedColors::Active => prefers_forced_colors, -+ ForcedColors::None => !prefers_forced_colors, - } - } - diff --git a/toolkit/components/browser/nsIWebBrowserChrome.idl b/toolkit/components/browser/nsIWebBrowserChrome.idl -index 517c87a285dd93220cb2654d6ba7bb05c66cdeb7..e3010421d8dbe5ed5ed72feedb9f15805b32503e 100644 +index 75555352b8a15a50e4a21e34fc8ede4e9246c7cc..72855a404effa42b6c55cd0c2fcb8bdd6c2b3f9f 100644 --- a/toolkit/components/browser/nsIWebBrowserChrome.idl +++ b/toolkit/components/browser/nsIWebBrowserChrome.idl @@ -74,6 +74,9 @@ interface nsIWebBrowserChrome : nsISupports @@ -2551,27 +2793,58 @@ index 517c87a285dd93220cb2654d6ba7bb05c66cdeb7..e3010421d8dbe5ed5ed72feedb9f1580 // ignored for Linux. const unsigned long CHROME_SUPPRESS_ANIMATION = 1 << 24; diff --git a/toolkit/components/enterprisepolicies/EnterprisePoliciesParent.sys.mjs b/toolkit/components/enterprisepolicies/EnterprisePoliciesParent.sys.mjs -index 15fa2193c6116b5bd0cf2ee608eb5971f3d24370..aa92eb63b8f907e0df9ef8df60fd076aa3d6a472 100644 +index 76fb919603e8d2b7864d351eb47be2a38e40e31e..9f1e880fe9027d1a2540ffeaa11fc0c4e1a36133 100644 --- a/toolkit/components/enterprisepolicies/EnterprisePoliciesParent.sys.mjs +++ b/toolkit/components/enterprisepolicies/EnterprisePoliciesParent.sys.mjs -@@ -108,6 +108,12 @@ EnterprisePoliciesManager.prototype = { +@@ -108,7 +108,9 @@ EnterprisePoliciesManager.prototype = { Services.prefs.clearUserPref(PREF_POLICIES_APPLIED); } -+ // Playwright: Disable enterprise policies -+ if (true) { -+ this.status = Ci.nsIEnterprisePolicies.INACTIVE; -+ return; -+ } -+ - let provider = this._chooseProvider(); +- let provider = this._chooseProvider(); ++ // --- Playwright begin --- ++ let provider = new PlaywrightPoliciesProvider(); ++ // --- Playwright end --- if (provider.failed) { + this.status = Ci.nsIEnterprisePolicies.FAILED; +@@ -631,6 +633,19 @@ class JSONPoliciesProvider { + } + } + ++class PlaywrightPoliciesProvider extends JSONPoliciesProvider { ++ _getConfigurationFile() { ++ let prefPath = Services.prefs.getStringPref(PREF_ALTERNATE_PATH, ""); ++ if (!prefPath) ++ return null; ++ ++ dump(`Playwright: loading enterprise policies from ${prefPath}\n`); ++ let configFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); ++ configFile.initWithPath(prefPath); ++ return configFile; ++ } ++} ++ + class WindowsGPOPoliciesProvider { + constructor() { + this._policies = null; +diff --git a/toolkit/components/resistfingerprinting/nsUserCharacteristics.cpp b/toolkit/components/resistfingerprinting/nsUserCharacteristics.cpp +index 253171bed4dea54fc28bb4ddc9920823dbd9351c..6dc0e620b399ed9ee6b53f97bc080ec17ee4e1b5 100644 +--- a/toolkit/components/resistfingerprinting/nsUserCharacteristics.cpp ++++ b/toolkit/components/resistfingerprinting/nsUserCharacteristics.cpp +@@ -490,7 +490,7 @@ void PopulateLanguages() { + // sufficient to only collect this information as the other properties are + // just reformats of Navigator::GetAcceptLanguages. + nsTArray languages; +- dom::Navigator::GetAcceptLanguages(languages); ++ dom::Navigator::GetAcceptLanguages(nullptr, languages); + nsCString output = "["_ns; + + for (const auto& language : languages) { diff --git a/toolkit/components/startup/nsAppStartup.cpp b/toolkit/components/startup/nsAppStartup.cpp -index 3314cb813f6ceb67096eeda0864ad3b16c0616cb..5aac63649e186d624a9905a5d16513f8353f5515 100644 +index dc0826f72134b91482e30d183ddf52e95146e12f..119a324e162b6965ddd3d6b2d53bd2856a174452 100644 --- a/toolkit/components/startup/nsAppStartup.cpp +++ b/toolkit/components/startup/nsAppStartup.cpp -@@ -371,7 +371,7 @@ nsAppStartup::Quit(uint32_t aMode, int aExitCode, bool* aUserAllowedQuit) { +@@ -361,7 +361,7 @@ nsAppStartup::Quit(uint32_t aMode, int aExitCode, bool* aUserAllowedQuit) { nsCOMPtr windowEnumerator; nsCOMPtr mediator( do_GetService(NS_WINDOWMEDIATOR_CONTRACTID)); @@ -2596,10 +2869,10 @@ index 654903fadb709be976b72f36f155e23bc0622152..815b3dc24c9fda6b1db6c4666ac68904 int32_t aMaxSelfProgress, int32_t aCurTotalProgress, diff --git a/toolkit/components/windowwatcher/nsWindowWatcher.cpp b/toolkit/components/windowwatcher/nsWindowWatcher.cpp -index 209af157a35cf9c4586424421ee19b3f680796b6..1feb61e2f18e9a13631addc935f00da07739291e 100644 +index 811fb16410e8cf900ad873797269e5fe715579a5..821f5b0c2af8e1dc8754cd023571d1d0ff09eeb6 100644 --- a/toolkit/components/windowwatcher/nsWindowWatcher.cpp +++ b/toolkit/components/windowwatcher/nsWindowWatcher.cpp -@@ -1853,7 +1853,11 @@ uint32_t nsWindowWatcher::CalculateChromeFlagsForContent( +@@ -1880,7 +1880,11 @@ uint32_t nsWindowWatcher::CalculateChromeFlagsForContent( // Open a minimal popup. *aIsPopupRequested = true; @@ -2613,23 +2886,23 @@ index 209af157a35cf9c4586424421ee19b3f680796b6..1feb61e2f18e9a13631addc935f00da0 /** diff --git a/toolkit/mozapps/update/UpdateService.sys.mjs b/toolkit/mozapps/update/UpdateService.sys.mjs -index 34bf1b9e19ae54f78d134b023af96820bc13a905..b85793edcd1996833420a026cb08706d648ece14 100644 +index 40f04aeace0efd701e9454bb8dc6260dec90807e..5b70f65f3e78fc0889b15651ff203bb82e79d202 100644 --- a/toolkit/mozapps/update/UpdateService.sys.mjs +++ b/toolkit/mozapps/update/UpdateService.sys.mjs -@@ -3852,6 +3852,8 @@ UpdateService.prototype = { - }, +@@ -3814,6 +3814,8 @@ export class UpdateService { + } get disabledForTesting() { + /* playwright */ + return true; - return ( - (Cu.isInAutomation || - lazy.Marionette.running || + return lazy.UpdateServiceStub.updateDisabledForTesting; + } + diff --git a/toolkit/toolkit.mozbuild b/toolkit/toolkit.mozbuild -index b697eb1e3b02b0ffcc95a6e492dc23eb888488cc..0f4059341dbb3c2ecb2c46be0850e0d56e2a7453 100644 +index c50b7f3932e18da9fad4b673e353974a001e78c4..708e0d75594ddcd62276d4e08c4bd5c64d7f0698 100644 --- a/toolkit/toolkit.mozbuild +++ b/toolkit/toolkit.mozbuild -@@ -155,6 +155,7 @@ if CONFIG["ENABLE_WEBDRIVER"]: +@@ -152,6 +152,7 @@ if CONFIG["ENABLE_WEBDRIVER"]: "/remote", "/testing/firefox-ui", "/testing/marionette", @@ -2638,7 +2911,7 @@ index b697eb1e3b02b0ffcc95a6e492dc23eb888488cc..0f4059341dbb3c2ecb2c46be0850e0d5 ] diff --git a/toolkit/xre/nsWindowsWMain.cpp b/toolkit/xre/nsWindowsWMain.cpp -index 2a91deec5c10f87ed09f99b659baab77b2b638f2..78f4f30a0efe314563c6405f7b0848d2c3ca0551 100644 +index 7eb9e1104682d4eb47060654f43a1efa8b2a6bb2..a8315d6decf654b5302bea5beeea34140c300ded 100644 --- a/toolkit/xre/nsWindowsWMain.cpp +++ b/toolkit/xre/nsWindowsWMain.cpp @@ -14,8 +14,10 @@ @@ -2652,10 +2925,10 @@ index 2a91deec5c10f87ed09f99b659baab77b2b638f2..78f4f30a0efe314563c6405f7b0848d2 #include #ifdef __MINGW32__ -@@ -137,6 +139,19 @@ int wmain(int argc, WCHAR** argv) { +@@ -114,6 +116,19 @@ static void FreeAllocStrings(int argc, char** argv) { + int wmain(int argc, WCHAR** argv) { SanitizeEnvironmentVariables(); SetDllDirectoryW(L""); - RemovePrefetchArguments(argc, argv); + bool hasJugglerPipe = + mozilla::CheckArg(argc, argv, "juggler-pipe", nullptr, + mozilla::CheckArgFlag::None) == mozilla::ARG_FOUND; @@ -2673,10 +2946,10 @@ index 2a91deec5c10f87ed09f99b659baab77b2b638f2..78f4f30a0efe314563c6405f7b0848d2 // Only run this code if LauncherProcessWin.h was included beforehand, thus // signalling that the hosting process should support launcher mode. diff --git a/uriloader/base/nsDocLoader.cpp b/uriloader/base/nsDocLoader.cpp -index fe72a2715da8846146377e719559c16e6ef1f7ff..a5959143bac8f62ee359fa3883a844f3fe541685 100644 +index e5cc386651e192710b61858ab5625c97a02b92da..e560ad4fef232a26ce1e1b244f4ccea05f4aea71 100644 --- a/uriloader/base/nsDocLoader.cpp +++ b/uriloader/base/nsDocLoader.cpp -@@ -813,6 +813,12 @@ void nsDocLoader::DocLoaderIsEmpty(bool aFlushLayout, +@@ -812,6 +812,12 @@ void nsDocLoader::DocLoaderIsEmpty(bool aFlushLayout, ("DocLoader:%p: Firing load event for document.open\n", this)); @@ -2690,7 +2963,7 @@ index fe72a2715da8846146377e719559c16e6ef1f7ff..a5959143bac8f62ee359fa3883a844f3 // nsDocumentViewer::LoadComplete that doesn't do various things // that are not relevant here because this wasn't an actual diff --git a/uriloader/exthandler/nsExternalHelperAppService.cpp b/uriloader/exthandler/nsExternalHelperAppService.cpp -index 4573e28470c5112f5ac2c5dd53e7a9d1ceedb943..b53b86d8e39f1de4b0d0f1a8d5d7295ea050b878 100644 +index e23df8e6f982ea71eb1f07dd677ed13109d2831b..d98f49d34a346113fd0ed5c242d5ef228ea0e0cd 100644 --- a/uriloader/exthandler/nsExternalHelperAppService.cpp +++ b/uriloader/exthandler/nsExternalHelperAppService.cpp @@ -112,6 +112,7 @@ @@ -2701,7 +2974,7 @@ index 4573e28470c5112f5ac2c5dd53e7a9d1ceedb943..b53b86d8e39f1de4b0d0f1a8d5d7295e #include "mozilla/Preferences.h" #include "mozilla/ipc/URIUtils.h" -@@ -831,6 +832,12 @@ NS_IMETHODIMP nsExternalHelperAppService::ApplyDecodingForExtension( +@@ -865,6 +866,12 @@ NS_IMETHODIMP nsExternalHelperAppService::ApplyDecodingForExtension( return NS_OK; } @@ -2714,9 +2987,9 @@ index 4573e28470c5112f5ac2c5dd53e7a9d1ceedb943..b53b86d8e39f1de4b0d0f1a8d5d7295e nsresult nsExternalHelperAppService::GetFileTokenForPath( const char16_t* aPlatformAppPath, nsIFile** aFile) { nsDependentString platformAppPath(aPlatformAppPath); -@@ -1442,7 +1449,12 @@ nsresult nsExternalAppHandler::SetUpTempFile(nsIChannel* aChannel) { +@@ -1486,7 +1493,12 @@ nsresult nsExternalAppHandler::SetUpTempFile(nsIChannel* aChannel) { // Strip off the ".part" from mTempLeafName - mTempLeafName.Truncate(mTempLeafName.Length() - ArrayLength(".part") + 1); + mTempLeafName.Truncate(mTempLeafName.Length() - std::size(".part") + 1); + return CreateSaverForTempFile(); +} @@ -2727,7 +3000,7 @@ index 4573e28470c5112f5ac2c5dd53e7a9d1ceedb943..b53b86d8e39f1de4b0d0f1a8d5d7295e mSaver = do_CreateInstance(NS_BACKGROUNDFILESAVERSTREAMLISTENER_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); -@@ -1631,7 +1643,36 @@ NS_IMETHODIMP nsExternalAppHandler::OnStartRequest(nsIRequest* request) { +@@ -1672,7 +1684,36 @@ NS_IMETHODIMP nsExternalAppHandler::OnStartRequest(nsIRequest* request) { return NS_OK; } @@ -2765,7 +3038,7 @@ index 4573e28470c5112f5ac2c5dd53e7a9d1ceedb943..b53b86d8e39f1de4b0d0f1a8d5d7295e if (NS_FAILED(rv)) { nsresult transferError = rv; -@@ -1683,6 +1724,9 @@ NS_IMETHODIMP nsExternalAppHandler::OnStartRequest(nsIRequest* request) { +@@ -1733,6 +1774,9 @@ NS_IMETHODIMP nsExternalAppHandler::OnStartRequest(nsIRequest* request) { bool alwaysAsk = true; mMimeInfo->GetAlwaysAskBeforeHandling(&alwaysAsk); @@ -2775,7 +3048,7 @@ index 4573e28470c5112f5ac2c5dd53e7a9d1ceedb943..b53b86d8e39f1de4b0d0f1a8d5d7295e if (alwaysAsk) { // But we *don't* ask if this mimeInfo didn't come from // our user configuration datastore and the user has said -@@ -2199,6 +2243,16 @@ nsExternalAppHandler::OnSaveComplete(nsIBackgroundFileSaver* aSaver, +@@ -2249,6 +2293,16 @@ nsExternalAppHandler::OnSaveComplete(nsIBackgroundFileSaver* aSaver, NotifyTransfer(aStatus); } @@ -2792,7 +3065,7 @@ index 4573e28470c5112f5ac2c5dd53e7a9d1ceedb943..b53b86d8e39f1de4b0d0f1a8d5d7295e return NS_OK; } -@@ -2680,6 +2734,15 @@ NS_IMETHODIMP nsExternalAppHandler::Cancel(nsresult aReason) { +@@ -2732,6 +2786,15 @@ NS_IMETHODIMP nsExternalAppHandler::Cancel(nsresult aReason) { } } @@ -2809,10 +3082,10 @@ index 4573e28470c5112f5ac2c5dd53e7a9d1ceedb943..b53b86d8e39f1de4b0d0f1a8d5d7295e // OnStartRequest) mDialog = nullptr; diff --git a/uriloader/exthandler/nsExternalHelperAppService.h b/uriloader/exthandler/nsExternalHelperAppService.h -index 1f77e095dbfa3acc046779114007d83fc1cfa087..2354abbab7af6f6bdc3bd628722f03ea401d236a 100644 +index 2dd4ff87bda3e0ba395cca168c42b37db1713ddf..83e8a3d328e325b3f50f593c9ea71692f9c7d401 100644 --- a/uriloader/exthandler/nsExternalHelperAppService.h +++ b/uriloader/exthandler/nsExternalHelperAppService.h -@@ -257,6 +257,8 @@ class nsExternalHelperAppService : public nsIExternalHelperAppService, +@@ -258,6 +258,8 @@ class nsExternalHelperAppService : public nsIExternalHelperAppService, mozilla::dom::BrowsingContext* aContentContext, bool aForceSave, nsIInterfaceRequestor* aWindowContext, nsIStreamListener** aStreamListener); @@ -2821,7 +3094,7 @@ index 1f77e095dbfa3acc046779114007d83fc1cfa087..2354abbab7af6f6bdc3bd628722f03ea }; /** -@@ -462,6 +464,9 @@ class nsExternalAppHandler final : public nsIStreamListener, +@@ -455,6 +457,9 @@ class nsExternalAppHandler final : public nsIStreamListener, * Upon successful return, both mTempFile and mSaver will be valid. */ nsresult SetUpTempFile(nsIChannel* aChannel); @@ -2832,7 +3105,7 @@ index 1f77e095dbfa3acc046779114007d83fc1cfa087..2354abbab7af6f6bdc3bd628722f03ea * When we download a helper app, we are going to retarget all load * notifications into our own docloader and load group instead of diff --git a/uriloader/exthandler/nsIExternalHelperAppService.idl b/uriloader/exthandler/nsIExternalHelperAppService.idl -index 4a399acb72d4fd475c9ae43e9eadbc32f261e290..31e9490a7dfd7d7eff69ad23c9ce277f367d1524 100644 +index 53ea934dd4876e4b491b724385c8fbf7d00ee6cd..0b7b88c853b21ce778d8e87fea0a2bfe839ad412 100644 --- a/uriloader/exthandler/nsIExternalHelperAppService.idl +++ b/uriloader/exthandler/nsIExternalHelperAppService.idl @@ -6,8 +6,11 @@ @@ -2857,7 +3130,7 @@ index 4a399acb72d4fd475c9ae43e9eadbc32f261e290..31e9490a7dfd7d7eff69ad23c9ce277f +[scriptable, uuid(9a20e9b0-75d0-11ea-bc55-0242ac130003)] +interface nsIDownloadInterceptor : nsISupports +{ -+ bool interceptDownloadRequest(in nsIHelperAppLauncher aHandler, in nsIRequest aRequest, in BrowsingContext aBrowsingContext, out nsIFile file); ++ boolean interceptDownloadRequest(in nsIHelperAppLauncher aHandler, in nsIRequest aRequest, in BrowsingContext aBrowsingContext, out nsIFile file); + + void onDownloadComplete(in nsIHelperAppLauncher aHandler, in ACString aErrorName); +}; @@ -2865,10 +3138,11 @@ index 4a399acb72d4fd475c9ae43e9eadbc32f261e290..31e9490a7dfd7d7eff69ad23c9ce277f /** * The external helper app service is used for finding and launching * platform specific external applications for a given mime content type. -@@ -76,6 +90,7 @@ interface nsIExternalHelperAppService : nsISupports - boolean applyDecodingForExtension(in AUTF8String aExtension, - in ACString aEncodingType); - +@@ -87,6 +101,8 @@ interface nsIExternalHelperAppService : nsISupports + * `DownloadIntegration.sys.mjs`, which is implemented on all platforms. + */ + nsIFile getPreferredDownloadsDirectory(); ++ + void setDownloadInterceptor(in nsIDownloadInterceptor interceptor); }; @@ -2902,56 +3176,32 @@ index 1c25e9d9a101233f71e92288a0f93125b81ac1c5..22cf67b0f6e3ddd2b3ed725a314ba6a9 } #endif diff --git a/widget/MouseEvents.h b/widget/MouseEvents.h -index d29b406524c8b4afe437b559e33b4b2b5824ee58..6bef9c1657f93f90f96735d76fedb6ba3888b5c1 100644 +index 5ca1a6fa13233b1bd00ee0467732c5875c51d343..0d3b8ebe127e59516802e8819f4bbed961f0992b 100644 --- a/widget/MouseEvents.h +++ b/widget/MouseEvents.h -@@ -258,6 +258,7 @@ class WidgetMouseEvent : public WidgetMouseEventBase, - : mReason(eReal), - mContextMenuTrigger(eNormal), - mClickCount(0), -+ mJugglerEventId(0), - mIgnoreRootScrollFrame(false), - mClickEventPrevented(false) {} - -@@ -269,6 +270,7 @@ class WidgetMouseEvent : public WidgetMouseEventBase, - mReason(aReason), - mContextMenuTrigger(eNormal), - mClickCount(0), -+ mJugglerEventId(0), - mIgnoreRootScrollFrame(false), - mClickEventPrevented(false) {} - -@@ -288,6 +290,7 @@ class WidgetMouseEvent : public WidgetMouseEventBase, - mReason(aReason), - mContextMenuTrigger(aContextMenuTrigger), - mClickCount(0), -+ mJugglerEventId(0), - mIgnoreRootScrollFrame(false), - mClickEventPrevented(false) { - if (aMessage == eContextMenu) { -@@ -336,6 +339,9 @@ class WidgetMouseEvent : public WidgetMouseEventBase, +@@ -368,6 +368,9 @@ class WidgetMouseEvent : public WidgetMouseEventBase, // Otherwise, this must be 0. - uint32_t mClickCount; + uint32_t mClickCount = 0; + // Unique event ID -+ uint32_t mJugglerEventId; ++ uint32_t mJugglerEventId = 0; + // Whether the event should ignore scroll frame bounds during dispatch. - bool mIgnoreRootScrollFrame; - -@@ -348,6 +354,7 @@ class WidgetMouseEvent : public WidgetMouseEventBase, + bool mIgnoreRootScrollFrame = false; +@@ -391,6 +394,7 @@ class WidgetMouseEvent : public WidgetMouseEventBase, + mContextMenuTrigger = aEvent.mContextMenuTrigger; mExitFrom = aEvent.mExitFrom; mClickCount = aEvent.mClickCount; + mJugglerEventId = aEvent.mJugglerEventId; mIgnoreRootScrollFrame = aEvent.mIgnoreRootScrollFrame; + mIgnoreCapturingContent = aEvent.mIgnoreCapturingContent; mClickEventPrevented = aEvent.mClickEventPrevented; - } diff --git a/widget/cocoa/NativeKeyBindings.mm b/widget/cocoa/NativeKeyBindings.mm -index e4bdf715e2fb899e97a5bfeb2e147127460d6047..3554f919480278b7353617481c7ce8050630a1aa 100644 +index 24b70173c2e8bb9be9fd6255984a70efe3b14099..75ac367a1c4bb44d4b68b5f4ecc6adf56dbd408e 100644 --- a/widget/cocoa/NativeKeyBindings.mm +++ b/widget/cocoa/NativeKeyBindings.mm -@@ -528,6 +528,13 @@ +@@ -549,6 +549,13 @@ break; case KEY_NAME_INDEX_ArrowLeft: if (aEvent.IsAlt()) { @@ -2965,7 +3215,7 @@ index e4bdf715e2fb899e97a5bfeb2e147127460d6047..3554f919480278b7353617481c7ce805 break; } if (aEvent.IsMeta() || (aEvent.IsControl() && aEvent.IsShift())) { -@@ -550,6 +557,13 @@ +@@ -571,6 +578,13 @@ break; case KEY_NAME_INDEX_ArrowRight: if (aEvent.IsAlt()) { @@ -2979,7 +3229,7 @@ index e4bdf715e2fb899e97a5bfeb2e147127460d6047..3554f919480278b7353617481c7ce805 break; } if (aEvent.IsMeta() || (aEvent.IsControl() && aEvent.IsShift())) { -@@ -572,6 +586,10 @@ +@@ -593,6 +607,10 @@ break; case KEY_NAME_INDEX_ArrowUp: if (aEvent.IsControl()) { @@ -2990,7 +3240,7 @@ index e4bdf715e2fb899e97a5bfeb2e147127460d6047..3554f919480278b7353617481c7ce805 break; } if (aEvent.IsMeta()) { -@@ -582,7 +600,7 @@ +@@ -603,7 +621,7 @@ !aEvent.IsShift() ? ToObjcSelectorPtr(@selector(moveToBeginningOfDocument:)) : ToObjcSelectorPtr( @@ -2999,7 +3249,7 @@ index e4bdf715e2fb899e97a5bfeb2e147127460d6047..3554f919480278b7353617481c7ce805 aCommands); break; } -@@ -609,6 +627,10 @@ +@@ -630,6 +648,10 @@ break; case KEY_NAME_INDEX_ArrowDown: if (aEvent.IsControl()) { @@ -3010,6 +3260,18 @@ index e4bdf715e2fb899e97a5bfeb2e147127460d6047..3554f919480278b7353617481c7ce805 break; } if (aEvent.IsMeta()) { +diff --git a/widget/gtk/nsFilePicker.cpp b/widget/gtk/nsFilePicker.cpp +index f4bded345e95674c66e4d4ad56b50844fce0871b..321e22d334a8bbc6057ee78e77e139a2804b2403 100644 +--- a/widget/gtk/nsFilePicker.cpp ++++ b/widget/gtk/nsFilePicker.cpp +@@ -21,6 +21,7 @@ + #include "mozilla/Components.h" + #include "mozilla/Preferences.h" + #include "mozilla/dom/Promise.h" ++#include "gfxPlatform.h" + + #include "nsArrayEnumerator.h" + #include "nsEnumeratorUtils.h" diff --git a/widget/headless/HeadlessCompositorWidget.cpp b/widget/headless/HeadlessCompositorWidget.cpp index bb4ee9175e66dc40de1871a7f91368fe309494a3..747625e3869882300bfbc18b184db5151dd90c1a 100644 --- a/widget/headless/HeadlessCompositorWidget.cpp @@ -3160,7 +3422,7 @@ index facd2bc65afab8ec1aa322faa20a67464964dfb9..d6dea95472bec6006411753c3dfdab2e } // namespace widget diff --git a/widget/headless/HeadlessWidget.cpp b/widget/headless/HeadlessWidget.cpp -index 083d026d3c019cb76fff2b8f605f3d6ef8dd578f..84c049709ead92c980b86230513a634bf6337085 100644 +index daa2d455374fd9f75a5c6ac9f7b91696d88b065c..f45184137b52db0a5774bf3365b15f784532fbdf 100644 --- a/widget/headless/HeadlessWidget.cpp +++ b/widget/headless/HeadlessWidget.cpp @@ -111,6 +111,8 @@ void HeadlessWidget::Destroy() { @@ -3172,7 +3434,7 @@ index 083d026d3c019cb76fff2b8f605f3d6ef8dd578f..84c049709ead92c980b86230513a634b nsBaseWidget::OnDestroy(); nsBaseWidget::Destroy(); -@@ -621,5 +623,14 @@ nsresult HeadlessWidget::SynthesizeNativeTouchpadPan( +@@ -593,5 +595,14 @@ nsresult HeadlessWidget::SynthesizeNativeTouchpadPan( return NS_OK; } @@ -3188,12 +3450,12 @@ index 083d026d3c019cb76fff2b8f605f3d6ef8dd578f..84c049709ead92c980b86230513a634b } // namespace widget } // namespace mozilla diff --git a/widget/headless/HeadlessWidget.h b/widget/headless/HeadlessWidget.h -index 9856991ef32f25f51942f8cd664a09bec2192c70..948947a421179e91c51005aeb83ed0d18cfc84ce 100644 +index 39833c28e40c61e354119cde429b8389056bafac..a638fb7520b857219ce58fcbf9ca0ed939528924 100644 --- a/widget/headless/HeadlessWidget.h +++ b/widget/headless/HeadlessWidget.h -@@ -141,6 +141,9 @@ class HeadlessWidget : public nsBaseWidget { - int32_t aModifierFlags, - nsIObserver* aObserver) override; +@@ -132,6 +132,9 @@ class HeadlessWidget final : public nsBaseWidget { + int32_t aModifierFlags, + nsIObserver* aObserver) override; + using SnapshotListener = std::function&&)>; + void SetSnapshotListener(SnapshotListener&& listener); @@ -3202,10 +3464,10 @@ index 9856991ef32f25f51942f8cd664a09bec2192c70..948947a421179e91c51005aeb83ed0d1 ~HeadlessWidget(); bool mEnabled; diff --git a/widget/nsGUIEventIPC.h b/widget/nsGUIEventIPC.h -index 8ba46829357fc4acc47bf20842fd869902efa000..a1b5b2c5230d90981bd563d4df2d2bf1c2e05cef 100644 +index f7262978239665cbe20470da0790d4d177d4c501..70d11aca3d5b509cf5b37d626299a23fede73ba3 100644 --- a/widget/nsGUIEventIPC.h +++ b/widget/nsGUIEventIPC.h -@@ -234,6 +234,7 @@ struct ParamTraits { +@@ -244,6 +244,7 @@ struct ParamTraits { aParam.mExitFrom.value())); } WriteParam(aWriter, aParam.mClickCount); @@ -3213,7 +3475,7 @@ index 8ba46829357fc4acc47bf20842fd869902efa000..a1b5b2c5230d90981bd563d4df2d2bf1 } static bool Read(MessageReader* aReader, paramType* aResult) { -@@ -258,6 +259,7 @@ struct ParamTraits { +@@ -268,6 +269,7 @@ struct ParamTraits { aResult->mExitFrom = Some(static_cast(exitFrom)); } rv = rv && ReadParam(aReader, &aResult->mClickCount); @@ -3222,10 +3484,10 @@ index 8ba46829357fc4acc47bf20842fd869902efa000..a1b5b2c5230d90981bd563d4df2d2bf1 } }; diff --git a/xpcom/reflect/xptinfo/xptinfo.h b/xpcom/reflect/xptinfo/xptinfo.h -index 2456c2c2b58b27cd595880b547ed20fb687a1835..e967c089b2331c7cd36d34e511543fbc84320b7d 100644 +index 787d30d881adedd57d2025ca57bff4bc6c57e803..ae1a0172c960ab16919133485722d2ae0cdbcbd4 100644 --- a/xpcom/reflect/xptinfo/xptinfo.h +++ b/xpcom/reflect/xptinfo/xptinfo.h -@@ -514,7 +514,7 @@ static_assert(sizeof(nsXPTMethodInfo) == 8, "wrong size"); +@@ -505,7 +505,7 @@ static_assert(sizeof(nsXPTMethodInfo) == 8, "wrong size"); #if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE) # define PARAM_BUFFER_COUNT 18 #else diff --git a/browser_patches/firefox/preferences/playwright.cfg b/browser_patches/firefox/preferences/playwright.cfg index 99fbf39420999..5dc8986c19c4d 100644 --- a/browser_patches/firefox/preferences/playwright.cfg +++ b/browser_patches/firefox/preferences/playwright.cfg @@ -8,6 +8,13 @@ pref("dom.input_events.security.minTimeElapsedInMS", 0); pref("dom.iframe_lazy_loading.enabled", false); +// Allows a custom "policies.json" file. +pref("browser.policies.alternatePath", getenv("PLAYWRIGHT_FIREFOX_POLICIES_JSON") || ""); + +// This setting is experimental and is only enabled on early betas. +// Disable it unconditionally since it breaks proxy tests. +pref("dom.security.https_first", false); + pref("datareporting.policy.dataSubmissionEnabled", false); pref("datareporting.policy.dataSubmissionPolicyAccepted", false); pref("datareporting.policy.dataSubmissionPolicyBypassNotification", true); @@ -47,6 +54,9 @@ pref("permissions.isolateBy.userContext", true); // |Page.setFileInputFiles| protocol method. pref("dom.file.createInChild", true); +// Allow uploading directorys in content process. +pref("dom.filesystem.pathcheck.disabled", true); + // Do not warn when closing all open tabs pref("browser.tabs.warnOnClose", false); @@ -85,6 +95,18 @@ pref("geo.provider.testing", true); // THESE ARE NICHE PROPERTIES THAT ARE NICE TO HAVE // ================================================================= +// We never want to have interactive screen capture picker enabled in FF build. +pref("media.getdisplaymedia.screencapturekit.enabled", false); +pref("media.getdisplaymedia.screencapturekit.picker.enabled", false); + +// Allow proxying loopback URLs; see https://phabricator.services.mozilla.com/D237187 +pref("network.proxy.allow_hijacking_localhost", true); +pref("network.proxy.testing_localhost_is_secure_when_hijacked", true); + +// Disable double-dispatching of "input" event for the text composition. +// See https://phabricator.services.mozilla.com/D234620 for details. +pref("dom.input_events.dispatch_before_compositionend", false); + // Enable software-backed webgl. See https://phabricator.services.mozilla.com/D164016 pref("webgl.forbid-software", false); @@ -97,6 +119,11 @@ pref("extensions.formautofill.addresses.supported", "off"); // firefox behavior with other browser defaults. pref("security.enterprise_roots.enabled", true); +// There's a security features warning that might be shown on certain Linux distributions & configurations: +// https://support.mozilla.org/en-US/kb/install-firefox-linux#w_security-features-warning +// This notification should never be shown in automation scenarios. +pref("security.sandbox.warn_unprivileged_namespaces", false); + // Avoid stalling on shutdown, after "xpcom-will-shutdown" phase. // This at least happens when shutting down soon after launching. // See AppShutdown.cpp for more details on shutdown phases. diff --git a/browser_patches/webkit/UPSTREAM_CONFIG.sh b/browser_patches/webkit/UPSTREAM_CONFIG.sh index 069f24571c3c3..574e1f310aa7f 100644 --- a/browser_patches/webkit/UPSTREAM_CONFIG.sh +++ b/browser_patches/webkit/UPSTREAM_CONFIG.sh @@ -1,3 +1,3 @@ REMOTE_URL="https://github.com/WebKit/WebKit.git" BASE_BRANCH="main" -BASE_REVISION="b2ca06dc3d84b356d01cdf09a82049f80515fbfe" +BASE_REVISION="153da00a252619799ba4b32cd0ac6c5b8faf6a35" diff --git a/browser_patches/webkit/embedder/Playwright/mac/AppDelegate.m b/browser_patches/webkit/embedder/Playwright/mac/AppDelegate.m index a6c7be8ae48a9..b4d08b700ac91 100644 --- a/browser_patches/webkit/embedder/Playwright/mac/AppDelegate.m +++ b/browser_patches/webkit/embedder/Playwright/mac/AppDelegate.m @@ -33,6 +33,7 @@ #import #import #import +#import #import #import #import @@ -97,7 +98,7 @@ - (id)init for (NSString *argument in subArray) { if (![argument hasPrefix:@"--"]) - _initialURL = argument; + _initialURL = [argument copy]; if ([argument hasPrefix:@"--user-data-dir="]) { NSRange range = NSMakeRange(16, [argument length] - 16); _userDataDir = [[argument substringWithRange:range] copy]; @@ -230,7 +231,7 @@ - (WKWebViewConfiguration *)defaultConfiguration configuration = [[WKWebViewConfiguration alloc] init]; configuration.websiteDataStore = [self persistentDataStore]; configuration._controlledByAutomation = true; - configuration.preferences._fullScreenEnabled = YES; + configuration.preferences.elementFullscreenEnabled = YES; configuration.preferences._developerExtrasEnabled = YES; configuration.preferences._mediaDevicesEnabled = YES; configuration.preferences._mockCaptureDevicesEnabled = YES; @@ -240,6 +241,8 @@ - (WKWebViewConfiguration *)defaultConfiguration configuration.preferences._hiddenPageDOMTimerThrottlingAutoIncreases = NO; configuration.preferences._pageVisibilityBasedProcessSuppressionEnabled = NO; configuration.preferences._domTimersThrottlingEnabled = NO; + // Do not auto play audio and video with sound. + configuration.defaultWebpagePreferences._autoplayPolicy = _WKWebsiteAutoplayPolicyAllowWithoutSound; _WKProcessPoolConfiguration *processConfiguration = [[[_WKProcessPoolConfiguration alloc] init] autorelease]; processConfiguration.forceOverlayScrollbars = YES; configuration.processPool = [[[WKProcessPool alloc] _initWithConfiguration:processConfiguration] autorelease]; diff --git a/browser_patches/webkit/embedder/Playwright/win/Common.cpp b/browser_patches/webkit/embedder/Playwright/win/Common.cpp index 66dee5b68ba49..01a10f7be9ced 100644 --- a/browser_patches/webkit/embedder/Playwright/win/Common.cpp +++ b/browser_patches/webkit/embedder/Playwright/win/Common.cpp @@ -44,6 +44,8 @@ HINSTANCE hInst; POINT s_windowPosition = { 100, 100 }; SIZE s_windowSize = { 500, 200 }; +bool s_headless; + namespace WebCore { float deviceScaleFactorForWindow(HWND); } diff --git a/browser_patches/webkit/embedder/Playwright/win/Common.h b/browser_patches/webkit/embedder/Playwright/win/Common.h index 3c534fd3701c3..29edbe39dad34 100644 --- a/browser_patches/webkit/embedder/Playwright/win/Common.h +++ b/browser_patches/webkit/embedder/Playwright/win/Common.h @@ -64,6 +64,7 @@ std::wstring replaceString(std::wstring src, const std::wstring& oldValue, const extern HINSTANCE hInst; extern POINT s_windowPosition; extern SIZE s_windowSize; +extern bool s_headless; std::wstring createString(WKStringRef wkString); std::wstring createString(WKURLRef wkURL); diff --git a/browser_patches/webkit/embedder/Playwright/win/MainWindow.cpp b/browser_patches/webkit/embedder/Playwright/win/MainWindow.cpp index e74590c491860..ca65ccb0221fc 100644 --- a/browser_patches/webkit/embedder/Playwright/win/MainWindow.cpp +++ b/browser_patches/webkit/embedder/Playwright/win/MainWindow.cpp @@ -48,12 +48,10 @@ static INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); std::wstring MainWindow::s_windowClass; size_t MainWindow::s_numInstances; -bool MainWindow::s_headless = false; bool MainWindow::s_controlledRemotely = false; bool MainWindow::s_disableAcceleratedCompositing = false; -void MainWindow::configure(bool headless, bool controlledRemotely, bool disableAcceleratedCompositing) { - s_headless = headless; +void MainWindow::configure(bool controlledRemotely, bool disableAcceleratedCompositing) { s_controlledRemotely = controlledRemotely; s_disableAcceleratedCompositing = disableAcceleratedCompositing; } @@ -140,7 +138,7 @@ void MainWindow::createToolbar(HINSTANCE hInstance) SendMessage(m_hToolbarWnd, TB_ADDBUTTONS, _countof(tbButtons), reinterpret_cast(&tbButtons)); ShowWindow(m_hToolbarWnd, true); - m_hURLBarWnd = CreateWindow(L"EDIT", 0, WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT | ES_AUTOVSCROLL, 0, 0, 0, 0, m_hToolbarWnd, 0, hInstance, 0); + m_hURLBarWnd = CreateWindow(L"EDIT", 0, WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT | ES_AUTOHSCROLL, 0, 0, 0, 0, m_hToolbarWnd, 0, hInstance, 0); DefEditProc = reinterpret_cast(GetWindowLongPtr(m_hURLBarWnd, GWLP_WNDPROC)); SetWindowLongPtr(m_hURLBarWnd, GWLP_WNDPROC, reinterpret_cast(EditProc)); @@ -210,7 +208,9 @@ bool MainWindow::init(HINSTANCE hInstance, WKPageConfigurationRef conf) resizeSubViews(); if (s_headless) { + auto menu = GetMenu(m_hMainWnd); SetMenu(m_hMainWnd, NULL); + DestroyMenu(menu); } else { SetFocus(m_hURLBarWnd); ShowWindow(m_hMainWnd, SW_SHOW); diff --git a/browser_patches/webkit/embedder/Playwright/win/MainWindow.h b/browser_patches/webkit/embedder/Playwright/win/MainWindow.h index c34241fb1df15..e0af565f4b98b 100644 --- a/browser_patches/webkit/embedder/Playwright/win/MainWindow.h +++ b/browser_patches/webkit/embedder/Playwright/win/MainWindow.h @@ -35,7 +35,7 @@ class MainWindow : public BrowserWindowClient { public: - static void configure(bool headless, bool controlledRemotely, bool disableAcceleratedCompositing); + static void configure(bool controlledRemotely, bool disableAcceleratedCompositing); MainWindow(); @@ -55,7 +55,6 @@ class MainWindow : public BrowserWindowClient { static void registerClass(HINSTANCE hInstance); static std::wstring s_windowClass; static size_t s_numInstances; - static bool s_headless; static bool s_controlledRemotely; static bool s_disableAcceleratedCompositing; diff --git a/browser_patches/webkit/embedder/Playwright/win/Playwright.ico b/browser_patches/webkit/embedder/Playwright/win/Playwright.ico index 0137fe83a54dd..cea0bdebc38b2 100644 Binary files a/browser_patches/webkit/embedder/Playwright/win/Playwright.ico and b/browser_patches/webkit/embedder/Playwright/win/Playwright.ico differ diff --git a/browser_patches/webkit/embedder/Playwright/win/WebKitBrowserWindow.cpp b/browser_patches/webkit/embedder/Playwright/win/WebKitBrowserWindow.cpp index ee4ea065a71b2..c850d820763a5 100644 --- a/browser_patches/webkit/embedder/Playwright/win/WebKitBrowserWindow.cpp +++ b/browser_patches/webkit/embedder/Playwright/win/WebKitBrowserWindow.cpp @@ -41,16 +41,18 @@ #include #include -std::wstring createPEMString(WKCertificateInfoRef certificateInfo) +std::wstring createPEMString(WKProtectionSpaceRef protectionSpace) { - auto chainSize = WKCertificateInfoGetCertificateChainSize(certificateInfo); + auto chain = adoptWK(WKProtectionSpaceCopyCertificateChain(protectionSpace)); std::wstring pems; - for (auto i = 0; i < chainSize; i++) { - auto certificate = adoptWK(WKCertificateInfoCopyCertificateAtIndex(certificateInfo, i)); - auto size = WKDataGetSize(certificate.get()); - auto data = WKDataGetBytes(certificate.get()); + for (size_t i = 0; i < WKArrayGetSize(chain.get()); i++) { + auto item = WKArrayGetItemAtIndex(chain.get(), i); + assert(WKGetTypeID(item) == WKDataGetTypeID()); + auto certificate = static_cast(item); + auto size = WKDataGetSize(certificate); + auto data = WKDataGetBytes(certificate); for (size_t i = 0; i < size; i++) pems.push_back(data[i]); @@ -241,7 +243,7 @@ void WebKitBrowserWindow::didReceiveAuthenticationChallenge(WKPageRef page, WKAu WKAuthenticationDecisionListenerUseCredential(decisionListener, wkCredential.get()); return; } - } else { + } else if (!s_headless) { WKRetainPtr realm(WKProtectionSpaceCopyRealm(protectionSpace)); if (auto credential = askCredential(thisWindow.hwnd(), createString(realm.get()))) { @@ -259,10 +261,9 @@ void WebKitBrowserWindow::didReceiveAuthenticationChallenge(WKPageRef page, WKAu bool WebKitBrowserWindow::canTrustServerCertificate(WKProtectionSpaceRef protectionSpace) { auto host = createString(adoptWK(WKProtectionSpaceCopyHost(protectionSpace)).get()); - auto certificateInfo = adoptWK(WKProtectionSpaceCopyCertificateInfo(protectionSpace)); - auto verificationError = WKCertificateInfoGetVerificationError(certificateInfo.get()); - auto description = createString(adoptWK(WKCertificateInfoCopyVerificationErrorDescription(certificateInfo.get())).get()); - auto pem = createPEMString(certificateInfo.get()); + auto verificationError = WKProtectionSpaceGetCertificateVerificationError(protectionSpace); + auto description = createString(adoptWK(WKProtectionSpaceCopyCertificateVerificationErrorDescription(protectionSpace)).get()); + auto pem = createPEMString(protectionSpace); auto it = m_acceptedServerTrustCerts.find(host); if (it != m_acceptedServerTrustCerts.end() && it->second == pem) @@ -273,6 +274,9 @@ bool WebKitBrowserWindow::canTrustServerCertificate(WKProtectionSpaceRef protect textString.append(L"[DESCRIPTION] " + description + L"\r\n"); textString.append(pem); + if (s_headless) + return false; + if (askServerTrustEvaluation(hwnd(), textString)) { m_acceptedServerTrustCerts.emplace(host, pem); return true; diff --git a/browser_patches/webkit/embedder/Playwright/win/WinMain.cpp b/browser_patches/webkit/embedder/Playwright/win/WinMain.cpp index d80ba9f7bd28c..2261c2b810d2e 100644 --- a/browser_patches/webkit/embedder/Playwright/win/WinMain.cpp +++ b/browser_patches/webkit/embedder/Playwright/win/WinMain.cpp @@ -102,7 +102,8 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, if (SetProcessDpiAwarenessContextPtr()) SetProcessDpiAwarenessContextPtr()(DPI_AWARENESS_CONTEXT_UNAWARE); - MainWindow::configure(g_options.headless, g_options.inspectorPipe, g_options.disableAcceleratedCompositing); + s_headless = g_options.headless; + MainWindow::configure(g_options.inspectorPipe, g_options.disableAcceleratedCompositing); if (!g_options.noStartupWindow) { auto configuration = adoptWK(WKWebsiteDataStoreConfigurationCreate()); diff --git a/browser_patches/webkit/patches/bootstrap.diff b/browser_patches/webkit/patches/bootstrap.diff index 5df5d455da9cc..9d644885f063b 100644 --- a/browser_patches/webkit/patches/bootstrap.diff +++ b/browser_patches/webkit/patches/bootstrap.diff @@ -1,8 +1,8 @@ diff --git a/Source/JavaScriptCore/CMakeLists.txt b/Source/JavaScriptCore/CMakeLists.txt -index dcd4c26b1cd99333e9498a483ff4139a8d42d14b..f041439eff7f2649b1560faf18661165b1fd7771 100644 +index 458e1d4118805169ee6f9139af942cc5c3f88f8e..238f2a33ba150fae735915244910eaa66f5fd267 100644 --- a/Source/JavaScriptCore/CMakeLists.txt +++ b/Source/JavaScriptCore/CMakeLists.txt -@@ -1400,22 +1400,27 @@ set(JavaScriptCore_INSPECTOR_DOMAINS +@@ -1411,21 +1411,26 @@ set(JavaScriptCore_INSPECTOR_DOMAINS ${JAVASCRIPTCORE_DIR}/inspector/protocol/CSS.json ${JAVASCRIPTCORE_DIR}/inspector/protocol/Canvas.json ${JAVASCRIPTCORE_DIR}/inspector/protocol/Console.json @@ -10,7 +10,6 @@ index dcd4c26b1cd99333e9498a483ff4139a8d42d14b..f041439eff7f2649b1560faf18661165 ${JAVASCRIPTCORE_DIR}/inspector/protocol/DOM.json ${JAVASCRIPTCORE_DIR}/inspector/protocol/DOMDebugger.json ${JAVASCRIPTCORE_DIR}/inspector/protocol/DOMStorage.json - ${JAVASCRIPTCORE_DIR}/inspector/protocol/Database.json ${JAVASCRIPTCORE_DIR}/inspector/protocol/Debugger.json + ${JAVASCRIPTCORE_DIR}/inspector/protocol/Emulation.json ${JAVASCRIPTCORE_DIR}/inspector/protocol/GenericTypes.json @@ -31,10 +30,10 @@ index dcd4c26b1cd99333e9498a483ff4139a8d42d14b..f041439eff7f2649b1560faf18661165 ${JAVASCRIPTCORE_DIR}/inspector/protocol/ServiceWorker.json ${JAVASCRIPTCORE_DIR}/inspector/protocol/Target.json diff --git a/Source/JavaScriptCore/DerivedSources-input.xcfilelist b/Source/JavaScriptCore/DerivedSources-input.xcfilelist -index b26ef7b2b8f732160ddee36697a61ca7776fc2c3..9a442a4cda7efd7f2bd4e225d8bcbfedf8c4a0c5 100644 +index 9fd3a4e6a53eb3339ced1e87f0b4cacd16f73167..a77d72ab052625c7b5a4d7c56a71befbad884871 100644 --- a/Source/JavaScriptCore/DerivedSources-input.xcfilelist +++ b/Source/JavaScriptCore/DerivedSources-input.xcfilelist -@@ -98,21 +98,26 @@ $(PROJECT_DIR)/inspector/protocol/CPUProfiler.json +@@ -98,20 +98,25 @@ $(PROJECT_DIR)/inspector/protocol/CPUProfiler.json $(PROJECT_DIR)/inspector/protocol/CSS.json $(PROJECT_DIR)/inspector/protocol/Canvas.json $(PROJECT_DIR)/inspector/protocol/Console.json @@ -42,7 +41,6 @@ index b26ef7b2b8f732160ddee36697a61ca7776fc2c3..9a442a4cda7efd7f2bd4e225d8bcbfed $(PROJECT_DIR)/inspector/protocol/DOM.json $(PROJECT_DIR)/inspector/protocol/DOMDebugger.json $(PROJECT_DIR)/inspector/protocol/DOMStorage.json - $(PROJECT_DIR)/inspector/protocol/Database.json $(PROJECT_DIR)/inspector/protocol/Debugger.json +$(PROJECT_DIR)/inspector/protocol/Emulation.json $(PROJECT_DIR)/inspector/protocol/GenericTypes.json @@ -62,10 +60,10 @@ index b26ef7b2b8f732160ddee36697a61ca7776fc2c3..9a442a4cda7efd7f2bd4e225d8bcbfed $(PROJECT_DIR)/inspector/protocol/Security.json $(PROJECT_DIR)/inspector/protocol/ServiceWorker.json diff --git a/Source/JavaScriptCore/DerivedSources.make b/Source/JavaScriptCore/DerivedSources.make -index 15d6e32cd525905b116f25a5bdd50bd1ef390cee..74b1415d21dcddc49e842e077e87e06724af8365 100644 +index 3db6c2e250371dedc6a9f88bf1688112d467434a..a3832759ea36fb50bdbea6809b9fd13e6f66e46b 100644 --- a/Source/JavaScriptCore/DerivedSources.make +++ b/Source/JavaScriptCore/DerivedSources.make -@@ -298,22 +298,27 @@ INSPECTOR_DOMAINS := \ +@@ -301,21 +301,26 @@ INSPECTOR_DOMAINS := \ $(JavaScriptCore)/inspector/protocol/CSS.json \ $(JavaScriptCore)/inspector/protocol/Canvas.json \ $(JavaScriptCore)/inspector/protocol/Console.json \ @@ -73,7 +71,6 @@ index 15d6e32cd525905b116f25a5bdd50bd1ef390cee..74b1415d21dcddc49e842e077e87e067 $(JavaScriptCore)/inspector/protocol/DOM.json \ $(JavaScriptCore)/inspector/protocol/DOMDebugger.json \ $(JavaScriptCore)/inspector/protocol/DOMStorage.json \ - $(JavaScriptCore)/inspector/protocol/Database.json \ $(JavaScriptCore)/inspector/protocol/Debugger.json \ + $(JavaScriptCore)/inspector/protocol/Emulation.json \ $(JavaScriptCore)/inspector/protocol/GenericTypes.json \ @@ -94,7 +91,7 @@ index 15d6e32cd525905b116f25a5bdd50bd1ef390cee..74b1415d21dcddc49e842e077e87e067 $(JavaScriptCore)/inspector/protocol/ServiceWorker.json \ $(JavaScriptCore)/inspector/protocol/Target.json \ diff --git a/Source/JavaScriptCore/inspector/IdentifiersFactory.cpp b/Source/JavaScriptCore/inspector/IdentifiersFactory.cpp -index 528cceee66a1b1c91a0d0e59d5f1a1770a050c17..0f3a341056f429ff282abcab22be4843c60f546c 100644 +index 9bc5d1fd8e2a7e576be046b3c6ae1266696cf552..610f810db1dd6865c500c0796386a8284f4178e9 100644 --- a/Source/JavaScriptCore/inspector/IdentifiersFactory.cpp +++ b/Source/JavaScriptCore/inspector/IdentifiersFactory.cpp @@ -32,14 +32,21 @@ @@ -108,7 +105,7 @@ index 528cceee66a1b1c91a0d0e59d5f1a1770a050c17..0f3a341056f429ff282abcab22be4843 static String addPrefixToIdentifier(unsigned long identifier) { - return makeString("0."_s, identifier); -+ return makeString(s_processID, ".", identifier); ++ return makeString(s_processID, '.', identifier); } +void IdentifiersFactory::initializeWithProcessID(uint64_t processID) { @@ -121,22 +118,22 @@ index 528cceee66a1b1c91a0d0e59d5f1a1770a050c17..0f3a341056f429ff282abcab22be4843 { return addPrefixToIdentifier(++s_lastUsedIdentifier); diff --git a/Source/JavaScriptCore/inspector/IdentifiersFactory.h b/Source/JavaScriptCore/inspector/IdentifiersFactory.h -index eb25aedee4cd9ebe007e06c2515b37ee095b06f4..badf6559595c8377db1089ca3c25008e1be2c8f1 100644 +index 4113ddb45d4a8d08379d4dc56c44cde56162accf..e00cb9cb01a7a241f3f25b1e4cdc2fcaee92b3ac 100644 --- a/Source/JavaScriptCore/inspector/IdentifiersFactory.h +++ b/Source/JavaScriptCore/inspector/IdentifiersFactory.h @@ -31,6 +31,7 @@ namespace Inspector { - class JS_EXPORT_PRIVATE IdentifiersFactory { + class IdentifiersFactory { public: -+ static void initializeWithProcessID(uint64_t); - static String createIdentifier(); - static String requestId(unsigned long identifier); ++ JS_EXPORT_PRIVATE static void initializeWithProcessID(uint64_t); + JS_EXPORT_PRIVATE static String createIdentifier(); + JS_EXPORT_PRIVATE static String requestId(unsigned long identifier); }; diff --git a/Source/JavaScriptCore/inspector/InjectedScriptBase.cpp b/Source/JavaScriptCore/inspector/InjectedScriptBase.cpp -index 731a91727561c1507d074ad27f592d274dfeb324..9320b24579466bb1baa8b68430fe9cbb6c152770 100644 +index 8b39848154ecab9f7daa2d21c85562a319cd06d7..c8a1f44cb4516993899ffe1404b6c3865d42433a 100644 --- a/Source/JavaScriptCore/inspector/InjectedScriptBase.cpp +++ b/Source/JavaScriptCore/inspector/InjectedScriptBase.cpp -@@ -84,7 +84,10 @@ static RefPtr jsToInspectorValue(JSC::JSGlobalObject* globalObject, +@@ -85,7 +85,10 @@ static RefPtr jsToInspectorValue(JSC::JSGlobalObject* globalObject, JSC::PropertyNameArray propertyNames(vm, JSC::PropertyNameMode::Strings, JSC::PrivateSymbolMode::Exclude); object.methodTable()->getOwnPropertyNames(&object, globalObject, propertyNames, JSC::DontEnumPropertiesMode::Exclude); for (auto& name : propertyNames) { @@ -149,10 +146,10 @@ index 731a91727561c1507d074ad27f592d274dfeb324..9320b24579466bb1baa8b68430fe9cbb return nullptr; inspectorObject->setValue(name.string(), inspectorValue.releaseNonNull()); diff --git a/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.cpp b/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.cpp -index 820a08fc660633e09675d0e647bd0c50d2fa905a..5ca5ee5a6897b7ef332d906018b457122096df98 100644 +index 1f5d0adbf624bd24ef1e525967e6e82e8c37b4e5..4fe0f364b4ccd11774bf29f772e0a568549a4322 100644 --- a/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.cpp +++ b/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.cpp -@@ -101,7 +101,7 @@ void BackendDispatcher::registerDispatcherForDomain(const String& domain, Supple +@@ -102,7 +102,7 @@ void BackendDispatcher::registerDispatcherForDomain(const String& domain, Supple m_dispatchers.set(domain, dispatcher); } @@ -161,7 +158,7 @@ index 820a08fc660633e09675d0e647bd0c50d2fa905a..5ca5ee5a6897b7ef332d906018b45712 { Ref protect(*this); -@@ -146,6 +146,9 @@ void BackendDispatcher::dispatch(const String& message) +@@ -147,6 +147,9 @@ void BackendDispatcher::dispatch(const String& message) requestId = *requestIdInt; } @@ -172,18 +169,19 @@ index 820a08fc660633e09675d0e647bd0c50d2fa905a..5ca5ee5a6897b7ef332d906018b45712 // We could be called re-entrantly from a nested run loop, so restore the previous id. SetForScope scopedRequestId(m_currentRequestId, requestId); diff --git a/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.h b/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.h -index 31957be19b946aa90d316dc978a301f80956dd9c..d1a01e7546996535eb3884524c251c50a998eb33 100644 +index 28f4cdacf6ebd7037a42a75872618436332d90ec..463f014be2bd29a75bee7b2113b6f929da13aca5 100644 --- a/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.h +++ b/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.h -@@ -83,7 +83,10 @@ public: +@@ -95,8 +95,11 @@ public: + ServerError }; - void registerDispatcherForDomain(const String& domain, SupplementalBackendDispatcher*); -- void dispatch(const String& message); -+ + enum class InterceptionResult { Intercepted, Continue }; + using Interceptor = WTF::Function&)>; -+ void dispatch(const String& message, Interceptor&& interceptor = Interceptor()); ++ + JS_EXPORT_PRIVATE void registerDispatcherForDomain(const String& domain, SupplementalBackendDispatcher*); +- JS_EXPORT_PRIVATE void dispatch(const String& message); ++ JS_EXPORT_PRIVATE void dispatch(const String& message, Interceptor&& interceptor = Interceptor()); // Note that 'unused' is a workaround so the compiler can pick the right sendResponse based on arity. // When is fixed or this class is renamed for the JSON::Object case, @@ -222,10 +220,10 @@ index 0cc2127c9c12c2d82dea9550bad73f4ffb99ba24..8ca65cc042d435cbc0e05dcc5c5dfc95 } diff --git a/Source/JavaScriptCore/inspector/InspectorTarget.h b/Source/JavaScriptCore/inspector/InspectorTarget.h -index 88b72e94c4e8636de88419733b0a63ad4e0b9a73..153ee84f2c7ef86c548c62a65d6ad99214090230 100644 +index b555c2e5a071d0a6a016061cc60755449557556d..d019346f0932296d15212c76a4a9b56beb565ff4 100644 --- a/Source/JavaScriptCore/inspector/InspectorTarget.h +++ b/Source/JavaScriptCore/inspector/InspectorTarget.h -@@ -57,8 +57,12 @@ public: +@@ -66,8 +66,12 @@ public: virtual void connect(FrontendChannel::ConnectionType) = 0; virtual void disconnect() = 0; virtual void sendMessageToTargetBackend(const String&) = 0; @@ -239,16 +237,16 @@ index 88b72e94c4e8636de88419733b0a63ad4e0b9a73..153ee84f2c7ef86c548c62a65d6ad992 bool m_isPaused { false }; }; diff --git a/Source/JavaScriptCore/inspector/JSGlobalObjectConsoleClient.cpp b/Source/JavaScriptCore/inspector/JSGlobalObjectConsoleClient.cpp -index 15d2592d36b402bf2210dc4970ff40957022e84a..99ac14dc75ff5296e1f6c42bdbf8c128f2d82254 100644 +index 13eb84b3cba851e14eae8894f8f7aeb242b6f9d4..30bfdf65a7b891420a25bbc54bfe7f03db694273 100644 --- a/Source/JavaScriptCore/inspector/JSGlobalObjectConsoleClient.cpp +++ b/Source/JavaScriptCore/inspector/JSGlobalObjectConsoleClient.cpp -@@ -221,6 +221,14 @@ void JSGlobalObjectConsoleClient::screenshot(JSGlobalObject*, RefdeveloperExtrasEnabled())) ++ if (!m_consoleAgent->developerExtrasEnabled()) + return; + + warnUnimplemented("console.bindingCalled"_s); @@ -256,7 +254,7 @@ index 15d2592d36b402bf2210dc4970ff40957022e84a..99ac14dc75ff5296e1f6c42bdbf8c128 + void JSGlobalObjectConsoleClient::warnUnimplemented(const String& method) { - String message = method + " is currently ignored in JavaScript context inspection."_s; + auto message = makeString(method, " is currently ignored in JavaScript context inspection."_s); diff --git a/Source/JavaScriptCore/inspector/JSGlobalObjectConsoleClient.h b/Source/JavaScriptCore/inspector/JSGlobalObjectConsoleClient.h index 6bbd0729a65b4a901e7da4dc50cc47c669bd9897..452b25d0e8eba3df1d5f6623dc222048bef120cd 100644 --- a/Source/JavaScriptCore/inspector/JSGlobalObjectConsoleClient.h @@ -270,7 +268,7 @@ index 6bbd0729a65b4a901e7da4dc50cc47c669bd9897..452b25d0e8eba3df1d5f6623dc222048 void warnUnimplemented(const String& method); void internalAddMessage(MessageType, MessageLevel, JSC::JSGlobalObject*, Ref&&); diff --git a/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp b/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp -index 594584db96a3de67b92910f472f1403bc9b26ce2..8ba453f9ae8726ccfb26c55180371c20bed6962e 100644 +index 0cb6efeef2430faa5dbd812f71d4abfd5f6eb9df..787ec6a5f8413c0a9dc133cb0e51ccdab58d40d0 100644 --- a/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp +++ b/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp @@ -194,9 +194,8 @@ void InspectorRuntimeAgent::callFunctionOn(const Protocol::Runtime::RemoteObject @@ -367,10 +365,10 @@ index e47c6ca59f37fbf18ca8a393df72e0472363fabd..b393465540595220561ae00afb854082 void InspectorTargetAgent::didCommitProvisionalTarget(const String& oldTargetID, const String& committedTargetID) diff --git a/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.h b/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.h -index 4edcbf5f4aee2eb8e5675a23b9db67e9d640ef7f..a32b0f3a5de49e58b8a35cec9202b7880e91a2f0 100644 +index 04377b714a6ccb5294c65d592e74350621d470ba..b6de937bfa3e6185ce29f4e432d327a3cedee6df 100644 --- a/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.h +++ b/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.h -@@ -51,15 +51,20 @@ public: +@@ -53,8 +53,11 @@ public: Protocol::ErrorStringOr setPauseOnStart(bool) final; Protocol::ErrorStringOr resume(const String& targetId) final; Protocol::ErrorStringOr sendMessageToTarget(const String& targetId, const String& message) final; @@ -378,21 +376,22 @@ index 4edcbf5f4aee2eb8e5675a23b9db67e9d640ef7f..a32b0f3a5de49e58b8a35cec9202b788 + Protocol::ErrorStringOr close(const String& targetId, std::optional&& runBeforeUnload) override; // Target lifecycle. ++ void targetCrashed(InspectorTarget&); void targetCreated(InspectorTarget&); void targetDestroyed(InspectorTarget&); -+ void targetCrashed(InspectorTarget&); void didCommitProvisionalTarget(const String& oldTargetID, const String& committedTargetID); - +@@ -62,6 +65,9 @@ public: // Target messages. void sendMessageFromTargetToFrontend(const String& targetId, const String& message); ++ bool shouldPauseOnStart() const { return m_shouldPauseOnStart; } + bool isConnected() { return m_isConnected; } + private: // FrontendChannel FrontendChannel::ConnectionType connectionType() const; diff --git a/Source/JavaScriptCore/inspector/protocol/DOM.json b/Source/JavaScriptCore/inspector/protocol/DOM.json -index fc7612613d09e03f481c567a8a4a121884e2cb6c..b0a7b284684bccaa7dfb0892a64d4a803357ccc1 100644 +index 25711ac1aa269d7e0231a6169be1bc495f2c8dc0..bcb4d83e58a51458de6e070ef7cb859ee333bdbc 100644 --- a/Source/JavaScriptCore/inspector/protocol/DOM.json +++ b/Source/JavaScriptCore/inspector/protocol/DOM.json @@ -80,6 +80,16 @@ @@ -412,24 +411,7 @@ index fc7612613d09e03f481c567a8a4a121884e2cb6c..b0a7b284684bccaa7dfb0892a64d4a80 { "id": "EventListener", "type": "object", -@@ -267,6 +277,16 @@ - { "name": "width", "type": "number" }, - { "name": "height", "type": "number" } - ] -+ }, -+ { -+ "id": "FilePayload", -+ "type": "object", -+ "description": "Data to construct File object.", -+ "properties": [ -+ { "name": "name", "type": "string", "description": "File name." }, -+ { "name": "type", "type": "string", "description": "File type." }, -+ { "name": "data", "type": "string", "description": "Base64-encoded file data." } -+ ] - } - ], - "commands": [ -@@ -696,7 +716,10 @@ +@@ -745,7 +755,10 @@ "description": "Resolves JavaScript node object for given node id.", "targetTypes": ["page"], "parameters": [ @@ -441,7 +423,7 @@ index fc7612613d09e03f481c567a8a4a121884e2cb6c..b0a7b284684bccaa7dfb0892a64d4a80 { "name": "objectGroup", "type": "string", "optional": true, "description": "Symbolic group name that can be used to release multiple objects." } ], "returns": [ -@@ -773,6 +796,46 @@ +@@ -822,6 +835,46 @@ "returns": [ { "name": "mediaStats", "$ref": "MediaStats", "description": "An interleaved array of node attribute names and values." } ] @@ -482,9 +464,9 @@ index fc7612613d09e03f481c567a8a4a121884e2cb6c..b0a7b284684bccaa7dfb0892a64d4a80 + "description": "Sets input files for given ", + "parameters": [ + { "name": "objectId", "$ref": "Runtime.RemoteObjectId", "description": "Input element handle." }, -+ { "name": "files", "type": "array", "items": { "$ref": "FilePayload" }, "optional": true, "description": "Files to set" }, -+ { "name": "paths", "type": "array", "items": { "type": "string" }, "optional": true, "description": "File paths to set" } -+ ] ++ { "name": "paths", "type": "array", "items": { "type": "string" }, "description": "File paths to set" } ++ ], ++ "async": true } ], "events": [ @@ -532,10 +514,10 @@ index 0000000000000000000000000000000000000000..79edea03fed4e9be5da96e1275e182a4 +} diff --git a/Source/JavaScriptCore/inspector/protocol/Emulation.json b/Source/JavaScriptCore/inspector/protocol/Emulation.json new file mode 100644 -index 0000000000000000000000000000000000000000..2a49dd417360da37c83c4d375de468f949dce5db +index 0000000000000000000000000000000000000000..8377901cb3ad75c29532a1f0f547efb53558a327 --- /dev/null +++ b/Source/JavaScriptCore/inspector/protocol/Emulation.json -@@ -0,0 +1,52 @@ +@@ -0,0 +1,59 @@ +{ + "domain": "Emulation", + "availability": ["web"], @@ -585,15 +567,22 @@ index 0000000000000000000000000000000000000000..2a49dd417360da37c83c4d375de468f9 + { + "name": "resetPermissions", + "description": "Clears permission overrides." ++ }, ++ { ++ "name": "setOrientationOverride", ++ "description": "Overrides window.orientation with provided value.", ++ "parameters": [ ++ { "name": "angle", "type": "integer", "optional": true } ++ ] + } + ] +} diff --git a/Source/JavaScriptCore/inspector/protocol/Input.json b/Source/JavaScriptCore/inspector/protocol/Input.json new file mode 100644 -index 0000000000000000000000000000000000000000..b9ab57a2b5739ed997231399b4bd4042a0cb0935 +index 0000000000000000000000000000000000000000..1c43b476603325fa412bcfded9163e7a00aebbfa --- /dev/null +++ b/Source/JavaScriptCore/inspector/protocol/Input.json -@@ -0,0 +1,223 @@ +@@ -0,0 +1,264 @@ +{ + "domain": "Input", + "availability": ["web"], @@ -602,6 +591,16 @@ index 0000000000000000000000000000000000000000..b9ab57a2b5739ed997231399b4bd4042 + "id": "TimeSinceEpoch", + "description": "UTC time in seconds, counted from January 1, 1970.", + "type": "number" ++ }, ++ { ++ "id": "TouchPoint", ++ "type": "object", ++ "description": "Touch point.", ++ "properties": [ ++ { "name": "x", "type": "integer", "description": "X coordinate of the event relative to the main frame's viewport in CSS pixels." }, ++ { "name": "y", "type": "integer", "description": "Y coordinate of the event relative to the main frame's viewport in CSS pixels." }, ++ { "name": "id", "type": "integer", "description": "Identifier used to track touch sources between events, must be unique within an event." } ++ ] + } + ], + "commands": [ @@ -814,6 +813,37 @@ index 0000000000000000000000000000000000000000..b9ab57a2b5739ed997231399b4bd4042 + "type": "integer" + } + ] ++ }, ++ { ++ "name": "dispatchTouchEvent", ++ "description": "Dispatches a touch event to the page.", ++ "async": true, ++ "parameters": [ ++ { ++ "name": "type", ++ "description": "Type of the touch event.", ++ "type": "string", ++ "enum": [ ++ "touchStart", ++ "touchMove", ++ "touchEnd", ++ "touchCancel" ++ ] ++ }, ++ { ++ "name": "modifiers", ++ "description": "Bit field representing pressed modifier keys. Alt=1, Ctrl=2, Meta/Command=4, Shift=8\n(default: 0).", ++ "optional": true, ++ "type": "integer" ++ }, ++ { ++ "name": "touchPoints", ++ "description": "List of touch points", ++ "type": "array", ++ "optional": true, ++ "items": { "$ref": "TouchPoint" } ++ } ++ ] + } + ] +} @@ -836,10 +866,10 @@ index 96af27ece2ac200e11c4311b3ca0d9d3b5a048da..3168f7806fcbdabec07acc5e304bae1e ], "events": [ diff --git a/Source/JavaScriptCore/inspector/protocol/Page.json b/Source/JavaScriptCore/inspector/protocol/Page.json -index b5e2bb2eb58765ec20392b36bf5ef1ac35857a69..7e6c8b8954ed3d5d4ac77dfe51d0e08c56a7a5fc 100644 +index 3d032713a7f3bb9645bfc7d42455a0494b5376c0..913dda5e90b86cc5f8e4ca6881f6db57520a7f66 100644 --- a/Source/JavaScriptCore/inspector/protocol/Page.json +++ b/Source/JavaScriptCore/inspector/protocol/Page.json -@@ -20,7 +20,14 @@ +@@ -20,7 +20,15 @@ "ScriptEnabled", "ShowDebugBorders", "ShowRepaintCounter", @@ -851,11 +881,12 @@ index b5e2bb2eb58765ec20392b36bf5ef1ac35857a69..7e6c8b8954ed3d5d4ac77dfe51d0e08c + "NotificationsEnabled", + "FullScreenEnabled", + "InputTypeMonthEnabled", -+ "InputTypeWeekEnabled" ++ "InputTypeWeekEnabled", ++ "FixedBackgroundsPaintRelativeToDocument" ] }, { -@@ -62,6 +69,12 @@ +@@ -62,6 +70,12 @@ "enum": ["None", "Lax", "Strict"], "description": "Same-Site policy of a cookie." }, @@ -868,9 +899,9 @@ index b5e2bb2eb58765ec20392b36bf5ef1ac35857a69..7e6c8b8954ed3d5d4ac77dfe51d0e08c { "id": "Frame", "type": "object", -@@ -125,6 +138,50 @@ - { "name": "secure", "type": "boolean", "description": "True if cookie is secure." }, - { "name": "sameSite", "$ref": "CookieSameSitePolicy", "description": "Cookie Same-Site policy." } +@@ -126,6 +140,50 @@ + { "name": "sameSite", "$ref": "CookieSameSitePolicy", "description": "Cookie Same-Site policy." }, + { "name": "partitionKey", "type": "string", "optional": true, "description": "Cookie partition key. If null and partitioned property is true, then key must be computed." } ] + }, + { @@ -919,7 +950,7 @@ index b5e2bb2eb58765ec20392b36bf5ef1ac35857a69..7e6c8b8954ed3d5d4ac77dfe51d0e08c } ], "commands": [ -@@ -144,6 +201,14 @@ +@@ -145,6 +203,14 @@ { "name": "revalidateAllResources", "type": "boolean", "optional": true, "description": "If true, all cached subresources will be revalidated when the main resource loads. Otherwise, only expired cached subresources will be revalidated (the default behavior for most WebKit clients)." } ] }, @@ -934,7 +965,7 @@ index b5e2bb2eb58765ec20392b36bf5ef1ac35857a69..7e6c8b8954ed3d5d4ac77dfe51d0e08c { "name": "navigate", "description": "Navigates current page to the given URL.", -@@ -160,6 +225,14 @@ +@@ -161,6 +227,14 @@ { "name": "value", "type": "string", "optional": true, "description": "Value to override the user agent with. If this value is not provided, the override is removed. Overrides are removed when Web Inspector closes/disconnects." } ] }, @@ -949,7 +980,7 @@ index b5e2bb2eb58765ec20392b36bf5ef1ac35857a69..7e6c8b8954ed3d5d4ac77dfe51d0e08c { "name": "overrideSetting", "description": "Allows the frontend to override the inspected page's settings.", -@@ -283,6 +356,28 @@ +@@ -285,6 +359,28 @@ { "name": "media", "type": "string", "description": "Media type to emulate. Empty string disables the override." } ] }, @@ -978,7 +1009,7 @@ index b5e2bb2eb58765ec20392b36bf5ef1ac35857a69..7e6c8b8954ed3d5d4ac77dfe51d0e08c { "name": "snapshotNode", "description": "Capture a snapshot of the specified node that does not include unrelated layers.", -@@ -303,7 +398,8 @@ +@@ -305,7 +401,8 @@ { "name": "y", "type": "integer", "description": "Y coordinate" }, { "name": "width", "type": "integer", "description": "Rectangle width" }, { "name": "height", "type": "integer", "description": "Rectangle height" }, @@ -988,7 +1019,7 @@ index b5e2bb2eb58765ec20392b36bf5ef1ac35857a69..7e6c8b8954ed3d5d4ac77dfe51d0e08c ], "returns": [ { "name": "dataURL", "type": "string", "description": "Base64-encoded image data (PNG)." } -@@ -321,12 +417,71 @@ +@@ -323,12 +420,64 @@ { "name": "setScreenSizeOverride", "description": "Overrides screen size exposed to DOM and used in media queries for testing with provided values.", @@ -1049,19 +1080,12 @@ index b5e2bb2eb58765ec20392b36bf5ef1ac35857a69..7e6c8b8954ed3d5d4ac77dfe51d0e08c + "description": "Crashes the page process" + }, + { -+ "name": "setOrientationOverride", -+ "description": "Overrides window.orientation with provided value.", -+ "parameters": [ -+ { "name": "angle", "type": "integer", "optional": true } -+ ] -+ }, -+ { + "name": "updateScrollingState", + "description": "Ensures that the scroll regions are up to date." } ], "events": [ -@@ -334,14 +489,16 @@ +@@ -336,14 +485,16 @@ "name": "domContentEventFired", "targetTypes": ["page"], "parameters": [ @@ -1080,7 +1104,7 @@ index b5e2bb2eb58765ec20392b36bf5ef1ac35857a69..7e6c8b8954ed3d5d4ac77dfe51d0e08c ] }, { -@@ -351,6 +508,14 @@ +@@ -353,6 +504,14 @@ { "name": "frame", "$ref": "Frame", "description": "Frame object." } ] }, @@ -1095,7 +1119,7 @@ index b5e2bb2eb58765ec20392b36bf5ef1ac35857a69..7e6c8b8954ed3d5d4ac77dfe51d0e08c { "name": "frameDetached", "description": "Fired when frame has been detached from its parent.", -@@ -379,7 +544,8 @@ +@@ -381,7 +540,8 @@ "targetTypes": ["page"], "parameters": [ { "name": "frameId", "$ref": "Network.FrameId", "description": "Id of the frame that has scheduled a navigation." }, @@ -1105,7 +1129,7 @@ index b5e2bb2eb58765ec20392b36bf5ef1ac35857a69..7e6c8b8954ed3d5d4ac77dfe51d0e08c ] }, { -@@ -390,6 +556,22 @@ +@@ -392,6 +552,22 @@ { "name": "frameId", "$ref": "Network.FrameId", "description": "Id of the frame that has cleared its scheduled navigation." } ] }, @@ -1128,7 +1152,7 @@ index b5e2bb2eb58765ec20392b36bf5ef1ac35857a69..7e6c8b8954ed3d5d4ac77dfe51d0e08c { "name": "defaultUserPreferencesDidChange", "description": "Fired when the default value of a user preference changes at the system level.", -@@ -397,6 +579,42 @@ +@@ -399,6 +575,42 @@ "parameters": [ { "name": "preferences", "type": "array", "items": { "$ref": "UserPreference" }, "description": "List of user preferences that can be overriden and their new system (default) values." } ] @@ -1173,10 +1197,10 @@ index b5e2bb2eb58765ec20392b36bf5ef1ac35857a69..7e6c8b8954ed3d5d4ac77dfe51d0e08c } diff --git a/Source/JavaScriptCore/inspector/protocol/Playwright.json b/Source/JavaScriptCore/inspector/protocol/Playwright.json new file mode 100644 -index 0000000000000000000000000000000000000000..978d6f92b18498633c982969299f068332eb2884 +index 0000000000000000000000000000000000000000..440dd95173e066a886de120fb3dab7597d85feb6 --- /dev/null +++ b/Source/JavaScriptCore/inspector/protocol/Playwright.json -@@ -0,0 +1,307 @@ +@@ -0,0 +1,315 @@ +{ + "domain": "Playwright", + "availability": ["web"], @@ -1352,6 +1376,14 @@ index 0000000000000000000000000000000000000000..978d6f92b18498633c982969299f0683 + ] + }, + { ++ "name": "setPageZoomFactor", ++ "description": "Changes page zoom factor.", ++ "parameters": [ ++ { "name": "pageProxyId", "$ref": "PageProxyID", "description": "Unique identifier of the page proxy." }, ++ { "name": "zoomFactor", "type": "number" } ++ ] ++ }, ++ { + "name": "getAllCookies", + "description": "Returns all cookies in the given browser context.", + "async": true, @@ -1634,23 +1666,11 @@ index 52920cded24a9c6b0ef6fb4e518664955db4f9fa..bbbabc4e7259088b9404e8cc07eecd6f ] }, { -diff --git a/Source/JavaScriptCore/profiler/ProfilerBytecodeSequence.cpp b/Source/JavaScriptCore/profiler/ProfilerBytecodeSequence.cpp -index dd1286cec6e77895f519911c89719b6064db6949..b732e0eab0fd29e1a1c9a2179cc86a951768c062 100644 ---- a/Source/JavaScriptCore/profiler/ProfilerBytecodeSequence.cpp -+++ b/Source/JavaScriptCore/profiler/ProfilerBytecodeSequence.cpp -@@ -28,7 +28,6 @@ - - #include "CodeBlock.h" - #include "JSCInlines.h" --#include "ProfilerDumper.h" - #include - - namespace JSC { namespace Profiler { diff --git a/Source/JavaScriptCore/runtime/ConsoleClient.h b/Source/JavaScriptCore/runtime/ConsoleClient.h -index 72c81757450ad5ebacd5fd20d2a16095514802ec..b7d8ab1e04d3850180079870468b28eff504626a 100644 +index 24891ad836086fd23024fcb4d08ca63f6974c812..29f4b6b1923383fec7a99d28a4e815dc4536d160 100644 --- a/Source/JavaScriptCore/runtime/ConsoleClient.h +++ b/Source/JavaScriptCore/runtime/ConsoleClient.h -@@ -69,6 +69,7 @@ public: +@@ -78,6 +78,7 @@ public: virtual void record(JSGlobalObject*, Ref&&) = 0; virtual void recordEnd(JSGlobalObject*, Ref&&) = 0; virtual void screenshot(JSGlobalObject*, Ref&&) = 0; @@ -1659,18 +1679,10 @@ index 72c81757450ad5ebacd5fd20d2a16095514802ec..b7d8ab1e04d3850180079870468b28ef private: enum ArgumentRequirement { ArgumentRequired, ArgumentNotRequired }; diff --git a/Source/ThirdParty/libwebrtc/CMakeLists.txt b/Source/ThirdParty/libwebrtc/CMakeLists.txt -index d6b1e73b1268a1224c2d77b936ce46347be62dac..acd1950327608988059a7e972fb4d40f9efc0c68 100644 +index ca4f3508a44e3c6677a72fbe3d7c853714b4f2c6..ae117f5f402a7eb259e376ca9440e00062e22d9f 100644 --- a/Source/ThirdParty/libwebrtc/CMakeLists.txt +++ b/Source/ThirdParty/libwebrtc/CMakeLists.txt -@@ -452,6 +452,7 @@ set(webrtc_SOURCES - Source/third_party/boringssl/src/crypto/x509/x_val.c - Source/third_party/boringssl/src/crypto/x509/x_x509a.c - Source/third_party/boringssl/src/crypto/x509/x_x509.c -+ - Source/third_party/boringssl/src/decrepit/bio/base64_bio.c - Source/third_party/boringssl/src/decrepit/blowfish/blowfish.c - Source/third_party/boringssl/src/decrepit/cast/cast.c -@@ -530,6 +531,11 @@ set(webrtc_SOURCES +@@ -532,6 +532,11 @@ set(webrtc_SOURCES Source/third_party/crc32c/src/src/crc32c.cc Source/third_party/crc32c/src/src/crc32c_portable.cc Source/third_party/crc32c/src/src/crc32c_sse42.cc @@ -1682,47 +1694,40 @@ index d6b1e73b1268a1224c2d77b936ce46347be62dac..acd1950327608988059a7e972fb4d40f Source/third_party/libyuv/source/compare.cc Source/third_party/libyuv/source/compare_common.cc Source/third_party/libyuv/source/compare_gcc.cc -@@ -2270,6 +2276,10 @@ set(webrtc_INCLUDE_DIRECTORIES PRIVATE +@@ -2348,6 +2353,11 @@ set(webrtc_INCLUDE_DIRECTORIES PRIVATE Source/third_party/libsrtp/config Source/third_party/libsrtp/crypto/include Source/third_party/libsrtp/include +# Playwright begin + Source/third_party/libwebm + Source/third_party/libvpx/source/libvpx ++ Source/third_party/libvpx/source/libvpx/third_party/googletest/src/include +# Playwright end Source/third_party/libyuv/include Source/third_party/opus/src/celt Source/third_party/opus/src/include diff --git a/Source/ThirdParty/libwebrtc/Configurations/Base-libwebrtc.xcconfig b/Source/ThirdParty/libwebrtc/Configurations/Base-libwebrtc.xcconfig -index 94f6675a8b7ca64e12aaf1c3b01848f0a6b737a8..20660f511914ebb7877e050bb5bc232c3df2daa5 100644 +index 0c5c8e689bdddec766f9de5bffd4444a5e068d77..330dd1f585e530722178c65c883641a2b8c0f1bd 100644 --- a/Source/ThirdParty/libwebrtc/Configurations/Base-libwebrtc.xcconfig +++ b/Source/ThirdParty/libwebrtc/Configurations/Base-libwebrtc.xcconfig -@@ -21,7 +21,7 @@ - // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - --HEADER_SEARCH_PATHS = Source Source/third_party/libsrtp/crypto/include Source/third_party/libsrtp/include Source/third_party/boringssl/src/include Source/third_party/libyuv/include Source/webrtc/sdk/objc/Framework/Headers Source/webrtc/common_audio/signal_processing/include Source/webrtc/modules/audio_coding/codecs/isac/main/include Source/third_party/opus/src/celt Source/third_party/opus/src/include Source/third_party/opus/src/src Source/webrtc/modules/audio_device/mac Source/webrtc/modules/audio_device/ios Source/webrtc Source/webrtc/sdk/objc Source/webrtc/sdk/objc/base Source/webrtc/sdk/objc/Framework/Classes Source/third_party/libsrtp/config Source/webrtc/sdk/objc/Framework/Classes/Common Source/webrtc/sdk/objc/Framework/Classes/Video Source/webrtc/sdk/objc/Framework/Classes/PeerConnection Source/third_party/abseil-cpp Source/third_party/libvpx/source/libvpx Source/third_party/libwebm/webm_parser/include Source/third_party/crc32c/config Source/third_party/crc32c/include Source/third_party/crc32c/src/include Source/third_party/libaom/source/libaom; -+HEADER_SEARCH_PATHS = Source Source/third_party/libsrtp/crypto/include Source/third_party/libsrtp/include Source/third_party/boringssl/src/include Source/third_party/libyuv/include Source/webrtc/sdk/objc/Framework/Headers Source/webrtc/common_audio/signal_processing/include Source/webrtc/modules/audio_coding/codecs/isac/main/include Source/third_party/opus/src/celt Source/third_party/opus/src/include Source/third_party/opus/src/src Source/webrtc/modules/audio_device/mac Source/webrtc/modules/audio_device/ios Source/webrtc Source/webrtc/sdk/objc Source/webrtc/sdk/objc/base Source/webrtc/sdk/objc/Framework/Classes Source/third_party/libsrtp/config Source/webrtc/sdk/objc/Framework/Classes/Common Source/webrtc/sdk/objc/Framework/Classes/Video Source/webrtc/sdk/objc/Framework/Classes/PeerConnection Source/third_party/abseil-cpp Source/third_party/libvpx/source/libvpx Source/third_party/libwebm/webm_parser/include Source/third_party/crc32c/config Source/third_party/crc32c/include Source/third_party/crc32c/src/include Source/third_party/libaom/source/libaom Source/third_party/libwebm/mkvmuxer Source/third_party/libvpx/source/libvpx/third_party/libwebm; +@@ -24,6 +24,8 @@ + HEADER_SEARCH_PATHS = Source Source/third_party/libsrtp/crypto/include Source/third_party/libsrtp/include Source/third_party/boringssl/src/include Source/third_party/libyuv/include Source/webrtc/webkit_sdk/objc/Framework/Headers Source/webrtc/common_audio/signal_processing/include Source/webrtc/modules/audio_coding/codecs/isac/main/include Source/third_party/opus/src/celt Source/third_party/opus/src/include Source/third_party/opus/src/src Source/webrtc/modules/audio_device/mac Source/webrtc/modules/audio_device/ios Source/webrtc Source/webrtc/webkit_sdk/objc Source/webrtc/webkit_sdk/objc/base Source/webrtc/webkit_sdk/objc/Framework/Classes Source/third_party/libsrtp/config Source/webrtc/webkit_sdk/objc/Framework/Classes/Common Source/webrtc/webkit_sdk/objc/Framework/Classes/Video Source/webrtc/webkit_sdk/objc/Framework/Classes/PeerConnection Source/third_party/abseil-cpp Source/third_party/libvpx/source/libvpx Source/third_party/libwebm/webm_parser/include Source/third_party/crc32c/config Source/third_party/crc32c/include Source/third_party/crc32c/src/include Source/third_party/libaom/source/libaom; USE_HEADERMAP = NO; ++HEADER_SEARCH_PATHS = ${HEADER_SEARCH_PATHS} Source/third_party/libwebm/mkvmuxer Source/third_party/libvpx/source/libvpx/third_party/libwebm; ++ WARNING_CFLAGS = -Wno-deprecated-declarations $(inherited); + + // FIXME: Set WEBRTC_USE_BUILTIN_ISAC_FIX and WEBRTC_USE_BUILTIN_ISAC_FLOAT for iOS and Mac diff --git a/Source/ThirdParty/libwebrtc/Configurations/libwebrtc.exp b/Source/ThirdParty/libwebrtc/Configurations/libwebrtc.exp -index a01284369bedab3d44e7a3c2671590b3ca2b18fc..6a75fd2d366386e12dc612bdcfb914613c636478 100644 +index 13c5b5ea562fe808a3251c3ae789f8106632cd25..36b77e7d6bc78ba2e982cad5a2b4792775d3280d 100644 --- a/Source/ThirdParty/libwebrtc/Configurations/libwebrtc.exp +++ b/Source/ThirdParty/libwebrtc/Configurations/libwebrtc.exp -@@ -402,3 +402,24 @@ __ZN3rtc7LogSink12OnLogMessageENSt3__117basic_string_viewIcNS1_11char_traitsIcEE - __ZN3rtc7LogSink12OnLogMessageERKNS_10LogLineRefE - __ZN3rtc7LogSink12OnLogMessageERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEENS_15LoggingSeverityEPKc - __ZTVN3rtc7LogSinkE -+__ZN8mkvmuxer11SegmentInfo15set_writing_appEPKc +@@ -434,3 +434,16 @@ __ZN6webrtc18VideoFrameMetadata7SetSsrcEj + __ZN6webrtc18VideoFrameMetadata8SetCsrcsENSt3__16vectorIjNS1_9allocatorIjEEEE + __ZN6webrtc18VideoFrameMetadata8SetWidthEt + __ZN6webrtc18VideoFrameMetadata9SetHeightEt +__ZN8mkvmuxer11SegmentInfo4InitEv -+__ZN8mkvmuxer7Segment10OutputCuesEb -+__ZN8mkvmuxer7Segment13AddVideoTrackEiii -+__ZN8mkvmuxer7Segment4InitEPNS_10IMkvWriterE -+__ZN8mkvmuxer7Segment8AddFrameEPKhyyyb -+__ZN8mkvmuxer7Segment8FinalizeEv -+__ZN8mkvmuxer7SegmentC1Ev -+__ZN8mkvmuxer7SegmentD1Ev +__ZN8mkvmuxer9MkvWriterC1EP7__sFILE +_ARGBToI420 +_vpx_codec_destroy @@ -1735,35 +1740,11 @@ index a01284369bedab3d44e7a3c2671590b3ca2b18fc..6a75fd2d366386e12dc612bdcfb91461 +_vpx_codec_iface_name +_vpx_codec_version_str +_vpx_codec_vp8_cx -diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/rtp_rtcp/source/rtcp_transceiver_impl.cc b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/rtp_rtcp/source/rtcp_transceiver_impl.cc -index 625cb7fefc6a699d9e2f28c6acc1bc7681ea3984..cd6677a7ffd3321978427a9fc6fbed5179aebb60 100644 ---- a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/rtp_rtcp/source/rtcp_transceiver_impl.cc -+++ b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/rtp_rtcp/source/rtcp_transceiver_impl.cc -@@ -16,6 +16,7 @@ - #include "absl/algorithm/container.h" - #include "absl/memory/memory.h" - #include "absl/types/optional.h" -+#include "api/call/transport.h" - #include "api/video/video_bitrate_allocation.h" - #include "modules/rtp_rtcp/include/receive_statistics.h" - #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" -diff --git a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/rtp_rtcp/source/rtp_format_h264.h b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/rtp_rtcp/source/rtp_format_h264.h -index f95c3b6c6b73a01974f26d88bcc533e5032ddb66..6a9368c60824cd32649c93286522d779cac59bd2 100644 ---- a/Source/ThirdParty/libwebrtc/Source/webrtc/modules/rtp_rtcp/source/rtp_format_h264.h -+++ b/Source/ThirdParty/libwebrtc/Source/webrtc/modules/rtp_rtcp/source/rtp_format_h264.h -@@ -16,6 +16,7 @@ - - #include - #include -+#include - #include - - #include "api/array_view.h" diff --git a/Source/ThirdParty/libwebrtc/libwebrtc.xcodeproj/project.pbxproj b/Source/ThirdParty/libwebrtc/libwebrtc.xcodeproj/project.pbxproj -index f5f1d0ef71f7fcf175b016ddaefd99f18d96c1c3..5632dcb4919eb22133a62810b91e143329e31ee0 100644 +index 7585b2e5e9bffdc8cabd888dd822313d53b30141..5909d33b9726cdc7d2d53b538f7da18bc221e30b 100644 --- a/Source/ThirdParty/libwebrtc/libwebrtc.xcodeproj/project.pbxproj +++ b/Source/ThirdParty/libwebrtc/libwebrtc.xcodeproj/project.pbxproj -@@ -35,6 +35,20 @@ +@@ -56,6 +56,20 @@ }; /* End PBXAggregateTarget section */ @@ -1784,17 +1765,7 @@ index f5f1d0ef71f7fcf175b016ddaefd99f18d96c1c3..5632dcb4919eb22133a62810b91e1433 /* Begin PBXBuildFile section */ 2D6BFF60280A93DF00A1A74F /* video_coding.h in Headers */ = {isa = PBXBuildFile; fileRef = 4131C45B234C81710028A615 /* video_coding.h */; settings = {ATTRIBUTES = (Public, ); }; }; 2D6BFF61280A93EC00A1A74F /* video_codec_initializer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4131C45E234C81720028A615 /* video_codec_initializer.h */; settings = {ATTRIBUTES = (Public, ); }; }; -@@ -5118,6 +5132,9 @@ - DDF30D9127C5C725006A526F /* receive_side_congestion_controller.h in Headers */ = {isa = PBXBuildFile; fileRef = DDF30D9027C5C725006A526F /* receive_side_congestion_controller.h */; }; - DDF30D9527C5C756006A526F /* bwe_defines.h in Headers */ = {isa = PBXBuildFile; fileRef = DDF30D9327C5C756006A526F /* bwe_defines.h */; }; - DDF30D9627C5C756006A526F /* remote_bitrate_estimator.h in Headers */ = {isa = PBXBuildFile; fileRef = DDF30D9427C5C756006A526F /* remote_bitrate_estimator.h */; }; -+ F3B7819924C7CC5200FCB122 /* mkvmuxerutil.cc in Sources */ = {isa = PBXBuildFile; fileRef = F3B7819624C7CC5100FCB122 /* mkvmuxerutil.cc */; }; -+ F3B7819A24C7CC5200FCB122 /* mkvmuxer.cc in Sources */ = {isa = PBXBuildFile; fileRef = F3B7819724C7CC5200FCB122 /* mkvmuxer.cc */; }; -+ F3B7819B24C7CC5200FCB122 /* mkvwriter.cc in Sources */ = {isa = PBXBuildFile; fileRef = F3B7819824C7CC5200FCB122 /* mkvwriter.cc */; }; - /* End PBXBuildFile section */ - - /* Begin PBXBuildRule section */ -@@ -5606,6 +5623,13 @@ +@@ -5786,6 +5800,13 @@ remoteGlobalIDString = DDF30D0527C5C003006A526F; remoteInfo = absl; }; @@ -1808,42 +1779,7 @@ index f5f1d0ef71f7fcf175b016ddaefd99f18d96c1c3..5632dcb4919eb22133a62810b91e1433 /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ -@@ -11165,6 +11189,9 @@ - DDF30D9027C5C725006A526F /* receive_side_congestion_controller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = receive_side_congestion_controller.h; sourceTree = ""; }; - DDF30D9327C5C756006A526F /* bwe_defines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bwe_defines.h; sourceTree = ""; }; - DDF30D9427C5C756006A526F /* remote_bitrate_estimator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = remote_bitrate_estimator.h; sourceTree = ""; }; -+ F3B7819624C7CC5100FCB122 /* mkvmuxerutil.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = mkvmuxerutil.cc; path = mkvmuxer/mkvmuxerutil.cc; sourceTree = ""; }; -+ F3B7819724C7CC5200FCB122 /* mkvmuxer.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = mkvmuxer.cc; path = mkvmuxer/mkvmuxer.cc; sourceTree = ""; }; -+ F3B7819824C7CC5200FCB122 /* mkvwriter.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = mkvwriter.cc; path = mkvmuxer/mkvwriter.cc; sourceTree = ""; }; - FB39D0D11200F0E300088E69 /* libwebrtc.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libwebrtc.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; - /* End PBXFileReference section */ - -@@ -19991,6 +20018,7 @@ - isa = PBXGroup; - children = ( - CDFD2F9224C4B2F90048DAC3 /* common */, -+ F3B7819524C7CC1300FCB122 /* mkvmuxer */, - CDEBB19224C0191800ADBD44 /* webm_parser */, - ); - path = libwebm; -@@ -20418,6 +20446,16 @@ - path = include; - sourceTree = ""; - }; -+ F3B7819524C7CC1300FCB122 /* mkvmuxer */ = { -+ isa = PBXGroup; -+ children = ( -+ F3B7819724C7CC5200FCB122 /* mkvmuxer.cc */, -+ F3B7819624C7CC5100FCB122 /* mkvmuxerutil.cc */, -+ F3B7819824C7CC5200FCB122 /* mkvwriter.cc */, -+ ); -+ name = mkvmuxer; -+ sourceTree = ""; -+ }; - FB39D06E1200ED9200088E69 = { - isa = PBXGroup; - children = ( -@@ -23693,6 +23731,7 @@ +@@ -24271,6 +24292,7 @@ ); dependencies = ( 410B3827292B73E90003E515 /* PBXTargetDependency */, @@ -1851,7 +1787,7 @@ index f5f1d0ef71f7fcf175b016ddaefd99f18d96c1c3..5632dcb4919eb22133a62810b91e1433 DD2E76E827C6B69A00F2A74C /* PBXTargetDependency */, CDEBB4CC24C01AB400ADBD44 /* PBXTargetDependency */, 411ED040212E0811004320BA /* PBXTargetDependency */, -@@ -23775,6 +23814,7 @@ +@@ -24364,6 +24386,7 @@ 4460B8B92B155B6A00392062 /* vp9_qp_parser_fuzzer */, 444A6EF02AEADFC9005FE121 /* vp9_replay_fuzzer */, 44945C512B9BA1C300447FFD /* webm_fuzzer */, @@ -1859,9 +1795,9 @@ index f5f1d0ef71f7fcf175b016ddaefd99f18d96c1c3..5632dcb4919eb22133a62810b91e1433 ); }; /* End PBXProject section */ -@@ -23858,6 +23898,23 @@ +@@ -24467,6 +24490,23 @@ shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Scripts/create-symlink-to-altroot.sh\"\n"; + shellScript = "[ -z \"${WK_DERIVED_SDK_HEADERS_DIR}\" -o -d \"${WK_DERIVED_SDK_HEADERS_DIR}\" ] && touch \"${SCRIPT_OUTPUT_FILE_0}\"\n"; }; + F31720B127FE216400EEE407 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; @@ -1883,17 +1819,7 @@ index f5f1d0ef71f7fcf175b016ddaefd99f18d96c1c3..5632dcb4919eb22133a62810b91e1433 /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ -@@ -25831,6 +25888,9 @@ - 5CDD865E1E43B8B500621E92 /* min_max_operations.c in Sources */, - 4189395B242A71F5007FDC41 /* min_video_bitrate_experiment.cc in Sources */, - 41B8D8FB28CB85CB00E5FA37 /* missing_mandatory_parameter_cause.cc in Sources */, -+ F3B7819A24C7CC5200FCB122 /* mkvmuxer.cc in Sources */, -+ F3B7819924C7CC5200FCB122 /* mkvmuxerutil.cc in Sources */, -+ F3B7819B24C7CC5200FCB122 /* mkvwriter.cc in Sources */, - 4131C387234B957D0028A615 /* moving_average.cc in Sources */, - 41FCBB1521B1F7AA00A5DF27 /* moving_average.cc in Sources */, - 5CD286101E6A64C90094FDC8 /* moving_max.cc in Sources */, -@@ -26708,6 +26768,11 @@ +@@ -27437,6 +27477,11 @@ target = DDF30D0527C5C003006A526F /* absl */; targetProxy = DD2E76E727C6B69A00F2A74C /* PBXContainerItemProxy */; }; @@ -1905,7 +1831,7 @@ index f5f1d0ef71f7fcf175b016ddaefd99f18d96c1c3..5632dcb4919eb22133a62810b91e1433 /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ -@@ -27283,6 +27348,27 @@ +@@ -28204,6 +28249,27 @@ }; name = Production; }; @@ -1933,7 +1859,7 @@ index f5f1d0ef71f7fcf175b016ddaefd99f18d96c1c3..5632dcb4919eb22133a62810b91e1433 FB39D0711200ED9200088E69 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 5D7C59C71208C68B001C873E /* DebugRelease.xcconfig */; -@@ -27585,6 +27671,16 @@ +@@ -28586,6 +28652,16 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Production; }; @@ -1950,116 +1876,206 @@ index f5f1d0ef71f7fcf175b016ddaefd99f18d96c1c3..5632dcb4919eb22133a62810b91e1433 FB39D0731200ED9200088E69 /* Build configuration list for PBXProject "libwebrtc" */ = { isa = XCConfigurationList; buildConfigurations = ( +diff --git a/Source/ThirdParty/skia/CMakeLists.txt b/Source/ThirdParty/skia/CMakeLists.txt +index 6bfc5cba986488f3d808ebd0583c476cd93da70e..f4c4222d17bce640355ba52e00152069d5b14432 100644 +--- a/Source/ThirdParty/skia/CMakeLists.txt ++++ b/Source/ThirdParty/skia/CMakeLists.txt +@@ -10,6 +10,8 @@ if (USE_SKIA_ENCODERS) + find_package(WebP REQUIRED COMPONENTS mux) + endif () + ++find_package(Threads REQUIRED) ++ + if (ANDROID) + find_package(EXPAT REQUIRED) + endif () +@@ -948,6 +950,7 @@ endif () + target_link_libraries(Skia PRIVATE + JPEG::JPEG + PNG::PNG ++ Threads::Threads + ) + + WEBKIT_ADD_TARGET_CXX_FLAGS(Skia +diff --git a/Source/ThirdParty/skia/src/opts/SkOpts_SetTarget.h b/Source/ThirdParty/skia/src/opts/SkOpts_SetTarget.h +index 525cfcb862ae96bf8573d00b67dc9e5e23c10d22..f2debc0444cb8f5b80a0e99a2214bceaab3960c1 100644 +--- a/Source/ThirdParty/skia/src/opts/SkOpts_SetTarget.h ++++ b/Source/ThirdParty/skia/src/opts/SkOpts_SetTarget.h +@@ -65,6 +65,7 @@ + // Each of the specific intrinsic headers also checks to ensure that immintrin.h has been + // included, so do that here, first. + #if defined(__clang__) && defined(_MSC_VER) ++ #define __RTMINTRIN_H // Workaround for https://github.com/llvm/llvm-project/issues/95133 + #include + #endif + diff --git a/Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml b/Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml -index 110e762586d9dc98b3a11a5cf5d1501334b2463f..870e1950740d745588cbfdc8abd3f3709867ab8f 100644 +index 3437d1ccf6e9a78bb9a42158e54ba99f4d9d25f9..b67f7d77bdf4090ec9c29abd221562cd7bf5a80f 100644 --- a/Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml +++ b/Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml -@@ -562,6 +562,7 @@ ApplePayEnabled: - default: false +@@ -588,6 +588,7 @@ ApplePayEnabled: + richJavaScript: true # FIXME: This is on by default in WebKit2 PLATFORM(COCOA). Perhaps we should consider turning it on for WebKitLegacy as well. +# Playwright: enable on all platforms to align with Safari. AsyncClipboardAPIEnabled: type: bool status: mature -@@ -572,7 +573,7 @@ AsyncClipboardAPIEnabled: +@@ -598,7 +599,7 @@ AsyncClipboardAPIEnabled: default: false WebKit: - "PLATFORM(COCOA) || PLATFORM(GTK)" : true + "PLATFORM(COCOA) || PLATFORM(GTK) || PLATFORM(WPE)" : true - default: false + default: true WebCore: default: false -@@ -1739,9 +1740,10 @@ CrossOriginEmbedderPolicyEnabled: +@@ -857,13 +858,10 @@ BlobFileAccessEnforcementEnabled: + sharedPreferenceForWebProcess: true + defaultValue: + WebKitLegacy: +- "PLATFORM(COCOA)": true + default: false + WebKit: +- "PLATFORM(COCOA)": true + default: false + WebCore: +- "PLATFORM(COCOA)": true + default: false + + BlockFontServiceInWebContentSandbox: +@@ -2143,6 +2141,7 @@ CrossOriginEmbedderPolicyEnabled: WebCore: default: false +# Playwright: disable setting. CrossOriginOpenerPolicyEnabled: type: bool -- status: stable -+ status: preview - category: security - humanReadableName: "Cross-Origin-Opener-Policy (COOP) header" - humanReadableDescription: "Support for Cross-Origin-Opener-Policy (COOP) header" -@@ -1749,7 +1751,7 @@ CrossOriginOpenerPolicyEnabled: + status: stable +@@ -2216,6 +2215,7 @@ DOMAudioSessionFullEnabled: + WebCore: + default: false + ++# Playwright: enable on all platforms to align with Safari. + DOMPasteAccessRequestsEnabled: + type: bool + status: internal +@@ -2227,7 +2227,7 @@ DOMPasteAccessRequestsEnabled: + default: false + WebKit: + "PLATFORM(IOS) || PLATFORM(MAC) || PLATFORM(GTK) || PLATFORM(WPE) || PLATFORM(VISION)": true +- default: false ++ default: true + WebCore: + default: false + +@@ -2293,10 +2293,10 @@ DataListElementEnabled: WebKitLegacy: default: false WebKit: -- default: true -+ default: false +- "(PLATFORM(COCOA) && !PLATFORM(WATCHOS)) || PLATFORM(GTK)": true ++ "(PLATFORM(COCOA) && !PLATFORM(WATCHOS)) || PLATFORM(GTK) || PLATFORM(WPE) || PLATFORM(WIN)": true + default: false WebCore: +- "(PLATFORM(COCOA) && !PLATFORM(WATCHOS)) || PLATFORM(GTK)": true ++ "(PLATFORM(COCOA) && !PLATFORM(WATCHOS)) || PLATFORM(GTK) || PLATFORM(WPE) || PLATFORM(WIN)": true default: false + sharedPreferenceForWebProcess: true -@@ -1793,7 +1795,7 @@ CustomPasteboardDataEnabled: +@@ -2309,7 +2309,7 @@ DataTransferItemsEnabled: + WebKitLegacy: + default: true + WebKit: +- "PLATFORM(COCOA) || PLATFORM(GTK) || PLATFORM(WPE)": true ++ "PLATFORM(COCOA) || PLATFORM(GTK) || PLATFORM(WPE) || PLATFORM(WIN)": true + default: false + WebCore: + default: false +@@ -2537,7 +2537,7 @@ DirectoryUploadEnabled: WebKitLegacy: default: false WebKit: -- "PLATFORM(COCOA) || PLATFORM(GTK) || PLATFORM(WIN)": true +- "PLATFORM(COCOA) || PLATFORM(GTK) || PLATFORM(WPE)": true + "PLATFORM(COCOA) || PLATFORM(GTK) || PLATFORM(WPE) || PLATFORM(WIN)": true default: false - - CustomStateSetEnabled: -@@ -1852,6 +1854,7 @@ DOMAudioSessionFullEnabled: WebCore: default: false - -+# Playwright: enable on all platforms to align with Safari. - DOMPasteAccessRequestsEnabled: - type: bool - status: internal -@@ -1863,7 +1866,7 @@ DOMPasteAccessRequestsEnabled: +@@ -3020,10 +3020,10 @@ FullScreenEnabled: + WebKitLegacy: default: false WebKit: - "PLATFORM(IOS) || PLATFORM(MAC) || PLATFORM(GTK) || PLATFORM(VISION)": true -- default: false -+ default: true +- "PLATFORM(GTK) || PLATFORM(WPE)": true ++ "PLATFORM(WIN) || PLATFORM(GTK) || PLATFORM(WPE)": true + default: false WebCore: +- "PLATFORM(GTK) || PLATFORM(WPE)": true ++ "PLATFORM(WIN) || PLATFORM(GTK) || PLATFORM(WPE)": true default: false + sharedPreferenceForWebProcess: true -@@ -3232,6 +3235,7 @@ InspectorAttachmentSide: +@@ -3614,7 +3614,7 @@ InputTypeColorEnabled: + WebKitLegacy: + default: false WebKit: - default: 0 +- "PLATFORM(COCOA) && !PLATFORM(WATCHOS) || PLATFORM(GTK)": true ++ "PLATFORM(COCOA) && !PLATFORM(WATCHOS) || PLATFORM(GTK) || PLATFORM(WPE)": true + default: false + WebCore: + default: false +@@ -3647,7 +3647,7 @@ InputTypeDateEnabled: + "PLATFORM(IOS_FAMILY)": true + default: false + WebKit: +- "PLATFORM(COCOA) || PLATFORM(GTK)": true ++ "PLATFORM(COCOA) || PLATFORM(GTK) || PLATFORM(WPE)": true + default: false + WebCore: + default: false +@@ -3663,7 +3663,7 @@ InputTypeDateTimeLocalEnabled: + "PLATFORM(IOS_FAMILY)": true + default: false + WebKit: +- "PLATFORM(COCOA) || PLATFORM(GTK)": true ++ "PLATFORM(COCOA) || PLATFORM(GTK) || PLATFORM(WPE)": true + default: false + WebCore: + default: false +@@ -3695,7 +3695,7 @@ InputTypeTimeEnabled: + "PLATFORM(IOS_FAMILY)": true + default: false + WebKit: +- "PLATFORM(COCOA) || PLATFORM(GTK)": true ++ "PLATFORM(COCOA) || PLATFORM(GTK) || PLATFORM(WPE)": true + default: false + WebCore: + default: false +@@ -3756,6 +3756,7 @@ InspectorMaximumResourcesContentSize: + "PLATFORM(WPE)": 50 + default: 200 +# Playwright: disable setting. InspectorStartsAttached: type: bool status: embedder -@@ -3239,7 +3243,7 @@ InspectorStartsAttached: +@@ -3763,7 +3764,7 @@ InspectorStartsAttached: exposed: [ WebKit ] defaultValue: WebKit: - default: true + default: false - InspectorWindowFrame: - type: String -@@ -3593,9 +3597,10 @@ LayoutViewportHeightExpansionFactor: - WebCore: - default: 0 - -+# Playwright: disable setting. - LazyIframeLoadingEnabled: + InspectorSupportsShowingCertificate: type: bool -- status: stable -+ status: preview - category: html - humanReadableName: "Lazy iframe loading" - humanReadableDescription: "Enable lazy iframe loading support" -@@ -3603,9 +3608,9 @@ LazyIframeLoadingEnabled: +@@ -5683,7 +5684,7 @@ PermissionsAPIEnabled: WebKitLegacy: - default: true + default: false WebKit: -- default: true -+ default: false +- "PLATFORM(COCOA) || PLATFORM(GTK) || PLATFORM(WPE)" : true ++ "PLATFORM(COCOA) || PLATFORM(GTK) || PLATFORM(WPE) || PLATFORM(WIN)" : true + default: false WebCore: -- default: true -+ default: false - - LazyImageLoadingEnabled: - type: bool -@@ -5028,6 +5033,19 @@ PitchCorrectionAlgorithm: + default: false +@@ -5762,6 +5763,19 @@ PitchCorrectionAlgorithm: WebCore: default: MediaPlayerEnums::PitchCorrectionAlgorithm::BestAllAround @@ -2078,16 +2094,25 @@ index 110e762586d9dc98b3a11a5cf5d1501334b2463f..870e1950740d745588cbfdc8abd3f370 + PointerLockOptionsEnabled: type: bool - status: testable -@@ -6778,6 +6796,7 @@ UseCGDisplayListsForDOMRendering: + status: stable +@@ -6344,7 +6358,7 @@ ScreenOrientationAPIEnabled: + WebKitLegacy: + default: false WebKit: +- default: WebKit::defaultShouldEnableScreenOrientationAPI() ++ default: true + WebCore: + default: false + sharedPreferenceForWebProcess: true +@@ -7806,6 +7820,7 @@ UseCGDisplayListsForDOMRendering: default: true + sharedPreferenceForWebProcess: true +# Playwright: force-disable on Windows. UseGPUProcessForCanvasRenderingEnabled: type: bool status: stable -@@ -6790,7 +6809,7 @@ UseGPUProcessForCanvasRenderingEnabled: +@@ -7818,7 +7833,7 @@ UseGPUProcessForCanvasRenderingEnabled: defaultValue: WebKit: "ENABLE(GPU_PROCESS_BY_DEFAULT)": true @@ -2096,24 +2121,15 @@ index 110e762586d9dc98b3a11a5cf5d1501334b2463f..870e1950740d745588cbfdc8abd3f370 default: false UseGPUProcessForDOMRenderingEnabled: -@@ -6800,7 +6819,7 @@ UseGPUProcessForDOMRenderingEnabled: - humanReadableName: "GPU Process: DOM Rendering" - humanReadableDescription: "Enable DOM rendering in GPU Process" - webcoreBinding: none -- condition: ENABLE(GPU_PROCESS) -+ condition: ENABLE(GPU_PROCESS) && !PLATFORM(WIN) - exposed: [ WebKit ] - defaultValue: - WebKit: -@@ -6832,6 +6851,7 @@ UseGPUProcessForMediaEnabled: - "ENABLE(GPU_PROCESS_BY_DEFAULT)": true - default: false +@@ -7863,6 +7878,7 @@ UseGPUProcessForMediaEnabled: + sharedPreferenceForWebProcess: true + mediaPlaybackRelated: true +# Playwright: force-disable on Windows. UseGPUProcessForWebGLEnabled: type: bool status: internal -@@ -6843,7 +6863,7 @@ UseGPUProcessForWebGLEnabled: +@@ -7874,7 +7890,7 @@ UseGPUProcessForWebGLEnabled: default: false WebKit: "ENABLE(GPU_PROCESS_BY_DEFAULT) && ENABLE(GPU_PROCESS_WEBGL_BY_DEFAULT)": true @@ -2123,10 +2139,10 @@ index 110e762586d9dc98b3a11a5cf5d1501334b2463f..870e1950740d745588cbfdc8abd3f370 WebCore: "ENABLE(GPU_PROCESS_BY_DEFAULT) && ENABLE(GPU_PROCESS_WEBGL_BY_DEFAULT)": true diff --git a/Source/WTF/wtf/PlatformEnable.h b/Source/WTF/wtf/PlatformEnable.h -index 6f547f01a22d1aba86b813fc77679124a643ef72..34fbae99c2e64f2a34a83d878da76f9c75d0bea5 100644 +index a36395e83c53617c2f894695846f8798fc277624..f0b8dd0fd12b4cde24975c20015cee30292abf9d 100644 --- a/Source/WTF/wtf/PlatformEnable.h +++ b/Source/WTF/wtf/PlatformEnable.h -@@ -401,7 +401,7 @@ +@@ -385,7 +385,7 @@ // ORIENTATION_EVENTS should never get enabled on Desktop, only Mobile. #if !defined(ENABLE_ORIENTATION_EVENTS) @@ -2135,7 +2151,7 @@ index 6f547f01a22d1aba86b813fc77679124a643ef72..34fbae99c2e64f2a34a83d878da76f9c #endif #if !defined(ENABLE_OVERFLOW_SCROLLING_TOUCH) -@@ -506,7 +506,7 @@ +@@ -502,7 +502,7 @@ #endif #if !defined(ENABLE_TOUCH_EVENTS) @@ -2145,10 +2161,10 @@ index 6f547f01a22d1aba86b813fc77679124a643ef72..34fbae99c2e64f2a34a83d878da76f9c #if !defined(ENABLE_TOUCH_ACTION_REGIONS) diff --git a/Source/WTF/wtf/PlatformEnableCocoa.h b/Source/WTF/wtf/PlatformEnableCocoa.h -index d797c28eccac0578c7c504fa0c7b34d517746b17..32e815241e2513c979d1af01ef88b494851a2409 100644 +index 8304147ff102789180b2682eb64d599791528c93..af8cb85981bda7b91edfa21b6cc321849d93b909 100644 --- a/Source/WTF/wtf/PlatformEnableCocoa.h +++ b/Source/WTF/wtf/PlatformEnableCocoa.h -@@ -775,7 +775,7 @@ +@@ -808,7 +808,7 @@ #endif #if !defined(ENABLE_SEC_ITEM_SHIM) @@ -2158,19 +2174,10 @@ index d797c28eccac0578c7c504fa0c7b34d517746b17..32e815241e2513c979d1af01ef88b494 #if !defined(ENABLE_SERVER_PRECONNECT) diff --git a/Source/WTF/wtf/PlatformHave.h b/Source/WTF/wtf/PlatformHave.h -index cb5e806040f4e6e2bf94a4c27b05892af7e4301d..81fd915ce2643522b225139661da9f7dedf32469 100644 +index 9e91a26aac61faea9634328f9a46421a4b4b7c38..b70776d97be4025435dc3c0364105cb17c429f6a 100644 --- a/Source/WTF/wtf/PlatformHave.h +++ b/Source/WTF/wtf/PlatformHave.h -@@ -419,7 +419,7 @@ - #define HAVE_FOUNDATION_WITH_SAME_SITE_COOKIE_SUPPORT 1 - #endif - --#if PLATFORM(MAC) || PLATFORM(IOS) || PLATFORM(MACCATALYST) || PLATFORM(VISION) || PLATFORM(GTK) || PLATFORM(WPE) -+#if PLATFORM(MAC) || PLATFORM(IOS) || PLATFORM(MACCATALYST) || PLATFORM(VISION) || PLATFORM(GTK) || PLATFORM(WPE) || PLATFORM(WIN) - #define HAVE_OS_DARK_MODE_SUPPORT 1 - #endif - -@@ -1274,7 +1274,8 @@ +@@ -1189,7 +1189,8 @@ #endif #if PLATFORM(MAC) @@ -2181,13 +2188,14 @@ index cb5e806040f4e6e2bf94a4c27b05892af7e4301d..81fd915ce2643522b225139661da9f7d #if !defined(HAVE_LOCKDOWN_MODE_PDF_ADDITIONS) && \ diff --git a/Source/WTF/wtf/unicode/UTF8Conversion.h b/Source/WTF/wtf/unicode/UTF8Conversion.h -index f45ef73d81bd02c0b542e98ff01f59d88f57b8a0..0fb91174b8e6641d20b4ee084ec48910cdf7b836 100644 +index 007b8fe3292f326504013be8198ae020f7aacf35..1c722c473732ffe05fdb61010fa4417e3e399d1f 100644 --- a/Source/WTF/wtf/unicode/UTF8Conversion.h +++ b/Source/WTF/wtf/unicode/UTF8Conversion.h -@@ -28,6 +28,10 @@ - #include +@@ -27,6 +27,11 @@ + #include ++// Can be probably removed when we drop Debian 11. +#ifdef Success +#undef Success +#endif @@ -2196,13 +2204,13 @@ index f45ef73d81bd02c0b542e98ff01f59d88f57b8a0..0fb91174b8e6641d20b4ee084ec48910 namespace Unicode { diff --git a/Source/WebCore/DerivedSources.make b/Source/WebCore/DerivedSources.make -index 9dd05dd4e7ad824cae7c47d61117a2bbde10c3e5..015b2ce422f594860a77b0382e9a3857f2db4ff6 100644 +index 0f0341624503ae9744b71d3675dc96545371456a..cc73c79374f07fbf1f83e7075e53a3d99da0705c 100644 --- a/Source/WebCore/DerivedSources.make +++ b/Source/WebCore/DerivedSources.make -@@ -1149,6 +1149,10 @@ JS_BINDING_IDLS := \ - $(WebCore)/dom/Slotable.idl \ - $(WebCore)/dom/StaticRange.idl \ - $(WebCore)/dom/StringCallback.idl \ +@@ -1229,6 +1229,10 @@ JS_BINDING_IDLS := \ + $(WebCore)/dom/SubscriberCallback.idl \ + $(WebCore)/dom/SubscriptionObserver.idl \ + $(WebCore)/dom/SubscriptionObserverCallback.idl \ + $(WebCore)/dom/Document+Touch.idl \ + $(WebCore)/dom/Touch.idl \ + $(WebCore)/dom/TouchEvent.idl \ @@ -2210,7 +2218,7 @@ index 9dd05dd4e7ad824cae7c47d61117a2bbde10c3e5..015b2ce422f594860a77b0382e9a3857 $(WebCore)/dom/Text.idl \ $(WebCore)/dom/TextDecoder.idl \ $(WebCore)/dom/TextDecoderStream.idl \ -@@ -1735,9 +1739,6 @@ JS_BINDING_IDLS := \ +@@ -1829,9 +1833,6 @@ JS_BINDING_IDLS := \ ADDITIONAL_BINDING_IDLS = \ DocumentTouch.idl \ GestureEvent.idl \ @@ -2221,22 +2229,22 @@ index 9dd05dd4e7ad824cae7c47d61117a2bbde10c3e5..015b2ce422f594860a77b0382e9a3857 vpath %.in $(WEBKITADDITIONS_HEADER_SEARCH_PATHS) diff --git a/Source/WebCore/Modules/geolocation/Geolocation.cpp b/Source/WebCore/Modules/geolocation/Geolocation.cpp -index 32fde85425cbb82eb30bcc7aef58155026d2b7b7..a35495d97fcf0346e4696e26df80cf4a8fb890d6 100644 +index 7d0ca9a308e7aeaf132dccfddeae129fc8c9e093..0eeac0eec23fbc8c3df6c56d63603acc46e8590c 100644 --- a/Source/WebCore/Modules/geolocation/Geolocation.cpp +++ b/Source/WebCore/Modules/geolocation/Geolocation.cpp -@@ -357,8 +357,9 @@ bool Geolocation::shouldBlockGeolocationRequests() - bool isSecure = SecurityOrigin::isSecure(document()->url()) || document()->isSecureContext(); - bool hasMixedContent = !document()->foundMixedContent().isEmpty(); +@@ -362,8 +362,9 @@ bool Geolocation::shouldBlockGeolocationRequests() + bool isSecure = SecurityOrigin::isSecure(document->url()) || document->isSecureContext(); + bool hasMixedContent = !document->foundMixedContent().isEmpty(); bool isLocalOrigin = securityOrigin()->isLocal(); + bool isPotentiallyTrustworthy = securityOrigin()->isPotentiallyTrustworthy(); - if (document()->canAccessResource(ScriptExecutionContext::ResourceType::Geolocation) != ScriptExecutionContext::HasResourceAccess::No) { + if (document->canAccessResource(ScriptExecutionContext::ResourceType::Geolocation) != ScriptExecutionContext::HasResourceAccess::No) { - if (isLocalOrigin || (isSecure && !hasMixedContent)) -+ if (isLocalOrigin || isPotentiallyTrustworthy || (isSecure && !hasMixedContent)) ++ if (isLocalOrigin || (isSecure && !hasMixedContent) || isPotentiallyTrustworthy) return false; } diff --git a/Source/WebCore/Modules/speech/cocoa/WebSpeechRecognizerTask.mm b/Source/WebCore/Modules/speech/cocoa/WebSpeechRecognizerTask.mm -index 506ebb25fa290f27a75674a6fe5506fc311910d6..07d34c567b42aca08b188243c3f036f64a8da0c4 100644 +index b2b0391c120d527a9ab4bc6daf8bff7ea5d03cf7..d490a95f89f21536fce4f403b86399160abefc23 100644 --- a/Source/WebCore/Modules/speech/cocoa/WebSpeechRecognizerTask.mm +++ b/Source/WebCore/Modules/speech/cocoa/WebSpeechRecognizerTask.mm @@ -195,6 +195,7 @@ - (void)sendEndIfNeeded @@ -2271,26 +2279,14 @@ index 506ebb25fa290f27a75674a6fe5506fc311910d6..07d34c567b42aca08b188243c3f036f6 ASSERT(isMainThread()); [self sendSpeechEndIfNeeded]; -diff --git a/Source/WebCore/PlatformWPE.cmake b/Source/WebCore/PlatformWPE.cmake -index c6a03b56d8358316c9ce422c1a11438bd216f80f..69fbd319b7cd084ca125a8db1b5d92ef6a4dc10f 100644 ---- a/Source/WebCore/PlatformWPE.cmake -+++ b/Source/WebCore/PlatformWPE.cmake -@@ -60,6 +60,7 @@ list(APPEND WebCore_PRIVATE_FRAMEWORK_HEADERS - platform/graphics/libwpe/PlatformDisplayLibWPE.h - - platform/graphics/wayland/PlatformDisplayWayland.h -+ platform/wpe/SelectionData.h - ) - - set(CSS_VALUE_PLATFORM_DEFINES "HAVE_OS_DARK_MODE_SUPPORT=1") diff --git a/Source/WebCore/SourcesCocoa.txt b/Source/WebCore/SourcesCocoa.txt -index eece14fded1942140af81dede0861fb5f79fb532..cd3c5ebaccd268695d9e7bc0b96f30522c42e43e 100644 +index 06a9accfc8e6c46493733663b5d76b07fc80db22..4946d012d166c84b25d4d954266c4dc528f7d8ad 100644 --- a/Source/WebCore/SourcesCocoa.txt +++ b/Source/WebCore/SourcesCocoa.txt -@@ -713,3 +713,9 @@ testing/cocoa/WebViewVisualIdentificationOverlay.mm +@@ -734,3 +734,9 @@ testing/cocoa/WebViewVisualIdentificationOverlay.mm platform/graphics/angle/GraphicsContextGLANGLE.cpp @no-unify platform/graphics/cocoa/GraphicsContextGLCocoa.mm @no-unify - platform/graphics/cv/GraphicsContextGLCVCocoa.cpp @no-unify + platform/graphics/cv/GraphicsContextGLCVCocoa.mm @no-unify + +// Playwright begin +JSTouch.cpp @@ -2298,10 +2294,10 @@ index eece14fded1942140af81dede0861fb5f79fb532..cd3c5ebaccd268695d9e7bc0b96f3052 +JSTouchList.cpp +// Playwright end diff --git a/Source/WebCore/SourcesGTK.txt b/Source/WebCore/SourcesGTK.txt -index af2081f34b9d8d97864a6e9507805abc9e8eb6d7..06ed467b2c6e529baba22a04e03a4858f8552e19 100644 +index 2b22eb2071e32741cb1383601466e537dca917f2..4da3cb8c1f1247bbc9886b060cd2d53047ca6572 100644 --- a/Source/WebCore/SourcesGTK.txt +++ b/Source/WebCore/SourcesGTK.txt -@@ -110,3 +110,10 @@ platform/unix/LoggingUnix.cpp +@@ -112,3 +112,10 @@ platform/unix/LoggingUnix.cpp platform/unix/SharedMemoryUnix.cpp platform/xdg/MIMETypeRegistryXdg.cpp @@ -2313,10 +2309,10 @@ index af2081f34b9d8d97864a6e9507805abc9e8eb6d7..06ed467b2c6e529baba22a04e03a4858 +JSSpeechSynthesisEventInit.cpp +// Playwright: end. diff --git a/Source/WebCore/SourcesWPE.txt b/Source/WebCore/SourcesWPE.txt -index 92f1879df295fc63a9194dc54d3f7499c5fe3041..67c40d056aee6a8149ed1ff16ce4c835e19f7f6c 100644 +index ce3cf51287e5891289bd23580084b8137ee4276b..c46e4e0c6faaca888e3ea62afd0e16d6f4cfda35 100644 --- a/Source/WebCore/SourcesWPE.txt +++ b/Source/WebCore/SourcesWPE.txt -@@ -46,6 +46,8 @@ editing/libwpe/EditorLibWPE.cpp +@@ -48,6 +48,8 @@ editing/glib/WebContentReaderGLib.cpp loader/soup/ResourceLoaderSoup.cpp @@ -2325,18 +2321,14 @@ index 92f1879df295fc63a9194dc54d3f7499c5fe3041..67c40d056aee6a8149ed1ff16ce4c835 page/linux/ResourceUsageOverlayLinux.cpp page/linux/ResourceUsageThreadLinux.cpp -@@ -87,6 +89,17 @@ platform/text/LocaleICU.cpp - platform/unix/LoggingUnix.cpp - platform/unix/SharedMemoryUnix.cpp - -+platform/wpe/DragDataWPE.cpp -+platform/wpe/DragImageWPE.cpp +@@ -97,3 +99,13 @@ platform/wpe/PasteboardWPE.cpp platform/wpe/PlatformScreenWPE.cpp platform/xdg/MIMETypeRegistryXdg.cpp + +// Playwright: begin. -+platform/wpe/SelectionData.cpp ++platform/wpe/DragDataWPE.cpp ++platform/wpe/DragImageWPE.cpp + +JSSpeechSynthesisErrorCode.cpp +JSSpeechSynthesisErrorEvent.cpp @@ -2344,12 +2336,12 @@ index 92f1879df295fc63a9194dc54d3f7499c5fe3041..67c40d056aee6a8149ed1ff16ce4c835 +JSSpeechSynthesisEventInit.cpp +// Playwright: end. diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj -index 8807578bc8e503fce83e9acc30029cef75b7f071..7fffb6499c200dca0c3ee777feaf284999d5d763 100644 +index e522afd2d6f038d2a2c9804313d1d8e75c63e914..03f521d898bd7d80a94e7e3c0fc4c904d279a0ba 100644 --- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj +++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj -@@ -6216,6 +6216,13 @@ - EDE3A5000C7A430600956A37 /* ColorMac.h in Headers */ = {isa = PBXBuildFile; fileRef = EDE3A4FF0C7A430600956A37 /* ColorMac.h */; settings = {ATTRIBUTES = (Private, ); }; }; - EDEC98030AED7E170059137F /* WebCorePrefix.h in Headers */ = {isa = PBXBuildFile; fileRef = EDEC98020AED7E170059137F /* WebCorePrefix.h */; }; +@@ -6452,6 +6452,13 @@ + EE0C7E042CE845CB0043DAF8 /* CSSPositionTryRule.h in Headers */ = {isa = PBXBuildFile; fileRef = EE0C7E002CE845CB0043DAF8 /* CSSPositionTryRule.h */; }; + EE0D3C492D2F4B4C00072978 /* StageModeOperations.h in Headers */ = {isa = PBXBuildFile; fileRef = EE0D3C482D2F4AE600072978 /* StageModeOperations.h */; settings = {ATTRIBUTES = (Private, ); }; }; EFCC6C8F20FE914400A2321B /* CanvasActivityRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = EFCC6C8D20FE914000A2321B /* CanvasActivityRecord.h */; settings = {ATTRIBUTES = (Private, ); }; }; + F050E16823AC9C080011CE47 /* PlatformTouchEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = F050E16623AC9C070011CE47 /* PlatformTouchEvent.h */; settings = {ATTRIBUTES = (Private, ); }; }; + F050E16A23AD660C0011CE47 /* Touch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F050E16923AD660C0011CE47 /* Touch.cpp */; }; @@ -2361,8 +2353,8 @@ index 8807578bc8e503fce83e9acc30029cef75b7f071..7fffb6499c200dca0c3ee777feaf2849 F12171F616A8CF0B000053CA /* WebVTTElement.h in Headers */ = {isa = PBXBuildFile; fileRef = F12171F416A8BC63000053CA /* WebVTTElement.h */; }; F32BDCD92363AACA0073B6AE /* UserGestureEmulationScope.h in Headers */ = {isa = PBXBuildFile; fileRef = F32BDCD72363AACA0073B6AE /* UserGestureEmulationScope.h */; }; F344C7141125B82C00F26EEE /* InspectorFrontendClient.h in Headers */ = {isa = PBXBuildFile; fileRef = F344C7121125B82C00F26EEE /* InspectorFrontendClient.h */; settings = {ATTRIBUTES = (Private, ); }; }; -@@ -20126,6 +20133,14 @@ - EDEC98020AED7E170059137F /* WebCorePrefix.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = WebCorePrefix.h; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; +@@ -21141,6 +21148,14 @@ + EE7A169F2C607BFA0057B563 /* StartViewTransitionOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = StartViewTransitionOptions.h; sourceTree = ""; }; EFB7287B2124C73D005C2558 /* CanvasActivityRecord.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CanvasActivityRecord.cpp; sourceTree = ""; }; EFCC6C8D20FE914000A2321B /* CanvasActivityRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CanvasActivityRecord.h; sourceTree = ""; }; + F050E16623AC9C070011CE47 /* PlatformTouchEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformTouchEvent.h; sourceTree = ""; }; @@ -2376,7 +2368,7 @@ index 8807578bc8e503fce83e9acc30029cef75b7f071..7fffb6499c200dca0c3ee777feaf2849 F12171F316A8BC63000053CA /* WebVTTElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebVTTElement.cpp; sourceTree = ""; }; F12171F416A8BC63000053CA /* WebVTTElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebVTTElement.h; sourceTree = ""; }; F32BDCD52363AAC90073B6AE /* UserGestureEmulationScope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UserGestureEmulationScope.cpp; sourceTree = ""; }; -@@ -27745,6 +27760,11 @@ +@@ -28928,6 +28943,11 @@ BC4A5324256055590028C592 /* TextDirectionSubmenuInclusionBehavior.h */, 2D4F96F11A1ECC240098BF88 /* TextIndicator.cpp */, 2D4F96F21A1ECC240098BF88 /* TextIndicator.h */, @@ -2388,16 +2380,16 @@ index 8807578bc8e503fce83e9acc30029cef75b7f071..7fffb6499c200dca0c3ee777feaf2849 F48570A42644C76D00C05F71 /* TranslationContextMenuInfo.h */, F4E1965F21F26E4E00285078 /* UndoItem.cpp */, 2ECDBAD521D8906300F00ECD /* UndoItem.h */, -@@ -34075,6 +34095,8 @@ +@@ -35916,6 +35936,8 @@ 29E4D8DF16B0940F00C84704 /* PlatformSpeechSynthesizer.h */, 1AD8F81A11CAB9E900E93E54 /* PlatformStrategies.cpp */, 1AD8F81911CAB9E900E93E54 /* PlatformStrategies.h */, + F050E16623AC9C070011CE47 /* PlatformTouchEvent.h */, + F050E17623AD70C40011CE47 /* PlatformTouchPoint.h */, + FE3DC9932D0C063C0021B6FC /* PlatformTZoneImpls.cpp */, 0FD7C21D23CE41E30096D102 /* PlatformWheelEvent.cpp */, 935C476A09AC4D4F00A6AAB4 /* PlatformWheelEvent.h */, - F491A66A2A9FEFA300F96146 /* PlatformWheelEvent.serialization.in */, -@@ -36745,6 +36767,7 @@ +@@ -38777,6 +38799,7 @@ AD6E71AB1668899D00320C13 /* DocumentSharedObjectPool.h */, 6BDB5DC1227BD3B800919770 /* DocumentStorageAccess.cpp */, 6BDB5DC0227BD3B800919770 /* DocumentStorageAccess.h */, @@ -2405,7 +2397,7 @@ index 8807578bc8e503fce83e9acc30029cef75b7f071..7fffb6499c200dca0c3ee777feaf2849 7CE7FA5B1EF882300060C9D6 /* DocumentTouch.cpp */, 7CE7FA591EF882300060C9D6 /* DocumentTouch.h */, A8185F3209765765005826D9 /* DocumentType.cpp */, -@@ -41482,6 +41505,8 @@ +@@ -43729,6 +43752,8 @@ F4E90A3C2B52038E002DA469 /* PlatformTextAlternatives.h in Headers */, 0F7D07331884C56C00B4AF86 /* PlatformTextTrack.h in Headers */, 074E82BB18A69F0E007EF54C /* PlatformTimeRanges.h in Headers */, @@ -2414,7 +2406,7 @@ index 8807578bc8e503fce83e9acc30029cef75b7f071..7fffb6499c200dca0c3ee777feaf2849 CDD08ABD277E542600EA3755 /* PlatformTrackConfiguration.h in Headers */, CD1F9B022700323D00617EB6 /* PlatformVideoColorPrimaries.h in Headers */, CD1F9B01270020B700617EB6 /* PlatformVideoColorSpace.h in Headers */, -@@ -42762,6 +42787,7 @@ +@@ -45097,6 +45122,7 @@ 0F54DD081881D5F5003EEDBB /* Touch.h in Headers */, 71B7EE0D21B5C6870031C1EF /* TouchAction.h in Headers */, 0F54DD091881D5F5003EEDBB /* TouchEvent.h in Headers */, @@ -2422,7 +2414,7 @@ index 8807578bc8e503fce83e9acc30029cef75b7f071..7fffb6499c200dca0c3ee777feaf2849 0F54DD0A1881D5F5003EEDBB /* TouchList.h in Headers */, 070334D71459FFD5008D8D45 /* TrackBase.h in Headers */, BE88E0C21715CE2600658D98 /* TrackListBase.h in Headers */, -@@ -43910,6 +43936,8 @@ +@@ -46300,6 +46326,8 @@ 2D22830323A8470700364B7E /* CursorMac.mm in Sources */, 5CBD59592280E926002B22AA /* CustomHeaderFields.cpp in Sources */, 07E4BDBF2A3A5FAB000D5509 /* DictationCaretAnimator.cpp in Sources */, @@ -2431,7 +2423,7 @@ index 8807578bc8e503fce83e9acc30029cef75b7f071..7fffb6499c200dca0c3ee777feaf2849 7CE6CBFD187F394900D46BF5 /* FormatConverter.cpp in Sources */, 4667EA3E2968D9DA00BAB1E2 /* GameControllerHapticEffect.mm in Sources */, 46FE73D32968E52000B8064C /* GameControllerHapticEngines.mm in Sources */, -@@ -43997,6 +44025,9 @@ +@@ -46390,6 +46418,9 @@ CE88EE262414467B007F29C2 /* TextAlternativeWithRange.mm in Sources */, BE39137129B267F500FA5D4F /* TextTransformCocoa.cpp in Sources */, 51DF6D800B92A18E00C2DC85 /* ThreadCheck.mm in Sources */, @@ -2442,18 +2434,18 @@ index 8807578bc8e503fce83e9acc30029cef75b7f071..7fffb6499c200dca0c3ee777feaf2849 538EC8021F96AF81004D22A8 /* UnifiedSource1.cpp in Sources */, 538EC8051F96AF81004D22A8 /* UnifiedSource2-mm.mm in Sources */, diff --git a/Source/WebCore/accessibility/AccessibilityObject.cpp b/Source/WebCore/accessibility/AccessibilityObject.cpp -index 9253fbb9de00b2768dd67c6efa20a2242e2e6621..c758a4e9b6f779458a611b6458ba89de1c17e4c8 100644 +index 3f19caf891dfa1cc70aa630f4e82c405825ab40c..62b2978c8d5e8af5e337d8b27c1d2ad938b773fe 100644 --- a/Source/WebCore/accessibility/AccessibilityObject.cpp +++ b/Source/WebCore/accessibility/AccessibilityObject.cpp -@@ -66,6 +66,7 @@ - #include "HTMLSlotElement.h" +@@ -72,6 +72,7 @@ + #include "HTMLTableSectionElement.h" #include "HTMLTextAreaElement.h" #include "HitTestResult.h" +#include "InspectorInstrumentation.h" #include "LocalFrame.h" #include "LocalizedStrings.h" #include "MathMLNames.h" -@@ -4075,9 +4076,14 @@ AccessibilityObjectInclusion AccessibilityObject::defaultObjectInclusion() const +@@ -3931,7 +3932,12 @@ AccessibilityObjectInclusion AccessibilityObject::defaultObjectInclusion() const if (roleValue() == AccessibilityRole::ApplicationDialog) return AccessibilityObjectInclusion::IncludeObject; @@ -2465,16 +2457,13 @@ index 9253fbb9de00b2768dd67c6efa20a2242e2e6621..c758a4e9b6f779458a611b6458ba89de + } + return platformBehavior; } -- -+ - bool AccessibilityObject::accessibilityIsIgnored() const - { - AXComputedObjectAttributeCache* attributeCache = nullptr; + + bool AccessibilityObject::isWithinHiddenWebArea() const diff --git a/Source/WebCore/bindings/js/WebCoreBuiltinNames.h b/Source/WebCore/bindings/js/WebCoreBuiltinNames.h -index f20ac9d4d61a6f396e9ed796c8e6c5b8a7ea0577..3151b5e54ea17c0d979d22a0cc43c5ce0688c183 100644 +index 158dc6af1464896ac4c4727c52581729ac132352..b8bd22a7d80d08d6dd56ea1bc10addbe3f839b6d 100644 --- a/Source/WebCore/bindings/js/WebCoreBuiltinNames.h +++ b/Source/WebCore/bindings/js/WebCoreBuiltinNames.h -@@ -183,6 +183,8 @@ namespace WebCore { +@@ -190,6 +190,8 @@ namespace WebCore { macro(DelayNode) \ macro(DeprecationReportBody) \ macro(DigitalCredential) \ @@ -2484,13 +2473,13 @@ index f20ac9d4d61a6f396e9ed796c8e6c5b8a7ea0577..3151b5e54ea17c0d979d22a0cc43c5ce macro(DynamicsCompressorNode) \ macro(ElementInternals) \ diff --git a/Source/WebCore/css/query/MediaQueryFeatures.cpp b/Source/WebCore/css/query/MediaQueryFeatures.cpp -index 9892fda4291cae0e0d338fac8b0f98cd0126807d..7ecfd659809ab30e82a9c00ec7710292a1bd5611 100644 +index aec43490053f95341ef979385b5e6c1daf03a090..4e44b7e341c8247f916f8597092248d8ec884518 100644 --- a/Source/WebCore/css/query/MediaQueryFeatures.cpp +++ b/Source/WebCore/css/query/MediaQueryFeatures.cpp -@@ -368,7 +368,11 @@ const FeatureSchema& forcedColors() - static MainThreadNeverDestroyed schema { +@@ -498,7 +498,11 @@ static const IdentifierSchema& forcedColorsFeatureSchema() "forced-colors"_s, FixedVector { CSSValueNone, CSSValueActive }, + OptionSet(), - [](auto&) { + [](auto& context) { + auto* page = context.document->frame()->page(); @@ -2500,7 +2489,7 @@ index 9892fda4291cae0e0d338fac8b0f98cd0126807d..7ecfd659809ab30e82a9c00ec7710292 return MatchingIdentifiers { CSSValueNone }; } }; -@@ -547,6 +551,9 @@ const FeatureSchema& prefersReducedMotion() +@@ -686,6 +690,9 @@ static const IdentifierSchema& prefersReducedMotionFeatureSchema() [](auto& context) { bool userPrefersReducedMotion = [&] { Ref frame = *context.document->frame(); @@ -2511,10 +2500,10 @@ index 9892fda4291cae0e0d338fac8b0f98cd0126807d..7ecfd659809ab30e82a9c00ec7710292 case ForcedAccessibilityValue::On: return true; diff --git a/Source/WebCore/dom/DataTransfer.cpp b/Source/WebCore/dom/DataTransfer.cpp -index b56c600b6159973dc8a33db1deba0cfbb77abf48..a347a85381888e2f6423393552d619938ad34f21 100644 +index c6f2dca0d4aede2bea015d1cca45dff434425938..e6f41af39befe69f47d0e0953f7d689c338ca184 100644 --- a/Source/WebCore/dom/DataTransfer.cpp +++ b/Source/WebCore/dom/DataTransfer.cpp -@@ -510,6 +510,14 @@ Ref DataTransfer::createForDrag(const Document& document) +@@ -523,6 +523,14 @@ Ref DataTransfer::createForDrag(const Document& document) return adoptRef(*new DataTransfer(StoreMode::ReadWrite, Pasteboard::createForDragAndDrop(PagePasteboardContext::create(document.pageID())), Type::DragAndDropData)); } @@ -2530,10 +2519,10 @@ index b56c600b6159973dc8a33db1deba0cfbb77abf48..a347a85381888e2f6423393552d61993 { auto dataTransfer = adoptRef(*new DataTransfer(StoreMode::ReadWrite, makeUnique(), Type::DragAndDropData)); diff --git a/Source/WebCore/dom/DataTransfer.h b/Source/WebCore/dom/DataTransfer.h -index 6ca2550bf509381165e5da22cc894ccf6378f45c..535bd1b05e8d90b291235cfc3cb425084455ff26 100644 +index 34ef2f454a732d39acae04987584cab5638b8c60..5e7b788612718dffe3423c89d96141b5b53621fb 100644 --- a/Source/WebCore/dom/DataTransfer.h +++ b/Source/WebCore/dom/DataTransfer.h -@@ -91,6 +91,9 @@ public: +@@ -92,6 +92,9 @@ public: #if ENABLE(DRAG_SUPPORT) static Ref createForDrag(const Document&); @@ -2544,7 +2533,7 @@ index 6ca2550bf509381165e5da22cc894ccf6378f45c..535bd1b05e8d90b291235cfc3cb42508 static Ref createForDrop(const Document&, std::unique_ptr&&, OptionSet, bool draggingFiles); static Ref createForUpdatingDropTarget(const Document&, std::unique_ptr&&, OptionSet, bool draggingFiles); diff --git a/Source/WebCore/dom/DeviceMotionEvent.idl b/Source/WebCore/dom/DeviceMotionEvent.idl -index ea39a33a6250b4d10b20802f98aa9a5d57e63a7b..300a763508d311fd7b34cb3df3cc93080bb52930 100644 +index d59cba0b1c3e1876614476cd887fa1b2a9619d0c..565987a3f9ef7dc29edf8315cebe51b00953dc84 100644 --- a/Source/WebCore/dom/DeviceMotionEvent.idl +++ b/Source/WebCore/dom/DeviceMotionEvent.idl @@ -25,6 +25,7 @@ @@ -2604,24 +2593,26 @@ index 9b344003de17b96d8b9ca8c7f32143a27543b1ea..2208a3f2b7d930bcd291e65b474d4c30 ] partial interface Element { // Returns Promise if PointerLockOptionsEnabled Runtime Flag is set, otherwise returns undefined. diff --git a/Source/WebCore/dom/PointerEvent.cpp b/Source/WebCore/dom/PointerEvent.cpp -index c35c7851f168954a0c5265ea218a2173b7b079a8..500b267351d2e4ac9864129650b6c00627a8ea6f 100644 +index 6b0390aba75731707ce48ea206b87974ffb15857..8c634c0748f0d447476d460ee2800f82d232d7ff 100644 --- a/Source/WebCore/dom/PointerEvent.cpp +++ b/Source/WebCore/dom/PointerEvent.cpp -@@ -27,9 +27,11 @@ - #include "PointerEvent.h" +@@ -28,10 +28,13 @@ #include "EventNames.h" + #include "MouseEventTypes.h" +#include "MouseEvent.h" #include "Node.h" - #include "PlatformMouseEvent.h" - #include "PointerEventTypeNames.h" +#include "PlatformTouchEvent.h" - #include + #include "PointerEventTypeNames.h" + #include + #include ++#include namespace WebCore { -@@ -122,4 +124,51 @@ PointerEvent::PointerEvent(const AtomString& type, PointerID pointerId, const St - PointerEvent::~PointerEvent() = default; +@@ -293,4 +296,59 @@ void PointerEvent::receivedTarget() + predictedEvent->setTarget(this->target()); + } +#if ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS_FAMILY) && !PLATFORM(WPE) + @@ -2645,26 +2636,34 @@ index c35c7851f168954a0c5265ea218a2173b7b079a8..500b267351d2e4ac9864129650b6c006 + return nullAtom(); +} + -+Ref PointerEvent::create(const PlatformTouchEvent& event, unsigned index, bool isPrimary, Ref&& view, const IntPoint& touchDelta) ++Ref PointerEvent::create(const PlatformTouchEvent& event, const Vector>& coalescedEvents, const Vector>& predictedEvents, unsigned touchIndex, bool isPrimary, Ref&& view, const IntPoint& touchDelta) ++{ ++ const auto& type = pointerEventType(event.touchPoints().at(touchIndex).state()); ++ return adoptRef(*new PointerEvent(type, event, coalescedEvents, predictedEvents, typeCanBubble(type), typeIsCancelable(type), touchIndex, isPrimary, WTFMove(view), touchDelta)); ++} ++ ++Ref PointerEvent::create(const PlatformTouchEvent& event, const Vector>& coalescedEvents, const Vector>& predictedEvents, CanBubble canBubble, IsCancelable isCancelable, unsigned touchIndex, bool isPrimary, Ref&& view, const IntPoint& touchDelta) +{ -+ const auto& type = pointerEventType(event.touchPoints().at(index).state()); -+ return adoptRef(*new PointerEvent(type, event, typeIsCancelable(type), index, isPrimary, WTFMove(view), touchDelta)); ++ const auto& type = pointerEventType(event.touchPoints().at(touchIndex).state()); ++ return adoptRef(*new PointerEvent(type, event, coalescedEvents, predictedEvents, canBubble, isCancelable, touchIndex, isPrimary, WTFMove(view), touchDelta)); +} + -+Ref PointerEvent::create(const AtomString& type, const PlatformTouchEvent& event, unsigned index, bool isPrimary, Ref&& view, const IntPoint& touchDelta) ++Ref PointerEvent::create(const AtomString& type, const PlatformTouchEvent& event, const Vector>& coalescedEvents, const Vector>& predictedEvents, unsigned touchIndex, bool isPrimary, Ref&& view, const IntPoint& touchDelta) +{ -+ return adoptRef(*new PointerEvent(type, event, typeIsCancelable(type), index, isPrimary, WTFMove(view), touchDelta)); ++ return adoptRef(*new PointerEvent(type, event, coalescedEvents, predictedEvents, typeCanBubble(type), typeIsCancelable(type), touchIndex, isPrimary, WTFMove(view), touchDelta)); +} + -+PointerEvent::PointerEvent(const AtomString& type, const PlatformTouchEvent& event, IsCancelable isCancelable, unsigned index, bool isPrimary, Ref&& view, const IntPoint& touchDelta) -+ : MouseEvent(EventInterfaceType::PointerEvent, type, typeCanBubble(type), isCancelable, typeIsComposed(type), event.timestamp().approximateMonotonicTime(), WTFMove(view), 0, -+ event.touchPoints().at(index).pos(), event.touchPoints().at(index).pos(), touchDelta.x(), touchDelta.y(), event.modifiers(), buttonForType(type), buttonsForType(type), nullptr, 0, SyntheticClickType::NoTap, IsSimulated::No, IsTrusted::Yes) -+ , m_pointerId(event.touchPoints().at(index).id()) -+ , m_width(2 * event.touchPoints().at(index).radiusX()) -+ , m_height(2 * event.touchPoints().at(index).radiusY()) -+ , m_pressure(event.touchPoints().at(index).force()) ++PointerEvent::PointerEvent(const AtomString& type, const PlatformTouchEvent& event, const Vector>& coalescedEvents, const Vector>& predictedEvents, CanBubble canBubble, IsCancelable isCancelable, unsigned touchIndex, bool isPrimary, Ref&& view, const IntPoint& touchDelta) ++ : MouseEvent(EventInterfaceType::PointerEvent, type, canBubble, isCancelable, typeIsComposed(type), event.timestamp().approximateMonotonicTime(), WTFMove(view), 0, ++ event.touchPoints().at(touchIndex).pos(), event.touchPoints().at(touchIndex).pos(), touchDelta.x(), touchDelta.y(), event.modifiers(), buttonForType(type), buttonsForType(type), nullptr, 0, SyntheticClickType::NoTap, { }, { }, IsSimulated::No, IsTrusted::Yes) ++ , m_pointerId(event.touchPoints().at(touchIndex).id()) ++ , m_width(2 * event.touchPoints().at(touchIndex).radiusX()) ++ , m_height(2 * event.touchPoints().at(touchIndex).radiusY()) ++ , m_pressure(event.touchPoints().at(touchIndex).force()) + , m_pointerType(touchPointerEventType()) + , m_isPrimary(isPrimary) ++ , m_coalescedEvents(coalescedEvents) ++ , m_predictedEvents(predictedEvents) +{ +} + @@ -2672,7 +2671,7 @@ index c35c7851f168954a0c5265ea218a2173b7b079a8..500b267351d2e4ac9864129650b6c006 + } // namespace WebCore diff --git a/Source/WebCore/dom/PointerEvent.h b/Source/WebCore/dom/PointerEvent.h -index 261a8c7e8946cac87b9ebc5fc5e3b697f326b7f4..02645d3bdce44f40a648e720e99a6b296f371fb2 100644 +index b034595d01bb63f3d72183c427fcc14695339ae2..1886e4bbba04c6177fad1562c891f2aeff0a8247 100644 --- a/Source/WebCore/dom/PointerEvent.h +++ b/Source/WebCore/dom/PointerEvent.h @@ -34,6 +34,8 @@ @@ -2684,37 +2683,37 @@ index 261a8c7e8946cac87b9ebc5fc5e3b697f326b7f4..02645d3bdce44f40a648e720e99a6b29 #endif #if ENABLE(TOUCH_EVENTS) && PLATFORM(WPE) -@@ -86,7 +88,7 @@ public: - static Ref create(const AtomString& type, MouseButton, const MouseEvent&, PointerID, const String& pointerType); +@@ -94,7 +96,7 @@ public: + static Ref create(const AtomString& type, MouseButton, const MouseEvent&, PointerID, const String& pointerType, CanBubble, IsCancelable); static Ref create(const AtomString& type, PointerID, const String& pointerType, IsPrimary = IsPrimary::No); -#if ENABLE(TOUCH_EVENTS) && (PLATFORM(IOS_FAMILY) || PLATFORM(WPE)) +#if ENABLE(TOUCH_EVENTS) - static Ref create(const PlatformTouchEvent&, unsigned touchIndex, bool isPrimary, Ref&&, const IntPoint& touchDelta = { }); - static Ref create(const AtomString& type, const PlatformTouchEvent&, unsigned touchIndex, bool isPrimary, Ref&&, const IntPoint& touchDelta = { }); - #endif -@@ -140,7 +142,7 @@ private: - PointerEvent(const AtomString&, Init&&); - PointerEvent(const AtomString& type, MouseButton, const MouseEvent&, PointerID, const String& pointerType); + static Ref create(const PlatformTouchEvent&, const Vector>& coalescedEvents, const Vector>& predictedEvents, unsigned touchIndex, bool isPrimary, Ref&&, const IntPoint& touchDelta = { }); + static Ref create(const PlatformTouchEvent&, const Vector>& coalescedEvents, const Vector>& predictedEvents, CanBubble, IsCancelable, unsigned touchIndex, bool isPrimary, Ref&& view, const IntPoint& touchDelta = { }); + static Ref create(const AtomString& type, const PlatformTouchEvent&, const Vector>& coalescedEvents, const Vector>& predictedEvents, unsigned touchIndex, bool isPrimary, Ref&&, const IntPoint& touchDelta = { }); +@@ -173,7 +175,7 @@ private: + PointerEvent(); + PointerEvent(const AtomString&, Init&&, IsTrusted); PointerEvent(const AtomString& type, PointerID, const String& pointerType, IsPrimary); -#if ENABLE(TOUCH_EVENTS) && (PLATFORM(IOS_FAMILY) || PLATFORM(WPE)) +#if ENABLE(TOUCH_EVENTS) - PointerEvent(const AtomString& type, const PlatformTouchEvent&, IsCancelable isCancelable, unsigned touchIndex, bool isPrimary, Ref&&, const IntPoint& touchDelta = { }); + PointerEvent(const AtomString& type, const PlatformTouchEvent&, const Vector>& coalescedEvents, const Vector>& predictedEvents, CanBubble canBubble, IsCancelable isCancelable, unsigned touchIndex, bool isPrimary, Ref&&, const IntPoint& touchDelta = { }); #endif diff --git a/Source/WebCore/editing/libwpe/EditorLibWPE.cpp b/Source/WebCore/editing/libwpe/EditorLibWPE.cpp -index 7813532cc52d582c42aebc979a1ecd1137765f08..c01cbd53ad2430a6ffab9a80fc73e74a8523800a 100644 +index d0a3d5c048647b07772e1581c76c4eb60ecf41b0..bec324636991079264e620c0dfdaf9842ff585cd 100644 --- a/Source/WebCore/editing/libwpe/EditorLibWPE.cpp +++ b/Source/WebCore/editing/libwpe/EditorLibWPE.cpp -@@ -34,6 +34,7 @@ - #include "NotImplemented.h" +@@ -35,6 +35,7 @@ #include "Pasteboard.h" #include "Settings.h" + #include "SimpleRange.h" +#include "WebContentReader.h" #include "markup.h" namespace WebCore { -@@ -99,6 +100,14 @@ void Editor::platformPasteFont() +@@ -100,6 +101,14 @@ void Editor::platformPasteFont() { } @@ -2730,10 +2729,10 @@ index 7813532cc52d582c42aebc979a1ecd1137765f08..c01cbd53ad2430a6ffab9a80fc73e74a #endif // USE(LIBWPE) diff --git a/Source/WebCore/html/FileInputType.cpp b/Source/WebCore/html/FileInputType.cpp -index dde92a4942d3f6679b6ef2455fa15d023544dfbc..c6ed18b40209195d1cf5c7785091d37fd40dad80 100644 +index d5234a678a77e24ce0a95fe08740416ab8acbadb..c9a42fd354e88c5a8c3ee53974442ec9d4cb1224 100644 --- a/Source/WebCore/html/FileInputType.cpp +++ b/Source/WebCore/html/FileInputType.cpp -@@ -37,6 +37,7 @@ +@@ -38,6 +38,7 @@ #include "HTMLNames.h" #include "Icon.h" #include "InputTypeNames.h" @@ -2741,52 +2740,41 @@ index dde92a4942d3f6679b6ef2455fa15d023544dfbc..c6ed18b40209195d1cf5c7785091d37f #include "LocalFrame.h" #include "LocalizedStrings.h" #include "MIMETypeRegistry.h" -@@ -157,6 +158,11 @@ void FileInputType::handleDOMActivateEvent(Event& event) - if (input.isDisabledFormControl()) +@@ -161,6 +162,11 @@ void FileInputType::handleDOMActivateEvent(Event& event) + if (protectedElement()->isDisabledFormControl()) return; + bool intercept = false; -+ InspectorInstrumentation::runOpenPanel(input.document().frame(), element(), &intercept); ++ InspectorInstrumentation::runOpenPanel(element()->document().frame(), element(), &intercept); + if (intercept) + return; + if (!UserGestureIndicator::processingUserGesture()) return; -@@ -345,7 +351,9 @@ void FileInputType::setFiles(RefPtr&& files, RequestIcon shouldRequest - pathsChanged = true; - else { - for (unsigned i = 0; i < length; ++i) { -- if (files->file(i).path() != m_fileList->file(i).path() || !FileSystem::fileIDsAreEqual(files->file(i).fileID(), m_fileList->file(i).fileID())) { -+ if (files->file(i).path() != m_fileList->file(i).path() || !FileSystem::fileIDsAreEqual(files->file(i).fileID(), m_fileList->file(i).fileID()) || -+ // Files created from Blob have empty path. -+ (files->file(i).path().isEmpty() && files->file(i).name() != m_fileList->file(i).name())) { - pathsChanged = true; - break; - } diff --git a/Source/WebCore/inspector/InspectorController.cpp b/Source/WebCore/inspector/InspectorController.cpp -index 3844ae7bab48f46b77cfd85530e4ab19392a71dd..8d705215457f89711e78e3bee9c983d131b08245 100644 +index 48efc5356601313e907846283f753e44d6a0f983..f153fd7da52da98d033e4070d79c64d4a38ff197 100644 --- a/Source/WebCore/inspector/InspectorController.cpp +++ b/Source/WebCore/inspector/InspectorController.cpp -@@ -287,6 +287,8 @@ void InspectorController::disconnectFrontend(FrontendChannel& frontendChannel) +@@ -296,6 +296,8 @@ void InspectorController::disconnectFrontend(FrontendChannel& frontendChannel) // Unplug all instrumentations since they aren't needed now. InspectorInstrumentation::unregisterInstrumentingAgents(m_instrumentingAgents.get()); + -+ m_pauseWhenShown = false; ++ m_pauseOnStart = PauseCondition::DONT_PAUSE; } m_inspectorClient->frontendCountChanged(m_frontendRouter->frontendCount()); -@@ -306,6 +308,8 @@ void InspectorController::disconnectAllFrontends() +@@ -315,6 +317,8 @@ void InspectorController::disconnectAllFrontends() // The frontend should call setInspectorFrontendClient(nullptr) under closeWindow(). ASSERT(!m_inspectorFrontendClient); -+ m_pauseWhenShown = false; ++ m_pauseOnStart = PauseCondition::DONT_PAUSE; + if (!m_frontendRouter->hasFrontends()) return; -@@ -394,8 +398,8 @@ void InspectorController::inspect(Node* node) +@@ -398,8 +402,8 @@ void InspectorController::inspect(Node* node) if (!enabled()) return; @@ -2797,25 +2785,35 @@ index 3844ae7bab48f46b77cfd85530e4ab19392a71dd..8d705215457f89711e78e3bee9c983d1 ensureDOMAgent().inspect(node); } -@@ -538,4 +542,24 @@ void InspectorController::didComposite(LocalFrame& frame) +@@ -542,4 +546,34 @@ void InspectorController::didComposite(LocalFrame& frame) InspectorInstrumentation::didComposite(frame); } -+void InspectorController::pauseWhenShown() ++void InspectorController::pauseOnStart(PauseCondition condition) +{ -+ m_pauseWhenShown = true; ++ m_pauseOnStart = condition; +} + +void InspectorController::resumeIfPausedInNewWindow() +{ -+ m_pauseWhenShown = false; ++ m_pauseOnStart = PauseCondition::DONT_PAUSE; +} + -+void InspectorController::didShowNewWindow() ++void InspectorController::didFinishPageCreation() +{ -+ if (!m_pauseWhenShown) -+ return; -+ while (m_pauseWhenShown) { ++ if (m_pauseOnStart == PauseCondition::WHEN_CREATION_FINISHED) ++ runLoopWhilePaused(); ++} ++ ++void InspectorController::didShowPage() ++{ ++ if (m_pauseOnStart == PauseCondition::WHEN_SHOWN) ++ runLoopWhilePaused(); ++} ++ ++void InspectorController::runLoopWhilePaused() ++{ ++ while (m_pauseOnStart != PauseCondition::DONT_PAUSE) { + if (RunLoop::cycle() == RunLoop::CycleResult::Stop) + break; + } @@ -2823,33 +2821,43 @@ index 3844ae7bab48f46b77cfd85530e4ab19392a71dd..8d705215457f89711e78e3bee9c983d1 + } // namespace WebCore diff --git a/Source/WebCore/inspector/InspectorController.h b/Source/WebCore/inspector/InspectorController.h -index 3a981b5bf5ca0bbf4d1c9f0b125564742cd8cad9..f8fc2ca6700461627933f149c5837075226a51a9 100644 +index 4f5c1e836876710a554455ec53733f72db63de58..774c4a66af84664a7a83ba0790d147f7bbb4236a 100644 --- a/Source/WebCore/inspector/InspectorController.h +++ b/Source/WebCore/inspector/InspectorController.h -@@ -101,6 +101,10 @@ public: +@@ -106,6 +106,12 @@ public: WEBCORE_EXPORT void willComposite(LocalFrame&); WEBCORE_EXPORT void didComposite(LocalFrame&); -+ WEBCORE_EXPORT void pauseWhenShown(); ++ enum class PauseCondition { DONT_PAUSE, WHEN_SHOWN, WHEN_CREATION_FINISHED }; ++ WEBCORE_EXPORT void pauseOnStart(PauseCondition); + WEBCORE_EXPORT void resumeIfPausedInNewWindow(); -+ WEBCORE_EXPORT void didShowNewWindow(); ++ WEBCORE_EXPORT void didShowPage(); ++ WEBCORE_EXPORT void didFinishPageCreation(); + // Testing support. - WEBCORE_EXPORT bool isUnderTest() const; + bool isUnderTest() const { return m_isUnderTest; } void setIsUnderTest(bool isUnderTest) { m_isUnderTest = isUnderTest; } -@@ -154,6 +158,7 @@ private: +@@ -136,6 +142,7 @@ private: + + PageAgentContext pageAgentContext(); + void createLazyAgents(); ++ void runLoopWhilePaused(); + + WeakRef m_page; + Ref m_instrumentingAgents; +@@ -159,6 +166,7 @@ private: bool m_isAutomaticInspection { false }; bool m_pauseAfterInitialization = { false }; bool m_didCreateLazyAgents { false }; -+ bool m_pauseWhenShown { false }; ++ PauseCondition m_pauseOnStart { PauseCondition::DONT_PAUSE }; }; } // namespace WebCore diff --git a/Source/WebCore/inspector/InspectorInstrumentation.cpp b/Source/WebCore/inspector/InspectorInstrumentation.cpp -index 8c7b186092793bf301511be969030c92674ce211..bcad9353cd568ed435b42d5b9d505b3ca973aaea 100644 +index 1c660f381ad7e9a9201aeced2906f39135e810f6..6c47abc2f32b39fd5c0bf9048b9c1224959ba08c 100644 --- a/Source/WebCore/inspector/InspectorInstrumentation.cpp +++ b/Source/WebCore/inspector/InspectorInstrumentation.cpp -@@ -597,6 +597,12 @@ void InspectorInstrumentation::applyUserAgentOverrideImpl(InstrumentingAgents& i +@@ -595,6 +595,12 @@ void InspectorInstrumentation::applyUserAgentOverrideImpl(InstrumentingAgents& i pageAgent->applyUserAgentOverride(userAgent); } @@ -2862,7 +2870,7 @@ index 8c7b186092793bf301511be969030c92674ce211..bcad9353cd568ed435b42d5b9d505b3c void InspectorInstrumentation::applyEmulatedMediaImpl(InstrumentingAgents& instrumentingAgents, AtomString& media) { if (auto* pageAgent = instrumentingAgents.enabledPageAgent()) -@@ -680,6 +686,12 @@ void InspectorInstrumentation::didFailLoadingImpl(InstrumentingAgents& instrumen +@@ -678,6 +684,12 @@ void InspectorInstrumentation::didFailLoadingImpl(InstrumentingAgents& instrumen consoleAgent->didFailLoading(identifier, error); // This should come AFTER resource notification, front-end relies on this. } @@ -2875,7 +2883,7 @@ index 8c7b186092793bf301511be969030c92674ce211..bcad9353cd568ed435b42d5b9d505b3c void InspectorInstrumentation::willLoadXHRSynchronouslyImpl(InstrumentingAgents& instrumentingAgents) { if (auto* networkAgent = instrumentingAgents.enabledNetworkAgent()) -@@ -712,20 +724,17 @@ void InspectorInstrumentation::didReceiveScriptResponseImpl(InstrumentingAgents& +@@ -710,20 +722,17 @@ void InspectorInstrumentation::didReceiveScriptResponseImpl(InstrumentingAgents& void InspectorInstrumentation::domContentLoadedEventFiredImpl(InstrumentingAgents& instrumentingAgents, LocalFrame& frame) { @@ -2899,7 +2907,7 @@ index 8c7b186092793bf301511be969030c92674ce211..bcad9353cd568ed435b42d5b9d505b3c } void InspectorInstrumentation::frameDetachedFromParentImpl(InstrumentingAgents& instrumentingAgents, LocalFrame& frame) -@@ -808,12 +817,6 @@ void InspectorInstrumentation::frameDocumentUpdatedImpl(InstrumentingAgents& ins +@@ -803,12 +812,6 @@ void InspectorInstrumentation::frameDocumentUpdatedImpl(InstrumentingAgents& ins pageDOMDebuggerAgent->frameDocumentUpdated(frame); } @@ -2912,7 +2920,7 @@ index 8c7b186092793bf301511be969030c92674ce211..bcad9353cd568ed435b42d5b9d505b3c void InspectorInstrumentation::frameStartedLoadingImpl(InstrumentingAgents& instrumentingAgents, LocalFrame& frame) { if (frame.isMainFrame()) { -@@ -844,10 +847,10 @@ void InspectorInstrumentation::frameStoppedLoadingImpl(InstrumentingAgents& inst +@@ -839,10 +842,10 @@ void InspectorInstrumentation::frameStoppedLoadingImpl(InstrumentingAgents& inst inspectorPageAgent->frameStoppedLoading(frame); } @@ -2925,7 +2933,7 @@ index 8c7b186092793bf301511be969030c92674ce211..bcad9353cd568ed435b42d5b9d505b3c } void InspectorInstrumentation::frameClearedScheduledNavigationImpl(InstrumentingAgents& instrumentingAgents, Frame& frame) -@@ -862,6 +865,12 @@ void InspectorInstrumentation::accessibilitySettingsDidChangeImpl(InstrumentingA +@@ -857,6 +860,12 @@ void InspectorInstrumentation::accessibilitySettingsDidChangeImpl(InstrumentingA inspectorPageAgent->accessibilitySettingsDidChange(); } @@ -2935,10 +2943,23 @@ index 8c7b186092793bf301511be969030c92674ce211..bcad9353cd568ed435b42d5b9d505b3c + inspectorPageAgent->didNavigateWithinPage(frame); +} + - #if ENABLE(DARK_MODE_CSS) || HAVE(OS_DARK_MODE_SUPPORT) + #if ENABLE(DARK_MODE_CSS) void InspectorInstrumentation::defaultAppearanceDidChangeImpl(InstrumentingAgents& instrumentingAgents) { -@@ -1050,6 +1059,12 @@ void InspectorInstrumentation::consoleStopRecordingCanvasImpl(InstrumentingAgent +@@ -909,6 +918,12 @@ void InspectorInstrumentation::interceptResponseImpl(InstrumentingAgents& instru + networkAgent->interceptResponse(response, identifier, WTFMove(handler)); + } + ++void InspectorInstrumentation::setStoppingLoadingDueToProcessSwapImpl(InstrumentingAgents& instrumentingAgents, bool value) ++{ ++ if (auto* networkAgent = instrumentingAgents.enabledNetworkAgent()) ++ networkAgent->setStoppingLoadingDueToProcessSwap(value); ++} ++ + // JavaScriptCore InspectorDebuggerAgent should know Console MessageTypes. + static bool isConsoleAssertMessage(MessageSource source, MessageType type) + { +@@ -1027,6 +1042,12 @@ void InspectorInstrumentation::consoleStopRecordingCanvasImpl(InstrumentingAgent canvasAgent->consoleStopRecordingCanvas(context); } @@ -2948,10 +2969,10 @@ index 8c7b186092793bf301511be969030c92674ce211..bcad9353cd568ed435b42d5b9d505b3c + pageRuntimeAgent->bindingCalled(globalObject, name, arg); +} + - void InspectorInstrumentation::didOpenDatabaseImpl(InstrumentingAgents& instrumentingAgents, Database& database) + void InspectorInstrumentation::didDispatchDOMStorageEventImpl(InstrumentingAgents& instrumentingAgents, const String& key, const String& oldValue, const String& newValue, StorageType storageType, const SecurityOrigin& securityOrigin) { - if (auto* databaseAgent = instrumentingAgents.enabledDatabaseAgent()) -@@ -1356,6 +1371,36 @@ void InspectorInstrumentation::renderLayerDestroyedImpl(InstrumentingAgents& ins + if (auto* domStorageAgent = instrumentingAgents.enabledDOMStorageAgent()) +@@ -1317,6 +1338,36 @@ void InspectorInstrumentation::renderLayerDestroyedImpl(InstrumentingAgents& ins layerTreeAgent->renderLayerDestroyed(renderLayer); } @@ -2988,7 +3009,7 @@ index 8c7b186092793bf301511be969030c92674ce211..bcad9353cd568ed435b42d5b9d505b3c InstrumentingAgents& InspectorInstrumentation::instrumentingAgents(WorkerOrWorkletGlobalScope& globalScope) { return globalScope.inspectorController().m_instrumentingAgents; -@@ -1367,6 +1412,13 @@ InstrumentingAgents& InspectorInstrumentation::instrumentingAgents(Page& page) +@@ -1333,6 +1384,13 @@ InstrumentingAgents& InspectorInstrumentation::instrumentingAgents(Page& page) return page.inspectorController().m_instrumentingAgents.get(); } @@ -3003,7 +3024,7 @@ index 8c7b186092793bf301511be969030c92674ce211..bcad9353cd568ed435b42d5b9d505b3c { // Using RefPtr makes us hit the m_inRemovedLastRefFunction assert. diff --git a/Source/WebCore/inspector/InspectorInstrumentation.h b/Source/WebCore/inspector/InspectorInstrumentation.h -index 7aa2d9e599359d9302cbdde8a7a0b9399e37d313..7b4ec6ee9adb5687e16eb0fe746a3114fca4d82a 100644 +index ed15dcc0dd1eb8d22dc48d8c6515b2258db574c5..c297c2d0e61b8ca1f881bb7942c463626bf0118f 100644 --- a/Source/WebCore/inspector/InspectorInstrumentation.h +++ b/Source/WebCore/inspector/InspectorInstrumentation.h @@ -31,6 +31,7 @@ @@ -3030,7 +3051,7 @@ index 7aa2d9e599359d9302cbdde8a7a0b9399e37d313..7b4ec6ee9adb5687e16eb0fe746a3114 class HTTPHeaderMap; class InspectorTimelineAgent; class InstrumentingAgents; -@@ -192,6 +195,7 @@ public: +@@ -197,6 +200,7 @@ public: static void didRecalculateStyle(Document&); static void didScheduleStyleRecalculation(Document&); static void applyUserAgentOverride(LocalFrame&, String&); @@ -3038,39 +3059,47 @@ index 7aa2d9e599359d9302cbdde8a7a0b9399e37d313..7b4ec6ee9adb5687e16eb0fe746a3114 static void applyEmulatedMedia(LocalFrame&, AtomString&); static void flexibleBoxRendererBeganLayout(const RenderObject&); -@@ -204,6 +208,7 @@ public: +@@ -209,6 +213,7 @@ public: static void didReceiveData(LocalFrame*, ResourceLoaderIdentifier, const SharedBuffer*, int encodedDataLength); static void didFinishLoading(LocalFrame*, DocumentLoader*, ResourceLoaderIdentifier, const NetworkLoadMetrics&, ResourceLoader*); static void didFailLoading(LocalFrame*, DocumentLoader*, ResourceLoaderIdentifier, const ResourceError&); + static void didReceiveMainResourceError(LocalFrame&, const ResourceError&); - static void willSendRequest(WorkerOrWorkletGlobalScope&, ResourceLoaderIdentifier, ResourceRequest&); - static void didReceiveResourceResponse(WorkerOrWorkletGlobalScope&, ResourceLoaderIdentifier, const ResourceResponse&); -@@ -230,13 +235,13 @@ public: + static void willSendRequest(ServiceWorkerGlobalScope&, ResourceLoaderIdentifier, ResourceRequest&); + static void didReceiveResourceResponse(ServiceWorkerGlobalScope&, ResourceLoaderIdentifier, const ResourceResponse&); +@@ -235,13 +240,13 @@ public: static void frameDetachedFromParent(LocalFrame&); static void didCommitLoad(LocalFrame&, DocumentLoader*); static void frameDocumentUpdated(LocalFrame&); - static void loaderDetachedFromFrame(LocalFrame&, DocumentLoader&); static void frameStartedLoading(LocalFrame&); static void frameStoppedLoading(LocalFrame&); - static void didCompleteRenderingFrame(LocalFrame&); + static void didCompleteRenderingFrame(Frame&); - static void frameScheduledNavigation(Frame&, Seconds delay); + static void frameScheduledNavigation(Frame&, Seconds delay, bool targetIsCurrentFrame); static void frameClearedScheduledNavigation(Frame&); static void accessibilitySettingsDidChange(Page&); + static void didNavigateWithinPage(LocalFrame&); - #if ENABLE(DARK_MODE_CSS) || HAVE(OS_DARK_MODE_SUPPORT) + #if ENABLE(DARK_MODE_CSS) static void defaultAppearanceDidChange(Page&); #endif -@@ -268,6 +273,7 @@ public: - static void stopProfiling(Page&, JSC::JSGlobalObject*, const String& title); +@@ -252,6 +257,7 @@ public: + static bool shouldInterceptResponse(const LocalFrame&, const ResourceResponse&); + static void interceptRequest(ResourceLoader&, Function&&); + static void interceptResponse(const LocalFrame&, const ResourceResponse&, ResourceLoaderIdentifier, CompletionHandler)>&&); ++ static void setStoppingLoadingDueToProcessSwap(Page*, bool); + + static void addMessageToConsole(Page&, std::unique_ptr); + static void addMessageToConsole(WorkerOrWorkletGlobalScope&, std::unique_ptr); +@@ -277,6 +283,7 @@ public: + static void stopProfiling(WorkerOrWorkletGlobalScope&, const String& title); static void consoleStartRecordingCanvas(CanvasRenderingContext&, JSC::JSGlobalObject&, JSC::JSObject* options); static void consoleStopRecordingCanvas(CanvasRenderingContext&); + static void bindingCalled(Page& , JSC::JSGlobalObject*, const String& name, const String& arg); - static void performanceMark(ScriptExecutionContext&, const String&, std::optional, LocalFrame*); + static void performanceMark(ScriptExecutionContext&, const String&, std::optional); -@@ -326,6 +332,12 @@ public: +@@ -330,6 +337,12 @@ public: static void layerTreeDidChange(Page*); static void renderLayerDestroyed(Page*, const RenderLayer&); @@ -3083,7 +3112,7 @@ index 7aa2d9e599359d9302cbdde8a7a0b9399e37d313..7b4ec6ee9adb5687e16eb0fe746a3114 static void frontendCreated(); static void frontendDeleted(); static bool hasFrontends() { return InspectorInstrumentationPublic::hasFrontends(); } -@@ -342,6 +354,8 @@ public: +@@ -346,6 +359,8 @@ public: static void registerInstrumentingAgents(InstrumentingAgents&); static void unregisterInstrumentingAgents(InstrumentingAgents&); @@ -3092,7 +3121,7 @@ index 7aa2d9e599359d9302cbdde8a7a0b9399e37d313..7b4ec6ee9adb5687e16eb0fe746a3114 private: static void didClearWindowObjectInWorldImpl(InstrumentingAgents&, LocalFrame&, DOMWrapperWorld&); static bool isDebuggerPausedImpl(InstrumentingAgents&); -@@ -421,6 +435,7 @@ private: +@@ -427,6 +442,7 @@ private: static void didRecalculateStyleImpl(InstrumentingAgents&); static void didScheduleStyleRecalculationImpl(InstrumentingAgents&, Document&); static void applyUserAgentOverrideImpl(InstrumentingAgents&, String&); @@ -3100,7 +3129,7 @@ index 7aa2d9e599359d9302cbdde8a7a0b9399e37d313..7b4ec6ee9adb5687e16eb0fe746a3114 static void applyEmulatedMediaImpl(InstrumentingAgents&, AtomString&); static void flexibleBoxRendererBeganLayoutImpl(InstrumentingAgents&, const RenderObject&); -@@ -435,6 +450,7 @@ private: +@@ -441,6 +457,7 @@ private: static void didReceiveDataImpl(InstrumentingAgents&, ResourceLoaderIdentifier, const SharedBuffer*, int encodedDataLength); static void didFinishLoadingImpl(InstrumentingAgents&, ResourceLoaderIdentifier, DocumentLoader*, const NetworkLoadMetrics&, ResourceLoader*); static void didFailLoadingImpl(InstrumentingAgents&, ResourceLoaderIdentifier, DocumentLoader*, const ResourceError&); @@ -3108,7 +3137,7 @@ index 7aa2d9e599359d9302cbdde8a7a0b9399e37d313..7b4ec6ee9adb5687e16eb0fe746a3114 static void willLoadXHRSynchronouslyImpl(InstrumentingAgents&); static void didLoadXHRSynchronouslyImpl(InstrumentingAgents&); static void scriptImportedImpl(InstrumentingAgents&, ResourceLoaderIdentifier, const String& sourceString); -@@ -445,13 +461,13 @@ private: +@@ -451,13 +468,13 @@ private: static void frameDetachedFromParentImpl(InstrumentingAgents&, LocalFrame&); static void didCommitLoadImpl(InstrumentingAgents&, LocalFrame&, DocumentLoader*); static void frameDocumentUpdatedImpl(InstrumentingAgents&, LocalFrame&); @@ -3121,18 +3150,26 @@ index 7aa2d9e599359d9302cbdde8a7a0b9399e37d313..7b4ec6ee9adb5687e16eb0fe746a3114 static void frameClearedScheduledNavigationImpl(InstrumentingAgents&, Frame&); static void accessibilitySettingsDidChangeImpl(InstrumentingAgents&); + static void didNavigateWithinPageImpl(InstrumentingAgents&, LocalFrame&); - #if ENABLE(DARK_MODE_CSS) || HAVE(OS_DARK_MODE_SUPPORT) + #if ENABLE(DARK_MODE_CSS) static void defaultAppearanceDidChangeImpl(InstrumentingAgents&); #endif -@@ -478,6 +494,7 @@ private: - static void stopProfilingImpl(InstrumentingAgents&, JSC::JSGlobalObject*, const String& title); +@@ -468,6 +485,7 @@ private: + static bool shouldInterceptResponseImpl(InstrumentingAgents&, const ResourceResponse&); + static void interceptRequestImpl(InstrumentingAgents&, ResourceLoader&, Function&&); + static void interceptResponseImpl(InstrumentingAgents&, const ResourceResponse&, ResourceLoaderIdentifier, CompletionHandler)>&&); ++ static void setStoppingLoadingDueToProcessSwapImpl(InstrumentingAgents&, bool); + + static void addMessageToConsoleImpl(InstrumentingAgents&, std::unique_ptr); + +@@ -482,6 +500,7 @@ private: + static void stopProfilingImpl(InstrumentingAgents&, const String& title); static void consoleStartRecordingCanvasImpl(InstrumentingAgents&, CanvasRenderingContext&, JSC::JSGlobalObject&, JSC::JSObject* options); static void consoleStopRecordingCanvasImpl(InstrumentingAgents&, CanvasRenderingContext&); + static void bindingCalledImpl(InstrumentingAgents&, JSC::JSGlobalObject*, const String& name, const String& arg); - static void performanceMarkImpl(InstrumentingAgents&, const String& label, std::optional, LocalFrame*); + static void performanceMarkImpl(InstrumentingAgents&, const String& label, std::optional); -@@ -536,6 +553,12 @@ private: +@@ -535,6 +554,12 @@ private: static void layerTreeDidChangeImpl(InstrumentingAgents&); static void renderLayerDestroyedImpl(InstrumentingAgents&, const RenderLayer&); @@ -3144,8 +3181,8 @@ index 7aa2d9e599359d9302cbdde8a7a0b9399e37d313..7b4ec6ee9adb5687e16eb0fe746a3114 + static InstrumentingAgents& instrumentingAgents(Page&); static InstrumentingAgents& instrumentingAgents(WorkerOrWorkletGlobalScope&); - -@@ -1068,6 +1091,13 @@ inline void InspectorInstrumentation::applyUserAgentOverride(LocalFrame& frame, + static InstrumentingAgents& instrumentingAgents(ServiceWorkerGlobalScope&); +@@ -1094,6 +1119,13 @@ inline void InspectorInstrumentation::applyUserAgentOverride(LocalFrame& frame, applyUserAgentOverrideImpl(*agents, userAgent); } @@ -3159,7 +3196,7 @@ index 7aa2d9e599359d9302cbdde8a7a0b9399e37d313..7b4ec6ee9adb5687e16eb0fe746a3114 inline void InspectorInstrumentation::applyEmulatedMedia(LocalFrame& frame, AtomString& media) { FAST_RETURN_IF_NO_FRONTENDS(void()); -@@ -1170,6 +1200,13 @@ inline void InspectorInstrumentation::didFailLoading(WorkerOrWorkletGlobalScope& +@@ -1196,6 +1228,13 @@ inline void InspectorInstrumentation::didFailLoading(ServiceWorkerGlobalScope& g didFailLoadingImpl(instrumentingAgents(globalScope), identifier, nullptr, error); } @@ -3173,7 +3210,7 @@ index 7aa2d9e599359d9302cbdde8a7a0b9399e37d313..7b4ec6ee9adb5687e16eb0fe746a3114 inline void InspectorInstrumentation::continueAfterXFrameOptionsDenied(LocalFrame& frame, ResourceLoaderIdentifier identifier, DocumentLoader& loader, const ResourceResponse& response) { // Treat the same as didReceiveResponse. -@@ -1260,13 +1297,6 @@ inline void InspectorInstrumentation::frameDocumentUpdated(LocalFrame& frame) +@@ -1286,13 +1325,6 @@ inline void InspectorInstrumentation::frameDocumentUpdated(LocalFrame& frame) frameDocumentUpdatedImpl(*agents, frame); } @@ -3187,7 +3224,7 @@ index 7aa2d9e599359d9302cbdde8a7a0b9399e37d313..7b4ec6ee9adb5687e16eb0fe746a3114 inline void InspectorInstrumentation::frameStartedLoading(LocalFrame& frame) { FAST_RETURN_IF_NO_FRONTENDS(void()); -@@ -1288,11 +1318,11 @@ inline void InspectorInstrumentation::frameStoppedLoading(LocalFrame& frame) +@@ -1314,11 +1346,11 @@ inline void InspectorInstrumentation::frameStoppedLoading(LocalFrame& frame) frameStoppedLoadingImpl(*agents, frame); } @@ -3201,7 +3238,7 @@ index 7aa2d9e599359d9302cbdde8a7a0b9399e37d313..7b4ec6ee9adb5687e16eb0fe746a3114 } inline void InspectorInstrumentation::frameClearedScheduledNavigation(Frame& frame) -@@ -1308,6 +1338,13 @@ inline void InspectorInstrumentation::accessibilitySettingsDidChange(Page& page) +@@ -1334,6 +1366,13 @@ inline void InspectorInstrumentation::accessibilitySettingsDidChange(Page& page) accessibilitySettingsDidChangeImpl(instrumentingAgents(page)); } @@ -3212,11 +3249,25 @@ index 7aa2d9e599359d9302cbdde8a7a0b9399e37d313..7b4ec6ee9adb5687e16eb0fe746a3114 + didNavigateWithinPageImpl(*agents, frame); +} + - #if ENABLE(DARK_MODE_CSS) || HAVE(OS_DARK_MODE_SUPPORT) + #if ENABLE(DARK_MODE_CSS) inline void InspectorInstrumentation::defaultAppearanceDidChange(Page& page) { -@@ -1696,6 +1733,11 @@ inline void InspectorInstrumentation::performanceMark(ScriptExecutionContext& co - performanceMarkImpl(*agents, label, WTFMove(startTime), frame); +@@ -1386,6 +1425,13 @@ inline void InspectorInstrumentation::interceptResponse(const LocalFrame& frame, + interceptResponseImpl(*agents, response, identifier, WTFMove(handler)); + } + ++inline void InspectorInstrumentation::setStoppingLoadingDueToProcessSwap(Page* page, bool value) ++{ ++ ASSERT(InspectorInstrumentationPublic::hasFrontends()); ++ if (auto* agents = instrumentingAgents(page)) ++ setStoppingLoadingDueToProcessSwapImpl(*agents, value); ++} ++ + inline void InspectorInstrumentation::didDispatchDOMStorageEvent(Page& page, const String& key, const String& oldValue, const String& newValue, StorageType storageType, const SecurityOrigin& securityOrigin) + { + FAST_RETURN_IF_NO_FRONTENDS(void()); +@@ -1726,6 +1772,11 @@ inline void InspectorInstrumentation::performanceMark(ScriptExecutionContext& co + performanceMarkImpl(*agents, label, WTFMove(startTime)); } +inline void InspectorInstrumentation::bindingCalled(Page& page, JSC::JSGlobalObject* globalObject, const String& name, const String& arg) @@ -3224,10 +3275,10 @@ index 7aa2d9e599359d9302cbdde8a7a0b9399e37d313..7b4ec6ee9adb5687e16eb0fe746a3114 + bindingCalledImpl(instrumentingAgents(page), globalObject, name, arg); +} + - inline void InspectorInstrumentation::didRequestAnimationFrame(Document& document, int callbackId) + inline void InspectorInstrumentation::didRequestAnimationFrame(ScriptExecutionContext& scriptExecutionContext, int callbackId) { FAST_RETURN_IF_NO_FRONTENDS(void()); -@@ -1752,6 +1794,42 @@ inline void InspectorInstrumentation::renderLayerDestroyed(Page* page, const Ren +@@ -1782,6 +1833,42 @@ inline void InspectorInstrumentation::renderLayerDestroyed(Page* page, const Ren renderLayerDestroyedImpl(*agents, renderLayer); } @@ -3270,26 +3321,86 @@ index 7aa2d9e599359d9302cbdde8a7a0b9399e37d313..7b4ec6ee9adb5687e16eb0fe746a3114 inline InstrumentingAgents* InspectorInstrumentation::instrumentingAgents(ScriptExecutionContext* context) { return context ? instrumentingAgents(*context) : nullptr; +diff --git a/Source/WebCore/inspector/InspectorInstrumentationWebKit.cpp b/Source/WebCore/inspector/InspectorInstrumentationWebKit.cpp +index a67a1244fa526ad5759068e97e0d220f59565d6e..0048589109fccb9472fe35a410337771b1063d72 100644 +--- a/Source/WebCore/inspector/InspectorInstrumentationWebKit.cpp ++++ b/Source/WebCore/inspector/InspectorInstrumentationWebKit.cpp +@@ -50,4 +50,9 @@ void InspectorInstrumentationWebKit::interceptResponseInternal(const LocalFrame& + InspectorInstrumentation::interceptResponse(frame, response, identifier, WTFMove(handler)); + } + ++void InspectorInstrumentationWebKit::setStoppingLoadingDueToProcessSwapInternal(Page* page, bool value) ++{ ++ InspectorInstrumentation::setStoppingLoadingDueToProcessSwap(page, value); ++} ++ + } // namespace WebCore +diff --git a/Source/WebCore/inspector/InspectorInstrumentationWebKit.h b/Source/WebCore/inspector/InspectorInstrumentationWebKit.h +index c028341e84e59a6b1b16107fd74feb21f70b12ab..d385418ac34e8f315f201801a2c65226c8f6fee2 100644 +--- a/Source/WebCore/inspector/InspectorInstrumentationWebKit.h ++++ b/Source/WebCore/inspector/InspectorInstrumentationWebKit.h +@@ -33,6 +33,7 @@ + namespace WebCore { + + class LocalFrame; ++class Page; + class ResourceLoader; + class ResourceRequest; + class ResourceResponse; +@@ -44,12 +45,14 @@ public: + static bool shouldInterceptResponse(const LocalFrame*, const ResourceResponse&); + static void interceptRequest(ResourceLoader&, Function&&); + static void interceptResponse(const LocalFrame*, const ResourceResponse&, ResourceLoaderIdentifier, CompletionHandler)>&&); ++ static void setStoppingLoadingDueToProcessSwap(Page*, bool); + + private: + static bool shouldInterceptRequestInternal(const ResourceLoader&); + static bool shouldInterceptResponseInternal(const LocalFrame&, const ResourceResponse&); + static void interceptRequestInternal(ResourceLoader&, Function&&); + static void interceptResponseInternal(const LocalFrame&, const ResourceResponse&, ResourceLoaderIdentifier, CompletionHandler)>&&); ++ static void setStoppingLoadingDueToProcessSwapInternal(Page*, bool); + }; + + inline bool InspectorInstrumentationWebKit::shouldInterceptRequest(const ResourceLoader& loader) +@@ -79,4 +82,10 @@ inline void InspectorInstrumentationWebKit::interceptResponse(const LocalFrame* + interceptResponseInternal(*frame, response, identifier, WTFMove(handler)); + } + ++inline void InspectorInstrumentationWebKit::setStoppingLoadingDueToProcessSwap(Page* page, bool value) ++{ ++ FAST_RETURN_IF_NO_FRONTENDS(void()); ++ setStoppingLoadingDueToProcessSwapInternal(page, value); ++} ++ + } diff --git a/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp b/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp -index a5167242b6b1ee9d6ccfcd81ef86a5729882d3a4..d64c560f86db46786ba47fe55654c140efd1d31b 100644 +index 94492280fc724f299655a5df34492f929d82c57c..af0aafa701a9c697650aad2d86ddcf6b3022dcc5 100644 --- a/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp +++ b/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp -@@ -65,10 +65,14 @@ +@@ -54,6 +54,7 @@ + #include "Cookie.h" + #include "CookieJar.h" + #include "CustomElementRegistry.h" ++#include "DirectoryFileListCreator.h" + #include "DOMEditor.h" + #include "DOMException.h" + #include "DOMPatchSupport.h" +@@ -65,9 +66,14 @@ #include "Event.h" #include "EventListener.h" #include "EventNames.h" +#include "File.h" ++#include +#include "FileList.h" - #include "FrameTree.h" - #include "FullscreenManager.h" +#include "FloatQuad.h" + #include "FrameTree.h" #include "HTMLElement.h" #include "HTMLFrameOwnerElement.h" +#include "HTMLInputElement.h" #include "HTMLMediaElement.h" #include "HTMLNames.h" #include "HTMLScriptElement.h" -@@ -102,12 +106,14 @@ +@@ -102,12 +108,14 @@ #include "Pasteboard.h" #include "PseudoElement.h" #include "RenderGrid.h" @@ -3304,7 +3415,7 @@ index a5167242b6b1ee9d6ccfcd81ef86a5729882d3a4..d64c560f86db46786ba47fe55654c140 #include "StaticNodeList.h" #include "StyleProperties.h" #include "StyleResolver.h" -@@ -145,7 +151,8 @@ using namespace HTMLNames; +@@ -149,7 +157,8 @@ using namespace HTMLNames; static const size_t maxTextSize = 10000; static const UChar horizontalEllipsisUChar[] = { horizontalEllipsis, 0 }; @@ -3314,7 +3425,7 @@ index a5167242b6b1ee9d6ccfcd81ef86a5729882d3a4..d64c560f86db46786ba47fe55654c140 { if (!colorObject) return std::nullopt; -@@ -164,7 +171,7 @@ static std::optional parseColor(RefPtr&& colorObject) +@@ -168,7 +177,7 @@ static std::optional parseColor(RefPtr&& colorObject) static std::optional parseRequiredConfigColor(const String& fieldName, JSON::Object& configObject) { @@ -3323,7 +3434,7 @@ index a5167242b6b1ee9d6ccfcd81ef86a5729882d3a4..d64c560f86db46786ba47fe55654c140 } static Color parseOptionalConfigColor(const String& fieldName, JSON::Object& configObject) -@@ -192,6 +199,20 @@ static bool parseQuad(Ref&& quadArray, FloatQuad* quad) +@@ -195,6 +204,20 @@ static bool parseQuad(Ref&& quadArray, FloatQuad* quad) return true; } @@ -3341,10 +3452,10 @@ index a5167242b6b1ee9d6ccfcd81ef86a5729882d3a4..d64c560f86db46786ba47fe55654c140 + renderer->absoluteQuads(quads); +} + - class RevalidateStyleAttributeTask { - WTF_MAKE_FAST_ALLOCATED; - public: -@@ -466,6 +487,20 @@ Node* InspectorDOMAgent::assertNode(Inspector::Protocol::ErrorString& errorStrin + class RevalidateStyleAttributeTask final : public CanMakeCheckedPtr { + WTF_MAKE_TZONE_ALLOCATED(RevalidateStyleAttributeTask); + WTF_OVERRIDE_DELETE_FOR_CHECKED_PTR(RevalidateStyleAttributeTask); +@@ -475,6 +498,20 @@ Node* InspectorDOMAgent::assertNode(Inspector::Protocol::ErrorString& errorStrin return node.get(); } @@ -3365,7 +3476,7 @@ index a5167242b6b1ee9d6ccfcd81ef86a5729882d3a4..d64c560f86db46786ba47fe55654c140 Document* InspectorDOMAgent::assertDocument(Inspector::Protocol::ErrorString& errorString, Inspector::Protocol::DOM::NodeId nodeId) { RefPtr node = assertNode(errorString, nodeId); -@@ -1540,16 +1575,7 @@ Inspector::Protocol::ErrorStringOr InspectorDOMAgent::highlightNode(std::o +@@ -1593,16 +1630,7 @@ Inspector::Protocol::ErrorStringOr InspectorDOMAgent::highlightNode(std::o Inspector::Protocol::ErrorStringOr InspectorDOMAgent::highlightNode(std::optional&& nodeId, const Inspector::Protocol::Runtime::RemoteObjectId& objectId, Ref&& highlightInspectorObject, RefPtr&& gridOverlayInspectorObject, RefPtr&& flexOverlayInspectorObject, std::optional&& showRulers) { Inspector::Protocol::ErrorString errorString; @@ -3383,7 +3494,7 @@ index a5167242b6b1ee9d6ccfcd81ef86a5729882d3a4..d64c560f86db46786ba47fe55654c140 if (!node) return makeUnexpected(errorString); -@@ -1804,15 +1830,155 @@ Inspector::Protocol::ErrorStringOr InspectorDOMAgent::setInspectedNode(Ins +@@ -1857,15 +1885,159 @@ Inspector::Protocol::ErrorStringOr InspectorDOMAgent::setInspectedNode(Ins return { }; } @@ -3393,13 +3504,17 @@ index a5167242b6b1ee9d6ccfcd81ef86a5729882d3a4..d64c560f86db46786ba47fe55654c140 + return containingView.convertToRootView(point - toFloatSize(containingView.documentScrollPositionRelativeToViewOrigin())); +} + -+static void frameQuadToViewport(LocalFrameView& containingView, FloatQuad& quad, float pageScaleFactor) ++static void frameQuadToViewport(LocalFrameView& containingView, FloatQuad& quad, Page& inspectedPage) +{ ++ float pageScaleFactor = inspectedPage.pageScaleFactor(); ++ auto mainFrame = inspectedPage.localMainFrame(); ++ float scale = pageScaleFactor * mainFrame->pageZoomFactor(); ++ + // Return css (not dip) coordinates by scaling back. -+ quad.setP1(contentsToRootView(containingView, quad.p1()).scaled(1 / pageScaleFactor)); -+ quad.setP2(contentsToRootView(containingView, quad.p2()).scaled(1 / pageScaleFactor)); -+ quad.setP3(contentsToRootView(containingView, quad.p3()).scaled(1 / pageScaleFactor)); -+ quad.setP4(contentsToRootView(containingView, quad.p4()).scaled(1 / pageScaleFactor)); ++ quad.setP1(contentsToRootView(containingView, quad.p1()).scaled(1 / scale)); ++ quad.setP2(contentsToRootView(containingView, quad.p2()).scaled(1 / scale)); ++ quad.setP3(contentsToRootView(containingView, quad.p3()).scaled(1 / scale)); ++ quad.setP4(contentsToRootView(containingView, quad.p4()).scaled(1 / scale)); +} + +static Ref buildObjectForQuad(const FloatQuad& quad) @@ -3457,7 +3572,7 @@ index a5167242b6b1ee9d6ccfcd81ef86a5729882d3a4..d64c560f86db46786ba47fe55654c140 + if (!node) + return makeUnexpected("Node not found"_s); + -+ m_inspectedPage.isolatedUpdateRendering(); ++ m_inspectedPage->isolatedUpdateRendering(); + if (!node->isConnected()) + return makeUnexpected("Node is detached from document"_s); + @@ -3503,7 +3618,7 @@ index a5167242b6b1ee9d6ccfcd81ef86a5729882d3a4..d64c560f86db46786ba47fe55654c140 + return makeUnexpected("Node not found"_s); + + // Ensure quads are up to date. -+ m_inspectedPage.isolatedUpdateRendering(); ++ m_inspectedPage->isolatedUpdateRendering(); + + LocalFrameView* containingView = node->document().view(); + if (!containingView) @@ -3512,7 +3627,7 @@ index a5167242b6b1ee9d6ccfcd81ef86a5729882d3a4..d64c560f86db46786ba47fe55654c140 + Vector quads; + CollectQuads(node, quads); + for (auto& quad : quads) -+ frameQuadToViewport(*containingView, quad, m_inspectedPage.pageScaleFactor()); ++ frameQuadToViewport(*containingView, quad, m_inspectedPage.get()); + return buildArrayOfQuads(quads); +} + @@ -3542,7 +3657,7 @@ index a5167242b6b1ee9d6ccfcd81ef86a5729882d3a4..d64c560f86db46786ba47fe55654c140 if (!object) return makeUnexpected("Missing injected script for given nodeId"_s); -@@ -3061,7 +3227,7 @@ Inspector::Protocol::ErrorStringOr InspectorDO +@@ -3131,7 +3303,7 @@ Inspector::Protocol::ErrorStringOr InspectorDO return makeUnexpected("Missing node for given path"_s); } @@ -3551,7 +3666,7 @@ index a5167242b6b1ee9d6ccfcd81ef86a5729882d3a4..d64c560f86db46786ba47fe55654c140 { Document* document = &node->document(); if (auto* templateHost = document->templateDocumentHost()) -@@ -3070,12 +3236,18 @@ RefPtr InspectorDOMAgent::resolveNod +@@ -3140,12 +3312,18 @@ RefPtr InspectorDOMAgent::resolveNod if (!frame) return nullptr; @@ -3573,69 +3688,65 @@ index a5167242b6b1ee9d6ccfcd81ef86a5729882d3a4..d64c560f86db46786ba47fe55654c140 } Node* InspectorDOMAgent::scriptValueAsNode(JSC::JSValue value) -@@ -3183,4 +3355,57 @@ Inspector::Protocol::ErrorStringOr> In +@@ -3291,4 +3469,53 @@ Inspector::Protocol::ErrorStringOr> In #endif } -+Protocol::ErrorStringOr InspectorDOMAgent::setInputFiles(const String& objectId, RefPtr&& files, RefPtr&& paths) { ++void InspectorDOMAgent::setInputFiles(const String& objectId, Ref&& paths, Ref&& callback) { + InjectedScript injectedScript = m_injectedScriptManager.injectedScriptForObjectId(objectId); -+ if (injectedScript.hasNoValue()) -+ return makeUnexpected("Can not find element's context for given id"_s); ++ if (injectedScript.hasNoValue()) { ++ callback->sendFailure("Can not find element's context for given id"_s); ++ return; ++ } + + Node* node = scriptValueAsNode(injectedScript.findObjectById(objectId)); -+ if (!node) -+ return makeUnexpected("Can not find element for given id"_s); ++ if (!node) { ++ callback->sendFailure("Can not find element for given id"_s); ++ return; ++ } + -+ if (node->nodeType() != Node::ELEMENT_NODE || node->nodeName() != "INPUT"_s) -+ return makeUnexpected("Not an input node"_s); -+ -+ if (!(bool(files) ^ bool(paths))) -+ return makeUnexpected("Exactly one of files and paths should be specified"_s); ++ if (node->nodeType() != Node::ELEMENT_NODE || node->nodeName() != "INPUT"_s) { ++ callback->sendFailure("Not an input node"_s); ++ return; ++ } + + HTMLInputElement* element = static_cast(node); + Vector> fileObjects; -+ if (files) { -+ for (unsigned i = 0; i < files->length(); ++i) { -+ RefPtr item = files->get(i); -+ RefPtr obj = item->asObject(); -+ if (!obj) -+ return makeUnexpected("Invalid file payload format"_s); -+ -+ String name; -+ String type; -+ String data; -+ if (!obj->getString("name"_s, name) || !obj->getString("type"_s, type) || !obj->getString("data"_s, data)) -+ return makeUnexpected("Invalid file payload format"_s); -+ -+ std::optional> buffer = base64Decode(data); -+ if (!buffer) -+ return makeUnexpected("Unable to decode given content"_s); -+ -+ ScriptExecutionContext* context = element->scriptExecutionContext(); -+ fileObjects.append(File::create(context, Blob::create(context, WTFMove(*buffer), type), name)); ++ if (element->hasAttributeWithoutSynchronization(webkitdirectoryAttr)) { ++ auto directoryFileListCreator = DirectoryFileListCreator::create([element = RefPtr { element }, callback = WTFMove(callback)](Ref&& fileList) mutable { ++ ASSERT(isMainThread()); ++ element->setFiles(WTFMove(fileList)); ++ callback->sendSuccess(); ++ }); ++ Vector fileChooserFiles; ++ for (size_t i = 0; i < paths->length(); ++i) { ++ fileChooserFiles.append(FileChooserFileInfo { paths->get(i)->asString(), nullString(), { } }); + } ++ directoryFileListCreator->start(m_document.get(), fileChooserFiles); + } else { + for (unsigned i = 0; i < paths->length(); ++i) { + RefPtr item = paths->get(i); + String path = item->asString(); -+ if (path.isEmpty()) -+ return makeUnexpected("Invalid file path"_s); ++ if (path.isEmpty()) { ++ callback->sendFailure("Invalid file path"_s); ++ return; ++ } + + ScriptExecutionContext* context = element->scriptExecutionContext(); + fileObjects.append(File::create(context, path)); + } ++ RefPtr fileList = FileList::create(WTFMove(fileObjects)); ++ element->setFiles(WTFMove(fileList)); ++ callback->sendSuccess(); + } -+ RefPtr fileList = FileList::create(WTFMove(fileObjects)); -+ element->setFiles(WTFMove(fileList)); -+ return { }; +} + } // namespace WebCore diff --git a/Source/WebCore/inspector/agents/InspectorDOMAgent.h b/Source/WebCore/inspector/agents/InspectorDOMAgent.h -index 5f1dba2bc4d5c2f113a88dcc9ba479679cb79233..5616c853a99b5fdb38306a804cc0e91799ac12b1 100644 +index 3496e0037572430b993ea91704501a742dd15627..9eb0ce0094fdb2ab9ca94bb5cddb082f201bf4cf 100644 --- a/Source/WebCore/inspector/agents/InspectorDOMAgent.h +++ b/Source/WebCore/inspector/agents/InspectorDOMAgent.h -@@ -57,6 +57,7 @@ namespace WebCore { +@@ -59,6 +59,7 @@ namespace WebCore { class AXCoreObject; class CharacterData; @@ -3643,7 +3754,7 @@ index 5f1dba2bc4d5c2f113a88dcc9ba479679cb79233..5616c853a99b5fdb38306a804cc0e917 class DOMEditor; class Document; class Element; -@@ -91,6 +92,7 @@ public: +@@ -95,6 +96,7 @@ public: static String toErrorString(Exception&&); static String documentURLString(Document*); @@ -3651,7 +3762,7 @@ index 5f1dba2bc4d5c2f113a88dcc9ba479679cb79233..5616c853a99b5fdb38306a804cc0e917 // We represent embedded doms as a part of the same hierarchy. Hence we treat children of frame owners differently. // We also skip whitespace text nodes conditionally. Following methods encapsulate these specifics. -@@ -134,7 +136,7 @@ public: +@@ -140,7 +142,7 @@ public: Inspector::Protocol::ErrorStringOr> performSearch(const String& query, RefPtr&& nodeIds, std::optional&& caseSensitive); Inspector::Protocol::ErrorStringOr>> getSearchResults(const String& searchId, int fromIndex, int toIndex); Inspector::Protocol::ErrorStringOr discardSearchResults(const String& searchId); @@ -3660,18 +3771,18 @@ index 5f1dba2bc4d5c2f113a88dcc9ba479679cb79233..5616c853a99b5fdb38306a804cc0e917 Inspector::Protocol::ErrorStringOr>> getAttributes(Inspector::Protocol::DOM::NodeId); #if PLATFORM(IOS_FAMILY) Inspector::Protocol::ErrorStringOr setInspectModeEnabled(bool, RefPtr&& highlightConfig, RefPtr&& gridOverlayConfig, RefPtr&& flexOverlayConfig); -@@ -171,6 +173,10 @@ public: +@@ -177,6 +179,10 @@ public: Inspector::Protocol::ErrorStringOr setInspectedNode(Inspector::Protocol::DOM::NodeId); Inspector::Protocol::ErrorStringOr setAllowEditingUserAgentShadowTrees(bool); Inspector::Protocol::ErrorStringOr> getMediaStats(Inspector::Protocol::DOM::NodeId); + Inspector::Protocol::ErrorStringOr> describeNode(const String& objectId); + Inspector::Protocol::ErrorStringOr scrollIntoViewIfNeeded(const String& objectId, RefPtr&& rect); + Inspector::Protocol::ErrorStringOr>> getContentQuads(const String& objectId); -+ Inspector::Protocol::ErrorStringOr setInputFiles(const String& objectId, RefPtr&& files, RefPtr&& paths); ++ void setInputFiles(const String& objectId, Ref&& paths, Ref&& callback); // InspectorInstrumentation Inspector::Protocol::DOM::NodeId identifierForNode(Node&); -@@ -212,7 +218,7 @@ public: +@@ -218,7 +224,7 @@ public: Node* nodeForId(Inspector::Protocol::DOM::NodeId); Inspector::Protocol::DOM::NodeId boundNodeId(const Node*); @@ -3680,7 +3791,7 @@ index 5f1dba2bc4d5c2f113a88dcc9ba479679cb79233..5616c853a99b5fdb38306a804cc0e917 bool handleMousePress(); void mouseDidMoveOverElement(const HitTestResult&, OptionSet); void inspect(Node*); -@@ -224,12 +230,15 @@ public: +@@ -230,12 +236,15 @@ public: void reset(); Node* assertNode(Inspector::Protocol::ErrorString&, Inspector::Protocol::DOM::NodeId); @@ -3696,7 +3807,7 @@ index 5f1dba2bc4d5c2f113a88dcc9ba479679cb79233..5616c853a99b5fdb38306a804cc0e917 private: #if ENABLE(VIDEO) void mediaMetricsTimerFired(); -@@ -259,7 +268,6 @@ private: +@@ -265,7 +274,6 @@ private: void processAccessibilityChildren(AXCoreObject&, JSON::ArrayOf&); Node* nodeForPath(const String& path); @@ -3705,18 +3816,18 @@ index 5f1dba2bc4d5c2f113a88dcc9ba479679cb79233..5616c853a99b5fdb38306a804cc0e917 void discardBindings(); diff --git a/Source/WebCore/inspector/agents/InspectorNetworkAgent.cpp b/Source/WebCore/inspector/agents/InspectorNetworkAgent.cpp -index 00dba5735f2f682d00f7e17ef2abddf85a4c7f90..4c2ca023d6ad04a3ccda68d5f707df8065d50419 100644 +index f3a0bdf189aed455ceb84f4023c2dbfda8e5dc16..25d54fc33be2ccd42565cb7ddf879344ab8aa3f2 100644 --- a/Source/WebCore/inspector/agents/InspectorNetworkAgent.cpp +++ b/Source/WebCore/inspector/agents/InspectorNetworkAgent.cpp -@@ -59,6 +59,7 @@ +@@ -58,6 +58,7 @@ + #include "LocalFrame.h" #include "MIMETypeRegistry.h" #include "MemoryCache.h" - #include "NetworkResourcesData.h" +#include "NetworkStateNotifier.h" #include "Page.h" #include "PlatformStrategies.h" #include "ProgressTracker.h" -@@ -339,8 +340,8 @@ static Ref buildObjectForResourceRequest( +@@ -344,8 +345,8 @@ static Ref buildObjectForResourceRequest( .release(); if (request.httpBody() && !request.httpBody()->isEmpty()) { @@ -3727,7 +3838,7 @@ index 00dba5735f2f682d00f7e17ef2abddf85a4c7f90..4c2ca023d6ad04a3ccda68d5f707df80 } if (resourceLoader) { -@@ -393,6 +394,8 @@ RefPtr InspectorNetworkAgent::buildObjec +@@ -398,6 +399,8 @@ RefPtr InspectorNetworkAgent::buildObjec .setSource(responseSource(response.source())) .release(); @@ -3736,7 +3847,25 @@ index 00dba5735f2f682d00f7e17ef2abddf85a4c7f90..4c2ca023d6ad04a3ccda68d5f707df80 if (resourceLoader) { auto* metrics = response.deprecatedNetworkLoadMetricsOrNull(); responseObject->setTiming(buildObjectForTiming(metrics ? *metrics : NetworkLoadMetrics::emptyMetrics(), *resourceLoader)); -@@ -960,6 +963,7 @@ void InspectorNetworkAgent::continuePendingResponses() +@@ -684,6 +687,9 @@ void InspectorNetworkAgent::didFailLoading(ResourceLoaderIdentifier identifier, + String requestId = IdentifiersFactory::requestId(identifier.toUInt64()); + + if (loader && m_resourcesData->resourceType(requestId) == InspectorPageAgent::DocumentResource) { ++ if (m_stoppingLoadingDueToProcessSwap) ++ return; ++ + auto* frame = loader->frame(); + if (frame && frame->loader().documentLoader() && frame->document()) { + m_resourcesData->addResourceSharedBuffer(requestId, +@@ -913,6 +919,7 @@ Inspector::Protocol::ErrorStringOr InspectorNetworkAgent::disable() + m_instrumentingAgents.setEnabledNetworkAgent(nullptr); + m_resourcesData->clear(); + m_extraRequestHeaders.clear(); ++ m_stoppingLoadingDueToProcessSwap = false; + + continuePendingRequests(); + continuePendingResponses(); +@@ -958,6 +965,7 @@ void InspectorNetworkAgent::continuePendingResponses() Inspector::Protocol::ErrorStringOr InspectorNetworkAgent::setExtraHTTPHeaders(Ref&& headers) { @@ -3744,7 +3873,19 @@ index 00dba5735f2f682d00f7e17ef2abddf85a4c7f90..4c2ca023d6ad04a3ccda68d5f707df80 for (auto& entry : headers.get()) { auto stringValue = entry.value->asString(); if (!!stringValue) -@@ -1238,6 +1242,9 @@ Inspector::Protocol::ErrorStringOr InspectorNetworkAgent::interceptWithReq +@@ -1207,6 +1215,11 @@ void InspectorNetworkAgent::interceptResponse(const ResourceResponse& response, + m_frontendDispatcher->responseIntercepted(requestId, resourceResponse.releaseNonNull()); + } + ++void InspectorNetworkAgent::setStoppingLoadingDueToProcessSwap(bool stopping) ++{ ++ m_stoppingLoadingDueToProcessSwap = stopping; ++} ++ + Inspector::Protocol::ErrorStringOr InspectorNetworkAgent::interceptContinue(const Inspector::Protocol::Network::RequestId& requestId, Inspector::Protocol::Network::NetworkStage networkStage) + { + switch (networkStage) { +@@ -1236,6 +1249,9 @@ Inspector::Protocol::ErrorStringOr InspectorNetworkAgent::interceptWithReq return makeUnexpected("Missing pending intercept request for given requestId"_s); auto& loader = *pendingRequest->m_loader; @@ -3754,7 +3895,7 @@ index 00dba5735f2f682d00f7e17ef2abddf85a4c7f90..4c2ca023d6ad04a3ccda68d5f707df80 ResourceRequest request = loader.request(); if (!!url) request.setURL(URL({ }, url)); -@@ -1333,14 +1340,23 @@ Inspector::Protocol::ErrorStringOr InspectorNetworkAgent::interceptRequest +@@ -1331,13 +1347,22 @@ Inspector::Protocol::ErrorStringOr InspectorNetworkAgent::interceptRequest response.setHTTPStatusCode(status); response.setHTTPStatusText(String { statusText }); HTTPHeaderMap explicitHeaders; @@ -3770,17 +3911,15 @@ index 00dba5735f2f682d00f7e17ef2abddf85a4c7f90..4c2ca023d6ad04a3ccda68d5f707df80 } response.setHTTPHeaderFields(WTFMove(explicitHeaders)); response.setHTTPHeaderField(HTTPHeaderName::ContentType, response.mimeType()); -- loader->didReceiveResponse(response, [loader, buffer = data.releaseNonNull()]() { + + auto* frame = loader->frame(); + if (!setCookieValue.isEmpty() && frame && frame->page()) + frame->page()->cookieJar().setCookieFromResponse(*loader.get(), setCookieValue); + -+ loader->didReceiveResponse(response, [loader, buffer = data.releaseNonNull()]() mutable { + loader->didReceiveResponse(WTFMove(response), [loader, buffer = data.releaseNonNull()]() { if (loader->reachedTerminalState()) return; - -@@ -1403,6 +1419,12 @@ Inspector::Protocol::ErrorStringOr InspectorNetworkAgent::setEmulatedCondi +@@ -1401,6 +1426,12 @@ Inspector::Protocol::ErrorStringOr InspectorNetworkAgent::setEmulatedCondi #endif // ENABLE(INSPECTOR_NETWORK_THROTTLING) @@ -3794,19 +3933,19 @@ index 00dba5735f2f682d00f7e17ef2abddf85a4c7f90..4c2ca023d6ad04a3ccda68d5f707df80 { return startsWithLettersIgnoringASCIICase(mimeType, "text/"_s) diff --git a/Source/WebCore/inspector/agents/InspectorNetworkAgent.h b/Source/WebCore/inspector/agents/InspectorNetworkAgent.h -index dc7e574ee6e9256a1f75ea838d20ca7f5e9190de..5dd4464256e0f5d652fa51fd611286ddc1da6f5c 100644 +index de6b2dd844943074c5a383c7b9b8ccba1c96419a..7a3404f2380b5e62f1c0523a70f8ef442014759d 100644 --- a/Source/WebCore/inspector/agents/InspectorNetworkAgent.h +++ b/Source/WebCore/inspector/agents/InspectorNetworkAgent.h -@@ -34,6 +34,8 @@ - #include "InspectorInstrumentation.h" +@@ -35,6 +35,8 @@ #include "InspectorPageAgent.h" #include "InspectorWebAgentBase.h" + #include "NetworkResourcesData.h" +#include "ResourceError.h" +#include "SharedBuffer.h" #include "WebSocket.h" + #include #include - #include -@@ -101,6 +103,7 @@ public: +@@ -104,6 +106,7 @@ public: #if ENABLE(INSPECTOR_NETWORK_THROTTLING) Inspector::Protocol::ErrorStringOr setEmulatedConditions(std::optional&& bytesPerSecondLimit) final; #endif @@ -3814,14 +3953,31 @@ index dc7e574ee6e9256a1f75ea838d20ca7f5e9190de..5dd4464256e0f5d652fa51fd611286dd // InspectorInstrumentation void willRecalculateStyle(); +@@ -135,6 +138,7 @@ public: + bool shouldInterceptResponse(const ResourceResponse&); + void interceptResponse(const ResourceResponse&, ResourceLoaderIdentifier, CompletionHandler)>&&); + void interceptRequest(ResourceLoader&, Function&&); ++ void setStoppingLoadingDueToProcessSwap(bool); + + void searchOtherRequests(const JSC::Yarr::RegularExpression&, Ref>&); + void searchInRequest(Inspector::Protocol::ErrorString&, const Inspector::Protocol::Network::RequestId&, const String& query, bool caseSensitive, bool isRegex, RefPtr>&); +@@ -275,6 +279,7 @@ private: + bool m_enabled { false }; + bool m_loadingXHRSynchronously { false }; + bool m_interceptionEnabled { false }; ++ bool m_stoppingLoadingDueToProcessSwap { false }; + }; + + } // namespace WebCore diff --git a/Source/WebCore/inspector/agents/InspectorPageAgent.cpp b/Source/WebCore/inspector/agents/InspectorPageAgent.cpp -index 5329fd0a2c24031a74d05d7c6c342a5f8398eaae..a64e486220e4fc8e37c34856fce8c3d8dea87401 100644 +index cc649f41559f905102d7a8785190f3157d3e6dea..ee7fee8a4ac224d27dd40d04be0803ff89720232 100644 --- a/Source/WebCore/inspector/agents/InspectorPageAgent.cpp +++ b/Source/WebCore/inspector/agents/InspectorPageAgent.cpp -@@ -32,19 +32,26 @@ +@@ -32,19 +32,27 @@ #include "config.h" #include "InspectorPageAgent.h" ++#include "AXCoreObject.h" +#include "AXObjectCache.h" +#include "BackForwardController.h" #include "CachedResource.h" @@ -3845,22 +4001,22 @@ index 5329fd0a2c24031a74d05d7c6c342a5f8398eaae..a64e486220e4fc8e37c34856fce8c3d8 #include "HTMLNames.h" #include "ImageBuffer.h" #include "InspectorClient.h" -@@ -55,10 +62,13 @@ - #include "LocalFrame.h" - #include "LocalFrameView.h" +@@ -57,24 +65,38 @@ #include "MIMETypeRegistry.h" --#include "MemoryCache.h" + #include "MemoryCache.h" #include "Page.h" +#include "PageRuntimeAgent.h" +#include "PlatformScreen.h" - #include "RenderObject.h" + #include "RenderObjectInlines.h" #include "RenderTheme.h" +#include "DeprecatedGlobalSettings.h" +#include "SimpleRange.h" #include "ScriptController.h" #include "ScriptSourceCode.h" ++#include "ScrollingCoordinator.h" #include "SecurityOrigin.h" -@@ -66,11 +76,18 @@ + #include "Settings.h" + #include "ShouldPartitionCookie.h" #include "StyleScope.h" #include "Theme.h" #include @@ -3874,29 +4030,29 @@ index 5329fd0a2c24031a74d05d7c6c342a5f8398eaae..a64e486220e4fc8e37c34856fce8c3d8 +#include #include +#include ++#include +#include +#include #include + #include #include ++#include #include -@@ -83,11 +100,15 @@ - #include "LegacyWebArchive.h" - #endif -- - namespace WebCore { + #if ENABLE(APPLICATION_MANIFEST) +@@ -96,6 +118,11 @@ using namespace Inspector; - using namespace Inspector; + WTF_MAKE_TZONE_ALLOCATED_IMPL(InspectorPageAgent); -+static HashMap>& createdUserWorlds() { -+ static NeverDestroyed>> nameToWorld; ++static UncheckedKeyHashMap>& createdUserWorlds() { ++ static NeverDestroyed>> nameToWorld; + return nameToWorld; +} + static bool decodeBuffer(std::span buffer, const String& textEncodingName, String* result) { if (buffer.data()) { -@@ -334,6 +355,7 @@ InspectorPageAgent::InspectorPageAgent(PageAgentContext& context, InspectorClien +@@ -348,6 +375,7 @@ InspectorPageAgent::InspectorPageAgent(PageAgentContext& context, InspectorClien , m_frontendDispatcher(makeUnique(context.frontendRouter)) , m_backendDispatcher(Inspector::PageBackendDispatcher::create(context.backendDispatcher, this)) , m_inspectedPage(context.inspectedPage) @@ -3904,7 +4060,7 @@ index 5329fd0a2c24031a74d05d7c6c342a5f8398eaae..a64e486220e4fc8e37c34856fce8c3d8 , m_client(client) , m_overlay(overlay) { -@@ -363,12 +385,20 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::enable() +@@ -377,12 +405,20 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::enable() defaultUserPreferencesDidChange(); @@ -3925,13 +4081,13 @@ index 5329fd0a2c24031a74d05d7c6c342a5f8398eaae..a64e486220e4fc8e37c34856fce8c3d8 setShowPaintRects(false); #if !PLATFORM(IOS_FAMILY) -@@ -420,6 +450,22 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::reload(std::optiona +@@ -435,6 +471,22 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::reload(std::optiona return { }; } +Inspector::Protocol::ErrorStringOr InspectorPageAgent::goBack() +{ -+ if (!m_inspectedPage.backForward().goBack()) ++ if (!m_inspectedPage->backForward().goBack()) + return makeUnexpected("Failed to go back"_s); + + return { }; @@ -3939,7 +4095,7 @@ index 5329fd0a2c24031a74d05d7c6c342a5f8398eaae..a64e486220e4fc8e37c34856fce8c3d8 + +Inspector::Protocol::ErrorStringOr InspectorPageAgent::goForward() +{ -+ if (!m_inspectedPage.backForward().goForward()) ++ if (!m_inspectedPage->backForward().goForward()) + return makeUnexpected("Failed to go forward"_s); + + return { }; @@ -3947,8 +4103,8 @@ index 5329fd0a2c24031a74d05d7c6c342a5f8398eaae..a64e486220e4fc8e37c34856fce8c3d8 + Inspector::Protocol::ErrorStringOr InspectorPageAgent::navigate(const String& url) { - auto* localMainFrame = dynamicDowncast(m_inspectedPage.mainFrame()); -@@ -443,6 +489,13 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::overrideUserAgent(c + RefPtr localMainFrame = m_inspectedPage->localMainFrame(); +@@ -461,6 +513,13 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::overrideUserAgent(c return { }; } @@ -3961,8 +4117,8 @@ index 5329fd0a2c24031a74d05d7c6c342a5f8398eaae..a64e486220e4fc8e37c34856fce8c3d8 + Inspector::Protocol::ErrorStringOr InspectorPageAgent::overrideSetting(Inspector::Protocol::Page::Setting setting, std::optional&& value) { - auto& inspectedPageSettings = m_inspectedPage.settings(); -@@ -456,6 +509,12 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::overrideSetting(Ins + auto& inspectedPageSettings = m_inspectedPage->settings(); +@@ -474,6 +533,12 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::overrideSetting(Ins inspectedPageSettings.setAuthorAndUserStylesEnabledInspectorOverride(value); return { }; @@ -3975,8 +4131,8 @@ index 5329fd0a2c24031a74d05d7c6c342a5f8398eaae..a64e486220e4fc8e37c34856fce8c3d8 case Inspector::Protocol::Page::Setting::ICECandidateFilteringEnabled: inspectedPageSettings.setICECandidateFilteringEnabledInspectorOverride(value); return { }; -@@ -481,6 +540,38 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::overrideSetting(Ins - inspectedPageSettings.setNeedsSiteSpecificQuirksInspectorOverride(value); +@@ -500,6 +565,39 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::overrideSetting(Ins + m_client->setDeveloperPreferenceOverride(InspectorClient::DeveloperPreference::NeedsSiteSpecificQuirks, value); return { }; +#if ENABLE(NOTIFICATIONS) @@ -3992,17 +4148,18 @@ index 5329fd0a2c24031a74d05d7c6c342a5f8398eaae..a64e486220e4fc8e37c34856fce8c3d8 +#endif + + case Protocol::Page::Setting::InputTypeMonthEnabled: -+// Playwright client sends it even if it's not supported. -+#if ENABLE(INPUT_TYPE_MONTH) + inspectedPageSettings.setInputTypeMonthEnabled(value.value_or(false)); -+#endif + return { }; + + case Protocol::Page::Setting::InputTypeWeekEnabled: -+// Playwright client sends it even if it's not supported. -+#if ENABLE(INPUT_TYPE_WEEK) + inspectedPageSettings.setInputTypeWeekEnabled(value.value_or(false)); -+#endif ++ return { }; ++ ++ case Protocol::Page::Setting::FixedBackgroundsPaintRelativeToDocument: ++ // Enable this setting similar to iOS to ensure scrolling works with ++ // `background-attachment: fixed`. ++ // See https://github.com/microsoft/playwright/issues/31551. ++ inspectedPageSettings.setFixedBackgroundsPaintRelativeToDocument(value.value_or(false)); + return { }; + +#if ENABLE(POINTER_LOCK) @@ -4014,7 +4171,7 @@ index 5329fd0a2c24031a74d05d7c6c342a5f8398eaae..a64e486220e4fc8e37c34856fce8c3d8 case Inspector::Protocol::Page::Setting::ScriptEnabled: inspectedPageSettings.setScriptEnabledInspectorOverride(value); return { }; -@@ -493,6 +584,12 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::overrideSetting(Ins +@@ -512,6 +610,12 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::overrideSetting(Ins inspectedPageSettings.setShowRepaintCounterInspectorOverride(value); return { }; @@ -4027,7 +4184,7 @@ index 5329fd0a2c24031a74d05d7c6c342a5f8398eaae..a64e486220e4fc8e37c34856fce8c3d8 case Inspector::Protocol::Page::Setting::WebSecurityEnabled: inspectedPageSettings.setWebSecurityEnabledInspectorOverride(value); return { }; -@@ -893,15 +990,16 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::setShowPaintRects(b +@@ -920,15 +1024,16 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::setShowPaintRects(b return { }; } @@ -4049,27 +4206,31 @@ index 5329fd0a2c24031a74d05d7c6c342a5f8398eaae..a64e486220e4fc8e37c34856fce8c3d8 } void InspectorPageAgent::frameNavigated(LocalFrame& frame) -@@ -909,13 +1007,25 @@ void InspectorPageAgent::frameNavigated(LocalFrame& frame) +@@ -936,13 +1041,29 @@ void InspectorPageAgent::frameNavigated(LocalFrame& frame) m_frontendDispatcher->frameNavigated(buildObjectForFrame(&frame)); } -+String InspectorPageAgent::makeFrameID(ProcessIdentifier processID, FrameIdentifier frameID) ++String InspectorPageAgent::serializeFrameID(FrameIdentifier frameID) +{ -+ return makeString(processID.toUInt64(), ".", frameID.object().toUInt64()); ++ return makeString(frameID.toUInt64()); +} + -+static String globalIDForFrame(Frame& frame) ++std::optional InspectorPageAgent::parseFrameID(String frameID) +{ -+ // TODO(playwright): for OOPIF we have to use id of the web process where the frame is hosted. -+ // Working at the moment because OOPIF is diabled. -+ return InspectorPageAgent::makeFrameID(Process::identifier(), frame.frameID()); ++ if (!frameID.containsOnlyASCII()) ++ return std::nullopt; ++ ++WTF_ALLOW_UNSAFE_BUFFER_USAGE_BEGIN ++ uint64_t frameIDNumber = strtoull(frameID.ascii().data(), 0, 10); ++WTF_ALLOW_UNSAFE_BUFFER_USAGE_END ++ return WebCore::FrameIdentifier(frameIDNumber); +} + void InspectorPageAgent::frameDetached(LocalFrame& frame) { - auto identifier = m_frameToIdentifier.take(frame); - if (identifier.isNull()) -+ String identifier = globalIDForFrame(frame); ++ String identifier = serializeFrameID(frame.frameID()); + if (!m_identifierToFrame.take(identifier)) return; + @@ -4078,7 +4239,7 @@ index 5329fd0a2c24031a74d05d7c6c342a5f8398eaae..a64e486220e4fc8e37c34856fce8c3d8 } Frame* InspectorPageAgent::frameForId(const Inspector::Protocol::Network::FrameId& frameId) -@@ -927,20 +1037,17 @@ String InspectorPageAgent::frameId(Frame* frame) +@@ -954,20 +1075,21 @@ String InspectorPageAgent::frameId(Frame* frame) { if (!frame) return emptyString(); @@ -4087,7 +4248,7 @@ index 5329fd0a2c24031a74d05d7c6c342a5f8398eaae..a64e486220e4fc8e37c34856fce8c3d8 - m_identifierToFrame.set(identifier, frame); - return identifier; - }).iterator->value; -+ String identifier = globalIDForFrame(*frame); ++ String identifier = serializeFrameID(frame->frameID()); + m_identifierToFrame.set(identifier, frame); + return identifier; } @@ -4100,11 +4261,15 @@ index 5329fd0a2c24031a74d05d7c6c342a5f8398eaae..a64e486220e4fc8e37c34856fce8c3d8 - return IdentifiersFactory::createIdentifier(); - }).iterator->value; + -+ return String::number(loader->navigationID()); ++ auto navigationID = loader->navigationID(); ++ if (!navigationID) ++ return emptyString(); ++ ++ return String::number(navigationID->toUInt64()); } LocalFrame* InspectorPageAgent::assertFrame(Inspector::Protocol::ErrorString& errorString, const Inspector::Protocol::Network::FrameId& frameId) -@@ -951,11 +1058,6 @@ LocalFrame* InspectorPageAgent::assertFrame(Inspector::Protocol::ErrorString& er +@@ -978,11 +1100,6 @@ LocalFrame* InspectorPageAgent::assertFrame(Inspector::Protocol::ErrorString& er return frame; } @@ -4116,7 +4281,7 @@ index 5329fd0a2c24031a74d05d7c6c342a5f8398eaae..a64e486220e4fc8e37c34856fce8c3d8 void InspectorPageAgent::frameStartedLoading(LocalFrame& frame) { m_frontendDispatcher->frameStartedLoading(frameId(&frame)); -@@ -966,9 +1068,9 @@ void InspectorPageAgent::frameStoppedLoading(LocalFrame& frame) +@@ -993,9 +1110,9 @@ void InspectorPageAgent::frameStoppedLoading(LocalFrame& frame) m_frontendDispatcher->frameStoppedLoading(frameId(&frame)); } @@ -4128,7 +4293,7 @@ index 5329fd0a2c24031a74d05d7c6c342a5f8398eaae..a64e486220e4fc8e37c34856fce8c3d8 } void InspectorPageAgent::frameClearedScheduledNavigation(Frame& frame) -@@ -1015,6 +1117,12 @@ void InspectorPageAgent::defaultUserPreferencesDidChange() +@@ -1042,6 +1159,12 @@ void InspectorPageAgent::defaultUserPreferencesDidChange() m_frontendDispatcher->defaultUserPreferencesDidChange(WTFMove(defaultUserPreferences)); } @@ -4138,10 +4303,10 @@ index 5329fd0a2c24031a74d05d7c6c342a5f8398eaae..a64e486220e4fc8e37c34856fce8c3d8 + m_frontendDispatcher->navigatedWithinDocument(frameId(&frame), url); +} + - #if ENABLE(DARK_MODE_CSS) || HAVE(OS_DARK_MODE_SUPPORT) + #if ENABLE(DARK_MODE_CSS) void InspectorPageAgent::defaultAppearanceDidChange() { -@@ -1028,6 +1136,9 @@ void InspectorPageAgent::didClearWindowObjectInWorld(LocalFrame& frame, DOMWrapp +@@ -1055,6 +1178,9 @@ void InspectorPageAgent::didClearWindowObjectInWorld(LocalFrame& frame, DOMWrapp return; if (m_bootstrapScript.isEmpty()) @@ -4151,8 +4316,8 @@ index 5329fd0a2c24031a74d05d7c6c342a5f8398eaae..a64e486220e4fc8e37c34856fce8c3d8 return; frame.script().evaluateIgnoringException(ScriptSourceCode(m_bootstrapScript, JSC::SourceTaintedOrigin::Untainted, URL { "web-inspector://bootstrap.js"_str })); -@@ -1075,6 +1186,51 @@ void InspectorPageAgent::didRecalculateStyle() - m_overlay->update(); +@@ -1102,6 +1228,51 @@ void InspectorPageAgent::didRecalculateStyle() + protectedOverlay()->update(); } +void InspectorPageAgent::runOpenPanel(HTMLInputElement* element, bool* intercept) @@ -4203,7 +4368,7 @@ index 5329fd0a2c24031a74d05d7c6c342a5f8398eaae..a64e486220e4fc8e37c34856fce8c3d8 Ref InspectorPageAgent::buildObjectForFrame(LocalFrame* frame) { ASSERT_ARG(frame, frame); -@@ -1172,6 +1328,12 @@ void InspectorPageAgent::applyUserAgentOverride(String& userAgent) +@@ -1195,6 +1366,12 @@ void InspectorPageAgent::applyUserAgentOverride(String& userAgent) userAgent = m_userAgentOverride; } @@ -4216,38 +4381,38 @@ index 5329fd0a2c24031a74d05d7c6c342a5f8398eaae..a64e486220e4fc8e37c34856fce8c3d8 void InspectorPageAgent::applyEmulatedMedia(AtomString& media) { if (!m_emulatedMedia.isEmpty()) -@@ -1199,11 +1361,13 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::snapshotNode(Insp +@@ -1222,11 +1399,13 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::snapshotNode(Insp return snapshot->toDataURL("image/png"_s, std::nullopt, PreserveResolution::Yes); } -Inspector::Protocol::ErrorStringOr InspectorPageAgent::snapshotRect(int x, int y, int width, int height, Inspector::Protocol::Page::CoordinateSystem coordinateSystem) +Inspector::Protocol::ErrorStringOr InspectorPageAgent::snapshotRect(int x, int y, int width, int height, Inspector::Protocol::Page::CoordinateSystem coordinateSystem, std::optional&& omitDeviceScaleFactor) { - SnapshotOptions options { { }, PixelFormat::BGRA8, DestinationColorSpace::SRGB() }; + SnapshotOptions options { { }, ImageBufferPixelFormat::BGRA8, DestinationColorSpace::SRGB() }; if (coordinateSystem == Inspector::Protocol::Page::CoordinateSystem::Viewport) options.flags.add(SnapshotFlags::InViewCoordinates); + if (omitDeviceScaleFactor.has_value() && *omitDeviceScaleFactor) + options.flags.add(SnapshotFlags::OmitDeviceScaleFactor); IntRect rectangle(x, y, width, height); - auto* localMainFrame = dynamicDowncast(m_inspectedPage.mainFrame()); -@@ -1217,6 +1381,43 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::snapshotRect(int + RefPtr localMainFrame = m_inspectedPage->localMainFrame(); +@@ -1240,6 +1419,43 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::snapshotRect(int return snapshot->toDataURL("image/png"_s, std::nullopt, PreserveResolution::Yes); } +Protocol::ErrorStringOr InspectorPageAgent::setForcedColors(std::optional&& forcedColors) +{ + if (!forcedColors) { -+ m_inspectedPage.setUseForcedColorsOverride(std::nullopt); ++ m_inspectedPage->setUseForcedColorsOverride(std::nullopt); + return { }; + } + + switch (*forcedColors) { + case Protocol::Page::ForcedColors::Active: -+ m_inspectedPage.setUseForcedColorsOverride(true); ++ m_inspectedPage->setUseForcedColorsOverride(true); + return { }; + case Protocol::Page::ForcedColors::None: -+ m_inspectedPage.setUseForcedColorsOverride(false); ++ m_inspectedPage->setUseForcedColorsOverride(false); + return { }; + } + @@ -4259,7 +4424,7 @@ index 5329fd0a2c24031a74d05d7c6c342a5f8398eaae..a64e486220e4fc8e37c34856fce8c3d8 +{ + bool success = WTF::setTimeZoneOverride(timeZone); + if (!success) -+ return makeUnexpected("Invalid time zone " + timeZone); ++ return makeUnexpected(makeString("Invalid time zone "_s, timeZone)); + + return { }; +} @@ -4267,7 +4432,7 @@ index 5329fd0a2c24031a74d05d7c6c342a5f8398eaae..a64e486220e4fc8e37c34856fce8c3d8 +Protocol::ErrorStringOr InspectorPageAgent::setTouchEmulationEnabled(bool enabled) +{ + setScreenHasTouchDeviceOverride(enabled); -+ m_inspectedPage.settings().setTouchEventsEnabled(enabled); ++ m_inspectedPage->settings().setTouchEventDOMAttributesEnabled(enabled); + return { }; +} + @@ -4275,7 +4440,7 @@ index 5329fd0a2c24031a74d05d7c6c342a5f8398eaae..a64e486220e4fc8e37c34856fce8c3d8 #if ENABLE(WEB_ARCHIVE) && USE(CF) Inspector::Protocol::ErrorStringOr InspectorPageAgent::archive() { -@@ -1233,7 +1434,6 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::archive() +@@ -1256,7 +1472,6 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::archive() } #endif @@ -4283,15 +4448,16 @@ index 5329fd0a2c24031a74d05d7c6c342a5f8398eaae..a64e486220e4fc8e37c34856fce8c3d8 Inspector::Protocol::ErrorStringOr InspectorPageAgent::setScreenSizeOverride(std::optional&& width, std::optional&& height) { if (width.has_value() != height.has_value()) -@@ -1251,6 +1451,519 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::setScreenSizeOverri +@@ -1274,6 +1489,496 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::setScreenSizeOverri localMainFrame->setOverrideScreenSize(FloatSize(width.value_or(0), height.value_or(0))); return { }; } +-#endif + +Protocol::ErrorStringOr InspectorPageAgent::insertText(const String& text) +{ + UserGestureIndicator indicator { IsProcessingUserGesture::Yes }; -+ RefPtr frame = m_inspectedPage.checkedFocusController()->focusedOrMainFrame(); ++ RefPtr frame = m_inspectedPage->checkedFocusController()->focusedOrMainFrame(); + if (!frame) + return { }; + @@ -4299,7 +4465,7 @@ index 5329fd0a2c24031a74d05d7c6c342a5f8398eaae..a64e486220e4fc8e37c34856fce8c3d8 + frame->editor().confirmComposition(text); + } else { + Document* focusedDocument = frame->document(); -+ TypingCommand::insertText(*focusedDocument, text, { }); ++ TypingCommand::insertText(*focusedDocument, text, nullptr, { }); + } + return { }; +} @@ -4413,10 +4579,6 @@ index 5329fd0a2c24031a74d05d7c6c342a5f8398eaae..a64e486220e4fc8e37c34856fce8c3d8 + return "Image"_s; + case AccessibilityRole::ImageMap: + return "ImageMap"_s; -+ case AccessibilityRole::ImageMapLink: -+ return "ImageMapLink"_s; -+ case AccessibilityRole::Incrementor: -+ return "Incrementor"_s; + case AccessibilityRole::Insertion: + return "Insertion"_s; + case AccessibilityRole::Label: @@ -4461,8 +4623,6 @@ index 5329fd0a2c24031a74d05d7c6c342a5f8398eaae..a64e486220e4fc8e37c34856fce8c3d8 + return "Menu"_s; + case AccessibilityRole::MenuBar: + return "MenuBar"_s; -+ case AccessibilityRole::MenuButton: -+ return "MenuButton"_s; + case AccessibilityRole::MenuItem: + return "MenuItem"_s; + case AccessibilityRole::MenuItemCheckbox: @@ -4499,14 +4659,8 @@ index 5329fd0a2c24031a74d05d7c6c342a5f8398eaae..a64e486220e4fc8e37c34856fce8c3d8 + return "Row"_s; + case AccessibilityRole::RowGroup: + return "RowGroup"_s; -+ case AccessibilityRole::RubyBase: -+ return "RubyBase"_s; -+ case AccessibilityRole::RubyBlock: -+ return "RubyBlock"_s; + case AccessibilityRole::RubyInline: + return "RubyInline"_s; -+ case AccessibilityRole::RubyRun: -+ return "RubyRun"_s; + case AccessibilityRole::RubyText: + return "RubyText"_s; + case AccessibilityRole::ScrollArea: @@ -4595,7 +4749,7 @@ index 5329fd0a2c24031a74d05d7c6c342a5f8398eaae..a64e486220e4fc8e37c34856fce8c3d8 + return "Unknown"_s; +} + -+static Ref snapshotForAXObject(RefPtr axObject, Node* nodeToFind) ++static Ref snapshotForAXObject(WTF::RefPtr axObject, Node* nodeToFind) +{ + auto axNode = Inspector::Protocol::Page::AXNode::create() + .setRole(roleFromObject(axObject)) @@ -4685,7 +4839,7 @@ index 5329fd0a2c24031a74d05d7c6c342a5f8398eaae..a64e486220e4fc8e37c34856fce8c3d8 + if (!axObject->children().isEmpty()) { + Ref> children = JSON::ArrayOf::create(); + for (auto& childObject : axObject->children()) -+ children->addItem(snapshotForAXObject(childObject, nodeToFind)); ++ children->addItem(snapshotForAXObject(childObject.ptr(), nodeToFind)); + axNode->setChildren(WTFMove(children)); + } + return axNode; @@ -4697,7 +4851,7 @@ index 5329fd0a2c24031a74d05d7c6c342a5f8398eaae..a64e486220e4fc8e37c34856fce8c3d8 + if (!WebCore::AXObjectCache::accessibilityEnabled()) + WebCore::AXObjectCache::enableAccessibility(); + -+ auto* localMainFrame = dynamicDowncast(m_inspectedPage.mainFrame()); ++ auto* localMainFrame = dynamicDowncast(m_inspectedPage->mainFrame()); + if (!localMainFrame) + return makeUnexpected("No local main frame"_s); + @@ -4709,7 +4863,7 @@ index 5329fd0a2c24031a74d05d7c6c342a5f8398eaae..a64e486220e4fc8e37c34856fce8c3d8 + if (!axObjectCache) + return makeUnexpected("No AXObjectCache for main document"_s); + -+ AXCoreObject* axObject = axObjectCache->rootObject(); ++ AXCoreObject* axObject = axObjectCache->rootObjectForFrame(*localMainFrame); + if (!axObject) + return makeUnexpected("No AXObject for main document"_s); + @@ -4736,7 +4890,7 @@ index 5329fd0a2c24031a74d05d7c6c342a5f8398eaae..a64e486220e4fc8e37c34856fce8c3d8 + +Protocol::ErrorStringOr InspectorPageAgent::setDefaultBackgroundColorOverride(RefPtr&& color) +{ -+ auto* localFrame = dynamicDowncast(m_inspectedPage.mainFrame()); ++ auto* localFrame = dynamicDowncast(m_inspectedPage->mainFrame()); + LocalFrameView* view = localFrame ? localFrame->view() : nullptr; + if (!view) + return makeUnexpected("Internal error: No frame view to set color two"_s); @@ -4763,7 +4917,7 @@ index 5329fd0a2c24031a74d05d7c6c342a5f8398eaae..a64e486220e4fc8e37c34856fce8c3d8 + +void InspectorPageAgent::ensureUserWorldsExistInAllFrames(const Vector& worlds) +{ -+ for (Frame* frame = &m_inspectedPage.mainFrame(); frame; frame = frame->tree().traverseNext()) { ++ for (Frame* frame = &m_inspectedPage->mainFrame(); frame; frame = frame->tree().traverseNext()) { + auto* localFrame = dynamicDowncast(frame); + for (auto* world : worlds) + localFrame->windowProxy().jsWindowProxy(*world)->window(); @@ -4778,24 +4932,13 @@ index 5329fd0a2c24031a74d05d7c6c342a5f8398eaae..a64e486220e4fc8e37c34856fce8c3d8 + +Protocol::ErrorStringOr InspectorPageAgent::crash() +{ -+ CRASH(); -+ return { }; -+} -+ -+Protocol::ErrorStringOr InspectorPageAgent::setOrientationOverride(std::optional&& angle) -+{ -+#if ENABLE(ORIENTATION_EVENTS) -+ m_inspectedPage.setOverrideOrientation(WTFMove(angle)); ++ WTFCrash(); + return { }; -+#else -+ UNUSED_PARAM(angle); -+ return makeUnexpected("Orientation events are disabled in this build"); - #endif +} + +Protocol::ErrorStringOr InspectorPageAgent::updateScrollingState() +{ -+ auto* scrollingCoordinator = m_inspectedPage.scrollingCoordinator(); ++ auto* scrollingCoordinator = m_inspectedPage->scrollingCoordinator(); + if (!scrollingCoordinator) + return {}; + scrollingCoordinator->commitTreeStateIfNeeded(); @@ -4804,7 +4947,7 @@ index 5329fd0a2c24031a74d05d7c6c342a5f8398eaae..a64e486220e4fc8e37c34856fce8c3d8 } // namespace WebCore diff --git a/Source/WebCore/inspector/agents/InspectorPageAgent.h b/Source/WebCore/inspector/agents/InspectorPageAgent.h -index 371bcfcf1d0ae17471f8e69706d2f12356793418..6bc660d683a639f1d6f6a0dca8db5e058d32cd21 100644 +index 7daa8d1d5c96afe1829aa21ccb8ed1b8ebcc3861..da57245795d7cb287daaaaf5d09a523c0f88fcc7 100644 --- a/Source/WebCore/inspector/agents/InspectorPageAgent.h +++ b/Source/WebCore/inspector/agents/InspectorPageAgent.h @@ -32,8 +32,10 @@ @@ -4818,8 +4961,8 @@ index 371bcfcf1d0ae17471f8e69706d2f12356793418..6bc660d683a639f1d6f6a0dca8db5e05 #include #include #include -@@ -41,11 +43,16 @@ - #include +@@ -43,11 +45,16 @@ + #include #include +namespace Inspector { @@ -4835,15 +4978,16 @@ index 371bcfcf1d0ae17471f8e69706d2f12356793418..6bc660d683a639f1d6f6a0dca8db5e05 class InspectorClient; class InspectorOverlay; class LocalFrame; -@@ -78,6 +85,7 @@ public: +@@ -80,6 +87,8 @@ public: OtherResource, }; -+ WEBCORE_EXPORT static String makeFrameID(ProcessIdentifier processID, FrameIdentifier frameID); ++ WEBCORE_EXPORT static String serializeFrameID(FrameIdentifier frameID); ++ WEBCORE_EXPORT static std::optional parseFrameID(String frameID); static bool sharedBufferContent(RefPtr&&, const String& textEncodingName, bool withBase64Encode, String* result); static Vector cachedResourcesForFrame(LocalFrame*); static void resourceContent(Inspector::Protocol::ErrorString&, LocalFrame*, const URL&, String* result, bool* base64Encoded); -@@ -98,8 +106,11 @@ public: +@@ -100,8 +109,11 @@ public: Inspector::Protocol::ErrorStringOr enable(); Inspector::Protocol::ErrorStringOr disable(); Inspector::Protocol::ErrorStringOr reload(std::optional&& ignoreCache, std::optional&& revalidateAllResources); @@ -4855,7 +4999,7 @@ index 371bcfcf1d0ae17471f8e69706d2f12356793418..6bc660d683a639f1d6f6a0dca8db5e05 Inspector::Protocol::ErrorStringOr overrideSetting(Inspector::Protocol::Page::Setting, std::optional&& value); Inspector::Protocol::ErrorStringOr overrideUserPreference(Inspector::Protocol::Page::UserPreferenceName, std::optional&&); Inspector::Protocol::ErrorStringOr>> getCookies(); -@@ -115,45 +126,66 @@ public: +@@ -117,45 +129,65 @@ public: #endif Inspector::Protocol::ErrorStringOr setShowPaintRects(bool); Inspector::Protocol::ErrorStringOr setEmulatedMedia(const String&); @@ -4879,7 +5023,6 @@ index 371bcfcf1d0ae17471f8e69706d2f12356793418..6bc660d683a639f1d6f6a0dca8db5e05 + Inspector::Protocol::ErrorStringOr createUserWorld(const String&); + Inspector::Protocol::ErrorStringOr setBypassCSP(bool); + Inspector::Protocol::ErrorStringOr crash(); -+ Inspector::Protocol::ErrorStringOr setOrientationOverride(std::optional&& angle); + Inspector::Protocol::ErrorStringOr updateScrollingState(); // InspectorInstrumentation @@ -4898,7 +5041,7 @@ index 371bcfcf1d0ae17471f8e69706d2f12356793418..6bc660d683a639f1d6f6a0dca8db5e05 void accessibilitySettingsDidChange(); void defaultUserPreferencesDidChange(); + void didNavigateWithinPage(LocalFrame&); - #if ENABLE(DARK_MODE_CSS) || HAVE(OS_DARK_MODE_SUPPORT) + #if ENABLE(DARK_MODE_CSS) void defaultAppearanceDidChange(); #endif void applyUserAgentOverride(String&); @@ -4927,19 +5070,19 @@ index 371bcfcf1d0ae17471f8e69706d2f12356793418..6bc660d683a639f1d6f6a0dca8db5e05 double timestamp(); + void ensureUserWorldsExistInAllFrames(const Vector&); - static bool mainResourceContent(LocalFrame*, bool withBase64Encode, String* result); - static bool dataContent(std::span data, const String& textEncodingName, bool withBase64Encode, String* result); -@@ -169,17 +201,21 @@ private: + Ref protectedOverlay() const; + +@@ -173,17 +205,22 @@ private: RefPtr m_backendDispatcher; - Page& m_inspectedPage; + WeakRef m_inspectedPage; + Inspector::InjectedScriptManager& m_injectedScriptManager; InspectorClient* m_client { nullptr }; - InspectorOverlay* m_overlay { nullptr }; + WeakRef m_overlay; - WeakHashMap m_frameToIdentifier; MemoryCompactRobinHoodHashMap> m_identifierToFrame; -- HashMap m_loaderToIdentifier; + HashMap m_loaderToIdentifier; String m_userAgentOverride; + String m_platformOverride; AtomString m_emulatedMedia; @@ -4954,7 +5097,7 @@ index 371bcfcf1d0ae17471f8e69706d2f12356793418..6bc660d683a639f1d6f6a0dca8db5e05 } // namespace WebCore diff --git a/Source/WebCore/inspector/agents/page/PageRuntimeAgent.cpp b/Source/WebCore/inspector/agents/page/PageRuntimeAgent.cpp -index 61b797e08f5e6d90cc2724dd7a3b45c0f45af4f8..919a8b963d93742cc99c2739e472361deea84e4c 100644 +index 0cc351959aaa96bd427ecbf75dd2ba51e730fc30..fb2b6c842a2e2b819ce746403e33550c0d4e2440 100644 --- a/Source/WebCore/inspector/agents/page/PageRuntimeAgent.cpp +++ b/Source/WebCore/inspector/agents/page/PageRuntimeAgent.cpp @@ -34,6 +34,7 @@ @@ -4973,7 +5116,7 @@ index 61b797e08f5e6d90cc2724dd7a3b45c0f45af4f8..919a8b963d93742cc99c2739e472361d #include "SecurityOrigin.h" #include "UserGestureEmulationScope.h" #include -@@ -85,13 +87,73 @@ Inspector::Protocol::ErrorStringOr PageRuntimeAgent::disable() +@@ -88,13 +90,74 @@ Inspector::Protocol::ErrorStringOr PageRuntimeAgent::disable() { m_instrumentingAgents.setEnabledPageRuntimeAgent(nullptr); @@ -5018,8 +5161,9 @@ index 61b797e08f5e6d90cc2724dd7a3b45c0f45af4f8..919a8b963d93742cc99c2739e472361d + +static void addBindingToFrame(LocalFrame& frame, const String& name) +{ -+ JSC::JSGlobalObject* globalObject = frame.script().globalObject(mainThreadNormalWorld()); ++ JSC::JSGlobalObject* globalObject = frame.script().globalObject(mainThreadNormalWorldSingleton()); + auto& vm = globalObject->vm(); ++ JSC::JSLockHolder lock(vm); + globalObject->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(vm, name), 1, bindingCallback, JSC::ImplementationVisibility::Public, JSC::NoIntrinsic, JSC::attributesForStructure(static_cast(JSC::PropertyAttribute::Function))); +} + @@ -5028,7 +5172,7 @@ index 61b797e08f5e6d90cc2724dd7a3b45c0f45af4f8..919a8b963d93742cc99c2739e472361d + if (!m_bindingNames.add(name).isNewEntry) + return {}; + -+ m_inspectedPage.forEachLocalFrame([&](LocalFrame& frame) { ++ m_inspectedPage->forEachLocalFrame([&](LocalFrame& frame) { + if (!frame.script().canExecuteScripts(ReasonForCallingCanExecuteScripts::NotAboutToExecuteScript)) + return; + @@ -5047,7 +5191,7 @@ index 61b797e08f5e6d90cc2724dd7a3b45c0f45af4f8..919a8b963d93742cc99c2739e472361d } void PageRuntimeAgent::didClearWindowObjectInWorld(LocalFrame& frame, DOMWrapperWorld& world) -@@ -100,7 +162,26 @@ void PageRuntimeAgent::didClearWindowObjectInWorld(LocalFrame& frame, DOMWrapper +@@ -103,7 +166,26 @@ void PageRuntimeAgent::didClearWindowObjectInWorld(LocalFrame& frame, DOMWrapper if (!pageAgent) return; @@ -5074,10 +5218,10 @@ index 61b797e08f5e6d90cc2724dd7a3b45c0f45af4f8..919a8b963d93742cc99c2739e472361d } InjectedScript PageRuntimeAgent::injectedScriptForEval(Inspector::Protocol::ErrorString& errorString, std::optional&& executionContextId) -@@ -139,9 +220,6 @@ void PageRuntimeAgent::reportExecutionContextCreation() +@@ -142,9 +224,6 @@ void PageRuntimeAgent::reportExecutionContextCreation() return; - m_inspectedPage.forEachLocalFrame([&](LocalFrame& frame) { + m_inspectedPage->forEachLocalFrame([&](LocalFrame& frame) { - if (!frame.script().canExecuteScripts(ReasonForCallingCanExecuteScripts::NotAboutToExecuteScript)) - return; - @@ -5085,10 +5229,10 @@ index 61b797e08f5e6d90cc2724dd7a3b45c0f45af4f8..919a8b963d93742cc99c2739e472361d // Always send the main world first. diff --git a/Source/WebCore/inspector/agents/page/PageRuntimeAgent.h b/Source/WebCore/inspector/agents/page/PageRuntimeAgent.h -index 9501fc840e35f3badc701e7622555dba394cae9b..1391c73d9b3ba250ad3a831bfe7c92c98de0c93c 100644 +index ab49ddd13fc6e1ed967cf501afb0230c1e795159..5ea038212cedc1a7b250588b616225edad6f643c 100644 --- a/Source/WebCore/inspector/agents/page/PageRuntimeAgent.h +++ b/Source/WebCore/inspector/agents/page/PageRuntimeAgent.h -@@ -37,6 +37,7 @@ +@@ -38,6 +38,7 @@ namespace JSC { class CallFrame; @@ -5096,7 +5240,7 @@ index 9501fc840e35f3badc701e7622555dba394cae9b..1391c73d9b3ba250ad3a831bfe7c92c9 } namespace WebCore { -@@ -58,10 +59,13 @@ public: +@@ -59,10 +60,13 @@ public: Inspector::Protocol::ErrorStringOr disable(); Inspector::Protocol::ErrorStringOr, std::optional /* wasThrown */, std::optional /* savedResultIndex */>> evaluate(const String& expression, const String& objectGroup, std::optional&& includeCommandLineAPI, std::optional&& doNotPauseOnExceptionsAndMuteConsole, std::optional&&, std::optional&& returnByValue, std::optional&& generatePreview, std::optional&& saveResult, std::optional&& emulateUserGesture); void callFunctionOn(const Inspector::Protocol::Runtime::RemoteObjectId&, const String& functionDeclaration, RefPtr&& arguments, std::optional&& doNotPauseOnExceptionsAndMuteConsole, std::optional&& returnByValue, std::optional&& generatePreview, std::optional&& emulateUserGesture, std::optional&& awaitPromise, Ref&&); @@ -5110,27 +5254,27 @@ index 9501fc840e35f3badc701e7622555dba394cae9b..1391c73d9b3ba250ad3a831bfe7c92c9 private: Inspector::InjectedScript injectedScriptForEval(Inspector::Protocol::ErrorString&, std::optional&&); -@@ -76,6 +80,7 @@ private: +@@ -77,6 +81,7 @@ private: InstrumentingAgents& m_instrumentingAgents; - Page& m_inspectedPage; + WeakRef m_inspectedPage; + HashSet m_bindingNames; }; } // namespace WebCore diff --git a/Source/WebCore/loader/CookieJar.h b/Source/WebCore/loader/CookieJar.h -index edfc601a36f006122f26946de5b3a60573a07968..794a6c389be8af23989a54696d57312340ddcd37 100644 +index 8fb27c1045b8073d1487d5b61ccdec23a395bfd1..5008052f587ca4ba90da973c539188deb9551621 100644 --- a/Source/WebCore/loader/CookieJar.h +++ b/Source/WebCore/loader/CookieJar.h -@@ -46,6 +46,7 @@ struct CookieStoreGetOptions; - class NetworkStorageSession; +@@ -48,6 +48,7 @@ class NetworkStorageSession; class StorageSessionProvider; struct SameSiteInfo; + enum class ShouldPartitionCookie : bool; +class ResourceLoader; - class WEBCORE_EXPORT CookieJar : public RefCounted, public CanMakeWeakPtr { + class WEBCORE_EXPORT CookieJar : public RefCountedAndCanMakeWeakPtr { public: -@@ -78,6 +79,9 @@ public: +@@ -80,6 +81,9 @@ public: virtual void clearCache() { } virtual void clearCacheForHost(const String&) { } @@ -5141,25 +5285,25 @@ index edfc601a36f006122f26946de5b3a60573a07968..794a6c389be8af23989a54696d573123 protected: static SameSiteInfo sameSiteInfo(const Document&, IsForDOMCookieAccess = IsForDOMCookieAccess::No); diff --git a/Source/WebCore/loader/DocumentLoader.cpp b/Source/WebCore/loader/DocumentLoader.cpp -index 90023ca4ebad0d8608b74434ca5d870ffeb00871..7360ea6857f98e60bdfa74ad4a0d595958cfc11f 100644 +index 541963eb00a1e5700da683be152543ac57f177a1..bd0debb9cdf2fac02bcf0243571a4a668be9decc 100644 --- a/Source/WebCore/loader/DocumentLoader.cpp +++ b/Source/WebCore/loader/DocumentLoader.cpp -@@ -763,8 +763,10 @@ void DocumentLoader::willSendRequest(ResourceRequest&& newRequest, const Resourc +@@ -774,8 +774,10 @@ void DocumentLoader::willSendRequest(ResourceRequest&& newRequest, const Resourc if (!didReceiveRedirectResponse) return completionHandler(WTFMove(newRequest)); -+ InspectorInstrumentation::willCheckNavigationPolicy(*m_frame); - auto navigationPolicyCompletionHandler = [this, protectedThis = Ref { *this }, protectedFrame = Ref { *m_frame }, completionHandler = WTFMove(completionHandler)] (ResourceRequest&& request, WeakPtr&&, NavigationPolicyDecision navigationPolicyDecision) mutable { ++ InspectorInstrumentation::willCheckNavigationPolicy(*frame); + auto navigationPolicyCompletionHandler = [this, protectedThis = Ref { *this }, frame, completionHandler = WTFMove(completionHandler)] (ResourceRequest&& request, WeakPtr&&, NavigationPolicyDecision navigationPolicyDecision) mutable { m_waitingForNavigationPolicy = false; -+ InspectorInstrumentation::didCheckNavigationPolicy(protectedFrame.get(), navigationPolicyDecision != NavigationPolicyDecision::ContinueLoad); ++ InspectorInstrumentation::didCheckNavigationPolicy(*frame, navigationPolicyDecision != NavigationPolicyDecision::ContinueLoad); switch (navigationPolicyDecision) { case NavigationPolicyDecision::IgnoreLoad: case NavigationPolicyDecision::LoadWillContinueInAnotherProcess: -@@ -1532,11 +1534,17 @@ void DocumentLoader::detachFromFrame(LoadWillContinueInAnotherProcess loadWillCo - if (auto navigationID = std::exchange(m_navigationID, 0)) - m_frame->loader().client().documentLoaderDetached(navigationID, loadWillContinueInAnotherProcess); +@@ -1572,11 +1574,17 @@ void DocumentLoader::detachFromFrame(LoadWillContinueInAnotherProcess loadWillCo + if (auto navigationID = std::exchange(m_navigationID, { })) + frame->loader().client().documentLoaderDetached(*navigationID, loadWillContinueInAnotherProcess); -- InspectorInstrumentation::loaderDetachedFromFrame(*m_frame, *this); +- InspectorInstrumentation::loaderDetachedFromFrame(*frame, *this); - observeFrame(nullptr); } @@ -5168,31 +5312,31 @@ index 90023ca4ebad0d8608b74434ca5d870ffeb00871..7360ea6857f98e60bdfa74ad4a0d5959 +{ + ASSERT(!this->frame()); + // Notify WebPageProxy that the navigation has been converted into same page navigation. -+ if (auto navigationID = std::exchange(m_navigationID, 0)) -+ frame.loader().client().documentLoaderDetached(navigationID, LoadWillContinueInAnotherProcess::No); ++ if (auto navigationID = std::exchange(m_navigationID, { })) ++ frame.loader().client().documentLoaderDetached(*navigationID, LoadWillContinueInAnotherProcess::No); +} + - void DocumentLoader::setNavigationID(uint64_t navigationID) + void DocumentLoader::setNavigationID(NavigationIdentifier navigationID) { - ASSERT(navigationID); + m_navigationID = navigationID; diff --git a/Source/WebCore/loader/DocumentLoader.h b/Source/WebCore/loader/DocumentLoader.h -index aa98ba7e3eb896b65a156fe8f75ae3c0bc99f246..00531c35e1d5041d3bcc13c54308eb7eff387baf 100644 +index a3e5891cc44903ec74da16164904c12673498d97..9f8566a8c1cc20c1d2a495c9765f1c522890e993 100644 --- a/Source/WebCore/loader/DocumentLoader.h +++ b/Source/WebCore/loader/DocumentLoader.h -@@ -191,6 +191,8 @@ public: +@@ -218,6 +218,8 @@ public: WEBCORE_EXPORT virtual void detachFromFrame(LoadWillContinueInAnotherProcess); + void replacedByFragmentNavigation(LocalFrame&); + WEBCORE_EXPORT FrameLoader* frameLoader() const; - CheckedPtr checkedFrameLoader() const; + WEBCORE_EXPORT RefPtr protectedFrameLoader() const; WEBCORE_EXPORT SubresourceLoader* mainResourceLoader() const; diff --git a/Source/WebCore/loader/FrameLoader.cpp b/Source/WebCore/loader/FrameLoader.cpp -index 4882d1ded68a2e88595c1ce7e2a6891f066b3457..e630a3cd7022449e6eec9516f7bb5e63f3085b0e 100644 +index 0974e98f02b59150df7054af753a3c3bb1d3b0e9..559a8532162d4c9e106c1059dfbf50fc63ee9326 100644 --- a/Source/WebCore/loader/FrameLoader.cpp +++ b/Source/WebCore/loader/FrameLoader.cpp -@@ -1355,6 +1355,7 @@ void FrameLoader::loadInSameDocument(URL url, RefPtr stat +@@ -1325,6 +1325,7 @@ void FrameLoader::loadInSameDocument(URL url, RefPtr stat } m_client->dispatchDidNavigateWithinPage(); @@ -5200,40 +5344,35 @@ index 4882d1ded68a2e88595c1ce7e2a6891f066b3457..e630a3cd7022449e6eec9516f7bb5e63 document->statePopped(stateObject ? stateObject.releaseNonNull() : SerializedScriptValue::nullValue()); m_client->dispatchDidPopStateWithinPage(); -@@ -1820,6 +1821,8 @@ void FrameLoader::loadWithDocumentLoader(DocumentLoader* loader, FrameLoadType t +@@ -1867,6 +1868,7 @@ void FrameLoader::loadWithDocumentLoader(DocumentLoader* loader, FrameLoadType t const String& httpMethod = loader->request().httpMethod(); if (shouldPerformFragmentNavigation(isFormSubmission, httpMethod, policyChecker().loadType(), newURL)) { + loader->replacedByFragmentNavigation(m_frame); -+ + RefPtr oldDocumentLoader = m_documentLoader; NavigationAction action { frame->protectedDocument().releaseNonNull(), loader->request(), InitiatedByMainFrame::Unknown, loader->isRequestFromClientOrUserInput(), policyChecker().loadType(), isFormSubmission }; - oldDocumentLoader->setTriggeringAction(WTFMove(action)); -@@ -1853,7 +1856,9 @@ void FrameLoader::loadWithDocumentLoader(DocumentLoader* loader, FrameLoadType t - } +@@ -1905,7 +1907,9 @@ void FrameLoader::loadWithDocumentLoader(DocumentLoader* loader, FrameLoadType t + auto policyDecisionMode = loader->triggeringAction().isFromNavigationAPI() ? PolicyDecisionMode::Synchronous : PolicyDecisionMode::Asynchronous; RELEASE_ASSERT(!isBackForwardLoadType(policyChecker().loadType()) || history().provisionalItem()); + InspectorInstrumentation::willCheckNavigationPolicy(m_frame); - policyChecker().checkNavigationPolicy(ResourceRequest(loader->request()), ResourceResponse { } /* redirectResponse */, loader, WTFMove(formState), [this, frame, allowNavigationToInvalidURL, completionHandler = completionHandlerCaller.release()] (const ResourceRequest& request, WeakPtr&& weakFormState, NavigationPolicyDecision navigationPolicyDecision) mutable { + policyChecker().checkNavigationPolicy(ResourceRequest(loader->request()), ResourceResponse { } /* redirectResponse */, loader, WTFMove(formState), [this, protectedThis = Ref { *this }, allowNavigationToInvalidURL, completionHandler = completionHandlerCaller.release()] (const ResourceRequest& request, WeakPtr&& weakFormState, NavigationPolicyDecision navigationPolicyDecision) mutable { + InspectorInstrumentation::didCheckNavigationPolicy(m_frame, navigationPolicyDecision != NavigationPolicyDecision::ContinueLoad); continueLoadAfterNavigationPolicy(request, RefPtr { weakFormState.get() }.get(), navigationPolicyDecision, allowNavigationToInvalidURL); completionHandler(); - }, PolicyDecisionMode::Asynchronous); -@@ -3115,14 +3120,19 @@ String FrameLoader::userAgent(const URL& url) const + }, policyDecisionMode); +@@ -3219,10 +3223,15 @@ String FrameLoader::userAgent(const URL& url) const String FrameLoader::navigatorPlatform() const { + String platform; + - if (RefPtr localFrame = dynamicDowncast(m_frame->mainFrame())) { - if (RefPtr documentLoader = localFrame->loader().activeDocumentLoader()) { - auto& customNavigatorPlatform = documentLoader->customNavigatorPlatform(); - if (!customNavigatorPlatform.isEmpty()) -- return customNavigatorPlatform; -+ platform = customNavigatorPlatform; - } - } + auto customNavigatorPlatform = m_frame->protectedMainFrame()->customNavigatorPlatform(); + if (!customNavigatorPlatform.isEmpty()) +- return customNavigatorPlatform; - return String(); ++ platform = customNavigatorPlatform; + + InspectorInstrumentation::applyPlatformOverride(m_frame, platform); + @@ -5241,16 +5380,16 @@ index 4882d1ded68a2e88595c1ce7e2a6891f066b3457..e630a3cd7022449e6eec9516f7bb5e63 } void FrameLoader::dispatchOnloadEvents() -@@ -3572,6 +3582,8 @@ void FrameLoader::receivedMainResourceError(const ResourceError& error) +@@ -3682,6 +3691,8 @@ void FrameLoader::receivedMainResourceError(const ResourceError& error, LoadWill checkCompleted(); if (frame->page()) - checkLoadComplete(); + checkLoadComplete(loadWillContinueInAnotherProcess); + + InspectorInstrumentation::didReceiveMainResourceError(m_frame, error); } - void FrameLoader::continueFragmentScrollAfterNavigationPolicy(const ResourceRequest& request, const SecurityOrigin* requesterOrigin, bool shouldContinue) -@@ -4425,9 +4437,6 @@ String FrameLoader::referrer() const + void FrameLoader::continueFragmentScrollAfterNavigationPolicy(const ResourceRequest& request, const SecurityOrigin* requesterOrigin, bool shouldContinue, NavigationHistoryBehavior historyHandling) +@@ -4576,9 +4587,6 @@ String FrameLoader::referrer() const void FrameLoader::dispatchDidClearWindowObjectsInAllWorlds() { @@ -5260,11 +5399,11 @@ index 4882d1ded68a2e88595c1ce7e2a6891f066b3457..e630a3cd7022449e6eec9516f7bb5e63 Vector> worlds; ScriptController::getAllWorlds(worlds); for (auto& world : worlds) -@@ -4437,13 +4446,12 @@ void FrameLoader::dispatchDidClearWindowObjectsInAllWorlds() +@@ -4588,13 +4596,12 @@ void FrameLoader::dispatchDidClearWindowObjectsInAllWorlds() void FrameLoader::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld& world) { Ref frame = m_frame.get(); -- if (!frame->checkedScript()->canExecuteScripts(ReasonForCallingCanExecuteScripts::NotAboutToExecuteScript) || !frame->windowProxy().existingJSWindowProxy(world)) +- if (!frame->checkedScript()->canExecuteScripts(ReasonForCallingCanExecuteScripts::NotAboutToExecuteScript) || !frame->protectedWindowProxy()->existingJSWindowProxy(world)) - return; - - m_client->dispatchDidClearWindowObjectInWorld(world); @@ -5281,7 +5420,7 @@ index 4882d1ded68a2e88595c1ce7e2a6891f066b3457..e630a3cd7022449e6eec9516f7bb5e63 InspectorInstrumentation::didClearWindowObjectInWorld(frame, world); } diff --git a/Source/WebCore/loader/LoaderStrategy.h b/Source/WebCore/loader/LoaderStrategy.h -index 91340dc21042f545592b442bc42dbceed06219b2..f3591fe333761b10a25ddaf4a4f8d72170dfe336 100644 +index 1b34dfdd2a8e56beab49591a3517aba02c510ee6..768b895c132b73d935198cbfc2126a227a656b46 100644 --- a/Source/WebCore/loader/LoaderStrategy.h +++ b/Source/WebCore/loader/LoaderStrategy.h @@ -86,6 +86,7 @@ public: @@ -5293,10 +5432,10 @@ index 91340dc21042f545592b442bc42dbceed06219b2..f3591fe333761b10a25ddaf4a4f8d721 virtual bool shouldPerformSecurityChecks() const { return false; } virtual bool havePerformedSecurityChecks(const ResourceResponse&) const { return false; } diff --git a/Source/WebCore/loader/NavigationScheduler.cpp b/Source/WebCore/loader/NavigationScheduler.cpp -index a6270e0e1ceb02fee0a3c91a0cc755351908c5e5..f5e7330fa741eff7917adf227760161c5ba1e5f8 100644 +index d1d57f421c8570468b8c1ad2dc3c081b50cc4f0a..17a75616518d81eb3ce1e8107ee1f3546b477e30 100644 --- a/Source/WebCore/loader/NavigationScheduler.cpp +++ b/Source/WebCore/loader/NavigationScheduler.cpp -@@ -690,7 +690,7 @@ void NavigationScheduler::startTimer() +@@ -806,7 +806,7 @@ void NavigationScheduler::startTimer() Seconds delay = 1_s * m_redirect->delay(); m_timer.startOneShot(delay); @@ -5305,24 +5444,12 @@ index a6270e0e1ceb02fee0a3c91a0cc755351908c5e5..f5e7330fa741eff7917adf227760161c m_redirect->didStartTimer(frame, m_timer); // m_redirect may be null on return (e.g. the client canceled the load) } -diff --git a/Source/WebCore/loader/PolicyChecker.cpp b/Source/WebCore/loader/PolicyChecker.cpp -index ca3dc2575f3c9cb87ac902d79610f0738b09fdff..2ddbbfed658961e8231f641a889508aa4869070d 100644 ---- a/Source/WebCore/loader/PolicyChecker.cpp -+++ b/Source/WebCore/loader/PolicyChecker.cpp -@@ -46,6 +46,7 @@ - #include "HTMLFrameOwnerElement.h" - #include "HTMLPlugInElement.h" - #include "HitTestResult.h" -+#include "InspectorInstrumentation.h" - #include "LocalDOMWindow.h" - #include "LocalFrame.h" - #include "LocalFrameLoaderClient.h" diff --git a/Source/WebCore/loader/ProgressTracker.cpp b/Source/WebCore/loader/ProgressTracker.cpp -index b74c5258454b0df9f74aa8a5297674b733925685..b6c3999745368c7f7e2e6176bfca6dc09c49f539 100644 +index a1554c16a0b836bcf87fea0f4e7831d9e0d7baf0..354e4fef6de9c77b7cad96cc428056ae4e2ff067 100644 --- a/Source/WebCore/loader/ProgressTracker.cpp +++ b/Source/WebCore/loader/ProgressTracker.cpp -@@ -161,6 +161,8 @@ void ProgressTracker::progressCompleted(LocalFrame& frame) - if (!m_numProgressTrackedFrames || m_originatingProgressFrame == &frame) +@@ -163,6 +163,8 @@ void ProgressTracker::progressCompleted(LocalFrame& frame) + if (!m_numProgressTrackedFrames || originatingProgressFrame == &frame) finalProgressComplete(); + InspectorInstrumentation::frameStoppedLoading(frame); @@ -5330,22 +5457,22 @@ index b74c5258454b0df9f74aa8a5297674b733925685..b6c3999745368c7f7e2e6176bfca6dc0 m_client->didChangeEstimatedProgress(); } -@@ -187,8 +189,6 @@ void ProgressTracker::finalProgressComplete() - m_client->progressFinished(*frame); - protectedPage()->progressFinished(*frame); - frame->checkedLoader()->loadProgressingStatusChanged(); +@@ -189,8 +191,6 @@ void ProgressTracker::finalProgressComplete() + m_client->progressFinished(*frame); + protectedPage()->progressFinished(*frame); + frame->protectedLoader()->loadProgressingStatusChanged(); - -- InspectorInstrumentation::frameStoppedLoading(*frame); +- InspectorInstrumentation::frameStoppedLoading(*frame); + } } - void ProgressTracker::incrementProgress(ResourceLoaderIdentifier identifier, const ResourceResponse& response) diff --git a/Source/WebCore/loader/cache/CachedResourceLoader.cpp b/Source/WebCore/loader/cache/CachedResourceLoader.cpp -index f0d0aeb93ca42f7178a9dc07beeba911a38c32fe..1f82595cbbbc4f32b5cc4330b4d71e05d51b27a0 100644 +index c6a8c86e12ba98ad8b9aab74430523c3dd8cb42e..61c73db33d4c629803d14f243862acea15e762cb 100644 --- a/Source/WebCore/loader/cache/CachedResourceLoader.cpp +++ b/Source/WebCore/loader/cache/CachedResourceLoader.cpp -@@ -1054,8 +1054,11 @@ ResourceErrorOr> CachedResourceLoader::requ +@@ -1173,8 +1173,11 @@ ResourceErrorOr> CachedResourceLoader::requ - request.updateReferrerPolicy(document() ? document()->referrerPolicy() : ReferrerPolicy::Default); + request.updateReferrerPolicy(document ? document->referrerPolicy() : ReferrerPolicy::Default); - if (InspectorInstrumentation::willIntercept(frame.ptr(), request.resourceRequest())) - request.setCachingPolicy(CachingPolicy::DisallowCaching); @@ -5355,9 +5482,9 @@ index f0d0aeb93ca42f7178a9dc07beeba911a38c32fe..1f82595cbbbc4f32b5cc4330b4d71e05 + // request.setCachingPolicy(CachingPolicy::DisallowCaching); + } - Ref page = *frame->page(); - -@@ -1663,8 +1666,9 @@ Vector> CachedResourceLoader::allCachedSVGImages() const + if (RefPtr documentLoader = m_documentLoader.get()) { + bool madeHTTPS { request.resourceRequest().wasSchemeOptimisticallyUpgraded() }; +@@ -1810,8 +1813,9 @@ Vector> CachedResourceLoader::allCachedSVGImages() const ResourceErrorOr> CachedResourceLoader::preload(CachedResource::Type type, CachedResourceRequest&& request) { @@ -5367,13 +5494,13 @@ index f0d0aeb93ca42f7178a9dc07beeba911a38c32fe..1f82595cbbbc4f32b5cc4330b4d71e05 + // if (InspectorInstrumentation::willIntercept(protectedFrame().get(), request.resourceRequest())) + // return makeUnexpected(ResourceError { errorDomainWebKitInternal, 0, request.resourceRequest().url(), "Inspector intercept"_s }); - ASSERT(m_document); - if (request.charset().isEmpty() && m_document && (type == CachedResource::Type::Script || type == CachedResource::Type::CSSStyleSheet)) + RefPtr document = m_document.get(); + ASSERT(document); diff --git a/Source/WebCore/page/ChromeClient.h b/Source/WebCore/page/ChromeClient.h -index 20666cc080e04b0fa12e654ac357531f18c7c1df..3cf1823363aacdc014326957f98f3435cf505beb 100644 +index 60ba4d0aaa365301aa80d144f2d07e842a71a6b8..a962ce78e3ad912886a9d3328d64cf0faec3177d 100644 --- a/Source/WebCore/page/ChromeClient.h +++ b/Source/WebCore/page/ChromeClient.h -@@ -335,7 +335,7 @@ public: +@@ -379,7 +379,7 @@ public: #endif #if ENABLE(ORIENTATION_EVENTS) @@ -5381,12 +5508,12 @@ index 20666cc080e04b0fa12e654ac357531f18c7c1df..3cf1823363aacdc014326957f98f3435 + virtual IntDegrees deviceOrientation() const { return 0; } #endif - #if ENABLE(INPUT_TYPE_COLOR) + virtual RefPtr createColorChooser(ColorChooserClient&, const Color&) = 0; diff --git a/Source/WebCore/page/EventHandler.cpp b/Source/WebCore/page/EventHandler.cpp -index 1171407b2f308431ba948ec477a56c90e66911e8..a96feb7fe5a299adaeb950a11512bdf26b1f2836 100644 +index 04fce4219bdfc1c4a78eb2d849045280416b6f2d..9e44a302b10ba3bc18496f5678262171e8b30b2c 100644 --- a/Source/WebCore/page/EventHandler.cpp +++ b/Source/WebCore/page/EventHandler.cpp -@@ -4325,6 +4325,12 @@ bool EventHandler::handleDrag(const MouseEventWithHitTestResults& event, CheckDr +@@ -4483,6 +4483,12 @@ bool EventHandler::handleDrag(const MouseEventWithHitTestResults& event, CheckDr if (!document) return false; @@ -5399,7 +5526,15 @@ index 1171407b2f308431ba948ec477a56c90e66911e8..a96feb7fe5a299adaeb950a11512bdf2 dragState().dataTransfer = DataTransfer::createForDrag(*document); auto hasNonDefaultPasteboardData = HasNonDefaultPasteboardData::No; -@@ -4951,7 +4957,7 @@ HandleUserInputEventResult EventHandler::handleTouchEvent(const PlatformTouchEve +@@ -5077,6 +5083,7 @@ static HitTestResult hitTestResultInFrame(LocalFrame* frame, const LayoutPoint& + return result; + } + ++WTF_ALLOW_UNSAFE_BUFFER_USAGE_BEGIN + Expected EventHandler::handleTouchEvent(const PlatformTouchEvent& event) + { + Ref frame = m_frame.get(); +@@ -5150,7 +5157,7 @@ Expected EventHandler::handleTouchEvent(co // Increment the platform touch id by 1 to avoid storing a key of 0 in the hashmap. unsigned touchPointTargetKey = point.id() + 1; @@ -5408,7 +5543,7 @@ index 1171407b2f308431ba948ec477a56c90e66911e8..a96feb7fe5a299adaeb950a11512bdf2 bool pointerCancelled = false; #endif RefPtr touchTarget; -@@ -4998,7 +5004,7 @@ HandleUserInputEventResult EventHandler::handleTouchEvent(const PlatformTouchEve +@@ -5197,7 +5204,7 @@ Expected EventHandler::handleTouchEvent(co // we also remove it from the map. touchTarget = m_originatingTouchPointTargets.take(touchPointTargetKey); @@ -5417,7 +5552,7 @@ index 1171407b2f308431ba948ec477a56c90e66911e8..a96feb7fe5a299adaeb950a11512bdf2 HitTestResult result = hitTestResultAtPoint(pagePoint, hitType | HitTestRequest::Type::AllowChildFrameContent); pointerTarget = result.targetElement(); pointerCancelled = (pointerTarget != touchTarget); -@@ -5021,7 +5027,7 @@ HandleUserInputEventResult EventHandler::handleTouchEvent(const PlatformTouchEve +@@ -5220,7 +5227,7 @@ Expected EventHandler::handleTouchEvent(co if (!targetFrame) continue; @@ -5426,34 +5561,58 @@ index 1171407b2f308431ba948ec477a56c90e66911e8..a96feb7fe5a299adaeb950a11512bdf2 // FIXME: WPE currently does not send touch stationary events, so create a naive TouchReleased PlatformTouchPoint // on release if the hit test result changed since the previous TouchPressed or TouchMoved if (pointState == PlatformTouchPoint::TouchReleased && pointerCancelled) { +@@ -5310,6 +5317,7 @@ Expected EventHandler::handleTouchEvent(co + + return swallowedEvent; + } ++WTF_ALLOW_UNSAFE_BUFFER_USAGE_BEGIN + #endif // ENABLE(TOUCH_EVENTS) && !ENABLE(IOS_TOUCH_EVENTS) + + #if ENABLE(TOUCH_EVENTS) +diff --git a/Source/WebCore/page/FocusController.cpp b/Source/WebCore/page/FocusController.cpp +index 1b183750e1c51e96fcca727bed3c2eb1d30e77e9..e1d00211b5051387bd4495d88cef637704cf1704 100644 +--- a/Source/WebCore/page/FocusController.cpp ++++ b/Source/WebCore/page/FocusController.cpp +@@ -580,13 +580,14 @@ bool FocusController::relinquishFocusToChrome(FocusDirection direction) + return false; + + Ref page = m_page.get(); +- if (!page->chrome().canTakeFocus(direction) || page->isControlledByAutomation()) ++ if (!page->chrome().canTakeFocus(direction)) + return false; + + clearSelectionIfNeeded(frame.get(), nullptr, nullptr); + document->setFocusedElement(nullptr); + setFocusedFrame(nullptr); +- page->chrome().takeFocus(direction); ++ if (!page->isControlledByAutomation()) ++ page->chrome().takeFocus(direction); + return true; + } + diff --git a/Source/WebCore/page/FrameSnapshotting.cpp b/Source/WebCore/page/FrameSnapshotting.cpp -index 36ff7673bffcfea97e705d03f31459c36dc46164..1a65fcc874877b8b54e4e6aebb56b66294ef1ceb 100644 +index 3474800864049dcbe6c84746c4216e72a68fa48f..8f5d536921eeb41c77fe689c036dcb77e625e431 100644 --- a/Source/WebCore/page/FrameSnapshotting.cpp +++ b/Source/WebCore/page/FrameSnapshotting.cpp -@@ -113,7 +113,7 @@ RefPtr snapshotFrameRectWithClip(LocalFrame& frame, const IntRect& +@@ -115,7 +115,7 @@ RefPtr snapshotFrameRectWithClip(LocalFrame& frame, const IntRect& // Other paint behaviors are set by paintContentsForSnapshot. frame.view()->setPaintBehavior(paintBehavior); - float scaleFactor = frame.page()->deviceScaleFactor(); + float scaleFactor = options.flags.contains(SnapshotFlags::OmitDeviceScaleFactor) ? 1 : frame.page()->deviceScaleFactor(); + if (options.flags.contains(SnapshotFlags::PaintWith3xBaseScale)) + scaleFactor = 3; - if (frame.page()->delegatesScaling()) - scaleFactor *= frame.page()->pageScaleFactor(); -@@ -128,7 +128,13 @@ RefPtr snapshotFrameRectWithClip(LocalFrame& frame, const IntRect& - if (!buffer) +@@ -134,6 +134,8 @@ RefPtr snapshotFrameRectWithClip(LocalFrame& frame, const IntRect& return nullptr; -+#if !PLATFORM(MAC) -+ buffer->context().scale(scaleFactor); -+#endif -+ buffer->context().translate(-imageRect.location()); + if (coordinateSpace != LocalFrameView::ViewCoordinates) + buffer->context().scale(1 / frame.page()->pageScaleFactor()); if (!clipRects.isEmpty()) { Path clipPath; -@@ -137,7 +143,10 @@ RefPtr snapshotFrameRectWithClip(LocalFrame& frame, const IntRect& +@@ -142,7 +144,10 @@ RefPtr snapshotFrameRectWithClip(LocalFrame& frame, const IntRect& buffer->context().clipPath(clipPath); } @@ -5466,19 +5625,19 @@ index 36ff7673bffcfea97e705d03f31459c36dc46164..1a65fcc874877b8b54e4e6aebb56b662 } diff --git a/Source/WebCore/page/FrameSnapshotting.h b/Source/WebCore/page/FrameSnapshotting.h -index e4f52ca1cb3228868bc77a5498c87e1f2af59ce4..9ce6b102570cdcd2775ebf5adcd1650db837f311 100644 +index 713cb9c3c59bbad23ef0b821ab27b3d669a7dea8..12077ebf0978b6b52e6af4602767c09d9f3cd9de 100644 --- a/Source/WebCore/page/FrameSnapshotting.h +++ b/Source/WebCore/page/FrameSnapshotting.h -@@ -54,6 +54,7 @@ enum class SnapshotFlags : uint16_t { - PaintWithIntegralScaleFactor = 1 << 6, - Shareable = 1 << 7, - Accelerated = 1 << 8, -+ OmitDeviceScaleFactor = 1 << 9, +@@ -58,6 +58,7 @@ enum class SnapshotFlags : uint16_t { + PaintWith3xBaseScale = 1 << 10, + ExcludeText = 1 << 11, + FixedAndStickyLayersOnly = 1 << 12, ++ OmitDeviceScaleFactor = 1 << 13, }; struct SnapshotOptions { diff --git a/Source/WebCore/page/History.cpp b/Source/WebCore/page/History.cpp -index 28dacedeebc77b2da6428cdbe166581c96348dfa..9c5bfaf9c81c2e5904f69071ee674363ee9decf8 100644 +index adc6185687b6fcee3a49819d0149cde24a4485bf..a33e5db46933c514abce86e3f264de9b7e7c20d9 100644 --- a/Source/WebCore/page/History.cpp +++ b/Source/WebCore/page/History.cpp @@ -32,6 +32,7 @@ @@ -5489,27 +5648,28 @@ index 28dacedeebc77b2da6428cdbe166581c96348dfa..9c5bfaf9c81c2e5904f69071ee674363 #include "LocalFrame.h" #include "LocalFrameLoaderClient.h" #include "Logging.h" -@@ -298,6 +299,7 @@ ExceptionOr History::stateObjectAdded(RefPtr&& data +@@ -309,6 +310,8 @@ ExceptionOr History::stateObjectAdded(RefPtr&& data + } - if (!urlString.isEmpty()) - frame->protectedDocument()->updateURLForPushOrReplaceState(fullURL); + frame->loader().updateURLAndHistory(fullURL, WTFMove(data), historyBehavior); + InspectorInstrumentation::didNavigateWithinPage(*frame); ++ + return { }; + } - if (stateObjectType == StateObjectType::Push) { - frame->loader().history().pushState(WTFMove(data), fullURL.string()); diff --git a/Source/WebCore/page/LocalFrame.cpp b/Source/WebCore/page/LocalFrame.cpp -index 9f480cb9a6000333711f0e9630522ddc77534015..f2d62e42e926b0d1d53f3a9feb3ce4ea93507ca3 100644 +index f6e26519619d560b5edddb30170f166ac76bd57f..51019ccda3f5953c4a154c271690f3923c1a530a 100644 --- a/Source/WebCore/page/LocalFrame.cpp +++ b/Source/WebCore/page/LocalFrame.cpp -@@ -40,6 +40,7 @@ +@@ -42,6 +42,7 @@ #include "CachedResourceLoader.h" #include "Chrome.h" #include "ChromeClient.h" +#include "ComposedTreeIterator.h" + #include "DiagnosticLoggingClient.h" + #include "DiagnosticLoggingKeys.h" #include "DocumentLoader.h" - #include "DocumentTimelinesController.h" - #include "DocumentType.h" -@@ -57,6 +58,7 @@ +@@ -60,6 +61,7 @@ #include "FrameSelection.h" #include "GraphicsContext.h" #include "GraphicsLayer.h" @@ -5517,23 +5677,23 @@ index 9f480cb9a6000333711f0e9630522ddc77534015..f2d62e42e926b0d1d53f3a9feb3ce4ea #include "HTMLAttachmentElement.h" #include "HTMLFormControlElement.h" #include "HTMLFormElement.h" -@@ -77,6 +79,7 @@ +@@ -82,6 +84,7 @@ #include "Logging.h" #include "Navigator.h" #include "NodeList.h" +#include "NodeRenderStyle.h" #include "NodeTraversal.h" #include "Page.h" - #include "ProcessWarming.h" -@@ -187,6 +190,7 @@ LocalFrame::LocalFrame(Page& page, UniqueRef&& frameLoad + #include "PaymentSession.h" +@@ -217,6 +220,7 @@ LocalFrame::LocalFrame(Page& page, ClientCreator&& clientCreator, FrameIdentifie void LocalFrame::init() { + InspectorInstrumentation::frameAttached(this); - checkedLoader()->init(); + protectedLoader()->init(); } -@@ -411,7 +415,7 @@ void LocalFrame::orientationChanged() +@@ -444,7 +448,7 @@ void LocalFrame::orientationChanged() IntDegrees LocalFrame::orientation() const { if (RefPtr page = this->page()) @@ -5542,8 +5702,8 @@ index 9f480cb9a6000333711f0e9630522ddc77534015..f2d62e42e926b0d1d53f3a9feb3ce4ea return 0; } #endif // ENABLE(ORIENTATION_EVENTS) -@@ -1340,6 +1344,362 @@ String LocalFrame::customUserAgentAsSiteSpecificQuirks() const - return { }; +@@ -1599,6 +1603,364 @@ RefPtr LocalFrame::frameDocumentSecurityOrigin() const + return nullptr; } +#if !PLATFORM(IOS_FAMILY) @@ -5592,6 +5752,7 @@ index 9f480cb9a6000333711f0e9630522ddc77534015..f2d62e42e926b0d1d53f3a9feb3ce4ea + return true; +} + ++WTF_ALLOW_UNSAFE_BUFFER_USAGE_BEGIN +Node* LocalFrame::qualifyingNodeAtViewportLocation(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation, const NodeQualifier& nodeQualifierFunction, ShouldApproximate shouldApproximate, ShouldFindRootEditableElement shouldFindRootEditableElement) +{ + adjustedViewportLocation = viewportLocation; @@ -5703,6 +5864,7 @@ index 9f480cb9a6000333711f0e9630522ddc77534015..f2d62e42e926b0d1d53f3a9feb3ce4ea + + return approximateNode; +} ++WTF_ALLOW_UNSAFE_BUFFER_USAGE_END + +Node* LocalFrame::deepestNodeAtLocation(const FloatPoint& viewportLocation) +{ @@ -5906,29 +6068,18 @@ index 9f480cb9a6000333711f0e9630522ddc77534015..f2d62e42e926b0d1d53f3a9feb3ce4ea #undef FRAME_RELEASE_LOG_ERROR diff --git a/Source/WebCore/page/LocalFrame.h b/Source/WebCore/page/LocalFrame.h -index 976a7e01a1a83902d2eddcdbe044c1ec1cd9a7b8..d548c31e6beffe704b8093669ee07d576941a50a 100644 +index 7e8505e025af3f52a0adbd5e6b98d6a22f449d9c..667a9578f073c216231ca8834354c1d5ce49370d 100644 --- a/Source/WebCore/page/LocalFrame.h +++ b/Source/WebCore/page/LocalFrame.h -@@ -28,8 +28,10 @@ - #pragma once +@@ -29,6 +29,7 @@ - #include "AdjustViewSizeOrNot.h" -+#include "DOMPasteAccess.h" - #include "Document.h" + #include "DOMPasteAccess.h" #include "Frame.h" +#include "IntDegrees.h" - #include "ScrollTypes.h" - #include "UserScriptTypes.h" + #include "ScrollbarMode.h" #include -@@ -70,7 +72,6 @@ namespace WebCore { - class Color; - class LocalDOMWindow; - class DataDetectionResultsStorage; --class Document; - class Editor; - class Element; - class EventHandler; -@@ -111,8 +112,8 @@ enum { + #include +@@ -122,8 +123,8 @@ enum { }; enum OverflowScrollAction { DoNotPerformOverflowScroll, PerformOverflowScroll }; @@ -5938,7 +6089,7 @@ index 976a7e01a1a83902d2eddcdbe044c1ec1cd9a7b8..d548c31e6beffe704b8093669ee07d57 class LocalFrame final : public Frame { public: -@@ -219,10 +220,6 @@ public: +@@ -233,10 +234,6 @@ public: WEBCORE_EXPORT DataDetectionResultsStorage& dataDetectionResults(); #endif @@ -5949,7 +6100,7 @@ index 976a7e01a1a83902d2eddcdbe044c1ec1cd9a7b8..d548c31e6beffe704b8093669ee07d57 WEBCORE_EXPORT Node* deepestNodeAtLocation(const FloatPoint& viewportLocation); WEBCORE_EXPORT Node* nodeRespondingToClickEvents(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation, SecurityOrigin* = nullptr); WEBCORE_EXPORT Node* nodeRespondingToDoubleClickEvent(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation); -@@ -230,6 +227,10 @@ public: +@@ -244,6 +241,10 @@ public: WEBCORE_EXPORT Node* nodeRespondingToScrollWheelEvents(const FloatPoint& viewportLocation); WEBCORE_EXPORT Node* approximateNodeAtViewportLocationLegacy(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation); @@ -5960,15 +6111,15 @@ index 976a7e01a1a83902d2eddcdbe044c1ec1cd9a7b8..d548c31e6beffe704b8093669ee07d57 WEBCORE_EXPORT NSArray *wordsInCurrentParagraph() const; WEBCORE_EXPORT CGRect renderRectForPoint(CGPoint, bool* isReplaced, float* fontSize) const; -@@ -297,6 +298,7 @@ public: +@@ -311,6 +312,7 @@ public: WEBCORE_EXPORT FloatSize screenSize() const; void setOverrideScreenSize(FloatSize&&); -+ bool hasScreenSizeOverride() const { return !m_overrideScreenSize.isEmpty(); } ++ bool hasScreenSizeOverride() const { return !!m_overrideScreenSize; } void selfOnlyRef(); void selfOnlyDeref(); -@@ -352,7 +354,6 @@ private: +@@ -382,7 +384,6 @@ private: #if ENABLE(DATA_DETECTION) std::unique_ptr m_dataDetectionResults; #endif @@ -5976,20 +6127,20 @@ index 976a7e01a1a83902d2eddcdbe044c1ec1cd9a7b8..d548c31e6beffe704b8093669ee07d57 void betterApproximateNode(const IntPoint& testPoint, const NodeQualifier&, Node*& best, Node* failedNode, IntPoint& bestPoint, IntRect& bestRect, const IntRect& testRect); bool hitTestResultAtViewportLocation(const FloatPoint& viewportLocation, HitTestResult&, IntPoint& center); -@@ -360,6 +361,7 @@ private: +@@ -390,6 +391,7 @@ private: enum class ShouldFindRootEditableElement : bool { No, Yes }; Node* qualifyingNodeAtViewportLocation(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation, const NodeQualifier&, ShouldApproximate, ShouldFindRootEditableElement = ShouldFindRootEditableElement::Yes); +#if PLATFORM(IOS_FAMILY) void setTimersPausedInternal(bool); - ViewportArguments m_viewportArguments; + UniqueRef m_viewportArguments; diff --git a/Source/WebCore/page/Page.cpp b/Source/WebCore/page/Page.cpp -index 2da22620311314dc67bec3563c7f1b6525bd7b28..e7c530d193fe0c318dfa89f5ae72e3598bdf44bd 100644 +index 08315ed1fb551d8ad9f9a7dcdc4fea487cd9a8fb..44cf9866c35e309cb90138b73c3d35e5409aa7eb 100644 --- a/Source/WebCore/page/Page.cpp +++ b/Source/WebCore/page/Page.cpp -@@ -569,6 +569,45 @@ void Page::setOverrideViewportArguments(const std::optional& - document->updateViewportArguments(); +@@ -663,6 +663,45 @@ void Page::setOverrideViewportArguments(const std::optional& + localTopDocument->updateViewportArguments(); } +FloatSize Page::screenSize() @@ -6034,8 +6185,8 @@ index 2da22620311314dc67bec3563c7f1b6525bd7b28..e7c530d193fe0c318dfa89f5ae72e359 ScrollingCoordinator* Page::scrollingCoordinator() { if (!m_scrollingCoordinator && m_settings->scrollingCoordinatorEnabled()) { -@@ -3870,6 +3909,26 @@ void Page::setUseDarkAppearanceOverride(std::optional valueOverride) - #endif +@@ -4242,6 +4281,26 @@ void Page::setUseDarkAppearanceOverride(std::optional valueOverride) + appearanceDidChange(); } +void Page::setUseReducedMotionOverride(std::optional valueOverride) @@ -6062,11 +6213,11 @@ index 2da22620311314dc67bec3563c7f1b6525bd7b28..e7c530d193fe0c318dfa89f5ae72e359 { if (insets == m_fullscreenInsets) diff --git a/Source/WebCore/page/Page.h b/Source/WebCore/page/Page.h -index 551ffa245a63f05cd7d58a86048ed22c1feb6205..cd1ce84ec63f5ed8ae75178f79c35b9fd91b37f7 100644 +index 9f107570fbb2195211ad46358369acb791e0376b..8c753ef756e9fe64ffdca36683ec486edb758f6b 100644 --- a/Source/WebCore/page/Page.h +++ b/Source/WebCore/page/Page.h -@@ -316,6 +316,9 @@ public: - const std::optional& overrideViewportArguments() const { return m_overrideViewportArguments; } +@@ -389,6 +389,9 @@ public: + const ViewportArguments* overrideViewportArguments() const { return m_overrideViewportArguments.get(); } WEBCORE_EXPORT void setOverrideViewportArguments(const std::optional&); + WEBCORE_EXPORT FloatSize screenSize(); @@ -6074,8 +6225,8 @@ index 551ffa245a63f05cd7d58a86048ed22c1feb6205..cd1ce84ec63f5ed8ae75178f79c35b9f + static void refreshPlugins(bool reload); WEBCORE_EXPORT PluginData& pluginData(); - void clearPluginData(); -@@ -380,6 +383,10 @@ public: + WEBCORE_EXPORT Ref protectedPluginData(); +@@ -486,6 +489,10 @@ public: #if ENABLE(DRAG_SUPPORT) DragController& dragController() { return m_dragController.get(); } const DragController& dragController() const { return m_dragController.get(); } @@ -6086,8 +6237,8 @@ index 551ffa245a63f05cd7d58a86048ed22c1feb6205..cd1ce84ec63f5ed8ae75178f79c35b9f #endif FocusController& focusController() const { return *m_focusController; } WEBCORE_EXPORT CheckedRef checkedFocusController() const; -@@ -563,6 +570,10 @@ public: - WEBCORE_EXPORT void effectiveAppearanceDidChange(bool useDarkAppearance, bool useElevatedUserInterfaceLevel); +@@ -671,6 +678,10 @@ public: + WEBCORE_EXPORT void setUseColorAppearance(bool useDarkAppearance, bool useElevatedUserInterfaceLevel); bool defaultUseDarkAppearance() const { return m_useDarkAppearance; } void setUseDarkAppearanceOverride(std::optional); + std::optional useReducedMotionOverride() const { return m_useReducedMotionOverride; } @@ -6097,29 +6248,29 @@ index 551ffa245a63f05cd7d58a86048ed22c1feb6205..cd1ce84ec63f5ed8ae75178f79c35b9f #if ENABLE(TEXT_AUTOSIZING) float textAutosizingWidth() const { return m_textAutosizingWidth; } -@@ -1011,6 +1022,11 @@ public: +@@ -1143,6 +1154,11 @@ public: WEBCORE_EXPORT void setInteractionRegionsEnabled(bool); #endif +#if ENABLE(ORIENTATION_EVENTS) + int orientation() const; -+ void setOverrideOrientation(std::optional); ++ WEBCORE_EXPORT void setOverrideOrientation(std::optional); +#endif + #if ENABLE(DEVICE_ORIENTATION) && PLATFORM(IOS_FAMILY) DeviceOrientationUpdateProvider* deviceOrientationUpdateProvider() const { return m_deviceOrientationUpdateProvider.get(); } #endif -@@ -1181,6 +1197,9 @@ private: +@@ -1424,6 +1440,9 @@ private: #if ENABLE(DRAG_SUPPORT) - UniqueRef m_dragController; + const UniqueRef m_dragController; +#if PLATFORM(MAC) + String m_overrideDragPasteboardName; +#endif #endif std::unique_ptr m_focusController; #if ENABLE(CONTEXT_MENUS) -@@ -1259,6 +1278,8 @@ private: +@@ -1502,6 +1521,8 @@ private: bool m_useElevatedUserInterfaceLevel { false }; bool m_useDarkAppearance { false }; std::optional m_useDarkAppearanceOverride; @@ -6128,10 +6279,10 @@ index 551ffa245a63f05cd7d58a86048ed22c1feb6205..cd1ce84ec63f5ed8ae75178f79c35b9f #if ENABLE(TEXT_AUTOSIZING) float m_textAutosizingWidth { 0 }; -@@ -1437,6 +1458,11 @@ private: +@@ -1683,6 +1704,11 @@ private: #endif - std::optional m_overrideViewportArguments; + std::unique_ptr m_overrideViewportArguments; + std::optional m_overrideScreenSize; + +#if ENABLE(ORIENTATION_EVENTS) @@ -6141,10 +6292,10 @@ index 551ffa245a63f05cd7d58a86048ed22c1feb6205..cd1ce84ec63f5ed8ae75178f79c35b9f #if ENABLE(DEVICE_ORIENTATION) && PLATFORM(IOS_FAMILY) RefPtr m_deviceOrientationUpdateProvider; diff --git a/Source/WebCore/page/PageConsoleClient.cpp b/Source/WebCore/page/PageConsoleClient.cpp -index 18e3cde7b9ae368de4b87c88c2f8324b77cbd7c8..1ebc51b6d81fc6ae17124e7be7da039609df03d0 100644 +index e3f5517e30956f17aea53324fc3c5ce11238254c..278ddea00b98d979797e1e82a5cb3f97239b63bc 100644 --- a/Source/WebCore/page/PageConsoleClient.cpp +++ b/Source/WebCore/page/PageConsoleClient.cpp -@@ -439,4 +439,9 @@ Ref PageConsoleClient::protectedPage() const +@@ -456,4 +456,9 @@ Ref PageConsoleClient::protectedPage() const return m_page.get(); } @@ -6155,10 +6306,10 @@ index 18e3cde7b9ae368de4b87c88c2f8324b77cbd7c8..1ebc51b6d81fc6ae17124e7be7da0396 + } // namespace WebCore diff --git a/Source/WebCore/page/PageConsoleClient.h b/Source/WebCore/page/PageConsoleClient.h -index 6ee10d6ca68ad8ea93ae45adb0876c80953d3278..d4e14d54af6cd21fc5649d18dbc6af2020fae4a2 100644 +index 153fc36199f26adbfb61cbef6744ffe31a68b951..cc667e06700013fd5e994467e19536d2e4cab189 100644 --- a/Source/WebCore/page/PageConsoleClient.h +++ b/Source/WebCore/page/PageConsoleClient.h -@@ -85,6 +85,7 @@ private: +@@ -86,6 +86,7 @@ private: void record(JSC::JSGlobalObject*, Ref&&) override; void recordEnd(JSC::JSGlobalObject*, Ref&&) override; void screenshot(JSC::JSGlobalObject*, Ref&&) override; @@ -6167,10 +6318,10 @@ index 6ee10d6ca68ad8ea93ae45adb0876c80953d3278..d4e14d54af6cd21fc5649d18dbc6af20 Ref protectedPage() const; diff --git a/Source/WebCore/page/PointerCaptureController.cpp b/Source/WebCore/page/PointerCaptureController.cpp -index 315c1bbcff9bdacc7e25eb91d8d4d2ede4d61a9a..8e918fe4a64a425814fd8d4b951bf48dda74fde8 100644 +index 7f0fe2766310d43552d12b85d1484cc095a752a4..1ab97c02215826ad9210489b64573145755a1b4f 100644 --- a/Source/WebCore/page/PointerCaptureController.cpp +++ b/Source/WebCore/page/PointerCaptureController.cpp -@@ -195,7 +195,7 @@ bool PointerCaptureController::preventsCompatibilityMouseEventsForIdentifier(Poi +@@ -207,7 +207,7 @@ bool PointerCaptureController::preventsCompatibilityMouseEventsForIdentifier(Poi return capturingData && capturingData->preventsCompatibilityMouseEvents; } @@ -6179,7 +6330,7 @@ index 315c1bbcff9bdacc7e25eb91d8d4d2ede4d61a9a..8e918fe4a64a425814fd8d4b951bf48d static bool hierarchyHasCapturingEventListeners(Element* target, const AtomString& eventName) { for (RefPtr currentNode = target; currentNode; currentNode = currentNode->parentInComposedTree()) { -@@ -501,7 +501,7 @@ void PointerCaptureController::cancelPointer(PointerID pointerId, const IntPoint +@@ -557,7 +557,7 @@ void PointerCaptureController::cancelPointer(PointerID pointerId, const IntPoint capturingData->pendingTargetOverride = nullptr; capturingData->state = CapturingData::State::Cancelled; @@ -6189,10 +6340,10 @@ index 315c1bbcff9bdacc7e25eb91d8d4d2ede4d61a9a..8e918fe4a64a425814fd8d4b951bf48d #endif diff --git a/Source/WebCore/page/PointerCaptureController.h b/Source/WebCore/page/PointerCaptureController.h -index 91a9847a4083393e225f42e71c2dd590a88c0289..b0838c84e4ba24378db42f40a68856afe95fb9a7 100644 +index e50f38c2c45f665b4b88fe1aa4f99d1a51328d63..8144be1724ef71a93b8870f64ec5abcb98eaa27f 100644 --- a/Source/WebCore/page/PointerCaptureController.h +++ b/Source/WebCore/page/PointerCaptureController.h -@@ -58,7 +58,7 @@ public: +@@ -60,7 +60,7 @@ public: RefPtr pointerEventForMouseEvent(const MouseEvent&, PointerID, const String& pointerType); @@ -6201,8 +6352,8 @@ index 91a9847a4083393e225f42e71c2dd590a88c0289..b0838c84e4ba24378db42f40a68856af void dispatchEventForTouchAtIndex(EventTarget&, const PlatformTouchEvent&, unsigned, bool isPrimary, WindowProxy&, const IntPoint&); #endif -@@ -78,12 +78,12 @@ private: - +@@ -81,12 +81,12 @@ private: + WeakPtr activeDocument; RefPtr pendingTargetOverride; RefPtr targetOverride; -#if ENABLE(TOUCH_EVENTS) && (PLATFORM(IOS_FAMILY) || PLATFORM(WPE)) @@ -6217,11 +6368,11 @@ index 91a9847a4083393e225f42e71c2dd590a88c0289..b0838c84e4ba24378db42f40a68856af #endif ; diff --git a/Source/WebCore/page/Screen.cpp b/Source/WebCore/page/Screen.cpp -index 4e4dfdebe954bf3f047d3a86a758dfd0913f732e..da2bcd0256cdfc2ba28fb07094abd0b6f9c5f754 100644 +index 24ed7c019bea4df52f2883db0e40bdbc2dc74ebd..a788f534d9e0e8124153c7f380b4fdb232c51a1a 100644 --- a/Source/WebCore/page/Screen.cpp +++ b/Source/WebCore/page/Screen.cpp -@@ -111,6 +111,9 @@ int Screen::availLeft() const - if (fingerprintingProtectionsEnabled(*frame)) +@@ -124,6 +124,9 @@ int Screen::availLeft() const + if (shouldApplyScreenFingerprintingProtections(*frame)) return 0; + if (frame->hasScreenSizeOverride()) @@ -6230,8 +6381,8 @@ index 4e4dfdebe954bf3f047d3a86a758dfd0913f732e..da2bcd0256cdfc2ba28fb07094abd0b6 return static_cast(screenAvailableRect(frame->protectedView().get()).x()); } -@@ -126,6 +129,9 @@ int Screen::availTop() const - if (fingerprintingProtectionsEnabled(*frame)) +@@ -139,6 +142,9 @@ int Screen::availTop() const + if (shouldApplyScreenFingerprintingProtections(*frame)) return 0; + if (frame->hasScreenSizeOverride()) @@ -6240,8 +6391,8 @@ index 4e4dfdebe954bf3f047d3a86a758dfd0913f732e..da2bcd0256cdfc2ba28fb07094abd0b6 return static_cast(screenAvailableRect(frame->protectedView().get()).y()); } -@@ -141,6 +147,9 @@ int Screen::availHeight() const - if (fingerprintingProtectionsEnabled(*frame)) +@@ -154,6 +160,9 @@ int Screen::availHeight() const + if (shouldApplyScreenFingerprintingProtections(*frame)) return static_cast(frame->screenSize().height()); + if (frame->hasScreenSizeOverride()) @@ -6250,8 +6401,8 @@ index 4e4dfdebe954bf3f047d3a86a758dfd0913f732e..da2bcd0256cdfc2ba28fb07094abd0b6 return static_cast(screenAvailableRect(frame->protectedView().get()).height()); } -@@ -156,6 +165,9 @@ int Screen::availWidth() const - if (fingerprintingProtectionsEnabled(*frame)) +@@ -169,6 +178,9 @@ int Screen::availWidth() const + if (shouldApplyScreenFingerprintingProtections(*frame)) return static_cast(frame->screenSize().width()); + if (frame->hasScreenSizeOverride()) @@ -6261,19 +6412,19 @@ index 4e4dfdebe954bf3f047d3a86a758dfd0913f732e..da2bcd0256cdfc2ba28fb07094abd0b6 } diff --git a/Source/WebCore/page/csp/ContentSecurityPolicy.cpp b/Source/WebCore/page/csp/ContentSecurityPolicy.cpp -index a35951b3150fe859450c5f781e44032078ca5f74..7fd0c71777a3fb451f3bd97b16911c01e5aa2203 100644 +index e8cf919fd1d0147fce390aa5750843a6bce40190..fb2d56e3a3b6901f993544e297ad678c469a9cc1 100644 --- a/Source/WebCore/page/csp/ContentSecurityPolicy.cpp +++ b/Source/WebCore/page/csp/ContentSecurityPolicy.cpp -@@ -336,6 +336,8 @@ bool ContentSecurityPolicy::allowContentSecurityPolicySourceStarToMatchAnyProtoc - template - typename std::enable_if::value, bool>::type ContentSecurityPolicy::allPoliciesWithDispositionAllow(Disposition disposition, Predicate&& predicate, Args&&... args) const +@@ -374,6 +374,8 @@ template + bool ContentSecurityPolicy::allPoliciesWithDispositionAllow(Disposition disposition, Predicate&& predicate, Args&&... args) const + requires (!std::is_convertible_v) { + if (InspectorInstrumentation::shouldBypassCSP(m_scriptExecutionContext.get())) + return true; bool isReportOnly = disposition == ContentSecurityPolicy::Disposition::ReportOnly; for (auto& policy : m_policies) { if (policy->isReportOnly() != isReportOnly) -@@ -349,6 +351,8 @@ typename std::enable_if bool ContentSecurityPolicy::allPoliciesWithDispositionAllow(Disposition disposition, ViolatedDirectiveCallback&& callback, Predicate&& predicate, Args&&... args) const { @@ -6282,9 +6433,9 @@ index a35951b3150fe859450c5f781e44032078ca5f74..7fd0c71777a3fb451f3bd97b16911c01 bool isReportOnly = disposition == ContentSecurityPolicy::Disposition::ReportOnly; bool isAllowed = true; for (auto& policy : m_policies) { -@@ -365,6 +369,8 @@ bool ContentSecurityPolicy::allPoliciesWithDispositionAllow(Disposition disposit +@@ -403,6 +407,8 @@ bool ContentSecurityPolicy::allPoliciesWithDispositionAllow(Disposition disposit template - bool ContentSecurityPolicy::allPoliciesAllow(ViolatedDirectiveCallback&& callback, Predicate&& predicate, Args&&... args) const + bool ContentSecurityPolicy::allPoliciesAllow(NOESCAPE const ViolatedDirectiveCallback& callback, Predicate&& predicate, Args&&... args) const { + if (InspectorInstrumentation::shouldBypassCSP(m_scriptExecutionContext.get())) + return true; @@ -6377,20 +6528,8 @@ index 0000000000000000000000000000000000000000..803239911006cfb3b03ea911c003f2d2 +} + +} -diff --git a/Source/WebCore/platform/Cairo.cmake b/Source/WebCore/platform/Cairo.cmake -index 29492dd39b08db28aad2bf2439eb3e2bbcf25ad7..2b603cb8440b1b5057c87fcbd6909c61bae4ceb8 100644 ---- a/Source/WebCore/platform/Cairo.cmake -+++ b/Source/WebCore/platform/Cairo.cmake -@@ -14,6 +14,7 @@ list(APPEND WebCore_PRIVATE_FRAMEWORK_HEADERS - platform/graphics/cairo/ImageBufferCairoBackend.h - platform/graphics/cairo/ImageBufferCairoImageSurfaceBackend.h - platform/graphics/cairo/ImageBufferCairoSurfaceBackend.h -+ platform/graphics/cairo/ImageBufferUtilitiesCairo.h - platform/graphics/cairo/RefPtrCairo.h - ) - diff --git a/Source/WebCore/platform/DragData.h b/Source/WebCore/platform/DragData.h -index 35cce31f0f77478754a7859c16f42b6a7ec6edda..03660bd492fad8863aeb21d73a54e7b914147f09 100644 +index 2ebb3221cb3818f20abc7b7c3307ea7644f49d49..e0bffb6f5adee0b0a202340f633c2def1955b384 100644 --- a/Source/WebCore/platform/DragData.h +++ b/Source/WebCore/platform/DragData.h @@ -47,7 +47,7 @@ typedef void* DragDataRef; @@ -6413,7 +6552,7 @@ index 35cce31f0f77478754a7859c16f42b6a7ec6edda..03660bd492fad8863aeb21d73a54e7b9 void getDragFileDescriptorData(int& size, String& pathname); void getDragFileContentData(int size, void* dataBlob); #endif -@@ -141,7 +141,7 @@ private: +@@ -143,7 +143,7 @@ private: String m_pasteboardName; #endif #if PLATFORM(WIN) @@ -6423,7 +6562,7 @@ index 35cce31f0f77478754a7859c16f42b6a7ec6edda..03660bd492fad8863aeb21d73a54e7b9 bool m_disallowFileAccess { false }; }; diff --git a/Source/WebCore/platform/DragImage.cpp b/Source/WebCore/platform/DragImage.cpp -index dc894343a5d9ce0e45a370a83bebf97fdcbeccc5..00003bd9bada8f134b6cc49f47c8c5cb459d1ebd 100644 +index 41b4b3ca89d0df2ccba562d83c33097539b5ae1c..071bee507b730b89796420222b9787bd411a19ad 100644 --- a/Source/WebCore/platform/DragImage.cpp +++ b/Source/WebCore/platform/DragImage.cpp @@ -280,7 +280,7 @@ DragImage::~DragImage() @@ -6435,11 +6574,24 @@ index dc894343a5d9ce0e45a370a83bebf97fdcbeccc5..00003bd9bada8f134b6cc49f47c8c5cb IntSize dragImageSize(DragImageRef) { +diff --git a/Source/WebCore/platform/DragImage.h b/Source/WebCore/platform/DragImage.h +index 77286d8e715825c9c7c0d329480fc0fc497fe561..5ea53eb8b7e53dd5a5950c65a38c1d23bfe46681 100644 +--- a/Source/WebCore/platform/DragImage.h ++++ b/Source/WebCore/platform/DragImage.h +@@ -60,7 +60,7 @@ class Node; + typedef RetainPtr DragImageRef; + #elif PLATFORM(MAC) + typedef RetainPtr DragImageRef; +-#elif PLATFORM(WIN) ++#elif PLATFORM(WIN) && USE(CAIRO) + typedef HBITMAP DragImageRef; + #elif USE(CAIRO) + typedef RefPtr DragImageRef; diff --git a/Source/WebCore/platform/Pasteboard.h b/Source/WebCore/platform/Pasteboard.h -index 2203effb3a0a745170680a23d0ff07f3a1a1cd1b..11c0fe944d603349087c942caff9081d819c40da 100644 +index f8de8815d483bd3ac684c018159c593798c0495a..e84ce8eec7424fbc3456623289588b1832d9fb7f 100644 --- a/Source/WebCore/platform/Pasteboard.h +++ b/Source/WebCore/platform/Pasteboard.h -@@ -45,7 +45,7 @@ OBJC_CLASS NSString; +@@ -46,7 +46,7 @@ OBJC_CLASS NSString; OBJC_CLASS NSArray; #endif @@ -6448,17 +6600,8 @@ index 2203effb3a0a745170680a23d0ff07f3a1a1cd1b..11c0fe944d603349087c942caff9081d #include "SelectionData.h" #endif -@@ -108,7 +108,7 @@ struct PasteboardURL { - #if PLATFORM(MAC) - String userVisibleForm; - #endif --#if PLATFORM(GTK) -+#if PLATFORM(GTK) || PLATFORM(WPE) - String markup; - #endif - }; -@@ -197,6 +197,11 @@ public: - #endif +@@ -200,6 +200,11 @@ public: + explicit Pasteboard(std::unique_ptr&&, const String& name); #endif +#if PLATFORM(WPE) && ENABLE(DRAG_SUPPORT) @@ -6469,8 +6612,8 @@ index 2203effb3a0a745170680a23d0ff07f3a1a1cd1b..11c0fe944d603349087c942caff9081d #if PLATFORM(WIN) explicit Pasteboard(std::unique_ptr&&, IDataObject*); explicit Pasteboard(std::unique_ptr&&, WCDataObject*); -@@ -264,6 +269,12 @@ public: - int64_t changeCount() const; +@@ -266,6 +271,12 @@ public: + static std::unique_ptr createForGlobalSelection(std::unique_ptr&&); #endif +#if PLATFORM(WPE) @@ -6482,7 +6625,7 @@ index 2203effb3a0a745170680a23d0ff07f3a1a1cd1b..11c0fe944d603349087c942caff9081d #if PLATFORM(IOS_FAMILY) explicit Pasteboard(std::unique_ptr&&, int64_t changeCount); explicit Pasteboard(std::unique_ptr&&, const String& pasteboardName); -@@ -306,6 +317,7 @@ public: +@@ -311,6 +322,7 @@ public: COMPtr dataObject() const { return m_dataObject; } WEBCORE_EXPORT void setExternalDataObject(IDataObject*); const DragDataMap& dragDataMap() const { return m_dragDataMap; } @@ -6490,7 +6633,7 @@ index 2203effb3a0a745170680a23d0ff07f3a1a1cd1b..11c0fe944d603349087c942caff9081d void writeURLToWritableDataObject(const URL&, const String&); COMPtr writableDataObject() const { return m_writableDataObject; } void writeImageToDataObject(Element&, const URL&); // FIXME: Layering violation. -@@ -358,6 +370,10 @@ private: +@@ -366,6 +378,10 @@ private: int64_t m_changeCount { 0 }; #endif @@ -6501,7 +6644,7 @@ index 2203effb3a0a745170680a23d0ff07f3a1a1cd1b..11c0fe944d603349087c942caff9081d #if PLATFORM(COCOA) String m_pasteboardName; int64_t m_changeCount; -@@ -373,6 +389,7 @@ private: +@@ -381,6 +397,7 @@ private: COMPtr m_dataObject; COMPtr m_writableDataObject; DragDataMap m_dragDataMap; @@ -6510,10 +6653,10 @@ index 2203effb3a0a745170680a23d0ff07f3a1a1cd1b..11c0fe944d603349087c942caff9081d }; diff --git a/Source/WebCore/platform/PlatformKeyboardEvent.h b/Source/WebCore/platform/PlatformKeyboardEvent.h -index 4aa768e1c2a8da63004f34ccbf0d347b2484c37b..515c99ed21cde6c157bb9a1378a783727cffc6e7 100644 +index 63ffd6ca32c3baee03db2a9419c4f7e9de45388a..c60c7a8d1f110472117c8c4e969fd05fef71f908 100644 --- a/Source/WebCore/platform/PlatformKeyboardEvent.h +++ b/Source/WebCore/platform/PlatformKeyboardEvent.h -@@ -134,6 +134,7 @@ namespace WebCore { +@@ -135,6 +135,7 @@ namespace WebCore { static String keyCodeForHardwareKeyCode(unsigned); static String keyIdentifierForGdkKeyCode(unsigned); static int windowsKeyCodeForGdkKeyCode(unsigned); @@ -6521,7 +6664,7 @@ index 4aa768e1c2a8da63004f34ccbf0d347b2484c37b..515c99ed21cde6c157bb9a1378a78372 static String singleCharacterString(unsigned); #endif -@@ -142,6 +143,7 @@ namespace WebCore { +@@ -143,6 +144,7 @@ namespace WebCore { static String keyCodeForHardwareKeyCode(unsigned); static String keyIdentifierForWPEKeyCode(unsigned); static int windowsKeyCodeForWPEKeyCode(unsigned); @@ -6530,18 +6673,10 @@ index 4aa768e1c2a8da63004f34ccbf0d347b2484c37b..515c99ed21cde6c157bb9a1378a78372 #endif diff --git a/Source/WebCore/platform/PlatformScreen.cpp b/Source/WebCore/platform/PlatformScreen.cpp -index ae46341ba71c7f6df7c607bd852338cdb7f83fe1..b318c0771192344a6891c1f097cb0b93dabe8237 100644 +index ef0abc9a93e878897ffc9d2497a3da0fca5b37b7..abd96c6d1a6c3ab9e0121c1e78f2f75a5f805b32 100644 --- a/Source/WebCore/platform/PlatformScreen.cpp +++ b/Source/WebCore/platform/PlatformScreen.cpp -@@ -25,6 +25,7 @@ - - #include "config.h" - #include "PlatformScreen.h" -+#include "DeprecatedGlobalSettings.h" - - #if PLATFORM(COCOA) || PLATFORM(GTK) || (PLATFORM(WPE) && ENABLE(WPE_PLATFORM)) - -@@ -73,3 +74,25 @@ const ScreenData* screenData(PlatformDisplayID screenDisplayID) +@@ -85,3 +85,24 @@ OptionSet screenContentsFormatsForTesting() } // namespace WebCore #endif // PLATFORM(COCOA) || PLATFORM(GTK) || (PLATFORM(WPE) && ENABLE(WPE_PLATFORM)) @@ -6549,57 +6684,51 @@ index ae46341ba71c7f6df7c607bd852338cdb7f83fe1..b318c0771192344a6891c1f097cb0b93 +#if ENABLE(TOUCH_EVENTS) +namespace WebCore { + -+static std::optional screenHasTouchDeviceOverride = std::nullopt; ++static std::optional _screenHasTouchDeviceOverride = std::nullopt; ++ +void setScreenHasTouchDeviceOverride(bool value) { -+ screenHasTouchDeviceOverride = value; ++ _screenHasTouchDeviceOverride = value; ++} ++std::optional screenHasTouchDeviceOverride() { ++ return _screenHasTouchDeviceOverride; +} + +bool screenHasTouchDevice() { -+ if (screenHasTouchDeviceOverride) -+ return screenHasTouchDeviceOverride.value(); ++ if (screenHasTouchDeviceOverride()) ++ return screenHasTouchDeviceOverride().value(); + return platformScreenHasTouchDevice(); +} -+bool screenIsTouchPrimaryInputDevice() { -+ if (screenHasTouchDeviceOverride) -+ return screenHasTouchDeviceOverride.value(); -+ return platformScreenIsTouchPrimaryInputDevice(); -+} + +} // namespace WebCore +#endif diff --git a/Source/WebCore/platform/PlatformScreen.h b/Source/WebCore/platform/PlatformScreen.h -index 6c64c7040eb190c3d67380070e884a8230029c26..d0f8341c538cbc2323ac0074a5ef3226d00a5fd6 100644 +index 82a54ac2de2ddf4650e4b48db129fe25f6562264..d144ba15d18d2e892c25988dab27636135353a99 100644 --- a/Source/WebCore/platform/PlatformScreen.h +++ b/Source/WebCore/platform/PlatformScreen.h -@@ -151,13 +151,18 @@ WEBCORE_EXPORT float screenScaleFactor(UIScreen * = nullptr); +@@ -160,10 +160,14 @@ WEBCORE_EXPORT float screenScaleFactor(UIScreen * = nullptr); #endif #if ENABLE(TOUCH_EVENTS) --#if PLATFORM(GTK) || PLATFORM(WPE) +-#if PLATFORM(GTK) +WEBCORE_EXPORT void setScreenHasTouchDeviceOverride(bool); ++WEBCORE_EXPORT std::optional screenHasTouchDeviceOverride(); + WEBCORE_EXPORT bool screenHasTouchDevice(); - WEBCORE_EXPORT bool screenIsTouchPrimaryInputDevice(); -+#if PLATFORM(GTK) || PLATFORM(WPE) ++#if PLATFORM(GTK) +bool platformScreenHasTouchDevice(); -+bool platformScreenIsTouchPrimaryInputDevice(); #else -constexpr bool screenHasTouchDevice() { return true; } --constexpr bool screenIsTouchPrimaryInputDevice() { return true; } +constexpr bool platformScreenHasTouchDevice() { return true; } -+constexpr bool platformScreenIsTouchPrimaryInputDevice() { return true; } #endif #endif -+ - } // namespace WebCore diff --git a/Source/WebCore/platform/PlatformTouchEvent.h b/Source/WebCore/platform/PlatformTouchEvent.h -index 27b46407faf6ae9d245856fd0ed664984e8729f8..2b8912789dcda373ceffa8f23996566ff07df2dd 100644 +index 23f011953c66f401553bedfaef3485af215ae083..a73da2ebe47f0d8dc57f3d0159e8f299abb61c96 100644 --- a/Source/WebCore/platform/PlatformTouchEvent.h +++ b/Source/WebCore/platform/PlatformTouchEvent.h -@@ -38,7 +38,7 @@ public: +@@ -42,7 +42,7 @@ public: - const Vector& touchPoints() const { return m_touchPoints; } + const Vector& predictedEvents() const { return m_predictedEvents; } -#if PLATFORM(WPE) +#if !ENABLE(IOS_TOUCH_EVENTS) @@ -6619,11 +6748,23 @@ index 34715d27b529750fc866db87cd330b5184286771..3eefa218af075f76d98012cdeae7e4b3 // FIXME: since WPE currently does not send touch stationary events, we need to be able to // create a PlatformTouchPoint of type TouchCancelled artificially PlatformTouchPoint(unsigned id, State state, IntPoint screenPos, IntPoint pos) +diff --git a/Source/WebCore/platform/Skia.cmake b/Source/WebCore/platform/Skia.cmake +index c39b57e01190b833be46452c3d964fe243c216d3..6e4af1509037697421cf0c80e2459da0bad79ba8 100644 +--- a/Source/WebCore/platform/Skia.cmake ++++ b/Source/WebCore/platform/Skia.cmake +@@ -14,6 +14,7 @@ list(APPEND WebCore_PRIVATE_FRAMEWORK_HEADERS + platform/graphics/skia/FontCascadeSkiaInlines.h + platform/graphics/skia/GraphicsContextSkia.h + platform/graphics/skia/ImageBufferSkiaBackend.h ++ platform/graphics/skia/ImageBufferUtilitiesSkia.h + platform/graphics/skia/SkiaHarfBuzzFont.h + platform/graphics/skia/SkiaHarfBuzzFontCache.h + platform/graphics/skia/SkiaPaintingEngine.h diff --git a/Source/WebCore/platform/adwaita/ScrollbarThemeAdwaita.cpp b/Source/WebCore/platform/adwaita/ScrollbarThemeAdwaita.cpp -index e280025043b3c03c3974289e62ef7cc88ebfa2c7..077a4ab4aa5b688937ed4d5018745aa6f6af7442 100644 +index 492c5e76290c2379cda40b9663f5f67ff8f66360..096752985edf39960eb4be6eb733ebe3713313cb 100644 --- a/Source/WebCore/platform/adwaita/ScrollbarThemeAdwaita.cpp +++ b/Source/WebCore/platform/adwaita/ScrollbarThemeAdwaita.cpp -@@ -43,7 +43,7 @@ +@@ -46,7 +46,7 @@ namespace WebCore { @@ -6632,106 +6773,11 @@ index e280025043b3c03c3974289e62ef7cc88ebfa2c7..077a4ab4aa5b688937ed4d5018745aa6 static const unsigned scrollbarBorderSize = 1; static const unsigned thumbBorderSize = 1; static const unsigned overlayThumbSize = 3; -diff --git a/Source/WebCore/platform/graphics/cairo/ImageBufferUtilitiesCairo.cpp b/Source/WebCore/platform/graphics/cairo/ImageBufferUtilitiesCairo.cpp -index d137ffd1a8ed0b788bd28197c6d7e9f7d14e852f..dcf8bf3f7ee6b037a370712e2ac36b6e2e4bbebc 100644 ---- a/Source/WebCore/platform/graphics/cairo/ImageBufferUtilitiesCairo.cpp -+++ b/Source/WebCore/platform/graphics/cairo/ImageBufferUtilitiesCairo.cpp -@@ -48,6 +48,13 @@ - #include - #endif - -+#if PLATFORM(WPE) || PLATFORM(WIN) -+#include // Needed by jpeglib.h for FILE. -+extern "C" { -+#include "jpeglib.h" -+} -+#endif -+ - namespace WebCore { - - #if !PLATFORM(GTK) -@@ -65,8 +72,75 @@ static bool encodeImage(cairo_surface_t* image, const String& mimeType, Vector encodeData(cairo_surface_t* image, const String& mimeType, std::optional) -+static Vector encodeJpeg(cairo_surface_t* image, int quality) -+{ -+ if (cairo_surface_get_type(image) != CAIRO_SURFACE_TYPE_IMAGE) { -+ fprintf(stderr, "Unexpected cairo surface type: %d\n", cairo_surface_get_type(image)); -+ return { }; -+ } -+ -+ if (cairo_image_surface_get_format(image) != CAIRO_FORMAT_ARGB32) { -+ fprintf(stderr, "Unexpected surface image format: %d\n", cairo_image_surface_get_format(image)); -+ return { }; -+ } -+ -+ struct jpeg_compress_struct info; -+ struct 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 = cairo_image_surface_get_width(image); -+ info.image_height = cairo_image_surface_get_height(image); -+ -+#ifndef LIBJPEG_TURBO_VERSION -+ COMPILE_ASSERT(false, only_libjpeg_turbo_is_supported); -+#endif -+ -+#if CPU(LITTLE_ENDIAN) -+ info.in_color_space = JCS_EXT_BGRA; -+#else -+ info.in_color_space = JCS_EXT_ARGB; -+#endif -+ // # of color components in input image -+ info.input_components = 4; -+ -+ jpeg_set_defaults(&info); -+ jpeg_set_quality(&info, quality, true); -+ -+ jpeg_start_compress(&info, true); -+ -+ while (info.next_scanline < info.image_height) -+ { -+ JSAMPROW row = cairo_image_surface_get_data(image) + (info.next_scanline * cairo_image_surface_get_stride(image)); -+ 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); -+ -+ Vector output; -+ output.append(std::span { bufferPtr, bufferSize }); -+ // Cannot use unique_ptr as bufferPtr changes during compression. GUniquePtr would work -+ // but it's under GLib and won't work on Windows. -+ free(bufferPtr); -+ return output; -+} -+ -+Vector encodeData(cairo_surface_t* image, const String& mimeType, std::optional quality) - { -+ if (mimeType == "image/jpeg"_s) { -+ int qualityPercent = 100; -+ if (quality) -+ qualityPercent = static_cast(*quality * 100.0 + 0.5); -+ return encodeJpeg(image, qualityPercent); -+ } -+ - Vector encodedImage; - if (!image || !encodeImage(image, mimeType, &encodedImage)) - return { }; diff --git a/Source/WebCore/platform/graphics/cg/ImageBufferUtilitiesCG.h b/Source/WebCore/platform/graphics/cg/ImageBufferUtilitiesCG.h -index a82b748682f984fcdd4f5413d0254e0f5573f043..2c3d4bba92c63235c124a400d89455499aa3a189 100644 +index 5b659c763b9754b025a63f89522954cc39915b9a..448b50a2b131361a75d3f816cdcbb6a102551280 100644 --- a/Source/WebCore/platform/graphics/cg/ImageBufferUtilitiesCG.h +++ b/Source/WebCore/platform/graphics/cg/ImageBufferUtilitiesCG.h -@@ -38,7 +38,7 @@ WEBCORE_EXPORT uint8_t verifyImageBufferIsBigEnough(const void* buffer, size_t b +@@ -38,7 +38,7 @@ WEBCORE_EXPORT uint8_t verifyImageBufferIsBigEnough(std::span buf RetainPtr utiFromImageBufferMIMEType(const String& mimeType); CFStringRef jpegUTI(); @@ -6741,7 +6787,7 @@ index a82b748682f984fcdd4f5413d0254e0f5573f043..2c3d4bba92c63235c124a400d8945549 Vector encodeData(std::span, const String& mimeType, std::optional quality); diff --git a/Source/WebCore/platform/graphics/filters/software/FEComponentTransferSoftwareApplier.h b/Source/WebCore/platform/graphics/filters/software/FEComponentTransferSoftwareApplier.h -index b60f9a64bacc8282860da6de299b75aeb295b9b5..55bd017c03c6478ca334bd5ef164160fef5d5302 100644 +index c7542b821af8c87660e10b0c07b360cfcc8e28a2..a3cc131ff0410ae31df30c115dd9fd26aec5adf8 100644 --- a/Source/WebCore/platform/graphics/filters/software/FEComponentTransferSoftwareApplier.h +++ b/Source/WebCore/platform/graphics/filters/software/FEComponentTransferSoftwareApplier.h @@ -23,6 +23,7 @@ @@ -6749,18 +6795,18 @@ index b60f9a64bacc8282860da6de299b75aeb295b9b5..55bd017c03c6478ca334bd5ef164160f #include "FilterEffectApplier.h" +#include "PixelBuffer.h" + #include namespace WebCore { - diff --git a/Source/WebCore/platform/graphics/win/ComplexTextControllerUniscribe.cpp b/Source/WebCore/platform/graphics/win/ComplexTextControllerUniscribe.cpp -index 3f96ccee98a29188e4af376484ab6514b319ddf8..20d9ba661aa10adada5ef5688854b4bc3c0f0702 100644 +index 78ea08023ebd5f1b41b06cd843b6dce4ee80dd50..55fed94b774f033b4f75e2dee85dc27cf2e2689e 100644 --- a/Source/WebCore/platform/graphics/win/ComplexTextControllerUniscribe.cpp +++ b/Source/WebCore/platform/graphics/win/ComplexTextControllerUniscribe.cpp -@@ -169,6 +169,33 @@ static Vector stringIndicesFromClusters(const Vector& clusters, +@@ -168,6 +168,33 @@ static Vector stringIndicesFromClusters(const Vector& clusters, return stringIndices; } -+static int compactScriptItemsIfNeeded(const UChar* cp, unsigned stringLength, Vector& items, int numItems, const Font* font) ++static int compactScriptItemsIfNeeded(std::span cp, Vector& items, int numItems, const Font* font) +{ + // https://bugs.webkit.org/show_bug.cgi?id=201214 + // Uniscribe is overly aggressive in separating the runs. It'll split "3d_rotation" into "3", "d", "_" and "rotation" and we @@ -6771,11 +6817,11 @@ index 3f96ccee98a29188e4af376484ab6514b319ddf8..20d9ba661aa10adada5ef5688854b4bc + if (!numItems) + return numItems; + -+ if (font->platformData().isSystemFont() || font->platformData().hasVariations()) ++ if (font->platformData().hasVariations()) + return numItems; + + bool allGoodCharacters = true; -+ for (unsigned i = 0; allGoodCharacters && i < stringLength; ++i) { ++ for (unsigned i = 0; allGoodCharacters && i < cp.size(); ++i) { + const UChar c = cp[i]; + allGoodCharacters = (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_'; + } @@ -6787,39 +6833,40 @@ index 3f96ccee98a29188e4af376484ab6514b319ddf8..20d9ba661aa10adada5ef5688854b4bc + return 1; +} + - void ComplexTextController::collectComplexTextRunsForCharacters(const UChar* cp, unsigned stringLength, unsigned stringLocation, const Font* font) + void ComplexTextController::collectComplexTextRunsForCharacters(std::span cp, unsigned stringLocation, const Font* font) { if (!font) { -@@ -198,6 +225,8 @@ void ComplexTextController::collectComplexTextRunsForCharacters(const UChar* cp, +@@ -197,6 +224,8 @@ void ComplexTextController::collectComplexTextRunsForCharacters(std::span #include #include +#include #include + #include +#include namespace WebCore { -@@ -1301,6 +1303,246 @@ int PlatformKeyboardEvent::windowsKeyCodeForGdkKeyCode(unsigned keycode) +@@ -1302,6 +1304,246 @@ int PlatformKeyboardEvent::windowsKeyCodeForGdkKeyCode(unsigned keycode) } -+static const HashMap& gdkToWindowsKeyCodeMap() ++static const UncheckedKeyHashMap& gdkToWindowsKeyCodeMap() +{ -+ static HashMap* result; ++ static UncheckedKeyHashMap* result; + static std::once_flag once; + std::call_once( + once, @@ -7042,7 +7089,7 @@ index 58f2ac6c28396289c55493c7a78b2b4709e5f129..cf9687900fdeeebe9d829907d121da24 + GDK_KEY_Subtitle, + GDK_KEY_Video + }; -+ result = new HashMap(); ++ result = new UncheckedKeyHashMap(); + for (unsigned gdkKeyCode : gdkKeyCodes) { + int winKeyCode = PlatformKeyboardEvent::windowsKeyCodeForGdkKeyCode(gdkKeyCode); + // If several gdk key codes map to the same win key code first one is used. @@ -7061,256 +7108,41 @@ index 58f2ac6c28396289c55493c7a78b2b4709e5f129..cf9687900fdeeebe9d829907d121da24 { switch (val) { diff --git a/Source/WebCore/platform/gtk/PlatformScreenGtk.cpp b/Source/WebCore/platform/gtk/PlatformScreenGtk.cpp -index ae1da37330aa06a8f660876ba415ff2821f59813..c358a925347187181fbe1b381428c7bd0018455c 100644 +index 1339241aae69b657ffa40b603eea992c45db0e65..9194ff5f8308e5cf22fb250723ae4161142da45f 100644 --- a/Source/WebCore/platform/gtk/PlatformScreenGtk.cpp +++ b/Source/WebCore/platform/gtk/PlatformScreenGtk.cpp -@@ -124,7 +124,7 @@ bool screenSupportsExtendedColor(Widget*) +@@ -121,7 +121,7 @@ bool screenSupportsExtendedColor(Widget*) } #if ENABLE(TOUCH_EVENTS) -bool screenHasTouchDevice() +bool platformScreenHasTouchDevice() { - auto* display = gdk_display_get_default(); - if (!display) -@@ -134,7 +134,7 @@ bool screenHasTouchDevice() - return seat ? gdk_seat_get_capabilities(seat) & GDK_SEAT_CAPABILITY_TOUCH : true; + return getScreenProperties().screenHasTouchDevice; } +diff --git a/Source/WebCore/platform/libwpe/PlatformKeyboardEventLibWPE.cpp b/Source/WebCore/platform/libwpe/PlatformKeyboardEventLibWPE.cpp +index a8674916429908cabb86bd95dc5b3da217e1556b..6a464e2b0c1c45cd4e8effba678b8dde9dd870da 100644 +--- a/Source/WebCore/platform/libwpe/PlatformKeyboardEventLibWPE.cpp ++++ b/Source/WebCore/platform/libwpe/PlatformKeyboardEventLibWPE.cpp +@@ -30,9 +30,11 @@ --bool screenIsTouchPrimaryInputDevice() -+bool platformScreenIsTouchPrimaryInputDevice() - { - auto* display = gdk_display_get_default(); - if (!display) -diff --git a/Source/WebCore/platform/libwpe/PasteboardLibWPE.cpp b/Source/WebCore/platform/libwpe/PasteboardLibWPE.cpp -index ae439e30f1fb239d18e1164e8896dfb272c75673..eddcb9bda783fcdcbf9f924d4eaa6cc78dd54395 100644 ---- a/Source/WebCore/platform/libwpe/PasteboardLibWPE.cpp -+++ b/Source/WebCore/platform/libwpe/PasteboardLibWPE.cpp -@@ -32,6 +32,10 @@ - #include "PasteboardStrategy.h" - #include "PlatformStrategies.h" + #include "WindowsKeyboardCodes.h" + #include ++#include + #include + #include + #include ++#include -+#if ENABLE(DRAG_SUPPORT) -+#include "DragData.h" -+#endif -+ namespace WebCore { - std::unique_ptr Pasteboard::createForCopyAndPaste(std::unique_ptr&& context) -@@ -52,9 +56,28 @@ bool Pasteboard::hasData() - return !types.isEmpty(); - } - --Vector Pasteboard::typesSafeForBindings(const String&) -+Vector Pasteboard::typesSafeForBindings(const String& origin) - { -- notImplemented(); -+ if (m_selectionData) { -+ ListHashSet types; -+ if (auto* buffer = m_selectionData->customData()) { -+ auto customData = PasteboardCustomData::fromSharedBuffer(*buffer); -+ if (customData.origin() == origin) { -+ for (auto& type : customData.orderedTypes()) -+ types.add(type); -+ } -+ } -+ -+ if (m_selectionData->hasText()) -+ types.add("text/plain"_s); -+ if (m_selectionData->hasMarkup()) -+ types.add("text/html"_s); -+ if (m_selectionData->hasURIList()) -+ types.add("text/uri-list"_s); -+ -+ return copyToVector(types); -+ } -+ - return { }; - } - -@@ -67,23 +90,55 @@ Vector Pasteboard::typesForLegacyUnsafeBindings() - - String Pasteboard::readOrigin() - { -- notImplemented(); // webkit.org/b/177633: [GTK] Move to new Pasteboard API -+ if (m_selectionData) { -+ if (auto* buffer = m_selectionData->customData()) -+ return PasteboardCustomData::fromSharedBuffer(*buffer).origin(); -+ -+ return { }; -+ } -+ - return { }; - } - - String Pasteboard::readString(const String& type) - { -+ if (m_selectionData) { -+ if (type == "text/plain"_s) -+ return m_selectionData->text();; -+ if (type == "text/html"_s) -+ return m_selectionData->markup(); -+ if (type == "Files"_s || type == "text/uri-list"_s) -+ return m_selectionData->uriList(); -+ return { }; -+ } -+ - return platformStrategies()->pasteboardStrategy()->readStringFromPasteboard(0, type, name(), context()); - } - --String Pasteboard::readStringInCustomData(const String&) -+String Pasteboard::readStringInCustomData(const String& type) - { -+ if (m_selectionData) { -+ if (auto* buffer = m_selectionData->customData()) -+ return PasteboardCustomData::fromSharedBuffer(*buffer).readStringInCustomData(type); -+ -+ return { }; -+ } -+ - notImplemented(); - return { }; - } - - void Pasteboard::writeString(const String& type, const String& text) - { -+ if (m_selectionData) { -+ if (type == "Files"_s || type == "text/uri-list"_s) -+ m_selectionData->setURIList(text); -+ else if (type == "text/html"_s) -+ m_selectionData->setMarkup(text); -+ else if (type == "text/plain"_s) -+ m_selectionData->setText(text); -+ return; -+ } - platformStrategies()->pasteboardStrategy()->writeToPasteboard(type, text); +@@ -1303,6 +1305,246 @@ int PlatformKeyboardEvent::windowsKeyCodeForWPEKeyCode(unsigned keycode) + return 0; } -@@ -111,7 +166,12 @@ void Pasteboard::read(PasteboardFileReader&, std::optional) - - void Pasteboard::write(const PasteboardURL& url) - { -- platformStrategies()->pasteboardStrategy()->writeToPasteboard("text/plain;charset=utf-8"_s, url.url.string()); -+ if (m_selectionData) { -+ m_selectionData->clearAll(); -+ m_selectionData->setURL(url.url, url.title); -+ } else { -+ platformStrategies()->pasteboardStrategy()->writeToPasteboard("text/plain;charset=utf-8"_s, url.url.string()); -+ } - } - - void Pasteboard::writeTrustworthyWebURLsPboardType(const PasteboardURL&) -@@ -119,8 +179,16 @@ void Pasteboard::writeTrustworthyWebURLsPboardType(const PasteboardURL&) - notImplemented(); - } - --void Pasteboard::write(const PasteboardImage&) -+void Pasteboard::write(const PasteboardImage& pasteboardImage) - { -+ if (m_selectionData) { -+ m_selectionData->clearAll(); -+ if (!pasteboardImage.url.url.isEmpty()) { -+ m_selectionData->setURL(pasteboardImage.url.url, pasteboardImage.url.title); -+ m_selectionData->setMarkup(pasteboardImage.url.markup); -+ } -+ m_selectionData->setImage(pasteboardImage.image.get()); -+ } - } - - void Pasteboard::write(const PasteboardBuffer&) -@@ -129,7 +197,13 @@ void Pasteboard::write(const PasteboardBuffer&) - - void Pasteboard::write(const PasteboardWebContent& content) - { -- platformStrategies()->pasteboardStrategy()->writeToPasteboard(content); -+ if (m_selectionData) { -+ m_selectionData->clearAll(); -+ m_selectionData->setText(content.text); -+ m_selectionData->setMarkup(content.markup); -+ } else { -+ platformStrategies()->pasteboardStrategy()->writeToPasteboard(content); -+ } - } - - Pasteboard::FileContentState Pasteboard::fileContentState() -@@ -152,14 +226,54 @@ void Pasteboard::writePlainText(const String& text, SmartReplaceOption) - writeString("text/plain;charset=utf-8"_s, text); - } - --void Pasteboard::writeCustomData(const Vector&) -+void Pasteboard::writeCustomData(const Vector& data) - { -+ if (m_selectionData) { -+ if (!data.isEmpty()) { -+ const auto& customData = data[0]; -+ customData.forEachPlatformString([this] (auto& type, auto& string) { -+ writeString(type, string); -+ }); -+ if (customData.hasSameOriginCustomData() || !customData.origin().isEmpty()) -+ m_selectionData->setCustomData(customData.createSharedBuffer()); -+ } -+ return; -+ } - } - - void Pasteboard::write(const Color&) - { - } - -+#if ENABLE(DRAG_SUPPORT) -+ -+Pasteboard::Pasteboard(std::unique_ptr&& context, SelectionData&& selectionData) -+ : m_context(WTFMove(context)) -+ , m_selectionData(WTFMove(selectionData)) -+{ -+} -+ -+Pasteboard::Pasteboard(std::unique_ptr&& context, SelectionData& selectionData) -+ : m_context(WTFMove(context)) -+ , m_selectionData(selectionData) -+{ -+} -+ -+std::unique_ptr Pasteboard::createForDragAndDrop(std::unique_ptr&& context) ++static const UncheckedKeyHashMap& WPEToWindowsKeyCodeMap() +{ -+ return makeUnique(WTFMove(context), SelectionData()); -+} -+ -+std::unique_ptr Pasteboard::create(const DragData& dragData) -+{ -+ RELEASE_ASSERT(dragData.platformData()); -+ return makeUnique(dragData.createPasteboardContext(), *dragData.platformData()); -+} -+void Pasteboard::setDragImage(DragImage, const IntPoint&) -+{ -+} -+#endif -+ - } // namespace WebCore - - #endif // USE(LIBWPE) -diff --git a/Source/WebCore/platform/libwpe/PlatformKeyboardEventLibWPE.cpp b/Source/WebCore/platform/libwpe/PlatformKeyboardEventLibWPE.cpp -index e187936cbef017c080d1dfa14de439b3f5bc2cf8..270c237c8db2f6809719ecfd54a95306728676bc 100644 ---- a/Source/WebCore/platform/libwpe/PlatformKeyboardEventLibWPE.cpp -+++ b/Source/WebCore/platform/libwpe/PlatformKeyboardEventLibWPE.cpp -@@ -30,8 +30,10 @@ - - #include "WindowsKeyboardCodes.h" - #include -+#include - #include - #include -+#include - - namespace WebCore { - -@@ -1302,6 +1304,246 @@ int PlatformKeyboardEvent::windowsKeyCodeForWPEKeyCode(unsigned keycode) - return 0; - } - -+static const HashMap& WPEToWindowsKeyCodeMap() -+{ -+ static HashMap* result; ++ static UncheckedKeyHashMap* result; + static std::once_flag once; + std::call_once( + once, @@ -7533,7 +7365,7 @@ index e187936cbef017c080d1dfa14de439b3f5bc2cf8..270c237c8db2f6809719ecfd54a95306 + WPE_KEY_Subtitle, + WPE_KEY_Video + }; -+ result = new HashMap(); ++ result = new UncheckedKeyHashMap(); + for (unsigned WPEKeyCode : WPEKeyCodes) { + int winKeyCode = PlatformKeyboardEvent::windowsKeyCodeForWPEKeyCode(WPEKeyCode); + // If several gdk key codes map to the same win key code first one is used. @@ -7552,7 +7384,7 @@ index e187936cbef017c080d1dfa14de439b3f5bc2cf8..270c237c8db2f6809719ecfd54a95306 { switch (val) { diff --git a/Source/WebCore/platform/libwpe/PlatformPasteboardLibWPE.cpp b/Source/WebCore/platform/libwpe/PlatformPasteboardLibWPE.cpp -index c62e88f8c3aa40f01618cdaf0c0e22a2404b17ad..02411ac6bb361c2677c269945f665e0a92ccb902 100644 +index f21f7d66c5dd661c289a453994597ae166c8f3d0..c293b72154e2cb8f4f1ad3cc222a05f29888891d 100644 --- a/Source/WebCore/platform/libwpe/PlatformPasteboardLibWPE.cpp +++ b/Source/WebCore/platform/libwpe/PlatformPasteboardLibWPE.cpp @@ -31,10 +31,18 @@ @@ -7565,25 +7397,24 @@ index c62e88f8c3aa40f01618cdaf0c0e22a2404b17ad..02411ac6bb361c2677c269945f665e0a namespace WebCore { -+static HashMap& sharedPasteboard() ++static UncheckedKeyHashMap& sharedPasteboard() +{ -+ static NeverDestroyed> pasteboard; ++ static NeverDestroyed> pasteboard; + return pasteboard.get(); +} + PlatformPasteboard::PlatformPasteboard(const String&) : m_pasteboard(wpe_pasteboard_get_singleton()) { -@@ -54,72 +62,26 @@ void PlatformPasteboard::performAsDataOwner(DataOwnerType, Function&& ac +@@ -59,74 +67,26 @@ int64_t PlatformPasteboard::changeCount() const void PlatformPasteboard::getTypes(Vector& types) const { - struct wpe_pasteboard_string_vector pasteboardTypes = { nullptr, 0 }; - wpe_pasteboard_get_types(m_pasteboard, &pasteboardTypes); -- -- for (unsigned i = 0; i < pasteboardTypes.length; ++i) { -- auto& typeString = pasteboardTypes.strings[i]; -- types.append(String({ typeString.data, typeString.length })); +- for (auto& typeString : unsafeMakeSpan(pasteboardTypes.strings, pasteboardTypes.length)) { +- const auto length = std::min(static_cast(typeString.length), std::numeric_limits::max()); +- types.append(String(unsafeMakeSpan(typeString.data, length))); - } - - wpe_pasteboard_string_vector_free(&pasteboardTypes); @@ -7598,7 +7429,8 @@ index c62e88f8c3aa40f01618cdaf0c0e22a2404b17ad..02411ac6bb361c2677c269945f665e0a - if (!string.length) - return String(); - -- String returnValue({ string.data, string.length }); +- const auto length = std::min(static_cast(string.length), std::numeric_limits::max()); +- String returnValue(unsafeMakeSpan(string.data, length)); - - wpe_pasteboard_string_free(&string); - return returnValue; @@ -7607,23 +7439,24 @@ index c62e88f8c3aa40f01618cdaf0c0e22a2404b17ad..02411ac6bb361c2677c269945f665e0a void PlatformPasteboard::write(const PasteboardWebContent& content) { -- static const char plainText[] = "text/plain;charset=utf-8"; -- static const char htmlText[] = "text/html;charset=utf-8"; +- static constexpr auto plainText = "text/plain;charset=utf-8"_s; +- static constexpr auto htmlText = "text/html"_s; - - CString textString = content.text.utf8(); - CString markupString = content.markup.utf8(); - -- struct wpe_pasteboard_string_pair pairs[] = { +- std::array pairs = { { - { { nullptr, 0 }, { nullptr, 0 } }, - { { nullptr, 0 }, { nullptr, 0 } }, -- }; +- } }; - wpe_pasteboard_string_initialize(&pairs[0].type, plainText, strlen(plainText)); - wpe_pasteboard_string_initialize(&pairs[0].string, textString.data(), textString.length()); - wpe_pasteboard_string_initialize(&pairs[1].type, htmlText, strlen(htmlText)); - wpe_pasteboard_string_initialize(&pairs[1].string, markupString.data(), markupString.length()); -- struct wpe_pasteboard_string_map map = { pairs, 2 }; +- struct wpe_pasteboard_string_map map = { pairs.data(), pairs.size() }; - - wpe_pasteboard_write(m_pasteboard, &map); +- m_changeCount++; - - wpe_pasteboard_string_free(&pairs[0].type); - wpe_pasteboard_string_free(&pairs[0].string); @@ -7648,6 +7481,7 @@ index c62e88f8c3aa40f01618cdaf0c0e22a2404b17ad..02411ac6bb361c2677c269945f665e0a - struct wpe_pasteboard_string_map map = { pairs, 1 }; - - wpe_pasteboard_write(m_pasteboard, &map); +- m_changeCount++; - - wpe_pasteboard_string_free(&pairs[0].type); - wpe_pasteboard_string_free(&pairs[0].string); @@ -7655,62 +7489,61 @@ index c62e88f8c3aa40f01618cdaf0c0e22a2404b17ad..02411ac6bb361c2677c269945f665e0a } Vector PlatformPasteboard::typesSafeForDOMToReadAndWrite(const String&) const -diff --git a/Source/WebCore/platform/mediastream/libwebrtc/gstreamer/LibWebRTCProviderGStreamer.h b/Source/WebCore/platform/mediastream/libwebrtc/gstreamer/LibWebRTCProviderGStreamer.h -index 0552842dbe3f3a2c12a504178f5a8ca977e1c4db..2ef3b1b459d8a9b4e86b4556feeb4f0737f05c54 100644 ---- a/Source/WebCore/platform/mediastream/libwebrtc/gstreamer/LibWebRTCProviderGStreamer.h -+++ b/Source/WebCore/platform/mediastream/libwebrtc/gstreamer/LibWebRTCProviderGStreamer.h -@@ -31,6 +31,8 @@ - #include "GStreamerVideoEncoderFactory.h" - #include "LibWebRTCProvider.h" - -+#include "LibWebRTCProvider.h" -+ - namespace WebCore { - - class WEBCORE_EXPORT LibWebRTCProviderGStreamer : public LibWebRTCProvider { +diff --git a/Source/WebCore/platform/mediastream/libwebrtc/gstreamer/GStreamerVideoFrameLibWebRTC.cpp b/Source/WebCore/platform/mediastream/libwebrtc/gstreamer/GStreamerVideoFrameLibWebRTC.cpp +index 80c20938d5ec8282485fb0152b96304c83124354..22975b7c1b99357a7689747251410f306bfb3dcc 100644 +--- a/Source/WebCore/platform/mediastream/libwebrtc/gstreamer/GStreamerVideoFrameLibWebRTC.cpp ++++ b/Source/WebCore/platform/mediastream/libwebrtc/gstreamer/GStreamerVideoFrameLibWebRTC.cpp +@@ -23,6 +23,8 @@ + + #include + #include ++#include ++#include + #include + #include + #include diff --git a/Source/WebCore/platform/network/HTTPHeaderMap.cpp b/Source/WebCore/platform/network/HTTPHeaderMap.cpp -index 34caadc74c1ad6b411e9043289fece53b9757f17..1e8ec2fe9f16ddd0a33e261172689a9d35ec5194 100644 +index 1178c8fb001994bc9e6166376a367d9bc148913c..fcc6534568cad6b42a819a435f84ba2b9baae6f8 100644 --- a/Source/WebCore/platform/network/HTTPHeaderMap.cpp +++ b/Source/WebCore/platform/network/HTTPHeaderMap.cpp -@@ -235,8 +235,11 @@ void HTTPHeaderMap::add(HTTPHeaderName name, const String& value) +@@ -237,8 +237,11 @@ void HTTPHeaderMap::add(HTTPHeaderName name, const String& value) auto index = m_commonHeaders.findIf([&](auto& header) { return header.key == name; }); + // Align with Chromium and Firefox, but just for SetCookies where it is critical: + // https://bit.ly/2HCa0iq -+ String separator = name == HTTPHeaderName::SetCookie ? "\n "_s : ", "_s; ++ String separator = name == HTTPHeaderName::SetCookie ? "playwright-set-cookie-separator"_s : ", "_s; if (index != notFound) -- m_commonHeaders[index].value = makeString(m_commonHeaders[index].value, ", ", value); +- m_commonHeaders[index].value = makeString(m_commonHeaders[index].value, ", "_s, value); + m_commonHeaders[index].value = makeString(m_commonHeaders[index].value, separator, value); else m_commonHeaders.append(CommonHeader { name, value }); } diff --git a/Source/WebCore/platform/network/NetworkStorageSession.h b/Source/WebCore/platform/network/NetworkStorageSession.h -index e745131ddc12d23cd5e2429f565f910ad3520e82..dd23b06a3ceab1675e7e59d8642abc589c360d2a 100644 +index c1e50549e674e1620ad0515a061376ba728e75df..7e6e323436d9b1a87dbf4d6fa275629f531e3ce8 100644 --- a/Source/WebCore/platform/network/NetworkStorageSession.h +++ b/Source/WebCore/platform/network/NetworkStorageSession.h -@@ -167,6 +167,8 @@ public: +@@ -198,6 +198,7 @@ public: + NetworkingContext* context() const; #endif - + WEBCORE_EXPORT void setCookiesFromResponse(const URL& firstParty, const SameSiteInfo&, const URL&, const String& setCookieValue); -+ + WEBCORE_EXPORT HTTPCookieAcceptPolicy cookieAcceptPolicy() const; WEBCORE_EXPORT void setCookie(const Cookie&); - WEBCORE_EXPORT void setCookies(const Vector&, const URL&, const URL& mainDocumentURL); diff --git a/Source/WebCore/platform/network/ResourceResponseBase.cpp b/Source/WebCore/platform/network/ResourceResponseBase.cpp -index d47b089014717dc98928aa597ff881f3909559e1..3ab3262fd35c1ae740b6b8c01b6ce950fee0c224 100644 +index a4ed6a5f1182b43432f6082ffc10b62473c248e5..05113dbf615171a0b18f8998411e603076bdc15b 100644 --- a/Source/WebCore/platform/network/ResourceResponseBase.cpp +++ b/Source/WebCore/platform/network/ResourceResponseBase.cpp -@@ -74,6 +74,7 @@ ResourceResponseBase::ResourceResponseBase(std::optional d - , m_httpStatusText(data ? data->httpStatusText : String { }) - , m_httpVersion(data ? data->httpVersion : String { }) - , m_httpHeaderFields(data ? data->httpHeaderFields : HTTPHeaderMap { }) +@@ -78,6 +78,7 @@ ResourceResponseBase::ResourceResponseBase(std::optional&& + , m_httpStatusText(data ? WTFMove(data->httpStatusText) : String { }) + , m_httpVersion(data ? WTFMove(data->httpVersion) : String { }) + , m_httpHeaderFields(data ? WTFMove(data->httpHeaderFields) : HTTPHeaderMap { }) + , m_httpRequestHeaderFields(data ? data->httpRequestHeaderFields : HTTPHeaderMap { }) - , m_networkLoadMetrics(data && data->networkLoadMetrics ? Box::create(*data->networkLoadMetrics) : Box { }) - , m_certificateInfo(data ? data->certificateInfo : std::nullopt) + , m_networkLoadMetrics(data && data->networkLoadMetrics ? Box::create(WTFMove(*data->networkLoadMetrics)) : Box { }) + , m_certificateInfo(data ? WTFMove(data->certificateInfo) : std::nullopt) , m_httpStatusCode(data ? data->httpStatusCode : 0) -@@ -892,6 +893,7 @@ std::optional ResourceResponseBase::getResponseData() cons +@@ -904,6 +905,7 @@ std::optional ResourceResponseBase::getResponseData() cons String { m_httpStatusText }, String { m_httpVersion }, HTTPHeaderMap { m_httpHeaderFields }, @@ -7718,7 +7551,7 @@ index d47b089014717dc98928aa597ff881f3909559e1..3ab3262fd35c1ae740b6b8c01b6ce950 m_networkLoadMetrics ? std::optional(*m_networkLoadMetrics) : std::nullopt, m_source, m_type, -@@ -965,6 +967,11 @@ std::optional Coder Coder httpStatusCode; decoder >> httpStatusCode; if (!httpStatusCode) -@@ -1019,6 +1026,7 @@ std::optional Coder Coder m_networkLoadMetrics; mutable std::optional m_certificateInfo; -@@ -291,7 +296,7 @@ struct ResourceResponseData { +@@ -297,7 +302,7 @@ struct ResourceResponseData { ResourceResponseData() = default; ResourceResponseData(ResourceResponseData&&) = default; ResourceResponseData& operator=(ResourceResponseData&&) = default; -- ResourceResponseData(URL&& url, String&& mimeType, long long expectedContentLength, String&& textEncodingName, int httpStatusCode, String&& httpStatusText, String&& httpVersion, HTTPHeaderMap&& httpHeaderFields, std::optional&& networkLoadMetrics, ResourceResponseBaseSource source, ResourceResponseBaseType type, ResourceResponseBaseTainting tainting, bool isRedirected, UsedLegacyTLS usedLegacyTLS, WasPrivateRelayed wasPrivateRelayed, bool isRangeRequested, std::optional certificateInfo) -+ ResourceResponseData(URL&& url, String&& mimeType, long long expectedContentLength, String&& textEncodingName, int httpStatusCode, String&& httpStatusText, String&& httpVersion, HTTPHeaderMap&& httpHeaderFields, HTTPHeaderMap&& httpRequestHeaderFields, std::optional&& networkLoadMetrics, ResourceResponseBaseSource source, ResourceResponseBaseType type, ResourceResponseBaseTainting tainting, bool isRedirected, UsedLegacyTLS usedLegacyTLS, WasPrivateRelayed wasPrivateRelayed, bool isRangeRequested, std::optional certificateInfo) +- ResourceResponseData(URL&& url, String&& mimeType, long long expectedContentLength, String&& textEncodingName, int httpStatusCode, String&& httpStatusText, String&& httpVersion, HTTPHeaderMap&& httpHeaderFields, std::optional&& networkLoadMetrics, ResourceResponseSource source, ResourceResponseBaseType type, ResourceResponseBaseTainting tainting, bool isRedirected, UsedLegacyTLS usedLegacyTLS, WasPrivateRelayed wasPrivateRelayed, String&& proxyName, bool isRangeRequested, std::optional certificateInfo) ++ ResourceResponseData(URL&& url, String&& mimeType, long long expectedContentLength, String&& textEncodingName, int httpStatusCode, String&& httpStatusText, String&& httpVersion, HTTPHeaderMap&& httpHeaderFields, HTTPHeaderMap&& httpRequestHeaderFields, std::optional&& networkLoadMetrics, ResourceResponseSource source, ResourceResponseBaseType type, ResourceResponseBaseTainting tainting, bool isRedirected, UsedLegacyTLS usedLegacyTLS, WasPrivateRelayed wasPrivateRelayed, String&& proxyName, bool isRangeRequested, std::optional certificateInfo) : url(WTFMove(url)) , mimeType(WTFMove(mimeType)) , expectedContentLength(expectedContentLength) -@@ -300,6 +305,7 @@ struct ResourceResponseData { +@@ -306,6 +311,7 @@ struct ResourceResponseData { , httpStatusText(WTFMove(httpStatusText)) , httpVersion(WTFMove(httpVersion)) , httpHeaderFields(WTFMove(httpHeaderFields)) @@ -7771,7 +7604,7 @@ index 203c591edc985e99ec7dc7a2bfaf69c92d3de99c..461b774d446528b7259ffc6ea3982d17 , networkLoadMetrics(WTFMove(networkLoadMetrics)) , source(source) , type(type) -@@ -322,6 +328,7 @@ struct ResourceResponseData { +@@ -329,6 +335,7 @@ struct ResourceResponseData { String httpStatusText; String httpVersion; HTTPHeaderMap httpHeaderFields; @@ -7780,10 +7613,10 @@ index 203c591edc985e99ec7dc7a2bfaf69c92d3de99c..461b774d446528b7259ffc6ea3982d17 ResourceResponseBase::Source source; ResourceResponseBase::Type type; diff --git a/Source/WebCore/platform/network/cocoa/NetworkStorageSessionCocoa.mm b/Source/WebCore/platform/network/cocoa/NetworkStorageSessionCocoa.mm -index 305080a5c298eaa1ef4644bdc6d90e243bcd061d..e3cbec55b164a49b9ed92b66ff70134618ab53f5 100644 +index 4a6533db6aff0620e7122e684f1ef6c723bf7942..395f275722b93a7ab08429588fbc1fdc1ebac4f3 100644 --- a/Source/WebCore/platform/network/cocoa/NetworkStorageSessionCocoa.mm +++ b/Source/WebCore/platform/network/cocoa/NetworkStorageSessionCocoa.mm -@@ -518,6 +518,22 @@ bool NetworkStorageSession::setCookieFromDOM(const URL& firstParty, const SameSi +@@ -553,6 +553,22 @@ bool NetworkStorageSession::setCookieFromDOM(const URL& firstParty, const SameSi return false; } @@ -7793,24 +7626,24 @@ index 305080a5c298eaa1ef4644bdc6d90e243bcd061d..e3cbec55b164a49b9ed92b66ff701346 + size_t count = cookieValues.size(); + auto* cookies = [NSMutableArray arrayWithCapacity:count]; + for (const auto& cookieValue : cookieValues) { -+ NSString* cookieString = (NSString *)cookieValue; ++ NSString* cookieString = cookieValue.createNSString().autorelease(); + NSString* cookieKey = @"Set-Cookie"; + NSDictionary* headers = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObject:cookieString] forKeys:[NSArray arrayWithObject:cookieKey]]; -+ NSArray* parsedCookies = [NSHTTPCookie cookiesWithResponseHeaderFields:headers forURL:(NSURL *)url]; ++ NSArray* parsedCookies = [NSHTTPCookie cookiesWithResponseHeaderFields:headers forURL:url.createNSURL().get()]; + [cookies addObject:parsedCookies[0]]; + } -+ NSURL *cookieURL = url; -+ setHTTPCookiesForURL(cookieStorage().get(), cookies, cookieURL, firstParty, sameSiteInfo); ++ NSURL *cookieURL = url.createNSURL().get(); ++ setHTTPCookiesForURL(cookieStorage().get(), cookies, cookieURL, firstParty.createNSURL().get(), sameSiteInfo); +} + static NSHTTPCookieAcceptPolicy httpCookieAcceptPolicy(CFHTTPCookieStorageRef cookieStorage) { ASSERT(hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies)); diff --git a/Source/WebCore/platform/network/curl/CookieJarDB.h b/Source/WebCore/platform/network/curl/CookieJarDB.h -index 7788bfea8bb631c51fe858b29cc33e43347cbfab..ad9f347ce55cbea4374a45d3c65f8e11bd7a00f4 100644 +index 37e129136c69b27d509acc01f10be42a8a1fe35a..9df0babc8f82372925fddf2211a7c8c908f3bb18 100644 --- a/Source/WebCore/platform/network/curl/CookieJarDB.h +++ b/Source/WebCore/platform/network/curl/CookieJarDB.h -@@ -72,7 +72,7 @@ public: +@@ -73,7 +73,7 @@ public: WEBCORE_EXPORT ~CookieJarDB(); private: @@ -7819,88 +7652,8 @@ index 7788bfea8bb631c51fe858b29cc33e43347cbfab..ad9f347ce55cbea4374a45d3c65f8e11 String m_databasePath; bool m_detectedDatabaseCorruption { false }; -diff --git a/Source/WebCore/platform/network/curl/CurlStream.cpp b/Source/WebCore/platform/network/curl/CurlStream.cpp -index 4b01a35fa4bff5e1ccc7fed23940345c9c6fbd15..5e2c2f7f92c5edf4b075670a2a02da65d97c4f45 100644 ---- a/Source/WebCore/platform/network/curl/CurlStream.cpp -+++ b/Source/WebCore/platform/network/curl/CurlStream.cpp -@@ -34,7 +34,7 @@ - - namespace WebCore { - --CurlStream::CurlStream(CurlStreamScheduler& scheduler, CurlStreamID streamID, URL&& url, ServerTrustEvaluation serverTrustEvaluation, LocalhostAlias localhostAlias) -+CurlStream::CurlStream(CurlStreamScheduler& scheduler, CurlStreamID streamID, bool ignoreCertificateErrors, URL&& url, ServerTrustEvaluation serverTrustEvaluation, LocalhostAlias localhostAlias) - : m_scheduler(scheduler) - , m_streamID(streamID) - { -@@ -49,6 +49,9 @@ CurlStream::CurlStream(CurlStreamScheduler& scheduler, CurlStreamID streamID, UR - m_curlHandle->disableServerTrustEvaluation(); - - m_curlHandle->enableConnectionOnly(); -+ if (ignoreCertificateErrors) -+ m_curlHandle->disableServerTrustEvaluation(); -+ - - auto errorCode = m_curlHandle->perform(); - if (errorCode != CURLE_OK) { -diff --git a/Source/WebCore/platform/network/curl/CurlStream.h b/Source/WebCore/platform/network/curl/CurlStream.h -index bc9c731a0e69c4923bb8b4bdda088c2be30b3f1c..2088662fb2ce29b7ed843586460630fbf82c0856 100644 ---- a/Source/WebCore/platform/network/curl/CurlStream.h -+++ b/Source/WebCore/platform/network/curl/CurlStream.h -@@ -55,12 +55,12 @@ public: - virtual void didFail(CurlStreamID, CURLcode, CertificateInfo&&) = 0; - }; - -- static std::unique_ptr create(CurlStreamScheduler& scheduler, CurlStreamID streamID, URL&& url, ServerTrustEvaluation serverTrustEvaluation, LocalhostAlias localhostAlias) -+ static std::unique_ptr create(CurlStreamScheduler& scheduler, CurlStreamID streamID, bool ignoreCertificateErrors, URL&& url, ServerTrustEvaluation serverTrustEvaluation, LocalhostAlias localhostAlias) - { -- return makeUnique(scheduler, streamID, WTFMove(url), serverTrustEvaluation, localhostAlias); -+ return makeUnique(scheduler, streamID, ignoreCertificateErrors, WTFMove(url), serverTrustEvaluation, localhostAlias); - } - -- CurlStream(CurlStreamScheduler&, CurlStreamID, URL&&, ServerTrustEvaluation, LocalhostAlias); -+ CurlStream(CurlStreamScheduler&, CurlStreamID, bool ignoreCertificateErrors, URL&&, ServerTrustEvaluation, LocalhostAlias); - virtual ~CurlStream(); - - void send(UniqueArray&&, size_t); -diff --git a/Source/WebCore/platform/network/curl/CurlStreamScheduler.cpp b/Source/WebCore/platform/network/curl/CurlStreamScheduler.cpp -index 048cd352dd9b4cc952337308337a4bd9c31f00f1..de54623b601aea9fbd6a88f5c646b20524b8ee2b 100644 ---- a/Source/WebCore/platform/network/curl/CurlStreamScheduler.cpp -+++ b/Source/WebCore/platform/network/curl/CurlStreamScheduler.cpp -@@ -40,7 +40,7 @@ CurlStreamScheduler::~CurlStreamScheduler() - ASSERT(isMainThread()); - } - --CurlStreamID CurlStreamScheduler::createStream(const URL& url, CurlStream::Client& client, CurlStream::ServerTrustEvaluation serverTrustEvaluation, CurlStream::LocalhostAlias localhostAlias) -+CurlStreamID CurlStreamScheduler::createStream(const URL& url, bool ignoreCertificateErrors, CurlStream::Client& client, CurlStream::ServerTrustEvaluation serverTrustEvaluation, CurlStream::LocalhostAlias localhostAlias) - { - ASSERT(isMainThread()); - -@@ -51,8 +51,8 @@ CurlStreamID CurlStreamScheduler::createStream(const URL& url, CurlStream::Clien - auto streamID = m_currentStreamID; - m_clientList.add(streamID, &client); - -- callOnWorkerThread([this, streamID, url = url.isolatedCopy(), serverTrustEvaluation, localhostAlias]() mutable { -- m_streamList.add(streamID, CurlStream::create(*this, streamID, WTFMove(url), serverTrustEvaluation, localhostAlias)); -+ callOnWorkerThread([this, streamID, ignoreCertificateErrors, url = url.isolatedCopy(), serverTrustEvaluation, localhostAlias]() mutable { -+ m_streamList.add(streamID, CurlStream::create(*this, streamID, ignoreCertificateErrors, WTFMove(url), serverTrustEvaluation, localhostAlias)); - }); - - return streamID; -diff --git a/Source/WebCore/platform/network/curl/CurlStreamScheduler.h b/Source/WebCore/platform/network/curl/CurlStreamScheduler.h -index 41af70e9bddcb507bf7e57841e4051bc99a78410..87899280f985ca5f0cb135fb9ba53cde822a3b84 100644 ---- a/Source/WebCore/platform/network/curl/CurlStreamScheduler.h -+++ b/Source/WebCore/platform/network/curl/CurlStreamScheduler.h -@@ -38,7 +38,7 @@ public: - CurlStreamScheduler(); - virtual ~CurlStreamScheduler(); - -- WEBCORE_EXPORT CurlStreamID createStream(const URL&, CurlStream::Client&, CurlStream::ServerTrustEvaluation, CurlStream::LocalhostAlias); -+ WEBCORE_EXPORT CurlStreamID createStream(const URL&, bool ignoreCertificateErrors, CurlStream::Client&, CurlStream::ServerTrustEvaluation, CurlStream::LocalhostAlias); - WEBCORE_EXPORT void destroyStream(CurlStreamID); - WEBCORE_EXPORT void send(CurlStreamID, UniqueArray&&, size_t); - diff --git a/Source/WebCore/platform/network/curl/NetworkStorageSessionCurl.cpp b/Source/WebCore/platform/network/curl/NetworkStorageSessionCurl.cpp -index f46f26a553e0634fd6a4d383c0821aadd504a399..738327163771952be91bc024e92070c015de2dd3 100644 +index 96289d8ae2e4feb60a91fab3f5cf1fc27b9e7c87..8c0b62c44a18571d1f3ea1ed81d59a0aae28d3f1 100644 --- a/Source/WebCore/platform/network/curl/NetworkStorageSessionCurl.cpp +++ b/Source/WebCore/platform/network/curl/NetworkStorageSessionCurl.cpp @@ -136,6 +136,12 @@ void NetworkStorageSession::setCookieAcceptPolicy(CookieAcceptPolicy policy) con @@ -7917,11 +7670,11 @@ index f46f26a553e0634fd6a4d383c0821aadd504a399..738327163771952be91bc024e92070c0 { switch (cookieDatabase().acceptPolicy()) { diff --git a/Source/WebCore/platform/network/soup/NetworkStorageSessionSoup.cpp b/Source/WebCore/platform/network/soup/NetworkStorageSessionSoup.cpp -index 09ab1320beacc41ae92399f3320aaf805d9d81d1..4c63cb2a3f6fbf277227a88b92f206402bc12cd7 100644 +index 274d671614fdca8f425adecb405d5f2402e92f8b..1b19e79e10f0768cfdd66b0fc1b1855388c9f559 100644 --- a/Source/WebCore/platform/network/soup/NetworkStorageSessionSoup.cpp +++ b/Source/WebCore/platform/network/soup/NetworkStorageSessionSoup.cpp -@@ -424,6 +424,30 @@ void NetworkStorageSession::replaceCookies(const Vector& cookies) - g_signal_emit(jar, signalId, 0); +@@ -551,6 +551,26 @@ void NetworkStorageSession::replaceCookies(const Vector& cookies) + g_signal_emit(jar, signalId, 0, nullptr, nullptr); } +void NetworkStorageSession::setCookiesFromResponse(const URL& firstParty, const SameSiteInfo&, const URL& url, const String& setCookieValue) @@ -7940,11 +7693,7 @@ index 09ab1320beacc41ae92399f3320aaf805d9d81d1..4c63cb2a3f6fbf277227a88b92f20640 + if (!cookie) + continue; + -+#if SOUP_CHECK_VERSION(2, 67, 1) + soup_cookie_jar_add_cookie_full(cookieStorage(), cookie.release(), origin.get(), firstPartyURI.get()); -+#else -+ soup_cookie_jar_add_cookie_with_first_party(cookieStorage(), firstPartyURI.get(), cookie.release()); -+#endif + } +} + @@ -7952,10 +7701,10 @@ index 09ab1320beacc41ae92399f3320aaf805d9d81d1..4c63cb2a3f6fbf277227a88b92f20640 { GUniquePtr targetCookie(cookie.toSoupCookie()); diff --git a/Source/WebCore/platform/win/ClipboardUtilitiesWin.cpp b/Source/WebCore/platform/win/ClipboardUtilitiesWin.cpp -index 15f47d0d2a99bcb1a7b9dd9764a9766a20e97692..f623d165826485f58cef60c4b3551055f4352de6 100644 +index bbcc12d58f7b5df3462c93617f6ef19eef403cf2..b255b05da89248a99ff11965ceae840ef45b9fab 100644 --- a/Source/WebCore/platform/win/ClipboardUtilitiesWin.cpp +++ b/Source/WebCore/platform/win/ClipboardUtilitiesWin.cpp -@@ -39,6 +39,7 @@ +@@ -40,6 +40,7 @@ #include #include #include @@ -7963,7 +7712,7 @@ index 15f47d0d2a99bcb1a7b9dd9764a9766a20e97692..f623d165826485f58cef60c4b3551055 namespace WebCore { -@@ -689,7 +690,10 @@ template void getStringData(IDataObject* data, FORMATETC* format, Ve +@@ -691,7 +692,10 @@ template void getStringData(IDataObject* data, FORMATETC* format, Ve STGMEDIUM store; if (FAILED(data->GetData(format, &store))) return; @@ -7988,10 +7737,10 @@ index c3ffc7392c0b7fa099a7dd4e4be977cdee1c803c..9570dbb0f2c42ca38598a8898183c9b3 HGLOBAL createGlobalData(const String&); HGLOBAL createGlobalData(const Vector&); diff --git a/Source/WebCore/platform/win/DragDataWin.cpp b/Source/WebCore/platform/win/DragDataWin.cpp -index 7bdb180c89bf3fe9d48098318d3b7503b8fd6279..296a3b2b82733b27272acb51ab4f883decfbaf14 100644 +index 0379437d84807e4a8d3846afac5ec8a70e743e70..5b0461bf12535d4900ffaddc2a87826280505233 100644 --- a/Source/WebCore/platform/win/DragDataWin.cpp +++ b/Source/WebCore/platform/win/DragDataWin.cpp -@@ -40,7 +40,7 @@ +@@ -40,12 +40,13 @@ namespace WebCore { @@ -8000,14 +7749,12 @@ index 7bdb180c89bf3fe9d48098318d3b7503b8fd6279..296a3b2b82733b27272acb51ab4f883d : m_clientPosition(clientPosition) , m_globalPosition(globalPosition) , m_platformDragData(0) -@@ -48,6 +48,7 @@ DragData::DragData(const DragDataMap& data, const IntPoint& clientPosition, cons + , m_draggingSourceOperationMask(sourceOperationMask) , m_applicationFlags(flags) ++ , m_dragDestinationActionMask(dragDestinationAction) , m_pageID(pageID) , m_dragDataMap(data) -+ , m_dragDestinationActionMask(dragDestinationAction) { - } - @@ -63,7 +64,7 @@ bool DragData::containsURL(FilenameConversionPolicy filenamePolicy) const || (filenamePolicy == ConvertFilenames && (m_dragDataMap.contains(filenameWFormat()->cfFormat) || m_dragDataMap.contains(filenameFormat()->cfFormat))); } @@ -8017,11 +7764,74 @@ index 7bdb180c89bf3fe9d48098318d3b7503b8fd6279..296a3b2b82733b27272acb51ab4f883d { if (!m_dragDataMap.isEmpty() || !m_platformDragData) return m_dragDataMap; +diff --git a/Source/WebCore/platform/win/DragImageWin.cpp b/Source/WebCore/platform/win/DragImageWin.cpp +index dd24e15115aeff41f0f4452a9cac292d75bc0d5d..8df467c008bdb3de59d301b14c1c20b8bb0b6a41 100644 +--- a/Source/WebCore/platform/win/DragImageWin.cpp ++++ b/Source/WebCore/platform/win/DragImageWin.cpp +@@ -62,16 +62,22 @@ IntSize dragImageSize(DragImageRef image) + { + if (!image) + return IntSize(); +- BITMAP b; +- GetObject(image, sizeof(BITMAP), &b); +- return IntSize(b.bmWidth, b.bmHeight); ++ return { image->width(), image->height() }; + } + ++#if USE(CAIRO) + void deleteDragImage(DragImageRef image) + { + if (image) + ::DeleteObject(image); + } ++#else ++void deleteDragImage(DragImageRef) ++{ ++ // Since this is a RefPtr, there's nothing additional we need to do to ++ // delete it. It will be released when it falls out of scope. ++} ++#endif + + DragImageRef dissolveDragImageToFraction(DragImageRef image, float) + { +@@ -79,8 +85,9 @@ DragImageRef dissolveDragImageToFraction(DragImageRef image, float) + return image; + } + +-DragImageRef createDragImageIconForCachedImageFilename(const String& filename) ++DragImageRef createDragImageIconForCachedImageFilename(const String&) + { ++#if USE(CAIRO) + SHFILEINFO shfi { }; + auto fname = filename.wideCharacters(); + if (FAILED(SHGetFileInfo(fname.data(), FILE_ATTRIBUTE_NORMAL, &shfi, sizeof(shfi), SHGFI_ICON | SHGFI_USEFILEATTRIBUTES))) +@@ -96,6 +103,9 @@ DragImageRef createDragImageIconForCachedImageFilename(const String& filename) + DeleteObject(iconInfo.hbmMask); + + return iconInfo.hbmColor; ++#else ++ return nullptr; ++#endif + } + + #if USE(CAIRO) +@@ -221,9 +231,9 @@ DragImageRef createDragImageForColor(const Color&, const FloatRect&, float, Path + } + + #if USE(SKIA) +-DragImageRef createDragImageFromImage(Image*, ImageOrientation, GraphicsClient*, float) ++DragImageRef createDragImageFromImage(Image* image, ImageOrientation, GraphicsClient*, float) + { +- return nullptr; ++ return image->currentNativeImage()->platformImage(); + } + + DragImageRef scaleDragImage(DragImageRef, FloatSize) diff --git a/Source/WebCore/platform/win/KeyEventWin.cpp b/Source/WebCore/platform/win/KeyEventWin.cpp -index b9f728911d34163c1ca14d359741d44cc05ab755..1609197044eaa8e9036e6dae23d1c5270b53e08b 100644 +index d450bf9d0fd1f0bf8f28db483ac9d3d60fa9d114..72a59403a0b5493aea4a8e28eb15eac24b652b09 100644 --- a/Source/WebCore/platform/win/KeyEventWin.cpp +++ b/Source/WebCore/platform/win/KeyEventWin.cpp -@@ -242,10 +242,16 @@ PlatformKeyboardEvent::PlatformKeyboardEvent(HWND, WPARAM code, LPARAM keyData, +@@ -243,10 +243,16 @@ PlatformKeyboardEvent::PlatformKeyboardEvent(HWND, WPARAM code, LPARAM keyData, { } @@ -8042,10 +7852,10 @@ index b9f728911d34163c1ca14d359741d44cc05ab755..1609197044eaa8e9036e6dae23d1c527 OptionSet PlatformKeyboardEvent::currentStateOfModifierKeys() diff --git a/Source/WebCore/platform/win/PasteboardWin.cpp b/Source/WebCore/platform/win/PasteboardWin.cpp -index 5728033e25919cef5b81d08516964aa5445c5d6e..0e588ebd34299d56ace86806bdec6e9ce337b053 100644 +index 7987d1cd71b05ba4cf09eaf0a8b0d55da6bcffb0..5edaa06c1a648402dc0c3224e69c4721a234aa06 100644 --- a/Source/WebCore/platform/win/PasteboardWin.cpp +++ b/Source/WebCore/platform/win/PasteboardWin.cpp -@@ -1130,7 +1130,21 @@ void Pasteboard::writeCustomData(const Vector& data) +@@ -1144,7 +1144,21 @@ void Pasteboard::writeCustomData(const Vector& data) } clear(); @@ -8067,7 +7877,7 @@ index 5728033e25919cef5b81d08516964aa5445c5d6e..0e588ebd34299d56ace86806bdec6e9c if (::OpenClipboard(m_owner)) { const auto& customData = data.first(); customData.forEachPlatformStringOrBuffer([](auto& type, auto& stringOrBuffer) { -@@ -1169,4 +1183,25 @@ void Pasteboard::write(const Color&) +@@ -1183,4 +1197,25 @@ void Pasteboard::write(const Color&) { } @@ -8095,10 +7905,10 @@ index 5728033e25919cef5b81d08516964aa5445c5d6e..0e588ebd34299d56ace86806bdec6e9c } // namespace WebCore diff --git a/Source/WebCore/platform/wpe/DragDataWPE.cpp b/Source/WebCore/platform/wpe/DragDataWPE.cpp new file mode 100644 -index 0000000000000000000000000000000000000000..f8fc3fa43bfe62a1c066689f48ddabaaa357a437 +index 0000000000000000000000000000000000000000..fbd32d390129129fd5b213f7f9c3e96bdca9355b --- /dev/null +++ b/Source/WebCore/platform/wpe/DragDataWPE.cpp -@@ -0,0 +1,87 @@ +@@ -0,0 +1,92 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public @@ -8185,13 +7995,18 @@ index 0000000000000000000000000000000000000000..f8fc3fa43bfe62a1c066689f48ddabaa + return m_platformDragData->url().string(); +} + ++bool DragData::shouldMatchStyleOnDrop() const ++{ ++ return false; ++} ++ +} diff --git a/Source/WebCore/platform/wpe/DragImageWPE.cpp b/Source/WebCore/platform/wpe/DragImageWPE.cpp new file mode 100644 -index 0000000000000000000000000000000000000000..a2454253889d4c7d5129c2d7895c089f54bc2e3d +index 0000000000000000000000000000000000000000..4383ede4974fb2b938aa01f2f19eb5e0c47f208c --- /dev/null +++ b/Source/WebCore/platform/wpe/DragImageWPE.cpp -@@ -0,0 +1,73 @@ +@@ -0,0 +1,74 @@ +/* + * Copyright (C) 2010,2017 Igalia S.L. + * @@ -8212,6 +8027,7 @@ index 0000000000000000000000000000000000000000..a2454253889d4c7d5129c2d7895c089f + +#include "config.h" +#include "DragImage.h" ++#include "NativeImage.h" +#include "NotImplemented.h" + +#include "Image.h" @@ -8241,7 +8057,7 @@ index 0000000000000000000000000000000000000000..a2454253889d4c7d5129c2d7895c089f + return image; +} + -+DragImageRef createDragImageFromImage(Image* image, ImageOrientation) ++DragImageRef createDragImageFromImage(Image* image, ImageOrientation, GraphicsClient*, float) +{ + return image->currentNativeImage()->platformImage(); +} @@ -8265,258 +8081,209 @@ index 0000000000000000000000000000000000000000..a2454253889d4c7d5129c2d7895c089f +} + +} -diff --git a/Source/WebCore/platform/wpe/PlatformScreenWPE.cpp b/Source/WebCore/platform/wpe/PlatformScreenWPE.cpp -index 77bdff686770e56f5445fa12216c6bff93bb5cfb..e16583ea6298864df9c8b82cb0686b2afb18ce95 100644 ---- a/Source/WebCore/platform/wpe/PlatformScreenWPE.cpp -+++ b/Source/WebCore/platform/wpe/PlatformScreenWPE.cpp -@@ -151,12 +151,12 @@ bool screenSupportsExtendedColor(Widget*) - } +diff --git a/Source/WebCore/platform/wpe/PasteboardWPE.cpp b/Source/WebCore/platform/wpe/PasteboardWPE.cpp +index c0847a84e4aeba3dac78a8ffe9826d906d33a387..c1c60572473dad33e436ab4f52e5cac5bc2d2f76 100644 +--- a/Source/WebCore/platform/wpe/PasteboardWPE.cpp ++++ b/Source/WebCore/platform/wpe/PasteboardWPE.cpp +@@ -36,6 +36,10 @@ + #include "SharedBuffer.h" + #include - #if ENABLE(TOUCH_EVENTS) --bool screenHasTouchDevice() -+bool platformScreenHasTouchDevice() ++#if ENABLE(DRAG_SUPPORT) ++#include "DragData.h" ++#endif ++ + namespace WebCore { + + std::unique_ptr Pasteboard::createForCopyAndPaste(std::unique_ptr&& context) +@@ -55,8 +59,17 @@ Pasteboard::Pasteboard(std::unique_ptr&& context) { - return true; } --bool screenIsTouchPrimaryInputDevice() -+bool platformScreenIsTouchPrimaryInputDevice() +-void Pasteboard::writeString(const String&, const String&) ++void Pasteboard::writeString(const String& type, const String& text) { - return true; ++ if (m_selectionData) { ++ if (type == "Files"_s || type == "text/uri-list"_s) ++ m_selectionData->setURIList(text); ++ else if (type == "text/html"_s) ++ m_selectionData->setMarkup(text); ++ else if (type == "text/plain"_s) ++ m_selectionData->setText(text); ++ return; ++ } + notImplemented(); } -diff --git a/Source/WebCore/platform/wpe/SelectionData.cpp b/Source/WebCore/platform/wpe/SelectionData.cpp -new file mode 100644 -index 0000000000000000000000000000000000000000..39756417d475f3aae77c2f3d7772a71a6e1bec57 ---- /dev/null -+++ b/Source/WebCore/platform/wpe/SelectionData.cpp -@@ -0,0 +1,134 @@ -+/* -+ * Copyright (C) 2009, Martin Robinson -+ * -+ * 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 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 -+ */ -+ -+#include "config.h" -+#include "SelectionData.h" -+ -+#include -+#include -+#include -+ -+namespace WebCore { -+ -+static void replaceNonBreakingSpaceWithSpace(String& str) -+{ -+ static const UChar NonBreakingSpaceCharacter = 0xA0; -+ static const UChar SpaceCharacter = ' '; -+ str = makeStringByReplacingAll(str, NonBreakingSpaceCharacter, SpaceCharacter); -+} -+ -+void SelectionData::setText(const String& newText) -+{ -+ m_text = newText; -+ replaceNonBreakingSpaceWithSpace(m_text); -+} -+ -+void SelectionData::setURIList(const String& uriListString) -+{ -+ m_uriList = uriListString; -+ -+ // This code is originally from: platform/chromium/ChromiumDataObject.cpp. -+ // FIXME: We should make this code cross-platform eventually. -+ -+ // Line separator is \r\n per RFC 2483 - however, for compatibility -+ // reasons we also allow just \n here. -+ -+ // Process the input and copy the first valid URL into the url member. -+ // In case no URLs can be found, subsequent calls to getData("URL") -+ // will get an empty string. This is in line with the HTML5 spec (see -+ // "The DragEvent and DataTransfer interfaces"). Also extract all filenames -+ // from the URI list. -+ bool setURL = hasURL(); -+ for (auto& line : uriListString.split('\n')) { -+ line = line.trim(deprecatedIsSpaceOrNewline); -+ if (line.isEmpty()) -+ continue; -+ if (line[0] == '#') -+ continue; -+ -+ URL url = URL(URL(), line); -+ if (url.isValid()) { -+ if (!setURL) { -+ m_url = url; -+ setURL = true; -+ } -+ -+ GUniqueOutPtr error; -+ GUniquePtr filename(g_filename_from_uri(line.utf8().data(), 0, &error.outPtr())); -+ if (!error && filename) -+ m_filenames.append(String::fromUTF8(filename.get())); + +@@ -69,6 +82,11 @@ void Pasteboard::writePlainText(const String& text, SmartReplaceOption) + + void Pasteboard::write(const PasteboardURL& pasteboardURL) + { ++ if (m_selectionData) { ++ m_selectionData->clearAll(); ++ m_selectionData->setURL(pasteboardURL.url, pasteboardURL.title); ++ return; ++ } + ASSERT(!pasteboardURL.url.isEmpty()); + SelectionData data; + data.setURL(pasteboardURL.url, pasteboardURL.title); +@@ -82,6 +100,15 @@ void Pasteboard::writeTrustworthyWebURLsPboardType(const PasteboardURL&) + + void Pasteboard::write(const PasteboardImage& pasteboardImage) + { ++ if (m_selectionData) { ++ m_selectionData->clearAll(); ++ if (!pasteboardImage.url.url.isEmpty()) { ++ m_selectionData->setURL(pasteboardImage.url.url, pasteboardImage.url.title); ++ m_selectionData->setMarkup(pasteboardImage.url.markup); + } ++ m_selectionData->setImage(pasteboardImage.image.get()); ++ return; + } -+} -+ -+void SelectionData::setURL(const URL& url, const String& label) -+{ -+ m_url = url; -+ if (m_uriList.isEmpty()) -+ m_uriList = url.string(); + SelectionData data; + if (!pasteboardImage.url.url.isEmpty()) { + data.setURL(pasteboardImage.url.url, pasteboardImage.url.title); +@@ -98,6 +125,12 @@ void Pasteboard::write(const PasteboardBuffer&) + + void Pasteboard::write(const PasteboardWebContent& pasteboardContent) + { ++ if (m_selectionData) { ++ m_selectionData->clearAll(); ++ m_selectionData->setText(pasteboardContent.text); ++ m_selectionData->setMarkup(pasteboardContent.markup); ++ return; ++ } + SelectionData data; + data.setText(pasteboardContent.text); + data.setMarkup(pasteboardContent.markup); +@@ -191,6 +224,26 @@ bool Pasteboard::hasData() + + Vector Pasteboard::typesSafeForBindings(const String& origin) + { ++ if (m_selectionData) { ++ ListHashSet types; ++ if (auto& buffer = m_selectionData->customData()) { ++ auto customData = PasteboardCustomData::fromSharedBuffer(*buffer); ++ if (customData.origin() == origin) { ++ for (auto& type : customData.orderedTypes()) ++ types.add(type); ++ } ++ } + -+ if (!hasText()) -+ setText(url.string()); ++ if (m_selectionData->hasText()) ++ types.add("text/plain"_s); ++ if (m_selectionData->hasMarkup()) ++ types.add("text/html"_s); ++ if (m_selectionData->hasURIList()) ++ types.add("text/uri-list"_s); + -+ if (hasMarkup()) -+ return; ++ return copyToVector(types); ++ } + -+ String actualLabel(label); -+ if (actualLabel.isEmpty()) -+ actualLabel = url.string(); + return platformStrategies()->pasteboardStrategy()->typesSafeForDOMToReadAndWrite(m_name, origin, context()); + } + +@@ -201,6 +254,13 @@ Vector Pasteboard::typesForLegacyUnsafeBindings() + + String Pasteboard::readOrigin() + { ++ if (m_selectionData) { ++ if (auto& buffer = m_selectionData->customData()) ++ return PasteboardCustomData::fromSharedBuffer(*buffer).origin(); + -+ StringBuilder markup; -+ markup.append(""); -+ GUniquePtr escaped(g_markup_escape_text(actualLabel.utf8().data(), -1)); -+ markup.append(String::fromUTF8(escaped.get())); -+ markup.append(""); -+ setMarkup(markup.toString()); -+} ++ return { }; ++ } + -+const String& SelectionData::urlLabel() const -+{ -+ if (hasText()) -+ return text(); + // FIXME: cache custom data? + if (auto buffer = platformStrategies()->pasteboardStrategy()->readBufferFromClipboard(m_name, PasteboardCustomData::wpeType())) + return PasteboardCustomData::fromSharedBuffer(*buffer).origin(); +@@ -210,11 +270,27 @@ String Pasteboard::readOrigin() + + String Pasteboard::readString(const String& type) + { ++ if (m_selectionData) { ++ if (type == "text/plain"_s) ++ return m_selectionData->text();; ++ if (type == "text/html"_s) ++ return m_selectionData->markup(); ++ if (type == "Files"_s || type == "text/uri-list"_s) ++ return m_selectionData->uriList(); ++ return { }; ++ } + -+ if (hasURL()) -+ return url().string(); + return platformStrategies()->pasteboardStrategy()->readTextFromClipboard(m_name, type); + } + + String Pasteboard::readStringInCustomData(const String& type) + { ++ if (m_selectionData) { ++ if (auto& buffer = m_selectionData->customData()) ++ return PasteboardCustomData::fromSharedBuffer(*buffer).readStringInCustomData(type); + -+ return emptyString(); ++ return { }; ++ } + // FIXME: cache custom data? + if (auto buffer = platformStrategies()->pasteboardStrategy()->readBufferFromClipboard(m_name, PasteboardCustomData::wpeType())) + return PasteboardCustomData::fromSharedBuffer(*buffer).readStringInCustomData(type); +@@ -244,6 +320,17 @@ void Pasteboard::writeMarkup(const String&) + + void Pasteboard::writeCustomData(const Vector& data) + { ++ if (m_selectionData) { ++ if (!data.isEmpty()) { ++ const auto& customData = data[0]; ++ customData.forEachPlatformString([this] (auto& type, auto& string) { ++ writeString(type, string); ++ }); ++ if (customData.hasSameOriginCustomData() || !customData.origin().isEmpty()) ++ m_selectionData->setCustomData(customData.createSharedBuffer()); ++ } ++ return; ++ } + m_changeCount = platformStrategies()->pasteboardStrategy()->writeCustomData(data, m_name, context()); + } + +@@ -257,6 +344,35 @@ int64_t Pasteboard::changeCount() const + return platformStrategies()->pasteboardStrategy()->changeCount(m_name); + } + ++#if ENABLE(DRAG_SUPPORT) ++Pasteboard::Pasteboard(std::unique_ptr&& context, SelectionData&& selectionData) ++ : m_context(WTFMove(context)) ++ , m_selectionData(WTFMove(selectionData)) ++{ +} + -+void SelectionData::clearAllExceptFilenames() ++Pasteboard::Pasteboard(std::unique_ptr&& context, SelectionData& selectionData) ++ : m_context(WTFMove(context)) ++ , m_selectionData(selectionData) +{ -+ clearText(); -+ clearMarkup(); -+ clearURIList(); -+ clearURL(); -+ clearImage(); -+ clearCustomData(); -+ -+ m_canSmartReplace = false; +} + -+void SelectionData::clearAll() ++std::unique_ptr Pasteboard::createForDragAndDrop(std::unique_ptr&& context) +{ -+ clearAllExceptFilenames(); -+ m_filenames.clear(); ++ return makeUnique(WTFMove(context), SelectionData()); +} + -+} // namespace WebCore -diff --git a/Source/WebCore/platform/wpe/SelectionData.h b/Source/WebCore/platform/wpe/SelectionData.h -new file mode 100644 -index 0000000000000000000000000000000000000000..cf2b51f6f02837a1106f4d999f2f130e2580986a ---- /dev/null -+++ b/Source/WebCore/platform/wpe/SelectionData.h -@@ -0,0 +1,82 @@ -+/* -+ * Copyright (C) 2009, Martin Robinson -+ * -+ * 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 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 -+ */ -+ -+#pragma once -+ -+#include "Image.h" -+#include "SharedBuffer.h" -+#include -+#include -+#include -+ -+namespace WebCore { -+ -+class SelectionData { -+ WTF_MAKE_FAST_ALLOCATED; -+public: -+ void setText(const String&); -+ const String& text() const { return m_text; } -+ bool hasText() const { return !m_text.isEmpty(); } -+ void clearText() { m_text = emptyString(); } -+ -+ void setMarkup(const String& newMarkup) { m_markup = newMarkup; } -+ const String& markup() const { return m_markup; } -+ bool hasMarkup() const { return !m_markup.isEmpty(); } -+ void clearMarkup() { m_markup = emptyString(); } -+ -+ void setURL(const URL&, const String&); -+ const URL& url() const { return m_url; } -+ const String& urlLabel() const; -+ bool hasURL() const { return !m_url.isEmpty() && m_url.isValid(); } -+ void clearURL() { m_url = URL(); } -+ -+ void setURIList(const String&); -+ const String& uriList() const { return m_uriList; } -+ const Vector& filenames() const { return m_filenames; } -+ bool hasURIList() const { return !m_uriList.isEmpty(); } -+ bool hasFilenames() const { return !m_filenames.isEmpty(); } -+ void clearURIList() { m_uriList = emptyString(); } -+ -+ void setImage(Image* newImage) { m_image = newImage; } -+ Image* image() const { return m_image.get(); } -+ bool hasImage() const { return m_image; } -+ void clearImage() { m_image = nullptr; } -+ -+ void setCanSmartReplace(bool canSmartReplace) { m_canSmartReplace = canSmartReplace; } -+ bool canSmartReplace() const { return m_canSmartReplace; } -+ -+ void setCustomData(Ref&& buffer) { m_customData = WTFMove(buffer); } -+ SharedBuffer* customData() const { return m_customData.get(); } -+ bool hasCustomData() const { return !!m_customData; } -+ void clearCustomData() { m_customData = nullptr; } -+ -+ void clearAll(); -+ void clearAllExceptFilenames(); ++std::unique_ptr Pasteboard::create(const DragData& dragData) ++{ ++ RELEASE_ASSERT(dragData.platformData()); ++ return makeUnique(dragData.createPasteboardContext(), *dragData.platformData()); ++} + -+private: -+ String m_text; -+ String m_markup; -+ URL m_url; -+ String m_uriList; -+ Vector m_filenames; -+ RefPtr m_image; -+ bool m_canSmartReplace { false }; -+ RefPtr m_customData; -+}; ++void Pasteboard::setDragImage(DragImage, const IntPoint&) ++{ ++} ++#endif + -+} // namespace WebCore + } // namespace WebCore + + #endif // PLATFORM(WPE) diff --git a/Source/WebCore/rendering/RenderTextControl.cpp b/Source/WebCore/rendering/RenderTextControl.cpp -index 58574b4d9fb503918e2cac0993ffe778f256a953..23de6aecb4ea7f7a1a36af6a93611559f19cfc11 100644 +index f8240cb9f855d0c35268d8c0c8fc2a0b985f4be0..3586db4ccf16a4a6bd174c09fc75915730c45ae2 100644 --- a/Source/WebCore/rendering/RenderTextControl.cpp +++ b/Source/WebCore/rendering/RenderTextControl.cpp -@@ -222,13 +222,13 @@ void RenderTextControl::layoutExcludedChildren(bool relayoutChildren) +@@ -230,13 +230,13 @@ void RenderTextControl::layoutExcludedChildren(RelayoutChildren relayoutChildren } } @@ -8532,12 +8299,12 @@ index 58574b4d9fb503918e2cac0993ffe778f256a953..23de6aecb4ea7f7a1a36af6a93611559 { auto innerText = innerTextElement(); diff --git a/Source/WebCore/rendering/RenderTextControl.h b/Source/WebCore/rendering/RenderTextControl.h -index 0c3b0f009ba9fca604f9bea904aae15142ee600e..b55788795cb550764d3de2e4dd0368773a14f290 100644 +index faf34133df0bf205072145ffbab8163b93d3c874..fdc4554952e0e33f8827bb3d00c827dec966ad15 100644 --- a/Source/WebCore/rendering/RenderTextControl.h +++ b/Source/WebCore/rendering/RenderTextControl.h -@@ -37,9 +37,9 @@ public: - +@@ -38,9 +38,9 @@ public: WEBCORE_EXPORT HTMLTextFormControlElement& textFormControlElement() const; + WEBCORE_EXPORT Ref protectedTextFormControlElement() const; -#if PLATFORM(IOS_FAMILY) bool canScroll() const; @@ -8547,10 +8314,10 @@ index 0c3b0f009ba9fca604f9bea904aae15142ee600e..b55788795cb550764d3de2e4dd036877 int innerLineHeight() const override; #endif diff --git a/Source/WebCore/workers/WorkerConsoleClient.cpp b/Source/WebCore/workers/WorkerConsoleClient.cpp -index 2cd5580e166c7eb03d7813fba647cb9748ee72ab..8d897cd56b35301031626bc4160fac907677f9f6 100644 +index 7546c0266801803c9f73179e7a370a4f42a4f05e..05bb106972e648f6fe98aaa1f471390e3a98c674 100644 --- a/Source/WebCore/workers/WorkerConsoleClient.cpp +++ b/Source/WebCore/workers/WorkerConsoleClient.cpp -@@ -101,4 +101,6 @@ void WorkerConsoleClient::recordEnd(JSC::JSGlobalObject*, Ref&& +@@ -124,4 +124,6 @@ void WorkerConsoleClient::recordEnd(JSC::JSGlobalObject*, Ref&& // FIXME: Web Inspector: support console screenshots in a Worker void WorkerConsoleClient::screenshot(JSC::JSGlobalObject*, Ref&&) { } @@ -8558,10 +8325,10 @@ index 2cd5580e166c7eb03d7813fba647cb9748ee72ab..8d897cd56b35301031626bc4160fac90 + } // namespace WebCore diff --git a/Source/WebCore/workers/WorkerConsoleClient.h b/Source/WebCore/workers/WorkerConsoleClient.h -index 1d8488e0d36288e09cd5662bd7f770ade95dfee3..dee07f87b47d62d4ef8ede45824bdb2f6a39ad0a 100644 +index db95c8273bd0deb3f903a45d02fc07bbbd8ab305..bf88228b4c838b90d11d430cc9429d5130631afa 100644 --- a/Source/WebCore/workers/WorkerConsoleClient.h +++ b/Source/WebCore/workers/WorkerConsoleClient.h -@@ -57,6 +57,7 @@ private: +@@ -58,6 +58,7 @@ private: void record(JSC::JSGlobalObject*, Ref&&) override; void recordEnd(JSC::JSGlobalObject*, Ref&&) override; void screenshot(JSC::JSGlobalObject*, Ref&&) override; @@ -8570,10 +8337,10 @@ index 1d8488e0d36288e09cd5662bd7f770ade95dfee3..dee07f87b47d62d4ef8ede45824bdb2f WorkerOrWorkletGlobalScope& m_globalScope; }; diff --git a/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp b/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp -index caf9b8fe4c94e56154fa70b4b09391dc1db5b4b6..e9c038a464ac0e30bce7c1e162911d12086c1082 100644 +index 23a9f5b5afdb7aba0efdc6a1db7898abc641b0fa..220ed1f59582562268f02262ea2f7ed3388aab1f 100644 --- a/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp +++ b/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp -@@ -96,6 +96,8 @@ +@@ -97,6 +97,8 @@ #if PLATFORM(COCOA) #include @@ -8582,7 +8349,7 @@ index caf9b8fe4c94e56154fa70b4b09391dc1db5b4b6..e9c038a464ac0e30bce7c1e162911d12 #endif #if ENABLE(APPLE_PAY_REMOTE_UI) -@@ -1093,6 +1095,14 @@ void NetworkConnectionToWebProcess::clearPageSpecificData(PageIdentifier pageID) +@@ -1237,6 +1239,14 @@ void NetworkConnectionToWebProcess::clearPageSpecificData(PageIdentifier pageID) storageSession->clearPageSpecificDataForResourceLoadStatistics(pageID); } @@ -8596,12 +8363,12 @@ index caf9b8fe4c94e56154fa70b4b09391dc1db5b4b6..e9c038a464ac0e30bce7c1e162911d12 + void NetworkConnectionToWebProcess::removeStorageAccessForFrame(FrameIdentifier frameID, PageIdentifier pageID) { - if (auto* storageSession = networkProcess().storageSession(m_sessionID)) + if (auto* storageSession = protectedNetworkProcess()->storageSession(m_sessionID)) diff --git a/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.h b/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.h -index a9fd7f7625ca67043c8ed0dcd7979df49cd65266..8e7903e0c5acefb8c5381f8297b52d610b8e4a29 100644 +index 3f1539237c6c8d1cd832cd3ece2ba20939e01a41..1259c36e38d46c0ebfdf98be20f217433f831ca5 100644 --- a/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.h +++ b/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.h -@@ -343,6 +343,8 @@ private: +@@ -388,6 +388,8 @@ private: void clearPageSpecificData(WebCore::PageIdentifier); @@ -8611,10 +8378,10 @@ index a9fd7f7625ca67043c8ed0dcd7979df49cd65266..8e7903e0c5acefb8c5381f8297b52d61 void logUserInteraction(RegistrableDomain&&); diff --git a/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.messages.in b/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.messages.in -index b90021dcc3e4d70cb7b42b538050c5a37653b3cd..acc42255c8d3fb08971f62e6771f022f544199b7 100644 +index b10706aafd037a2b92a68b0d2c474ec2e42cd2fe..f80792c02d880dbd61849233fdbc348f1eeffb33 100644 --- a/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.messages.in +++ b/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.messages.in -@@ -74,6 +74,8 @@ messages -> NetworkConnectionToWebProcess LegacyReceiver { +@@ -80,6 +80,8 @@ messages -> NetworkConnectionToWebProcess WantsDispatchMessage { ClearPageSpecificData(WebCore::PageIdentifier pageID); @@ -8623,105 +8390,15 @@ index b90021dcc3e4d70cb7b42b538050c5a37653b3cd..acc42255c8d3fb08971f62e6771f022f RemoveStorageAccessForFrame(WebCore::FrameIdentifier frameID, WebCore::PageIdentifier pageID); LogUserInteraction(WebCore::RegistrableDomain domain) ResourceLoadStatisticsUpdated(Vector statistics) -> () -diff --git a/Source/WebKit/NetworkProcess/NetworkProcess.cpp b/Source/WebKit/NetworkProcess/NetworkProcess.cpp -index cd174626a10faea7348b568bcfc384d9aaa86f5a..72e66509f540301cedc64ac9ea69f50fb1044245 100644 ---- a/Source/WebKit/NetworkProcess/NetworkProcess.cpp -+++ b/Source/WebKit/NetworkProcess/NetworkProcess.cpp -@@ -658,6 +658,12 @@ void NetworkProcess::registrableDomainsExemptFromWebsiteDataDeletion(PAL::Sessio - completionHandler({ }); - } - -+void NetworkProcess::setIgnoreCertificateErrors(PAL::SessionID sessionID, bool ignore) -+{ -+ if (auto* networkSession = this->networkSession(sessionID)) -+ networkSession->setIgnoreCertificateErrors(ignore); -+} -+ - void NetworkProcess::dumpResourceLoadStatistics(PAL::SessionID sessionID, CompletionHandler&& completionHandler) - { - if (auto* session = networkSession(sessionID)) { -diff --git a/Source/WebKit/NetworkProcess/NetworkProcess.h b/Source/WebKit/NetworkProcess/NetworkProcess.h -index 6d41842684f3e0e8b1190359f87105b747cf9da9..279d5c033397afb120a082953c0112f34bf2878a 100644 ---- a/Source/WebKit/NetworkProcess/NetworkProcess.h -+++ b/Source/WebKit/NetworkProcess/NetworkProcess.h -@@ -33,6 +33,7 @@ - #include "DownloadManager.h" - #include "NetworkContentRuleListManager.h" - #include "QuotaIncreaseRequestIdentifier.h" -+#include "StorageNamespaceIdentifier.h" - #include "WebPageProxyIdentifier.h" - #include "WebResourceLoadStatisticsStore.h" - #include "WebsiteData.h" -@@ -82,6 +83,7 @@ class SessionID; - - namespace WebCore { - class CertificateInfo; -+struct Cookie; - class CurlProxySettings; - class ProtectionSpace; - class NetworkStorageSession; -@@ -212,6 +214,9 @@ public: - - void registrableDomainsWithLastAccessedTime(PAL::SessionID, CompletionHandler>)>&&); - void registrableDomainsExemptFromWebsiteDataDeletion(PAL::SessionID, CompletionHandler)>&&); -+ -+ void setIgnoreCertificateErrors(PAL::SessionID, bool); -+ - void clearPrevalentResource(PAL::SessionID, RegistrableDomain&&, CompletionHandler&&); - void clearUserInteraction(PAL::SessionID, RegistrableDomain&&, CompletionHandler&&); - void deleteAndRestrictWebsiteDataForRegistrableDomains(PAL::SessionID, OptionSet, RegistrableDomainsToDeleteOrRestrictWebsiteDataFor&&, bool shouldNotifyPage, CompletionHandler&&)>&&); -diff --git a/Source/WebKit/NetworkProcess/NetworkProcess.messages.in b/Source/WebKit/NetworkProcess/NetworkProcess.messages.in -index 5e590b5a09f8bd5d040e2e68d54c545c52d4b179..c58bb6270ab75026187fdda6c94822f6aa47a35a 100644 ---- a/Source/WebKit/NetworkProcess/NetworkProcess.messages.in -+++ b/Source/WebKit/NetworkProcess/NetworkProcess.messages.in -@@ -79,6 +79,8 @@ messages -> NetworkProcess LegacyReceiver { - - SetInspectionForServiceWorkersAllowed(PAL::SessionID sessionID, bool inspectable) - -+ SetIgnoreCertificateErrors(PAL::SessionID sessionID, bool ignoreTLSErrors) -+ - ClearPrevalentResource(PAL::SessionID sessionID, WebCore::RegistrableDomain resourceDomain) -> () - ClearUserInteraction(PAL::SessionID sessionID, WebCore::RegistrableDomain resourceDomain) -> () - DumpResourceLoadStatistics(PAL::SessionID sessionID) -> (String dumpedStatistics) -diff --git a/Source/WebKit/NetworkProcess/NetworkSession.h b/Source/WebKit/NetworkProcess/NetworkSession.h -index b22ff912dba5b116a979119af6721bcfcc72ec5d..deb9a0b67adb51b190833354e7ea5d8e46aea56c 100644 ---- a/Source/WebKit/NetworkProcess/NetworkSession.h -+++ b/Source/WebKit/NetworkProcess/NetworkSession.h -@@ -200,6 +200,9 @@ public: - - void lowMemoryHandler(WTF::Critical); - -+ void setIgnoreCertificateErrors(bool ignore) { m_ignoreCertificateErrors = ignore; } -+ bool ignoreCertificateErrors() { return m_ignoreCertificateErrors; } -+ - void removeSoftUpdateLoader(ServiceWorkerSoftUpdateLoader* loader) { m_softUpdateLoaders.remove(loader); } - void addNavigationPreloaderTask(ServiceWorkerFetchTask&); - ServiceWorkerFetchTask* navigationPreloaderTaskFromFetchIdentifier(WebCore::FetchIdentifier); -@@ -309,6 +312,7 @@ protected: - bool m_privateClickMeasurementDebugModeEnabled { false }; - std::optional m_ephemeralMeasurement; - bool m_isRunningEphemeralMeasurementTest { false }; -+ bool m_ignoreCertificateErrors { false }; - - HashSet> m_keptAliveLoads; - diff --git a/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm b/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm -index 95d84783fe56cc381e67113924780bf1e2d9320e..129e7ada7fa90665a80ccf79641d7fcaf9f085a0 100644 +index 00a6ce04cae578c8ac9d934e6c4e38041e4a4aee..ab587ef45e27bddf3e31d28882794f7fb11dea0d 100644 --- a/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm +++ b/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm -@@ -761,6 +761,8 @@ - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didRece - - if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { - sessionCocoa->setClientAuditToken(challenge); -+ if (sessionCocoa->ignoreCertificateErrors()) -+ return completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]); - - NSURLSessionTaskTransactionMetrics *metrics = task._incompleteTaskMetrics.transactionMetrics.lastObject; - auto tlsVersion = (tls_protocol_version_t)metrics.negotiatedTLSProtocolVersion.unsignedShortValue; -@@ -1100,6 +1102,13 @@ ALLOW_DEPRECATED_DECLARATIONS_END - - resourceResponse.setDeprecatedNetworkLoadMetrics(WebCore::copyTimingData(taskMetrics, networkDataTask->networkLoadMetrics())); +@@ -1148,6 +1148,14 @@ - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)data + resourceResponse.setDeprecatedNetworkLoadMetrics(WebCore::copyTimingData(taskMetrics.get(), networkDataTask->networkLoadMetrics())); + resourceResponse.setProxyName(WTFMove(proxyName)); ++ + __block WebCore::HTTPHeaderMap requestHeaders; + NSURLSessionTaskTransactionMetrics *m = dataTask._incompleteTaskMetrics.transactionMetrics.lastObject; + [m.request.allHTTPHeaderFields enumerateKeysAndObjectsUsingBlock:^(NSString *name, NSString *value, BOOL *) { @@ -8731,35 +8408,12 @@ index 95d84783fe56cc381e67113924780bf1e2d9320e..129e7ada7fa90665a80ccf79641d7fca + networkDataTask->didReceiveResponse(WTFMove(resourceResponse), negotiatedLegacyTLS, privateRelayed, [completionHandler = makeBlockPtr(completionHandler), taskIdentifier](WebCore::PolicyAction policyAction) { #if !LOG_DISABLED - LOG(NetworkSession, "%llu didReceiveResponse completionHandler (%d)", taskIdentifier, policyAction); + LOG(NetworkSession, "%llu didReceiveResponse completionHandler (%s)", taskIdentifier, toString(policyAction).characters()); diff --git a/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.cpp b/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.cpp -index 383b0c08feda5c59455407093f656311c0a0c3fc..4522f3a562e67f41f29ee699ab9ed9dad999d90e 100644 +index 975e4097fb5b9cb610ce67c70ea85e6434ec7a9d..6e2676cd751883e2eae26e38ffaefa873857b604 100644 --- a/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.cpp +++ b/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.cpp -@@ -80,10 +80,18 @@ NetworkDataTaskCurl::NetworkDataTaskCurl(NetworkSession& session, NetworkDataTas - blockCookies(); - restrictRequestReferrerToOriginIfNeeded(request); - -- m_curlRequest = createCurlRequest(WTFMove(request)); -- if (!m_initialCredential.isEmpty()) { -- m_curlRequest->setUserPass(m_initialCredential.user(), m_initialCredential.password()); -- m_curlRequest->setAuthenticationScheme(ProtectionSpace::AuthenticationScheme::HTTPBasic); -+ if (request.url().protocolIsData()) { -+ DataURLDecoder::decode(request.url(), { }, DataURLDecoder::ShouldValidatePadding::Yes, [this, protectedThis = Ref { *this }](auto decodeResult) mutable { -+ didReadDataURL(WTFMove(decodeResult)); -+ }); -+ } else { -+ m_curlRequest = createCurlRequest(WTFMove(request)); -+ if (!m_initialCredential.isEmpty()) { -+ m_curlRequest->setUserPass(m_initialCredential.user(), m_initialCredential.password()); -+ m_curlRequest->setAuthenticationScheme(ProtectionSpace::AuthenticationScheme::HTTPBasic); -+ } -+ if (m_session->ignoreCertificateErrors()) -+ m_curlRequest->disableServerTrustEvaluation(); - } - } - -@@ -166,6 +174,7 @@ void NetworkDataTaskCurl::curlDidReceiveResponse(CurlRequest& request, CurlRespo +@@ -166,6 +166,7 @@ void NetworkDataTaskCurl::curlDidReceiveResponse(CurlRequest& request, CurlRespo updateNetworkLoadMetrics(receivedResponse.networkLoadMetrics); m_response.setDeprecatedNetworkLoadMetrics(Box::create(WTFMove(receivedResponse.networkLoadMetrics))); @@ -8767,177 +8421,11 @@ index 383b0c08feda5c59455407093f656311c0a0c3fc..4522f3a562e67f41f29ee699ab9ed9da handleCookieHeaders(request.resourceRequest(), receivedResponse); -@@ -290,6 +299,36 @@ bool NetworkDataTaskCurl::shouldRedirectAsGET(const ResourceRequest& request, bo - return false; - } - -+void NetworkDataTaskCurl::didReadDataURL(std::optional&& result) -+{ -+ if (state() == State::Canceling || state() == State::Completed) -+ return; -+ -+ m_dataURLResult = WTFMove(result); -+ m_response = ResourceResponse::dataURLResponse(firstRequest().url(), m_dataURLResult.value()); -+ invokeDidReceiveResponse(); -+} -+ -+void NetworkDataTaskCurl::downloadDataURL(Download& download) -+{ -+ if (!m_dataURLResult) { -+ deleteDownloadFile(); -+ download.didFail(internalError(firstRequest().url()), std::span()); -+ return; -+ } -+ -+ if (-1 == FileSystem::writeToFile(m_downloadDestinationFile, static_cast(m_dataURLResult.value().data.data()), m_dataURLResult.value().data.size())) { -+ deleteDownloadFile(); -+ download.didFail(ResourceError(CURLE_WRITE_ERROR, m_response.url()), std::span()); -+ return; -+ } -+ -+ download.didReceiveData(m_dataURLResult.value().data.size(), 0, 0); -+ FileSystem::closeFile(m_downloadDestinationFile); -+ m_downloadDestinationFile = FileSystem::invalidPlatformFileHandle; -+ download.didFinish(); -+} -+ - void NetworkDataTaskCurl::invokeDidReceiveResponse() - { - didReceiveResponse(ResourceResponse(m_response), NegotiatedLegacyTLS::No, PrivateRelayed::No, [this, protectedThis = Ref { *this }](PolicyAction policyAction) { -@@ -320,6 +359,8 @@ void NetworkDataTaskCurl::invokeDidReceiveResponse() - downloadPtr->didCreateDestination(m_pendingDownloadLocation); - if (m_curlRequest) - m_curlRequest->completeDidReceiveResponse(); -+ else if (firstRequest().url().protocolIsData()) -+ downloadDataURL(*downloadPtr); - break; - } - default: -@@ -408,6 +449,8 @@ void NetworkDataTaskCurl::willPerformHTTPRedirection() - m_curlRequest->setUserPass(m_initialCredential.user(), m_initialCredential.password()); - m_curlRequest->setAuthenticationScheme(ProtectionSpace::AuthenticationScheme::HTTPBasic); - } -+ if (m_session->ignoreCertificateErrors()) -+ m_curlRequest->disableServerTrustEvaluation(); - - if (m_state != State::Suspended) { - m_state = State::Suspended; -diff --git a/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.h b/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.h -index bfff08efb10d4d6cd1a27755403ed53ed58ce919..1a59755f684229bd47fd70369e4a9d4282950ef7 100644 ---- a/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.h -+++ b/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.h -@@ -28,6 +28,7 @@ - #include "NetworkDataTask.h" - #include "NetworkLoadParameters.h" - #include -+#include - #include - #include - #include -@@ -43,6 +44,8 @@ class SharedBuffer; - - namespace WebKit { - -+class Download; -+ - class NetworkDataTaskCurl final : public NetworkDataTask, public WebCore::CurlRequestClient { - public: - static Ref create(NetworkSession& session, NetworkDataTaskClient& client, const NetworkLoadParameters& parameters) -@@ -75,6 +78,9 @@ private: - void curlDidComplete(WebCore::CurlRequest&, WebCore::NetworkLoadMetrics&&) override; - void curlDidFailWithError(WebCore::CurlRequest&, WebCore::ResourceError&&, WebCore::CertificateInfo&&) override; - -+ void didReadDataURL(std::optional&&); -+ void downloadDataURL(Download&); -+ - void invokeDidReceiveResponse(); - - bool shouldStartHTTPRedirection(); -@@ -113,6 +119,9 @@ private: - unsigned m_authFailureCount { 0 }; - - bool m_allowOverwriteDownload { false }; -+ -+ std::optional m_dataURLResult; -+ - FileSystem::PlatformFileHandle m_downloadDestinationFile { FileSystem::invalidPlatformFileHandle }; - - bool m_blockingCookies { false }; -diff --git a/Source/WebKit/NetworkProcess/curl/NetworkSessionCurl.cpp b/Source/WebKit/NetworkProcess/curl/NetworkSessionCurl.cpp -index 486849ef6f550a0f3caab311abf5743c6d38e5af..afeaac63a18d9e71d3afead23b7da4fecfc27544 100644 ---- a/Source/WebKit/NetworkProcess/curl/NetworkSessionCurl.cpp -+++ b/Source/WebKit/NetworkProcess/curl/NetworkSessionCurl.cpp -@@ -68,7 +68,7 @@ void NetworkSessionCurl::clearAlternativeServices(WallTime) - - std::unique_ptr NetworkSessionCurl::createWebSocketTask(WebPageProxyIdentifier webPageProxyID, std::optional, std::optional, NetworkSocketChannel& channel, const WebCore::ResourceRequest& request, const String& protocol, const WebCore::ClientOrigin& clientOrigin, bool, bool, OptionSet, ShouldRelaxThirdPartyCookieBlocking, StoredCredentialsPolicy) - { -- return makeUnique(channel, webPageProxyID, request, protocol, clientOrigin); -+ return makeUnique(channel, webPageProxyID, request, protocol, ignoreCertificateErrors(), clientOrigin); - } - - void NetworkSessionCurl::didReceiveChallenge(WebSocketTask& webSocketTask, WebCore::AuthenticationChallenge&& challenge, CompletionHandler&& challengeCompletionHandler) -diff --git a/Source/WebKit/NetworkProcess/curl/WebSocketTaskCurl.cpp b/Source/WebKit/NetworkProcess/curl/WebSocketTaskCurl.cpp -index 60106d6125f85d0cf848e828fd4ed7a50005f105..021d7b6d12baf4671a2968753969ca4675044313 100644 ---- a/Source/WebKit/NetworkProcess/curl/WebSocketTaskCurl.cpp -+++ b/Source/WebKit/NetworkProcess/curl/WebSocketTaskCurl.cpp -@@ -36,11 +36,12 @@ - - namespace WebKit { - --WebSocketTask::WebSocketTask(NetworkSocketChannel& channel, WebPageProxyIdentifier webProxyPageID, const WebCore::ResourceRequest& request, const String& protocol, const WebCore::ClientOrigin& clientOrigin) -+WebSocketTask::WebSocketTask(NetworkSocketChannel& channel, WebPageProxyIdentifier webProxyPageID, const WebCore::ResourceRequest& request, const String& protocol, bool ignoreCertificateErrors, const WebCore::ClientOrigin& clientOrigin) - : m_channel(channel) - , m_webProxyPageID(webProxyPageID) - , m_request(request.isolatedCopy()) - , m_protocol(protocol) -+ , m_ignoreCertificateErrors(ignoreCertificateErrors) - , m_scheduler(WebCore::CurlContext::singleton().streamScheduler()) - { - // We use topOrigin in case of service worker websocket connections, for which pageID does not link to a real page. -@@ -52,7 +53,7 @@ WebSocketTask::WebSocketTask(NetworkSocketChannel& channel, WebPageProxyIdentifi - if (networkSession() && networkSession()->networkProcess().localhostAliasesForTesting().contains(m_request.url().host())) - localhostAlias = WebCore::CurlStream::LocalhostAlias::Enable; - -- m_streamID = m_scheduler.createStream(request.url(), *this, WebCore::CurlStream::ServerTrustEvaluation::Enable, localhostAlias); -+ m_streamID = m_scheduler.createStream(request.url(), ignoreCertificateErrors, *this, WebCore::CurlStream::ServerTrustEvaluation::Enable, localhostAlias); - m_channel.didSendHandshakeRequest(WebCore::ResourceRequest(m_request)); - } - -@@ -257,7 +258,7 @@ void WebSocketTask::tryServerTrustEvaluation(WebCore::AuthenticationChallenge&& - if (networkSession() && networkSession()->networkProcess().localhostAliasesForTesting().contains(m_request.url().host())) - localhostAlias = WebCore::CurlStream::LocalhostAlias::Enable; - -- m_streamID = m_scheduler.createStream(m_request.url(), *this, WebCore::CurlStream::ServerTrustEvaluation::Disable, localhostAlias); -+ m_streamID = m_scheduler.createStream(m_request.url(), m_ignoreCertificateErrors, *this, WebCore::CurlStream::ServerTrustEvaluation::Disable, localhostAlias); - } else - didFail(WTFMove(errorReason)); - }); -diff --git a/Source/WebKit/NetworkProcess/curl/WebSocketTaskCurl.h b/Source/WebKit/NetworkProcess/curl/WebSocketTaskCurl.h -index 5023a9be6554abc9ffe8fb37968978cb28c5b9a1..9cfdedd0411bf32843c2c9a7d7d722c5ee4f6e46 100644 ---- a/Source/WebKit/NetworkProcess/curl/WebSocketTaskCurl.h -+++ b/Source/WebKit/NetworkProcess/curl/WebSocketTaskCurl.h -@@ -49,7 +49,7 @@ struct SessionSet; - class WebSocketTask : public CanMakeWeakPtr, public WebCore::CurlStream::Client { - WTF_MAKE_FAST_ALLOCATED; - public: -- WebSocketTask(NetworkSocketChannel&, WebPageProxyIdentifier, const WebCore::ResourceRequest&, const String& protocol, const WebCore::ClientOrigin&); -+ WebSocketTask(NetworkSocketChannel&, WebPageProxyIdentifier, const WebCore::ResourceRequest&, const String& protocol, bool ignoreCertificateErrors, const WebCore::ClientOrigin&); - virtual ~WebSocketTask(); - - void sendString(std::span, CompletionHandler&&); -@@ -102,6 +102,7 @@ private: - WebPageProxyIdentifier m_webProxyPageID; - WebCore::ResourceRequest m_request; - String m_protocol; -+ bool m_ignoreCertificateErrors { false }; - WebCore::SecurityOriginData m_topOrigin; - - WebCore::CurlStreamScheduler& m_scheduler; diff --git a/Source/WebKit/NetworkProcess/mac/com.apple.WebKit.NetworkProcess.sb.in b/Source/WebKit/NetworkProcess/mac/com.apple.WebKit.NetworkProcess.sb.in -index 51f3fb7ae9a4e208bc11ac583b72e772eac5e4dc..386ec972eba86763b83407c322a971a30286f40f 100644 +index aebce13abcf8f93c8fa48936120c2065f0a664b1..7b003cf0d65d0179b165fcbce775cfd5b6a19374 100644 --- a/Source/WebKit/NetworkProcess/mac/com.apple.WebKit.NetworkProcess.sb.in +++ b/Source/WebKit/NetworkProcess/mac/com.apple.WebKit.NetworkProcess.sb.in -@@ -448,9 +448,11 @@ +@@ -451,9 +451,11 @@ ;; FIXME: This should be removed when is fixed. ;; Restrict AppSandboxed processes from creating /Library/Keychains, but allow access to the contents of /Library/Keychains: @@ -8953,93 +8441,23 @@ index 51f3fb7ae9a4e208bc11ac583b72e772eac5e4dc..386ec972eba86763b83407c322a971a3 ;; Except deny access to new-style iOS Keychain folders which are UUIDs. (deny file-read* file-write* diff --git a/Source/WebKit/NetworkProcess/soup/NetworkDataTaskSoup.cpp b/Source/WebKit/NetworkProcess/soup/NetworkDataTaskSoup.cpp -index 4295b59484942084404ff7b03669aba249667e97..73dea05ac933938a19bbd6ec5bbcbd6139f98c25 100644 +index 983947a9ad3abf138c1a6052807c4e86beb5c1d1..c5de2e1f1c74317ee00b9558e0e5c3093496c386 100644 --- a/Source/WebKit/NetworkProcess/soup/NetworkDataTaskSoup.cpp +++ b/Source/WebKit/NetworkProcess/soup/NetworkDataTaskSoup.cpp -@@ -466,6 +466,8 @@ void NetworkDataTaskSoup::didSendRequest(GRefPtr&& inputStream) - m_networkLoadMetrics.failsTAOCheck = !passesTimingAllowOriginCheck(m_response, *origin); - } +@@ -461,6 +461,8 @@ void NetworkDataTaskSoup::didSendRequest(GRefPtr&& inputStream) + m_networkLoadMetrics.responseStart = MonotonicTime::now(); + #endif + auto& additionalMetrics = additionalNetworkLoadMetricsForWebInspector(); + m_response.m_httpRequestHeaderFields = additionalMetrics.requestHeaders; dispatchDidReceiveResponse(); } -@@ -563,6 +565,8 @@ bool NetworkDataTaskSoup::acceptCertificate(GTlsCertificate* certificate, GTlsCe - { - ASSERT(m_soupMessage); - URL url = soupURIToURL(soup_message_get_uri(m_soupMessage.get())); -+ if (m_session->ignoreCertificateErrors()) -+ return true; - auto error = static_cast(*m_session).soupNetworkSession().checkTLSErrors(url, certificate, tlsErrors); - if (!error) - return true; -diff --git a/Source/WebKit/NetworkProcess/soup/NetworkSessionSoup.cpp b/Source/WebKit/NetworkProcess/soup/NetworkSessionSoup.cpp -index 60e79ff683e280591d686468c42decf1ac109ed2..ef74cb09e75c3e6f57d180487fa266b7a0f09af5 100644 ---- a/Source/WebKit/NetworkProcess/soup/NetworkSessionSoup.cpp -+++ b/Source/WebKit/NetworkProcess/soup/NetworkSessionSoup.cpp -@@ -97,6 +97,11 @@ void NetworkSessionSoup::clearCredentials(WallTime) - #endif - } - -+static gboolean webSocketAcceptCertificateCallbackIgnoreTLSErrors(GTlsConnection* connection, GTlsCertificate* certificate, GTlsCertificateFlags errors, NetworkSessionSoup* session) -+{ -+ return TRUE; -+} -+ - #if USE(SOUP2) - static gboolean webSocketAcceptCertificateCallback(GTlsConnection* connection, GTlsCertificate* certificate, GTlsCertificateFlags errors, NetworkSessionSoup* session) - { -@@ -117,6 +122,15 @@ static void webSocketMessageNetworkEventCallback(SoupMessage* soupMessage, GSock - } - #endif - -+static void webSocketMessageNetworkEventCallbackIgnoreTLSErrors(SoupMessage* soupMessage, GSocketClientEvent event, GIOStream* connection) -+{ -+ if (event != G_SOCKET_CLIENT_TLS_HANDSHAKING) -+ return; -+ -+ g_object_set_data(G_OBJECT(connection), "wk-soup-message", soupMessage); -+ g_signal_connect(connection, "accept-certificate", G_CALLBACK(webSocketAcceptCertificateCallbackIgnoreTLSErrors), soupMessage); -+} -+ - std::unique_ptr NetworkSessionSoup::createWebSocketTask(WebPageProxyIdentifier, std::optional frameID, std::optional pageID, NetworkSocketChannel& channel, const ResourceRequest& request, const String& protocol, const ClientOrigin&, bool, bool, OptionSet, ShouldRelaxThirdPartyCookieBlocking shouldRelaxThirdPartyCookieBlocking, StoredCredentialsPolicy) - { - GRefPtr soupMessage = request.createSoupMessage(blobRegistry()); -@@ -125,14 +139,21 @@ std::unique_ptr NetworkSessionSoup::createWebSocketTask(WebPagePr - - if (request.url().protocolIs("wss"_s)) { - #if USE(SOUP2) -- g_signal_connect(soupMessage.get(), "network-event", G_CALLBACK(webSocketMessageNetworkEventCallback), this); -+ if (ignoreCertificateErrors()) -+ g_signal_connect(soupMessage.get(), "network-event", G_CALLBACK(webSocketMessageNetworkEventCallbackIgnoreTLSErrors), this); -+ else -+ g_signal_connect(soupMessage.get(), "network-event", G_CALLBACK(webSocketMessageNetworkEventCallback), this); - #else -- g_signal_connect(soupMessage.get(), "accept-certificate", G_CALLBACK(+[](SoupMessage* message, GTlsCertificate* certificate, GTlsCertificateFlags errors, NetworkSessionSoup* session) -> gboolean { -- if (DeprecatedGlobalSettings::allowsAnySSLCertificate()) -- return TRUE; -- -- return !session->soupNetworkSession().checkTLSErrors(soup_message_get_uri(message), certificate, errors); -- }), this); -+ if (ignoreCertificateErrors()) { -+ g_signal_connect(soupMessage.get(), "accept-certificate", G_CALLBACK(webSocketAcceptCertificateCallbackIgnoreTLSErrors), this); -+ } else { -+ g_signal_connect(soupMessage.get(), "accept-certificate", G_CALLBACK(+[](SoupMessage* message, GTlsCertificate* certificate, GTlsCertificateFlags errors, NetworkSessionSoup* session) -> gboolean { -+ if (DeprecatedGlobalSettings::allowsAnySSLCertificate()) -+ return TRUE; -+ -+ return !session->soupNetworkSession().checkTLSErrors(soup_message_get_uri(message), certificate, errors); -+ }), this); -+ } - #endif - } - diff --git a/Source/WebKit/PlatformGTK.cmake b/Source/WebKit/PlatformGTK.cmake -index bd8dab990c4c034059d21588921784f047bb6d6a..46a61dcef89e94a9a1a25e6ae352ec88f0aec5e7 100644 +index 1f0116517d88a3a0fffade7288a4909bd848df88..83b9598353ad6dd9192b0c8827bba25d1cb069ad 100644 --- a/Source/WebKit/PlatformGTK.cmake +++ b/Source/WebKit/PlatformGTK.cmake -@@ -321,6 +321,9 @@ list(APPEND WebKit_SYSTEM_INCLUDE_DIRECTORIES +@@ -320,6 +320,9 @@ list(APPEND WebKit_SYSTEM_INCLUDE_DIRECTORIES ${GSTREAMER_PBUTILS_INCLUDE_DIRS} ${GTK_INCLUDE_DIRS} ${LIBSOUP_INCLUDE_DIRS} @@ -9049,7 +8467,7 @@ index bd8dab990c4c034059d21588921784f047bb6d6a..46a61dcef89e94a9a1a25e6ae352ec88 ) list(APPEND WebKit_INTERFACE_INCLUDE_DIRECTORIES -@@ -351,6 +354,9 @@ if (USE_LIBWEBRTC) +@@ -359,6 +362,9 @@ if (USE_LIBWEBRTC) list(APPEND WebKit_SYSTEM_INCLUDE_DIRECTORIES "${THIRDPARTY_DIR}/libwebrtc/Source/" "${THIRDPARTY_DIR}/libwebrtc/Source/webrtc" @@ -9059,7 +8477,7 @@ index bd8dab990c4c034059d21588921784f047bb6d6a..46a61dcef89e94a9a1a25e6ae352ec88 ) endif () -@@ -402,6 +408,12 @@ else () +@@ -410,6 +416,12 @@ else () set(WebKitGTK_ENUM_HEADER_TEMPLATE ${WEBKIT_DIR}/UIProcess/API/gtk/WebKitEnumTypesGtk3.h.in) endif () @@ -9073,10 +8491,10 @@ index bd8dab990c4c034059d21588921784f047bb6d6a..46a61dcef89e94a9a1a25e6ae352ec88 set(WebKitGTK_ENUM_GENERATION_HEADERS ${WebKitGTK_INSTALLED_HEADERS}) list(REMOVE_ITEM WebKitGTK_ENUM_GENERATION_HEADERS ${WebKitGTK_DERIVED_SOURCES_DIR}/webkit/WebKitEnumTypes.h) diff --git a/Source/WebKit/PlatformWPE.cmake b/Source/WebKit/PlatformWPE.cmake -index 8f27536b690e863fcaf086c04d1b0fb21356a622..a0207624821b4179d7adc646adf06aae65f0ca33 100644 +index 56b8ece0181ad1dacd3e33ee1463ac1cc4b2ac20..fb0b4169f860e9064397216b176024760a3503cd 100644 --- a/Source/WebKit/PlatformWPE.cmake +++ b/Source/WebKit/PlatformWPE.cmake -@@ -212,6 +212,7 @@ set(WPE_API_HEADER_TEMPLATES +@@ -221,6 +221,7 @@ set(WPE_API_HEADER_TEMPLATES ${WEBKIT_DIR}/UIProcess/API/glib/WebKitWindowProperties.h.in ${WEBKIT_DIR}/UIProcess/API/glib/WebKitWebsitePolicies.h.in ${WEBKIT_DIR}/UIProcess/API/glib/webkit.h.in @@ -9084,7 +8502,7 @@ index 8f27536b690e863fcaf086c04d1b0fb21356a622..a0207624821b4179d7adc646adf06aae ) if (ENABLE_2022_GLIB_API) -@@ -423,8 +424,17 @@ list(APPEND WebKit_SYSTEM_INCLUDE_DIRECTORIES +@@ -432,8 +433,17 @@ list(APPEND WebKit_SYSTEM_INCLUDE_DIRECTORIES ${GIO_UNIX_INCLUDE_DIRS} ${GLIB_INCLUDE_DIRS} ${LIBSOUP_INCLUDE_DIRS} @@ -9103,13 +8521,13 @@ index 8f27536b690e863fcaf086c04d1b0fb21356a622..a0207624821b4179d7adc646adf06aae WPE::libwpe ${GLIB_LIBRARIES} diff --git a/Source/WebKit/PlatformWin.cmake b/Source/WebKit/PlatformWin.cmake -index 06a86d0cfd1ca90f383af2b079f60ce220f8eb02..9e21935463bf964ecb090be48e68b50ef29c049b 100644 +index 8429fc8b2e3721830edf197b3369f4f21bb70a9a..35e99519b9a23ac19757a8b67fe477ce26c06cd0 100644 --- a/Source/WebKit/PlatformWin.cmake +++ b/Source/WebKit/PlatformWin.cmake -@@ -56,8 +56,13 @@ list(APPEND WebKit_SOURCES - UIProcess/WebsiteData/win/WebsiteDataStoreWin.cpp +@@ -54,8 +54,13 @@ list(APPEND WebKit_SOURCES UIProcess/win/AutomationClientWin.cpp + UIProcess/win/AutomationSessionClientWin.cpp + + UIProcess/win/InspectorTargetProxyWin.cpp + UIProcess/win/InspectorPlaywrightAgentClientWin.cpp @@ -9120,7 +8538,7 @@ index 06a86d0cfd1ca90f383af2b079f60ce220f8eb02..9e21935463bf964ecb090be48e68b50e UIProcess/win/WebPageProxyWin.cpp UIProcess/win/WebPopupMenuProxyWin.cpp UIProcess/win/WebProcessPoolWin.cpp -@@ -73,6 +78,7 @@ list(APPEND WebKit_SOURCES +@@ -71,6 +76,7 @@ list(APPEND WebKit_SOURCES WebProcess/MediaCache/WebMediaKeyStorageManager.cpp WebProcess/WebCoreSupport/win/WebPopupMenuWin.cpp @@ -9128,13 +8546,10 @@ index 06a86d0cfd1ca90f383af2b079f60ce220f8eb02..9e21935463bf964ecb090be48e68b50e WebProcess/WebPage/AcceleratedSurface.cpp -@@ -121,8 +127,81 @@ list(APPEND WebKit_PUBLIC_FRAMEWORK_HEADERS - - list(APPEND WebKit_PRIVATE_LIBRARIES +@@ -121,6 +127,36 @@ list(APPEND WebKit_PRIVATE_LIBRARIES comctl32 -+ ${LIBVPX_CUSTOM_LIBRARY} -+) -+ + ) + +# Playwright begin +list(APPEND WebKit_SYSTEM_INCLUDE_DIRECTORIES + "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/include" @@ -9143,99 +8558,49 @@ index 06a86d0cfd1ca90f383af2b079f60ce220f8eb02..9e21935463bf964ecb090be48e68b50e + +list(APPEND WebKit_PRIVATE_INCLUDE_DIRECTORIES + "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libwebm" - ) - -+set(vpxutils_SOURCES ++) ++ ++add_library(mkvmuxer STATIC + "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libwebm/mkvmuxer/mkvmuxer.cc" + "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libwebm/mkvmuxer/mkvmuxerutil.cc" + "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libwebm/mkvmuxer/mkvwriter.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/compare.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/compare_common.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/compare_gcc.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/compare_msa.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/compare_neon64.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/compare_neon.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/compare_win.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/convert_argb.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/convert.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/convert_from_argb.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/convert_from.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/convert_jpeg.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/convert_to_argb.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/convert_to_i420.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/cpu_id.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/mjpeg_decoder.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/mjpeg_validate.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/planar_functions.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate_any.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate_argb.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate_common.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate_gcc.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate_msa.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate_neon64.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate_neon.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/rotate_win.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/row_any.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/row_common.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/row_gcc.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/row_msa.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/row_neon64.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/row_neon.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/row_win.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale_any.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale_argb.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale_common.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale_gcc.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale_msa.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale_neon64.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale_neon.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale_rvv.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale_uv.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/scale_win.cc" -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/source/video_common.cc" +) -+ -+add_library(vpxutils STATIC ${vpxutils_SOURCES}) -+ -+target_include_directories(vpxutils PRIVATE -+ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv/include" ++target_include_directories(mkvmuxer PRIVATE + "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libwebm" +) ++target_link_libraries(WebKit PRIVATE mkvmuxer) ++ ++add_subdirectory( ++ "${THIRDPARTY_DIR}/libwebrtc/Source/third_party/libyuv" ++ "${CMAKE_BINARY_DIR}/libyuv" ++ EXCLUDE_FROM_ALL ++) ++target_link_libraries(WebKit PRIVATE yuv) ++target_link_libraries(WebKit PRIVATE ${LIBVPX_LIBRARIES}) + -+target_link_libraries(WebKit PRIVATE vpxutils) +# Playwright end + list(APPEND WebProcess_SOURCES WebProcess/EntryPoint/win/WebProcessMain.cpp - ) -diff --git a/Source/WebKit/Shared/API/c/wpe/WebKit.h b/Source/WebKit/Shared/API/c/wpe/WebKit.h -index a9aa21f5589dec453db1713c8846e0d2e687f552..9b94469d078d92e4b9e0c8149122b19a4d3b5307 100644 ---- a/Source/WebKit/Shared/API/c/wpe/WebKit.h -+++ b/Source/WebKit/Shared/API/c/wpe/WebKit.h -@@ -76,6 +76,7 @@ - // From Source/WebKit/UIProcess/API/C - #include - #include -+#include - #include - #include - #include -diff --git a/Source/WebKit/Shared/Cocoa/CompletionHandlerCallChecker.h b/Source/WebKit/Shared/Cocoa/CompletionHandlerCallChecker.h -index b09b17a5bff38e3ba8d6bb53da9ef09d229bdb61..46aa1caa93402711a08f5980387a957f783038e5 100644 ---- a/Source/WebKit/Shared/Cocoa/CompletionHandlerCallChecker.h -+++ b/Source/WebKit/Shared/Cocoa/CompletionHandlerCallChecker.h -@@ -27,6 +27,7 @@ - #import - #import -+#import - - namespace WebKit { +diff --git a/Source/WebKit/Shared/AuxiliaryProcess.h b/Source/WebKit/Shared/AuxiliaryProcess.h +index 35fd0f0397cd92c5bf025d89d7f7c8139c03c69d..b1559f1bb2d2d7a74d0b534f81352e366498bfc8 100644 +--- a/Source/WebKit/Shared/AuxiliaryProcess.h ++++ b/Source/WebKit/Shared/AuxiliaryProcess.h +@@ -216,6 +216,11 @@ struct AuxiliaryProcessInitializationParameters { + IPC::Connection::Identifier connectionIdentifier; + HashMap extraInitializationData; + WTF::AuxiliaryProcessType processType; ++// Playwright begin ++#if !PLATFORM(COCOA) ++ bool shouldEnableSharedArrayBuffer { false }; ++#endif ++// Playwright end + }; + } // namespace WebKit diff --git a/Source/WebKit/Shared/NativeWebKeyboardEvent.h b/Source/WebKit/Shared/NativeWebKeyboardEvent.h -index 17cb42104f3fe7e78388cdb1acd78efb34022f8d..c824a8c7ab5c4717773bff23c03156e744d192c0 100644 +index c72c9733800b6f836c4d3ccb0b50d40c3ee83067..e2955ddebe388d886ca43d733dce0eb58256ce8b 100644 --- a/Source/WebKit/Shared/NativeWebKeyboardEvent.h +++ b/Source/WebKit/Shared/NativeWebKeyboardEvent.h @@ -33,6 +33,7 @@ @@ -9246,7 +8611,7 @@ index 17cb42104f3fe7e78388cdb1acd78efb34022f8d..c824a8c7ab5c4717773bff23c03156e7 #endif #if PLATFORM(GTK) -@@ -70,22 +71,38 @@ public: +@@ -70,23 +71,39 @@ public: #if USE(APPKIT) // FIXME: Share iOS's HandledByInputMethod enum here instead of passing a boolean. NativeWebKeyboardEvent(NSEvent *, bool handledByInputMethod, bool replacesSoftSpace, const Vector&); @@ -9275,6 +8640,7 @@ index 17cb42104f3fe7e78388cdb1acd78efb34022f8d..c824a8c7ab5c4717773bff23c03156e7 + } #if PLATFORM(WPE) && ENABLE(WPE_PLATFORM) NativeWebKeyboardEvent(WPEEvent*, const String&, bool isAutoRepeat); + NativeWebKeyboardEvent(const String&, std::optional>&&, std::optional&&); #endif #elif PLATFORM(WIN) NativeWebKeyboardEvent(HWND, UINT message, WPARAM, LPARAM, Vector&& pendingCharEvents); @@ -9286,19 +8652,11 @@ index 17cb42104f3fe7e78388cdb1acd78efb34022f8d..c824a8c7ab5c4717773bff23c03156e7 #if USE(APPKIT) diff --git a/Source/WebKit/Shared/NativeWebMouseEvent.h b/Source/WebKit/Shared/NativeWebMouseEvent.h -index d51a12fba25ccd4b8bdd2e4a37bf9f1268034617..e36921913825f18522551c7847efae89d0679cc6 100644 +index a39b6dd673e1639f9fe64c23dd054f0ff57f7464..4026f6244889e5a0ee85edb72696d0be20ba531d 100644 --- a/Source/WebKit/Shared/NativeWebMouseEvent.h +++ b/Source/WebKit/Shared/NativeWebMouseEvent.h -@@ -31,6 +31,7 @@ - #if USE(APPKIT) - #include - OBJC_CLASS NSView; -+OBJC_CLASS NSEvent; - #endif - - #if PLATFORM(GTK) -@@ -86,6 +87,11 @@ public: - NativeWebMouseEvent(HWND, UINT message, WPARAM, LPARAM, bool); +@@ -87,6 +87,11 @@ public: + NativeWebMouseEvent(HWND, UINT message, WPARAM, LPARAM, bool, float deviceScaleFactor); #endif +#if PLATFORM(GTK) || USE(LIBWPE) || PLATFORM(WIN) @@ -9310,12 +8668,12 @@ index d51a12fba25ccd4b8bdd2e4a37bf9f1268034617..e36921913825f18522551c7847efae89 NSEvent* nativeEvent() const { return m_nativeEvent.get(); } #elif PLATFORM(GTK) diff --git a/Source/WebKit/Shared/NativeWebWheelEvent.h b/Source/WebKit/Shared/NativeWebWheelEvent.h -index bd941fd1cc5ddbae5d9fbe59976defd8fac3550b..b707e8e1739d95573270848d4e7f7719f4663c41 100644 +index f8e96218fd2671d1c0aca5e549efe0d8b94ef0f9..6cebd61bceb39c08e916fe991e4c3fc6f34b4704 100644 --- a/Source/WebKit/Shared/NativeWebWheelEvent.h +++ b/Source/WebKit/Shared/NativeWebWheelEvent.h -@@ -73,7 +73,8 @@ public: +@@ -74,7 +74,8 @@ public: #elif PLATFORM(WIN) - NativeWebWheelEvent(HWND, UINT message, WPARAM, LPARAM); + NativeWebWheelEvent(HWND, UINT message, WPARAM, LPARAM, float deviceScaleFactor); #endif - + NativeWebWheelEvent(const WebWheelEvent & webWheelEvent) @@ -9323,24 +8681,11 @@ index bd941fd1cc5ddbae5d9fbe59976defd8fac3550b..b707e8e1739d95573270848d4e7f7719 #if USE(APPKIT) NSEvent* nativeEvent() const { return m_nativeEvent.get(); } #elif PLATFORM(GTK) -diff --git a/Source/WebKit/Shared/Pasteboard.serialization.in b/Source/WebKit/Shared/Pasteboard.serialization.in -index 72ad2880160a374e8fa663e561d59becf9d2f36d..372ae6953199245fe4fc55a49813c7cae868f8b3 100644 ---- a/Source/WebKit/Shared/Pasteboard.serialization.in -+++ b/Source/WebKit/Shared/Pasteboard.serialization.in -@@ -75,7 +75,7 @@ header: - #if PLATFORM(MAC) - String userVisibleForm - #endif --#if PLATFORM(GTK) -+#if PLATFORM(GTK) || PLATFORM(WPE) - String markup - #endif - }; diff --git a/Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in b/Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in -index 2a11967151ca0bebd14b6a64482a793e2a536333..f4fc1b8eab49eba96badf4151358325a0bb7072c 100644 +index e59ca0120c0a684ea1fbdb2262a6a89ccc848828..4fcb529af731becaf446538be42075bfc19bbf90 100644 --- a/Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in +++ b/Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in -@@ -2658,6 +2658,9 @@ class WebCore::AuthenticationChallenge { +@@ -2827,6 +2827,9 @@ class WebCore::AuthenticationChallenge { class WebCore::DragData { #if PLATFORM(COCOA) String pasteboardName(); @@ -9350,7 +8695,7 @@ index 2a11967151ca0bebd14b6a64482a793e2a536333..f4fc1b8eab49eba96badf4151358325a #endif WebCore::IntPoint clientPosition(); WebCore::IntPoint globalPosition(); -@@ -3221,6 +3224,7 @@ enum class WebCore::WasPrivateRelayed : bool; +@@ -3625,6 +3628,7 @@ enum class WebCore::WasPrivateRelayed : bool; String httpStatusText; String httpVersion; WebCore::HTTPHeaderMap httpHeaderFields; @@ -9359,10 +8704,10 @@ index 2a11967151ca0bebd14b6a64482a793e2a536333..f4fc1b8eab49eba96badf4151358325a WebCore::ResourceResponseBase::Source source; WebCore::ResourceResponseBase::Type type; diff --git a/Source/WebKit/Shared/WebKeyboardEvent.cpp b/Source/WebKit/Shared/WebKeyboardEvent.cpp -index b80bcb39473ecec86be5671f38698130bd9acbf3..d886cbac5f4c073e14e12f257fa920419ea0cf39 100644 +index 8040819bba9dcde87311aaafe7d8177d0e07281d..24972c0a357324d27910ae6ff1979d1c6b8bc758 100644 --- a/Source/WebKit/Shared/WebKeyboardEvent.cpp +++ b/Source/WebKit/Shared/WebKeyboardEvent.cpp -@@ -52,6 +52,24 @@ WebKeyboardEvent::WebKeyboardEvent(WebEvent&& event, const String& text, const S +@@ -51,6 +51,24 @@ WebKeyboardEvent::WebKeyboardEvent(WebEvent&& event, const String& text, const S ASSERT(isKeyboardEventType(type())); } @@ -9387,7 +8732,7 @@ index b80bcb39473ecec86be5671f38698130bd9acbf3..d886cbac5f4c073e14e12f257fa92041 #elif PLATFORM(GTK) WebKeyboardEvent::WebKeyboardEvent(WebEvent&& event, const String& text, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, bool handledByInputMethod, std::optional>&& preeditUnderlines, std::optional&& preeditSelectionRange, Vector&& commands, bool isAutoRepeat, bool isKeypad) -@@ -75,6 +93,24 @@ WebKeyboardEvent::WebKeyboardEvent(WebEvent&& event, const String& text, const S +@@ -74,6 +92,24 @@ WebKeyboardEvent::WebKeyboardEvent(WebEvent&& event, const String& text, const S ASSERT(isKeyboardEventType(type())); } @@ -9412,7 +8757,7 @@ index b80bcb39473ecec86be5671f38698130bd9acbf3..d886cbac5f4c073e14e12f257fa92041 #elif PLATFORM(IOS_FAMILY) WebKeyboardEvent::WebKeyboardEvent(WebEvent&& event, const String& text, const String& unmodifiedText, const String& key, const String& code, const String& keyIdentifier, int windowsVirtualKeyCode, int nativeVirtualKeyCode, int macCharCode, bool handledByInputMethod, bool isAutoRepeat, bool isKeypad, bool isSystemKey) -@@ -138,6 +174,27 @@ WebKeyboardEvent::WebKeyboardEvent(WebEvent&& event, const String& text, const S +@@ -137,6 +173,27 @@ WebKeyboardEvent::WebKeyboardEvent(WebEvent&& event, const String& text, const S #endif @@ -9464,7 +8809,7 @@ index 8e4e2d6d5ebb08fba210fe0a328d45290348dd11..32a43192ec1e918c33b1b046b71d2ec5 const String& text() const { return m_text; } diff --git a/Source/WebKit/Shared/WebMouseEvent.h b/Source/WebKit/Shared/WebMouseEvent.h -index 5da1ed78e5a55bf63e9e52e33dfa9e704922589a..6630725885bbfe6123537ea799bf5b6885ea977f 100644 +index 20a6e465457151b02daa22e6bc059cf0e117ece5..ef4b1f737aaa683bc13c447aa4ca77e5cf0d64d7 100644 --- a/Source/WebKit/Shared/WebMouseEvent.h +++ b/Source/WebKit/Shared/WebMouseEvent.h @@ -70,6 +70,7 @@ public: @@ -9476,31 +8821,53 @@ index 5da1ed78e5a55bf63e9e52e33dfa9e704922589a..6630725885bbfe6123537ea799bf5b68 void setPosition(const WebCore::IntPoint& position) { m_position = position; } const WebCore::IntPoint& globalPosition() const { return m_globalPosition; } diff --git a/Source/WebKit/Shared/WebPageCreationParameters.h b/Source/WebKit/Shared/WebPageCreationParameters.h -index e0f2fcf54bf77b41619a9b76a3f42cc17303029f..4f79a4a9e081bfbb6a05c2c8afcbdaae060f2229 100644 +index 36e44162c6f211876bf86b20e186f3da7e895536..68fe668470fef43c7a3af7a5c45ca4bac1fbbb28 100644 --- a/Source/WebKit/Shared/WebPageCreationParameters.h +++ b/Source/WebKit/Shared/WebPageCreationParameters.h -@@ -300,6 +300,8 @@ struct WebPageCreationParameters { +@@ -301,6 +301,8 @@ struct WebPageCreationParameters { + WebCore::ShouldRelaxThirdPartyCookieBlocking shouldRelaxThirdPartyCookieBlocking { WebCore::ShouldRelaxThirdPartyCookieBlocking::No }; bool httpsUpgradeEnabled { true }; - -+ bool shouldPauseInInspectorWhenShown { false }; + - #if PLATFORM(IOS) || PLATFORM(VISION) - bool allowsDeprecatedSynchronousXMLHttpRequestDuringUnload { false }; - #endif ++ bool shouldPauseInInspectorWhenShown { false }; + + #if ENABLE(APP_HIGHLIGHTS) + WebCore::HighlightVisibility appHighlightsVisible { WebCore::HighlightVisibility::Hidden }; diff --git a/Source/WebKit/Shared/WebPageCreationParameters.serialization.in b/Source/WebKit/Shared/WebPageCreationParameters.serialization.in -index c7c3aac107d2b528d63a31645d84573ba4115a89..4e6932d22e24e2df15e045c0cbb177e8e0a8e880 100644 +index 6df2cea7d9ba7328456822475ed765e33966d4b8..39c08e228a2346b18915bc90e76965e0586d006b 100644 --- a/Source/WebKit/Shared/WebPageCreationParameters.serialization.in +++ b/Source/WebKit/Shared/WebPageCreationParameters.serialization.in -@@ -228,6 +228,8 @@ enum class WebCore::UserInterfaceLayoutDirection : bool; +@@ -223,6 +223,8 @@ enum class WebCore::UserInterfaceLayoutDirection : bool; bool httpsUpgradeEnabled; + bool shouldPauseInInspectorWhenShown; + - #if PLATFORM(IOS) || PLATFORM(VISION) - bool allowsDeprecatedSynchronousXMLHttpRequestDuringUnload; + #if ENABLE(APP_HIGHLIGHTS) + WebCore::HighlightVisibility appHighlightsVisible; #endif +diff --git a/Source/WebKit/Shared/glib/ProcessExecutablePathGLib.cpp b/Source/WebKit/Shared/glib/ProcessExecutablePathGLib.cpp +index 9899d60864664d1abff2b71c1c01e564e5dfb08c..391e0e42ca6a39f82b5a12c6aede069d61095ee2 100644 +--- a/Source/WebKit/Shared/glib/ProcessExecutablePathGLib.cpp ++++ b/Source/WebKit/Shared/glib/ProcessExecutablePathGLib.cpp +@@ -32,7 +32,7 @@ + + namespace WebKit { + +-#if ENABLE(DEVELOPER_MODE) ++#if TRUE + static String getExecutablePath() + { + CString executablePath = FileSystem::currentExecutablePath(); +@@ -44,7 +44,7 @@ static String getExecutablePath() + + static String findWebKitProcess(const char* processName) + { +-#if ENABLE(DEVELOPER_MODE) ++#if TRUE + static const char* execDirectory = g_getenv("WEBKIT_EXEC_PATH"); + if (execDirectory) { + String processPath = FileSystem::pathByAppendingComponent(FileSystem::stringFromFileSystemRepresentation(execDirectory), StringView::fromLatin1(processName)); diff --git a/Source/WebKit/Shared/gtk/NativeWebKeyboardEventGtk.cpp b/Source/WebKit/Shared/gtk/NativeWebKeyboardEventGtk.cpp index 8d33ceb065fb3e90372b0c696779189d07838da0..6e3194c3e96e46bfa09f8d706324e6515df1e7f4 100644 --- a/Source/WebKit/Shared/gtk/NativeWebKeyboardEventGtk.cpp @@ -9533,247 +8900,57 @@ index 9a1c3f09c756ea368ac2d68e183a13e2eb47ead7..01c738376230f83376d80d6d225543a3 , m_nativeEvent(event.nativeEvent() ? constructNativeEvent(const_cast(event.nativeEvent())) : nullptr) { } -diff --git a/Source/WebKit/Shared/libwpe/ArgumentCodersWPE.cpp b/Source/WebKit/Shared/libwpe/ArgumentCodersWPE.cpp -new file mode 100644 -index 0000000000000000000000000000000000000000..c837e53b425d8f647a96398962f23a37fb2cfde5 ---- /dev/null -+++ b/Source/WebKit/Shared/libwpe/ArgumentCodersWPE.cpp -@@ -0,0 +1,170 @@ -+/* -+ * Copyright (C) 2011 Igalia S.L. -+ * -+ * 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 APPLE INC. AND ITS 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 APPLE INC. OR ITS 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. -+ */ -+ -+#include "config.h" -+#include "ArgumentCodersWPE.h" -+ -+#include "WebCoreArgumentCoders.h" -+#include -+#include -+#include -+#include -+ -+namespace IPC { -+using namespace WebCore; -+using namespace WebKit; -+ -+static void encodeImage(Encoder& encoder, Image& image) -+{ -+ RefPtr bitmap = ShareableBitmap::create({ IntSize(image.size()) }); -+ bitmap->createGraphicsContext()->drawImage(image, IntPoint()); -+ -+ encoder << bitmap->createHandle(); -+} -+ -+static WARN_UNUSED_RETURN bool decodeImage(Decoder& decoder, RefPtr& image) -+{ -+ std::optional> handle; -+ decoder >> handle; -+ if (!handle || !*handle) -+ return false; -+ -+ RefPtr bitmap = ShareableBitmap::create(WTFMove(**handle)); -+ if (!bitmap) -+ return false; -+ image = bitmap->createImage(); -+ if (!image) -+ return false; -+ return true; -+} -+ -+void ArgumentCoder::encode(Encoder& encoder, const SelectionData& selection) -+{ -+ bool hasText = selection.hasText(); -+ encoder << hasText; -+ if (hasText) -+ encoder << selection.text(); -+ bool hasMarkup = selection.hasMarkup(); -+ encoder << hasMarkup; -+ if (hasMarkup) -+ encoder << selection.markup(); -+ -+ bool hasURL = selection.hasURL(); -+ encoder << hasURL; -+ if (hasURL) -+ encoder << selection.url().string(); -+ -+ bool hasURIList = selection.hasURIList(); -+ encoder << hasURIList; -+ if (hasURIList) -+ encoder << selection.uriList(); -+ -+ bool hasImage = selection.hasImage(); -+ encoder << hasImage; -+ if (hasImage) -+ encodeImage(encoder, *selection.image()); -+ -+ bool hasCustomData = selection.hasCustomData(); -+ encoder << hasCustomData; -+ if (hasCustomData) -+ encoder << RefPtr(selection.customData()); -+ -+ bool canSmartReplace = selection.canSmartReplace(); -+ encoder << canSmartReplace; -+} -+ -+std::optional ArgumentCoder::decode(Decoder& decoder) +diff --git a/Source/WebKit/Shared/unix/AuxiliaryProcessMain.cpp b/Source/WebKit/Shared/unix/AuxiliaryProcessMain.cpp +index 7fcd22cd2172cd7fa77aee12ad5cfcf7a435abba..bc822b40eea889fb0499dd4e78f89f04d87c64a1 100644 +--- a/Source/WebKit/Shared/unix/AuxiliaryProcessMain.cpp ++++ b/Source/WebKit/Shared/unix/AuxiliaryProcessMain.cpp +@@ -40,6 +40,15 @@ + + namespace WebKit { + ++static bool hasArgument(const char* argument, int argc, char** argv) +{ -+ SelectionData selection; -+ -+ bool hasText; -+ if (!decoder.decode(hasText)) -+ return std::nullopt; -+ if (hasText) { -+ String text; -+ if (!decoder.decode(text)) -+ return std::nullopt; -+ selection.setText(text); -+ } -+ -+ bool hasMarkup; -+ if (!decoder.decode(hasMarkup)) -+ return std::nullopt; -+ if (hasMarkup) { -+ String markup; -+ if (!decoder.decode(markup)) -+ return std::nullopt; -+ selection.setMarkup(markup); ++ for (int i = 0; i < argc; ++i) { ++ if (!strcmp(argument, argv[i])) ++ return true; + } -+ -+ bool hasURL; -+ if (!decoder.decode(hasURL)) -+ return std::nullopt; -+ if (hasURL) { -+ String url; -+ if (!decoder.decode(url)) -+ return std::nullopt; -+ selection.setURL(URL(URL(), url), String()); -+ } -+ -+ bool hasURIList; -+ if (!decoder.decode(hasURIList)) -+ return std::nullopt; -+ if (hasURIList) { -+ String uriList; -+ if (!decoder.decode(uriList)) -+ return std::nullopt; -+ selection.setURIList(uriList); -+ } -+ -+ bool hasImage; -+ if (!decoder.decode(hasImage)) -+ return std::nullopt; -+ if (hasImage) { -+ RefPtr image; -+ if (!decodeImage(decoder, image)) -+ return std::nullopt; -+ selection.setImage(image.get()); -+ } -+ -+ bool hasCustomData; -+ if (!decoder.decode(hasCustomData)) -+ return std::nullopt; -+ if (hasCustomData) { -+ RefPtr buffer; -+ if (!decoder.decode(buffer)) -+ return std::nullopt; -+ selection.setCustomData(Ref(*buffer)); -+ } -+ -+ bool canSmartReplace; -+ if (!decoder.decode(canSmartReplace)) -+ return std::nullopt; -+ selection.setCanSmartReplace(canSmartReplace); -+ -+ return selection; -+} -+ -+} -diff --git a/Source/WebKit/Shared/libwpe/ArgumentCodersWPE.h b/Source/WebKit/Shared/libwpe/ArgumentCodersWPE.h -new file mode 100644 -index 0000000000000000000000000000000000000000..789a0d7cf69704c8f665a9ed79348fbcbc1301c4 ---- /dev/null -+++ b/Source/WebKit/Shared/libwpe/ArgumentCodersWPE.h -@@ -0,0 +1,41 @@ -+/* -+ * Copyright (C) 2011 Igalia S.L. -+ * -+ * 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 APPLE INC. AND ITS 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 APPLE INC. OR ITS 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. -+ */ -+ -+#pragma once -+ -+#include "ArgumentCoders.h" -+ -+namespace WebCore { -+class SelectionData; ++ return false; +} + -+namespace IPC { -+ -+template<> struct ArgumentCoder { -+ static void encode(Encoder&, const WebCore::SelectionData&); -+ static std::optional decode(Decoder&); -+}; -+ -+} // namespace IPC -diff --git a/Source/WebKit/Shared/win/WebEventFactory.cpp b/Source/WebKit/Shared/win/WebEventFactory.cpp -index eae9e21a437c04cec91d1a4848038e11f4ee3e07..4fe63a9042d875555d9d1b934a9f53ea352e47aa 100644 ---- a/Source/WebKit/Shared/win/WebEventFactory.cpp -+++ b/Source/WebKit/Shared/win/WebEventFactory.cpp -@@ -476,7 +476,7 @@ WebKeyboardEvent WebEventFactory::createWebKeyboardEvent(HWND hwnd, UINT message - #if ENABLE(TOUCH_EVENTS) - WebTouchEvent WebEventFactory::createWebTouchEvent() + AuxiliaryProcessMainCommon::AuxiliaryProcessMainCommon() { -- return WebTouchEvent(); -+ return WebTouchEvent({ WebEventType::TouchMove, OptionSet { }, WallTime::now()}, { }); + #if ENABLE(BREAKPAD) +@@ -94,6 +103,10 @@ WTF_ALLOW_UNSAFE_BUFFER_USAGE_END + } + #endif + ++// Playwright begin ++ if (hasArgument("--enable-shared-array-buffer", argc, argv)) ++ m_parameters.shouldEnableSharedArrayBuffer = true; ++// Playwright end + return true; } - #endif // ENABLE(TOUCH_EVENTS) +diff --git a/Source/WebKit/Shared/win/AuxiliaryProcessMainWin.cpp b/Source/WebKit/Shared/win/AuxiliaryProcessMainWin.cpp +index 053e9336017d8818b3cbea79ce7c145fd5c46274..5632498d6ef875df80fc68ec206a9d08e5d05a6f 100644 +--- a/Source/WebKit/Shared/win/AuxiliaryProcessMainWin.cpp ++++ b/Source/WebKit/Shared/win/AuxiliaryProcessMainWin.cpp +@@ -47,6 +47,10 @@ bool AuxiliaryProcessMainCommon::parseCommandLine(int argc, char** argv) + m_parameters.connectionIdentifier = IPC::Connection::Identifier { reinterpret_cast(parseIntegerAllowingTrailingJunk(StringView::fromLatin1(argv[++i])).value_or(0)) }; + else if (!strcmp(argv[i], "-processIdentifier") && i + 1 < argc) + m_parameters.processIdentifier = ObjectIdentifier(parseIntegerAllowingTrailingJunk(StringView::fromLatin1(argv[++i])).value_or(0)); ++// Playwright begin ++ else if (!strcmp(argv[i], "-enable-shared-array-buffer")) ++ m_parameters.shouldEnableSharedArrayBuffer = true; ++// Playwright end + else if (!strcmp(argv[i], "-configure-jsc-for-testing")) + JSC::Config::configureForTesting(); + else if (!strcmp(argv[i], "-disable-jit")) diff --git a/Source/WebKit/Sources.txt b/Source/WebKit/Sources.txt -index d3b9afee939c3ec362f48851865da60251a5700f..fe0c3cc89c0823ed145eb1c374edd13239f48ee7 100644 +index bd7ec1f455c83cb4d24185099b6c7f569e612a33..cf4183ca9b2bb85b00bb58a4bc0c4d6b6f44af76 100644 --- a/Source/WebKit/Sources.txt +++ b/Source/WebKit/Sources.txt -@@ -379,6 +379,7 @@ Shared/XR/XRDeviceProxy.cpp +@@ -392,6 +392,7 @@ UIProcess/AboutSchemeHandler.cpp UIProcess/AuxiliaryProcessProxy.cpp UIProcess/BackgroundProcessResponsivenessTimer.cpp UIProcess/BrowsingContextGroup.cpp @@ -9781,7 +8958,7 @@ index d3b9afee939c3ec362f48851865da60251a5700f..fe0c3cc89c0823ed145eb1c374edd132 UIProcess/DeviceIdHashSaltStorage.cpp UIProcess/DisplayLink.cpp UIProcess/DisplayLinkProcessProxyClient.cpp -@@ -388,16 +389,20 @@ UIProcess/FrameLoadState.cpp +@@ -401,16 +402,20 @@ UIProcess/FrameLoadState.cpp UIProcess/FrameProcess.cpp UIProcess/GeolocationPermissionRequestManagerProxy.cpp UIProcess/GeolocationPermissionRequestProxy.cpp @@ -9800,9 +8977,9 @@ index d3b9afee939c3ec362f48851865da60251a5700f..fe0c3cc89c0823ed145eb1c374edd132 UIProcess/ProvisionalPageProxy.cpp +UIProcess/RemoteInspectorPipe.cpp UIProcess/RemotePageDrawingAreaProxy.cpp + UIProcess/RemotePageFullscreenManagerProxy.cpp UIProcess/RemotePageProxy.cpp - UIProcess/ResponsivenessTimer.cpp -@@ -441,6 +446,8 @@ UIProcess/WebOpenPanelResultListenerProxy.cpp +@@ -453,6 +458,8 @@ UIProcess/WebOpenPanelResultListenerProxy.cpp UIProcess/WebPageDiagnosticLoggingClient.cpp UIProcess/WebPageGroup.cpp UIProcess/WebPageInjectedBundleClient.cpp @@ -9810,12 +8987,10 @@ index d3b9afee939c3ec362f48851865da60251a5700f..fe0c3cc89c0823ed145eb1c374edd132 +UIProcess/WebPageInspectorInputAgent.cpp UIProcess/WebPageProxy.cpp UIProcess/WebPageProxyMessageReceiverRegistration.cpp - UIProcess/WebPasteboardProxy.cpp -@@ -576,7 +583,11 @@ UIProcess/Inspector/WebInspectorUtilities.cpp - UIProcess/Inspector/WebPageDebuggable.cpp + UIProcess/WebPageProxyTesting.cpp +@@ -604,6 +611,9 @@ UIProcess/Inspector/WebPageDebuggable.cpp UIProcess/Inspector/WebPageInspectorController.cpp -+UIProcess/Inspector/Agents/CairoJpegEncoder.cpp UIProcess/Inspector/Agents/InspectorBrowserAgent.cpp +UIProcess/Inspector/Agents/InspectorScreencastAgent.cpp +UIProcess/Inspector/Agents/ScreencastEncoder.cpp @@ -9824,10 +8999,10 @@ index d3b9afee939c3ec362f48851865da60251a5700f..fe0c3cc89c0823ed145eb1c374edd132 UIProcess/Media/AudioSessionRoutingArbitratorProxy.cpp UIProcess/Media/MediaUsageManager.cpp diff --git a/Source/WebKit/SourcesCocoa.txt b/Source/WebKit/SourcesCocoa.txt -index 8dc390feda97fbe8e80e0bdfd62b682be36c81e5..9dee9867202c5e63e81dec992fa348fd16a557d8 100644 +index c146d8baabb0bc80396dc07d7cde88207ef02efa..b13cb0a6e8e10dcf3a068a4bde97536d490f3b52 100644 --- a/Source/WebKit/SourcesCocoa.txt +++ b/Source/WebKit/SourcesCocoa.txt -@@ -271,6 +271,7 @@ UIProcess/API/Cocoa/_WKArchiveExclusionRule.mm +@@ -272,6 +272,7 @@ UIProcess/API/Cocoa/_WKArchiveExclusionRule.mm UIProcess/API/Cocoa/_WKAttachment.mm UIProcess/API/Cocoa/_WKAutomationSession.mm UIProcess/API/Cocoa/_WKAutomationSessionConfiguration.mm @@ -9835,7 +9010,7 @@ index 8dc390feda97fbe8e80e0bdfd62b682be36c81e5..9dee9867202c5e63e81dec992fa348fd UIProcess/API/Cocoa/_WKContentRuleListAction.mm UIProcess/API/Cocoa/_WKContextMenuElementInfo.mm UIProcess/API/Cocoa/_WKCustomHeaderFields.mm @no-unify -@@ -455,6 +456,7 @@ UIProcess/Inspector/ios/WKInspectorHighlightView.mm +@@ -469,6 +470,7 @@ UIProcess/Inspector/ios/WKInspectorHighlightView.mm UIProcess/Inspector/ios/WKInspectorNodeSearchGestureRecognizer.mm UIProcess/Inspector/mac/RemoteWebInspectorUIProxyMac.mm @@ -9844,10 +9019,10 @@ index 8dc390feda97fbe8e80e0bdfd62b682be36c81e5..9dee9867202c5e63e81dec992fa348fd UIProcess/Inspector/mac/WKInspectorResourceURLSchemeHandler.mm UIProcess/Inspector/mac/WKInspectorViewController.mm diff --git a/Source/WebKit/SourcesGTK.txt b/Source/WebKit/SourcesGTK.txt -index bec1e568f9ad00bfff883318692d9c404e012e2c..de45461d0851248f44973780b07d0ba7692fd578 100644 +index 5bf7f2a0c8d6e6d32a2845885b943064618fe951..9d8bfa3d2cf0920dcfdae5b95563c5cab5e755f4 100644 --- a/Source/WebKit/SourcesGTK.txt +++ b/Source/WebKit/SourcesGTK.txt -@@ -134,6 +134,7 @@ UIProcess/API/glib/WebKitAutomationSession.cpp @no-unify +@@ -122,6 +122,7 @@ UIProcess/API/glib/WebKitAutomationSession.cpp @no-unify UIProcess/API/glib/WebKitBackForwardList.cpp @no-unify UIProcess/API/glib/WebKitBackForwardListItem.cpp @no-unify UIProcess/API/glib/WebKitClipboardPermissionRequest.cpp @no-unify @@ -9855,23 +9030,23 @@ index bec1e568f9ad00bfff883318692d9c404e012e2c..de45461d0851248f44973780b07d0ba7 UIProcess/API/glib/WebKitContextMenuClient.cpp @no-unify UIProcess/API/glib/WebKitCookieManager.cpp @no-unify UIProcess/API/glib/WebKitCredential.cpp @no-unify -@@ -262,6 +263,7 @@ UIProcess/glib/DisplayLinkGLib.cpp - UIProcess/glib/DisplayVBlankMonitor.cpp +@@ -253,6 +254,7 @@ UIProcess/glib/DisplayVBlankMonitor.cpp UIProcess/glib/DisplayVBlankMonitorDRM.cpp UIProcess/glib/DisplayVBlankMonitorTimer.cpp + UIProcess/glib/FenceMonitor.cpp +UIProcess/glib/InspectorPlaywrightAgentClientGLib.cpp UIProcess/glib/ScreenManager.cpp + UIProcess/glib/SystemSettingsManagerProxy.cpp UIProcess/glib/WebPageProxyGLib.cpp - UIProcess/glib/WebProcessPoolGLib.cpp -@@ -277,6 +279,7 @@ UIProcess/gtk/ClipboardGtk4.cpp @no-unify +@@ -271,6 +273,7 @@ UIProcess/gtk/DisplayX11.cpp @no-unify + UIProcess/gtk/DisplayWayland.cpp @no-unify UIProcess/gtk/WebDateTimePickerGtk.cpp - UIProcess/gtk/GtkSettingsManager.cpp UIProcess/gtk/HardwareAccelerationManager.cpp +UIProcess/gtk/InspectorTargetProxyGtk.cpp UIProcess/gtk/KeyBindingTranslator.cpp UIProcess/gtk/PointerLockManager.cpp @no-unify UIProcess/gtk/PointerLockManagerWayland.cpp @no-unify -@@ -289,6 +292,8 @@ UIProcess/gtk/ViewGestureControllerGtk.cpp +@@ -284,6 +287,8 @@ UIProcess/gtk/ViewGestureControllerGtk.cpp UIProcess/gtk/WebColorPickerGtk.cpp UIProcess/gtk/WebContextMenuProxyGtk.cpp UIProcess/gtk/WebDataListSuggestionsDropdownGtk.cpp @@ -9881,18 +9056,10 @@ index bec1e568f9ad00bfff883318692d9c404e012e2c..de45461d0851248f44973780b07d0ba7 UIProcess/gtk/WebPasteboardProxyGtk.cpp UIProcess/gtk/WebPopupMenuProxyGtk.cpp diff --git a/Source/WebKit/SourcesWPE.txt b/Source/WebKit/SourcesWPE.txt -index 3eefd6cc3eb22329583901518442756d728378a1..45f2092be52d2d347660972a6723741176ff4b42 100644 +index 8569ab98ebf37a8e25c9e79f99a26c76b175d2c8..48c634968f8dcf42ca2690c07aa1b2c4c83d5884 100644 --- a/Source/WebKit/SourcesWPE.txt +++ b/Source/WebKit/SourcesWPE.txt -@@ -86,6 +86,7 @@ Shared/glib/ProcessExecutablePathGLib.cpp - Shared/glib/UserMessage.cpp - Shared/glib/WebContextMenuItemGlib.cpp - -+Shared/libwpe/ArgumentCodersWPE.cpp - Shared/libwpe/NativeWebKeyboardEventLibWPE.cpp - Shared/libwpe/NativeWebMouseEventLibWPE.cpp - Shared/libwpe/NativeWebTouchEventLibWPE.cpp -@@ -136,6 +137,7 @@ UIProcess/API/glib/WebKitAuthenticationRequest.cpp @no-unify +@@ -124,6 +124,7 @@ UIProcess/API/glib/WebKitAuthenticationRequest.cpp @no-unify UIProcess/API/glib/WebKitAutomationSession.cpp @no-unify UIProcess/API/glib/WebKitBackForwardList.cpp @no-unify UIProcess/API/glib/WebKitBackForwardListItem.cpp @no-unify @@ -9900,7 +9067,7 @@ index 3eefd6cc3eb22329583901518442756d728378a1..45f2092be52d2d347660972a67237411 UIProcess/API/glib/WebKitContextMenuClient.cpp @no-unify UIProcess/API/glib/WebKitCookieManager.cpp @no-unify UIProcess/API/glib/WebKitCredential.cpp @no-unify -@@ -169,6 +171,7 @@ UIProcess/API/glib/WebKitOptionMenu.cpp @no-unify +@@ -157,6 +158,7 @@ UIProcess/API/glib/WebKitOptionMenu.cpp @no-unify UIProcess/API/glib/WebKitOptionMenuItem.cpp @no-unify UIProcess/API/glib/WebKitPermissionRequest.cpp @no-unify UIProcess/API/glib/WebKitPermissionStateQuery.cpp @no-unify @@ -9908,36 +9075,30 @@ index 3eefd6cc3eb22329583901518442756d728378a1..45f2092be52d2d347660972a67237411 UIProcess/API/glib/WebKitPolicyDecision.cpp @no-unify UIProcess/API/glib/WebKitPrivate.cpp @no-unify UIProcess/API/glib/WebKitProtocolHandler.cpp @no-unify -@@ -205,6 +208,7 @@ UIProcess/API/soup/HTTPCookieStoreSoup.cpp - UIProcess/API/wpe/InputMethodFilterWPE.cpp @no-unify - UIProcess/API/wpe/PageClientImpl.cpp @no-unify - UIProcess/API/wpe/WebKitColor.cpp @no-unify -+UIProcess/API/wpe/WebKitDataListSuggestionsDropdown.cpp @no-unify - UIProcess/API/wpe/WebKitInputMethodContextWPE.cpp @no-unify - UIProcess/API/wpe/WebKitPopupMenu.cpp @no-unify - UIProcess/API/wpe/WebKitRectangle.cpp @no-unify -@@ -228,6 +232,7 @@ UIProcess/glib/DisplayLinkGLib.cpp - UIProcess/glib/DisplayVBlankMonitor.cpp +@@ -225,6 +227,7 @@ UIProcess/glib/DisplayVBlankMonitor.cpp UIProcess/glib/DisplayVBlankMonitorDRM.cpp UIProcess/glib/DisplayVBlankMonitorTimer.cpp + UIProcess/glib/FenceMonitor.cpp +UIProcess/glib/InspectorPlaywrightAgentClientGLib.cpp UIProcess/glib/ScreenManager.cpp + UIProcess/glib/SystemSettingsManagerProxy.cpp UIProcess/glib/WebPageProxyGLib.cpp - UIProcess/glib/WebProcessPoolGLib.cpp -@@ -258,7 +263,12 @@ UIProcess/linux/MemoryPressureMonitor.cpp +@@ -256,8 +259,14 @@ UIProcess/linux/MemoryPressureMonitor.cpp UIProcess/soup/WebProcessPoolSoup.cpp UIProcess/wpe/AcceleratedBackingStoreDMABuf.cpp +UIProcess/wpe/InspectorTargetProxyWPE.cpp UIProcess/wpe/ScreenManagerWPE.cpp + UIProcess/wpe/SystemSettingsManagerProxyWPE.cpp +UIProcess/wpe/WebColorPickerWPE.cpp ++UIProcess/wpe/WebDataListSuggestionsDropdownWPE.cpp +UIProcess/wpe/WebDateTimePickerWPE.cpp +UIProcess/wpe/WebPageInspectorEmulationAgentWPE.cpp +UIProcess/wpe/WebPageInspectorInputAgentWPE.cpp UIProcess/wpe/WebPageProxyWPE.cpp + UIProcess/wpe/WebPasteboardProxyWPE.cpp UIProcess/wpe/WebPreferencesWPE.cpp - -@@ -282,6 +292,8 @@ WebProcess/WebCoreSupport/glib/WebEditorClientGLib.cpp +@@ -285,6 +294,8 @@ WebProcess/WebCoreSupport/glib/WebEditorClientGLib.cpp WebProcess/WebCoreSupport/soup/WebFrameNetworkingContext.cpp @@ -9946,8 +9107,47 @@ index 3eefd6cc3eb22329583901518442756d728378a1..45f2092be52d2d347660972a67237411 WebProcess/WebCoreSupport/wpe/WebEditorClientWPE.cpp WebProcess/WebPage/AcceleratedSurface.cpp +diff --git a/Source/WebKit/UIProcess/API/APIPageConfiguration.cpp b/Source/WebKit/UIProcess/API/APIPageConfiguration.cpp +index 64952ccd02d9db28c2e1388ce7713703430c8212..c616408e2d09f6d5d98dfd609a51ad080ebb990c 100644 +--- a/Source/WebKit/UIProcess/API/APIPageConfiguration.cpp ++++ b/Source/WebKit/UIProcess/API/APIPageConfiguration.cpp +@@ -268,6 +268,11 @@ WebPageProxy* PageConfiguration::relatedPage() const + return m_data.relatedPage.get(); + } + ++WebKit::WebPageProxy* PageConfiguration::openerPageForInspector() const ++{ ++ return m_data.openerPageForInspector.get(); ++} ++ + WebPageProxy* PageConfiguration::pageToCloneSessionStorageFrom() const + { + return m_data.pageToCloneSessionStorageFrom.get(); +diff --git a/Source/WebKit/UIProcess/API/APIPageConfiguration.h b/Source/WebKit/UIProcess/API/APIPageConfiguration.h +index ade928c03e6e504dc485e75427c56edfb0b1a4a4..1eef15db8aaecea65be8ec3be5d9be903055e840 100644 +--- a/Source/WebKit/UIProcess/API/APIPageConfiguration.h ++++ b/Source/WebKit/UIProcess/API/APIPageConfiguration.h +@@ -159,6 +159,10 @@ public: + WebKit::WebPageProxy* relatedPage() const; + void setRelatedPage(WeakPtr&& relatedPage) { m_data.relatedPage = WTFMove(relatedPage); } + ++ // This is similar to relatedPage(), but it is also set for noopener links. ++ WebKit::WebPageProxy* openerPageForInspector() const; ++ void setOpenerPageForInspector(WeakPtr&& openerPageForInspector) { m_data.openerPageForInspector = WTFMove(openerPageForInspector); } ++ + WebKit::WebPageProxy* pageToCloneSessionStorageFrom() const; + void setPageToCloneSessionStorageFrom(WeakPtr&&); + +@@ -515,6 +519,7 @@ private: + #endif + RefPtr pageGroup; + WeakPtr relatedPage; ++ WeakPtr openerPageForInspector; + Box> openerInfo; + WebCore::Site openedSite; + WTF::String openedMainFrameName; diff --git a/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.cpp b/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.cpp -index d561c07ae53a60c6503a355ed620bc289a2220ae..b950ac5190d8d05c66718c545c76d53d45cfff9d 100644 +index e256b905bf9727aa7c8a48012237a6a6bc9acdbc..4e855c441af6f235f0fd8dfdd57b9bd6e4646492 100644 --- a/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.cpp +++ b/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.cpp @@ -52,6 +52,10 @@ Ref ProcessPoolConfiguration::copy() @@ -9962,7 +9162,7 @@ index d561c07ae53a60c6503a355ed620bc289a2220ae..b950ac5190d8d05c66718c545c76d53d copy->m_shouldTakeUIBackgroundAssertion = this->m_shouldTakeUIBackgroundAssertion; copy->m_shouldCaptureDisplayInUIProcess = this->m_shouldCaptureDisplayInUIProcess; diff --git a/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.h b/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.h -index 32ef9bd308e520f5ac7173639c8b23ea91cde037..7a80553c2d91b9236f563fa1b76aa8a50b8545ba 100644 +index af4944e5a5d373bc51995b50d1ea7c70f64ef1b3..403cfdeda26db2b648e32aa0e5f3ef6e076634f6 100644 --- a/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.h +++ b/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.h @@ -96,6 +96,16 @@ public: @@ -9982,7 +9182,7 @@ index 32ef9bd308e520f5ac7173639c8b23ea91cde037..7a80553c2d91b9236f563fa1b76aa8a5 bool alwaysRunsAtBackgroundPriority() const { return m_alwaysRunsAtBackgroundPriority; } void setAlwaysRunsAtBackgroundPriority(bool alwaysRunsAtBackgroundPriority) { m_alwaysRunsAtBackgroundPriority = alwaysRunsAtBackgroundPriority; } -@@ -173,6 +183,10 @@ private: +@@ -178,6 +188,10 @@ private: bool m_ignoreSynchronousMessagingTimeoutsForTesting { false }; bool m_attrStyleEnabled { false }; bool m_shouldThrowExceptionForGlobalConstantRedeclaration { true }; @@ -9994,7 +9194,7 @@ index 32ef9bd308e520f5ac7173639c8b23ea91cde037..7a80553c2d91b9236f563fa1b76aa8a5 bool m_shouldTakeUIBackgroundAssertion { true }; bool m_shouldCaptureDisplayInUIProcess { DEFAULT_CAPTURE_DISPLAY_IN_UI_PROCESS }; diff --git a/Source/WebKit/UIProcess/API/APIUIClient.h b/Source/WebKit/UIProcess/API/APIUIClient.h -index f8baf3b5cbd1613da54c001cbff573125742358d..be628650e5562978187f8cc1d0afed8849a083b2 100644 +index b0450278b8949985df9f39c7d7a5adbaecb55afe..ac80a31058249d467d21e64f5a053cf0f0012fe1 100644 --- a/Source/WebKit/UIProcess/API/APIUIClient.h +++ b/Source/WebKit/UIProcess/API/APIUIClient.h @@ -114,6 +114,7 @@ public: @@ -10006,7 +9206,7 @@ index f8baf3b5cbd1613da54c001cbff573125742358d..be628650e5562978187f8cc1d0afed88 virtual void setStatusText(WebKit::WebPageProxy*, const WTF::String&) { } virtual void mouseDidMoveOverElement(WebKit::WebPageProxy&, const WebKit::WebHitTestResultData&, OptionSet, Object*) { } diff --git a/Source/WebKit/UIProcess/API/C/WKInspector.cpp b/Source/WebKit/UIProcess/API/C/WKInspector.cpp -index 990b0e5ebad19fdaf1b0036585be2ed88bc125d2..9f1931dbdd8c70d3637a2d71406b5968896037f2 100644 +index bba39f6228ae9cc67c68526c75676648cf3917ef..f1c6f6f14ef0d599bd05410edbe9360e75d6d77a 100644 --- a/Source/WebKit/UIProcess/API/C/WKInspector.cpp +++ b/Source/WebKit/UIProcess/API/C/WKInspector.cpp @@ -28,6 +28,11 @@ @@ -10049,11 +9249,11 @@ index 026121d114c5fcad84c1396be8d692625beaa3bd..edd6e5cae033124c589959a42522fde0 } #endif diff --git a/Source/WebKit/UIProcess/API/C/WKPage.cpp b/Source/WebKit/UIProcess/API/C/WKPage.cpp -index 81d4f44bd1f4201cb0ddd9d4b8ef210862551cdb..6e750c6e1f4624b5cf54a642b831ab10d4448649 100644 +index 908163888f737cb72569f6ff36dae276a51118eb..636ccf3834aaa47328388a008dbc2bf755ecdf70 100644 --- a/Source/WebKit/UIProcess/API/C/WKPage.cpp +++ b/Source/WebKit/UIProcess/API/C/WKPage.cpp -@@ -1780,6 +1780,13 @@ void WKPageSetPageUIClient(WKPageRef pageRef, const WKPageUIClientBase* wkClient - completionHandler(String()); +@@ -1935,6 +1935,13 @@ void WKPageSetPageUIClient(WKPageRef pageRef, const WKPageUIClientBase* wkClient + m_client.addMessageToConsole(toAPI(&page), toAPI(message.impl()), m_client.base.clientInfo); } + void handleJavaScriptDialog(WebPageProxy& page, bool accept, const String& value) final { @@ -10066,7 +9266,7 @@ index 81d4f44bd1f4201cb0ddd9d4b8ef210862551cdb..6e750c6e1f4624b5cf54a642b831ab10 void setStatusText(WebPageProxy* page, const String& text) final { if (!m_client.setStatusText) -@@ -1809,6 +1816,8 @@ void WKPageSetPageUIClient(WKPageRef pageRef, const WKPageUIClientBase* wkClient +@@ -1964,6 +1971,8 @@ void WKPageSetPageUIClient(WKPageRef pageRef, const WKPageUIClientBase* wkClient { if (!m_client.didNotHandleKeyEvent) return; @@ -10076,7 +9276,7 @@ index 81d4f44bd1f4201cb0ddd9d4b8ef210862551cdb..6e750c6e1f4624b5cf54a642b831ab10 } diff --git a/Source/WebKit/UIProcess/API/C/WKPageUIClient.h b/Source/WebKit/UIProcess/API/C/WKPageUIClient.h -index 1484f064ec89ee8c25c35df9f0a4462896699415..0622f4d5fc9144b9059395d9d0730a4ae00b7497 100644 +index fc43c44a85a0fc6bf5f8c643bd120a16ce762914..ee86fd213d25682f9b6553ec7da99bc8a812212b 100644 --- a/Source/WebKit/UIProcess/API/C/WKPageUIClient.h +++ b/Source/WebKit/UIProcess/API/C/WKPageUIClient.h @@ -98,6 +98,7 @@ typedef void (*WKPageRunBeforeUnloadConfirmPanelCallback)(WKPageRef page, WKStri @@ -10087,7 +9287,7 @@ index 1484f064ec89ee8c25c35df9f0a4462896699415..0622f4d5fc9144b9059395d9d0730a4a typedef void (*WKPageRequestStorageAccessConfirmCallback)(WKPageRef page, WKFrameRef frame, WKStringRef requestingDomain, WKStringRef currentDomain, WKPageRequestStorageAccessConfirmResultListenerRef listener, const void *clientInfo); typedef void (*WKPageTakeFocusCallback)(WKPageRef page, WKFocusDirection direction, const void *clientInfo); typedef void (*WKPageFocusCallback)(WKPageRef page, const void *clientInfo); -@@ -1364,6 +1365,7 @@ typedef struct WKPageUIClientV14 { +@@ -1365,6 +1366,7 @@ typedef struct WKPageUIClientV14 { // Version 14. WKPageRunWebAuthenticationPanelCallback runWebAuthenticationPanel; @@ -10095,7 +9295,7 @@ index 1484f064ec89ee8c25c35df9f0a4462896699415..0622f4d5fc9144b9059395d9d0730a4a } WKPageUIClientV14; typedef struct WKPageUIClientV15 { -@@ -1471,6 +1473,7 @@ typedef struct WKPageUIClientV15 { +@@ -1472,6 +1474,7 @@ typedef struct WKPageUIClientV15 { // Version 14. WKPageRunWebAuthenticationPanelCallback runWebAuthenticationPanel; @@ -10103,7 +9303,7 @@ index 1484f064ec89ee8c25c35df9f0a4462896699415..0622f4d5fc9144b9059395d9d0730a4a // Version 15. WKPageDecidePolicyForSpeechRecognitionPermissionRequestCallback decidePolicyForSpeechRecognitionPermissionRequest; -@@ -1582,6 +1585,7 @@ typedef struct WKPageUIClientV16 { +@@ -1583,6 +1586,7 @@ typedef struct WKPageUIClientV16 { // Version 14. WKPageRunWebAuthenticationPanelCallback runWebAuthenticationPanel; @@ -10111,7 +9311,7 @@ index 1484f064ec89ee8c25c35df9f0a4462896699415..0622f4d5fc9144b9059395d9d0730a4a // Version 15. WKPageDecidePolicyForSpeechRecognitionPermissionRequestCallback decidePolicyForSpeechRecognitionPermissionRequest; -@@ -1696,6 +1700,7 @@ typedef struct WKPageUIClientV17 { +@@ -1697,6 +1701,7 @@ typedef struct WKPageUIClientV17 { // Version 14. WKPageRunWebAuthenticationPanelCallback runWebAuthenticationPanel; @@ -10119,7 +9319,7 @@ index 1484f064ec89ee8c25c35df9f0a4462896699415..0622f4d5fc9144b9059395d9d0730a4a // Version 15. WKPageDecidePolicyForSpeechRecognitionPermissionRequestCallback decidePolicyForSpeechRecognitionPermissionRequest; -@@ -1810,6 +1815,7 @@ typedef struct WKPageUIClientV18 { +@@ -1811,6 +1816,7 @@ typedef struct WKPageUIClientV18 { // Version 14. WKPageRunWebAuthenticationPanelCallback runWebAuthenticationPanel; @@ -10127,7 +9327,7 @@ index 1484f064ec89ee8c25c35df9f0a4462896699415..0622f4d5fc9144b9059395d9d0730a4a // Version 15. WKPageDecidePolicyForSpeechRecognitionPermissionRequestCallback decidePolicyForSpeechRecognitionPermissionRequest; -@@ -1926,6 +1932,7 @@ typedef struct WKPageUIClientV19 { +@@ -1927,6 +1933,7 @@ typedef struct WKPageUIClientV19 { // Version 14. WKPageRunWebAuthenticationPanelCallback runWebAuthenticationPanel; @@ -10136,10 +9336,10 @@ index 1484f064ec89ee8c25c35df9f0a4462896699415..0622f4d5fc9144b9059395d9d0730a4a // Version 15. WKPageDecidePolicyForSpeechRecognitionPermissionRequestCallback decidePolicyForSpeechRecognitionPermissionRequest; diff --git a/Source/WebKit/UIProcess/API/Cocoa/WKPreferences.mm b/Source/WebKit/UIProcess/API/Cocoa/WKPreferences.mm -index 857afb1b892c2ee7327808f3dab0cff441c92c52..332bb2e687d6b97fd11f1366ade5b17841bcae58 100644 +index f2ee51f3f5dc9c55bcfe96d5bd52268957cc5e1a..472eb2530e812d50ecc38d9bfaa5bbe9948bad68 100644 --- a/Source/WebKit/UIProcess/API/Cocoa/WKPreferences.mm +++ b/Source/WebKit/UIProcess/API/Cocoa/WKPreferences.mm -@@ -702,6 +702,16 @@ - (void)_setMediaCaptureRequiresSecureConnection:(BOOL)requiresSecureConnection +@@ -712,6 +712,16 @@ - (void)_setMediaCaptureRequiresSecureConnection:(BOOL)requiresSecureConnection _preferences->setMediaCaptureRequiresSecureConnection(requiresSecureConnection); } @@ -10153,11 +9353,11 @@ index 857afb1b892c2ee7327808f3dab0cff441c92c52..332bb2e687d6b97fd11f1366ade5b178 + _preferences->setAlternateWebMPlayerEnabled(enabled); +} + - - (double)_inactiveMediaCaptureSteamRepromptIntervalInMinutes + - (double)_inactiveMediaCaptureStreamRepromptIntervalInMinutes { - return _preferences->inactiveMediaCaptureSteamRepromptIntervalInMinutes(); + return _preferences->inactiveMediaCaptureStreamRepromptIntervalInMinutes(); diff --git a/Source/WebKit/UIProcess/API/Cocoa/WKPreferencesPrivate.h b/Source/WebKit/UIProcess/API/Cocoa/WKPreferencesPrivate.h -index 48e4b28374b93173df1be63444aa5ca3abd626d6..194b2099be032c800a463891976364ab7cd74890 100644 +index 41525c8980f698aa4326e7d4d232311cee2c43d5..1f1745431c6cc7af66b47dd5d015c52389626e6f 100644 --- a/Source/WebKit/UIProcess/API/Cocoa/WKPreferencesPrivate.h +++ b/Source/WebKit/UIProcess/API/Cocoa/WKPreferencesPrivate.h @@ -119,6 +119,7 @@ typedef NS_ENUM(NSInteger, _WKPitchCorrectionAlgorithm) { @@ -10167,14 +9367,14 @@ index 48e4b28374b93173df1be63444aa5ca3abd626d6..194b2099be032c800a463891976364ab +@property (nonatomic, setter=_setAlternateWebMPlayerEnabled:) BOOL _alternateWebMPlayerEnabled WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA)); @property (nonatomic, setter=_setEnumeratingAllNetworkInterfacesEnabled:) BOOL _enumeratingAllNetworkInterfacesEnabled WK_API_AVAILABLE(macos(10.13), ios(11.0)); @property (nonatomic, setter=_setICECandidateFilteringEnabled:) BOOL _iceCandidateFilteringEnabled WK_API_AVAILABLE(macos(10.13.4), ios(11.3)); - @property (nonatomic, setter=_setInactiveMediaCaptureSteamRepromptIntervalInMinutes:) double _inactiveMediaCaptureSteamRepromptIntervalInMinutes WK_API_AVAILABLE(macos(10.13.4), ios(11.3)); + @property (nonatomic, setter=_setInactiveMediaCaptureStreamRepromptIntervalInMinutes:) double _inactiveMediaCaptureStreamRepromptIntervalInMinutes WK_API_AVAILABLE(macos(10.13.4), ios(11.3)); diff --git a/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegate.h b/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegate.h -index 24b33cf16d46efce11a30032925600b97e64c65d..422355368191b9189b6283338bea2244b2fddd9e 100644 +index 2ce017d213d7875eee965e554af6befb5a3c3908..79b11310d358d3edc49e30420728e1eb905309cb 100644 --- a/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegate.h +++ b/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegate.h -@@ -148,6 +148,12 @@ typedef NS_ENUM(NSInteger, WKDialogResult) { +@@ -153,6 +153,12 @@ WK_SWIFT_UI_ACTOR */ - - (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable result))completionHandler; + - (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(WK_SWIFT_UI_ACTOR void (^)(NSString * _Nullable result))completionHandler; +/*! @abstract Handle a JavaScript dialog. + @param webView The web view invoking the delegate method. @@ -10186,18 +9386,10 @@ index 24b33cf16d46efce11a30032925600b97e64c65d..422355368191b9189b6283338bea2244 /*! @abstract A delegate to request permission for microphone audio and camera video access. @param webView The web view invoking the delegate method. diff --git a/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.h b/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.h -index 4f5956098f0e83c2e9c421c97056b6718b124a3c..1eb51dd70dc6ef1b7e95a09118aa816b4f77e2d7 100644 +index 930357ac3469195e9f33d5ffce92777018bb0b13..f62555ec562f8416976d31692e8fb1751a04d458 100644 --- a/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.h +++ b/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.h -@@ -24,7 +24,6 @@ - */ - - #import -- - #import - - #if __has_include() -@@ -124,6 +123,8 @@ WK_CLASS_AVAILABLE(macos(10.11), ios(9.0)) +@@ -138,6 +138,8 @@ WK_CLASS_AVAILABLE(macos(10.11), ios(9.0)) #endif #endif @@ -10207,18 +9399,18 @@ index 4f5956098f0e83c2e9c421c97056b6718b124a3c..1eb51dd70dc6ef1b7e95a09118aa816b NS_ASSUME_NONNULL_END diff --git a/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm b/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm -index 350914dd5352683024925bb820148ba2582cd0c7..ac9767ff4920e066b11da4556b2df77debd18a1f 100644 +index 7e793fe01f479b9135c54253af2114ce61924fa0..d22dc512f73af0e4152b4503866ba2a4cf5c3e5e 100644 --- a/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm +++ b/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm -@@ -51,6 +51,7 @@ - #import "_WKResourceLoadStatisticsThirdPartyInternal.h" +@@ -55,6 +55,7 @@ + #import "_WKWebPushActionInternal.h" #import "_WKWebsiteDataStoreConfigurationInternal.h" #import "_WKWebsiteDataStoreDelegate.h" +#import #import #import #import -@@ -446,6 +447,11 @@ - (void)removeDataOfTypes:(NSSet *)dataTypes modifiedSince:(NSDate *)date comple +@@ -523,6 +524,11 @@ - (void)removeDataOfTypes:(NSSet *)dataTypes modifiedSince:(NSDate *)date comple }); } @@ -10358,7 +9550,7 @@ index 0000000000000000000000000000000000000000..69eb9c6aa30beb8ea21a0ef647e46304 +} +@end diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.h b/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.h -index da0374cf56919b7324a90586d0a7009bfe895be1..1a6f5ff024592a6c3a5c7018045e0a5015aac2c0 100644 +index 426c7cbc897e22fd2e962dd3744959975d6ae6a0..f7a52359d7d42f970ef424b6c702b0ec1121a902 100644 --- a/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.h +++ b/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.h @@ -67,6 +67,7 @@ WK_CLASS_AVAILABLE(macos(10.10), ios(8.0)) @@ -10370,7 +9562,7 @@ index da0374cf56919b7324a90586d0a7009bfe895be1..1a6f5ff024592a6c3a5c7018045e0a50 @property (nonatomic) BOOL processSwapsOnNavigationWithinSameNonHTTPFamilyProtocol WK_API_AVAILABLE(macos(12.0), ios(15.0)); @property (nonatomic) BOOL prewarmsProcessesAutomatically WK_API_AVAILABLE(macos(10.14.4), ios(12.2)); diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.mm b/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.mm -index df71be1e30c4a13fe9565d309c7bbfb82e049d06..8424a471e7841d300174aa54143578f8d18ad15f 100644 +index 7ccfd9a46cd024c8f6644594b9d0cde8ae7e60db..921ec683dce77583f24d27a0b1b6f478242dfb42 100644 --- a/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.mm +++ b/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.mm @@ -241,6 +241,16 @@ - (BOOL)processSwapsOnNavigation @@ -10390,18 +9582,6 @@ index df71be1e30c4a13fe9565d309c7bbfb82e049d06..8424a471e7841d300174aa54143578f8 - (void)setPrewarmsProcessesAutomatically:(BOOL)prewarms { _processPoolConfiguration->setIsAutomaticProcessWarmingEnabled(prewarms); -diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKRemoteWebInspectorViewController.mm b/Source/WebKit/UIProcess/API/Cocoa/_WKRemoteWebInspectorViewController.mm -index 500a748e78bdcd418b18fb4de416b95e9042d2c4..63d4ea68cbc711ba8f12e126d0f6b78aad5f5155 100644 ---- a/Source/WebKit/UIProcess/API/Cocoa/_WKRemoteWebInspectorViewController.mm -+++ b/Source/WebKit/UIProcess/API/Cocoa/_WKRemoteWebInspectorViewController.mm -@@ -24,6 +24,7 @@ - */ - - #import "config.h" -+#import "WKWebViewPrivate.h" - #import "_WKRemoteWebInspectorViewControllerInternal.h" - - #if PLATFORM(MAC) diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKUserStyleSheet.h b/Source/WebKit/UIProcess/API/Cocoa/_WKUserStyleSheet.h index 4974e14214e2bb3e982325b885bab33e54f83998..cacdf8c71fab248d38d2faf03f7affdcfed1ef62 100644 --- a/Source/WebKit/UIProcess/API/Cocoa/_WKUserStyleSheet.h @@ -10414,18 +9594,20 @@ index 4974e14214e2bb3e982325b885bab33e54f83998..cacdf8c71fab248d38d2faf03f7affdc typedef NS_ENUM(NSInteger, _WKUserStyleLevel) { _WKUserStyleUserLevel, -diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKUserStyleSheet.mm b/Source/WebKit/UIProcess/API/Cocoa/_WKUserStyleSheet.mm -index 383bd33cc0b53ea049d2e6fb1bf338d584caeb18..e29ba10dceced9d115b09e014cc086c5453e33fe 100644 ---- a/Source/WebKit/UIProcess/API/Cocoa/_WKUserStyleSheet.mm -+++ b/Source/WebKit/UIProcess/API/Cocoa/_WKUserStyleSheet.mm -@@ -35,6 +35,7 @@ - #import "WebPageProxy.h" - #import "_WKUserContentWorldInternal.h" +diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKWebPushSubscriptionData.mm b/Source/WebKit/UIProcess/API/Cocoa/_WKWebPushSubscriptionData.mm +index d139d35f09a999e2c85f48799a399d791d421ffd..f79c073291c6071c566220a40f7dd4bbc57192a1 100644 +--- a/Source/WebKit/UIProcess/API/Cocoa/_WKWebPushSubscriptionData.mm ++++ b/Source/WebKit/UIProcess/API/Cocoa/_WKWebPushSubscriptionData.mm +@@ -28,6 +28,9 @@ #import -+#import - #import + #import + ++#import ++#import ++ + @implementation _WKWebPushSubscriptionData - @implementation _WKUserStyleSheet + - (void)dealloc diff --git a/Source/WebKit/UIProcess/API/glib/WebKitBrowserInspector.cpp b/Source/WebKit/UIProcess/API/glib/WebKitBrowserInspector.cpp new file mode 100644 index 0000000000000000000000000000000000000000..575245fc1f279a75f7e74c26652cf772a2fc95b7 @@ -10629,10 +9811,10 @@ index 0000000000000000000000000000000000000000..e0b1da48465c850f541532ed961d1b77 +WebKit::WebPageProxy* webkitBrowserInspectorCreateNewPageInContext(WebKitWebContext*); +void webkitBrowserInspectorQuitApplication(); diff --git a/Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp b/Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp -index d6b7f61b141870b4af00fdd0a104dc6cf382fc36..bacc29f875ec5dccb65f7653a772bb99ceee2129 100644 +index ef24e41f2c62e77e701a6e2b698c60004eaf0789..fd332a5b07f1dea7792eeee3bd9b5efb48afc0c5 100644 --- a/Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp +++ b/Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp -@@ -95,6 +95,10 @@ private: +@@ -101,6 +101,10 @@ private: page.makeViewBlankIfUnpaintedSinceLastLoadCommit(); webkitWebViewRunJavaScriptPrompt(m_webView, message.utf8(), defaultValue.utf8(), WTFMove(completionHandler)); } @@ -10644,10 +9826,10 @@ index d6b7f61b141870b4af00fdd0a104dc6cf382fc36..bacc29f875ec5dccb65f7653a772bb99 bool canRunBeforeUnloadConfirmPanel() const final { return true; } diff --git a/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp b/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp -index 14c655bdd47bfb87d548e8c4ddd826e6bbb5d7c5..05440a65021ff70887fc88dc5fbfff71f4990957 100644 +index 5479cf466e1ba77ede37ff980e78bee85bbb094c..224c04a4bd9de6ad5661b15071c1267a57430547 100644 --- a/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp +++ b/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp -@@ -415,10 +415,19 @@ static void webkitWebContextSetProperty(GObject* object, guint propID, const GVa +@@ -423,10 +423,19 @@ static void webkitWebContextSetProperty(GObject* object, guint propID, const GVa } } @@ -10667,7 +9849,7 @@ index 14c655bdd47bfb87d548e8c4ddd826e6bbb5d7c5..05440a65021ff70887fc88dc5fbfff71 GUniquePtr bundleFilename(g_build_filename(injectedBundleDirectory(), INJECTED_BUNDLE_FILENAME, nullptr)); WebKitWebContext* webContext = WEBKIT_WEB_CONTEXT(object); -@@ -475,6 +484,8 @@ static void webkitWebContextConstructed(GObject* object) +@@ -485,6 +494,8 @@ static void webkitWebContextConstructed(GObject* object) static void webkitWebContextDispose(GObject* object) { @@ -10676,7 +9858,7 @@ index 14c655bdd47bfb87d548e8c4ddd826e6bbb5d7c5..05440a65021ff70887fc88dc5fbfff71 WebKitWebContextPrivate* priv = WEBKIT_WEB_CONTEXT(object)->priv; if (!priv->clientsDetached) { priv->clientsDetached = true; -@@ -934,6 +945,11 @@ WebKitNetworkSession* webkit_web_context_get_network_session_for_automation(WebK +@@ -946,6 +957,11 @@ WebKitNetworkSession* webkit_web_context_get_network_session_for_automation(WebK return nullptr; #endif } @@ -10689,7 +9871,7 @@ index 14c655bdd47bfb87d548e8c4ddd826e6bbb5d7c5..05440a65021ff70887fc88dc5fbfff71 /** * webkit_web_context_set_cache_model: diff --git a/Source/WebKit/UIProcess/API/glib/WebKitWebContext.h.in b/Source/WebKit/UIProcess/API/glib/WebKitWebContext.h.in -index fa559936ba819425cfca7ad0f26e9d373690180a..112eb9f64b9c08385eb9a7ac4d6815f574efed0e 100644 +index 15fe3e8e5652147ba54af266eda66b3962c074b9..d463fa78af375badb239c890da50ba1125e19de8 100644 --- a/Source/WebKit/UIProcess/API/glib/WebKitWebContext.h.in +++ b/Source/WebKit/UIProcess/API/glib/WebKitWebContext.h.in @@ -161,6 +161,10 @@ webkit_web_context_set_automation_allowed (WebKitWebContext @@ -10704,7 +9886,7 @@ index fa559936ba819425cfca7ad0f26e9d373690180a..112eb9f64b9c08385eb9a7ac4d6815f5 WEBKIT_API void diff --git a/Source/WebKit/UIProcess/API/glib/WebKitWebContextPrivate.h b/Source/WebKit/UIProcess/API/glib/WebKitWebContextPrivate.h -index e994309b097c1b140abfa4373fd2fafee46c05ec..6e0cc677a3bf33683ae8c89d12a4819144b3df89 100644 +index c1945fbe717a42afc1f51d64a80c7de3fa9009ba..ab63fe19b00ecbd64c9421e6eecad3e25cbb2361 100644 --- a/Source/WebKit/UIProcess/API/glib/WebKitWebContextPrivate.h +++ b/Source/WebKit/UIProcess/API/glib/WebKitWebContextPrivate.h @@ -43,3 +43,4 @@ void webkitWebContextInitializeNotificationPermissions(WebKitWebContext*); @@ -10713,10 +9895,10 @@ index e994309b097c1b140abfa4373fd2fafee46c05ec..6e0cc677a3bf33683ae8c89d12a48191 #endif +int webkitWebContextExistingCount(); diff --git a/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp b/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp -index 1e389f70c7b4722458cffbf4ac34b1d67efa4ba8..b9f5f22c8e866de1909240b72d23c06d7525d863 100644 +index df1381b577be94114401e1faaf1979183d82614f..fb8bb4c7676154bb284a06fc3f05d3b45805e938 100644 --- a/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp +++ b/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp -@@ -33,6 +33,7 @@ +@@ -39,6 +39,7 @@ #include "WebContextMenuItem.h" #include "WebContextMenuItemData.h" #include "WebFrameProxy.h" @@ -10724,23 +9906,7 @@ index 1e389f70c7b4722458cffbf4ac34b1d67efa4ba8..b9f5f22c8e866de1909240b72d23c06d #include "WebKitAuthenticationRequestPrivate.h" #include "WebKitBackForwardListPrivate.h" #include "WebKitContextMenuClient.h" -@@ -50,6 +51,7 @@ - #include "WebKitNavigationClient.h" - #include "WebKitNotificationPrivate.h" - #include "WebKitPermissionStateQueryPrivate.h" -+#include "WebKitPointerLockPermissionRequest.h" - #include "WebKitPrivate.h" - #include "WebKitResponsePolicyDecision.h" - #include "WebKitScriptDialogPrivate.h" -@@ -89,7 +91,6 @@ - #include "GtkSettingsManager.h" - #include "WebKitFaviconDatabasePrivate.h" - #include "WebKitInputMethodContextImplGtk.h" --#include "WebKitPointerLockPermissionRequest.h" - #include "WebKitPrintOperationPrivate.h" - #include "WebKitWebInspectorPrivate.h" - #include "WebKitWebViewBasePrivate.h" -@@ -141,6 +142,7 @@ enum { +@@ -152,6 +153,7 @@ enum { CLOSE, SCRIPT_DIALOG, @@ -10748,29 +9914,35 @@ index 1e389f70c7b4722458cffbf4ac34b1d67efa4ba8..b9f5f22c8e866de1909240b72d23c06d DECIDE_POLICY, PERMISSION_REQUEST, -@@ -494,6 +496,9 @@ GRefPtr WebKitWebViewClient::showOptionMenu(WebKitPopupMenu& p +@@ -520,6 +522,13 @@ GRefPtr WebKitWebViewClient::showOptionMenu(WebKitPopupMenu& p void WebKitWebViewClient::frameDisplayed(WKWPE::View&) { -+ if (RefPtr surface = adoptRef(webkitWebViewBackendTakeScreenshot(m_webView->priv->backend.get()))) -+ getPage(m_webView).inspectorController().didPaint(surface.get()); ++ ++#if USE(SKIA) ++ sk_sp surface(webkitWebViewBackendTakeScreenshot(m_webView->priv->backend.get())); ++ if (surface) ++ getPage(m_webView).inspectorController().didPaint(WTFMove(surface)); ++#endif + { SetForScope inFrameDisplayedGuard(m_webView->priv->inFrameDisplayed, true); for (const auto& callback : m_webView->priv->frameDisplayedCallbacks) { -@@ -510,6 +515,11 @@ void WebKitWebViewClient::frameDisplayed(WKWPE::View&) +@@ -536,6 +545,13 @@ void WebKitWebViewClient::frameDisplayed(WKWPE::View&) } } -+cairo_surface_t* WebKitWebViewClient::takeViewScreenshot() ++#if USE(SKIA) ++sk_sp WebKitWebViewClient::takeViewScreenshot() +{ -+ return webkitWebViewBackendTakeScreenshot(m_webView->priv->backend.get()); ++ return sk_sp(webkitWebViewBackendTakeScreenshot(m_webView->priv->backend.get())); +} ++#endif + void WebKitWebViewClient::willStartLoad(WKWPE::View&) { webkitWebViewWillStartLoad(m_webView); -@@ -596,7 +606,7 @@ static gboolean webkitWebViewDecidePolicy(WebKitWebView*, WebKitPolicyDecision* +@@ -622,7 +638,7 @@ static gboolean webkitWebViewDecidePolicy(WebKitWebView*, WebKitPolicyDecision* static gboolean webkitWebViewPermissionRequest(WebKitWebView*, WebKitPermissionRequest* request) { @@ -10779,7 +9951,18 @@ index 1e389f70c7b4722458cffbf4ac34b1d67efa4ba8..b9f5f22c8e866de1909240b72d23c06d if (WEBKIT_IS_POINTER_LOCK_PERMISSION_REQUEST(request)) { webkit_permission_request_allow(request); return TRUE; -@@ -1903,6 +1913,15 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) +@@ -945,6 +961,10 @@ static void webkitWebViewConstructed(GObject* object) + priv->websitePolicies = adoptGRef(webkit_website_policies_new()); + + Ref configuration = priv->relatedView && priv->relatedView->priv->configurationForNextRelatedView ? priv->relatedView->priv->configurationForNextRelatedView.releaseNonNull() : webkitWebViewCreatePageConfiguration(webView); ++ ++ // Playwright: REGRESSION(278896@main): Need to preserve configuration's preferences. ++ configuration->setPreferences(webkitSettingsGetPreferences(priv->settings.get())); ++ + webkitWebViewCreatePage(webView, WTFMove(configuration)); + webkitWebContextWebViewCreated(priv->context.get(), webView); + +@@ -1984,6 +2004,15 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) G_TYPE_BOOLEAN, 1, WEBKIT_TYPE_SCRIPT_DIALOG); @@ -10795,7 +9978,7 @@ index 1e389f70c7b4722458cffbf4ac34b1d67efa4ba8..b9f5f22c8e866de1909240b72d23c06d /** * WebKitWebView::decide-policy: * @web_view: the #WebKitWebView on which the signal is emitted -@@ -2702,6 +2721,23 @@ void webkitWebViewRunJavaScriptBeforeUnloadConfirm(WebKitWebView* webView, const +@@ -2769,6 +2798,23 @@ void webkitWebViewRunJavaScriptBeforeUnloadConfirm(WebKitWebView* webView, const webkit_script_dialog_unref(webView->priv->currentScriptDialog); } @@ -10820,10 +10003,10 @@ index 1e389f70c7b4722458cffbf4ac34b1d67efa4ba8..b9f5f22c8e866de1909240b72d23c06d { if (!webView->priv->currentScriptDialog) diff --git a/Source/WebKit/UIProcess/API/glib/WebKitWebViewPrivate.h b/Source/WebKit/UIProcess/API/glib/WebKitWebViewPrivate.h -index 1a04ee05c3ddec0628ef5b8b8c181cbcc2b7d622..2a24f8f3fdc3f0eed13f8a79050258a4e4a489f0 100644 +index bf5b4c2bcca722e4d008f12194344c29c0db8824..ee6ee6b476ac28dee3a5983d03ba89ad0c9eb9ff 100644 --- a/Source/WebKit/UIProcess/API/glib/WebKitWebViewPrivate.h +++ b/Source/WebKit/UIProcess/API/glib/WebKitWebViewPrivate.h -@@ -66,6 +66,7 @@ void webkitWebViewRunJavaScriptAlert(WebKitWebView*, const CString& message, Fun +@@ -64,6 +64,7 @@ void webkitWebViewRunJavaScriptAlert(WebKitWebView*, const CString& message, Fun void webkitWebViewRunJavaScriptConfirm(WebKitWebView*, const CString& message, Function&& completionHandler); void webkitWebViewRunJavaScriptPrompt(WebKitWebView*, const CString& message, const CString& defaultText, Function&& completionHandler); void webkitWebViewRunJavaScriptBeforeUnloadConfirm(WebKitWebView*, const CString& message, Function&& completionHandler); @@ -10832,7 +10015,7 @@ index 1a04ee05c3ddec0628ef5b8b8c181cbcc2b7d622..2a24f8f3fdc3f0eed13f8a79050258a4 bool webkitWebViewIsScriptDialogRunning(WebKitWebView*, WebKitScriptDialog*); String webkitWebViewGetCurrentScriptDialogMessage(WebKitWebView*); diff --git a/Source/WebKit/UIProcess/API/glib/webkit.h.in b/Source/WebKit/UIProcess/API/glib/webkit.h.in -index 805f9f638c1630b5e9310494ae2970262de001cc..add3e80896c2e82bdd12cee15c8014bf88391ee0 100644 +index 763cd55f7abca011ac8bc4fef7f233bf52854cda..bd43917b274bf19ff9f3d96b7e80e20710372cba 100644 --- a/Source/WebKit/UIProcess/API/glib/webkit.h.in +++ b/Source/WebKit/UIProcess/API/glib/webkit.h.in @@ -45,6 +45,7 @@ @@ -10844,10 +10027,10 @@ index 805f9f638c1630b5e9310494ae2970262de001cc..add3e80896c2e82bdd12cee15c8014bf #include <@API_INCLUDE_PREFIX@/WebKitClipboardPermissionRequest.h> #include <@API_INCLUDE_PREFIX@/WebKitColorChooserRequest.h> diff --git a/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp b/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp -index cea5882f6c455898e1b5a231e1213e6b71ff21b6..d82b93d3c759b1184869b3504e1c3c07f53cc8ce 100644 +index 12efcb801d9d63d159a7f7d2e733cda141dc4e55..54f6703d64d5bcfd1d0f42be444492f9cd923bb0 100644 --- a/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp +++ b/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp -@@ -269,6 +269,8 @@ void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent& event, bool +@@ -270,6 +270,8 @@ void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent& event, bool { if (wasEventHandled || event.type() != WebEventType::KeyDown || !event.nativeEvent()) return; @@ -10856,7 +10039,7 @@ index cea5882f6c455898e1b5a231e1213e6b71ff21b6..d82b93d3c759b1184869b3504e1c3c07 // Always consider arrow keys as handled, otherwise the GtkWindow key bindings will move the focus. guint keyval; -@@ -371,9 +373,9 @@ void PageClientImpl::selectionDidChange() +@@ -362,9 +364,9 @@ void PageClientImpl::selectionDidChange() webkitWebViewSelectionDidChange(WEBKIT_WEB_VIEW(m_viewWidget)); } @@ -10869,12 +10052,12 @@ index cea5882f6c455898e1b5a231e1213e6b71ff21b6..d82b93d3c759b1184869b3504e1c3c07 void PageClientImpl::didChangeContentSize(const IntSize& size) diff --git a/Source/WebKit/UIProcess/API/gtk/PageClientImpl.h b/Source/WebKit/UIProcess/API/gtk/PageClientImpl.h -index 0445554dc296421d56237b07ea8d09b6e5e533b5..d7d91b30309e7106ae801aaad8162277ed636d1b 100644 +index c20bdf245d4e6d2a215615cf573cbbdefdb574c0..8c9f3f8e2e111bd3d19314e33a394c371944d358 100644 --- a/Source/WebKit/UIProcess/API/gtk/PageClientImpl.h +++ b/Source/WebKit/UIProcess/API/gtk/PageClientImpl.h -@@ -105,7 +105,7 @@ private: - #endif - Ref createValidationBubble(const String& message, const WebCore::ValidationBubble::Settings&) final; +@@ -104,7 +104,7 @@ private: + RefPtr createDataListSuggestionsDropdown(WebPageProxy&) override; + Ref createValidationBubble(String&& message, const WebCore::ValidationBubble::Settings&) final; void selectionDidChange() override; - RefPtr takeViewSnapshot(std::optional&&) override; + RefPtr takeViewSnapshot(std::optional&&, bool nominalResolution = false) override; @@ -10982,10 +10165,10 @@ index 496079da90993ac37689b060b69ecd4a67c2b6a8..af30181ca922f16c0f6e245c70e5ce7d G_BEGIN_DECLS diff --git a/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp b/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp -index 9ce95b0e5ec142f4067c99d4aeb388fa08ae3f89..0718c8d9764d100fc8f41348a9273020645f0825 100644 +index 3bbacbe1dbe27e9743f608322f06abb1adc75173..be721a26127ffff7904072aa2d9e7d72050ca514 100644 --- a/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp +++ b/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp -@@ -2908,6 +2908,11 @@ void webkitWebViewBaseResetClickCounter(WebKitWebViewBase* webkitWebViewBase) +@@ -2875,6 +2875,11 @@ void webkitWebViewBaseResetClickCounter(WebKitWebViewBase* webkitWebViewBase) #endif } @@ -10997,7 +10180,7 @@ index 9ce95b0e5ec142f4067c99d4aeb388fa08ae3f89..0718c8d9764d100fc8f41348a9273020 void webkitWebViewBaseEnterAcceleratedCompositingMode(WebKitWebViewBase* webkitWebViewBase, const LayerTreeContext& layerTreeContext) { ASSERT(webkitWebViewBase->priv->acceleratedBackingStore); -@@ -2964,12 +2969,12 @@ void webkitWebViewBasePageClosed(WebKitWebViewBase* webkitWebViewBase) +@@ -2931,12 +2936,12 @@ void webkitWebViewBasePageClosed(WebKitWebViewBase* webkitWebViewBase) webkitWebViewBase->priv->acceleratedBackingStore->update({ }); } @@ -11013,7 +10196,7 @@ index 9ce95b0e5ec142f4067c99d4aeb388fa08ae3f89..0718c8d9764d100fc8f41348a9273020 #if !USE(GTK4) diff --git a/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBasePrivate.h b/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBasePrivate.h -index a227380c1171e1e5824370b21c66440bb744c7f7..9b7bc68d01ef5d7c5d34720a6ab7c27f9e8c2156 100644 +index 3b8ca9470bab69dc26313111a79f954b10b30bf4..5c056dd6734f42d24bc168b4f5ba436584b3f7a8 100644 --- a/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBasePrivate.h +++ b/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBasePrivate.h @@ -27,6 +27,7 @@ @@ -11024,7 +10207,7 @@ index a227380c1171e1e5824370b21c66440bb744c7f7..9b7bc68d01ef5d7c5d34720a6ab7c27f #include "APIPageConfiguration.h" #include "InputMethodState.h" #include "RendererBufferFormat.h" -@@ -107,7 +108,7 @@ void webkitWebViewBaseStartDrag(WebKitWebViewBase*, WebCore::SelectionData&&, Op +@@ -104,7 +105,7 @@ void webkitWebViewBaseStartDrag(WebKitWebViewBase*, WebCore::SelectionData&&, Op void webkitWebViewBaseDidPerformDragControllerAction(WebKitWebViewBase*); #endif @@ -11033,68 +10216,95 @@ index a227380c1171e1e5824370b21c66440bb744c7f7..9b7bc68d01ef5d7c5d34720a6ab7c27f void webkitWebViewBaseSetEnableBackForwardNavigationGesture(WebKitWebViewBase*, bool enabled); WebKit::ViewGestureController* webkitWebViewBaseViewGestureController(WebKitWebViewBase*); -@@ -148,3 +149,5 @@ void webkitWebViewBaseSetPlugID(WebKitWebViewBase*, const String&); +@@ -145,3 +146,5 @@ void webkitWebViewBaseSetPlugID(WebKitWebViewBase*, const String&); #endif WebKit::RendererBufferFormat webkitWebViewBaseGetRendererBufferFormat(WebKitWebViewBase*); + +WebKit::AcceleratedBackingStore* webkitWebViewBaseGetAcceleratedBackingStore(WebKitWebViewBase*); diff --git a/Source/WebKit/UIProcess/API/wpe/APIViewClient.h b/Source/WebKit/UIProcess/API/wpe/APIViewClient.h -index 26d1790017e528f26ae04dac635678d5494bfd04..48dbe50eb05628307264a350350ac19f0acb3ae3 100644 +index 7636ad733e7be66a74f8fede966b0acb905a5842..777d86d6e160a7cfba6dd50d416ed1881f448de4 100644 --- a/Source/WebKit/UIProcess/API/wpe/APIViewClient.h +++ b/Source/WebKit/UIProcess/API/wpe/APIViewClient.h -@@ -26,6 +26,7 @@ +@@ -26,6 +26,9 @@ #pragma once #include "UserMessage.h" -+#include ++#if USE(SKIA) ++#include ++#endif #include + #include - typedef struct OpaqueJSContext* JSGlobalContextRef; -@@ -49,6 +50,9 @@ public: +@@ -50,6 +53,11 @@ public: virtual bool isGLibBasedAPI() { return false; } virtual void frameDisplayed(WKWPE::View&) { } +// Playwright begin -+ virtual cairo_surface_t* takeViewScreenshot() { return nullptr; } ++#if USE(SKIA) ++ virtual sk_sp takeViewScreenshot() { return nullptr; } ++#endif +// Playwright end virtual void willStartLoad(WKWPE::View&) { } virtual void didChangePageID(WKWPE::View&) { } virtual void didReceiveUserMessage(WKWPE::View&, WebKit::UserMessage&&, CompletionHandler&& completionHandler) { completionHandler(WebKit::UserMessage()); } diff --git a/Source/WebKit/UIProcess/API/wpe/PageClientImpl.cpp b/Source/WebKit/UIProcess/API/wpe/PageClientImpl.cpp -index f498562d70a4652f6831ac6bc12ef86e537d3930..503a8875fed34fd7925646b61a1eed11d7c866b7 100644 +index bbbdaf4b823048adcb1e77756560b3dfd525297d..d4f873d6778bae8150817968b992d91dd2428518 100644 --- a/Source/WebKit/UIProcess/API/wpe/PageClientImpl.cpp +++ b/Source/WebKit/UIProcess/API/wpe/PageClientImpl.cpp -@@ -33,9 +33,13 @@ - #include "NativeWebWheelEvent.h" - #include "TouchGestureController.h" - #include "WPEWebView.h" +@@ -35,9 +35,12 @@ + #include "WPEWebViewLegacy.h" + #include "WPEWebViewPlatform.h" + #include "WebColorPicker.h" +#include "WebColorPickerWPE.h" +#include "WebDateTimePickerWPE.h" #include "WebContextMenuProxy.h" #include "WebContextMenuProxyWPE.h" -+#include "WebKitDataListSuggestionsDropdown.h" + #include "WebDataListSuggestionsDropdown.h" ++#include "WebDataListSuggestionsDropdownWPE.h" + #include "WebDateTimePicker.h" #include "WebKitPopupMenu.h" -+#include "WebColorPicker.h" #include - #include - #include -@@ -203,7 +207,7 @@ WebCore::IntPoint PageClientImpl::accessibilityScreenToRootView(const WebCore::I +@@ -58,6 +61,12 @@ + #include + #endif + ++#if USE(SKIA) ++#include ++#include ++#include ++#endif ++ + namespace WebKit { + + WTF_MAKE_TZONE_ALLOCATED_IMPL(PageClientImpl); +@@ -302,14 +311,14 @@ Ref PageClientImpl::createContextMenuProxy(WebPageProxy& pa + } + #endif + +-RefPtr PageClientImpl::createColorPicker(WebPageProxy&, const WebCore::Color& intialColor, const WebCore::IntRect&, ColorControlSupportsAlpha supportsAlpha, Vector&&) ++RefPtr PageClientImpl::createColorPicker(WebPageProxy& page, const WebCore::Color& intialColor, const WebCore::IntRect& rect, ColorControlSupportsAlpha supportsAlpha, Vector&&) + { +- return nullptr; ++ return WebColorPickerWPE::create(page, intialColor, rect); + } - WebCore::IntRect PageClientImpl::rootViewToAccessibilityScreen(const WebCore::IntRect& rect) +-RefPtr PageClientImpl::createDataListSuggestionsDropdown(WebPageProxy&) ++RefPtr PageClientImpl::createDataListSuggestionsDropdown(WebKit::WebPageProxy& page) { -- return rootViewToScreen(rect); -+ return rootViewToScreen(rect); +- return nullptr; ++ return WebDataListSuggestionsDropdownWPE::create(page); } - void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent&, bool) -@@ -465,6 +469,33 @@ void PageClientImpl::selectionDidChange() + RefPtr PageClientImpl::createDateTimePicker(WebPageProxy& page) +@@ -546,6 +555,37 @@ void PageClientImpl::selectionDidChange() m_view.selectionDidChange(); } -+RefPtr PageClientImpl::takeViewSnapshot(std::optional&& clipRect, bool nominalResolution) ++#if USE(SKIA) ++sk_sp PageClientImpl::takeViewSnapshot(std::optional&& clipRect, bool nominalResolution) +{ -+ RefPtr fullScreenshot = adoptRef(m_view.client().takeViewScreenshot()); ++ sk_sp fullScreenshot = m_view.client().takeViewScreenshot(); + float deviceScale = m_view.page().deviceScaleFactor(); + if (!clipRect && (!nominalResolution || deviceScale == 1)) + return fullScreenshot; @@ -11105,39 +10315,30 @@ index f498562d70a4652f6831ac6bc12ef86e537d3930..503a8875fed34fd7925646b61a1eed11 + if (clipRect) + clipRect->scale(deviceScale); + } -+ RefPtr surface = adoptRef(cairo_image_surface_create(CAIRO_FORMAT_RGB24, size.width(), size.height())); -+ RefPtr cr = adoptRef(cairo_create(surface.get())); ++ ++ SkBitmap bitmap; ++ bitmap.allocPixels(SkImageInfo::Make(size.width(), size.height(), kN32_SkColorType, kPremul_SkAlphaType)); ++ SkCanvas canvas(bitmap); + if (clipRect) { -+ cairo_translate(cr.get(), -clipRect->x(), -clipRect->y()); -+ cairo_rectangle(cr.get(), clipRect->x(), clipRect->y(), clipRect->width(), clipRect->height()); -+ cairo_clip(cr.get()); ++ canvas.translate(-clipRect->x(), -clipRect->y()); ++ SkRect rect = SkRect::MakeXYWH(clipRect->x(), clipRect->y(), clipRect->width(), clipRect->height()); ++ canvas.clipRect(rect); + } + if (nominalResolution) -+ cairo_scale(cr.get(), 1/deviceScale, 1/deviceScale); -+ cairo_set_source_surface(cr.get(), fullScreenshot.get(), 0, 0); -+ cairo_paint(cr.get()); -+ return surface; ++ canvas.scale(1/deviceScale, 1/deviceScale); ++ canvas.drawImage(fullScreenshot, 0, 0); ++ return bitmap.asImage(); +} ++#endif ++ + WebKitWebResourceLoadManager* PageClientImpl::webResourceLoadManager() { return m_view.webResourceLoadManager(); -@@ -475,4 +506,23 @@ void PageClientImpl::callAfterNextPresentationUpdate(CompletionHandler&& +@@ -556,4 +596,11 @@ void PageClientImpl::callAfterNextPresentationUpdate(CompletionHandler&& m_view.callAfterNextPresentationUpdate(WTFMove(callback)); } -+#if ENABLE(DATALIST_ELEMENT) -+RefPtr PageClientImpl::createDataListSuggestionsDropdown(WebKit::WebPageProxy& page) -+{ -+ return WebKitDataListSuggestionsDropdown::create(page); -+} -+#endif -+ -+RefPtr PageClientImpl::createColorPicker(WebPageProxy* page, const WebCore::Color& color, const WebCore::IntRect& rect, Vector&&) -+{ -+ return WebColorPickerWPE::create(*page, color, rect); -+} -+ +#if ENABLE(DATE_AND_TIME_INPUT_TYPES) +RefPtr PageClientImpl::createDateTimePicker(WebPageProxy& page) +{ @@ -11147,46 +10348,26 @@ index f498562d70a4652f6831ac6bc12ef86e537d3930..503a8875fed34fd7925646b61a1eed11 + } // namespace WebKit diff --git a/Source/WebKit/UIProcess/API/wpe/PageClientImpl.h b/Source/WebKit/UIProcess/API/wpe/PageClientImpl.h -index a7ece2c8dc3fd30bfb850de04c4fc10004444d5a..b5ee1a1877b3e748dea3ce195cd75cb0701a7034 100644 +index 8809d3fbeeae0387bf683f6154e6db741c3ecc4a..4f1671804b06c82ba221ad74b2b30d0f47ee8718 100644 --- a/Source/WebKit/UIProcess/API/wpe/PageClientImpl.h +++ b/Source/WebKit/UIProcess/API/wpe/PageClientImpl.h -@@ -166,9 +166,21 @@ private: +@@ -183,9 +183,15 @@ private: void didChangeWebPageID() const override; void selectionDidChange() override; -+ RefPtr takeViewSnapshot(std::optional&&, bool nominalResolution) override; - +- ++#if USE(SKIA) ++ sk_sp takeViewSnapshot(std::optional&&, bool nominalResolution) override; ++#endif WebKitWebResourceLoadManager* webResourceLoadManager() override; -+#if ENABLE(DATALIST_ELEMENT) -+ RefPtr createDataListSuggestionsDropdown(WebKit::WebPageProxy& page) override; -+#endif -+ -+#if ENABLE(INPUT_TYPE_COLOR) -+ RefPtr createColorPicker(WebPageProxy*, const WebCore::Color& initialColor, const WebCore::IntRect&, Vector&&) override; -+#endif +#if ENABLE(DATE_AND_TIME_INPUT_TYPES) + RefPtr createDateTimePicker(WebPageProxy&) override; +#endif + WKWPE::View& m_view; - }; - -diff --git a/Source/WebKit/UIProcess/API/wpe/WPEWebView.cpp b/Source/WebKit/UIProcess/API/wpe/WPEWebView.cpp -index 8a9b8a7a853f2bdb6ae0b8bb389d3db1e1a53ac4..c22553b96c3e9afc126ce93c4e45e3af0fbd38f0 100644 ---- a/Source/WebKit/UIProcess/API/wpe/WPEWebView.cpp -+++ b/Source/WebKit/UIProcess/API/wpe/WPEWebView.cpp -@@ -98,7 +98,9 @@ View::View(struct wpe_view_backend* backend, WPEDisplay* display, const API::Pag - auto& preferences = configuration->preferences(); - preferences.setAcceleratedCompositingEnabled(true); - preferences.setForceCompositingMode(true); -- preferences.setThreadedScrollingEnabled(true); -+ // Playwright override begin -+ preferences.setThreadedScrollingEnabled(false); -+ // Playwright override end - - auto& pool = configuration->processPool(); - m_pageProxy = pool.createWebPage(*m_pageClient, WTFMove(configuration)); + #if ENABLE(FULLSCREEN_API) + std::unique_ptr m_fullscreenClientForTesting; diff --git a/Source/WebKit/UIProcess/API/wpe/WebKitBrowserInspector.h b/Source/WebKit/UIProcess/API/wpe/WebKitBrowserInspector.h new file mode 100644 index 0000000000000000000000000000000000000000..273c5105cdf1638955cea01128c9bbab3e64436c @@ -11274,133 +10455,8 @@ index 0000000000000000000000000000000000000000..273c5105cdf1638955cea01128c9bbab +G_END_DECLS + +#endif -diff --git a/Source/WebKit/UIProcess/API/wpe/WebKitDataListSuggestionsDropdown.cpp b/Source/WebKit/UIProcess/API/wpe/WebKitDataListSuggestionsDropdown.cpp -new file mode 100644 -index 0000000000000000000000000000000000000000..afafef2b7fb433e006b1763e653e200bc80edcbd ---- /dev/null -+++ b/Source/WebKit/UIProcess/API/wpe/WebKitDataListSuggestionsDropdown.cpp -@@ -0,0 +1,58 @@ -+/* -+ * Copyright (C) 2019 Igalia S.L. -+ * -+ * 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 APPLE INC. AND ITS 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 APPLE INC. OR ITS 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. -+ */ -+ -+#include "config.h" -+#include "WebKitDataListSuggestionsDropdown.h" -+ -+#if ENABLE(DATALIST_ELEMENT) -+ -+#include "WebPageProxy.h" -+ -+namespace WebKit { -+ -+WebKitDataListSuggestionsDropdown::WebKitDataListSuggestionsDropdown(WebPageProxy& page) -+ : WebDataListSuggestionsDropdown(page) -+{ -+} -+ -+WebKitDataListSuggestionsDropdown::~WebKitDataListSuggestionsDropdown() -+{ -+} -+ -+void WebKitDataListSuggestionsDropdown::show(WebCore::DataListSuggestionInformation&& information) -+{ -+} -+ -+void WebKitDataListSuggestionsDropdown::handleKeydownWithIdentifier(const String& key) -+{ -+} -+ -+void WebKitDataListSuggestionsDropdown::close() -+{ -+} -+ -+} // namespace WebKit -+ -+#endif // ENABLE(DATALIST_ELEMENT) -diff --git a/Source/WebKit/UIProcess/API/wpe/WebKitDataListSuggestionsDropdown.h b/Source/WebKit/UIProcess/API/wpe/WebKitDataListSuggestionsDropdown.h -new file mode 100644 -index 0000000000000000000000000000000000000000..0a099832c3dd959f456fcae49a1d62a9477d2758 ---- /dev/null -+++ b/Source/WebKit/UIProcess/API/wpe/WebKitDataListSuggestionsDropdown.h -@@ -0,0 +1,55 @@ -+/* -+ * Copyright (C) 2019 Igalia S.L. -+ * -+ * 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 APPLE INC. AND ITS 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 APPLE INC. OR ITS 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. -+ */ -+ -+#pragma once -+ -+#if ENABLE(DATALIST_ELEMENT) -+ -+#include "WebDataListSuggestionsDropdown.h" -+ -+namespace WebKit { -+ -+class WebPageProxy; -+ -+class WebKitDataListSuggestionsDropdown final : public WebDataListSuggestionsDropdown { -+public: -+ static Ref create(WebPageProxy& page) -+ { -+ return adoptRef(*new WebKitDataListSuggestionsDropdown(page)); -+ } -+ -+ ~WebKitDataListSuggestionsDropdown(); -+ -+private: -+ WebKitDataListSuggestionsDropdown(WebPageProxy&); -+ -+ void show(WebCore::DataListSuggestionInformation&&) final; -+ void handleKeydownWithIdentifier(const String&) final; -+ void close() final; -+}; -+ -+} // namespace WebKit -+ -+#endif // ENABLE(DATALIST_ELEMENT) diff --git a/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackend.cpp b/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackend.cpp -index 763bda5b29304f7ed7133c0a8158e6c8b94c5ea1..ff5d01438e44ce6785a2aa70fc5423ba74e7101c 100644 +index 763bda5b29304f7ed7133c0a8158e6c8b94c5ea1..8ed962e8c1af62b9b73a68348d0d88765429861d 100644 --- a/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackend.cpp +++ b/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackend.cpp @@ -54,6 +54,7 @@ struct _WebKitWebViewBackend { @@ -11420,7 +10476,7 @@ index 763bda5b29304f7ed7133c0a8158e6c8b94c5ea1..ff5d01438e44ce6785a2aa70fc5423ba + view_backend->screenshotCallback = callback; +} + -+cairo_surface_t* webkitWebViewBackendTakeScreenshot(WebKitWebViewBackend* view_backend) ++PlatformImage webkitWebViewBackendTakeScreenshot(WebKitWebViewBackend* view_backend) +{ + if (!view_backend->screenshotCallback) + return nullptr; @@ -11432,22 +10488,26 @@ index 763bda5b29304f7ed7133c0a8158e6c8b94c5ea1..ff5d01438e44ce6785a2aa70fc5423ba template <> WebKitWebViewBackend* refGPtr(WebKitWebViewBackend* ptr) diff --git a/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackend.h b/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackend.h -index 16dcc1f69c38cd8ad630bc49d6d69feaa3aa811e..ddbd14645944fdb02925c381f06721d368a434f8 100644 +index 16dcc1f69c38cd8ad630bc49d6d69feaa3aa811e..98677028c19c12c3b6d513bb5e45375a1528fe8a 100644 --- a/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackend.h +++ b/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackend.h -@@ -27,6 +27,7 @@ - #include +@@ -28,6 +28,11 @@ #include #include -+#include ++#if defined(USE_SKIA) && USE_SKIA ++#include ++using PlatformImage = SkImage*; ++#endif ++ G_BEGIN_DECLS -@@ -44,6 +45,12 @@ webkit_web_view_backend_new (struct wpe_view_backend *backend, + #define WEBKIT_TYPE_WEB_VIEW_BACKEND (webkit_web_view_backend_get_type()) +@@ -44,6 +49,12 @@ webkit_web_view_backend_new (struct wpe_view_backend *backend, WEBKIT_API struct wpe_view_backend * webkit_web_view_backend_get_wpe_backend (WebKitWebViewBackend *view_backend); -+typedef cairo_surface_t* (*take_screenshot_callback)(gpointer user_data); ++typedef PlatformImage (*take_screenshot_callback)(gpointer user_data); + +WEBKIT_API void +webkit_web_view_backend_set_screenshot_callback (WebKitWebViewBackend *view_backend, @@ -11457,7 +10517,7 @@ index 16dcc1f69c38cd8ad630bc49d6d69feaa3aa811e..ddbd14645944fdb02925c381f06721d3 #endif /* WebKitWebViewBackend_h */ diff --git a/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackendPrivate.h b/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackendPrivate.h -index e4b92ace1531090ae38a7aec3d3d4febf19aee84..43690f9ef4969a39084501613bfc00a77fd5df49 100644 +index e4b92ace1531090ae38a7aec3d3d4febf19aee84..b66b573f9148c39c5ce2738add6cd01a9a352be8 100644 --- a/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackendPrivate.h +++ b/Source/WebKit/UIProcess/API/wpe/WebKitWebViewBackendPrivate.h @@ -31,3 +31,5 @@ template <> void derefGPtr(WebKitWebViewBackend* ptr); @@ -11465,26 +10525,49 @@ index e4b92ace1531090ae38a7aec3d3d4febf19aee84..43690f9ef4969a39084501613bfc00a7 void webkitWebViewBackendUnref(WebKitWebViewBackend*); + -+cairo_surface_t* webkitWebViewBackendTakeScreenshot(WebKitWebViewBackend*); ++PlatformImage webkitWebViewBackendTakeScreenshot(WebKitWebViewBackend*); diff --git a/Source/WebKit/UIProcess/API/wpe/WebKitWebViewClient.h b/Source/WebKit/UIProcess/API/wpe/WebKitWebViewClient.h -index 720c88818bdb4cde3cb58e95785454754f6c1396..7f702c0b922e13128522d2bb1ace6a233812a7d4 100644 +index 2f1182cb91a00353eace0b71612df096391c2450..f2d09ba39f7d3c1b76ed705a0d945b869823c03e 100644 --- a/Source/WebKit/UIProcess/API/wpe/WebKitWebViewClient.h +++ b/Source/WebKit/UIProcess/API/wpe/WebKitWebViewClient.h -@@ -50,6 +50,9 @@ private: +@@ -51,6 +51,11 @@ private: bool isGLibBasedAPI() override { return true; } void frameDisplayed(WKWPE::View&) override; +// Playwright begin -+ cairo_surface_t* takeViewScreenshot() override; ++#if USE(SKIA) ++ sk_sp takeViewScreenshot() override; ++#endif +// Playwright end void willStartLoad(WKWPE::View&) override; void didChangePageID(WKWPE::View&) override; void didReceiveUserMessage(WKWPE::View&, WebKit::UserMessage&&, CompletionHandler&&) override; +diff --git a/Source/WebKit/UIProcess/Automation/WebAutomationSession.h b/Source/WebKit/UIProcess/Automation/WebAutomationSession.h +index b351f11524a994ac6136daf9c277419fce44df0f..31679e63462cfaceeac00ebf31985c118ff1e4e4 100644 +--- a/Source/WebKit/UIProcess/Automation/WebAutomationSession.h ++++ b/Source/WebKit/UIProcess/Automation/WebAutomationSession.h +@@ -287,6 +287,8 @@ public: + + void didDestroyFrame(WebCore::FrameIdentifier); + ++ static std::optional platformGetBase64EncodedPNGData(const ViewSnapshot&); ++ + RefPtr webPageProxyForHandle(const String&); + String handleForWebPageProxy(const WebPageProxy&); + +@@ -338,7 +340,6 @@ private: + + // Get base64-encoded PNG data from a bitmap. + static std::optional platformGetBase64EncodedPNGData(WebCore::ShareableBitmap::Handle&&); +- static std::optional platformGetBase64EncodedPNGData(const ViewSnapshot&); + + // Save base64-encoded file contents to a local file path and return the path. + // This reuses the basename of the remote file path so that the filename exposed to DOM API remains the same. diff --git a/Source/WebKit/UIProcess/AuxiliaryProcessProxy.cpp b/Source/WebKit/UIProcess/AuxiliaryProcessProxy.cpp -index 6f69cd9d4db8544a2c0c8b11fb557697f9b6a183..750a565d8a0c1208cd6950740b2beffa8c1d69d9 100644 +index d5186484fee73b83dbcd611a9695d92a0a6f9579..e26cea229aeb1f6aad23f1265baccfe67e508a13 100644 --- a/Source/WebKit/UIProcess/AuxiliaryProcessProxy.cpp +++ b/Source/WebKit/UIProcess/AuxiliaryProcessProxy.cpp -@@ -158,7 +158,11 @@ void AuxiliaryProcessProxy::getLaunchOptions(ProcessLauncher::LaunchOptions& lau +@@ -173,7 +173,11 @@ void AuxiliaryProcessProxy::getLaunchOptions(ProcessLauncher::LaunchOptions& lau launchOptions.processCmdPrefix = String::fromUTF8(processCmdPrefix); #endif // ENABLE(DEVELOPER_MODE) && (PLATFORM(GTK) || PLATFORM(WPE)) @@ -11497,12 +10580,12 @@ index 6f69cd9d4db8544a2c0c8b11fb557697f9b6a183..750a565d8a0c1208cd6950740b2beffa platformGetLaunchOptions(launchOptions); } diff --git a/Source/WebKit/UIProcess/AuxiliaryProcessProxy.h b/Source/WebKit/UIProcess/AuxiliaryProcessProxy.h -index e2d1e9dfbc77e3d520ce8d31c812a8482facae10..28238da43a4fc45466b43753bc5ad8aa07963f94 100644 +index 53b4c647c013643d45d845154dd640e8c21c3fd4..d7cc83ec06678945d6e71cdebf3227f86f7661e6 100644 --- a/Source/WebKit/UIProcess/AuxiliaryProcessProxy.h +++ b/Source/WebKit/UIProcess/AuxiliaryProcessProxy.h -@@ -264,13 +264,16 @@ protected: - static RefPtr fetchAudioComponentServerRegistrations(); - #endif +@@ -298,13 +298,16 @@ protected: + + InitializationActivityAndGrant initializationActivityAndGrant(); + /* playwright revert 50f8fee - make protected to allow use from WebProcessProxy */ + Vector platformOverrideLanguages() const; @@ -11517,16 +10600,20 @@ index e2d1e9dfbc77e3d520ce8d31c812a8482facae10..28238da43a4fc45466b43753bc5ad8aa - Vector platformOverrideLanguages() const; void platformStartConnectionTerminationWatchdog(); - ResponsivenessTimer m_responsivenessTimer; + // Connection::Client diff --git a/Source/WebKit/UIProcess/BackingStore.h b/Source/WebKit/UIProcess/BackingStore.h -index f9b557ae57a25f53f6d17aab23a256e3cc7d1e66..cced83f477cb1344dd079b9c3523b109ee5cfd89 100644 +index 945c62704e0b25f04e9ee4be88b21f88aeda8bd9..b57ea0f359ab586c88a7d463f2be437b780c267c 100644 --- a/Source/WebKit/UIProcess/BackingStore.h +++ b/Source/WebKit/UIProcess/BackingStore.h -@@ -61,6 +61,7 @@ public: +@@ -67,6 +67,11 @@ public: float deviceScaleFactor() const { return m_deviceScaleFactor; } void paint(PlatformPaintContextPtr, const WebCore::IntRect&); ++#if PLATFORM(GTK) + RefPtr surface() const { return m_surface; } ++#elif USE(SKIA) ++ sk_sp surface() const { return m_surface; } ++#endif void incorporateUpdate(UpdateInfo&&); private: @@ -11641,32 +10728,23 @@ index 0000000000000000000000000000000000000000..cd66887de171cda7d15a8e4dc6dbff63 +} // namespace WebKit + +#endif // ENABLE(REMOTE_INSPECTOR) -diff --git a/Source/WebKit/UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.h b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.h -index 957f7f088087169668a9b4f1ba65d9f206a2a836..15e44c8d5b6a3eafb7f1148707366b0cddcd119f 100644 ---- a/Source/WebKit/UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.h -+++ b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.h -@@ -29,6 +29,7 @@ +diff --git a/Source/WebKit/UIProcess/Cocoa/SOAuthorization/WKSOAuthorizationDelegate.h b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/WKSOAuthorizationDelegate.h +index 89d125f7742f81ead8c50f218ecb1771b8000636..baa6cf58ad502c6c033ee6293a6cc8d4ce608e7b 100644 +--- a/Source/WebKit/UIProcess/Cocoa/SOAuthorization/WKSOAuthorizationDelegate.h ++++ b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/WKSOAuthorizationDelegate.h +@@ -25,6 +25,7 @@ - #include "SOAuthorizationSession.h" - #include -+#include + #if HAVE(APP_SSO) - OBJC_CLASS WKSOSecretDelegate; - OBJC_CLASS WKWebView; -@@ -39,6 +40,8 @@ class NavigationAction; ++#import "SOAuthorizationSession.h" + #import namespace WebKit { - -+class WebPageProxy; -+ - // FSM: Idle => Active => Completed - class PopUpSOAuthorizationSession final : public SOAuthorizationSession { - public: diff --git a/Source/WebKit/UIProcess/Cocoa/UIDelegate.h b/Source/WebKit/UIProcess/Cocoa/UIDelegate.h -index 20af8a02d6dee5af7328accca7cd88a06995c4bb..16e8fc676e4bd70f3f35414434963ccb9f277311 100644 +index 554009ae0e083f7721f97a3952f0f17b7d8d7d9d..fbf643cc61caab6389e4bc727adb897ebbb6a109 100644 --- a/Source/WebKit/UIProcess/Cocoa/UIDelegate.h +++ b/Source/WebKit/UIProcess/Cocoa/UIDelegate.h -@@ -96,6 +96,7 @@ private: +@@ -103,6 +103,7 @@ private: void runJavaScriptAlert(WebPageProxy&, const WTF::String&, WebFrameProxy*, FrameInfoData&&, Function&& completionHandler) final; void runJavaScriptConfirm(WebPageProxy&, const WTF::String&, WebFrameProxy*, FrameInfoData&&, Function&& completionHandler) final; void runJavaScriptPrompt(WebPageProxy&, const WTF::String&, const WTF::String&, WebFrameProxy*, FrameInfoData&&, Function&&) final; @@ -11674,7 +10752,7 @@ index 20af8a02d6dee5af7328accca7cd88a06995c4bb..16e8fc676e4bd70f3f35414434963ccb void presentStorageAccessConfirmDialog(const WTF::String& requestingDomain, const WTF::String& currentDomain, CompletionHandler&&); void requestStorageAccessConfirm(WebPageProxy&, WebFrameProxy*, const WebCore::RegistrableDomain& requestingDomain, const WebCore::RegistrableDomain& currentDomain, std::optional&&, CompletionHandler&&) final; void decidePolicyForGeolocationPermissionRequest(WebPageProxy&, WebFrameProxy&, const FrameInfoData&, Function&) final; -@@ -207,6 +208,7 @@ private: +@@ -221,6 +222,7 @@ private: bool webViewRunJavaScriptAlertPanelWithMessageInitiatedByFrameCompletionHandler : 1; bool webViewRunJavaScriptConfirmPanelWithMessageInitiatedByFrameCompletionHandler : 1; bool webViewRunJavaScriptTextInputPanelWithPromptDefaultTextInitiatedByFrameCompletionHandler : 1; @@ -11683,10 +10761,10 @@ index 20af8a02d6dee5af7328accca7cd88a06995c4bb..16e8fc676e4bd70f3f35414434963ccb bool webViewRequestStorageAccessPanelForDomainUnderCurrentDomainForQuirkDomainsCompletionHandler : 1; bool webViewRunBeforeUnloadConfirmPanelWithMessageInitiatedByFrameCompletionHandler : 1; diff --git a/Source/WebKit/UIProcess/Cocoa/UIDelegate.mm b/Source/WebKit/UIProcess/Cocoa/UIDelegate.mm -index db0e7523899917cc9055ced3127a1e4eb493313d..c5a8a5a7da934deda55313465c26a38b1b33d2ac 100644 +index 30de92c390b49a383369fb59397810187f752c8a..0752cc7cefcc4c3579eafca4fa1cc6e4045d5d84 100644 --- a/Source/WebKit/UIProcess/Cocoa/UIDelegate.mm +++ b/Source/WebKit/UIProcess/Cocoa/UIDelegate.mm -@@ -118,6 +118,7 @@ void UIDelegate::setDelegate(id delegate) +@@ -135,6 +135,7 @@ void UIDelegate::setDelegate(id delegate) m_delegateMethods.webViewRunJavaScriptAlertPanelWithMessageInitiatedByFrameCompletionHandler = [delegate respondsToSelector:@selector(webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:completionHandler:)]; m_delegateMethods.webViewRunJavaScriptConfirmPanelWithMessageInitiatedByFrameCompletionHandler = [delegate respondsToSelector:@selector(webView:runJavaScriptConfirmPanelWithMessage:initiatedByFrame:completionHandler:)]; m_delegateMethods.webViewRunJavaScriptTextInputPanelWithPromptDefaultTextInitiatedByFrameCompletionHandler = [delegate respondsToSelector:@selector(webView:runJavaScriptTextInputPanelWithPrompt:defaultText:initiatedByFrame:completionHandler:)]; @@ -11694,7 +10772,7 @@ index db0e7523899917cc9055ced3127a1e4eb493313d..c5a8a5a7da934deda55313465c26a38b m_delegateMethods.webViewRequestStorageAccessPanelUnderFirstPartyCompletionHandler = [delegate respondsToSelector:@selector(_webView:requestStorageAccessPanelForDomain:underCurrentDomain:completionHandler:)]; m_delegateMethods.webViewRequestStorageAccessPanelForDomainUnderCurrentDomainForQuirkDomainsCompletionHandler = [delegate respondsToSelector:@selector(_webView:requestStorageAccessPanelForDomain:underCurrentDomain:forQuirkDomains:completionHandler:)]; m_delegateMethods.webViewRunBeforeUnloadConfirmPanelWithMessageInitiatedByFrameCompletionHandler = [delegate respondsToSelector:@selector(_webView:runBeforeUnloadConfirmPanelWithMessage:initiatedByFrame:completionHandler:)]; -@@ -442,6 +443,15 @@ void UIDelegate::UIClient::runJavaScriptPrompt(WebPageProxy& page, const WTF::St +@@ -495,6 +496,15 @@ void UIDelegate::UIClient::runJavaScriptPrompt(WebPageProxy& page, const WTF::St }).get()]; } @@ -11704,33 +10782,36 @@ index db0e7523899917cc9055ced3127a1e4eb493313d..c5a8a5a7da934deda55313465c26a38b + auto delegate = m_uiDelegate->m_delegate.get(); + if (!delegate) + return; -+ [delegate webView:m_uiDelegate->m_webView.get().get() handleJavaScriptDialog:accept value:value]; ++ [delegate webView:m_uiDelegate->m_webView.get().get() handleJavaScriptDialog:accept value:value.createNSString().get()]; +} + void UIDelegate::UIClient::requestStorageAccessConfirm(WebPageProxy& webPageProxy, WebFrameProxy*, const WebCore::RegistrableDomain& requestingDomain, const WebCore::RegistrableDomain& currentDomain, std::optional&& organizationStorageAccessPromptQuirk, CompletionHandler&& completionHandler) { - if (!m_uiDelegate) + RefPtr uiDelegate = m_uiDelegate.get(); diff --git a/Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm b/Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm -index b77d46b64193c5cf2017da8d81623e54d5f6f7a8..61a08b78ff3829995b54ce14c1752d4e073d5796 100644 +index 0eaba44d278da255e3035a4f71ddffb276ad2164..23838dad0c6f4a150ec99ecc1105163db1140a0a 100644 --- a/Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm +++ b/Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm -@@ -38,6 +38,7 @@ - #import "LoadParameters.h" - #import "MessageSenderInlines.h" +@@ -43,7 +43,9 @@ + #import "NativeWebKeyboardEvent.h" + #import "NativeWebMouseEvent.h" + #import "NavigationState.h" ++#import "NetworkProcessMessages.h" #import "PageClient.h" +#import "PasteboardTypes.h" + #import "PlatformXRSystem.h" #import "PlaybackSessionManagerProxy.h" - #import "QuickLookThumbnailLoader.h" #import "RemoteLayerTreeTransaction.h" -@@ -283,10 +284,87 @@ bool WebPageProxy::scrollingUpdatesDisabledForTesting() +@@ -347,11 +349,86 @@ bool WebPageProxy::scrollingUpdatesDisabledForTesting() - void WebPageProxy::startDrag(const DragItem& dragItem, ShareableBitmap::Handle&& dragImageHandle) + void WebPageProxy::startDrag(const DragItem& dragItem, ShareableBitmap::Handle&& dragImageHandle, const std::optional& elementID) { + if (m_interceptDrags) { -+ NSPasteboard *pasteboard = [NSPasteboard pasteboardWithName: m_overrideDragPasteboardName]; ++ NSPasteboard *pasteboard = [NSPasteboard pasteboardWithName: m_overrideDragPasteboardName.createNSString().get()]; + + m_dragSelectionData = String([pasteboard name]); -+ grantAccessToCurrentPasteboardData(String([pasteboard name])); ++ if (auto replyID = grantAccessToCurrentPasteboardData(String([pasteboard name]), [] () { })) ++ websiteDataStore().protectedNetworkProcess()->connection().waitForAsyncReplyAndDispatchImmediately(*replyID, 100_ms); + m_dragSourceOperationMask = WebCore::anyDragOperation(); + + if (auto& info = dragItem.promisedAttachmentInfo) { @@ -11739,18 +10820,15 @@ index b77d46b64193c5cf2017da8d81623e54d5f6f7a8..61a08b78ff3829995b54ce14c1752d4e + dragCancelled(); + return; + } -+ NSString *utiType = attachment->utiType(); ++ NSString *utiType = attachment->utiType().createNSString().get(); + if (!utiType.length) { + dragCancelled(); + return; + } + -+ ASSERT(info.additionalTypes.size() == info.additionalData.size()); -+ if (info.additionalTypes.size() == info.additionalData.size()) { -+ for (size_t index = 0; index < info.additionalTypes.size(); ++index) { -+ auto nsData = info.additionalData[index]->createNSData(); -+ [pasteboard setData:nsData.get() forType:info.additionalTypes[index]]; -+ } ++ for (size_t index = 0; index < info.additionalTypesAndData.size(); ++index) { ++ auto nsData = info.additionalTypesAndData[index].second->createNSData(); ++ [pasteboard setData:nsData.get() forType:info.additionalTypesAndData[index].first.createNSString().get()]; + } + } else { + [pasteboard setString:@"" forType:PasteboardTypes::WebDummyPboardType]; @@ -11759,7 +10837,8 @@ index b77d46b64193c5cf2017da8d81623e54d5f6f7a8..61a08b78ff3829995b54ce14c1752d4e + return; + } + - protectedPageClient()->startDrag(dragItem, WTFMove(dragImageHandle)); + if (RefPtr pageClient = this->pageClient()) + pageClient->startDrag(dragItem, WTFMove(dragImageHandle), elementID); } -#endif @@ -11781,9 +10860,9 @@ index b77d46b64193c5cf2017da8d81623e54d5f6f7a8..61a08b78ff3829995b54ce14c1752d4e + NSPasteboard *pasteboard = [NSPasteboard pasteboardWithUniqueName]; + m_overrideDragPasteboardName = String([pasteboard name]); + } -+ send(Messages::WebPage::SetDragPasteboardName(m_overrideDragPasteboardName)); ++ legacyMainFrameProcess().send(Messages::WebPage::SetDragPasteboardName(m_overrideDragPasteboardName), webPageIDInMainFrameProcess()); + } else { -+ send(Messages::WebPage::SetDragPasteboardName(""_s)); ++ legacyMainFrameProcess().send(Messages::WebPage::SetDragPasteboardName(""_s), webPageIDInMainFrameProcess()); + } +} + @@ -11802,29 +10881,29 @@ index b77d46b64193c5cf2017da8d81623e54d5f6f7a8..61a08b78ff3829995b54ce14c1752d4e + + auto previousRect = m_currentDragCaretRect; + m_currentDragCaretRect = dragCaretRect; -+ pageClient().didChangeDragCaretRect(previousRect, dragCaretRect); ++ pageClient()->didChangeDragCaretRect(previousRect, dragCaretRect); +} + +#endif // PLATFORM(IOS_FAMILY) + +#endif // ENABLE(DRAG_SUPPORT) - #if ENABLE(UNIFIED_TEXT_REPLACEMENT) + #if ENABLE(ATTACHMENT_ELEMENT) diff --git a/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm b/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm -index ba0c5fe1678dc1055c7f495f5ff421438db7e082..bdf2dd23de87c114db52603b919f29188a2c4bed 100644 +index 7f9f0ecf631ab772460603adb4d0426e1d468085..a98a1388e589d5f079fe29f5b6091aa022b6ecfc 100644 --- a/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm +++ b/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm -@@ -434,7 +434,7 @@ ALLOW_DEPRECATED_DECLARATIONS_END +@@ -436,7 +436,7 @@ ALLOW_DEPRECATED_DECLARATIONS_END auto screenProperties = WebCore::collectScreenProperties(); parameters.screenProperties = WTFMove(screenProperties); #if PLATFORM(MAC) - parameters.useOverlayScrollbars = ([NSScroller preferredScrollerStyle] == NSScrollerStyleOverlay); + parameters.useOverlayScrollbars = m_configuration->forceOverlayScrollbars() || ([NSScroller preferredScrollerStyle] == NSScrollerStyleOverlay); #endif - - #if (PLATFORM(IOS) || PLATFORM(VISION)) && HAVE(AGX_COMPILER_SERVICE) -@@ -803,8 +803,8 @@ void WebProcessPool::registerNotificationObservers() + + #if PLATFORM(VISION) +@@ -835,8 +835,8 @@ void WebProcessPool::registerNotificationObservers() }]; m_scrollerStyleNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSPreferredScrollerStyleDidChangeNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *notification) { @@ -11836,10 +10915,10 @@ index ba0c5fe1678dc1055c7f495f5ff421438db7e082..bdf2dd23de87c114db52603b919f2918 m_activationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSApplicationDidBecomeActiveNotification object:NSApp queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *notification) { diff --git a/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.cpp b/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.cpp -index 3796110b3f6ffb29bc1eae80505017dee9e779d1..1a181f4ac8ce8d15d5e65a9df6afc8fe5695e85c 100644 +index 183a2dc44f4d2921e68a6ff5fd2fb0fb815753af..f9e80d965f5b7cd64049d85e57e668d6f2a73d87 100644 --- a/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.cpp +++ b/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.cpp -@@ -33,14 +33,17 @@ +@@ -33,6 +33,7 @@ #include "LayerTreeContext.h" #include "MessageSenderInlines.h" #include "UpdateInfo.h" @@ -11847,35 +10926,38 @@ index 3796110b3f6ffb29bc1eae80505017dee9e779d1..1a181f4ac8ce8d15d5e65a9df6afc8fe #include "WebPageProxy.h" #include "WebPreferences.h" #include "WebProcessPool.h" - #include "WebProcessProxy.h" +@@ -40,15 +41,26 @@ #include #include + #include +#include #if PLATFORM(GTK) +#include "WebKitWebViewBasePrivate.h" #include ++#include ++#include ++#include ++#include #endif -@@ -48,6 +51,13 @@ + #if USE(GLIB_EVENT_LOOP) #include #endif +#if PLATFORM(WIN) -+#include +#include +#include -+#include +#endif + namespace WebKit { using namespace WebCore; -@@ -160,6 +170,11 @@ void DrawingAreaProxyCoordinatedGraphics::deviceScaleFactorDidChange() - send(Messages::DrawingArea::SetDeviceScaleFactor(m_webPageProxy->deviceScaleFactor())); +@@ -182,6 +194,11 @@ void DrawingAreaProxyCoordinatedGraphics::deviceScaleFactorDidChange(CompletionH + sendWithAsyncReply(Messages::DrawingArea::SetDeviceScaleFactor(m_webPageProxy->deviceScaleFactor()), WTFMove(completionHandler)); } -+void DrawingAreaProxyCoordinatedGraphics::waitForSizeUpdate(Function&& callback) ++void DrawingAreaProxyCoordinatedGraphics::waitForSizeUpdate(Function&& callback) +{ + m_callbacks.append(WTFMove(callback)); +} @@ -11883,38 +10965,20 @@ index 3796110b3f6ffb29bc1eae80505017dee9e779d1..1a181f4ac8ce8d15d5e65a9df6afc8fe void DrawingAreaProxyCoordinatedGraphics::setBackingStoreIsDiscardable(bool isBackingStoreDiscardable) { #if !PLATFORM(WPE) -@@ -221,6 +236,45 @@ void DrawingAreaProxyCoordinatedGraphics::updateAcceleratedCompositingMode(uint6 +@@ -243,6 +260,59 @@ void DrawingAreaProxyCoordinatedGraphics::updateAcceleratedCompositingMode(uint6 updateAcceleratedCompositingMode(layerTreeContext); } -+#if PLATFORM(WIN) -+void DrawingAreaProxyCoordinatedGraphics::didChangeAcceleratedCompositingMode(bool enabled) -+{ -+ m_isInAcceleratedCompositingMode = enabled; -+} -+#endif -+ -+#if !PLATFORM(WPE) ++#if PLATFORM(GTK) +void DrawingAreaProxyCoordinatedGraphics::captureFrame() +{ + RefPtr surface; -+#if PLATFORM(WIN) -+ HWndDC dc; -+ if (m_isInAcceleratedCompositingMode) { -+ dc.setHWnd(reinterpret_cast(protectedWebPageProxy()->viewWidget())); -+ surface = adoptRef(cairo_win32_surface_create(dc)); -+#else + if (isInAcceleratedCompositingMode()) { -+# if PLATFORM(GTK) + AcceleratedBackingStore* backingStore = webkitWebViewBaseGetAcceleratedBackingStore(WEBKIT_WEB_VIEW_BASE(protectedWebPageProxy()->viewWidget())); + if (!backingStore) + return; + + surface = backingStore->surface(); -+# else -+ fprintf(stderr, "captureFrame() is not supported in accelerated compositing mode on this platform.\n"); -+# endif -+#endif + } else if (m_backingStore) { + surface = m_backingStore->surface(); + } @@ -11922,27 +10986,60 @@ index 3796110b3f6ffb29bc1eae80505017dee9e779d1..1a181f4ac8ce8d15d5e65a9df6afc8fe + if (!surface) + return; + -+ protectedWebPageProxy()->inspectorController().didPaint(surface.get()); ++ if (cairo_surface_get_type(surface.get()) != CAIRO_SURFACE_TYPE_IMAGE) ++ return; ++ ++ unsigned char* data = cairo_image_surface_get_data(surface.get()); ++ int width = cairo_image_surface_get_width(surface.get()); ++ int height = cairo_image_surface_get_height(surface.get()); ++ int stride = cairo_image_surface_get_stride(surface.get()); ++ ++ SkImageInfo info = SkImageInfo::Make( ++ width, height, ++ kBGRA_8888_SkColorType, // matches CAIRO_FORMAT_ARGB32 on LE ++ kPremul_SkAlphaType ++ ); ++ sk_sp skImage = SkImages::RasterFromData(info, SkData::MakeWithCopy(data, height * stride), stride); ++ if (!skImage) ++ return; ++ ++ protectedWebPageProxy()->inspectorController().didPaint(WTFMove(skImage)); +} -+#endif ++#endif // PLATFORM(GTK) ++ ++#if PLATFORM(WIN) ++void DrawingAreaProxyCoordinatedGraphics::captureFrame() ++{ ++ if (!m_backingStore) ++ return; ++ auto surface = m_backingStore->surface(); ++ if (!surface) ++ return; ++ auto image = surface->makeImageSnapshot(); ++ if (!image) ++ return; ++ protectedWebPageProxy()->inspectorController().didPaint(WTFMove(image)); ++} ++#endif // PLATFORM(WIN) + bool DrawingAreaProxyCoordinatedGraphics::alwaysUseCompositing() const { - return m_webPageProxy->preferences().acceleratedCompositingEnabled() && m_webPageProxy->preferences().forceCompositingMode(); -@@ -275,6 +329,11 @@ void DrawingAreaProxyCoordinatedGraphics::didUpdateGeometry() + if (!m_webPageProxy) +@@ -310,6 +380,12 @@ void DrawingAreaProxyCoordinatedGraphics::didUpdateGeometry() // we need to resend the new size here. if (m_lastSentSize != m_size) sendUpdateGeometry(); + else { -+ for (auto& value : m_callbacks) -+ value(); -+ m_callbacks.clear(); ++ Vector> callbacks; ++ callbacks.swap(m_callbacks); ++ for (auto& cb : callbacks) ++ cb(*this); + } } #if !PLATFORM(WPE) diff --git a/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.h b/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.h -index d2ceeda76e90ab2041f238c240f81bf9e37f6072..faa338a2b4af13663bb63efc940b7efe5544e409 100644 +index 9c2bde0db0e4032a32e6ae02dc45af335df92f7a..3f3a58ee9b0f5c0ddad84f41cf3acd6199d81c37 100644 --- a/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.h +++ b/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.h @@ -29,6 +29,7 @@ @@ -11950,54 +11047,33 @@ index d2ceeda76e90ab2041f238c240f81bf9e37f6072..faa338a2b4af13663bb63efc940b7efe #include "DrawingAreaProxy.h" #include "LayerTreeContext.h" +#include + #include #include - - #if !PLATFORM(WPE) -@@ -52,6 +53,10 @@ public: + #include +@@ -60,6 +61,10 @@ public: bool isInAcceleratedCompositingMode() const { return !m_layerTreeContext.isEmpty(); } const LayerTreeContext& layerTreeContext() const { return m_layerTreeContext; } -+ void waitForSizeUpdate(Function&&); -+#if !PLATFORM(WPE) -+ void captureFrame(); -+#endif - - void dispatchAfterEnsuringDrawing(CompletionHandler&&); - -@@ -75,6 +80,9 @@ private: - void enterAcceleratedCompositingMode(uint64_t backingStoreStateID, const LayerTreeContext&) override; - void exitAcceleratedCompositingMode(uint64_t backingStoreStateID, UpdateInfo&&) override; - void updateAcceleratedCompositingMode(uint64_t backingStoreStateID, const LayerTreeContext&) override; -+#if PLATFORM(WIN) -+ void didChangeAcceleratedCompositingMode(bool enabled) override; ++ void waitForSizeUpdate(Function&&); ++#if !PLATFORM(WPE) ++ void captureFrame(); +#endif - bool shouldSendWheelEventsToEventDispatcher() const override { return true; } + void dispatchAfterEnsuringDrawing(CompletionHandler&&); -@@ -117,6 +125,7 @@ private: +@@ -129,6 +134,7 @@ private: // The last size we sent to the web process. WebCore::IntSize m_lastSentSize; -+ Vector> m_callbacks; ++ Vector> m_callbacks; #if !PLATFORM(WPE) bool m_isBackingStoreDiscardable { true }; -@@ -125,6 +134,10 @@ private: - RunLoop::Timer m_discardBackingStoreTimer; - #endif - std::unique_ptr m_drawingMonitor; -+ -+#if PLATFORM(WIN) -+ bool m_isInAcceleratedCompositingMode { false }; -+#endif - }; - - } // namespace WebKit diff --git a/Source/WebKit/UIProcess/Downloads/DownloadProxy.cpp b/Source/WebKit/UIProcess/Downloads/DownloadProxy.cpp -index 0295a560194b82bf172bfe978c711bb8f280f8e4..e8584dc0133a6a57734c63f6020f3d27dbcd04d7 100644 +index bdc3efe299296ef6ef10d32672e22fba05ca230c..a24e9c7e4b0da65099326b6921ed03b4deb4cc86 100644 --- a/Source/WebKit/UIProcess/Downloads/DownloadProxy.cpp +++ b/Source/WebKit/UIProcess/Downloads/DownloadProxy.cpp -@@ -40,8 +40,10 @@ +@@ -41,8 +41,10 @@ #include #include #include @@ -12008,32 +11084,35 @@ index 0295a560194b82bf172bfe978c711bb8f280f8e4..e8584dc0133a6a57734c63f6020f3d27 #if PLATFORM(MAC) #include -@@ -58,7 +60,10 @@ DownloadProxy::DownloadProxy(DownloadProxyMap& downloadProxyMap, WebsiteDataStor - , m_request(resourceRequest) - , m_originatingPage(originatingPage) - , m_frameInfo(API::FrameInfo::create(FrameInfoData { frameInfoData }, originatingPage)) +@@ -66,7 +68,10 @@ DownloadProxy::DownloadProxy(DownloadProxyMap& downloadProxyMap, WebsiteDataStor + #if HAVE(MODERN_DOWNLOADPROGRESS) + , m_assertion(ProcessAssertion::create(getCurrentProcessID(), "WebKit DownloadProxy DecideDestination"_s, ProcessAssertionType::FinishTaskInterruptable)) + #endif + , m_uuid(createVersion4UUIDString()) { + if (auto* instrumentation = m_dataStore->downloadInstrumentation()) -+ instrumentation->downloadCreated(m_uuid, m_request, frameInfoData, originatingPage, this); ++ instrumentation->downloadCreated(m_uuid, m_request, m_frameInfo->frameInfoData(), originatingPage, this); } DownloadProxy::~DownloadProxy() -@@ -77,9 +82,12 @@ static RefPtr createData(std::span data) - void DownloadProxy::cancel(CompletionHandler&& completionHandler) +@@ -86,12 +91,15 @@ void DownloadProxy::cancel(CompletionHandler&& completionHandl { + m_downloadIsCancelled = true; if (m_dataStore) { -- m_dataStore->networkProcess().sendWithAsyncReply(Messages::NetworkProcess::CancelDownload(m_downloadID), [this, protectedThis = Ref { *this }, completionHandler = WTFMove(completionHandler)] (std::span resumeData) mutable { +- protectedDataStore()->protectedNetworkProcess()->sendWithAsyncReply(Messages::NetworkProcess::CancelDownload(m_downloadID), [weakThis = WeakPtr { *this }, completionHandler = WTFMove(completionHandler)] (std::span resumeData) mutable { + auto* instrumentation = m_dataStore->downloadInstrumentation(); -+ m_dataStore->networkProcess().sendWithAsyncReply(Messages::NetworkProcess::CancelDownload(m_downloadID), [this, protectedThis = Ref { *this }, completionHandler = WTFMove(completionHandler), instrumentation] (std::span resumeData) mutable { - m_legacyResumeData = createData(resumeData); - completionHandler(m_legacyResumeData.get()); ++ protectedDataStore()->protectedNetworkProcess()->sendWithAsyncReply(Messages::NetworkProcess::CancelDownload(m_downloadID), [weakThis = WeakPtr { *this }, completionHandler = WTFMove(completionHandler), instrumentation] (std::span resumeData) mutable { + RefPtr protectedThis = weakThis.get(); + if (!protectedThis) + return completionHandler(nullptr); + protectedThis->m_legacyResumeData = createData(resumeData); + completionHandler(protectedThis->m_legacyResumeData.get()); + if (instrumentation) -+ instrumentation->downloadFinished(m_uuid, "canceled"_s); - m_downloadProxyMap.downloadFinished(*this); ++ instrumentation->downloadFinished(protectedThis->m_uuid, "canceled"_s); + if (RefPtr downloadProxyMap = protectedThis->m_downloadProxyMap.get()) + downloadProxyMap->downloadFinished(*protectedThis); }); - } else -@@ -164,6 +172,21 @@ void DownloadProxy::decideDestinationWithSuggestedFilename(const WebCore::Resour +@@ -163,6 +171,33 @@ void DownloadProxy::decideDestinationWithSuggestedFilename(const WebCore::Resour suggestedFilename = m_suggestedFilename; suggestedFilename = MIMETypeRegistry::appendFileExtensionIfNecessary(suggestedFilename, response.mimeType()); @@ -12048,48 +11127,60 @@ index 0295a560194b82bf172bfe978c711bb8f280f8e4..e8584dc0133a6a57734c63f6020f3d27 + if (auto handle = SandboxExtension::createHandle(destination, SandboxExtension::Type::ReadWrite)) + sandboxExtensionHandle = WTFMove(*handle); + } -+ completionHandler(destination, WTFMove(sandboxExtensionHandle), AllowOverwrite::Yes); ++ m_client->decidePlaceholderPolicy(*this, [completionHandler = WTFMove(completionHandler), destination = WTFMove(destination), sandboxExtensionHandle = WTFMove(sandboxExtensionHandle)] (WebKit::UseDownloadPlaceholder usePlaceholder, const URL& url) mutable { ++ SandboxExtension::Handle placeHolderSandboxExtensionHandle; ++ Vector bookmarkData; ++ Vector activityTokenData; ++#if HAVE(MODERN_DOWNLOADPROGRESS) ++ bookmarkData = bookmarkDataForURL(url); ++ activityTokenData = activityAccessToken(); ++#else ++ if (auto handle = SandboxExtension::createHandle(url.fileSystemPath(), SandboxExtension::Type::ReadWrite)) ++ placeHolderSandboxExtensionHandle = WTFMove(*handle); ++#endif ++ completionHandler(destination, WTFMove(sandboxExtensionHandle), AllowOverwrite::Yes, WebKit::UseDownloadPlaceholder::No, url, WTFMove(placeHolderSandboxExtensionHandle), bookmarkData.span(), activityTokenData.span()); ++ }); + return; + } + - m_client->decideDestinationWithSuggestedFilename(*this, response, ResourceResponseBase::sanitizeSuggestedFilename(suggestedFilename), [this, protectedThis = Ref { *this }, completionHandler = WTFMove(completionHandler)] (AllowOverwrite allowOverwrite, String destination) mutable { + protectedClient()->decideDestinationWithSuggestedFilename(*this, response, ResourceResponseBase::sanitizeSuggestedFilename(suggestedFilename), [this, protectedThis = Ref { *this }, completionHandler = WTFMove(completionHandler)] (AllowOverwrite allowOverwrite, String destination) mutable { SandboxExtension::Handle sandboxExtensionHandle; if (!destination.isNull()) { -@@ -212,6 +235,8 @@ void DownloadProxy::didFinish() - updateQuarantinePropertiesIfPossible(); - #endif - m_client->didFinish(*this); +@@ -227,6 +262,8 @@ void DownloadProxy::didFinish() + protectedClient()->didFinish(*this); + if (m_downloadIsCancelled) + return; + if (auto* instrumentation = m_dataStore->downloadInstrumentation()) + instrumentation->downloadFinished(m_uuid, String()); // This can cause the DownloadProxy object to be deleted. - m_downloadProxyMap.downloadFinished(*this); -@@ -222,6 +247,8 @@ void DownloadProxy::didFail(const ResourceError& error, std::span + if (RefPtr downloadProxyMap = m_downloadProxyMap.get()) +@@ -241,6 +278,8 @@ void DownloadProxy::didFail(const ResourceError& error, std::span m_legacyResumeData = createData(resumeData); - m_client->didFail(*this, error, m_legacyResumeData.get()); + protectedClient()->didFail(*this, error, m_legacyResumeData.get()); + if (auto* instrumentation = m_dataStore->downloadInstrumentation()) + instrumentation->downloadFinished(m_uuid, error.localizedDescription()); // This can cause the DownloadProxy object to be deleted. - m_downloadProxyMap.downloadFinished(*this); + if (RefPtr downloadProxyMap = m_downloadProxyMap.get()) diff --git a/Source/WebKit/UIProcess/Downloads/DownloadProxy.h b/Source/WebKit/UIProcess/Downloads/DownloadProxy.h -index 6f0d076b1b1cb0ec3e1c7fdc5f3a6dfffe9ee63d..656d4259dbf9ab97a8b0408c061c0fd2de8beaa7 100644 +index 9a92a8cde3b5d1da0fbbf5fe7c549cebb8a7f2f7..9ce201ca2d7aa002c7bd389f1fe03edfb306df5d 100644 --- a/Source/WebKit/UIProcess/Downloads/DownloadProxy.h +++ b/Source/WebKit/UIProcess/Downloads/DownloadProxy.h -@@ -143,6 +143,7 @@ private: - #if PLATFORM(COCOA) - RetainPtr m_progress; +@@ -166,6 +166,7 @@ private: + #if HAVE(MODERN_DOWNLOADPROGRESS) + RefPtr m_assertion; #endif + String m_uuid; }; } // namespace WebKit diff --git a/Source/WebKit/UIProcess/DrawingAreaProxy.h b/Source/WebKit/UIProcess/DrawingAreaProxy.h -index 8cfe9bf3d49afd3345209c22c59663f72791fea4..9c13c012e21b33a889eb04a3733712a66470a88e 100644 +index e1f55b4a7fbc452ca1f2eb025b0c88ec9f4b845f..beb3c7a6619b554bb3186a0de917f497ac0f47f8 100644 --- a/Source/WebKit/UIProcess/DrawingAreaProxy.h +++ b/Source/WebKit/UIProcess/DrawingAreaProxy.h -@@ -89,6 +89,7 @@ public: +@@ -94,6 +94,7 @@ public: const WebCore::IntSize& size() const { return m_size; } bool setSize(const WebCore::IntSize&, const WebCore::IntSize& scrollOffset = { }); @@ -12097,323 +11188,12 @@ index 8cfe9bf3d49afd3345209c22c59663f72791fea4..9c13c012e21b33a889eb04a3733712a6 virtual void minimumSizeForAutoLayoutDidChange() { } virtual void sizeToContentAutoSizeMaximumSizeDidChange() { } -@@ -172,6 +173,10 @@ private: - virtual void update(uint64_t /* backingStoreStateID */, UpdateInfo&&) { } - virtual void exitAcceleratedCompositingMode(uint64_t /* backingStoreStateID */, UpdateInfo&&) { } - #endif -+ -+#if PLATFORM(WIN) -+ virtual void didChangeAcceleratedCompositingMode(bool) { } -+#endif - }; - - } // namespace WebKit -diff --git a/Source/WebKit/UIProcess/DrawingAreaProxy.messages.in b/Source/WebKit/UIProcess/DrawingAreaProxy.messages.in -index fc5c53f18ad2dee2c2f40cdbb86ca7f24b262d8d..d93d804d3a8ebaa30856710df544f3db5aa7ad2d 100644 ---- a/Source/WebKit/UIProcess/DrawingAreaProxy.messages.in -+++ b/Source/WebKit/UIProcess/DrawingAreaProxy.messages.in -@@ -30,4 +30,7 @@ messages -> DrawingAreaProxy NotRefCounted { - Update(uint64_t stateID, struct WebKit::UpdateInfo updateInfo) CanDispatchOutOfOrder - ExitAcceleratedCompositingMode(uint64_t backingStoreStateID, struct WebKit::UpdateInfo updateInfo) - #endif -+#if PLATFORM(WIN) -+ DidChangeAcceleratedCompositingMode(bool enabled) -+#endif - } -diff --git a/Source/WebKit/UIProcess/Inspector/Agents/CairoJpegEncoder.cpp b/Source/WebKit/UIProcess/Inspector/Agents/CairoJpegEncoder.cpp -new file mode 100644 -index 0000000000000000000000000000000000000000..f9af359a8b81babaf855132ec168feb22ef5799b ---- /dev/null -+++ b/Source/WebKit/UIProcess/Inspector/Agents/CairoJpegEncoder.cpp -@@ -0,0 +1,246 @@ -+/* Copyright 2018 Bernhard R. Fischer, 4096R/8E24F29D -+ * -+ * This file is part of Cairo_JPG. -+ * -+ * Cairo_JPG 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 3 of the License, or -+ * (at your option) any later version. -+ * -+ * Cairo_JPG 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 General Public License -+ * along with Cairo_JPG. If not, see . -+ */ -+ -+/*! \file cairo_jpg.c -+ * This file contains two functions for reading and writing JPEG files from -+ * and to Cairo image surfaces. It uses the functions from the libjpeg. -+ * Most of the code is directly derived from the online example at -+ * http://libjpeg-turbo.virtualgl.org/Documentation/Documentation -+ * -+ * All prototypes are defined in cairo_jpg.h All functions and their parameters -+ * and return values are described below directly at the functions. You may -+ * also have a look at the preprocessor macros defined below. -+ * -+ * To compile this code you need to have installed the packages libcairo2-dev -+ * and libjpeg-dev. Compile with the following to create an object file to link -+ * with your code: -+ * gcc -std=c99 -Wall -c `pkg-config cairo libjpeg --cflags --libs` cairo_jpg.c -+ * Use the following command to include the main() function and create an -+ * executable for testing of this code: -+ * gcc -std=c99 -Wall -o cairo_jpg -DCAIRO_JPEG_MAIN `pkg-config cairo libjpeg --cflags --libs` cairo_jpg.c -+ * -+ * @author Bernhard R. Fischer, 4096R/8E24F29D bf@abenteuerland.at -+ * @version 2020/01/18 -+ * @license LGPL3. -+ */ -+ -+#include "config.h" -+ -+#if USE(CAIRO) -+ -+#include "CairoJpegEncoder.h" -+ -+#include -+#include -+#include -+#include -+#include -+#include -+extern "C" { -+#include "jpeglib.h" -+} -+ -+/*! Macro to activate main() function. This is only used for testing. Comment -+ * it out (#undef) if you link this file to your own program. -+ */ -+//#define CAIRO_JPEG_MAIN -+// -+/*! Define this to use an alternate implementation of -+ * cairo_image_surface_create_from_jpeg() which fstat(3)s the file before -+ * reading (see below). For huge files this /may/ be slightly faster. -+ */ -+#undef CAIRO_JPEG_USE_FSTAT -+ -+/*! This is the read block size for the stream reader -+ * cairo_image_surface_create_from_jpeg_stream(). -+ */ -+#ifdef USE_CAIRO_READ_FUNC_LEN_T -+#define CAIRO_JPEG_IO_BLOCK_SIZE 4096 -+#else -+/*! Block size has to be one if cairo_read_func_t is in use because of the lack -+ * to detect EOF (truncated reads). -+ */ -+#define CAIRO_JPEG_IO_BLOCK_SIZE 1 -+/*! In case of original cairo_read_func_t is used fstat() should be used for -+ * performance reasons (see CAIRO_JPEG_USE_FSTAT above). -+ */ -+#define CAIRO_JPEG_USE_FSTAT -+#endif -+ -+/*! Define this to test jpeg creation with non-image surfaces. This is only for -+ * testing and is to be used together with CAIRO_JPEG_MAIN. -+ */ -+#undef CAIRO_JPEG_TEST_SIMILAR -+#if defined(CAIRO_JPEG_TEST_SIMILAR) && defined(CAIRO_JPEG_MAIN) -+#include -+#endif -+ -+ -+#ifndef LIBJPEG_TURBO_VERSION -+/*! This function makes a covnersion for "odd" pixel sizes which typically is a -+ * conversion from a 3-byte to a 4-byte (or more) pixel size or vice versa. -+ * The conversion is done from the source buffer src to the destination buffer -+ * dst. The caller MUST ensure that src and dst have the correct memory size. -+ * This is dw * num for dst and sw * num for src. src and dst may point to the -+ * same memory address. -+ * @param dst Pointer to destination buffer. -+ * @param dw Pixel width (in bytes) of pixels in destination buffer, dw >= 3. -+ * @param src Pointer to source buffer. -+ * @param sw Pixel width (in bytes) of pixels in source buffer, sw >= 3. -+ * @param num Number of pixels to convert, num >= 1; -+ */ -+static void pix_conv(unsigned char *dst, int dw, const unsigned char *src, int sw, int num) -+{ -+ int si, di; -+ -+ // safety check -+ if (dw < 3 || sw < 3 || dst == NULL || src == NULL) -+ return; -+ -+ num--; -+ for (si = num * sw, di = num * dw; si >= 0; si -= sw, di -= dw) -+ { -+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -+ dst[di + 2] = src[si ]; -+ dst[di + 1] = src[si + 1]; -+ dst[di + 0] = src[si + 2]; -+#else -+ // FIXME: This is untested, it may be wrong. -+ dst[di - 3] = src[si - 3]; -+ dst[di - 2] = src[si - 2]; -+ dst[di - 1] = src[si - 1]; -+#endif -+ } -+} -+#endif -+ -+ -+/*! This function creates a JPEG file in memory from a Cairo image surface. -+ * @param sfc Pointer to a Cairo surface. It should be an image surface of -+ * either CAIRO_FORMAT_ARGB32 or CAIRO_FORMAT_RGB24. Other formats are -+ * converted to CAIRO_FORMAT_RGB24 before compression. -+ * Please note that this may give unexpected results because JPEG does not -+ * support transparency. Thus, default background color is used to replace -+ * transparent regions. The default background color is black if not specified -+ * explicitly. Thus converting e.g. PDF surfaces without having any specific -+ * background color set will apear with black background and not white as you -+ * might expect. In such cases it is suggested to manually convert the surface -+ * to RGB24 before calling this function. -+ * @param data Pointer to a memory pointer. This parameter receives a pointer -+ * to the memory area where the final JPEG data is found in memory. This -+ * function reserves the memory properly and it has to be freed by the caller -+ * with free(3). -+ * @param len Pointer to a variable of type size_t which will receive the final -+ * lenght of the memory buffer. -+ * @param quality Compression quality, 0-100. -+ * @return On success the function returns CAIRO_STATUS_SUCCESS. In case of -+ * error CAIRO_STATUS_INVALID_FORMAT is returned. -+ */ -+cairo_status_t cairo_image_surface_write_to_jpeg_mem(cairo_surface_t *sfc, unsigned char **data, size_t *len, int quality) -+{ -+ struct jpeg_compress_struct cinfo; -+ struct jpeg_error_mgr jerr; -+ JSAMPROW row_pointer[1]; -+ cairo_surface_t *other = NULL; -+ -+ // check valid input format (must be IMAGE_SURFACE && (ARGB32 || RGB24)) -+ if (cairo_surface_get_type(sfc) != CAIRO_SURFACE_TYPE_IMAGE || -+ (cairo_image_surface_get_format(sfc) != CAIRO_FORMAT_ARGB32 && -+ cairo_image_surface_get_format(sfc) != CAIRO_FORMAT_RGB24)) -+ { -+ // create a similar surface with a proper format if supplied input format -+ // does not fulfill the requirements -+ double x1, y1, x2, y2; -+ other = sfc; -+ cairo_t *ctx = cairo_create(other); -+ // get extents of original surface -+ cairo_clip_extents(ctx, &x1, &y1, &x2, &y2); -+ cairo_destroy(ctx); -+ -+ // create new image surface -+ sfc = cairo_surface_create_similar_image(other, CAIRO_FORMAT_RGB24, x2 - x1, y2 - y1); -+ if (cairo_surface_status(sfc) != CAIRO_STATUS_SUCCESS) -+ return CAIRO_STATUS_INVALID_FORMAT; -+ -+ // paint original surface to new surface -+ ctx = cairo_create(sfc); -+ cairo_set_source_surface(ctx, other, 0, 0); -+ cairo_paint(ctx); -+ cairo_destroy(ctx); -+ } -+ -+ // finish queued drawing operations -+ cairo_surface_flush(sfc); -+ -+ // init jpeg compression structures -+ cinfo.err = jpeg_std_error(&jerr); -+ jpeg_create_compress(&cinfo); -+ -+ // set compression parameters -+ unsigned long targetSize; -+ jpeg_mem_dest(&cinfo, data, &targetSize); -+ -+ cinfo.image_width = cairo_image_surface_get_width(sfc); -+ cinfo.image_height = cairo_image_surface_get_height(sfc); -+#ifdef LIBJPEG_TURBO_VERSION -+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -+ //cinfo.in_color_space = JCS_EXT_BGRX; -+ cinfo.in_color_space = cairo_image_surface_get_format(sfc) == CAIRO_FORMAT_ARGB32 ? JCS_EXT_BGRA : JCS_EXT_BGRX; -+#else -+ //cinfo.in_color_space = JCS_EXT_XRGB; -+ cinfo.in_color_space = cairo_image_surface_get_format(sfc) == CAIRO_FORMAT_ARGB32 ? JCS_EXT_ARGB : JCS_EXT_XRGB; -+#endif -+ cinfo.input_components = 4; -+#else -+ cinfo.in_color_space = JCS_RGB; -+ cinfo.input_components = 3; -+#endif -+ jpeg_set_defaults(&cinfo); -+ jpeg_set_quality(&cinfo, quality, TRUE); -+ -+ // start compressor -+ jpeg_start_compress(&cinfo, TRUE); -+ -+ // loop over all lines and compress -+ while (cinfo.next_scanline < cinfo.image_height) -+ { -+#ifdef LIBJPEG_TURBO_VERSION -+ row_pointer[0] = cairo_image_surface_get_data(sfc) + (cinfo.next_scanline -+ * cairo_image_surface_get_stride(sfc)); -+#else -+ unsigned char row_buf[3 * cinfo.image_width]; -+ pix_conv(row_buf, 3, cairo_image_surface_get_data(sfc) + -+ (cinfo.next_scanline * cairo_image_surface_get_stride(sfc)), 4, cinfo.image_width); -+ row_pointer[0] = row_buf; -+#endif -+ (void) jpeg_write_scanlines(&cinfo, row_pointer, 1); -+ } -+ -+ // finalize and close everything -+ jpeg_finish_compress(&cinfo); -+ jpeg_destroy_compress(&cinfo); -+ -+ // destroy temporary image surface (if available) -+ if (other != NULL) -+ cairo_surface_destroy(sfc); -+ -+ *len = targetSize; -+ return CAIRO_STATUS_SUCCESS; -+} -+ -+#endif -diff --git a/Source/WebKit/UIProcess/Inspector/Agents/CairoJpegEncoder.h b/Source/WebKit/UIProcess/Inspector/Agents/CairoJpegEncoder.h -new file mode 100644 -index 0000000000000000000000000000000000000000..4ec8b96bbbddf8a7b042f53a8068754a384fc7ad ---- /dev/null -+++ b/Source/WebKit/UIProcess/Inspector/Agents/CairoJpegEncoder.h -@@ -0,0 +1,30 @@ -+/* -+ * Copyright (C) Microsoft. All rights reserved. -+ * -+ * 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 APPLE INC. AND ITS 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 APPLE INC. OR ITS 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. -+ */ -+ -+#pragma once -+ -+#include -+ -+cairo_status_t cairo_image_surface_write_to_jpeg_mem(cairo_surface_t *sfc, unsigned char **data, size_t *len, int quality); diff --git a/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.cpp b/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.cpp new file mode 100644 -index 0000000000000000000000000000000000000000..91cf94cd292350afb3e3ed071ca44760acda1c14 +index 0000000000000000000000000000000000000000..0615d7de9494901c53131b45018ee48612e7cfca --- /dev/null +++ b/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.cpp -@@ -0,0 +1,305 @@ +@@ -0,0 +1,326 @@ +/* + * Copyright (C) 2020 Microsoft Corporation. + * @@ -12450,20 +11230,29 @@ index 0000000000000000000000000000000000000000..91cf94cd292350afb3e3ed071ca44760 +#include +#include +#include ++#include +#include +#include +#include + -+#if USE(CAIRO) -+#include "CairoJpegEncoder.h" ++#if USE(SKIA) +#include "DrawingAreaProxyCoordinatedGraphics.h" +#include "DrawingAreaProxy.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include +#endif + +#if PLATFORM(MAC) +#include +#endif + ++WTF_ALLOW_UNSAFE_BUFFER_USAGE_BEGIN ++ +namespace WebKit { + +const int kMaxFramesInFlight = 1; @@ -12500,33 +11289,36 @@ index 0000000000000000000000000000000000000000..91cf94cd292350afb3e3ed071ca44760 + m_encoder = nullptr; +} + -+#if USE(CAIRO) -+void InspectorScreencastAgent::didPaint(cairo_surface_t* surface) ++#if USE(SKIA) ++void InspectorScreencastAgent::didPaint(sk_sp&& surface) +{ -+#if PLATFORM(WPE) ++ sk_sp image(surface); ++#if PLATFORM(WPE) || PLATFORM(WIN) + // Get actual image size (in device pixels). -+ WebCore::IntSize displaySize(cairo_image_surface_get_width(surface), cairo_image_surface_get_height(surface)); ++ WebCore::IntSize displaySize(image->width(), image->height()); + + WebCore::IntSize drawingAreaSize = m_page.drawingArea()->size(); + drawingAreaSize.scale(m_page.deviceScaleFactor()); + if (drawingAreaSize != displaySize) { + return; + } -+ +#else + WebCore::IntSize displaySize = m_page.drawingArea()->size(); +#endif ++ // Do not WTFMove image here as it is used below + if (m_encoder) -+ m_encoder->encodeFrame(surface, displaySize); ++ m_encoder->encodeFrame(sk_sp(image), displaySize); + if (m_screencast) { -+ + { ++ SkPixmap pixmap; ++ if (!image->peekPixels(&pixmap)) { ++ fprintf(stderr, "Failed to peek pixels from SkImage to compute hash\n"); ++ return; ++ } + // Do not send the same frame over and over. -+ unsigned char *data = cairo_image_surface_get_data(surface); -+ int stride = cairo_image_surface_get_stride(surface); -+ int height = cairo_image_surface_get_height(surface); ++ size_t len = pixmap.computeByteSize(); + auto cryptoDigest = PAL::CryptoDigest::create(PAL::CryptoDigest::Algorithm::SHA_1); -+ cryptoDigest->addBytes(std::span(data, stride * height)); ++ cryptoDigest->addBytes(std::span(reinterpret_cast(pixmap.addr()), len)); + auto digest = cryptoDigest->computeHash(); + if (m_lastFrameDigest == digest) + return; @@ -12537,23 +11329,30 @@ index 0000000000000000000000000000000000000000..91cf94cd292350afb3e3ed071ca44760 + return; + // Scale image to fit width / height + double scale = std::min(m_screencastWidth / displaySize.width(), m_screencastHeight / displaySize.height()); -+ RefPtr scaledSurface; + if (scale < 1) { -+ WebCore::IntSize scaledSize = displaySize; -+ scaledSize.scale(scale); -+ cairo_matrix_t transform; -+ cairo_matrix_init_scale(&transform, scale, scale); -+ scaledSurface = adoptRef(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, scaledSize.width(), scaledSize.height())); -+ RefPtr cr = adoptRef(cairo_create(scaledSurface.get())); -+ cairo_transform(cr.get(), &transform); -+ cairo_set_source_surface(cr.get(), surface, 0, 0); -+ cairo_paint(cr.get()); -+ surface = scaledSurface.get(); ++ SkBitmap dstBitmap; ++ dstBitmap.allocPixels(SkImageInfo::MakeN32Premul(displaySize.width() * scale, displaySize.height() * scale)); ++ SkCanvas canvas(dstBitmap); ++ canvas.scale(scale, scale); ++ canvas.drawImage(image, 0, 0); ++ image = dstBitmap.asImage(); ++ } ++ ++ SkPixmap pixmap; ++ if (!image->peekPixels(&pixmap)) { ++ fprintf(stderr, "Failed to peek pixels from SkImage for JPEG encoding\n"); ++ return; ++ } ++ ++ SkJpegEncoder::Options options; ++ options.fQuality = 90; ++ SkDynamicMemoryWStream stream; ++ if (!SkJpegEncoder::Encode(&stream, pixmap, options)) { ++ fprintf(stderr, "Failed to encode image to JPEG\n"); ++ return; + } -+ unsigned char *data = nullptr; -+ size_t len = 0; -+ cairo_image_surface_write_to_jpeg_mem(surface, &data, &len, m_screencastQuality); -+ String result = base64EncodeToString(data, len); ++ sk_sp jpegData = stream.detachAsData(); ++ String result = base64EncodeToString(std::span(reinterpret_cast(jpegData->data()), jpegData->size())); + ++m_screencastFramesInFlight; + m_frontendDispatcher->screencastFrame(result, displaySize.width(), displaySize.height()); + } @@ -12642,7 +11441,7 @@ index 0000000000000000000000000000000000000000..91cf94cd292350afb3e3ed071ca44760 + scheduleFrameEncoding(); +#endif + } -+ m_page.forceRepaint([] { }); ++ m_page.updateRenderingWithForcedRepaint([] { }); +} + +#if !PLATFORM(WPE) @@ -12668,7 +11467,7 @@ index 0000000000000000000000000000000000000000..91cf94cd292350afb3e3ed071ca44760 +{ + if (!m_encoder && !m_screencast) + return; -+ RetainPtr imageRef = m_page.pageClient().takeSnapshotForAutomation(); ++ RetainPtr imageRef = m_page.pageClient()->takeSnapshotForAutomation(); + if (m_screencast && m_screencastFramesInFlight <= kMaxFramesInFlight) { + CGImage* imagePtr = imageRef.get(); + WebCore::IntSize imageSize(CGImageGetWidth(imagePtr), CGImageGetHeight(imagePtr)); @@ -12707,7 +11506,7 @@ index 0000000000000000000000000000000000000000..91cf94cd292350afb3e3ed071ca44760 +} +#endif + -+#if USE(CAIRO) && !PLATFORM(WPE) ++#if PLATFORM(GTK) || PLATFORM(WIN) +void InspectorScreencastAgent::encodeFrame() +{ + if (!m_encoder && !m_screencast) @@ -12719,12 +11518,14 @@ index 0000000000000000000000000000000000000000..91cf94cd292350afb3e3ed071ca44760 +#endif + +} // namespace WebKit ++ ++WTF_ALLOW_UNSAFE_BUFFER_USAGE_END diff --git a/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.h b/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.h new file mode 100644 -index 0000000000000000000000000000000000000000..d28dde452275f18739e3b1c8d709185c9bf0f40e +index 0000000000000000000000000000000000000000..6e031f61b132176587643bc79b23202009c4aca4 --- /dev/null +++ b/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.h -@@ -0,0 +1,97 @@ +@@ -0,0 +1,102 @@ +/* + * Copyright (C) 2020 Microsoft Corporation. + * @@ -12756,10 +11557,6 @@ index 0000000000000000000000000000000000000000..d28dde452275f18739e3b1c8d709185c +#include +#include + -+#if USE(CAIRO) -+#include -+#endif -+ +#include +#include +#include @@ -12772,6 +11569,15 @@ index 0000000000000000000000000000000000000000..d28dde452275f18739e3b1c8d709185c +} + +namespace WebKit { ++class InspectorScreencastAgent; ++} ++ ++namespace WTF { ++template struct IsDeprecatedWeakRefSmartPointerException; ++template<> struct IsDeprecatedWeakRefSmartPointerException : std::true_type { }; ++} ++ ++namespace WebKit { + +class ScreencastEncoder; +class WebPageProxy; @@ -12786,8 +11592,8 @@ index 0000000000000000000000000000000000000000..d28dde452275f18739e3b1c8d709185c + void didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*) override; + void willDestroyFrontendAndBackend(Inspector::DisconnectReason) override; + -+#if USE(CAIRO) -+ void didPaint(cairo_surface_t*); ++#if USE(SKIA) ++ void didPaint(sk_sp&& surface); +#endif + + Inspector::Protocol::ErrorStringOr startVideo(const String& file, int width, int height, int toolbarHeight) override; @@ -12824,10 +11630,10 @@ index 0000000000000000000000000000000000000000..d28dde452275f18739e3b1c8d709185c +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.cpp b/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.cpp new file mode 100644 -index 0000000000000000000000000000000000000000..90080e92c8278e73355c1fd4c571ea12f0bca9c5 +index 0000000000000000000000000000000000000000..203cedeea9cbec6964fd297884e03ef791632fe5 --- /dev/null +++ b/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.cpp -@@ -0,0 +1,391 @@ +@@ -0,0 +1,398 @@ +/* + * Copyright (c) 2010, The WebM Project authors. All rights reserved. + * Copyright (c) 2013 The Chromium Authors. All rights reserved. @@ -12864,15 +11670,22 @@ index 0000000000000000000000000000000000000000..90080e92c8278e73355c1fd4c571ea12 +#include +#include +#include ++#include +#include +#include +#include ++#include +#include + -+#if USE(CAIRO) -+#include ++#if USE(SKIA) ++#include ++#include ++#include ++#include +#endif + ++WTF_ALLOW_UNSAFE_BUFFER_USAGE_BEGIN ++ +using namespace WebCore; + +namespace WebKit { @@ -12957,8 +11770,8 @@ index 0000000000000000000000000000000000000000..90080e92c8278e73355c1fd4c571ea12 + WTF_MAKE_NONCOPYABLE(VPXFrame); + WTF_MAKE_FAST_ALLOCATED; +public: -+#if USE(CAIRO) -+ explicit VPXFrame(RefPtr&& surface) ++#if USE(SKIA) ++ explicit VPXFrame(sk_sp&& surface) + : m_surface(WTFMove(surface)) + { } +#elif PLATFORM(MAC) @@ -12973,10 +11786,15 @@ index 0000000000000000000000000000000000000000..90080e92c8278e73355c1fd4c571ea12 + + void convertToVpxImage(vpx_image_t* image) + { -+#if USE(CAIRO) ++#if USE(SKIA) + // Convert the updated region to YUV ready for encoding. -+ const uint8_t* argb_data = cairo_image_surface_get_data(m_surface.get()); -+ int argb_stride = cairo_image_surface_get_stride(m_surface.get()); ++ SkImageInfo info = SkImageInfo::Make(m_surface->width(), m_surface->height(), kN32_SkColorType, kPremul_SkAlphaType); ++ int argb_stride = info.minRowBytes(); ++ size_t bufferSize = info.computeByteSize(argb_stride); ++ UniqueArray buffer = makeUniqueArray(bufferSize); ++ uint8_t* argb_data = buffer.get(); ++ if (!m_surface->readPixels(info, argb_data, argb_stride, 0, 0)) ++ fprintf(stderr, "Read SkImage to ARGB buffer\n"); +#elif PLATFORM(MAC) + int argb_stride = image->w * 4; + UniqueArray buffer = makeUniqueArray(argb_stride * image->h); @@ -12999,8 +11817,8 @@ index 0000000000000000000000000000000000000000..90080e92c8278e73355c1fd4c571ea12 + } + +private: -+#if USE(CAIRO) -+ RefPtr m_surface; ++#if USE(SKIA) ++ sk_sp m_surface; +#elif PLATFORM(MAC) + RetainPtr m_windowImage; + int m_offsetTop { 0 }; @@ -13121,7 +11939,7 @@ index 0000000000000000000000000000000000000000..90080e92c8278e73355c1fd4c571ea12 + memset(&cfg, 0, sizeof(cfg)); + vpx_codec_err_t error = vpx_codec_enc_config_default(codec_interface, &cfg, 0); + if (error) { -+ errorString = makeString("Failed to get default codec config: "_s, vpx_codec_err_to_string(error)); ++ errorString = makeString("Failed to get default codec config: "_s, unsafeSpan(vpx_codec_err_to_string(error))); + return nullptr; + } + @@ -13133,13 +11951,13 @@ index 0000000000000000000000000000000000000000..90080e92c8278e73355c1fd4c571ea12 + + ScopedVpxCodec codec(new vpx_codec_ctx_t); + if (vpx_codec_enc_init(codec.get(), codec_interface, &cfg, 0)) { -+ errorString = makeString("Failed to initialize encoder: "_s, vpx_codec_error(codec.get())); ++ errorString = makeString("Failed to initialize encoder: "_s, unsafeSpan(vpx_codec_error(codec.get()))); + return nullptr; + } + + FILE* file = fopen(filePath.utf8().data(), "wb"); + if (!file) { -+ errorString = makeString("Failed to open file '", filePath, "' for writing: ", strerror(errno)); ++ errorString = makeString("Failed to open file '"_s, filePath, "' for writing: "_s, unsafeSpan(strerror(errno))); + return nullptr; + } + @@ -13162,8 +11980,8 @@ index 0000000000000000000000000000000000000000..90080e92c8278e73355c1fd4c571ea12 + m_lastFrameTimestamp = now; +} + -+#if USE(CAIRO) -+void ScreencastEncoder::encodeFrame(cairo_surface_t* drawingAreaSurface, IntSize size) ++#if USE(SKIA) ++void ScreencastEncoder::encodeFrame(sk_sp&& image, IntSize size) +{ + flushLastFrame(); + // Note that in WPE drawing area size is updated asynchronously and may differ from acutal @@ -13171,27 +11989,20 @@ index 0000000000000000000000000000000000000000..90080e92c8278e73355c1fd4c571ea12 + if (size.isZero()) { + return; + } -+ -+ RefPtr surface = adoptRef(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, m_size.width(), m_size.height())); -+ { -+ RefPtr cr = adoptRef(cairo_create(surface.get())); -+ -+ cairo_matrix_t transform; -+ if (size.width() > m_size.width() || size.height() > m_size.height()) { -+ // If no scale is specified shrink to fit the frame. -+ double scale = std::min(static_cast(m_size.width()) / size.width(), -+ static_cast(m_size.height()) / size.height()); -+ cairo_matrix_init_scale(&transform, scale, scale); -+ cairo_transform(cr.get(), &transform); -+ } -+ -+ // Record top left part of the drawing area that fits into the frame. -+ cairo_set_source_surface(cr.get(), drawingAreaSurface, 0, 0); -+ cairo_paint(cr.get()); ++ SkBitmap surface; ++ surface.allocPixels(SkImageInfo::Make(m_size.width(), m_size.height(), kBGRA_8888_SkColorType, kPremul_SkAlphaType)); ++ SkCanvas canvas(surface); ++ SkMatrix transform; ++ if (size.width() > m_size.width() || size.height() > m_size.height()) { ++ // If no scale is specified shrink to fit the frame. ++ double scale = std::min(static_cast(m_size.width()) / size.width(), ++ static_cast(m_size.height()) / size.height()); ++ transform.setScale(scale, scale); ++ canvas.setMatrix(transform); + } -+ cairo_surface_flush(surface.get()); -+ -+ m_lastFrame = makeUnique(WTFMove(surface)); ++ // Record top left part of the drawing area that fits into the frame. ++ canvas.drawImage(image, 0, 0); ++ m_lastFrame = makeUnique(surface.asImage()); +} +#elif PLATFORM(MAC) +void ScreencastEncoder::encodeFrame(RetainPtr&& windowImage) @@ -13219,9 +12030,11 @@ index 0000000000000000000000000000000000000000..90080e92c8278e73355c1fd4c571ea12 + + +} // namespace WebKit ++ ++WTF_ALLOW_UNSAFE_BUFFER_USAGE_END diff --git a/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.h b/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.h new file mode 100644 -index 0000000000000000000000000000000000000000..36df6131950ca95f74dc191628376fc589dbcb33 +index 0000000000000000000000000000000000000000..433af017b68b71cfb68c3ebcc0bd2aeb9efc40f7 --- /dev/null +++ b/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.h @@ -0,0 +1,80 @@ @@ -13259,8 +12072,8 @@ index 0000000000000000000000000000000000000000..36df6131950ca95f74dc191628376fc5 +#include +#include + -+#if USE(CAIRO) -+#include ++#if USE(SKIA) ++#include +#endif + +namespace WebKit { @@ -13279,8 +12092,8 @@ index 0000000000000000000000000000000000000000..36df6131950ca95f74dc191628376fc5 + ScreencastEncoder(std::unique_ptr&&, WebCore::IntSize); + ~ScreencastEncoder(); + -+#if USE(CAIRO) -+ void encodeFrame(cairo_surface_t*, WebCore::IntSize); ++#if USE(SKIA) ++ void encodeFrame(sk_sp&&, WebCore::IntSize); +#elif PLATFORM(MAC) + void encodeFrame(RetainPtr&&); + void setOffsetTop(int offset) { m_offsetTop = offset;} @@ -13440,10 +12253,10 @@ index 0000000000000000000000000000000000000000..e2ce910f3fd7f587add552275b7e7176 + +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.cpp b/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.cpp -index fedef553cec70feb6c6475a5f752fbc6833dbb38..16e73d6a724dd80487b7b140aaaccfec253eb7aa 100644 +index 76cc869ca4d5fc311040a285d50a44f00273fd63..633f8323697f0c2f30311a35ac3876bf8e03b741 100644 --- a/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.cpp +++ b/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.cpp -@@ -28,11 +28,10 @@ +@@ -28,7 +28,7 @@ #include "MessageSenderInlines.h" #include "ProvisionalPageProxy.h" @@ -13452,43 +12265,30 @@ index fedef553cec70feb6c6475a5f752fbc6833dbb38..16e73d6a724dd80487b7b140aaaccfec #include "WebPageInspectorTarget.h" #include "WebPageMessages.h" #include "WebPageProxy.h" --#include "WebProcessProxy.h" - - namespace WebKit { - -@@ -40,19 +39,17 @@ using namespace Inspector; - - std::unique_ptr InspectorTargetProxy::create(WebPageProxy& page, const String& targetId, Inspector::InspectorTargetType type) - { -- return makeUnique(page, targetId, type); -+ return makeUnique(page, nullptr, targetId, type); +@@ -46,13 +46,13 @@ std::unique_ptr InspectorTargetProxy::create(WebPageProxy& + return makeUnique(page, targetId, type); } -std::unique_ptr InspectorTargetProxy::create(ProvisionalPageProxy& provisionalPage, const String& targetId, Inspector::InspectorTargetType type) +std::unique_ptr InspectorTargetProxy::create(ProvisionalPageProxy& provisionalPage, const String& targetId) { -- Ref page = provisionalPage.page(); -- auto target = InspectorTargetProxy::create(page, targetId, type); -- target->m_provisionalPage = provisionalPage; -- return target; -+ return makeUnique(provisionalPage.page(), &provisionalPage, targetId, Inspector::InspectorTargetType::Page); - } - --InspectorTargetProxy::InspectorTargetProxy(WebPageProxy& page, const String& targetId, Inspector::InspectorTargetType type) -+InspectorTargetProxy::InspectorTargetProxy(WebPageProxy& page, ProvisionalPageProxy* provisionalPage, const String& targetId, Inspector::InspectorTargetType type) - : m_page(page) -+ , m_provisionalPage(provisionalPage) - , m_identifier(targetId) - , m_type(type) - { -@@ -99,6 +96,31 @@ void InspectorTargetProxy::didCommitProvisionalTarget() + RefPtr page = provisionalPage.page(); + if (!page) + return nullptr; + +- auto target = InspectorTargetProxy::create(*page, targetId, type); ++ auto target = InspectorTargetProxy::create(*page, targetId, Inspector::InspectorTargetType::Page); + target->m_provisionalPage = provisionalPage; + return target; + } +@@ -108,6 +108,31 @@ void InspectorTargetProxy::didCommitProvisionalTarget() m_provisionalPage = nullptr; } +void InspectorTargetProxy::willResume() +{ -+ if (m_page.hasRunningProcess()) -+ m_page.send(Messages::WebPage::ResumeInspectorIfPausedInNewWindow()); ++ if (m_page->hasRunningProcess()) ++ m_page->legacyMainFrameProcess().send(Messages::WebPage::ResumeInspectorIfPausedInNewWindow(), m_page->webPageIDInMainFrameProcess()); +} + +void InspectorTargetProxy::activate(String& error) @@ -13505,36 +12305,34 @@ index fedef553cec70feb6c6475a5f752fbc6833dbb38..16e73d6a724dd80487b7b140aaaccfec + return InspectorTarget::close(error, runBeforeUnload); + + if (runBeforeUnload) -+ m_page.tryClose(); ++ m_page->tryClose(); + else -+ m_page.closePage(); ++ m_page->closePage(); +} + bool InspectorTargetProxy::isProvisional() const { return !!m_provisionalPage; diff --git a/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.h b/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.h -index a2239cec8e18850f35f7f88a9c4ebadc62bf4023..79f3ff84327dc075ec96983e04db4b10343b7fae 100644 +index edd6e7f1799279ed3d0eb81b6c2eef9f5b375134..d4231f84f3c52641f4d9e88559e8e1a4845b7163 100644 --- a/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.h +++ b/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.h -@@ -37,13 +37,13 @@ class WebPageProxy; +@@ -38,12 +38,12 @@ class WebPageProxy; // NOTE: This UIProcess side InspectorTarget doesn't care about the frontend channel, since // any target -> frontend messages will be routed to the WebPageProxy with a targetId. -class InspectorTargetProxy final : public Inspector::InspectorTarget { +class InspectorTargetProxy : public Inspector::InspectorTarget { - WTF_MAKE_FAST_ALLOCATED; + WTF_MAKE_TZONE_ALLOCATED(InspectorTargetProxy); WTF_MAKE_NONCOPYABLE(InspectorTargetProxy); public: static std::unique_ptr create(WebPageProxy&, const String& targetId, Inspector::InspectorTargetType); - static std::unique_ptr create(ProvisionalPageProxy&, const String& targetId, Inspector::InspectorTargetType); -- InspectorTargetProxy(WebPageProxy&, const String& targetId, Inspector::InspectorTargetType); + static std::unique_ptr create(ProvisionalPageProxy&, const String& targetId); -+ InspectorTargetProxy(WebPageProxy&, ProvisionalPageProxy*, const String& targetId, Inspector::InspectorTargetType); + InspectorTargetProxy(WebPageProxy&, const String& targetId, Inspector::InspectorTargetType); ~InspectorTargetProxy() = default; - Inspector::InspectorTargetType type() const final { return m_type; } -@@ -55,12 +55,17 @@ public: +@@ -56,8 +56,13 @@ public: void connect(Inspector::FrontendChannel::ConnectionType) override; void disconnect() override; void sendMessageToTargetBackend(const String&) override; @@ -13545,23 +12343,19 @@ index a2239cec8e18850f35f7f88a9c4ebadc62bf4023..79f3ff84327dc075ec96983e04db4b10 + void willResume() override; + void platformActivate(String& error) const; + - WebPageProxy& m_page; -+ WeakPtr m_provisionalPage; + WeakRef m_page; String m_identifier; Inspector::InspectorTargetType m_type; -- WeakPtr m_provisionalPage; - }; - - } // namespace WebKit diff --git a/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.cpp b/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.cpp -index 6d229b943fe69cd258b32b1e38c5716715a4cd4b..7294731b4ff75a0cec1dd010cc7facaf140b6a8a 100644 +index 45eb87344ce4249eea90dc0a73a2c717f69f55fa..c070e869819c36e60a5c64bf4c762a50915d8a5e 100644 --- a/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.cpp +++ b/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.cpp -@@ -26,13 +26,21 @@ +@@ -26,13 +26,23 @@ #include "config.h" #include "WebPageInspectorController.h" +#include "APINavigation.h" ++#include "APIPageConfiguration.h" #include "APIUIClient.h" #include "InspectorBrowserAgent.h" +#include "InspectorDialogAgent.h" @@ -13575,13 +12369,14 @@ index 6d229b943fe69cd258b32b1e38c5716715a4cd4b..7294731b4ff75a0cec1dd010cc7facaf #include "WebPageProxy.h" +#include "WebPreferences.h" +#include ++#include +#include #include #include #include -@@ -49,32 +57,119 @@ static String getTargetID(const ProvisionalPageProxy& provisionalPage) - return WebPageInspectorTarget::toTargetID(provisionalPage.webPageID()); - } +@@ -52,34 +62,115 @@ static String getTargetID(const ProvisionalPageProxy& provisionalPage) + + WTF_MAKE_TZONE_ALLOCATED_IMPL(WebPageInspectorController); +WebPageInspectorControllerObserver* WebPageInspectorController::s_observer = nullptr; + @@ -13604,6 +12399,8 @@ index 6d229b943fe69cd258b32b1e38c5716715a4cd4b..7294731b4ff75a0cec1dd010cc7facaf - m_agents.append(WTFMove(targetAgent)); } + WebPageInspectorController::~WebPageInspectorController() = default; + -Ref WebPageInspectorController::protectedInspectedPage() +WeakRef WebPageInspectorController::protectedInspectedPage() { @@ -13613,6 +12410,8 @@ index 6d229b943fe69cd258b32b1e38c5716715a4cd4b..7294731b4ff75a0cec1dd010cc7facaf void WebPageInspectorController::init() { +- String pageTargetId = WebPageInspectorTarget::toTargetID(m_inspectedPage->webPageIDInMainFrameProcess()); +- createInspectorTarget(pageTargetId, Inspector::InspectorTargetType::Page); + auto targetAgent = makeUnique(m_frontendRouter.get(), m_backendDispatcher.get()); + m_targetAgent = targetAgent.get(); + m_agents.append(WTFMove(targetAgent)); @@ -13628,27 +12427,21 @@ index 6d229b943fe69cd258b32b1e38c5716715a4cd4b..7294731b4ff75a0cec1dd010cc7facaf + m_agents.append(WTFMove(screencastAgent)); + if (s_observer) + s_observer->didCreateInspectorController(m_inspectedPage); ++} + -+ // window.open will create page with already running process. -+ if (!m_inspectedPage->hasRunningProcess()) -+ return; - String pageTargetId = WebPageInspectorTarget::toTargetID(m_inspectedPage->webPageID()); - createInspectorTarget(pageTargetId, Inspector::InspectorTargetType::Page); - } - -+void WebPageInspectorController::didFinishAttachingToWebProcess() ++void WebPageInspectorController::didInitializeWebPage() +{ -+ String pageTargetID = WebPageInspectorTarget::toTargetID(m_inspectedPage->webPageID()); ++ String pageTargetID = WebPageInspectorTarget::toTargetID(m_inspectedPage->webPageIDInMainFrameProcess()); + // Create target only after attaching to a Web Process first time. Before that + // we cannot event establish frontend connection. + if (m_targets.contains(pageTargetID)) + return; + createInspectorTarget(pageTargetID, Inspector::InspectorTargetType::Page); -+} -+ + } + void WebPageInspectorController::pageClosed() { -+ String pageTargetId = WebPageInspectorTarget::toTargetID(m_inspectedPage->webPageID()); ++ String pageTargetId = WebPageInspectorTarget::toTargetID(m_inspectedPage->webPageIDInMainFrameProcess()); + destroyInspectorTarget(pageTargetId); + disconnectAllFrontends(); @@ -13663,7 +12456,7 @@ index 6d229b943fe69cd258b32b1e38c5716715a4cd4b..7294731b4ff75a0cec1dd010cc7facaf +{ + if (reason != ProcessTerminationReason::Crash) + return false; -+ String targetId = WebPageInspectorTarget::toTargetID(m_inspectedPage->webPageID()); ++ String targetId = WebPageInspectorTarget::toTargetID(m_inspectedPage->webPageIDInMainFrameProcess()); + auto it = m_targets.find(targetId); + if (it == m_targets.end()) + return false; @@ -13704,7 +12497,7 @@ index 6d229b943fe69cd258b32b1e38c5716715a4cd4b..7294731b4ff75a0cec1dd010cc7facaf } bool WebPageInspectorController::hasLocalFrontend() const -@@ -88,6 +183,17 @@ void WebPageInspectorController::connectFrontend(Inspector::FrontendChannel& fro +@@ -93,6 +184,17 @@ void WebPageInspectorController::connectFrontend(Inspector::FrontendChannel& fro bool connectingFirstFrontend = !m_frontendRouter->hasFrontends(); @@ -13722,7 +12515,7 @@ index 6d229b943fe69cd258b32b1e38c5716715a4cd4b..7294731b4ff75a0cec1dd010cc7facaf m_frontendRouter->connectFrontend(frontendChannel); if (connectingFirstFrontend) -@@ -107,8 +213,10 @@ void WebPageInspectorController::disconnectFrontend(FrontendChannel& frontendCha +@@ -112,8 +214,10 @@ void WebPageInspectorController::disconnectFrontend(FrontendChannel& frontendCha m_frontendRouter->disconnectFrontend(frontendChannel); bool disconnectingLastFrontend = !m_frontendRouter->hasFrontends(); @@ -13734,7 +12527,7 @@ index 6d229b943fe69cd258b32b1e38c5716715a4cd4b..7294731b4ff75a0cec1dd010cc7facaf auto inspectedPage = protectedInspectedPage(); inspectedPage->didChangeInspectorFrontendCount(m_frontendRouter->frontendCount()); -@@ -132,6 +240,8 @@ void WebPageInspectorController::disconnectAllFrontends() +@@ -137,6 +241,8 @@ void WebPageInspectorController::disconnectAllFrontends() // Disconnect any remaining remote frontends. m_frontendRouter->disconnectAllFrontends(); @@ -13743,17 +12536,17 @@ index 6d229b943fe69cd258b32b1e38c5716715a4cd4b..7294731b4ff75a0cec1dd010cc7facaf auto inspectedPage = protectedInspectedPage(); inspectedPage->didChangeInspectorFrontendCount(m_frontendRouter->frontendCount()); -@@ -160,6 +270,66 @@ void WebPageInspectorController::setIndicating(bool indicating) +@@ -165,6 +271,66 @@ void WebPageInspectorController::setIndicating(bool indicating) } #endif -+#if USE(CAIRO) -+void WebPageInspectorController::didPaint(cairo_surface_t* surface) ++#if USE(SKIA) ++void WebPageInspectorController::didPaint(sk_sp&& surface) +{ + if (!m_frontendRouter->hasFrontends()) + return; + -+ m_screecastAgent->didPaint(surface); ++ m_screecastAgent->didPaint(WTFMove(surface)); +} +#endif + @@ -13762,14 +12555,14 @@ index 6d229b943fe69cd258b32b1e38c5716715a4cd4b..7294731b4ff75a0cec1dd010cc7facaf +{ + auto navigation = m_inspectedPage->loadRequestForInspector(WTFMove(request), frame); + if (!navigation) { -+ completionHandler("Failed to navigate"_s, 0); ++ completionHandler("Failed to navigate"_s, { }); + return; + } + + m_pendingNavigations.set(navigation->navigationID(), WTFMove(completionHandler)); +} + -+void WebPageInspectorController::didReceivePolicyDecision(WebCore::PolicyAction action, uint64_t navigationID) ++void WebPageInspectorController::didReceivePolicyDecision(WebCore::PolicyAction action, std::optional navigationID) +{ + if (!m_frontendRouter->hasFrontends()) + return; @@ -13777,17 +12570,17 @@ index 6d229b943fe69cd258b32b1e38c5716715a4cd4b..7294731b4ff75a0cec1dd010cc7facaf + if (!navigationID) + return; + -+ auto completionHandler = m_pendingNavigations.take(navigationID); ++ auto completionHandler = m_pendingNavigations.take(*navigationID); + if (!completionHandler) + return; + + if (action == WebCore::PolicyAction::Ignore) -+ completionHandler("Navigation cancelled"_s, 0); ++ completionHandler("Navigation cancelled"_s, { }); + else -+ completionHandler(String(), navigationID); ++ completionHandler(String(), *navigationID); +} + -+void WebPageInspectorController::didDestroyNavigation(uint64_t navigationID) ++void WebPageInspectorController::didDestroyNavigation(WebCore::NavigationIdentifier navigationID) +{ + if (!m_frontendRouter->hasFrontends()) + return; @@ -13798,10 +12591,10 @@ index 6d229b943fe69cd258b32b1e38c5716715a4cd4b..7294731b4ff75a0cec1dd010cc7facaf + + // Inspector initiated navigation is destroyed before policy check only when it + // becomes a fragment navigation (which always reuses current navigation). -+ completionHandler(String(), 0); ++ completionHandler(String(), { }); +} + -+void WebPageInspectorController::didFailProvisionalLoadForFrame(uint64_t navigationID, const WebCore::ResourceError& error) ++void WebPageInspectorController::didFailProvisionalLoadForFrame(WebCore::NavigationIdentifier navigationID, const WebCore::ResourceError& error) +{ + if (s_observer) + s_observer->didFailProvisionalLoad(m_inspectedPage, navigationID, error.localizedDescription()); @@ -13810,7 +12603,7 @@ index 6d229b943fe69cd258b32b1e38c5716715a4cd4b..7294731b4ff75a0cec1dd010cc7facaf void WebPageInspectorController::createInspectorTarget(const String& targetId, Inspector::InspectorTargetType type) { addTarget(InspectorTargetProxy::create(protectedInspectedPage(), targetId, type)); -@@ -179,6 +349,32 @@ void WebPageInspectorController::sendMessageToInspectorFrontend(const String& ta +@@ -184,6 +350,52 @@ void WebPageInspectorController::sendMessageToInspectorFrontend(const String& ta m_targetAgent->sendMessageFromTargetToFrontend(targetId, message); } @@ -13820,7 +12613,7 @@ index 6d229b943fe69cd258b32b1e38c5716715a4cd4b..7294731b4ff75a0cec1dd010cc7facaf + m_targetAgent->setPauseOnStart(shouldPause); +} + -+bool WebPageInspectorController::shouldPauseLoading() const ++bool WebPageInspectorController::shouldPauseLoadRequest() const +{ + if (!m_frontendRouter->hasFrontends()) + return false; @@ -13828,14 +12621,34 @@ index 6d229b943fe69cd258b32b1e38c5716715a4cd4b..7294731b4ff75a0cec1dd010cc7facaf + if (!m_inspectedPage->isPageOpenedByDOMShowingInitialEmptyDocument()) + return false; + -+ auto* target = m_targets.get(WebPageInspectorTarget::toTargetID(m_inspectedPage->webPageID())); ++ auto* target = m_targets.get(WebPageInspectorTarget::toTargetID(m_inspectedPage->webPageIDInMainFrameProcess())); ++ // The method is expeted to be called only when the WebPage has already been ++ // initilized, so the target must exist. + ASSERT(target); + return target->isPaused(); +} + ++bool WebPageInspectorController::shouldPauseInInspectorWhenShown() const ++{ ++ if (!m_frontendRouter->hasFrontends()) ++ return false; ++ ++ // Only pause if the page was opened by window.open() or new tab navigation. ++ // We cannot use isPageOpenedByDOMShowingInitialEmptyDocument() here because ++ // this method maybe called from WebPageProxy::initializeWebPage and setOpenedByDOM ++ // is called after the page is initialized. ++ if (!m_inspectedPage->configuration().windowFeatures()) ++ return false; ++ ++ // The method is called from WebPageProxy::initializePage and the ++ // target is not created yet (it is created after the new page is ++ // initialized and attached to the process). ++ return m_targetAgent->shouldPauseOnStart(); ++} ++ +void WebPageInspectorController::setContinueLoadingCallback(WTF::Function&& callback) +{ -+ auto* target = m_targets.get(WebPageInspectorTarget::toTargetID(m_inspectedPage->webPageID())); ++ auto* target = m_targets.get(WebPageInspectorTarget::toTargetID(m_inspectedPage->webPageIDInMainFrameProcess())); + ASSERT(target); + target->setResumeCallback(WTFMove(callback)); +} @@ -13843,7 +12656,7 @@ index 6d229b943fe69cd258b32b1e38c5716715a4cd4b..7294731b4ff75a0cec1dd010cc7facaf bool WebPageInspectorController::shouldPauseLoading(const ProvisionalPageProxy& provisionalPage) const { if (!m_frontendRouter->hasFrontends()) -@@ -198,7 +394,7 @@ void WebPageInspectorController::setContinueLoadingCallback(const ProvisionalPag +@@ -203,7 +415,7 @@ void WebPageInspectorController::setContinueLoadingCallback(const ProvisionalPag void WebPageInspectorController::didCreateProvisionalPage(ProvisionalPageProxy& provisionalPage) { @@ -13852,7 +12665,7 @@ index 6d229b943fe69cd258b32b1e38c5716715a4cd4b..7294731b4ff75a0cec1dd010cc7facaf } void WebPageInspectorController::willDestroyProvisionalPage(const ProvisionalPageProxy& provisionalPage) -@@ -277,4 +473,27 @@ void WebPageInspectorController::browserExtensionsDisabled(HashSet&& ext +@@ -287,4 +499,29 @@ void WebPageInspectorController::browserExtensionsDisabled(HashSet&& ext m_enabledBrowserAgent->extensionsDisabled(WTFMove(extensionIDs)); } @@ -13872,34 +12685,39 @@ index 6d229b943fe69cd258b32b1e38c5716715a4cd4b..7294731b4ff75a0cec1dd010cc7facaf + m_inspectedPage->preferences().setJavaScriptCanOpenWindowsAutomatically(true); + + // Enable media stream. -+ if (!m_inspectedPage->preferences().mediaStreamEnabled()) { ++ if (!m_inspectedPage->preferences().mediaDevicesEnabled()) { + m_inspectedPage->preferences().setMediaDevicesEnabled(true); -+ m_inspectedPage->preferences().setMediaStreamEnabled(true); + m_inspectedPage->preferences().setPeerConnectionEnabled(true); + } ++ ++ // Disable local storage partitioning. See https://github.com/microsoft/playwright/issues/32230 ++ m_inspectedPage->preferences().setStorageBlockingPolicy(static_cast(WebCore::StorageBlockingPolicy::AllowAll)); +} + } // namespace WebKit diff --git a/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.h b/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.h -index c6aafe0e9339c8ac02dc133754ddc23e1cb522ff..91473e6a0b4a37a15959f966fc75134c15e1112d 100644 +index c219e0a072057a8d40d8a30a1d404851d6c12d43..aff66705b9acadb9d811f2da439a59dbf5e6ea06 100644 --- a/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.h +++ b/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.h -@@ -26,6 +26,7 @@ +@@ -26,19 +26,39 @@ #pragma once #include "InspectorTargetProxy.h" +#include "ProcessTerminationReason.h" #include #include ++#include #include -@@ -33,11 +34,28 @@ + #include #include #include + #include #include +#include + -+#if USE(CAIRO) -+#include ++#if USE(SKIA) ++#include ++#include +#endif namespace Inspector { @@ -13921,7 +12739,7 @@ index c6aafe0e9339c8ac02dc133754ddc23e1cb522ff..91473e6a0b4a37a15959f966fc75134c } namespace WebKit { -@@ -45,6 +63,23 @@ namespace WebKit { +@@ -46,6 +66,23 @@ namespace WebKit { class InspectorBrowserAgent; struct WebPageAgentContext; @@ -13934,7 +12752,7 @@ index c6aafe0e9339c8ac02dc133754ddc23e1cb522ff..91473e6a0b4a37a15959f966fc75134c +public: + virtual void didCreateInspectorController(WebPageProxy&) = 0; + virtual void willDestroyInspectorController(WebPageProxy&) = 0; -+ virtual void didFailProvisionalLoad(WebPageProxy&, uint64_t navigationID, const String& error) = 0; ++ virtual void didFailProvisionalLoad(WebPageProxy&, WebCore::NavigationIdentifier, const String& error) = 0; + virtual void willCreateNewPage(WebPageProxy&, const WebCore::WindowFeatures&, const URL&) = 0; + virtual void didFinishScreencast(const PAL::SessionID& sessionID, const String& screencastID) = 0; + @@ -13943,13 +12761,13 @@ index c6aafe0e9339c8ac02dc133754ddc23e1cb522ff..91473e6a0b4a37a15959f966fc75134c +}; + class WebPageInspectorController { + WTF_MAKE_TZONE_ALLOCATED(WebPageInspectorController); WTF_MAKE_NONCOPYABLE(WebPageInspectorController); - WTF_MAKE_FAST_ALLOCATED; -@@ -52,7 +87,21 @@ public: - WebPageInspectorController(WebPageProxy&); +@@ -54,7 +91,21 @@ public: + ~WebPageInspectorController(); void init(); -+ void didFinishAttachingToWebProcess(); ++ void didInitializeWebPage(); + + static void setObserver(WebPageInspectorControllerObserver*); + static WebPageInspectorControllerObserver* observer(); @@ -13967,19 +12785,20 @@ index c6aafe0e9339c8ac02dc133754ddc23e1cb522ff..91473e6a0b4a37a15959f966fc75134c bool hasLocalFrontend() const; -@@ -65,11 +114,25 @@ public: +@@ -67,11 +118,27 @@ public: #if ENABLE(REMOTE_INSPECTOR) void setIndicating(bool); #endif -+#if USE(CAIRO) -+ void didPaint(cairo_surface_t*); ++#if USE(SKIA) ++ void didPaint(sk_sp&&); +#endif -+ using NavigationHandler = Function; ++ using NavigationHandler = Function)>; + void navigate(WebCore::ResourceRequest&&, WebFrameProxy*, NavigationHandler&&); -+ void didReceivePolicyDecision(WebCore::PolicyAction action, uint64_t navigationID); -+ void didDestroyNavigation(uint64_t navigationID); ++ void didReceivePolicyDecision(WebCore::PolicyAction action, std::optional navigationID); ++ ++ void didDestroyNavigation(WebCore::NavigationIdentifier navigationID); + -+ void didFailProvisionalLoadForFrame(uint64_t navigationID, const WebCore::ResourceError& error); ++ void didFailProvisionalLoadForFrame(WebCore::NavigationIdentifier navigationID, const WebCore::ResourceError& error); void createInspectorTarget(const String& targetId, Inspector::InspectorTargetType); void destroyInspectorTarget(const String& targetId); @@ -13987,13 +12806,14 @@ index c6aafe0e9339c8ac02dc133754ddc23e1cb522ff..91473e6a0b4a37a15959f966fc75134c + void setPauseOnStart(bool); + -+ bool shouldPauseLoading() const; ++ bool shouldPauseLoadRequest() const; ++ bool shouldPauseInInspectorWhenShown() const; + void setContinueLoadingCallback(WTF::Function&&); + bool shouldPauseLoading(const ProvisionalPageProxy&) const; void setContinueLoadingCallback(const ProvisionalPageProxy&, WTF::Function&&); -@@ -84,11 +147,12 @@ public: +@@ -86,11 +153,12 @@ public: void browserExtensionsDisabled(HashSet&&); private: @@ -14005,21 +12825,20 @@ index c6aafe0e9339c8ac02dc133754ddc23e1cb522ff..91473e6a0b4a37a15959f966fc75134c void addTarget(std::unique_ptr&&); + void adjustPageSettings(); - Ref m_frontendRouter; - Ref m_backendDispatcher; -@@ -97,11 +161,17 @@ private: - WeakRef m_inspectedPage; + const Ref m_frontendRouter; + const Ref m_backendDispatcher; +@@ -101,9 +169,16 @@ private: + CheckedPtr m_targetAgent; + HashMap> m_targets; - Inspector::InspectorTargetAgent* m_targetAgent { nullptr }; + WebPageInspectorEmulationAgent* m_emulationAgent { nullptr }; + WebPageInspectorInputAgent* m_inputAgent { nullptr }; + InspectorScreencastAgent* m_screecastAgent { nullptr }; - HashMap> m_targets; - - InspectorBrowserAgent* m_enabledBrowserAgent { nullptr }; ++ + CheckedPtr m_enabledBrowserAgent; bool m_didCreateLazyAgents { false }; -+ HashMap m_pendingNavigations; ++ UncheckedKeyHashMap m_pendingNavigations; + + static WebPageInspectorControllerObserver* s_observer; }; @@ -14258,10 +13077,10 @@ index 0000000000000000000000000000000000000000..d0e11ed81a6257c011df23d5870da740 +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/InspectorPlaywrightAgent.cpp b/Source/WebKit/UIProcess/InspectorPlaywrightAgent.cpp new file mode 100644 -index 0000000000000000000000000000000000000000..a494ee1006f70d398149753f8953515d434cbcd4 +index 0000000000000000000000000000000000000000..8026d3e9aaca3434fc1d7316a19cd92827566a67 --- /dev/null +++ b/Source/WebKit/UIProcess/InspectorPlaywrightAgent.cpp -@@ -0,0 +1,1019 @@ +@@ -0,0 +1,1009 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * @@ -14333,6 +13152,7 @@ index 0000000000000000000000000000000000000000..a494ee1006f70d398149753f8953515d +#include +#include +#include ++#include + +using namespace Inspector; + @@ -14444,13 +13264,13 @@ index 0000000000000000000000000000000000000000..a494ee1006f70d398149753f8953515d +static Ref> getEnabledWindowFeatures(const WebCore::WindowFeatures& features) { + auto result = JSON::ArrayOf::create(); + if (features.x) -+ result->addItem("left=" + String::number(*features.x)); ++ result->addItem(makeString("left="_s, String::number(*features.x))); + if (features.y) -+ result->addItem("top=" + String::number(*features.y)); ++ result->addItem(makeString("top="_s, String::number(*features.y))); + if (features.width) -+ result->addItem("width=" + String::number(*features.width)); ++ result->addItem(makeString("width="_s, String::number(*features.width))); + if (features.height) -+ result->addItem("height=" + String::number(*features.height)); ++ result->addItem(makeString("height="_s, String::number(*features.height))); + if (features.menuBarVisible) + result->addItem("menubar"_s); + if (features.toolBarVisible) @@ -14634,14 +13454,14 @@ index 0000000000000000000000000000000000000000..a494ee1006f70d398149753f8953515d + if (!m_isEnabled) + return; + -+ if (isInspectorProcessPool(page.process().processPool())) ++ if (isInspectorProcessPool(page.legacyMainFrameProcess().processPool())) + return; + + ASSERT(m_frontendChannel); + + String browserContextID = toBrowserContextIDProtocolString(page.sessionID()); + String pageProxyID = toPageProxyIDProtocolString(page); -+ auto* opener = page.configuration().relatedPage(); ++ auto* opener = page.configuration().openerPageForInspector(); + String openerId; + if (opener) + openerId = toPageProxyIDProtocolString(*opener); @@ -14664,7 +13484,7 @@ index 0000000000000000000000000000000000000000..a494ee1006f70d398149753f8953515d + if (!m_isEnabled) + return; + -+ if (isInspectorProcessPool(page.process().processPool())) ++ if (isInspectorProcessPool(page.legacyMainFrameProcess().processPool())) + return; + + String browserContextID = toBrowserContextIDProtocolString(page.sessionID()); @@ -14686,14 +13506,14 @@ index 0000000000000000000000000000000000000000..a494ee1006f70d398149753f8953515d + m_pageProxyChannels.remove(channelIt); +} + -+void InspectorPlaywrightAgent::didFailProvisionalLoad(WebPageProxy& page, uint64_t navigationID, const String& error) ++void InspectorPlaywrightAgent::didFailProvisionalLoad(WebPageProxy& page, WebCore::NavigationIdentifier navigationID, const String& error) +{ + if (!m_isEnabled) + return; + + m_frontendDispatcher->provisionalLoadFailed( + toPageProxyIDProtocolString(page), -+ String::number(navigationID), error); ++ String::number(navigationID.toUInt64()), error); +} + +void InspectorPlaywrightAgent::willCreateNewPage(WebPageProxy& page, const WebCore::WindowFeatures& features, const URL& url) @@ -14897,33 +13717,13 @@ index 0000000000000000000000000000000000000000..a494ee1006f70d398149753f8953515d + +WebFrameProxy* InspectorPlaywrightAgent::frameForID(const String& frameID, String& error) +{ -+ size_t dotPos = frameID.find("."_s); -+ if (dotPos == notFound) { ++ std::optional frameIdentifier = WebCore::InspectorPageAgent::parseFrameID(frameID); ++ if (!frameIdentifier) { + error = "Invalid frame id"_s; + return nullptr; + } + -+ if (!frameID.containsOnlyASCII()) { -+ error = "Invalid frame id"_s; -+ return nullptr; -+ } -+ -+ String processIDString = frameID.left(dotPos); -+ uint64_t pid = strtoull(processIDString.ascii().data(), 0, 10); -+ auto processID = ObjectIdentifier(pid); -+ auto process = WebProcessProxy::processForIdentifier(processID); -+ if (!process) { -+ error = "Cannot find web process for the frame id"_s; -+ return nullptr; -+ } -+ -+ String frameIDString = frameID.substring(dotPos + 1); -+ uint64_t frameIDNumber = strtoull(frameIDString.ascii().data(), 0, 10); -+ auto frameIdentifier = WebCore::FrameIdentifier { -+ ObjectIdentifier(frameIDNumber), -+ processID -+ }; -+ WebFrameProxy* frame = WebFrameProxy::webFrame(frameIdentifier); ++ WebFrameProxy* frame = WebFrameProxy::webFrame(*frameIdentifier); + if (!frame) { + error = "Cannot find web frame for the frame id"_s; + return nullptr; @@ -14940,7 +13740,7 @@ index 0000000000000000000000000000000000000000..a494ee1006f70d398149753f8953515d + return; + } + -+ WebCore::ResourceRequest resourceRequest { url }; ++ auto resourceRequest = WebCore::ResourceRequest(URL { url }); + + if (!!referrer) + resourceRequest.setHTTPReferrer(referrer); @@ -14965,7 +13765,7 @@ index 0000000000000000000000000000000000000000..a494ee1006f70d398149753f8953515d + } + } + -+ pageProxyChannel->page().inspectorController().navigate(WTFMove(resourceRequest), frame, [callback = WTFMove(callback)](const String& error, uint64_t navigationID) { ++ pageProxyChannel->page().inspectorController().navigate(WTFMove(resourceRequest), frame, [callback = WTFMove(callback)](const String& error, Markable navigationID) { + if (!error.isEmpty()) { + callback->sendFailure(error); + return; @@ -14973,7 +13773,7 @@ index 0000000000000000000000000000000000000000..a494ee1006f70d398149753f8953515d + + String navigationIDString; + if (navigationID) -+ navigationIDString = String::number(navigationID); ++ navigationIDString = String::number(navigationID->toUInt64()); + callback->sendSuccess(navigationIDString); + }); +} @@ -14995,7 +13795,7 @@ index 0000000000000000000000000000000000000000..a494ee1006f70d398149753f8953515d + } + + auto sandboxExtensionHandles = SandboxExtension::createReadOnlyHandlesForFiles("InspectorPlaywrightAgent::grantFileReadAccess"_s, files); -+ pageProxyChannel->page().send(Messages::WebPage::ExtendSandboxForFilesFromOpenPanel(WTFMove(sandboxExtensionHandles))); ++ pageProxyChannel->page().legacyMainFrameProcess().send(Messages::WebPage::ExtendSandboxForFilesFromOpenPanel(WTFMove(sandboxExtensionHandles)), pageProxyChannel->page().webPageIDInMainFrameProcess()); +#endif + return { }; +} @@ -15030,9 +13830,17 @@ index 0000000000000000000000000000000000000000..a494ee1006f70d398149753f8953515d + if (!errorString.isEmpty()) + return makeUnexpected(errorString); + -+ PAL::SessionID sessionID = browserContext->dataStore->sessionID(); -+ NetworkProcessProxy& networkProcess = browserContext->dataStore->networkProcess(); -+ networkProcess.send(Messages::NetworkProcess::SetIgnoreCertificateErrors(sessionID, ignore), 0); ++ browserContext->dataStore->setIgnoreTLSErrors(ignore); ++ return { }; ++} ++ ++Inspector::Protocol::ErrorStringOr InspectorPlaywrightAgent::setPageZoomFactor(const String& pageProxyID, double zoomFactor) ++{ ++ auto* pageProxyChannel = m_pageProxyChannels.get(pageProxyID); ++ if (!pageProxyChannel) ++ return makeUnexpected("Unknown pageProxyID"_s); ++ ++ pageProxyChannel->page().setPageZoomFactor(zoomFactor); + return { }; +} + @@ -15050,12 +13858,7 @@ index 0000000000000000000000000000000000000000..a494ee1006f70d398149753f8953515d + return; + auto cookies = JSON::ArrayOf::create(); + -+// Soup returns cookies in the reverse order. -+#if USE(SOUP) -+ for (const auto& cookie : makeReversedRange(allCookies)) -+#else + for (const auto& cookie : allCookies) -+#endif + cookies->addItem(buildObjectForCookie(cookie)); + callback->sendSuccess(WTFMove(cookies)); + }); @@ -15105,6 +13908,12 @@ index 0000000000000000000000000000000000000000..a494ee1006f70d398149753f8953515d + cookie.sameSite = WebCore::Cookie::SameSitePolicy::Lax; + if (sameSite == "Strict"_s) + cookie.sameSite = WebCore::Cookie::SameSitePolicy::Strict; ++#if USE(SOUP) ++ } else { ++ // Cookies are Lax by default in libsoup and will reject cookies with ++ // sameSite: None and secure: false (defaults in WebCore::Cookie). ++ cookie.sameSite = WebCore::Cookie::SameSitePolicy::Lax; ++#endif + } + cookies.append(WTFMove(cookie)); + } @@ -15203,7 +14012,7 @@ index 0000000000000000000000000000000000000000..a494ee1006f70d398149753f8953515d +{ + if (!m_isEnabled) + return; -+ String frameID = WebCore::InspectorPageAgent::makeFrameID(page->process().coreProcessIdentifier(), frameInfoData.frameID); ++ String frameID = WebCore::InspectorPageAgent::serializeFrameID(frameInfoData.frameID); + m_downloads.set(uuid, download); + m_frontendDispatcher->downloadCreated( + toPageProxyIDProtocolString(*page), @@ -15283,10 +14092,10 @@ index 0000000000000000000000000000000000000000..a494ee1006f70d398149753f8953515d +#endif // ENABLE(REMOTE_INSPECTOR) diff --git a/Source/WebKit/UIProcess/InspectorPlaywrightAgent.h b/Source/WebKit/UIProcess/InspectorPlaywrightAgent.h new file mode 100644 -index 0000000000000000000000000000000000000000..36b7f12b5d9fce000715b42ee2980c20e0e91ef7 +index 0000000000000000000000000000000000000000..f9185788a118f57e98bec149909a206dc1aa5d99 --- /dev/null +++ b/Source/WebKit/UIProcess/InspectorPlaywrightAgent.h -@@ -0,0 +1,130 @@ +@@ -0,0 +1,141 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * @@ -15324,6 +14133,7 @@ index 0000000000000000000000000000000000000000..36b7f12b5d9fce000715b42ee2980c20 +#include +#include +#include ++#include + +namespace Inspector { +class BackendDispatcher; @@ -15337,6 +14147,15 @@ index 0000000000000000000000000000000000000000..36b7f12b5d9fce000715b42ee2980c20 +} + +namespace WebKit { ++class OverridenGeolocationProvider; ++} ++ ++namespace WTF { ++template struct IsDeprecatedWeakRefSmartPointerException; ++template<> struct IsDeprecatedWeakRefSmartPointerException : std::true_type { }; ++} ++ ++namespace WebKit { + +class WebFrameProxy; + @@ -15363,7 +14182,7 @@ index 0000000000000000000000000000000000000000..36b7f12b5d9fce000715b42ee2980c20 + // WebPageInspectorControllerObserver + void didCreateInspectorController(WebPageProxy&) override; + void willDestroyInspectorController(WebPageProxy&) override; -+ void didFailProvisionalLoad(WebPageProxy&, uint64_t navigationID, const String& error) override; ++ void didFailProvisionalLoad(WebPageProxy&, WebCore::NavigationIdentifier navigationID, const String& error) override; + void willCreateNewPage(WebPageProxy&, const WebCore::WindowFeatures&, const URL&) override; + void didFinishScreencast(const PAL::SessionID& sessionID, const String& screencastID) override; + @@ -15379,6 +14198,7 @@ index 0000000000000000000000000000000000000000..36b7f12b5d9fce000715b42ee2980c20 + Inspector::Protocol::ErrorStringOr grantFileReadAccess(const String& pageProxyID, Ref&& paths) override; + void takePageScreenshot(const String& pageProxyID, int x, int y, int width, int height, std::optional&& omitDeviceScaleFactor, Ref&&) override; + Inspector::Protocol::ErrorStringOr setIgnoreCertificateErrors(const String& browserContextID, bool ignore) override; ++ Inspector::Protocol::ErrorStringOr setPageZoomFactor(const String& pageProxyID, double zoomFactor) override; + + void getAllCookies(const String& browserContextID, Ref&&) override; + void setCookies(const String& browserContextID, Ref&& in_cookies, Ref&&) override; @@ -15406,11 +14226,11 @@ index 0000000000000000000000000000000000000000..36b7f12b5d9fce000715b42ee2980c20 + std::unique_ptr m_client; + std::unique_ptr m_frontendDispatcher; + Ref m_playwrightDispatcher; -+ HashMap> m_pageProxyChannels; ++ UncheckedKeyHashMap> m_pageProxyChannels; + BrowserContext* m_defaultContext; -+ HashMap> m_downloads; -+ HashMap> m_browserContexts; -+ HashMap> m_browserContextDeletions; ++ UncheckedKeyHashMap> m_downloads; ++ UncheckedKeyHashMap> m_browserContexts; ++ UncheckedKeyHashMap> m_browserContextDeletions; + bool m_isEnabled { false }; +}; + @@ -15496,11 +14316,50 @@ index 0000000000000000000000000000000000000000..e7a3dcc533294bb6e12f65d79b5b716b +} // namespace WebKit + +#endif // ENABLE(REMOTE_INSPECTOR) +diff --git a/Source/WebKit/UIProcess/Launcher/glib/ProcessLauncherGLib.cpp b/Source/WebKit/UIProcess/Launcher/glib/ProcessLauncherGLib.cpp +index 272e0a6edea50acd35032a854d625b5af5a1472e..486c807ba879ecf534db1ffb593709d117e0c35a 100644 +--- a/Source/WebKit/UIProcess/Launcher/glib/ProcessLauncherGLib.cpp ++++ b/Source/WebKit/UIProcess/Launcher/glib/ProcessLauncherGLib.cpp +@@ -168,6 +168,13 @@ void ProcessLauncher::launchProcess() + nargs++; + } + #endif ++// Playwright begin ++ bool enableSharedArrayBuffer = false; ++ if (m_launchOptions.processType == ProcessLauncher::ProcessType::Web && m_client && m_client->shouldEnableSharedArrayBuffer()) { ++ enableSharedArrayBuffer = true; ++ nargs++; ++ } ++// Playwright end + + WTF_ALLOW_UNSAFE_BUFFER_USAGE_BEGIN // GTK/WPE port + +@@ -188,6 +195,10 @@ void ProcessLauncher::launchProcess() + if (configureJSCForTesting) + argv[i++] = const_cast("--configure-jsc-for-testing"); + #endif ++// Playwright begin ++ if (enableSharedArrayBuffer) ++ argv[i++] = const_cast("--enable-shared-array-buffer"); ++// Playwright end + argv[i++] = nullptr; + + WTF_ALLOW_UNSAFE_BUFFER_USAGE_END diff --git a/Source/WebKit/UIProcess/Launcher/win/ProcessLauncherWin.cpp b/Source/WebKit/UIProcess/Launcher/win/ProcessLauncherWin.cpp -index 1a26781907e71c9cc3e99aff38d8060c4387abd7..b4e6e7edec5a716da63c74a6be5d08b6e1981f52 100644 +index a108acd8a4503a07309fe8c54afc80b0f4175eae..1421d9a761042c31a6ecf3cc78ce3f0e96109abe 100644 --- a/Source/WebKit/UIProcess/Launcher/win/ProcessLauncherWin.cpp +++ b/Source/WebKit/UIProcess/Launcher/win/ProcessLauncherWin.cpp -@@ -97,8 +97,11 @@ void ProcessLauncher::launchProcess() +@@ -91,14 +91,21 @@ void ProcessLauncher::launchProcess() + commandLineBuilder.append(" -configure-jsc-for-testing"_s); + if (!m_client->isJITEnabled()) + commandLineBuilder.append(" -disable-jit"_s); ++// Playwright begin ++ if (m_launchOptions.processType == ProcessLauncher::ProcessType::Web && m_client->shouldEnableSharedArrayBuffer()) ++ commandLineBuilder.append(" -enable-shared-array-buffer"_s); ++// Playwright end + commandLineBuilder.append('\0'); + + auto commandLine = commandLineBuilder.toString().wideCharacters(); STARTUPINFO startupInfo { }; startupInfo.cb = sizeof(startupInfo); @@ -15513,34 +14372,23 @@ index 1a26781907e71c9cc3e99aff38d8060c4387abd7..b4e6e7edec5a716da63c74a6be5d08b6 PROCESS_INFORMATION processInformation { }; BOOL result = ::CreateProcess(0, commandLine.data(), 0, 0, true, 0, 0, 0, &startupInfo, &processInformation); -diff --git a/Source/WebKit/UIProcess/Media/RemoteMediaSessionCoordinatorProxy.cpp b/Source/WebKit/UIProcess/Media/RemoteMediaSessionCoordinatorProxy.cpp -index 3fe0abcfe36bef7ca45bed5661a737ed2bfe56d0..510656948af01ec65d4543c805e9667a307018fd 100644 ---- a/Source/WebKit/UIProcess/Media/RemoteMediaSessionCoordinatorProxy.cpp -+++ b/Source/WebKit/UIProcess/Media/RemoteMediaSessionCoordinatorProxy.cpp -@@ -30,6 +30,7 @@ - - #include "Logging.h" - #include "MediaSessionCoordinatorProxyPrivate.h" -+#include "MessageSenderInlines.h" - #include "RemoteMediaSessionCoordinatorMessages.h" - #include "RemoteMediaSessionCoordinatorProxyMessages.h" - #include "WebPageProxy.h" diff --git a/Source/WebKit/UIProcess/PageClient.h b/Source/WebKit/UIProcess/PageClient.h -index 46f725b53f67ed41ff3312d106a23174d6a16363..369ee3539762a6286977d94a7958b25291f11ed6 100644 +index 1e06e94f26fc73c323605da1afb0474559b35c33..1ac2f393d3dc0a7812c1b9a1bdaa6cea4f150bf4 100644 --- a/Source/WebKit/UIProcess/PageClient.h +++ b/Source/WebKit/UIProcess/PageClient.h -@@ -92,6 +92,10 @@ OBJC_CLASS WKView; - #endif +@@ -74,6 +74,11 @@ + #include #endif -+#if PLATFORM(GTK) || PLATFORM(WPE) -+#include ++#if USE(SKIA) ++#include ++#include +#endif + - namespace API { - class Attachment; - class HitTestResult; -@@ -347,7 +351,16 @@ public: + OBJC_CLASS AVPlayerViewController; + OBJC_CLASS CALayer; + OBJC_CLASS NSFileWrapper; +@@ -381,7 +386,16 @@ public: virtual void selectionDidChange() = 0; #endif @@ -15549,7 +14397,7 @@ index 46f725b53f67ed41ff3312d106a23174d6a16363..369ee3539762a6286977d94a7958b252 +#if PLATFORM(COCOA) + virtual RetainPtr takeSnapshotForAutomation() = 0; +#elif PLATFORM(WPE) -+ virtual RefPtr takeViewSnapshot(std::optional&&, bool nominalResolution = false) = 0; ++ virtual sk_sp takeViewSnapshot(std::optional&&, bool nominalResolution = false) = 0; +#elif PLATFORM(GTK) + virtual RefPtr takeViewSnapshot(std::optional&&, bool nominalResolution = false) = 0; +#endif @@ -15560,10 +14408,10 @@ index 46f725b53f67ed41ff3312d106a23174d6a16363..369ee3539762a6286977d94a7958b252 diff --git a/Source/WebKit/UIProcess/PlaywrightFullScreenManagerProxyClient.cpp b/Source/WebKit/UIProcess/PlaywrightFullScreenManagerProxyClient.cpp new file mode 100644 -index 0000000000000000000000000000000000000000..d365dfd28dcc5d101b4d3859302b1bfe75f01a55 +index 0000000000000000000000000000000000000000..95b682567eba682f927317cd3327a531358dfebc --- /dev/null +++ b/Source/WebKit/UIProcess/PlaywrightFullScreenManagerProxyClient.cpp -@@ -0,0 +1,57 @@ +@@ -0,0 +1,64 @@ +/* + * Copyright (C) 2023 Microsoft Corporation. + * @@ -15605,17 +14453,24 @@ index 0000000000000000000000000000000000000000..d365dfd28dcc5d101b4d3859302b1bfe +{ +} + -+void PlaywrightFullScreenManagerProxyClient::enterFullScreen() ++void PlaywrightFullScreenManagerProxyClient::enterFullScreen(WebCore::FloatSize, CompletionHandler&& completionHandler) +{ -+ m_pageProxy.fullScreenManager()->willEnterFullScreen(); -+ m_pageProxy.fullScreenManager()->didEnterFullScreen(); ++ completionHandler(true); ++} ++ ++void PlaywrightFullScreenManagerProxyClient::exitFullScreen(CompletionHandler&& completionHandler) ++{ ++ completionHandler(); +} + -+void PlaywrightFullScreenManagerProxyClient::exitFullScreen() ++void PlaywrightFullScreenManagerProxyClient::beganEnterFullScreen(const WebCore::IntRect&, const WebCore::IntRect&, CompletionHandler&& completionHandler) +{ -+ m_pageProxy.fullScreenManager()->willExitFullScreen(); -+ m_pageProxy.fullScreenManager()->didExitFullScreen(); ++ completionHandler(true); ++} + ++void PlaywrightFullScreenManagerProxyClient::beganExitFullScreen(const WebCore::IntRect&, const WebCore::IntRect&, CompletionHandler&& completionHandler) ++{ ++ completionHandler(); +} + +} // namespace WebKit @@ -15623,7 +14478,7 @@ index 0000000000000000000000000000000000000000..d365dfd28dcc5d101b4d3859302b1bfe +#endif // ENABLE(FULLSCREEN_API) diff --git a/Source/WebKit/UIProcess/PlaywrightFullScreenManagerProxyClient.h b/Source/WebKit/UIProcess/PlaywrightFullScreenManagerProxyClient.h new file mode 100644 -index 0000000000000000000000000000000000000000..3c8fd0549f1847515d35092f0f49b0602be86819 +index 0000000000000000000000000000000000000000..a8a92a6c5f4b03724decc97828291f6f27cfc6aa --- /dev/null +++ b/Source/WebKit/UIProcess/PlaywrightFullScreenManagerProxyClient.h @@ -0,0 +1,56 @@ @@ -15671,10 +14526,10 @@ index 0000000000000000000000000000000000000000..3c8fd0549f1847515d35092f0f49b060 +private: + void closeFullScreenManager() override { } + bool isFullScreen() override { return m_isFullScreen; } -+ void enterFullScreen() override; -+ void exitFullScreen() override; -+ void beganEnterFullScreen(const WebCore::IntRect& initialFrame, const WebCore::IntRect& finalFrame) override { } -+ void beganExitFullScreen(const WebCore::IntRect& initialFrame, const WebCore::IntRect& finalFrame) override { } ++ void enterFullScreen(WebCore::FloatSize mediaDimensions, CompletionHandler&&) override; ++ void exitFullScreen(CompletionHandler&&) override; ++ void beganEnterFullScreen(const WebCore::IntRect& initialFrame, const WebCore::IntRect& finalFrame, CompletionHandler&&) override; ++ void beganExitFullScreen(const WebCore::IntRect& initialFrame, const WebCore::IntRect& finalFrame, CompletionHandler&&) override; + + WebPageProxy& m_pageProxy; + bool m_isFullScreen { false }; @@ -15684,7 +14539,7 @@ index 0000000000000000000000000000000000000000..3c8fd0549f1847515d35092f0f49b060 + +#endif // ENABLE(FULLSCREEN_API) diff --git a/Source/WebKit/UIProcess/ProvisionalFrameProxy.cpp b/Source/WebKit/UIProcess/ProvisionalFrameProxy.cpp -index b2dc99d6ca28e7f1140122a259d9fbcf3b4eeabf..4f182cd32458d19b775f79deb1f6da22a4077ba6 100644 +index 493bde430bef5c064ff6807296ad088d8dee1a72..9b6dbc259e150fba3ba5fb4b488d91e3fb16be7e 100644 --- a/Source/WebKit/UIProcess/ProvisionalFrameProxy.cpp +++ b/Source/WebKit/UIProcess/ProvisionalFrameProxy.cpp @@ -25,6 +25,7 @@ @@ -15694,13 +14549,13 @@ index b2dc99d6ca28e7f1140122a259d9fbcf3b4eeabf..4f182cd32458d19b775f79deb1f6da22 +#include "WebFrameProxy.h" #include "FrameProcess.h" - #include "VisitedLinkStore.h" + #include "ProvisionalFrameCreationParameters.h" diff --git a/Source/WebKit/UIProcess/RemoteInspectorPipe.cpp b/Source/WebKit/UIProcess/RemoteInspectorPipe.cpp new file mode 100644 -index 0000000000000000000000000000000000000000..1a824be7d9fcb225d018b4a821fa895e844d7805 +index 0000000000000000000000000000000000000000..b1ddac8c1442cb4da17f50d92599ef9aff6d4066 --- /dev/null +++ b/Source/WebKit/UIProcess/RemoteInspectorPipe.cpp -@@ -0,0 +1,225 @@ +@@ -0,0 +1,230 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * @@ -15733,6 +14588,7 @@ index 0000000000000000000000000000000000000000..1a824be7d9fcb225d018b4a821fa895e + +#include "InspectorPlaywrightAgent.h" +#include ++#include +#include +#include +#include @@ -15748,6 +14604,8 @@ index 0000000000000000000000000000000000000000..1a824be7d9fcb225d018b4a821fa895e +#include +#endif + ++WTF_ALLOW_UNSAFE_BUFFER_USAGE_BEGIN ++ +namespace WebKit { + +namespace { @@ -15926,6 +14784,8 @@ index 0000000000000000000000000000000000000000..1a824be7d9fcb225d018b4a821fa895e +} // namespace WebKit + +#endif // ENABLE(REMOTE_INSPECTOR) ++ ++WTF_ALLOW_UNSAFE_BUFFER_USAGE_END diff --git a/Source/WebKit/UIProcess/RemoteInspectorPipe.h b/Source/WebKit/UIProcess/RemoteInspectorPipe.h new file mode 100644 index 0000000000000000000000000000000000000000..6d04f9290135069359ce6bf8726546482fd1dc95 @@ -15997,136 +14857,24 @@ index 0000000000000000000000000000000000000000..6d04f9290135069359ce6bf872654648 +} // namespace WebKit + +#endif // ENABLE(REMOTE_INSPECTOR) -diff --git a/Source/WebKit/UIProcess/RemoteLayerTree/mac/RemoteLayerTreeEventDispatcher.h b/Source/WebKit/UIProcess/RemoteLayerTree/mac/RemoteLayerTreeEventDispatcher.h -index d499ee31f32b9dcdb456ba0b476d211fba115673..43b349887d18e21162b59fa8174df32c0dd6abbd 100644 ---- a/Source/WebKit/UIProcess/RemoteLayerTree/mac/RemoteLayerTreeEventDispatcher.h -+++ b/Source/WebKit/UIProcess/RemoteLayerTree/mac/RemoteLayerTreeEventDispatcher.h -@@ -30,6 +30,7 @@ - #include "DisplayLinkObserverID.h" - #include "MomentumEventDispatcher.h" - #include "NativeWebWheelEvent.h" -+#include "RemoteLayerTreeNode.h" - #include - #include - #include -@@ -41,6 +42,11 @@ - #include - #include - #include -+#include -+#include -+ -+#include "NativeWebWheelEvent.h" -+#include "WebPage.h" - - namespace WebCore { - class PlatformWheelEvent; -diff --git a/Source/WebKit/UIProcess/RemotePageProxy.cpp b/Source/WebKit/UIProcess/RemotePageProxy.cpp -index 1db0914af03203844ccbda63b50f8486dc823586..3bf331ae9866aaea83e3bea6ca5bb196d4039110 100644 ---- a/Source/WebKit/UIProcess/RemotePageProxy.cpp -+++ b/Source/WebKit/UIProcess/RemotePageProxy.cpp -@@ -43,6 +43,7 @@ - #include "WebPageProxyMessages.h" - #include "WebProcessMessages.h" - #include "WebProcessProxy.h" -+#include "WebProcessMessages.h" - #include - - namespace WebKit { -diff --git a/Source/WebKit/UIProcess/RemotePageProxy.h b/Source/WebKit/UIProcess/RemotePageProxy.h -index 5ecfa03204724d8e5696149dd45e4d35877993f0..fc8262fb617aef3eb68cf13117747dc48a7d843e 100644 ---- a/Source/WebKit/UIProcess/RemotePageProxy.h -+++ b/Source/WebKit/UIProcess/RemotePageProxy.h -@@ -64,7 +64,6 @@ class WebProcessProxy; - - struct FrameInfoData; - struct FrameTreeCreationParameters; --struct NavigationActionData; - - class RemotePageProxy : public IPC::MessageReceiver { - WTF_MAKE_FAST_ALLOCATED; -diff --git a/Source/WebKit/UIProcess/WebAuthentication/fido/U2fAuthenticator.cpp b/Source/WebKit/UIProcess/WebAuthentication/fido/U2fAuthenticator.cpp -index 4d8a16e02d2d3c1d11df5df2c84197da76539324..5de382d79c2dd8f7884eb27ef454ba0b99f3fab8 100644 ---- a/Source/WebKit/UIProcess/WebAuthentication/fido/U2fAuthenticator.cpp -+++ b/Source/WebKit/UIProcess/WebAuthentication/fido/U2fAuthenticator.cpp -@@ -37,6 +37,7 @@ - #include - #include - #include -+#include - - #define U2F_RELEASE_LOG(fmt, ...) RELEASE_LOG(WebAuthn, "%p [transport=%s] - U2fAuthenticator::" fmt, this, transportForDebugging().utf8().data(), ##__VA_ARGS__) - -diff --git a/Source/WebKit/UIProcess/WebContextMenuProxy.cpp b/Source/WebKit/UIProcess/WebContextMenuProxy.cpp -index d74ec9892f9a57bd7622ff5a4e16b67262165661..e884998f2a0823c32f33fe7a8499c7b4904a2fc0 100644 ---- a/Source/WebKit/UIProcess/WebContextMenuProxy.cpp -+++ b/Source/WebKit/UIProcess/WebContextMenuProxy.cpp -@@ -33,6 +33,7 @@ - #include "WebPageMessages.h" - #include "WebPageProxy.h" - #include "WebProcessProxy.h" -+#include "MessageSenderInlines.h" - - namespace WebKit { - diff --git a/Source/WebKit/UIProcess/WebContextMenuProxy.h b/Source/WebKit/UIProcess/WebContextMenuProxy.h -index e7d6621532fcc73212cc9130a7cafbb13f458d1d..ec931c8f19d2a61c0fa7d78b52df7f3f94bdd2c5 100644 +index 697a350812e1bf73dd44cc3d723a6a291f9d59d1..a8e1edd710d88f48632d51fd05aa964732d727d3 100644 --- a/Source/WebKit/UIProcess/WebContextMenuProxy.h +++ b/Source/WebKit/UIProcess/WebContextMenuProxy.h -@@ -46,6 +46,7 @@ public: - virtual ~WebContextMenuProxy(); +@@ -49,6 +49,7 @@ public: + void deref() const final { RefCounted::deref(); } virtual void show(); + virtual void hide() {} WebPageProxy* page() const { return m_page.get(); } - -diff --git a/Source/WebKit/UIProcess/WebFrameProxy.cpp b/Source/WebKit/UIProcess/WebFrameProxy.cpp -index 6e6560e17721ed182ab27277759488c410ae130e..207bda7e3c53118344536568ef18ccc043104ba1 100644 ---- a/Source/WebKit/UIProcess/WebFrameProxy.cpp -+++ b/Source/WebKit/UIProcess/WebFrameProxy.cpp -@@ -31,6 +31,7 @@ - #include "Connection.h" - #include "DrawingAreaMessages.h" - #include "DrawingAreaProxy.h" -+#include "FormDataReference.h" - #include "FrameProcess.h" - #include "FrameTreeCreationParameters.h" - #include "FrameTreeNodeData.h" -@@ -43,6 +44,7 @@ - #include "RemotePageProxy.h" - #include "WebFramePolicyListenerProxy.h" - #include "WebNavigationState.h" -+#include "WebPageInspectorController.h" - #include "WebPageMessages.h" - #include "WebPageProxy.h" - #include "WebPageProxyMessages.h" -diff --git a/Source/WebKit/UIProcess/WebNavigationState.h b/Source/WebKit/UIProcess/WebNavigationState.h -index f68592e910d61293346fbc251afd9bcbd28cd3a5..2f92c407fa357031a1d054aa39a65a20cbe30751 100644 ---- a/Source/WebKit/UIProcess/WebNavigationState.h -+++ b/Source/WebKit/UIProcess/WebNavigationState.h -@@ -29,6 +29,7 @@ - #include - #include - #include -+#include "WebPageProxy.h" - - namespace API { - class Navigation; -@@ -43,7 +44,6 @@ enum class FrameLoadType : uint8_t; - - namespace WebKit { - --class WebPageProxy; - class WebBackForwardListItem; - - class WebNavigationState : public CanMakeWeakPtr { + RefPtr protectedPage() const; diff --git a/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.cpp b/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.cpp new file mode 100644 -index 0000000000000000000000000000000000000000..fef34b5cf77742521c679a46f38111c1e198b9bf +index 0000000000000000000000000000000000000000..653b3550dda624df82de679315711fd1dd4ed0b6 --- /dev/null +++ b/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.cpp -@@ -0,0 +1,147 @@ +@@ -0,0 +1,159 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * @@ -16200,9 +14948,9 @@ index 0000000000000000000000000000000000000000..fef34b5cf77742521c679a46f38111c1 +#endif + + if (deviceScaleFactor) -+ m_page.setCustomDeviceScaleFactor(deviceScaleFactor.value()); ++ m_page.setCustomDeviceScaleFactor(deviceScaleFactor.value(), [] { }); + m_page.setUseFixedLayout(fixedlayout); -+ if (!m_page.pageClient().isViewVisible() && m_page.configuration().relatedPage()) { ++ if (!m_page.pageClient()->isViewVisible() && m_page.configuration().relatedPage()) { + m_commandsToRunWhenShown.append([this, width, height, callback = WTFMove(callback)]() mutable { + setSize(width, height, WTFMove(callback)); + }); @@ -16231,10 +14979,10 @@ index 0000000000000000000000000000000000000000..fef34b5cf77742521c679a46f38111c1 + +Inspector::Protocol::ErrorStringOr WebPageInspectorEmulationAgent::setAuthCredentials(const String& username, const String& password, const String& origin) +{ -+ if (!!username && !!password) -+ m_page.setAuthCredentialsForAutomation(WebCore::Credential(username, password, WebCore::CredentialPersistence::Permanent), URL(origin)); ++ if (username.isNull() && password.isNull()) ++ m_page.setAuthCredentialsForAutomation(std::nullopt, std::nullopt); + else -+ m_page.setAuthCredentialsForAutomation(std::optional(), std::optional()); ++ m_page.setAuthCredentialsForAutomation(WebCore::Credential(username, password, WebCore::CredentialPersistence::Permanent), URL(origin)); + return { }; +} + @@ -16266,6 +15014,18 @@ index 0000000000000000000000000000000000000000..fef34b5cf77742521c679a46f38111c1 + return { }; +} + ++Inspector::Protocol::ErrorStringOr WebPageInspectorEmulationAgent::setOrientationOverride(std::optional&& angle) ++{ ++#if ENABLE(ORIENTATION_EVENTS) ++ m_page.setOrientationOverride(WTFMove(angle)); ++ return { }; ++#else ++ UNUSED_PARAM(angle); ++ return makeUnexpected("Orientation events are disabled in this build"_s); ++#endif ++} ++ ++ +void WebPageInspectorEmulationAgent::didShowPage() +{ + for (auto& command : m_commandsToRunWhenShown) @@ -16276,10 +15036,10 @@ index 0000000000000000000000000000000000000000..fef34b5cf77742521c679a46f38111c1 +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.h b/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.h new file mode 100644 -index 0000000000000000000000000000000000000000..12657f8e7c4b2596707680d299dc8084d48f03c2 +index 0000000000000000000000000000000000000000..d00d00ce8fd800dc1497b36b8a495c5b9aef6f58 --- /dev/null +++ b/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.h -@@ -0,0 +1,75 @@ +@@ -0,0 +1,76 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * @@ -16341,6 +15101,7 @@ index 0000000000000000000000000000000000000000..12657f8e7c4b2596707680d299dc8084 + Inspector::Protocol::ErrorStringOr setActiveAndFocused(std::optional&&) override; + Inspector::Protocol::ErrorStringOr grantPermissions(const String& origin, Ref&& permissions) override; + Inspector::Protocol::ErrorStringOr resetPermissions() override; ++ Inspector::Protocol::ErrorStringOr setOrientationOverride(std::optional&& angle) override; + + void didShowPage(); + @@ -16351,16 +15112,16 @@ index 0000000000000000000000000000000000000000..12657f8e7c4b2596707680d299dc8084 + Ref m_backendDispatcher; + WebPageProxy& m_page; + Vector> m_commandsToRunWhenShown; -+ HashMap> m_permissions; ++ UncheckedKeyHashMap> m_permissions; +}; + +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/WebPageInspectorInputAgent.cpp b/Source/WebKit/UIProcess/WebPageInspectorInputAgent.cpp new file mode 100644 -index 0000000000000000000000000000000000000000..f4519d0655e1e92e6d47a9e59cf01b0fd07ababf +index 0000000000000000000000000000000000000000..6cb20d95c1cd8682b025cfdf4ac74f49fd8e9cda --- /dev/null +++ b/Source/WebKit/UIProcess/WebPageInspectorInputAgent.cpp -@@ -0,0 +1,334 @@ +@@ -0,0 +1,394 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * @@ -16393,8 +15154,9 @@ index 0000000000000000000000000000000000000000..f4519d0655e1e92e6d47a9e59cf01b0f +#include "NativeWebKeyboardEvent.h" +#include "NativeWebMouseEvent.h" +#include "NativeWebWheelEvent.h" -+#include "WebWheelEvent.h" +#include "WebPageProxy.h" ++#include "WebTouchEvent.h" ++#include "WebWheelEvent.h" +#include +#include +#include @@ -16486,7 +15248,7 @@ index 0000000000000000000000000000000000000000..f4519d0655e1e92e6d47a9e59cf01b0f +static String keyIdentifierForKey(const String& key) +{ + if (key.length() == 1) -+ return makeString("U+", hex(toASCIIUpper(key.characterAt(0)), 4)); ++ return makeString("U+"_s, hex(toASCIIUpper(key.characterAt(0)), 4)); + if (key == "Delete"_s) + return "U+007F"_s; + if (key == "Backspace"_s) @@ -16627,7 +15389,7 @@ index 0000000000000000000000000000000000000000..f4519d0655e1e92e6d47a9e59cf01b0f + m_mouseCallbacks->append(WTFMove(callback)); + + // Convert css coordinates to view coordinates (dip). -+ double totalScale = m_page.pageScaleFactor() * m_page.viewScaleFactor(); ++ double totalScale = m_page.pageScaleFactor() * m_page.viewScaleFactor() * m_page.pageZoomFactor(); + x = clampToInteger(roundf(x * totalScale)); + y = clampToInteger(roundf(y * totalScale)); + eventDeltaX = clampToInteger(roundf(eventDeltaX * totalScale)); @@ -16660,10 +15422,69 @@ index 0000000000000000000000000000000000000000..f4519d0655e1e92e6d47a9e59cf01b0f +#endif +} + -+void WebPageInspectorInputAgent::dispatchTapEvent(int x, int y, std::optional&& modifiers, Ref&& callback) { -+ m_page.sendWithAsyncReply(Messages::WebPage::FakeTouchTap(WebCore::IntPoint(x, y), modifiers ? *modifiers : 0), [callback]() { ++void WebPageInspectorInputAgent::dispatchTapEvent(int x, int y, std::optional&& modifiers, Ref&& callback) ++{ ++ m_page.legacyMainFrameProcess().sendWithAsyncReply(Messages::WebPage::FakeTouchTap(WebCore::IntPoint(x, y), modifiers ? *modifiers : 0), [callback]() { + callback->sendSuccess(); -+ }); ++ }, m_page.webPageIDInMainFrameProcess()); ++} ++ ++void WebPageInspectorInputAgent::dispatchTouchEvent(const String& type, std::optional&& modifiers, RefPtr&& in_touchPoints, Ref&& callback) ++{ ++ float rotationAngle = 0.0; ++ float force = 1.0; ++ const WebCore::IntSize radius(1, 1); ++ ++ uint8_t unsignedModifiers = modifiers ? static_cast(*modifiers) : 0; ++ OptionSet eventModifiers; ++ eventModifiers = eventModifiers.fromRaw(unsignedModifiers); ++ ++ WebPlatformTouchPoint::State state; ++ if (type == "touchStart"_s) ++ state = WebPlatformTouchPoint::State::Pressed; ++ else if (type == "touchMove"_s) ++ state = WebPlatformTouchPoint::State::Moved; ++ else if (type == "touchEnd"_s) ++ state = WebPlatformTouchPoint::State::Released; ++ else if (type == "touchCancel"_s) ++ state = WebPlatformTouchPoint::State::Cancelled; ++ else { ++ callback->sendFailure("Unsupported event type"_s); ++ return; ++ } ++ ++ Vector touchPoints; ++ for (unsigned i = 0; i < in_touchPoints->length(); ++i) { ++ RefPtr item = in_touchPoints->get(i); ++ RefPtr obj = item->asObject(); ++ if (!obj) { ++ callback->sendFailure("Invalid TouchPoint format"_s); ++ return; ++ } ++ std::optional x = obj->getInteger("x"_s); ++ if (!x) { ++ callback->sendFailure("TouchPoint does not have x"_s); ++ return; ++ } ++ std::optional y = obj->getInteger("y"_s); ++ if (!y) { ++ callback->sendFailure("TouchPoint does not have y"_s); ++ return; ++ } ++ std::optional optionalId = obj->getInteger("id"_s); ++ int id = optionalId ? *optionalId : 0; ++ const WebCore::IntPoint position(*x, *y); ++ touchPoints.append(WebPlatformTouchPoint(id, state, position, position, radius, rotationAngle, force)); ++ } ++ ++ WebTouchEvent touchEvent({WebEventType::TouchStart, eventModifiers, WallTime::now()}, WTFMove(touchPoints), {}, {}); ++ m_page.legacyMainFrameProcess().sendWithAsyncReply(Messages::WebPage::TouchEvent(touchEvent), [callback] (std::optional eventType, bool) { ++ if (!eventType) { ++ callback->sendFailure("Failed to dispatch touch event."_s); ++ return; ++ } ++ callback->sendSuccess(); ++ }, m_page.webPageIDInMainFrameProcess()); +} + +void WebPageInspectorInputAgent::dispatchWheelEvent(int x, int y, std::optional&& modifiers, std::optional&& deltaX, std::optional&& deltaY, Ref&& callback) @@ -16681,7 +15502,7 @@ index 0000000000000000000000000000000000000000..f4519d0655e1e92e6d47a9e59cf01b0f + m_wheelCallbacks->append(WTFMove(callback)); + + // Convert css coordinates to view coordinates (dip). -+ double totalScale = m_page.pageScaleFactor() * m_page.viewScaleFactor(); ++ double totalScale = m_page.pageScaleFactor() * m_page.viewScaleFactor() * m_page.pageZoomFactor(); + x = clampToInteger(roundf(x * totalScale)); + y = clampToInteger(roundf(y * totalScale)); + @@ -16697,10 +15518,10 @@ index 0000000000000000000000000000000000000000..f4519d0655e1e92e6d47a9e59cf01b0f +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/WebPageInspectorInputAgent.h b/Source/WebKit/UIProcess/WebPageInspectorInputAgent.h new file mode 100644 -index 0000000000000000000000000000000000000000..3e87bf40ced2301f4fb145c6cb31f2cf7fa15dd6 +index 0000000000000000000000000000000000000000..26a2a3c0791c334f811ec99a630314f8e8521d02 --- /dev/null +++ b/Source/WebKit/UIProcess/WebPageInspectorInputAgent.h -@@ -0,0 +1,86 @@ +@@ -0,0 +1,87 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * @@ -16765,6 +15586,7 @@ index 0000000000000000000000000000000000000000..3e87bf40ced2301f4fb145c6cb31f2cf + void dispatchKeyEvent(const String& type, std::optional&& modifiers, const String& text, const String& unmodifiedText, const String& code, const String& key, std::optional&& windowsVirtualKeyCode, std::optional&& nativeVirtualKeyCode, std::optional&& autoRepeat, std::optional&& isKeypad, std::optional&& isSystemKey, RefPtr&&, Ref&& callback) override; + void dispatchMouseEvent(const String& type, int x, int y, std::optional&& modifiers, const String& button, std::optional&& buttons, std::optional&& clickCount, std::optional&& deltaX, std::optional&& deltaY, Ref&& callback) override; + void dispatchTapEvent(int x, int y, std::optional&& modifiers, Ref&& callback) override; ++ void dispatchTouchEvent(const String& type, std::optional&& modifiers, RefPtr&& touchPoints, Ref&& callback) override; + void dispatchWheelEvent(int x, int y, std::optional&& modifiers, std::optional&& deltaX, std::optional&& deltaY, Ref&& callback) override; + +private: @@ -16788,25 +15610,26 @@ index 0000000000000000000000000000000000000000..3e87bf40ced2301f4fb145c6cb31f2cf + +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/WebPageProxy.cpp b/Source/WebKit/UIProcess/WebPageProxy.cpp -index 365c5e2c7925347531f2e488d720973612f25d39..585c51dd017a628f08d443c863fd1453d4592996 100644 +index 7c380219c6ff83938d0b7425b62932521cdb1edb..7439ed4314cd66866e0eb570e46744cad3254e10 100644 --- a/Source/WebKit/UIProcess/WebPageProxy.cpp +++ b/Source/WebKit/UIProcess/WebPageProxy.cpp -@@ -185,12 +185,14 @@ - #include +@@ -205,6 +205,7 @@ #include #include + #include +#include #include #include - #include - #include - #include - #include + #include +@@ -217,6 +218,7 @@ + #include + #include + #include +#include #include #include #include -@@ -211,6 +213,7 @@ +@@ -242,6 +244,7 @@ #include #include #include @@ -16814,7 +15637,7 @@ index 365c5e2c7925347531f2e488d720973612f25d39..585c51dd017a628f08d443c863fd1453 #include #include #include -@@ -218,11 +221,13 @@ +@@ -250,10 +253,13 @@ #include #include #include @@ -16823,22 +15646,22 @@ index 365c5e2c7925347531f2e488d720973612f25d39..585c51dd017a628f08d443c863fd1453 #include #include #include - #include ++#include +#include #include + #include #include - #include -@@ -298,6 +303,9 @@ +@@ -349,6 +355,9 @@ + #if USE(GBM) #include "AcceleratedBackingStoreDMABuf.h" #endif - #include "GtkSettingsManager.h" +#endif + +#if PLATFORM(GTK) || PLATFORM(WPE) #include #endif -@@ -419,6 +427,8 @@ static constexpr Seconds tryCloseTimeoutDelay = 50_ms; +@@ -474,6 +483,8 @@ static constexpr Seconds tryCloseTimeoutDelay = 50_ms; static constexpr Seconds audibleActivityClearDelay = 10_s; #endif @@ -16847,36 +15670,36 @@ index 365c5e2c7925347531f2e488d720973612f25d39..585c51dd017a628f08d443c863fd1453 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, webPageProxyCounter, ("WebPageProxy")); #if PLATFORM(COCOA) -@@ -823,6 +833,10 @@ WebPageProxy::~WebPageProxy() - if (preferences->mediaSessionCoordinatorEnabled()) - GroupActivitiesSessionNotifier::sharedNotifier().removeWebPage(*this); +@@ -1007,6 +1018,10 @@ WebPageProxy::~WebPageProxy() #endif + + internals().updatePlayingMediaDidChangeTimer.stop(); + +#if PLATFORM(COCOA) + releaseInspectorDragPasteboard(); +#endif } - void WebPageProxy::addAllMessageReceivers() -@@ -1361,6 +1375,7 @@ void WebPageProxy::finishAttachingToWebProcess(ProcessLaunchReason reason) - - protectedPageClient()->didRelaunchProcess(); - internals().pageLoadState.didSwapWebProcesses(); -+ m_inspectorController->didFinishAttachingToWebProcess(); - } - - void WebPageProxy::didAttachToRunningProcess() -@@ -1369,7 +1384,7 @@ void WebPageProxy::didAttachToRunningProcess() + Ref WebPageProxy::Internals::protectedPage() const +@@ -1580,7 +1595,7 @@ void WebPageProxy::didAttachToRunningProcess() #if ENABLE(FULLSCREEN_API) ASSERT(!m_fullScreenManager); -- m_fullScreenManager = makeUnique(*this, protectedPageClient()->fullScreenManagerProxyClient()); -+ m_fullScreenManager = makeUnique(*this, m_fullScreenManagerClientOverride ? *m_fullScreenManagerClientOverride : protectedPageClient()->fullScreenManagerProxyClient()); +- m_fullScreenManager = WebFullScreenManagerProxy::create(*this, protectedPageClient()->fullScreenManagerProxyClient()); ++ m_fullScreenManager = WebFullScreenManagerProxy::create(*this, m_fullScreenManagerClientOverride ? *m_fullScreenManagerClientOverride : protectedPageClient()->fullScreenManagerProxyClient()); #endif #if ENABLE(VIDEO_PRESENTATION_MODE) ASSERT(!m_playbackSessionManager); -@@ -1764,6 +1779,21 @@ WebProcessProxy& WebPageProxy::ensureRunningProcess() - return m_process; +@@ -1739,6 +1754,7 @@ void WebPageProxy::initializeWebPage(const Site& site, WebCore::SandboxFlags eff + if (preferences->siteIsolationEnabled()) + browsingContextGroup->addPage(*this); + process->send(Messages::WebProcess::CreateWebPage(m_webPageID, creationParameters(process, *m_drawingArea, m_mainFrame->frameID(), std::nullopt)), 0); ++ m_inspectorController->didInitializeWebPage(); + + #if ENABLE(WINDOW_PROXY_PROPERTY_ACCESS_NOTIFICATION) + internals().frameLoadStateObserver = makeUniqueWithoutRefCountedCheck(*this); +@@ -2021,6 +2037,21 @@ Ref WebPageProxy::ensureProtectedRunningProcess() + return ensureRunningProcess(); } +RefPtr WebPageProxy::loadRequestForInspector(WebCore::ResourceRequest&& request, WebFrameProxy* frame) @@ -16884,21 +15707,55 @@ index 365c5e2c7925347531f2e488d720973612f25d39..585c51dd017a628f08d443c863fd1453 + if (!frame || frame == mainFrame()) + return loadRequest(WTFMove(request), WebCore::ShouldOpenExternalURLsPolicy::ShouldNotAllow); + -+ auto navigation = m_navigationState->createLoadRequestNavigation(process().coreProcessIdentifier(), ResourceRequest(request), m_backForwardList->currentItem()); ++ auto navigation = m_navigationState->createLoadRequestNavigation(legacyMainFrameProcess().coreProcessIdentifier(), ResourceRequest(request), m_backForwardList->currentItem()); + LoadParameters loadParameters; + loadParameters.navigationID = navigation->navigationID(); + loadParameters.request = WTFMove(request); + loadParameters.shouldOpenExternalURLsPolicy = WebCore::ShouldOpenExternalURLsPolicy::ShouldNotAllow; + loadParameters.shouldTreatAsContinuingLoad = ShouldTreatAsContinuingLoad::No; -+ m_process->send(Messages::WebPage::LoadRequestInFrameForInspector(WTFMove(loadParameters), frame->frameID()), internals().webPageID); ++ m_legacyMainFrameProcess->send(Messages::WebPage::LoadRequestInFrameForInspector(WTFMove(loadParameters), frame->frameID()), m_webPageID); + return navigation; +} + - RefPtr WebPageProxy::loadRequest(ResourceRequest&& request, ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy, API::Object* userData) + RefPtr WebPageProxy::loadRequest(WebCore::ResourceRequest&& request, ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy, IsPerformingHTTPFallback isPerformingHTTPFallback, std::unique_ptr&& lastNavigationAction, API::Object* userData) { if (m_isClosed) -@@ -2336,6 +2366,42 @@ void WebPageProxy::setControlledByAutomation(bool controlled) - websiteDataStore().protectedNetworkProcess()->send(Messages::NetworkProcess::SetSessionIsControlledByAutomation(m_websiteDataStore->sessionID(), m_controlledByAutomation), 0); +@@ -2136,11 +2167,29 @@ void WebPageProxy::loadRequestWithNavigationShared(Ref&& proces + + navigation->setIsLoadedWithNavigationShared(true); + protectedProcess->markProcessAsRecentlyUsed(); +- if (!protectedProcess->isLaunching() || !url.protocolIsFile()) +- protectedProcess->send(Messages::WebPage::LoadRequest(WTFMove(loadParameters)), webPageID); ++ ++ // Pause loading for new window navigation. ++ Function continuation = [ ++ weakThis = WeakPtr { protectedThis }, ++ weakProcess = WeakPtr { protectedProcess }, ++ loadParameters = WTFMove(loadParameters), ++ webPageID, ++ url ++ ]() mutable { ++ RefPtr innerProtectedProcess = weakProcess.get(); ++ RefPtr innerProtectedThis = weakThis.get(); ++ if (!innerProtectedProcess || !innerProtectedThis) ++ return; ++ if (!innerProtectedProcess->isLaunching() || !url.protocolIsFile()) ++ innerProtectedProcess->send(Messages::WebPage::LoadRequest(WTFMove(loadParameters)), webPageID); ++ else ++ innerProtectedProcess->send(Messages::WebPage::LoadRequestWaitingForProcessLaunch(WTFMove(loadParameters), innerProtectedThis->internals().pageLoadState.resourceDirectoryURL(), innerProtectedThis->identifier(), true), webPageID); ++ innerProtectedProcess->startResponsivenessTimer(); ++ }; ++ if (protectedThis->m_inspectorController->shouldPauseLoadRequest()) ++ protectedThis->m_inspectorController->setContinueLoadingCallback(WTFMove(continuation)); + else +- protectedProcess->send(Messages::WebPage::LoadRequestWaitingForProcessLaunch(WTFMove(loadParameters), protectedThis->pageLoadState().resourceDirectoryURL(), protectedThis->identifier(), true), webPageID); +- protectedProcess->startResponsivenessTimer(); ++ continuation(); + }); + } + +@@ -2696,6 +2745,63 @@ void WebPageProxy::setControlledByAutomation(bool controlled) + protectedWebsiteDataStore()->protectedNetworkProcess()->send(Messages::NetworkProcess::SetSessionIsControlledByAutomation(m_websiteDataStore->sessionID(), m_controlledByAutomation), 0); } +void WebPageProxy::setAuthCredentialsForAutomation(std::optional&& credentials, std::optional&& origin) @@ -16907,11 +15764,30 @@ index 365c5e2c7925347531f2e488d720973612f25d39..585c51dd017a628f08d443c863fd1453 + m_authOriginForAutomation = WTFMove(origin); +} + -+void WebPageProxy::setPermissionsForAutomation(const HashMap>& permissions) ++void WebPageProxy::setPermissionsForAutomation(const UncheckedKeyHashMap>& permissions) +{ + m_permissionsForAutomation = permissions; +} + ++static inline WebCore::ScreenOrientationType toScreenOrientationType(int angle) ++{ ++ if (angle == -90) ++ return WebCore::ScreenOrientationType::LandscapeSecondary; ++ if (angle == 180) ++ return WebCore::ScreenOrientationType::PortraitSecondary; ++ if (angle == 90) ++ return WebCore::ScreenOrientationType::LandscapePrimary; ++ return WebCore::ScreenOrientationType::PortraitPrimary; ++} ++ ++void WebPageProxy::setOrientationOverride(std::optional&& angle) ++{ ++ auto deviceOrientation = toScreenOrientationType(angle.value_or(0)); ++ if (m_screenOrientationManager) ++ m_screenOrientationManager->setCurrentOrientation(deviceOrientation); ++ m_legacyMainFrameProcess->send(Messages::WebPage::SetDeviceOrientation(angle.value_or(0)), webPageIDInMainFrameProcess()); ++} ++ +std::optional WebPageProxy::permissionForAutomation(const String& origin, const String& permission) const +{ + auto permissions = m_permissionsForAutomation.find(origin); @@ -16934,15 +15810,17 @@ index 365c5e2c7925347531f2e488d720973612f25d39..585c51dd017a628f08d443c863fd1453 + +void WebPageProxy::logToStderr(const String& str) +{ ++WTF_ALLOW_UNSAFE_BUFFER_USAGE_BEGIN + fprintf(stderr, "RENDERER: %s\n", str.utf8().data()); ++WTF_ALLOW_UNSAFE_BUFFER_USAGE_END +} + - void WebPageProxy::createInspectorTarget(const String& targetId, Inspector::InspectorTargetType type) + void WebPageProxy::createInspectorTarget(IPC::Connection& connection, const String& targetId, Inspector::InspectorTargetType type) { - MESSAGE_CHECK(m_process, !targetId.isEmpty()); -@@ -2577,6 +2643,24 @@ void WebPageProxy::updateActivityState(OptionSet flagsToUpdate) + MESSAGE_CHECK_BASE(!targetId.isEmpty(), connection); +@@ -2955,6 +3061,24 @@ void WebPageProxy::updateActivityState(OptionSet flagsToUpdate) bool wasVisible = isViewVisible(); - Ref pageClient = this->pageClient(); + RefPtr pageClient = this->pageClient(); internals().activityState.remove(flagsToUpdate); + + if (m_activeForAutomation) { @@ -16965,37 +15843,37 @@ index 365c5e2c7925347531f2e488d720973612f25d39..585c51dd017a628f08d443c863fd1453 if (flagsToUpdate & ActivityState::IsFocused && pageClient->isViewFocused()) internals().activityState.add(ActivityState::IsFocused); if (flagsToUpdate & ActivityState::WindowIsActive && pageClient->isViewWindowActive()) -@@ -3302,7 +3386,7 @@ void WebPageProxy::performDragOperation(DragData& dragData, const String& dragSt - grantAccessToCurrentPasteboardData(dragStorageName); - #endif +@@ -3718,7 +3842,7 @@ void WebPageProxy::performDragOperation(DragData& dragData, const String& dragSt + if (!hasRunningProcess()) + return; -#if PLATFORM(GTK) +#if PLATFORM(GTK) || PLATFORM(WPE) - performDragControllerAction(DragControllerAction::PerformDragOperation, dragData); - #else - if (!hasRunningProcess()) -@@ -3319,6 +3403,8 @@ void WebPageProxy::performDragControllerAction(DragControllerAction action, Drag + URL url { dragData.asURL() }; + if (url.protocolIsFile()) + protectedLegacyMainFrameProcess()->assumeReadAccessToBaseURL(*this, url.string(), [] { }); +@@ -3746,6 +3870,8 @@ void WebPageProxy::performDragControllerAction(DragControllerAction action, Drag if (!hasRunningProcess()) return; + m_dragEventsQueued++; + auto completionHandler = [this, protectedThis = Ref { *this }, action, dragData] (std::optional dragOperation, WebCore::DragHandlingMethod dragHandlingMethod, bool mouseIsOverFileInput, unsigned numberOfItemsToBeAccepted, const IntRect& insertionRect, const IntRect& editableElementRect, std::optional remoteUserInputEventData) mutable { - if (!remoteUserInputEventData) { - didPerformDragControllerAction(dragOperation, dragHandlingMethod, mouseIsOverFileInput, numberOfItemsToBeAccepted, insertionRect, editableElementRect); -@@ -3335,6 +3421,8 @@ void WebPageProxy::performDragControllerAction(DragControllerAction action, Drag - protectedProcess()->assumeReadAccessToBaseURL(*this, url); - - ASSERT(dragData.platformData()); -+#endif + if (!m_pageClient) + return; +@@ -3757,7 +3883,7 @@ void WebPageProxy::performDragControllerAction(DragControllerAction action, Drag + dragData.setClientPosition(remoteUserInputEventData->transformedPoint); + performDragControllerAction(action, dragData, remoteUserInputEventData->targetFrameID); + }; +-#if PLATFORM(GTK) +#if PLATFORM(GTK) || PLATFORM(WPE) - sendWithAsyncReply(Messages::WebPage::PerformDragControllerAction(action, dragData.clientPosition(), dragData.globalPosition(), dragData.draggingSourceOperationMask(), *dragData.platformData(), dragData.flags()), WTFMove(completionHandler)); + ASSERT(dragData.platformData()); + sendWithAsyncReplyToProcessContainingFrame(frameID, Messages::WebPage::PerformDragControllerAction(action, dragData.clientPosition(), dragData.globalPosition(), dragData.draggingSourceOperationMask(), *dragData.platformData(), dragData.flags()), WTFMove(completionHandler)); #else - sendToProcessContainingFrame(frameID, Messages::WebPage::PerformDragControllerAction(frameID, action, dragData), WTFMove(completionHandler)); -@@ -3350,14 +3438,34 @@ void WebPageProxy::didPerformDragControllerAction(std::optionaldidPerformDragControllerAction(); + if (RefPtr pageClient = this->pageClient()) + pageClient->didPerformDragControllerAction(); + m_dragEventsQueued--; + if (m_dragEventsQueued == 0 && internals().mouseEventQueue.isEmpty()) + m_inspectorController->didProcessAllPendingMouseEvents(); @@ -17005,32 +15883,34 @@ index 365c5e2c7925347531f2e488d720973612f25d39..585c51dd017a628f08d443c863fd1453 +#if PLATFORM(GTK) || PLATFORM(WPE) void WebPageProxy::startDrag(SelectionData&& selectionData, OptionSet dragOperationMask, std::optional&& dragImageHandle, IntPoint&& dragImageHotspot) { -- RefPtr dragImage = dragImageHandle ? ShareableBitmap::create(WTFMove(*dragImageHandle)) : nullptr; -- protectedPageClient()->startDrag(WTFMove(selectionData), dragOperationMask, WTFMove(dragImage), WTFMove(dragImageHotspot)); +- if (RefPtr pageClient = this->pageClient()) { +- RefPtr dragImage = dragImageHandle ? ShareableBitmap::create(WTFMove(*dragImageHandle)) : nullptr; +- pageClient->startDrag(WTFMove(selectionData), dragOperationMask, WTFMove(dragImage), WTFMove(dragImageHotspot)); + if (m_interceptDrags) { + m_dragSelectionData = WTFMove(selectionData); + m_dragSourceOperationMask = dragOperationMask; + } else { +#if PLATFORM(GTK) -+ RefPtr dragImage = dragImageHandle ? ShareableBitmap::create(WTFMove(*dragImageHandle)) : nullptr; -+ protectedPageClient()->startDrag(WTFMove(selectionData), dragOperationMask, WTFMove(dragImage), WTFMove(dragImageHotspot)); ++ if (RefPtr pageClient = this->pageClient()) { ++ RefPtr dragImage = dragImageHandle ? ShareableBitmap::create(WTFMove(*dragImageHandle)) : nullptr; ++ pageClient->startDrag(WTFMove(selectionData), dragOperationMask, WTFMove(dragImage), WTFMove(dragImageHotspot)); ++ } +#endif + } + didStartDrag(); +} +#endif - ++ +#if PLATFORM(WIN) && ENABLE(DRAG_SUPPORT) +void WebPageProxy::startDrag(WebCore::DragDataMap&& dragDataMap) +{ + if (m_interceptDrags) { + m_dragSelectionData = WTFMove(dragDataMap); + m_dragSourceOperationMask = WebCore::anyDragOperation(); -+ } + } didStartDrag(); } - #endif -@@ -3378,6 +3486,24 @@ void WebPageProxy::dragEnded(const IntPoint& clientPosition, const IntPoint& glo +@@ -3821,6 +3968,24 @@ void WebPageProxy::dragEnded(const IntPoint& clientPosition, const IntPoint& glo setDragCaretRect({ }); } @@ -17055,24 +15935,34 @@ index 365c5e2c7925347531f2e488d720973612f25d39..585c51dd017a628f08d443c863fd1453 void WebPageProxy::didStartDrag() { if (!hasRunningProcess()) -@@ -3385,6 +3511,16 @@ void WebPageProxy::didStartDrag() +@@ -3828,6 +3993,26 @@ void WebPageProxy::didStartDrag() discardQueuedMouseEvents(); send(Messages::WebPage::DidStartDrag()); + + if (m_interceptDrags) { ++ { ++#if PLATFORM(WIN) || PLATFORM(COCOA) ++ DragData dragData(*m_dragSelectionData, m_lastMousePositionForDrag, WebCore::IntPoint(), m_dragSourceOperationMask); ++#else ++ DragData dragData(&*m_dragSelectionData, m_lastMousePositionForDrag, WebCore::IntPoint(), m_dragSourceOperationMask); ++#endif ++ dragEntered(dragData); ++ } ++ ++ { +#if PLATFORM(WIN) || PLATFORM(COCOA) -+ DragData dragData(*m_dragSelectionData, m_lastMousePositionForDrag, WebCore::IntPoint(), m_dragSourceOperationMask); ++ DragData dragData(*m_dragSelectionData, m_lastMousePositionForDrag, WebCore::IntPoint(), m_dragSourceOperationMask); +#else -+ DragData dragData(&*m_dragSelectionData, m_lastMousePositionForDrag, WebCore::IntPoint(), m_dragSourceOperationMask); ++ DragData dragData(&*m_dragSelectionData, m_lastMousePositionForDrag, WebCore::IntPoint(), m_dragSourceOperationMask); +#endif -+ dragEntered(dragData); -+ dragUpdated(dragData); ++ dragUpdated(dragData); ++ } + } } void WebPageProxy::dragCancelled() -@@ -3540,16 +3676,37 @@ void WebPageProxy::processNextQueuedMouseEvent() +@@ -3999,26 +4184,47 @@ void WebPageProxy::processNextQueuedMouseEvent() process->startResponsivenessTimer(); } @@ -17090,10 +15980,26 @@ index 365c5e2c7925347531f2e488d720973612f25d39..585c51dd017a628f08d443c863fd1453 + sandboxExtensions = SandboxExtension::createHandlesForMachLookup({ "com.apple.iconservices"_s, "com.apple.iconservices.store"_s }, process->auditToken(), SandboxExtension::MachBootstrapOptions::EnableMachBootstrap); #endif -- LOG_WITH_STREAM(MouseHandling, stream << "UIProcess: sent mouse event " << eventType << " (queue size " << internals().mouseEventQueue.size() << ")"); -- sendMouseEvent(m_mainFrame->frameID(), event, WTFMove(sandboxExtensions)); -+ LOG_WITH_STREAM(MouseHandling, stream << "UIProcess: sent mouse event " << eventType << " (queue size " << internals().mouseEventQueue.size() << ")"); -+ sendMouseEvent(m_mainFrame->frameID(), event, WTFMove(sandboxExtensions)); +- auto eventWithCoalescedEvents = event; ++ auto eventWithCoalescedEvents = event; + +- if (event.type() == WebEventType::MouseMove) { +- internals().coalescedMouseEvents.append(event); +- eventWithCoalescedEvents.setCoalescedEvents(internals().coalescedMouseEvents); +- } ++ if (event.type() == WebEventType::MouseMove) { ++ internals().coalescedMouseEvents.append(event); ++ eventWithCoalescedEvents.setCoalescedEvents(internals().coalescedMouseEvents); ++ } + +- LOG_WITH_STREAM(MouseHandling, stream << "UIProcess: sent mouse event " << eventType << " (queue size " << internals().mouseEventQueue.size() << ", coalesced events size " << internals().coalescedMouseEvents.size() << ")"); ++ LOG_WITH_STREAM(MouseHandling, stream << "UIProcess: sent mouse event " << eventType << " (queue size " << internals().mouseEventQueue.size() << ", coalesced events size " << internals().coalescedMouseEvents.size() << ")"); + +- sendMouseEvent(m_mainFrame->frameID(), eventWithCoalescedEvents, WTFMove(sandboxExtensions)); ++ sendMouseEvent(m_mainFrame->frameID(), eventWithCoalescedEvents, WTFMove(sandboxExtensions)); + +- internals().coalescedMouseEvents.clear(); ++ internals().coalescedMouseEvents.clear(); + } else { +#if PLATFORM(WIN) || PLATFORM(COCOA) + DragData dragData(*m_dragSelectionData, event.position(), event.globalPosition(), m_dragSourceOperationMask); @@ -17111,91 +16017,82 @@ index 365c5e2c7925347531f2e488d720973612f25d39..585c51dd017a628f08d443c863fd1453 + m_dragSelectionData = std::nullopt; + dragEnded(event.position(), event.globalPosition(), m_dragSourceOperationMask); + } -+ didReceiveEvent(eventType, true); ++ didReceiveEventIPC(process->connection(), eventType, true, std::nullopt); + } } void WebPageProxy::doAfterProcessingAllPendingMouseEvents(WTF::Function&& action) -@@ -3715,6 +3872,8 @@ void WebPageProxy::wheelEventHandlingCompleted(bool wasHandled) +@@ -4215,6 +4421,8 @@ void WebPageProxy::wheelEventHandlingCompleted(bool wasHandled) - if (RefPtr automationSession = process().processPool().automationSession()) + if (RefPtr automationSession = m_configuration->processPool().automationSession()) automationSession->wheelEventsFlushedForPage(*this); + + m_inspectorController->didProcessAllPendingWheelEvents(); } void WebPageProxy::cacheWheelEventScrollingAccelerationCurve(const NativeWebWheelEvent& nativeWheelEvent) -@@ -3863,7 +4022,7 @@ static TrackingType mergeTrackingTypes(TrackingType a, TrackingType b) +@@ -4351,7 +4559,7 @@ static TrackingType mergeTrackingTypes(TrackingType a, TrackingType b) void WebPageProxy::updateTouchEventTracking(const WebTouchEvent& touchStartEvent) { -#if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA) +#if ENABLE(ASYNC_SCROLLING) && PLATFORM(IOS_FAMILY) for (auto& touchPoint : touchStartEvent.touchPoints()) { - auto location = touchPoint.location(); + auto location = touchPoint.locationInRootView(); auto update = [this, location](TrackingType& trackingType, EventTrackingRegions::EventType eventType) { -@@ -4460,6 +4619,7 @@ void WebPageProxy::receivedNavigationActionPolicyDecision(WebProcessProxy& proce +@@ -5012,6 +5220,7 @@ void WebPageProxy::receivedNavigationActionPolicyDecision(WebProcessProxy& proce void WebPageProxy::receivedPolicyDecision(PolicyAction action, API::Navigation* navigation, RefPtr&& websitePolicies, Ref&& navigationAction, WillContinueLoadInNewProcess willContinueLoadInNewProcess, std::optional sandboxExtensionHandle, std::optional&& consoleMessage, CompletionHandler&& completionHandler) { -+ m_inspectorController->didReceivePolicyDecision(action, navigation ? navigation->navigationID() : 0); ++ m_inspectorController->didReceivePolicyDecision(action, navigation ? std::optional { navigation->navigationID() } : std::nullopt); if (!hasRunningProcess()) return completionHandler(PolicyDecision { }); -@@ -5382,6 +5542,11 @@ void WebPageProxy::pageScaleFactorDidChange(double scaleFactor) - m_pageScaleFactor = scaleFactor; - } - -+void WebPageProxy::viewScaleFactorDidChange(double scaleFactor) -+{ +@@ -6013,6 +6222,7 @@ void WebPageProxy::viewScaleFactorDidChange(IPC::Connection& connection, double + MESSAGE_CHECK_BASE(scaleFactorIsValid(scaleFactor), connection); + if (!legacyMainFrameProcess().hasConnection(connection)) + return; + m_viewScaleFactor = scaleFactor; -+} -+ - void WebPageProxy::pluginScaleFactorDidChange(double pluginScaleFactor) - { - MESSAGE_CHECK(m_process, scaleFactorIsValid(pluginScaleFactor)); -@@ -5935,6 +6100,7 @@ void WebPageProxy::didDestroyNavigationShared(Ref&& process, ui - Ref protectedPageClient { pageClient() }; - m_navigationState->didDestroyNavigation(process->coreProcessIdentifier(), navigationID); + forEachWebContentProcess([&] (auto& process, auto pageID) { + if (&process == &legacyMainFrameProcess()) +@@ -6664,6 +6874,7 @@ void WebPageProxy::didDestroyNavigationShared(Ref&& process, We + RefPtr protectedPageClient { pageClient() }; + + protectedNavigationState()->didDestroyNavigation(process->coreProcessIdentifier(), navigationID); + m_inspectorController->didDestroyNavigation(navigationID); } - void WebPageProxy::didStartProvisionalLoadForFrame(FrameIdentifier frameID, FrameInfoData&& frameInfo, ResourceRequest&& request, uint64_t navigationID, URL&& url, URL&& unreachableURL, const UserData& userData) -@@ -6189,6 +6355,8 @@ void WebPageProxy::didFailProvisionalLoadForFrameShared(Ref&& p + void WebPageProxy::didStartProvisionalLoadForFrame(IPC::Connection& connection, FrameIdentifier frameID, FrameInfoData&& frameInfo, ResourceRequest&& request, std::optional navigationID, URL&& url, URL&& unreachableURL, const UserData& userData, WallTime timestamp) +@@ -7008,6 +7219,8 @@ void WebPageProxy::didFailProvisionalLoadForFrameShared(Ref&& p m_failingProvisionalLoadURL = { }; -+ m_inspectorController->didFailProvisionalLoadForFrame(navigationID, error); ++ m_inspectorController->didFailProvisionalLoadForFrame(*navigationID, error); + // If the provisional page's load fails then we destroy the provisional page. if (m_provisionalPage && m_provisionalPage->mainFrame() == &frame && willContinueLoading == WillContinueLoading::No) m_provisionalPage = nullptr; -@@ -6834,7 +7002,14 @@ void WebPageProxy::beginSafeBrowsingCheck(const URL&, bool, WebFramePolicyListen - - void WebPageProxy::decidePolicyForNavigationActionAsync(NavigationActionData&& data, CompletionHandler&& completionHandler) - { -- decidePolicyForNavigationActionAsyncShared(protectedProcess(), WTFMove(data), WTFMove(completionHandler)); -+ if (m_inspectorController->shouldPauseLoading()) { -+ decidePolicyForNavigationActionAsyncShared(protectedProcess(), WTFMove(data), WTFMove(completionHandler)); -+ m_inspectorController->setContinueLoadingCallback([this, protectedThis = Ref { *this }, data = WTFMove(data), completionHandler = WTFMove(completionHandler)] () mutable { -+ decidePolicyForNavigationActionAsyncShared(protectedProcess(), WTFMove(data), WTFMove(completionHandler)); -+ }); -+ } else { -+ decidePolicyForNavigationActionAsyncShared(protectedProcess(), WTFMove(data), WTFMove(completionHandler)); -+ } - } - - void WebPageProxy::decidePolicyForNavigationActionAsyncShared(Ref&& process, NavigationActionData&& data, CompletionHandler&& completionHandler) -@@ -7474,6 +7649,7 @@ void WebPageProxy::createNewPage(WindowFeatures&& windowFeatures, NavigationActi +@@ -8536,8 +8749,9 @@ void WebPageProxy::createNewPage(IPC::Connection& connection, WindowFeatures&& w if (RefPtr page = originatingFrameInfo->page()) openerAppInitiatedState = page->lastNavigationWasAppInitiated(); +- auto navigationDataForNewProcess = navigationActionData.hasOpener ? nullptr : makeUnique(navigationActionData); + m_inspectorController->willCreateNewPage(windowFeatures, request.url()); + ++ auto navigationDataForNewProcess = navigationActionData.hasOpener ? nullptr : makeUnique(navigationActionData); auto completionHandler = [ this, protectedThis = Ref { *this }, -@@ -7540,6 +7716,7 @@ void WebPageProxy::createNewPage(WindowFeatures&& windowFeatures, NavigationActi +@@ -8617,6 +8831,7 @@ void WebPageProxy::createNewPage(IPC::Connection& connection, WindowFeatures&& w + configuration->setOpenedMainFrameName(openedMainFrameName); + if (!protectedPreferences()->siteIsolationEnabled()) + configuration->setRelatedPage(*this); ++ configuration->setOpenerPageForInspector(*this); + + if (RefPtr openerFrame = WebFrameProxy::webFrame(originatingFrameInfoData.frameID); navigationActionData.hasOpener && openerFrame) { + configuration->setOpenerInfo({ { +@@ -8644,6 +8859,7 @@ void WebPageProxy::createNewPage(IPC::Connection& connection, WindowFeatures&& w void WebPageProxy::showPage() { m_uiClient->showPage(this); @@ -17203,7 +16100,7 @@ index 365c5e2c7925347531f2e488d720973612f25d39..585c51dd017a628f08d443c863fd1453 } bool WebPageProxy::hasOpenedPage() const -@@ -7621,6 +7798,10 @@ void WebPageProxy::closePage() +@@ -8775,6 +8991,10 @@ void WebPageProxy::closePage() if (isClosed()) return; @@ -17212,36 +16109,36 @@ index 365c5e2c7925347531f2e488d720973612f25d39..585c51dd017a628f08d443c863fd1453 + m_activeContextMenu->hide(); +#endif WEBPAGEPROXY_RELEASE_LOG(Process, "closePage:"); - protectedPageClient()->clearAllEditCommands(); - m_uiClient->close(this); -@@ -7657,6 +7838,8 @@ void WebPageProxy::runJavaScriptAlert(FrameIdentifier frameID, FrameInfoData&& f + if (RefPtr pageClient = this->pageClient()) + pageClient->clearAllEditCommands(); +@@ -8813,6 +9033,8 @@ void WebPageProxy::runJavaScriptAlert(IPC::Connection& connection, FrameIdentifi } - runModalJavaScriptDialog(WTFMove(frame), WTFMove(frameInfo), message, [reply = WTFMove(reply)](WebPageProxy& page, WebFrameProxy* frame, FrameInfoData&& frameInfo, const String& message, CompletionHandler&& completion) mutable { + runModalJavaScriptDialog(WTFMove(frame), WTFMove(frameInfo), WTFMove(message), [reply = WTFMove(reply)](WebPageProxy& page, WebFrameProxy* frame, FrameInfoData&& frameInfo, String&& message, CompletionHandler&& completion) mutable { + if (page.m_inspectorDialogAgent) + page.m_inspectorDialogAgent->javascriptDialogOpening("alert"_s, message); - page.m_uiClient->runJavaScriptAlert(page, message, frame, WTFMove(frameInfo), [reply = WTFMove(reply), completion = WTFMove(completion)]() mutable { + page.m_uiClient->runJavaScriptAlert(page, WTFMove(message), frame, WTFMove(frameInfo), [reply = WTFMove(reply), completion = WTFMove(completion)]() mutable { reply(); completion(); -@@ -7678,6 +7861,8 @@ void WebPageProxy::runJavaScriptConfirm(FrameIdentifier frameID, FrameInfoData&& - if (RefPtr automationSession = process().processPool().automationSession()) - automationSession->willShowJavaScriptDialog(*this); +@@ -8835,6 +9057,8 @@ void WebPageProxy::runJavaScriptConfirm(IPC::Connection& connection, FrameIdenti + if (RefPtr automationSession = configuration().processPool().automationSession()) + automationSession->willShowJavaScriptDialog(*this, message, std::nullopt); } + if (m_inspectorDialogAgent) + m_inspectorDialogAgent->javascriptDialogOpening("confirm"_s, message); - runModalJavaScriptDialog(WTFMove(frame), WTFMove(frameInfo), message, [reply = WTFMove(reply)](WebPageProxy& page, WebFrameProxy* frame, FrameInfoData&& frameInfo, const String& message, CompletionHandler&& completion) mutable { - page.m_uiClient->runJavaScriptConfirm(page, message, frame, WTFMove(frameInfo), [reply = WTFMove(reply), completion = WTFMove(completion)](bool result) mutable { -@@ -7701,6 +7886,8 @@ void WebPageProxy::runJavaScriptPrompt(FrameIdentifier frameID, FrameInfoData&& - if (RefPtr automationSession = process().processPool().automationSession()) - automationSession->willShowJavaScriptDialog(*this); + runModalJavaScriptDialog(WTFMove(frame), WTFMove(frameInfo), WTFMove(message), [reply = WTFMove(reply)](WebPageProxy& page, WebFrameProxy* frame, FrameInfoData&& frameInfo, String&& message, CompletionHandler&& completion) mutable { + page.m_uiClient->runJavaScriptConfirm(page, WTFMove(message), frame, WTFMove(frameInfo), [reply = WTFMove(reply), completion = WTFMove(completion)](bool result) mutable { +@@ -8859,6 +9083,8 @@ void WebPageProxy::runJavaScriptPrompt(IPC::Connection& connection, FrameIdentif + if (RefPtr automationSession = configuration().processPool().automationSession()) + automationSession->willShowJavaScriptDialog(*this, message, defaultValue); } + if (m_inspectorDialogAgent) + m_inspectorDialogAgent->javascriptDialogOpening("prompt"_s, message, defaultValue); - runModalJavaScriptDialog(WTFMove(frame), WTFMove(frameInfo), message, [reply = WTFMove(reply), defaultValue](WebPageProxy& page, WebFrameProxy* frame, FrameInfoData&& frameInfo, const String& message, CompletionHandler&& completion) mutable { - page.m_uiClient->runJavaScriptPrompt(page, message, defaultValue, frame, WTFMove(frameInfo), [reply = WTFMove(reply), completion = WTFMove(completion)](auto& result) mutable { -@@ -7817,6 +8004,8 @@ void WebPageProxy::runBeforeUnloadConfirmPanel(FrameIdentifier frameID, FrameInf + runModalJavaScriptDialog(WTFMove(frame), WTFMove(frameInfo), WTFMove(message), [reply = WTFMove(reply), defaultValue= WTFMove(defaultValue)](WebPageProxy& page, WebFrameProxy* frame, FrameInfoData&& frameInfo, String&& message, CompletionHandler&& completion) mutable { + page.m_uiClient->runJavaScriptPrompt(page, WTFMove(message), WTFMove(defaultValue), frame, WTFMove(frameInfo), [reply = WTFMove(reply), completion = WTFMove(completion)](auto& result) mutable { +@@ -9000,6 +9226,8 @@ void WebPageProxy::runBeforeUnloadConfirmPanel(IPC::Connection& connection, Fram return; } } @@ -17249,8 +16146,8 @@ index 365c5e2c7925347531f2e488d720973612f25d39..585c51dd017a628f08d443c863fd1453 + m_inspectorDialogAgent->javascriptDialogOpening("beforeunload"_s, message); // Since runBeforeUnloadConfirmPanel() can spin a nested run loop we need to turn off the responsiveness timer and the tryClose timer. - protectedProcess()->stopResponsivenessTimer(); -@@ -8307,6 +8496,11 @@ void WebPageProxy::resourceLoadDidCompleteWithError(ResourceLoadInfo&& loadInfo, + webProcess->stopResponsivenessTimer(); +@@ -9626,6 +9854,11 @@ void WebPageProxy::resourceLoadDidCompleteWithError(ResourceLoadInfo&& loadInfo, } #if ENABLE(FULLSCREEN_API) @@ -17262,26 +16159,26 @@ index 365c5e2c7925347531f2e488d720973612f25d39..585c51dd017a628f08d443c863fd1453 WebFullScreenManagerProxy* WebPageProxy::fullScreenManager() { return m_fullScreenManager.get(); -@@ -8383,6 +8577,17 @@ void WebPageProxy::requestDOMPasteAccess(WebCore::DOMPasteAccessCategory pasteAc - { - MESSAGE_CHECK_COMPLETION(m_process, !originIdentifier.isEmpty(), completionHandler(DOMPasteAccessResponse::DeniedForGesture)); +@@ -9753,6 +9986,17 @@ void WebPageProxy::requestDOMPasteAccess(IPC::Connection& connection, DOMPasteAc + } + } + if (isControlledByAutomation()) { + DOMPasteAccessResponse response = DOMPasteAccessResponse::DeniedForGesture; + if (permissionForAutomation(originIdentifier, "clipboard-read"_s).value_or(false)) { + response = DOMPasteAccessResponse::GrantedForGesture; + // Grant access to general pasteboard. -+ willPerformPasteCommand(DOMPasteAccessCategory::General); ++ willPerformPasteCommand(DOMPasteAccessCategory::General, [] () { }, frameID); + } + completionHandler(response); + return; + } + - m_pageClient->requestDOMPasteAccess(pasteAccessCategory, elementRect, originIdentifier, WTFMove(completionHandler)); + protectedPageClient()->requestDOMPasteAccess(pasteAccessCategory, requiresInteraction, elementRect, originIdentifier, WTFMove(completionHandler)); } -@@ -9232,6 +9437,8 @@ void WebPageProxy::mouseEventHandlingCompleted(std::optional event - if (RefPtr automationSession = process().processPool().automationSession()) +@@ -10795,6 +11039,8 @@ void WebPageProxy::mouseEventHandlingCompleted(std::optional event + if (RefPtr automationSession = configuration().processPool().automationSession()) automationSession->mouseEventsFlushedForPage(*this); didFinishProcessingAllPendingMouseEvents(); + if (m_dragEventsQueued == 0) @@ -17289,17 +16186,17 @@ index 365c5e2c7925347531f2e488d720973612f25d39..585c51dd017a628f08d443c863fd1453 } } -@@ -9266,6 +9473,7 @@ void WebPageProxy::keyEventHandlingCompleted(std::optional eventTy +@@ -10830,6 +11076,7 @@ void WebPageProxy::keyEventHandlingCompleted(std::optional eventTy if (!canProcessMoreKeyEvents) { - if (RefPtr automationSession = process().processPool().automationSession()) + if (RefPtr automationSession = configuration().processPool().automationSession()) automationSession->keyboardEventsFlushedForPage(*this); + m_inspectorController->didProcessAllPendingKeyboardEvents(); } } -@@ -9671,7 +9879,10 @@ void WebPageProxy::dispatchProcessDidTerminate(ProcessTerminationReason reason) - { - WEBPAGEPROXY_RELEASE_LOG_ERROR(Loading, "dispatchProcessDidTerminate: reason=%" PUBLIC_LOG_STRING, processTerminationReasonToString(reason).characters()); +@@ -11262,7 +11509,10 @@ void WebPageProxy::dispatchProcessDidTerminate(WebProcessProxy& process, Process + if (protectedPreferences()->siteIsolationEnabled()) + protectedBrowsingContextGroup()->processDidTerminate(*this, process); - bool handledByClient = false; + bool handledByClient = m_inspectorController->pageCrashed(reason); @@ -17309,26 +16206,18 @@ index 365c5e2c7925347531f2e488d720973612f25d39..585c51dd017a628f08d443c863fd1453 if (m_loaderClient) handledByClient = reason != ProcessTerminationReason::RequestedByClient && m_loaderClient->processDidCrash(*this); else -@@ -10041,6 +10252,7 @@ bool WebPageProxy::useGPUProcessForDOMRenderingEnabled() const - - WebPageCreationParameters WebPageProxy::creationParameters(WebProcessProxy& process, DrawingAreaProxy& drawingArea, std::optional&& subframeProcessPageParameters, bool isProcessSwap, RefPtr&& websitePolicies, std::optional&& mainFrameIdentifier, std::optional topContentInset) - { -+ - WebPageCreationParameters parameters; - - parameters.processDisplayName = configuration().processDisplayName(); -@@ -10267,6 +10479,8 @@ WebPageCreationParameters WebPageProxy::creationParameters(WebProcessProxy& proc +@@ -11913,6 +12163,8 @@ WebPageCreationParameters WebPageProxy::creationParameters(WebProcessProxy& proc + parameters.canUseCredentialStorage = m_canUseCredentialStorage; - parameters.httpsUpgradeEnabled = preferences().upgradeKnownHostsToHTTPSEnabled() ? m_configuration->httpsUpgradeEnabled() : false; - -+ parameters.shouldPauseInInspectorWhenShown = m_inspectorController->shouldPauseLoading(); + parameters.httpsUpgradeEnabled = preferences->upgradeKnownHostsToHTTPSEnabled() ? m_configuration->httpsUpgradeEnabled() : false; + - #if PLATFORM(IOS) || PLATFORM(VISION) - // FIXME: This is also being passed over the to WebProcess via the PreferencesStore. - parameters.allowsDeprecatedSynchronousXMLHttpRequestDuringUnload = allowsDeprecatedSynchronousXMLHttpRequestDuringUnload(); -@@ -10373,8 +10587,42 @@ void WebPageProxy::gamepadActivity(const Vector>& gam ++ parameters.shouldPauseInInspectorWhenShown = m_inspectorController->shouldPauseInInspectorWhenShown(); + + #if ENABLE(APP_HIGHLIGHTS) + parameters.appHighlightsVisible = appHighlightsVisibility() ? HighlightVisibility::Visible : HighlightVisibility::Hidden; +@@ -12081,8 +12333,47 @@ void WebPageProxy::allowGamepadAccess() - #endif + #endif // ENABLE(GAMEPAD) +bool WebPageProxy::shouldSendAutomationCredentialsForProtectionSpace(const WebProtectionSpace& protectionSpace) +{ @@ -17357,6 +16246,11 @@ index 365c5e2c7925347531f2e488d720973612f25d39..585c51dd017a628f08d443c863fd1453 + void WebPageProxy::didReceiveAuthenticationChallengeProxy(Ref&& authenticationChallenge, NegotiatedLegacyTLS negotiatedLegacyTLS) { ++ if (authenticationChallenge->core().protectionSpace().authenticationScheme() == WebCore::ProtectionSpaceBaseAuthenticationScheme::ServerTrustEvaluationRequested && websiteDataStore().ignoreTLSErrors()) { ++ authenticationChallenge->listener().completeChallenge(AuthenticationChallengeDisposition::UseCredential, WebCore::Credential("accept server trust"_s, ""_s, WebCore::CredentialPersistence::None)); ++ return; ++ } ++ + if (m_credentialsForAutomation.has_value()) { + if (m_credentialsForAutomation->isEmpty() || authenticationChallenge->core().previousFailureCount() || + !shouldSendAutomationCredentialsForProtectionSpace(*authenticationChallenge->protectionSpace())) { @@ -17369,7 +16263,7 @@ index 365c5e2c7925347531f2e488d720973612f25d39..585c51dd017a628f08d443c863fd1453 if (negotiatedLegacyTLS == NegotiatedLegacyTLS::Yes) { m_navigationClient->shouldAllowLegacyTLS(*this, authenticationChallenge.get(), [this, protectedThis = Ref { *this }, authenticationChallenge] (bool shouldAllowLegacyTLS) { if (shouldAllowLegacyTLS) -@@ -10469,6 +10717,12 @@ void WebPageProxy::requestGeolocationPermissionForFrame(GeolocationIdentifier ge +@@ -12178,6 +12469,12 @@ void WebPageProxy::requestGeolocationPermissionForFrame(IPC::Connection& connect request->deny(); }; @@ -17382,7 +16276,7 @@ index 365c5e2c7925347531f2e488d720973612f25d39..585c51dd017a628f08d443c863fd1453 // FIXME: Once iOS migrates to the new WKUIDelegate SPI, clean this up // and make it one UIClient call that calls the completionHandler with false // if there is no delegate instead of returning the completionHandler -@@ -10531,6 +10785,12 @@ void WebPageProxy::queryPermission(const ClientOrigin& clientOrigin, const Permi +@@ -12244,6 +12541,12 @@ void WebPageProxy::queryPermission(const ClientOrigin& clientOrigin, const Permi shouldChangeDeniedToPrompt = false; if (sessionID().isEphemeral()) { @@ -17395,7 +16289,7 @@ index 365c5e2c7925347531f2e488d720973612f25d39..585c51dd017a628f08d443c863fd1453 completionHandler(shouldChangeDeniedToPrompt ? PermissionState::Prompt : PermissionState::Denied); return; } -@@ -10545,6 +10805,12 @@ void WebPageProxy::queryPermission(const ClientOrigin& clientOrigin, const Permi +@@ -12258,6 +12561,12 @@ void WebPageProxy::queryPermission(const ClientOrigin& clientOrigin, const Permi return; } @@ -17409,7 +16303,7 @@ index 365c5e2c7925347531f2e488d720973612f25d39..585c51dd017a628f08d443c863fd1453 completionHandler(shouldChangeDeniedToPrompt ? PermissionState::Prompt : PermissionState::Denied); return; diff --git a/Source/WebKit/UIProcess/WebPageProxy.h b/Source/WebKit/UIProcess/WebPageProxy.h -index 2e40bbb43a05c10eee30296c5a7febdcdb74c157..4deb131a7c531d9035833f22062cf9e8f0aa3a6c 100644 +index c220a17ba9d98b37e16bea6ef2c37ffd4599c906..d5e57548822361620b9a18c283e5e5e6821de584 100644 --- a/Source/WebKit/UIProcess/WebPageProxy.h +++ b/Source/WebKit/UIProcess/WebPageProxy.h @@ -26,6 +26,7 @@ @@ -17418,9 +16312,9 @@ index 2e40bbb43a05c10eee30296c5a7febdcdb74c157..4deb131a7c531d9035833f22062cf9e8 #include "APIObject.h" +#include "APIWebsitePolicies.h" #include "MessageReceiver.h" - #include "MessageSender.h" - #include -@@ -36,6 +37,24 @@ + #include + #include +@@ -46,6 +47,20 @@ #include #include #include @@ -17435,33 +16329,21 @@ index 2e40bbb43a05c10eee30296c5a7febdcdb74c157..4deb131a7c531d9035833f22062cf9e8 + +OBJC_CLASS NSPasteboard; + -+#if PLATFORM(WPE) -+#include "ArgumentCodersWPE.h" -+#endif -+ +#if PLATFORM(GTK) || PLATFORM(WPE) +#include +#endif #if USE(DICTATION_ALTERNATIVES) #include -@@ -106,6 +125,7 @@ class DestinationColorSpace; - class DragData; +@@ -130,6 +145,7 @@ class DragData; + class Exception; class FloatPoint; class FloatQuad; -+typedef HashMap> DragDataMap; ++typedef UncheckedKeyHashMap> DragDataMap; class FloatRect; class FloatSize; class FontAttributeChanges; -@@ -421,6 +441,7 @@ class WebExtensionController; - class WebFramePolicyListenerProxy; - class WebFrameProxy; - class WebFullScreenManagerProxy; -+class WebFullScreenManagerProxyClient; - class WebInspectorUIProxy; - class WebKeyboardEvent; - class WebMouseEvent; -@@ -649,6 +670,8 @@ public: +@@ -735,6 +751,8 @@ public: void setControlledByAutomation(bool); WebPageInspectorController& inspectorController() { return *m_inspectorController; } @@ -17470,59 +16352,53 @@ index 2e40bbb43a05c10eee30296c5a7febdcdb74c157..4deb131a7c531d9035833f22062cf9e8 #if PLATFORM(IOS_FAMILY) void showInspectorIndication(); -@@ -682,6 +705,7 @@ public: +@@ -768,6 +786,7 @@ public: bool hasSleepDisabler() const; #if ENABLE(FULLSCREEN_API) + void setFullScreenManagerClientOverride(std::unique_ptr&&); WebFullScreenManagerProxy* fullScreenManager(); + RefPtr protectedFullScreenManager(); + void setFullScreenClientForTesting(std::unique_ptr&&); +@@ -859,6 +878,12 @@ public: - API::FullscreenClient& fullscreenClient() const { return *m_fullscreenClient; } -@@ -770,6 +794,11 @@ public: - - void setPageLoadStateObserver(std::unique_ptr&&); + void setPageLoadStateObserver(RefPtr&&); + void setAuthCredentialsForAutomation(std::optional&&, std::optional&&); -+ void setPermissionsForAutomation(const HashMap>&); ++ void setPermissionsForAutomation(const UncheckedKeyHashMap>&); ++ void setOrientationOverride(std::optional&& angle); + void setActiveForAutomation(std::optional active); + void logToStderr(const String& str); + - void initializeWebPage(); - void setDrawingArea(std::unique_ptr&&); + void initializeWebPage(const WebCore::Site&, WebCore::SandboxFlags); + void setDrawingArea(RefPtr&&); + +@@ -890,6 +915,8 @@ public: + RefPtr loadRequest(WebCore::ResourceRequest&&, WebCore::ShouldOpenExternalURLsPolicy, WebCore::IsPerformingHTTPFallback); + RefPtr loadRequest(WebCore::ResourceRequest&&, WebCore::ShouldOpenExternalURLsPolicy, WebCore::IsPerformingHTTPFallback, std::unique_ptr&&, API::Object* userData = nullptr); -@@ -796,6 +825,7 @@ public: - void addPlatformLoadParameters(WebProcessProxy&, LoadParameters&); - RefPtr loadRequest(WebCore::ResourceRequest&&); - RefPtr loadRequest(WebCore::ResourceRequest&&, WebCore::ShouldOpenExternalURLsPolicy, API::Object* userData = nullptr); + RefPtr loadRequestForInspector(WebCore::ResourceRequest&&, WebFrameProxy*); ++ RefPtr loadFile(const String& fileURL, const String& resourceDirectoryURL, bool isAppInitiated = true, API::Object* userData = nullptr); - RefPtr loadData(std::span, const String& MIMEType, const String& encoding, const String& baseURL, API::Object* userData = nullptr); - RefPtr loadData(std::span, const String& MIMEType, const String& encoding, const String& baseURL, API::Object* userData, WebCore::ShouldOpenExternalURLsPolicy); -@@ -862,6 +892,7 @@ public: + RefPtr loadData(Ref&&, const String& MIMEType, const String& encoding, const String& baseURL, API::Object* userData = nullptr); + RefPtr loadData(Ref&&, const String& MIMEType, const String& encoding, const String& baseURL, API::Object* userData, WebCore::ShouldOpenExternalURLsPolicy); +@@ -978,6 +1005,7 @@ public: - PageClient& pageClient() const; - Ref protectedPageClient() const; + PageClient* pageClient() const; + RefPtr protectedPageClient() const; + bool hasPageClient() const { return !!m_pageClient; } void setViewNeedsDisplay(const WebCore::Region&); void requestScroll(const WebCore::FloatPoint& scrollPosition, const WebCore::IntPoint& scrollOrigin, WebCore::ScrollIsAnimated); -@@ -1389,6 +1420,7 @@ public: - #endif - - void pageScaleFactorDidChange(double); -+ void viewScaleFactorDidChange(double); - void pluginScaleFactorDidChange(double); - void pluginZoomFactorDidChange(double); - -@@ -1473,14 +1505,20 @@ public: +@@ -1620,17 +1648,23 @@ public: void didStartDrag(); void dragCancelled(); void setDragCaretRect(const WebCore::IntRect&); + void setInterceptDrags(bool shouldIntercept); + bool cancelDragIfNeeded(); #if PLATFORM(COCOA) - void startDrag(const WebCore::DragItem&, WebCore::ShareableBitmapHandle&& dragImageHandle); - void setPromisedDataForImage(const String& pasteboardName, WebCore::SharedMemoryHandle&& imageHandle, const String& filename, const String& extension, + void startDrag(const WebCore::DragItem&, WebCore::ShareableBitmapHandle&& dragImageHandle, const std::optional&); + void setPromisedDataForImage(IPC::Connection&, const String& pasteboardName, WebCore::SharedMemoryHandle&& imageHandle, const String& filename, const String& extension, const String& title, const String& url, const String& visibleURL, WebCore::SharedMemoryHandle&& archiveHandle, const String& originIdentifier); + void releaseInspectorDragPasteboard(); #endif @@ -17530,13 +16406,16 @@ index 2e40bbb43a05c10eee30296c5a7febdcdb74c157..4deb131a7c531d9035833f22062cf9e8 +#if PLATFORM(GTK) || PLATFORM(WPE) void startDrag(WebCore::SelectionData&&, OptionSet, std::optional&& dragImage, WebCore::IntPoint&& dragImageHotspot); #endif + #if ENABLE(MODEL_PROCESS) + void modelDragEnded(const WebCore::ElementIdentifier); + #endif +#if PLATFORM(WIN) + void startDrag(WebCore::DragDataMap&& dragDataMap); +#endif #endif void processDidBecomeUnresponsive(); -@@ -1713,6 +1751,7 @@ public: +@@ -1883,6 +1917,7 @@ public: void setViewportSizeForCSSViewportUnits(const WebCore::FloatSize&); WebCore::FloatSize viewportSizeForCSSViewportUnits() const; @@ -17544,16 +16423,16 @@ index 2e40bbb43a05c10eee30296c5a7febdcdb74c157..4deb131a7c531d9035833f22062cf9e8 void didReceiveAuthenticationChallengeProxy(Ref&&, NegotiatedLegacyTLS); void negotiatedLegacyTLS(); void didNegotiateModernTLS(const URL&); -@@ -1747,6 +1786,8 @@ public: - +@@ -1916,6 +1951,8 @@ public: #if PLATFORM(COCOA) || PLATFORM(GTK) RefPtr takeViewSnapshot(std::optional&&); + RefPtr takeViewSnapshot(std::optional&&, ForceSoftwareCapturingViewportSnapshot); +#elif PLATFORM(WPE) + RefPtr takeViewSnapshot(std::optional&&) { return nullptr; } #endif - void wrapCryptoKey(const Vector&, CompletionHandler>&&)>&&); -@@ -2639,6 +2680,7 @@ private: + void serializeAndWrapCryptoKey(IPC::Connection&, WebCore::CryptoKeyData&&, CompletionHandler>&&)>&&); +@@ -2931,6 +2968,7 @@ private: RefPtr launchProcessForReload(); void requestNotificationPermission(const String& originString, CompletionHandler&&); @@ -17561,18 +16440,18 @@ index 2e40bbb43a05c10eee30296c5a7febdcdb74c157..4deb131a7c531d9035833f22062cf9e8 void didChangeContentSize(const WebCore::IntSize&); void didChangeIntrinsicContentSize(const WebCore::IntSize&); -@@ -3145,8 +3187,10 @@ private: - String m_overrideContentSecurityPolicy; +@@ -3450,8 +3488,10 @@ private: + String m_openedMainFrameName; RefPtr m_inspector; + InspectorDialogAgent* m_inspectorDialogAgent { nullptr }; #if ENABLE(FULLSCREEN_API) + std::unique_ptr m_fullScreenManagerClientOverride; - std::unique_ptr m_fullScreenManager; + RefPtr m_fullScreenManager; std::unique_ptr m_fullscreenClient; #endif -@@ -3336,6 +3380,22 @@ private: +@@ -3650,6 +3690,22 @@ private: std::optional m_currentDragOperation; bool m_currentDragIsOverFileInput { false }; unsigned m_currentDragNumberOfFilesToBeAccepted { 0 }; @@ -17595,39 +16474,31 @@ index 2e40bbb43a05c10eee30296c5a7febdcdb74c157..4deb131a7c531d9035833f22062cf9e8 #endif bool m_mainFrameHasHorizontalScrollbar { false }; -@@ -3507,6 +3567,10 @@ private: +@@ -3821,6 +3877,10 @@ private: RefPtr messageBody; }; Vector m_pendingInjectedBundleMessages; + std::optional m_credentialsForAutomation; + std::optional m_authOriginForAutomation; -+ HashMap> m_permissionsForAutomation; ++ UncheckedKeyHashMap> m_permissionsForAutomation; + std::optional m_activeForAutomation; #if PLATFORM(IOS_FAMILY) && ENABLE(DEVICE_ORIENTATION) - std::unique_ptr m_webDeviceOrientationUpdateProviderProxy; + RefPtr m_webDeviceOrientationUpdateProviderProxy; diff --git a/Source/WebKit/UIProcess/WebPageProxy.messages.in b/Source/WebKit/UIProcess/WebPageProxy.messages.in -index 3907e52e0136c24b8cdc24cb6e178b201e3e482a..03ef59a3032b12f91dcdd4a1160c7c8ef12cc0e3 100644 +index acdb79859685a55f3cda48014621340177f30e3d..36aca25956f9b073eefa5a68a013cde6017df39a 100644 --- a/Source/WebKit/UIProcess/WebPageProxy.messages.in +++ b/Source/WebKit/UIProcess/WebPageProxy.messages.in -@@ -29,6 +29,7 @@ messages -> WebPageProxy { +@@ -35,6 +35,7 @@ messages -> WebPageProxy { RunJavaScriptConfirm(WebCore::FrameIdentifier frameID, struct WebKit::FrameInfoData frameInfo, String message) -> (bool result) Synchronous RunJavaScriptPrompt(WebCore::FrameIdentifier frameID, struct WebKit::FrameInfoData frameInfo, String message, String defaultValue) -> (String result) Synchronous MouseDidMoveOverElement(struct WebKit::WebHitTestResultData hitTestResultData, OptionSet modifiers, WebKit::UserData userData) + LogToStderr(String text) - DidChangeViewportProperties(struct WebCore::ViewportAttributes attributes) - DidReceiveEvent(enum:uint8_t WebKit::WebEventType eventType, bool handled) -@@ -182,6 +183,7 @@ messages -> WebPageProxy { - #endif - - PageScaleFactorDidChange(double scaleFactor) -+ ViewScaleFactorDidChange(double scaleFactor) - PluginScaleFactorDidChange(double zoomFactor) - PluginZoomFactorDidChange(double zoomFactor) - -@@ -309,10 +311,14 @@ messages -> WebPageProxy { - StartDrag(struct WebCore::DragItem dragItem, WebCore::ShareableBitmapHandle dragImage) + DidReceiveEventIPC(enum:uint8_t WebKit::WebEventType eventType, bool handled, struct std::optional remoteUserInputEventData) + SetCursor(WebCore::Cursor cursor) +@@ -333,10 +334,14 @@ messages -> WebPageProxy { + StartDrag(struct WebCore::DragItem dragItem, WebCore::ShareableBitmapHandle dragImage, std::optional elementID) SetPromisedDataForImage(String pasteboardName, WebCore::SharedMemory::Handle imageHandle, String filename, String extension, String title, String url, String visibleURL, WebCore::SharedMemory::Handle archiveHandle, String originIdentifier) #endif -#if PLATFORM(GTK) && ENABLE(DRAG_SUPPORT) @@ -17636,17 +16507,17 @@ index 3907e52e0136c24b8cdc24cb6e178b201e3e482a..03ef59a3032b12f91dcdd4a1160c7c8e #endif +#if PLATFORM(WIN) && ENABLE(DRAG_SUPPORT) -+ StartDrag(HashMap> dragDataMap) ++ StartDrag(UncheckedKeyHashMap> dragDataMap) +#endif + #if PLATFORM(IOS_FAMILY) && ENABLE(DRAG_SUPPORT) - DidHandleDragStartRequest(bool started) - DidHandleAdditionalDragItemsRequest(bool added) + WillReceiveEditDragSnapshot() + DidReceiveEditDragSnapshot(struct std::optional textIndicator) diff --git a/Source/WebKit/UIProcess/WebProcessCache.cpp b/Source/WebKit/UIProcess/WebProcessCache.cpp -index c909cd634d6acd72695de8372866691269ad6a04..ff5b37e3b4a17eab4bd3f8e9a2a6ef8460110052 100644 +index dc6f440403cccc5cd93f75806cffbf05cc56041c..e880beba2034cc2b87dcfb3e1e8bacf1bed78cf3 100644 --- a/Source/WebKit/UIProcess/WebProcessCache.cpp +++ b/Source/WebKit/UIProcess/WebProcessCache.cpp -@@ -88,6 +88,10 @@ bool WebProcessCache::canCacheProcess(WebProcessProxy& process) const +@@ -100,6 +100,10 @@ bool WebProcessCache::canCacheProcess(WebProcessProxy& process) const return false; } @@ -17658,10 +16529,10 @@ index c909cd634d6acd72695de8372866691269ad6a04..ff5b37e3b4a17eab4bd3f8e9a2a6ef84 } diff --git a/Source/WebKit/UIProcess/WebProcessPool.cpp b/Source/WebKit/UIProcess/WebProcessPool.cpp -index f997e69f867ecaa6ec60a94a21ac89d51de413a4..78008ea36f1d08948c671fdfeeef08b30c7fc7fa 100644 +index 794f1e40dea081e818326f1d4123ebdf33569f86..35b0c4cdda0257c4844d4390d5901e71809c23f8 100644 --- a/Source/WebKit/UIProcess/WebProcessPool.cpp +++ b/Source/WebKit/UIProcess/WebProcessPool.cpp -@@ -430,10 +430,10 @@ void WebProcessPool::setAutomationClient(std::unique_ptr& +@@ -447,10 +447,10 @@ void WebProcessPool::setAutomationClient(std::unique_ptr& void WebProcessPool::setOverrideLanguages(Vector&& languages) { @@ -17674,7 +16545,7 @@ index f997e69f867ecaa6ec60a94a21ac89d51de413a4..78008ea36f1d08948c671fdfeeef08b3 #if ENABLE(GPU_PROCESS) if (RefPtr gpuProcess = GPUProcessProxy::singletonIfCreated()) -@@ -441,9 +441,10 @@ void WebProcessPool::setOverrideLanguages(Vector&& languages) +@@ -458,9 +458,10 @@ void WebProcessPool::setOverrideLanguages(Vector&& languages) #endif #if USE(SOUP) for (Ref networkProcess : NetworkProcessProxy::allNetworkProcesses()) @@ -17686,7 +16557,7 @@ index f997e69f867ecaa6ec60a94a21ac89d51de413a4..78008ea36f1d08948c671fdfeeef08b3 void WebProcessPool::fullKeyboardAccessModeChanged(bool fullKeyboardAccessEnabled) { -@@ -936,7 +937,7 @@ void WebProcessPool::initializeNewWebProcess(WebProcessProxy& process, WebsiteDa +@@ -945,7 +946,7 @@ void WebProcessPool::initializeNewWebProcess(WebProcessProxy& process, WebsiteDa #endif parameters.cacheModel = LegacyGlobalSettings::singleton().cacheModel(); @@ -17696,10 +16567,10 @@ index f997e69f867ecaa6ec60a94a21ac89d51de413a4..78008ea36f1d08948c671fdfeeef08b3 parameters.urlSchemesRegisteredAsEmptyDocument = copyToVector(m_schemesToRegisterAsEmptyDocument); diff --git a/Source/WebKit/UIProcess/WebProcessProxy.cpp b/Source/WebKit/UIProcess/WebProcessProxy.cpp -index b8305771145ecb6b92e28de1bcb370dc8ccbba0d..d3b591bc81ccd07367223270c545056fbdb51f49 100644 +index f1074d1138c9e6f2a76c1ce76807c775b16c657c..b7386197a24a689a5b0cae6772abefb17819dbe9 100644 --- a/Source/WebKit/UIProcess/WebProcessProxy.cpp +++ b/Source/WebKit/UIProcess/WebProcessProxy.cpp -@@ -188,6 +188,11 @@ Vector> WebProcessProxy::allProcesses() +@@ -208,6 +208,11 @@ Vector> WebProcessProxy::allProcesses() }); } @@ -17711,8 +16582,8 @@ index b8305771145ecb6b92e28de1bcb370dc8ccbba0d..d3b591bc81ccd07367223270c545056f RefPtr WebProcessProxy::processForIdentifier(ProcessIdentifier identifier) { return allProcessMap().get(identifier); -@@ -555,6 +560,26 @@ void WebProcessProxy::getLaunchOptions(ProcessLauncher::LaunchOptions& launchOpt - if (WebKit::isInspectorProcessPool(processPool())) +@@ -577,6 +582,26 @@ void WebProcessProxy::getLaunchOptions(ProcessLauncher::LaunchOptions& launchOpt + if (WebKit::isInspectorProcessPool(protectedProcessPool())) launchOptions.extraInitializationData.add("inspector-process"_s, "1"_s); + /* playwright revert fb205fb, 50f8fee */ @@ -17739,32 +16610,38 @@ index b8305771145ecb6b92e28de1bcb370dc8ccbba0d..d3b591bc81ccd07367223270c545056f if (isPrewarmed()) diff --git a/Source/WebKit/UIProcess/WebProcessProxy.h b/Source/WebKit/UIProcess/WebProcessProxy.h -index 92ebcbaf5abecd997e8bfd3cb5cb41b02191b7c5..bec4da91324e832f1dd027ad9e064a3336b3e047 100644 +index 4471fdf4a46180f78cea1cf035671bfe3c83b8e2..0858fe7f56eb3d8648467f5b82c2d77d6c958b77 100644 --- a/Source/WebKit/UIProcess/WebProcessProxy.h +++ b/Source/WebKit/UIProcess/WebProcessProxy.h -@@ -166,6 +166,7 @@ public: +@@ -185,6 +185,7 @@ public: - static void forWebPagesWithOrigin(PAL::SessionID, const WebCore::SecurityOriginData&, const Function&); + static void forWebPagesWithOrigin(PAL::SessionID, const WebCore::SecurityOriginData&, NOESCAPE const Function&); static Vector> allowedFirstPartiesForCookies(); + static Vector> allProcessesForInspector(); - WebConnection* webConnection() const { return m_webConnection.get(); } - RefPtr protectedWebConnection() const { return m_webConnection; } + void initializeWebProcess(WebProcessCreationParameters&&); + diff --git a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp -index 9729698017cabce150921532f0dd40e10634f0ce..9bb75eda6f3e5e0633d6ef55b3980f8ce35b2f2f 100644 +index c13d50e1828843714be1f49d2b1d5ea45e9c85aa..d7c76f184e77f1d828cde263ddf01f262c6c8f3a 100644 --- a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp +++ b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp -@@ -305,7 +305,8 @@ SOAuthorizationCoordinator& WebsiteDataStore::soAuthorizationCoordinator(const W +@@ -2061,6 +2061,15 @@ void WebsiteDataStore::setCacheModelSynchronouslyForTesting(CacheModel cacheMode + processPool->setCacheModelSynchronouslyForTesting(cacheModel); + } - static Ref networkProcessForSession(PAL::SessionID sessionID) ++// Playwright begin ++#if !USE(SOUP) ++void WebsiteDataStore::setIgnoreTLSErrors(bool ignoreTLSErrors) ++{ ++ m_ignoreTLSErrors = ignoreTLSErrors; ++} ++#endif ++// Playwright begin ++ + Vector WebsiteDataStore::parametersFromEachWebsiteDataStore() { --#if ((PLATFORM(GTK) || PLATFORM(WPE)) && !ENABLE(2022_GLIB_API)) -+// Playwright wants to isolate per BrowserContext. -+#if ((PLATFORM(GTK) || PLATFORM(WPE))) - if (sessionID.isEphemeral()) { - // Reuse a previous persistent session network process for ephemeral sessions. - for (auto& dataStore : allDataStores().values()) { -@@ -2278,6 +2279,12 @@ void WebsiteDataStore::originDirectoryForTesting(WebCore::ClientOrigin&& origin, + return WTF::map(allDataStores(), [](auto& entry) { +@@ -2509,6 +2518,12 @@ void WebsiteDataStore::originDirectoryForTesting(WebCore::ClientOrigin&& origin, protectedNetworkProcess()->websiteDataOriginDirectoryForTesting(m_sessionID, WTFMove(origin), type, WTFMove(completionHandler)); } @@ -17778,10 +16655,10 @@ index 9729698017cabce150921532f0dd40e10634f0ce..9bb75eda6f3e5e0633d6ef55b3980f8c void WebsiteDataStore::hasAppBoundSession(CompletionHandler&& completionHandler) const { diff --git a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h -index 165885137ca032390c6b55baacc30a8c4c423eb5..930ceeca56587636993f9a0c0e0a21d0ebab3835 100644 +index f1a113cc08f6543ab22be75a03823f49a3f52017..ef6dc1b450e2f4b0bcd374135a4cbc3d626a89d9 100644 --- a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h +++ b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h -@@ -97,6 +97,7 @@ class DeviceIdHashSaltStorage; +@@ -98,6 +98,7 @@ class DeviceIdHashSaltStorage; class DownloadProxy; class NetworkProcessProxy; class SOAuthorizationCoordinator; @@ -17789,7 +16666,7 @@ index 165885137ca032390c6b55baacc30a8c4c423eb5..930ceeca56587636993f9a0c0e0a21d0 class VirtualAuthenticatorManager; class WebPageProxy; class WebProcessPool; -@@ -112,12 +113,21 @@ enum class UnifiedOriginStorageLevel : uint8_t; +@@ -113,6 +114,7 @@ enum class UnifiedOriginStorageLevel : uint8_t; enum class WebsiteDataFetchOption : uint8_t; enum class WebsiteDataType : uint32_t; @@ -17797,8 +16674,9 @@ index 165885137ca032390c6b55baacc30a8c4c423eb5..930ceeca56587636993f9a0c0e0a21d0 struct ITPThirdPartyData; struct NetworkProcessConnectionInfo; struct WebPushMessage; - struct WebsiteDataRecord; - struct WebsiteDataStoreParameters; +@@ -122,6 +124,14 @@ struct WebsiteDataStoreParameters; + enum RemoveDataTaskCounterType { }; + using RemoveDataTaskCounter = RefCounter; +class DownloadInstrumentation { +public: @@ -17811,22 +16689,18 @@ index 165885137ca032390c6b55baacc30a8c4c423eb5..930ceeca56587636993f9a0c0e0a21d0 class WebsiteDataStore : public API::ObjectImpl, public CanMakeWeakPtr { public: static Ref defaultDataStore(); -@@ -305,11 +315,13 @@ public: - const WebCore::CurlProxySettings& networkProxySettings() const { return m_proxySettings; } - #endif - --#if USE(SOUP) -+#if USE(SOUP) || PLATFORM(COCOA) || PLATFORM(WIN) +@@ -321,8 +331,10 @@ public: + #if USE(SOUP) void setPersistentCredentialStorageEnabled(bool); bool persistentCredentialStorageEnabled() const { return m_persistentCredentialStorageEnabled && isPersistent(); } ++#endif void setIgnoreTLSErrors(bool); bool ignoreTLSErrors() const { return m_ignoreTLSErrors; } -+#endif +#if USE(SOUP) void setNetworkProxySettings(WebCore::SoupNetworkProxySettings&&); const WebCore::SoupNetworkProxySettings& networkProxySettings() const { return m_networkProxySettings; } void setCookiePersistentStorage(const String&, SoupCookiePersistentStorageType); -@@ -394,6 +406,12 @@ public: +@@ -420,6 +432,12 @@ public: static const String& defaultBaseDataDirectory(); #endif @@ -17839,20 +16713,18 @@ index 165885137ca032390c6b55baacc30a8c4c423eb5..930ceeca56587636993f9a0c0e0a21d0 void resetQuota(CompletionHandler&&); void resetStoragePersistedState(CompletionHandler&&); #if PLATFORM(IOS_FAMILY) -@@ -564,9 +582,11 @@ private: - WebCore::CurlProxySettings m_proxySettings; - #endif +@@ -618,7 +636,9 @@ private: --#if USE(SOUP) -+#if USE(SOUP) || PLATFORM(COCOA) || PLATFORM(WIN) + #if USE(SOUP) bool m_persistentCredentialStorageEnabled { true }; - bool m_ignoreTLSErrors { true }; +- bool m_ignoreTLSErrors { true }; +#endif ++ bool m_ignoreTLSErrors { false }; +#if USE(SOUP) WebCore::SoupNetworkProxySettings m_networkProxySettings; String m_cookiePersistentStoragePath; SoupCookiePersistentStorageType m_cookiePersistentStorageType { SoupCookiePersistentStorageType::SQLite }; -@@ -593,6 +613,10 @@ private: +@@ -645,6 +665,10 @@ private: RefPtr m_cookieStore; RefPtr m_networkProcess; @@ -17864,10 +16736,10 @@ index 165885137ca032390c6b55baacc30a8c4c423eb5..930ceeca56587636993f9a0c0e0a21d0 std::unique_ptr m_soAuthorizationCoordinator; #endif diff --git a/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.cpp b/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.cpp -index d02a8ad4cd66f7f277eee16d21e9ffb0e1a961db..ef35d46977b9b6a866b665e3a01eac94a648cc97 100644 +index 19934de3173ecc0507c5e59956bcf6730a8a88b4..bc0e52f6f28caeca8b9b7aab14b7ff991d7e6b41 100644 --- a/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.cpp +++ b/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.cpp -@@ -101,6 +101,14 @@ void GeoclueGeolocationProvider::stop() +@@ -114,6 +114,14 @@ void GeoclueGeolocationProvider::stop() } m_sourceType = LocationProviderSource::Unknown; @@ -17882,7 +16754,7 @@ index d02a8ad4cd66f7f277eee16d21e9ffb0e1a961db..ef35d46977b9b6a866b665e3a01eac94 } void GeoclueGeolocationProvider::setEnableHighAccuracy(bool enabled) -@@ -373,6 +381,8 @@ void GeoclueGeolocationProvider::createGeoclueClient(const char* clientPath) +@@ -386,6 +394,8 @@ void GeoclueGeolocationProvider::createGeoclueClient(const char* clientPath) return; } @@ -17892,10 +16764,10 @@ index d02a8ad4cd66f7f277eee16d21e9ffb0e1a961db..ef35d46977b9b6a866b665e3a01eac94 "org.freedesktop.GeoClue2", clientPath, "org.freedesktop.GeoClue2.Client", m_cancellable.get(), [](GObject*, GAsyncResult* result, gpointer userData) { diff --git a/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.h b/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.h -index 69610f8f7b81d914d74444d9c86b3b039251edb6..c234848afb5e523165bf827bac8008486d2f8e14 100644 +index 96bf77411e2e1f4c835f56b409dc179977d197ee..512af5ffce511711b502248e34e49e45e85dbc4e 100644 --- a/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.h +++ b/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.h -@@ -90,6 +90,9 @@ private: +@@ -92,6 +92,9 @@ private: unsigned responseSignalId; } m_portal; GRefPtr m_cancellable; @@ -17907,10 +16779,10 @@ index 69610f8f7b81d914d74444d9c86b3b039251edb6..c234848afb5e523165bf827bac800848 RunLoop::Timer m_destroyLaterTimer; diff --git a/Source/WebKit/UIProcess/glib/InspectorPlaywrightAgentClientGLib.cpp b/Source/WebKit/UIProcess/glib/InspectorPlaywrightAgentClientGLib.cpp new file mode 100644 -index 0000000000000000000000000000000000000000..93de9be341045a616b0219a965af2447ecbfc926 +index 0000000000000000000000000000000000000000..5185677fc67a418fac7a09c69246f4406a74c706 --- /dev/null +++ b/Source/WebKit/UIProcess/glib/InspectorPlaywrightAgentClientGLib.cpp -@@ -0,0 +1,184 @@ +@@ -0,0 +1,192 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * @@ -17944,18 +16816,21 @@ index 0000000000000000000000000000000000000000..93de9be341045a616b0219a965af2447 +#include "InspectorPlaywrightAgent.h" +#include "PageClient.h" +#include "ViewSnapshotStore.h" ++#include "WebAutomationSession.h" +#include "WebKitBrowserInspectorPrivate.h" +#include "WebKitWebContextPrivate.h" +#include "WebKitWebsiteDataManagerPrivate.h" +#include "WebKitWebViewPrivate.h" +#include "WebPageProxy.h" -+#include +#include +#include +#include +#include +#include + ++#if USE(SKIA) ++#include ++#endif + +namespace WebKit { + @@ -18036,8 +16911,10 @@ index 0000000000000000000000000000000000000000..93de9be341045a616b0219a965af2447 +#endif + // WPE has PSON enabled by default and doesn't have such parameter. +#if PLATFORM(GTK) ++#if !ENABLE(2022_GLIB_API) + "process-swap-on-cross-site-navigation-enabled", true, +#endif ++#endif + nullptr))); + if (!context) { + error = "Failed to create GLib ephemeral context"_s; @@ -18073,21 +16950,24 @@ index 0000000000000000000000000000000000000000..93de9be341045a616b0219a965af2447 +void InspectorPlaywrightAgentClientGlib::takePageScreenshot(WebPageProxy& page, WebCore::IntRect&& clip, bool nominalResolution, CompletionHandler&& completionHandler) +{ + page.callAfterNextPresentationUpdate([protectedPage = Ref{ page }, clip = WTFMove(clip), nominalResolution, completionHandler = WTFMove(completionHandler)]() mutable { -+ cairo_surface_t* surface = nullptr; +#if PLATFORM(GTK) -+ RefPtr viewSnapshot = protectedPage->pageClient().takeViewSnapshot(WTFMove(clip), nominalResolution); -+ if (viewSnapshot) -+ surface = viewSnapshot->surface(); ++ RefPtr viewSnapshot = protectedPage->pageClient()->takeViewSnapshot(WTFMove(clip), nominalResolution); ++ if (viewSnapshot) { ++ std::optional data = WebAutomationSession::platformGetBase64EncodedPNGData(*viewSnapshot); ++ if (data) { ++ completionHandler(emptyString(), makeString("data:image/png;base64,"_s, *data)); ++ return; ++ } ++ } +#elif PLATFORM(WPE) -+ RefPtr protectPtr = protectedPage->pageClient().takeViewSnapshot(WTFMove(clip), nominalResolution); -+ surface = protectPtr.get(); -+#endif ++ sk_sp protectPtr = protectedPage->pageClient()->takeViewSnapshot(WTFMove(clip), nominalResolution); ++ SkImage* surface = protectPtr.get(); + if (surface) { + Vector encodeData = WebCore::encodeData(surface, "image/png"_s, std::nullopt); + completionHandler(emptyString(), makeString("data:image/png;base64,"_s, base64Encoded(encodeData))); + return; + } -+ ++#endif + completionHandler("Failed to take screenshot"_s, emptyString()); + }); +} @@ -18097,7 +16977,7 @@ index 0000000000000000000000000000000000000000..93de9be341045a616b0219a965af2447 +#endif // ENABLE(REMOTE_INSPECTOR) diff --git a/Source/WebKit/UIProcess/glib/InspectorPlaywrightAgentClientGLib.h b/Source/WebKit/UIProcess/glib/InspectorPlaywrightAgentClientGLib.h new file mode 100644 -index 0000000000000000000000000000000000000000..394f07e1754be52b7d503d5720cba5d3724c5f4d +index 0000000000000000000000000000000000000000..441442d899e4088f5c24ae9f70c3e4ffa1e6d340 --- /dev/null +++ b/Source/WebKit/UIProcess/glib/InspectorPlaywrightAgentClientGLib.h @@ -0,0 +1,61 @@ @@ -18155,26 +17035,39 @@ index 0000000000000000000000000000000000000000..394f07e1754be52b7d503d5720cba5d3 +private: + WebKitWebContext* findContext(WTF::String& error, PAL::SessionID); + -+ HashMap> m_idToContext; ++ UncheckedKeyHashMap> m_idToContext; + WebCore::SoupNetworkProxySettings m_proxySettings; +}; + +} // namespace API + +#endif // ENABLE(REMOTE_INSPECTOR) +diff --git a/Source/WebKit/UIProcess/glib/WebProcessPoolGLib.cpp b/Source/WebKit/UIProcess/glib/WebProcessPoolGLib.cpp +index 51ba8b585ca37a2eed54bce5218e1c92c2844cc6..dc04a2ca0b0ac2333036b897dd18d5303c5237c6 100644 +--- a/Source/WebKit/UIProcess/glib/WebProcessPoolGLib.cpp ++++ b/Source/WebKit/UIProcess/glib/WebProcessPoolGLib.cpp +@@ -124,6 +124,8 @@ static OptionSet availableInputDevices() + return toAvailableInputDevices(gdk_seat_get_capabilities(seat)); + } + #endif ++ if (!WebCore::screenHasTouchDeviceOverride() || !WebCore::screenHasTouchDeviceOverride().value()) ++ return AvailableInputDevices::Mouse; + #if ENABLE(TOUCH_EVENTS) + return AvailableInputDevices::Touchscreen; + #else diff --git a/Source/WebKit/UIProcess/gtk/AcceleratedBackingStore.h b/Source/WebKit/UIProcess/gtk/AcceleratedBackingStore.h -index b02c70d85fe1a93899640a8b909b0cf734d28b18..b1dc8e89eb265be81e083bf337109561e08cbf45 100644 +index 5529f52048b24290f424e877cd9dbfb890e02ffb..c2b76b6188dd9596c4a1f31c137daff7d7644c7f 100644 --- a/Source/WebKit/UIProcess/gtk/AcceleratedBackingStore.h +++ b/Source/WebKit/UIProcess/gtk/AcceleratedBackingStore.h -@@ -29,6 +29,7 @@ - #include +@@ -32,6 +32,7 @@ + #include typedef struct _cairo cairo_t; +typedef struct _cairo_surface cairo_surface_t; #if USE(GTK4) typedef struct _GdkSnapshot GdkSnapshot; -@@ -57,6 +58,8 @@ public: +@@ -62,6 +63,8 @@ public: #else virtual bool paint(cairo_t*, const WebCore::IntRect&) = 0; #endif @@ -18184,17 +17077,17 @@ index b02c70d85fe1a93899640a8b909b0cf734d28b18..b1dc8e89eb265be81e083bf337109561 virtual void unrealize() { }; virtual int renderHostFileDescriptor() { return -1; } diff --git a/Source/WebKit/UIProcess/gtk/AcceleratedBackingStoreDMABuf.cpp b/Source/WebKit/UIProcess/gtk/AcceleratedBackingStoreDMABuf.cpp -index bef1f57ad45eaef04640991d4afd34138b8d7b76..a37024640fbf6eb79838c039001ee1cf4907042e 100644 +index 395a409b6302d4146606fc0b45a15cff63c7f327..666d9629e0155e8c03b0672f7a9274de7f04d642 100644 --- a/Source/WebKit/UIProcess/gtk/AcceleratedBackingStoreDMABuf.cpp +++ b/Source/WebKit/UIProcess/gtk/AcceleratedBackingStoreDMABuf.cpp -@@ -659,4 +659,30 @@ RendererBufferFormat AcceleratedBackingStoreDMABuf::bufferFormat() const - return buffer ? buffer->format() : RendererBufferFormat { }; +@@ -812,4 +812,30 @@ RefPtr AcceleratedBackingStoreDMABuf::bufferAsNativeImageF + return m_committedBuffer->asNativeImageForTesting(); } +// Playwright begin +cairo_surface_t* AcceleratedBackingStoreDMABuf::surface() +{ -+ RefPtr buffer = m_renderer.buffer(); ++ RefPtr buffer = m_committedBuffer.get(); + if (!buffer) + return nullptr; + @@ -18219,10 +17112,10 @@ index bef1f57ad45eaef04640991d4afd34138b8d7b76..a37024640fbf6eb79838c039001ee1cf + } // namespace WebKit diff --git a/Source/WebKit/UIProcess/gtk/AcceleratedBackingStoreDMABuf.h b/Source/WebKit/UIProcess/gtk/AcceleratedBackingStoreDMABuf.h -index cd95ceb063fc776b5d68ff45262c4d84e572c509..041c562551cd467c320b8f566264885d00d1434b 100644 +index 63dfbed03bd898c822d426a5449141fec2841226..eaf141843da3f02c5ba6fd0322f3175248a7195b 100644 --- a/Source/WebKit/UIProcess/gtk/AcceleratedBackingStoreDMABuf.h +++ b/Source/WebKit/UIProcess/gtk/AcceleratedBackingStoreDMABuf.h -@@ -88,6 +88,7 @@ private: +@@ -98,6 +98,7 @@ private: #else bool paint(cairo_t*, const WebCore::IntRect&) override; #endif @@ -18230,9 +17123,9 @@ index cd95ceb063fc776b5d68ff45262c4d84e572c509..041c562551cd467c320b8f566264885d void unrealize() override; void update(const LayerTreeContext&) override; RendererBufferFormat bufferFormat() const override; -@@ -243,6 +244,9 @@ private: - RefPtr m_pendingBuffer; +@@ -253,6 +254,9 @@ private: RefPtr m_committedBuffer; + Rects m_pendingDamageRects; HashMap> m_buffers; +// Playwright begin + RefPtr m_flippedSurface; @@ -18242,10 +17135,10 @@ index cd95ceb063fc776b5d68ff45262c4d84e572c509..041c562551cd467c320b8f566264885d } // namespace WebKit diff --git a/Source/WebKit/UIProcess/gtk/InspectorTargetProxyGtk.cpp b/Source/WebKit/UIProcess/gtk/InspectorTargetProxyGtk.cpp new file mode 100644 -index 0000000000000000000000000000000000000000..f5f811ced4eafef530d101c4e397fe2780ac3071 +index 0000000000000000000000000000000000000000..bf78de1915940c2d3292514cf0fe4e682b636f70 --- /dev/null +++ b/Source/WebKit/UIProcess/gtk/InspectorTargetProxyGtk.cpp -@@ -0,0 +1,44 @@ +@@ -0,0 +1,48 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * @@ -18282,7 +17175,11 @@ index 0000000000000000000000000000000000000000..f5f811ced4eafef530d101c4e397fe27 + +void InspectorTargetProxy::platformActivate(String& error) const +{ -+ GtkWidget* parent = gtk_widget_get_toplevel(m_page.viewWidget()); ++#if USE(GTK4) ++ GtkWidget* parent = GTK_WIDGET(gtk_widget_get_root(m_page->viewWidget())); ++#else ++ GtkWidget* parent = gtk_widget_get_toplevel(m_page->viewWidget()); ++#endif + if (WebCore::widgetIsOnscreenToplevelWindow(parent)) + gtk_window_present(GTK_WINDOW(parent)); + else @@ -18290,25 +17187,25 @@ index 0000000000000000000000000000000000000000..f5f811ced4eafef530d101c4e397fe27 +} + +} // namespace WebKit -diff --git a/Source/WebKit/UIProcess/gtk/WebDateTimePickerGtk.cpp b/Source/WebKit/UIProcess/gtk/WebDateTimePickerGtk.cpp -index 6029857cfcd6c4fea14de28243f1955138a62844..8a1bda8f2637670cf88baca998cbff09157d2a6f 100644 ---- a/Source/WebKit/UIProcess/gtk/WebDateTimePickerGtk.cpp -+++ b/Source/WebKit/UIProcess/gtk/WebDateTimePickerGtk.cpp -@@ -34,6 +34,8 @@ - #include - #include - -+using namespace WebCore; -+ - namespace WebKit { +diff --git a/Source/WebKit/UIProcess/gtk/SystemSettingsManagerProxyGtk.cpp b/Source/WebKit/UIProcess/gtk/SystemSettingsManagerProxyGtk.cpp +index 9ef483a6b0ab1558c059304d727311ea7984184d..f532d2d2dbe2d7cb66323b6ea5fe2daace15d7b8 100644 +--- a/Source/WebKit/UIProcess/gtk/SystemSettingsManagerProxyGtk.cpp ++++ b/Source/WebKit/UIProcess/gtk/SystemSettingsManagerProxyGtk.cpp +@@ -126,6 +126,8 @@ int SystemSettingsManagerProxy::xftDPI() const - Ref WebDateTimePickerGtk::create(WebPageProxy& page) + bool SystemSettingsManagerProxy::followFontSystemSettings() const + { ++ // Align with WPE's behavior, which always returns false. ++ return false; + #if USE(GTK4) + #if GTK_CHECK_VERSION(4, 16, 0) + GtkFontRendering fontRendering; diff --git a/Source/WebKit/UIProcess/gtk/WebPageInspectorEmulationAgentGtk.cpp b/Source/WebKit/UIProcess/gtk/WebPageInspectorEmulationAgentGtk.cpp new file mode 100644 -index 0000000000000000000000000000000000000000..e5e25acebabb76a05a77db02a99f1267bd99a3af +index 0000000000000000000000000000000000000000..7d9672b0f831b5b7f6acf14ede26e1e8e9a65389 --- /dev/null +++ b/Source/WebKit/UIProcess/gtk/WebPageInspectorEmulationAgentGtk.cpp -@@ -0,0 +1,69 @@ +@@ -0,0 +1,117 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * @@ -18342,8 +17239,22 @@ index 0000000000000000000000000000000000000000..e5e25acebabb76a05a77db02a99f1267 +#include + +namespace WebKit { ++ ++#if USE(GTK4) ++bool windowHasManyTabs(GtkWidget* widget) { ++ for (GtkWidget* parent = gtk_widget_get_parent(widget); parent; parent = gtk_widget_get_parent(parent)) { ++ if (GTK_IS_NOTEBOOK(parent)) { ++ int pages = gtk_notebook_get_n_pages(GTK_NOTEBOOK(parent)); ++ return pages > 1; ++ } ++ } ++ return false; ++} ++#endif ++ +void WebPageInspectorEmulationAgent::platformSetSize(int width, int height, Function&& callback) +{ ++ WebCore::IntSize viewSize(width, height); + GtkWidget* viewWidget = m_page.viewWidget(); + GtkWidget* window = gtk_widget_get_toplevel(viewWidget); + if (!window) { @@ -18356,6 +17267,14 @@ index 0000000000000000000000000000000000000000..e5e25acebabb76a05a77db02a99f1267 + } + GtkAllocation viewAllocation; + gtk_widget_get_allocation(viewWidget, &viewAllocation); ++#if USE(GTK4) ++ // In GTK4 newly added tabs will have allocation size of 0x0, before the tab is shown. ++ // This is a Ctrl+click scenario. We invoke callback righ await to not stall. ++ if (!viewAllocation.width && !viewAllocation.height && windowHasManyTabs(viewWidget)) { ++ callback(String()); ++ return; ++ } ++#endif + if (viewAllocation.width == width && viewAllocation.height == height) { + callback(String()); + return; @@ -18368,22 +17287,48 @@ index 0000000000000000000000000000000000000000..e5e25acebabb76a05a77db02a99f1267 + height += windowAllocation.height - viewAllocation.height; + + if (auto* drawingArea = static_cast(m_page.drawingArea())) { -+ drawingArea->waitForSizeUpdate([callback = WTFMove(callback)]() { ++ bool didNotHaveInitialAllocation = !windowAllocation.width && !windowAllocation.height; ++ // The callback can only be called if the page is still alive, so we can safely capture `this`. ++ drawingArea->waitForSizeUpdate([this, callback = WTFMove(callback), didNotHaveInitialAllocation, viewSize](const DrawingAreaProxyCoordinatedGraphics& drawingArea) mutable { ++#if USE(GTK4) ++ if (viewSize == drawingArea.size()) { ++ callback(String()); ++ return; ++ } ++ if (didNotHaveInitialAllocation) { ++ // In gtk4 resize request may be lost (overridden by default one) if the window is not yet ++ // allocated when we are changing the size, so we try again. ++ platformSetSize(viewSize.width(), viewSize.height(), WTFMove(callback)); ++ return; ++ } ++ callback("Failed to resize window"_s); ++#else ++ UNUSED_PARAM(this); ++ UNUSED_PARAM(didNotHaveInitialAllocation); ++ UNUSED_PARAM(drawingArea); + callback(String()); ++#endif + }); + } else { + callback("No backing store for window"_s); + } ++#if USE(GTK4) ++ // Depending on whether default size has been applied or not, we need to ++ // do one of the calls, so we just do both. ++ gtk_window_set_default_size(GTK_WINDOW(window), width, height); ++ gtk_widget_set_size_request(window, width, height); ++#else + gtk_window_resize(GTK_WINDOW(window), width, height); ++#endif +} + +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/gtk/WebPageInspectorInputAgentGtk.cpp b/Source/WebKit/UIProcess/gtk/WebPageInspectorInputAgentGtk.cpp new file mode 100644 -index 0000000000000000000000000000000000000000..6a204c5bba8fb95ddb2d1c14cae7a3a79610abc6 +index 0000000000000000000000000000000000000000..36ab6e9aec9f8d79fb13a8a49beadaafb3da58f5 --- /dev/null +++ b/Source/WebKit/UIProcess/gtk/WebPageInspectorInputAgentGtk.cpp -@@ -0,0 +1,105 @@ +@@ -0,0 +1,76 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * @@ -18417,23 +17362,7 @@ index 0000000000000000000000000000000000000000..6a204c5bba8fb95ddb2d1c14cae7a3a7 +#include "WebPageProxy.h" +#include + -+namespace WebKit { -+ -+static Vector commandsForKeyEvent(GdkEventType type, unsigned keyVal, unsigned state) -+{ -+ ASSERT(type == GDK_KEY_PRESS || type == GDK_KEY_RELEASE); -+ -+ GUniquePtr event(gdk_event_new(type)); -+ event->key.keyval = keyVal; -+ event->key.time = GDK_CURRENT_TIME; -+ event->key.state = state; -+ // When synthesizing an event, an invalid hardware_keycode value can cause it to be badly processed by GTK+. -+ GUniqueOutPtr keys; -+ int keysCount; -+ if (gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(), keyVal, &keys.outPtr(), &keysCount) && keysCount) -+ event->key.hardware_keycode = keys.get()[0].keycode; -+ return KeyBindingTranslator().commandsForKeyEvent(&event->key); -+} ++namespace WebKit { + +static unsigned modifiersToEventState(OptionSet modifiers) +{ @@ -18454,21 +17383,8 @@ index 0000000000000000000000000000000000000000..6a204c5bba8fb95ddb2d1c14cae7a3a7 + Vector commands; + const guint keyVal = WebCore::PlatformKeyboardEvent::gdkKeyCodeForWindowsKeyCode(windowsVirtualKeyCode); + if (keyVal) { -+ GdkEventType event = GDK_NOTHING; -+ switch (type) -+ { -+ case WebEventType::KeyDown: -+ event = GDK_KEY_PRESS; -+ break; -+ case WebEventType::KeyUp: -+ event = GDK_KEY_RELEASE; -+ break; -+ default: -+ fprintf(stderr, "Unsupported event type = %d\n", type); -+ break; -+ } + unsigned state = modifiersToEventState(modifiers); -+ commands = commandsForKeyEvent(event, keyVal, state); ++ commands = KeyBindingTranslator().commandsForKeyval(keyVal, state); + } + NativeWebKeyboardEvent event( + type, @@ -18490,10 +17406,10 @@ index 0000000000000000000000000000000000000000..6a204c5bba8fb95ddb2d1c14cae7a3a7 + +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/gtk/WebPasteboardProxyGtk.cpp b/Source/WebKit/UIProcess/gtk/WebPasteboardProxyGtk.cpp -index d18b3e777203ef5d0f33884f909bc598d3526831..aef80b47359d7a2e4805a006dc59cd60d499a60e 100644 +index c7db5171b505ea9656f409c95c422dce9f0fa1ae..1992a112468e03840be3696245eecd8452ca51ed 100644 --- a/Source/WebKit/UIProcess/gtk/WebPasteboardProxyGtk.cpp +++ b/Source/WebKit/UIProcess/gtk/WebPasteboardProxyGtk.cpp -@@ -77,8 +77,10 @@ void WebPasteboardProxy::setPrimarySelectionOwner(WebFrameProxy* frame) +@@ -85,8 +85,10 @@ void WebPasteboardProxy::setPrimarySelectionOwner(WebFrameProxy* frame) if (m_primarySelectionOwner == frame) return; @@ -18506,19 +17422,6 @@ index d18b3e777203ef5d0f33884f909bc598d3526831..aef80b47359d7a2e4805a006dc59cd60 m_primarySelectionOwner = frame; } -diff --git a/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm b/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm -index 286877d14b4eb6ac45092fa1cce5ce530558f8af..85240554255d69a30269e764214a139743de521b 100644 ---- a/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm -+++ b/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm -@@ -504,6 +504,8 @@ IntRect PageClientImpl::rootViewToAccessibilityScreen(const IntRect& rect) - - void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent& event, bool eventWasHandled) - { -+ if (!event.nativeEvent()) -+ return; - [contentView() _didHandleKeyEvent:event.nativeEvent() eventWasHandled:eventWasHandled]; - } - diff --git a/Source/WebKit/UIProcess/mac/InspectorPlaywrightAgentClientMac.h b/Source/WebKit/UIProcess/mac/InspectorPlaywrightAgentClientMac.h new file mode 100644 index 0000000000000000000000000000000000000000..2aabc02a4b5432f68a6e85fd9689775608f05a67 @@ -18580,7 +17483,7 @@ index 0000000000000000000000000000000000000000..2aabc02a4b5432f68a6e85fd96897756 +} // namespace API diff --git a/Source/WebKit/UIProcess/mac/InspectorPlaywrightAgentClientMac.mm b/Source/WebKit/UIProcess/mac/InspectorPlaywrightAgentClientMac.mm new file mode 100644 -index 0000000000000000000000000000000000000000..0de68ad69c87f9d5b0a5f0d24fb358a50b59b4a2 +index 0000000000000000000000000000000000000000..a4b23bf4cf7c4cb6ef9d25d4121b20a611809479 --- /dev/null +++ b/Source/WebKit/UIProcess/mac/InspectorPlaywrightAgentClientMac.mm @@ -0,0 +1,96 @@ @@ -18651,7 +17554,7 @@ index 0000000000000000000000000000000000000000..0de68ad69c87f9d5b0a5f0d24fb358a5 + +std::unique_ptr InspectorPlaywrightAgentClientMac::createBrowserContext(WTF::String& error, const WTF::String& proxyServer, const WTF::String& proxyBypassList) +{ -+ _WKBrowserContext* wkBrowserContext = [[delegate_ createBrowserContext:proxyServer WithBypassList:proxyBypassList] autorelease]; ++ _WKBrowserContext* wkBrowserContext = [[delegate_ createBrowserContext:proxyServer.createNSString().get() WithBypassList:proxyBypassList.createNSString().get()] autorelease]; + auto browserContext = std::make_unique(); + browserContext->processPool = &static_cast([[wkBrowserContext processPool] _apiObject]); + browserContext->dataStore = &static_cast([[wkBrowserContext dataStore] _apiObject]); @@ -18667,7 +17570,7 @@ index 0000000000000000000000000000000000000000..0de68ad69c87f9d5b0a5f0d24fb358a5 +{ + int toolbarHeight = headless_ ? 0 : 59; + page.callAfterNextPresentationUpdate([protectedPage = Ref { page }, toolbarHeight, clipRect = WTFMove(clipRect), completionHandler = WTFMove(completionHandler)]() mutable { -+ RetainPtr imageRef = protectedPage->pageClient().takeSnapshotForAutomation(); ++ RetainPtr imageRef = protectedPage->pageClient()->takeSnapshotForAutomation(); + if (!imageRef) { + completionHandler("Could not take view snapshot"_s, emptyString()); + return; @@ -18682,7 +17585,7 @@ index 0000000000000000000000000000000000000000..0de68ad69c87f9d5b0a5f0d24fb358a5 +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/mac/InspectorTargetProxyMac.mm b/Source/WebKit/UIProcess/mac/InspectorTargetProxyMac.mm new file mode 100644 -index 0000000000000000000000000000000000000000..721826c8c98fc85b68a4f45deaee69c1219a7254 +index 0000000000000000000000000000000000000000..8adbd51bfecad2a273117588bf50f8f741850d14 --- /dev/null +++ b/Source/WebKit/UIProcess/mac/InspectorTargetProxyMac.mm @@ -0,0 +1,42 @@ @@ -18721,7 +17624,7 @@ index 0000000000000000000000000000000000000000..721826c8c98fc85b68a4f45deaee69c1 + +void InspectorTargetProxy::platformActivate(String& error) const +{ -+ NSWindow* window = m_page.platformWindow(); ++ NSWindow* window = m_page->platformWindow(); + [window makeKeyAndOrderFront:nil]; +} + @@ -18729,19 +17632,19 @@ index 0000000000000000000000000000000000000000..721826c8c98fc85b68a4f45deaee69c1 + +#endif diff --git a/Source/WebKit/UIProcess/mac/PageClientImplMac.h b/Source/WebKit/UIProcess/mac/PageClientImplMac.h -index 1647891b55a718f66ee2f4a084439edd655c623a..2099b9166e2cac062d4161d704050a0795a26c93 100644 +index 27627ddb817e90c92ff5e533618ded9d017d36d9..9169b380a79d57201a7d3dceab04a1d16d987865 100644 --- a/Source/WebKit/UIProcess/mac/PageClientImplMac.h +++ b/Source/WebKit/UIProcess/mac/PageClientImplMac.h -@@ -54,6 +54,8 @@ class PageClientImpl final : public PageClientImplCocoa +@@ -61,6 +61,8 @@ class PageClientImpl final : public PageClientImplCocoa + WTF_OVERRIDE_DELETE_FOR_CHECKED_PTR(PageClientImpl); #endif - { public: + static void setHeadless(bool headless); + PageClientImpl(NSView *, WKWebView *); virtual ~PageClientImpl(); -@@ -170,6 +172,9 @@ private: +@@ -176,6 +178,9 @@ private: void updateAcceleratedCompositingMode(const LayerTreeContext&) override; void didFirstLayerFlush(const LayerTreeContext&) override; @@ -18749,32 +17652,24 @@ index 1647891b55a718f66ee2f4a084439edd655c623a..2099b9166e2cac062d4161d704050a07 + RetainPtr takeSnapshotForAutomation() override; +// Paywright end RefPtr takeViewSnapshot(std::optional&&) override; + RefPtr takeViewSnapshot(std::optional&&, ForceSoftwareCapturingViewportSnapshot) override; void wheelEventWasNotHandledByWebCore(const NativeWebWheelEvent&) override; - #if ENABLE(MAC_GESTURE_EVENTS) -@@ -222,6 +227,10 @@ private: - void beganExitFullScreen(const WebCore::IntRect& initialFrame, const WebCore::IntRect& finalFrame) override; +@@ -227,6 +232,10 @@ private: + void beganExitFullScreen(const WebCore::IntRect& initialFrame, const WebCore::IntRect& finalFrame, CompletionHandler&&) override; #endif +#if ENABLE(TOUCH_EVENTS) -+ void doneWithTouchEvent(const NativeWebTouchEvent&, bool wasEventHandled) override; ++ void doneWithTouchEvent(const WebTouchEvent&, bool wasEventHandled) override; +#endif + void navigationGestureDidBegin() override; void navigationGestureWillEnd(bool willNavigate, WebBackForwardListItem&) override; void navigationGestureDidEnd(bool willNavigate, WebBackForwardListItem&) override; diff --git a/Source/WebKit/UIProcess/mac/PageClientImplMac.mm b/Source/WebKit/UIProcess/mac/PageClientImplMac.mm -index 3fe2a9487a96b31f476bb17e45374f880e80da9a..b72433e5981f298d4d1ca93274df51cd830855c0 100644 +index 22f6f6f08ba1601647898ca0f350672c3cac3816..6fad8bc05d1b458e25f8ddb9515ec8e1dcd896d6 100644 --- a/Source/WebKit/UIProcess/mac/PageClientImplMac.mm +++ b/Source/WebKit/UIProcess/mac/PageClientImplMac.mm -@@ -80,6 +80,7 @@ - #import - #import - #import -+#import - #import - #import - #import -@@ -106,6 +107,13 @@ namespace WebKit { +@@ -108,6 +108,13 @@ namespace WebKit { using namespace WebCore; @@ -18788,7 +17683,7 @@ index 3fe2a9487a96b31f476bb17e45374f880e80da9a..b72433e5981f298d4d1ca93274df51cd PageClientImpl::PageClientImpl(NSView *view, WKWebView *webView) : PageClientImplCocoa(webView) , m_view(view) -@@ -159,6 +167,9 @@ NSWindow *PageClientImpl::activeWindow() const +@@ -161,6 +168,9 @@ NSWindow *PageClientImpl::activeWindow() const bool PageClientImpl::isViewWindowActive() { @@ -18796,9 +17691,9 @@ index 3fe2a9487a96b31f476bb17e45374f880e80da9a..b72433e5981f298d4d1ca93274df51cd + return true; + ASSERT(hasProcessPrivilege(ProcessPrivilege::CanCommunicateWithWindowServer)); - NSWindow *activeViewWindow = activeWindow(); - return activeViewWindow.isKeyWindow || (activeViewWindow && [NSApp keyWindow] == activeViewWindow); -@@ -166,6 +177,9 @@ bool PageClientImpl::isViewWindowActive() + RetainPtr activeViewWindow = activeWindow(); + return activeViewWindow.get().isKeyWindow || (activeViewWindow && [NSApp keyWindow] == activeViewWindow.get()); +@@ -168,6 +178,9 @@ bool PageClientImpl::isViewWindowActive() bool PageClientImpl::isViewFocused() { @@ -18808,17 +17703,17 @@ index 3fe2a9487a96b31f476bb17e45374f880e80da9a..b72433e5981f298d4d1ca93274df51cd // FIXME: This is called from the WebPageProxy constructor before we have a WebViewImpl. // Once WebViewImpl and PageClient merge, this won't be a problem. if (!m_impl) -@@ -189,6 +203,9 @@ void PageClientImpl::makeFirstResponder() +@@ -191,6 +204,9 @@ void PageClientImpl::makeFirstResponder() bool PageClientImpl::isViewVisible() { + if (_headless) + return true; + - NSView *activeView = this->activeView(); - NSWindow *activeViewWindow = activeWindow(); + RetainPtr activeView = this->activeView(); + RetainPtr activeViewWindow = activeWindow(); -@@ -272,7 +289,8 @@ void PageClientImpl::didRelaunchProcess() +@@ -265,7 +281,8 @@ void PageClientImpl::didRelaunchProcess() void PageClientImpl::preferencesDidChange() { @@ -18828,7 +17723,7 @@ index 3fe2a9487a96b31f476bb17e45374f880e80da9a..b72433e5981f298d4d1ca93274df51cd } void PageClientImpl::toolTipChanged(const String& oldToolTip, const String& newToolTip) -@@ -475,6 +493,8 @@ IntRect PageClientImpl::rootViewToAccessibilityScreen(const IntRect& rect) +@@ -474,6 +491,8 @@ IntRect PageClientImpl::rootViewToAccessibilityScreen(const IntRect& rect) void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent& event, bool eventWasHandled) { @@ -18837,16 +17732,16 @@ index 3fe2a9487a96b31f476bb17e45374f880e80da9a..b72433e5981f298d4d1ca93274df51cd m_impl->doneWithKeyEvent(event.nativeEvent(), eventWasHandled); } -@@ -494,6 +514,8 @@ void PageClientImpl::computeHasVisualSearchResults(const URL& imageURL, Shareabl +@@ -493,6 +512,8 @@ void PageClientImpl::computeHasVisualSearchResults(const URL& imageURL, Shareabl RefPtr PageClientImpl::createPopupMenuProxy(WebPageProxy& page) { + if (_headless) + return nullptr; - return WebPopupMenuProxyMac::create(m_view, page.popupMenuClient()); + return WebPopupMenuProxyMac::create(m_view.get().get(), page.popupMenuClient()); } -@@ -635,6 +657,12 @@ CALayer *PageClientImpl::footerBannerLayer() const +@@ -633,6 +654,12 @@ CALayer *PageClientImpl::footerBannerLayer() const return m_impl->footerBannerLayer(); } @@ -18859,12 +17754,12 @@ index 3fe2a9487a96b31f476bb17e45374f880e80da9a..b72433e5981f298d4d1ca93274df51cd RefPtr PageClientImpl::takeViewSnapshot(std::optional&&) { return m_impl->takeViewSnapshot(); -@@ -810,6 +838,13 @@ void PageClientImpl::beganExitFullScreen(const IntRect& initialFrame, const IntR +@@ -844,6 +871,13 @@ void PageClientImpl::beganExitFullScreen(const IntRect& initialFrame, const IntR #endif // ENABLE(FULLSCREEN_API) +#if ENABLE(TOUCH_EVENTS) -+void PageClientImpl::doneWithTouchEvent(const NativeWebTouchEvent& event, bool wasEventHandled) ++void PageClientImpl::doneWithTouchEvent(const WebTouchEvent& event, bool wasEventHandled) +{ + notImplemented(); +} @@ -18873,7 +17768,7 @@ index 3fe2a9487a96b31f476bb17e45374f880e80da9a..b72433e5981f298d4d1ca93274df51cd void PageClientImpl::navigationGestureDidBegin() { m_impl->dismissContentRelativeChildWindowsWithAnimation(true); -@@ -997,6 +1032,9 @@ void PageClientImpl::requestScrollToRect(const WebCore::FloatRect& targetRect, c +@@ -1024,6 +1058,9 @@ void PageClientImpl::requestScrollToRect(const WebCore::FloatRect& targetRect, c bool PageClientImpl::windowIsFrontWindowUnderMouse(const NativeWebMouseEvent& event) { @@ -18884,15 +17779,20 @@ index 3fe2a9487a96b31f476bb17e45374f880e80da9a..b72433e5981f298d4d1ca93274df51cd } diff --git a/Source/WebKit/UIProcess/mac/SecItemShimProxy.messages.in b/Source/WebKit/UIProcess/mac/SecItemShimProxy.messages.in -index 21c925bafb662dbe961baaad7f25bf4296236d76..5496a33c558a00a5ba96d10223e600aa38de99c4 100644 +index f46895285dbc84c624537a194814c18f771a0c08..29ef9e5afa13b8d2b47b7f2dd4ce37846b61c35f 100644 --- a/Source/WebKit/UIProcess/mac/SecItemShimProxy.messages.in +++ b/Source/WebKit/UIProcess/mac/SecItemShimProxy.messages.in -@@ -20,11 +20,11 @@ +@@ -20,6 +20,7 @@ # 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. +#if ENABLE(SEC_ITEM_SHIM) - messages -> SecItemShimProxy NotRefCounted { + [ + DispatchedFrom=Networking, + DispatchedTo=UI, +@@ -27,9 +28,8 @@ + ] + messages -> SecItemShimProxy { -#if ENABLE(SEC_ITEM_SHIM) SecItemRequestSync(WebKit::SecItemRequestData request) -> (std::optional response) Synchronous @@ -18902,10 +17802,10 @@ index 21c925bafb662dbe961baaad7f25bf4296236d76..5496a33c558a00a5ba96d10223e600aa } +#endif diff --git a/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.h b/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.h -index 6ab7aacaebfda818e3010bb06db72c8552ac598a..3e19cba50d73084392f62f176ad4c3153803e579 100644 +index a3c53c0bf913385d4d2d92900360d5f7d75927f8..e5570ef599ff1b59224648c353f8ab16f8fe7f88 100644 --- a/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.h +++ b/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.h -@@ -68,6 +68,7 @@ private: +@@ -81,6 +81,7 @@ private: void show() override; void showContextMenuWithItems(Vector>&&) override; void useContextMenuItems(Vector>&&) override; @@ -18914,10 +17814,10 @@ index 6ab7aacaebfda818e3010bb06db72c8552ac598a..3e19cba50d73084392f62f176ad4c315 bool showAfterPostProcessingContextData(); diff --git a/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.mm b/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.mm -index 6da27ca16f9f4d359118053049caa5033b6789d7..254e582066fbc774fc02c69dddbc1ae589efdc7a 100644 +index c8d9a4ae3fb5ef85afa837a1743c119ae34e1f7b..486a774cd1c98d9985c9d3c92418f835a9be2de1 100644 --- a/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.mm +++ b/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.mm -@@ -481,6 +481,12 @@ void WebContextMenuProxyMac::getShareMenuItem(CompletionHandler WebContextMenuProxyMac::createShareMenuItem(ShareMenuItemT } #endif @@ -18982,10 +17882,10 @@ index 0000000000000000000000000000000000000000..6113f4cd60a5d72b8ead61176cb43200 +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/mac/WebPageInspectorInputAgentMac.mm b/Source/WebKit/UIProcess/mac/WebPageInspectorInputAgentMac.mm new file mode 100644 -index 0000000000000000000000000000000000000000..4ec25daff6a0c75e378eb25b2f2638e2311a783c +index 0000000000000000000000000000000000000000..dd52991f936aa1c046b404801ee97237d0a55748 --- /dev/null +++ b/Source/WebKit/UIProcess/mac/WebPageInspectorInputAgentMac.mm -@@ -0,0 +1,130 @@ +@@ -0,0 +1,135 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * @@ -19013,8 +17913,12 @@ index 0000000000000000000000000000000000000000..4ec25daff6a0c75e378eb25b2f2638e2 + +#import "config.h" +#import "NativeWebMouseEvent.h" ++#import "NetworkProcessMessages.h" ++#import "NetworkProcessProxy.h" +#import "WebPageInspectorInputAgent.h" +#import "WebPageProxy.h" ++#import "WebPageProxyMessages.h" ++#import "WebsiteDataStore.h" +#import +#import +#import "NativeWebKeyboardEvent.h" @@ -19096,7 +18000,8 @@ index 0000000000000000000000000000000000000000..4ec25daff6a0c75e378eb25b2f2638e2 + if (text.length() > 0 && macCommands.size() == 0) + macCommands.append(WebCore::KeypressCommand("insertText:"_s, text)); + if (!macCommands.isEmpty()) -+ m_page.grantAccessToCurrentPasteboardData(NSPasteboardNameGeneral); ++ if (auto replyID = m_page.grantAccessToCurrentPasteboardData(NSPasteboardNameGeneral, [] () { })) ++ m_page.websiteDataStore().protectedNetworkProcess()->connection().waitForAsyncReplyAndDispatchImmediately(*replyID, 100_ms); + NativeWebKeyboardEvent event( + type, + text, @@ -19117,10 +18022,18 @@ index 0000000000000000000000000000000000000000..4ec25daff6a0c75e378eb25b2f2638e2 + +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/mac/WebViewImpl.h b/Source/WebKit/UIProcess/mac/WebViewImpl.h -index 363c8b384c7e2e2379f06903c77c7d139e1a454f..b0ca037bc8741ec245d9afefa2be734e1aa6ba32 100644 +index 85f0df23b0b5c1e76f2c9e12ad43b9802c23f579..9202e7923ded8b543dcee636166c100e739a094f 100644 --- a/Source/WebKit/UIProcess/mac/WebViewImpl.h +++ b/Source/WebKit/UIProcess/mac/WebViewImpl.h -@@ -526,6 +526,9 @@ ALLOW_DEPRECATED_DECLARATIONS_END +@@ -35,6 +35,7 @@ + #include "WKLayoutMode.h" + #include "WKTextAnimationType.h" + #include ++#include + #include + #include + #include +@@ -570,6 +571,9 @@ public: void provideDataForPasteboard(NSPasteboard *, NSString *type); NSArray *namesOfPromisedFilesDroppedAtDestination(NSURL *dropDestination); @@ -19128,13 +18041,13 @@ index 363c8b384c7e2e2379f06903c77c7d139e1a454f..b0ca037bc8741ec245d9afefa2be734e + RetainPtr takeSnapshotForAutomation(); +// Paywright end RefPtr takeViewSnapshot(); + RefPtr takeViewSnapshot(ForceSoftwareCapturingViewportSnapshot); void saveBackForwardSnapshotForCurrentItem(); - void saveBackForwardSnapshotForItem(WebBackForwardListItem&); diff --git a/Source/WebKit/UIProcess/mac/WebViewImpl.mm b/Source/WebKit/UIProcess/mac/WebViewImpl.mm -index b12b690eff989c9f4235c874360e26543c3e95ee..e8be29392d3c1765fc977f8a0036a24e7d95c799 100644 +index fa8aba243a8808dc781d40f1daf1480e6b655656..85f02dbfa3cfe47ee2adceee2714104445cdb7ba 100644 --- a/Source/WebKit/UIProcess/mac/WebViewImpl.mm +++ b/Source/WebKit/UIProcess/mac/WebViewImpl.mm -@@ -2410,6 +2410,11 @@ WebCore::DestinationColorSpace WebViewImpl::colorSpace() +@@ -2444,6 +2444,11 @@ WebCore::DestinationColorSpace WebViewImpl::colorSpace() if (!m_colorSpace) m_colorSpace = [NSColorSpace sRGBColorSpace]; } @@ -19146,8 +18059,8 @@ index b12b690eff989c9f4235c874360e26543c3e95ee..e8be29392d3c1765fc977f8a0036a24e ASSERT(m_colorSpace); return WebCore::DestinationColorSpace { [m_colorSpace CGColorSpace] }; -@@ -4487,6 +4492,18 @@ ALLOW_DEPRECATED_DECLARATIONS_BEGIN - ALLOW_DEPRECATED_DECLARATIONS_END +@@ -4724,6 +4729,17 @@ static RetainPtr takeWindowSnapshot(CGSWindowID windowID, bool captu + return WebCore::cgWindowListCreateImage(CGRectNull, kCGWindowListOptionIncludingWindow, windowID, imageOptions); } +// Paywright begin @@ -19157,20 +18070,19 @@ index b12b690eff989c9f4235c874360e26543c3e95ee..e8be29392d3c1765fc977f8a0036a24e + CGSWindowID windowID = (CGSWindowID)window.windowNumber; + if (!windowID || !window.isVisible) + return nullptr; -+ -+ return takeWindowSnapshot(windowID, true); ++ return takeWindowSnapshot(windowID, true, ForceSoftwareCapturingViewportSnapshot::Yes); +} +// Paywright end + RefPtr WebViewImpl::takeViewSnapshot() { - NSWindow *window = [m_view window]; + return takeViewSnapshot(ForceSoftwareCapturingViewportSnapshot::No); diff --git a/Source/WebKit/UIProcess/win/InspectorPlaywrightAgentClientWin.cpp b/Source/WebKit/UIProcess/win/InspectorPlaywrightAgentClientWin.cpp new file mode 100644 -index 0000000000000000000000000000000000000000..dd7fe0604188bb025f361f1c44685e38bbf935ca +index 0000000000000000000000000000000000000000..4f54a9445e5a7ecdb750c5c521da4f397776e633 --- /dev/null +++ b/Source/WebKit/UIProcess/win/InspectorPlaywrightAgentClientWin.cpp -@@ -0,0 +1,90 @@ +@@ -0,0 +1,89 @@ +/* + * Copyright (C) 2020 Microsoft Corporation. + * @@ -19250,7 +18162,6 @@ index 0000000000000000000000000000000000000000..dd7fe0604188bb025f361f1c44685e38 + WebCore::CurlProxySettings settings(WTFMove(proxyURL), String(proxyBypassList)); + browserContext->dataStore->setNetworkProxySettings(WTFMove(settings)); + } -+ PAL::SessionID sessionID = browserContext->dataStore->sessionID(); + return browserContext; +} + @@ -19370,10 +18281,10 @@ index 0000000000000000000000000000000000000000..135a60361fa8fbf907382625e7c8dd4e + +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/win/WebContextMenuProxyWin.cpp b/Source/WebKit/UIProcess/win/WebContextMenuProxyWin.cpp -index da6859dcd444de953a255a5c835c659b018a08a6..95fefa995acaedf879c88130e44d9a1bbd0d107f 100644 +index bae35256ed815f7dac0b11ae439531d4ef3cb108..81e063b50a0132f8b36f3461f95d2ce1968198f5 100644 --- a/Source/WebKit/UIProcess/win/WebContextMenuProxyWin.cpp +++ b/Source/WebKit/UIProcess/win/WebContextMenuProxyWin.cpp -@@ -112,5 +112,11 @@ WebContextMenuProxyWin::~WebContextMenuProxyWin() +@@ -115,5 +115,11 @@ WebContextMenuProxyWin::~WebContextMenuProxyWin() ::DestroyMenu(m_menu); } @@ -19386,17 +18297,17 @@ index da6859dcd444de953a255a5c835c659b018a08a6..95fefa995acaedf879c88130e44d9a1b } // namespace WebKit #endif // ENABLE(CONTEXT_MENUS) diff --git a/Source/WebKit/UIProcess/win/WebContextMenuProxyWin.h b/Source/WebKit/UIProcess/win/WebContextMenuProxyWin.h -index 0c80d970c3f9a987faf620081c909f6c7021970d..1467e5481f7417913c0d12a1cb492d02b2a7d1b7 100644 +index e7f71156d7a897ab477d0d7f167b2c2992cdb161..325d8813afff13d86a4892a8e99738f19c2729ac 100644 --- a/Source/WebKit/UIProcess/win/WebContextMenuProxyWin.h +++ b/Source/WebKit/UIProcess/win/WebContextMenuProxyWin.h -@@ -47,6 +47,7 @@ public: +@@ -49,6 +49,7 @@ public: private: - WebContextMenuProxyWin(WebPageProxy&, ContextMenuContextData&&, const UserData&); + WebContextMenuProxyWin(WebPageProxy&, FrameInfoData&&, ContextMenuContextData&&, const UserData&); void showContextMenuWithItems(Vector>&&) override; + void hide() override; HMENU m_menu; - }; + FrameInfoData m_frameInfo; diff --git a/Source/WebKit/UIProcess/win/WebPageInspectorEmulationAgentWin.cpp b/Source/WebKit/UIProcess/win/WebPageInspectorEmulationAgentWin.cpp new file mode 100644 index 0000000000000000000000000000000000000000..df55ee613ec085cb85ed12b45deff3a1b046861c @@ -19522,9 +18433,22 @@ index 0000000000000000000000000000000000000000..8b474c730139b44a13c9d5b2d13ee204 +} + +} // namespace WebKit +diff --git a/Source/WebKit/UIProcess/win/WebView.cpp b/Source/WebKit/UIProcess/win/WebView.cpp +index 5180da3ec22d56e8a9520e31cad076d86ae5be9f..f01be74573843e7b374c34035c09f114bdc7349c 100644 +--- a/Source/WebKit/UIProcess/win/WebView.cpp ++++ b/Source/WebKit/UIProcess/win/WebView.cpp +@@ -576,7 +576,7 @@ LRESULT WebView::onSizeEvent(HWND hwnd, UINT, WPARAM, LPARAM lParam, bool& handl + float intrinsicDeviceScaleFactor = deviceScaleFactorForWindow(hwnd); + if (m_page) + m_page->setIntrinsicDeviceScaleFactor(intrinsicDeviceScaleFactor); +- m_viewSize = expandedIntSize(FloatSize(LOWORD(lParam), HIWORD(lParam)) / intrinsicDeviceScaleFactor); ++ m_viewSize = expandedIntSize(FloatSize(LOWORD(lParam), HIWORD(lParam))); + + if (m_page && m_page->drawingArea()) { + // FIXME specify correctly layerPosition. diff --git a/Source/WebKit/UIProcess/wpe/InspectorTargetProxyWPE.cpp b/Source/WebKit/UIProcess/wpe/InspectorTargetProxyWPE.cpp new file mode 100644 -index 0000000000000000000000000000000000000000..7453194ca6f032ba86a4c67f5bf12688ab6ec1be +index 0000000000000000000000000000000000000000..24da079059ed4a45131e18d7fbf56a29a54bd513 --- /dev/null +++ b/Source/WebKit/UIProcess/wpe/InspectorTargetProxyWPE.cpp @@ -0,0 +1,40 @@ @@ -19563,17 +18487,17 @@ index 0000000000000000000000000000000000000000..7453194ca6f032ba86a4c67f5bf12688 + +void InspectorTargetProxy::platformActivate(String& error) const +{ -+ struct wpe_view_backend* backend = m_page.viewBackend(); ++ struct wpe_view_backend* backend = m_page->viewBackend(); + wpe_view_backend_add_activity_state(backend, wpe_view_activity_state_visible | wpe_view_activity_state_focused | wpe_view_activity_state_in_window); +} + +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/wpe/WebColorPickerWPE.cpp b/Source/WebKit/UIProcess/wpe/WebColorPickerWPE.cpp new file mode 100644 -index 0000000000000000000000000000000000000000..adec63a0a9d6d67bdbdadb4024005ff97ce79d10 +index 0000000000000000000000000000000000000000..7df77e30c2e7303dc6aaad560434e5b8e35f4f3c --- /dev/null +++ b/Source/WebKit/UIProcess/wpe/WebColorPickerWPE.cpp -@@ -0,0 +1,61 @@ +@@ -0,0 +1,57 @@ +/* + * Copyright (C) 2015 Igalia S.L. + * @@ -19602,8 +18526,6 @@ index 0000000000000000000000000000000000000000..adec63a0a9d6d67bdbdadb4024005ff9 +#include "config.h" +#include "WebColorPickerWPE.h" + -+#if ENABLE(INPUT_TYPE_COLOR) -+ +#include "WebPageProxy.h" + +namespace WebKit { @@ -19633,14 +18555,12 @@ index 0000000000000000000000000000000000000000..adec63a0a9d6d67bdbdadb4024005ff9 +} + +} // namespace WebKit -+ -+#endif // ENABLE(INPUT_TYPE_COLOR) diff --git a/Source/WebKit/UIProcess/wpe/WebColorPickerWPE.h b/Source/WebKit/UIProcess/wpe/WebColorPickerWPE.h new file mode 100644 -index 0000000000000000000000000000000000000000..7edc93b3873dd42a7f877626551ec994395baae9 +index 0000000000000000000000000000000000000000..da58334235809cfed62e90150784bf2506f7a8f2 --- /dev/null +++ b/Source/WebKit/UIProcess/wpe/WebColorPickerWPE.h -@@ -0,0 +1,57 @@ +@@ -0,0 +1,54 @@ +/* + * Copyright (C) 2015 Igalia S.L. + * @@ -19669,8 +18589,6 @@ index 0000000000000000000000000000000000000000..7edc93b3873dd42a7f877626551ec994 +#ifndef WebColorPickerWPE_h +#define WebColorPickerWPE_h + -+#if ENABLE(INPUT_TYPE_COLOR) -+ +#include "WebColorPicker.h" + +typedef struct _GtkColorChooser GtkColorChooser; @@ -19696,8 +18614,125 @@ index 0000000000000000000000000000000000000000..7edc93b3873dd42a7f877626551ec994 + +} // namespace WebKit + -+#endif // ENABLE(INPUT_TYPE_COLOR) +#endif // WebColorPickerWPE_h +diff --git a/Source/WebKit/UIProcess/wpe/WebDataListSuggestionsDropdownWPE.cpp b/Source/WebKit/UIProcess/wpe/WebDataListSuggestionsDropdownWPE.cpp +new file mode 100644 +index 0000000000000000000000000000000000000000..694eb24db4a407553da12fb0a25d8963fd0ef6ac +--- /dev/null ++++ b/Source/WebKit/UIProcess/wpe/WebDataListSuggestionsDropdownWPE.cpp +@@ -0,0 +1,55 @@ ++/* ++ * Copyright (C) 2019 Igalia S.L. ++ * ++ * 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 APPLE INC. AND ITS 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 APPLE INC. OR ITS 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. ++ */ ++ ++#include "config.h" ++#include "WebDataListSuggestionsDropdownWPE.h" ++ ++#include "WebPageProxy.h" ++#include ++ ++namespace WebKit { ++ ++WebDataListSuggestionsDropdownWPE::WebDataListSuggestionsDropdownWPE(WebPageProxy& page) ++ : WebDataListSuggestionsDropdown(page) ++{ ++} ++ ++WebDataListSuggestionsDropdownWPE::~WebDataListSuggestionsDropdownWPE() ++{ ++} ++ ++void WebDataListSuggestionsDropdownWPE::show(WebCore::DataListSuggestionInformation&& information) ++{ ++} ++ ++void WebDataListSuggestionsDropdownWPE::handleKeydownWithIdentifier(const String& key) ++{ ++} ++ ++void WebDataListSuggestionsDropdownWPE::close() ++{ ++} ++ ++} // namespace WebKit +diff --git a/Source/WebKit/UIProcess/wpe/WebDataListSuggestionsDropdownWPE.h b/Source/WebKit/UIProcess/wpe/WebDataListSuggestionsDropdownWPE.h +new file mode 100644 +index 0000000000000000000000000000000000000000..5d4b0d204b7dc564564d2126e9f256fa4f4bd6f6 +--- /dev/null ++++ b/Source/WebKit/UIProcess/wpe/WebDataListSuggestionsDropdownWPE.h +@@ -0,0 +1,51 @@ ++/* ++ * Copyright (C) 2019 Igalia S.L. ++ * ++ * 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 APPLE INC. AND ITS 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 APPLE INC. OR ITS 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. ++ */ ++ ++#pragma once ++ ++#include "WebDataListSuggestionsDropdown.h" ++ ++namespace WebKit { ++ ++class WebPageProxy; ++ ++class WebDataListSuggestionsDropdownWPE final : public WebDataListSuggestionsDropdown { ++public: ++ static Ref create(WebPageProxy& page) ++ { ++ return adoptRef(*new WebDataListSuggestionsDropdownWPE(page)); ++ } ++ ++ ~WebDataListSuggestionsDropdownWPE(); ++ ++private: ++ WebDataListSuggestionsDropdownWPE(WebPageProxy&); ++ ++ void show(WebCore::DataListSuggestionInformation&&) final; ++ void handleKeydownWithIdentifier(const String&) final; ++ void close() final; ++}; ++ ++} // namespace WebKit diff --git a/Source/WebKit/UIProcess/wpe/WebDateTimePickerWPE.cpp b/Source/WebKit/UIProcess/wpe/WebDateTimePickerWPE.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a44463faf011fbab08f87bb7007a5e71c2a73758 @@ -19818,10 +18853,10 @@ index 0000000000000000000000000000000000000000..0c0e3fce33b06ee72c4c29d2a4abe964 +#endif // ENABLE(DATE_AND_TIME_INPUT_TYPES) diff --git a/Source/WebKit/UIProcess/wpe/WebPageInspectorEmulationAgentWPE.cpp b/Source/WebKit/UIProcess/wpe/WebPageInspectorEmulationAgentWPE.cpp new file mode 100644 -index 0000000000000000000000000000000000000000..5dc76aa302cb574307059e66a1b73730efe920da +index 0000000000000000000000000000000000000000..182398f24909cbc42cac897d66546991f46c1d5d --- /dev/null +++ b/Source/WebKit/UIProcess/wpe/WebPageInspectorEmulationAgentWPE.cpp -@@ -0,0 +1,41 @@ +@@ -0,0 +1,53 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * @@ -19850,6 +18885,7 @@ index 0000000000000000000000000000000000000000..5dc76aa302cb574307059e66a1b73730 +#include "config.h" +#include "WebPageInspectorEmulationAgent.h" + ++#include "DrawingAreaProxyCoordinatedGraphics.h" +#include "WebPageProxy.h" +#include + @@ -19857,9 +18893,20 @@ index 0000000000000000000000000000000000000000..5dc76aa302cb574307059e66a1b73730 + +void WebPageInspectorEmulationAgent::platformSetSize(int width, int height, Function&& callback) +{ ++ WebCore::IntSize viewSize(width, height); ++ if (m_page.viewSize() == viewSize) { ++ callback(String()); ++ return; ++ } ++ + struct wpe_view_backend* backend = m_page.viewBackend(); -+ wpe_view_backend_dispatch_set_size(backend, width, height); -+ callback(String()); ++ wpe_view_backend_dispatch_set_size(backend, viewSize.width(), viewSize.height()); ++ if (auto* drawingArea = static_cast(m_page.drawingArea())) { ++ drawingArea->waitForSizeUpdate([callback = WTFMove(callback)](const DrawingAreaProxyCoordinatedGraphics&) mutable { ++ callback(String()); ++ }); ++ } else ++ callback(String()); +} + +} // namespace WebKit @@ -19924,35 +18971,26 @@ index 0000000000000000000000000000000000000000..a7d88f8c745f95af21db71dcfce368ba +} + +} // namespace WebKit -diff --git a/Source/WebKit/UIProcess/wpe/WebPageProxyWPE.cpp b/Source/WebKit/UIProcess/wpe/WebPageProxyWPE.cpp -index b6536b74452c26a4d661bcf6039af54824f258d0..ade7c4ad1cef7bc69c452bef404eb38437c93088 100644 ---- a/Source/WebKit/UIProcess/wpe/WebPageProxyWPE.cpp -+++ b/Source/WebKit/UIProcess/wpe/WebPageProxyWPE.cpp -@@ -29,6 +29,7 @@ - #include "EditorState.h" - #include "InputMethodState.h" - #include "PageClientImpl.h" -+#include - #include - - #if USE(ATK) -diff --git a/Source/WebKit/WPEPlatform/CMakeLists.txt b/Source/WebKit/WPEPlatform/CMakeLists.txt -index 9319cacf6dff2c3ffdd469927c91a880978a80aa..17a829b23ae6941b184d32e8701f0fd774639449 100644 ---- a/Source/WebKit/WPEPlatform/CMakeLists.txt -+++ b/Source/WebKit/WPEPlatform/CMakeLists.txt -@@ -82,6 +82,7 @@ set(WPEPlatform_SYSTEM_INCLUDE_DIRECTORIES - - set(WPEPlatform_LIBRARIES - Epoxy::Epoxy -+ rt - WTF - ${GLIB_GIO_LIBRARIES} - ${GLIB_GOBJECT_LIBRARIES} +diff --git a/Source/WebKit/UIProcess/wpe/WebPreferencesWPE.cpp b/Source/WebKit/UIProcess/wpe/WebPreferencesWPE.cpp +index 9b688ad328317fea4fd96ce66e9714bad8f0f937..402a36a9c565e13ec298aa7f014f0d9208ebddb7 100644 +--- a/Source/WebKit/UIProcess/wpe/WebPreferencesWPE.cpp ++++ b/Source/WebKit/UIProcess/wpe/WebPreferencesWPE.cpp +@@ -33,6 +33,10 @@ void WebPreferences::platformInitializeStore() + setAcceleratedCompositingEnabled(true); + setForceCompositingMode(true); + setThreadedScrollingEnabled(true); ++ ++ // Playwright override begin ++ setThreadedScrollingEnabled(false); ++ // Playwright override end + } + + } // namespace WebKit diff --git a/Source/WebKit/WebKit.xcodeproj/project.pbxproj b/Source/WebKit/WebKit.xcodeproj/project.pbxproj -index 5638e7e7ca660b2bb7c9b3f21dde5f5dfb68dad0..d4c7e4081d7b4c80423e2a406f8471c3ffb292f7 100644 +index 7504d2cdd6d31bdfb1892dab8e1716253ce54ccc..c1ecef732f88cbf5c6277a0aa5c0d48806565ac2 100644 --- a/Source/WebKit/WebKit.xcodeproj/project.pbxproj +++ b/Source/WebKit/WebKit.xcodeproj/project.pbxproj -@@ -1542,6 +1542,7 @@ +@@ -1560,6 +1560,7 @@ 5CABDC8722C40FED001EDE8E /* APIMessageListener.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CABDC8322C40FA7001EDE8E /* APIMessageListener.h */; }; 5CADDE05215046BD0067D309 /* WKWebProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C74300E21500492004BFA17 /* WKWebProcess.h */; settings = {ATTRIBUTES = (Private, ); }; }; 5CAECB6627465AE400AB78D0 /* UnifiedSource115.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5CAECB5E27465AE300AB78D0 /* UnifiedSource115.cpp */; }; @@ -19960,7 +18998,7 @@ index 5638e7e7ca660b2bb7c9b3f21dde5f5dfb68dad0..d4c7e4081d7b4c80423e2a406f8471c3 5CAF7AA726F93AB00003F19E /* adattributiond.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5CAF7AA526F93A950003F19E /* adattributiond.cpp */; }; 5CAFDE452130846300B1F7E1 /* _WKInspector.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CAFDE422130843500B1F7E1 /* _WKInspector.h */; settings = {ATTRIBUTES = (Private, ); }; }; 5CAFDE472130846A00B1F7E1 /* _WKInspectorInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CAFDE442130843600B1F7E1 /* _WKInspectorInternal.h */; }; -@@ -2381,6 +2382,18 @@ +@@ -2346,6 +2347,18 @@ DF0C5F28252ECB8E00D921DB /* WKDownload.h in Headers */ = {isa = PBXBuildFile; fileRef = DF0C5F24252ECB8D00D921DB /* WKDownload.h */; settings = {ATTRIBUTES = (Public, ); }; }; DF0C5F2A252ECB8E00D921DB /* WKDownloadDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = DF0C5F26252ECB8E00D921DB /* WKDownloadDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; DF0C5F2B252ED44000D921DB /* WKDownloadInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = DF0C5F25252ECB8E00D921DB /* WKDownloadInternal.h */; }; @@ -19979,7 +19017,7 @@ index 5638e7e7ca660b2bb7c9b3f21dde5f5dfb68dad0..d4c7e4081d7b4c80423e2a406f8471c3 DF462E0F23F22F5500EFF35F /* WKHTTPCookieStorePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = DF462E0E23F22F5300EFF35F /* WKHTTPCookieStorePrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; DF462E1223F338BE00EFF35F /* WKContentWorldPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = DF462E1123F338AD00EFF35F /* WKContentWorldPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; DF7A231C291B088D00B98DF3 /* WKSnapshotConfigurationPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = DF7A231B291B088D00B98DF3 /* WKSnapshotConfigurationPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; -@@ -2468,6 +2481,8 @@ +@@ -2447,6 +2460,8 @@ E5BEF6822130C48000F31111 /* WebDataListSuggestionsDropdownIOS.h in Headers */ = {isa = PBXBuildFile; fileRef = E5BEF6802130C47F00F31111 /* WebDataListSuggestionsDropdownIOS.h */; }; E5CB07DC20E1678F0022C183 /* WKFormColorControl.h in Headers */ = {isa = PBXBuildFile; fileRef = E5CB07DA20E1678F0022C183 /* WKFormColorControl.h */; }; E5CBA76427A318E100DF7858 /* UnifiedSource120.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E5CBA75F27A3187800DF7858 /* UnifiedSource120.cpp */; }; @@ -19988,17 +19026,17 @@ index 5638e7e7ca660b2bb7c9b3f21dde5f5dfb68dad0..d4c7e4081d7b4c80423e2a406f8471c3 E5CBA76527A318E100DF7858 /* UnifiedSource118.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E5CBA76127A3187900DF7858 /* UnifiedSource118.cpp */; }; E5CBA76627A318E100DF7858 /* UnifiedSource116.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E5CBA76327A3187B00DF7858 /* UnifiedSource116.cpp */; }; E5CBA76727A318E100DF7858 /* UnifiedSource119.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E5CBA76027A3187900DF7858 /* UnifiedSource119.cpp */; }; -@@ -2488,6 +2503,9 @@ - EBA8D3B627A5E33F00CB7900 /* MockPushServiceConnection.mm in Sources */ = {isa = PBXBuildFile; fileRef = EBA8D3B027A5E33F00CB7900 /* MockPushServiceConnection.mm */; }; - EBA8D3B727A5E33F00CB7900 /* PushServiceConnection.mm in Sources */ = {isa = PBXBuildFile; fileRef = EBA8D3B127A5E33F00CB7900 /* PushServiceConnection.mm */; }; - ED82A7F2128C6FAF004477B3 /* WKBundlePageOverlay.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A22F0FF1289FCD90085E74F /* WKBundlePageOverlay.h */; settings = {ATTRIBUTES = (Private, ); }; }; +@@ -2485,6 +2500,9 @@ + F3EEEE592DB318270038CC1D /* BidiBrowserAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = F3EEEE572DB318270038CC1D /* BidiBrowserAgent.h */; }; + F3EEEE5A2DB318270038CC1D /* BidiBrowserAgent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F3EEEE582DB318270038CC1D /* BidiBrowserAgent.cpp */; }; + F404455C2D5CFB56000E587E /* AppKitSoftLink.h in Headers */ = {isa = PBXBuildFile; fileRef = F404455A2D5CFB56000E587E /* AppKitSoftLink.h */; }; + F303B849249A8D640031DE5C /* ScreencastEncoder.h in Headers */ = {isa = PBXBuildFile; fileRef = F303B848249A8D3A0031DE5C /* ScreencastEncoder.h */; }; + F33C7AC7249AD79C0018BE41 /* libwebrtc.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = F33C7AC6249AD79C0018BE41 /* libwebrtc.dylib */; }; + F3867F0A24607D4E008F0F31 /* InspectorScreencastAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = F3867F0424607D2B008F0F31 /* InspectorScreencastAgent.h */; }; F409BA181E6E64BC009DA28E /* WKDragDestinationAction.h in Headers */ = {isa = PBXBuildFile; fileRef = F409BA171E6E64B3009DA28E /* WKDragDestinationAction.h */; settings = {ATTRIBUTES = (Private, ); }; }; F40C3B712AB401C5007A3567 /* WKDatePickerPopoverController.h in Headers */ = {isa = PBXBuildFile; fileRef = F40C3B6F2AB40167007A3567 /* WKDatePickerPopoverController.h */; }; - F41795A62AC61B78007F5F12 /* CompactContextMenuPresenter.h in Headers */ = {isa = PBXBuildFile; fileRef = F41795A42AC619A2007F5F12 /* CompactContextMenuPresenter.h */; }; -@@ -6218,6 +6236,7 @@ + F41145682CD939E0004CDBD1 /* _WKTouchEventGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = F41145652CD939E0004CDBD1 /* _WKTouchEventGenerator.h */; settings = {ATTRIBUTES = (Private, ); }; }; +@@ -6443,6 +6461,7 @@ 5CABDC8522C40FCC001EDE8E /* WKMessageListener.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKMessageListener.h; sourceTree = ""; }; 5CABE07A28F60E8A00D83FD9 /* WebPushMessage.serialization.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = WebPushMessage.serialization.in; sourceTree = ""; }; 5CADDE0D2151AA010067D309 /* AuthenticationChallengeDisposition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AuthenticationChallengeDisposition.h; sourceTree = ""; }; @@ -20006,7 +19044,7 @@ index 5638e7e7ca660b2bb7c9b3f21dde5f5dfb68dad0..d4c7e4081d7b4c80423e2a406f8471c3 5CAECB5E27465AE300AB78D0 /* UnifiedSource115.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = UnifiedSource115.cpp; sourceTree = ""; }; 5CAF7AA426F93A750003F19E /* adattributiond */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = adattributiond; sourceTree = BUILT_PRODUCTS_DIR; }; 5CAF7AA526F93A950003F19E /* adattributiond.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = adattributiond.cpp; sourceTree = ""; }; -@@ -7930,6 +7949,19 @@ +@@ -8171,6 +8190,19 @@ DF0C5F24252ECB8D00D921DB /* WKDownload.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKDownload.h; sourceTree = ""; }; DF0C5F25252ECB8E00D921DB /* WKDownloadInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKDownloadInternal.h; sourceTree = ""; }; DF0C5F26252ECB8E00D921DB /* WKDownloadDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKDownloadDelegate.h; sourceTree = ""; }; @@ -20026,19 +19064,19 @@ index 5638e7e7ca660b2bb7c9b3f21dde5f5dfb68dad0..d4c7e4081d7b4c80423e2a406f8471c3 DF462E0E23F22F5300EFF35F /* WKHTTPCookieStorePrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKHTTPCookieStorePrivate.h; sourceTree = ""; }; DF462E1123F338AD00EFF35F /* WKContentWorldPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKContentWorldPrivate.h; sourceTree = ""; }; DF58C6311371AC5800F9A37C /* NativeWebWheelEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NativeWebWheelEvent.h; sourceTree = ""; }; -@@ -8082,6 +8114,8 @@ +@@ -8346,6 +8378,8 @@ E5CBA76127A3187900DF7858 /* UnifiedSource118.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = UnifiedSource118.cpp; sourceTree = ""; }; E5CBA76227A3187900DF7858 /* UnifiedSource117.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = UnifiedSource117.cpp; sourceTree = ""; }; E5CBA76327A3187B00DF7858 /* UnifiedSource116.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = UnifiedSource116.cpp; sourceTree = ""; }; + E5CBA76F27A3187800DF7858 /* UnifiedSource121.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = UnifiedSource121.cpp; sourceTree = ""; }; + E5CBA77F27A3187800DF7858 /* UnifiedSource122.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = UnifiedSource122.cpp; sourceTree = ""; }; E5DEFA6726F8F42600AB68DB /* PhotosUISPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PhotosUISPI.h; sourceTree = ""; }; - EB0D312D275AE13300863D8F /* com.apple.webkit.webpushd.mac.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = com.apple.webkit.webpushd.mac.plist; sourceTree = ""; }; - EB0D312E275AE13300863D8F /* com.apple.webkit.webpushd.ios.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = com.apple.webkit.webpushd.ios.plist; sourceTree = ""; }; -@@ -8106,6 +8140,14 @@ - ECA680D31E6904B500731D20 /* ExtraPrivateSymbolsForTAPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExtraPrivateSymbolsForTAPI.h; sourceTree = ""; }; - ECBFC1DB1E6A4D66000300C7 /* ExtraPublicSymbolsForTAPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ExtraPublicSymbolsForTAPI.h; sourceTree = ""; }; - F036978715F4BF0500C3A80E /* WebColorPicker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebColorPicker.cpp; sourceTree = ""; }; + E88885662DC914C400C572B8 /* WKISO18013Request.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WKISO18013Request.h; sourceTree = ""; }; + E890313A2D96411E00AB0B09 /* DigitalCredentialsCoordinator.messages.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = DigitalCredentialsCoordinator.messages.in; sourceTree = ""; }; +@@ -8398,6 +8432,14 @@ + F404455A2D5CFB56000E587E /* AppKitSoftLink.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppKitSoftLink.h; sourceTree = ""; }; + F404455B2D5CFB56000E587E /* AppKitSoftLink.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = AppKitSoftLink.mm; sourceTree = ""; }; + F4063DDE2D71481E00F3FE6E /* LLVMProfiling.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LLVMProfiling.h; sourceTree = ""; }; + F303B847249A8D3A0031DE5C /* ScreencastEncoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScreencastEncoder.cpp; sourceTree = ""; }; + F303B848249A8D3A0031DE5C /* ScreencastEncoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScreencastEncoder.h; sourceTree = ""; }; + F31E2DA424C76E4B004B2775 /* WebMFileWriter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebMFileWriter.cpp; sourceTree = ""; }; @@ -20050,7 +19088,7 @@ index 5638e7e7ca660b2bb7c9b3f21dde5f5dfb68dad0..d4c7e4081d7b4c80423e2a406f8471c3 F409BA171E6E64B3009DA28E /* WKDragDestinationAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKDragDestinationAction.h; sourceTree = ""; }; F40C3B6F2AB40167007A3567 /* WKDatePickerPopoverController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = WKDatePickerPopoverController.h; path = ios/forms/WKDatePickerPopoverController.h; sourceTree = ""; }; F40C3B702AB40167007A3567 /* WKDatePickerPopoverController.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = WKDatePickerPopoverController.mm; path = ios/forms/WKDatePickerPopoverController.mm; sourceTree = ""; }; -@@ -8404,6 +8446,7 @@ +@@ -8825,6 +8867,7 @@ 3766F9EE189A1241003CF19B /* JavaScriptCore.framework in Frameworks */, 3766F9F1189A1254003CF19B /* libicucore.dylib in Frameworks */, 7B9FC5BB28A5233B007570E7 /* libWebKitPlatform.a in Frameworks */, @@ -20058,7 +19096,7 @@ index 5638e7e7ca660b2bb7c9b3f21dde5f5dfb68dad0..d4c7e4081d7b4c80423e2a406f8471c3 3766F9EF189A1244003CF19B /* QuartzCore.framework in Frameworks */, 37694525184FC6B600CDE21F /* Security.framework in Frameworks */, 37BEC4DD1948FC6A008B4286 /* WebCore.framework in Frameworks */, -@@ -11278,6 +11321,7 @@ +@@ -12013,6 +12056,7 @@ 99788ACA1F421DCA00C08000 /* _WKAutomationSessionConfiguration.mm */, 990D28A81C6404B000986977 /* _WKAutomationSessionDelegate.h */, 990D28AF1C65203900986977 /* _WKAutomationSessionInternal.h */, @@ -20066,7 +19104,7 @@ index 5638e7e7ca660b2bb7c9b3f21dde5f5dfb68dad0..d4c7e4081d7b4c80423e2a406f8471c3 5C4609E222430E4C009943C2 /* _WKContentRuleListAction.h */, 5C4609E322430E4D009943C2 /* _WKContentRuleListAction.mm */, 5C4609E422430E4D009943C2 /* _WKContentRuleListActionInternal.h */, -@@ -12589,6 +12633,7 @@ +@@ -13392,6 +13436,7 @@ E34B110C27C46BC6006D2F2E /* libWebCoreTestShim.dylib */, E34B110F27C46D09006D2F2E /* libWebCoreTestSupport.dylib */, DDE992F4278D06D900F60D26 /* libWebKitAdditions.a */, @@ -20074,7 +19112,7 @@ index 5638e7e7ca660b2bb7c9b3f21dde5f5dfb68dad0..d4c7e4081d7b4c80423e2a406f8471c3 57A9FF15252C6AEF006A2040 /* libWTF.a */, 5750F32A2032D4E500389347 /* LocalAuthentication.framework */, 570DAAB0230273D200E8FC04 /* NearField.framework */, -@@ -13159,6 +13204,12 @@ +@@ -13974,6 +14019,12 @@ children = ( 9197940423DBC4BB00257892 /* InspectorBrowserAgent.cpp */, 9197940323DBC4BB00257892 /* InspectorBrowserAgent.h */, @@ -20087,7 +19125,7 @@ index 5638e7e7ca660b2bb7c9b3f21dde5f5dfb68dad0..d4c7e4081d7b4c80423e2a406f8471c3 ); path = Agents; sourceTree = ""; -@@ -13167,6 +13218,7 @@ +@@ -13982,6 +14033,7 @@ isa = PBXGroup; children = ( A5D3504D1D78F0D2005124A9 /* RemoteWebInspectorUIProxyMac.mm */, @@ -20095,15 +19133,15 @@ index 5638e7e7ca660b2bb7c9b3f21dde5f5dfb68dad0..d4c7e4081d7b4c80423e2a406f8471c3 1CA8B935127C774E00576C2B /* WebInspectorUIProxyMac.mm */, 99A7ACE326012919006D57FD /* WKInspectorResourceURLSchemeHandler.h */, 99A7ACE42601291A006D57FD /* WKInspectorResourceURLSchemeHandler.mm */, -@@ -13884,6 +13936,7 @@ +@@ -14736,6 +14788,7 @@ E1513C65166EABB200149FCB /* AuxiliaryProcessProxy.h */, 46A2B6061E5675A200C3DEDA /* BackgroundProcessResponsivenessTimer.cpp */, 46A2B6071E5675A200C3DEDA /* BackgroundProcessResponsivenessTimer.h */, + D71A944B237239FB002C4D9E /* BrowserInspectorPipe.h */, 5C6D69352AC3935D0099BDAF /* BrowsingContextGroup.cpp */, 5C6D69362AC3935D0099BDAF /* BrowsingContextGroup.h */, - 07297F9C1C1711EA003F0735 /* DeviceIdHashSaltStorage.cpp */, -@@ -13907,6 +13960,8 @@ + 5CA98549210BEB5A0057EB6B /* BrowsingWarning.h */, +@@ -14760,6 +14813,8 @@ BC06F43912DBCCFB002D78DE /* GeolocationPermissionRequestProxy.cpp */, BC06F43812DBCCFB002D78DE /* GeolocationPermissionRequestProxy.h */, 2DD5A72A1EBF09A7009BA597 /* HiddenPageThrottlingAutoIncreasesCounter.h */, @@ -20112,24 +19150,24 @@ index 5638e7e7ca660b2bb7c9b3f21dde5f5dfb68dad0..d4c7e4081d7b4c80423e2a406f8471c3 5CEABA2B2333251400797797 /* LegacyGlobalSettings.cpp */, 5CEABA2A2333247700797797 /* LegacyGlobalSettings.h */, 31607F3819627002009B87DA /* LegacySessionStateCoding.h */, -@@ -13940,6 +13995,7 @@ - 1A0C227D2451130A00ED614D /* QuickLookThumbnailingSoftLink.mm */, - 1AEE57232409F142002005D6 /* QuickLookThumbnailLoader.h */, - 1AEE57242409F142002005D6 /* QuickLookThumbnailLoader.mm */, +@@ -14789,6 +14844,7 @@ + 4683569B21E81CC7006E27A3 /* ProvisionalPageProxy.cpp */, + 4683569A21E81CC7006E27A3 /* ProvisionalPageProxy.h */, + 411B89CB27B2B89600F9EBD3 /* QueryPermissionResultCallback.h */, + D71A94392370F060002C4D9E /* RemoteInspectorPipe.h */, 5CCB54DC2A4FEA6A0005FAA8 /* RemotePageDrawingAreaProxy.cpp */, 5CCB54DB2A4FEA6A0005FAA8 /* RemotePageDrawingAreaProxy.h */, - 5C907E9A294D507100B3402D /* RemotePageProxy.cpp */, -@@ -14045,6 +14101,8 @@ + FABBBC802D35AC6800820017 /* RemotePageFullscreenManagerProxy.cpp */, +@@ -14892,6 +14948,8 @@ BC7B6204129A0A6700D174A4 /* WebPageGroup.h */, 2D9EA3101A96D9EB002D2807 /* WebPageInjectedBundleClient.cpp */, 2D9EA30E1A96CBFF002D2807 /* WebPageInjectedBundleClient.h */, + D71A943F2371F67E002C4D9E /* WebPageInspectorEmulationAgent.h */, + D71A94402371F67E002C4D9E /* WebPageInspectorInputAgent.h */, + 9B7F8A502C785725000057F3 /* WebPageLoadTiming.h */, BC111B0B112F5E4F00337BAB /* WebPageProxy.cpp */, BC032DCB10F4389F0058C15A /* WebPageProxy.h */, - BCBD38FA125BAB9A00D2C29F /* WebPageProxy.messages.in */, -@@ -14209,6 +14267,7 @@ +@@ -15070,6 +15128,7 @@ BC646C1911DD399F006455B0 /* WKBackForwardListItemRef.h */, BC646C1611DD399F006455B0 /* WKBackForwardListRef.cpp */, BC646C1711DD399F006455B0 /* WKBackForwardListRef.h */, @@ -20137,17 +19175,17 @@ index 5638e7e7ca660b2bb7c9b3f21dde5f5dfb68dad0..d4c7e4081d7b4c80423e2a406f8471c3 BCB9E24A1120E15C00A137E0 /* WKContext.cpp */, BCB9E2491120E15C00A137E0 /* WKContext.h */, 1AE52F9319201F6B00A1FA37 /* WKContextConfigurationRef.cpp */, -@@ -14792,6 +14851,9 @@ +@@ -15646,6 +15705,9 @@ + 07EF07592745A8160066EA04 /* DisplayCaptureSessionManager.h */, + 07EF07582745A8160066EA04 /* DisplayCaptureSessionManager.mm */, 7AFA6F682A9F57C50055322A /* DisplayLinkMac.cpp */, - 31ABA79C215AF9E000C90E31 /* HighPerformanceGPUManager.h */, - 31ABA79D215AF9E000C90E31 /* HighPerformanceGPUManager.mm */, + D71A94302370E025002C4D9E /* InspectorPlaywrightAgentClientMac.h */, + D7EB04E62372A73B00F744CE /* InspectorPlaywrightAgentClientMac.mm */, + D79902AF236E9404005D6F7E /* InspectorTargetProxyMac.mm */, 1AFDE65B1954E8D500C48FFA /* LegacySessionStateCoding.cpp */, 0FCB4E5818BBE3D9000FCFC9 /* PageClientImplMac.h */, 0FCB4E5918BBE3D9000FCFC9 /* PageClientImplMac.mm */, -@@ -14815,6 +14877,8 @@ +@@ -15669,6 +15731,8 @@ E568B92120A3AC6A00E3C856 /* WebDataListSuggestionsDropdownMac.mm */, E55CD20124D09F1F0042DB9C /* WebDateTimePickerMac.h */, E55CD20224D09F1F0042DB9C /* WebDateTimePickerMac.mm */, @@ -20156,23 +19194,23 @@ index 5638e7e7ca660b2bb7c9b3f21dde5f5dfb68dad0..d4c7e4081d7b4c80423e2a406f8471c3 BC857E8512B71EBB00EDEB2E /* WebPageProxyMac.mm */, BC5750951268F3C6006F0F12 /* WebPopupMenuProxyMac.h */, BC5750961268F3C6006F0F12 /* WebPopupMenuProxyMac.mm */, -@@ -15820,6 +15884,7 @@ +@@ -16775,6 +16839,7 @@ 99788ACB1F421DDA00C08000 /* _WKAutomationSessionConfiguration.h in Headers */, 990D28AC1C6420CF00986977 /* _WKAutomationSessionDelegate.h in Headers */, 990D28B11C65208D00986977 /* _WKAutomationSessionInternal.h in Headers */, + D71A944A2372290B002C4D9E /* _WKBrowserInspector.h in Headers */, 5C4609E7224317B4009943C2 /* _WKContentRuleListAction.h in Headers */, 5C4609E8224317BB009943C2 /* _WKContentRuleListActionInternal.h in Headers */, - 1A5704F81BE01FF400874AF1 /* _WKContextMenuElementInfo.h in Headers */, -@@ -16129,6 +16194,7 @@ + 9B4CE9512CD99B7C00351173 /* _WKContentWorldConfiguration.h in Headers */, +@@ -17087,6 +17152,7 @@ E170876C16D6CA6900F99226 /* BlobRegistryProxy.h in Headers */, 4F601432155C5AA2001FBDE0 /* BlockingResponseMap.h in Headers */, 1A5705111BE410E600874AF1 /* BlockSPI.h in Headers */, + D71A944C237239FB002C4D9E /* BrowserInspectorPipe.h in Headers */, + 5CA9854A210BEB640057EB6B /* BrowsingWarning.h in Headers */, A7E69BCC2B2117A100D43D3F /* BufferAndBackendInfo.h in Headers */, BC3065FA1259344E00E71278 /* CacheModel.h in Headers */, - 935BF7FC2936BF1A00B41326 /* CacheStorageCache.h in Headers */, -@@ -16309,7 +16375,11 @@ +@@ -17270,7 +17336,11 @@ BC14DF77120B5B7900826C0C /* InjectedBundleScriptWorld.h in Headers */, CE550E152283752200D28791 /* InsertTextOptions.h in Headers */, 9197940523DBC4BB00257892 /* InspectorBrowserAgent.h in Headers */, @@ -20184,23 +19222,23 @@ index 5638e7e7ca660b2bb7c9b3f21dde5f5dfb68dad0..d4c7e4081d7b4c80423e2a406f8471c3 A5E391FD2183C1F800C8FB31 /* InspectorTargetProxy.h in Headers */, C5BCE5DF1C50766A00CDE3FA /* InteractionInformationAtPosition.h in Headers */, 2D4D2C811DF60BF3002EB10C /* InteractionInformationRequest.h in Headers */, -@@ -16567,6 +16637,7 @@ - CDAC20C923FC2F750021DEE3 /* RemoteCDMInstanceSessionIdentifier.h in Headers */, +@@ -17531,6 +17601,7 @@ + 0F6E7C532C4C386800F1DB85 /* RemoteDisplayListRecorderMessages.h in Headers */, F451C0FE2703B263002BA03B /* RemoteDisplayListRecorderProxy.h in Headers */, A78A5FE42B0EB39E005036D3 /* RemoteImageBufferSetIdentifier.h in Headers */, + D71A943A2370F061002C4D9E /* RemoteInspectorPipe.h in Headers */, 2D47B56D1810714E003A3AEE /* RemoteLayerBackingStore.h in Headers */, 2DDF731518E95060004F5A66 /* RemoteLayerBackingStoreCollection.h in Headers */, 1AB16AEA164B3A8800290D62 /* RemoteLayerTreeContext.h in Headers */, -@@ -16622,6 +16693,7 @@ +@@ -17588,6 +17659,7 @@ E1E552C516AE065F004ED653 /* SandboxInitializationParameters.h in Headers */, E36FF00327F36FBD004BE21A /* SandboxStateVariables.h in Headers */, 7BAB111025DD02B3008FC479 /* ScopedActiveMessageReceiveQueue.h in Headers */, + F303B849249A8D640031DE5C /* ScreencastEncoder.h in Headers */, + 6D4DF20C2D824242001F964C /* ScreenTimeWebsiteDataSupport.h in Headers */, 463BB93A2B9D08D80098C5C3 /* ScriptMessageHandlerIdentifier.h in Headers */, - E4D54D0421F1D72D007E3C36 /* ScrollingTreeFrameScrollingNodeRemoteIOS.h in Headers */, - 0F931C1C18C5711900DBA7C3 /* ScrollingTreeOverflowScrollingNodeIOS.h in Headers */, -@@ -16972,6 +17044,8 @@ + F4E28A362C923814008120DD /* ScriptTelemetry.h in Headers */, +@@ -17950,6 +18022,8 @@ 939EF87029D112EE00F23AEE /* WebPageInlines.h in Headers */, 9197940823DBC4CB00257892 /* WebPageInspectorAgentBase.h in Headers */, A513F5402154A5D700662841 /* WebPageInspectorController.h in Headers */, @@ -20209,29 +19247,64 @@ index 5638e7e7ca660b2bb7c9b3f21dde5f5dfb68dad0..d4c7e4081d7b4c80423e2a406f8471c3 A543E30C215C8A8D00279CD9 /* WebPageInspectorTarget.h in Headers */, A543E30D215C8A9000279CD9 /* WebPageInspectorTargetController.h in Headers */, A543E307215AD13700279CD9 /* WebPageInspectorTargetFrontendChannel.h in Headers */, -@@ -19367,6 +19441,8 @@ +@@ -20613,7 +20687,43 @@ 522F792928D50EBB0069B45B /* HidService.mm in Sources */, 2749F6442146561B008380BF /* InjectedBundleNodeHandle.cpp in Sources */, 2749F6452146561E008380BF /* InjectedBundleRangeHandle.cpp in Sources */, + D7EB04E72372A73B00F744CE /* InspectorPlaywrightAgentClientMac.mm in Sources */, + D79902B2236E9404005D6F7E /* InspectorTargetProxyMac.mm in Sources */, - 1CC94E532AC92F190045F269 /* JSWebExtensionAPIAction.mm in Sources */, - 1C2B4D4B2A819D0D00C528A1 /* JSWebExtensionAPIAlarms.mm in Sources */, - 1C8ECFEA2AFC7DCB007BAA62 /* JSWebExtensionAPICommands.mm in Sources */, -@@ -19807,6 +19883,8 @@ - E3816B3D27E2463A005EAFC0 /* WebMockContentFilterManager.cpp in Sources */, - 31BA924D148831260062EDB5 /* WebNotificationManagerMessageReceiver.cpp in Sources */, - 2DF6FE52212E110900469030 /* WebPage.cpp in Sources */, ++ 1CC94E532AC92F190045F269 /* JSWebExtensionAPIAction.mm in Sources */, ++ 1C2B4D4B2A819D0D00C528A1 /* JSWebExtensionAPIAlarms.mm in Sources */, ++ 1C8ECFEA2AFC7DCB007BAA62 /* JSWebExtensionAPICommands.mm in Sources */, ++ 1C40052C2B2B953D00F2D9EE /* JSWebExtensionAPICookies.mm in Sources */, ++ 331102402B17B99800B21C8C /* JSWebExtensionAPIDeclarativeNetRequest.mm in Sources */, ++ 1C517F452B74393C00C46EDC /* JSWebExtensionAPIDevTools.mm in Sources */, ++ 1C517F432B74393C00C46EDC /* JSWebExtensionAPIDevToolsExtensionPanel.mm in Sources */, ++ 1C517F472B74393C00C46EDC /* JSWebExtensionAPIDevToolsInspectedWindow.mm in Sources */, ++ 1C517F462B74393C00C46EDC /* JSWebExtensionAPIDevToolsNetwork.mm in Sources */, ++ 1C517F412B74393C00C46EDC /* JSWebExtensionAPIDevToolsPanels.mm in Sources */, ++ B6114A7F29394A1600380B1B /* JSWebExtensionAPIEvent.mm in Sources */, ++ 1C5DC471290B33A20061EC62 /* JSWebExtensionAPIExtension.mm in Sources */, ++ B6CCAAB929A445E90092E846 /* JSWebExtensionAPILocalization.mm in Sources */, ++ 1CCEE4532B0989FC0034E059 /* JSWebExtensionAPIMenus.mm in Sources */, ++ 1C5DC4552908AC900061EC62 /* JSWebExtensionAPINamespace.mm in Sources */, ++ 1C386F362AF409F9004108F0 /* JSWebExtensionAPINotifications.mm in Sources */, ++ B61AFA4929510D0F008220B1 /* JSWebExtensionAPIPermissions.mm in Sources */, ++ 1C9A15CF2ABDF1E2002CC12A /* JSWebExtensionAPIPort.mm in Sources */, ++ 1C5DC472290B33A60061EC62 /* JSWebExtensionAPIRuntime.mm in Sources */, ++ B63E9A6F2AAF2B2D005F4561 /* JSWebExtensionAPIScripting.mm in Sources */, ++ 029D6BB22C407AA30068CF99 /* JSWebExtensionAPISidebarAction.mm in Sources */, ++ 029D6BB12C407AA30068CF99 /* JSWebExtensionAPISidePanel.mm in Sources */, ++ B63C10342B51C0B6004A69B8 /* JSWebExtensionAPIStorage.mm in Sources */, ++ B63C10372B51C102004A69B8 /* JSWebExtensionAPIStorageArea.mm in Sources */, ++ 1C5ACFAB2A96F8D500C041C0 /* JSWebExtensionAPITabs.mm in Sources */, ++ 1C15497F2926C073001B9E5B /* JSWebExtensionAPITest.mm in Sources */, + 1C0F05BE2CFA5D2E007D1F62 /* JSWebExtensionAPIUnified.mm in Sources */, ++ 3375A3772942A19D0028536D /* JSWebExtensionAPIWebNavigation.mm in Sources */, ++ 33F68338293FF6F5005C63C0 /* JSWebExtensionAPIWebNavigationEvent.mm in Sources */, ++ B63A99772B7EA002004611FD /* JSWebExtensionAPIWebPageNamespace.mm in Sources */, ++ B63A99782B7EA002004611FD /* JSWebExtensionAPIWebPageRuntime.mm in Sources */, ++ 3399E1532B59EFD7008BFB60 /* JSWebExtensionAPIWebRequest.mm in Sources */, ++ 337042022B58A0B70077FF78 /* JSWebExtensionAPIWebRequestEvent.mm in Sources */, ++ 1C5ACFA62A96F8C400C041C0 /* JSWebExtensionAPIWindows.mm in Sources */, ++ 1C5ACFA72A96F8C400C041C0 /* JSWebExtensionAPIWindowsEvent.mm in Sources */, + 1C5DC45F2909B05A0061EC62 /* JSWebExtensionWrapperCocoa.mm in Sources */, + C14D37FE24ACE086007FF014 /* LaunchServicesDatabaseManager.mm in Sources */, + C1710CF724AA643200D7C112 /* LaunchServicesDatabaseObserver.mm in Sources */, +@@ -21013,6 +21123,8 @@ + 074E87E12CF8EA3D0059E469 /* WebPage+NavigationDeciding.swift in Sources */, + 078B04A02CF18EAB00B453A6 /* WebPage+NavigationPreferences.swift in Sources */, + 07CB79962CE9435700199C49 /* WebPage.swift in Sources */, + D79902B1236E9404005D6F7E /* WebPageInspectorEmulationAgentMac.mm in Sources */, + D79902B3236E9404005D6F7E /* WebPageInspectorInputAgentMac.mm in Sources */, - C0CE72A01247E71D00BC0EC4 /* WebPageMessageReceiver.cpp in Sources */, - BCBD3914125BB1A800D2C29F /* WebPageProxyMessageReceiver.cpp in Sources */, 7CE9CE101FA0767A000177DE /* WebPageUpdatePreferences.cpp in Sources */, + 079A4DA12D72CC0D00CA387F /* WebPageWebView.swift in Sources */, + CA2506A82DD65327001D1954 /* WebPageWebViewAdditions.swift in Sources */, diff --git a/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp b/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp -index 0ab7a191b4d1b35579666f381f87d8a3995e3501..bfd50e5c4f82ad02d9a96afb9a297450257bd2fb 100644 +index bd3aaaf9309aec01820d0950d3b6f14a23c6076c..8cdb9a0c339c0499034fa801395367dd62346268 100644 --- a/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp +++ b/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp -@@ -229,6 +229,11 @@ void WebLoaderStrategy::scheduleLoad(ResourceLoader& resourceLoader, CachedResou +@@ -271,6 +271,11 @@ void WebLoaderStrategy::scheduleLoad(ResourceLoader& resourceLoader, CachedResou } #endif @@ -20243,18 +19316,44 @@ index 0ab7a191b4d1b35579666f381f87d8a3995e3501..bfd50e5c4f82ad02d9a96afb9a297450 #if ENABLE(PDFJS) if (tryLoadingUsingPDFJSHandler(resourceLoader, trackingParameters)) return; -@@ -360,7 +365,8 @@ static void addParametersShared(const LocalFrame* frame, NetworkResourceLoadPara +@@ -285,12 +290,16 @@ void WebLoaderStrategy::scheduleLoad(ResourceLoader& resourceLoader, CachedResou + } + + if (InspectorInstrumentationWebKit::shouldInterceptRequest(resourceLoader)) { +- InspectorInstrumentationWebKit::interceptRequest(resourceLoader, [this, protectedThis = Ref { *this }, protectedResourceLoader = Ref { resourceLoader }, trackingParameters, shouldClearReferrerOnHTTPSToHTTPRedirect, resource](const ResourceRequest& request) { +- auto& resourceLoader = protectedResourceLoader.get(); +- WEBLOADERSTRATEGY_RELEASE_LOG("scheduleLoad: intercepted URL will be scheduled with the NetworkProcess"); +- scheduleLoadFromNetworkProcess(resourceLoader, request, *trackingParameters, shouldClearReferrerOnHTTPSToHTTPRedirect, maximumBufferingTime(resource)); +- }); +- return; ++ bool isMainFrameNavigation = resourceLoader.frame() && resourceLoader.frame()->isMainFrame() && resourceLoader.options().mode == FetchOptions::Mode::Navigate; ++ // Do not intercept navigation request which could already have been intercepted and resumed. ++ if (!(isMainFrameNavigation && m_existingNetworkResourceLoadIdentifierToResume)) { ++ InspectorInstrumentationWebKit::interceptRequest(resourceLoader, [this, protectedThis = Ref { *this }, protectedResourceLoader = Ref { resourceLoader }, trackingParameters, shouldClearReferrerOnHTTPSToHTTPRedirect, resource](const ResourceRequest& request) { ++ auto& resourceLoader = protectedResourceLoader.get(); ++ WEBLOADERSTRATEGY_RELEASE_LOG("scheduleLoad: intercepted URL will be scheduled with the NetworkProcess"); ++ scheduleLoadFromNetworkProcess(resourceLoader, request, *trackingParameters, shouldClearReferrerOnHTTPSToHTTPRedirect, maximumBufferingTime(resource)); ++ }); ++ return; ++ } + } + + WEBLOADERSTRATEGY_RELEASE_LOG_FORWARDABLE(WEBLOADERSTRATEGY_SCHEDULELOAD); +@@ -415,7 +424,7 @@ static void addParametersShared(const LocalFrame* frame, NetworkResourceLoadPara parameters.linkPreconnectEarlyHintsEnabled = mainFrame->settings().linkPreconnectEarlyHintsEnabled(); } -void WebLoaderStrategy::scheduleLoadFromNetworkProcess(ResourceLoader& resourceLoader, const ResourceRequest& request, const WebResourceLoader::TrackingParameters& trackingParameters, bool shouldClearReferrerOnHTTPSToHTTPRedirect, Seconds maximumBufferingTime) -+// static +bool WebLoaderStrategy::fillParametersForNetworkProcessLoad(ResourceLoader& resourceLoader, const ResourceRequest& request, const WebResourceLoader::TrackingParameters& trackingParameters, bool shouldClearReferrerOnHTTPSToHTTPRedirect, Seconds maximumBufferingTime, NetworkResourceLoadParameters& loadParameters) { - auto identifier = resourceLoader.identifier(); - ASSERT(identifier); -@@ -376,7 +382,7 @@ void WebLoaderStrategy::scheduleLoadFromNetworkProcess(ResourceLoader& resourceL - RunLoop::main().dispatch([resourceLoader = Ref { resourceLoader }, error = blockedError(request)] { + auto identifier = *resourceLoader.identifier(); + +@@ -427,10 +436,10 @@ void WebLoaderStrategy::scheduleLoadFromNetworkProcess(ResourceLoader& resourceL + && resourceLoader.frameLoader()->notifier().isInitialRequestIdentifier(identifier) + ? MainFrameMainResource::Yes : MainFrameMainResource::No; + if (!page->allowsLoadFromURL(request.url(), mainFrameMainResource)) { +- RunLoop::protectedMain()->dispatch([resourceLoader = Ref { resourceLoader }, error = blockedError(request)] { ++ RunLoop::protectedMain()->dispatch([resourceLoader = Ref { resourceLoader }, error = platformStrategies()->loaderStrategy()->blockedError(request)] { resourceLoader->didFail(error); }); - return; @@ -20262,15 +19361,22 @@ index 0ab7a191b4d1b35579666f381f87d8a3995e3501..bfd50e5c4f82ad02d9a96afb9a297450 } } -@@ -386,7 +392,6 @@ void WebLoaderStrategy::scheduleLoadFromNetworkProcess(ResourceLoader& resourceL +@@ -440,14 +449,6 @@ void WebLoaderStrategy::scheduleLoadFromNetworkProcess(ResourceLoader& resourceL LOG(NetworkScheduling, "(WebProcess) WebLoaderStrategy::scheduleLoad, url '%s' will be scheduled with the NetworkProcess with priority %d, storedCredentialsPolicy %i", resourceLoader.url().string().latin1().data(), static_cast(resourceLoader.request().priority()), (int)storedCredentialsPolicy); -- NetworkResourceLoadParameters loadParameters; +- NetworkResourceLoadParameters loadParameters { +- trackingParameters.webPageProxyID, +- trackingParameters.pageID, +- trackingParameters.frameID, +- request +- }; +- loadParameters.createSandboxExtensionHandlesIfNecessary(); +- loadParameters.identifier = identifier; - loadParameters.webPageProxyID = trackingParameters.webPageProxyID; - loadParameters.webPageID = trackingParameters.pageID; -@@ -476,14 +481,11 @@ void WebLoaderStrategy::scheduleLoadFromNetworkProcess(ResourceLoader& resourceL + loadParameters.parentPID = legacyPresentingApplicationPID(); + loadParameters.contentSniffingPolicy = contentSniffingPolicy; +@@ -531,14 +532,11 @@ void WebLoaderStrategy::scheduleLoadFromNetworkProcess(ResourceLoader& resourceL if (loadParameters.options.mode != FetchOptions::Mode::Navigate) { ASSERT(loadParameters.sourceOrigin); @@ -20284,38 +19390,46 @@ index 0ab7a191b4d1b35579666f381f87d8a3995e3501..bfd50e5c4f82ad02d9a96afb9a297450 } - loadParameters.shouldRestrictHTTPResponseAccess = shouldPerformSecurityChecks(); -+ loadParameters.shouldRestrictHTTPResponseAccess = DeprecatedGlobalSettings::restrictedHTTPResponseAccess(); ++ loadParameters.shouldRestrictHTTPResponseAccess = true; loadParameters.isMainFrameNavigation = isMainFrameNavigation; if (loadParameters.isMainFrameNavigation && document) -@@ -525,6 +527,17 @@ void WebLoaderStrategy::scheduleLoadFromNetworkProcess(ResourceLoader& resourceL - } +@@ -585,6 +583,25 @@ void WebLoaderStrategy::scheduleLoadFromNetworkProcess(ResourceLoader& resourceL + if (RefPtr frameLoader = resourceLoader.frameLoader()) + loadParameters.requiredCookiesVersion = frameLoader->requiredCookiesVersion(); - ASSERT((loadParameters.webPageID && loadParameters.webFrameID) || loadParameters.clientCredentialPolicy == ClientCredentialPolicy::CannotAskClientForCredentials); + return true; +} + +void WebLoaderStrategy::scheduleLoadFromNetworkProcess(ResourceLoader& resourceLoader, const ResourceRequest& request, const WebResourceLoader::TrackingParameters& trackingParameters, bool shouldClearReferrerOnHTTPSToHTTPRedirect, Seconds maximumBufferingTime) +{ -+ NetworkResourceLoadParameters loadParameters; ++ NetworkResourceLoadParameters loadParameters { ++ trackingParameters.webPageProxyID, ++ trackingParameters.pageID, ++ trackingParameters.frameID, ++ request ++ }; ++ loadParameters.createSandboxExtensionHandlesIfNecessary(); ++ + if (!fillParametersForNetworkProcessLoad(resourceLoader, request, trackingParameters, shouldClearReferrerOnHTTPSToHTTPRedirect, maximumBufferingTime, loadParameters)) { + WEBLOADERSTRATEGY_RELEASE_LOG_ERROR("scheduleLoad: no sourceOrigin (priority=%d)", static_cast(resourceLoader.request().priority())); + scheduleInternallyFailedLoad(resourceLoader); + return; + } - ++ std::optional existingNetworkResourceLoadIdentifierToResume; if (loadParameters.isMainFrameNavigation) -@@ -540,7 +553,7 @@ void WebLoaderStrategy::scheduleLoadFromNetworkProcess(ResourceLoader& resourceL + existingNetworkResourceLoadIdentifierToResume = std::exchange(m_existingNetworkResourceLoadIdentifierToResume, std::nullopt); +@@ -599,7 +616,7 @@ void WebLoaderStrategy::scheduleLoadFromNetworkProcess(ResourceLoader& resourceL } auto loader = WebResourceLoader::create(resourceLoader, trackingParameters); - m_webResourceLoaders.set(identifier, WTFMove(loader)); -+ m_webResourceLoaders.set(resourceLoader.identifier(), WTFMove(loader)); ++ m_webResourceLoaders.set(*resourceLoader.identifier(), WTFMove(loader)); } void WebLoaderStrategy::scheduleInternallyFailedLoad(WebCore::ResourceLoader& resourceLoader) -@@ -950,7 +963,7 @@ void WebLoaderStrategy::didFinishPreconnection(WebCore::ResourceLoaderIdentifier +@@ -1017,7 +1034,7 @@ void WebLoaderStrategy::didFinishPreconnection(WebCore::ResourceLoaderIdentifier bool WebLoaderStrategy::isOnLine() const { @@ -20324,7 +19438,7 @@ index 0ab7a191b4d1b35579666f381f87d8a3995e3501..bfd50e5c4f82ad02d9a96afb9a297450 } void WebLoaderStrategy::addOnlineStateChangeListener(Function&& listener) -@@ -977,6 +990,11 @@ void WebLoaderStrategy::isResourceLoadFinished(CachedResource& resource, Complet +@@ -1044,6 +1061,11 @@ void WebLoaderStrategy::isResourceLoadFinished(CachedResource& resource, Complet void WebLoaderStrategy::setOnLineState(bool isOnLine) { @@ -20336,7 +19450,7 @@ index 0ab7a191b4d1b35579666f381f87d8a3995e3501..bfd50e5c4f82ad02d9a96afb9a297450 if (m_isOnLine == isOnLine) return; -@@ -985,6 +1003,12 @@ void WebLoaderStrategy::setOnLineState(bool isOnLine) +@@ -1052,6 +1074,12 @@ void WebLoaderStrategy::setOnLineState(bool isOnLine) listener(isOnLine); } @@ -20350,28 +19464,28 @@ index 0ab7a191b4d1b35579666f381f87d8a3995e3501..bfd50e5c4f82ad02d9a96afb9a297450 { WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::SetCaptureExtraNetworkLoadMetricsEnabled(enabled), 0); diff --git a/Source/WebKit/WebProcess/Network/WebLoaderStrategy.h b/Source/WebKit/WebProcess/Network/WebLoaderStrategy.h -index 3ef86cc236b8acee2fbe5d0b9c3fd755fcc9f06f..75951fc0fc5e4ef566582c0a494827933ac8bfd1 100644 +index 6492031de6ed6effab3f28e5321419f3390f7651..678139fc26f26e2224a70b0087ddb849280b8ace 100644 --- a/Source/WebKit/WebProcess/Network/WebLoaderStrategy.h +++ b/Source/WebKit/WebProcess/Network/WebLoaderStrategy.h -@@ -42,6 +42,7 @@ struct FetchOptions; - namespace WebKit { +@@ -26,6 +26,7 @@ + #pragma once - class NetworkProcessConnection; -+class NetworkResourceLoadParameters; - class WebFrame; - class WebPage; - class WebURLSchemeTaskProxy; -@@ -89,6 +90,9 @@ public: + #include "NetworkResourceLoadIdentifier.h" ++#include "NetworkResourceLoadParameters.h" + #include "WebResourceLoader.h" + #include + #include +@@ -96,6 +97,9 @@ public: bool isOnLine() const final; void addOnlineStateChangeListener(Function&&) final; void setOnLineState(bool); + void setEmulateOfflineState(bool) final; + -+ static bool fillParametersForNetworkProcessLoad(WebCore::ResourceLoader&, const WebCore::ResourceRequest&, const WebResourceLoader::TrackingParameters&, bool shouldClearReferrerOnHTTPSToHTTPRedirect, Seconds maximumBufferingTime, NetworkResourceLoadParameters&); ++ bool fillParametersForNetworkProcessLoad(WebCore::ResourceLoader&, const WebCore::ResourceRequest&, const WebResourceLoader::TrackingParameters&, bool shouldClearReferrerOnHTTPSToHTTPRedirect, Seconds maximumBufferingTime, NetworkResourceLoadParameters&); void setExistingNetworkResourceLoadIdentifierToResume(std::optional existingNetworkResourceLoadIdentifierToResume) { m_existingNetworkResourceLoadIdentifierToResume = existingNetworkResourceLoadIdentifierToResume; } -@@ -141,6 +145,7 @@ private: +@@ -164,6 +168,7 @@ private: Vector> m_onlineStateChangeListeners; std::optional m_existingNetworkResourceLoadIdentifierToResume; bool m_isOnLine { true }; @@ -20380,20 +19494,20 @@ index 3ef86cc236b8acee2fbe5d0b9c3fd755fcc9f06f..75951fc0fc5e4ef566582c0a49482793 } // namespace WebKit diff --git a/Source/WebKit/WebProcess/Network/WebResourceLoader.cpp b/Source/WebKit/WebProcess/Network/WebResourceLoader.cpp -index ee6ed68f57ac7205087c7f0abe59fb56ee0fa012..9d81ae6dff0ab154a0665d6430be58affae6d820 100644 +index ce50de02306dfe542299fbb9e534a6db929b8052..5c0a3215a78f3fdcf19fd8bb56c2a9c5596240ed 100644 --- a/Source/WebKit/WebProcess/Network/WebResourceLoader.cpp +++ b/Source/WebKit/WebProcess/Network/WebResourceLoader.cpp -@@ -189,9 +189,6 @@ void WebResourceLoader::didReceiveResponse(ResourceResponse&& response, PrivateR - } +@@ -202,9 +202,6 @@ void WebResourceLoader::didReceiveResponse(ResourceResponse&& response, PrivateR - m_coreLoader->didReceiveResponse(inspectorResponse, [this, protectedThis = WTFMove(protectedThis), interceptedRequestIdentifier, policyDecisionCompletionHandler = WTFMove(policyDecisionCompletionHandler), overrideData = WTFMove(overrideData)]() mutable { + coreLoader->didReceiveResponse(ResourceResponse { inspectorResponse }, [this, protectedThis = Ref { *this }, interceptedRequestIdentifier, policyDecisionCompletionHandler = WTFMove(policyDecisionCompletionHandler), overrideData = WTFMove(overrideData)]() mutable { + RefPtr coreLoader = m_coreLoader; - if (policyDecisionCompletionHandler) - policyDecisionCompletionHandler(); - - if (!m_coreLoader || !m_coreLoader->identifier()) { + if (!m_coreLoader || !coreLoader->identifier()) { m_interceptController.continueResponse(interceptedRequestIdentifier); return; -@@ -209,6 +206,8 @@ void WebResourceLoader::didReceiveResponse(ResourceResponse&& response, PrivateR +@@ -221,6 +218,8 @@ void WebResourceLoader::didReceiveResponse(ResourceResponse&& response, PrivateR } }); }); @@ -20402,83 +19516,38 @@ index ee6ed68f57ac7205087c7f0abe59fb56ee0fa012..9d81ae6dff0ab154a0665d6430be58af return; } -diff --git a/Source/WebKit/WebProcess/Notifications/NotificationPermissionRequestManager.cpp b/Source/WebKit/WebProcess/Notifications/NotificationPermissionRequestManager.cpp -index ee9c3c4f48c328daaa015e2122235e51349bd999..5b3a4d3e742147195e0ff9e88176759df1b799db 100644 ---- a/Source/WebKit/WebProcess/Notifications/NotificationPermissionRequestManager.cpp -+++ b/Source/WebKit/WebProcess/Notifications/NotificationPermissionRequestManager.cpp -@@ -85,7 +85,7 @@ void NotificationPermissionRequestManager::startRequest(const SecurityOriginData - - m_page->sendWithAsyncReply(Messages::WebPageProxy::RequestNotificationPermission(securityOrigin.toString()), [this, protectedThis = Ref { *this }, securityOrigin, permissionHandler = WTFMove(permissionHandler)](bool allowed) mutable { - -- auto innerPermissionHandler = [this, protectedThis = Ref { *this }, securityOrigin, permissionHandler = WTFMove(permissionHandler)] (bool allowed) mutable { -+ auto innerPermissionHandler = [this, protectedThis, securityOrigin, permissionHandler = WTFMove(permissionHandler)] (bool allowed) mutable { - WebProcess::singleton().supplement()->didUpdateNotificationDecision(securityOrigin.toString(), allowed); - - auto permissionHandlers = m_requestsPerOrigin.take(securityOrigin); diff --git a/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp b/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp -index 3fa53c3e4977dcc0b83d48091490c2261ed785e0..bef114c5988a88eaca305287471c55515fc22ff6 100644 +index 78e75b9ebfa13611e7f2f9df4395a586ed9db55e..ad6db691640a56bba7fb153bd4a71eb6b618bb50 100644 --- a/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp +++ b/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp -@@ -468,6 +468,8 @@ void WebChromeClient::addMessageToConsole(MessageSource source, MessageLevel lev - { - // Notify the bundle client. - auto page = protectedPage(); +@@ -532,6 +532,9 @@ void WebChromeClient::addMessageToConsole(MessageSource source, MessageLevel lev + if (!page) + return; + + if (level == MessageLevel::Error) + page->send(Messages::WebPageProxy::LogToStderr(message)); - page->injectedBundleUIClient().willAddMessageToConsole(page.ptr(), source, level, message, lineNumber, columnNumber, sourceID); - } ++ + // FIXME: Remove this after rdar://143399667 is fixed. + page->injectedBundleUIClient().willAddMessageToConsole(page.get(), source, level, message, lineNumber, columnNumber, sourceID); diff --git a/Source/WebKit/WebProcess/WebCoreSupport/WebDragClient.cpp b/Source/WebKit/WebProcess/WebCoreSupport/WebDragClient.cpp -index 2eb0886f13ed035a53b8eaa60605de4dfe53fbe3..0f6a539f00a42149c0f2b2237a9cbdd8334459d6 100644 +index 2f5b6d189eae2e153847cbf8496805a2660d1105..837f71ee8d9e0b0fb8ae1841f6820431f592dfd8 100644 --- a/Source/WebKit/WebProcess/WebCoreSupport/WebDragClient.cpp +++ b/Source/WebKit/WebProcess/WebCoreSupport/WebDragClient.cpp -@@ -29,6 +29,13 @@ - #if ENABLE(DRAG_SUPPORT) - - #include "WebPage.h" -+#include -+#include -+#include -+ -+#if PLATFORM(WPE) -+#include "ArgumentCodersWPE.h" -+#endif - - namespace WebKit { - using namespace WebCore; -@@ -50,7 +57,7 @@ OptionSet WebDragClient::dragSourceActionMaskForPoint(const In +@@ -53,7 +53,7 @@ OptionSet WebDragClient::dragSourceActionMaskForPoint(const In return m_page->allowedDragSourceActions(); } -#if !PLATFORM(COCOA) && !PLATFORM(GTK) +#if !PLATFORM(COCOA) && !PLATFORM(GTK) && !PLATFORM(WPE) && !PLATFORM(WIN) - void WebDragClient::startDrag(DragItem, DataTransfer&, Frame&) + void WebDragClient::startDrag(DragItem, DataTransfer&, Frame&, const std::optional&) { } -diff --git a/Source/WebKit/WebProcess/WebCoreSupport/WebLocalFrameLoaderClient.cpp b/Source/WebKit/WebProcess/WebCoreSupport/WebLocalFrameLoaderClient.cpp -index 7b9b0348c1a3b606ad31b3fe2df3eedcb64cf233..97a6a56cc8427bd3eadfacc8fd5c4f15d5bfcdf7 100644 ---- a/Source/WebKit/WebProcess/WebCoreSupport/WebLocalFrameLoaderClient.cpp -+++ b/Source/WebKit/WebProcess/WebCoreSupport/WebLocalFrameLoaderClient.cpp -@@ -1592,14 +1592,6 @@ void WebLocalFrameLoaderClient::transitionToCommittedForNewPage(InitializingIfra - - if (initializingIframe == InitializingIframe::No) - webPage->scheduleFullEditorStateUpdate(); -- --#if USE(COORDINATED_GRAPHICS) -- if (shouldUseFixedLayout) { -- view->setDelegatedScrollingMode(shouldUseFixedLayout ? DelegatedScrollingMode::DelegatedToNativeScrollView : DelegatedScrollingMode::NotDelegated); -- view->setPaintsEntireContents(shouldUseFixedLayout); -- return; -- } --#endif - } - - void WebLocalFrameLoaderClient::didRestoreFromBackForwardCache() diff --git a/Source/WebKit/WebProcess/WebCoreSupport/mac/WebDragClientMac.mm b/Source/WebKit/WebProcess/WebCoreSupport/mac/WebDragClientMac.mm -index 69b851554679018aefe2c22b79671f7796d9e8b8..50e985ded3cdc9aaa5f30f7776c29cbc23c2b2b8 100644 +index cf8aa32077a57057649722d73358ac91b7130551..b555eb998bab677a452c37e78935ea9bad2196fc 100644 --- a/Source/WebKit/WebProcess/WebCoreSupport/mac/WebDragClientMac.mm +++ b/Source/WebKit/WebProcess/WebCoreSupport/mac/WebDragClientMac.mm -@@ -129,7 +129,8 @@ static WebCore::CachedImage* cachedImage(Element& element) +@@ -128,7 +128,8 @@ static WebCore::CachedImage* cachedImage(Element& element) void WebDragClient::declareAndWriteDragImage(const String& pasteboardName, Element& element, const URL& url, const String& label, LocalFrame*) { @@ -20490,7 +19559,7 @@ index 69b851554679018aefe2c22b79671f7796d9e8b8..50e985ded3cdc9aaa5f30f7776c29cbc diff --git a/Source/WebKit/WebProcess/WebCoreSupport/win/WebDragClientWin.cpp b/Source/WebKit/WebProcess/WebCoreSupport/win/WebDragClientWin.cpp new file mode 100644 -index 0000000000000000000000000000000000000000..66972b66094050b2429a927861ff7d0d30925ef0 +index 0000000000000000000000000000000000000000..2d2ab369bfc1b42695dbc207e1d6e05deb16990f --- /dev/null +++ b/Source/WebKit/WebProcess/WebCoreSupport/win/WebDragClientWin.cpp @@ -0,0 +1,58 @@ @@ -20524,17 +19593,17 @@ index 0000000000000000000000000000000000000000..66972b66094050b2429a927861ff7d0d + +#if ENABLE(DRAG_SUPPORT) + -+//#include "ArgumentCodersWPE.h" +#include "MessageSenderInlines.h" +#include "WebPage.h" +#include "WebPageProxyMessages.h" +#include +#include ++#include +#include +#include +#include + -+//#include ++#include + +namespace WebKit { +using namespace WebCore; @@ -20543,7 +19612,7 @@ index 0000000000000000000000000000000000000000..66972b66094050b2429a927861ff7d0d +{ +} + -+void WebDragClient::startDrag(DragItem, DataTransfer& dataTransfer, Frame& frame) ++void WebDragClient::startDrag(DragItem, DataTransfer& dataTransfer, Frame& frame, const std::optional&) +{ + m_page->willStartDrag(); + m_page->send(Messages::WebPageProxy::StartDrag(dataTransfer.pasteboard().createDragDataMap())); @@ -20554,10 +19623,10 @@ index 0000000000000000000000000000000000000000..66972b66094050b2429a927861ff7d0d +#endif // ENABLE(DRAG_SUPPORT) diff --git a/Source/WebKit/WebProcess/WebCoreSupport/wpe/WebDragClientWPE.cpp b/Source/WebKit/WebProcess/WebCoreSupport/wpe/WebDragClientWPE.cpp new file mode 100644 -index 0000000000000000000000000000000000000000..4fa6b70b978998849950d1fe4d9f902ede155956 +index 0000000000000000000000000000000000000000..d069b5eba1a64add1a2c370f8d519826ec7be213 --- /dev/null +++ b/Source/WebKit/WebProcess/WebCoreSupport/wpe/WebDragClientWPE.cpp -@@ -0,0 +1,57 @@ +@@ -0,0 +1,59 @@ +/* + * Copyright (C) 2011 Igalia S.L. + * @@ -20588,15 +19657,17 @@ index 0000000000000000000000000000000000000000..4fa6b70b978998849950d1fe4d9f902e + +#if ENABLE(DRAG_SUPPORT) + -+#include "ArgumentCodersWPE.h" +#include "WebPage.h" +#include "WebPageProxyMessages.h" +#include +#include ++#include +#include +#include +#include + ++#include ++ +namespace WebKit { +using namespace WebCore; + @@ -20604,130 +19675,43 @@ index 0000000000000000000000000000000000000000..4fa6b70b978998849950d1fe4d9f902e +{ +} + -+void WebDragClient::startDrag(DragItem, DataTransfer& dataTransfer, Frame&) ++void WebDragClient::startDrag(DragItem, DataTransfer& dataTransfer, Frame&, const std::optional&) +{ + m_page->willStartDrag(); + + std::optional handle; + m_page->send(Messages::WebPageProxy::StartDrag(dataTransfer.pasteboard().selectionData(), dataTransfer.sourceOperationMask(), WTFMove(handle), dataTransfer.dragLocation())); +} -+ -+}; // namespace WebKit. -+ -+#endif // ENABLE(DRAG_SUPPORT) -diff --git a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp -index 6780fb04b94241977df3396ffb77585f10faf035..db015c88e2b3413c9fde348779b62c90896ba09c 100644 ---- a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp -+++ b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp -@@ -39,6 +39,7 @@ - #include "WebPreferencesKeys.h" - #include "WebProcess.h" - #include -+#include - #include - #include - #include -@@ -103,6 +104,16 @@ void DrawingAreaCoordinatedGraphics::scroll(const IntRect& scrollRect, const Int - ASSERT(m_scrollRect.isEmpty()); - ASSERT(m_scrollOffset.isEmpty()); - ASSERT(m_dirtyRegion.isEmpty()); -+// Playwright begin -+#if !PLATFORM(WIN) -+ if (m_webPage->mainFrameView() && m_webPage->mainFrameView()->useFixedLayout()) { -+ IntRect visibleRect = IntRect(m_layerTreeHost->viewportController().visibleContentsRect()); -+ visibleRect.move(-scrollDelta.width(), -scrollDelta.height()); -+ m_layerTreeHost->scrollNonCompositedContents(visibleRect); -+ return; -+ } -+#endif -+// Playwright end - m_layerTreeHost->scrollNonCompositedContents(scrollRect); - return; - } -@@ -562,6 +573,11 @@ void DrawingAreaCoordinatedGraphics::enterAcceleratedCompositingMode(GraphicsLay - m_scrollOffset = IntSize(); - m_displayTimer.stop(); - m_isWaitingForDidUpdate = false; -+// Playwright begin -+#if PLATFORM(WIN) -+ didChangeAcceleratedCompositingMode(true); -+#endif -+// Playwright end - } - - void DrawingAreaCoordinatedGraphics::sendEnterAcceleratedCompositingModeIfNeeded() -@@ -619,6 +635,11 @@ void DrawingAreaCoordinatedGraphics::exitAcceleratedCompositingMode() - // UI process, we still need to let it know about the new contents, so send an Update message. - send(Messages::DrawingAreaProxy::Update(0, WTFMove(updateInfo))); - } -+// Playwright begin -+#if PLATFORM(WIN) -+ didChangeAcceleratedCompositingMode(false); -+#endif -+// Playwright end - } - - void DrawingAreaCoordinatedGraphics::scheduleDisplay() -diff --git a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp -index d453fc33b2a366e4944b48c47bbe056d508124e7..4b58d67c55ebcde8598a1045cbc99202bf6f8feb 100644 ---- a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp -+++ b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp -@@ -193,8 +193,16 @@ void LayerTreeHost::setViewOverlayRootLayer(GraphicsLayer* viewOverlayRootLayer) - void LayerTreeHost::scrollNonCompositedContents(const IntRect& rect) - { - auto* frameView = m_webPage.localMainFrameView(); -+ -+// Playwright begin -+#if PLATFORM(WIN) - if (!frameView || !frameView->delegatesScrolling()) -+ return -+#else -+ if (!frameView) - return; -+#endif -+// Playwright end - - m_viewportController.didScroll(rect.location()); - didChangeViewport(); -@@ -273,6 +281,7 @@ GraphicsLayerFactory* LayerTreeHost::graphicsLayerFactory() - void LayerTreeHost::contentsSizeChanged(const IntSize& newSize) - { - m_viewportController.didChangeContentsSize(newSize); -+ didChangeViewport(); - } - - void LayerTreeHost::didChangeViewportAttributes(ViewportAttributes&& attr) -@@ -312,6 +321,10 @@ void LayerTreeHost::didChangeViewport() - - if (!view->useFixedLayout()) - view->notifyScrollPositionChanged(m_lastScrollPosition); -+// Playwright begin -+ else -+ m_viewportController.didScroll(m_lastScrollPosition); -+// Playwright end - } - - if (m_lastPageScaleFactor != pageScale) { ++ ++}; // namespace WebKit. ++ ++#endif // ENABLE(DRAG_SUPPORT) +diff --git a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp +index 5fed15fd5dbbfbaff305ce26a8bcf5ba3d0435d9..fec04b9a4d640dcf47e0a2312d8b71234bf10d09 100644 +--- a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp ++++ b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp +@@ -39,6 +39,7 @@ + #include "WebPreferencesKeys.h" + #include "WebProcess.h" + #include ++#include + #include + #include + #include diff --git a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.h b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.h -index 40926ecda30b9f7cdb4d1908436b1af4353999a4..2fa2c6363cfedd3dac46692cc6c8642752ec728f 100644 +index 31af5390779e2ec5f3bc3dc0bbddf56f2617657a..df7af98f4d38f380ee5c0b607570659260a955e0 100644 --- a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.h +++ b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.h -@@ -115,6 +115,13 @@ public: +@@ -145,6 +145,7 @@ public: #if PLATFORM(WPE) && USE(GBM) && ENABLE(WPE_PLATFORM) void preferredBufferFormatsDidChange(); #endif -+ -+// Playwright begin -+#if USE(COORDINATED_GRAPHICS) -+ const SimpleViewportController& viewportController() const { return m_viewportController; } -+#endif -+// Playwright end + private: - #if USE(COORDINATED_GRAPHICS) - void layerFlushTimerFired(); + void updateRootLayer(); + WebCore::FloatRect visibleContentsRect() const; diff --git a/Source/WebKit/WebProcess/WebPage/DrawingArea.cpp b/Source/WebKit/WebProcess/WebPage/DrawingArea.cpp -index 94bbead87936ab599f79c3c08b260cad939aea62..5099d3d7bdf220aa5c8f3729a04397ec38cfed05 100644 +index c07ca9e847d03c27877cf650b67b96b3c3f7bddb..b966edc8778d4a68c6e5bae0c0883ab3bfd0a387 100644 --- a/Source/WebKit/WebProcess/WebPage/DrawingArea.cpp +++ b/Source/WebKit/WebProcess/WebPage/DrawingArea.cpp @@ -27,6 +27,7 @@ @@ -20738,36 +19722,8 @@ index 94bbead87936ab599f79c3c08b260cad939aea62..5099d3d7bdf220aa5c8f3729a04397ec #include "Logging.h" #include "WebPage.h" #include "WebPageCreationParameters.h" -@@ -112,6 +113,13 @@ void DrawingArea::tryMarkLayersVolatile(CompletionHandler&& completi - completionFunction(true); - } - -+#if PLATFORM(WIN) -+void DrawingArea::didChangeAcceleratedCompositingMode(bool enabled) -+{ -+ send(Messages::DrawingAreaProxy::DidChangeAcceleratedCompositingMode(enabled)); -+} -+#endif -+ - void DrawingArea::removeMessageReceiverIfNeeded() - { - if (m_hasRemovedMessageReceiver) -diff --git a/Source/WebKit/WebProcess/WebPage/DrawingArea.h b/Source/WebKit/WebProcess/WebPage/DrawingArea.h -index e61851e273de92fc97b7707c4427b4d03cd2df70..d1e0850461624188febc8a477e6d3d6bc44fee50 100644 ---- a/Source/WebKit/WebProcess/WebPage/DrawingArea.h -+++ b/Source/WebKit/WebProcess/WebPage/DrawingArea.h -@@ -164,6 +164,9 @@ public: - virtual bool enterAcceleratedCompositingModeIfNeeded() = 0; - virtual void backgroundColorDidChange() { }; - #endif -+#if PLATFORM(WIN) -+ void didChangeAcceleratedCompositingMode(bool enabled); -+#endif - - #if PLATFORM(WPE) && USE(GBM) && ENABLE(WPE_PLATFORM) - virtual void preferredBufferFormatsDidChange() { } diff --git a/Source/WebKit/WebProcess/WebPage/WebCookieJar.cpp b/Source/WebKit/WebProcess/WebPage/WebCookieJar.cpp -index 935edefd61482ee2b268415ed24f7e2639bdbe35..8ec21eb117958c455ea4772907dd4e3afe0c1fcc 100644 +index 412dd3c46cb61ec5f3de076de61c34b6a32c6281..77c02eedfb60a7f816788452e20aaf3fbc434164 100644 --- a/Source/WebKit/WebProcess/WebPage/WebCookieJar.cpp +++ b/Source/WebKit/WebProcess/WebPage/WebCookieJar.cpp @@ -44,6 +44,7 @@ @@ -20775,10 +19731,10 @@ index 935edefd61482ee2b268415ed24f7e2639bdbe35..8ec21eb117958c455ea4772907dd4e3a #include #include +#include + #include #include #include - #include -@@ -393,6 +394,12 @@ void WebCookieJar::removeChangeListener(const String& host, const WebCore::Cooki +@@ -447,6 +448,12 @@ void WebCookieJar::setOptInCookiePartitioningEnabled(bool enabled) } #endif @@ -20792,138 +19748,100 @@ index 935edefd61482ee2b268415ed24f7e2639bdbe35..8ec21eb117958c455ea4772907dd4e3a String WebCookieJar::cookiesInPartitionedCookieStorage(const WebCore::Document&, const URL&, const WebCore::SameSiteInfo&) const diff --git a/Source/WebKit/WebProcess/WebPage/WebCookieJar.h b/Source/WebKit/WebProcess/WebPage/WebCookieJar.h -index b6e5283f51db82b60091320df44ef0bbf20c33c6..0d82fbb98b93e760cecf5fa7a41327d0473f8a03 100644 +index d5bac4fe6d5103b4e752a7219d7870d4cddcaf27..033effbb445f5da6db5798594e2dbef34afec363 100644 --- a/Source/WebKit/WebProcess/WebPage/WebCookieJar.h +++ b/Source/WebKit/WebProcess/WebPage/WebCookieJar.h -@@ -74,6 +74,8 @@ public: +@@ -77,6 +77,8 @@ public: void clearCache() final; + void setCookieFromResponse(WebCore::ResourceLoader&, const String& setCookieValue); + - private: - WebCookieJar(); - + #if HAVE(ALLOW_ONLY_PARTITIONED_COOKIES) + void setOptInCookiePartitioningEnabled(bool); + #endif diff --git a/Source/WebKit/WebProcess/WebPage/WebPage.cpp b/Source/WebKit/WebProcess/WebPage/WebPage.cpp -index 36ca16c66c74db2f7d4b2a4938e7714b5ef49ca1..821029c298841fc1408f80579d43ec7c8d54faad 100644 +index eebb80386522babc1ae192dbc470facea0b76e6b..02da88a1fd0d655faf69c7d3bd348009da32851c 100644 --- a/Source/WebKit/WebProcess/WebPage/WebPage.cpp +++ b/Source/WebKit/WebProcess/WebPage/WebPage.cpp -@@ -1034,6 +1034,9 @@ WebPage::WebPage(PageIdentifier pageID, WebPageCreationParameters&& parameters) +@@ -244,6 +244,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1165,6 +1166,12 @@ WebPage::WebPage(PageIdentifier pageID, WebPageCreationParameters&& parameters) + setLinkDecorationFilteringData(WTFMove(parameters.linkDecorationFilteringData)); + setAllowedQueryParametersForAdvancedPrivacyProtections(WTFMove(parameters.allowedQueryParametersForAdvancedPrivacyProtections)); #endif - #endif // HAVE(SANDBOX_STATE_FLAGS) - ++ // For popup windows WebPage::Show() maybe called in the next lines from the constructor, ++ // at which point the page is not in the WebProcess's map yet and it is not safe to ++ // dispatch nested message loop and receive IPC messages. To mitigate that, the actual ++ // pause is postponed until the page is added to the map. + if (parameters.shouldPauseInInspectorWhenShown) -+ m_page->inspectorController().pauseWhenShown(); -+ - updateThrottleState(); - #if ENABLE(ACCESSIBILITY_ANIMATION_CONTROL) - updateImageAnimationEnabled(); -@@ -2007,6 +2010,22 @@ void WebPage::transitionFrameToLocal(LocalFrameCreationParameters&& creationPara - frame->transitionToLocal(creationParameters.layerHostingContextIdentifier); ++ m_page->inspectorController().pauseOnStart(parameters.windowFeatures ? InspectorController::PauseCondition::WHEN_CREATION_FINISHED : InspectorController::PauseCondition::WHEN_SHOWN); + if (parameters.windowFeatures) { + page->applyWindowFeatures(*parameters.windowFeatures); + page->chrome().show(); +@@ -2098,6 +2105,22 @@ void WebPage::loadDidCommitInAnotherProcess(WebCore::FrameIdentifier frameID, st + frame->loadDidCommitInAnotherProcess(layerHostingContextIdentifier); } +void WebPage::loadRequestInFrameForInspector(LoadParameters&& loadParameters, WebCore::FrameIdentifier frameID) +{ + WebFrame* frame = WebProcess::singleton().webFrame(frameID); + if (!frame) { -+ send(Messages::WebPageProxy::DidDestroyNavigation(loadParameters.navigationID)); ++ send(Messages::WebPageProxy::DidDestroyNavigation(*loadParameters.navigationID)); + return; + } + + // FIXME: use m_pendingNavigationID instead? + m_pendingFrameNavigationID = loadParameters.navigationID; + -+ FrameLoadRequest frameLoadRequest { *frame->coreLocalFrame(), loadParameters.request }; ++ FrameLoadRequest frameLoadRequest { *frame->coreLocalFrame(), WTFMove(loadParameters.request) }; + frame->coreLocalFrame()->loader().load(WTFMove(frameLoadRequest)); + ASSERT(!m_pendingFrameNavigationID); +} + void WebPage::loadRequest(LoadParameters&& loadParameters) { - WEBPAGE_RELEASE_LOG(Loading, "loadRequest: navigationID=%" PRIu64 ", shouldTreatAsContinuingLoad=%u, lastNavigationWasAppInitiated=%d, existingNetworkResourceLoadIdentifierToResume=%" PRIu64, loadParameters.navigationID, static_cast(loadParameters.shouldTreatAsContinuingLoad), loadParameters.request.isAppInitiated(), valueOrDefault(loadParameters.existingNetworkResourceLoadIdentifierToResume).toUInt64()); -@@ -2283,17 +2302,14 @@ void WebPage::setSize(const WebCore::IntSize& viewSize) - view->resize(viewSize); - m_drawingArea->setNeedsDisplay(); - --#if USE(COORDINATED_GRAPHICS) - if (view->useFixedLayout()) - sendViewportAttributesChanged(m_page->viewportArguments()); --#endif - - #if ENABLE(ACCESSIBILITY_ISOLATED_TREE) - cacheAXSize(m_viewSize); - #endif - } - --#if USE(COORDINATED_GRAPHICS) - void WebPage::sendViewportAttributesChanged(const ViewportArguments& viewportArguments) - { - RefPtr localMainFrame = dynamicDowncast(m_page->mainFrame()); -@@ -2318,20 +2334,18 @@ void WebPage::sendViewportAttributesChanged(const ViewportArguments& viewportArg - - ViewportAttributes attr = computeViewportAttributes(viewportArguments, minimumLayoutFallbackWidth, deviceWidth, deviceHeight, 1, m_viewSize); - -- // If no layout was done yet set contentFixedOrigin to (0,0). -- IntPoint contentFixedOrigin = view->didFirstLayout() ? view->fixedVisibleContentRect().location() : IntPoint(); -- -- // Put the width and height to the viewport width and height. In css units however. -- // Use FloatSize to avoid truncated values during scale. -- FloatSize contentFixedSize = m_viewSize; -- -- contentFixedSize.scale(1 / attr.initialScale); -- view->setFixedVisibleContentRect(IntRect(contentFixedOrigin, roundedIntSize(contentFixedSize))); -+#if ENABLE(CSS_DEVICE_ADAPTATION) -+ FrameView* view = m_page->mainFrame().view(); -+ // CSS viewport descriptors might be applied to already affected viewport size -+ // if the page enables/disables stylesheets, so need to keep initial viewport size. -+ view->setInitialViewportSize(roundedIntSize(m_viewSize)); -+#endif - - attr.initialScale = m_page->viewportArguments().zoom; // Resets auto (-1) if no value was set by user. - - // This also takes care of the relayout. - setFixedLayoutSize(roundedIntSize(attr.layoutSize)); -+ scaleView(deviceWidth / attr.layoutSize.width()); - - #if USE(COORDINATED_GRAPHICS) - m_drawingArea->didChangeViewportAttributes(WTFMove(attr)); -@@ -2339,7 +2353,6 @@ void WebPage::sendViewportAttributesChanged(const ViewportArguments& viewportArg - send(Messages::WebPageProxy::DidChangeViewportProperties(attr)); - #endif - } --#endif - - void WebPage::scrollMainFrameIfNotAtMaxScrollPosition(const IntSize& scrollOffset) + WEBPAGE_RELEASE_LOG_FORWARDABLE(Loading, WEBPAGE_LOADREQUEST, loadParameters.navigationID ? loadParameters.navigationID->toUInt64() : 0, static_cast(loadParameters.shouldTreatAsContinuingLoad), loadParameters.request.isAppInitiated(), loadParameters.existingNetworkResourceLoadIdentifierToResume ? loadParameters.existingNetworkResourceLoadIdentifierToResume->toUInt64() : 0); +@@ -2295,7 +2318,9 @@ void WebPage::stopLoading() + void WebPage::stopLoadingDueToProcessSwap() { -@@ -2640,6 +2653,7 @@ void WebPage::scaleView(double scale) - } - - m_page->setViewScaleFactor(scale); -+ send(Messages::WebPageProxy::ViewScaleFactorDidChange(scale)); - scalePage(pageScale, scrollPositionAtNewScale); + SetForScope isStoppingLoadingDueToProcessSwap(m_isStoppingLoadingDueToProcessSwap, true); ++ InspectorInstrumentationWebKit::setStoppingLoadingDueToProcessSwap(m_page.get(), true); + stopLoading(); ++ InspectorInstrumentationWebKit::setStoppingLoadingDueToProcessSwap(m_page.get(), false); } -@@ -2819,18 +2833,14 @@ void WebPage::viewportPropertiesDidChange(const ViewportArguments& viewportArgum + bool WebPage::defersLoading() const +@@ -2871,7 +2896,7 @@ void WebPage::viewportPropertiesDidChange(const ViewportArguments& viewportArgum + #if PLATFORM(IOS_FAMILY) + if (m_viewportConfiguration.setViewportArguments(viewportArguments)) viewportConfigurationChanged(); - #endif - --#if USE(COORDINATED_GRAPHICS) - RefPtr localMainFrame = dynamicDowncast(m_page->mainFrame()); +-#elif PLATFORM(GTK) || PLATFORM(WPE) ++#elif PLATFORM(GTK) || PLATFORM(WPE) || PLATFORM(WIN) || PLATFORM(MAC) + // Adjust view dimensions when using fixed layout. + RefPtr localMainFrame = this->localMainFrame(); RefPtr view = localMainFrame ? localMainFrame->view() : nullptr; - if (view && view->useFixedLayout()) - sendViewportAttributesChanged(viewportArguments); -+#if USE(COORDINATED_GRAPHICS) - else - m_drawingArea->didChangeViewportAttributes(ViewportAttributes()); - #endif -- --#if !PLATFORM(IOS_FAMILY) && !USE(COORDINATED_GRAPHICS) -- UNUSED_PARAM(viewportArguments); --#endif +@@ -3628,6 +3653,13 @@ void WebPage::flushDeferredScrollEvents() + protectedCorePage()->flushDeferredScrollEvents(); } - #if !PLATFORM(IOS_FAMILY) -@@ -3830,6 +3840,97 @@ void WebPage::touchEvent(const WebTouchEvent& touchEvent, CompletionHandlersetOverrideOrientation(deviceOrientation); ++} ++#endif ++ + void WebPage::flushDeferredDidReceiveMouseEvent() + { + if (auto info = std::exchange(m_deferredDidReceiveMouseEvent, std::nullopt)) +@@ -3902,6 +3934,97 @@ void WebPage::touchEvent(const WebTouchEvent& touchEvent, CompletionHandlermainFrame().frameID(), touchEvent, m_page.get()).wasHandled(); ++ handled = handleTouchEvent(m_page->mainFrame().frameID(), touchEvent, m_page.get()).value_or(false); + } + { + Vector touchPoints; + WebPlatformTouchPoint::State state = WebPlatformTouchPoint::State::Released; + touchPoints.append(WebPlatformTouchPoint(id, state, screenPosition, position, radius, rotationAngle, force)); + -+ WebTouchEvent touchEvent({WebEventType::TouchEnd, eventModifiers, WallTime::now()}, WTFMove(touchPoints)); ++ WebTouchEvent touchEvent({WebEventType::TouchEnd, eventModifiers, WallTime::now()}, WTFMove(touchPoints), {}, {}); + + CurrentEvent currentEvent(touchEvent); -+ handled = handleTouchEvent(m_page->mainFrame().frameID(), touchEvent, m_page.get()).wasHandled() || handled; ++ handled = handleTouchEvent(m_page->mainFrame().frameID(), touchEvent, m_page.get()).value_or(false) || handled; + } + if (!handled) { + FloatPoint adjustedPoint; @@ -21021,7 +19939,7 @@ index 36ca16c66c74db2f7d4b2a4938e7714b5ef49ca1..821029c298841fc1408f80579d43ec7c #endif void WebPage::cancelPointer(WebCore::PointerID pointerId, const WebCore::IntPoint& documentPoint) -@@ -3915,6 +4016,11 @@ void WebPage::sendMessageToTargetBackend(const String& targetId, const String& m +@@ -3990,6 +4113,16 @@ void WebPage::sendMessageToTargetBackend(const String& targetId, const String& m m_inspectorTargetController->sendMessageToTargetBackend(targetId, message); } @@ -21029,19 +19947,24 @@ index 36ca16c66c74db2f7d4b2a4938e7714b5ef49ca1..821029c298841fc1408f80579d43ec7c +{ + m_page->inspectorController().resumeIfPausedInNewWindow(); +} ++ ++void WebPage::didAddWebPageToWebProcess() ++{ ++ m_page->inspectorController().didFinishPageCreation(); ++} + void WebPage::insertNewlineInQuotedContent() { - RefPtr frame = m_page->checkedFocusController()->focusedOrMainFrame(); -@@ -4150,6 +4256,7 @@ void WebPage::didCompletePageTransition() + RefPtr frame = protectedCorePage()->checkedFocusController()->focusedOrMainFrame(); +@@ -4233,6 +4366,7 @@ void WebPage::setMainFrameDocumentVisualUpdatesAllowed(bool allowed) void WebPage::show() { send(Messages::WebPageProxy::ShowPage()); -+ m_page->inspectorController().didShowNewWindow(); ++ m_page->inspectorController().didShowPage(); } void WebPage::setIsTakingSnapshotsForApplicationSuspension(bool isTakingSnapshotsForApplicationSuspension) -@@ -5249,7 +5356,7 @@ NotificationPermissionRequestManager* WebPage::notificationPermissionRequestMana +@@ -5448,7 +5582,7 @@ RefPtr WebPage::protectedNotificationPermi #if ENABLE(DRAG_SUPPORT) @@ -21050,8 +19973,8 @@ index 36ca16c66c74db2f7d4b2a4938e7714b5ef49ca1..821029c298841fc1408f80579d43ec7c void WebPage::performDragControllerAction(DragControllerAction action, const IntPoint& clientPosition, const IntPoint& globalPosition, OptionSet draggingSourceOperationMask, SelectionData&& selectionData, OptionSet flags, CompletionHandler, DragHandlingMethod, bool, unsigned, IntRect, IntRect, std::optional)>&& completionHandler) { if (!m_page) -@@ -7586,6 +7693,10 @@ void WebPage::didCommitLoad(WebFrame* frame) - #endif +@@ -7961,6 +8095,10 @@ void WebPage::didCommitLoad(WebFrame* frame) + m_needsFixedContainerEdgesUpdate = true; flushDeferredDidReceiveMouseEvent(); +// Playwright begin @@ -21061,40 +19984,29 @@ index 36ca16c66c74db2f7d4b2a4938e7714b5ef49ca1..821029c298841fc1408f80579d43ec7c } void WebPage::didFinishDocumentLoad(WebFrame& frame) -@@ -7850,6 +7961,9 @@ Ref WebPage::createDocumentLoader(LocalFrame& frame, const Resou - WebsitePoliciesData::applyToDocumentLoader(WTFMove(*m_pendingWebsitePolicies), documentLoader); - m_pendingWebsitePolicies = std::nullopt; +@@ -8270,6 +8408,9 @@ Ref WebPage::createDocumentLoader(LocalFrame& frame, ResourceReq + m_allowsContentJavaScriptFromMostRecentNavigation = m_internals->pendingWebsitePolicies->allowsContentJavaScript; + WebsitePoliciesData::applyToDocumentLoader(*std::exchange(m_internals->pendingWebsitePolicies, std::nullopt), documentLoader); } + } else if (m_pendingFrameNavigationID) { -+ documentLoader->setNavigationID(m_pendingFrameNavigationID); -+ m_pendingFrameNavigationID = 0; ++ documentLoader->setNavigationID(*m_pendingFrameNavigationID); ++ m_pendingFrameNavigationID = std::nullopt; } return documentLoader; diff --git a/Source/WebKit/WebProcess/WebPage/WebPage.h b/Source/WebKit/WebProcess/WebPage/WebPage.h -index a8d232fda1bf1dc7a9b3e866b3cbfb2952b26eef..b048960902cdd660209be177b4ecbe7719c74f8d 100644 +index 360c7068495346fa326a3409afe64c03ff11506e..263acb1412dd593a45a264c7fbd3fc16582db710 100644 --- a/Source/WebKit/WebProcess/WebPage/WebPage.h +++ b/Source/WebKit/WebProcess/WebPage/WebPage.h -@@ -70,6 +70,7 @@ - #include +@@ -47,6 +47,7 @@ #include #include + #include +#include #include #include #include -@@ -112,6 +113,10 @@ - #include "WebPrintOperationGtk.h" - #endif - -+#if PLATFORM(WPE) -+#include "ArgumentCodersWPE.h" -+#endif -+ - #if PLATFORM(GTK) || PLATFORM(WPE) - #include "InputMethodState.h" - #endif -@@ -1145,11 +1150,11 @@ public: +@@ -1286,11 +1287,11 @@ public: void clearSelection(); void restoreSelectionInFocusedEditableElement(); @@ -21106,35 +20018,49 @@ index a8d232fda1bf1dc7a9b3e866b3cbfb2952b26eef..b048960902cdd660209be177b4ecbe77 -#if ENABLE(DRAG_SUPPORT) && !PLATFORM(GTK) +#if ENABLE(DRAG_SUPPORT) && !PLATFORM(GTK) && !PLATFORM(WPE) void performDragControllerAction(std::optional, DragControllerAction, WebCore::DragData&&, CompletionHandler, WebCore::DragHandlingMethod, bool, unsigned, WebCore::IntRect, WebCore::IntRect, std::optional)>&&); - void performDragOperation(WebCore::DragData&&, SandboxExtension::Handle&&, Vector&&, CompletionHandler&&); + void performDragOperation(WebCore::DragData&&, SandboxExtensionHandle&&, Vector&&, CompletionHandler&&); + #endif +@@ -1308,6 +1309,9 @@ public: + #if ENABLE(MODEL_PROCESS) + void modelDragEnded(WebCore::ElementIdentifier); #endif -@@ -1164,6 +1169,9 @@ public: - void didStartDrag(); - void dragCancelled(); - OptionSet allowedDragSourceActions() const { return m_allowedDragSourceActions; } +#if PLATFORM(MAC) + void setDragPasteboardName(const String& pasteboardName) { m_page->setDragPasteboardName(pasteboardName); } +#endif #endif - void beginPrinting(WebCore::FrameIdentifier, const PrintInfo&); -@@ -1387,6 +1395,7 @@ public: + #if ENABLE(MODEL_PROCESS) +@@ -1394,8 +1398,11 @@ public: + void gestureEvent(WebCore::FrameIdentifier, const WebGestureEvent&, CompletionHandler, bool, std::optional)>&&); + #endif + +-#if PLATFORM(IOS_FAMILY) ++#if ENABLE(ORIENTATION_EVENTS) + void setDeviceOrientation(WebCore::IntDegrees); ++#endif ++ ++#if PLATFORM(IOS_FAMILY) + void dynamicViewportSizeUpdate(const DynamicViewportSizeUpdate&); + bool scaleWasSetByUIProcess() const { return m_scaleWasSetByUIProcess; } + void willStartUserTriggeredZooming(); +@@ -1548,6 +1555,8 @@ public: void connectInspector(const String& targetId, Inspector::FrontendChannel::ConnectionType); void disconnectInspector(const String& targetId); void sendMessageToTargetBackend(const String& targetId, const String& message); + void resumeInspectorIfPausedInNewWindow(); ++ void didAddWebPageToWebProcess(); void insertNewlineInQuotedContent(); -@@ -1863,6 +1872,7 @@ private: - void tryClose(CompletionHandler&&); - void platformDidReceiveLoadParameters(const LoadParameters&); - void transitionFrameToLocal(LocalFrameCreationParameters&&, WebCore::FrameIdentifier); -+ void loadRequestInFrameForInspector(LoadParameters&&, WebCore::FrameIdentifier); +@@ -1969,6 +1978,7 @@ public: + void showContextMenuFromFrame(const FrameInfoData&, const ContextMenuContextData&, const UserData&); + #endif void loadRequest(LoadParameters&&); - [[noreturn]] void loadRequestWaitingForProcessLaunch(LoadParameters&&, URL&&, WebPageProxyIdentifier, bool); - void loadData(LoadParameters&&); -@@ -1902,6 +1912,7 @@ private: ++ void loadRequestInFrameForInspector(LoadParameters&&, WebCore::FrameIdentifier); + + void setObscuredContentInsets(const WebCore::FloatBoxExtent&); + +@@ -2171,6 +2181,7 @@ private: void updatePotentialTapSecurityOrigin(const WebTouchEvent&, bool wasHandled); #elif ENABLE(TOUCH_EVENTS) void touchEvent(const WebTouchEvent&, CompletionHandler, bool)>&&); @@ -21142,29 +20068,34 @@ index a8d232fda1bf1dc7a9b3e866b3cbfb2952b26eef..b048960902cdd660209be177b4ecbe77 #endif void cancelPointer(WebCore::PointerID, const WebCore::IntPoint&); -@@ -2046,9 +2057,7 @@ private: - void addLayerForFindOverlay(CompletionHandler&&); - void removeLayerForFindOverlay(CompletionHandler&&); - --#if USE(COORDINATED_GRAPHICS) - void sendViewportAttributesChanged(const WebCore::ViewportArguments&); --#endif +@@ -2941,6 +2952,7 @@ private: + bool m_isAppNapEnabled { true }; - void didChangeSelectedIndexForActivePopupMenu(int32_t newIndex); - void setTextForActivePopupMenu(int32_t index); -@@ -2649,6 +2658,7 @@ private: - UserActivity m_userActivity; - - uint64_t m_pendingNavigationID { 0 }; -+ uint64_t m_pendingFrameNavigationID { 0 }; - std::optional m_pendingWebsitePolicies; + Markable m_pendingNavigationID; ++ Markable m_pendingFrameNavigationID; bool m_mainFrameProgressCompleted { false }; + bool m_shouldDispatchFakeMouseMoveEvents { true }; diff --git a/Source/WebKit/WebProcess/WebPage/WebPage.messages.in b/Source/WebKit/WebProcess/WebPage/WebPage.messages.in -index b67b771976b46970925529207e0153bc5637c533..7fc087a6d9769664347d62776d744287ec39c3a3 100644 +index c4ae18f9803e00d09a3f479c03ec858dd98c9045..9b1cbcf627f104e97a7ca46b560cdb9d99dc0ffc 100644 --- a/Source/WebKit/WebProcess/WebPage/WebPage.messages.in +++ b/Source/WebKit/WebProcess/WebPage/WebPage.messages.in -@@ -147,6 +147,7 @@ GenerateSyntheticEditingCommand(enum:uint8_t WebKit::SyntheticEditingCommandType +@@ -58,10 +58,13 @@ messages -> WebPage WantsAsyncDispatchMessage { + MouseEvent(WebCore::FrameIdentifier frameID, WebKit::WebMouseEvent event, std::optional> sandboxExtensions) + SetLastKnownMousePosition(WebCore::FrameIdentifier frameID, WebCore::IntPoint eventPoint, WebCore::IntPoint globalPoint); + ++#if ENABLE(ORIENTATION_EVENTS) ++ SetDeviceOrientation(WebCore::IntDegrees deviceOrientation) ++#endif ++ + #if PLATFORM(IOS_FAMILY) + SetSceneIdentifier(String sceneIdentifier) + SetViewportConfigurationViewLayoutSize(WebCore::FloatSize size, double scaleFactor, double minimumEffectiveDeviceWidth) +- SetDeviceOrientation(WebCore::IntDegrees deviceOrientation) + SetOverrideViewportArguments(struct std::optional arguments) + DynamicViewportSizeUpdate(struct WebKit::DynamicViewportSizeUpdate target) + +@@ -153,6 +156,7 @@ messages -> WebPage WantsAsyncDispatchMessage { ConnectInspector(String targetId, Inspector::FrontendChannel::ConnectionType connectionType) DisconnectInspector(String targetId) SendMessageToTargetBackend(String targetId, String message) @@ -21172,37 +20103,37 @@ index b67b771976b46970925529207e0153bc5637c533..7fc087a6d9769664347d62776d744287 #if ENABLE(REMOTE_INSPECTOR) SetIndicating(bool indicating); -@@ -157,6 +158,7 @@ GenerateSyntheticEditingCommand(enum:uint8_t WebKit::SyntheticEditingCommandType +@@ -163,6 +167,7 @@ messages -> WebPage WantsAsyncDispatchMessage { #endif #if !ENABLE(IOS_TOUCH_EVENTS) && ENABLE(TOUCH_EVENTS) - TouchEvent(WebKit::WebTouchEvent event) -> (std::optional eventType, bool handled) + TouchEvent(WebKit::WebTouchEvent event) -> (enum:uint8_t std::optional eventType, bool handled) + FakeTouchTap(WebCore::IntPoint position, uint8_t modifiers) -> () Async #endif CancelPointer(WebCore::PointerID pointerId, WebCore::IntPoint documentPoint) -@@ -188,6 +190,7 @@ GenerateSyntheticEditingCommand(enum:uint8_t WebKit::SyntheticEditingCommandType +@@ -188,6 +193,7 @@ messages -> WebPage WantsAsyncDispatchMessage { LoadDataInFrame(std::span data, String MIMEType, String encodingName, URL baseURL, WebCore::FrameIdentifier frameID) LoadRequest(struct WebKit::LoadParameters loadParameters) - TransitionFrameToLocal(struct WebKit::LocalFrameCreationParameters creationParameters, WebCore::FrameIdentifier frameID) + LoadDidCommitInAnotherProcess(WebCore::FrameIdentifier frameID, std::optional layerHostingContextIdentifier) + LoadRequestInFrameForInspector(struct WebKit::LoadParameters loadParameters, WebCore::FrameIdentifier frameID) LoadRequestWaitingForProcessLaunch(struct WebKit::LoadParameters loadParameters, URL resourceDirectoryURL, WebKit::WebPageProxyIdentifier pageID, bool checkAssumedReadAccessToResourceURL) LoadData(struct WebKit::LoadParameters loadParameters) LoadSimulatedRequestAndResponse(struct WebKit::LoadParameters loadParameters, WebCore::ResourceResponse simulatedResponse) -@@ -353,10 +356,10 @@ GenerateSyntheticEditingCommand(enum:uint8_t WebKit::SyntheticEditingCommandType +@@ -352,10 +358,10 @@ messages -> WebPage WantsAsyncDispatchMessage { RemoveLayerForFindOverlay() -> () # Drag and drop. -#if PLATFORM(GTK) && ENABLE(DRAG_SUPPORT) +#if (PLATFORM(GTK) || PLATFORM(WPE)) && ENABLE(DRAG_SUPPORT) - PerformDragControllerAction(enum:uint8_t WebKit::DragControllerAction action, WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, OptionSet draggingSourceOperationMask, WebCore::SelectionData selection, OptionSet flags) -> (std::optional dragOperation, enum:uint8_t WebCore::DragHandlingMethod dragHandlingMethod, bool mouseIsOverFileInput, unsigned numberOfItemsToBeAccepted, WebCore::IntRect insertionRect, WebCore::IntRect editableElementRect, struct std::optional remoteUserInputEventData) + PerformDragControllerAction(enum:uint8_t WebKit::DragControllerAction action, WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, OptionSet draggingSourceOperationMask, WebCore::SelectionData selection, OptionSet flags) -> (enum:uint8_t std::optional dragOperation, enum:uint8_t WebCore::DragHandlingMethod dragHandlingMethod, bool mouseIsOverFileInput, unsigned numberOfItemsToBeAccepted, WebCore::IntRect insertionRect, WebCore::IntRect editableElementRect, struct std::optional remoteUserInputEventData) #endif -#if !PLATFORM(GTK) && ENABLE(DRAG_SUPPORT) +#if !PLATFORM(GTK) && !PLATFORM(WPE) && ENABLE(DRAG_SUPPORT) - PerformDragControllerAction(std::optional frameID, enum:uint8_t WebKit::DragControllerAction action, WebCore::DragData dragData) -> (std::optional dragOperation, enum:uint8_t WebCore::DragHandlingMethod dragHandlingMethod, bool mouseIsOverFileInput, unsigned numberOfItemsToBeAccepted, WebCore::IntRect insertionRect, WebCore::IntRect editableElementRect, struct std::optional remoteUserInputEventData) + PerformDragControllerAction(std::optional frameID, enum:uint8_t WebKit::DragControllerAction action, WebCore::DragData dragData) -> (enum:uint8_t std::optional dragOperation, enum:uint8_t WebCore::DragHandlingMethod dragHandlingMethod, bool mouseIsOverFileInput, unsigned numberOfItemsToBeAccepted, WebCore::IntRect insertionRect, WebCore::IntRect editableElementRect, struct std::optional remoteUserInputEventData) PerformDragOperation(WebCore::DragData dragData, WebKit::SandboxExtensionHandle sandboxExtensionHandle, Vector sandboxExtensionsForUpload) -> (bool handled) #endif -@@ -366,6 +369,10 @@ GenerateSyntheticEditingCommand(enum:uint8_t WebKit::SyntheticEditingCommandType - DragCancelled() +@@ -375,6 +381,10 @@ messages -> WebPage WantsAsyncDispatchMessage { + ModelDragEnded(WebCore::ElementIdentifier elementID) #endif +#if PLATFORM(MAC) && ENABLE(DRAG_SUPPORT) @@ -21210,18 +20141,56 @@ index b67b771976b46970925529207e0153bc5637c533..7fc087a6d9769664347d62776d744287 +#endif + #if PLATFORM(IOS_FAMILY) && ENABLE(DRAG_SUPPORT) - RequestDragStart(WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, OptionSet allowedActionsMask) - RequestAdditionalItemsForDragSession(WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, OptionSet allowedActionsMask) + RequestDragStart(std::optional remoteFrameID, WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, OptionSet allowedActionsMask) -> (struct WebKit::DragInitiationResult result) + RequestAdditionalItemsForDragSession(std::optional rootFrameID, WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, OptionSet allowedActionsMask) -> (struct WebKit::DragInitiationResult result) +diff --git a/Source/WebKit/WebProcess/WebPage/glib/WebPageGLib.cpp b/Source/WebKit/WebProcess/WebPage/glib/WebPageGLib.cpp +index 40ec42bb4f998774a2ce4a19e82f68512ad2ebb8..080794e14bfbb3a336d8a89791baee0e1aec3c75 100644 +--- a/Source/WebKit/WebProcess/WebPage/glib/WebPageGLib.cpp ++++ b/Source/WebKit/WebProcess/WebPage/glib/WebPageGLib.cpp +@@ -210,16 +210,23 @@ String WebPage::platformUserAgent(const URL& url) const + + bool WebPage::hoverSupportedByPrimaryPointingDevice() const + { ++ if (screenHasTouchDeviceOverride()) ++ return !screenHasTouchDeviceOverride().value(); + return WebProcess::singleton().primaryPointingDevice() == AvailableInputDevices::Mouse; + } + + bool WebPage::hoverSupportedByAnyAvailablePointingDevice() const + { ++ if (screenHasTouchDeviceOverride()) ++ return !screenHasTouchDeviceOverride().value(); + return WebProcess::singleton().availableInputDevices().contains(AvailableInputDevices::Mouse); + } + + std::optional WebPage::pointerCharacteristicsOfPrimaryPointingDevice() const + { ++ if (screenHasTouchDeviceOverride() && screenHasTouchDeviceOverride().value()) ++ return PointerCharacteristics::Coarse; ++ + const auto& primaryPointingDevice = WebProcess::singleton().primaryPointingDevice(); + if (primaryPointingDevice == AvailableInputDevices::Mouse) + return PointerCharacteristics::Fine; +@@ -230,6 +237,9 @@ std::optional WebPage::pointerCharacteristicsOfPrimaryPo + + OptionSet WebPage::pointerCharacteristicsOfAllAvailablePointingDevices() const + { ++ if (screenHasTouchDeviceOverride() && screenHasTouchDeviceOverride().value()) ++ return PointerCharacteristics::Coarse; ++ + OptionSet pointerCharacteristics; + const auto& availableInputs = WebProcess::singleton().availableInputDevices(); + if (availableInputs.contains(AvailableInputDevices::Mouse)) diff --git a/Source/WebKit/WebProcess/WebPage/mac/WebPageMac.mm b/Source/WebKit/WebProcess/WebPage/mac/WebPageMac.mm -index 46b5327ff8777f3dce83ecf37219ad08321e8462..364d1010f0356a37d3f3b07d7fde187973028857 100644 +index e9dc2250f0f5e68db6ae61f5f734e2e2cf24cf9b..3dc31fc41d8efd990f94a713c0490abf1f1d9f60 100644 --- a/Source/WebKit/WebProcess/WebPage/mac/WebPageMac.mm +++ b/Source/WebKit/WebProcess/WebPage/mac/WebPageMac.mm -@@ -800,21 +800,37 @@ String WebPage::platformUserAgent(const URL&) const +@@ -705,21 +705,37 @@ String WebPage::platformUserAgent(const URL&) const bool WebPage::hoverSupportedByPrimaryPointingDevice() const { +#if ENABLE(TOUCH_EVENTS) -+ return !screenIsTouchPrimaryInputDevice(); ++ return !screenHasTouchDevice(); +#else return true; +#endif @@ -21239,7 +20208,7 @@ index 46b5327ff8777f3dce83ecf37219ad08321e8462..364d1010f0356a37d3f3b07d7fde1879 std::optional WebPage::pointerCharacteristicsOfPrimaryPointingDevice() const { +#if ENABLE(TOUCH_EVENTS) -+ if (screenIsTouchPrimaryInputDevice()) ++ if (screenHasTouchDevice()) + return PointerCharacteristics::Coarse; +#endif return PointerCharacteristics::Fine; @@ -21255,10 +20224,10 @@ index 46b5327ff8777f3dce83ecf37219ad08321e8462..364d1010f0356a37d3f3b07d7fde1879 } diff --git a/Source/WebKit/WebProcess/WebPage/win/WebPageWin.cpp b/Source/WebKit/WebProcess/WebPage/win/WebPageWin.cpp -index f17f5d719d892309ed9c7093384945866b5117b9..1dba47bbf0dbd0362548423a74b380346dbea147 100644 +index ea3a03b5ee6d4ecadd771314c6059268db917087..91be6f4c687157afcfdaa431d7a1a6ff712b551c 100644 --- a/Source/WebKit/WebProcess/WebPage/win/WebPageWin.cpp +++ b/Source/WebKit/WebProcess/WebPage/win/WebPageWin.cpp -@@ -43,6 +43,7 @@ +@@ -45,6 +45,7 @@ #include #include #include @@ -21266,12 +20235,12 @@ index f17f5d719d892309ed9c7093384945866b5117b9..1dba47bbf0dbd0362548423a74b38034 #include #include #include -@@ -81,21 +82,37 @@ String WebPage::platformUserAgent(const URL&) const +@@ -83,21 +84,37 @@ String WebPage::platformUserAgent(const URL&) const bool WebPage::hoverSupportedByPrimaryPointingDevice() const { +#if ENABLE(TOUCH_EVENTS) -+ return !screenIsTouchPrimaryInputDevice(); ++ return !screenHasTouchDevice(); +#else return true; +#endif @@ -21289,7 +20258,7 @@ index f17f5d719d892309ed9c7093384945866b5117b9..1dba47bbf0dbd0362548423a74b38034 std::optional WebPage::pointerCharacteristicsOfPrimaryPointingDevice() const { +#if ENABLE(TOUCH_EVENTS) -+ if (screenIsTouchPrimaryInputDevice()) ++ if (screenHasTouchDevice()) + return PointerCharacteristics::Coarse; +#endif return PointerCharacteristics::Fine; @@ -21305,10 +20274,10 @@ index f17f5d719d892309ed9c7093384945866b5117b9..1dba47bbf0dbd0362548423a74b38034 } diff --git a/Source/WebKit/WebProcess/WebProcess.cpp b/Source/WebKit/WebProcess/WebProcess.cpp -index 4b52cd3a81eceb55531d48d4e4a54dc7d62b4d32..e3427d76d44a9bf148f4f9dca7ed7d7b58319b53 100644 +index 230b9bb1f8b1f218f94c10f18f4d672286ce5a9d..c9741c132685eb27737d21c7c840edb9447ec596 100644 --- a/Source/WebKit/WebProcess/WebProcess.cpp +++ b/Source/WebKit/WebProcess/WebProcess.cpp -@@ -88,6 +88,7 @@ +@@ -93,6 +93,7 @@ #include "WebsiteData.h" #include "WebsiteDataStoreParameters.h" #include "WebsiteDataType.h" @@ -21316,7 +20285,22 @@ index 4b52cd3a81eceb55531d48d4e4a54dc7d62b4d32..e3427d76d44a9bf148f4f9dca7ed7d7b #include #include #include -@@ -365,6 +366,8 @@ void WebProcess::initializeProcess(const AuxiliaryProcessInitializationParameter +@@ -388,6 +389,14 @@ void WebProcess::initializeProcess(const AuxiliaryProcessInitializationParameter + { + JSC::Options::AllowUnfinalizedAccessScope scope; + JSC::Options::allowNonSPTagging() = false; ++ // Playwright begin ++ // SharedBufferArray is enabled only on Mac via XPC sercvice "enable-shared-array-buffer" option. ++ // For other platforms, enable it here. ++#if !PLATFORM(COCOA) ++ if (parameters.shouldEnableSharedArrayBuffer) ++ JSC::Options::useSharedArrayBuffer() = true; ++#endif ++ // Playwright end + JSC::Options::notifyOptionsChanged(); + } + +@@ -395,6 +404,8 @@ void WebProcess::initializeProcess(const AuxiliaryProcessInitializationParameter platformInitializeProcess(parameters); updateCPULimit(); @@ -21325,26 +20309,20 @@ index 4b52cd3a81eceb55531d48d4e4a54dc7d62b4d32..e3427d76d44a9bf148f4f9dca7ed7d7b } void WebProcess::initializeConnection(IPC::Connection* connection) -diff --git a/Source/WebKit/WebProcess/win/WebProcessMainWin.cpp b/Source/WebKit/WebProcess/win/WebProcessMainWin.cpp -index 8987c3964a9308f2454759de7f8972215a3ae416..bcac0afeb94ed8123d1f9fb0b932c8497d157b49 100644 ---- a/Source/WebKit/WebProcess/win/WebProcessMainWin.cpp -+++ b/Source/WebKit/WebProcess/win/WebProcessMainWin.cpp -@@ -42,7 +42,9 @@ public: - bool platformInitialize() override - { - if (SetProcessDpiAwarenessContextPtr()) -- SetProcessDpiAwarenessContextPtr()(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); -+ // Playwright begin -+ SetProcessDpiAwarenessContextPtr()(DPI_AWARENESS_CONTEXT_UNAWARE); -+ // Playwright end - else - SetProcessDPIAware(); - return true; +@@ -975,6 +986,8 @@ void WebProcess::createWebPage(PageIdentifier pageID, WebPageCreationParameters& + accessibilityRelayProcessSuspended(false); + } + ASSERT(result.iterator->value); ++ ++ result.iterator->value->didAddWebPageToWebProcess(); + } + + void WebProcess::removeWebPage(PageIdentifier pageID) diff --git a/Source/WebKitLegacy/mac/WebView/WebHTMLView.mm b/Source/WebKitLegacy/mac/WebView/WebHTMLView.mm -index 1ef662de86f8b92a7a5c6414df2dac6dbb3882f0..793785e12f96fe52193e8c27ec8b015521e06390 100644 +index 9dd01c8ef00f00d49d54a16996142681d1486852..51a02893b48bc930ebca7dd4b76dc874beecb157 100644 --- a/Source/WebKitLegacy/mac/WebView/WebHTMLView.mm +++ b/Source/WebKitLegacy/mac/WebView/WebHTMLView.mm -@@ -4214,7 +4214,7 @@ ALLOW_DEPRECATED_DECLARATIONS_END +@@ -4225,7 +4225,7 @@ ALLOW_DEPRECATED_DECLARATIONS_END _private->handlingMouseDownEvent = NO; } @@ -21354,10 +20332,10 @@ index 1ef662de86f8b92a7a5c6414df2dac6dbb3882f0..793785e12f96fe52193e8c27ec8b0155 - (void)touch:(WebEvent *)event { diff --git a/Source/WebKitLegacy/mac/WebView/WebView.mm b/Source/WebKitLegacy/mac/WebView/WebView.mm -index c892fdcdb2834ab3d93a4a0575b712c848b662c0..0e817f6ac6cf4e0bc04e1acd178ef976105d9b16 100644 +index 222de8db3d8475b7a68b017dc88994d4ca7e08fd..ed3460c7b59772410af898d4fb107cc88c3b40a6 100644 --- a/Source/WebKitLegacy/mac/WebView/WebView.mm +++ b/Source/WebKitLegacy/mac/WebView/WebView.mm -@@ -3979,7 +3979,7 @@ + (void)_doNotStartObservingNetworkReachability +@@ -4002,7 +4002,7 @@ + (void)_doNotStartObservingNetworkReachability } #endif // PLATFORM(IOS_FAMILY) @@ -21366,7 +20344,7 @@ index c892fdcdb2834ab3d93a4a0575b712c848b662c0..0e817f6ac6cf4e0bc04e1acd178ef976 - (NSArray *)_touchEventRegions { -@@ -4021,7 +4021,7 @@ - (NSArray *)_touchEventRegions +@@ -4044,7 +4044,7 @@ - (NSArray *)_touchEventRegions }).autorelease(); } @@ -21377,14 +20355,16 @@ index c892fdcdb2834ab3d93a4a0575b712c848b662c0..0e817f6ac6cf4e0bc04e1acd178ef976 // a per-WebView and a per-preferences setting for whether to use the back/forward cache. diff --git a/Source/cmake/FindLibVPX.cmake b/Source/cmake/FindLibVPX.cmake new file mode 100644 -index 0000000000000000000000000000000000000000..dd6a53e2d57318489b7e49dd7373706d5d9dc387 +index 0000000000000000000000000000000000000000..a9db9ec38d05e36517414248237e885b25109647 --- /dev/null +++ b/Source/cmake/FindLibVPX.cmake -@@ -0,0 +1,25 @@ +@@ -0,0 +1,27 @@ +# Find LibVPX + +find_package(PkgConfig QUIET) -+pkg_check_modules(PC_LIBVPX REQUIRED vpx) ++if (PkgConfig_FOUND) ++ pkg_check_modules(PC_LIBVPX REQUIRED vpx) ++endif () + +find_path(LIBVPX_INCLUDE_DIRS + NAMES vpx/vp8.h @@ -21407,24 +20387,21 @@ index 0000000000000000000000000000000000000000..dd6a53e2d57318489b7e49dd7373706d + LIBVPX_LIBRARIES +) diff --git a/Source/cmake/OptionsGTK.cmake b/Source/cmake/OptionsGTK.cmake -index 31085c5a7f8d4e1680887ff9f20de2d421256a62..d1374f5f68f26d166d9a6e4f1ae9a23dd9151e13 100644 +index 303550b9618e8c621e246e8c95b9e7542585f1fc..efdb66ef47e46e83287350933047295e6dc0c268 100644 --- a/Source/cmake/OptionsGTK.cmake +++ b/Source/cmake/OptionsGTK.cmake -@@ -11,8 +11,13 @@ if (${CMAKE_VERSION} VERSION_LESS "3.20" AND NOT ${CMAKE_GENERATOR} STREQUAL "Ni - message(FATAL_ERROR "Building with Makefiles requires CMake 3.20 or newer. Either enable Ninja by passing -GNinja, or upgrade CMake.") - endif () +@@ -9,6 +9,10 @@ set(USER_AGENT_BRANDING "" CACHE STRING "Branding to add to user agent string") -+set(ENABLE_WEBKIT_LEGACY OFF) + # Update Source/WTF/wtf/Platform.h to match required GLib versions. + find_package(GLIB 2.70.0 REQUIRED COMPONENTS gio gio-unix gobject gthread gmodule) + - set(USER_AGENT_BRANDING "" CACHE STRING "Branding to add to user agent string") - +set(CMAKE_THREAD_PREFER_PTHREAD TRUE) +set(THREADS_PREFER_PTHREAD_FLAG TRUE) + find_package(Cairo 1.16.0 REQUIRED) find_package(LibGcrypt 1.7.0 REQUIRED) find_package(Libtasn1 REQUIRED) -@@ -29,6 +34,10 @@ find_package(ZLIB REQUIRED) +@@ -24,6 +28,10 @@ find_package(ZLIB REQUIRED) find_package(WebP REQUIRED COMPONENTS demux) find_package(ATSPI 2.5.3) @@ -21435,71 +20412,43 @@ index 31085c5a7f8d4e1680887ff9f20de2d421256a62..d1374f5f68f26d166d9a6e4f1ae9a23d include(GStreamerDefinitions) include(FindGLibCompileResources) -@@ -88,14 +97,14 @@ endif () - # without approval from a GTK reviewer. There must be strong reason to support - # changing the value of the option. - WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DRAG_SUPPORT PUBLIC ON) --WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_GAMEPAD PUBLIC ON) +@@ -71,6 +79,10 @@ WEBKIT_OPTION_DEFINE(USE_SYSTEM_UNIFDEF "Whether to use a system-provided unifde + + WEBKIT_OPTION_DEPEND(USE_SYSTEM_SYSPROF_CAPTURE USE_SYSPROF_CAPTURE) + ++# Playwright begin. ++WEBKIT_OPTION_DEFAULT_PORT_VALUE(USE_SYSTEM_SYSPROF_CAPTURE PRIVATE OFF) ++# Playwright end. ++ + SET_AND_EXPOSE_TO_BUILD(ENABLE_DEVELOPER_MODE ${DEVELOPER_MODE}) + if (DEVELOPER_MODE) + WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_API_TESTS PRIVATE ON) +@@ -147,6 +159,20 @@ endif () + + WEBKIT_OPTION_DEPEND(ENABLE_GPU_PROCESS USE_GBM) + ++# Playwright begin. +WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_GAMEPAD PUBLIC OFF) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MINIBROWSER PUBLIC ON) --WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_PDFJS PUBLIC ON) +WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_PDFJS PUBLIC OFF) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_SPELLCHECK PUBLIC ON) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_TOUCH_EVENTS PUBLIC ON) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEBDRIVER PUBLIC ON) - --WEBKIT_OPTION_DEFAULT_PORT_VALUE(USE_AVIF PUBLIC ON) -+WEBKIT_OPTION_DEFAULT_PORT_VALUE(USE_AVIF PUBLIC OFF) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(USE_LCMS PUBLIC ON) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(USE_JPEGXL PUBLIC ON) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(USE_WOFF2 PUBLIC ON) -@@ -119,7 +128,7 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_INPUT_TYPE_DATETIMELOCAL PRIVATE ON) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_INPUT_TYPE_MONTH PRIVATE ON) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_INPUT_TYPE_TIME PRIVATE ON) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_INPUT_TYPE_WEEK PRIVATE ON) --WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MEDIA_RECORDER PRIVATE ON) +WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MEDIA_RECORDER PRIVATE OFF) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MEDIA_SESSION PRIVATE ON) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MEDIA_SESSION_PLAYLIST PRIVATE OFF) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MEDIA_STREAM PRIVATE ON) -@@ -131,7 +140,7 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_NETWORK_CACHE_SPECULATIVE_REVALIDATION P - WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_NETWORK_CACHE_STALE_WHILE_REVALIDATE PRIVATE ON) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_OFFSCREEN_CANVAS PRIVATE ${ENABLE_EXPERIMENTAL_FEATURES}) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_OFFSCREEN_CANVAS_IN_WORKERS PRIVATE ${ENABLE_EXPERIMENTAL_FEATURES}) --WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_THUNDER PRIVATE ${ENABLE_DEVELOPER_MODE}) +WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_THUNDER PRIVATE OFF) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_PERIODIC_MEMORY_MONITOR PRIVATE ON) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_POINTER_LOCK PRIVATE ON) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_SHAREABLE_RESOURCE PRIVATE ON) -@@ -141,6 +150,14 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEB_API_STATISTICS PRIVATE ON) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEB_CODECS PRIVATE ON) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEB_RTC PRIVATE ${ENABLE_EXPERIMENTAL_FEATURES}) - -+# Playwright ++ +WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_APPLICATION_MANIFEST PRIVATE ON) +WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CURSOR_VISIBILITY PRIVATE ON) +WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DEVICE_ORIENTATION PRIVATE ON) +WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_GAMEPAD PRIVATE ON) +WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_SPEECH_SYNTHESIS PRIVATE ON) +WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_POINTER_LOCK PRIVATE ON) ++# Playwright end. + include(GStreamerDependencies) # Finalize the value for all options. Do not attempt to use an option before diff --git a/Source/cmake/OptionsWPE.cmake b/Source/cmake/OptionsWPE.cmake -index e0c8dc92717c31173b6848b9f04856276125fb9d..24bbbae0654cded5197e6a4ce13246f71f5d5590 100644 +index 45b4da4575d41bdf1b829ddf68947f30bc57734f..378b9114ae03c18f0caead71750c1169b2c45b27 100644 --- a/Source/cmake/OptionsWPE.cmake +++ b/Source/cmake/OptionsWPE.cmake -@@ -9,6 +9,8 @@ if (${CMAKE_VERSION} VERSION_LESS "3.20" AND NOT ${CMAKE_GENERATOR} STREQUAL "Ni - message(FATAL_ERROR "Building with Makefiles requires CMake 3.20 or newer. Either enable Ninja by passing -GNinja, or upgrade CMake.") - endif () - -+set(ENABLE_WEBKIT_LEGACY OFF) -+ - set(USER_AGENT_BRANDING "" CACHE STRING "Branding to add to user agent string") - - find_package(HarfBuzz 1.4.2 REQUIRED COMPONENTS ICU) -@@ -27,6 +29,9 @@ find_package(WebP REQUIRED COMPONENTS demux) +@@ -23,6 +23,9 @@ find_package(WebP REQUIRED COMPONENTS demux) find_package(WPE REQUIRED) find_package(ZLIB REQUIRED) @@ -21509,106 +20458,56 @@ index e0c8dc92717c31173b6848b9f04856276125fb9d..24bbbae0654cded5197e6a4ce13246f7 WEBKIT_OPTION_BEGIN() SET_AND_EXPOSE_TO_BUILD(ENABLE_DEVELOPER_MODE ${DEVELOPER_MODE}) -@@ -38,11 +43,11 @@ include(FindGLibCompileResources) - # without approval from a WPE reviewer. There must be strong reason to support - # changing the value of the option. - WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_ENCRYPTED_MEDIA PUBLIC ${ENABLE_EXPERIMENTAL_FEATURES}) --WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_PDFJS PUBLIC ON) +@@ -81,6 +84,21 @@ else () + WEBKIT_OPTION_DEFAULT_PORT_VALUE(USE_SKIA PRIVATE OFF) + endif () + ++# Playwright begin. ++WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MINIBROWSER PUBLIC ON) +WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_PDFJS PUBLIC OFF) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEBDRIVER PUBLIC ON) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_XSLT PUBLIC ON) - --WEBKIT_OPTION_DEFAULT_PORT_VALUE(USE_AVIF PUBLIC ON) -+WEBKIT_OPTION_DEFAULT_PORT_VALUE(USE_AVIF PUBLIC OFF) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(USE_LCMS PUBLIC ON) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(USE_JPEGXL PUBLIC ON) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(USE_WOFF2 PUBLIC ON) -@@ -58,7 +63,7 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DARK_MODE_CSS PRIVATE ON) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_FTPDIR PRIVATE OFF) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_GPU_PROCESS PRIVATE OFF) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MEDIA_CONTROLS_CONTEXT_MENUS PRIVATE ON) --WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MEDIA_RECORDER PRIVATE ON) +WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MEDIA_RECORDER PRIVATE OFF) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MEDIA_SESSION PRIVATE ON) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MEDIA_SESSION_PLAYLIST PRIVATE OFF) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MEDIA_STREAM PRIVATE ON) -@@ -72,7 +77,7 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_OFFSCREEN_CANVAS_IN_WORKERS PRIVATE ${EN - WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_PERIODIC_MEMORY_MONITOR PRIVATE ON) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_SHAREABLE_RESOURCE PRIVATE ON) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_SPEECH_SYNTHESIS PRIVATE ${ENABLE_EXPERIMENTAL_FEATURES}) --WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_THUNDER PRIVATE ${ENABLE_DEVELOPER_MODE}) +WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_THUNDER PRIVATE OFF) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_TOUCH_EVENTS PRIVATE ON) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_VARIATION_FONTS PRIVATE ON) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEB_CODECS PRIVATE ON) -@@ -83,6 +88,23 @@ if (WPE_VERSION VERSION_GREATER_EQUAL 1.13.90) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_GAMEPAD PUBLIC ON) - endif () - -+# Playwright ++ +WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_APPLICATION_MANIFEST PRIVATE ON) +WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CURSOR_VISIBILITY PRIVATE ON) +WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DARK_MODE_CSS PRIVATE ON) -+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DATALIST_ELEMENT PRIVATE ON) +WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DRAG_SUPPORT PRIVATE ON) +WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DEVICE_ORIENTATION PRIVATE ON) -+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_INPUT_TYPE_COLOR PRIVATE ON) -+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_INPUT_TYPE_DATE PRIVATE ON) -+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_INPUT_TYPE_DATETIMELOCAL PRIVATE ON) -+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_INPUT_TYPE_MONTH PRIVATE ON) -+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_INPUT_TYPE_TIME PRIVATE ON) -+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_INPUT_TYPE_WEEK PRIVATE ON) -+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_DATE_AND_TIME_INPUT_TYPES PRIVATE ON) +WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_SPEECH_SYNTHESIS PRIVATE ON) +WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_POINTER_LOCK PRIVATE ON) ++# Playwright end. + # Public options specific to the WPE port. Do not add any options here unless # there is a strong reason we should support changing the value of the option, # and the option is not relevant to other WebKit ports. -@@ -92,7 +114,7 @@ WEBKIT_OPTION_DEFINE(ENABLE_JOURNALD_LOG "Whether to enable journald logging" PU - WEBKIT_OPTION_DEFINE(ENABLE_WPE_PLATFORM_DRM "Whether to enable support for DRM platform" PUBLIC ON) - WEBKIT_OPTION_DEFINE(ENABLE_WPE_PLATFORM_HEADLESS "Whether to enable support for headless platform" PUBLIC ON) - WEBKIT_OPTION_DEFINE(ENABLE_WPE_PLATFORM_WAYLAND "Whether to enable support for Wayland platform" PUBLIC ON) --WEBKIT_OPTION_DEFINE(ENABLE_WPE_QT_API "Whether to enable support for the Qt5/QML plugin" PUBLIC ${ENABLE_DEVELOPER_MODE}) -+WEBKIT_OPTION_DEFINE(ENABLE_WPE_QT_API "Whether to enable support for the Qt5/QML plugin" PUBLIC OFF) - WEBKIT_OPTION_DEFINE(ENABLE_WPE_1_1_API "Whether to build WPE 1.1 instead of WPE 2.0" PUBLIC OFF) - WEBKIT_OPTION_DEFINE(USE_ATK "Whether to enable usage of ATK." PUBLIC ON) - WEBKIT_OPTION_DEFINE(USE_GBM "Whether to enable usage of GBM." PUBLIC ON) +@@ -116,6 +134,11 @@ WEBKIT_OPTION_DEPEND(USE_QT6 ENABLE_WPE_PLATFORM) + WEBKIT_OPTION_DEPEND(USE_SKIA_OPENTYPE_SVG USE_SKIA) + WEBKIT_OPTION_DEPEND(USE_SYSTEM_SYSPROF_CAPTURE USE_SYSPROF_CAPTURE) + ++# Playwright begin. ++WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WPE_QT_API PUBLIC OFF) ++WEBKIT_OPTION_DEFAULT_PORT_VALUE(USE_SYSTEM_SYSPROF_CAPTURE PRIVATE OFF) ++# Playwright end. ++ + if (CMAKE_SYSTEM_NAME MATCHES "Linux") + WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_BUBBLEWRAP_SANDBOX PUBLIC ON) + WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MEMORY_SAMPLER PRIVATE ON) diff --git a/Source/cmake/OptionsWin.cmake b/Source/cmake/OptionsWin.cmake -index 2ed9985c35980ba0fca09c2fc9ea5ab300b19b00..a5f773d071cb67025b16614a998bd09355061572 100644 +index 95393f0a6063615b417eb3249d3838ad0e3024d8..beedf862d572718b8f0f5e6daa0f8d029a96ea77 100644 --- a/Source/cmake/OptionsWin.cmake +++ b/Source/cmake/OptionsWin.cmake -@@ -86,6 +86,29 @@ find_package(ZLIB 1.2.11 REQUIRED) +@@ -55,6 +55,10 @@ find_package(ZLIB 1.2.11 REQUIRED) find_package(LibPSL 0.20.2 REQUIRED) find_package(WebP REQUIRED COMPONENTS demux) +# Playwright begin -+if (NOT LIBVPX_PACKAGE_PATH) -+ set(LIBVPX_PACKAGE_PATH "C:\\vcpkg\\packages\\libvpx_x64-windows") -+endif() -+file(TO_CMAKE_PATH "${LIBVPX_PACKAGE_PATH}" LIBVPX_PACKAGE_PATH) -+message(STATUS "Using LIBVPX_PACKAGE_PATH = ${LIBVPX_PACKAGE_PATH}") -+ -+find_library(LIBVPX_CUSTOM_LIBRARY vpx.lib -+ HINTS ${LIBVPX_PACKAGE_PATH}/lib -+ REQIRED -+ NO_DEFAULT_PATH -+) -+message(STATUS "Found LIBVPX_CUSTOM_LIBRARY = ${LIBVPX_CUSTOM_LIBRARY}") -+ -+find_path(LIBVPX_CUSTOM_INCLUDE_DIR -+ NAMES vpx/vp8.h -+ HINTS ${LIBVPX_PACKAGE_PATH}/include -+ REQUIRED -+ NO_DEFAULT_PATH -+) -+message(STATUS "Found LIBVPX_CUSTOM_INCLUDE_DIR = ${LIBVPX_CUSTOM_INCLUDE_DIR}") ++find_package(LibVPX REQUIRED) +# Playwright end + WEBKIT_OPTION_BEGIN() # FIXME: Most of these options should not be public. -@@ -159,6 +182,14 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_FTPDIR PRIVATE OFF) +@@ -113,6 +117,14 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_FTPDIR PRIVATE OFF) SET_AND_EXPOSE_TO_BUILD(ENABLE_WEBDRIVER_KEYBOARD_INTERACTIONS ON) SET_AND_EXPOSE_TO_BUILD(ENABLE_WEBDRIVER_MOUSE_INTERACTIONS ON) @@ -21624,7 +20523,7 @@ index 2ed9985c35980ba0fca09c2fc9ea5ab300b19b00..a5f773d071cb67025b16614a998bd093 set(USE_ANGLE_EGL ON) diff --git a/Source/cmake/WebKitCompilerFlags.cmake b/Source/cmake/WebKitCompilerFlags.cmake -index 26f8c4421bf45bb2f7e5f67ebd31ecfd9c0ddd3d..52ad063be9977fbbfa17ed0ae09676fd9455aef9 100644 +index d8fe5503609122c55c2c675934b3678cfe709cf0..2e706bb436d6c01689bec8cc7b7de3c125ca258a 100644 --- a/Source/cmake/WebKitCompilerFlags.cmake +++ b/Source/cmake/WebKitCompilerFlags.cmake @@ -122,7 +122,7 @@ macro(WEBKIT_ADD_TARGET_CXX_FLAGS _target) @@ -21637,7 +20536,7 @@ index 26f8c4421bf45bb2f7e5f67ebd31ecfd9c0ddd3d..52ad063be9977fbbfa17ed0ae09676fd if (MSVC) set(FATAL_WARNINGS_FLAG /WX) diff --git a/Tools/DumpRenderTree/DerivedSources.make b/Tools/DumpRenderTree/DerivedSources.make -index 57aae19f1a16d08ba1579562eeff264c8768af4d..6ce36f40cc954bd02b86f84bd9a0bd2928459938 100644 +index 576835410df6deac60f0158f1d2d1ef1e5f4c78d..9b492cfe5fef8de340a80f2af70a7d68672ef2e4 100644 --- a/Tools/DumpRenderTree/DerivedSources.make +++ b/Tools/DumpRenderTree/DerivedSources.make @@ -73,8 +73,8 @@ $(IDL_FILE_NAMES_LIST) : $(UICONTEXT_INTERFACES:%=%.idl) @@ -21651,10 +20550,33 @@ index 57aae19f1a16d08ba1579562eeff264c8768af4d..6ce36f40cc954bd02b86f84bd9a0bd29 WEB_PREFERENCES_GENERATED_FILES = \ TestOptionsGeneratedWebKitLegacyKeyMapping.cpp \ diff --git a/Tools/MiniBrowser/gtk/BrowserTab.c b/Tools/MiniBrowser/gtk/BrowserTab.c -index 61616b96e2f4e21aa6d098445e0f1a933e512a9c..33732da18013679a869ff8eb2b44543413f7cf0f 100644 +index 6d48c378699e87f55bbd2550d4971a295b831a24..efb0d8e1e0f7db5d4ce81bc58a97e6c4034ff0b3 100644 --- a/Tools/MiniBrowser/gtk/BrowserTab.c +++ b/Tools/MiniBrowser/gtk/BrowserTab.c -@@ -123,13 +123,16 @@ static gboolean decidePolicy(WebKitWebView *webView, WebKitPolicyDecision *decis +@@ -117,19 +117,38 @@ static void isLoadingChanged(WebKitWebView *webView, GParamSpec *paramSpec, Brow + } + } + ++static gboolean response_policy_decision_can_show(WebKitResponsePolicyDecision *responseDecision) ++{ ++ if (webkit_response_policy_decision_is_mime_type_supported(responseDecision)) ++ return TRUE; ++ WebKitURIResponse* response = webkit_response_policy_decision_get_response(responseDecision); ++ const guint statusCode = webkit_uri_response_get_status_code(response); ++ if (statusCode == 205 || statusCode == 204) ++ return TRUE; ++ const gchar* mimeType = webkit_uri_response_get_mime_type(response); ++ if (!mimeType || mimeType[0] == '\0') ++ return FALSE; ++ // https://bugs.webkit.org/show_bug.cgi?id=277204 / Ubuntu 24.04 / glib 2.76+ or higher ++ if (g_ascii_strcasecmp(mimeType, "application/x-zerosize") == 0) ++ return TRUE; ++ return FALSE; ++} ++ + static gboolean decidePolicy(WebKitWebView *webView, WebKitPolicyDecision *decision, WebKitPolicyDecisionType decisionType, BrowserTab *tab) + { + if (decisionType != WEBKIT_POLICY_DECISION_TYPE_RESPONSE) return FALSE; WebKitResponsePolicyDecision *responseDecision = WEBKIT_RESPONSE_POLICY_DECISION(decision); @@ -21665,8 +20587,7 @@ index 61616b96e2f4e21aa6d098445e0f1a933e512a9c..33732da18013679a869ff8eb2b445434 return FALSE; - webkit_policy_decision_download(decision); -+ const gchar* mimeType = webkit_uri_response_get_mime_type(webkit_response_policy_decision_get_response(responseDecision)); -+ if (!webkit_response_policy_decision_is_mime_type_supported(responseDecision) && mimeType && mimeType[0] != '\0') { ++ if (!response_policy_decision_can_show(responseDecision)) { + webkit_policy_decision_download(decision); + return TRUE; + } @@ -21675,7 +20596,7 @@ index 61616b96e2f4e21aa6d098445e0f1a933e512a9c..33732da18013679a869ff8eb2b445434 return TRUE; } -@@ -159,6 +162,11 @@ static void loadChanged(WebKitWebView *webView, WebKitLoadEvent loadEvent, Brows +@@ -180,6 +199,11 @@ static void loadChanged(WebKitWebView *webView, WebKitLoadEvent loadEvent, Brows #endif } @@ -21687,7 +20608,7 @@ index 61616b96e2f4e21aa6d098445e0f1a933e512a9c..33732da18013679a869ff8eb2b445434 static GtkWidget *createInfoBarQuestionMessage(const char *title, const char *text) { GtkWidget *dialog = gtk_info_bar_new_with_buttons("No", GTK_RESPONSE_NO, "Yes", GTK_RESPONSE_YES, NULL); -@@ -720,6 +728,7 @@ static void browserTabConstructed(GObject *gObject) +@@ -746,6 +770,7 @@ static void browserTabConstructed(GObject *gObject) g_signal_connect(tab->webView, "notify::is-loading", G_CALLBACK(isLoadingChanged), tab); g_signal_connect(tab->webView, "decide-policy", G_CALLBACK(decidePolicy), tab); g_signal_connect(tab->webView, "load-changed", G_CALLBACK(loadChanged), tab); @@ -21695,7 +20616,7 @@ index 61616b96e2f4e21aa6d098445e0f1a933e512a9c..33732da18013679a869ff8eb2b445434 g_signal_connect(tab->webView, "load-failed-with-tls-errors", G_CALLBACK(loadFailedWithTLSerrors), tab); g_signal_connect(tab->webView, "permission-request", G_CALLBACK(decidePermissionRequest), tab); g_signal_connect(tab->webView, "run-color-chooser", G_CALLBACK(runColorChooserCallback), tab); -@@ -772,6 +781,9 @@ static char *getInternalURI(const char *uri) +@@ -798,6 +823,9 @@ static char *getInternalURI(const char *uri) if (g_str_has_prefix(uri, "about:") && !g_str_equal(uri, "about:blank")) return g_strconcat(BROWSER_ABOUT_SCHEME, uri + strlen ("about"), NULL); @@ -21706,7 +20627,7 @@ index 61616b96e2f4e21aa6d098445e0f1a933e512a9c..33732da18013679a869ff8eb2b445434 } diff --git a/Tools/MiniBrowser/gtk/BrowserWindow.c b/Tools/MiniBrowser/gtk/BrowserWindow.c -index bd00606c26b6fedb75978ed26a9b07f4b70828d8..8460a4ae5ff7461e3435fe2e704bb04e0a8bd0f8 100644 +index d39b809a879babcdbbf4b5f7687204df5ccc43f3..2862876cb515da09db653e71659d64215a636758 100644 --- a/Tools/MiniBrowser/gtk/BrowserWindow.c +++ b/Tools/MiniBrowser/gtk/BrowserWindow.c @@ -73,7 +73,7 @@ struct _BrowserWindowClass { @@ -21739,7 +20660,7 @@ index bd00606c26b6fedb75978ed26a9b07f4b70828d8..8460a4ae5ff7461e3435fe2e704bb04e gtk_window_set_title(GTK_WINDOW(window), privateTitle ? privateTitle : title); g_free(privateTitle); } -@@ -520,8 +514,12 @@ static gboolean webViewDecidePolicy(WebKitWebView *webView, WebKitPolicyDecision +@@ -524,8 +518,12 @@ static gboolean webViewDecidePolicy(WebKitWebView *webView, WebKitPolicyDecision return FALSE; WebKitNavigationAction *navigationAction = webkit_navigation_policy_decision_get_navigation_action(WEBKIT_NAVIGATION_POLICY_DECISION(decision)); @@ -21754,30 +20675,51 @@ index bd00606c26b6fedb75978ed26a9b07f4b70828d8..8460a4ae5ff7461e3435fe2e704bb04e return FALSE; /* Multiple tabs are not allowed in editor mode. */ -@@ -1498,6 +1496,12 @@ static gboolean browserWindowDeleteEvent(GtkWidget *widget, GdkEventAny* event) +@@ -1502,6 +1500,28 @@ static gboolean browserWindowDeleteEvent(GtkWidget *widget, GdkEventAny* event) } #endif ++#if GTK_CHECK_VERSION(3, 98, 0) ++static void zero_widget_measure (GtkWidget *widget, ++ GtkOrientation orientation, ++ int for_size, ++ int *minimum_size, ++ int *natural_size, ++ int *minimum_baseline, ++ int *natural_baseline) ++{ ++ *minimum_size = 10; ++ *natural_size = 10; ++ // *minimum_baseline = 10; ++ // *natural_baseline = 10; ++} ++#else +static void zeroPreferredSize(GtkWidget* widget, gint* minimumSize, gint* naturalSize) +{ + *minimumSize = 10; + *naturalSize = 10; +} ++#endif + static void browser_window_class_init(BrowserWindowClass *klass) { GObjectClass *gobjectClass = G_OBJECT_CLASS(klass); -@@ -1511,6 +1515,14 @@ static void browser_window_class_init(BrowserWindowClass *klass) +@@ -1515,6 +1535,19 @@ static void browser_window_class_init(BrowserWindowClass *klass) GtkWidgetClass *widgetClass = GTK_WIDGET_CLASS(klass); widgetClass->delete_event = browserWindowDeleteEvent; #endif + +// Playwrigth begin -+ // Override preferred (which is minimum :-) size to 0 so that we can -+ // emulate arbitrary resolution. ++// Override preferred (which is minimum :-) size to 0 so that we can ++// emulate arbitrary resolution. ++#if GTK_CHECK_VERSION(3, 98, 0) ++ GtkWidgetClass* browserWidgetClass = GTK_WIDGET_CLASS(klass); ++ browserWidgetClass->measure = zero_widget_measure; ++#else + GtkWidgetClass* browserWidgetClass = GTK_WIDGET_CLASS(klass); + browserWidgetClass->get_preferred_width = zeroPreferredSize; + browserWidgetClass->get_preferred_height = zeroPreferredSize; ++#endif +// Playwrigth end } @@ -21796,10 +20738,10 @@ index 1fd07efb828b85b6d8def6c6cd92a0c11debfe1b..da9fac7975d477857ead2adb1d67108d typedef struct _BrowserWindow BrowserWindow; diff --git a/Tools/MiniBrowser/gtk/main.c b/Tools/MiniBrowser/gtk/main.c -index 451e0333dd4e8f5d6313fa80c5027ef2661a61ac..7398af4772ed9a479b1632e38af2d4ee6c664754 100644 +index d3fbb968ee463f86c64fecb855b46c8634b4b72d..01dbbfbb93f2cfa6eb6440cce9794ec99b097c30 100644 --- a/Tools/MiniBrowser/gtk/main.c +++ b/Tools/MiniBrowser/gtk/main.c -@@ -75,7 +75,12 @@ static char* timeZone; +@@ -65,9 +65,14 @@ static char* timeZone; static gboolean enableITP; static gboolean exitAfterLoad; static gboolean webProcessCrashed; @@ -21808,14 +20750,16 @@ index 451e0333dd4e8f5d6313fa80c5027ef2661a61ac..7398af4772ed9a479b1632e38af2d4ee +static gboolean noStartupWindow; +static const char *userDataDir; static gboolean printVersion; + static char *configFile; + static GSettings *interfaceSettings; +static GtkApplication *browserApplication = NULL; #if !GTK_CHECK_VERSION(3, 98, 0) static gboolean enableSandbox; -@@ -179,6 +184,10 @@ static const GOptionEntry commandLineOptions[] = - { "exit-after-load", 0, 0, G_OPTION_ARG_NONE, &exitAfterLoad, "Quit the browser after the load finishes", NULL }, +@@ -172,6 +177,10 @@ static const GOptionEntry commandLineOptions[] = { "time-zone", 't', 0, G_OPTION_ARG_STRING, &timeZone, "Set time zone", "TIMEZONE" }, { "version", 'v', 0, G_OPTION_ARG_NONE, &printVersion, "Print the WebKitGTK version", NULL }, + { "config", 'C', 0, G_OPTION_ARG_FILENAME, &configFile, "Path to a configuration file", "PATH" }, + { "inspector-pipe", 0, 0, G_OPTION_ARG_NONE, &inspectorPipe, "Open pipe connection to the remote inspector", NULL }, + { "user-data-dir", 0, 0, G_OPTION_ARG_STRING, &userDataDir, "Default profile persistence folder location", NULL }, + { "headless", 0, 0, G_OPTION_ARG_NONE, &headless, "Noop headless operation", NULL }, @@ -21823,15 +20767,20 @@ index 451e0333dd4e8f5d6313fa80c5027ef2661a61ac..7398af4772ed9a479b1632e38af2d4ee { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &uriArguments, 0, "[URL…]" }, { 0, 0, 0, 0, 0, 0, 0 } }; -@@ -736,6 +745,57 @@ static void filterSavedCallback(WebKitUserContentFilterStore *store, GAsyncResul +@@ -729,6 +738,70 @@ static void filterSavedCallback(WebKitUserContentFilterStore *store, GAsyncResul g_main_loop_quit(data->mainLoop); } +static WebKitSettings* createPlaywrightSettings() { + WebKitSettings* webkitSettings = webkit_settings_new(); ++#if GTK_CHECK_VERSION(3, 98, 0) ++ // FIXME(Playwright): in GTK4, WEBKIT_HARDWARE_ACCELERATION_POLICY_ALWAYS is the default, but the page content is just black in that case. ++ webkit_settings_set_hardware_acceleration_policy(webkitSettings, WEBKIT_HARDWARE_ACCELERATION_POLICY_NEVER); ++#else + // Playwright: revert to the default state before https://github.com/WebKit/WebKit/commit/a73a25b9ea9229987c8fa7b2e092e6324cb17913 + webkit_settings_set_hardware_acceleration_policy(webkitSettings, WEBKIT_HARDWARE_ACCELERATION_POLICY_NEVER); + webkit_settings_set_hardware_acceleration_policy(webkitSettings, WEBKIT_HARDWARE_ACCELERATION_POLICY_ON_DEMAND); ++#endif + return webkitSettings; +} + @@ -21845,10 +20794,18 @@ index 451e0333dd4e8f5d6313fa80c5027ef2661a61ac..7398af4772ed9a479b1632e38af2d4ee + WebKitWebView *newWebView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW, + "web-context", context, + "settings", createPlaywrightSettings(), ++#if GTK_CHECK_VERSION(3, 98, 0) ++ "network-session", webkit_web_context_get_network_session_for_automation(context), ++#else + "is-ephemeral", webkit_web_context_is_ephemeral(context), ++#endif + "is-controlled-by-automation", TRUE, + NULL)); ++#if GTK_CHECK_VERSION(3, 98, 0) ++ GtkWidget *newWindow = browser_window_new(NULL, context, webkit_web_context_get_network_session_for_automation(context)); ++#else + GtkWidget *newWindow = browser_window_new(NULL, context); ++#endif + gtk_window_set_application(GTK_WINDOW(newWindow), browserApplication); + browser_window_append_view(BROWSER_WINDOW(newWindow), newWebView); + gtk_widget_grab_focus(GTK_WIDGET(newWebView)); @@ -21881,7 +20838,7 @@ index 451e0333dd4e8f5d6313fa80c5027ef2661a61ac..7398af4772ed9a479b1632e38af2d4ee static void startup(GApplication *application) { const char *actionAccels[] = { -@@ -766,6 +826,14 @@ static void startup(GApplication *application) +@@ -787,17 +860,30 @@ static void setupDarkMode(GtkSettings *settings) static void activate(GApplication *application, WebKitSettings *webkitSettings) { @@ -21896,7 +20853,36 @@ index 451e0333dd4e8f5d6313fa80c5027ef2661a61ac..7398af4772ed9a479b1632e38af2d4ee #if GTK_CHECK_VERSION(3, 98, 0) WebKitWebContext *webContext = g_object_new(WEBKIT_TYPE_WEB_CONTEXT, "time-zone-override", timeZone, NULL); webkit_web_context_set_automation_allowed(webContext, automationMode); -@@ -818,9 +886,12 @@ static void activate(GApplication *application, WebKitSettings *webkitSettings) + g_signal_connect(webContext, "automation-started", G_CALLBACK(automationStartedCallback), application); + + WebKitNetworkSession *networkSession; +- if (automationMode) +- networkSession = g_object_ref(webkit_web_context_get_network_session_for_automation(webContext)); +- else if (privateMode) ++ if (userDataDir) { ++ char *dataDirectory = g_build_filename(userDataDir, "data", NULL); ++ char *cacheDirectory = g_build_filename(userDataDir, "cache", NULL); ++ networkSession = webkit_network_session_new(dataDirectory, cacheDirectory); ++ g_free(dataDirectory); ++ g_free(cacheDirectory); ++ cookiesFile = g_build_filename(userDataDir, "cookies.txt", NULL); ++ } else if (inspectorPipe || privateMode || automationMode) { + networkSession = webkit_network_session_new_ephemeral(); +- else { ++ } else { + char *dataDirectory = g_build_filename(g_get_user_data_dir(), "webkitgtk-" WEBKITGTK_API_VERSION, "MiniBrowser", NULL); + char *cacheDirectory = g_build_filename(g_get_user_cache_dir(), "webkitgtk-" WEBKITGTK_API_VERSION, "MiniBrowser", NULL); + networkSession = webkit_network_session_new(dataDirectory, cacheDirectory); +@@ -805,6 +891,8 @@ static void activate(GApplication *application, WebKitSettings *webkitSettings) + g_free(cacheDirectory); + } + ++ webkit_web_context_set_network_session_for_automation(webContext, networkSession); ++ + webkit_network_session_set_itp_enabled(networkSession, enableITP); + + if (!automationMode) { +@@ -839,9 +927,12 @@ static void activate(GApplication *application, WebKitSettings *webkitSettings) } #else WebKitWebsiteDataManager *manager; @@ -21911,7 +20897,7 @@ index 451e0333dd4e8f5d6313fa80c5027ef2661a61ac..7398af4772ed9a479b1632e38af2d4ee char *dataDirectory = g_build_filename(g_get_user_data_dir(), "webkitgtk-" WEBKITGTK_API_VERSION, "MiniBrowser", NULL); char *cacheDirectory = g_build_filename(g_get_user_cache_dir(), "webkitgtk-" WEBKITGTK_API_VERSION, "MiniBrowser", NULL); manager = webkit_website_data_manager_new("base-data-directory", dataDirectory, "base-cache-directory", cacheDirectory, NULL); -@@ -871,6 +942,7 @@ static void activate(GApplication *application, WebKitSettings *webkitSettings) +@@ -891,6 +982,7 @@ static void activate(GApplication *application, WebKitSettings *webkitSettings) // Enable the favicon database. webkit_web_context_set_favicon_database_directory(webContext, NULL); #endif @@ -21919,7 +20905,7 @@ index 451e0333dd4e8f5d6313fa80c5027ef2661a61ac..7398af4772ed9a479b1632e38af2d4ee webkit_web_context_register_uri_scheme(webContext, BROWSER_ABOUT_SCHEME, (WebKitURISchemeRequestCallback)aboutURISchemeRequestCallback, NULL, NULL); -@@ -941,9 +1013,7 @@ static void activate(GApplication *application, WebKitSettings *webkitSettings) +@@ -955,9 +1047,7 @@ static void activate(GApplication *application, WebKitSettings *webkitSettings) if (exitAfterLoad) exitAfterWebViewLoadFinishes(webView, application); } @@ -21930,7 +20916,7 @@ index 451e0333dd4e8f5d6313fa80c5027ef2661a61ac..7398af4772ed9a479b1632e38af2d4ee } } else { WebKitWebView *webView = createBrowserTab(mainWindow, webkitSettings, userContentManager, defaultWebsitePolicies); -@@ -993,7 +1063,7 @@ int main(int argc, char *argv[]) +@@ -1007,7 +1097,7 @@ int main(int argc, char *argv[]) g_option_context_add_group(context, gst_init_get_option_group()); #endif @@ -21939,7 +20925,7 @@ index 451e0333dd4e8f5d6313fa80c5027ef2661a61ac..7398af4772ed9a479b1632e38af2d4ee webkit_settings_set_enable_developer_extras(webkitSettings, TRUE); webkit_settings_set_enable_webgl(webkitSettings, TRUE); webkit_settings_set_enable_media_stream(webkitSettings, TRUE); -@@ -1025,9 +1095,11 @@ int main(int argc, char *argv[]) +@@ -1059,9 +1149,11 @@ int main(int argc, char *argv[]) } GtkApplication *application = gtk_application_new("org.webkitgtk.MiniBrowser", G_APPLICATION_NON_UNIQUE); @@ -21950,12 +20936,12 @@ index 451e0333dd4e8f5d6313fa80c5027ef2661a61ac..7398af4772ed9a479b1632e38af2d4ee + browserApplication = NULL; g_object_unref(application); - return exitAfterLoad && webProcessCrashed ? 1 : 0; + g_clear_object(&interfaceSettings); diff --git a/Tools/MiniBrowser/wpe/main.cpp b/Tools/MiniBrowser/wpe/main.cpp -index 3c2476471ef67299da6312d0f995fc0738aa96c9..b13ab78bfe62c8c2cdd052e24255a780bbc2afa3 100644 +index 6a898a5bd79a4e6f2f26be7f63347cef7a5c0ab4..d895941dab0f7a0bdfafcf60f203aa82c46874a6 100644 --- a/Tools/MiniBrowser/wpe/main.cpp +++ b/Tools/MiniBrowser/wpe/main.cpp -@@ -45,6 +45,9 @@ static gboolean headlessMode; +@@ -52,6 +52,9 @@ static gboolean headlessMode; static gboolean privateMode; static gboolean automationMode; static gboolean ignoreTLSErrors; @@ -21965,9 +20951,9 @@ index 3c2476471ef67299da6312d0f995fc0738aa96c9..b13ab78bfe62c8c2cdd052e24255a780 static const char* contentFilter; static const char* cookiesFile; static const char* cookiesPolicy; -@@ -78,6 +81,9 @@ static const GOptionEntry commandLineOptions[] = - { "use-wpe-platform-api", 0, 0, G_OPTION_ARG_NONE, &useWPEPlatformAPI, "Use the WPE platform API", nullptr }, +@@ -130,6 +133,9 @@ static const GOptionEntry commandLineOptions[] = #endif + { "size", 's', 0, G_OPTION_ARG_CALLBACK, reinterpret_cast(parseWindowSize), "Specify the window size to use, e.g. --size=\"800x600\"", nullptr }, { "version", 'v', 0, G_OPTION_ARG_NONE, &printVersion, "Print the WPE version", nullptr }, + { "inspector-pipe", 'v', 0, G_OPTION_ARG_NONE, &inspectorPipe, "Expose remote debugging protocol over pipe", nullptr }, + { "user-data-dir", 0, 0, G_OPTION_ARG_STRING, &userDataDir, "Default profile persistence folder location", "FILE" }, @@ -21975,7 +20961,7 @@ index 3c2476471ef67299da6312d0f995fc0738aa96c9..b13ab78bfe62c8c2cdd052e24255a780 { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &uriArguments, nullptr, "[URL]" }, { nullptr, 0, 0, G_OPTION_ARG_NONE, nullptr, nullptr, nullptr } }; -@@ -220,15 +226,38 @@ static void filterSavedCallback(WebKitUserContentFilterStore *store, GAsyncResul +@@ -288,15 +294,38 @@ static void filterSavedCallback(WebKitUserContentFilterStore *store, GAsyncResul g_main_loop_quit(data->mainLoop); } @@ -22014,9 +21000,9 @@ index 3c2476471ef67299da6312d0f995fc0738aa96c9..b13ab78bfe62c8c2cdd052e24255a780 + +static WebKitWebView* createWebViewImpl(WebKitWebView* webView, WebKitWebContext *webContext, gpointer user_data) { - - auto backend = createViewBackend(1280, 720); -@@ -244,18 +273,37 @@ static WebKitWebView* createWebView(WebKitWebView* webView, WebKitNavigationActi + auto backend = createViewBackend(defaultWindowWidthLegacyAPI, defaultWindowHeightLegacyAPI); + WebKitWebViewBackend* viewBackend = nullptr; +@@ -311,12 +340,27 @@ static WebKitWebView* createWebView(WebKitWebView* webView, WebKitNavigationActi }, backend.release()); } @@ -22048,27 +21034,50 @@ index 3c2476471ef67299da6312d0f995fc0738aa96c9..b13ab78bfe62c8c2cdd052e24255a780 + nullptr)); + } + #if ENABLE_WPE_PLATFORM + if (auto* wpeView = webkit_web_view_get_wpe_view(newWebView)) { +@@ -328,9 +372,13 @@ static WebKitWebView* createWebView(WebKitWebView* webView, WebKitNavigationActi + g_signal_connect(newWebView, "create", G_CALLBACK(createWebView), user_data); g_signal_connect(newWebView, "close", G_CALLBACK(webViewClose), user_data); - - g_hash_table_add(openViews, newWebView); - +- ++// Playwright begin + g_signal_connect(newWebView, "load-failed", G_CALLBACK(webViewLoadFailed), nullptr); + g_signal_connect(newWebView, "script-dialog", G_CALLBACK(scriptDialog), nullptr); + g_signal_connect(newWebView, "script-dialog-handled", G_CALLBACK(scriptDialogHandled), nullptr); + g_signal_connect(newWebView, "decide-policy", G_CALLBACK(webViewDecidePolicy), nullptr); ++// Playwright end + g_hash_table_add(openViews, newWebView); +- return newWebView; } -@@ -269,13 +317,89 @@ static WebKitFeature* findFeature(WebKitFeatureList* featureList, const char* id - return nullptr; +@@ -418,13 +466,105 @@ void loadConfigFile(WPESettings* settings) } + #endif +static WebKitWebView* createWebView(WebKitWebView* webView, WebKitNavigationAction*, gpointer user_data) +{ + return createWebViewImpl(webView, nullptr, user_data); +} + ++inline bool response_policy_decision_can_show(WebKitResponsePolicyDecision* responseDecision) ++{ ++ if (webkit_response_policy_decision_is_mime_type_supported(responseDecision)) ++ return true; ++ auto response = webkit_response_policy_decision_get_response(responseDecision); ++ const auto statusCode = webkit_uri_response_get_status_code(response); ++ if (statusCode == 205 || statusCode == 204) ++ return true; ++ const gchar* mimeType = webkit_uri_response_get_mime_type(response); ++ if (!mimeType || mimeType[0] == '\0') ++ return false; ++ // https://bugs.webkit.org/show_bug.cgi?id=277204 / Ubuntu 24.04 / glib 2.76+ or higher ++ if (g_ascii_strcasecmp(mimeType, "application/x-zerosize") == 0) ++ return true; ++ return false; ++} ++ +static gboolean webViewDecidePolicy(WebKitWebView *webView, WebKitPolicyDecision *decision, WebKitPolicyDecisionType decisionType, gpointer user_data) +{ + if (decisionType == WEBKIT_POLICY_DECISION_TYPE_RESPONSE) { @@ -22076,8 +21085,7 @@ index 3c2476471ef67299da6312d0f995fc0738aa96c9..b13ab78bfe62c8c2cdd052e24255a780 + if (!webkit_response_policy_decision_is_main_frame_main_resource(responseDecision)) + return FALSE; + -+ const gchar* mimeType = webkit_uri_response_get_mime_type(webkit_response_policy_decision_get_response(responseDecision)); -+ if (!webkit_response_policy_decision_is_mime_type_supported(responseDecision) && mimeType && mimeType[0] != '\0') { ++ if (!response_policy_decision_can_show(responseDecision)) { + webkit_policy_decision_download(decision); + return TRUE; + } @@ -22117,7 +21125,7 @@ index 3c2476471ef67299da6312d0f995fc0738aa96c9..b13ab78bfe62c8c2cdd052e24255a780 + return webView; +} + -+static void quitBroserApplication(WebKitBrowserInspector* browser_inspector, gpointer data) ++static void quitBroserApplication(WebKitBrowserInspector*, gpointer data) +{ + GApplication* application = static_cast(data); + g_application_quit(application); @@ -22151,7 +21159,7 @@ index 3c2476471ef67299da6312d0f995fc0738aa96c9..b13ab78bfe62c8c2cdd052e24255a780 webkit_network_session_set_itp_enabled(networkSession, enableITP); if (proxy) { -@@ -302,10 +426,18 @@ static void activate(GApplication* application, WPEToolingBackends::ViewBackend* +@@ -451,10 +591,18 @@ static void activate(GApplication* application, WPEToolingBackends::ViewBackend* webkit_cookie_manager_set_persistent_storage(cookieManager, cookiesFile, storageType); } } @@ -22172,7 +21180,7 @@ index 3c2476471ef67299da6312d0f995fc0738aa96c9..b13ab78bfe62c8c2cdd052e24255a780 webkit_website_data_manager_set_itp_enabled(manager, enableITP); if (proxy) { -@@ -336,6 +468,7 @@ static void activate(GApplication* application, WPEToolingBackends::ViewBackend* +@@ -485,6 +633,7 @@ static void activate(GApplication* application, WPEToolingBackends::ViewBackend* } #endif @@ -22180,7 +21188,7 @@ index 3c2476471ef67299da6312d0f995fc0738aa96c9..b13ab78bfe62c8c2cdd052e24255a780 WebKitUserContentManager* userContentManager = nullptr; if (contentFilter) { GFile* contentFilterFile = g_file_new_for_commandline_arg(contentFilter); -@@ -408,6 +541,15 @@ static void activate(GApplication* application, WPEToolingBackends::ViewBackend* +@@ -563,6 +712,15 @@ static void activate(GApplication* application, WPEToolingBackends::ViewBackend* "autoplay", WEBKIT_AUTOPLAY_ALLOW, nullptr); @@ -22196,16 +21204,26 @@ index 3c2476471ef67299da6312d0f995fc0738aa96c9..b13ab78bfe62c8c2cdd052e24255a780 auto* webView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW, "backend", viewBackend, "web-context", webContext, -@@ -436,8 +578,6 @@ static void activate(GApplication* application, WPEToolingBackends::ViewBackend* - g_signal_connect(wpeView, "event", G_CALLBACK(wpeViewEventCallback), webView); +@@ -609,12 +767,16 @@ static void activate(GApplication* application, WPEToolingBackends::ViewBackend* + } #endif - openViews = g_hash_table_new_full(nullptr, nullptr, g_object_unref, nullptr); - - webkit_web_context_set_automation_allowed(webContext, automationMode); g_signal_connect(webContext, "automation-started", G_CALLBACK(automationStartedCallback), webView); g_signal_connect(webView, "permission-request", G_CALLBACK(decidePermissionRequest), nullptr); -@@ -450,16 +590,9 @@ static void activate(GApplication* application, WPEToolingBackends::ViewBackend* + g_signal_connect(webView, "create", G_CALLBACK(createWebView), application); + g_signal_connect(webView, "close", G_CALLBACK(webViewClose), application); ++// Playwright begin ++ g_signal_connect(webView, "load-failed", G_CALLBACK(webViewLoadFailed), nullptr); ++ g_signal_connect(webView, "script-dialog", G_CALLBACK(scriptDialog), nullptr); ++ g_signal_connect(webView, "script-dialog-handled", G_CALLBACK(scriptDialogHandled), nullptr); ++ g_signal_connect(webView, "decide-policy", G_CALLBACK(webViewDecidePolicy), nullptr); ++// Playwright end + g_hash_table_add(openViews, webView); + + WebKitColor color; +@@ -622,16 +784,11 @@ static void activate(GApplication* application, WPEToolingBackends::ViewBackend* webkit_web_view_set_background_color(webView, &color); if (uriArguments) { @@ -22218,14 +21236,16 @@ index 3c2476471ef67299da6312d0f995fc0738aa96c9..b13ab78bfe62c8c2cdd052e24255a780 - g_object_unref(file); - webkit_web_view_load_uri(webView, url); - g_free(url); -- } else if (automationMode) +- } else if (!automationMode) + // Playwright: avoid weird url transformation like http://trac.webkit.org/r240840 + webkit_web_view_load_uri(webView, uriArguments[0]); + } else if (automationMode || inspectorPipe) - webkit_web_view_load_uri(webView, "about:blank"); - else ++ webkit_web_view_load_uri(webView, "about:blank"); ++ else webkit_web_view_load_uri(webView, "https://wpewebkit.org"); -@@ -533,8 +666,14 @@ int main(int argc, char *argv[]) + + g_object_unref(webContext); +@@ -728,8 +885,14 @@ int main(int argc, char *argv[]) } } @@ -22253,10 +21273,10 @@ index 1067b31bc989748dfcc5502209d36d001b9b239e..7629263fb8bc93dca6dfc01c75eed8d2 + add_subdirectory(Playwright/win) +endif () diff --git a/Tools/Scripts/build-webkit b/Tools/Scripts/build-webkit -index 39c351abbdd7b1b7f7016c5fd071ec2ae59b4a42..dc804e1d5284b15da6fa0679932d6cca8ece499a 100755 +index fcbf4620e66e0a49396fb650f2da1fad43e8a6fc..7c38c04e082313cbd7513ba8b5626f377f6850d4 100755 --- a/Tools/Scripts/build-webkit +++ b/Tools/Scripts/build-webkit -@@ -273,7 +273,7 @@ if (isAppleCocoaWebKit()) { +@@ -278,7 +278,7 @@ if (isAppleCocoaWebKit()) { push @projects, ("Source/WebKit"); if (!isEmbeddedWebKit()) { @@ -22281,24 +21301,32 @@ index 9e53f459e444b9c10fc5248f0e8059df6c1e0041..c17c875a7dd3ca05c4489578ab32378b "${WebKitTestRunner_DIR}/InjectedBundle/Bindings/AccessibilityController.idl" "${WebKitTestRunner_DIR}/InjectedBundle/Bindings/AccessibilityTextMarker.idl" diff --git a/Tools/WebKitTestRunner/TestController.cpp b/Tools/WebKitTestRunner/TestController.cpp -index 244cfc247fa50bf073ba523913543cab0c6f1b3b..d1cd4657f513d1be167f8d1176dc1217f57acbbd 100644 +index ee6c2488fd655c40d250b405a82358e81e2661f6..5b9baf3c2ee0e9bb28fd765c7fdacb3a70f9ef36 100644 --- a/Tools/WebKitTestRunner/TestController.cpp +++ b/Tools/WebKitTestRunner/TestController.cpp -@@ -964,6 +964,7 @@ void TestController::createWebViewWithOptions(const TestOptions& options) - 0, // requestStorageAccessConfirm +@@ -713,6 +713,7 @@ PlatformWebView* TestController::createOtherPlatformWebView(PlatformWebView* par + nullptr, // requestStorageAccessConfirm + nullptr, // shouldAllowDeviceOrientationAndMotionAccess + nullptr, // runWebAuthenticationPanel ++ 0, // handleJavaScriptDialog + nullptr, // decidePolicyForSpeechRecognitionPermissionRequest + nullptr, // decidePolicyForMediaKeySystemPermissionRequest + nullptr, // queryPermission +@@ -1188,6 +1189,7 @@ void TestController::createWebViewWithOptions(const TestOptions& options) + nullptr, // requestStorageAccessConfirm shouldAllowDeviceOrientationAndMotionAccess, runWebAuthenticationPanel, + 0, // handleJavaScriptDialog - 0, + nullptr, // decidePolicyForSpeechRecognitionPermissionRequest decidePolicyForMediaKeySystemPermissionRequest, queryPermission, diff --git a/Tools/WebKitTestRunner/mac/EventSenderProxy.mm b/Tools/WebKitTestRunner/mac/EventSenderProxy.mm -index c7c925b66ea04d8f7a44fb7410ad45acb74f022f..b4738697e5ecb5c947d2bc1864a0f3907d9a3795 100644 +index 9419696018c076d0e5b4ef04ea7c58be9504cd96..06c537e3c022517449068a11ea59400413e8f4dc 100644 --- a/Tools/WebKitTestRunner/mac/EventSenderProxy.mm +++ b/Tools/WebKitTestRunner/mac/EventSenderProxy.mm -@@ -950,4 +950,51 @@ void EventSenderProxy::scaleGestureEnd(double scale) - - #endif // ENABLE(MAC_GESTURE_EVENTS) +@@ -961,4 +961,51 @@ void EventSenderProxy::waitForPendingMouseEvents() + } + } +#if ENABLE(TOUCH_EVENTS) +void EventSenderProxy::addTouchPoint(int, int) @@ -22348,117 +21376,56 @@ index c7c925b66ea04d8f7a44fb7410ad45acb74f022f..b4738697e5ecb5c947d2bc1864a0f390 + + } // namespace WTR -diff --git a/Tools/glib/dependencies/apt b/Tools/glib/dependencies/apt -index 7ae5cb94f966df2b730fc54489abf1d8174ed390..c1baaeb0a411ad80d9f6771bd8a3811c4d71d337 100644 ---- a/Tools/glib/dependencies/apt -+++ b/Tools/glib/dependencies/apt -@@ -1,11 +1,11 @@ - #!/usr/bin/env bash - --# If the package $1 is available, prints it. Otherwise prints $2. -+# If the package $1 is available, prints it. Otherwise if package $2 is available, prints $2. - # Useful for handling when a package is renamed on new versions of Debian/Ubuntu. - aptIfElse() { - if apt-cache show $1 &>/dev/null; then - echo $1 -- else -+ elif apt-cache show $2 &>/dev/null; then - echo $2 - fi - } -@@ -71,10 +71,12 @@ PACKAGES=( - $(aptIfExists libwpe-1.0-dev) - $(aptIfExists libwpebackend-fdo-1.0-dev) - libxml2-utils -+ libxcb-glx0-dev - libxslt1-dev - mesa-common-dev - ninja-build - patch -+ patchelf - ruby - - # These are dependencies necessary for running tests. -diff --git a/Tools/gtk/dependencies/apt b/Tools/gtk/dependencies/apt -index 1e2a9202f88c63afa6525d97d0f945438f5f2032..e6cdee08aff723eb5c6b16491051ca39dfee3f5b 100644 ---- a/Tools/gtk/dependencies/apt -+++ b/Tools/gtk/dependencies/apt -@@ -33,6 +33,9 @@ PACKAGES+=( - libxtst-dev - unifdef - xfonts-utils -+ $(aptIfElse libenchant-dev libenchant-2-dev) -+ $(aptIfExists libwpe-1.0-dev) -+ $(aptIfExists libwpebackend-fdo-1.0-dev) - - # These are dependencies necessary for running tests. - cups-daemon -diff --git a/Tools/gtk/jhbuild.modules b/Tools/gtk/jhbuild.modules -index 5453eb855928744d58e459f8a986535825dc29a0..b7d9568aef262d8e2825569b021ea0f5d0923ba0 100644 ---- a/Tools/gtk/jhbuild.modules -+++ b/Tools/gtk/jhbuild.modules -@@ -252,10 +252,10 @@ - - - -- -+ hash="sha256:83673c685b910fb7d39f1f28eee5afbefb71c05798fc350ac3bf1b885e1efaa1"> - - - diff --git a/Tools/jhbuild/jhbuild-minimal.modules b/Tools/jhbuild/jhbuild-minimal.modules -index fe58a444522de94d8f2a57c538a8e7bca93e5c74..78fd69a2a98cb0a826cba13f95c3f419b4376045 100644 +index 3a0b7425900b14ce2aa0d48aa914cd69bff1f332..0ce07cc1368c6f521b51d6300dca9c4d078beef3 100644 --- a/Tools/jhbuild/jhbuild-minimal.modules +++ b/Tools/jhbuild/jhbuild-minimal.modules -@@ -32,7 +32,6 @@ - - - -- - - - -@@ -132,10 +131,10 @@ - - +@@ -67,8 +67,8 @@ + + ++ version="1.16.0" ++ hash="sha256:c7f3a3c6b3d006790d486dc7cceda2b6d2e329de07f33bc47dfc53f00f334b2a"/> + + + +@@ -77,8 +77,8 @@ -- -+ hash="sha256:83673c685b910fb7d39f1f28eee5afbefb71c05798fc350ac3bf1b885e1efaa1"> + ++ version="1.14.3" ++ hash="sha256:10121842595a850291db3e82f3db0b9984df079022d386ce42c2b8508159dc6c"> -@@ -231,6 +230,16 @@ +@@ -186,7 +186,6 @@ + + + +- libsoup-3.0.pc + + + +@@ -194,8 +193,8 @@ + -+ -+ -+ libdrm.pc -+ -+ -+ - - - - -+ - - - -@@ -102,10 +103,10 @@ - - - -- -+ hash="sha256:83673c685b910fb7d39f1f28eee5afbefb71c05798fc350ac3bf1b885e1efaa1"> - - - -@@ -334,6 +335,16 @@ - hash="sha256:c625a83b4838befc8cafcd54e3619946515d9e44d63d61c4adf7f5513ddfbebf"/> - - -+ -+ -+ libdrm.pc -+ -+ -+ - - - ## Disclaimer Automated accessibility tests can detect some common accessibility problems such as missing or invalid properties. But many accessibility problems can only be discovered through manual testing. We recommend using a combination of automated testing, manual accessibility assessments, and inclusive user testing. @@ -72,22 +70,24 @@ For example, you can use [`AxeBuilder.include()`](https://github.com/dequelabs/a `AxeBuilder.analyze()` will scan the page *in its current state* when you call it. To scan parts of a page that are revealed based on UI interactions, use [Locators](./locators.md) to interact with the page before invoking `analyze()`: ```java -@Test -void navigationMenuFlyoutShouldNotHaveAutomaticallyDetectableAccessibilityViolations() throws Exception { - page.navigate("https://your-site.com/"); +public class HomepageTests { + @Test + void navigationMenuFlyoutShouldNotHaveAutomaticallyDetectableAccessibilityViolations() throws Exception { + page.navigate("https://your-site.com/"); - page.locator("button[aria-label=\"Navigation Menu\"]").click(); + page.locator("button[aria-label=\"Navigation Menu\"]").click(); - // It is important to waitFor() the page to be in the desired - // state *before* running analyze(). Otherwise, axe might not - // find all the elements your test expects it to scan. - page.locator("#navigation-menu-flyout").waitFor(); + // It is important to waitFor() the page to be in the desired + // state *before* running analyze(). Otherwise, axe might not + // find all the elements your test expects it to scan. + page.locator("#navigation-menu-flyout").waitFor(); - AxeResults accessibilityScanResults = new AxeBuilder(page) - .include(Arrays.asList("#navigation-menu-flyout")) - .analyze(); + AxeResults accessibilityScanResults = new AxeBuilder(page) + .include(Arrays.asList("#navigation-menu-flyout")) + .analyze(); - assertEquals(Collections.emptyList(), accessibilityScanResults.getViolations()); + assertEquals(Collections.emptyList(), accessibilityScanResults.getViolations()); + } } ``` @@ -107,7 +107,7 @@ AxeResults accessibilityScanResults = new AxeBuilder(page) assertEquals(Collections.emptyList(), accessibilityScanResults.getViolations()); ``` -You can find a complete listing of the rule tags axe-core supports in [the "Axe-core Tags" section of the axe API documentation](https://www.deque.com/axe/core-documentation/api-documentation/#axe-core-tags). +You can find a complete listing of the rule tags axe-core supports in [the "Axe-core Tags" section of the axe API documentation](https://www.deque.com/axe/core-documentation/api-documentation/#axecore-tags). ## Handling known issues @@ -160,38 +160,40 @@ This approach avoids the downsides of using `AxeBuilder.exclude()` at the cost o Here is an example of using fingerprints based on only rule IDs and "target" selectors pointing to each violation: ```java -@Test -shouldOnlyHaveAccessibilityViolationsMatchingKnownFingerprints() throws Exception { - page.navigate("https://your-site.com/"); +public class HomepageTests { + @Test + shouldOnlyHaveAccessibilityViolationsMatchingKnownFingerprints() throws Exception { + page.navigate("https://your-site.com/"); - AxeResults accessibilityScanResults = new AxeBuilder(page).analyze(); + AxeResults accessibilityScanResults = new AxeBuilder(page).analyze(); - List violationFingerprints = fingerprintsFromScanResults(accessibilityScanResults); + List violationFingerprints = fingerprintsFromScanResults(accessibilityScanResults); - assertEquals(Arrays.asList( - new ViolationFingerprint("aria-roles", "[span[role=\"invalid\"]]"), - new ViolationFingerprint("color-contrast", "[li:nth-child(2) > span]"), - new ViolationFingerprint("label", "[input]") - ), violationFingerprints); -} + assertEquals(Arrays.asList( + new ViolationFingerprint("aria-roles", "[span[role=\"invalid\"]]"), + new ViolationFingerprint("color-contrast", "[li:nth-child(2) > span]"), + new ViolationFingerprint("label", "[input]") + ), violationFingerprints); + } -// You can make your "fingerprint" as specific as you like. This one considers a violation to be -// "the same" if it corresponds the same Axe rule on the same element. -// -// Using a record type makes it easy to compare fingerprints with assertEquals -public record ViolationFingerprint(String ruleId, String target) { } - -public List fingerprintsFromScanResults(AxeResults results) { - return results.getViolations().stream() - // Each violation refers to one rule and multiple "nodes" which violate it - .flatMap(violation -> violation.getNodes().stream() - .map(node -> new ViolationFingerprint( - violation.getId(), - // Each node contains a "target", which is a CSS selector that uniquely identifies it - // If the page involves iframes or shadow DOMs, it may be a chain of CSS selectors - node.getTarget().toString() - ))) - .collect(Collectors.toList()); + // You can make your "fingerprint" as specific as you like. This one considers a violation to be + // "the same" if it corresponds the same Axe rule on the same element. + // + // Using a record type makes it easy to compare fingerprints with assertEquals + public record ViolationFingerprint(String ruleId, String target) { } + + public List fingerprintsFromScanResults(AxeResults results) { + return results.getViolations().stream() + // Each violation refers to one rule and multiple "nodes" which violate it + .flatMap(violation -> violation.getNodes().stream() + .map(node -> new ViolationFingerprint( + violation.getId(), + // Each node contains a "target", which is a CSS selector that uniquely identifies it + // If the page involves iframes or shadow DOMs, it may be a chain of CSS selectors + node.getTarget().toString() + ))) + .collect(Collectors.toList()); + } } ``` @@ -210,11 +212,11 @@ This example fixture creates an `AxeBuilder` object which is pre-configured with ```java class AxeTestFixtures extends TestFixtures { - AxeBuilder makeAxeBuilder() { - return new AxeBuilder(page) - .withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa']) - .exclude('#commonly-reused-element-with-known-issue'); - } + AxeBuilder makeAxeBuilder() { + return new AxeBuilder(page) + .withTags(new String[]{"wcag2a", "wcag2aa", "wcag21a", "wcag21aa"}) + .exclude("#commonly-reused-element-with-known-issue"); + } } ``` @@ -231,7 +233,7 @@ public class HomepageTests extends AxeTestFixtures { AxeResults accessibilityScanResults = makeAxeBuilder() // Automatically uses the shared AxeBuilder configuration, // but supports additional test-specific configuration too - .include('#specific-element-under-test') + .include("#specific-element-under-test") .analyze(); assertEquals(Collections.emptyList(), accessibilityScanResults.getViolations()); diff --git a/docs/src/accessibility-testing-js.md b/docs/src/accessibility-testing-js.md index 65db5ae55cef8..f547e8850642f 100644 --- a/docs/src/accessibility-testing-js.md +++ b/docs/src/accessibility-testing-js.md @@ -113,7 +113,7 @@ test('should not have any automatically detectable WCAG A or AA violations', asy }); ``` -You can find a complete listing of the rule tags axe-core supports in [the "Axe-core Tags" section of the axe API documentation](https://www.deque.com/axe/core-documentation/api-documentation/#axe-core-tags). +You can find a complete listing of the rule tags axe-core supports in [the "Axe-core Tags" section of the axe API documentation](https://www.deque.com/axe/core-documentation/api-documentation/#axecore-tags). ## Handling known issues @@ -244,7 +244,7 @@ type AxeFixture = { // This new "test" can be used in multiple test files, and each of them will get // a consistently configured AxeBuilder instance. export const test = base.extend({ - makeAxeBuilder: async ({ page }, use, testInfo) => { + makeAxeBuilder: async ({ page }, use) => { const makeAxeBuilder = () => new AxeBuilder({ page }) .withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa']) .exclude('#commonly-reused-element-with-known-issue'); @@ -255,8 +255,7 @@ export const test = base.extend({ export { expect } from '@playwright/test'; ``` -```js tab=js-js -// axe-test.js +```js tab=js-js title="axe-test.js" const base = require('@playwright/test'); const AxeBuilder = require('@axe-core/playwright').default; @@ -265,7 +264,7 @@ const AxeBuilder = require('@axe-core/playwright').default; // This new "test" can be used in multiple test files, and each of them will get // a consistently configured AxeBuilder instance. exports.test = base.test.extend({ - makeAxeBuilder: async ({ page }, use, testInfo) => { + makeAxeBuilder: async ({ page }, use) => { const makeAxeBuilder = () => new AxeBuilder({ page }) .withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa']) .exclude('#commonly-reused-element-with-known-issue'); diff --git a/docs/src/actionability.md b/docs/src/actionability.md index 4a84f5f5b2bbf..3510171e5c328 100644 --- a/docs/src/actionability.md +++ b/docs/src/actionability.md @@ -93,11 +93,20 @@ Element is considered stable when it has maintained the same bounding box for at ## Enabled -Element is considered enabled unless it is a ``); - expect(await generate(page, 'span')).toBe('internal:role=button[name="text"i]'); + expect(await generate(page, 'span', 'button')).toBe('internal:role=button[name="text"i]'); }); it('should prefer role=button over inner span', async ({ page }) => { await page.setContent(`
text
`); - expect(await generate(page, 'span')).toBe('internal:role=button[name="text"i]'); + expect(await generate(page, 'span', 'div')).toBe('internal:role=button[name="text"i]'); }); it('should not prefer zero-sized button over inner span', async ({ page }) => { @@ -58,7 +69,7 @@ it.describe('selector generator', () => { it('should not escape spaces inside named attr selectors', async ({ page }) => { await page.setContent(``); - expect(await generate(page, 'input')).toBe('internal:attr=[placeholder=\"Foo b ar\"i]'); + expect(await generate(page, 'input')).toBe('internal:role=textbox[name=\"Foo b ar\"i]'); }); it('should generate text for ', async ({ page }) => { @@ -91,7 +102,7 @@ it.describe('selector generator', () => { it('should try to improve label text by shortening', async ({ page }) => { await page.setContent(``); - expect(await generate(page, 'input')).toBe('internal:label="Longest verbose description"i'); + expect(await generate(page, 'input')).toBe('internal:role=textbox[name=\"Longest verbose description\"i]'); }); it('should not improve guid text', async ({ page }) => { @@ -132,9 +143,8 @@ it.describe('selector generator', () => { expect(await generate(page, '[data-testid="a"]')).toBe('internal:testid=[data-testid=\"a\"s]'); }); - it('should use data-testid in strict errors', async ({ page, playwright }) => { - playwright.selectors.setTestIdAttribute('data-custom-id'); - await page.setContent(` + it('should use data-testid in strict errors', async ({ contextFactory, page, playwright }) => { + const content = `
@@ -147,13 +157,27 @@ it.describe('selector generator', () => {
-
`); - const error = await page.locator('.foo').hover().catch(e => e); - expect(error.message).toContain('strict mode violation'); - expect(error.message).toContain('
+ `; + + const checkPage = async (page: Page) => { + await page.setContent(content); + const error = await page.locator('.foo').hover().catch(e => e); + expect(error.message).toContain('strict mode violation'); + expect(error.message).toContain('
{ @@ -279,6 +303,24 @@ it.describe('selector generator', () => { expect(await generate(page, 'c[mark="1"]')).toBe('b:nth-child(2) > c'); }); + it('should prefer class to ordinal', async ({ page }) => { + await page.setContent(` +
+
+ + + + + + + +
+
+ `); + await page.$eval('[mark="1"]', c => c.parentElement.className = 'foo 12.bar.baz[&x]-_?"\''); + expect(await generate(page, 'c[mark="1"]')).toBe(`.foo.\\31 2\\.bar\\.baz\\[\\&x\\]-_\\?\\"\\' > c`); + }); + it('should properly join child selectors under nested ordinals', async ({ page }) => { await page.setContent(`
@@ -309,14 +351,14 @@ it.describe('selector generator', () => { expect(await generate(page, 'input[mark="1"]')).toBe('internal:role=textbox >> nth=1'); }); - it.describe('should prioritise attributes correctly', () => { + it.describe('should prioritize attributes correctly', () => { it('role', async ({ page }) => { await page.setContent(``); expect(await generate(page, 'input')).toBe('internal:role=textbox'); }); it('placeholder', async ({ page }) => { await page.setContent(``); - expect(await generate(page, 'input')).toBe('internal:attr=[placeholder=\"foobar\"i]'); + expect(await generate(page, 'input')).toBe('internal:role=textbox[name=\"foobar\"i]'); }); it('name', async ({ page }) => { await page.setContent(` @@ -406,19 +448,18 @@ it.describe('selector generator', () => { it('should work with tricky attributes', async ({ page }) => { await page.setContent(``); - expect(await generate(page, 'button')).toBe('[id="this\\:is-my-tricky\\.id"]'); + expect(await generate(page, 'button')).toBe('[id="this:is-my-tricky.id"]'); await page.setContent(``); expect(await generate(page, 'ng\\:switch')).toBe('ng\\:switch'); await page.setContent(``); - await page.$eval('span', span => span.textContent = `!#'!?:`); - expect(await generate(page, 'button')).toBe(`internal:role=button[name="!#'!?:"i]`); - expect(await page.$(`role=button[name="!#'!?:"]`)).toBeTruthy(); + await page.$eval('span', span => span.textContent = `!#'!?"\\:`); + expect(await generate(page, 'button')).toBe(`internal:role=button[name="!#'!?\\"\\\\:"i]`); await page.setContent(`
`); - await page.$eval('div', div => div.id = `!#'!?:`); - expect(await generate(page, 'div')).toBe("[id=\"\\!\\#\\'\\!\\?\\:\"]"); + await page.$eval('div', div => div.id = `!#'!?"\\:`); + expect(await generate(page, 'div')).toBe(`[id="!#'!?\\"\\\\:"]`); }); it('should work without CSS.escape', async ({ page }) => { @@ -427,7 +468,12 @@ it.describe('selector generator', () => { delete window.CSS.escape; button.setAttribute('name', '-tricky\u0001name'); }); - expect(await generate(page, 'button')).toBe(`button[name="-tricky\\1 name"]`); + expect(await generate(page, 'button')).toBe(`button[name="-tricky\u0001name"]`); + }); + + it('should not over-escape for CSS syntax', async ({ page }) => { + await page.setContent(`
`); + expect(await generate(page, 'button')).toBe(`button[name="123"]`); }); it('should ignore empty aria-label for candidate consideration', async ({ page }) => { @@ -437,7 +483,7 @@ it.describe('selector generator', () => { it('should accept valid aria-label for candidate consideration', async ({ page }) => { await page.setContent(``); - expect(await generate(page, 'button')).toBe('internal:label="ariaLabel"i'); + expect(await generate(page, 'button')).toBe('internal:role=button[name=\"ariaLabel\"i]'); }); it('should ignore empty role for candidate consideration', async ({ page }) => { @@ -469,15 +515,15 @@ it.describe('selector generator', () => {
text
`); - expect(await generate(page, '#target1')).toBe('internal:label="Target1"i'); - expect(await generate(page, '#target2')).toBe('internal:label="Target2"i'); - expect(await generate(page, '#target3')).toBe('internal:label="Target3"i'); - expect(await generate(page, '#target4')).toBe('internal:label="Target4"i'); - expect(await generate(page, '#target5')).toBe('#target5'); - expect(await generate(page, '#target6')).toBe('internal:text="text"i'); + expect.soft(await generate(page, '#target1')).toBe('internal:role=textbox[name=\"Target1\"i]'); + expect.soft(await generate(page, '#target2')).toBe('internal:role=button[name=\"Target2\"i]'); + expect.soft(await generate(page, '#target3')).toBe('internal:label=\"Target3\"i'); + expect.soft(await generate(page, '#target4')).toBe('internal:label=\"Target4\"i'); + expect.soft(await generate(page, '#target5')).toBe('#target5'); + expect.soft(await generate(page, '#target6')).toBe('internal:text="text"i'); await page.setContent(``); - expect(await generate(page, 'input')).toBe('internal:label="Coun\\\"try"i'); + expect(await generate(page, 'input')).toBe('internal:role=textbox[name=\"Coun\\\"try\"i]'); }); it('should prefer role other input[type]', async ({ page }) => { @@ -514,7 +560,7 @@ it.describe('selector generator', () => { `); - expect(await generate(page, 'input')).toBe('internal:attr=[placeholder=\"Text\"s]'); + expect(await generate(page, 'input')).toBe('internal:role=textbox[name=\"Text\"s]'); }); it('should generate exact role when necessary', async ({ page }) => { @@ -530,7 +576,7 @@ it.describe('selector generator', () => { `); - expect(await generate(page, 'input')).toBe('internal:label=\"Text\"s'); + expect(await generate(page, 'input')).toBe('internal:role=textbox[name=\"Text\"s]'); }); it('should generate relative selector', async ({ page }) => { @@ -596,4 +642,23 @@ it.describe('selector generator', () => { `span >> nth=1`, ]); }); + + it('should prefer role with hasText to css with hasText', async ({ page }) => { + await page.setContent(` +
    +
  • + + buy flowers +
  • +
  • + + sell milk +
  • +
+ `); + expect(await generateMultiple(page, 'input')).toEqual([ + `internal:role=listitem >> internal:has-text=\"buy flowers\"i >> internal:label=\"Toggle Todo\"i`, + `internal:label=\"Toggle Todo\"i >> nth=0`, + ]); + }); }); diff --git a/tests/library/selectors-register.spec.ts b/tests/library/selectors-register.spec.ts index eff9dea9e558f..b7393761865d6 100644 --- a/tests/library/selectors-register.spec.ts +++ b/tests/library/selectors-register.spec.ts @@ -52,7 +52,9 @@ it('should work', async ({ playwright, browser }) => { await context.close(); }); -it('should work when registered on global', async ({ browser }) => { +it('should work when registered on global', async ({ browser, mode }) => { + it.skip(mode === 'driver', 'We expect registering selectors on the right Playwright instance.'); + await require('@playwright/test').selectors.register('oop-tag', `(${createTagSelector.toString()})()`); const context = await browser.newContext(); @@ -74,15 +76,14 @@ it('should work when registered on global', async ({ browser }) => { }); it('should work with path', async ({ playwright, browser, asset }) => { - const page = await browser.newPage(); await playwright.selectors.register('foo', { path: asset('sectionselectorengine.js') }); + const page = await browser.newPage(); await page.setContent('
'); expect(await page.$eval('foo=whatever', e => e.nodeName)).toBe('SECTION'); await page.close(); }); it('should work in main and isolated world', async ({ playwright, browser }) => { - const page = await browser.newPage(); const createDummySelector = () => ({ query(root, selector) { return window['__answer']; @@ -93,6 +94,7 @@ it('should work in main and isolated world', async ({ playwright, browser }) => }); await playwright.selectors.register('main', createDummySelector); await playwright.selectors.register('isolated', createDummySelector, { contentScript: true }); + const page = await browser.newPage(); await page.setContent('
'); await page.evaluate(() => window['__answer'] = document.querySelector('span')); // Works in main if asked. @@ -143,8 +145,12 @@ it('should handle errors', async ({ playwright, browser }) => { await page.close(); }); +it('should throw "already registered" error when registering', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/36467' } }, async ({ playwright }) => { + await playwright.selectors.register('alreadyRegistered', createTagSelector); + await expect(playwright.selectors.register('alreadyRegistered', createTagSelector)).rejects.toThrowError('selectors.register: "alreadyRegistered" selector engine has been already registered'); +}); + it('should not rely on engines working from the root', async ({ playwright, browser }) => { - const page = await browser.newPage(); const createValueEngine = () => ({ query(root, selector) { return root && root.value.includes(selector) ? root : undefined; @@ -153,15 +159,14 @@ it('should not rely on engines working from the root', async ({ playwright, brow return root && root.value.includes(selector) ? [root] : []; }, }); - await playwright.selectors.register('__value', createValueEngine); + const page = await browser.newPage(); await page.setContent(``); expect(await page.$eval('input >> __value=value2', e => e.id)).toBe('input2'); await page.close(); }); it('should throw a nice error if the selector returns a bad value', async ({ playwright, browser }) => { - const page = await browser.newPage(); const createFakeEngine = () => ({ query(root, selector) { return [document.body]; @@ -172,6 +177,7 @@ it('should throw a nice error if the selector returns a bad value', async ({ pla }); await playwright.selectors.register('__fake', createFakeEngine); + const page = await browser.newPage(); const error = await page.$('__fake=value2').catch(e => e); expect(error.message).toContain('Expected a Node but got [object Array]'); await page.close(); diff --git a/tests/library/signals.spec.ts b/tests/library/signals.spec.ts index 70f7eb51f1124..50bbd05f8c87a 100644 --- a/tests/library/signals.spec.ts +++ b/tests/library/signals.spec.ts @@ -59,11 +59,11 @@ test('should remove temp dir on process.exit', async ({ startRemoteServer, serve test.describe('signals', () => { test.skip(({ platform }) => platform === 'win32'); - test('should report browser close signal 2', async ({ startRemoteServer, server, isMac, browserName }) => { + test('should report browser close signal 2', async ({ startRemoteServer, server, isMac, macVersion, browserName }) => { const remoteServer = await startRemoteServer('launchServer', { url: server.EMPTY_PAGE }); const pid = await remoteServer.out('pid'); process.kill(-pid, 'SIGKILL'); - if (isMac && browserName === 'webkit' && parseInt(os.release(), 10) > 22 && os.arch() === 'arm64') { + if (isMac && browserName === 'webkit' && macVersion > 13 && os.arch() === 'arm64') { // WebKit on newer macOS exits sometimes with exit code, sometimes with signal. expect('exitCode:' + await remoteServer.out('exitCode') + 'signal:' + await remoteServer.out('signal')).toMatch(/exitCode:137|signal:SIGKILL/); diff --git a/tests/library/slowmo.spec.ts b/tests/library/slowmo.spec.ts index de25e6cdb1cf5..8a1872532b5f8 100644 --- a/tests/library/slowmo.spec.ts +++ b/tests/library/slowmo.spec.ts @@ -21,18 +21,17 @@ import type { TestServer } from '../config/testserver'; async function checkSlowMo(toImpl: (api: any) => any, page: Page, task: () => Promise) { let didSlowMo = false; - const contextDebugger = toImpl(page.context()).debugger(); - contextDebugger._slowMo = 100; - const orig = contextDebugger._doSlowMo; - contextDebugger._doSlowMo = async () => { + const dispatcherConnection = toImpl((page as any)._connection); + const orig = dispatcherConnection._doSlowMo; + dispatcherConnection._doSlowMo = async (sdkObject: any) => { if (didSlowMo) throw new Error('already did slowmo'); await new Promise(x => setTimeout(x, 100)); didSlowMo = true; - return orig.call(contextDebugger); }; await task(); expect(!!didSlowMo).toBe(true); + dispatcherConnection._doSlowMo = orig; } async function checkPageSlowMo(toImpl: (api: any) => any, page: Page, task: () => Promise) { diff --git a/tests/library/snapshotter.spec.ts b/tests/library/snapshotter.spec.ts index b6c45b9252fed..9eb839b7e8b71 100644 --- a/tests/library/snapshotter.spec.ts +++ b/tests/library/snapshotter.spec.ts @@ -30,7 +30,7 @@ it.describe('snapshots', () => { it('should collect snapshot', async ({ page, toImpl, snapshotter }) => { await page.setContent(''); const snapshot = await snapshotter.captureSnapshot(toImpl(page), 'call@1', 'snapshot@call@1'); - expect(distillSnapshot(snapshot)).toBe(''); + expect(distillSnapshot(snapshot, page.url())).toBe(''); }); it('should preserve BASE and other content on reset', async ({ page, toImpl, snapshotter, server }) => { @@ -51,7 +51,7 @@ it.describe('snapshots', () => { }); await page.setContent(''); const snapshot = await snapshotter.captureSnapshot(toImpl(page), 'call@1', 'snapshot@call@1'); - const resource = snapshot.resourceByUrl(`http://localhost:${server.PORT}/style.css`, 'GET'); + const resource = snapshot.resourceByUrl(`${server.PREFIX}/style.css`, 'GET'); expect(resource).toBeTruthy(); }); @@ -65,11 +65,11 @@ it.describe('snapshots', () => { it('should respect inline CSSOM change', async ({ page, toImpl, snapshotter }) => { await page.setContent(''); const snapshot1 = await snapshotter.captureSnapshot(toImpl(page), 'call@1', 'snapshot@call@1'); - expect(distillSnapshot(snapshot1)).toBe(''); + expect(distillSnapshot(snapshot1, page.url())).toBe(''); await page.evaluate(() => { (document.styleSheets[0].cssRules[0] as any).style.color = 'blue'; }); const snapshot2 = await snapshotter.captureSnapshot(toImpl(page), 'call@2', 'snapshot@call@2'); - expect(distillSnapshot(snapshot2)).toBe(''); + expect(distillSnapshot(snapshot2, page.url())).toBe(''); }); it('should respect CSSOM change through CSSGroupingRule', async ({ page, toImpl, snapshotter }) => { @@ -79,33 +79,33 @@ it.describe('snapshots', () => { void 0; }); const snapshot1 = await snapshotter.captureSnapshot(toImpl(page), 'call@1', 'snapshot@call@1'); - expect(distillSnapshot(snapshot1)).toBe(''); + expect(distillSnapshot(snapshot1, page.url())).toBe(''); await page.evaluate(() => { window['rule'].cssRules[0].style.color = 'blue'; }); const snapshot2 = await snapshotter.captureSnapshot(toImpl(page), 'call@2', 'snapshot@call@2'); - expect(distillSnapshot(snapshot2)).toBe(''); + expect(distillSnapshot(snapshot2, page.url())).toBe(''); await page.evaluate(() => { window['rule'].insertRule('button { color: green; }', 1); }); const snapshot3 = await snapshotter.captureSnapshot(toImpl(page), 'call@3', 'snapshot@call@3'); - expect(distillSnapshot(snapshot3)).toBe(''); + expect(distillSnapshot(snapshot3, page.url())).toBe(''); }); it('should respect node removal', async ({ page, toImpl, snapshotter }) => { await page.setContent('
'); const snapshot1 = await snapshotter.captureSnapshot(toImpl(page), 'call@1', 'snapshot@call@1'); - expect(distillSnapshot(snapshot1)).toBe('
'); + expect(distillSnapshot(snapshot1, page.url())).toBe('
'); await page.evaluate(() => document.getElementById('button2').remove()); const snapshot2 = await snapshotter.captureSnapshot(toImpl(page), 'call@2', 'snapshot@call@2'); - expect(distillSnapshot(snapshot2)).toBe('
'); + expect(distillSnapshot(snapshot2, page.url())).toBe('
'); }); it('should respect attr removal', async ({ page, toImpl, snapshotter }) => { await page.setContent('
'); const snapshot1 = await snapshotter.captureSnapshot(toImpl(page), 'call@1', 'snapshot@call@1'); - expect(distillSnapshot(snapshot1)).toBe('
'); + expect(distillSnapshot(snapshot1, page.url())).toBe('
'); await page.evaluate(() => document.getElementById('div').removeAttribute('attr2')); const snapshot2 = await snapshotter.captureSnapshot(toImpl(page), 'call@2', 'snapshot@call@2'); - expect(distillSnapshot(snapshot2)).toBe('
'); + expect(distillSnapshot(snapshot2, page.url())).toBe('
'); }); it('should have a custom doctype', async ({ page, server, toImpl, snapshotter }) => { @@ -113,21 +113,21 @@ it.describe('snapshots', () => { await page.setContent('hi'); const snapshot = await snapshotter.captureSnapshot(toImpl(page), 'call@1', 'snapshot@call@1'); - expect(distillSnapshot(snapshot)).toBe('hi'); + expect(distillSnapshot(snapshot, page.url())).toBe('hi'); }); it('should replace meta charset attr that specifies charset', async ({ page, server, toImpl, snapshotter }) => { await page.goto(server.EMPTY_PAGE); await page.setContent(''); const snapshot = await snapshotter.captureSnapshot(toImpl(page), 'call@1', 'snapshot@call@1'); - expect(distillSnapshot(snapshot)).toBe(''); + expect(distillSnapshot(snapshot, page.url())).toBe(''); }); it('should replace meta content attr that specifies charset', async ({ page, server, toImpl, snapshotter }) => { await page.goto(server.EMPTY_PAGE); await page.setContent(''); const snapshot = await snapshotter.captureSnapshot(toImpl(page), 'call@1', 'snapshot@call@1'); - expect(distillSnapshot(snapshot)).toBe(''); + expect(distillSnapshot(snapshot, page.url())).toBe(''); }); it('should respect subresource CSSOM change', async ({ page, server, toImpl, snapshotter }) => { @@ -138,11 +138,11 @@ it.describe('snapshots', () => { await page.setContent(''); const snapshot1 = await snapshotter.captureSnapshot(toImpl(page), 'call@1', 'snapshot@call@1'); - expect(distillSnapshot(snapshot1)).toBe(''); + expect(distillSnapshot(snapshot1, page.url())).toBe(''); await page.evaluate(() => { (document.styleSheets[0].cssRules[0] as any).style.color = 'blue'; }); const snapshot2 = await snapshotter.captureSnapshot(toImpl(page), 'call@2', 'snapshot@call@2'); - const resource = snapshot2.resourceByUrl(`http://localhost:${server.PORT}/style.css`, 'GET'); + const resource = snapshot2.resourceByUrl(`${server.PREFIX}/style.css`, 'GET'); expect((await snapshotter.resourceContentForTest(resource.response.content._sha1)).toString()).toBe('button { color: blue; }'); }); @@ -163,7 +163,7 @@ it.describe('snapshots', () => { for (let counter = 0; ; ++counter) { const snapshot = await snapshotter.captureSnapshot(toImpl(page), 'call@' + counter, 'snapshot@call@' + counter); - const text = distillSnapshot(snapshot).replace(/frame@[^"]+["]/, '"'); + const text = distillSnapshot(snapshot, page.url()).replace(/frame@[^"]+["]/, '"'); if (text === '\">') break; await page.waitForTimeout(250); @@ -188,7 +188,7 @@ it.describe('snapshots', () => { // Marking iframe hierarchy is racy, do not expect snapshot, wait for it. for (let counter = 0; ; ++counter) { const snapshot = await snapshotter.captureSnapshot(toImpl(page), 'call@' + counter, 'snapshot@call@' + counter); - const text = distillSnapshot(snapshot).replace(/frame@[^"]+["]/, '"'); + const text = distillSnapshot(snapshot, page.url()).replace(/frame@[^"]+["]/, '"'); if (text === '') break; await page.waitForTimeout(250); @@ -208,47 +208,33 @@ it.describe('snapshots', () => { // Marking iframe hierarchy is racy, do not expect snapshot, wait for it. for (let counter = 0; ; ++counter) { const snapshot = await snapshotter.captureSnapshot(toImpl(page), 'call@' + counter, 'snapshot@call@' + counter); - const text = distillSnapshot(snapshot).replace(/frame@[^"]+["]/, '"'); + const text = distillSnapshot(snapshot, page.url()).replace(/frame@[^"]+["]/, '"'); if (text === '') break; await page.waitForTimeout(250); } }); - it('should capture snapshot target', async ({ page, toImpl, snapshotter }) => { - await page.setContent(''); - { - const handle = await page.$('text=Hello'); - const snapshot = await snapshotter.captureSnapshot(toImpl(page), 'call@1', 'snapshot@call@1', toImpl(handle)); - expect(distillSnapshot(snapshot, false /* distillTarget */)).toBe(''); - } - { - const handle = await page.$('text=World'); - const snapshot = await snapshotter.captureSnapshot(toImpl(page), 'call@2', 'snapshot@call@2', toImpl(handle)); - expect(distillSnapshot(snapshot, false /* distillTarget */)).toBe(''); - } - }); - it('should collect on attribute change', async ({ page, toImpl, snapshotter }) => { await page.setContent(''); { const snapshot = await snapshotter.captureSnapshot(toImpl(page), 'call@1', 'snapshot@call@1'); - expect(distillSnapshot(snapshot)).toBe(''); + expect(distillSnapshot(snapshot, page.url())).toBe(''); } const handle = await page.$('text=Hello')!; await handle.evaluate(element => element.setAttribute('data', 'one')); { const snapshot = await snapshotter.captureSnapshot(toImpl(page), 'call@2', 'snapshot@call@2'); - expect(distillSnapshot(snapshot)).toBe(''); + expect(distillSnapshot(snapshot, page.url())).toBe(''); } await handle.evaluate(element => element.setAttribute('data', 'two')); { const snapshot = await snapshotter.captureSnapshot(toImpl(page), 'call@3', 'snapshot@call@3'); - expect(distillSnapshot(snapshot)).toBe(''); + expect(distillSnapshot(snapshot, page.url())).toBe(''); } }); - it('empty adopted style sheets should not prevent node refs', async ({ page, toImpl, snapshotter, browserName }) => { + it('empty adopted style sheets should not prevent node refs', async ({ page, toImpl, snapshotter }) => { await page.setContent(''); await page.evaluate(() => { const sheet = new CSSStyleSheet(); @@ -267,7 +253,7 @@ it.describe('snapshots', () => { const renderer1 = await snapshotter.captureSnapshot(toImpl(page), 'call@1', 'snapshot@call@1'); // Expect some adopted style sheets. - expect(distillSnapshot(renderer1)).toContain('__playwright_style_sheet_'); + expect(distillSnapshot(renderer1, page.url())).toContain('__playwright_style_sheet_'); const renderer2 = await snapshotter.captureSnapshot(toImpl(page), 'call@2', 'snapshot@call@2'); const snapshot2 = renderer2.snapshot(); @@ -278,20 +264,22 @@ it.describe('snapshots', () => { it('should not navigate on anchor clicks', async ({ page, toImpl, snapshotter }) => { await page.setContent('example.com'); const snapshot = await snapshotter.captureSnapshot(toImpl(page), 'call@1', 'snapshot@call@1'); - expect(distillSnapshot(snapshot)).toBe('example.com'); + expect(distillSnapshot(snapshot, page.url())).toBe('example.com'); }); }); -function distillSnapshot(snapshot, distillTarget = true) { +function distillSnapshot(snapshot, url: string, options: { distillTarget: boolean, distillBoundingRect: boolean } = { distillTarget: true, distillBoundingRect: true }) { let { html } = snapshot.render(); - if (distillTarget) + if (options.distillTarget) html = html.replace(/\s__playwright_target__="[^"]+"/g, ''); + if (options.distillBoundingRect) + html = html.replace(/\s__playwright_bounding_rect__="[^"]+"/g, ''); return html .replace(/ + + +
hello
+ world + + + `); + const css = ` + div { + background-image: url( 'data:image/svg+xml,Custom Title'); + color: rgb(1, 2, 3); + } + span { + color: rgb(4, 5, 6); + background-image: url("data:image/svg+xml,Custom Title" ); + } + `; + await page.evaluate(css => document.querySelector('style').textContent = css, css); + }); + + const snapshot = await traceViewer.snapshotFrame('Evaluate'); + // Just "hello world", no gibberish from the
@@ -371,7 +534,7 @@ test.describe('toBeInViewport', () => { test('should have good stack', async ({ page }) => { let error; try { - await expect(page.locator('body')).not.toBeInViewport({ timeout: 100 }); + await expect(page.locator('body')).not.toBeInViewport({ timeout: 500 }); } catch (e) { error = e; } @@ -419,40 +582,3 @@ test('toHaveText that does not match should not produce logs twice', async ({ pa expect(error.message).not.toContain('locator resolved to'); expect(error.message.replace(waitingForMessage, '')).not.toContain(waitingForMessage); }); - -test('toHaveAccessibleName', async ({ page }) => { - await page.setContent(` -
- `); - await expect(page.locator('div')).toHaveAccessibleName('Hello'); - await expect(page.locator('div')).not.toHaveAccessibleName('hello'); - await expect(page.locator('div')).toHaveAccessibleName('hello', { ignoreCase: true }); - await expect(page.locator('div')).toHaveAccessibleName(/ell\w/); - await expect(page.locator('div')).not.toHaveAccessibleName(/hello/); - await expect(page.locator('div')).toHaveAccessibleName(/hello/, { ignoreCase: true }); -}); - -test('toHaveAccessibleDescription', async ({ page }) => { - await page.setContent(` -
- `); - await expect(page.locator('div')).toHaveAccessibleDescription('Hello'); - await expect(page.locator('div')).not.toHaveAccessibleDescription('hello'); - await expect(page.locator('div')).toHaveAccessibleDescription('hello', { ignoreCase: true }); - await expect(page.locator('div')).toHaveAccessibleDescription(/ell\w/); - await expect(page.locator('div')).not.toHaveAccessibleDescription(/hello/); - await expect(page.locator('div')).toHaveAccessibleDescription(/hello/, { ignoreCase: true }); -}); - -test('toHaveRole', async ({ page }) => { - await page.setContent(`
Button!
`); - await expect(page.locator('div')).toHaveRole('button'); - await expect(page.locator('div')).not.toHaveRole('checkbox'); - try { - // @ts-expect-error - await expect(page.locator('div')).toHaveRole(/button|checkbox/); - expect(1, 'Must throw when given a regular expression').toBe(2); - } catch (error) { - expect(error.message).toBe(`"role" argument in toHaveRole must be a string`); - } -}); diff --git a/tests/page/expect-timeout.spec.ts b/tests/page/expect-timeout.spec.ts index 16b3210caa72a..7143d309f8af6 100644 --- a/tests/page/expect-timeout.spec.ts +++ b/tests/page/expect-timeout.spec.ts @@ -20,38 +20,79 @@ import { test, expect } from './pageTest'; test('should print timed out error message', async ({ page }) => { await page.setContent('
Text content
'); const error = await expect(page.locator('no-such-thing')).toHaveText('hey', { timeout: 1000 }).catch(e => e); - expect(stripAnsi(error.message)).toContain(`Timed out 1000ms waiting for expect(locator).toHaveText(expected)`); + expect(stripAnsi(error.message)).toContain(`expect(locator).toHaveText(expected) failed + +Locator: locator('no-such-thing') +Expected string: "hey" +Received: +Timeout: 1000ms`); }); test('should print timed out error message when value does not match', async ({ page }) => { await page.setContent('
Text content
'); const error = await expect(page.locator('div')).toHaveText('hey', { timeout: 1000 }).catch(e => e); - expect(stripAnsi(error.message)).toContain(`Timed out 1000ms waiting for expect(locator).toHaveText(expected)`); + expect(stripAnsi(error.message)).toContain(`expect(locator).toHaveText(expected) failed + +Locator: locator('div') +Expected string: "hey" +Received string: "Text content" +Timeout: 1000ms`); }); test('should print timed out error message with impossible timeout', async ({ page }) => { await page.setContent('
Text content
'); const error = await expect(page.locator('no-such-thing')).toHaveText('hey', { timeout: 1 }).catch(e => e); - expect(stripAnsi(error.message)).toContain(`Timed out 1ms waiting for expect(locator).toHaveText(expected)`); + expect(stripAnsi(error.message)).toContain(`expect(locator).toHaveText(expected) failed + +Locator: locator('no-such-thing') +Expected string: "hey" +Received: +Timeout: 1ms`); }); test('should print timed out error message when value does not match with impossible timeout', async ({ page }) => { await page.setContent('
Text content
'); const error = await expect(page.locator('div')).toHaveText('hey', { timeout: 1 }).catch(e => e); - expect(stripAnsi(error.message)).toContain(`Timed out 1ms waiting for expect(locator).toHaveText(expected)`); -}); + expect(stripAnsi(error.message)).toContain(`expect(locator).toHaveText(expected) failed -test('should not print timed out error message when page closes', async ({ page }) => { - await page.setContent('
Text content
'); - const [error] = await Promise.all([ - expect(page.locator('div')).toHaveText('hey', { timeout: 100000 }).catch(e => e), - page.close(), - ]); - expect(stripAnsi(error.message)).toContain('expect.toHaveText with timeout 100000ms'); - expect(stripAnsi(error.message)).not.toContain('Timed out'); +Locator: locator('div') +Expected string: "hey" +Received string: "Text content" +Timeout: 1ms`); }); test('should have timeout error name', async ({ page }) => { const error = await page.waitForSelector('#not-found', { timeout: 1 }).catch(e => e); expect(error.name).toBe('TimeoutError'); }); + +test('should not throw when navigating during one-shot check', async ({ page, server }) => { + await page.setContent(`
hello
`); + const promise = expect(page.locator('div')).toHaveText('bye'); + await page.goto(server.EMPTY_PAGE); + await page.setContent(`
bye
`); + await promise; +}); + +test('should not throw when navigating during first locator handler check', async ({ page, server }) => { + await page.addLocatorHandler(page.locator('span'), async locator => {}); + await page.setContent(`
hello
`); + const promise = expect(page.locator('div')).toHaveText('bye'); + await page.goto(server.EMPTY_PAGE); + await page.setContent(`
bye
`); + await promise; +}); + +test('should timeout during first locator handler check', async ({ page, server }) => { + await page.addLocatorHandler(page.locator('div'), async locator => {}); + await page.setContent(`
hello
bye`); + const error = await expect(page.locator('span')).toHaveText('bye', { timeout: 3000 }).catch(e => e); + expect(stripAnsi(error.message)).toContain(`expect(locator).toHaveText(expected) failed + +Locator: locator('span') +Expected string: "bye" +Received string: "" +Timeout: 3000ms`); + expect(error.message).toContain(`locator handler has finished, waiting for locator('div') to be hidden`); + expect(error.message).toContain(`locator resolved to visible
hello
`); +}); diff --git a/tests/page/expect-to-have-accessible.spec.ts b/tests/page/expect-to-have-accessible.spec.ts new file mode 100644 index 0000000000000..f3bd3083c9caf --- /dev/null +++ b/tests/page/expect-to-have-accessible.spec.ts @@ -0,0 +1,200 @@ +/** + * 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. + */ + +import { test, expect } from './pageTest'; + +test('toHaveAccessibleName', async ({ page }) => { + await page.setContent(` +
+ `); + await expect(page.locator('div')).toHaveAccessibleName('Hello'); + await expect(page.locator('div')).not.toHaveAccessibleName('hello'); + await expect(page.locator('div')).toHaveAccessibleName('hello', { ignoreCase: true }); + await expect(page.locator('div')).toHaveAccessibleName(/ell\w/); + await expect(page.locator('div')).not.toHaveAccessibleName(/hello/); + await expect(page.locator('div')).toHaveAccessibleName(/hello/, { ignoreCase: true }); + + await page.setContent(``); + await expect(page.locator('button')).toHaveAccessibleName('foo bar baz'); +}); + +test('toHaveAccessibleDescription', async ({ page }) => { + await page.setContent(` +
+ `); + await expect(page.locator('div')).toHaveAccessibleDescription('Hello'); + await expect(page.locator('div')).not.toHaveAccessibleDescription('hello'); + await expect(page.locator('div')).toHaveAccessibleDescription('hello', { ignoreCase: true }); + await expect(page.locator('div')).toHaveAccessibleDescription(/ell\w/); + await expect(page.locator('div')).not.toHaveAccessibleDescription(/hello/); + await expect(page.locator('div')).toHaveAccessibleDescription(/hello/, { ignoreCase: true }); + + await page.setContent(` +
+ foo bar\nbaz + `); + await expect(page.locator('div')).toHaveAccessibleDescription('foo bar baz'); +}); + +test('toHaveAccessibleErrorMessage', async ({ page }) => { + await page.setContent(` +
+ +
Hello
+
This should not be considered.
+
+ `); + + const locator = page.locator('input[role="textbox"]'); + await expect(locator).toHaveAccessibleErrorMessage('Hello'); + await expect(locator).not.toHaveAccessibleErrorMessage('hello'); + await expect(locator).toHaveAccessibleErrorMessage('hello', { ignoreCase: true }); + await expect(locator).toHaveAccessibleErrorMessage(/ell\w/); + await expect(locator).not.toHaveAccessibleErrorMessage(/hello/); + await expect(locator).toHaveAccessibleErrorMessage(/hello/, { ignoreCase: true }); + await expect(locator).not.toHaveAccessibleErrorMessage('This should not be considered.'); +}); + +test('toHaveAccessibleErrorMessage should handle multiple aria-errormessage references', async ({ page }) => { + await page.setContent(` +
+ +
First error message.
+
Second error message.
+
This should not be considered.
+
+ `); + + const locator = page.locator('input[role="textbox"]'); + + await expect(locator).toHaveAccessibleErrorMessage('First error message. Second error message.'); + await expect(locator).toHaveAccessibleErrorMessage(/first error message./i); + await expect(locator).toHaveAccessibleErrorMessage(/second error message./i); + await expect(locator).not.toHaveAccessibleErrorMessage(/This should not be considered./i); +}); + +test.describe('toHaveAccessibleErrorMessage should handle aria-invalid attribute', () => { + const errorMessageText = 'Error message'; + + async function setupPage(page, ariaInvalidValue: string | null) { + const ariaInvalidAttr = ariaInvalidValue === null ? '' : `aria-invalid="${ariaInvalidValue}"`; + await page.setContent(` +
+ +
${errorMessageText}
+
+ `); + return page.locator('#node'); + } + + test.describe('evaluated in false', () => { + test('no aria-invalid attribute', async ({ page }) => { + const locator = await setupPage(page, null); + await expect(locator).not.toHaveAccessibleErrorMessage(errorMessageText); + }); + test('aria-invalid="false"', async ({ page }) => { + const locator = await setupPage(page, 'false'); + await expect(locator).not.toHaveAccessibleErrorMessage(errorMessageText); + }); + test('aria-invalid="" (empty string)', async ({ page }) => { + const locator = await setupPage(page, ''); + await expect(locator).not.toHaveAccessibleErrorMessage(errorMessageText); + }); + }); + test.describe('evaluated in true', () => { + test('aria-invalid="true"', async ({ page }) => { + const locator = await setupPage(page, 'true'); + await expect(locator).toHaveAccessibleErrorMessage(errorMessageText); + }); + test('aria-invalid="foo" (unrecognized value)', async ({ page }) => { + const locator = await setupPage(page, 'foo'); + await expect(locator).toHaveAccessibleErrorMessage(errorMessageText); + }); + }); +}); + +const errorMessageText = 'Error message'; + +test('should show error message when validity is false and aria-invalid is true', async ({ page }) => { + await page.setContent(` +
+ +
${errorMessageText}
+
+ `); + const locator = page.locator('#node'); + await locator.fill('101'); + await expect(locator).toHaveAccessibleErrorMessage(errorMessageText); +}); + +test('should show error message when validity is true and aria-invalid is true', async ({ page }) => { + await page.setContent(` +
+ +
${errorMessageText}
+
+ `); + const locator = page.locator('#node'); + await locator.fill('99'); + await expect(locator).toHaveAccessibleErrorMessage(errorMessageText); +}); + +test('should show error message when validity is false and aria-invalid is false', async ({ page }) => { + await page.setContent(` +
+ +
${errorMessageText}
+
+ `); + const locator = page.locator('#node'); + await locator.fill('101'); + await expect(locator).toHaveAccessibleErrorMessage(errorMessageText); +}); + +test('should not show error message when validity is true and aria-invalid is false', async ({ page }) => { + await page.setContent(` +
+ +
${errorMessageText}
+
+ `); + const locator = page.locator('#node'); + await locator.fill('99'); + await expect(locator).not.toHaveAccessibleErrorMessage(errorMessageText); +}); + +test('should show error message for all roles', async ({ page }) => { + await page.setContent(` + + + + `); + const locator = page.getByLabel('File input'); + await expect(locator).toHaveAccessibleErrorMessage('File is incorrect'); +}); + +test('toHaveRole', async ({ page }) => { + await page.setContent(`
Button!
`); + await expect(page.locator('div')).toHaveRole('button'); + await expect(page.locator('div')).not.toHaveRole('checkbox'); + try { + // @ts-expect-error + await expect(page.locator('div')).toHaveRole(/button|checkbox/); + expect(1, 'Must throw when given a regular expression').toBe(2); + } catch (error) { + expect(error.message).toBe(`"role" argument in toHaveRole must be a string`); + } +}); diff --git a/tests/page/expect-to-have-text.spec.ts b/tests/page/expect-to-have-text.spec.ts index d10700e98b94d..b1b19cc02a294 100644 --- a/tests/page/expect-to-have-text.spec.ts +++ b/tests/page/expect-to-have-text.spec.ts @@ -71,6 +71,8 @@ test.describe('toHaveText with text', () => { await expect(locator).toHaveText('text CONTENT', { ignoreCase: true }); // Should support falsy ignoreCase. await expect(locator).not.toHaveText('TEXT', { ignoreCase: false }); + // Should normalize soft hyphens. + await expect(locator).toHaveText('T\u00ade\u00adxt content'); }); test('pass contain', async ({ page }) => { @@ -206,7 +208,9 @@ test.describe('toHaveText with array', () => { await page.setContent('
'); const locator = page.locator('p'); const error = await expect(locator).not.toHaveText([], { timeout: 1000 }).catch(e => e); - expect(error.message).toContain('expect.not.toHaveText with timeout 1000ms'); + expect(stripAnsi(error.message)).toContain(`expect(locator).not.toHaveText(expected)`); + expect(stripAnsi(error.message)).toContain(`Timeout: 1000ms`); + expect(stripAnsi(error.message)).toContain(`- Expect "not toHaveText" with timeout 1000ms`); }); test('pass eventually empty', async ({ page }) => { @@ -223,9 +227,11 @@ test.describe('toHaveText with array', () => { const locator = page.locator('div'); const error = await expect(locator).toHaveText(['Text 1', /Text \d/, 'Extra'], { timeout: 1000 }).catch(e => e); expect(stripAnsi(error.message)).toContain('- "Extra"'); - expect(error.message).toContain('expect.toHaveText with timeout 1000ms'); - expect(error.message).toContain('waiting for locator(\'div\')'); - expect(error.message).toContain('locator resolved to 2 elements'); + expect(stripAnsi(error.message)).toContain(`expect(locator).toHaveText(expected)`); + expect(stripAnsi(error.message)).toContain(`Timeout: 1000ms`); + expect(stripAnsi(error.message)).toContain(`- Expect "toHaveText" with timeout 1000ms`); + expect(stripAnsi(error.message)).toContain('waiting for locator(\'div\')'); + expect(stripAnsi(error.message)).toContain('locator resolved to 2 elements'); }); test('fail on repeating array matchers', async ({ page }) => { diff --git a/tests/page/frame-evaluate.spec.ts b/tests/page/frame-evaluate.spec.ts index b7feb2c0d64a0..5a1c3fa874341 100644 --- a/tests/page/frame-evaluate.spec.ts +++ b/tests/page/frame-evaluate.spec.ts @@ -37,9 +37,9 @@ it('should have correct execution contexts @smoke', async ({ page, server }) => function expectContexts(pageImpl, count, browserName) { if (browserName === 'chromium') - expect(pageImpl._delegate._mainFrameSession._contextIdToContext.size).toBe(count); + expect(pageImpl.delegate._mainFrameSession._contextIdToContext.size).toBe(count); else - expect(pageImpl._delegate._contextIdToContext.size).toBe(count); + expect(pageImpl.delegate._contextIdToContext.size).toBe(count); } it('should dispose context on navigation', async ({ page, server, toImpl, browserName, isElectron }) => { @@ -133,8 +133,7 @@ it('should be isolated between frames', async ({ page, server }) => { }); it('should work in iframes that failed initial navigation', async ({ page, browserName }) => { - it.fail(browserName === 'chromium'); - it.fixme(browserName === 'firefox'); + it.fixme(browserName !== 'webkit'); // - Firefox does not report domcontentloaded for the iframe. // - Chromium and Firefox report empty url. @@ -181,4 +180,3 @@ it('evaluateHandle should work', async ({ page, server }) => { const windowHandle = await mainFrame.evaluateHandle(() => window); expect(windowHandle).toBeTruthy(); }); - diff --git a/tests/page/frame-frame-element.spec.ts b/tests/page/frame-frame-element.spec.ts index e3b25a8fe1a0a..e44e7deb3ec26 100644 --- a/tests/page/frame-frame-element.spec.ts +++ b/tests/page/frame-frame-element.spec.ts @@ -75,3 +75,19 @@ it('should work inside closed shadow root', async ({ page, server, browserName } const element = await frame.frameElement(); expect(await element.getAttribute('name')).toBe('myframe'); }); + +it('should work inside declarative shadow root', async ({ page, server, browserName }) => { + await page.goto(server.EMPTY_PAGE); + await page.setContent(` +
+ + footer +
+ `); + const frame = page.frame({ name: 'myframe' }); + const element = await frame.frameElement(); + expect(await element.getAttribute('name')).toBe('myframe'); +}); diff --git a/tests/page/frame-goto.spec.ts b/tests/page/frame-goto.spec.ts index 56146572f2c1f..6603282bb323f 100644 --- a/tests/page/frame-goto.spec.ts +++ b/tests/page/frame-goto.spec.ts @@ -43,8 +43,9 @@ it('should reject when frame detaches', async ({ page, server, browserName }) => expect(error.message.toLowerCase()).toContain('frame was detached'); }); -it('should continue after client redirect', async ({ page, server, isAndroid, mode }) => { +it('should continue after client redirect', async ({ page, server, isAndroid, browserName }) => { it.fixme(isAndroid); + it.fixme(browserName === 'firefox', 'script.js is requested before navigationCommitted arrives'); server.setRoute('/frames/script.js', () => {}); const url = server.PREFIX + '/frames/child-redirect.html'; diff --git a/tests/page/frame-hierarchy.spec.ts b/tests/page/frame-hierarchy.spec.ts index 3b8f0fb19bd7c..46e9dace1a4ca 100644 --- a/tests/page/frame-hierarchy.spec.ts +++ b/tests/page/frame-hierarchy.spec.ts @@ -20,7 +20,7 @@ import { attachFrame, detachFrame } from '../config/utils'; import type { Frame } from 'playwright-core'; function dumpFrames(frame: Frame, indentation: string = ''): string[] { - let description = frame.url().replace(/:\d+\//, ':/'); + let description = frame.url(); if (frame.name()) description += ' (' + frame.name() + ')'; const result = [indentation + description]; @@ -40,11 +40,11 @@ it('should handle nested frames @smoke', async ({ page, server, isAndroid }) => await page.goto(server.PREFIX + '/frames/nested-frames.html'); expect(dumpFrames(page.mainFrame())).toEqual([ - 'http://localhost:/frames/nested-frames.html', - ' http://localhost:/frames/frame.html (aframe)', - ' http://localhost:/frames/two-frames.html (2frames)', - ' http://localhost:/frames/frame.html (dos)', - ' http://localhost:/frames/frame.html (uno)', + `${server.PREFIX}/frames/nested-frames.html`, + ` ${server.PREFIX}/frames/frame.html (aframe)`, + ` ${server.PREFIX}/frames/two-frames.html (2frames)`, + ` ${server.PREFIX}/frames/frame.html (dos)`, + ` ${server.PREFIX}/frames/frame.html (uno)`, ]); }); diff --git a/tests/page/interception.spec.ts b/tests/page/interception.spec.ts index d71675cc39e5b..08c502e9e1a85 100644 --- a/tests/page/interception.spec.ts +++ b/tests/page/interception.spec.ts @@ -16,7 +16,7 @@ */ import { test as it, expect } from './pageTest'; -import { globToRegex } from '../../packages/playwright-core/lib/utils/glob'; +import { globToRegexPattern, urlMatches } from '../../packages/playwright-core/lib/utils/isomorphic/urlMatch'; import vm from 'vm'; it('should work with navigation @smoke', async ({ page, server }) => { @@ -71,12 +71,14 @@ it('should intercept after a service worker', async ({ page, server, browserName }); it('should work with glob', async () => { + function globToRegex(glob: string): RegExp { + return new RegExp(globToRegexPattern(glob)); + } expect(globToRegex('**/*.js').test('https://localhost:8080/foo.js')).toBeTruthy(); expect(globToRegex('**/*.css').test('https://localhost:8080/foo.js')).toBeFalsy(); expect(globToRegex('*.js').test('https://localhost:8080/foo.js')).toBeFalsy(); expect(globToRegex('https://**/*.js').test('https://localhost:8080/foo.js')).toBeTruthy(); expect(globToRegex('http://localhost:8080/simple/path.js').test('http://localhost:8080/simple/path.js')).toBeTruthy(); - expect(globToRegex('http://localhost:8080/?imple/path.js').test('http://localhost:8080/Simple/path.js')).toBeTruthy(); expect(globToRegex('**/{a,b}.js').test('https://localhost:8080/a.js')).toBeTruthy(); expect(globToRegex('**/{a,b}.js').test('https://localhost:8080/b.js')).toBeTruthy(); expect(globToRegex('**/{a,b}.js').test('https://localhost:8080/c.js')).toBeFalsy(); @@ -90,18 +92,75 @@ it('should work with glob', async () => { expect(globToRegex('http://localhost:3000/signin-oidc*').test('http://localhost:3000/signin-oidc/foo')).toBeFalsy(); expect(globToRegex('http://localhost:3000/signin-oidc*').test('http://localhost:3000/signin-oidcnice')).toBeTruthy(); - expect(globToRegex('**/three-columns/settings.html?**id=[a-z]**').test('http://mydomain:8080/blah/blah/three-columns/settings.html?id=settings-e3c58efe-02e9-44b0-97ac-dd138100cf7c&blah')).toBeTruthy(); + // range [] is NOT supported + expect(globToRegex('**/api/v[0-9]').test('http://example.com/api/v[0-9]')).toBeTruthy(); + expect(globToRegex('**/api/v[0-9]').test('http://example.com/api/version')).toBeFalsy(); + + // query params + expect(globToRegex('**/api\\?param').test('http://example.com/api?param')).toBeTruthy(); + expect(globToRegex('**/api\\?param').test('http://example.com/api-param')).toBeFalsy(); + expect(globToRegex('**/three-columns/settings.html\\?**id=settings-**').test('http://mydomain:8080/blah/blah/three-columns/settings.html?id=settings-e3c58efe-02e9-44b0-97ac-dd138100cf7c&blah')).toBeTruthy(); expect(globToRegex('\\?')).toEqual(/^\?$/); expect(globToRegex('\\')).toEqual(/^\\$/); expect(globToRegex('\\\\')).toEqual(/^\\$/); expect(globToRegex('\\[')).toEqual(/^\[$/); - expect(globToRegex('[a-z]')).toEqual(/^[a-z]$/); + expect(globToRegex('[a-z]')).toEqual(/^\[a-z\]$/); expect(globToRegex('$^+.\\*()|\\?\\{\\}\\[\\]')).toEqual(/^\$\^\+\.\*\(\)\|\?\{\}\[\]$/); + + expect(urlMatches(undefined, 'http://playwright.dev/', 'http://playwright.dev')).toBeTruthy(); + expect(urlMatches(undefined, 'http://playwright.dev/?a=b', 'http://playwright.dev?a=b')).toBeTruthy(); + expect(urlMatches(undefined, 'http://playwright.dev/', 'h*://playwright.dev')).toBeTruthy(); + expect(urlMatches(undefined, 'http://api.playwright.dev/?x=y', 'http://*.playwright.dev?x=y')).toBeTruthy(); + expect(urlMatches(undefined, 'http://playwright.dev/foo/bar', '**/foo/**')).toBeTruthy(); + expect(urlMatches('http://playwright.dev', 'http://playwright.dev/?x=y', '?x=y')).toBeTruthy(); + expect(urlMatches('http://playwright.dev/foo/', 'http://playwright.dev/foo/bar?x=y', './bar?x=y')).toBeTruthy(); + + // Case insensitive matching + expect(urlMatches(undefined, 'https://playwright.dev/fooBAR', 'HtTpS://pLaYwRiGhT.dEv/fooBAR')).toBeTruthy(); + expect(urlMatches('http://ignored', 'https://playwright.dev/fooBAR', 'HtTpS://pLaYwRiGhT.dEv/fooBAR')).toBeTruthy(); + // Path and search query are case-sensitive + expect(urlMatches(undefined, 'https://playwright.dev/foobar', 'https://playwright.dev/fooBAR')).toBeFalsy(); + expect(urlMatches(undefined, 'https://playwright.dev/foobar?a=b', 'https://playwright.dev/foobar?A=B')).toBeFalsy(); + + // This is not supported, we treat ? as a query separator. + expect(globToRegex('http://localhost:8080/?imple/path.js').test('http://localhost:8080/Simple/path.js')).toBeFalsy(); + expect(urlMatches(undefined, 'http://playwright.dev/', 'http://playwright.?ev')).toBeFalsy(); + expect(urlMatches(undefined, 'http://playwright./?ev', 'http://playwright.?ev')).toBeTruthy(); + expect(urlMatches(undefined, 'http://playwright.dev/foo', 'http://playwright.dev/f??')).toBeFalsy(); + expect(urlMatches(undefined, 'http://playwright.dev/f??', 'http://playwright.dev/f??')).toBeTruthy(); + expect(urlMatches(undefined, 'http://playwright.dev/?x=y', 'http://playwright.dev\\?x=y')).toBeTruthy(); + expect(urlMatches(undefined, 'http://playwright.dev/?x=y', 'http://playwright.dev/\\?x=y')).toBeTruthy(); + expect(urlMatches('http://playwright.dev/foo', 'http://playwright.dev/foo?bar', '?bar')).toBeTruthy(); + expect(urlMatches('http://playwright.dev/foo', 'http://playwright.dev/foo?bar', '\\\\?bar')).toBeTruthy(); + expect(urlMatches('http://first.host/', 'http://second.host/foo', '**/foo')).toBeTruthy(); + expect(urlMatches('http://playwright.dev/', 'http://localhost/', '*//localhost/')).toBeTruthy(); + + const customPrefixes = ['about', 'data', 'chrome', 'edge', 'file']; + for (const prefix of customPrefixes) { + expect(urlMatches('http://playwright.dev/', `${prefix}:blank`, `${prefix}:blank`)).toBeTruthy(); + expect(urlMatches('http://playwright.dev/', `${prefix}:blank`, `http://playwright.dev/`)).toBeFalsy(); + expect(urlMatches(undefined, `${prefix}:blank`, `${prefix}:blank`)).toBeTruthy(); + expect(urlMatches(undefined, `${prefix}:blank`, `${prefix}:*`)).toBeTruthy(); + expect(urlMatches(undefined, `not${prefix}:blank`, `${prefix}:*`)).toBeFalsy(); + } +}); + +it('should intercept by glob', async function({ page, server, isAndroid }) { + it.skip(isAndroid); + + await page.goto(server.EMPTY_PAGE); + await page.route('http://localhos**?*oo', async route => { + await route.fulfill({ + status: 200, + body: 'intercepted', + }); + }); + const result = await page.evaluate(url => fetch(url).then(r => r.text()), server.PREFIX + '/?foo'); + expect(result).toBe('intercepted'); }); -it('should intercept network activity from worker', async function({ page, server, isAndroid, browserName, browserMajorVersion }) { - it.skip(browserName === 'firefox' && browserMajorVersion < 114, 'https://github.com/microsoft/playwright/issues/21760'); +it('should intercept network activity from worker', async function({ page, server, isAndroid }) { it.skip(isAndroid); await page.goto(server.EMPTY_PAGE); @@ -122,7 +181,42 @@ it('should intercept network activity from worker', async function({ page, serve expect(msg.text()).toBe('intercepted'); }); -it('should intercept network activity from worker 2', async function({ page, server, isAndroid }) { +it('should intercept worker requests when enabled after worker creation', { + annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/32355' } +}, async ({ page, server, isAndroid, browserName, browserMajorVersion }) => { + it.skip(isAndroid); + it.skip(browserName === 'chromium' && browserMajorVersion < 130, 'fixed in Chromium 130'); + + await page.goto(server.EMPTY_PAGE); + server.setRoute('/data_for_worker', (req, res) => res.end('failed to intercept')); + const url = server.PREFIX + '/data_for_worker'; + await Promise.all([ + page.waitForEvent('worker'), + page.evaluate(url => { + (window as any).w = new Worker(URL.createObjectURL(new Blob([` + onmessage = function(e) { + fetch("${url}").then(response => response.text()).then(console.log); + }; + `], { type: 'application/javascript' }))); + }, url), + ]); + // Install the route **after** the worker has been created. + await page.route(url, route => { + route.fulfill({ + status: 200, + body: 'intercepted', + }).catch(e => null); + }); + const [msg] = await Promise.all([ + page.waitForEvent('console'), + page.evaluate(() => (window as any).w.postMessage('')) + ]); + expect(msg.text()).toBe('intercepted'); +}); + +it('should intercept network activity from worker 2', { + annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/31747' } +}, async ({ page, server, isAndroid }) => { it.skip(isAndroid); const url = server.PREFIX + '/worker/worker.js'; @@ -164,7 +258,7 @@ it('should work with regular expression passed from a different context', async expect(intercepted).toBe(true); }); -it('should not break remote worker importScripts', async ({ page, server, browserName, browserMajorVersion }) => { +it('should not break remote worker importScripts', async ({ page, server }) => { await page.route('**', async route => { await route.continue(); }); @@ -189,3 +283,20 @@ it('should disable memory cache when intercepting', async ({ page, server }) => await expect(page).toHaveURL(server.PREFIX + '/page.html'); expect(interceted).toBe(2); }); + +it('should intercept blob url requests', async function({ page, server, browserName }) { + it.fixme(browserName !== 'webkit'); + await page.goto(server.EMPTY_PAGE); + await page.route('**/*', route => { + route.fulfill({ + status: 200, + body: 'intercepted', + }).catch(e => null); + }); + page.on('console', msg => console.log(msg.text())); + const response = await page.evaluate(async () => { + const blobUrl = URL.createObjectURL(new Blob(['failed to intercept'], { type: 'text/plain' })); + return await fetch(blobUrl).then(response => response.text()); + }); + expect(response).toBe('intercepted'); +}); diff --git a/tests/page/jshandle-to-string.spec.ts b/tests/page/jshandle-to-string.spec.ts index 930899ae3d880..6b90352bd5fd0 100644 --- a/tests/page/jshandle-to-string.spec.ts +++ b/tests/page/jshandle-to-string.spec.ts @@ -56,7 +56,7 @@ it('should work for promises', async ({ page }) => { expect(bHandle.toString()).toBe('Promise'); }); -it('should work with different subtypes @smoke', async ({ page, browserName, browserMajorVersion }) => { +it('should work with different subtypes @smoke', async ({ page, browserName }) => { expect((await page.evaluateHandle('(function(){})')).toString()).toContain('function'); expect((await page.evaluateHandle('12')).toString()).toBe('12'); expect((await page.evaluateHandle('true')).toString()).toBe('true'); @@ -67,11 +67,12 @@ it('should work with different subtypes @smoke', async ({ page, browserName, bro expect((await page.evaluateHandle('new Set()')).toString()).toContain('Set'); expect((await page.evaluateHandle('[]')).toString()).toContain('Array'); expect((await page.evaluateHandle('null')).toString()).toBe('null'); - expect((await page.evaluateHandle('document.body')).toString()).toBe('JSHandle@node'); + const bodyHandle = await page.evaluateHandle('document.body'); + await expect.poll(() => bodyHandle.toString()).toBe('JSHandle@'); expect((await page.evaluateHandle('new WeakMap()')).toString()).toBe('WeakMap'); expect((await page.evaluateHandle('new WeakSet()')).toString()).toBe('WeakSet'); expect((await page.evaluateHandle('new Error()')).toString()).toContain('Error'); - expect((await page.evaluateHandle('new Proxy({}, {})')).toString()).toBe((browserName === 'chromium' && browserMajorVersion >= 111) ? 'Proxy(Object)' : 'Proxy'); + expect((await page.evaluateHandle('new Proxy({}, {})')).toString()).toBe((browserName === 'chromium') ? 'Proxy(Object)' : 'Proxy'); }); it('should work with previewable subtypes', async ({ page, browserName }) => { diff --git a/tests/page/locator-convenience.spec.ts b/tests/page/locator-convenience.spec.ts index 143bd526d226c..d63b890fd9472 100644 --- a/tests/page/locator-convenience.spec.ts +++ b/tests/page/locator-convenience.spec.ts @@ -119,7 +119,15 @@ it('isEnabled and isDisabled should work', async ({ page }) => { }); it('isEditable should work', async ({ page }) => { - await page.setContent(``); + await page.setContent(` + + + +
+ + + + `); await page.$eval('textarea', t => t.readOnly = true); const input1 = page.locator('#input1'); expect(await input1.isEditable()).toBe(false); @@ -130,6 +138,11 @@ it('isEditable should work', async ({ page }) => { const textarea = page.locator('textarea'); expect(await textarea.isEditable()).toBe(false); expect(await page.isEditable('textarea')).toBe(false); + expect(await page.locator('div').isEditable()).toBe(true); + expect(await page.locator('#span1').isEditable()).toBe(false); + expect(await page.locator('#span2').isEditable()).toBe(true); + const error = await page.locator('button').isEditable().catch(e => e); + expect(error.message).toContain('Element is not an , + + + `); + await page.locator('button').click(); + await page.locator('#text').fill('Hello'); + await expect(page.locator('#text')).toHaveValue('Hello'); +}); + +it('press should throw on unknown keys', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/36697' } }, async ({ page, server }) => { + await page.setContent(``); + const locator = page.getByRole('textbox'); + await expect(locator.press('NotARealKey')).rejects.toThrowError(/Unknown key: "NotARealKey"/); + await expect(locator.press('ё')).rejects.toThrowError(/Unknown key: "ё"/); + await expect(locator.press('😊')).rejects.toThrowError(/Unknown key: "😊"/); +}); diff --git a/tests/page/locator-misc-2.spec.ts-snapshots/screenshot-element-bounding-box-moz-firefox-nightly.png b/tests/page/locator-misc-2.spec.ts-snapshots/screenshot-element-bounding-box-moz-firefox-nightly.png new file mode 100644 index 0000000000000..9e208f86d8f76 Binary files /dev/null and b/tests/page/locator-misc-2.spec.ts-snapshots/screenshot-element-bounding-box-moz-firefox-nightly.png differ diff --git a/tests/page/locator-query.spec.ts b/tests/page/locator-query.spec.ts index f1da9bbb34920..6503d93afe7f5 100644 --- a/tests/page/locator-query.spec.ts +++ b/tests/page/locator-query.spec.ts @@ -246,9 +246,9 @@ it('should allow some, but not all nested frameLocators', async ({ page }) => { await expect(page.frameLocator('iframe').locator('article').or(page.frameLocator('iframe').locator('span'))).toHaveText('world'); await expect(page.frameLocator('iframe').locator('span').and(page.frameLocator('iframe').locator('#target'))).toHaveText('world'); const error1 = await expect(page.frameLocator('iframe').locator('div').or(page.frameLocator('#iframe').locator('span'))).toHaveText('world').catch(e => e); - expect(error1.message).toContain(`Frame locators are not allowed inside composite locators, while querying "frameLocator('iframe').locator('div').or(frameLocator('#iframe').locator('span'))`); + expect(error1.message).toContain(`Frame locators are not allowed inside composite locators, while querying "locator('iframe').contentFrame().locator('div').or(locator('#iframe').contentFrame().locator('span'))`); const error2 = await expect(page.frameLocator('iframe').locator('div').and(page.frameLocator('#iframe').locator('span'))).toHaveText('world').catch(e => e); - expect(error2.message).toContain(`Frame locators are not allowed inside composite locators, while querying "frameLocator('iframe').locator('div').and(frameLocator('#iframe').locator('span'))`); + expect(error2.message).toContain(`Frame locators are not allowed inside composite locators, while querying "locator('iframe').contentFrame().locator('div').and(locator('#iframe').contentFrame().locator('span'))`); }); it('should enforce same frame for has/leftOf/rightOf/above/below/near', async ({ page, server }) => { @@ -272,3 +272,11 @@ it('alias methods coverage', async ({ page }) => { await expect(page.locator('div').getByRole('button')).toHaveCount(1); await expect(page.mainFrame().locator('button')).toHaveCount(1); }); + +it('count() should not throw during navigation', async ({ page, mode }) => { + it.skip(mode !== 'default', 'No test hooks'); + await page.setContent(`
A
`); + const __testHookBeforeQuery = () => page.goto('data:text/html,
A
B
'); + // @ts-expect-error + expect(await page.locator('div').count({ __testHookBeforeQuery })).toBe(0); +}); diff --git a/tests/page/page-accessibility.spec.ts b/tests/page/page-accessibility.spec.ts index e6717c5e20bcb..3e95dfe047be8 100644 --- a/tests/page/page-accessibility.spec.ts +++ b/tests/page/page-accessibility.spec.ts @@ -15,11 +15,11 @@ * limitations under the License. */ -import os from 'os'; import { test as it, expect } from './pageTest'; import { chromiumVersionLessThan } from '../config/utils'; -it('should work @smoke', async ({ page, browserName }) => { +it('should work @smoke', async ({ page, browserName, isMac }) => { + it.skip(browserName === 'webkit' && isMac); await page.setContent(` Accessibility Test @@ -75,8 +75,7 @@ it('should work @smoke', async ({ page, browserName }) => { { role: 'textbox', name: 'Input with whitespace', value: ' ' }, { role: 'textbox', name: '', value: 'value only' }, { role: 'textbox', name: 'placeholder', value: 'and a value' }, - // due to frozen WebKit on macOS 11 we have the if/else here - { role: 'textbox', name: parseInt(os.release(), 10) >= 21 ? 'placeholder' : 'This is a description!', value: 'and a value' }, // webkit uses the description over placeholder for the name + { role: 'textbox', name: isMac ? 'placeholder' : 'This is a description!', value: 'and a value' }, ] }; expect(await page.accessibility.snapshot()).toEqual(golden); @@ -143,9 +142,8 @@ it('should not report text nodes inside controls', async function({ page, browse expect(await page.accessibility.snapshot()).toEqual(golden); }); -it('rich text editable fields should have children', async function({ page, browserName, browserVersion, isWebView2 }) { +it('rich text editable fields should have children', async function({ page, browserName, browserVersion }) { it.skip(browserName === 'webkit', 'WebKit rich text accessibility is iffy'); - it.skip(isWebView2, 'WebView2 is missing a Chromium fix'); await page.setContent(`
@@ -177,9 +175,8 @@ it('rich text editable fields should have children', async function({ page, brow expect(snapshot.children[0]).toEqual(golden); }); -it('rich text editable fields with role should have children', async function({ page, browserName, browserMajorVersion, browserVersion, isWebView2 }) { +it('rich text editable fields with role should have children', async function({ page, browserName, browserVersion }) { it.skip(browserName === 'webkit', 'WebKit rich text accessibility is iffy'); - it.skip(isWebView2, 'WebView2 is missing a Chromium fix'); await page.setContent(`
@@ -196,7 +193,7 @@ it('rich text editable fields with role should have children', async function({ } : { role: 'textbox', name: '', - multiline: (browserName === 'chromium' && browserMajorVersion >= 92) ? true : undefined, + multiline: (browserName === 'chromium') ? true : undefined, value: 'Edit this image: ', children: (chromiumVersionLessThan(browserVersion, '104.0.1293.1') && browserName === 'chromium') ? [{ role: 'text', diff --git a/tests/page/page-add-init-script.spec.ts b/tests/page/page-add-init-script.spec.ts index b2b7782ebac91..a24c1dad39a27 100644 --- a/tests/page/page-add-init-script.spec.ts +++ b/tests/page/page-add-init-script.spec.ts @@ -98,14 +98,3 @@ it('init script should run only once in iframe', async ({ page, server, browserN 'init script: ' + (browserName === 'firefox' ? 'no url yet' : '/frames/frame.html'), ]); }); - -it('init script should run only once in popup', async ({ page, browserName }) => { - await page.context().addInitScript(() => { - window['callCount'] = (window['callCount'] || 0) + 1; - }); - const [popup] = await Promise.all([ - page.waitForEvent('popup'), - page.evaluate(() => window.open('about:blank')), - ]); - expect(await popup.evaluate('callCount')).toEqual(1); -}); diff --git a/tests/page/page-add-locator-handler.spec.ts b/tests/page/page-add-locator-handler.spec.ts index 0062ba15ab610..069dde024158b 100644 --- a/tests/page/page-add-locator-handler.spec.ts +++ b/tests/page/page-add-locator-handler.spec.ts @@ -15,7 +15,6 @@ */ import { test, expect } from './pageTest'; -import { kTargetClosedErrorMessage } from '../config/errors'; test('should work', async ({ page, server }) => { await page.goto(server.PREFIX + '/input/handle-locator.html'); @@ -87,7 +86,9 @@ test('should work with a custom check', async ({ page, server }) => { } }); -test('should work with locator.hover()', async ({ page, server }) => { +test('should work with locator.hover()', async ({ page, server, headless }) => { + test.skip(!headless, 'Stray hovers in headed mode'); + await page.goto(server.PREFIX + '/input/handle-locator.html'); await page.addLocatorHandler(page.getByText('This interstitial covers the button'), async () => { @@ -119,23 +120,6 @@ test('should not work with force:true', async ({ page, server }) => { expect(await page.evaluate('window.clicked')).toBe(undefined); }); -test('should throw when page closes', async ({ page, server, isAndroid }) => { - test.fixme(isAndroid, 'GPU process crash: https://issues.chromium.org/issues/324909825'); - await page.goto(server.PREFIX + '/input/handle-locator.html'); - - await page.addLocatorHandler(page.getByText('This interstitial covers the button'), async () => { - await page.close(); - }); - - await page.locator('#aside').hover(); - await page.evaluate(() => { - (window as any).clicked = 0; - (window as any).setupAnnoyingInterstitial('mouseover', 1); - }); - const error = await page.locator('#target').click().catch(e => e); - expect(error.message).toContain(kTargetClosedErrorMessage); -}); - test('should throw when handler times out', async ({ page, server }) => { await page.goto(server.PREFIX + '/input/handle-locator.html'); @@ -179,6 +163,24 @@ test('should work with toBeVisible', async ({ page, server }) => { expect(called).toBe(1); }); +test('should work with locator.waitFor', async ({ page, server }) => { + await page.goto(server.PREFIX + '/input/handle-locator.html'); + + let called = 0; + await page.addLocatorHandler(page.getByText('This interstitial covers the button'), async () => { + ++called; + await page.locator('#close').click(); + }); + + await page.evaluate(() => { + (window as any).clicked = 0; + (window as any).setupAnnoyingInterstitial('remove', 1); + }); + await page.locator('#target').waitFor(); + await expect(page.locator('#interstitial')).not.toBeVisible(); + expect(called).toBe(1); +}); + test('should work with toHaveScreenshot', async ({ page, server, isAndroid }) => { test.fixme(isAndroid, 'Screenshots are cut off on Android'); await page.setViewportSize({ width: 500, height: 500 }); @@ -293,7 +295,7 @@ test('should wait for hidden by default 2', async ({ page, server }) => { }); const error = await page.locator('#target').click({ timeout: 3000 }).catch(e => e); expect(await page.evaluate('window.clicked')).toBe(0); - await expect(page.locator('#interstitial')).toBeVisible(); + expect(await page.locator('#interstitial').isVisible()).toBe(true); expect(called).toBe(1); expect(error.message).toContain(`locator handler has finished, waiting for getByRole('button', { name: 'close' }) to be hidden`); }); diff --git a/tests/page/page-add-locator-handler.spec.ts-snapshots/screenshot-grid-moz-firefox-nightly.png b/tests/page/page-add-locator-handler.spec.ts-snapshots/screenshot-grid-moz-firefox-nightly.png new file mode 100644 index 0000000000000..7b164933553a5 Binary files /dev/null and b/tests/page/page-add-locator-handler.spec.ts-snapshots/screenshot-grid-moz-firefox-nightly.png differ diff --git a/tests/page/page-aria-snapshot-ai.spec.ts b/tests/page/page-aria-snapshot-ai.spec.ts new file mode 100644 index 0000000000000..c7afd03cf34da --- /dev/null +++ b/tests/page/page-aria-snapshot-ai.spec.ts @@ -0,0 +1,394 @@ +/** + * 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. + */ + +// @ts-ignore +import { asLocator } from 'playwright-core/lib/utils'; + +import { test as it, expect, unshift } from './pageTest'; + +function snapshotForAI(page: any, options?: { timeout?: number }): Promise { + return page._snapshotForAI(options); +} + +it('should generate refs', async ({ page }) => { + await page.setContent(` + + + + `); + + const snapshot1 = await snapshotForAI(page); + expect(snapshot1).toContainYaml(` + - generic [active] [ref=e1]: + - button "One" [ref=e2] + - button "Two" [ref=e3] + - button "Three" [ref=e4] + `); + await expect(page.locator('aria-ref=e2')).toHaveText('One'); + await expect(page.locator('aria-ref=e3')).toHaveText('Two'); + await expect(page.locator('aria-ref=e4')).toHaveText('Three'); + + await page.locator('aria-ref=e3').evaluate((e: HTMLElement) => { + e.textContent = 'Not Two'; + }); + + const snapshot2 = await snapshotForAI(page); + expect(snapshot2).toContainYaml(` + - generic [active] [ref=e1]: + - button "One" [ref=e2] + - button "Not Two" [ref=e5] + - button "Three" [ref=e4] + `); +}); + +it('should list iframes', async ({ page }) => { + await page.setContent(` +

Hello

+ + `, { waitUntil: 'domcontentloaded' }); + const snapshot = await snapshotForAI(page); + expect(snapshot).toContainYaml(` + - generic [active] [ref=e1]: + - paragraph [ref=e2]: Test + - iframe [ref=e3] + `); +}); + +it('should auto-wait for navigation', async ({ page, server }) => { + await page.goto(server.PREFIX + '/frames/frame.html'); + const [, snapshot] = await Promise.all([ + page.evaluate(() => window.location.reload()), + snapshotForAI(page) + ]); + expect(snapshot).toContainYaml(` + - generic [ref=e2]: Hi, I'm frame + `); +}); + +it('should auto-wait for blocking CSS', async ({ page, server }) => { + server.setRoute('/css', (req, res) => { + res.setHeader('Content-Type', 'text/css'); + setTimeout(() => res.end(`body { monospace }`), 1000); + }); + await page.setContent(` + +

Hello World

+ `, { waitUntil: 'commit' }); + expect(await snapshotForAI(page)).toContainYaml('Hello World'); +}); + +it('should show visible children of hidden elements', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/36296' } }, async ({ page }) => { + await page.setContent(` +
+
+ +
+
+ +
+
+
+ +
+ +
+
+ `); + + expect(await snapshotForAI(page)).toEqual(unshift(` + - generic [active] [ref=e1]: + - button "Visible" [ref=e3] + - button "Visible" [ref=e4] + `)); +}); + +it('should include active element information', async ({ page }) => { + await page.setContent(` + + +
Not focusable
+ `); + + // Wait for autofocus to take effect + await page.waitForFunction(() => document.activeElement?.id === 'btn2'); + + const snapshot = await snapshotForAI(page); + + expect(snapshot).toContainYaml(` + - generic [ref=e1]: + - button "Button 1" [ref=e2] + - button "Button 2" [active] [ref=e3] + - generic [ref=e4]: Not focusable + `); +}); + +it('should update active element on focus', async ({ page }) => { + await page.setContent(` + + + `); + + // Initially there shouldn't be an active element on the inputs + const initialSnapshot = await snapshotForAI(page); + expect(initialSnapshot).toContainYaml(` + - generic [active] [ref=e1]: + - textbox "First input" [ref=e2] + - textbox "Second input" [ref=e3] + `); + + // Focus the second input + await page.locator('#input2').focus(); + + // After focus, the second input should be active + const afterFocusSnapshot = await snapshotForAI(page); + + expect(afterFocusSnapshot).toContainYaml(` + - generic [ref=e1]: + - textbox "First input" [ref=e2] + - textbox "Second input" [active] [ref=e3] + `); +}); + +it('should mark iframe as active when it contains focused element', async ({ page }) => { + // Create a simple HTML file for the iframe + await page.setContent(` + + + `); + + // Test 1: Focus the input inside the iframe + await page.frameLocator('iframe').locator('#iframe-input').focus(); + const inputInIframeFocusedSnapshot = await snapshotForAI(page); + + // The iframe should be marked as active when it contains a focused element + expect(inputInIframeFocusedSnapshot).toContainYaml(` + - generic [ref=e1]: + - textbox "Regular input" [ref=e2] + - iframe [active] [ref=e3]: + - textbox "Input in iframe" [active] [ref=f1e2] + `); +}); + +it('return empty snapshot when iframe is not loaded', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/pull/36710' } }, async ({ page, server }) => { + await page.setContent(` +
Test
+ + `); + + // Wait for the iframe to load + await page.waitForSelector('iframe'); + + // Get the snapshot of the page + const snapshot = await snapshotForAI(page, { timeout: 100 }); + + // The iframe should be present but empty + expect(snapshot).toContainYaml(` + - generic [active] [ref=e1]: + - generic [ref=e2]: Test + - iframe [ref=e3] + `); +}); + +it('should support many properties on iframes', async ({ page }) => { + await page.setContent(` + + + `); + + // Test 1: Focus the input inside the iframe + await page.frameLocator('iframe').locator('#iframe-input').focus(); + const inputInIframeFocusedSnapshot = await snapshotForAI(page); + + expect(inputInIframeFocusedSnapshot).toContainYaml(` + - generic [ref=e1]: + - textbox "Regular input" [ref=e2] + - iframe [active] [ref=e3] [cursor=pointer]: + - textbox "Input in iframe" [active] [ref=f1e2] + `); +}); diff --git a/tests/page/page-aria-snapshot.spec.ts b/tests/page/page-aria-snapshot.spec.ts new file mode 100644 index 0000000000000..e08f4830da0f6 --- /dev/null +++ b/tests/page/page-aria-snapshot.spec.ts @@ -0,0 +1,671 @@ +/** + * 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. + */ + +import type { Locator } from '@playwright/test'; +import { test as it, expect, unshift } from './pageTest'; + +async function checkAndMatchSnapshot(locator: Locator, snapshot: string) { + expect.soft(await locator.ariaSnapshot()).toBe(unshift(snapshot)); + await expect.soft(locator).toMatchAriaSnapshot(snapshot); +} + +it('should snapshot', async ({ page }) => { + await page.setContent(`

title

`); + await checkAndMatchSnapshot(page.locator('body'), ` + - heading "title" [level=1] + `); +}); + +it('should snapshot list', async ({ page }) => { + await page.setContent(` +

title

+

title 2

+ `); + await checkAndMatchSnapshot(page.locator('body'), ` + - heading "title" [level=1] + - heading "title 2" [level=1] + `); +}); + +it('should snapshot list with accessible name', async ({ page }) => { + await page.setContent(` +
    +
  • one
  • +
  • two
  • +
+ `); + await checkAndMatchSnapshot(page.locator('body'), ` + - list "my list": + - listitem: one + - listitem: two + `); +}); + +it('should snapshot complex', async ({ page }) => { + await page.setContent(` + + `); + await checkAndMatchSnapshot(page.locator('body'), ` + - list: + - listitem: + - link "link": + - /url: about:blank + `); +}); + +it('should allow text nodes', async ({ page }) => { + await page.setContent(` +

Microsoft

+
Open source projects and samples from Microsoft
+ `); + + await checkAndMatchSnapshot(page.locator('body'), ` + - heading "Microsoft" [level=1] + - text: Open source projects and samples from Microsoft + `); +}); + +it('should snapshot details visibility', async ({ page }) => { + await page.setContent(` +
+ Summary +
Details
+
+ `); + + await checkAndMatchSnapshot(page.locator('body'), ` + - group: Summary + `); +}); + +it('should snapshot integration', async ({ page }) => { + await page.setContent(` +

Microsoft

+
Open source projects and samples from Microsoft
+ `); + + await checkAndMatchSnapshot(page.locator('body'), ` + - heading "Microsoft" [level=1] + - text: Open source projects and samples from Microsoft + - list: + - listitem: + - group: Verified + - listitem: + - link "Sponsor": + - /url: about:blank + `); +}); + +it('should support multiline text', async ({ page }) => { + await page.setContent(` +

+ Line 1 + Line 2 + Line 3 +

+ `); + + await checkAndMatchSnapshot(page.locator('body'), ` + - paragraph: Line 1 Line 2 Line 3 + `); + await expect(page.locator('body')).toMatchAriaSnapshot(` + - paragraph: | + Line 1 + Line 2 + Line 3 + `); +}); + +it('should concatenate span text', async ({ page }) => { + await page.setContent(` + One Two Three + `); + + await checkAndMatchSnapshot(page.locator('body'), ` + - text: One Two Three + `); +}); + +it('should concatenate span text 2', async ({ page }) => { + await page.setContent(` + One Two Three + `); + + await checkAndMatchSnapshot(page.locator('body'), ` + - text: One Two Three + `); +}); + +it('should concatenate div text with spaces', async ({ page }) => { + await page.setContent(` +
One
Two
Three
+ `); + + await checkAndMatchSnapshot(page.locator('body'), ` + - text: One Two Three + `); +}); + +it('should include pseudo in text', async ({ page }) => { + await page.setContent(` + + + hello +
hello
+
+ `); + + await checkAndMatchSnapshot(page.locator('body'), ` + - link "worldhello hellobye": + - /url: about:blank + `); +}); + +it('should not include hidden pseudo in text', async ({ page }) => { + await page.setContent(` + + + hello +
hello
+
+ `); + + await checkAndMatchSnapshot(page.locator('body'), ` + - link "hello hello": + - /url: about:blank + `); +}); + +it('should include new line for block pseudo', async ({ page }) => { + await page.setContent(` + + + hello +
hello
+
+ `); + + await checkAndMatchSnapshot(page.locator('body'), ` + - link "world hello hello bye": + - /url: about:blank + `); +}); + +it('should work with slots', async ({ page }) => { + // Text "foo" is assigned to the slot, should not be used twice. + await page.setContent(` + + + `); + await checkAndMatchSnapshot(page.locator('body'), ` + - button "foo" + `); + + // Text "foo" is assigned to the slot, should be used instead of slot content. + await page.setContent(` +
foo
+ + `); + await checkAndMatchSnapshot(page.locator('body'), ` + - button "foo" + `); + + // Nothing is assigned to the slot, should use slot content. + await page.setContent(` +
+ + `); + await checkAndMatchSnapshot(page.locator('body'), ` + - button "pre" + `); +}); + +it('should snapshot inner text', async ({ page }) => { + await page.setContent(` +
+
+
+ a.test.ts +
+
+ + + +
+
+
+
+
+
+ snapshot +
+
30ms
+
+ + + +
+
+
+ `); + + await checkAndMatchSnapshot(page.locator('body'), ` + - listitem: + - text: a.test.ts + - button "Run" + - button "Show source" + - button "Watch" + - listitem: + - text: snapshot 30ms + - button "Run" + - button "Show source" + - button "Watch" + `); +}); + +it('should include pseudo codepoints', async ({ page, server }) => { + await page.goto(server.EMPTY_PAGE); + await page.setContent(` + +

hello

+ `); + + await checkAndMatchSnapshot(page.locator('body'), ` + - paragraph: \ueab2hello + `); +}); + +it('check aria-hidden text', async ({ page }) => { + await page.setContent(` +

+ hello + +

+ `); + + await checkAndMatchSnapshot(page.locator('body'), ` + - paragraph: hello + `); +}); + +it('should ignore presentation and none roles', async ({ page }) => { + await page.setContent(` +
    +
  • hello
  • +
  • world
  • +
+ `); + + await checkAndMatchSnapshot(page.locator('body'), ` + - list: hello world + `); +}); + +it('should treat input value as text in templates, but not for checkbox/radio/file', async ({ page }) => { + await page.setContent(` + + + + + `); + + await checkAndMatchSnapshot(page.locator('body'), ` + - textbox: hello world + - button "Choose File" + - checkbox [checked] + - radio [checked] + `); +}); + +it('should not use on as checkbox value', async ({ page }) => { + await page.setContent(` + + + `); + + await checkAndMatchSnapshot(page.locator('body'), ` + - checkbox + - radio + `); +}); + +it('should respect aria-owns', async ({ page }) => { + await page.setContent(` + +
Link 1
+
+ +
Link 2
+
+ +

Paragraph

+ `); + + // - Different from Chrome DevTools which attributes ownership to the last element. + // - CDT also does not include non-owned children in accessible name. + // - Disregarding these as aria-owns can't suggest multiple parts by spec. + await checkAndMatchSnapshot(page.locator('body'), ` + - link "Link 1 Value Paragraph": + - /url: about:blank + - region: Link 1 + - textbox: Value + - paragraph: Paragraph + - link "Link 2 Value Paragraph": + - /url: about:blank + - region: Link 2 + `); +}); + +it('should be ok with circular ownership', async ({ page }) => { + await page.setContent(` + +
Hello
+
+ `); + + await checkAndMatchSnapshot(page.locator('body'), ` + - link "Hello": + - /url: about:blank + - region: Hello + `); +}); + +it('should escape yaml text in text nodes', async ({ page }) => { + await page.setContent(` +
+ one: link1 "two link2 'three link3 \`four +
+ +
[Select all]
+ `); + + await checkAndMatchSnapshot(page.locator('body'), ` + - group: + - text: "one:" + - link "link1": + - /url: "#" + - text: "\\\"two" + - link "link2": + - /url: "#" + - text: "'three" + - link "link3": + - /url: "#" + - text: "\`four" + - list: + - link "one": + - /url: "#" + - text: "," + - link "two": + - /url: "#" + - text: ( + - link "three": + - /url: "#" + - text: ") {" + - link "four": + - /url: "#" + - text: "} [" + - link "five": + - /url: "#" + - text: "]" + - text: "[Select all]" + `); +}); + +it('should normalize whitespace', async ({ page }) => { + await page.setContent(` +
+ one \n two link  \n 1 +
+ + + `); + + await checkAndMatchSnapshot(page.locator('body'), ` + - group: + - text: one two + - link "link 1": + - /url: "#" + - textbox: hello world + - button "helloworld" + `); + + // Weird whitespace in the template should be normalized. + await expect(page.locator('body')).toMatchAriaSnapshot(` + - group: + - text: | + one + two + - link " link 1 ": + - /url: "#" + - textbox: hello world + - button "he\u00adlloworld\u200b" + `); +}); + +it('should handle long strings', async ({ page }) => { + const s = 'a'.repeat(10000); + await page.setContent(` + +
${s}
+
+ `); + + await checkAndMatchSnapshot(page.locator('body'), ` + - link: + - /url: about:blank + - region: ${s} + `); +}); + +it('should escape special yaml characters', async ({ page }) => { + await page.setContent(` + @hello@hello + ]hello]hello + hello\n + hello\n\n hello\n hello + #hello#hello + `); + + await checkAndMatchSnapshot(page.locator('body'), ` + - link "@hello": + - /url: "#" + - text: "@hello" + - link "]hello": + - /url: "#" + - text: "]hello" + - link "hello": + - /url: "#" + - text: hello + - link "hello": + - /url: "#" + - text: hello + - link "#hello": + - /url: "#" + - text: "#hello" + `); +}); + +it('should escape special yaml values', async ({ page }) => { + await page.setContent(` + trueFalse + NOyes + yN + onOff + nullNULL + 123123 + -1.2-1.2 + -- + + `); + + await checkAndMatchSnapshot(page.locator('body'), ` + - link "true": + - /url: "#" + - text: "False" + - link "NO": + - /url: "#" + - text: "yes" + - link "y": + - /url: "#" + - text: "N" + - link "on": + - /url: "#" + - text: "Off" + - link "null": + - /url: "#" + - text: "NULL" + - link "123": + - /url: "#" + - text: "123" + - link "-1.2": + - /url: "#" + - text: "-1.2" + - link "-": + - /url: "#" + - text: "-" + - textbox: "555" + `); +}); + +it('should not report textarea textContent', async ({ page }) => { + await page.setContent(``); + await checkAndMatchSnapshot(page.locator('body'), ` + - textbox: Before + `); + await page.evaluate(() => { + document.querySelector('textarea').value = 'After'; + }); + await checkAndMatchSnapshot(page.locator('body'), ` + - textbox: After + `); +}); + +it('should not show visible children of hidden elements', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/36296' } }, async ({ page }) => { + await page.setContent(` +
+
+ +
+
+ `); + + expect(await page.locator('body').ariaSnapshot()).toBe(''); +}); + +it('should not show unhidden children of aria-hidden elements', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/36296' } }, async ({ page }) => { + await page.setContent(` + + `); + + expect(await page.locator('body').ariaSnapshot()).toBe(''); +}); diff --git a/tests/page/page-autowaiting-basic.spec.ts b/tests/page/page-autowaiting-basic.spec.ts index a2104530ef8ec..dbfe482c33492 100644 --- a/tests/page/page-autowaiting-basic.spec.ts +++ b/tests/page/page-autowaiting-basic.spec.ts @@ -15,6 +15,7 @@ * limitations under the License. */ +import { stripAnsi } from 'tests/config/utils'; import type { TestServer } from '../config/testserver'; import { test as it, expect } from './pageTest'; @@ -139,3 +140,21 @@ it('should report navigation in the log when clicking anchor', async ({ page, se expect(error.message).toContain('waiting for scheduled navigations to finish'); expect(error.message).toContain(`navigated to "${server.PREFIX + '/frames/one-frame.html'}"`); }); + +it('should report and collapse log in action', async ({ page, server, mode }) => { + await page.setContent(``); + const error = await page.locator('input').click({ timeout: 5000 }).catch(e => e); + const message = stripAnsi(error.message); + expect(message).toContain(`Call log:`); + expect(message).toMatch(/\d+ × waiting for/); + const logLines = message.substring(message.indexOf('Call log:')).split('\n'); + expect(logLines.length).toBeLessThan(30); +}); + +it('should report and collapse log in expect', async ({ page, server, mode }) => { + await page.setContent(``); + const error = await expect(page.locator('input')).toBeVisible({ timeout: 5000 }).catch(e => e); + const message = stripAnsi(error.message); + expect(message).toContain(`Call log:`); + expect(message).toMatch(/\d+ × locator resolved to/); +}); diff --git a/tests/page/page-autowaiting-no-hang.spec.ts b/tests/page/page-autowaiting-no-hang.spec.ts index f580b8629a142..1fba6fbfefd9e 100644 --- a/tests/page/page-autowaiting-no-hang.spec.ts +++ b/tests/page/page-autowaiting-no-hang.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { test as it } from './pageTest'; +import { test as it, expect } from './pageTest'; it('clicking on links which do not commit navigation', async ({ page, server, httpsServer }) => { await page.goto(server.EMPTY_PAGE); @@ -31,7 +31,7 @@ it('calling window.stop async', async ({ page, server }) => { }, server.EMPTY_PAGE); }); -it('calling window.stop sync', async ({ page, server }) => { +it('calling window.stop sync', async ({ page, server, browserName }) => { await page.evaluate(url => { window.location.href = url; window.stop(); @@ -65,3 +65,78 @@ it('opening a popup', async function({ page, server }) { page.evaluate(() => window.open(window.location.href) && 1), ]); }); + +it('clicking in the middle of navigation that aborts', async ({ page, server }) => { + let abortCallback; + const abortPromise = new Promise(f => abortCallback = f); + + let stallCallback; + const stallPromise = new Promise(f => stallCallback = f); + + server.setRoute('/stall.html', async (req, res) => { + stallCallback(); + await abortPromise; + req.socket.destroy(); + }); + + await page.goto(server.PREFIX + '/one-style.html'); + page.goto(server.PREFIX + '/stall.html').catch(() => {}); + await stallPromise; + + const clickPromise = page.click('body'); + await page.waitForTimeout(1000); + abortCallback(); + + await clickPromise; +}); + +it('clicking in the middle of navigation that commits', async ({ page, server }) => { + let commitCallback; + const abortPromise = new Promise(f => commitCallback = f); + + let stallCallback; + const stallPromise = new Promise(f => stallCallback = f); + + server.setRoute('/stall.html', async (req, res) => { + stallCallback(); + await abortPromise; + res.writeHead(200, { 'Content-Type': 'text/html' }); + res.end('hello world'); + }); + + await page.goto(server.PREFIX + '/one-style.html'); + page.goto(server.PREFIX + '/stall.html').catch(() => {}); + await stallPromise; + + const clickPromise = page.click('body'); + await page.waitForTimeout(1000); + commitCallback(); + + await clickPromise; + await expect(page.locator('body')).toContainText('hello world'); +}); + +it('goBack in the middle of navigation that commits', async ({ page, server }) => { + let commitCallback; + const abortPromise = new Promise(f => commitCallback = f); + + let stallCallback; + const stallPromise = new Promise(f => stallCallback = f); + + server.setRoute('/stall.html', async (req, res) => { + stallCallback(); + await abortPromise; + res.writeHead(200, { 'Content-Type': 'text/html' }); + res.end('hello world'); + }); + + await page.goto(server.PREFIX + '/one-style.html'); + page.goto(server.PREFIX + '/stall.html').catch(() => {}); + await stallPromise; + + const goBackPromise = page.goBack().catch(() => {}); + await page.waitForTimeout(1000); + commitCallback(); + + await goBackPromise; +}); diff --git a/tests/page/page-basic.spec.ts b/tests/page/page-basic.spec.ts index 0b99d0c8c5f64..d8e8d40dec7ce 100644 --- a/tests/page/page-basic.spec.ts +++ b/tests/page/page-basic.spec.ts @@ -15,66 +15,8 @@ * limitations under the License. */ -import { kTargetClosedErrorMessage } from '../config/errors'; import { test as it, expect } from './pageTest'; -it('should reject all promises when page is closed', async ({ page, isWebView2, isAndroid }) => { - it.skip(isWebView2, 'Page.close() is not supported in WebView2'); - it.fixme(isAndroid, '"Target crashed" instead of "Target closed"'); - - let error = null; - await Promise.all([ - page.evaluate(() => new Promise(r => {})).catch(e => error = e), - page.close(), - ]); - expect(error.message).toContain(kTargetClosedErrorMessage); -}); - -it('should set the page close state', async ({ page, isWebView2 }) => { - it.skip(isWebView2, 'Page.close() is not supported in WebView2'); - - expect(page.isClosed()).toBe(false); - await page.close(); - expect(page.isClosed()).toBe(true); -}); - -it('should pass page to close event', async ({ page, isAndroid, isWebView2 }) => { - it.fixme(isAndroid); - it.skip(isWebView2, 'Page.close() is not supported in WebView2'); - - const [closedPage] = await Promise.all([ - page.waitForEvent('close'), - page.close() - ]); - expect(closedPage).toBe(page); -}); - -it('should terminate network waiters', async ({ page, server, isAndroid, isWebView2 }) => { - it.fixme(isAndroid); - it.skip(isWebView2, 'Page.close() is not supported in WebView2'); - - const results = await Promise.all([ - page.waitForRequest(server.EMPTY_PAGE).catch(e => e), - page.waitForResponse(server.EMPTY_PAGE).catch(e => e), - page.close() - ]); - for (let i = 0; i < 2; i++) { - const message = results[i].message; - expect(message).toContain(kTargetClosedErrorMessage); - expect(message).not.toContain('Timeout'); - } -}); - -it('should be callable twice', async ({ page, isWebView2 }) => { - it.skip(isWebView2, 'Page.close() is not supported in WebView2'); - - await Promise.all([ - page.close(), - page.close(), - ]); - await page.close(); -}); - it('should fire load when expected', async ({ page }) => { await Promise.all([ page.goto('about:blank'), @@ -101,18 +43,6 @@ it('should provide access to the opener page', async ({ page }) => { expect(opener).toBe(page); }); -it('should return null if parent page has been closed', async ({ page, isWebView2 }) => { - it.skip(isWebView2, 'Page.close() is not supported in WebView2'); - - const [popup] = await Promise.all([ - page.waitForEvent('popup'), - page.evaluate(() => window.open('about:blank')), - ]); - await page.close(); - const opener = await popup.opener(); - expect(opener).toBe(null); -}); - it('should fire domcontentloaded when expected', async ({ page }) => { const navigatedPromise = page.goto('about:blank'); await page.waitForEvent('domcontentloaded'); @@ -135,17 +65,6 @@ it('should pass self as argument to load event', async ({ page }) => { expect(eventArg).toBe(page); }); -it('should fail with error upon disconnect', async ({ page, isAndroid, isWebView2 }) => { - it.skip(isWebView2, 'Page.close() is not supported in WebView2'); - it.fixme(isAndroid); - - let error; - const waitForPromise = page.waitForEvent('download').catch(e => error = e); - await page.close(); - await waitForPromise; - expect(error.message).toContain(kTargetClosedErrorMessage); -}); - it('page.url should work', async ({ page, server }) => { expect(page.url()).toBe('about:blank'); await page.goto(server.EMPTY_PAGE); @@ -175,14 +94,6 @@ it('page.close should work with window.close', async function({ page }) { await closedPromise; }); -it('page.close should work with page.close', async function({ page, isWebView2 }) { - it.skip(isWebView2, 'Page.close() is not supported in WebView2'); - - const closedPromise = new Promise(x => page.on('close', x)); - await page.close(); - await closedPromise; -}); - it('page.frame should respect name', async function({ page }) { await page.setContent(``); expect(page.frame({ name: 'bogus' })).toBe(null); diff --git a/tests/page/page-click-react.spec.ts b/tests/page/page-click-react.spec.ts index 35626910c10e7..f1ee9af3da4bb 100644 --- a/tests/page/page-click-react.spec.ts +++ b/tests/page/page-click-react.spec.ts @@ -21,47 +21,6 @@ declare const renderComponent; declare const e; declare const MyButton; -it('should report that selector does not match anymore', async ({ page, server }) => { - it.fixme(); - - await page.goto(server.PREFIX + '/react.html'); - await page.evaluate(() => { - renderComponent(e('div', {}, [e(MyButton, { name: 'button1' }), e(MyButton, { name: 'button2' })])); - }); - const __testHookAfterStable = () => page.evaluate(() => { - window['counter'] = (window['counter'] || 0) + 1; - if (window['counter'] === 1) - renderComponent(e('div', {}, [e(MyButton, { name: 'button2' }), e(MyButton, { name: 'button1' })])); - else - renderComponent(e('div', {}, [])); - }); - const error = await page.dblclick('text=button1', { __testHookAfterStable, timeout: 3000 } as any).catch(e => e); - expect(await page.evaluate('window.button1')).toBe(undefined); - expect(await page.evaluate('window.button2')).toBe(undefined); - expect(error.message).toContain('page.dblclick: Timeout 3000ms exceeded.'); - expect(error.message).toContain('element does not match the selector anymore'); -}); - -it('should not retarget the handle when element is recycled', async ({ page, server }) => { - it.fixme(); - - await page.goto(server.PREFIX + '/react.html'); - await page.evaluate(() => { - renderComponent(e('div', {}, [e(MyButton, { name: 'button1' }), e(MyButton, { name: 'button2', disabled: true })])); - }); - const __testHookBeforeStable = () => page.evaluate(() => { - window['counter'] = (window['counter'] || 0) + 1; - if (window['counter'] === 1) - renderComponent(e('div', {}, [e(MyButton, { name: 'button2', disabled: true }), e(MyButton, { name: 'button1' })])); - }); - const handle = await page.$('text=button1'); - const error = await handle.click({ __testHookBeforeStable, timeout: 3000 } as any).catch(e => e); - expect(await page.evaluate('window.button1')).toBe(undefined); - expect(await page.evaluate('window.button2')).toBe(undefined); - expect(error.message).toContain('elementHandle.click: Timeout 3000ms exceeded.'); - expect(error.message).toContain('element is disabled - waiting'); -}); - it('should timeout when click opens alert', async ({ page, server }) => { const dialogPromise = page.waitForEvent('dialog'); await page.setContent(`
Click me
`); @@ -71,40 +30,6 @@ it('should timeout when click opens alert', async ({ page, server }) => { await dialog.dismiss(); }); -it('should retarget when element is recycled during hit testing', async ({ page, server }) => { - it.fixme(); - - await page.goto(server.PREFIX + '/react.html'); - await page.evaluate(() => { - renderComponent(e('div', {}, [e(MyButton, { name: 'button1' }), e(MyButton, { name: 'button2' })])); - }); - const __testHookAfterStable = () => page.evaluate(() => { - window['counter'] = (window['counter'] || 0) + 1; - if (window['counter'] === 1) - renderComponent(e('div', {}, [e(MyButton, { name: 'button2' }), e(MyButton, { name: 'button1' })])); - }); - await page.click('text=button1', { __testHookAfterStable } as any); - expect(await page.evaluate('window.button1')).toBe(true); - expect(await page.evaluate('window.button2')).toBe(undefined); -}); - -it('should retarget when element is recycled before enabled check', async ({ page, server }) => { - it.fixme(); - - await page.goto(server.PREFIX + '/react.html'); - await page.evaluate(() => { - renderComponent(e('div', {}, [e(MyButton, { name: 'button1' }), e(MyButton, { name: 'button2', disabled: true })])); - }); - const __testHookBeforeStable = () => page.evaluate(() => { - window['counter'] = (window['counter'] || 0) + 1; - if (window['counter'] === 1) - renderComponent(e('div', {}, [e(MyButton, { name: 'button2', disabled: true }), e(MyButton, { name: 'button1' })])); - }); - await page.click('text=button1', { __testHookBeforeStable } as any); - expect(await page.evaluate('window.button1')).toBe(true); - expect(await page.evaluate('window.button2')).toBe(undefined); -}); - it('should not retarget when element changes on hover', async ({ page, server }) => { await page.goto(server.PREFIX + '/react.html'); await page.evaluate(() => { diff --git a/tests/page/page-click-scroll.spec.ts b/tests/page/page-click-scroll.spec.ts index 758a8d0eb95e3..d3e55cdffbc42 100644 --- a/tests/page/page-click-scroll.spec.ts +++ b/tests/page/page-click-scroll.spec.ts @@ -78,9 +78,8 @@ it('should scroll into view display:contents with position', async ({ page, brow expect(await page.evaluate('window._clicked')).toBe(true); }); -it('should not crash when force-clicking hidden input', async ({ page, isWebView2 }) => { +it('should not crash when force-clicking hidden input', async ({ page }) => { it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/18183' }); - it.fixme(isWebView2); await page.setContent(``); const error = await page.locator('input').click({ force: true, timeout: 2000 }).catch(e => e); diff --git a/tests/page/page-click-timeout-4.spec.ts b/tests/page/page-click-timeout-4.spec.ts index d00cc62c37abb..a973061ed81ea 100644 --- a/tests/page/page-click-timeout-4.spec.ts +++ b/tests/page/page-click-timeout-4.spec.ts @@ -48,3 +48,52 @@ it('should click for the second time after first timeout', async ({ page, server await page.click('button'); expect(await page.evaluate('result')).toBe('Clicked'); }); + +it('should fail to click the button behind a large header after scrolling around', async ({ page, isAndroid }) => { + it.skip(isAndroid, 'Different viewport size'); + await page.setViewportSize({ width: 500, height: 240 }); + await page.setContent(` + + +
+ +
    +
  1. hi1
  2. hi2
  3. hi3
  4. hi4
  5. hi5
  6. hi6
  7. hi7
  8. hi8
  9. +
  10. hi9
  11. +
  12. hi10
  13. hi11
  14. hi12
  15. hi13
  16. hi14
  17. +
+ + + `); + await page.$eval('#li14', e => e.scrollIntoView()); + const error = await page.click('#target', { timeout: 1500 }).catch(e => e); + expect(error.message).toContain(`
intercepts pointer events`); + expect(await page.evaluate(() => window['__clicked'])).toBe(undefined); + const scrollTops = await page.evaluate(() => window['scrollTops']); + const distinct = new Set(scrollTops); + expect(distinct.size).toBeGreaterThan(2); // At least three different scroll positions. +}); diff --git a/tests/page/page-click.spec.ts b/tests/page/page-click.spec.ts index aa02d210ebfe0..f048ea6c5710b 100644 --- a/tests/page/page-click.spec.ts +++ b/tests/page/page-click.spec.ts @@ -57,7 +57,7 @@ it('should issue clicks in parallel in page and popup', async ({ page, server }) it('should click svg', async ({ page }) => { await page.setContent(` - + `); await page.click('circle'); @@ -79,23 +79,44 @@ it('should click on a span with an inline element inside', async ({ page }) => { content: 'q'; } - + `); await page.click('span'); expect(await page.evaluate('CLICKED')).toBe(42); }); -it('should not throw UnhandledPromiseRejection when page closes', async ({ page, isWebView2 }) => { - it.skip(isWebView2, 'Page.close() is not supported in WebView2'); +it('should click the aligned 1x1 div', async ({ page }) => { + await page.setContent(`
`); + await page.click('div'); + expect(await page.evaluate('window.__clicked')).toBe(true); +}); - await Promise.all([ - page.close(), - page.mouse.click(1, 2), - ]).catch(e => {}); +it('should click the half-aligned 1x1 div', async ({ page }) => { + await page.setContent(`
`); + await page.click('div'); + expect(await page.evaluate('window.__clicked')).toBe(true); }); -it('should click the 1x1 div', async ({ page }) => { - await page.setContent(`
`); +it('should click the unaligned 1x1 div v1', async ({ page }) => { + await page.setContent(`
`); + await page.click('div'); + expect(await page.evaluate('window.__clicked')).toBe(true); +}); + +it('should click the unaligned 1x1 div v2', async ({ page }) => { + await page.setContent(`
`); + await page.click('div'); + expect(await page.evaluate('window.__clicked')).toBe(true); +}); + +it('should click the unaligned 1x1 div v3', async ({ page }) => { + await page.setContent(`
`); + await page.click('div'); + expect(await page.evaluate('window.__clicked')).toBe(true); +}); + +it('should click the unaligned 1x1 div v4', async ({ page }) => { + await page.setContent(`
`); await page.click('div'); expect(await page.evaluate('window.__clicked')).toBe(true); }); @@ -124,7 +145,7 @@ it('should click when one of inline box children is outside of viewport', async top: -1000px; } - woofdoggo + woofdoggo `); await page.click('span'); expect(await page.evaluate('CLICKED')).toBe(42); @@ -336,7 +357,7 @@ it('should click the button inside an iframe', async ({ page, server }) => { }); it('should click the button with fixed position inside an iframe', async ({ page, server, browserName }) => { - it.fixme(browserName === 'chromium' || browserName === 'webkit'); + it.fixme(browserName === 'chromium'); // @see https://github.com/GoogleChrome/puppeteer/issues/4110 // @see https://bugs.chromium.org/p/chromium/issues/detail?id=986390 @@ -388,6 +409,54 @@ it('should click the button behind sticky header', async ({ page }) => { expect(await page.evaluate(() => window['__clicked'])).toBe(true); }); +it('should click the button behind position:absolute header', { + annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/36339' }, +}, async ({ page }) => { + await page.setViewportSize({ width: 500, height: 240 }); + await page.setContent(` + + +
    +
  1. hi1
  2. hi2
  3. hi3
  4. hi4
  5. hi5
  6. hi6
  7. hi7
  8. hi8
  9. +
  10. hi9
  11. +
  12. hi10
  13. hi11
  14. hi12
  15. hi13
  16. hi14
  17. +
+ +
Overlay
+ `); + await page.$eval('ol', e => { + const target = document.querySelector('#target') as HTMLElement; + e.scrollTo({ top: target.offsetTop, behavior: 'instant' }); + }); + await page.click('#target'); + expect(await page.evaluate(() => window['__clicked'])).toBe(true); +}); + it('should click the button with px border with offset', async ({ page, server, browserName }) => { await page.goto(server.PREFIX + '/input/button.html'); await page.$eval('button', button => button.style.borderWidth = '8px'); @@ -409,7 +478,8 @@ it('should click the button with em border with offset', async ({ page, server, expect(await page.evaluate('offsetY')).toBe(browserName === 'webkit' ? 12 * 2 + 10 : 10); }); -it('should click a very large button with offset', async ({ page, server, browserName }) => { +it('should click a very large button with offset', async ({ page, server, browserName, isAndroid }) => { + it.fixme(isAndroid, 'Failed to scroll to a particular point'); await page.goto(server.PREFIX + '/input/button.html'); await page.$eval('button', button => button.style.borderWidth = '8px'); await page.$eval('button', button => button.style.height = button.style.width = '2000px'); @@ -420,7 +490,8 @@ it('should click a very large button with offset', async ({ page, server, browse expect(await page.evaluate('offsetY')).toBe(browserName === 'webkit' ? 1910 + 8 : 1910); }); -it('should click a button in scrolling container with offset', async ({ page, server, browserName }) => { +it('should click a button in scrolling container with offset', async ({ page, server, browserName, isAndroid }) => { + it.fixme(isAndroid, 'Failed to scroll to a particular point'); await page.goto(server.PREFIX + '/input/button.html'); await page.$eval('button', button => { const container = document.createElement('div'); @@ -573,7 +644,7 @@ it('should fail when obscured and not waiting for hit target', async ({ page, se }); it('should wait for button to be enabled', async ({ page }) => { - await page.setContent(''); + await page.setContent(''); let done = false; const clickPromise = page.click('text=Click target').then(() => done = true); await giveItAChanceToClick(page); @@ -585,7 +656,7 @@ it('should wait for button to be enabled', async ({ page }) => { }); it('should wait for input to be enabled', async ({ page }) => { - await page.setContent(''); + await page.setContent(''); let done = false; const clickPromise = page.click('input').then(() => done = true); await giveItAChanceToClick(page); @@ -617,13 +688,13 @@ it('should wait for select to be enabled', async ({ page }) => { }); it('should click disabled div', async ({ page }) => { - await page.setContent('
Click target
'); + await page.setContent('
Click target
'); await page.click('text=Click target'); expect(await page.evaluate('__CLICKED')).toBe(true); }); it('should wait for BUTTON to be clickable when it has pointer-events:none', async ({ page }) => { - await page.setContent(''); + await page.setContent(''); let done = false; const clickPromise = page.click('text=Click target').then(() => done = true); await giveItAChanceToClick(page); @@ -635,7 +706,7 @@ it('should wait for BUTTON to be clickable when it has pointer-events:none', asy }); it('should wait for LABEL to be clickable when it has pointer-events:none', async ({ page }) => { - await page.setContent(''); + await page.setContent(''); const clickPromise = page.click('text=Click target'); // Do a few roundtrips to the page. for (let i = 0; i < 5; ++i) @@ -880,13 +951,13 @@ it('should not hang when frame is detached', async ({ page, server, mode }) => { }); it('should climb dom for inner label with pointer-events:none', async ({ page }) => { - await page.setContent(''); + await page.setContent(''); await page.click('text=Click target'); expect(await page.evaluate('__CLICKED')).toBe(true); }); it('should climb up to [role=button]', async ({ page }) => { - await page.setContent('
Click target
'); + await page.setContent('
Click target
'); await page.click('text=Click target'); expect(await page.evaluate('__CLICKED')).toBe(true); }); @@ -894,13 +965,13 @@ it('should climb up to [role=button]', async ({ page }) => { it('should climb up to a anchor', async ({ page }) => { // For Firefox its not allowed to return anything: https://bugzilla.mozilla.org/show_bug.cgi?id=1392046 // Note the intermediate div - it is necessary, otherwise is not recognized as a clickable link. - await page.setContent(`
Inner
`); + await page.setContent(`
Inner
`); await page.click('#inner'); expect(await page.evaluate('__CLICKED')).toBe(true); }); it('should climb up to a [role=link]', async ({ page }) => { - await page.setContent(`
Inner
`); + await page.setContent(`
Inner
`); await page.click('#inner'); expect(await page.evaluate('__CLICKED')).toBe(true); }); @@ -1070,7 +1141,7 @@ it('ensure events are dispatched in the individual tasks', async ({ page, browse function onClick(name) { console.log(`click ${name}`); - window.builtinSetTimeout(function() { + window.builtins.setTimeout(function() { console.log(`timeout ${name}`); }, 0); @@ -1114,7 +1185,7 @@ it('should click if opened select covers the button', async ({ page }) => {
- +
`); await page.click('select'); @@ -1144,3 +1215,49 @@ it('should fire contextmenu event on right click in correct order', async ({ pag 'contextmenu', ]); }); + +it('should set PointerEvent.pressure on pointerdown', async ({ page, isLinux, headless }) => { + it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/35844' }); + it.fixme(isLinux && !headless, 'Stray mouse events on Linux headed mess up the tests.'); + await page.setContent(` + + + `); + await page.click('button'); + expect(await page.evaluate(() => window['pressures'])).toEqual([ + ['pointerdown', 0.5], + ['pointerup', 0], + ]); +}); + +it('should set PointerEvent.pressure on pointermove', async ({ page, isLinux, headless, isWindows, browserName, isAndroid }) => { + it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/35844' }); + it.fixme(isLinux && !headless, 'Stray mouse events on Linux headed mess up the tests.'); + it.fixme(isWindows && !headless && browserName === 'webkit', 'WebKit win also send stray mouse events.'); + it.fixme(isAndroid, 'Android coordinates seem to have rounding issues.'); + await page.setContent(` + +
+ + + `); + await page.click('div#target'); + await page.mouse.move(10, 10); + await page.mouse.down(); + await page.mouse.move(250, 250); + await page.mouse.up(); + await page.mouse.move(50, 50); + expect(await page.evaluate(() => window['pressures'])).toEqual([ + [0, 250, 250], + [0, 10, 10], + [0.5, 250, 250], + [0, 50, 50], + ]); +}); diff --git a/tests/page/page-close.spec.ts b/tests/page/page-close.spec.ts deleted file mode 100644 index c1123b819071d..0000000000000 --- a/tests/page/page-close.spec.ts +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Copyright 2017 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. - */ - -import { test as it, expect } from './pageTest'; - -it.skip(({ isWebView2 }) => isWebView2, 'Page.close() is not supported in WebView2'); - -it('should close page with active dialog', async ({ page }) => { - await page.evaluate('"trigger builtinSetTimeout"'); - await page.setContent(``); - void page.click('button').catch(() => {}); - await page.waitForEvent('dialog'); - await page.close(); -}); - -it('should not accept dialog after close', async ({ page, mode }) => { - it.fixme(mode.startsWith('service2'), 'Times out'); - const promise = page.waitForEvent('dialog'); - page.evaluate(() => alert()).catch(() => {}); - const dialog = await promise; - await page.close(); - const e = await dialog.dismiss().catch(e => e); - expect(e.message).toContain('Target page, context or browser has been closed'); -}); diff --git a/tests/page/page-dialog.spec.ts b/tests/page/page-dialog.spec.ts index 61499890817fa..657653a577b74 100644 --- a/tests/page/page-dialog.spec.ts +++ b/tests/page/page-dialog.spec.ts @@ -67,7 +67,7 @@ it('should dismiss the confirm prompt', async ({ page }) => { it('should be able to close context with open alert', async ({ page }) => { const alertPromise = page.waitForEvent('dialog'); await page.evaluate(() => { - window.builtinSetTimeout(() => alert('hello'), 0); + window.builtins.setTimeout(() => alert('hello'), 0); }); await alertPromise; }); diff --git a/tests/page/page-dispatchevent.spec.ts b/tests/page/page-dispatchevent.spec.ts index d4d780c190407..4ad21e2c16353 100644 --- a/tests/page/page-dispatchevent.spec.ts +++ b/tests/page/page-dispatchevent.spec.ts @@ -119,7 +119,7 @@ it('should be atomic', async ({ playwright, page }) => { } }); await playwright.selectors.register('dispatchEvent', createDummySelector); - await page.setContent(`
Hello
`); + await page.goto(`data:text/html,
Hello
`); await page.dispatchEvent('dispatchEvent=div', 'click'); expect(await page.evaluate(() => window['_clicked'])).toBe(true); }); diff --git a/tests/page/page-drag.spec.ts b/tests/page/page-drag.spec.ts index c227978f23268..e7e3d178378f3 100644 --- a/tests/page/page-drag.spec.ts +++ b/tests/page/page-drag.spec.ts @@ -358,7 +358,7 @@ it('should report event.buttons', async ({ page, browserName }) => { function onEvent(event) { logs.push({ type: event.type, buttons: event.buttons }); } - await new Promise(window.builtinRequestAnimationFrame); + await new Promise(window.builtins.requestAnimationFrame); return logs; }); await page.mouse.move(20, 20); diff --git a/tests/page/page-emulate-media.spec.ts b/tests/page/page-emulate-media.spec.ts index c895d64eff789..734bda766b1ca 100644 --- a/tests/page/page-emulate-media.spec.ts +++ b/tests/page/page-emulate-media.spec.ts @@ -15,7 +15,24 @@ * limitations under the License. */ -import { test as it, expect } from './pageTest'; +import type { Page } from 'packages/playwright-test'; +import { test as it, expect as baseExpect } from './pageTest'; + +const expect = baseExpect.extend({ + async toMatchMedia(page: Page, mediaQuery: string) { + const pass = await page.evaluate(mediaQuery => matchMedia(mediaQuery).matches, mediaQuery).catch(() => false); + return { + message() { + if (pass) + return `Expected "${mediaQuery}" not to match, but it did`; + else + return `Expected "${mediaQuery}" to match, but it did not`; + }, + pass, + name: 'toMatchMedia', + }; + }, +}); it('should emulate type @smoke', async ({ page }) => { expect(await page.evaluate(() => matchMedia('screen').matches)).toBe(true); @@ -158,3 +175,15 @@ it('should emulate forcedColors ', async ({ page, browserName }) => { await page.emulateMedia({ forcedColors: null }); expect(await page.evaluate(() => matchMedia('(forced-colors: none)').matches)).toBe(true); }); + +it('should emulate contrast ', async ({ page }) => { + await expect(page).toMatchMedia('(prefers-contrast: no-preference)'); + await page.emulateMedia({ contrast: 'no-preference' }); + await expect(page).toMatchMedia('(prefers-contrast: no-preference)'); + await expect(page).not.toMatchMedia('(prefers-contrast: more)'); + await page.emulateMedia({ contrast: 'more' }); + await expect(page).not.toMatchMedia('(prefers-contrast: no-preference)'); + await expect(page).toMatchMedia('(prefers-contrast: more)'); + await page.emulateMedia({ contrast: null }); + await expect(page).toMatchMedia('(prefers-contrast: no-preference)'); +}); diff --git a/tests/page/page-evaluate.spec.ts b/tests/page/page-evaluate.spec.ts index f0a97cf3262fe..d1598f150ef78 100644 --- a/tests/page/page-evaluate.spec.ts +++ b/tests/page/page-evaluate.spec.ts @@ -94,6 +94,27 @@ it('should transfer arrays as arrays, not objects', async ({ page }) => { expect(result).toBe(true); }); +it('should transfer typed arrays', async ({ page }) => { + const testCases = [ + new Int8Array([1, 2, 3]), + new Uint8Array([1, 2, 3]), + new Uint8ClampedArray([1, 2, 3]), + new Int16Array([1, 2, 3]), + new Uint16Array([1, 2, 3]), + new Int32Array([1, 2, 3]), + new Uint32Array([1, 2, 3]), + new Float32Array([1.1, 2.2, 3.3]), + new Float64Array([1.1, 2.2, 3.3]), + new BigInt64Array([1n, 2n, 3n]), + new BigUint64Array([1n, 2n, 3n]) + ]; + + for (const typedArray of testCases) { + const result = await page.evaluate(a => a, typedArray); + expect(result).toEqual(typedArray); + } +}); + it('should transfer bigint', async ({ page }) => { expect(await page.evaluate(() => 42n)).toBe(42n); expect(await page.evaluate(a => a, 17n)).toBe(17n); @@ -349,10 +370,10 @@ it('should properly serialize null fields', async ({ page }) => { it('should properly serialize PerformanceMeasure object', async ({ page }) => { expect(await page.evaluate(() => { - window.builtinPerformance.mark('start'); - window.builtinPerformance.mark('end'); - window.builtinPerformance.measure('my-measure', 'start', 'end'); - return window.builtinPerformance.getEntriesByType('measure'); + window.builtins.performance.mark('start'); + window.builtins.performance.mark('end'); + window.builtins.performance.measure('my-measure', 'start', 'end'); + return window.builtins.performance.getEntriesByType('measure'); })).toEqual([{ duration: expect.any(Number), entryType: 'measure', @@ -400,6 +421,41 @@ it('should return undefined for non-serializable objects', async ({ page }) => { expect(await page.evaluate(() => function() {})).toBe(undefined); }); +it('should throw for too deep reference chain', { + annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/33997' } +}, async ({ page, browserName }) => { + it.fixme(browserName === 'firefox', 'Firefox Juggler -> Playwright serialiser does not throw for deep references.\nThis causes large objects to get serialised back to the Playwright client.\nThere our validators throw \'Maximum call stack size exceeded\'.'); + await expect(page.evaluate(depth => { + const obj = {}; + let temp = obj; + for (let i = 0; i < depth; i++) { + temp[i] = {}; + temp = temp[i]; + } + return obj; + }, 1000)).rejects.toThrow('Cannot serialize result: object reference chain is too long.'); +}); + +it('should throw usable message for unserializable shallow function', async ({ page }) => { + await expect(() => page.evaluate(arg => arg, () => { })) + .rejects.toThrow(/Attempting to serialize unexpected value: \(\) => {}/); +}); + +it('should throw usable message for unserializable object one deep function', async ({ page }) => { + await expect(() => page.evaluate(arg => arg, { aProperty: () => { } })) + .rejects.toThrow(/Attempting to serialize unexpected value at position "aProperty": \(\) => {}/); +}); + +it('should throw usable message for unserializable object nested function', async ({ page }) => { + await expect(() => page.evaluate(arg => arg, { a: { inner: { property: () => { } } } })) + .rejects.toThrow(/Attempting to serialize unexpected value at position "a\.inner\.property": \(\) => {}/); +}); + +it('should throw usable message for unserializable array nested function', async ({ page }) => { + await expect(() => page.evaluate(arg => arg, { a: { inner: ['firstValue', { property: () => { } }] } })) + .rejects.toThrow(/Attempting to serialize unexpected value at position "a\.inner\[1\]\.property": \(\) => {}/); +}); + it('should alias Window, Document and Node', async ({ page }) => { const object = await page.evaluate('[window, document, document.body]'); expect(object).toEqual(['ref: ', 'ref: ', 'ref: ']); @@ -793,3 +849,17 @@ it('should work with Array.from/map', async ({ page }) => { return r('([a-f0-9]{2})', 3); })).toBe('([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})'); }); + +it('should ignore dangerous object keys', async ({ page }) => { + const input = { + __proto__: { polluted: true }, + safeKey: 'safeValue' + }; + const result = await page.evaluate(arg => arg, input); + expect(result).toEqual({ safeKey: 'safeValue' }); +}); + +it('should allow calling _evaluateFunction', async ({ page }) => { + const result = await (page as any)._evaluateFunction('() => 7 * 3'); + expect(result).toBe(21); +}); diff --git a/tests/page/page-event-console.spec.ts b/tests/page/page-event-console.spec.ts index ee47e81e02ef3..d37b28e734979 100644 --- a/tests/page/page-event-console.spec.ts +++ b/tests/page/page-event-console.spec.ts @@ -97,9 +97,9 @@ it('should format the message correctly with time/timeLog/timeEnd', async ({ pag page.on('console', msg => messages.push(msg)); await page.evaluate(async () => { console.time('foo time'); - await new Promise(x => window.builtinSetTimeout(x, 100)); + await new Promise(x => window.builtins.setTimeout(x, 100)); console.timeLog('foo time'); - await new Promise(x => window.builtinSetTimeout(x, 100)); + await new Promise(x => window.builtins.setTimeout(x, 100)); console.timeEnd('foo time'); }); expect(messages.length).toBe(2); diff --git a/tests/page/page-event-network.spec.ts b/tests/page/page-event-network.spec.ts index 8aa1462d5a71e..e7004f576a245 100644 --- a/tests/page/page-event-network.spec.ts +++ b/tests/page/page-event-network.spec.ts @@ -17,7 +17,6 @@ import type { ServerResponse } from 'http'; import { test as it, expect } from './pageTest'; -import { kTargetClosedErrorMessage } from '../config/errors'; it('Page.Events.Request @smoke', async ({ page, server }) => { const requests = []; @@ -138,23 +137,3 @@ it('should resolve responses after a navigation', async ({ page, server, browser // the response should resolve to null, because the page navigated. expect(await responsePromise).toBe(null); }); - -it('interrupt request.response() and request.allHeaders() on page.close', async ({ page, server, browserName }) => { - it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/27227' }); - server.setRoute('/one-style.css', (req, res) => { - res.setHeader('Content-Type', 'text/css'); - }); - const reqPromise = page.waitForRequest('**/one-style.css'); - await page.goto(server.PREFIX + '/one-style.html', { waitUntil: 'domcontentloaded' }); - const req = await reqPromise; - const respPromise = req.response().catch(e => e); - const headersPromise = req.allHeaders().catch(e => e); - await page.close(); - expect((await respPromise).message).toContain(kTargetClosedErrorMessage); - // All headers are the same as "provisional" headers in Firefox. - if (browserName === 'firefox') - expect((await headersPromise)['user-agent']).toBeTruthy(); - else - expect((await headersPromise).message).toContain(kTargetClosedErrorMessage); - -}); diff --git a/tests/page/page-event-pageerror.spec.ts b/tests/page/page-event-pageerror.spec.ts index 1e91ce7b7f145..c7fc699683ac0 100644 --- a/tests/page/page-event-pageerror.spec.ts +++ b/tests/page/page-event-pageerror.spec.ts @@ -70,7 +70,7 @@ it('should contain the Error.name property', async ({ page }) => { const [error] = await Promise.all([ page.waitForEvent('pageerror'), page.evaluate(() => { - window.builtinSetTimeout(() => { + window.builtins.setTimeout(() => { const error = new Error('my-message'); error.name = 'my-name'; throw error; @@ -85,7 +85,7 @@ it('should support an empty Error.name property', async ({ page }) => { const [error] = await Promise.all([ page.waitForEvent('pageerror'), page.evaluate(() => { - window.builtinSetTimeout(() => { + window.builtins.setTimeout(() => { const error = new Error('my-message'); error.name = ''; throw error; @@ -107,7 +107,7 @@ it('should handle odd values', async ({ page }) => { const [error] = await Promise.all([ page.waitForEvent('pageerror'), page.evaluate(value => { - window.builtinSetTimeout(() => { throw value; }, 0); + window.builtins.setTimeout(() => { throw value; }, 0); }, value), ]); expect(error.message).toBe(message); @@ -118,7 +118,7 @@ it('should handle object', async ({ page, browserName }) => { const [error] = await Promise.all([ page.waitForEvent('pageerror'), page.evaluate(() => { - window.builtinSetTimeout(() => { throw {}; }, 0); + window.builtins.setTimeout(() => { throw {}; }, 0); }), ]); expect(error.message).toBe(browserName === 'chromium' ? 'Object' : '[object Object]'); @@ -128,7 +128,7 @@ it('should handle window', async ({ page, browserName }) => { const [error] = await Promise.all([ page.waitForEvent('pageerror'), page.evaluate(() => { - window.builtinSetTimeout(() => { throw window; }, 0); + window.builtins.setTimeout(() => { throw window; }, 0); }), ]); expect(error.message).toBe(browserName === 'chromium' ? 'Window' : '[object Window]'); diff --git a/tests/page/page-event-popup.spec.ts b/tests/page/page-event-popup.spec.ts index 07b203709ae38..152136acdebf5 100644 --- a/tests/page/page-event-popup.spec.ts +++ b/tests/page/page-event-popup.spec.ts @@ -146,22 +146,6 @@ it('should work with clicking target=_blank and rel=noopener', async ({ page, se expect(await popup.evaluate(() => !!window.opener)).toBe(false); }); -it('should not treat navigations as new popups', async ({ page, server, isWebView2 }) => { - it.skip(isWebView2, 'Page.close() is not supported in WebView2'); - - await page.goto(server.EMPTY_PAGE); - await page.setContent('yo'); - const [popup] = await Promise.all([ - page.waitForEvent('popup'), - page.click('a'), - ]); - let badSecondPopup = false; - page.on('popup', () => badSecondPopup = true); - await popup.goto(server.CROSS_PROCESS_PREFIX + '/empty.html'); - await page.close(); - expect(badSecondPopup).toBe(false); -}); - it('should report popup opened from iframes', async ({ page, server, browserName }) => { await page.goto(server.PREFIX + '/frames/two-frames.html'); const frame = page.frame('uno'); diff --git a/tests/page/page-event-request.spec.ts b/tests/page/page-event-request.spec.ts index cfc2f7a1e225c..028ddcca54fbe 100644 --- a/tests/page/page-event-request.spec.ts +++ b/tests/page/page-event-request.spec.ts @@ -41,6 +41,19 @@ it('should fire for fetches', async ({ page, server }) => { expect(requests.length).toBe(2); }); +it('should fire for fetches with keepalive: true', { + annotation: { + type: 'issue', + description: 'https://github.com/microsoft/playwright/issues/34497' + } +}, async ({ page, server, browserName }) => { + const requests = []; + page.on('request', request => requests.push(request)); + await page.goto(server.EMPTY_PAGE); + await page.evaluate(() => fetch('/empty.html', { keepalive: true })); + expect(requests.length).toBe(2); +}); + it('should report requests and responses handled by service worker', async ({ page, server, isAndroid, isElectron }) => { it.fixme(isAndroid); it.fixme(isElectron); @@ -241,3 +254,125 @@ it('main resource xhr should have type xhr', async ({ page, server }) => { expect(request.isNavigationRequest()).toBe(false); expect(request.resourceType()).toBe('xhr'); }); + +it('should finish 204 request', { + annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/32752' } +}, async ({ page, server, browserName }) => { + it.fixme(browserName === 'chromium'); + server.setRoute('/204', (req, res) => { + res.writeHead(204, { 'Content-type': 'text/plain' }); + res.end(); + }); + await page.goto(server.EMPTY_PAGE); + const reqPromise = Promise.race([ + page.waitForEvent('requestfailed', r => r.url().endsWith('/204')).then(() => 'requestfailed'), + page.waitForEvent('requestfinished', r => r.url().endsWith('/204')).then(() => 'requestfinished'), + ]); + page.evaluate(async url => { await fetch(url); }, server.PREFIX + '/204').catch(() => {}); + expect(await reqPromise).toBe('requestfinished'); +}); + +it(' resource should have type image', async ({ page }) => { + it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/33148' }); + const [request] = await Promise.all([ + page.waitForEvent('request'), + page.setContent(` + + + + + + `) + ]); + expect(request.resourceType()).toBe('image'); +}); + +// Chromium: requestWillBeSentEvent.frameId is undefined for OPTIONS. +// WebKit: no requestWillBeSent event in the protocol for OPTIONS (at least on Mac). +// Firefox: OPTIONS request can be dispatched. +it('should not expose preflight OPTIONS request', { + annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/36311' } +}, async ({ page, server, browserName }) => { + const serverRequests = []; + server.setRoute('/cors', (req, res) => { + serverRequests.push(`${req.method} ${req.url}`); + if (req.method === 'OPTIONS') { + res.writeHead(204, { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': 'GET, POST, PUT, OPTIONS', + 'Access-Control-Allow-Headers': '*', + }); + res.end(); + return; + } + res.writeHead(200, { 'Content-type': 'text/plain', 'Access-Control-Allow-Origin': '*' }); + res.end('Hello there!'); + }); + const clientRequests = []; + page.on('request', request => { + clientRequests.push(`${request.method()} ${request.url()}`); + }); + const response = await page.evaluate(async url => { + const response = await fetch(url, { + method: 'POST', + body: '', + headers: { + 'Content-Type': 'application/json', + 'X-Custom-Header': 'test-value' + } + }); + return await response.text(); + }, server.CROSS_PROCESS_PREFIX + '/cors').catch(() => {}); + expect(response).toBe('Hello there!'); + expect(serverRequests).toEqual([ + 'OPTIONS /cors', + 'POST /cors', + ]); + expect(clientRequests).toEqual([ + `POST ${server.CROSS_PROCESS_PREFIX}/cors`, + ]); +}); + +it('should not expose preflight OPTIONS request with network interception', { + annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/36311' } +}, async ({ page, server, browserName }) => { + const serverRequests = []; + server.setRoute('/cors', (req, res) => { + serverRequests.push(`${req.method} ${req.url}`); + if (req.method === 'OPTIONS') { + res.writeHead(204, { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': 'GET, POST, PUT, OPTIONS', + 'Access-Control-Allow-Headers': '*', + }); + res.end(); + return; + } + res.writeHead(200, { 'Content-type': 'text/plain', 'Access-Control-Allow-Origin': '*' }); + res.end('Hello there!'); + }); + await page.route('**/*', route => route.continue()); + const clientRequests = []; + page.on('request', request => { + clientRequests.push(`${request.method()} ${request.url()}`); + }); + const response = await page.evaluate(async url => { + const response = await fetch(url, { + method: 'POST', + body: '', + headers: { + 'Content-Type': 'application/json', + 'X-Custom-Header': 'test-value' + } + }); + return await response.text(); + }, server.CROSS_PROCESS_PREFIX + '/cors').catch(() => {}); + expect(response).toBe('Hello there!'); + expect.soft(serverRequests).toEqual([ + ...(browserName !== 'chromium' ? ['OPTIONS /cors'] : []), + 'POST /cors', + ]); + expect.soft(clientRequests).toEqual([ + `POST ${server.CROSS_PROCESS_PREFIX}/cors`, + ]); +}); diff --git a/tests/page/page-expose-function.spec.ts b/tests/page/page-expose-function.spec.ts index ece4a602df5e2..e9334c4df08d3 100644 --- a/tests/page/page-expose-function.spec.ts +++ b/tests/page/page-expose-function.spec.ts @@ -95,7 +95,7 @@ it('should be callable from-inside addInitScript', async ({ page, server }) => { }); await page.addInitScript(() => window['woof']()); await page.reload(); - expect(called).toBe(true); + await expect.poll(() => called).toBe(true); }); it('should survive navigation', async ({ page, server }) => { @@ -221,23 +221,6 @@ it('exposeBindingHandle should throw for multiple arguments', async ({ page }) = expect(error.message).toContain('exposeBindingHandle supports a single argument, 2 received'); }); -it('should not result in unhandled rejection', async ({ page, isAndroid, isWebView2 }) => { - it.fixme(isAndroid); - it.skip(isWebView2, 'Page.close() is not supported in WebView2'); - - const closedPromise = page.waitForEvent('close'); - await page.exposeFunction('foo', async () => { - await page.close(); - }); - await page.evaluate(() => { - window.builtinSetTimeout(() => (window as any).foo(), 0); - return undefined; - }); - await closedPromise; - // Make a round-trip to be sure we did not throw immediately after closing. - expect(await page.evaluate('1 + 1').catch(e => e)).toBeInstanceOf(Error); -}); - it('exposeBinding(handle) should work with element handles', async ({ page }) => { let cb; const promise = new Promise(f => cb = f); @@ -300,3 +283,12 @@ it('should work with busted Array.prototype.map/push', async ({ page, server }) await page.exposeFunction('add', (a, b) => a + b); expect(await page.evaluate('add(5, 6)')).toBe(11); }); + +it('should fail with busted Array.prototype.toJSON', async ({ page }) => { + await page.evaluateHandle(() => (Array.prototype as any).toJSON = () => '"[]"'); + + await page.exposeFunction('add', (a, b) => a + b); + await expect(() => page.evaluate(`add(5, 6)`)).rejects.toThrowError('serializedArgs is not an array. This can happen when Array.prototype.toJSON is defined incorrectly'); + + expect.soft(await page.evaluate(() => ([] as any).toJSON())).toBe('"[]"'); +}); diff --git a/tests/page/page-filechooser.spec.ts b/tests/page/page-filechooser.spec.ts new file mode 100644 index 0000000000000..ba45345474535 --- /dev/null +++ b/tests/page/page-filechooser.spec.ts @@ -0,0 +1,368 @@ +/** + * Copyright 2017 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. + */ + +import { test, expect } from './pageTest'; +import { attachFrame } from '../config/utils'; + +import fs from 'fs'; +import formidable from 'formidable'; + +test('should upload multiple large files', async ({ page, server, isAndroid, isWebView2, mode }, testInfo) => { + test.skip(isAndroid); + test.skip(isWebView2); + test.skip(mode.startsWith('service')); + test.slow(); + + const filesCount = 10; + await page.goto(server.PREFIX + '/input/fileupload-multi.html'); + const uploadFile = testInfo.outputPath('50MB_1.zip'); + const str = 'A'.repeat(1024); + const stream = fs.createWriteStream(uploadFile); + // 49 is close to the actual limit + for (let i = 0; i < 49 * 1024; i++) { + await new Promise((fulfill, reject) => { + stream.write(str, err => { + if (err) + reject(err); + else + fulfill(); + }); + }); + } + await new Promise(f => stream.end(f)); + const input = page.locator('input[type="file"]'); + const uploadFiles = [uploadFile]; + for (let i = 2; i <= filesCount; i++) { + const dstFile = testInfo.outputPath(`50MB_${i}.zip`); + fs.copyFileSync(uploadFile, dstFile); + uploadFiles.push(dstFile); + } + const fileChooserPromise = page.waitForEvent('filechooser'); + await input.click(); + const fileChooser = await fileChooserPromise; + await fileChooser.setFiles(uploadFiles); + const filesLen = await page.evaluate('document.getElementsByTagName("input")[0].files.length'); + expect(fileChooser.isMultiple()).toBe(true); + expect(filesLen).toEqual(filesCount); + await Promise.all(uploadFiles.map(path => fs.promises.unlink(path))); +}); + +test('should emit event once', async ({ page, server }) => { + await page.setContent(``); + const [chooser] = await Promise.all([ + new Promise(f => page.once('filechooser', f)), + page.click('input'), + ]); + expect(chooser).toBeTruthy(); +}); + +test('should emit event via prepend', async ({ page, server }) => { + await page.setContent(``); + const [chooser] = await Promise.all([ + new Promise(f => page.prependListener('filechooser', f)), + page.click('input'), + ]); + expect(chooser).toBeTruthy(); +}); + +test('should emit event for iframe', async ({ page, server }) => { + const frame = await attachFrame(page, 'frame1', server.EMPTY_PAGE); + await frame.setContent(``); + const [chooser] = await Promise.all([ + new Promise(f => page.once('filechooser', f)), + frame.click('input'), + ]); + expect(chooser).toBeTruthy(); +}); + +test('should emit event on/off', async ({ page, server }) => { + await page.setContent(``); + const [chooser] = await Promise.all([ + new Promise(f => { + const listener = chooser => { + page.off('filechooser', listener); + f(chooser); + }; + page.on('filechooser', listener); + }), + page.click('input'), + ]); + expect(chooser).toBeTruthy(); +}); + +test('should emit event addListener/removeListener', async ({ page, server }) => { + await page.setContent(``); + const [chooser] = await Promise.all([ + new Promise(f => { + const listener = chooser => { + page.removeListener('filechooser', listener); + f(chooser); + }; + page.addListener('filechooser', listener); + }), + page.click('input'), + ]); + expect(chooser).toBeTruthy(); +}); + +test('should work when file input is attached to DOM', async ({ page, server }) => { + await page.setContent(``); + const [chooser] = await Promise.all([ + page.waitForEvent('filechooser'), + page.click('input'), + ]); + expect(chooser).toBeTruthy(); +}); + +test('should work when file input is not attached to DOM', async ({ page, asset }) => { + const [, content] = await Promise.all([ + page.waitForEvent('filechooser').then(chooser => chooser.setFiles(asset('file-to-upload.txt'))), + page.evaluate(async () => { + const el = document.createElement('input'); + el.type = 'file'; + el.click(); + await new Promise(x => el.oninput = x); + const reader = new FileReader(); + const promise = new Promise(fulfill => reader.onload = fulfill); + reader.readAsText(el.files[0]); + return promise.then(() => reader.result); + }), + ]); + expect(content).toBe('contents of the file'); +}); + +test('should not throw when filechooser belongs to iframe', async ({ page, server, browserName }) => { + await page.goto(server.PREFIX + '/frames/one-frame.html'); + const frame = page.mainFrame().childFrames()[0]; + await frame.setContent(` +
Click me
+ + `); + await Promise.all([ + page.waitForEvent('filechooser'), + frame.click('div') + ]); + await page.waitForFunction(() => (window as any).__done); +}); + +test('should not throw when frame is detached immediately', async ({ page, server }) => { + await page.goto(server.PREFIX + '/frames/one-frame.html'); + const frame = page.mainFrame().childFrames()[0]; + await frame.setContent(` +
Click me
+ + `); + page.on('filechooser', () => {}); // To ensure we handle file choosers. + await frame.click('div'); + await page.waitForFunction(() => (window as any).__done); +}); + +test('should respect timeout', async ({ page, playwright }) => { + let error = null; + await page.waitForEvent('filechooser', { timeout: 1 }).catch(e => error = e); + expect(error).toBeInstanceOf(playwright.errors.TimeoutError); +}); + +test('should respect default timeout when there is no custom timeout', async ({ page, playwright }) => { + page.setDefaultTimeout(1); + let error = null; + await page.waitForEvent('filechooser').catch(e => error = e); + expect(error).toBeInstanceOf(playwright.errors.TimeoutError); +}); + +test('should prioritize exact timeout over default timeout', async ({ page, playwright }) => { + page.setDefaultTimeout(0); + let error = null; + await page.waitForEvent('filechooser', { timeout: 1 }).catch(e => error = e); + expect(error).toBeInstanceOf(playwright.errors.TimeoutError); +}); + +test('should work with no timeout', async ({ page, server }) => { + const [chooser] = await Promise.all([ + page.waitForEvent('filechooser', { timeout: 0 }), + page.evaluate(() => window.builtins.setTimeout(() => { + const el = document.createElement('input'); + el.type = 'file'; + el.click(); + }, 50)) + ]); + expect(chooser).toBeTruthy(); +}); + +test('should return the same file chooser when there are many watchdogs simultaneously', async ({ page, server }) => { + await page.setContent(``); + const [fileChooser1, fileChooser2] = await Promise.all([ + page.waitForEvent('filechooser'), + page.waitForEvent('filechooser'), + page.$eval('input', input => input.click()), + ]); + expect(fileChooser1 === fileChooser2).toBe(true); +}); + +test('should accept single file', async ({ page, asset }) => { + await page.setContent(``); + const [fileChooser] = await Promise.all([ + page.waitForEvent('filechooser'), + page.click('input'), + ]); + expect(fileChooser.page()).toBe(page); + expect(fileChooser.element()).toBeTruthy(); + await fileChooser.setFiles(asset('file-to-upload.txt')); + expect(await page.$eval('input', input => input.files.length)).toBe(1); + expect(await page.$eval('input', input => input.files[0].name)).toBe('file-to-upload.txt'); +}); + +// @see https://github.com/microsoft/playwright/issues/4704 +test('should not trim big uploaded files', async ({ page, server }) => { + + let files: Record; + server.setRoute('/upload', async (req, res) => { + const form = new formidable.IncomingForm(); + form.parse(req, function(err, fields, f) { + files = f as Record; + res.end(); + }); + }); + await page.goto(server.EMPTY_PAGE); + + const DATA_SIZE = Math.pow(2, 20); + await Promise.all([ + page.evaluate(async size => { + const body = new FormData(); + body.set('file', new Blob([new Uint8Array(size)])); + await fetch('/upload', { method: 'POST', body }); + }, DATA_SIZE), + server.waitForRequest('/upload'), + ]); + expect(files.file.size).toBe(DATA_SIZE); +}); + +test('should be able to read selected file', async ({ page, asset }) => { + await page.setContent(``); + const [, content] = await Promise.all([ + page.waitForEvent('filechooser').then(fileChooser => fileChooser.setFiles(asset('file-to-upload.txt'))), + page.$eval('input', async picker => { + picker.click(); + await new Promise(x => picker.oninput = x); + const reader = new FileReader(); + const promise = new Promise(fulfill => reader.onload = fulfill); + reader.readAsText(picker.files[0]); + return promise.then(() => reader.result); + }), + ]); + expect(content).toBe('contents of the file'); +}); + +test('should be able to reset selected files with empty file list', async ({ page, asset }) => { + await page.setContent(``); + const [, fileLength1] = await Promise.all([ + page.waitForEvent('filechooser').then(fileChooser => fileChooser.setFiles(asset('file-to-upload.txt'))), + page.$eval('input', async picker => { + picker.click(); + await new Promise(x => picker.oninput = x); + return picker.files.length; + }), + ]); + expect(fileLength1).toBe(1); + const [, fileLength2] = await Promise.all([ + page.waitForEvent('filechooser').then(fileChooser => fileChooser.setFiles([])), + page.$eval('input', async picker => { + picker.click(); + await new Promise(x => picker.oninput = x); + return picker.files.length; + }), + ]); + expect(fileLength2).toBe(0); +}); + +test('should work for single file pick', async ({ page, server }) => { + await page.setContent(``); + const [fileChooser] = await Promise.all([ + page.waitForEvent('filechooser'), + page.click('input'), + ]); + expect(fileChooser.isMultiple()).toBe(false); +}); + +test('should work for "multiple"', async ({ page, server }) => { + await page.setContent(``); + const [fileChooser] = await Promise.all([ + page.waitForEvent('filechooser'), + page.click('input'), + ]); + expect(fileChooser.isMultiple()).toBe(true); +}); + +test('should work for "webkitdirectory"', async ({ page, server }) => { + await page.setContent(``); + const [fileChooser] = await Promise.all([ + page.waitForEvent('filechooser'), + page.click('input'), + ]); + expect(fileChooser.isMultiple()).toBe(true); +}); + +test('should emit event after navigation', async ({ page, server, browserName, browserMajorVersion }) => { + test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/11375' }); + test.skip(browserName === 'chromium' && browserMajorVersion < 99); + + const logs = []; + page.on('filechooser', () => logs.push('filechooser')); + await page.goto(server.PREFIX + '/empty.html'); + await page.setContent(``); + await Promise.all([ + page.waitForEvent('filechooser'), + page.click('input'), + ]); + await page.goto(server.CROSS_PROCESS_PREFIX + '/empty.html'); + await page.setContent(``); + await Promise.all([ + page.waitForEvent('filechooser'), + page.click('input'), + ]); + expect(logs).toEqual(['filechooser', 'filechooser']); +}); + +test('should trigger listener added before navigation', async ({ page, server, browserMajorVersion, isElectron }) => { + test.skip(isElectron && browserMajorVersion <= 98); + // Add listener before cross process navigation. + const chooserPromise = new Promise(f => page.once('filechooser', f)); + await page.goto(server.PREFIX + '/empty.html'); + await page.goto(server.CROSS_PROCESS_PREFIX + '/empty.html'); + await page.setContent(``); + const [chooser] = await Promise.all([ + chooserPromise, + page.click('input'), + ]); + expect(chooser).toBeTruthy(); +}); diff --git a/tests/page/page-fill.spec.ts b/tests/page/page-fill.spec.ts index 88cd33d4073f6..32dc69f550f55 100644 --- a/tests/page/page-fill.spec.ts +++ b/tests/page/page-fill.spec.ts @@ -210,6 +210,31 @@ it('should fill contenteditable with new lines', async ({ page, server, browserN expect(await page.locator('div[contenteditable]').innerText()).toBe('John\nDoe'); }); +it('should not double-fill in contenteditable with beforeinput handler in Firefox', { + annotation: { + type: 'issue', + description: 'https://github.com/microsoft/playwright/issues/36715' + } +}, async ({ page, browserName }) => { + it.fixme(browserName === 'firefox', 'https://github.com/microsoft/playwright/issues/36715'); + + await page.setContent(` +
+ + `); + + const locator = page.locator('#editor'); + const testValue = 'Playwright'; + await locator.fill(testValue); + await expect(locator).toHaveText(testValue); +}); + it('should fill elements with existing value and selection', async ({ page, server }) => { await page.goto(server.PREFIX + '/input/textarea.html'); @@ -238,8 +263,8 @@ it('should fill elements with existing value and selection', async ({ page, serv it('should throw nice error without injected script stack when element is not an ', async ({ page, server }) => { let error = null; - await page.goto(server.PREFIX + '/input/textarea.html'); - await page.fill('body', '').catch(e => error = e); + await page.setContent(``); + await page.fill('select', '').catch(e => error = e); expect(error.message).toContain('page.fill: Error: Element is not an ,