diff --git a/.github/workflows/create_test_report.yml b/.github/workflows/create_test_report.yml index b20f57573b..dfc6961c2c 100644 --- a/.github/workflows/create_test_report.yml +++ b/.github/workflows/create_test_report.yml @@ -35,7 +35,7 @@ jobs: run: | npx playwright merge-reports --config .github/workflows/merge.config.ts ./all-blob-reports env: - NODE_OPTIONS: --max-old-space-size=4096 + NODE_OPTIONS: --max-old-space-size=8192 - name: Azure Login uses: azure/login@v2 diff --git a/.github/workflows/tests_secondary.yml b/.github/workflows/tests_secondary.yml index 71c7ed105f..de9434d7df 100644 --- a/.github/workflows/tests_secondary.yml +++ b/.github/workflows/tests_secondary.yml @@ -268,40 +268,25 @@ jobs: - run: npx playwright install-deps - run: utils/build/build-playwright-driver.sh - test_linux_chromium_headless_new: - name: Linux Chromium Headless New - environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }} - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: ./.github/actions/run-test - with: - browsers-to-install: chromium - command: npm run ctest - bot-name: "headless-new" - 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 - - test_linux_chromium_headless_shell: - name: Chromium Headless Shell + test_channel_chromium: + name: Test channel=chromium environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }} strategy: fail-fast: false matrix: - runs-on: [ubuntu-latest, macos-latest, windows-latest] + runs-on: [ubuntu-latest, windows-latest, macos-latest] runs-on: ${{ matrix.runs-on }} steps: - uses: actions/checkout@v4 - uses: ./.github/actions/run-test with: - browsers-to-install: chromium-headless-shell + # 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-shell-${{ matrix.runs-on }}" + 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: - PWTEST_CHANNEL: chromium-headless-shell + PWTEST_CHANNEL: chromium diff --git a/README.md b/README.md index ce154c60d9..2f04b28a4f 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-131.0.6778.24-blue.svg?logo=google-chrome)](https://www.chromium.org/Home) [![Firefox version](https://img.shields.io/badge/firefox-131.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/) [![Join Discord](https://img.shields.io/badge/join-discord-infomational)](https://aka.ms/playwright/discord) +[![npm version](https://img.shields.io/npm/v/playwright.svg)](https://www.npmjs.com/package/playwright) [![Chromium version](https://img.shields.io/badge/chromium-132.0.6834.6-blue.svg?logo=google-chrome)](https://www.chromium.org/Home) [![Firefox version](https://img.shields.io/badge/firefox-132.0-blue.svg?logo=firefoxbrowser)](https://www.mozilla.org/en-US/firefox/new/) [![WebKit version](https://img.shields.io/badge/webkit-18.2-blue.svg?logo=safari)](https://webkit.org/) [![Join Discord](https://img.shields.io/badge/join-discord-infomational)](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 131.0.6778.24 | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| WebKit 18.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| Firefox 131.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| Chromium 132.0.6834.6 | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| WebKit 18.2 | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| Firefox 132.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. diff --git a/browser_patches/firefox/UPSTREAM_CONFIG.sh b/browser_patches/firefox/UPSTREAM_CONFIG.sh index da588ee687..7956cc114d 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" BASE_BRANCH="release" -BASE_REVISION="47bcb6d7d2013f9a3d864678675100e0b3d73c5e" +BASE_REVISION="bc78b98043438d8ee2727a483b6e10dedfda883f" diff --git a/browser_patches/firefox/juggler/protocol/PageHandler.js b/browser_patches/firefox/juggler/protocol/PageHandler.js index 8fa9a06361..bab151b392 100644 --- a/browser_patches/firefox/juggler/protocol/PageHandler.js +++ b/browser_patches/firefox/juggler/protocol/PageHandler.js @@ -256,6 +256,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); } diff --git a/browser_patches/firefox/juggler/protocol/Protocol.js b/browser_patches/firefox/juggler/protocol/Protocol.js index 1d6e197c97..2b93186e54 100644 --- a/browser_patches/firefox/juggler/protocol/Protocol.js +++ b/browser_patches/firefox/juggler/protocol/Protocol.js @@ -481,6 +481,17 @@ const Browser = { }, }; +const Heap = { + targets: ['page'], + types: {}, + events: {}, + methods: { + 'collectGarbage': { + params: {}, + }, + }, +}; + const Network = { targets: ['page'], types: networkTypes, @@ -996,7 +1007,7 @@ const Accessibility = { } this.protocol = { - domains: {Browser, Page, Runtime, Network, Accessibility}, + domains: {Browser, Heap, Page, Runtime, Network, Accessibility}, }; this.checkScheme = checkScheme; this.EXPORTED_SYMBOLS = ['protocol', 'checkScheme']; diff --git a/browser_patches/firefox/patches/bootstrap.diff b/browser_patches/firefox/patches/bootstrap.diff index 8204e591c8..5902d600c2 100644 --- a/browser_patches/firefox/patches/bootstrap.diff +++ b/browser_patches/firefox/patches/bootstrap.diff @@ -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 b40e0fceb567c0d217adf284e13f434e49cc8467..2c4e6d5fbf8da40954ad6a5b15e412493e43b14e 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 b40e0fceb567c0d217adf284e13f434e49cc8467..2c4e6d5fbf8da40954ad6a5b15e41249 #include #include -@@ -421,8 +422,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)}; @@ -167,7 +167,7 @@ index d49c6fbf1bf83b832795fa674f6b41f223eef812..7ea3540947ff5f61b15f27fbf4b95564 const transportProvider = { setListener(upgradeListener) { diff --git a/docshell/base/BrowsingContext.cpp b/docshell/base/BrowsingContext.cpp -index db5b5b990727aefcbaa47f89e0f53f4048e60038..bcd2321f46d9bca719fc530054984a2163c21f86 100644 +index e1721f31d491aa8a7977eaca3d2f7f8a048546de..b3bc2d575dc3f794cbc08c603e70d34bbe69efed 100644 --- a/docshell/base/BrowsingContext.cpp +++ b/docshell/base/BrowsingContext.cpp @@ -106,8 +106,15 @@ struct ParamTraits @@ -188,7 +188,7 @@ index db5b5b990727aefcbaa47f89e0f53f4048e60038..bcd2321f46d9bca719fc530054984a21 template <> struct ParamTraits -@@ -2807,6 +2814,40 @@ void BrowsingContext::DidSet(FieldIndex, +@@ -2818,6 +2825,40 @@ void BrowsingContext::DidSet(FieldIndex, PresContextAffectingFieldChanged(); } @@ -297,7 +297,7 @@ index 61135ab0d7894c500c3c5d80d107e283c01b6830..cc8eb043f1f78214843ec7b335dd9932 bool CanSet(FieldIndex, bool, ContentParent*) { diff --git a/docshell/base/CanonicalBrowsingContext.cpp b/docshell/base/CanonicalBrowsingContext.cpp -index 18b2bde3da2b1e17938fddda486b1bc4ddcf0e79..793a3d002b10298f7a19a2eae4d377f6f022fd36 100644 +index f0d8cb25398472d8720fcacc47081d95d3e9887c..a680d4458360c8515712ef0a986415113ae8a4e0 100644 --- a/docshell/base/CanonicalBrowsingContext.cpp +++ b/docshell/base/CanonicalBrowsingContext.cpp @@ -324,6 +324,8 @@ void CanonicalBrowsingContext::ReplacedBy( @@ -323,7 +323,7 @@ index 18b2bde3da2b1e17938fddda486b1bc4ddcf0e79..793a3d002b10298f7a19a2eae4d377f6 } diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp -index 60cbd5d5b8d202fc30d5ac931ac66030bade65e7..f552a695880c5838c89ce918f61d051577cc5598 100644 +index c15a424a05d23287ee21726a5fb21ff5691e4c2b..fa9989e313bbb7bf049ce1519733c4032e9f9b4b 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -15,6 +15,12 @@ @@ -609,7 +609,7 @@ index 60cbd5d5b8d202fc30d5ac931ac66030bade65e7..f552a695880c5838c89ce918f61d0515 if (RefPtr presShell = GetPresShell()) { presShell->ActivenessMaybeChanged(); } -@@ -6681,6 +6906,10 @@ bool nsDocShell::CanSavePresentation(uint32_t aLoadType, +@@ -6688,6 +6913,10 @@ bool nsDocShell::CanSavePresentation(uint32_t aLoadType, return false; // no entry to save into } @@ -620,7 +620,7 @@ index 60cbd5d5b8d202fc30d5ac931ac66030bade65e7..f552a695880c5838c89ce918f61d0515 MOZ_ASSERT(!mozilla::SessionHistoryInParent(), "mOSHE cannot be non-null with SHIP"); nsCOMPtr viewer = mOSHE->GetDocumentViewer(); -@@ -8413,6 +8642,12 @@ nsresult nsDocShell::PerformRetargeting(nsDocShellLoadState* aLoadState) { +@@ -8420,6 +8649,12 @@ nsresult nsDocShell::PerformRetargeting(nsDocShellLoadState* aLoadState) { true, // aForceNoOpener getter_AddRefs(newBC)); MOZ_ASSERT(!newBC); @@ -633,7 +633,7 @@ index 60cbd5d5b8d202fc30d5ac931ac66030bade65e7..f552a695880c5838c89ce918f61d0515 return rv; } -@@ -9549,6 +9784,16 @@ nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState, +@@ -9556,6 +9791,16 @@ nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState, nsINetworkPredictor::PREDICT_LOAD, attrs, nullptr); nsCOMPtr req; @@ -650,7 +650,7 @@ index 60cbd5d5b8d202fc30d5ac931ac66030bade65e7..f552a695880c5838c89ce918f61d0515 rv = DoURILoad(aLoadState, aCacheKey, getter_AddRefs(req)); if (NS_SUCCEEDED(rv)) { -@@ -12747,6 +12992,9 @@ class OnLinkClickEvent : public Runnable { +@@ -12754,6 +12999,9 @@ class OnLinkClickEvent : public Runnable { mHandler->OnLinkClickSync(mContent, mLoadState, mNoOpenerImplied, mTriggeringPrincipal); } @@ -660,7 +660,7 @@ index 60cbd5d5b8d202fc30d5ac931ac66030bade65e7..f552a695880c5838c89ce918f61d0515 return NS_OK; } -@@ -12836,6 +13084,8 @@ nsresult nsDocShell::OnLinkClick( +@@ -12843,6 +13091,8 @@ nsresult nsDocShell::OnLinkClick( nsCOMPtr ev = new OnLinkClickEvent(this, aContent, loadState, noOpenerImplied, aIsTrusted, aTriggeringPrincipal); @@ -781,10 +781,10 @@ index fdc04f16c6f547077ad8c872f9357d85d4513c50..199f8fdb0670265c715f99f5cac1a2b2 * 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 235e2fcfccda18b4e923d1c1b02b5e1d9b02b089..e81abc3e18d82fa235a69911eb117ad0dcf54fd2 100644 +index 79f3524037e954eb693e2882d91a7632e6e1df41..2b75a1eaff4d166f68ca4a943e10cf9c6ab28bbf 100644 --- a/dom/base/Document.cpp +++ b/dom/base/Document.cpp -@@ -3757,6 +3757,9 @@ void Document::SendToConsole(nsCOMArray& aMessages) { +@@ -3783,6 +3783,9 @@ void Document::SendToConsole(nsCOMArray& aMessages) { } void Document::ApplySettingsFromCSP(bool aSpeculative) { @@ -794,7 +794,7 @@ index 235e2fcfccda18b4e923d1c1b02b5e1d9b02b089..e81abc3e18d82fa235a69911eb117ad0 nsresult rv = NS_OK; if (!aSpeculative) { // 1) apply settings from regular CSP -@@ -3814,6 +3817,11 @@ nsresult Document::InitCSP(nsIChannel* aChannel) { +@@ -3840,6 +3843,11 @@ nsresult Document::InitCSP(nsIChannel* aChannel) { MOZ_ASSERT(!mScriptGlobalObject, "CSP must be initialized before mScriptGlobalObject is set!"); @@ -806,7 +806,7 @@ index 235e2fcfccda18b4e923d1c1b02b5e1d9b02b089..e81abc3e18d82fa235a69911eb117ad0 // If this is a data document - no need to set CSP. if (mLoadedAsData) { return NS_OK; -@@ -4613,6 +4621,10 @@ bool Document::HasFocus(ErrorResult& rv) const { +@@ -4641,6 +4649,10 @@ bool Document::HasFocus(ErrorResult& rv) const { return false; } @@ -817,7 +817,7 @@ index 235e2fcfccda18b4e923d1c1b02b5e1d9b02b089..e81abc3e18d82fa235a69911eb117ad0 if (!fm->IsInActiveWindow(bc)) { return false; } -@@ -19080,6 +19092,66 @@ ColorScheme Document::PreferredColorScheme(IgnoreRFP aIgnoreRFP) const { +@@ -19139,6 +19151,66 @@ ColorScheme Document::PreferredColorScheme(IgnoreRFP aIgnoreRFP) const { return PreferenceSheet::PrefsFor(*this).mColorScheme; } @@ -885,10 +885,10 @@ index 235e2fcfccda18b4e923d1c1b02b5e1d9b02b089..e81abc3e18d82fa235a69911eb117ad0 if (!sLoadingForegroundTopLevelContentDocument) { return false; diff --git a/dom/base/Document.h b/dom/base/Document.h -index 0021e452414f9b7dc7b32a1065a82986d12dfdd7..2325b7d65bc1fb98b1dce994724c8e75c902834e 100644 +index 7a8d8f2a716fc613c4095eaf1a18017887b9b924..e030e6b7ad63ad7c95227ed8f54e946190a638d8 100644 --- a/dom/base/Document.h +++ b/dom/base/Document.h -@@ -4053,6 +4053,9 @@ class Document : public nsINode, +@@ -4077,6 +4077,9 @@ class Document : public nsINode, // color-scheme meta tag. ColorScheme DefaultColorScheme() const; @@ -962,10 +962,10 @@ index 6abf6cef230c97815f17f6b7abf9f1b1de274a6f..46ead1f32e0d710b5b32e61dff72a4f7 dom::MediaCapabilities* MediaCapabilities(); dom::MediaSession* MediaSession(); diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp -index 7b7deca251cf20fa4896e63e32d17303dd603263..151dd519433de858673dc1620094a69257799fec 100644 +index 8518005d2938d35da7681c1b4230cacbe8fbaf03..e501e7e3351b6f5bdd07020dea658b9f8508b126 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp -@@ -8829,7 +8829,8 @@ nsresult nsContentUtils::SendMouseEvent( +@@ -8809,7 +8809,8 @@ nsresult nsContentUtils::SendMouseEvent( bool aIgnoreRootScrollFrame, float aPressure, unsigned short aInputSourceArg, uint32_t aIdentifier, bool aToWindow, PreventDefaultResult* aPreventDefault, bool aIsDOMEventSynthesized, @@ -975,7 +975,7 @@ index 7b7deca251cf20fa4896e63e32d17303dd603263..151dd519433de858673dc1620094a692 nsPoint offset; nsCOMPtr widget = GetWidget(aPresShell, &offset); if (!widget) return NS_ERROR_FAILURE; -@@ -8837,6 +8838,7 @@ nsresult nsContentUtils::SendMouseEvent( +@@ -8817,6 +8818,7 @@ nsresult nsContentUtils::SendMouseEvent( EventMessage msg; Maybe exitFrom; bool contextMenuKey = false; @@ -983,7 +983,7 @@ index 7b7deca251cf20fa4896e63e32d17303dd603263..151dd519433de858673dc1620094a692 if (aType.EqualsLiteral("mousedown")) { msg = eMouseDown; } else if (aType.EqualsLiteral("mouseup")) { -@@ -8861,6 +8863,12 @@ nsresult nsContentUtils::SendMouseEvent( +@@ -8841,6 +8843,12 @@ nsresult nsContentUtils::SendMouseEvent( msg = eMouseHitTest; } else if (aType.EqualsLiteral("MozMouseExploreByTouch")) { msg = eMouseExploreByTouch; @@ -996,7 +996,7 @@ index 7b7deca251cf20fa4896e63e32d17303dd603263..151dd519433de858673dc1620094a692 } else { return NS_ERROR_FAILURE; } -@@ -8871,7 +8879,14 @@ nsresult nsContentUtils::SendMouseEvent( +@@ -8851,7 +8859,14 @@ nsresult nsContentUtils::SendMouseEvent( Maybe pointerEvent; Maybe mouseEvent; @@ -1012,7 +1012,7 @@ index 7b7deca251cf20fa4896e63e32d17303dd603263..151dd519433de858673dc1620094a692 MOZ_ASSERT(!aIsWidgetEventSynthesized, "The event shouldn't be dispatched as a synthesized event"); if (MOZ_UNLIKELY(aIsWidgetEventSynthesized)) { -@@ -8890,8 +8905,11 @@ nsresult nsContentUtils::SendMouseEvent( +@@ -8870,8 +8885,11 @@ nsresult nsContentUtils::SendMouseEvent( contextMenuKey ? WidgetMouseEvent::eContextMenuKey : WidgetMouseEvent::eNormal); } @@ -1024,7 +1024,7 @@ index 7b7deca251cf20fa4896e63e32d17303dd603263..151dd519433de858673dc1620094a692 mouseOrPointerEvent.pointerId = aIdentifier; mouseOrPointerEvent.mModifiers = GetWidgetModifiers(aModifiers); mouseOrPointerEvent.mButton = aButton; -@@ -8904,6 +8922,8 @@ nsresult nsContentUtils::SendMouseEvent( +@@ -8884,6 +8902,8 @@ nsresult nsContentUtils::SendMouseEvent( mouseOrPointerEvent.mClickCount = aClickCount; mouseOrPointerEvent.mFlags.mIsSynthesizedForTests = aIsDOMEventSynthesized; mouseOrPointerEvent.mExitFrom = exitFrom; @@ -1034,10 +1034,10 @@ index 7b7deca251cf20fa4896e63e32d17303dd603263..151dd519433de858673dc1620094a692 nsPresContext* presContext = aPresShell->GetPresContext(); if (!presContext) return NS_ERROR_FAILURE; diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h -index 3837cce20cfb7cc3c5a93e7b595dee632739de5c..81ccfbe139e7041eb862ab3b085f1dae76bf0a5c 100644 +index b4b2244ddfbe43efa055788297a103c49989d921..2d22cdf8b25d9ce0e0daabb09f315d61a214a2be 100644 --- a/dom/base/nsContentUtils.h +++ b/dom/base/nsContentUtils.h -@@ -3093,7 +3093,8 @@ class nsContentUtils { +@@ -3047,7 +3047,8 @@ class nsContentUtils { int32_t aModifiers, bool aIgnoreRootScrollFrame, float aPressure, unsigned short aInputSourceArg, uint32_t aIdentifier, bool aToWindow, mozilla::PreventDefaultResult* aPreventDefault, @@ -1048,10 +1048,10 @@ index 3837cce20cfb7cc3c5a93e7b595dee632739de5c..81ccfbe139e7041eb862ab3b085f1dae static void FirePageShowEventForFrameLoaderSwap( nsIDocShellTreeItem* aItem, diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp -index e2de2b30c094e30db4d33e6cf8e5fbf83f219876..f937f561c0524e04563129f2cb762ae4127e6462 100644 +index c77bf80d5e1fc6db342ab47e85b7950f8a15a2d8..2f61c71cdb82b73c1de1a357315d9243a0b8c639 100644 --- a/dom/base/nsDOMWindowUtils.cpp +++ b/dom/base/nsDOMWindowUtils.cpp -@@ -684,6 +684,26 @@ nsDOMWindowUtils::GetPresShellId(uint32_t* aPresShellId) { +@@ -685,6 +685,26 @@ nsDOMWindowUtils::GetPresShellId(uint32_t* aPresShellId) { return NS_ERROR_FAILURE; } @@ -1078,7 +1078,7 @@ index e2de2b30c094e30db4d33e6cf8e5fbf83f219876..f937f561c0524e04563129f2cb762ae4 NS_IMETHODIMP nsDOMWindowUtils::SendMouseEvent( const nsAString& aType, float aX, float aY, int32_t aButton, -@@ -698,7 +718,7 @@ nsDOMWindowUtils::SendMouseEvent( +@@ -699,7 +719,7 @@ nsDOMWindowUtils::SendMouseEvent( aOptionalArgCount >= 7 ? aIdentifier : DEFAULT_MOUSE_POINTER_ID, false, aPreventDefault, aOptionalArgCount >= 4 ? aIsDOMEventSynthesized : true, aOptionalArgCount >= 5 ? aIsWidgetEventSynthesized : false, @@ -1087,7 +1087,7 @@ index e2de2b30c094e30db4d33e6cf8e5fbf83f219876..f937f561c0524e04563129f2cb762ae4 } NS_IMETHODIMP -@@ -716,7 +736,7 @@ nsDOMWindowUtils::SendMouseEventToWindow( +@@ -717,7 +737,7 @@ nsDOMWindowUtils::SendMouseEventToWindow( aOptionalArgCount >= 7 ? aIdentifier : DEFAULT_MOUSE_POINTER_ID, true, nullptr, aOptionalArgCount >= 4 ? aIsDOMEventSynthesized : true, aOptionalArgCount >= 5 ? aIsWidgetEventSynthesized : false, @@ -1096,7 +1096,7 @@ index e2de2b30c094e30db4d33e6cf8e5fbf83f219876..f937f561c0524e04563129f2cb762ae4 } NS_IMETHODIMP -@@ -725,13 +745,13 @@ nsDOMWindowUtils::SendMouseEventCommon( +@@ -726,13 +746,13 @@ nsDOMWindowUtils::SendMouseEventCommon( int32_t aClickCount, int32_t aModifiers, bool aIgnoreRootScrollFrame, float aPressure, unsigned short aInputSourceArg, uint32_t aPointerId, bool aToWindow, bool* aPreventDefault, bool aIsDOMEventSynthesized, @@ -1126,10 +1126,10 @@ index 47ff326b202266b1d7d6af8bdfb72776df8a6a93..b8e084b0c788c46345b1455b8257f171 MOZ_CAN_RUN_SCRIPT nsresult SendTouchEventCommon( diff --git a/dom/base/nsFocusManager.cpp b/dom/base/nsFocusManager.cpp -index 22c175c93ef7bc81640b0ad71bd6ca9c1082fea6..7d77e91afbfe7aebe0c94793c2e0606715e3acdb 100644 +index cbd5cb8e4525454cac0470a14bdc63d45bf53b9a..a73297f3faafe5895453f0a6996aa30a77a97267 100644 --- a/dom/base/nsFocusManager.cpp +++ b/dom/base/nsFocusManager.cpp -@@ -1684,6 +1684,10 @@ Maybe nsFocusManager::SetFocusInner(Element* aNewContent, +@@ -1697,6 +1697,10 @@ Maybe nsFocusManager::SetFocusInner(Element* aNewContent, (GetActiveBrowsingContext() == newRootBrowsingContext); } @@ -1140,7 +1140,7 @@ index 22c175c93ef7bc81640b0ad71bd6ca9c1082fea6..7d77e91afbfe7aebe0c94793c2e06067 // Exit fullscreen if a website focuses another window if (StaticPrefs::full_screen_api_exit_on_windowRaise() && !isElementInActiveWindow && (aFlags & FLAG_RAISE)) { -@@ -2269,6 +2273,7 @@ bool nsFocusManager::BlurImpl(BrowsingContext* aBrowsingContextToClear, +@@ -2282,6 +2286,7 @@ bool nsFocusManager::BlurImpl(BrowsingContext* aBrowsingContextToClear, bool aIsLeavingDocument, bool aAdjustWidget, bool aRemainActive, Element* aElementToFocus, uint64_t aActionId) { @@ -1148,7 +1148,7 @@ index 22c175c93ef7bc81640b0ad71bd6ca9c1082fea6..7d77e91afbfe7aebe0c94793c2e06067 LOGFOCUS(("<>", aActionId)); // hold a reference to the focused content, which may be null -@@ -2315,6 +2320,11 @@ bool nsFocusManager::BlurImpl(BrowsingContext* aBrowsingContextToClear, +@@ -2328,6 +2333,11 @@ bool nsFocusManager::BlurImpl(BrowsingContext* aBrowsingContextToClear, return true; } @@ -1160,7 +1160,7 @@ index 22c175c93ef7bc81640b0ad71bd6ca9c1082fea6..7d77e91afbfe7aebe0c94793c2e06067 // Keep a ref to presShell since dispatching the DOM event may cause // the document to be destroyed. RefPtr presShell = docShell->GetPresShell(); -@@ -2992,7 +3002,9 @@ void nsFocusManager::RaiseWindow(nsPIDOMWindowOuter* aWindow, +@@ -3005,7 +3015,9 @@ void nsFocusManager::RaiseWindow(nsPIDOMWindowOuter* aWindow, } } @@ -1172,10 +1172,10 @@ index 22c175c93ef7bc81640b0ad71bd6ca9c1082fea6..7d77e91afbfe7aebe0c94793c2e06067 // 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 e47d4979078343102f00e93df913ff778b841804..360ab27a8f3394d18b558de80b5d0bbb963c1391 100644 +index f2aa07e2c1e6df28e165b1868ad9717248360972..2b1b406c4fdf6d0716b9c29c3e640de210eae749 100644 --- a/dom/base/nsGlobalWindowOuter.cpp +++ b/dom/base/nsGlobalWindowOuter.cpp -@@ -2514,10 +2514,16 @@ nsresult nsGlobalWindowOuter::SetNewDocument(Document* aDocument, +@@ -2516,10 +2516,16 @@ nsresult nsGlobalWindowOuter::SetNewDocument(Document* aDocument, }(); if (!isContentAboutBlankInChromeDocshell) { @@ -1196,7 +1196,7 @@ index e47d4979078343102f00e93df913ff778b841804..360ab27a8f3394d18b558de80b5d0bbb } } -@@ -2637,6 +2643,19 @@ void nsGlobalWindowOuter::DispatchDOMWindowCreated() { +@@ -2639,6 +2645,19 @@ void nsGlobalWindowOuter::DispatchDOMWindowCreated() { } } @@ -1217,10 +1217,10 @@ index e47d4979078343102f00e93df913ff778b841804..360ab27a8f3394d18b558de80b5d0bbb void nsGlobalWindowOuter::SetDocShell(nsDocShell* aDocShell) { diff --git a/dom/base/nsGlobalWindowOuter.h b/dom/base/nsGlobalWindowOuter.h -index 0039d6d91b23953afbd6aec2b4d1f064db3c3b1c..7a6c5da16651d34ea60c69331365d94886da1993 100644 +index e2a2b560b565e6eb3cd5b4e77eb30051afe7a418..81eaca3fb0acfe90bf07acb4115a0db0786c6998 100644 --- a/dom/base/nsGlobalWindowOuter.h +++ b/dom/base/nsGlobalWindowOuter.h -@@ -314,6 +314,7 @@ class nsGlobalWindowOuter final : public mozilla::dom::EventTarget, +@@ -317,6 +317,7 @@ class nsGlobalWindowOuter final : public mozilla::dom::EventTarget, // Outer windows only. void DispatchDOMWindowCreated(); @@ -1229,7 +1229,7 @@ index 0039d6d91b23953afbd6aec2b4d1f064db3c3b1c..7a6c5da16651d34ea60c69331365d948 // Outer windows only. virtual void EnsureSizeAndPositionUpToDate() override; diff --git a/dom/base/nsINode.cpp b/dom/base/nsINode.cpp -index 4b54dcd5b4fc9c575552ae82d5ed66f313cdeb72..e75b5f148d55d8f7d7e098a84930fec0e28aa01d 100644 +index 091d04dd79da3acc33aa22405ddb984ba486dfe2..40bb124fd735c2d214221c1a5fac442e26f7564e 100644 --- a/dom/base/nsINode.cpp +++ b/dom/base/nsINode.cpp @@ -1402,6 +1402,61 @@ void nsINode::GetBoxQuadsFromWindowOrigin(const BoxQuadOptions& aOptions, @@ -1295,10 +1295,10 @@ index 4b54dcd5b4fc9c575552ae82d5ed66f313cdeb72..e75b5f148d55d8f7d7e098a84930fec0 DOMQuad& aQuad, const GeometryNode& aFrom, const ConvertCoordinateOptions& aOptions, CallerType aCallerType, diff --git a/dom/base/nsINode.h b/dom/base/nsINode.h -index 6f980f472aefe147de47212717ca300e62e02952..3d60daf88196ed502fc647cc7b51d2eb70a281ef 100644 +index 3bc7ff8a3d9e7f3148f51da13f34ea1b3ca2ba77..dcb47740ca93ab237e4f55d4225f77283f5f404b 100644 --- a/dom/base/nsINode.h +++ b/dom/base/nsINode.h -@@ -2303,6 +2303,10 @@ class nsINode : public mozilla::dom::EventTarget { +@@ -2317,6 +2317,10 @@ class nsINode : public mozilla::dom::EventTarget { nsTArray>& aResult, ErrorResult& aRv); @@ -1310,10 +1310,10 @@ index 6f980f472aefe147de47212717ca300e62e02952..3d60daf88196ed502fc647cc7b51d2eb 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 48df3ae2d30b975269d06e6354b143abd3e5fcd8..87c8d237355668b0ff324f49be879219b1761083 100644 --- a/dom/base/nsJSUtils.cpp +++ b/dom/base/nsJSUtils.cpp -@@ -177,6 +177,11 @@ bool nsJSUtils::GetScopeChainForElement( +@@ -149,6 +149,11 @@ bool nsJSUtils::GetScopeChainForElement( return true; } @@ -1326,10 +1326,10 @@ 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 8b4c1492c64884d83eb1553bc40b921e0da601b7..ee66eaa21d8e8c208204ef73fca5b3d78abefb24 100644 --- a/dom/base/nsJSUtils.h +++ b/dom/base/nsJSUtils.h -@@ -79,6 +79,7 @@ class nsJSUtils { +@@ -71,6 +71,7 @@ class nsJSUtils { JSContext* aCx, mozilla::dom::Element* aElement, JS::MutableHandleVector aScopeChain); @@ -1479,18 +1479,18 @@ index 7e1af00d05fbafa2d828e2c7e4dcc5c82d115f5b..e85af9718d064e4d2865bc944e9d4ba1 ~Geolocation(); diff --git a/dom/html/HTMLInputElement.cpp b/dom/html/HTMLInputElement.cpp -index e2a77a11435a80abbb6381ffabbb5711eca0ac0d..a614efef052ca7c39457726d1f1e66f7cff777f8 100644 +index d40c2a230c8c86f585935061d05e20b405c906fe..29547e7a0d75fdc8b8b30344db32287424e65fba 100644 --- a/dom/html/HTMLInputElement.cpp +++ b/dom/html/HTMLInputElement.cpp -@@ -59,6 +59,7 @@ +@@ -60,6 +60,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" -@@ -784,6 +785,13 @@ nsresult HTMLInputElement::InitFilePicker(FilePickerType aType) { + #include "nsRangeFrame.h" + #include "nsError.h" +@@ -783,6 +784,13 @@ nsresult HTMLInputElement::InitFilePicker(FilePickerType aType) { return NS_ERROR_FAILURE; } @@ -1505,7 +1505,7 @@ index e2a77a11435a80abbb6381ffabbb5711eca0ac0d..a614efef052ca7c39457726d1f1e66f7 return NS_OK; } diff --git a/dom/interfaces/base/nsIDOMWindowUtils.idl b/dom/interfaces/base/nsIDOMWindowUtils.idl -index ac0251b4989799e9bb370a8066d10f13154bbc7c..184f4d980c35652c67da06e917e9d0b85ff34cea 100644 +index 89202fa1ff22593e7cb5e20fc40b3b3b8e114449..61ed40c8454c6e85876cbc7c240496cc96f77239 100644 --- a/dom/interfaces/base/nsIDOMWindowUtils.idl +++ b/dom/interfaces/base/nsIDOMWindowUtils.idl @@ -374,6 +374,26 @@ interface nsIDOMWindowUtils : nsISupports { @@ -1536,7 +1536,7 @@ index ac0251b4989799e9bb370a8066d10f13154bbc7c..184f4d980c35652c67da06e917e9d0b8 * touchstart, touchend, touchmove, and touchcancel * diff --git a/dom/ipc/BrowserChild.cpp b/dom/ipc/BrowserChild.cpp -index 204ee71ece1afa8b416caafcb4bdd242344f1a26..8597f2d0c4bd7a6fbfed9f29d002d0c59c8f8ae9 100644 +index 0335a887fe157210f9eef58bf63be879f7d5de2b..dfbb8dae406f9d9276a2719f515ac5a51f8a671d 100644 --- a/dom/ipc/BrowserChild.cpp +++ b/dom/ipc/BrowserChild.cpp @@ -1656,6 +1656,21 @@ void BrowserChild::HandleRealMouseButtonEvent(const WidgetMouseEvent& aEvent, @@ -1822,7 +1822,7 @@ index 3b39538e51840cd9b1685b2efd2ff2e9ec83608a..c7bf4f2d53b58bbacb22b3ebebf6f3fc return aGlobalOrNull; diff --git a/dom/security/nsCSPUtils.cpp b/dom/security/nsCSPUtils.cpp -index 4eafb2247d5aa8e989c0359d6d9d864edf73759d..e0d0b5bc78537c6fa8d0cf02cc6c772993008b91 100644 +index ff2e907c0d8fc05c6e39fae612eceed405b62712..40ec25b5588a1628f9d9bd16886bed83dad49b90 100644 --- a/dom/security/nsCSPUtils.cpp +++ b/dom/security/nsCSPUtils.cpp @@ -22,6 +22,7 @@ @@ -1869,10 +1869,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 6085248083194be05e85c3be7f0e69fd1928bf3d..23b72e2d0030496d5b05c88f06ed1a30ed33396b 100644 +index 1ba2051ed316956a5a71f85ed5fa0735d54716e5..c0d6f45ce14040a79cfe134a4f8254434a4c53cc 100644 --- a/dom/workers/RuntimeService.cpp +++ b/dom/workers/RuntimeService.cpp -@@ -998,7 +998,7 @@ void PrefLanguagesChanged(const char* /* aPrefName */, void* /* aClosure */) { +@@ -1007,7 +1007,7 @@ void PrefLanguagesChanged(const char* /* aPrefName */, void* /* aClosure */) { AssertIsOnMainThread(); nsTArray languages; @@ -1881,7 +1881,7 @@ index 6085248083194be05e85c3be7f0e69fd1928bf3d..23b72e2d0030496d5b05c88f06ed1a30 RuntimeService* runtime = RuntimeService::GetService(); if (runtime) { -@@ -1185,8 +1185,7 @@ bool RuntimeService::RegisterWorker(WorkerPrivate& aWorkerPrivate) { +@@ -1194,8 +1194,7 @@ bool RuntimeService::RegisterWorker(WorkerPrivate& aWorkerPrivate) { } // The navigator overridden properties should have already been read. @@ -1891,7 +1891,7 @@ index 6085248083194be05e85c3be7f0e69fd1928bf3d..23b72e2d0030496d5b05c88f06ed1a30 mNavigatorPropertiesLoaded = true; } -@@ -1808,6 +1807,13 @@ void RuntimeService::PropagateStorageAccessPermissionGranted( +@@ -1817,6 +1816,13 @@ void RuntimeService::PropagateStorageAccessPermissionGranted( } } @@ -1905,7 +1905,7 @@ index 6085248083194be05e85c3be7f0e69fd1928bf3d..23b72e2d0030496d5b05c88f06ed1a30 template void RuntimeService::BroadcastAllWorkers(const Func& aFunc) { AssertIsOnMainThread(); -@@ -2333,6 +2339,14 @@ void PropagateStorageAccessPermissionGrantedToWorkers( +@@ -2342,6 +2348,14 @@ void PropagateStorageAccessPermissionGrantedToWorkers( } } @@ -1947,7 +1947,7 @@ index 58894a8361c7ef1dddd481ca5877a209a8b8ff5c..c481d40d79b6397b7f1d571bd9f6ae5c bool IsWorkerGlobal(JSObject* global); diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp -index 089f42307becf7c6f81199d970fb8870db494818..63fb760ac831bc88415aee1cddf8b59662e55f37 100644 +index 2b48cc2980165ce51ded62faef96b93b781ede32..d8dc90983353c2f5cc1db56e327c4533d524cc1d 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -700,6 +700,18 @@ class UpdateContextOptionsRunnable final : public WorkerControlRunnable { @@ -1969,7 +1969,7 @@ index 089f42307becf7c6f81199d970fb8870db494818..63fb760ac831bc88415aee1cddf8b596 class UpdateLanguagesRunnable final : public WorkerThreadRunnable { nsTArray mLanguages; -@@ -2108,6 +2120,16 @@ void WorkerPrivate::UpdateContextOptions( +@@ -2113,6 +2125,16 @@ void WorkerPrivate::UpdateContextOptions( } } @@ -1986,7 +1986,7 @@ index 089f42307becf7c6f81199d970fb8870db494818..63fb760ac831bc88415aee1cddf8b596 void WorkerPrivate::UpdateLanguages(const nsTArray& aLanguages) { AssertIsOnParentThread(); -@@ -5736,6 +5758,15 @@ void WorkerPrivate::UpdateContextOptionsInternal( +@@ -5740,6 +5762,15 @@ void WorkerPrivate::UpdateContextOptionsInternal( } } @@ -2003,7 +2003,7 @@ index 089f42307becf7c6f81199d970fb8870db494818..63fb760ac831bc88415aee1cddf8b596 const nsTArray& aLanguages) { WorkerGlobalScope* globalScope = GlobalScope(); diff --git a/dom/workers/WorkerPrivate.h b/dom/workers/WorkerPrivate.h -index dfb96b7b798785d7b75c683bc0969e39487137a3..a463eec618af51fdbc25db509870598846c0fd66 100644 +index da25a495a8930f7b88958553164d86fe2869416f..38f92829438ead78d73d96ee48a3fcab46c337d7 100644 --- a/dom/workers/WorkerPrivate.h +++ b/dom/workers/WorkerPrivate.h @@ -432,6 +432,8 @@ class WorkerPrivate final @@ -2015,7 +2015,7 @@ index dfb96b7b798785d7b75c683bc0969e39487137a3..a463eec618af51fdbc25db5098705988 void UpdateLanguagesInternal(const nsTArray& aLanguages); void UpdateJSWorkerMemoryParameterInternal(JSContext* aCx, JSGCParamKey key, -@@ -1059,6 +1061,8 @@ class WorkerPrivate final +@@ -1069,6 +1071,8 @@ class WorkerPrivate final void UpdateContextOptions(const JS::ContextOptions& aContextOptions); @@ -2247,10 +2247,10 @@ index 0ec6ee3eb37c6493d8a25352fd0e54e1927bceab..885dba71bc5815e5f6f3ec2700c376aa // No boxes to return return; diff --git a/layout/base/PresShell.cpp b/layout/base/PresShell.cpp -index f154e05a8c2e2ebf07565d087a42436feeb17f53..0af8c24c0f391c52fe2acfeb01cacb32358e6861 100644 +index 2cc3c5673e246ac38cdaddb457ce36ee4c7356ce..61093cd52fc049ad77d84dd837731071fdace69d 100644 --- a/layout/base/PresShell.cpp +++ b/layout/base/PresShell.cpp -@@ -11064,7 +11064,9 @@ bool PresShell::ComputeActiveness() const { +@@ -11163,7 +11163,9 @@ bool PresShell::ComputeActiveness() const { if (!browserChild->IsVisible()) { MOZ_LOG(gLog, LogLevel::Debug, (" > BrowserChild %p is not visible", browserChild)); @@ -2262,7 +2262,7 @@ index f154e05a8c2e2ebf07565d087a42436feeb17f53..0af8c24c0f391c52fe2acfeb01cacb32 // 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 0011b1a1a36da0dec7cc6afa6fd689a4c8710d37..25bebd7b03b0b8dc595607bae07f360f3be3f284 100644 +index d8995d6d94f5861d8ed839613768eb269b44e362..b946de49a0ecab449a9d1aff24c38f69a431eec0 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -698,6 +698,10 @@ bool nsLayoutUtils::AllowZoomingForDocument( @@ -2276,7 +2276,7 @@ index 0011b1a1a36da0dec7cc6afa6fd689a4c8710d37..25bebd7b03b0b8dc595607bae07f360f // True if we allow zooming for all documents on this platform, or if we are // in RDM. BrowsingContext* bc = aDocument->GetBrowsingContext(); -@@ -9791,6 +9795,9 @@ void nsLayoutUtils::ComputeSystemFont(nsFont* aSystemFont, +@@ -9768,6 +9772,9 @@ void nsLayoutUtils::ComputeSystemFont(nsFont* aSystemFont, /* static */ bool nsLayoutUtils::ShouldHandleMetaViewport(const Document* aDocument) { @@ -2287,10 +2287,10 @@ index 0011b1a1a36da0dec7cc6afa6fd689a4c8710d37..25bebd7b03b0b8dc595607bae07f360f return StaticPrefs::dom_meta_viewport_enabled() || (bc && bc->InRDMPane()); } diff --git a/layout/style/GeckoBindings.h b/layout/style/GeckoBindings.h -index d273793fc8d92b5c19ec0562730eab249cc41eb8..46b4078c6031318265a8338e01f52ab60bd9c0e8 100644 +index c18d38d8ad2f80bb0d3512d1a9ae965c594bb356..22736c86eb5e3d0a44563c312e34032c157f3abe 100644 --- a/layout/style/GeckoBindings.h +++ b/layout/style/GeckoBindings.h -@@ -596,6 +596,7 @@ float Gecko_MediaFeatures_GetResolution(const mozilla::dom::Document*); +@@ -595,6 +595,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*); @@ -2351,7 +2351,7 @@ index 21d5a5e1b4193d058c30268ab73c8d595436b381..11b960ec0ff3ea77857cb915d05bbdbb + } // namespace mozilla::net diff --git a/netwerk/base/LoadInfo.h b/netwerk/base/LoadInfo.h -index 52d867196a459578cbea1a4f626afbe51dd1abd5..2904832cbcad476fdebb54c7e24d5f14b1c0fb4b 100644 +index 6ba1d8e11efbbf75f4a44d4977587429ad1371f8..d834f1f5528264f59c4547f00825e0a3b433d9dd 100644 --- a/netwerk/base/LoadInfo.h +++ b/netwerk/base/LoadInfo.h @@ -413,9 +413,10 @@ class LoadInfo final : public nsILoadInfo { @@ -2360,7 +2360,7 @@ index 52d867196a459578cbea1a4f626afbe51dd1abd5..2904832cbcad476fdebb54c7e24d5f14 bool mWasSchemelessInput = false; - nsILoadInfo::HTTPSUpgradeTelemetryType mHttpsUpgradeTelemetry = - nsILoadInfo::NO_UPGRADE; + nsILoadInfo::NOT_INITIALIZED; + + uint64_t mJugglerLoadIdentifier = 0; }; @@ -2387,10 +2387,10 @@ index 9dc2bb0da6871b905abd17d931e555429977c6c2..b71cf6393492346f16417b3ba745a235 } // namespace net } // namespace mozilla diff --git a/netwerk/base/nsILoadInfo.idl b/netwerk/base/nsILoadInfo.idl -index 12f43b911006d5b0bbfa9936070dc0d561bc7bb4..94d20cdca548534ad5e4ef4f937e287c58768870 100644 +index daccd1dc75fb1f6ba88c8f734e10c14cbdbffe8f..9621ca5dc05f12a8d81da787fa479fe03ea99e4c 100644 --- a/netwerk/base/nsILoadInfo.idl +++ b/netwerk/base/nsILoadInfo.idl -@@ -1586,4 +1586,5 @@ interface nsILoadInfo : nsISupports +@@ -1590,4 +1590,5 @@ interface nsILoadInfo : nsISupports */ [infallible] attribute nsILoadInfo_HTTPSUpgradeTelemetryType httpsUpgradeTelemetry; @@ -2409,7 +2409,7 @@ index 7f91d2df6f8bb4020c75c132dc8f6bf26625fa1e..ba6569f4be8fc54ec96ee44d5de45a09 /** * Set the status and reason for the forthcoming synthesized response. diff --git a/netwerk/ipc/DocumentLoadListener.cpp b/netwerk/ipc/DocumentLoadListener.cpp -index 10f65a549ce886bf7f19de02714482e28a8931a5..f41d32ce90f7345ad5a9bd90e420354865f35235 100644 +index ef946929c9bbd7903c8e3b32bcb373d5096aed52..a2814c5c891e2877aca9fdb4698385282b8743a9 100644 --- a/netwerk/ipc/DocumentLoadListener.cpp +++ b/netwerk/ipc/DocumentLoadListener.cpp @@ -171,6 +171,7 @@ static auto CreateDocumentLoadInfo(CanonicalBrowsingContext* aBrowsingContext, @@ -2459,10 +2459,10 @@ index e81a4538fd45c13aa60d933de5f4f32ce69fb5f2..d7945f81295c497485a09696f06ce041 if (mPump && mLoadFlags & LOAD_CALL_CONTENT_SNIFFERS) { mPump->PeekStream(CallTypeSniffers, static_cast(this)); diff --git a/parser/html/nsHtml5TreeOpExecutor.cpp b/parser/html/nsHtml5TreeOpExecutor.cpp -index f25949e6cc907ff18a76d68fc2e8005bd40146ea..9be4cb34517b06b94c6e145aef8a8ea5d2687d97 100644 +index 071ed8da4135102b0b1fedce32326bdc0657c3fd..063b516001a674b558046f9191f08352eb671801 100644 --- a/parser/html/nsHtml5TreeOpExecutor.cpp +++ b/parser/html/nsHtml5TreeOpExecutor.cpp -@@ -1389,6 +1389,10 @@ void nsHtml5TreeOpExecutor::UpdateReferrerInfoFromMeta( +@@ -1391,6 +1391,10 @@ void nsHtml5TreeOpExecutor::UpdateReferrerInfoFromMeta( void nsHtml5TreeOpExecutor::AddSpeculationCSP(const nsAString& aCSP) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); @@ -2474,10 +2474,10 @@ index f25949e6cc907ff18a76d68fc2e8005bd40146ea..9be4cb34517b06b94c6e145aef8a8ea5 nsCOMPtr preloadCsp = mDocument->GetPreloadCsp(); if (!preloadCsp) { diff --git a/security/manager/ssl/nsCertOverrideService.cpp b/security/manager/ssl/nsCertOverrideService.cpp -index fcc2a45e6de8eaeb1af2404a69bd3df58cf2aec8..d4c1df007bf5993cf9e0dadbe91aa2c38afc42ec 100644 +index b2e328e7c7d7a89be34b84fd176c306a3620c77c..54f24b213bcdc78c702e15d4d45a3943bc082281 100644 --- a/security/manager/ssl/nsCertOverrideService.cpp +++ b/security/manager/ssl/nsCertOverrideService.cpp -@@ -437,7 +437,12 @@ nsCertOverrideService::HasMatchingOverride( +@@ -439,7 +439,12 @@ nsCertOverrideService::HasMatchingOverride( bool disableAllSecurityCheck = false; { MutexAutoLock lock(mMutex); @@ -2491,7 +2491,7 @@ index fcc2a45e6de8eaeb1af2404a69bd3df58cf2aec8..d4c1df007bf5993cf9e0dadbe91aa2c3 } if (disableAllSecurityCheck) { *aIsTemporary = false; -@@ -649,14 +654,24 @@ static bool IsDebugger() { +@@ -651,14 +656,24 @@ static bool IsDebugger() { NS_IMETHODIMP nsCertOverrideService:: @@ -2625,10 +2625,10 @@ index 00a5381133f8cec0de452c31c7151801a1acc0b9..5d3e3d6f566dc724f257beaeb994ceda if (provider.failed) { diff --git a/toolkit/components/resistfingerprinting/nsUserCharacteristics.cpp b/toolkit/components/resistfingerprinting/nsUserCharacteristics.cpp -index 144628a310662eb393d8c1a4fffbec3cf5fd1dff..69fa66f27d0533f3d90801acbfa23039ef81f7df 100644 +index 6a40d032449e780bfeb77934ba141317b94e7189..1468d38355058b985f18613bd6e3bc84086fae40 100644 --- a/toolkit/components/resistfingerprinting/nsUserCharacteristics.cpp +++ b/toolkit/components/resistfingerprinting/nsUserCharacteristics.cpp -@@ -632,7 +632,7 @@ void PopulateLanguages() { +@@ -553,7 +553,7 @@ void PopulateLanguages() { // sufficient to only collect this information as the other properties are // just reformats of Navigator::GetAcceptLanguages. nsTArray languages; @@ -2666,10 +2666,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 cdba76dc8ae2206a58d7e5eb6eba97c2c3732513..266fdc6235363eafc6c7b587d5c0f597deee6e59 100644 +index e3f616c4efd5d7e10ed372afa4b5c4d2d93e6a67..abb7772184c9baf23025c1577d1284b6ed1959fb 100644 --- a/toolkit/components/windowwatcher/nsWindowWatcher.cpp +++ b/toolkit/components/windowwatcher/nsWindowWatcher.cpp -@@ -1865,7 +1865,11 @@ uint32_t nsWindowWatcher::CalculateChromeFlagsForContent( +@@ -1881,7 +1881,11 @@ uint32_t nsWindowWatcher::CalculateChromeFlagsForContent( // Open a minimal popup. *aIsPopupRequested = true; @@ -2683,10 +2683,10 @@ index cdba76dc8ae2206a58d7e5eb6eba97c2c3732513..266fdc6235363eafc6c7b587d5c0f597 /** diff --git a/toolkit/mozapps/update/UpdateService.sys.mjs b/toolkit/mozapps/update/UpdateService.sys.mjs -index be01248253ee1bcc9435c3e8223ed032f498a023..0f05923c29a023511b72a81ec527300cafa17760 100644 +index 6c2b400952492266a184c96b4a1ce71e87df7ffe..6e1fb4f59b6a6d70100e1eb1d15c937d8480988a 100644 --- a/toolkit/mozapps/update/UpdateService.sys.mjs +++ b/toolkit/mozapps/update/UpdateService.sys.mjs -@@ -3888,6 +3888,8 @@ export class UpdateService { +@@ -3894,6 +3894,8 @@ export class UpdateService { } get disabledForTesting() { @@ -2696,10 +2696,10 @@ index be01248253ee1bcc9435c3e8223ed032f498a023..0f05923c29a023511b72a81ec527300c } diff --git a/toolkit/toolkit.mozbuild b/toolkit/toolkit.mozbuild -index 8c2b2bf996bd889651dc7fac1dc351b4c47b567e..07d237eb17a657ce051fd0aa5e53449c0c3159f6 100644 +index f42ed17a4a75689ae9c8e769d7b6e2c3f654b8ee..5af0877335339407160dd7d10b89bd3d62adff9f 100644 --- a/toolkit/toolkit.mozbuild +++ b/toolkit/toolkit.mozbuild -@@ -155,6 +155,7 @@ if CONFIG["ENABLE_WEBDRIVER"]: +@@ -156,6 +156,7 @@ if CONFIG["ENABLE_WEBDRIVER"]: "/remote", "/testing/firefox-ui", "/testing/marionette", @@ -2760,7 +2760,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 ad769a235b6a7ccf7791a3d9680f3bf373b30a86..ff18e7516a2bc3258b00d958cbaa4790eafcbc6a 100644 +index 139a43a1780dac34a6d8b135accac9cf39beef3f..2a855c3ae87e4e5a431cb1547cda0ee88490ca33 100644 --- a/uriloader/exthandler/nsExternalHelperAppService.cpp +++ b/uriloader/exthandler/nsExternalHelperAppService.cpp @@ -112,6 +112,7 @@ @@ -2771,7 +2771,7 @@ index ad769a235b6a7ccf7791a3d9680f3bf373b30a86..ff18e7516a2bc3258b00d958cbaa4790 #include "mozilla/Preferences.h" #include "mozilla/ipc/URIUtils.h" -@@ -831,6 +832,12 @@ NS_IMETHODIMP nsExternalHelperAppService::ApplyDecodingForExtension( +@@ -872,6 +873,12 @@ NS_IMETHODIMP nsExternalHelperAppService::ApplyDecodingForExtension( return NS_OK; } @@ -2784,7 +2784,7 @@ index ad769a235b6a7ccf7791a3d9680f3bf373b30a86..ff18e7516a2bc3258b00d958cbaa4790 nsresult nsExternalHelperAppService::GetFileTokenForPath( const char16_t* aPlatformAppPath, nsIFile** aFile) { nsDependentString platformAppPath(aPlatformAppPath); -@@ -1441,7 +1448,12 @@ nsresult nsExternalAppHandler::SetUpTempFile(nsIChannel* aChannel) { +@@ -1494,7 +1501,12 @@ nsresult nsExternalAppHandler::SetUpTempFile(nsIChannel* aChannel) { // Strip off the ".part" from mTempLeafName mTempLeafName.Truncate(mTempLeafName.Length() - ArrayLength(".part") + 1); @@ -2797,7 +2797,7 @@ index ad769a235b6a7ccf7791a3d9680f3bf373b30a86..ff18e7516a2bc3258b00d958cbaa4790 mSaver = do_CreateInstance(NS_BACKGROUNDFILESAVERSTREAMLISTENER_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); -@@ -1630,7 +1642,36 @@ NS_IMETHODIMP nsExternalAppHandler::OnStartRequest(nsIRequest* request) { +@@ -1683,7 +1695,36 @@ NS_IMETHODIMP nsExternalAppHandler::OnStartRequest(nsIRequest* request) { return NS_OK; } @@ -2835,7 +2835,7 @@ index ad769a235b6a7ccf7791a3d9680f3bf373b30a86..ff18e7516a2bc3258b00d958cbaa4790 if (NS_FAILED(rv)) { nsresult transferError = rv; -@@ -1682,6 +1723,9 @@ NS_IMETHODIMP nsExternalAppHandler::OnStartRequest(nsIRequest* request) { +@@ -1744,6 +1785,9 @@ NS_IMETHODIMP nsExternalAppHandler::OnStartRequest(nsIRequest* request) { bool alwaysAsk = true; mMimeInfo->GetAlwaysAskBeforeHandling(&alwaysAsk); @@ -2845,7 +2845,7 @@ index ad769a235b6a7ccf7791a3d9680f3bf373b30a86..ff18e7516a2bc3258b00d958cbaa4790 if (alwaysAsk) { // But we *don't* ask if this mimeInfo didn't come from // our user configuration datastore and the user has said -@@ -2198,6 +2242,16 @@ nsExternalAppHandler::OnSaveComplete(nsIBackgroundFileSaver* aSaver, +@@ -2260,6 +2304,16 @@ nsExternalAppHandler::OnSaveComplete(nsIBackgroundFileSaver* aSaver, NotifyTransfer(aStatus); } @@ -2862,7 +2862,7 @@ index ad769a235b6a7ccf7791a3d9680f3bf373b30a86..ff18e7516a2bc3258b00d958cbaa4790 return NS_OK; } -@@ -2679,6 +2733,15 @@ NS_IMETHODIMP nsExternalAppHandler::Cancel(nsresult aReason) { +@@ -2743,6 +2797,15 @@ NS_IMETHODIMP nsExternalAppHandler::Cancel(nsresult aReason) { } } @@ -2879,10 +2879,10 @@ index ad769a235b6a7ccf7791a3d9680f3bf373b30a86..ff18e7516a2bc3258b00d958cbaa4790 // OnStartRequest) mDialog = nullptr; diff --git a/uriloader/exthandler/nsExternalHelperAppService.h b/uriloader/exthandler/nsExternalHelperAppService.h -index 1f77e095dbfa3acc046779114007d83fc1cfa087..2354abbab7af6f6bdc3bd628722f03ea401d236a 100644 +index e880b90b2df85fb3b1ab3ba8d2fc181b824e2272..dbadd74dea9b245d68da3b2856e16b7b98c655d0 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); @@ -2891,7 +2891,7 @@ index 1f77e095dbfa3acc046779114007d83fc1cfa087..2354abbab7af6f6bdc3bd628722f03ea }; /** -@@ -462,6 +464,9 @@ class nsExternalAppHandler final : public nsIStreamListener, +@@ -463,6 +465,9 @@ class nsExternalAppHandler final : public nsIStreamListener, * Upon successful return, both mTempFile and mSaver will be valid. */ nsresult SetUpTempFile(nsIChannel* aChannel); @@ -2902,7 +2902,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..97ace81c82b16a9a993166dd4b0ddb3a721c9872 100644 +index 53ea934dd4876e4b491b724385c8fbf7d00ee6cd..0b7b88c853b21ce778d8e87fea0a2bfe839ad412 100644 --- a/uriloader/exthandler/nsIExternalHelperAppService.idl +++ b/uriloader/exthandler/nsIExternalHelperAppService.idl @@ -6,8 +6,11 @@ @@ -2935,10 +2935,11 @@ index 4a399acb72d4fd475c9ae43e9eadbc32f261e290..97ace81c82b16a9a993166dd4b0ddb3a /** * 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); }; diff --git a/browser_patches/webkit/UPSTREAM_CONFIG.sh b/browser_patches/webkit/UPSTREAM_CONFIG.sh index 57f8fb13f9..3fb94ec302 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="2ea46ab90e6511139bfb94415205038b672381e0" +BASE_REVISION="8ceb1da47e75a488ae4c12017a861636904acd4f" diff --git a/browser_patches/webkit/embedder/Playwright/mac/AppDelegate.m b/browser_patches/webkit/embedder/Playwright/mac/AppDelegate.m index a6c7be8ae4..f9708d364d 100644 --- a/browser_patches/webkit/embedder/Playwright/mac/AppDelegate.m +++ b/browser_patches/webkit/embedder/Playwright/mac/AppDelegate.m @@ -97,7 +97,7 @@ const NSActivityOptions ActivityOptions = 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 +230,7 @@ const NSActivityOptions ActivityOptions = 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; diff --git a/browser_patches/webkit/patches/bootstrap.diff b/browser_patches/webkit/patches/bootstrap.diff index df3776b1a6..ea833df5fd 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 74eeee34f579a6596f8d59ad81f5303dbaba1556..6bf3b11b950a8fe0af990b916501e73858b2f51c 100644 +index db9554ed7eb6ddb62de1bc549a8e7c50944c7869..b6ce1761f11281c6362790ee59d83feed6f717cf 100644 --- a/Source/JavaScriptCore/CMakeLists.txt +++ b/Source/JavaScriptCore/CMakeLists.txt -@@ -1385,22 +1385,27 @@ set(JavaScriptCore_INSPECTOR_DOMAINS +@@ -1398,22 +1398,27 @@ set(JavaScriptCore_INSPECTOR_DOMAINS ${JAVASCRIPTCORE_DIR}/inspector/protocol/CSS.json ${JAVASCRIPTCORE_DIR}/inspector/protocol/Canvas.json ${JAVASCRIPTCORE_DIR}/inspector/protocol/Console.json @@ -31,10 +31,10 @@ index 74eeee34f579a6596f8d59ad81f5303dbaba1556..6bf3b11b950a8fe0af990b916501e738 ${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 eebcd3f03aeb560fd70ab52b325e21c5ced74321..340323566ea7c8f5d85303c7adb4570913a41451 100644 --- a/Source/JavaScriptCore/DerivedSources-input.xcfilelist +++ b/Source/JavaScriptCore/DerivedSources-input.xcfilelist -@@ -98,21 +98,26 @@ $(PROJECT_DIR)/inspector/protocol/CPUProfiler.json +@@ -99,21 +99,26 @@ $(PROJECT_DIR)/inspector/protocol/CPUProfiler.json $(PROJECT_DIR)/inspector/protocol/CSS.json $(PROJECT_DIR)/inspector/protocol/Canvas.json $(PROJECT_DIR)/inspector/protocol/Console.json @@ -62,10 +62,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 3033ef7fc7e1db0e4b6fb85236997ce92b1946a5..87fc65714ad2caa21ac19aabf0a7d93badb4c848 100644 +index 99dd36c7234cecd9c6620c94c4e6e93ff6548d77..d2017ded67f3e811d0f905be238c73ccb0348aa7 100644 --- a/Source/JavaScriptCore/DerivedSources.make +++ b/Source/JavaScriptCore/DerivedSources.make -@@ -298,22 +298,27 @@ INSPECTOR_DOMAINS := \ +@@ -299,22 +299,27 @@ INSPECTOR_DOMAINS := \ $(JavaScriptCore)/inspector/protocol/CSS.json \ $(JavaScriptCore)/inspector/protocol/Canvas.json \ $(JavaScriptCore)/inspector/protocol/Console.json \ @@ -367,10 +367,25 @@ 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 1ccce5707ca2a4743029614777bb6b9938f8a09c..cbb3466a855887d4dac3a6064e5de6ead051c1a6 100644 --- a/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.h +++ b/Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.h -@@ -51,15 +51,20 @@ public: +@@ -37,12 +37,12 @@ namespace Inspector { + + class InspectorTarget; + +-class InspectorTargetAgent final : public InspectorAgentBase, public TargetBackendDispatcherHandler, public CanMakeCheckedPtr { ++class JS_EXPORT_PRIVATE InspectorTargetAgent final : public InspectorAgentBase, public TargetBackendDispatcherHandler, public CanMakeCheckedPtr { + WTF_MAKE_NONCOPYABLE(InspectorTargetAgent); + WTF_MAKE_TZONE_ALLOCATED(InspectorTargetAgent); + WTF_OVERRIDE_DELETE_FOR_CHECKED_PTR(InspectorTargetAgent); + public: +- JS_EXPORT_PRIVATE InspectorTargetAgent(FrontendRouter&, BackendDispatcher&); ++ InspectorTargetAgent(FrontendRouter&, BackendDispatcher&); + ~InspectorTargetAgent() final; + + // InspectorAgentBase +@@ -53,14 +53,19 @@ public: Protocol::ErrorStringOr setPauseOnStart(bool) final; Protocol::ErrorStringOr resume(const String& targetId) final; Protocol::ErrorStringOr sendMessageToTarget(const String& targetId, const String& message) final; @@ -378,19 +393,22 @@ index 4edcbf5f4aee2eb8e5675a23b9db67e9d640ef7f..a32b0f3a5de49e58b8a35cec9202b788 + Protocol::ErrorStringOr close(const String& targetId, std::optional&& runBeforeUnload) override; // Target lifecycle. - void targetCreated(InspectorTarget&); - void targetDestroyed(InspectorTarget&); +- JS_EXPORT_PRIVATE void targetCreated(InspectorTarget&); +- JS_EXPORT_PRIVATE void targetDestroyed(InspectorTarget&); +- JS_EXPORT_PRIVATE void didCommitProvisionalTarget(const String& oldTargetID, const String& committedTargetID); ++ void targetCreated(InspectorTarget&); ++ void targetDestroyed(InspectorTarget&); + void targetCrashed(InspectorTarget&); - void didCommitProvisionalTarget(const String& oldTargetID, const String& committedTargetID); ++ void didCommitProvisionalTarget(const String& oldTargetID, const String& committedTargetID); // Target messages. - void sendMessageFromTargetToFrontend(const String& targetId, const String& message); - -+ bool isConnected() { return m_isConnected; } +- JS_EXPORT_PRIVATE void sendMessageFromTargetToFrontend(const String& targetId, const String& message); ++ void sendMessageFromTargetToFrontend(const String& targetId, const String& message); + ++ 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 27c65fbda226f1cd5bfd68944fe87fb9b2a688a6..b036f050859ee88004a7bf6daa4bb73835360615 100644 --- a/Source/JavaScriptCore/inspector/protocol/DOM.json @@ -1677,7 +1695,7 @@ index 52920cded24a9c6b0ef6fb4e518664955db4f9fa..bbbabc4e7259088b9404e8cc07eecd6f }, { diff --git a/Source/JavaScriptCore/profiler/ProfilerBytecodeSequence.cpp b/Source/JavaScriptCore/profiler/ProfilerBytecodeSequence.cpp -index 56a8f09aa0f4985f1af99f31f000b03dcb0c3901..f6f577b897d0b37df5d193df07702a190b8ed6a4 100644 +index 7c2ecd2c9afe3882903a590a76504d98da49f0af..9472d74977234a97e7ede76a042e22884c492594 100644 --- a/Source/JavaScriptCore/profiler/ProfilerBytecodeSequence.cpp +++ b/Source/JavaScriptCore/profiler/ProfilerBytecodeSequence.cpp @@ -28,7 +28,6 @@ @@ -1749,7 +1767,7 @@ index 0c5c8e689bdddec766f9de5bffd4444a5e068d77..330dd1f585e530722178c65c883641a2 // 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 57588b1d0c8eefc9ab5a145a5e6cd65b0bd71f6c..1fca47ffc1166cd37a2ea56337440f26db6a2830 100644 +index fe9c7b3f648392219fdf5be8d2bab99e1b4959e4..def7770bc94a1f533add081e907826058f169bbe 100644 --- a/Source/ThirdParty/libwebrtc/Configurations/libwebrtc.exp +++ b/Source/ThirdParty/libwebrtc/Configurations/libwebrtc.exp @@ -403,3 +403,24 @@ __ZN3rtc15CountIPMaskBitsERKNS_9IPAddressE @@ -1993,10 +2011,10 @@ index 4450f961579b52a88876cfc2d72a59bab4ccb863..4a217d81585ce495237aa013d3ace98a isa = XCConfigurationList; buildConfigurations = ( diff --git a/Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml b/Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml -index adfe9cf8a01ce98f1a7cee8c77ff35f697e60f2e..e663c77ee07785a3b74a8f2eead876dd483d0d28 100644 +index 5b41178d65c94c1b0e1a51e37b21f9b6e827dbdd..716f80a56e5850b26bc7c0d1b2d91d70506b415d 100644 --- a/Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml +++ b/Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml -@@ -575,6 +575,7 @@ ApplePayEnabled: +@@ -607,6 +607,7 @@ ApplePayEnabled: default: false # FIXME: This is on by default in WebKit2 PLATFORM(COCOA). Perhaps we should consider turning it on for WebKitLegacy as well. @@ -2004,7 +2022,7 @@ index adfe9cf8a01ce98f1a7cee8c77ff35f697e60f2e..e663c77ee07785a3b74a8f2eead876dd AsyncClipboardAPIEnabled: type: bool status: mature -@@ -585,7 +586,7 @@ AsyncClipboardAPIEnabled: +@@ -617,7 +618,7 @@ AsyncClipboardAPIEnabled: default: false WebKit: "PLATFORM(COCOA) || PLATFORM(GTK)" : true @@ -2013,7 +2031,7 @@ index adfe9cf8a01ce98f1a7cee8c77ff35f697e60f2e..e663c77ee07785a3b74a8f2eead876dd WebCore: default: false -@@ -1893,6 +1894,7 @@ CrossOriginEmbedderPolicyEnabled: +@@ -2046,6 +2047,7 @@ CrossOriginEmbedderPolicyEnabled: WebCore: default: false @@ -2021,7 +2039,7 @@ index adfe9cf8a01ce98f1a7cee8c77ff35f697e60f2e..e663c77ee07785a3b74a8f2eead876dd CrossOriginOpenerPolicyEnabled: type: bool status: stable -@@ -1947,7 +1949,7 @@ CustomPasteboardDataEnabled: +@@ -2086,7 +2088,7 @@ CustomPasteboardDataEnabled: WebKitLegacy: default: false WebKit: @@ -2030,7 +2048,7 @@ index adfe9cf8a01ce98f1a7cee8c77ff35f697e60f2e..e663c77ee07785a3b74a8f2eead876dd default: false CustomStateSetEnabled: -@@ -2006,6 +2008,7 @@ DOMAudioSessionFullEnabled: +@@ -2145,6 +2147,7 @@ DOMAudioSessionFullEnabled: WebCore: default: false @@ -2038,7 +2056,7 @@ index adfe9cf8a01ce98f1a7cee8c77ff35f697e60f2e..e663c77ee07785a3b74a8f2eead876dd DOMPasteAccessRequestsEnabled: type: bool status: internal -@@ -2017,7 +2020,7 @@ DOMPasteAccessRequestsEnabled: +@@ -2156,7 +2159,7 @@ DOMPasteAccessRequestsEnabled: default: false WebKit: "PLATFORM(IOS) || PLATFORM(MAC) || PLATFORM(GTK) || PLATFORM(VISION)": true @@ -2047,7 +2065,7 @@ index adfe9cf8a01ce98f1a7cee8c77ff35f697e60f2e..e663c77ee07785a3b74a8f2eead876dd WebCore: default: false -@@ -2361,7 +2364,7 @@ DirectoryUploadEnabled: +@@ -2516,7 +2519,7 @@ DirectoryUploadEnabled: WebKitLegacy: default: false WebKit: @@ -2056,7 +2074,7 @@ index adfe9cf8a01ce98f1a7cee8c77ff35f697e60f2e..e663c77ee07785a3b74a8f2eead876dd default: false WebCore: default: false -@@ -2783,10 +2786,10 @@ FullScreenEnabled: +@@ -2939,10 +2942,10 @@ FullScreenEnabled: WebKitLegacy: default: false WebKit: @@ -2069,7 +2087,7 @@ index adfe9cf8a01ce98f1a7cee8c77ff35f697e60f2e..e663c77ee07785a3b74a8f2eead876dd default: false sharedPreferenceForWebProcess: true -@@ -3423,6 +3426,7 @@ InspectorAttachmentSide: +@@ -3595,6 +3598,7 @@ InspectorAttachmentSide: WebKit: default: 0 @@ -2077,7 +2095,7 @@ index adfe9cf8a01ce98f1a7cee8c77ff35f697e60f2e..e663c77ee07785a3b74a8f2eead876dd InspectorStartsAttached: type: bool status: embedder -@@ -3430,7 +3434,7 @@ InspectorStartsAttached: +@@ -3602,7 +3606,7 @@ InspectorStartsAttached: exposed: [ WebKit ] defaultValue: WebKit: @@ -2086,7 +2104,7 @@ index adfe9cf8a01ce98f1a7cee8c77ff35f697e60f2e..e663c77ee07785a3b74a8f2eead876dd InspectorWindowFrame: type: String -@@ -3781,9 +3785,10 @@ LayoutViewportHeightExpansionFactor: +@@ -3953,9 +3957,10 @@ LayoutViewportHeightExpansionFactor: WebCore: default: 0 @@ -2098,7 +2116,7 @@ index adfe9cf8a01ce98f1a7cee8c77ff35f697e60f2e..e663c77ee07785a3b74a8f2eead876dd category: html humanReadableName: "Lazy iframe loading" humanReadableDescription: "Enable lazy iframe loading support" -@@ -3791,9 +3796,9 @@ LazyIframeLoadingEnabled: +@@ -3963,9 +3968,9 @@ LazyIframeLoadingEnabled: WebKitLegacy: default: true WebKit: @@ -2110,7 +2128,7 @@ index adfe9cf8a01ce98f1a7cee8c77ff35f697e60f2e..e663c77ee07785a3b74a8f2eead876dd LazyImageLoadingEnabled: type: bool -@@ -5237,7 +5242,7 @@ PermissionsAPIEnabled: +@@ -5461,7 +5466,7 @@ PermissionsAPIEnabled: WebKitLegacy: default: false WebKit: @@ -2119,7 +2137,7 @@ index adfe9cf8a01ce98f1a7cee8c77ff35f697e60f2e..e663c77ee07785a3b74a8f2eead876dd default: false WebCore: default: false -@@ -5297,6 +5302,19 @@ PitchCorrectionAlgorithm: +@@ -5524,6 +5529,19 @@ PitchCorrectionAlgorithm: WebCore: default: MediaPlayerEnums::PitchCorrectionAlgorithm::BestAllAround @@ -2139,7 +2157,7 @@ index adfe9cf8a01ce98f1a7cee8c77ff35f697e60f2e..e663c77ee07785a3b74a8f2eead876dd PointerLockOptionsEnabled: type: bool status: testable -@@ -5853,7 +5871,7 @@ ScreenOrientationAPIEnabled: +@@ -6060,7 +6078,7 @@ ScreenOrientationAPIEnabled: WebKitLegacy: default: false WebKit: @@ -2147,8 +2165,8 @@ index adfe9cf8a01ce98f1a7cee8c77ff35f697e60f2e..e663c77ee07785a3b74a8f2eead876dd + default: true WebCore: default: false - -@@ -7110,6 +7128,7 @@ UseCGDisplayListsForDOMRendering: + sharedPreferenceForWebProcess: true +@@ -7389,6 +7407,7 @@ UseCGDisplayListsForDOMRendering: default: true sharedPreferenceForWebProcess: true @@ -2156,7 +2174,7 @@ index adfe9cf8a01ce98f1a7cee8c77ff35f697e60f2e..e663c77ee07785a3b74a8f2eead876dd UseGPUProcessForCanvasRenderingEnabled: type: bool status: stable -@@ -7122,7 +7141,7 @@ UseGPUProcessForCanvasRenderingEnabled: +@@ -7401,7 +7420,7 @@ UseGPUProcessForCanvasRenderingEnabled: defaultValue: WebKit: "ENABLE(GPU_PROCESS_BY_DEFAULT)": true @@ -2165,7 +2183,7 @@ index adfe9cf8a01ce98f1a7cee8c77ff35f697e60f2e..e663c77ee07785a3b74a8f2eead876dd default: false UseGPUProcessForDOMRenderingEnabled: -@@ -7165,6 +7184,7 @@ UseGPUProcessForMediaEnabled: +@@ -7444,6 +7463,7 @@ UseGPUProcessForMediaEnabled: "ENABLE(GPU_PROCESS_BY_DEFAULT)": true default: false @@ -2173,7 +2191,7 @@ index adfe9cf8a01ce98f1a7cee8c77ff35f697e60f2e..e663c77ee07785a3b74a8f2eead876dd UseGPUProcessForWebGLEnabled: type: bool status: internal -@@ -7176,7 +7196,7 @@ UseGPUProcessForWebGLEnabled: +@@ -7455,7 +7475,7 @@ UseGPUProcessForWebGLEnabled: default: false WebKit: "ENABLE(GPU_PROCESS_BY_DEFAULT) && ENABLE(GPU_PROCESS_WEBGL_BY_DEFAULT)": true @@ -2183,10 +2201,10 @@ index adfe9cf8a01ce98f1a7cee8c77ff35f697e60f2e..e663c77ee07785a3b74a8f2eead876dd 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 8d8c9fd0544f63fefcac20756addcb2933e5ab1a..322f0a70eb3154cb130b27f38cfb017acec1bf34 100644 +index 62e05e9711b88f291833ec11fea15caba8d1826c..279be00347cbe501ba09040a511627ed308ecdbd 100644 --- a/Source/WTF/wtf/PlatformEnable.h +++ b/Source/WTF/wtf/PlatformEnable.h -@@ -405,7 +405,7 @@ +@@ -409,7 +409,7 @@ // ORIENTATION_EVENTS should never get enabled on Desktop, only Mobile. #if !defined(ENABLE_ORIENTATION_EVENTS) @@ -2195,7 +2213,7 @@ index 8d8c9fd0544f63fefcac20756addcb2933e5ab1a..322f0a70eb3154cb130b27f38cfb017a #endif #if !defined(ENABLE_OVERFLOW_SCROLLING_TOUCH) -@@ -510,7 +510,7 @@ +@@ -514,7 +514,7 @@ #endif #if !defined(ENABLE_TOUCH_EVENTS) @@ -2205,10 +2223,10 @@ index 8d8c9fd0544f63fefcac20756addcb2933e5ab1a..322f0a70eb3154cb130b27f38cfb017a #if !defined(ENABLE_TOUCH_ACTION_REGIONS) diff --git a/Source/WTF/wtf/PlatformEnableCocoa.h b/Source/WTF/wtf/PlatformEnableCocoa.h -index 93ed6901c29ee2e814efa89f3ec96594f6c8c662..48aaaa90e26e3660253ff833d2ae50272d6c9a2c 100644 +index 256964d0373b4ec43ddccc4c7c50ab9d85259294..c6aff1223553dcdbe2ac5165bc2fd9df763ee191 100644 --- a/Source/WTF/wtf/PlatformEnableCocoa.h +++ b/Source/WTF/wtf/PlatformEnableCocoa.h -@@ -787,7 +787,7 @@ +@@ -794,7 +794,7 @@ #endif #if !defined(ENABLE_SEC_ITEM_SHIM) @@ -2218,28 +2236,19 @@ index 93ed6901c29ee2e814efa89f3ec96594f6c8c662..48aaaa90e26e3660253ff833d2ae5027 #if !defined(ENABLE_SERVER_PRECONNECT) diff --git a/Source/WTF/wtf/PlatformHave.h b/Source/WTF/wtf/PlatformHave.h -index b2a6395bbdc9e2877e28b7585f051ddebfbd137d..7ce9ce53d19a7be51018e90eb6b57e409de570a0 100644 +index fff5b0214d7706179adf40c2701018c260c1c657..fa53df1cd9bbe9348636ce70ede2bcdbfbb2af84 100644 --- a/Source/WTF/wtf/PlatformHave.h +++ b/Source/WTF/wtf/PlatformHave.h -@@ -278,7 +278,7 @@ - #define HAVE_FLOAT16_INSTRUCTION 1 - #endif - --#if ((CPU(ARM64) || (CPU(X86_64) && !PLATFORM(PLAYSTATION))) && defined(__FLT16_MANT_DIG__)) -+#if PLATFORM(COCOA) && (CPU(ARM64) || CPU(X86_64)) - #define HAVE_FLOAT16 1 - #endif - @@ -433,7 +433,7 @@ #define HAVE_FOUNDATION_WITH_SAME_SITE_COOKIE_SUPPORT 1 #endif --#if PLATFORM(COCOA) || PLATFORM(GTK) || PLATFORM(WPE) -+#if PLATFORM(COCOA) || PLATFORM(GTK) || PLATFORM(WPE) || PLATFORM(WIN) +-#if PLATFORM(COCOA) || PLATFORM(GTK) || PLATFORM(HAIKU) || PLATFORM(WPE) ++#if PLATFORM(COCOA) || PLATFORM(GTK) || PLATFORM(HAIKU) || PLATFORM(WPE) || PLATFORM(WIN) #define HAVE_OS_DARK_MODE_SUPPORT 1 #endif -@@ -1260,7 +1260,8 @@ +@@ -1249,7 +1249,8 @@ #endif #if PLATFORM(MAC) @@ -2250,20 +2259,20 @@ index b2a6395bbdc9e2877e28b7585f051ddebfbd137d..7ce9ce53d19a7be51018e90eb6b57e40 #if !defined(HAVE_LOCKDOWN_MODE_PDF_ADDITIONS) && \ diff --git a/Source/WTF/wtf/StdLibExtras.h b/Source/WTF/wtf/StdLibExtras.h -index f99e08e4982e87c54ee0cbd43f0a43489366f2cd..89f264d11a853fef42dbd6310510e8004c65e88e 100644 +index 134f4922b0bd97ff80caaf7e4ac31b387f1c064f..f132cea6ad3306c5f1bd6252a53bb7b411b0bb54 100644 --- a/Source/WTF/wtf/StdLibExtras.h +++ b/Source/WTF/wtf/StdLibExtras.h -@@ -26,6 +26,7 @@ - +@@ -27,6 +27,7 @@ #pragma once + #include +#include + #include + #include #include - #include - #include -@@ -39,6 +40,22 @@ - #include - #include +@@ -45,6 +46,22 @@ + + #define SINGLE_ARG(...) __VA_ARGS__ // useful when a macro argument includes a comma +// FIXME: Custom implementation not needed once all Linux systems use >libstdc++-10. +#if !defined(__cpp_lib_bit_cast) || __cpp_lib_bit_cast < 201806L @@ -2300,10 +2309,10 @@ index 007b8fe3292f326504013be8198ae020f7aacf35..4439f901b4a9a92d881c7cee24ad9cd2 namespace Unicode { diff --git a/Source/WebCore/DerivedSources.make b/Source/WebCore/DerivedSources.make -index 10d994c5a2cdcca44e4eccab4f308bfc5ac31eba..8b977dba42a481a70e36e72f068d904e05324e3e 100644 +index f4df43f3fca6ec439815f3d0f2195abad6b046d6..9706dd76ea82d1dc23226c0ad5fd8cb57ba555b0 100644 --- a/Source/WebCore/DerivedSources.make +++ b/Source/WebCore/DerivedSources.make -@@ -1159,6 +1159,10 @@ JS_BINDING_IDLS := \ +@@ -1191,6 +1191,10 @@ JS_BINDING_IDLS := \ $(WebCore)/dom/SubscriberCallback.idl \ $(WebCore)/dom/SubscriptionObserver.idl \ $(WebCore)/dom/SubscriptionObserverCallback.idl \ @@ -2314,7 +2323,7 @@ index 10d994c5a2cdcca44e4eccab4f308bfc5ac31eba..8b977dba42a481a70e36e72f068d904e $(WebCore)/dom/Text.idl \ $(WebCore)/dom/TextDecoder.idl \ $(WebCore)/dom/TextDecoderStream.idl \ -@@ -1749,9 +1753,6 @@ JS_BINDING_IDLS := \ +@@ -1783,9 +1787,6 @@ JS_BINDING_IDLS := \ ADDITIONAL_BINDING_IDLS = \ DocumentTouch.idl \ GestureEvent.idl \ @@ -2325,7 +2334,7 @@ index 10d994c5a2cdcca44e4eccab4f308bfc5ac31eba..8b977dba42a481a70e36e72f068d904e vpath %.in $(WEBKITADDITIONS_HEADER_SEARCH_PATHS) diff --git a/Source/WebCore/Modules/geolocation/Geolocation.cpp b/Source/WebCore/Modules/geolocation/Geolocation.cpp -index be20114bdebd713c5224893ac73078b03b22e392..4174bdf02631d421a0f1fdadfde21c308e4c7735 100644 +index 268f1dfa20097a708f1531975a908fa782b1adb2..5b5eb45dc77aa09be9df39073998eb7a25f44163 100644 --- a/Source/WebCore/Modules/geolocation/Geolocation.cpp +++ b/Source/WebCore/Modules/geolocation/Geolocation.cpp @@ -360,8 +360,9 @@ bool Geolocation::shouldBlockGeolocationRequests() @@ -2376,22 +2385,23 @@ index 506ebb25fa290f27a75674a6fe5506fc311910d6..07d34c567b42aca08b188243c3f036f6 [self sendSpeechEndIfNeeded]; diff --git a/Source/WebCore/PlatformWPE.cmake b/Source/WebCore/PlatformWPE.cmake -index 34db6a238244d9e0b0ab3478b449cdcfa4993169..672de4d1c7430952ff200725a5a72986cd7aa5cb 100644 +index 2aada6f29a04eb3fb0530c47d0fb76f8e3d1bb9f..b936f5862a246c9bf30adbb593c348450b1510ba 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 +@@ -59,6 +59,8 @@ list(APPEND WebCore_PRIVATE_FRAMEWORK_HEADERS + platform/graphics/gbm/PlatformDisplayGBM.h - platform/graphics/wayland/PlatformDisplayWayland.h + platform/graphics/libwpe/PlatformDisplayLibWPE.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 c5f7d089135e35c382700110a7f120cfe39d3e28..8ccc00a48d9b5622ccbd8fc750159d82c655e8fb 100644 +index 7b59e7fab81dbf2fa1847b40f1aac9437c6af62d..689a87649ab0a1aef273528d41840cca6ced46fe 100644 --- a/Source/WebCore/SourcesCocoa.txt +++ b/Source/WebCore/SourcesCocoa.txt -@@ -713,3 +713,9 @@ testing/cocoa/WebViewVisualIdentificationOverlay.mm +@@ -716,3 +716,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 @@ -2402,7 +2412,7 @@ index c5f7d089135e35c382700110a7f120cfe39d3e28..8ccc00a48d9b5622ccbd8fc750159d82 +JSTouchList.cpp +// Playwright end diff --git a/Source/WebCore/SourcesGTK.txt b/Source/WebCore/SourcesGTK.txt -index 599d83f5c87ddf7a0b1d3b62e84cba13c4f98804..192231714aab59ca708092d62e580238b0aedbe0 100644 +index cafba5ad19fcce8184f9caeaf50445b3b2065522..75fa95a4f8248ad2d19c2c19dc22166a843f03bb 100644 --- a/Source/WebCore/SourcesGTK.txt +++ b/Source/WebCore/SourcesGTK.txt @@ -112,3 +112,10 @@ platform/unix/LoggingUnix.cpp @@ -2417,7 +2427,7 @@ index 599d83f5c87ddf7a0b1d3b62e84cba13c4f98804..192231714aab59ca708092d62e580238 +JSSpeechSynthesisEventInit.cpp +// Playwright: end. diff --git a/Source/WebCore/SourcesWPE.txt b/Source/WebCore/SourcesWPE.txt -index 9508e6bb5bad8463ce2122a51612c53af47f5421..be18a3c31b7a4bfd184d4a35f2eeeb2eedd5af9b 100644 +index 3c68a8ed10cd24cffd26b4b70c3adad8eb6ba91f..b36dee714fdceba5248922bfb6d2046922ca6b34 100644 --- a/Source/WebCore/SourcesWPE.txt +++ b/Source/WebCore/SourcesWPE.txt @@ -46,6 +46,8 @@ editing/libwpe/EditorLibWPE.cpp @@ -2429,7 +2439,7 @@ index 9508e6bb5bad8463ce2122a51612c53af47f5421..be18a3c31b7a4bfd184d4a35f2eeeb2e page/linux/ResourceUsageOverlayLinux.cpp page/linux/ResourceUsageThreadLinux.cpp -@@ -89,6 +91,17 @@ platform/text/LocaleICU.cpp +@@ -90,6 +92,17 @@ platform/text/LocaleICU.cpp platform/unix/LoggingUnix.cpp platform/unix/SharedMemoryUnix.cpp @@ -2448,10 +2458,10 @@ index 9508e6bb5bad8463ce2122a51612c53af47f5421..be18a3c31b7a4bfd184d4a35f2eeeb2e +JSSpeechSynthesisEventInit.cpp +// Playwright: end. diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj -index 3ddce4b693ef515291c9873c87e9046df7b2b2e9..70fc70c56cdb71f3555819a0ad060cd7a26c4010 100644 +index 391eed371e8c521098e78df1990dd5dd0a2e1c52..0eb1418a2d334e58faf5011bc65f797b0c8cc322 100644 --- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj +++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj -@@ -6199,6 +6199,13 @@ +@@ -6224,6 +6224,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 */; }; EFCC6C8F20FE914400A2321B /* CanvasActivityRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = EFCC6C8D20FE914000A2321B /* CanvasActivityRecord.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -2465,8 +2475,8 @@ index 3ddce4b693ef515291c9873c87e9046df7b2b2e9..70fc70c56cdb71f3555819a0ad060cd7 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, ); }; }; -@@ -20164,6 +20171,14 @@ - EDEC98020AED7E170059137F /* WebCorePrefix.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = WebCorePrefix.h; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; +@@ -20367,6 +20374,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 = ""; }; @@ -2480,7 +2490,7 @@ index 3ddce4b693ef515291c9873c87e9046df7b2b2e9..70fc70c56cdb71f3555819a0ad060cd7 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 = ""; }; -@@ -27819,6 +27834,11 @@ +@@ -28052,6 +28067,11 @@ BC4A5324256055590028C592 /* TextDirectionSubmenuInclusionBehavior.h */, 2D4F96F11A1ECC240098BF88 /* TextIndicator.cpp */, 2D4F96F21A1ECC240098BF88 /* TextIndicator.h */, @@ -2492,7 +2502,7 @@ index 3ddce4b693ef515291c9873c87e9046df7b2b2e9..70fc70c56cdb71f3555819a0ad060cd7 F48570A42644C76D00C05F71 /* TranslationContextMenuInfo.h */, F4E1965F21F26E4E00285078 /* UndoItem.cpp */, 2ECDBAD521D8906300F00ECD /* UndoItem.h */, -@@ -34164,6 +34184,8 @@ +@@ -34451,6 +34471,8 @@ 29E4D8DF16B0940F00C84704 /* PlatformSpeechSynthesizer.h */, 1AD8F81A11CAB9E900E93E54 /* PlatformStrategies.cpp */, 1AD8F81911CAB9E900E93E54 /* PlatformStrategies.h */, @@ -2501,7 +2511,7 @@ index 3ddce4b693ef515291c9873c87e9046df7b2b2e9..70fc70c56cdb71f3555819a0ad060cd7 0FD7C21D23CE41E30096D102 /* PlatformWheelEvent.cpp */, 935C476A09AC4D4F00A6AAB4 /* PlatformWheelEvent.h */, F491A66A2A9FEFA300F96146 /* PlatformWheelEvent.serialization.in */, -@@ -36844,6 +36866,7 @@ +@@ -37208,6 +37230,7 @@ AD6E71AB1668899D00320C13 /* DocumentSharedObjectPool.h */, 6BDB5DC1227BD3B800919770 /* DocumentStorageAccess.cpp */, 6BDB5DC0227BD3B800919770 /* DocumentStorageAccess.h */, @@ -2509,7 +2519,7 @@ index 3ddce4b693ef515291c9873c87e9046df7b2b2e9..70fc70c56cdb71f3555819a0ad060cd7 7CE7FA5B1EF882300060C9D6 /* DocumentTouch.cpp */, 7CE7FA591EF882300060C9D6 /* DocumentTouch.h */, A8185F3209765765005826D9 /* DocumentType.cpp */, -@@ -41585,6 +41608,8 @@ +@@ -41975,6 +41998,8 @@ F4E90A3C2B52038E002DA469 /* PlatformTextAlternatives.h in Headers */, 0F7D07331884C56C00B4AF86 /* PlatformTextTrack.h in Headers */, 074E82BB18A69F0E007EF54C /* PlatformTimeRanges.h in Headers */, @@ -2518,7 +2528,7 @@ index 3ddce4b693ef515291c9873c87e9046df7b2b2e9..70fc70c56cdb71f3555819a0ad060cd7 CDD08ABD277E542600EA3755 /* PlatformTrackConfiguration.h in Headers */, CD1F9B022700323D00617EB6 /* PlatformVideoColorPrimaries.h in Headers */, CD1F9B01270020B700617EB6 /* PlatformVideoColorSpace.h in Headers */, -@@ -42864,6 +42889,7 @@ +@@ -43261,6 +43286,7 @@ 0F54DD081881D5F5003EEDBB /* Touch.h in Headers */, 71B7EE0D21B5C6870031C1EF /* TouchAction.h in Headers */, 0F54DD091881D5F5003EEDBB /* TouchEvent.h in Headers */, @@ -2526,7 +2536,7 @@ index 3ddce4b693ef515291c9873c87e9046df7b2b2e9..70fc70c56cdb71f3555819a0ad060cd7 0F54DD0A1881D5F5003EEDBB /* TouchList.h in Headers */, 070334D71459FFD5008D8D45 /* TrackBase.h in Headers */, BE88E0C21715CE2600658D98 /* TrackListBase.h in Headers */, -@@ -44018,6 +44044,8 @@ +@@ -44423,6 +44449,8 @@ 2D22830323A8470700364B7E /* CursorMac.mm in Sources */, 5CBD59592280E926002B22AA /* CustomHeaderFields.cpp in Sources */, 07E4BDBF2A3A5FAB000D5509 /* DictationCaretAnimator.cpp in Sources */, @@ -2535,7 +2545,7 @@ index 3ddce4b693ef515291c9873c87e9046df7b2b2e9..70fc70c56cdb71f3555819a0ad060cd7 7CE6CBFD187F394900D46BF5 /* FormatConverter.cpp in Sources */, 4667EA3E2968D9DA00BAB1E2 /* GameControllerHapticEffect.mm in Sources */, 46FE73D32968E52000B8064C /* GameControllerHapticEngines.mm in Sources */, -@@ -44106,6 +44134,9 @@ +@@ -44511,6 +44539,9 @@ CE88EE262414467B007F29C2 /* TextAlternativeWithRange.mm in Sources */, BE39137129B267F500FA5D4F /* TextTransformCocoa.cpp in Sources */, 51DF6D800B92A18E00C2DC85 /* ThreadCheck.mm in Sources */, @@ -2546,18 +2556,18 @@ index 3ddce4b693ef515291c9873c87e9046df7b2b2e9..70fc70c56cdb71f3555819a0ad060cd7 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 2a4e9158e4bf30f6331402e3a205dfabfa068e9a..33187f427cf77e05f5424651880b9f20f3fb9645 100644 +index 409ba22d242695a6612a1a2217bb555bd1a382cf..18d6af9e268b353d639aee78642576d6de96fc60 100644 --- a/Source/WebCore/accessibility/AccessibilityObject.cpp +++ b/Source/WebCore/accessibility/AccessibilityObject.cpp -@@ -68,6 +68,7 @@ - #include "HTMLSlotElement.h" +@@ -69,6 +69,7 @@ + #include "HTMLTableSectionElement.h" #include "HTMLTextAreaElement.h" #include "HitTestResult.h" +#include "InspectorInstrumentation.h" #include "LocalFrame.h" #include "LocalizedStrings.h" #include "MathMLNames.h" -@@ -3974,9 +3975,14 @@ AccessibilityObjectInclusion AccessibilityObject::defaultObjectInclusion() const +@@ -4018,7 +4019,12 @@ AccessibilityObjectInclusion AccessibilityObject::defaultObjectInclusion() const if (roleValue() == AccessibilityRole::ApplicationDialog) return AccessibilityObjectInclusion::IncludeObject; @@ -2569,13 +2579,10 @@ index 2a4e9158e4bf30f6331402e3a205dfabfa068e9a..33187f427cf77e05f5424651880b9f20 + } + return platformBehavior; } -- -+ - bool AccessibilityObject::accessibilityIsIgnored() const - { - AXComputedObjectAttributeCache* attributeCache = nullptr; + + bool AccessibilityObject::isWithinHiddenWebArea() const diff --git a/Source/WebCore/accessibility/atspi/AccessibilityObjectTextAtspi.cpp b/Source/WebCore/accessibility/atspi/AccessibilityObjectTextAtspi.cpp -index 7641906564fb1e480f56923343a8ee6149f60820..ed530124becb719e66b211f468c24376887c4cc4 100644 +index bdfc31aa68fb0cf0e71351ae86b2af8a903a3c57..fbe06025d4147848cc4c7f3e3bac299da8c98f85 100644 --- a/Source/WebCore/accessibility/atspi/AccessibilityObjectTextAtspi.cpp +++ b/Source/WebCore/accessibility/atspi/AccessibilityObjectTextAtspi.cpp @@ -289,7 +289,7 @@ String AccessibilityObjectAtspi::text() const @@ -2597,7 +2604,7 @@ index 7641906564fb1e480f56923343a8ee6149f60820..ed530124becb719e66b211f468c24376 return textLength; } diff --git a/Source/WebCore/bindings/js/WebCoreBuiltinNames.h b/Source/WebCore/bindings/js/WebCoreBuiltinNames.h -index 84431d6ef57495c781d1ac872c9118ecd6f0c9fd..38cf041f31cf54106706ae95d2ea47c88818b503 100644 +index 479938f501c65222a5820087c578184d64169dec..9bf7df2bc66c77b92edb1f93887922071d539458 100644 --- a/Source/WebCore/bindings/js/WebCoreBuiltinNames.h +++ b/Source/WebCore/bindings/js/WebCoreBuiltinNames.h @@ -185,6 +185,8 @@ namespace WebCore { @@ -2610,7 +2617,7 @@ index 84431d6ef57495c781d1ac872c9118ecd6f0c9fd..38cf041f31cf54106706ae95d2ea47c8 macro(DynamicsCompressorNode) \ macro(ElementInternals) \ diff --git a/Source/WebCore/css/query/MediaQueryFeatures.cpp b/Source/WebCore/css/query/MediaQueryFeatures.cpp -index 450c429a76a97ba079087eaecc0deca236f3a419..726765635432192654ee218874813a1d09a83af4 100644 +index a4f2b2d167f77b19104daa9c56f62ae76485cb1a..c877d2439414452c4dfb79a6881dcf85e1d35fa0 100644 --- a/Source/WebCore/css/query/MediaQueryFeatures.cpp +++ b/Source/WebCore/css/query/MediaQueryFeatures.cpp @@ -364,7 +364,11 @@ const FeatureSchema& forcedColors() @@ -2626,7 +2633,7 @@ index 450c429a76a97ba079087eaecc0deca236f3a419..726765635432192654ee218874813a1d return MatchingIdentifiers { CSSValueNone }; } }; -@@ -546,6 +550,9 @@ const FeatureSchema& prefersReducedMotion() +@@ -540,6 +544,9 @@ const FeatureSchema& prefersReducedMotion() [](auto& context) { bool userPrefersReducedMotion = [&] { Ref frame = *context.document->frame(); @@ -2637,10 +2644,10 @@ index 450c429a76a97ba079087eaecc0deca236f3a419..726765635432192654ee218874813a1d case ForcedAccessibilityValue::On: return true; diff --git a/Source/WebCore/dom/DataTransfer.cpp b/Source/WebCore/dom/DataTransfer.cpp -index b56c600b6159973dc8a33db1deba0cfbb77abf48..a347a85381888e2f6423393552d619938ad34f21 100644 +index 0aec57b302c54f2b02beaeec4a9a6733612212a9..726895552b252b83cdb4f9dd87867a6afc3ed101 100644 --- a/Source/WebCore/dom/DataTransfer.cpp +++ b/Source/WebCore/dom/DataTransfer.cpp -@@ -510,6 +510,14 @@ Ref DataTransfer::createForDrag(const Document& document) +@@ -512,6 +512,14 @@ Ref DataTransfer::createForDrag(const Document& document) return adoptRef(*new DataTransfer(StoreMode::ReadWrite, Pasteboard::createForDragAndDrop(PagePasteboardContext::create(document.pageID())), Type::DragAndDropData)); } @@ -2730,22 +2737,24 @@ 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 af8212c75d96b7bbc638a865e0a0b5ab907a5140..579b4e77ea64f956aa1b08b754b842b6e6b5f207 100644 +index 2a728c134f837ee36c033971e1c47792f4a3caf2..b1ecb3b2dd2efc43d679bb0f678457188cb2cb3a 100644 --- a/Source/WebCore/dom/PointerEvent.cpp +++ b/Source/WebCore/dom/PointerEvent.cpp -@@ -27,9 +27,11 @@ +@@ -27,10 +27,13 @@ #include "PointerEvent.h" #include "EventNames.h" +#include "MouseEvent.h" #include "Node.h" #include "PlatformMouseEvent.h" - #include "PointerEventTypeNames.h" +#include "PlatformTouchEvent.h" - #include + #include "PointerEventTypeNames.h" + #include ++#include namespace WebCore { -@@ -232,4 +234,59 @@ void PointerEvent::receivedTarget() + +@@ -292,4 +295,59 @@ void PointerEvent::receivedTarget() predictedEvent->setTarget(this->target()); } @@ -2806,7 +2815,7 @@ index af8212c75d96b7bbc638a865e0a0b5ab907a5140..579b4e77ea64f956aa1b08b754b842b6 + } // namespace WebCore diff --git a/Source/WebCore/dom/PointerEvent.h b/Source/WebCore/dom/PointerEvent.h -index f168aae7c04ef261961ec58b98c20086209370d0..3127dca1b62429bde1db5c3d0e613af1b5318ffe 100644 +index b034595d01bb63f3d72183c427fcc14695339ae2..1886e4bbba04c6177fad1562c891f2aeff0a8247 100644 --- a/Source/WebCore/dom/PointerEvent.h +++ b/Source/WebCore/dom/PointerEvent.h @@ -34,6 +34,8 @@ @@ -2818,7 +2827,7 @@ index f168aae7c04ef261961ec58b98c20086209370d0..3127dca1b62429bde1db5c3d0e613af1 #endif #if ENABLE(TOUCH_EVENTS) && PLATFORM(WPE) -@@ -90,7 +92,7 @@ public: +@@ -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); @@ -2827,9 +2836,9 @@ index f168aae7c04ef261961ec58b98c20086209370d0..3127dca1b62429bde1db5c3d0e613af1 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 = { }); -@@ -151,7 +153,7 @@ private: +@@ -173,7 +175,7 @@ private: + PointerEvent(); PointerEvent(const AtomString&, Init&&, IsTrusted); - PointerEvent(const AtomString& type, MouseButton, const MouseEvent&, PointerID, const String& pointerType, CanBubble, IsCancelable); PointerEvent(const AtomString& type, PointerID, const String& pointerType, IsPrimary); -#if ENABLE(TOUCH_EVENTS) && (PLATFORM(IOS_FAMILY) || PLATFORM(WPE)) +#if ENABLE(TOUCH_EVENTS) @@ -2864,7 +2873,7 @@ index 7813532cc52d582c42aebc979a1ecd1137765f08..c01cbd53ad2430a6ffab9a80fc73e74a #endif // USE(LIBWPE) diff --git a/Source/WebCore/html/FileInputType.cpp b/Source/WebCore/html/FileInputType.cpp -index 7a26cfbbaf3d9583064a5eb30a049b5ac04847f0..1377da39ae4cc134b87358871fdb39431161244b 100644 +index e582d1bc610c7794c4ad181511317d2378b9248b..4c6be4b94913a4649b33f1989def3433455b7109 100644 --- a/Source/WebCore/html/FileInputType.cpp +++ b/Source/WebCore/html/FileInputType.cpp @@ -37,6 +37,7 @@ @@ -2899,10 +2908,10 @@ index 7a26cfbbaf3d9583064a5eb30a049b5ac04847f0..1377da39ae4cc134b87358871fdb3943 break; } diff --git a/Source/WebCore/inspector/InspectorController.cpp b/Source/WebCore/inspector/InspectorController.cpp -index 79af2f2040520b6b1bba55c7fbf656828b95d885..1b41cedfe4fd49c1f5073a513df5a80fb492b973 100644 +index 9cffa4217cecadfc6813da5fa1a92ec1ca9b8796..32da50b05bb8563e0ded48734451a8e9967e48af 100644 --- a/Source/WebCore/inspector/InspectorController.cpp +++ b/Source/WebCore/inspector/InspectorController.cpp -@@ -287,6 +287,8 @@ void InspectorController::disconnectFrontend(FrontendChannel& frontendChannel) +@@ -290,6 +290,8 @@ void InspectorController::disconnectFrontend(FrontendChannel& frontendChannel) // Unplug all instrumentations since they aren't needed now. InspectorInstrumentation::unregisterInstrumentingAgents(m_instrumentingAgents.get()); @@ -2911,7 +2920,7 @@ index 79af2f2040520b6b1bba55c7fbf656828b95d885..1b41cedfe4fd49c1f5073a513df5a80f } m_inspectorClient->frontendCountChanged(m_frontendRouter->frontendCount()); -@@ -306,6 +308,8 @@ void InspectorController::disconnectAllFrontends() +@@ -309,6 +311,8 @@ void InspectorController::disconnectAllFrontends() // The frontend should call setInspectorFrontendClient(nullptr) under closeWindow(). ASSERT(!m_inspectorFrontendClient); @@ -2920,7 +2929,7 @@ index 79af2f2040520b6b1bba55c7fbf656828b95d885..1b41cedfe4fd49c1f5073a513df5a80f if (!m_frontendRouter->hasFrontends()) return; -@@ -394,8 +398,8 @@ void InspectorController::inspect(Node* node) +@@ -397,8 +401,8 @@ void InspectorController::inspect(Node* node) if (!enabled()) return; @@ -2931,7 +2940,7 @@ index 79af2f2040520b6b1bba55c7fbf656828b95d885..1b41cedfe4fd49c1f5073a513df5a80f ensureDOMAgent().inspect(node); } -@@ -538,4 +542,24 @@ void InspectorController::didComposite(LocalFrame& frame) +@@ -541,4 +545,24 @@ void InspectorController::didComposite(LocalFrame& frame) InspectorInstrumentation::didComposite(frame); } @@ -2957,10 +2966,10 @@ index 79af2f2040520b6b1bba55c7fbf656828b95d885..1b41cedfe4fd49c1f5073a513df5a80f + } // namespace WebCore diff --git a/Source/WebCore/inspector/InspectorController.h b/Source/WebCore/inspector/InspectorController.h -index 3a981b5bf5ca0bbf4d1c9f0b125564742cd8cad9..f8fc2ca6700461627933f149c5837075226a51a9 100644 +index 41cb9b8d298fbb4cb833346015fbf67c78577dbd..fa1b489eadfc5469bfeec6a35336ffa7fba2c8c1 100644 --- a/Source/WebCore/inspector/InspectorController.h +++ b/Source/WebCore/inspector/InspectorController.h -@@ -101,6 +101,10 @@ public: +@@ -103,6 +103,10 @@ public: WEBCORE_EXPORT void willComposite(LocalFrame&); WEBCORE_EXPORT void didComposite(LocalFrame&); @@ -2971,7 +2980,7 @@ index 3a981b5bf5ca0bbf4d1c9f0b125564742cd8cad9..f8fc2ca6700461627933f149c5837075 // Testing support. WEBCORE_EXPORT bool isUnderTest() const; void setIsUnderTest(bool isUnderTest) { m_isUnderTest = isUnderTest; } -@@ -154,6 +158,7 @@ private: +@@ -156,6 +160,7 @@ private: bool m_isAutomaticInspection { false }; bool m_pauseAfterInitialization = { false }; bool m_didCreateLazyAgents { false }; @@ -3500,7 +3509,7 @@ index c028341e84e59a6b1b16107fd74feb21f70b12ab..d385418ac34e8f315f201801a2c65226 + } diff --git a/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp b/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp -index ec5000cb553f244224ac2dc5be229c11c42e5d7f..cf6bc9545f04ad7fdba7c2dfaf46ac45e158f15e 100644 +index f2d47e0b0a15f48600bb6edd10430073ea60d9ee..20ee16a8c858599340ae33869baa188f9b17ae3f 100644 --- a/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp +++ b/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp @@ -55,6 +55,7 @@ @@ -3542,7 +3551,7 @@ index ec5000cb553f244224ac2dc5be229c11c42e5d7f..cf6bc9545f04ad7fdba7c2dfaf46ac45 #include "StaticNodeList.h" #include "StyleProperties.h" #include "StyleResolver.h" -@@ -146,7 +154,8 @@ using namespace HTMLNames; +@@ -149,7 +157,8 @@ using namespace HTMLNames; static const size_t maxTextSize = 10000; static const UChar horizontalEllipsisUChar[] = { horizontalEllipsis, 0 }; @@ -3552,7 +3561,7 @@ index ec5000cb553f244224ac2dc5be229c11c42e5d7f..cf6bc9545f04ad7fdba7c2dfaf46ac45 { if (!colorObject) return std::nullopt; -@@ -165,7 +174,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) { @@ -3561,7 +3570,7 @@ index ec5000cb553f244224ac2dc5be229c11c42e5d7f..cf6bc9545f04ad7fdba7c2dfaf46ac45 } static Color parseOptionalConfigColor(const String& fieldName, JSON::Object& configObject) -@@ -193,6 +202,20 @@ static bool parseQuad(Ref&& quadArray, FloatQuad* quad) +@@ -196,6 +205,20 @@ static bool parseQuad(Ref&& quadArray, FloatQuad* quad) return true; } @@ -3580,9 +3589,9 @@ index ec5000cb553f244224ac2dc5be229c11c42e5d7f..cf6bc9545f04ad7fdba7c2dfaf46ac45 +} + class RevalidateStyleAttributeTask { - WTF_MAKE_FAST_ALLOCATED; + WTF_MAKE_TZONE_ALLOCATED_INLINE(RevalidateStyleAttributeTask); public: -@@ -467,6 +490,20 @@ Node* InspectorDOMAgent::assertNode(Inspector::Protocol::ErrorString& errorStrin +@@ -470,6 +493,20 @@ Node* InspectorDOMAgent::assertNode(Inspector::Protocol::ErrorString& errorStrin return node.get(); } @@ -3603,7 +3612,7 @@ index ec5000cb553f244224ac2dc5be229c11c42e5d7f..cf6bc9545f04ad7fdba7c2dfaf46ac45 Document* InspectorDOMAgent::assertDocument(Inspector::Protocol::ErrorString& errorString, Inspector::Protocol::DOM::NodeId nodeId) { RefPtr node = assertNode(errorString, nodeId); -@@ -1541,16 +1578,7 @@ Inspector::Protocol::ErrorStringOr InspectorDOMAgent::highlightNode(std::o +@@ -1544,16 +1581,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; @@ -3621,7 +3630,7 @@ index ec5000cb553f244224ac2dc5be229c11c42e5d7f..cf6bc9545f04ad7fdba7c2dfaf46ac45 if (!node) return makeUnexpected(errorString); -@@ -1805,15 +1833,155 @@ Inspector::Protocol::ErrorStringOr InspectorDOMAgent::setInspectedNode(Ins +@@ -1808,15 +1836,155 @@ Inspector::Protocol::ErrorStringOr InspectorDOMAgent::setInspectedNode(Ins return { }; } @@ -3780,7 +3789,7 @@ index ec5000cb553f244224ac2dc5be229c11c42e5d7f..cf6bc9545f04ad7fdba7c2dfaf46ac45 if (!object) return makeUnexpected("Missing injected script for given nodeId"_s); -@@ -3079,7 +3247,7 @@ Inspector::Protocol::ErrorStringOr InspectorDO +@@ -3082,7 +3250,7 @@ Inspector::Protocol::ErrorStringOr InspectorDO return makeUnexpected("Missing node for given path"_s); } @@ -3789,7 +3798,7 @@ index ec5000cb553f244224ac2dc5be229c11c42e5d7f..cf6bc9545f04ad7fdba7c2dfaf46ac45 { Document* document = &node->document(); if (auto* templateHost = document->templateDocumentHost()) -@@ -3088,12 +3256,18 @@ RefPtr InspectorDOMAgent::resolveNod +@@ -3091,12 +3259,18 @@ RefPtr InspectorDOMAgent::resolveNod if (!frame) return nullptr; @@ -3811,7 +3820,7 @@ index ec5000cb553f244224ac2dc5be229c11c42e5d7f..cf6bc9545f04ad7fdba7c2dfaf46ac45 } Node* InspectorDOMAgent::scriptValueAsNode(JSC::JSValue value) -@@ -3201,4 +3375,89 @@ Inspector::Protocol::ErrorStringOr> In +@@ -3204,4 +3378,89 @@ Inspector::Protocol::ErrorStringOr> In #endif } @@ -3902,10 +3911,10 @@ index ec5000cb553f244224ac2dc5be229c11c42e5d7f..cf6bc9545f04ad7fdba7c2dfaf46ac45 + } // namespace WebCore diff --git a/Source/WebCore/inspector/agents/InspectorDOMAgent.h b/Source/WebCore/inspector/agents/InspectorDOMAgent.h -index 5f1dba2bc4d5c2f113a88dcc9ba479679cb79233..73e49d699919b68cffff41f612e461e25235155b 100644 +index 978176d20859bf70ce8e44acbb052ceca9463b06..44fd236a64a05290c9f3cbf0b17398f74c711d3b 100644 --- a/Source/WebCore/inspector/agents/InspectorDOMAgent.h +++ b/Source/WebCore/inspector/agents/InspectorDOMAgent.h -@@ -57,6 +57,7 @@ namespace WebCore { +@@ -58,6 +58,7 @@ namespace WebCore { class AXCoreObject; class CharacterData; @@ -3913,7 +3922,7 @@ index 5f1dba2bc4d5c2f113a88dcc9ba479679cb79233..73e49d699919b68cffff41f612e461e2 class DOMEditor; class Document; class Element; -@@ -91,6 +92,7 @@ public: +@@ -92,6 +93,7 @@ public: static String toErrorString(Exception&&); static String documentURLString(Document*); @@ -3921,7 +3930,7 @@ index 5f1dba2bc4d5c2f113a88dcc9ba479679cb79233..73e49d699919b68cffff41f612e461e2 // 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: +@@ -135,7 +137,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); @@ -3930,7 +3939,7 @@ index 5f1dba2bc4d5c2f113a88dcc9ba479679cb79233..73e49d699919b68cffff41f612e461e2 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: +@@ -172,6 +174,10 @@ public: Inspector::Protocol::ErrorStringOr setInspectedNode(Inspector::Protocol::DOM::NodeId); Inspector::Protocol::ErrorStringOr setAllowEditingUserAgentShadowTrees(bool); Inspector::Protocol::ErrorStringOr> getMediaStats(Inspector::Protocol::DOM::NodeId); @@ -3941,7 +3950,7 @@ index 5f1dba2bc4d5c2f113a88dcc9ba479679cb79233..73e49d699919b68cffff41f612e461e2 // InspectorInstrumentation Inspector::Protocol::DOM::NodeId identifierForNode(Node&); -@@ -212,7 +218,7 @@ public: +@@ -213,7 +219,7 @@ public: Node* nodeForId(Inspector::Protocol::DOM::NodeId); Inspector::Protocol::DOM::NodeId boundNodeId(const Node*); @@ -3950,7 +3959,7 @@ index 5f1dba2bc4d5c2f113a88dcc9ba479679cb79233..73e49d699919b68cffff41f612e461e2 bool handleMousePress(); void mouseDidMoveOverElement(const HitTestResult&, OptionSet); void inspect(Node*); -@@ -224,12 +230,15 @@ public: +@@ -225,12 +231,15 @@ public: void reset(); Node* assertNode(Inspector::Protocol::ErrorString&, Inspector::Protocol::DOM::NodeId); @@ -3966,7 +3975,7 @@ index 5f1dba2bc4d5c2f113a88dcc9ba479679cb79233..73e49d699919b68cffff41f612e461e2 private: #if ENABLE(VIDEO) void mediaMetricsTimerFired(); -@@ -259,7 +268,6 @@ private: +@@ -260,7 +269,6 @@ private: void processAccessibilityChildren(AXCoreObject&, JSON::ArrayOf&); Node* nodeForPath(const String& path); @@ -3975,7 +3984,7 @@ index 5f1dba2bc4d5c2f113a88dcc9ba479679cb79233..73e49d699919b68cffff41f612e461e2 void discardBindings(); diff --git a/Source/WebCore/inspector/agents/InspectorNetworkAgent.cpp b/Source/WebCore/inspector/agents/InspectorNetworkAgent.cpp -index f8a58175bdaa13ae7d2bb722df119e140ec7618f..b601fdd3d16a3fc016ce3af50d416a0880990d7b 100644 +index adbedee377dad747f03b98cfdcf719b4283e51b2..475365f50feeb28354fa3e86ff847a6fd65c8a21 100644 --- a/Source/WebCore/inspector/agents/InspectorNetworkAgent.cpp +++ b/Source/WebCore/inspector/agents/InspectorNetworkAgent.cpp @@ -59,6 +59,7 @@ @@ -3986,7 +3995,7 @@ index f8a58175bdaa13ae7d2bb722df119e140ec7618f..b601fdd3d16a3fc016ce3af50d416a08 #include "Page.h" #include "PlatformStrategies.h" #include "ProgressTracker.h" -@@ -340,8 +341,8 @@ static Ref buildObjectForResourceRequest( +@@ -345,8 +346,8 @@ static Ref buildObjectForResourceRequest( .release(); if (request.httpBody() && !request.httpBody()->isEmpty()) { @@ -3997,7 +4006,7 @@ index f8a58175bdaa13ae7d2bb722df119e140ec7618f..b601fdd3d16a3fc016ce3af50d416a08 } if (resourceLoader) { -@@ -394,6 +395,8 @@ RefPtr InspectorNetworkAgent::buildObjec +@@ -399,6 +400,8 @@ RefPtr InspectorNetworkAgent::buildObjec .setSource(responseSource(response.source())) .release(); @@ -4006,7 +4015,7 @@ index f8a58175bdaa13ae7d2bb722df119e140ec7618f..b601fdd3d16a3fc016ce3af50d416a08 if (resourceLoader) { auto* metrics = response.deprecatedNetworkLoadMetricsOrNull(); responseObject->setTiming(buildObjectForTiming(metrics ? *metrics : NetworkLoadMetrics::emptyMetrics(), *resourceLoader)); -@@ -680,6 +683,9 @@ void InspectorNetworkAgent::didFailLoading(ResourceLoaderIdentifier identifier, +@@ -685,6 +688,9 @@ void InspectorNetworkAgent::didFailLoading(ResourceLoaderIdentifier identifier, String requestId = IdentifiersFactory::requestId(identifier.toUInt64()); if (loader && m_resourcesData->resourceType(requestId) == InspectorPageAgent::DocumentResource) { @@ -4016,7 +4025,7 @@ index f8a58175bdaa13ae7d2bb722df119e140ec7618f..b601fdd3d16a3fc016ce3af50d416a08 auto* frame = loader->frame(); if (frame && frame->loader().documentLoader() && frame->document()) { m_resourcesData->addResourceSharedBuffer(requestId, -@@ -909,6 +915,7 @@ Inspector::Protocol::ErrorStringOr InspectorNetworkAgent::disable() +@@ -914,6 +920,7 @@ Inspector::Protocol::ErrorStringOr InspectorNetworkAgent::disable() m_instrumentingAgents.setEnabledNetworkAgent(nullptr); m_resourcesData->clear(); m_extraRequestHeaders.clear(); @@ -4024,7 +4033,7 @@ index f8a58175bdaa13ae7d2bb722df119e140ec7618f..b601fdd3d16a3fc016ce3af50d416a08 continuePendingRequests(); continuePendingResponses(); -@@ -961,6 +968,7 @@ void InspectorNetworkAgent::continuePendingResponses() +@@ -966,6 +973,7 @@ void InspectorNetworkAgent::continuePendingResponses() Inspector::Protocol::ErrorStringOr InspectorNetworkAgent::setExtraHTTPHeaders(Ref&& headers) { @@ -4032,7 +4041,7 @@ index f8a58175bdaa13ae7d2bb722df119e140ec7618f..b601fdd3d16a3fc016ce3af50d416a08 for (auto& entry : headers.get()) { auto stringValue = entry.value->asString(); if (!!stringValue) -@@ -1210,6 +1218,11 @@ void InspectorNetworkAgent::interceptResponse(const ResourceResponse& response, +@@ -1215,6 +1223,11 @@ void InspectorNetworkAgent::interceptResponse(const ResourceResponse& response, m_frontendDispatcher->responseIntercepted(requestId, resourceResponse.releaseNonNull()); } @@ -4044,7 +4053,7 @@ index f8a58175bdaa13ae7d2bb722df119e140ec7618f..b601fdd3d16a3fc016ce3af50d416a08 Inspector::Protocol::ErrorStringOr InspectorNetworkAgent::interceptContinue(const Inspector::Protocol::Network::RequestId& requestId, Inspector::Protocol::Network::NetworkStage networkStage) { switch (networkStage) { -@@ -1239,6 +1252,9 @@ Inspector::Protocol::ErrorStringOr InspectorNetworkAgent::interceptWithReq +@@ -1244,6 +1257,9 @@ Inspector::Protocol::ErrorStringOr InspectorNetworkAgent::interceptWithReq return makeUnexpected("Missing pending intercept request for given requestId"_s); auto& loader = *pendingRequest->m_loader; @@ -4054,7 +4063,7 @@ index f8a58175bdaa13ae7d2bb722df119e140ec7618f..b601fdd3d16a3fc016ce3af50d416a08 ResourceRequest request = loader.request(); if (!!url) request.setURL(URL({ }, url)); -@@ -1334,14 +1350,23 @@ Inspector::Protocol::ErrorStringOr InspectorNetworkAgent::interceptRequest +@@ -1339,14 +1355,23 @@ Inspector::Protocol::ErrorStringOr InspectorNetworkAgent::interceptRequest response.setHTTPStatusCode(status); response.setHTTPStatusText(String { statusText }); HTTPHeaderMap explicitHeaders; @@ -4080,7 +4089,7 @@ index f8a58175bdaa13ae7d2bb722df119e140ec7618f..b601fdd3d16a3fc016ce3af50d416a08 if (loader->reachedTerminalState()) return; -@@ -1404,6 +1429,12 @@ Inspector::Protocol::ErrorStringOr InspectorNetworkAgent::setEmulatedCondi +@@ -1409,6 +1434,12 @@ Inspector::Protocol::ErrorStringOr InspectorNetworkAgent::setEmulatedCondi #endif // ENABLE(INSPECTOR_NETWORK_THROTTLING) @@ -4094,7 +4103,7 @@ index f8a58175bdaa13ae7d2bb722df119e140ec7618f..b601fdd3d16a3fc016ce3af50d416a08 { return startsWithLettersIgnoringASCIICase(mimeType, "text/"_s) diff --git a/Source/WebCore/inspector/agents/InspectorNetworkAgent.h b/Source/WebCore/inspector/agents/InspectorNetworkAgent.h -index dc7e574ee6e9256a1f75ea838d20ca7f5e9190de..03a28b599df29e82392b70cf6b83a700134c53a3 100644 +index eda400879afb10b687fcbb317c9fdbb3be9c94cd..f3a382c44b53e6b1507fc046e22bff684abd55f9 100644 --- a/Source/WebCore/inspector/agents/InspectorNetworkAgent.h +++ b/Source/WebCore/inspector/agents/InspectorNetworkAgent.h @@ -34,6 +34,8 @@ @@ -4106,7 +4115,7 @@ index dc7e574ee6e9256a1f75ea838d20ca7f5e9190de..03a28b599df29e82392b70cf6b83a700 #include "WebSocket.h" #include #include -@@ -101,6 +103,7 @@ public: +@@ -102,6 +104,7 @@ public: #if ENABLE(INSPECTOR_NETWORK_THROTTLING) Inspector::Protocol::ErrorStringOr setEmulatedConditions(std::optional&& bytesPerSecondLimit) final; #endif @@ -4114,7 +4123,7 @@ index dc7e574ee6e9256a1f75ea838d20ca7f5e9190de..03a28b599df29e82392b70cf6b83a700 // InspectorInstrumentation void willRecalculateStyle(); -@@ -132,6 +135,7 @@ public: +@@ -133,6 +136,7 @@ public: bool shouldInterceptResponse(const ResourceResponse&); void interceptResponse(const ResourceResponse&, ResourceLoaderIdentifier, CompletionHandler)>&&); void interceptRequest(ResourceLoader&, Function&&); @@ -4122,7 +4131,7 @@ index dc7e574ee6e9256a1f75ea838d20ca7f5e9190de..03a28b599df29e82392b70cf6b83a700 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>&); -@@ -258,6 +262,7 @@ private: +@@ -259,6 +263,7 @@ private: bool m_enabled { false }; bool m_loadingXHRSynchronously { false }; bool m_interceptionEnabled { false }; @@ -4131,7 +4140,7 @@ index dc7e574ee6e9256a1f75ea838d20ca7f5e9190de..03a28b599df29e82392b70cf6b83a700 } // namespace WebCore diff --git a/Source/WebCore/inspector/agents/InspectorPageAgent.cpp b/Source/WebCore/inspector/agents/InspectorPageAgent.cpp -index 97fa6f1ae18db5b4a1fc8f8f99ce0605fb76a793..fd761459048e7e976b7351eb8714acc63f42bf2d 100644 +index 85f9e83e59abc5a1089a4f2b56f0dab99437d948..22843714b46b158faa929be669638cb98c6cc8fb 100644 --- a/Source/WebCore/inspector/agents/InspectorPageAgent.cpp +++ b/Source/WebCore/inspector/agents/InspectorPageAgent.cpp @@ -32,19 +32,26 @@ @@ -4176,7 +4185,7 @@ index 97fa6f1ae18db5b4a1fc8f8f99ce0605fb76a793..fd761459048e7e976b7351eb8714acc6 #include "ScriptController.h" #include "ScriptSourceCode.h" #include "SecurityOrigin.h" -@@ -66,14 +76,21 @@ +@@ -66,15 +76,23 @@ #include "StyleScope.h" #include "Theme.h" #include @@ -4190,18 +4199,20 @@ index 97fa6f1ae18db5b4a1fc8f8f99ce0605fb76a793..fd761459048e7e976b7351eb8714acc6 +#include #include +#include ++#include +#include +#include #include + #include #include -#include +#include #if ENABLE(APPLICATION_MANIFEST) #include "CachedApplicationManifest.h" -@@ -92,6 +109,11 @@ namespace WebCore { +@@ -95,6 +113,11 @@ using namespace Inspector; - using namespace Inspector; + WTF_MAKE_TZONE_ALLOCATED_IMPL(InspectorPageAgent); +static HashMap>& createdUserWorlds() { + static NeverDestroyed>> nameToWorld; @@ -4211,7 +4222,7 @@ index 97fa6f1ae18db5b4a1fc8f8f99ce0605fb76a793..fd761459048e7e976b7351eb8714acc6 static bool decodeBuffer(std::span buffer, const String& textEncodingName, String* result) { if (buffer.data()) { -@@ -338,6 +360,7 @@ InspectorPageAgent::InspectorPageAgent(PageAgentContext& context, InspectorClien +@@ -341,6 +364,7 @@ InspectorPageAgent::InspectorPageAgent(PageAgentContext& context, InspectorClien , m_frontendDispatcher(makeUnique(context.frontendRouter)) , m_backendDispatcher(Inspector::PageBackendDispatcher::create(context.backendDispatcher, this)) , m_inspectedPage(context.inspectedPage) @@ -4219,7 +4230,7 @@ index 97fa6f1ae18db5b4a1fc8f8f99ce0605fb76a793..fd761459048e7e976b7351eb8714acc6 , m_client(client) , m_overlay(overlay) { -@@ -367,12 +390,20 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::enable() +@@ -370,12 +394,20 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::enable() defaultUserPreferencesDidChange(); @@ -4240,7 +4251,7 @@ index 97fa6f1ae18db5b4a1fc8f8f99ce0605fb76a793..fd761459048e7e976b7351eb8714acc6 setShowPaintRects(false); #if !PLATFORM(IOS_FAMILY) -@@ -424,6 +455,22 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::reload(std::optiona +@@ -427,6 +459,22 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::reload(std::optiona return { }; } @@ -4263,7 +4274,7 @@ index 97fa6f1ae18db5b4a1fc8f8f99ce0605fb76a793..fd761459048e7e976b7351eb8714acc6 Inspector::Protocol::ErrorStringOr InspectorPageAgent::navigate(const String& url) { auto* localMainFrame = dynamicDowncast(m_inspectedPage.mainFrame()); -@@ -447,6 +494,13 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::overrideUserAgent(c +@@ -450,6 +498,13 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::overrideUserAgent(c return { }; } @@ -4277,7 +4288,7 @@ index 97fa6f1ae18db5b4a1fc8f8f99ce0605fb76a793..fd761459048e7e976b7351eb8714acc6 Inspector::Protocol::ErrorStringOr InspectorPageAgent::overrideSetting(Inspector::Protocol::Page::Setting setting, std::optional&& value) { auto& inspectedPageSettings = m_inspectedPage.settings(); -@@ -460,6 +514,12 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::overrideSetting(Ins +@@ -463,6 +518,12 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::overrideSetting(Ins inspectedPageSettings.setAuthorAndUserStylesEnabledInspectorOverride(value); return { }; @@ -4290,7 +4301,7 @@ index 97fa6f1ae18db5b4a1fc8f8f99ce0605fb76a793..fd761459048e7e976b7351eb8714acc6 case Inspector::Protocol::Page::Setting::ICECandidateFilteringEnabled: inspectedPageSettings.setICECandidateFilteringEnabledInspectorOverride(value); return { }; -@@ -485,6 +545,38 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::overrideSetting(Ins +@@ -488,6 +549,38 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::overrideSetting(Ins inspectedPageSettings.setNeedsSiteSpecificQuirksInspectorOverride(value); return { }; @@ -4329,7 +4340,7 @@ index 97fa6f1ae18db5b4a1fc8f8f99ce0605fb76a793..fd761459048e7e976b7351eb8714acc6 case Inspector::Protocol::Page::Setting::ScriptEnabled: inspectedPageSettings.setScriptEnabledInspectorOverride(value); return { }; -@@ -497,6 +589,12 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::overrideSetting(Ins +@@ -500,6 +593,12 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::overrideSetting(Ins inspectedPageSettings.setShowRepaintCounterInspectorOverride(value); return { }; @@ -4342,7 +4353,7 @@ index 97fa6f1ae18db5b4a1fc8f8f99ce0605fb76a793..fd761459048e7e976b7351eb8714acc6 case Inspector::Protocol::Page::Setting::WebSecurityEnabled: inspectedPageSettings.setWebSecurityEnabledInspectorOverride(value); return { }; -@@ -897,15 +995,16 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::setShowPaintRects(b +@@ -900,15 +999,16 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::setShowPaintRects(b return { }; } @@ -4364,27 +4375,40 @@ index 97fa6f1ae18db5b4a1fc8f8f99ce0605fb76a793..fd761459048e7e976b7351eb8714acc6 } void InspectorPageAgent::frameNavigated(LocalFrame& frame) -@@ -913,13 +1012,25 @@ void InspectorPageAgent::frameNavigated(LocalFrame& frame) +@@ -916,13 +1016,38 @@ 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.processIdentifier().toUInt64(), '.', frameID.object().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()); ++ size_t dotPos = frameID.find("."_s); ++ if (dotPos == notFound) ++ return std::nullopt; ++ ++ if (!frameID.containsOnlyASCII()) ++ return std::nullopt; ++ ++ String processIDString = frameID.left(dotPos); ++ uint64_t pid = strtoull(processIDString.ascii().data(), 0, 10); ++ auto processID = LegacyNullableObjectIdentifier(pid); ++ String frameIDString = frameID.substring(dotPos + 1); ++ uint64_t frameIDNumber = strtoull(frameIDString.ascii().data(), 0, 10); ++ return WebCore::FrameIdentifier { ++ ObjectIdentifier(frameIDNumber), ++ processID ++ }; +} + 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; + @@ -4393,7 +4417,7 @@ index 97fa6f1ae18db5b4a1fc8f8f99ce0605fb76a793..fd761459048e7e976b7351eb8714acc6 } Frame* InspectorPageAgent::frameForId(const Inspector::Protocol::Network::FrameId& frameId) -@@ -931,20 +1042,17 @@ String InspectorPageAgent::frameId(Frame* frame) +@@ -934,20 +1059,21 @@ String InspectorPageAgent::frameId(Frame* frame) { if (!frame) return emptyString(); @@ -4402,7 +4426,7 @@ index 97fa6f1ae18db5b4a1fc8f8f99ce0605fb76a793..fd761459048e7e976b7351eb8714acc6 - 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; } @@ -4415,11 +4439,15 @@ index 97fa6f1ae18db5b4a1fc8f8f99ce0605fb76a793..fd761459048e7e976b7351eb8714acc6 - 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) -@@ -955,11 +1063,6 @@ LocalFrame* InspectorPageAgent::assertFrame(Inspector::Protocol::ErrorString& er +@@ -958,11 +1084,6 @@ LocalFrame* InspectorPageAgent::assertFrame(Inspector::Protocol::ErrorString& er return frame; } @@ -4431,7 +4459,7 @@ index 97fa6f1ae18db5b4a1fc8f8f99ce0605fb76a793..fd761459048e7e976b7351eb8714acc6 void InspectorPageAgent::frameStartedLoading(LocalFrame& frame) { m_frontendDispatcher->frameStartedLoading(frameId(&frame)); -@@ -970,9 +1073,9 @@ void InspectorPageAgent::frameStoppedLoading(LocalFrame& frame) +@@ -973,9 +1094,9 @@ void InspectorPageAgent::frameStoppedLoading(LocalFrame& frame) m_frontendDispatcher->frameStoppedLoading(frameId(&frame)); } @@ -4443,7 +4471,7 @@ index 97fa6f1ae18db5b4a1fc8f8f99ce0605fb76a793..fd761459048e7e976b7351eb8714acc6 } void InspectorPageAgent::frameClearedScheduledNavigation(Frame& frame) -@@ -1019,6 +1122,12 @@ void InspectorPageAgent::defaultUserPreferencesDidChange() +@@ -1022,6 +1143,12 @@ void InspectorPageAgent::defaultUserPreferencesDidChange() m_frontendDispatcher->defaultUserPreferencesDidChange(WTFMove(defaultUserPreferences)); } @@ -4456,7 +4484,7 @@ index 97fa6f1ae18db5b4a1fc8f8f99ce0605fb76a793..fd761459048e7e976b7351eb8714acc6 #if ENABLE(DARK_MODE_CSS) || HAVE(OS_DARK_MODE_SUPPORT) void InspectorPageAgent::defaultAppearanceDidChange() { -@@ -1032,6 +1141,9 @@ void InspectorPageAgent::didClearWindowObjectInWorld(LocalFrame& frame, DOMWrapp +@@ -1035,6 +1162,9 @@ void InspectorPageAgent::didClearWindowObjectInWorld(LocalFrame& frame, DOMWrapp return; if (m_bootstrapScript.isEmpty()) @@ -4466,7 +4494,7 @@ index 97fa6f1ae18db5b4a1fc8f8f99ce0605fb76a793..fd761459048e7e976b7351eb8714acc6 return; frame.script().evaluateIgnoringException(ScriptSourceCode(m_bootstrapScript, JSC::SourceTaintedOrigin::Untainted, URL { "web-inspector://bootstrap.js"_str })); -@@ -1079,6 +1191,51 @@ void InspectorPageAgent::didRecalculateStyle() +@@ -1082,6 +1212,51 @@ void InspectorPageAgent::didRecalculateStyle() m_overlay->update(); } @@ -4518,7 +4546,7 @@ index 97fa6f1ae18db5b4a1fc8f8f99ce0605fb76a793..fd761459048e7e976b7351eb8714acc6 Ref InspectorPageAgent::buildObjectForFrame(LocalFrame* frame) { ASSERT_ARG(frame, frame); -@@ -1176,6 +1333,12 @@ void InspectorPageAgent::applyUserAgentOverride(String& userAgent) +@@ -1179,6 +1354,12 @@ void InspectorPageAgent::applyUserAgentOverride(String& userAgent) userAgent = m_userAgentOverride; } @@ -4531,7 +4559,7 @@ index 97fa6f1ae18db5b4a1fc8f8f99ce0605fb76a793..fd761459048e7e976b7351eb8714acc6 void InspectorPageAgent::applyEmulatedMedia(AtomString& media) { if (!m_emulatedMedia.isEmpty()) -@@ -1203,11 +1366,13 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::snapshotNode(Insp +@@ -1206,11 +1387,13 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::snapshotNode(Insp return snapshot->toDataURL("image/png"_s, std::nullopt, PreserveResolution::Yes); } @@ -4546,7 +4574,7 @@ index 97fa6f1ae18db5b4a1fc8f8f99ce0605fb76a793..fd761459048e7e976b7351eb8714acc6 IntRect rectangle(x, y, width, height); auto* localMainFrame = dynamicDowncast(m_inspectedPage.mainFrame()); -@@ -1221,6 +1386,43 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::snapshotRect(int +@@ -1224,6 +1407,43 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::snapshotRect(int return snapshot->toDataURL("image/png"_s, std::nullopt, PreserveResolution::Yes); } @@ -4590,7 +4618,7 @@ index 97fa6f1ae18db5b4a1fc8f8f99ce0605fb76a793..fd761459048e7e976b7351eb8714acc6 #if ENABLE(WEB_ARCHIVE) && USE(CF) Inspector::Protocol::ErrorStringOr InspectorPageAgent::archive() { -@@ -1237,7 +1439,6 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::archive() +@@ -1240,7 +1460,6 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::archive() } #endif @@ -4598,7 +4626,7 @@ index 97fa6f1ae18db5b4a1fc8f8f99ce0605fb76a793..fd761459048e7e976b7351eb8714acc6 Inspector::Protocol::ErrorStringOr InspectorPageAgent::setScreenSizeOverride(std::optional&& width, std::optional&& height) { if (width.has_value() != height.has_value()) -@@ -1255,6 +1456,508 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::setScreenSizeOverri +@@ -1258,6 +1477,508 @@ Inspector::Protocol::ErrorStringOr InspectorPageAgent::setScreenSizeOverri localMainFrame->setOverrideScreenSize(FloatSize(width.value_or(0), height.value_or(0))); return { }; } @@ -5109,7 +5137,7 @@ index 97fa6f1ae18db5b4a1fc8f8f99ce0605fb76a793..fd761459048e7e976b7351eb8714acc6 } // namespace WebCore diff --git a/Source/WebCore/inspector/agents/InspectorPageAgent.h b/Source/WebCore/inspector/agents/InspectorPageAgent.h -index 371bcfcf1d0ae17471f8e69706d2f12356793418..3e1d5a03edf17f42b566b6d0ec062fdd6d32f1c3 100644 +index 4f78a536c4030b8065d189aacc378d56d3451198..8ffac8bf16c00543ab8cf410e603b06204357714 100644 --- a/Source/WebCore/inspector/agents/InspectorPageAgent.h +++ b/Source/WebCore/inspector/agents/InspectorPageAgent.h @@ -32,8 +32,10 @@ @@ -5123,8 +5151,8 @@ index 371bcfcf1d0ae17471f8e69706d2f12356793418..3e1d5a03edf17f42b566b6d0ec062fdd #include #include #include -@@ -41,11 +43,16 @@ - #include +@@ -42,11 +44,16 @@ + #include #include +namespace Inspector { @@ -5140,15 +5168,16 @@ index 371bcfcf1d0ae17471f8e69706d2f12356793418..3e1d5a03edf17f42b566b6d0ec062fdd class InspectorClient; class InspectorOverlay; class LocalFrame; -@@ -78,6 +85,7 @@ public: +@@ -79,6 +86,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: +@@ -99,8 +108,11 @@ public: Inspector::Protocol::ErrorStringOr enable(); Inspector::Protocol::ErrorStringOr disable(); Inspector::Protocol::ErrorStringOr reload(std::optional&& ignoreCache, std::optional&& revalidateAllResources); @@ -5160,7 +5189,7 @@ index 371bcfcf1d0ae17471f8e69706d2f12356793418..3e1d5a03edf17f42b566b6d0ec062fdd 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,65 @@ public: +@@ -116,45 +128,65 @@ public: #endif Inspector::Protocol::ErrorStringOr setShowPaintRects(bool); Inspector::Protocol::ErrorStringOr setEmulatedMedia(const String&); @@ -5233,7 +5262,7 @@ index 371bcfcf1d0ae17471f8e69706d2f12356793418..3e1d5a03edf17f42b566b6d0ec062fdd static bool mainResourceContent(LocalFrame*, bool withBase64Encode, String* result); static bool dataContent(std::span data, const String& textEncodingName, bool withBase64Encode, String* result); -@@ -169,17 +200,21 @@ private: +@@ -170,17 +202,21 @@ private: RefPtr m_backendDispatcher; Page& m_inspectedPage; @@ -5258,7 +5287,7 @@ index 371bcfcf1d0ae17471f8e69706d2f12356793418..3e1d5a03edf17f42b566b6d0ec062fdd } // 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 009092f4dd46f22aef63ffa0a9758884859e7385..545da93ce753072c18279c67b1589aefcc7e0b8d 100644 --- a/Source/WebCore/inspector/agents/page/PageRuntimeAgent.cpp +++ b/Source/WebCore/inspector/agents/page/PageRuntimeAgent.cpp @@ -34,6 +34,7 @@ @@ -5277,7 +5306,7 @@ index 61b797e08f5e6d90cc2724dd7a3b45c0f45af4f8..919a8b963d93742cc99c2739e472361d #include "SecurityOrigin.h" #include "UserGestureEmulationScope.h" #include -@@ -85,13 +87,73 @@ Inspector::Protocol::ErrorStringOr PageRuntimeAgent::disable() +@@ -88,13 +90,73 @@ Inspector::Protocol::ErrorStringOr PageRuntimeAgent::disable() { m_instrumentingAgents.setEnabledPageRuntimeAgent(nullptr); @@ -5351,7 +5380,7 @@ index 61b797e08f5e6d90cc2724dd7a3b45c0f45af4f8..919a8b963d93742cc99c2739e472361d } void PageRuntimeAgent::didClearWindowObjectInWorld(LocalFrame& frame, DOMWrapperWorld& world) -@@ -100,7 +162,26 @@ void PageRuntimeAgent::didClearWindowObjectInWorld(LocalFrame& frame, DOMWrapper +@@ -103,7 +165,26 @@ void PageRuntimeAgent::didClearWindowObjectInWorld(LocalFrame& frame, DOMWrapper if (!pageAgent) return; @@ -5378,7 +5407,7 @@ index 61b797e08f5e6d90cc2724dd7a3b45c0f45af4f8..919a8b963d93742cc99c2739e472361d } InjectedScript PageRuntimeAgent::injectedScriptForEval(Inspector::Protocol::ErrorString& errorString, std::optional&& executionContextId) -@@ -139,9 +220,6 @@ void PageRuntimeAgent::reportExecutionContextCreation() +@@ -142,9 +223,6 @@ void PageRuntimeAgent::reportExecutionContextCreation() return; m_inspectedPage.forEachLocalFrame([&](LocalFrame& frame) { @@ -5389,10 +5418,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 b70ca7636463b9199bcbb21bfea055870ba33b34..25fdc23bfb71985fe1af04bddc360d118f329afe 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; @@ -5400,7 +5429,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&&); @@ -5414,7 +5443,7 @@ 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; @@ -5423,7 +5452,7 @@ index 9501fc840e35f3badc701e7622555dba394cae9b..1391c73d9b3ba250ad3a831bfe7c92c9 } // namespace WebCore diff --git a/Source/WebCore/loader/CookieJar.h b/Source/WebCore/loader/CookieJar.h -index 2ca6ee01a341eefead66a92e2af77875263a9df3..131bbd8c268a748b43cac105370d7b73753e47a8 100644 +index 2b0060e70df5765f37426eb32c98540dd3a51356..e4682fb4fad491c906ea4b5b1e98c0631e387a7b 100644 --- a/Source/WebCore/loader/CookieJar.h +++ b/Source/WebCore/loader/CookieJar.h @@ -46,6 +46,7 @@ struct CookieStoreGetOptions; @@ -5445,10 +5474,10 @@ index 2ca6ee01a341eefead66a92e2af77875263a9df3..131bbd8c268a748b43cac105370d7b73 protected: static SameSiteInfo sameSiteInfo(const Document&, IsForDOMCookieAccess = IsForDOMCookieAccess::No); diff --git a/Source/WebCore/loader/DocumentLoader.cpp b/Source/WebCore/loader/DocumentLoader.cpp -index 255bc13d586402e96890a3d756cef8467da21dce..d1793d8491e191e3ea76674a3f7e0bbc7411b1aa 100644 +index 1d674f45b41aa4dbd9c864e7da1af9cef5d6d127..2a004184f256d909ca19de77913162adde5d8486 100644 --- a/Source/WebCore/loader/DocumentLoader.cpp +++ b/Source/WebCore/loader/DocumentLoader.cpp -@@ -766,8 +766,10 @@ void DocumentLoader::willSendRequest(ResourceRequest&& newRequest, const Resourc +@@ -769,8 +769,10 @@ void DocumentLoader::willSendRequest(ResourceRequest&& newRequest, const Resourc if (!didReceiveRedirectResponse) return completionHandler(WTFMove(newRequest)); @@ -5459,9 +5488,9 @@ index 255bc13d586402e96890a3d756cef8467da21dce..d1793d8491e191e3ea76674a3f7e0bbc switch (navigationPolicyDecision) { case NavigationPolicyDecision::IgnoreLoad: case NavigationPolicyDecision::LoadWillContinueInAnotherProcess: -@@ -1533,11 +1535,17 @@ void DocumentLoader::detachFromFrame(LoadWillContinueInAnotherProcess loadWillCo - if (auto navigationID = std::exchange(m_navigationID, 0)) - m_frame->loader().client().documentLoaderDetached(navigationID, loadWillContinueInAnotherProcess); +@@ -1538,11 +1540,17 @@ void DocumentLoader::detachFromFrame(LoadWillContinueInAnotherProcess loadWillCo + if (auto navigationID = std::exchange(m_navigationID, { })) + m_frame->loader().client().documentLoaderDetached(*navigationID, loadWillContinueInAnotherProcess); - InspectorInstrumentation::loaderDetachedFromFrame(*m_frame, *this); - @@ -5472,18 +5501,18 @@ index 255bc13d586402e96890a3d756cef8467da21dce..d1793d8491e191e3ea76674a3f7e0bbc +{ + 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 90f993d39598e45732849d4eaa400c049f8f81d9..cf8244e052afad8830880bd998aeaed04d5157aa 100644 +index ef3d4036774db95ef807ad01744f1a9ce715fd81..50d78b5c277d034b8455e2df6f3dbf3d8425ea29 100644 --- a/Source/WebCore/loader/DocumentLoader.h +++ b/Source/WebCore/loader/DocumentLoader.h -@@ -208,6 +208,8 @@ public: +@@ -217,6 +217,8 @@ public: WEBCORE_EXPORT virtual void detachFromFrame(LoadWillContinueInAnotherProcess); @@ -5493,10 +5522,10 @@ index 90f993d39598e45732849d4eaa400c049f8f81d9..cf8244e052afad8830880bd998aeaed0 CheckedPtr checkedFrameLoader() const; WEBCORE_EXPORT SubresourceLoader* mainResourceLoader() const; diff --git a/Source/WebCore/loader/FrameLoader.cpp b/Source/WebCore/loader/FrameLoader.cpp -index 67f6448abad80e7cbb08efd34cf8b67637a1bc35..2b5f6fab94e2f917c84cb9a37a3d9a7fc8b79aaf 100644 +index 4061749da911827143c27b1db9c685a08c9bde6c..060da14ddac0bcf30f010ed9e65cc652b767a8bd 100644 --- a/Source/WebCore/loader/FrameLoader.cpp +++ b/Source/WebCore/loader/FrameLoader.cpp -@@ -1297,6 +1297,7 @@ void FrameLoader::loadInSameDocument(URL url, RefPtr stat +@@ -1306,6 +1306,7 @@ void FrameLoader::loadInSameDocument(URL url, RefPtr stat } m_client->dispatchDidNavigateWithinPage(); @@ -5504,7 +5533,7 @@ index 67f6448abad80e7cbb08efd34cf8b67637a1bc35..2b5f6fab94e2f917c84cb9a37a3d9a7f document->statePopped(stateObject ? stateObject.releaseNonNull() : SerializedScriptValue::nullValue()); m_client->dispatchDidPopStateWithinPage(); -@@ -1798,6 +1799,7 @@ void FrameLoader::loadWithDocumentLoader(DocumentLoader* loader, FrameLoadType t +@@ -1828,6 +1829,7 @@ void FrameLoader::loadWithDocumentLoader(DocumentLoader* loader, FrameLoadType t const String& httpMethod = loader->request().httpMethod(); if (shouldPerformFragmentNavigation(isFormSubmission, httpMethod, policyChecker().loadType(), newURL)) { @@ -5512,7 +5541,7 @@ index 67f6448abad80e7cbb08efd34cf8b67637a1bc35..2b5f6fab94e2f917c84cb9a37a3d9a7f RefPtr oldDocumentLoader = m_documentLoader; NavigationAction action { frame->protectedDocument().releaseNonNull(), loader->request(), InitiatedByMainFrame::Unknown, loader->isRequestFromClientOrUserInput(), policyChecker().loadType(), isFormSubmission }; -@@ -1834,7 +1836,9 @@ void FrameLoader::loadWithDocumentLoader(DocumentLoader* loader, FrameLoadType t +@@ -1864,7 +1866,9 @@ void FrameLoader::loadWithDocumentLoader(DocumentLoader* loader, FrameLoadType t } RELEASE_ASSERT(!isBackForwardLoadType(policyChecker().loadType()) || frame->history().provisionalItem()); @@ -5522,7 +5551,7 @@ index 67f6448abad80e7cbb08efd34cf8b67637a1bc35..2b5f6fab94e2f917c84cb9a37a3d9a7f continueLoadAfterNavigationPolicy(request, RefPtr { weakFormState.get() }.get(), navigationPolicyDecision, allowNavigationToInvalidURL); completionHandler(); }, PolicyDecisionMode::Asynchronous); -@@ -3111,10 +3115,15 @@ String FrameLoader::userAgent(const URL& url) const +@@ -3148,10 +3152,15 @@ String FrameLoader::userAgent(const URL& url) const String FrameLoader::navigatorPlatform() const { @@ -5540,7 +5569,7 @@ index 67f6448abad80e7cbb08efd34cf8b67637a1bc35..2b5f6fab94e2f917c84cb9a37a3d9a7f } void FrameLoader::dispatchOnloadEvents() -@@ -3579,6 +3588,8 @@ void FrameLoader::receivedMainResourceError(const ResourceError& error, LoadWill +@@ -3615,6 +3624,8 @@ void FrameLoader::receivedMainResourceError(const ResourceError& error, LoadWill checkCompleted(); if (frame->page()) checkLoadComplete(loadWillContinueInAnotherProcess); @@ -5549,7 +5578,7 @@ index 67f6448abad80e7cbb08efd34cf8b67637a1bc35..2b5f6fab94e2f917c84cb9a37a3d9a7f } void FrameLoader::continueFragmentScrollAfterNavigationPolicy(const ResourceRequest& request, const SecurityOrigin* requesterOrigin, bool shouldContinue, NavigationHistoryBehavior historyHandling) -@@ -4461,9 +4472,6 @@ String FrameLoader::referrer() const +@@ -4499,9 +4510,6 @@ String FrameLoader::referrer() const void FrameLoader::dispatchDidClearWindowObjectsInAllWorlds() { @@ -5559,7 +5588,7 @@ index 67f6448abad80e7cbb08efd34cf8b67637a1bc35..2b5f6fab94e2f917c84cb9a37a3d9a7f Vector> worlds; ScriptController::getAllWorlds(worlds); for (auto& world : worlds) -@@ -4473,13 +4481,12 @@ void FrameLoader::dispatchDidClearWindowObjectsInAllWorlds() +@@ -4511,13 +4519,12 @@ void FrameLoader::dispatchDidClearWindowObjectsInAllWorlds() void FrameLoader::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld& world) { Ref frame = m_frame.get(); @@ -5592,10 +5621,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 3eb4ad66cbbc66cd72b0d74dde61bc0c0508ba00..9456d74f591d8e32ad0b1f24be9172c6017ef317 100644 +index f8dc5dbb8e4583bc8d595cee184adf58aa765c6c..8c2d54e5d2543b71a733e7356c99e3c1b7642341 100644 --- a/Source/WebCore/loader/NavigationScheduler.cpp +++ b/Source/WebCore/loader/NavigationScheduler.cpp -@@ -703,7 +703,7 @@ void NavigationScheduler::startTimer() +@@ -766,7 +766,7 @@ void NavigationScheduler::startTimer() Seconds delay = 1_s * m_redirect->delay(); m_timer.startOneShot(delay); @@ -5605,7 +5634,7 @@ index 3eb4ad66cbbc66cd72b0d74dde61bc0c0508ba00..9456d74f591d8e32ad0b1f24be9172c6 } diff --git a/Source/WebCore/loader/PolicyChecker.cpp b/Source/WebCore/loader/PolicyChecker.cpp -index 15ce6dd0ee3c412bcaf33063e8610c5936677c9c..344172ad41a7915982aaef12b175a0f9dffdc388 100644 +index 8f9d997be3da9d2374e1fb50d48c48cdc6542559..4aae7eef8933ddd6a4cae28bc4ef43d3567fda68 100644 --- a/Source/WebCore/loader/PolicyChecker.cpp +++ b/Source/WebCore/loader/PolicyChecker.cpp @@ -46,6 +46,7 @@ @@ -5639,10 +5668,10 @@ index b74c5258454b0df9f74aa8a5297674b733925685..b6c3999745368c7f7e2e6176bfca6dc0 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 e65b301a2dbe9a873e872a6904a7344b9a3efe08..a8d34d05fb3b8f3b118f71fd223b673ee975998c 100644 +index 3d811dc807fe10e78221357f76e6851e5788b43e..a1bd9d168a1faa39bc8d122da5e3e8192eb392ce 100644 --- a/Source/WebCore/loader/cache/CachedResourceLoader.cpp +++ b/Source/WebCore/loader/cache/CachedResourceLoader.cpp -@@ -1123,8 +1123,11 @@ ResourceErrorOr> CachedResourceLoader::requ +@@ -1136,8 +1136,11 @@ ResourceErrorOr> CachedResourceLoader::requ request.updateReferrerPolicy(document() ? document()->referrerPolicy() : ReferrerPolicy::Default); @@ -5656,7 +5685,7 @@ index e65b301a2dbe9a873e872a6904a7344b9a3efe08..a8d34d05fb3b8f3b118f71fd223b673e if (RefPtr documentLoader = m_documentLoader.get()) { bool madeHTTPS { request.resourceRequest().wasSchemeOptimisticallyUpgraded() }; -@@ -1741,8 +1744,9 @@ Vector> CachedResourceLoader::allCachedSVGImages() const +@@ -1754,8 +1757,9 @@ Vector> CachedResourceLoader::allCachedSVGImages() const ResourceErrorOr> CachedResourceLoader::preload(CachedResource::Type type, CachedResourceRequest&& request) { @@ -5669,10 +5698,10 @@ index e65b301a2dbe9a873e872a6904a7344b9a3efe08..a8d34d05fb3b8f3b118f71fd223b673e ASSERT(m_document); if (request.charset().isEmpty() && m_document && (type == CachedResource::Type::Script || type == CachedResource::Type::CSSStyleSheet)) diff --git a/Source/WebCore/page/ChromeClient.h b/Source/WebCore/page/ChromeClient.h -index 6344c5f7d24e89cfd1ae70adf75ee591f15e797f..37e166d8b121aed461ed5aec838d3b29fe7fca4a 100644 +index bcc9390a5c7b00e0f3d41baea920453e7b3ac73a..07898280d090a78949876042a64103d4ead18d7f 100644 --- a/Source/WebCore/page/ChromeClient.h +++ b/Source/WebCore/page/ChromeClient.h -@@ -342,7 +342,7 @@ public: +@@ -341,7 +341,7 @@ public: #endif #if ENABLE(ORIENTATION_EVENTS) @@ -5682,10 +5711,10 @@ index 6344c5f7d24e89cfd1ae70adf75ee591f15e797f..37e166d8b121aed461ed5aec838d3b29 #if ENABLE(INPUT_TYPE_COLOR) diff --git a/Source/WebCore/page/EventHandler.cpp b/Source/WebCore/page/EventHandler.cpp -index 75ce051422ff276cf6ba5e699fb88c19c7474360..9eeeeb7aafc527392d5870e966c2d926848c9fdc 100644 +index cedf16dffeceb7941de7eca75f6c6800ecacf06f..03296e2cc70e9bd4468ff6161a16378077b0f69c 100644 --- a/Source/WebCore/page/EventHandler.cpp +++ b/Source/WebCore/page/EventHandler.cpp -@@ -4346,6 +4346,12 @@ bool EventHandler::handleDrag(const MouseEventWithHitTestResults& event, CheckDr +@@ -4372,6 +4372,12 @@ bool EventHandler::handleDrag(const MouseEventWithHitTestResults& event, CheckDr if (!document) return false; @@ -5698,7 +5727,7 @@ index 75ce051422ff276cf6ba5e699fb88c19c7474360..9eeeeb7aafc527392d5870e966c2d926 dragState().dataTransfer = DataTransfer::createForDrag(*document); auto hasNonDefaultPasteboardData = HasNonDefaultPasteboardData::No; -@@ -4972,7 +4978,7 @@ HandleUserInputEventResult EventHandler::handleTouchEvent(const PlatformTouchEve +@@ -5001,7 +5007,7 @@ HandleUserInputEventResult EventHandler::handleTouchEvent(const PlatformTouchEve // Increment the platform touch id by 1 to avoid storing a key of 0 in the hashmap. unsigned touchPointTargetKey = point.id() + 1; @@ -5707,7 +5736,7 @@ index 75ce051422ff276cf6ba5e699fb88c19c7474360..9eeeeb7aafc527392d5870e966c2d926 bool pointerCancelled = false; #endif RefPtr touchTarget; -@@ -5019,7 +5025,7 @@ HandleUserInputEventResult EventHandler::handleTouchEvent(const PlatformTouchEve +@@ -5048,7 +5054,7 @@ HandleUserInputEventResult EventHandler::handleTouchEvent(const PlatformTouchEve // we also remove it from the map. touchTarget = m_originatingTouchPointTargets.take(touchPointTargetKey); @@ -5716,7 +5745,7 @@ index 75ce051422ff276cf6ba5e699fb88c19c7474360..9eeeeb7aafc527392d5870e966c2d926 HitTestResult result = hitTestResultAtPoint(pagePoint, hitType | HitTestRequest::Type::AllowChildFrameContent); pointerTarget = result.targetElement(); pointerCancelled = (pointerTarget != touchTarget); -@@ -5042,7 +5048,7 @@ HandleUserInputEventResult EventHandler::handleTouchEvent(const PlatformTouchEve +@@ -5071,7 +5077,7 @@ HandleUserInputEventResult EventHandler::handleTouchEvent(const PlatformTouchEve if (!targetFrame) continue; @@ -5725,6 +5754,27 @@ index 75ce051422ff276cf6ba5e699fb88c19c7474360..9eeeeb7aafc527392d5870e966c2d926 // 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) { +diff --git a/Source/WebCore/page/FocusController.cpp b/Source/WebCore/page/FocusController.cpp +index c911a4a6ac3f89485cd69917d1f50145b0779b7e..081c8e9a23a5a5d8f4ccd2205016ca0acf2ce64a 100644 +--- a/Source/WebCore/page/FocusController.cpp ++++ b/Source/WebCore/page/FocusController.cpp +@@ -581,13 +581,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 084db825e36bd46126fea95fc7183bf2e931be7e..dac3caef67600f8c7c945fd857a91140a23d0303 100644 --- a/Source/WebCore/page/FrameSnapshotting.cpp @@ -5777,7 +5827,7 @@ index 5b365008debe6b8d5a95a572a4c2725b0a7a519d..2c6ad49a45a1759f446aced179c0c5a7 struct SnapshotOptions { diff --git a/Source/WebCore/page/History.cpp b/Source/WebCore/page/History.cpp -index 22ef70201db214f4a7c9c6b4d1eef699e1d7f334..7ddfe9b9c890927cc6a7d19fe1b82c466c5fc835 100644 +index 709a8aca3d10170ce8394efaeb8eaa0eff9bfacf..40b2ccc937b36b17686cc2231e6f33ebb3e6f712 100644 --- a/Source/WebCore/page/History.cpp +++ b/Source/WebCore/page/History.cpp @@ -32,6 +32,7 @@ @@ -5788,8 +5838,8 @@ index 22ef70201db214f4a7c9c6b4d1eef699e1d7f334..7ddfe9b9c890927cc6a7d19fe1b82c46 #include "LocalFrame.h" #include "LocalFrameLoaderClient.h" #include "Logging.h" -@@ -303,6 +304,8 @@ ExceptionOr History::stateObjectAdded(RefPtr&& data - m_mostRecentStateObjectUsage = payloadSize; +@@ -309,6 +310,8 @@ ExceptionOr History::stateObjectAdded(RefPtr&& data + } frame->loader().updateURLAndHistory(fullURL, WTFMove(data), historyBehavior); + InspectorInstrumentation::didNavigateWithinPage(*frame); @@ -5798,17 +5848,17 @@ index 22ef70201db214f4a7c9c6b4d1eef699e1d7f334..7ddfe9b9c890927cc6a7d19fe1b82c46 } diff --git a/Source/WebCore/page/LocalFrame.cpp b/Source/WebCore/page/LocalFrame.cpp -index fd1f944368f0afe4cf52774ded2007505f7322a3..0942514d3b2e4d65b31c6a4ec7eb930972d15bab 100644 +index 53f47ce0a1a4bccf35e183bdb1e7d7ea3208e7ed..9ce65588de61f0c2e8f6a7ee804c93c6a5520d2e 100644 --- a/Source/WebCore/page/LocalFrame.cpp +++ b/Source/WebCore/page/LocalFrame.cpp -@@ -40,6 +40,7 @@ +@@ -41,6 +41,7 @@ #include "CachedResourceLoader.h" #include "Chrome.h" #include "ChromeClient.h" +#include "ComposedTreeIterator.h" #include "DocumentLoader.h" - #include "DocumentTimelinesController.h" #include "DocumentType.h" + #include "Editing.h" @@ -57,6 +58,7 @@ #include "FrameSelection.h" #include "GraphicsContext.h" @@ -5825,7 +5875,7 @@ index fd1f944368f0afe4cf52774ded2007505f7322a3..0942514d3b2e4d65b31c6a4ec7eb9309 #include "NodeTraversal.h" #include "Page.h" #include "ProcessWarming.h" -@@ -188,6 +191,7 @@ LocalFrame::LocalFrame(Page& page, ClientCreator&& clientCreator, FrameIdentifie +@@ -189,6 +192,7 @@ LocalFrame::LocalFrame(Page& page, ClientCreator&& clientCreator, FrameIdentifie void LocalFrame::init() { @@ -5833,7 +5883,7 @@ index fd1f944368f0afe4cf52774ded2007505f7322a3..0942514d3b2e4d65b31c6a4ec7eb9309 checkedLoader()->init(); } -@@ -404,7 +408,7 @@ void LocalFrame::orientationChanged() +@@ -405,7 +409,7 @@ void LocalFrame::orientationChanged() IntDegrees LocalFrame::orientation() const { if (RefPtr page = this->page()) @@ -5842,8 +5892,8 @@ index fd1f944368f0afe4cf52774ded2007505f7322a3..0942514d3b2e4d65b31c6a4ec7eb9309 return 0; } #endif // ENABLE(ORIENTATION_EVENTS) -@@ -1350,6 +1354,362 @@ OptionSet LocalFrame::advancedPrivacyProtections() c - return { }; +@@ -1370,6 +1374,362 @@ void LocalFrame::updateSandboxFlags(SandboxFlags flags, NotifyUIProcess notifyUI + m_sandboxFlags = flags; } +#if !PLATFORM(IOS_FAMILY) @@ -6206,7 +6256,7 @@ index fd1f944368f0afe4cf52774ded2007505f7322a3..0942514d3b2e4d65b31c6a4ec7eb9309 #undef FRAME_RELEASE_LOG_ERROR diff --git a/Source/WebCore/page/LocalFrame.h b/Source/WebCore/page/LocalFrame.h -index c2fc366ed759fb9e1d83821c4fff4b05a6b8fe35..d3eec8aa3129ae6567b1402968374015f11efaa2 100644 +index 38fe2680b461f6a319f6b976412fff6a5af9950f..ca63f835abf84b00fb7e57361b1969400ceb8f4a 100644 --- a/Source/WebCore/page/LocalFrame.h +++ b/Source/WebCore/page/LocalFrame.h @@ -28,8 +28,10 @@ @@ -6228,7 +6278,7 @@ index c2fc366ed759fb9e1d83821c4fff4b05a6b8fe35..d3eec8aa3129ae6567b1402968374015 class Editor; class Element; class EventHandler; -@@ -112,8 +113,8 @@ enum { +@@ -115,8 +116,8 @@ enum { }; enum OverflowScrollAction { DoNotPerformOverflowScroll, PerformOverflowScroll }; @@ -6238,7 +6288,7 @@ index c2fc366ed759fb9e1d83821c4fff4b05a6b8fe35..d3eec8aa3129ae6567b1402968374015 class LocalFrame final : public Frame { public: -@@ -222,10 +223,6 @@ public: +@@ -226,10 +227,6 @@ public: WEBCORE_EXPORT DataDetectionResultsStorage& dataDetectionResults(); #endif @@ -6249,7 +6299,7 @@ index c2fc366ed759fb9e1d83821c4fff4b05a6b8fe35..d3eec8aa3129ae6567b1402968374015 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); -@@ -233,6 +230,10 @@ public: +@@ -237,6 +234,10 @@ public: WEBCORE_EXPORT Node* nodeRespondingToScrollWheelEvents(const FloatPoint& viewportLocation); WEBCORE_EXPORT Node* approximateNodeAtViewportLocationLegacy(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation); @@ -6260,7 +6310,7 @@ index c2fc366ed759fb9e1d83821c4fff4b05a6b8fe35..d3eec8aa3129ae6567b1402968374015 WEBCORE_EXPORT NSArray *wordsInCurrentParagraph() const; WEBCORE_EXPORT CGRect renderRectForPoint(CGPoint, bool* isReplaced, float* fontSize) const; -@@ -300,6 +301,7 @@ public: +@@ -304,6 +305,7 @@ public: WEBCORE_EXPORT FloatSize screenSize() const; void setOverrideScreenSize(FloatSize&&); @@ -6268,7 +6318,7 @@ index c2fc366ed759fb9e1d83821c4fff4b05a6b8fe35..d3eec8aa3129ae6567b1402968374015 void selfOnlyRef(); void selfOnlyDeref(); -@@ -355,7 +357,6 @@ private: +@@ -363,7 +365,6 @@ private: #if ENABLE(DATA_DETECTION) std::unique_ptr m_dataDetectionResults; #endif @@ -6276,7 +6326,7 @@ index c2fc366ed759fb9e1d83821c4fff4b05a6b8fe35..d3eec8aa3129ae6567b1402968374015 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); -@@ -363,6 +364,7 @@ private: +@@ -371,6 +372,7 @@ private: enum class ShouldFindRootEditableElement : bool { No, Yes }; Node* qualifyingNodeAtViewportLocation(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation, const NodeQualifier&, ShouldApproximate, ShouldFindRootEditableElement = ShouldFindRootEditableElement::Yes); @@ -6285,10 +6335,10 @@ index c2fc366ed759fb9e1d83821c4fff4b05a6b8fe35..d3eec8aa3129ae6567b1402968374015 ViewportArguments m_viewportArguments; diff --git a/Source/WebCore/page/Page.cpp b/Source/WebCore/page/Page.cpp -index ab89eb4e743e8e5aca46cdc0923eada1acc9f527..46dd2458db397a74402bcd4a14227bb8850126fa 100644 +index 93122d37376bc11488f27dea245534d7657e281d..1cccbbb3379a468bca19903ab1eb34cdd285a93c 100644 --- a/Source/WebCore/page/Page.cpp +++ b/Source/WebCore/page/Page.cpp -@@ -605,6 +605,45 @@ void Page::setOverrideViewportArguments(const std::optional& +@@ -609,6 +609,45 @@ void Page::setOverrideViewportArguments(const std::optional& document->updateViewportArguments(); } @@ -6334,7 +6384,7 @@ index ab89eb4e743e8e5aca46cdc0923eada1acc9f527..46dd2458db397a74402bcd4a14227bb8 ScrollingCoordinator* Page::scrollingCoordinator() { if (!m_scrollingCoordinator && m_settings->scrollingCoordinatorEnabled()) { -@@ -3912,6 +3951,26 @@ void Page::setUseDarkAppearanceOverride(std::optional valueOverride) +@@ -3974,6 +4013,26 @@ void Page::setUseDarkAppearanceOverride(std::optional valueOverride) #endif } @@ -6362,10 +6412,10 @@ index ab89eb4e743e8e5aca46cdc0923eada1acc9f527..46dd2458db397a74402bcd4a14227bb8 { if (insets == m_fullscreenInsets) diff --git a/Source/WebCore/page/Page.h b/Source/WebCore/page/Page.h -index cbed2c94bb7c3c0b437369b6b36913760d2d07aa..d5d7f00f3d59b9d6043c340512ba4131185b94bd 100644 +index 55887f532ee42163e7ea0c34a31f1c8bdc0d808f..cc0d6b05a2132c96e45e956cbccabe61df434953 100644 --- a/Source/WebCore/page/Page.h +++ b/Source/WebCore/page/Page.h -@@ -346,6 +346,9 @@ public: +@@ -354,6 +354,9 @@ public: const std::optional& overrideViewportArguments() const { return m_overrideViewportArguments; } WEBCORE_EXPORT void setOverrideViewportArguments(const std::optional&); @@ -6375,7 +6425,7 @@ index cbed2c94bb7c3c0b437369b6b36913760d2d07aa..d5d7f00f3d59b9d6043c340512ba4131 static void refreshPlugins(bool reload); WEBCORE_EXPORT PluginData& pluginData(); void clearPluginData(); -@@ -412,6 +415,10 @@ public: +@@ -422,6 +425,10 @@ public: #if ENABLE(DRAG_SUPPORT) DragController& dragController() { return m_dragController.get(); } const DragController& dragController() const { return m_dragController.get(); } @@ -6386,7 +6436,7 @@ index cbed2c94bb7c3c0b437369b6b36913760d2d07aa..d5d7f00f3d59b9d6043c340512ba4131 #endif FocusController& focusController() const { return *m_focusController; } WEBCORE_EXPORT CheckedRef checkedFocusController() const; -@@ -595,6 +602,10 @@ public: +@@ -605,6 +612,10 @@ public: WEBCORE_EXPORT void effectiveAppearanceDidChange(bool useDarkAppearance, bool useElevatedUserInterfaceLevel); bool defaultUseDarkAppearance() const { return m_useDarkAppearance; } void setUseDarkAppearanceOverride(std::optional); @@ -6397,7 +6447,7 @@ index cbed2c94bb7c3c0b437369b6b36913760d2d07aa..d5d7f00f3d59b9d6043c340512ba4131 #if ENABLE(TEXT_AUTOSIZING) float textAutosizingWidth() const { return m_textAutosizingWidth; } -@@ -1043,6 +1054,11 @@ public: +@@ -1057,6 +1068,11 @@ public: WEBCORE_EXPORT void setInteractionRegionsEnabled(bool); #endif @@ -6409,7 +6459,7 @@ index cbed2c94bb7c3c0b437369b6b36913760d2d07aa..d5d7f00f3d59b9d6043c340512ba4131 #if ENABLE(DEVICE_ORIENTATION) && PLATFORM(IOS_FAMILY) DeviceOrientationUpdateProvider* deviceOrientationUpdateProvider() const { return m_deviceOrientationUpdateProvider.get(); } #endif -@@ -1264,6 +1280,9 @@ private: +@@ -1289,6 +1305,9 @@ private: #if ENABLE(DRAG_SUPPORT) UniqueRef m_dragController; @@ -6419,7 +6469,7 @@ index cbed2c94bb7c3c0b437369b6b36913760d2d07aa..d5d7f00f3d59b9d6043c340512ba4131 #endif std::unique_ptr m_focusController; #if ENABLE(CONTEXT_MENUS) -@@ -1344,6 +1363,8 @@ private: +@@ -1369,6 +1388,8 @@ private: bool m_useElevatedUserInterfaceLevel { false }; bool m_useDarkAppearance { false }; std::optional m_useDarkAppearanceOverride; @@ -6428,7 +6478,7 @@ index cbed2c94bb7c3c0b437369b6b36913760d2d07aa..d5d7f00f3d59b9d6043c340512ba4131 #if ENABLE(TEXT_AUTOSIZING) float m_textAutosizingWidth { 0 }; -@@ -1524,6 +1545,11 @@ private: +@@ -1549,6 +1570,11 @@ private: #endif std::optional m_overrideViewportArguments; @@ -6441,10 +6491,10 @@ index cbed2c94bb7c3c0b437369b6b36913760d2d07aa..d5d7f00f3d59b9d6043c340512ba4131 #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 8fcc6f546882998be87d52c296c4637c6fd5af0f..73e3adc185923ba249f39f070a0b9fbb20418b0b 100644 +index 52ceeb42346f843bec6734584e7d36beb7845abd..5bf7ff1870fdd011ea16419ab517bfa6ff51d874 100644 --- a/Source/WebCore/page/PageConsoleClient.cpp +++ b/Source/WebCore/page/PageConsoleClient.cpp -@@ -434,4 +434,9 @@ Ref PageConsoleClient::protectedPage() const +@@ -437,4 +437,9 @@ Ref PageConsoleClient::protectedPage() const return m_page.get(); } @@ -6455,10 +6505,10 @@ index 8fcc6f546882998be87d52c296c4637c6fd5af0f..73e3adc185923ba249f39f070a0b9fbb + } // 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; @@ -6467,10 +6517,10 @@ index 6ee10d6ca68ad8ea93ae45adb0876c80953d3278..d4e14d54af6cd21fc5649d18dbc6af20 Ref protectedPage() const; diff --git a/Source/WebCore/page/PointerCaptureController.cpp b/Source/WebCore/page/PointerCaptureController.cpp -index 2e85dc0e40c12857b9bac2f672a9b6332f3156df..0b64153cdf6db62f42e332f269acb399176bdb42 100644 +index f1040d32a97110c5b8d802450f36794f1d0f34fd..469c6cc7674578e5f2623a23c3f151bc65d278c1 100644 --- a/Source/WebCore/page/PointerCaptureController.cpp +++ b/Source/WebCore/page/PointerCaptureController.cpp -@@ -195,7 +195,7 @@ bool PointerCaptureController::preventsCompatibilityMouseEventsForIdentifier(Poi +@@ -198,7 +198,7 @@ bool PointerCaptureController::preventsCompatibilityMouseEventsForIdentifier(Poi return capturingData && capturingData->preventsCompatibilityMouseEvents; } @@ -6479,7 +6529,7 @@ index 2e85dc0e40c12857b9bac2f672a9b6332f3156df..0b64153cdf6db62f42e332f269acb399 static bool hierarchyHasCapturingEventListeners(Element* target, const AtomString& eventName) { for (RefPtr currentNode = target; currentNode; currentNode = currentNode->parentInComposedTree()) { -@@ -513,7 +513,7 @@ void PointerCaptureController::cancelPointer(PointerID pointerId, const IntPoint +@@ -503,7 +503,7 @@ void PointerCaptureController::cancelPointer(PointerID pointerId, const IntPoint capturingData->pendingTargetOverride = nullptr; capturingData->state = CapturingData::State::Cancelled; @@ -6489,10 +6539,10 @@ index 2e85dc0e40c12857b9bac2f672a9b6332f3156df..0b64153cdf6db62f42e332f269acb399 #endif diff --git a/Source/WebCore/page/PointerCaptureController.h b/Source/WebCore/page/PointerCaptureController.h -index 91a9847a4083393e225f42e71c2dd590a88c0289..b0838c84e4ba24378db42f40a68856afe95fb9a7 100644 +index 99676da258803e8348ae1fee23e7e3883fb0b888..0477e6dff22db0e7f2d78cb8ecb863ec5fea136f 100644 --- a/Source/WebCore/page/PointerCaptureController.h +++ b/Source/WebCore/page/PointerCaptureController.h -@@ -58,7 +58,7 @@ public: +@@ -59,7 +59,7 @@ public: RefPtr pointerEventForMouseEvent(const MouseEvent&, PointerID, const String& pointerType); @@ -6501,7 +6551,7 @@ index 91a9847a4083393e225f42e71c2dd590a88c0289..b0838c84e4ba24378db42f40a68856af void dispatchEventForTouchAtIndex(EventTarget&, const PlatformTouchEvent&, unsigned, bool isPrimary, WindowProxy&, const IntPoint&); #endif -@@ -78,12 +78,12 @@ private: +@@ -79,12 +79,12 @@ private: RefPtr pendingTargetOverride; RefPtr targetOverride; @@ -6517,11 +6567,11 @@ index 91a9847a4083393e225f42e71c2dd590a88c0289..b0838c84e4ba24378db42f40a68856af #endif ; diff --git a/Source/WebCore/page/Screen.cpp b/Source/WebCore/page/Screen.cpp -index 706f67ca9d5b98f519080fad94d424a130b18a0e..c98147603680bd21c83a0b2b1593fa84a733f22f 100644 +index 24ed7c019bea4df52f2883db0e40bdbc2dc74ebd..a788f534d9e0e8124153c7f380b4fdb232c51a1a 100644 --- a/Source/WebCore/page/Screen.cpp +++ b/Source/WebCore/page/Screen.cpp -@@ -102,6 +102,9 @@ int Screen::availLeft() const - if (fingerprintingProtectionsEnabled(*frame)) +@@ -124,6 +124,9 @@ int Screen::availLeft() const + if (shouldApplyScreenFingerprintingProtections(*frame)) return 0; + if (frame->hasScreenSizeOverride()) @@ -6530,8 +6580,8 @@ index 706f67ca9d5b98f519080fad94d424a130b18a0e..c98147603680bd21c83a0b2b1593fa84 return static_cast(screenAvailableRect(frame->protectedView().get()).x()); } -@@ -117,6 +120,9 @@ int Screen::availTop() const - if (fingerprintingProtectionsEnabled(*frame)) +@@ -139,6 +142,9 @@ int Screen::availTop() const + if (shouldApplyScreenFingerprintingProtections(*frame)) return 0; + if (frame->hasScreenSizeOverride()) @@ -6540,8 +6590,8 @@ index 706f67ca9d5b98f519080fad94d424a130b18a0e..c98147603680bd21c83a0b2b1593fa84 return static_cast(screenAvailableRect(frame->protectedView().get()).y()); } -@@ -132,6 +138,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()) @@ -6550,8 +6600,8 @@ index 706f67ca9d5b98f519080fad94d424a130b18a0e..c98147603680bd21c83a0b2b1593fa84 return static_cast(screenAvailableRect(frame->protectedView().get()).height()); } -@@ -147,6 +156,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()) @@ -6561,10 +6611,10 @@ index 706f67ca9d5b98f519080fad94d424a130b18a0e..c98147603680bd21c83a0b2b1593fa84 } diff --git a/Source/WebCore/page/csp/ContentSecurityPolicy.cpp b/Source/WebCore/page/csp/ContentSecurityPolicy.cpp -index 50cf04e63a7de97d508448f181429f5b7fa438a3..6c2a5c085436eac669bce5f1d9094764ba0c6250 100644 +index 74e4e43482f969cf90c47d897f8226672d748cff..d2b491a7346677253891f4057b2cdb1d679fe08b 100644 --- a/Source/WebCore/page/csp/ContentSecurityPolicy.cpp +++ b/Source/WebCore/page/csp/ContentSecurityPolicy.cpp -@@ -344,6 +344,8 @@ bool ContentSecurityPolicy::allowContentSecurityPolicySourceStarToMatchAnyProtoc +@@ -347,6 +347,8 @@ bool ContentSecurityPolicy::allowContentSecurityPolicySourceStarToMatchAnyProtoc template typename std::enable_if::value, bool>::type ContentSecurityPolicy::allPoliciesWithDispositionAllow(Disposition disposition, Predicate&& predicate, Args&&... args) const { @@ -6573,7 +6623,7 @@ index 50cf04e63a7de97d508448f181429f5b7fa438a3..6c2a5c085436eac669bce5f1d9094764 bool isReportOnly = disposition == ContentSecurityPolicy::Disposition::ReportOnly; for (auto& policy : m_policies) { if (policy->isReportOnly() != isReportOnly) -@@ -357,6 +359,8 @@ typename std::enable_if bool ContentSecurityPolicy::allPoliciesWithDispositionAllow(Disposition disposition, ViolatedDirectiveCallback&& callback, Predicate&& predicate, Args&&... args) const { @@ -6582,7 +6632,7 @@ index 50cf04e63a7de97d508448f181429f5b7fa438a3..6c2a5c085436eac669bce5f1d9094764 bool isReportOnly = disposition == ContentSecurityPolicy::Disposition::ReportOnly; bool isAllowed = true; for (auto& policy : m_policies) { -@@ -373,6 +377,8 @@ bool ContentSecurityPolicy::allPoliciesWithDispositionAllow(Disposition disposit +@@ -376,6 +380,8 @@ bool ContentSecurityPolicy::allPoliciesWithDispositionAllow(Disposition disposit template bool ContentSecurityPolicy::allPoliciesAllow(ViolatedDirectiveCallback&& callback, Predicate&& predicate, Args&&... args) const { @@ -6736,10 +6786,10 @@ index c359242a7967dab94b8dc3c276a6df5473527145..64b0c6a0bfdf27a0305c25e8b8e0cda6 IntSize dragImageSize(DragImageRef) { diff --git a/Source/WebCore/platform/Pasteboard.h b/Source/WebCore/platform/Pasteboard.h -index 86205341336734eebfb9f1c98bb4b8ac4e81c3aa..1fd303a89a0431806f91ac072037806e7d6a2fe7 100644 +index 33841aa5cc1fc15557514d60096d8274234447c3..2c91d472a24c591215d6f2861aca6f86a00d086a 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 @@ -6748,7 +6798,7 @@ index 86205341336734eebfb9f1c98bb4b8ac4e81c3aa..1fd303a89a0431806f91ac072037806e #include "SelectionData.h" #endif -@@ -107,7 +107,7 @@ struct PasteboardURL { +@@ -108,7 +108,7 @@ struct PasteboardURL { #if PLATFORM(MAC) String userVisibleForm; #endif @@ -6757,7 +6807,7 @@ index 86205341336734eebfb9f1c98bb4b8ac4e81c3aa..1fd303a89a0431806f91ac072037806e String markup; #endif }; -@@ -195,6 +195,11 @@ public: +@@ -197,6 +197,11 @@ public: #endif #endif @@ -6769,7 +6819,7 @@ index 86205341336734eebfb9f1c98bb4b8ac4e81c3aa..1fd303a89a0431806f91ac072037806e #if PLATFORM(WIN) explicit Pasteboard(std::unique_ptr&&, IDataObject*); explicit Pasteboard(std::unique_ptr&&, WCDataObject*); -@@ -262,6 +267,12 @@ public: +@@ -264,6 +269,12 @@ public: int64_t changeCount() const; #endif @@ -6782,7 +6832,7 @@ index 86205341336734eebfb9f1c98bb4b8ac4e81c3aa..1fd303a89a0431806f91ac072037806e #if PLATFORM(IOS_FAMILY) explicit Pasteboard(std::unique_ptr&&, int64_t changeCount); explicit Pasteboard(std::unique_ptr&&, const String& pasteboardName); -@@ -304,6 +315,7 @@ public: +@@ -306,6 +317,7 @@ public: COMPtr dataObject() const { return m_dataObject; } WEBCORE_EXPORT void setExternalDataObject(IDataObject*); const DragDataMap& dragDataMap() const { return m_dragDataMap; } @@ -6790,7 +6840,7 @@ index 86205341336734eebfb9f1c98bb4b8ac4e81c3aa..1fd303a89a0431806f91ac072037806e void writeURLToWritableDataObject(const URL&, const String&); COMPtr writableDataObject() const { return m_writableDataObject; } void writeImageToDataObject(Element&, const URL&); // FIXME: Layering violation. -@@ -356,6 +368,10 @@ private: +@@ -358,6 +370,10 @@ private: int64_t m_changeCount { 0 }; #endif @@ -6801,7 +6851,7 @@ index 86205341336734eebfb9f1c98bb4b8ac4e81c3aa..1fd303a89a0431806f91ac072037806e #if PLATFORM(COCOA) String m_pasteboardName; int64_t m_changeCount; -@@ -371,6 +387,7 @@ private: +@@ -373,6 +389,7 @@ private: COMPtr m_dataObject; COMPtr m_writableDataObject; DragDataMap m_dragDataMap; @@ -6810,10 +6860,10 @@ index 86205341336734eebfb9f1c98bb4b8ac4e81c3aa..1fd303a89a0431806f91ac072037806e }; 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); @@ -6821,7 +6871,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); @@ -6868,7 +6918,7 @@ index ae46341ba71c7f6df7c607bd852338cdb7f83fe1..b318c0771192344a6891c1f097cb0b93 +} // namespace WebCore +#endif diff --git a/Source/WebCore/platform/PlatformScreen.h b/Source/WebCore/platform/PlatformScreen.h -index 6c64c7040eb190c3d67380070e884a8230029c26..d0f8341c538cbc2323ac0074a5ef3226d00a5fd6 100644 +index f10a43820dca4bdeafe67b330243a698f3334f5a..a8e3a9b96cd8b3b36174da42abc0ccac6cb5b17c 100644 --- a/Source/WebCore/platform/PlatformScreen.h +++ b/Source/WebCore/platform/PlatformScreen.h @@ -151,13 +151,18 @@ WEBCORE_EXPORT float screenScaleFactor(UIScreen * = nullptr); @@ -6920,7 +6970,7 @@ index 34715d27b529750fc866db87cd330b5184286771..3eefa218af075f76d98012cdeae7e4b3 // 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 c14a1b2e20cfc1dd15e483bd662ef40484da8c26..74b06820837d68b23e7a0eb5540b18688534ef09 100644 +index 616a44dba554ac1429c074f1fe9509a3f544ef1e..73c9b605221dbd036713afa9d1935902444833b3 100644 --- a/Source/WebCore/platform/Skia.cmake +++ b/Source/WebCore/platform/Skia.cmake @@ -13,6 +13,7 @@ list(APPEND WebCore_PRIVATE_FRAMEWORK_HEADERS @@ -6928,14 +6978,14 @@ index c14a1b2e20cfc1dd15e483bd662ef40484da8c26..74b06820837d68b23e7a0eb5540b1868 platform/graphics/skia/GraphicsContextSkia.h platform/graphics/skia/ImageBufferSkiaBackend.h + platform/graphics/skia/ImageBufferUtilitiesSkia.h - platform/graphics/skia/SkiaAcceleratedBufferPool.h platform/graphics/skia/SkiaHarfBuzzFont.h platform/graphics/skia/SkiaHarfBuzzFontCache.h + ) diff --git a/Source/WebCore/platform/adwaita/ScrollbarThemeAdwaita.cpp b/Source/WebCore/platform/adwaita/ScrollbarThemeAdwaita.cpp -index e280025043b3c03c3974289e62ef7cc88ebfa2c7..077a4ab4aa5b688937ed4d5018745aa6f6af7442 100644 +index 8f36dda49adafd4a542e24e3c4dd33d42be00d27..953b6f88f8deb597d2179a8cec7b717b7cf6dc5a 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 { @@ -7053,7 +7103,7 @@ index 5b659c763b9754b025a63f89522954cc39915b9a..448b50a2b131361a75d3f816cdcbb6a1 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 6f43c048cd8354c97097c8365b772b92a429b670..7bccf4f7921fb3b0848781252cd69b4bd6959287 100644 +index 3d0ab7eceaf2a6321685bc362eb9b25600fd98fd..2d7e9a399bf2e9dc3f373d5fa3db99fa0908bd9d 100644 --- a/Source/WebCore/platform/graphics/filters/software/FEComponentTransferSoftwareApplier.h +++ b/Source/WebCore/platform/graphics/filters/software/FEComponentTransferSoftwareApplier.h @@ -23,6 +23,7 @@ @@ -7061,22 +7111,9 @@ index 6f43c048cd8354c97097c8365b772b92a429b670..7bccf4f7921fb3b0848781252cd69b4b #include "FilterEffectApplier.h" +#include "PixelBuffer.h" + #include namespace WebCore { - -diff --git a/Source/WebCore/platform/graphics/gstreamer/GStreamerRegistryScanner.cpp b/Source/WebCore/platform/graphics/gstreamer/GStreamerRegistryScanner.cpp -index 6f4b01b50a2278bfd0d0a072f5d1b6b367128706..f258f5f3e769c8c3a78a7801ebde09234c0298f7 100644 ---- a/Source/WebCore/platform/graphics/gstreamer/GStreamerRegistryScanner.cpp -+++ b/Source/WebCore/platform/graphics/gstreamer/GStreamerRegistryScanner.cpp -@@ -860,7 +860,7 @@ MediaPlayerEnums::SupportsType GStreamerRegistryScanner::isContentTypeSupported( - return SupportsType::IsNotSupported; - } - #else -- if (!factories.hasElementForMediaType(ElementFactories::Type::Decryptor, "application/x-webm-enc")) -+ if (!factories.hasElementForMediaType(ElementFactories::Type::Decryptor, "application/x-webm-enc"_s)) - return SupportsType::IsNotSupported; - #endif // GST_CHECK_VERSION(1, 22, 0) - } diff --git a/Source/WebCore/platform/graphics/win/ComplexTextControllerUniscribe.cpp b/Source/WebCore/platform/graphics/win/ComplexTextControllerUniscribe.cpp index eb9710f7d61121f2414c8aa6734dc27653e292bb..9c0c7b350a6140681242ce36a180d6866e3e0fc2 100644 --- a/Source/WebCore/platform/graphics/win/ComplexTextControllerUniscribe.cpp @@ -7387,10 +7424,10 @@ index 979ec06ecd698b60066dc6775bf1b647624baa56..14d06fdd5b7b7df2a1942ed975cebf11 { switch (val) { diff --git a/Source/WebCore/platform/gtk/PlatformScreenGtk.cpp b/Source/WebCore/platform/gtk/PlatformScreenGtk.cpp -index a8fdb7d39e145778b27fdde0d407b7c01b61e12a..da36507b9d77bafd68a342affb4dc20512c6d7a2 100644 +index 9ea18000578dd47295b2ce4da7fa00b39b5cac81..41bdd2d741b469acb134220df7e0c10209bd9f62 100644 --- a/Source/WebCore/platform/gtk/PlatformScreenGtk.cpp +++ b/Source/WebCore/platform/gtk/PlatformScreenGtk.cpp -@@ -134,7 +134,7 @@ bool screenSupportsExtendedColor(Widget*) +@@ -132,7 +132,7 @@ bool screenSupportsExtendedColor(Widget*) } #if ENABLE(TOUCH_EVENTS) @@ -7399,7 +7436,7 @@ index a8fdb7d39e145778b27fdde0d407b7c01b61e12a..da36507b9d77bafd68a342affb4dc205 { auto* display = gdk_display_get_default(); if (!display) -@@ -144,7 +144,7 @@ bool screenHasTouchDevice() +@@ -142,7 +142,7 @@ bool screenHasTouchDevice() return seat ? gdk_seat_get_capabilities(seat) & GDK_SEAT_CAPABILITY_TOUCH : true; } @@ -7408,6 +7445,19 @@ index a8fdb7d39e145778b27fdde0d407b7c01b61e12a..da36507b9d77bafd68a342affb4dc205 { auto* display = gdk_display_get_default(); if (!display) +diff --git a/Source/WebCore/platform/gtk/ScrollbarThemeGtk.cpp b/Source/WebCore/platform/gtk/ScrollbarThemeGtk.cpp +index c65514727c0e915e06c460cba7530f9ae2d8e0e6..7836b21f81e77b869099f78ad6bdd0788df7eb70 100644 +--- a/Source/WebCore/platform/gtk/ScrollbarThemeGtk.cpp ++++ b/Source/WebCore/platform/gtk/ScrollbarThemeGtk.cpp +@@ -39,6 +39,8 @@ + + namespace WebCore { + ++ScrollbarThemeGtk::~ScrollbarThemeGtk() = default; ++ + ScrollbarTheme& ScrollbarTheme::nativeTheme() + { + static ScrollbarThemeGtk theme; diff --git a/Source/WebCore/platform/libwpe/PasteboardLibWPE.cpp b/Source/WebCore/platform/libwpe/PasteboardLibWPE.cpp index ae439e30f1fb239d18e1164e8896dfb272c75673..4cf29eda13d1f2dc2f03750c0ef8985b17de7f50 100644 --- a/Source/WebCore/platform/libwpe/PasteboardLibWPE.cpp @@ -8013,10 +8063,10 @@ index 65679251a5c66afcf60ed4d4267169eefed745f5..2cb9dc1f0e777fd172e52f5a6c8f4d69 m_commonHeaders.append(CommonHeader { name, value }); } diff --git a/Source/WebCore/platform/network/NetworkStorageSession.h b/Source/WebCore/platform/network/NetworkStorageSession.h -index cf43da22a5f7674a1b24c4d39b492e0b8c318f3a..524e671cf6959fc48aefe4ec5a0611cb0cadf02b 100644 +index bf887012d2f391eb6169a9e53b40cb3c682e6d70..4954dfb7ed9ee711b126552dc9130f265059d270 100644 --- a/Source/WebCore/platform/network/NetworkStorageSession.h +++ b/Source/WebCore/platform/network/NetworkStorageSession.h -@@ -184,6 +184,8 @@ public: +@@ -185,6 +185,8 @@ public: NetworkingContext* context() const; #endif @@ -8026,10 +8076,10 @@ index cf43da22a5f7674a1b24c4d39b492e0b8c318f3a..524e671cf6959fc48aefe4ec5a0611cb 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 97e5f6f38b9c036e8fc2fe6f4d4108f458113816..1391de13e58d82fd0ab9bf66bbc922d5bffa0627 100644 +index 91cba6cadafd7c3739c2293b6146321b5ba0ea28..a1a52db245a2b480614901b650524872596a6c47 100644 --- a/Source/WebCore/platform/network/ResourceResponseBase.cpp +++ b/Source/WebCore/platform/network/ResourceResponseBase.cpp -@@ -75,6 +75,7 @@ ResourceResponseBase::ResourceResponseBase(std::optional d +@@ -78,6 +78,7 @@ ResourceResponseBase::ResourceResponseBase(std::optional d , m_httpStatusText(data ? data->httpStatusText : String { }) , m_httpVersion(data ? data->httpVersion : String { }) , m_httpHeaderFields(data ? data->httpHeaderFields : HTTPHeaderMap { }) @@ -8037,7 +8087,7 @@ index 97e5f6f38b9c036e8fc2fe6f4d4108f458113816..1391de13e58d82fd0ab9bf66bbc922d5 , m_networkLoadMetrics(data && data->networkLoadMetrics ? Box::create(*data->networkLoadMetrics) : Box { }) , m_certificateInfo(data ? data->certificateInfo : std::nullopt) , m_httpStatusCode(data ? data->httpStatusCode : 0) -@@ -893,6 +894,7 @@ std::optional ResourceResponseBase::getResponseData() cons +@@ -896,6 +897,7 @@ std::optional ResourceResponseBase::getResponseData() cons String { m_httpStatusText }, String { m_httpVersion }, HTTPHeaderMap { m_httpHeaderFields }, @@ -8045,7 +8095,7 @@ index 97e5f6f38b9c036e8fc2fe6f4d4108f458113816..1391de13e58d82fd0ab9bf66bbc922d5 m_networkLoadMetrics ? std::optional(*m_networkLoadMetrics) : std::nullopt, m_source, m_type, -@@ -966,6 +968,11 @@ std::optional Coder Coder httpStatusCode; decoder >> httpStatusCode; if (!httpStatusCode) -@@ -1020,6 +1027,7 @@ std::optional Coder Coder m_networkLoadMetrics; mutable std::optional m_certificateInfo; -@@ -291,7 +296,7 @@ struct ResourceResponseData { +@@ -292,7 +297,7 @@ struct ResourceResponseData { ResourceResponseData() = default; ResourceResponseData(ResourceResponseData&&) = default; ResourceResponseData& operator=(ResourceResponseData&&) = default; @@ -8090,7 +8140,7 @@ index 20b1437401c9560e22fd9e218d8193f09ac2aaaa..ff32706566fefa61030a9e7a1523987d : url(WTFMove(url)) , mimeType(WTFMove(mimeType)) , expectedContentLength(expectedContentLength) -@@ -300,6 +305,7 @@ struct ResourceResponseData { +@@ -301,6 +306,7 @@ struct ResourceResponseData { , httpStatusText(WTFMove(httpStatusText)) , httpVersion(WTFMove(httpVersion)) , httpHeaderFields(WTFMove(httpHeaderFields)) @@ -8098,7 +8148,7 @@ index 20b1437401c9560e22fd9e218d8193f09ac2aaaa..ff32706566fefa61030a9e7a1523987d , networkLoadMetrics(WTFMove(networkLoadMetrics)) , source(source) , type(type) -@@ -322,6 +328,7 @@ struct ResourceResponseData { +@@ -323,6 +329,7 @@ struct ResourceResponseData { String httpStatusText; String httpVersion; HTTPHeaderMap httpHeaderFields; @@ -8107,10 +8157,10 @@ index 20b1437401c9560e22fd9e218d8193f09ac2aaaa..ff32706566fefa61030a9e7a1523987d 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 4ea947b9e847bed7abe42519481f563fc064b385..7beb54c1196128f67ef42331c89cb28ff9c8d450 100644 +index cac3c4ba93f274637a93e0a20a4a0828c9c1bb46..e9f310f158015ed7a14ef2eb06d1d4d3f96d067d 100644 --- a/Source/WebCore/platform/network/cocoa/NetworkStorageSessionCocoa.mm +++ b/Source/WebCore/platform/network/cocoa/NetworkStorageSessionCocoa.mm -@@ -491,6 +491,22 @@ bool NetworkStorageSession::setCookieFromDOM(const URL& firstParty, const SameSi +@@ -493,6 +493,22 @@ bool NetworkStorageSession::setCookieFromDOM(const URL& firstParty, const SameSi return false; } @@ -8134,10 +8184,10 @@ index 4ea947b9e847bed7abe42519481f563fc064b385..7beb54c1196128f67ef42331c89cb28f { 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: @@ -8147,19 +8197,19 @@ index 7788bfea8bb631c51fe858b29cc33e43347cbfab..ad9f347ce55cbea4374a45d3c65f8e11 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 +index d07f26d77447d05fa2b086d04e6aa105c3d6b4b1..52b09365fff63fa4099320d0eebc1d498e0c068e 100644 --- a/Source/WebCore/platform/network/curl/CurlStream.cpp +++ b/Source/WebCore/platform/network/curl/CurlStream.cpp -@@ -34,7 +34,7 @@ +@@ -37,7 +37,7 @@ namespace WebCore { - namespace WebCore { + WTF_MAKE_TZONE_ALLOCATED_IMPL(CurlStream); -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 +@@ -52,6 +52,9 @@ CurlStream::CurlStream(CurlStreamScheduler& scheduler, CurlStreamID streamID, UR m_curlHandle->disableServerTrustEvaluation(); m_curlHandle->enableConnectionOnly(); @@ -8170,10 +8220,10 @@ index 4b01a35fa4bff5e1ccc7fed23940345c9c6fbd15..5e2c2f7f92c5edf4b075670a2a02da65 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 +index 96c3d2c216d522cf5c8b53b06a87eb849d159618..b595a1cfe961ad98364d8893014ab5c2fc1007f5 100644 --- a/Source/WebCore/platform/network/curl/CurlStream.h +++ b/Source/WebCore/platform/network/curl/CurlStream.h -@@ -55,12 +55,12 @@ public: +@@ -56,12 +56,12 @@ public: virtual void didFail(CurlStreamID, CURLcode, CertificateInfo&&) = 0; }; @@ -8190,10 +8240,10 @@ index bc9c731a0e69c4923bb8b4bdda088c2be30b3f1c..2088662fb2ce29b7ed843586460630fb 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 +index 83c4ca7871e536077f2d0a1a8ba6e2b4adb584da..12a49c124283fbe50ac17ecaa0c1e6fee32741d6 100644 --- a/Source/WebCore/platform/network/curl/CurlStreamScheduler.cpp +++ b/Source/WebCore/platform/network/curl/CurlStreamScheduler.cpp -@@ -40,7 +40,7 @@ CurlStreamScheduler::~CurlStreamScheduler() +@@ -43,7 +43,7 @@ CurlStreamScheduler::~CurlStreamScheduler() ASSERT(isMainThread()); } @@ -8202,7 +8252,7 @@ index 048cd352dd9b4cc952337308337a4bd9c31f00f1..de54623b601aea9fbd6a88f5c646b205 { ASSERT(isMainThread()); -@@ -51,8 +51,8 @@ CurlStreamID CurlStreamScheduler::createStream(const URL& url, CurlStream::Clien +@@ -54,8 +54,8 @@ CurlStreamID CurlStreamScheduler::createStream(const URL& url, CurlStream::Clien auto streamID = m_currentStreamID; m_clientList.add(streamID, &client); @@ -8214,10 +8264,10 @@ index 048cd352dd9b4cc952337308337a4bd9c31f00f1..de54623b601aea9fbd6a88f5c646b205 return streamID; diff --git a/Source/WebCore/platform/network/curl/CurlStreamScheduler.h b/Source/WebCore/platform/network/curl/CurlStreamScheduler.h -index 41af70e9bddcb507bf7e57841e4051bc99a78410..87899280f985ca5f0cb135fb9ba53cde822a3b84 100644 +index 2d7a77d759aaea9a541030af5e6015a8ed9c97a4..a0c947d325c984045dbbdf2580d19a32eea86ada 100644 --- a/Source/WebCore/platform/network/curl/CurlStreamScheduler.h +++ b/Source/WebCore/platform/network/curl/CurlStreamScheduler.h -@@ -38,7 +38,7 @@ public: +@@ -39,7 +39,7 @@ public: CurlStreamScheduler(); virtual ~CurlStreamScheduler(); @@ -8874,7 +8924,7 @@ index 4613cfc6af155593459f8af9c2bf4211a01383b9..209542305a8454da2f80691ab7759b0f AncestorSubgridIterator::AncestorSubgridIterator(SingleThreadWeakPtr firstAncestorSubgrid, GridTrackSizingDirection direction) : m_firstAncestorSubgrid(firstAncestorSubgrid) diff --git a/Source/WebCore/rendering/RenderTextControl.cpp b/Source/WebCore/rendering/RenderTextControl.cpp -index 5d81c5942027e02222430036013e2a066a6bae06..0246502c570719cc9c9362726b9bc03ded002a0b 100644 +index 02afb718cfae6a4314ab704fbe6a70d88a530312..ed32870de0571317a6527d89a14a6a51b7acfd33 100644 --- a/Source/WebCore/rendering/RenderTextControl.cpp +++ b/Source/WebCore/rendering/RenderTextControl.cpp @@ -225,13 +225,13 @@ void RenderTextControl::layoutExcludedChildren(bool relayoutChildren) @@ -8893,7 +8943,7 @@ index 5d81c5942027e02222430036013e2a066a6bae06..0246502c570719cc9c9362726b9bc03d { auto innerText = innerTextElement(); diff --git a/Source/WebCore/rendering/RenderTextControl.h b/Source/WebCore/rendering/RenderTextControl.h -index 0c3b0f009ba9fca604f9bea904aae15142ee600e..b55788795cb550764d3de2e4dd0368773a14f290 100644 +index b55e0d2d78beb62a7efa08cf7d47e8a9ebad362d..352d12a72fa72479d70164ea130648d9c26ff05a 100644 --- a/Source/WebCore/rendering/RenderTextControl.h +++ b/Source/WebCore/rendering/RenderTextControl.h @@ -37,9 +37,9 @@ public: @@ -8908,10 +8958,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 5b64d59511778572142eae5e48b16cfaa1040d49..7082cd677870f4c359130bc065bdee097c82feda 100644 --- a/Source/WebCore/workers/WorkerConsoleClient.cpp +++ b/Source/WebCore/workers/WorkerConsoleClient.cpp -@@ -101,4 +101,6 @@ void WorkerConsoleClient::recordEnd(JSC::JSGlobalObject*, Ref&& +@@ -104,4 +104,6 @@ void WorkerConsoleClient::recordEnd(JSC::JSGlobalObject*, Ref&& // FIXME: Web Inspector: support console screenshots in a Worker void WorkerConsoleClient::screenshot(JSC::JSGlobalObject*, Ref&&) { } @@ -8919,10 +8969,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; @@ -8930,11 +8980,25 @@ index 1d8488e0d36288e09cd5662bd7f770ade95dfee3..dee07f87b47d62d4ef8ede45824bdb2f WorkerOrWorkletGlobalScope& m_globalScope; }; +diff --git a/Source/WebKit/InspectorGResources.cmake b/Source/WebKit/InspectorGResources.cmake +index b9c1f0ad55ef8ddf18e0314a6f4ad8b490e5b214..a1e3b60f8e74988b072eb8cbca201fd84a45b2bc 100644 +--- a/Source/WebKit/InspectorGResources.cmake ++++ b/Source/WebKit/InspectorGResources.cmake +@@ -13,4 +13,9 @@ macro(WEBKIT_BUILD_INSPECTOR_GRESOURCES _derived_sources_dir _output_file) + SOURCE_XML ${_derived_sources_dir}/InspectorGResourceBundle.xml + RESOURCE_DIRS ${_derived_sources_dir}/InspectorResources/WebInspectorUI + ) ++ ++ add_custom_target(${_output_file} ++ ALL ++ DEPENDS ${_derived_sources_dir}/${_output_file} ++ ) + endmacro() diff --git a/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp b/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp -index 6a87d4478288777a9a08fc92669841ea0d19c936..7fd9ee105769519f212d4e4d2480665ab437e274 100644 +index 298c215460d4c52d8d232e960bec52c2d05a9071..9c903e398c05e451df9131eae1d9a828cf2e6088 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 @@ -8943,7 +9007,7 @@ index 6a87d4478288777a9a08fc92669841ea0d19c936..7fd9ee105769519f212d4e4d2480665a #endif #if ENABLE(APPLE_PAY_REMOTE_UI) -@@ -1098,6 +1100,14 @@ void NetworkConnectionToWebProcess::clearPageSpecificData(PageIdentifier pageID) +@@ -1109,6 +1111,14 @@ void NetworkConnectionToWebProcess::clearPageSpecificData(PageIdentifier pageID) storageSession->clearPageSpecificDataForResourceLoadStatistics(pageID); } @@ -8957,12 +9021,12 @@ index 6a87d4478288777a9a08fc92669841ea0d19c936..7fd9ee105769519f212d4e4d2480665a + 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 d5d5921514e7f3abf30e67352d2f20ca32e3c175..e684f945a3057587f9ec2c03ecf062dca48a2a1a 100644 +index 99a6472171acdf8ebffa29a86d69f47d8ea55d64..a95eb97d93656e78bad1a1d3450d3563886fc485 100644 --- a/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.h +++ b/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.h -@@ -347,6 +347,8 @@ private: +@@ -366,6 +366,8 @@ private: void clearPageSpecificData(WebCore::PageIdentifier); @@ -8972,10 +9036,10 @@ index d5d5921514e7f3abf30e67352d2f20ca32e3c175..e684f945a3057587f9ec2c03ecf062dc void logUserInteraction(RegistrableDomain&&); diff --git a/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.messages.in b/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.messages.in -index e3a5c58cd28d82e62aa08b4800fb559d78a8af39..c9db082407eaa4fc1b69c5ae0e211606ed09c2c3 100644 +index 9377d0c9381ec40342dc8bbe60e80781116b2d3c..b29b70264d0b5e9409e8467db75bc0a5a3febc5a 100644 --- a/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.messages.in +++ b/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.messages.in -@@ -74,6 +74,8 @@ messages -> NetworkConnectionToWebProcess LegacyReceiver { +@@ -75,6 +75,8 @@ messages -> NetworkConnectionToWebProcess WantsDispatchMessage { ClearPageSpecificData(WebCore::PageIdentifier pageID); @@ -8985,10 +9049,10 @@ index e3a5c58cd28d82e62aa08b4800fb559d78a8af39..c9db082407eaa4fc1b69c5ae0e211606 LogUserInteraction(WebCore::RegistrableDomain domain) ResourceLoadStatisticsUpdated(Vector statistics) -> () diff --git a/Source/WebKit/NetworkProcess/NetworkProcess.cpp b/Source/WebKit/NetworkProcess/NetworkProcess.cpp -index 6a5370ac4579a2f3c4b7b1d7c8a1d4df510e8892..8c444c89546460f3a5c1c5ff92427ff8f1af681f 100644 +index 12b9f1488877b94e520f83191cd15b09836e9666..f65093ab8653a2f5c05a1c5a69f0f2b83d679e07 100644 --- a/Source/WebKit/NetworkProcess/NetworkProcess.cpp +++ b/Source/WebKit/NetworkProcess/NetworkProcess.cpp -@@ -666,6 +666,12 @@ void NetworkProcess::registrableDomainsExemptFromWebsiteDataDeletion(PAL::Sessio +@@ -638,6 +638,12 @@ void NetworkProcess::registrableDomainsExemptFromWebsiteDataDeletion(PAL::Sessio completionHandler({ }); } @@ -9002,7 +9066,7 @@ index 6a5370ac4579a2f3c4b7b1d7c8a1d4df510e8892..8c444c89546460f3a5c1c5ff92427ff8 { if (auto* session = networkSession(sessionID)) { diff --git a/Source/WebKit/NetworkProcess/NetworkProcess.h b/Source/WebKit/NetworkProcess/NetworkProcess.h -index 2b4e411ca19004bd4f18949f3196dc06c1995769..404b2d5d1ac5ce0a63a776ae4fc5022604c60a4e 100644 +index dbc90242cd84de5ef39b404e0b9262fcdf7cd371..82c91b9edb72f4f48676d0e458448981e346917a 100644 --- a/Source/WebKit/NetworkProcess/NetworkProcess.h +++ b/Source/WebKit/NetworkProcess/NetworkProcess.h @@ -33,6 +33,7 @@ @@ -9010,10 +9074,10 @@ index 2b4e411ca19004bd4f18949f3196dc06c1995769..404b2d5d1ac5ce0a63a776ae4fc50226 #include "NetworkContentRuleListManager.h" #include "QuotaIncreaseRequestIdentifier.h" +#include "StorageNamespaceIdentifier.h" + #include "UseDownloadPlaceholder.h" #include "WebPageProxyIdentifier.h" #include "WebResourceLoadStatisticsStore.h" - #include "WebsiteData.h" -@@ -82,6 +83,7 @@ class SessionID; +@@ -84,6 +85,7 @@ class SessionID; namespace WebCore { class CertificateInfo; @@ -9021,7 +9085,7 @@ index 2b4e411ca19004bd4f18949f3196dc06c1995769..404b2d5d1ac5ce0a63a776ae4fc50226 class CurlProxySettings; class ProtectionSpace; class NetworkStorageSession; -@@ -212,6 +214,9 @@ public: +@@ -220,6 +222,9 @@ public: void registrableDomainsWithLastAccessedTime(PAL::SessionID, CompletionHandler>)>&&); void registrableDomainsExemptFromWebsiteDataDeletion(PAL::SessionID, CompletionHandler)>&&); @@ -9030,12 +9094,12 @@ index 2b4e411ca19004bd4f18949f3196dc06c1995769..404b2d5d1ac5ce0a63a776ae4fc50226 + void clearPrevalentResource(PAL::SessionID, RegistrableDomain&&, CompletionHandler&&); void clearUserInteraction(PAL::SessionID, RegistrableDomain&&, CompletionHandler&&); - void deleteAndRestrictWebsiteDataForRegistrableDomains(PAL::SessionID, OptionSet, RegistrableDomainsToDeleteOrRestrictWebsiteDataFor&&, bool shouldNotifyPage, CompletionHandler&&)>&&); + void deleteAndRestrictWebsiteDataForRegistrableDomains(PAL::SessionID, OptionSet, RegistrableDomainsToDeleteOrRestrictWebsiteDataFor&&, CompletionHandler&&)>&&); diff --git a/Source/WebKit/NetworkProcess/NetworkProcess.messages.in b/Source/WebKit/NetworkProcess/NetworkProcess.messages.in -index 6178b4ee6d042a8e69f895ae56ca7e5393766b3d..1aa28797177a714faeb9a747388f02d1334906f6 100644 +index aa95d1cc6e90fd24d3dad3ff1b8052de66fc23f2..b57b6d72cd1d9bf34dc347750e2d2fb9d0111389 100644 --- a/Source/WebKit/NetworkProcess/NetworkProcess.messages.in +++ b/Source/WebKit/NetworkProcess/NetworkProcess.messages.in -@@ -83,6 +83,8 @@ messages -> NetworkProcess LegacyReceiver { +@@ -85,6 +85,8 @@ messages -> NetworkProcess : AuxiliaryProcess WantsAsyncDispatchMessage { SetInspectionForServiceWorkersAllowed(PAL::SessionID sessionID, bool inspectable) @@ -9045,10 +9109,10 @@ index 6178b4ee6d042a8e69f895ae56ca7e5393766b3d..1aa28797177a714faeb9a747388f02d1 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 8d86772e1b2b5e73e7f8c22042947ec4d7b610cc..9ec2764722032a5f0272757a33df1372218e8411 100644 +index 50b6499bcef54f3eeac6f3885e0e58783604100c..16b1fad0436fb307f524e3ae36e70043a3c6b168 100644 --- a/Source/WebKit/NetworkProcess/NetworkSession.h +++ b/Source/WebKit/NetworkProcess/NetworkSession.h -@@ -200,6 +200,9 @@ public: +@@ -202,6 +202,9 @@ public: void lowMemoryHandler(WTF::Critical); @@ -9058,7 +9122,7 @@ index 8d86772e1b2b5e73e7f8c22042947ec4d7b610cc..9ec2764722032a5f0272757a33df1372 void removeSoftUpdateLoader(ServiceWorkerSoftUpdateLoader* loader) { m_softUpdateLoaders.remove(loader); } void addNavigationPreloaderTask(ServiceWorkerFetchTask&); ServiceWorkerFetchTask* navigationPreloaderTaskFromFetchIdentifier(WebCore::FetchIdentifier); -@@ -311,6 +314,7 @@ protected: +@@ -317,6 +320,7 @@ protected: bool m_privateClickMeasurementDebugModeEnabled { false }; std::optional m_ephemeralMeasurement; bool m_isRunningEphemeralMeasurementTest { false }; @@ -9067,10 +9131,10 @@ index 8d86772e1b2b5e73e7f8c22042947ec4d7b610cc..9ec2764722032a5f0272757a33df1372 HashSet> m_keptAliveLoads; diff --git a/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm b/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm -index 78f92e5cf513a57060372a2448f291bbc90fdb7c..ea46b6ff9dc22fbb1df215c8e7e318a2dd6892ae 100644 +index 70ba7cd36661a2500783052f04076888f92c0eea..8b26ac70f0daa99ba8800e5785d54e31457f17af 100644 --- a/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm +++ b/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm -@@ -771,6 +771,8 @@ - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didRece +@@ -772,6 +772,8 @@ - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didRece if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { sessionCocoa->setClientAuditToken(challenge); @@ -9079,7 +9143,7 @@ index 78f92e5cf513a57060372a2448f291bbc90fdb7c..ea46b6ff9dc22fbb1df215c8e7e318a2 NSURLSessionTaskTransactionMetrics *metrics = task._incompleteTaskMetrics.transactionMetrics.lastObject; auto tlsVersion = (tls_protocol_version_t)metrics.negotiatedTLSProtocolVersion.unsignedShortValue; -@@ -1120,6 +1122,13 @@ - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)data +@@ -1121,6 +1123,13 @@ - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)data resourceResponse.setDeprecatedNetworkLoadMetrics(WebCore::copyTimingData(taskMetrics, networkDataTask->networkLoadMetrics())); @@ -9094,7 +9158,7 @@ index 78f92e5cf513a57060372a2448f291bbc90fdb7c..ea46b6ff9dc22fbb1df215c8e7e318a2 #if !LOG_DISABLED LOG(NetworkSession, "%llu didReceiveResponse completionHandler (%d)", taskIdentifier, policyAction); diff --git a/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.cpp b/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.cpp -index 7fea007b41d750e14b6807f894b3167d0e0963e1..fbcf34cc6d8291eab7768f5f33117e3dc5e9289e 100644 +index 63ca8f8066acb3be4b4dc8350bcc712e535bdd38..3dc3657ac2dc8ab89f56acb0615dd571091821b4 100644 --- a/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.cpp +++ b/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.cpp @@ -80,10 +80,18 @@ NetworkDataTaskCurl::NetworkDataTaskCurl(NetworkSession& session, NetworkDataTas @@ -9128,7 +9192,7 @@ index 7fea007b41d750e14b6807f894b3167d0e0963e1..fbcf34cc6d8291eab7768f5f33117e3d handleCookieHeaders(request.resourceRequest(), receivedResponse); -@@ -290,6 +299,36 @@ bool NetworkDataTaskCurl::shouldRedirectAsGET(const ResourceRequest& request, bo +@@ -294,6 +303,36 @@ bool NetworkDataTaskCurl::shouldRedirectAsGET(const ResourceRequest& request, bo return false; } @@ -9165,7 +9229,7 @@ index 7fea007b41d750e14b6807f894b3167d0e0963e1..fbcf34cc6d8291eab7768f5f33117e3d void NetworkDataTaskCurl::invokeDidReceiveResponse() { didReceiveResponse(ResourceResponse(m_response), NegotiatedLegacyTLS::No, PrivateRelayed::No, std::nullopt, [this, protectedThis = Ref { *this }](PolicyAction policyAction) { -@@ -320,6 +359,8 @@ void NetworkDataTaskCurl::invokeDidReceiveResponse() +@@ -324,6 +363,8 @@ void NetworkDataTaskCurl::invokeDidReceiveResponse() downloadPtr->didCreateDestination(m_pendingDownloadLocation); if (m_curlRequest) m_curlRequest->completeDidReceiveResponse(); @@ -9174,7 +9238,7 @@ index 7fea007b41d750e14b6807f894b3167d0e0963e1..fbcf34cc6d8291eab7768f5f33117e3d break; } default: -@@ -408,6 +449,8 @@ void NetworkDataTaskCurl::willPerformHTTPRedirection() +@@ -412,6 +453,8 @@ void NetworkDataTaskCurl::willPerformHTTPRedirection() m_curlRequest->setUserPass(m_initialCredential.user(), m_initialCredential.password()); m_curlRequest->setAuthenticationScheme(ProtectionSpace::AuthenticationScheme::HTTPBasic); } @@ -9184,7 +9248,7 @@ index 7fea007b41d750e14b6807f894b3167d0e0963e1..fbcf34cc6d8291eab7768f5f33117e3d 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 ce5e9ea8c6cf1966f0705732b6b37d1639847a3c..7a7a38947a8f3f20b0439bb84d00dcef6391f4a5 100644 +index 0f7c70e405d00416c9e5e58f9c56423a4cf3947c..b730722c5bdb3949bedc1a578089bb3ea2d4af67 100644 --- a/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.h +++ b/Source/WebKit/NetworkProcess/curl/NetworkDataTaskCurl.h @@ -28,6 +28,7 @@ @@ -9238,12 +9302,12 @@ index 486849ef6f550a0f3caab311abf5743c6d38e5af..afeaac63a18d9e71d3afead23b7da4fe 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 a5198bfa752746dd83dc2617606a27194afcd86f..3ca6b32e93bdaff2baae22170c84efe9bfe875d3 100644 +index 06a8233cbe44e7dfe1515498d511db39091f1acc..00818acd28155d526707967a01146d00199f4aa4 100644 --- a/Source/WebKit/NetworkProcess/curl/WebSocketTaskCurl.cpp +++ b/Source/WebKit/NetworkProcess/curl/WebSocketTaskCurl.cpp -@@ -37,11 +37,12 @@ - +@@ -39,11 +39,12 @@ namespace WebKit { + WTF_MAKE_TZONE_ALLOCATED_IMPL(WebSocketTask); -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) @@ -9255,16 +9319,16 @@ index a5198bfa752746dd83dc2617606a27194afcd86f..3ca6b32e93bdaff2baae22170c84efe9 , 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. -@@ -53,7 +54,7 @@ WebSocketTask::WebSocketTask(NetworkSocketChannel& channel, WebPageProxyIdentifi +@@ -55,7 +56,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)); + m_channel->didSendHandshakeRequest(WebCore::ResourceRequest(m_request)); } -@@ -258,7 +259,7 @@ void WebSocketTask::tryServerTrustEvaluation(WebCore::AuthenticationChallenge&& +@@ -260,7 +261,7 @@ void WebSocketTask::tryServerTrustEvaluation(WebCore::AuthenticationChallenge&& if (networkSession() && networkSession()->networkProcess().localhostAliasesForTesting().contains(m_request.url().host())) localhostAlias = WebCore::CurlStream::LocalhostAlias::Enable; @@ -9274,19 +9338,19 @@ index a5198bfa752746dd83dc2617606a27194afcd86f..3ca6b32e93bdaff2baae22170c84efe9 didFail(WTFMove(errorReason)); }); diff --git a/Source/WebKit/NetworkProcess/curl/WebSocketTaskCurl.h b/Source/WebKit/NetworkProcess/curl/WebSocketTaskCurl.h -index 41c99c4796ab2b624dffe35d34f9ea1bcf54f966..d83977c09adf271ddf7243a51300882e4f2bd0d9 100644 +index 0072cb40252b35ab54d8693562ee66a4c7ef6f45..2a44ad16131c80ee74bbb79a110ef16be9ab0765 100644 --- a/Source/WebKit/NetworkProcess/curl/WebSocketTaskCurl.h +++ b/Source/WebKit/NetworkProcess/curl/WebSocketTaskCurl.h -@@ -58,7 +58,7 @@ struct SessionSet; +@@ -59,7 +59,7 @@ struct SessionSet; class WebSocketTask : public CanMakeWeakPtr, public WebCore::CurlStream::Client { - WTF_MAKE_FAST_ALLOCATED; + WTF_MAKE_TZONE_ALLOCATED(WebSocketTask); 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&&); -@@ -111,6 +111,7 @@ private: +@@ -112,6 +112,7 @@ private: WebPageProxyIdentifier m_webProxyPageID; WebCore::ResourceRequest m_request; String m_protocol; @@ -9295,10 +9359,10 @@ index 41c99c4796ab2b624dffe35d34f9ea1bcf54f966..d83977c09adf271ddf7243a51300882e 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 a6d86f1388e8cae7c3939d1ecffb2c46eb5054c5..9e11224335211908fe8bf14edc4c22e9e4934582 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: @@ -9314,7 +9378,7 @@ 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 61d9c1d41fdc490faf800fb30d66eb4603950cbf..3dffffe74cd04b22e40ce0d94326760404fbbc6c 100644 +index 73b2b6b95706f735badf6235225a31926bfcca66..39cfe910a3cde500a41259be60ac2e6e32fdb82e 100644 --- a/Source/WebKit/NetworkProcess/soup/NetworkDataTaskSoup.cpp +++ b/Source/WebKit/NetworkProcess/soup/NetworkDataTaskSoup.cpp @@ -461,6 +461,8 @@ void NetworkDataTaskSoup::didSendRequest(GRefPtr&& inputStream) @@ -9336,10 +9400,10 @@ index 61d9c1d41fdc490faf800fb30d66eb4603950cbf..3dffffe74cd04b22e40ce0d943267604 if (!error) return true; diff --git a/Source/WebKit/NetworkProcess/soup/NetworkSessionSoup.cpp b/Source/WebKit/NetworkProcess/soup/NetworkSessionSoup.cpp -index 60e79ff683e280591d686468c42decf1ac109ed2..99707bc16644b88ff24a192029f3866e0a80e827 100644 +index 599c405513ee38c74da12c01dafc23c6ece86aa0..5af7dc9306d211a5cff1736013716b08933e2278 100644 --- a/Source/WebKit/NetworkProcess/soup/NetworkSessionSoup.cpp +++ b/Source/WebKit/NetworkProcess/soup/NetworkSessionSoup.cpp -@@ -97,6 +97,11 @@ void NetworkSessionSoup::clearCredentials(WallTime) +@@ -100,6 +100,11 @@ void NetworkSessionSoup::clearCredentials(WallTime) #endif } @@ -9351,7 +9415,7 @@ index 60e79ff683e280591d686468c42decf1ac109ed2..99707bc16644b88ff24a192029f3866e #if USE(SOUP2) static gboolean webSocketAcceptCertificateCallback(GTlsConnection* connection, GTlsCertificate* certificate, GTlsCertificateFlags errors, NetworkSessionSoup* session) { -@@ -127,12 +132,16 @@ std::unique_ptr NetworkSessionSoup::createWebSocketTask(WebPagePr +@@ -130,12 +135,16 @@ std::unique_ptr NetworkSessionSoup::createWebSocketTask(WebPagePr #if USE(SOUP2) g_signal_connect(soupMessage.get(), "network-event", G_CALLBACK(webSocketMessageNetworkEventCallback), this); #else @@ -9374,11 +9438,23 @@ index 60e79ff683e280591d686468c42decf1ac109ed2..99707bc16644b88ff24a192029f3866e #endif } +diff --git a/Source/WebKit/Platform/IPC/MessageSender.h b/Source/WebKit/Platform/IPC/MessageSender.h +index 214f41901fa6648d281da7e1129ae888f0b2c510..30081fb3bd783ef8cbfee1dcea4ffe5f8786eedc 100644 +--- a/Source/WebKit/Platform/IPC/MessageSender.h ++++ b/Source/WebKit/Platform/IPC/MessageSender.h +@@ -27,6 +27,7 @@ + + #include + #include ++#include + + namespace IPC { + diff --git a/Source/WebKit/PlatformGTK.cmake b/Source/WebKit/PlatformGTK.cmake -index a509f56343f94f1bc30658ec9928ec1796a5a9b8..e2fcf6d35053f6982975d238f17b76f49e1bacdc 100644 +index efbb4cdb0f382c1a917062c63727036e00723be1..8a9e53def5166e9a6afa983a1ed84634bb092ec0 100644 --- a/Source/WebKit/PlatformGTK.cmake +++ b/Source/WebKit/PlatformGTK.cmake -@@ -324,6 +324,9 @@ list(APPEND WebKit_SYSTEM_INCLUDE_DIRECTORIES +@@ -329,6 +329,9 @@ list(APPEND WebKit_SYSTEM_INCLUDE_DIRECTORIES ${GSTREAMER_PBUTILS_INCLUDE_DIRS} ${GTK_INCLUDE_DIRS} ${LIBSOUP_INCLUDE_DIRS} @@ -9388,7 +9464,7 @@ index a509f56343f94f1bc30658ec9928ec1796a5a9b8..e2fcf6d35053f6982975d238f17b76f4 ) list(APPEND WebKit_INTERFACE_INCLUDE_DIRECTORIES -@@ -354,6 +357,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" @@ -9398,7 +9474,7 @@ index a509f56343f94f1bc30658ec9928ec1796a5a9b8..e2fcf6d35053f6982975d238f17b76f4 ) endif () -@@ -405,6 +411,12 @@ else () +@@ -410,6 +416,12 @@ else () set(WebKitGTK_ENUM_HEADER_TEMPLATE ${WEBKIT_DIR}/UIProcess/API/gtk/WebKitEnumTypesGtk3.h.in) endif () @@ -9412,10 +9488,10 @@ index a509f56343f94f1bc30658ec9928ec1796a5a9b8..e2fcf6d35053f6982975d238f17b76f4 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 aa5c183a4c0946270713840071cf0167533158f6..637365fbb7d91f99ba1478188291bedff9b1cc2b 100644 +index e1d7d2a9e635c753459db079170ef5385dc1a637..28fbd58183e126f73a9f3ccbaa682ae3593f1e79 100644 --- a/Source/WebKit/PlatformWPE.cmake +++ b/Source/WebKit/PlatformWPE.cmake -@@ -111,6 +111,8 @@ list(APPEND WebKit_SERIALIZATION_IN_FILES +@@ -117,6 +117,8 @@ list(APPEND WebKit_SERIALIZATION_IN_FILES Shared/glib/UserMessage.serialization.in Shared/soup/WebCoreArgumentCodersSoup.serialization.in @@ -9424,7 +9500,7 @@ index aa5c183a4c0946270713840071cf0167533158f6..637365fbb7d91f99ba1478188291bedf ) list(APPEND WebKit_DERIVED_SOURCES -@@ -215,6 +217,7 @@ set(WPE_API_HEADER_TEMPLATES +@@ -221,6 +223,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 @@ -9432,7 +9508,7 @@ index aa5c183a4c0946270713840071cf0167533158f6..637365fbb7d91f99ba1478188291bedf ) if (ENABLE_2022_GLIB_API) -@@ -426,7 +429,16 @@ list(APPEND WebKit_SYSTEM_INCLUDE_DIRECTORIES +@@ -432,7 +435,16 @@ list(APPEND WebKit_SYSTEM_INCLUDE_DIRECTORIES ${GIO_UNIX_INCLUDE_DIRS} ${GLIB_INCLUDE_DIRS} ${LIBSOUP_INCLUDE_DIRS} @@ -9570,10 +9646,10 @@ index a9aa21f5589dec453db1713c8846e0d2e687f552..9b94469d078d92e4b9e0c8149122b19a #include #include diff --git a/Source/WebKit/Shared/AuxiliaryProcess.h b/Source/WebKit/Shared/AuxiliaryProcess.h -index bc4f258d0970d21655a311ba72932296440111f8..21bf2a8dc680ead511ddb17a9a7ae891c835ee30 100644 +index 33eb250f82068c481176be8e1ba6f9bc935f544a..519be7021eb53e3a6f18953ff004218e13f0819c 100644 --- a/Source/WebKit/Shared/AuxiliaryProcess.h +++ b/Source/WebKit/Shared/AuxiliaryProcess.h -@@ -210,6 +210,11 @@ struct AuxiliaryProcessInitializationParameters { +@@ -214,6 +214,11 @@ struct AuxiliaryProcessInitializationParameters { #if PLATFORM(COCOA) SDKAlignedBehaviors clientSDKAlignedBehaviors; #endif @@ -9598,7 +9674,7 @@ index b09b17a5bff38e3ba8d6bb53da9ef09d229bdb61..46aa1caa93402711a08f5980387a957f 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 @@ @@ -9609,7 +9685,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&); @@ -9638,6 +9714,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); @@ -9700,10 +9777,10 @@ index ea1eb9f00feaaecf73bdddc37c904e88f43bfa85..8a631e5293a11abd650958baad4e9678 #endif }; diff --git a/Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in b/Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in -index 7261dea8449a1c8f477aa2be76c5a2f887bfc330..9d87c926c337a59b3acdb952936fe466db42622a 100644 +index 13f2e0158846e32155fc0ee9e9639f66d96e0f3f..3e8be3a130075a67c07fa192e788b24dab997480 100644 --- a/Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in +++ b/Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in -@@ -2699,6 +2699,9 @@ class WebCore::AuthenticationChallenge { +@@ -2752,6 +2752,9 @@ class WebCore::AuthenticationChallenge { class WebCore::DragData { #if PLATFORM(COCOA) String pasteboardName(); @@ -9713,7 +9790,7 @@ index 7261dea8449a1c8f477aa2be76c5a2f887bfc330..9d87c926c337a59b3acdb952936fe466 #endif WebCore::IntPoint clientPosition(); WebCore::IntPoint globalPosition(); -@@ -3261,6 +3264,7 @@ enum class WebCore::WasPrivateRelayed : bool; +@@ -3311,6 +3314,7 @@ enum class WebCore::WasPrivateRelayed : bool; String httpStatusText; String httpVersion; WebCore::HTTPHeaderMap httpHeaderFields; @@ -9839,10 +9916,10 @@ index fd4722dd38df74f259d8add02025549022a0a205..e1c33f6d766707170935b3e77e81098c 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 80d76574435e35abf76eb640da5f93023dda9c0b..f167e8969328160136ce33368ce1fa746ee852df 100644 +index a75ea6985662cfb232a4910189191759a20f34b9..6e5fc673484ce3ca9750bb8a7dd56d6f704b7b66 100644 --- a/Source/WebKit/Shared/WebPageCreationParameters.h +++ b/Source/WebKit/Shared/WebPageCreationParameters.h -@@ -303,6 +303,8 @@ struct WebPageCreationParameters { +@@ -306,6 +306,8 @@ struct WebPageCreationParameters { bool httpsUpgradeEnabled { true }; @@ -9852,10 +9929,10 @@ index 80d76574435e35abf76eb640da5f93023dda9c0b..f167e8969328160136ce33368ce1fa74 bool allowsDeprecatedSynchronousXMLHttpRequestDuringUnload { false }; #endif diff --git a/Source/WebKit/Shared/WebPageCreationParameters.serialization.in b/Source/WebKit/Shared/WebPageCreationParameters.serialization.in -index 7ff97d01848ce5c63e2ab89433083a91d4ac67ec..9c4af6d477d66294e46b05d673924c4956970d3a 100644 +index 2c3fc666d67714ab966a9b991ed2eccc45cf1ff1..929ee387024355c40333ae7e12d7155688299e32 100644 --- a/Source/WebKit/Shared/WebPageCreationParameters.serialization.in +++ b/Source/WebKit/Shared/WebPageCreationParameters.serialization.in -@@ -227,6 +227,8 @@ enum class WebCore::UserInterfaceLayoutDirection : bool; +@@ -230,6 +230,8 @@ enum class WebCore::UserInterfaceLayoutDirection : bool; bool httpsUpgradeEnabled; @@ -9935,7 +10012,7 @@ index 0000000000000000000000000000000000000000..f4f09d171ebf9774b3f8744751d220d3 + bool canSmartReplace() +} diff --git a/Source/WebKit/Shared/unix/AuxiliaryProcessMain.cpp b/Source/WebKit/Shared/unix/AuxiliaryProcessMain.cpp -index f5de9fcc55cb68a75dd8cf748d3d5b3e27fd9555..04a29727614a02d04eb9a0eb3779d28d60bdef12 100644 +index ce942ed6ce6bfda002e94c81633d56b2464c129d..0db4d7e6ab7f584b18d923f1ece6b498be1d463d 100644 --- a/Source/WebKit/Shared/unix/AuxiliaryProcessMain.cpp +++ b/Source/WebKit/Shared/unix/AuxiliaryProcessMain.cpp @@ -44,6 +44,15 @@ @@ -9966,13 +10043,13 @@ index f5de9fcc55cb68a75dd8cf748d3d5b3e27fd9555..04a29727614a02d04eb9a0eb3779d28d } diff --git a/Source/WebKit/Shared/win/AuxiliaryProcessMainWin.cpp b/Source/WebKit/Shared/win/AuxiliaryProcessMainWin.cpp -index 9edb5fbcd103cd8d1b224dfd60ac88aabe9626d2..9ed392ae3809f8bda92a2765ffadc643f23fe856 100644 +index 7fd5cbb0fec93a2f305a6d41f14946ec6dae778e..4332ec81e0d24928000483b3e554e385ee3b9ff1 100644 --- a/Source/WebKit/Shared/win/AuxiliaryProcessMainWin.cpp +++ b/Source/WebKit/Shared/win/AuxiliaryProcessMainWin.cpp @@ -41,6 +41,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)); + m_parameters.processIdentifier = LegacyNullableObjectIdentifier(parseIntegerAllowingTrailingJunk(StringView::fromLatin1(argv[++i])).value_or(0)); +// Playwright begin + else if (!strcmp(argv[i], "-enable-shared-array-buffer")) + m_parameters.shouldEnableSharedArrayBuffer = true; @@ -9994,10 +10071,10 @@ index 4d418e2bd7f970bc5bfebceb88adb172e5eb8540..8a58380d830f9a8aec3b4240d9c8cf7e #endif // ENABLE(TOUCH_EVENTS) diff --git a/Source/WebKit/Sources.txt b/Source/WebKit/Sources.txt -index f6bf1fc5c07af2398b8f4bd054f06ad8c87ef9db..19fa3d40595e204170d5302499f36f9d73a7f20b 100644 +index e1914a5393ae2e099fd9fc70d46cb4f1ad2a9aee..3918547200acc80c76a4c55136d28295c60a4217 100644 --- a/Source/WebKit/Sources.txt +++ b/Source/WebKit/Sources.txt -@@ -377,6 +377,7 @@ Shared/XR/XRDeviceProxy.cpp +@@ -385,6 +385,7 @@ Shared/XR/XRDeviceProxy.cpp UIProcess/AuxiliaryProcessProxy.cpp UIProcess/BackgroundProcessResponsivenessTimer.cpp UIProcess/BrowsingContextGroup.cpp @@ -10005,7 +10082,7 @@ index f6bf1fc5c07af2398b8f4bd054f06ad8c87ef9db..19fa3d40595e204170d5302499f36f9d UIProcess/DeviceIdHashSaltStorage.cpp UIProcess/DisplayLink.cpp UIProcess/DisplayLinkProcessProxyClient.cpp -@@ -386,16 +387,20 @@ UIProcess/FrameLoadState.cpp +@@ -394,16 +395,20 @@ UIProcess/FrameLoadState.cpp UIProcess/FrameProcess.cpp UIProcess/GeolocationPermissionRequestManagerProxy.cpp UIProcess/GeolocationPermissionRequestProxy.cpp @@ -10026,7 +10103,7 @@ index f6bf1fc5c07af2398b8f4bd054f06ad8c87ef9db..19fa3d40595e204170d5302499f36f9d UIProcess/RemotePageDrawingAreaProxy.cpp UIProcess/RemotePageProxy.cpp UIProcess/ResponsivenessTimer.cpp -@@ -437,6 +442,8 @@ UIProcess/WebOpenPanelResultListenerProxy.cpp +@@ -445,6 +450,8 @@ UIProcess/WebOpenPanelResultListenerProxy.cpp UIProcess/WebPageDiagnosticLoggingClient.cpp UIProcess/WebPageGroup.cpp UIProcess/WebPageInjectedBundleClient.cpp @@ -10035,7 +10112,7 @@ index f6bf1fc5c07af2398b8f4bd054f06ad8c87ef9db..19fa3d40595e204170d5302499f36f9d UIProcess/WebPageProxy.cpp UIProcess/WebPageProxyMessageReceiverRegistration.cpp UIProcess/WebPageProxyTesting.cpp -@@ -574,7 +581,11 @@ UIProcess/Inspector/WebInspectorUtilities.cpp +@@ -588,7 +595,11 @@ UIProcess/Inspector/WebInspectorUtilities.cpp UIProcess/Inspector/WebPageDebuggable.cpp UIProcess/Inspector/WebPageInspectorController.cpp @@ -10048,10 +10125,10 @@ index f6bf1fc5c07af2398b8f4bd054f06ad8c87ef9db..19fa3d40595e204170d5302499f36f9d UIProcess/Media/AudioSessionRoutingArbitratorProxy.cpp UIProcess/Media/MediaUsageManager.cpp diff --git a/Source/WebKit/SourcesCocoa.txt b/Source/WebKit/SourcesCocoa.txt -index ef6151bae0fc9c79eb542cfa094242eb7d25e765..37a74fc32140c2cc7b93e3b93f05f0a73c6decd3 100644 +index 747fe6c2c1f8d8058ad4ecf3a671f80f5da60d78..1767179349cda6228a3dc7fc25e64b969e9a9668 100644 --- a/Source/WebKit/SourcesCocoa.txt +++ b/Source/WebKit/SourcesCocoa.txt -@@ -270,6 +270,7 @@ UIProcess/API/Cocoa/_WKArchiveExclusionRule.mm +@@ -267,6 +267,7 @@ UIProcess/API/Cocoa/_WKArchiveExclusionRule.mm UIProcess/API/Cocoa/_WKAttachment.mm UIProcess/API/Cocoa/_WKAutomationSession.mm UIProcess/API/Cocoa/_WKAutomationSessionConfiguration.mm @@ -10059,7 +10136,7 @@ index ef6151bae0fc9c79eb542cfa094242eb7d25e765..37a74fc32140c2cc7b93e3b93f05f0a7 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 +@@ -457,6 +458,7 @@ UIProcess/Inspector/ios/WKInspectorHighlightView.mm UIProcess/Inspector/ios/WKInspectorNodeSearchGestureRecognizer.mm UIProcess/Inspector/mac/RemoteWebInspectorUIProxyMac.mm @@ -10068,7 +10145,7 @@ index ef6151bae0fc9c79eb542cfa094242eb7d25e765..37a74fc32140c2cc7b93e3b93f05f0a7 UIProcess/Inspector/mac/WKInspectorResourceURLSchemeHandler.mm UIProcess/Inspector/mac/WKInspectorViewController.mm diff --git a/Source/WebKit/SourcesGTK.txt b/Source/WebKit/SourcesGTK.txt -index b2c71c867b291874c8b9cc8c36a4f19cdb20482c..838518aa70c36cfd27a915bd329bef6adb53845a 100644 +index e193244e152b0c7ca76ecfd3b761412e80e0019a..e557aa325075828ccb94cc2cd62d10751847c4ef 100644 --- a/Source/WebKit/SourcesGTK.txt +++ b/Source/WebKit/SourcesGTK.txt @@ -130,6 +130,7 @@ UIProcess/API/glib/WebKitAutomationSession.cpp @no-unify @@ -10079,23 +10156,23 @@ index b2c71c867b291874c8b9cc8c36a4f19cdb20482c..838518aa70c36cfd27a915bd329bef6a UIProcess/API/glib/WebKitContextMenuClient.cpp @no-unify UIProcess/API/glib/WebKitCookieManager.cpp @no-unify UIProcess/API/glib/WebKitCredential.cpp @no-unify -@@ -258,6 +259,7 @@ UIProcess/glib/DisplayVBlankMonitor.cpp +@@ -259,6 +260,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/SystemSettingsManager.cpp UIProcess/glib/WebPageProxyGLib.cpp - UIProcess/glib/WebProcessPoolGLib.cpp -@@ -273,6 +275,7 @@ UIProcess/gtk/ClipboardGtk4.cpp @no-unify +@@ -277,6 +279,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 -@@ -285,6 +288,8 @@ UIProcess/gtk/ViewGestureControllerGtk.cpp +@@ -290,6 +293,8 @@ UIProcess/gtk/ViewGestureControllerGtk.cpp UIProcess/gtk/WebColorPickerGtk.cpp UIProcess/gtk/WebContextMenuProxyGtk.cpp UIProcess/gtk/WebDataListSuggestionsDropdownGtk.cpp @@ -10105,7 +10182,7 @@ index b2c71c867b291874c8b9cc8c36a4f19cdb20482c..838518aa70c36cfd27a915bd329bef6a UIProcess/gtk/WebPasteboardProxyGtk.cpp UIProcess/gtk/WebPopupMenuProxyGtk.cpp diff --git a/Source/WebKit/SourcesWPE.txt b/Source/WebKit/SourcesWPE.txt -index df35af2dde4e966d500d67a732f9637cace6336d..2295fbc40e103f01812daf9aafd2182edc96cc0d 100644 +index a5952c5ba4380b03bc418ce33332ad3d9a3dc372..ca966a925647e37cc00f74b704957e270600a4e2 100644 --- a/Source/WebKit/SourcesWPE.txt +++ b/Source/WebKit/SourcesWPE.txt @@ -132,6 +132,7 @@ UIProcess/API/glib/WebKitAuthenticationRequest.cpp @no-unify @@ -10132,15 +10209,15 @@ index df35af2dde4e966d500d67a732f9637cace6336d..2295fbc40e103f01812daf9aafd2182e UIProcess/API/wpe/WebKitInputMethodContextWPE.cpp @no-unify UIProcess/API/wpe/WebKitInputMethodContextImplWPE.cpp @no-unify UIProcess/API/wpe/WebKitPopupMenu.cpp @no-unify -@@ -228,6 +231,7 @@ UIProcess/glib/DisplayVBlankMonitor.cpp +@@ -229,6 +232,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/SystemSettingsManager.cpp UIProcess/glib/WebPageProxyGLib.cpp - UIProcess/glib/WebProcessPoolGLib.cpp -@@ -260,7 +264,12 @@ UIProcess/linux/MemoryPressureMonitor.cpp +@@ -262,7 +266,12 @@ UIProcess/linux/MemoryPressureMonitor.cpp UIProcess/soup/WebProcessPoolSoup.cpp UIProcess/wpe/AcceleratedBackingStoreDMABuf.cpp @@ -10153,7 +10230,7 @@ index df35af2dde4e966d500d67a732f9637cace6336d..2295fbc40e103f01812daf9aafd2182e UIProcess/wpe/WebPageProxyWPE.cpp UIProcess/wpe/WebPreferencesWPE.cpp -@@ -287,6 +296,8 @@ WebProcess/WebCoreSupport/glib/WebEditorClientGLib.cpp +@@ -289,6 +298,8 @@ WebProcess/WebCoreSupport/glib/WebEditorClientGLib.cpp WebProcess/WebCoreSupport/soup/WebFrameNetworkingContext.cpp @@ -10210,7 +10287,7 @@ index 32ef9bd308e520f5ac7173639c8b23ea91cde037..7a80553c2d91b9236f563fa1b76aa8a5 bool m_shouldTakeUIBackgroundAssertion { true }; bool m_shouldCaptureDisplayInUIProcess { DEFAULT_CAPTURE_DISPLAY_IN_UI_PROCESS }; diff --git a/Source/WebKit/UIProcess/API/APITargetedElementRequest.h b/Source/WebKit/UIProcess/API/APITargetedElementRequest.h -index 6dc23b36695692f1052de941d4d89dcd72e9f337..804cbc2666d410d7465036621f1c7a16056f9e79 100644 +index 47e2ab76c6dc7ed92cd953f1462e6f4bd149e1d7..e70efd325dd229a207e1790cbf75954189ee87f6 100644 --- a/Source/WebKit/UIProcess/API/APITargetedElementRequest.h +++ b/Source/WebKit/UIProcess/API/APITargetedElementRequest.h @@ -34,7 +34,7 @@ class WebPageProxy; @@ -10220,13 +10297,13 @@ index 6dc23b36695692f1052de941d4d89dcd72e9f337..804cbc2666d410d7465036621f1c7a16 -class TargetedElementRequest final : public ObjectImpl { +class TargetedElementRequest final : public ObjectImpl { public: - bool shouldIgnorePointerEventsNone() const { return m_request.shouldIgnorePointerEventsNone; } + void setShouldIgnorePointerEventsNone(bool value) { m_request.shouldIgnorePointerEventsNone = value; } diff --git a/Source/WebKit/UIProcess/API/APIUIClient.h b/Source/WebKit/UIProcess/API/APIUIClient.h -index ad14acfbfe6ddc134471e52337a6e378951e94ac..c08cb43238008c4e2f49cb8db575db8f915b9faa 100644 +index 6c81074a5b918563a68a549b21be1c970a395643..0a9e1809f65ef749870c17d61e426e222af5463a 100644 --- a/Source/WebKit/UIProcess/API/APIUIClient.h +++ b/Source/WebKit/UIProcess/API/APIUIClient.h -@@ -115,6 +115,7 @@ public: +@@ -116,6 +116,7 @@ public: virtual void runJavaScriptAlert(WebKit::WebPageProxy&, const WTF::String&, WebKit::WebFrameProxy*, WebKit::FrameInfoData&&, Function&& completionHandler) { completionHandler(); } virtual void runJavaScriptConfirm(WebKit::WebPageProxy&, const WTF::String&, WebKit::WebFrameProxy*, WebKit::FrameInfoData&&, Function&& completionHandler) { completionHandler(false); } virtual void runJavaScriptPrompt(WebKit::WebPageProxy&, const WTF::String&, const WTF::String&, WebKit::WebFrameProxy*, WebKit::FrameInfoData&&, Function&& completionHandler) { completionHandler(WTF::String()); } @@ -10235,7 +10312,7 @@ index ad14acfbfe6ddc134471e52337a6e378951e94ac..c08cb43238008c4e2f49cb8db575db8f 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 16229e649d69b812be84b487ec87941cb0986250..88a5fa4bd77136a2370175696d078c20e1d58edd 100644 +index 8ecba5bacfa39f9f5309a127e2c0aed527373a04..0873b91211c89b9cddab9ed74120c0b77e4c6aec 100644 --- a/Source/WebKit/UIProcess/API/C/WKInspector.cpp +++ b/Source/WebKit/UIProcess/API/C/WKInspector.cpp @@ -28,6 +28,11 @@ @@ -10278,10 +10355,10 @@ index 026121d114c5fcad84c1396be8d692625beaa3bd..edd6e5cae033124c589959a42522fde0 } #endif diff --git a/Source/WebKit/UIProcess/API/C/WKPage.cpp b/Source/WebKit/UIProcess/API/C/WKPage.cpp -index 5b8eb0a1b7394a6fd45fc14eb14ca44e72d6ba2a..fad70f71c236a4d087f5ade713eb74a89bc6124e 100644 +index 01fa2b32627f99540d82009dad97b6dbe921b59f..c5eaffd5f2496215dc4d45bf415bf41d3e216901 100644 --- a/Source/WebKit/UIProcess/API/C/WKPage.cpp +++ b/Source/WebKit/UIProcess/API/C/WKPage.cpp -@@ -1781,6 +1781,13 @@ void WKPageSetPageUIClient(WKPageRef pageRef, const WKPageUIClientBase* wkClient +@@ -1795,6 +1795,13 @@ void WKPageSetPageUIClient(WKPageRef pageRef, const WKPageUIClientBase* wkClient completionHandler(String()); } @@ -10295,7 +10372,7 @@ index 5b8eb0a1b7394a6fd45fc14eb14ca44e72d6ba2a..fad70f71c236a4d087f5ade713eb74a8 void setStatusText(WebPageProxy* page, const String& text) final { if (!m_client.setStatusText) -@@ -1810,6 +1817,8 @@ void WKPageSetPageUIClient(WKPageRef pageRef, const WKPageUIClientBase* wkClient +@@ -1824,6 +1831,8 @@ void WKPageSetPageUIClient(WKPageRef pageRef, const WKPageUIClientBase* wkClient { if (!m_client.didNotHandleKeyEvent) return; @@ -10365,7 +10442,7 @@ 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 bc2cfdf33cf27ab45ddddf32075467313a063021..5f25865f940fa1d89c9f7d7588b2bf915814d156 100644 +index 26c2e39dbc49f9435a94ae4825e2ac5def1b061f..3bdf9f44707a0edc4c82a0f77a943df772e83828 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 @@ -10386,7 +10463,7 @@ index bc2cfdf33cf27ab45ddddf32075467313a063021..5f25865f940fa1d89c9f7d7588b2bf91 { return _preferences->inactiveMediaCaptureStreamRepromptIntervalInMinutes(); diff --git a/Source/WebKit/UIProcess/API/Cocoa/WKPreferencesPrivate.h b/Source/WebKit/UIProcess/API/Cocoa/WKPreferencesPrivate.h -index 9908171d94c74d52a4c4a83d6af11ccbaa8790b7..89f30465c0eaecefe2f5496de682857867a289ff 100644 +index 39065a0262f7c1a4ce35ba7373105df0b5ef17ee..fbde5990b2d881b2aec01dd99482bbb77f74e7b4 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) { @@ -10436,18 +10513,18 @@ index eff4cf557033561ab20762d93a58c2d71f5505f0..2fd5a2515c54d9edcab48fa3d993298f NS_ASSUME_NONNULL_END diff --git a/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm b/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm -index e085f3a02dce0f90d2c75c23d9ee8c61c5d63231..467633532033cc8019ac48b6d21baf1691805ed8 100644 +index 211037030a86db642e99c3881488897cd2d8caa9..eb6fb610dd5db0a10f1d121f0d9519943b9d9c0b 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 -@@ -450,6 +451,11 @@ - (void)removeDataOfTypes:(NSSet *)dataTypes modifiedSince:(NSDate *)date comple +@@ -489,6 +490,11 @@ - (void)removeDataOfTypes:(NSSet *)dataTypes modifiedSince:(NSDate *)date comple }); } @@ -10620,7 +10697,7 @@ index df71be1e30c4a13fe9565d309c7bbfb82e049d06..8424a471e7841d300174aa54143578f8 { _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 +index 041fc95fcabaa12ba65da4e8d3ee3e9253b8dff8..4506f3208b8a338fc1bcdae6e9f227f9434b8bda 100644 --- a/Source/WebKit/UIProcess/API/Cocoa/_WKRemoteWebInspectorViewController.mm +++ b/Source/WebKit/UIProcess/API/Cocoa/_WKRemoteWebInspectorViewController.mm @@ -24,6 +24,7 @@ @@ -10858,7 +10935,7 @@ 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 13452bf008a5a5b8cce2367296c20df5b05ced59..2055a9f371e8b60d7702988bfd7ffd1ad0bd55c2 100644 +index bfc64d267c52ab6174bbde5c6f6471313ffbbd22..4110313841d5b4c8b944d52e24e76dac0710453d 100644 --- a/Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp +++ b/Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp @@ -94,6 +94,10 @@ private: @@ -10873,7 +10950,7 @@ index 13452bf008a5a5b8cce2367296c20df5b05ced59..2055a9f371e8b60d7702988bfd7ffd1a 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 47eca6bcf0048acad8e4d213cae94edc03efbffc..b5b1e526b988be8c6ab5830d933c7becb52344f3 100644 +index f34220b0e7629d4bbdf311f73ce7a1b4d7212e0a..b4940b7058022c73402e5ea76b4e592a295f5b84 100644 --- a/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp +++ b/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp @@ -421,10 +421,19 @@ static void webkitWebContextSetProperty(GObject* object, guint propID, const GVa @@ -10896,7 +10973,7 @@ index 47eca6bcf0048acad8e4d213cae94edc03efbffc..b5b1e526b988be8c6ab5830d933c7bec GUniquePtr bundleFilename(g_build_filename(injectedBundleDirectory(), INJECTED_BUNDLE_FILENAME, nullptr)); WebKitWebContext* webContext = WEBKIT_WEB_CONTEXT(object); -@@ -481,6 +490,8 @@ static void webkitWebContextConstructed(GObject* object) +@@ -483,6 +492,8 @@ static void webkitWebContextConstructed(GObject* object) static void webkitWebContextDispose(GObject* object) { @@ -10905,7 +10982,7 @@ index 47eca6bcf0048acad8e4d213cae94edc03efbffc..b5b1e526b988be8c6ab5830d933c7bec WebKitWebContextPrivate* priv = WEBKIT_WEB_CONTEXT(object)->priv; if (!priv->clientsDetached) { priv->clientsDetached = true; -@@ -942,6 +953,11 @@ WebKitNetworkSession* webkit_web_context_get_network_session_for_automation(WebK +@@ -944,6 +955,11 @@ WebKitNetworkSession* webkit_web_context_get_network_session_for_automation(WebK return nullptr; #endif } @@ -10942,7 +11019,7 @@ index c1945fbe717a42afc1f51d64a80c7de3fa9009ba..ab63fe19b00ecbd64c9421e6eecad3e2 #endif +int webkitWebContextExistingCount(); diff --git a/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp b/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp -index 061a05bdd19eea75552cad40e78794dfd26f6668..d96b4efdb43131cfccff3ace107b3959eb6a4a1c 100644 +index 2d318375d33835ad78f75bd8169d9050ca850485..d607b8b2357c2b843b3654ccaa31fd7fe389b8a7 100644 --- a/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp +++ b/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp @@ -34,6 +34,7 @@ @@ -10961,7 +11038,7 @@ index 061a05bdd19eea75552cad40e78794dfd26f6668..d96b4efdb43131cfccff3ace107b3959 #include "WebKitPrivate.h" #include "WebKitResponsePolicyDecision.h" #include "WebKitScriptDialogPrivate.h" -@@ -90,7 +92,6 @@ +@@ -91,7 +93,6 @@ #if PLATFORM(GTK) #include "WebKitFaviconDatabasePrivate.h" #include "WebKitInputMethodContextImplGtk.h" @@ -10969,7 +11046,7 @@ index 061a05bdd19eea75552cad40e78794dfd26f6668..d96b4efdb43131cfccff3ace107b3959 #include "WebKitPrintOperationPrivate.h" #include "WebKitWebInspectorPrivate.h" #include "WebKitWebViewBasePrivate.h" -@@ -146,6 +147,7 @@ enum { +@@ -147,6 +148,7 @@ enum { CLOSE, SCRIPT_DIALOG, @@ -10977,7 +11054,7 @@ index 061a05bdd19eea75552cad40e78794dfd26f6668..d96b4efdb43131cfccff3ace107b3959 DECIDE_POLICY, PERMISSION_REQUEST, -@@ -506,6 +508,16 @@ GRefPtr WebKitWebViewClient::showOptionMenu(WebKitPopupMenu& p +@@ -507,6 +509,16 @@ GRefPtr WebKitWebViewClient::showOptionMenu(WebKitPopupMenu& p void WebKitWebViewClient::frameDisplayed(WKWPE::View&) { @@ -10994,7 +11071,7 @@ index 061a05bdd19eea75552cad40e78794dfd26f6668..d96b4efdb43131cfccff3ace107b3959 { SetForScope inFrameDisplayedGuard(m_webView->priv->inFrameDisplayed, true); for (const auto& callback : m_webView->priv->frameDisplayedCallbacks) { -@@ -522,6 +534,18 @@ void WebKitWebViewClient::frameDisplayed(WKWPE::View&) +@@ -523,6 +535,18 @@ void WebKitWebViewClient::frameDisplayed(WKWPE::View&) } } @@ -11013,7 +11090,7 @@ index 061a05bdd19eea75552cad40e78794dfd26f6668..d96b4efdb43131cfccff3ace107b3959 void WebKitWebViewClient::willStartLoad(WKWPE::View&) { webkitWebViewWillStartLoad(m_webView); -@@ -608,7 +632,7 @@ static gboolean webkitWebViewDecidePolicy(WebKitWebView*, WebKitPolicyDecision* +@@ -609,7 +633,7 @@ static gboolean webkitWebViewDecidePolicy(WebKitWebView*, WebKitPolicyDecision* static gboolean webkitWebViewPermissionRequest(WebKitWebView*, WebKitPermissionRequest* request) { @@ -11022,7 +11099,7 @@ index 061a05bdd19eea75552cad40e78794dfd26f6668..d96b4efdb43131cfccff3ace107b3959 if (WEBKIT_IS_POINTER_LOCK_PERMISSION_REQUEST(request)) { webkit_permission_request_allow(request); return TRUE; -@@ -927,6 +951,10 @@ static void webkitWebViewConstructed(GObject* object) +@@ -929,6 +953,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); @@ -11033,7 +11110,7 @@ index 061a05bdd19eea75552cad40e78794dfd26f6668..d96b4efdb43131cfccff3ace107b3959 webkitWebViewCreatePage(webView, WTFMove(configuration)); webkitWebContextWebViewCreated(priv->context.get(), webView); -@@ -1956,6 +1984,15 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) +@@ -1958,6 +1986,15 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) G_TYPE_BOOLEAN, 1, WEBKIT_TYPE_SCRIPT_DIALOG); @@ -11049,7 +11126,7 @@ index 061a05bdd19eea75552cad40e78794dfd26f6668..d96b4efdb43131cfccff3ace107b3959 /** * WebKitWebView::decide-policy: * @web_view: the #WebKitWebView on which the signal is emitted -@@ -2748,6 +2785,23 @@ void webkitWebViewRunJavaScriptBeforeUnloadConfirm(WebKitWebView* webView, const +@@ -2750,6 +2787,23 @@ void webkitWebViewRunJavaScriptBeforeUnloadConfirm(WebKitWebView* webView, const webkit_script_dialog_unref(webView->priv->currentScriptDialog); } @@ -11098,10 +11175,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 36a0e39f8b13dcaa57ac1221d24e06a35eabe9b0..6a51f9653ccfb26c52405e44390f4aa3dd5f23f6 100644 +index 8deb2ea57ad6e55b79053d392ef43e6191e036f4..54f45f129acb3b83aaae11f7895c749d20c3ce9e 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 +@@ -273,6 +273,8 @@ void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent& event, bool { if (wasEventHandled || event.type() != WebEventType::KeyDown || !event.nativeEvent()) return; @@ -11123,10 +11200,10 @@ index 36a0e39f8b13dcaa57ac1221d24e06a35eabe9b0..6a51f9653ccfb26c52405e44390f4aa3 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 8b747ca183ddd04160b29cd9b89e5e40ad8161ab..6c99ff9824ea2db3719b84ee3f5766011213d998 100644 +index 56693a6cace9e41e6f353393303e36290de768fe..f28839fee5f3769d0cebf2836615d0c91fddfb76 100644 --- a/Source/WebKit/UIProcess/API/gtk/PageClientImpl.h +++ b/Source/WebKit/UIProcess/API/gtk/PageClientImpl.h -@@ -105,7 +105,7 @@ private: +@@ -109,7 +109,7 @@ private: #endif Ref createValidationBubble(const String& message, const WebCore::ValidationBubble::Settings&) final; void selectionDidChange() override; @@ -11236,10 +11313,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 f6690c7780dff32a043c51f7afaba00119a92c44..f48f5b67505176bac3406212e266a6addd6e226a 100644 +index 55efbd0732f7d74fc0702d012d13465686b9bfae..9efb28a02ddb82da4b7ae0868ec29e5ec95af6f1 100644 --- a/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp +++ b/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp -@@ -2930,6 +2930,11 @@ void webkitWebViewBaseResetClickCounter(WebKitWebViewBase* webkitWebViewBase) +@@ -2894,6 +2894,11 @@ void webkitWebViewBaseResetClickCounter(WebKitWebViewBase* webkitWebViewBase) #endif } @@ -11251,7 +11328,7 @@ index f6690c7780dff32a043c51f7afaba00119a92c44..f48f5b67505176bac3406212e266a6ad void webkitWebViewBaseEnterAcceleratedCompositingMode(WebKitWebViewBase* webkitWebViewBase, const LayerTreeContext& layerTreeContext) { ASSERT(webkitWebViewBase->priv->acceleratedBackingStore); -@@ -2986,12 +2991,12 @@ void webkitWebViewBasePageClosed(WebKitWebViewBase* webkitWebViewBase) +@@ -2950,12 +2955,12 @@ void webkitWebViewBasePageClosed(WebKitWebViewBase* webkitWebViewBase) webkitWebViewBase->priv->acceleratedBackingStore->update({ }); } @@ -11267,7 +11344,7 @@ index f6690c7780dff32a043c51f7afaba00119a92c44..f48f5b67505176bac3406212e266a6ad #if !USE(GTK4) diff --git a/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBasePrivate.h b/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBasePrivate.h -index a99b65ba10a47d9806d1d61240e0e3e883bf91e5..61991ab00a922356e1ec74771a992751c6d219cc 100644 +index cfd4310b3c775e662b4d643d4f2edda56e101b58..65dc3319a8031b478b0faca89276f9dfed28c55f 100644 --- a/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBasePrivate.h +++ b/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBasePrivate.h @@ -27,6 +27,7 @@ @@ -11278,7 +11355,7 @@ index a99b65ba10a47d9806d1d61240e0e3e883bf91e5..61991ab00a922356e1ec74771a992751 #include "APIPageConfiguration.h" #include "InputMethodState.h" #include "RendererBufferFormat.h" -@@ -108,7 +109,7 @@ void webkitWebViewBaseStartDrag(WebKitWebViewBase*, WebCore::SelectionData&&, Op +@@ -104,7 +105,7 @@ void webkitWebViewBaseStartDrag(WebKitWebViewBase*, WebCore::SelectionData&&, Op void webkitWebViewBaseDidPerformDragControllerAction(WebKitWebViewBase*); #endif @@ -11287,14 +11364,14 @@ index a99b65ba10a47d9806d1d61240e0e3e883bf91e5..61991ab00a922356e1ec74771a992751 void webkitWebViewBaseSetEnableBackForwardNavigationGesture(WebKitWebViewBase*, bool enabled); WebKit::ViewGestureController* webkitWebViewBaseViewGestureController(WebKitWebViewBase*); -@@ -149,3 +150,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..b9832e9221edaa14af485d34ac6216ffebac4e0d 100644 +index 7636ad733e7be66a74f8fede966b0acb905a5842..cf54287353d1e529c6765e3caf8d283abe1e3472 100644 --- a/Source/WebKit/UIProcess/API/wpe/APIViewClient.h +++ b/Source/WebKit/UIProcess/API/wpe/APIViewClient.h @@ -26,6 +26,12 @@ @@ -11308,9 +11385,9 @@ index 26d1790017e528f26ae04dac635678d5494bfd04..b9832e9221edaa14af485d34ac6216ff +#include +#endif #include + #include - typedef struct OpaqueJSContext* JSGlobalContextRef; -@@ -49,6 +55,13 @@ public: +@@ -50,6 +56,13 @@ public: virtual bool isGLibBasedAPI() { return false; } virtual void frameDisplayed(WKWPE::View&) { } @@ -11325,7 +11402,7 @@ index 26d1790017e528f26ae04dac635678d5494bfd04..b9832e9221edaa14af485d34ac6216ff 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 b9b6b379136653e9dc13313715e0d281a2c8cb01..7cb887f31dc381739b079be0ab2548075fbc0690 100644 +index ee491999df7919658c48d8eb457577335d3c5b90..09b834a89f84fb6b37f059c2cc4cce98313817e2 100644 --- a/Source/WebKit/UIProcess/API/wpe/PageClientImpl.cpp +++ b/Source/WebKit/UIProcess/API/wpe/PageClientImpl.cpp @@ -34,9 +34,13 @@ @@ -11342,7 +11419,7 @@ index b9b6b379136653e9dc13313715e0d281a2c8cb01..7cb887f31dc381739b079be0ab254807 #include #include #include -@@ -50,6 +54,12 @@ +@@ -52,6 +56,12 @@ #include #endif @@ -11354,8 +11431,8 @@ index b9b6b379136653e9dc13313715e0d281a2c8cb01..7cb887f31dc381739b079be0ab254807 + namespace WebKit { - PageClientImpl::PageClientImpl(WKWPE::View& view) -@@ -208,7 +218,7 @@ WebCore::IntPoint PageClientImpl::accessibilityScreenToRootView(const WebCore::I + WTF_MAKE_TZONE_ALLOCATED_IMPL(PageClientImpl); +@@ -212,7 +222,7 @@ WebCore::IntPoint PageClientImpl::accessibilityScreenToRootView(const WebCore::I WebCore::IntRect PageClientImpl::rootViewToAccessibilityScreen(const WebCore::IntRect& rect) { @@ -11364,7 +11441,7 @@ index b9b6b379136653e9dc13313715e0d281a2c8cb01..7cb887f31dc381739b079be0ab254807 } void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent&, bool) -@@ -487,6 +497,64 @@ void PageClientImpl::selectionDidChange() +@@ -491,6 +501,64 @@ void PageClientImpl::selectionDidChange() m_view.selectionDidChange(); } @@ -11429,7 +11506,7 @@ index b9b6b379136653e9dc13313715e0d281a2c8cb01..7cb887f31dc381739b079be0ab254807 WebKitWebResourceLoadManager* PageClientImpl::webResourceLoadManager() { return m_view.webResourceLoadManager(); -@@ -497,4 +565,23 @@ void PageClientImpl::callAfterNextPresentationUpdate(CompletionHandler&& +@@ -501,4 +569,23 @@ void PageClientImpl::callAfterNextPresentationUpdate(CompletionHandler&& m_view.callAfterNextPresentationUpdate(WTFMove(callback)); } @@ -11454,10 +11531,10 @@ index b9b6b379136653e9dc13313715e0d281a2c8cb01..7cb887f31dc381739b079be0ab254807 + } // namespace WebKit diff --git a/Source/WebKit/UIProcess/API/wpe/PageClientImpl.h b/Source/WebKit/UIProcess/API/wpe/PageClientImpl.h -index dc56a4f5af6ddf3ff3d557493482b5b25efcd24d..f1f69fb9341fa8bfff6e1ae045db5465a1b85eed 100644 +index 8397c722a45b279415f1648ad4673e99240089d9..41955881ad0db72ba0a27f4960330bb8dc237d2a 100644 --- a/Source/WebKit/UIProcess/API/wpe/PageClientImpl.h +++ b/Source/WebKit/UIProcess/API/wpe/PageClientImpl.h -@@ -166,9 +166,24 @@ private: +@@ -171,9 +171,24 @@ private: void didChangeWebPageID() const override; void selectionDidChange() override; @@ -11771,10 +11848,10 @@ index e4b92ace1531090ae38a7aec3d3d4febf19aee84..b66b573f9148c39c5ce2738add6cd01a + +PlatformImage webkitWebViewBackendTakeScreenshot(WebKitWebViewBackend*); diff --git a/Source/WebKit/UIProcess/API/wpe/WebKitWebViewClient.h b/Source/WebKit/UIProcess/API/wpe/WebKitWebViewClient.h -index 720c88818bdb4cde3cb58e95785454754f6c1396..2658e6709a13e5d6258abca956ec52bc6b68324d 100644 +index 2f1182cb91a00353eace0b71612df096391c2450..d71d7fc724b046fab41285bb8f390cb6af6520ca 100644 --- a/Source/WebKit/UIProcess/API/wpe/WebKitWebViewClient.h +++ b/Source/WebKit/UIProcess/API/wpe/WebKitWebViewClient.h -@@ -50,6 +50,13 @@ private: +@@ -51,6 +51,13 @@ private: bool isGLibBasedAPI() override { return true; } void frameDisplayed(WKWPE::View&) override; @@ -11789,10 +11866,10 @@ index 720c88818bdb4cde3cb58e95785454754f6c1396..2658e6709a13e5d6258abca956ec52bc 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 07eda283848542ed7e8a2aa0abdfa543c8aa756d..75dfd2b0c2122c472cd796973aa4d1cefec471a3 100644 +index 1f2e33b690d6be4f27838008f0eb32696023c8c7..4cf688212cd7c57fc46b376e6be7b7b51fe342de 100644 --- a/Source/WebKit/UIProcess/Automation/WebAutomationSession.h +++ b/Source/WebKit/UIProcess/Automation/WebAutomationSession.h -@@ -235,6 +235,8 @@ public: +@@ -236,6 +236,8 @@ public: void didDestroyFrame(WebCore::FrameIdentifier); @@ -11801,7 +11878,7 @@ index 07eda283848542ed7e8a2aa0abdfa543c8aa756d..75dfd2b0c2122c472cd796973aa4d1ce private: RefPtr webPageProxyForHandle(const String&); String handleForWebPageProxy(const WebPageProxy&); -@@ -286,7 +288,6 @@ private: +@@ -287,7 +289,6 @@ private: // Get base64-encoded PNG data from a bitmap. static std::optional platformGetBase64EncodedPNGData(WebCore::ShareableBitmap::Handle&&); @@ -11810,10 +11887,10 @@ index 07eda283848542ed7e8a2aa0abdfa543c8aa756d..75dfd2b0c2122c472cd796973aa4d1ce // 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 a6864205241a0c2f31661f8a2629bdba4feae9b5..aa528ad3a1c1c850eed91ba01d500aaff8550d4a 100644 +index a3a4997f987ba09829d54f26c1cc70842c658f87..b8cb97db12695db3bec61a01cf8073213b40f6ac 100644 --- a/Source/WebKit/UIProcess/AuxiliaryProcessProxy.cpp +++ b/Source/WebKit/UIProcess/AuxiliaryProcessProxy.cpp -@@ -165,7 +165,11 @@ void AuxiliaryProcessProxy::getLaunchOptions(ProcessLauncher::LaunchOptions& lau +@@ -168,7 +168,11 @@ void AuxiliaryProcessProxy::getLaunchOptions(ProcessLauncher::LaunchOptions& lau launchOptions.processCmdPrefix = String::fromUTF8(processCmdPrefix); #endif // ENABLE(DEVELOPER_MODE) && (PLATFORM(GTK) || PLATFORM(WPE)) @@ -11826,10 +11903,10 @@ index a6864205241a0c2f31661f8a2629bdba4feae9b5..aa528ad3a1c1c850eed91ba01d500aaf platformGetLaunchOptions(launchOptions); } diff --git a/Source/WebKit/UIProcess/AuxiliaryProcessProxy.h b/Source/WebKit/UIProcess/AuxiliaryProcessProxy.h -index 306d6ae98067d79851f4622e5aabebe76d293a2e..701a70f88bc1978c9904eef19d33761e9668ea37 100644 +index 70aa53ec6d79c71bf2394e88f7e4c3bc8f70d4ec..bea35c50cc2288f16f86c4930d565e1247a1bba9 100644 --- a/Source/WebKit/UIProcess/AuxiliaryProcessProxy.h +++ b/Source/WebKit/UIProcess/AuxiliaryProcessProxy.h -@@ -287,13 +287,16 @@ protected: +@@ -294,13 +294,16 @@ protected: InitializationActivityAndGrant initializationActivityAndGrant(); @@ -11848,10 +11925,10 @@ index 306d6ae98067d79851f4622e5aabebe76d293a2e..701a70f88bc1978c9904eef19d33761e // Connection::Client diff --git a/Source/WebKit/UIProcess/BackingStore.h b/Source/WebKit/UIProcess/BackingStore.h -index e1d579d6d428c3575ddf83b9d78dae045beb218d..9a2830e50ec8ab965e4a5a2b5faa9285c99bcc99 100644 +index 945c62704e0b25f04e9ee4be88b21f88aeda8bd9..409c1c560b2462bf59f19dfee7941748b54fd22c 100644 --- a/Source/WebKit/UIProcess/BackingStore.h +++ b/Source/WebKit/UIProcess/BackingStore.h -@@ -66,6 +66,7 @@ public: +@@ -67,6 +67,7 @@ public: float deviceScaleFactor() const { return m_deviceScaleFactor; } void paint(PlatformPaintContextPtr, const WebCore::IntRect&); @@ -11971,7 +12048,7 @@ index 0000000000000000000000000000000000000000..cd66887de171cda7d15a8e4dc6dbff63 + +#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 +index aaa27547f4ad4e3cc5551f621472554f4ed287bb..294e11d5b5cac544b62254e9951580b4339f0f17 100644 --- a/Source/WebKit/UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.h +++ b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/PopUpSOAuthorizationSession.h @@ -29,6 +29,7 @@ @@ -11982,7 +12059,7 @@ index 957f7f088087169668a9b4f1ba65d9f206a2a836..15e44c8d5b6a3eafb7f1148707366b0c OBJC_CLASS WKSOSecretDelegate; OBJC_CLASS WKWebView; -@@ -39,6 +40,8 @@ class NavigationAction; +@@ -40,6 +41,8 @@ class PageConfiguration; namespace WebKit { @@ -11991,11 +12068,23 @@ index 957f7f088087169668a9b4f1ba65d9f206a2a836..15e44c8d5b6a3eafb7f1148707366b0c // FSM: Idle => Active => Completed class PopUpSOAuthorizationSession final : public SOAuthorizationSession { public: +diff --git a/Source/WebKit/UIProcess/Cocoa/SOAuthorization/SOAuthorizationCoordinator.h b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/SOAuthorizationCoordinator.h +index 11caa19f1f40a55fa4378ac092632731cd16f9e0..56b6ec4a8a1f6dfd199e24a91bb4c9113ba6e08c 100644 +--- a/Source/WebKit/UIProcess/Cocoa/SOAuthorization/SOAuthorizationCoordinator.h ++++ b/Source/WebKit/UIProcess/Cocoa/SOAuthorization/SOAuthorizationCoordinator.h +@@ -27,6 +27,7 @@ + + #if HAVE(APP_SSO) + ++#import "APIPageConfiguration.h" + #include + #include + #include diff --git a/Source/WebKit/UIProcess/Cocoa/UIDelegate.h b/Source/WebKit/UIProcess/Cocoa/UIDelegate.h -index 5f1c130ef8235f1002ffd0fa156cd5ff9e14a019..0c73c4cc5ccd1ab8745322926c68865d80fb2264 100644 +index 49c6fb1049761c89e9e0e40869f4d57d042c227b..acaa86f77435ba1be932e574d4b62ae2716f27e8 100644 --- a/Source/WebKit/UIProcess/Cocoa/UIDelegate.h +++ b/Source/WebKit/UIProcess/Cocoa/UIDelegate.h -@@ -105,6 +105,7 @@ private: +@@ -106,6 +106,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; @@ -12003,7 +12092,7 @@ index 5f1c130ef8235f1002ffd0fa156cd5ff9e14a019..0c73c4cc5ccd1ab8745322926c68865d 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; -@@ -222,6 +223,7 @@ private: +@@ -223,6 +224,7 @@ private: bool webViewRunJavaScriptAlertPanelWithMessageInitiatedByFrameCompletionHandler : 1; bool webViewRunJavaScriptConfirmPanelWithMessageInitiatedByFrameCompletionHandler : 1; bool webViewRunJavaScriptTextInputPanelWithPromptDefaultTextInitiatedByFrameCompletionHandler : 1; @@ -12012,10 +12101,10 @@ index 5f1c130ef8235f1002ffd0fa156cd5ff9e14a019..0c73c4cc5ccd1ab8745322926c68865d bool webViewRequestStorageAccessPanelForDomainUnderCurrentDomainForQuirkDomainsCompletionHandler : 1; bool webViewRunBeforeUnloadConfirmPanelWithMessageInitiatedByFrameCompletionHandler : 1; diff --git a/Source/WebKit/UIProcess/Cocoa/UIDelegate.mm b/Source/WebKit/UIProcess/Cocoa/UIDelegate.mm -index 71a1c0e707aa595be47e134096a5534c03c631a2..a7d2aee9b65ac13c9d2a231252f4c50a50f79404 100644 +index 45d81b21bbc47418f77dd5a49c032c694db3f08c..10466388e3380e939ad8199f059b25491a61e48f 100644 --- a/Source/WebKit/UIProcess/Cocoa/UIDelegate.mm +++ b/Source/WebKit/UIProcess/Cocoa/UIDelegate.mm -@@ -118,6 +118,7 @@ void UIDelegate::setDelegate(id delegate) +@@ -122,6 +122,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:)]; @@ -12023,7 +12112,7 @@ index 71a1c0e707aa595be47e134096a5534c03c631a2..a7d2aee9b65ac13c9d2a231252f4c50a 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:)]; -@@ -449,6 +450,15 @@ void UIDelegate::UIClient::runJavaScriptPrompt(WebPageProxy& page, const WTF::St +@@ -458,6 +459,15 @@ void UIDelegate::UIClient::runJavaScriptPrompt(WebPageProxy& page, const WTF::St }).get()]; } @@ -12040,18 +12129,20 @@ index 71a1c0e707aa595be47e134096a5534c03c631a2..a7d2aee9b65ac13c9d2a231252f4c50a { if (!m_uiDelegate) diff --git a/Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm b/Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm -index 7716347a00ce1829a464a8b9da072bc783e94a3b..ebac53978038e95870823b16440816c86e195a01 100644 +index 2d04117422e1e10ca59fec5af93b312352b948e5..d7a04374498d58311914ca538d316f362164ac62 100644 --- a/Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm +++ b/Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm -@@ -39,6 +39,7 @@ - #import "LoadParameters.h" - #import "MessageSenderInlines.h" +@@ -42,7 +42,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" -@@ -299,10 +300,84 @@ bool WebPageProxy::scrollingUpdatesDisabledForTesting() +@@ -317,11 +319,86 @@ bool WebPageProxy::scrollingUpdatesDisabledForTesting() void WebPageProxy::startDrag(const DragItem& dragItem, ShareableBitmap::Handle&& dragImageHandle) { @@ -12059,7 +12150,8 @@ index 7716347a00ce1829a464a8b9da072bc783e94a3b..ebac53978038e95870823b16440816c8 + NSPasteboard *pasteboard = [NSPasteboard pasteboardWithName: m_overrideDragPasteboardName]; + + 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) { @@ -12085,7 +12177,8 @@ index 7716347a00ce1829a464a8b9da072bc783e94a3b..ebac53978038e95870823b16440816c8 + return; + } + - protectedPageClient()->startDrag(dragItem, WTFMove(dragImageHandle)); + if (RefPtr pageClient = this->pageClient()) + pageClient->startDrag(dragItem, WTFMove(dragImageHandle)); } -#endif @@ -12128,7 +12221,7 @@ index 7716347a00ce1829a464a8b9da072bc783e94a3b..ebac53978038e95870823b16440816c8 + + auto previousRect = m_currentDragCaretRect; + m_currentDragCaretRect = dragCaretRect; -+ pageClient().didChangeDragCaretRect(previousRect, dragCaretRect); ++ pageClient()->didChangeDragCaretRect(previousRect, dragCaretRect); +} + +#endif // PLATFORM(IOS_FAMILY) @@ -12138,10 +12231,10 @@ index 7716347a00ce1829a464a8b9da072bc783e94a3b..ebac53978038e95870823b16440816c8 #if ENABLE(ATTACHMENT_ELEMENT) diff --git a/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm b/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm -index 9bfeb3569a88ea4c98f9948aa5a0229a4c3c9f35..44664d0a9a454e7d63d34b3603cf1f8a12c43548 100644 +index 2d583997574502b60b74208ad01349b7f1bc17d2..ffa9871e3679684d82d508c91137651231112c20 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) @@ -12150,7 +12243,7 @@ index 9bfeb3569a88ea4c98f9948aa5a0229a4c3c9f35..44664d0a9a454e7d63d34b3603cf1f8a #endif #if (PLATFORM(IOS) || PLATFORM(VISION)) && HAVE(AGX_COMPILER_SERVICE) -@@ -790,8 +790,8 @@ void WebProcessPool::registerNotificationObservers() +@@ -831,8 +831,8 @@ void WebProcessPool::registerNotificationObservers() }]; m_scrollerStyleNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSPreferredScrollerStyleDidChangeNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *notification) { @@ -12162,10 +12255,10 @@ index 9bfeb3569a88ea4c98f9948aa5a0229a4c3c9f35..44664d0a9a454e7d63d34b3603cf1f8a 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 39eb5f67b50e99eddac8e12b4ecee66fe1d81360..91f5b350d7ae87af8754b56662e8dbc286084d5b 100644 +index d15636e78679112ea910a43d45b2930676b15d6a..72c9a4c6327712073190c33774bec559bf026003 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" @@ -12173,9 +12266,10 @@ index 39eb5f67b50e99eddac8e12b4ecee66fe1d81360..91f5b350d7ae87af8754b56662e8dbc2 #include "WebPageProxy.h" #include "WebPreferences.h" #include "WebProcessPool.h" - #include "WebProcessProxy.h" +@@ -40,8 +41,10 @@ #include #include + #include +#include #if PLATFORM(GTK) @@ -12183,7 +12277,7 @@ index 39eb5f67b50e99eddac8e12b4ecee66fe1d81360..91f5b350d7ae87af8754b56662e8dbc2 #include #endif -@@ -48,6 +51,13 @@ +@@ -49,6 +52,13 @@ #include #endif @@ -12197,8 +12291,8 @@ index 39eb5f67b50e99eddac8e12b4ecee66fe1d81360..91f5b350d7ae87af8754b56662e8dbc2 namespace WebKit { using namespace WebCore; -@@ -160,6 +170,11 @@ void DrawingAreaProxyCoordinatedGraphics::deviceScaleFactorDidChange() - send(Messages::DrawingArea::SetDeviceScaleFactor(m_webPageProxy->deviceScaleFactor())); +@@ -164,6 +174,11 @@ void DrawingAreaProxyCoordinatedGraphics::deviceScaleFactorDidChange(CompletionH + completionHandler(); } +void DrawingAreaProxyCoordinatedGraphics::waitForSizeUpdate(Function&& callback) @@ -12209,7 +12303,7 @@ index 39eb5f67b50e99eddac8e12b4ecee66fe1d81360..91f5b350d7ae87af8754b56662e8dbc2 void DrawingAreaProxyCoordinatedGraphics::setBackingStoreIsDiscardable(bool isBackingStoreDiscardable) { #if !PLATFORM(WPE) -@@ -221,6 +236,45 @@ void DrawingAreaProxyCoordinatedGraphics::updateAcceleratedCompositingMode(uint6 +@@ -225,6 +240,45 @@ void DrawingAreaProxyCoordinatedGraphics::updateAcceleratedCompositingMode(uint6 updateAcceleratedCompositingMode(layerTreeContext); } @@ -12255,7 +12349,7 @@ index 39eb5f67b50e99eddac8e12b4ecee66fe1d81360..91f5b350d7ae87af8754b56662e8dbc2 bool DrawingAreaProxyCoordinatedGraphics::alwaysUseCompositing() const { return m_webPageProxy->preferences().acceleratedCompositingEnabled() && m_webPageProxy->preferences().forceCompositingMode(); -@@ -275,6 +329,12 @@ void DrawingAreaProxyCoordinatedGraphics::didUpdateGeometry() +@@ -279,6 +333,12 @@ void DrawingAreaProxyCoordinatedGraphics::didUpdateGeometry() // we need to resend the new size here. if (m_lastSentSize != m_size) sendUpdateGeometry(); @@ -12269,7 +12363,7 @@ index 39eb5f67b50e99eddac8e12b4ecee66fe1d81360..91f5b350d7ae87af8754b56662e8dbc2 #if !PLATFORM(WPE) diff --git a/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.h b/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.h -index 555814f9771f8f16d3572cd7007817ba4296d6d3..8850e4adb182e7f0b23e5cde45f14ad8c66bcc15 100644 +index a7cf6a9f232b4c2d6803ed8d6b3fa2273bfe0a2e..5fbbe2a55625f651e190b0c2197b9c7f97814624 100644 --- a/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.h +++ b/Source/WebKit/UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.h @@ -29,6 +29,7 @@ @@ -12278,9 +12372,9 @@ index 555814f9771f8f16d3572cd7007817ba4296d6d3..8850e4adb182e7f0b23e5cde45f14ad8 #include "LayerTreeContext.h" +#include #include + #include - #if !PLATFORM(WPE) -@@ -61,6 +62,10 @@ public: +@@ -56,6 +57,10 @@ public: bool isInAcceleratedCompositingMode() const { return !m_layerTreeContext.isEmpty(); } const LayerTreeContext& layerTreeContext() const { return m_layerTreeContext; } @@ -12291,7 +12385,7 @@ index 555814f9771f8f16d3572cd7007817ba4296d6d3..8850e4adb182e7f0b23e5cde45f14ad8 void dispatchAfterEnsuringDrawing(CompletionHandler&&); -@@ -84,6 +89,9 @@ private: +@@ -79,6 +84,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; @@ -12301,7 +12395,7 @@ index 555814f9771f8f16d3572cd7007817ba4296d6d3..8850e4adb182e7f0b23e5cde45f14ad8 bool shouldSendWheelEventsToEventDispatcher() const override { return true; } -@@ -126,6 +134,7 @@ private: +@@ -122,6 +130,7 @@ private: // The last size we sent to the web process. WebCore::IntSize m_lastSentSize; @@ -12309,7 +12403,7 @@ index 555814f9771f8f16d3572cd7007817ba4296d6d3..8850e4adb182e7f0b23e5cde45f14ad8 #if !PLATFORM(WPE) bool m_isBackingStoreDiscardable { true }; -@@ -134,6 +143,10 @@ private: +@@ -130,6 +139,10 @@ private: RunLoop::Timer m_discardBackingStoreTimer; #endif std::unique_ptr m_drawingMonitor; @@ -12321,7 +12415,7 @@ index 555814f9771f8f16d3572cd7007817ba4296d6d3..8850e4adb182e7f0b23e5cde45f14ad8 } // namespace WebKit diff --git a/Source/WebKit/UIProcess/Downloads/DownloadProxy.cpp b/Source/WebKit/UIProcess/Downloads/DownloadProxy.cpp -index cc5e0d803a2069c6a5539fe1bccb67c5c9b1b3aa..7841be001cb5bc6db99b3d71f881c6e9b298e5fd 100644 +index 81b64958bf7f9e86a54bc41028aea1b983ce7133..bd9697fc26ca4c903891178bfd884ee35c953eed 100644 --- a/Source/WebKit/UIProcess/Downloads/DownloadProxy.cpp +++ b/Source/WebKit/UIProcess/Downloads/DownloadProxy.cpp @@ -40,8 +40,10 @@ @@ -12350,17 +12444,17 @@ index cc5e0d803a2069c6a5539fe1bccb67c5c9b1b3aa..7841be001cb5bc6db99b3d71f881c6e9 void DownloadProxy::cancel(CompletionHandler&& completionHandler) { 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), [this, protectedThis = Ref { *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 { ++ protectedDataStore()->protectedNetworkProcess()->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()); + if (instrumentation) + instrumentation->downloadFinished(m_uuid, "canceled"_s); - m_downloadProxyMap.downloadFinished(*this); + m_downloadProxyMap->downloadFinished(*this); }); } else -@@ -153,6 +161,21 @@ void DownloadProxy::decideDestinationWithSuggestedFilename(const WebCore::Resour +@@ -153,6 +161,33 @@ void DownloadProxy::decideDestinationWithSuggestedFilename(const WebCore::Resour suggestedFilename = m_suggestedFilename; suggestedFilename = MIMETypeRegistry::appendFileExtensionIfNecessary(suggestedFilename, response.mimeType()); @@ -12375,14 +12469,26 @@ index cc5e0d803a2069c6a5539fe1bccb67c5c9b1b3aa..7841be001cb5bc6db99b3d71f881c6e9 + 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 { SandboxExtension::Handle sandboxExtensionHandle; if (!destination.isNull()) { -@@ -201,6 +224,8 @@ void DownloadProxy::didFinish() +@@ -215,6 +250,8 @@ void DownloadProxy::didFinish() updateQuarantinePropertiesIfPossible(); #endif m_client->didFinish(*this); @@ -12390,8 +12496,8 @@ index cc5e0d803a2069c6a5539fe1bccb67c5c9b1b3aa..7841be001cb5bc6db99b3d71f881c6e9 + instrumentation->downloadFinished(m_uuid, String()); // This can cause the DownloadProxy object to be deleted. - m_downloadProxyMap.downloadFinished(*this); -@@ -211,6 +236,8 @@ void DownloadProxy::didFail(const ResourceError& error, std::span + m_downloadProxyMap->downloadFinished(*this); +@@ -225,6 +262,8 @@ void DownloadProxy::didFail(const ResourceError& error, std::span m_legacyResumeData = createData(resumeData); m_client->didFail(*this, error, m_legacyResumeData.get()); @@ -12399,12 +12505,12 @@ index cc5e0d803a2069c6a5539fe1bccb67c5c9b1b3aa..7841be001cb5bc6db99b3d71f881c6e9 + instrumentation->downloadFinished(m_uuid, error.localizedDescription()); // This can cause the DownloadProxy object to be deleted. - m_downloadProxyMap.downloadFinished(*this); + m_downloadProxyMap->downloadFinished(*this); diff --git a/Source/WebKit/UIProcess/Downloads/DownloadProxy.h b/Source/WebKit/UIProcess/Downloads/DownloadProxy.h -index 6f0d076b1b1cb0ec3e1c7fdc5f3a6dfffe9ee63d..656d4259dbf9ab97a8b0408c061c0fd2de8beaa7 100644 +index 8418c16c5ee94c3ea37962d1db4b961d18dc391e..fb8a8ba64c499d92f17891e0268fe3c1163913c0 100644 --- a/Source/WebKit/UIProcess/Downloads/DownloadProxy.h +++ b/Source/WebKit/UIProcess/Downloads/DownloadProxy.h -@@ -143,6 +143,7 @@ private: +@@ -156,6 +156,7 @@ private: #if PLATFORM(COCOA) RetainPtr m_progress; #endif @@ -12413,10 +12519,10 @@ index 6f0d076b1b1cb0ec3e1c7fdc5f3a6dfffe9ee63d..656d4259dbf9ab97a8b0408c061c0fd2 } // namespace WebKit diff --git a/Source/WebKit/UIProcess/DrawingAreaProxy.h b/Source/WebKit/UIProcess/DrawingAreaProxy.h -index 77d47a91327391c2b8bc3a3fc12f512c25160649..3173e2545ae0a79b90342234b008fd26a0ad72a7 100644 +index a6897e8688b39c7ca3131b3b730a0fec1d3727e2..0f0e67c3eaa49351266d7666189e168a4f9cce7c 100644 --- a/Source/WebKit/UIProcess/DrawingAreaProxy.h +++ b/Source/WebKit/UIProcess/DrawingAreaProxy.h -@@ -98,6 +98,7 @@ public: +@@ -90,6 +90,7 @@ public: const WebCore::IntSize& size() const { return m_size; } bool setSize(const WebCore::IntSize&, const WebCore::IntSize& scrollOffset = { }); @@ -12424,7 +12530,7 @@ index 77d47a91327391c2b8bc3a3fc12f512c25160649..3173e2545ae0a79b90342234b008fd26 virtual void minimumSizeForAutoLayoutDidChange() { } virtual void sizeToContentAutoSizeMaximumSizeDidChange() { } -@@ -184,6 +185,10 @@ private: +@@ -177,6 +178,10 @@ private: virtual void update(uint64_t /* backingStoreStateID */, UpdateInfo&&) { } virtual void exitAcceleratedCompositingMode(uint64_t /* backingStoreStateID */, UpdateInfo&&) { } #endif @@ -12737,7 +12843,7 @@ index 0000000000000000000000000000000000000000..4ec8b96bbbddf8a7b042f53a8068754a +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..b0527d43bf28c7b6f25a5dc3f2b9ff42e0a96190 +index 0000000000000000000000000000000000000000..229fd8e721648b07057af413f0fb8424af2ed926 --- /dev/null +++ b/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.cpp @@ -0,0 +1,387 @@ @@ -13077,7 +13183,7 @@ index 0000000000000000000000000000000000000000..b0527d43bf28c7b6f25a5dc3f2b9ff42 +{ + 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)); @@ -13130,7 +13236,7 @@ index 0000000000000000000000000000000000000000..b0527d43bf28c7b6f25a5dc3f2b9ff42 +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.h b/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.h new file mode 100644 -index 0000000000000000000000000000000000000000..f1322caa318ca408731697b2eb6349e0dc9c8537 +index 0000000000000000000000000000000000000000..f53bb59c65a4ced0360e473fb9ed9a36d1179310 --- /dev/null +++ b/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.h @@ -0,0 +1,109 @@ @@ -13165,7 +13271,7 @@ index 0000000000000000000000000000000000000000..f1322caa318ca408731697b2eb6349e0 +#include +#include + -+#if USE(CAIRO) ++#if USE(CAIRO) || PLATFORM(GTK) +#include +#endif + @@ -13245,10 +13351,10 @@ index 0000000000000000000000000000000000000000..f1322caa318ca408731697b2eb6349e0 +} // 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..8690b1a245d463cd29c0196ab609ab69c80cc0a9 +index 0000000000000000000000000000000000000000..9f3a9fb9ca1881b9c81493bf5a21382d4015c74c --- /dev/null +++ b/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.cpp -@@ -0,0 +1,437 @@ +@@ -0,0 +1,438 @@ +/* + * Copyright (c) 2010, The WebM Project authors. All rights reserved. + * Copyright (c) 2013 The Chromium Authors. All rights reserved. @@ -13288,6 +13394,7 @@ index 0000000000000000000000000000000000000000..8690b1a245d463cd29c0196ab609ab69 +#include +#include +#include ++#include +#include + +#if USE(SKIA) && !PLATFORM(GTK) @@ -13688,7 +13795,7 @@ index 0000000000000000000000000000000000000000..8690b1a245d463cd29c0196ab609ab69 +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.h b/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.h new file mode 100644 -index 0000000000000000000000000000000000000000..f8701329f574bfad15f0e5456360a3ee3bd21b48 +index 0000000000000000000000000000000000000000..caf0474267c1bda6346f7b025b6646bb4f1b56d9 --- /dev/null +++ b/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.h @@ -0,0 +1,82 @@ @@ -13726,7 +13833,7 @@ index 0000000000000000000000000000000000000000..f8701329f574bfad15f0e5456360a3ee +#include +#include + -+#if USE(CAIRO) ++#if USE(CAIRO) || PLATFORM(GTK) +#include +#endif + @@ -13909,7 +14016,7 @@ index 0000000000000000000000000000000000000000..e2ce910f3fd7f587add552275b7e7176 + +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.cpp b/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.cpp -index 5cd89b25d3d87ec952d9a1a55351c9a7d76b9125..f43f2b64bcb6fffc672406f9eea9f7bda96918d6 100644 +index 23426ee5d9f3a01e5216267810f48091779384ca..78edcf784aa90cd9296faa539d235e741f826d32 100644 --- a/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.cpp +++ b/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.cpp @@ -28,7 +28,7 @@ @@ -13921,7 +14028,7 @@ index 5cd89b25d3d87ec952d9a1a55351c9a7d76b9125..f43f2b64bcb6fffc672406f9eea9f7bd #include "WebPageInspectorTarget.h" #include "WebPageMessages.h" #include "WebPageProxy.h" -@@ -40,19 +40,17 @@ using namespace Inspector; +@@ -43,19 +43,17 @@ WTF_MAKE_TZONE_ALLOCATED_IMPL(InspectorTargetProxy); std::unique_ptr InspectorTargetProxy::create(WebPageProxy& page, const String& targetId, Inspector::InspectorTargetType type) { @@ -13946,14 +14053,14 @@ index 5cd89b25d3d87ec952d9a1a55351c9a7d76b9125..f43f2b64bcb6fffc672406f9eea9f7bd , m_identifier(targetId) , m_type(type) { -@@ -99,6 +97,31 @@ void InspectorTargetProxy::didCommitProvisionalTarget() +@@ -102,6 +100,31 @@ void InspectorTargetProxy::didCommitProvisionalTarget() m_provisionalPage = nullptr; } +void InspectorTargetProxy::willResume() +{ -+ if (m_page.hasRunningProcess()) -+ m_page.legacyMainFrameProcess().send(Messages::WebPage::ResumeInspectorIfPausedInNewWindow(), m_page.webPageIDInMainFrameProcess()); ++ if (m_page->hasRunningProcess()) ++ m_page->legacyMainFrameProcess().send(Messages::WebPage::ResumeInspectorIfPausedInNewWindow(), m_page->webPageIDInMainFrameProcess()); +} + +void InspectorTargetProxy::activate(String& error) @@ -13970,25 +14077,25 @@ index 5cd89b25d3d87ec952d9a1a55351c9a7d76b9125..f43f2b64bcb6fffc672406f9eea9f7bd + 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..4552047ddc305d1da8ab2c0ca319392d95359a2c 100644 --- a/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.h +++ b/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.h -@@ -37,13 +37,13 @@ class WebPageProxy; +@@ -38,13 +38,13 @@ 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); @@ -13999,7 +14106,7 @@ index a2239cec8e18850f35f7f88a9c4ebadc62bf4023..79f3ff84327dc075ec96983e04db4b10 ~InspectorTargetProxy() = default; Inspector::InspectorTargetType type() const final { return m_type; } -@@ -55,12 +55,17 @@ public: +@@ -56,12 +56,17 @@ public: void connect(Inspector::FrontendChannel::ConnectionType) override; void disconnect() override; void sendMessageToTargetBackend(const String&) override; @@ -14010,7 +14117,7 @@ index a2239cec8e18850f35f7f88a9c4ebadc62bf4023..79f3ff84327dc075ec96983e04db4b10 + void willResume() override; + void platformActivate(String& error) const; + - WebPageProxy& m_page; + WeakRef m_page; + WeakPtr m_provisionalPage; String m_identifier; Inspector::InspectorTargetType m_type; @@ -14019,7 +14126,7 @@ index a2239cec8e18850f35f7f88a9c4ebadc62bf4023..79f3ff84327dc075ec96983e04db4b10 } // namespace WebKit diff --git a/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.cpp b/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.cpp -index 96cfb0cbc8749708d263a79270746a0185bff348..c6a71685084ca322925c848a404e5d80db0b727e 100644 +index e4f2f719746ed69b1226be2d47b16666f2067772..e94eba914cf44bad58c63be024a862d904baf690 100644 --- a/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.cpp +++ b/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.cpp @@ -26,13 +26,21 @@ @@ -14044,9 +14151,9 @@ index 96cfb0cbc8749708d263a79270746a0185bff348..c6a71685084ca322925c848a404e5d80 #include #include #include -@@ -49,32 +57,119 @@ static String getTargetID(const ProvisionalPageProxy& provisionalPage) - return WebPageInspectorTarget::toTargetID(provisionalPage.webPageID()); - } +@@ -52,34 +60,121 @@ static String getTargetID(const ProvisionalPageProxy& provisionalPage) + + WTF_MAKE_TZONE_ALLOCATED_IMPL(WebPageInspectorController); +WebPageInspectorControllerObserver* WebPageInspectorController::s_observer = nullptr; + @@ -14069,6 +14176,8 @@ index 96cfb0cbc8749708d263a79270746a0185bff348..c6a71685084ca322925c848a404e5d80 - m_agents.append(WTFMove(targetAgent)); } + WebPageInspectorController::~WebPageInspectorController() = default; + -Ref WebPageInspectorController::protectedInspectedPage() +WeakRef WebPageInspectorController::protectedInspectedPage() { @@ -14169,7 +14278,7 @@ index 96cfb0cbc8749708d263a79270746a0185bff348..c6a71685084ca322925c848a404e5d80 } bool WebPageInspectorController::hasLocalFrontend() const -@@ -88,6 +183,17 @@ void WebPageInspectorController::connectFrontend(Inspector::FrontendChannel& fro +@@ -93,6 +188,17 @@ void WebPageInspectorController::connectFrontend(Inspector::FrontendChannel& fro bool connectingFirstFrontend = !m_frontendRouter->hasFrontends(); @@ -14187,7 +14296,7 @@ index 96cfb0cbc8749708d263a79270746a0185bff348..c6a71685084ca322925c848a404e5d80 m_frontendRouter->connectFrontend(frontendChannel); if (connectingFirstFrontend) -@@ -107,8 +213,10 @@ void WebPageInspectorController::disconnectFrontend(FrontendChannel& frontendCha +@@ -112,8 +218,10 @@ void WebPageInspectorController::disconnectFrontend(FrontendChannel& frontendCha m_frontendRouter->disconnectFrontend(frontendChannel); bool disconnectingLastFrontend = !m_frontendRouter->hasFrontends(); @@ -14199,7 +14308,7 @@ index 96cfb0cbc8749708d263a79270746a0185bff348..c6a71685084ca322925c848a404e5d80 auto inspectedPage = protectedInspectedPage(); inspectedPage->didChangeInspectorFrontendCount(m_frontendRouter->frontendCount()); -@@ -132,6 +240,8 @@ void WebPageInspectorController::disconnectAllFrontends() +@@ -137,6 +245,8 @@ void WebPageInspectorController::disconnectAllFrontends() // Disconnect any remaining remote frontends. m_frontendRouter->disconnectAllFrontends(); @@ -14208,7 +14317,7 @@ index 96cfb0cbc8749708d263a79270746a0185bff348..c6a71685084ca322925c848a404e5d80 auto inspectedPage = protectedInspectedPage(); inspectedPage->didChangeInspectorFrontendCount(m_frontendRouter->frontendCount()); -@@ -160,6 +270,75 @@ void WebPageInspectorController::setIndicating(bool indicating) +@@ -165,6 +275,75 @@ void WebPageInspectorController::setIndicating(bool indicating) } #endif @@ -14236,14 +14345,14 @@ index 96cfb0cbc8749708d263a79270746a0185bff348..c6a71685084ca322925c848a404e5d80 +{ + 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; @@ -14251,17 +14360,17 @@ index 96cfb0cbc8749708d263a79270746a0185bff348..c6a71685084ca322925c848a404e5d80 + 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; @@ -14272,10 +14381,10 @@ index 96cfb0cbc8749708d263a79270746a0185bff348..c6a71685084ca322925c848a404e5d80 + + // 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()); @@ -14284,7 +14393,7 @@ index 96cfb0cbc8749708d263a79270746a0185bff348..c6a71685084ca322925c848a404e5d80 void WebPageInspectorController::createInspectorTarget(const String& targetId, Inspector::InspectorTargetType type) { addTarget(InspectorTargetProxy::create(protectedInspectedPage(), targetId, type)); -@@ -179,6 +358,32 @@ void WebPageInspectorController::sendMessageToInspectorFrontend(const String& ta +@@ -184,6 +363,32 @@ void WebPageInspectorController::sendMessageToInspectorFrontend(const String& ta m_targetAgent->sendMessageFromTargetToFrontend(targetId, message); } @@ -14317,7 +14426,7 @@ index 96cfb0cbc8749708d263a79270746a0185bff348..c6a71685084ca322925c848a404e5d80 bool WebPageInspectorController::shouldPauseLoading(const ProvisionalPageProxy& provisionalPage) const { if (!m_frontendRouter->hasFrontends()) -@@ -198,7 +403,7 @@ void WebPageInspectorController::setContinueLoadingCallback(const ProvisionalPag +@@ -203,7 +408,7 @@ void WebPageInspectorController::setContinueLoadingCallback(const ProvisionalPag void WebPageInspectorController::didCreateProvisionalPage(ProvisionalPageProxy& provisionalPage) { @@ -14326,7 +14435,7 @@ index 96cfb0cbc8749708d263a79270746a0185bff348..c6a71685084ca322925c848a404e5d80 } void WebPageInspectorController::willDestroyProvisionalPage(const ProvisionalPageProxy& provisionalPage) -@@ -277,4 +482,27 @@ void WebPageInspectorController::browserExtensionsDisabled(HashSet&& ext +@@ -287,4 +492,30 @@ void WebPageInspectorController::browserExtensionsDisabled(HashSet&& ext m_enabledBrowserAgent->extensionsDisabled(WTFMove(extensionIDs)); } @@ -14351,24 +14460,29 @@ index 96cfb0cbc8749708d263a79270746a0185bff348..c6a71685084ca322925c848a404e5d80 + 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..00b4ae5f9a7ac36f1fceab1c3ab39b20086302ae 100644 +index 29457fc3c76c963bf50b44c011f64398efbae676..999160e64365ad73e87601094b69a86224a2b54e 100644 --- a/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.h +++ b/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.h -@@ -26,6 +26,7 @@ +@@ -26,19 +26,43 @@ #pragma once #include "InspectorTargetProxy.h" +#include "ProcessTerminationReason.h" #include #include ++#include #include -@@ -33,11 +34,33 @@ + #include #include #include + #include #include +#include + @@ -14400,7 +14514,7 @@ index c6aafe0e9339c8ac02dc133754ddc23e1cb522ff..00b4ae5f9a7ac36f1fceab1c3ab39b20 } namespace WebKit { -@@ -45,6 +68,23 @@ namespace WebKit { +@@ -46,6 +70,23 @@ namespace WebKit { class InspectorBrowserAgent; struct WebPageAgentContext; @@ -14413,7 +14527,7 @@ index c6aafe0e9339c8ac02dc133754ddc23e1cb522ff..00b4ae5f9a7ac36f1fceab1c3ab39b20 +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; + @@ -14422,10 +14536,10 @@ index c6aafe0e9339c8ac02dc133754ddc23e1cb522ff..00b4ae5f9a7ac36f1fceab1c3ab39b20 +}; + class WebPageInspectorController { + WTF_MAKE_TZONE_ALLOCATED(WebPageInspectorController); WTF_MAKE_NONCOPYABLE(WebPageInspectorController); - WTF_MAKE_FAST_ALLOCATED; -@@ -52,7 +92,21 @@ public: - WebPageInspectorController(WebPageProxy&); +@@ -54,7 +95,21 @@ public: + ~WebPageInspectorController(); void init(); + void didFinishAttachingToWebProcess(); @@ -14446,7 +14560,7 @@ index c6aafe0e9339c8ac02dc133754ddc23e1cb522ff..00b4ae5f9a7ac36f1fceab1c3ab39b20 bool hasLocalFrontend() const; -@@ -65,11 +119,28 @@ public: +@@ -67,11 +122,29 @@ public: #if ENABLE(REMOTE_INSPECTOR) void setIndicating(bool); #endif @@ -14456,12 +14570,13 @@ index c6aafe0e9339c8ac02dc133754ddc23e1cb522ff..00b4ae5f9a7ac36f1fceab1c3ab39b20 +#if USE(CAIRO) || PLATFORM(GTK) + void didPaint(cairo_surface_t*); +#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 didFailProvisionalLoadForFrame(uint64_t navigationID, const WebCore::ResourceError& error); ++ void didDestroyNavigation(WebCore::NavigationIdentifier navigationID); ++ ++ void didFailProvisionalLoadForFrame(WebCore::NavigationIdentifier navigationID, const WebCore::ResourceError& error); void createInspectorTarget(const String& targetId, Inspector::InspectorTargetType); void destroyInspectorTarget(const String& targetId); @@ -14475,7 +14590,7 @@ index c6aafe0e9339c8ac02dc133754ddc23e1cb522ff..00b4ae5f9a7ac36f1fceab1c3ab39b20 bool shouldPauseLoading(const ProvisionalPageProxy&) const; void setContinueLoadingCallback(const ProvisionalPageProxy&, WTF::Function&&); -@@ -84,11 +155,12 @@ public: +@@ -86,11 +159,12 @@ public: void browserExtensionsDisabled(HashSet&&); private: @@ -14489,19 +14604,19 @@ index c6aafe0e9339c8ac02dc133754ddc23e1cb522ff..00b4ae5f9a7ac36f1fceab1c3ab39b20 Ref m_frontendRouter; Ref m_backendDispatcher; -@@ -97,11 +169,17 @@ private: +@@ -99,11 +173,17 @@ private: WeakRef m_inspectedPage; - Inspector::InspectorTargetAgent* m_targetAgent { nullptr }; + CheckedPtr m_targetAgent; + 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; ++ HashMap m_pendingNavigations; + + static WebPageInspectorControllerObserver* s_observer; }; @@ -14740,10 +14855,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..f0675fcaf55625bce9b23a378d556030c27997f8 +index 0000000000000000000000000000000000000000..a7a92f6d3730b64e1a8864158f6dbebbabc0b68c --- /dev/null +++ b/Source/WebKit/UIProcess/InspectorPlaywrightAgent.cpp -@@ -0,0 +1,1026 @@ +@@ -0,0 +1,1006 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * @@ -15169,14 +15284,14 @@ index 0000000000000000000000000000000000000000..f0675fcaf55625bce9b23a378d556030 + 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) @@ -15380,33 +15495,13 @@ index 0000000000000000000000000000000000000000..f0675fcaf55625bce9b23a378d556030 + +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; @@ -15448,7 +15543,7 @@ index 0000000000000000000000000000000000000000..f0675fcaf55625bce9b23a378d556030 + } + } + -+ 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; @@ -15456,7 +15551,7 @@ index 0000000000000000000000000000000000000000..f0675fcaf55625bce9b23a378d556030 + + String navigationIDString; + if (navigationID) -+ navigationIDString = String::number(navigationID); ++ navigationIDString = String::number(navigationID->toUInt64()); + callback->sendSuccess(navigationIDString); + }); +} @@ -15692,7 +15787,7 @@ index 0000000000000000000000000000000000000000..f0675fcaf55625bce9b23a378d556030 +{ + if (!m_isEnabled) + return; -+ String frameID = WebCore::InspectorPageAgent::makeFrameID(page->legacyMainFrameProcess().coreProcessIdentifier(), frameInfoData.frameID); ++ String frameID = WebCore::InspectorPageAgent::serializeFrameID(*frameInfoData.frameID); + m_downloads.set(uuid, download); + m_frontendDispatcher->downloadCreated( + toPageProxyIDProtocolString(*page), @@ -15772,10 +15867,10 @@ index 0000000000000000000000000000000000000000..f0675fcaf55625bce9b23a378d556030 +#endif // ENABLE(REMOTE_INSPECTOR) diff --git a/Source/WebKit/UIProcess/InspectorPlaywrightAgent.h b/Source/WebKit/UIProcess/InspectorPlaywrightAgent.h new file mode 100644 -index 0000000000000000000000000000000000000000..1a63e17a88f13f7e315cdcbd5644919c3217be4a +index 0000000000000000000000000000000000000000..0a3b5a7604ec1abca5c2fff66b02ada96ddce4d1 --- /dev/null +++ b/Source/WebKit/UIProcess/InspectorPlaywrightAgent.h -@@ -0,0 +1,139 @@ +@@ -0,0 +1,140 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * @@ -15813,6 +15908,7 @@ index 0000000000000000000000000000000000000000..1a63e17a88f13f7e315cdcbd5644919c +#include +#include +#include ++#include + +namespace Inspector { +class BackendDispatcher; @@ -15861,7 +15957,7 @@ index 0000000000000000000000000000000000000000..1a63e17a88f13f7e315cdcbd5644919c + // 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; + @@ -15995,10 +16091,10 @@ index 0000000000000000000000000000000000000000..e7a3dcc533294bb6e12f65d79b5b716b + +#endif // ENABLE(REMOTE_INSPECTOR) diff --git a/Source/WebKit/UIProcess/Launcher/glib/ProcessLauncherGLib.cpp b/Source/WebKit/UIProcess/Launcher/glib/ProcessLauncherGLib.cpp -index be2380f8940e72d217687fb12f30f5d8dd3fc242..0f8eede082cb1d034fdb84d1630736dc31d732cf 100644 +index 28a4d766b125615ec3111f4e42c0831bfb69e094..4f15f2335f56220da2fa50ff0ec61b6872d6fd3f 100644 --- a/Source/WebKit/UIProcess/Launcher/glib/ProcessLauncherGLib.cpp +++ b/Source/WebKit/UIProcess/Launcher/glib/ProcessLauncherGLib.cpp -@@ -197,6 +197,13 @@ void ProcessLauncher::launchProcess() +@@ -176,6 +176,13 @@ void ProcessLauncher::launchProcess() nargs++; } #endif @@ -16012,7 +16108,7 @@ index be2380f8940e72d217687fb12f30f5d8dd3fc242..0f8eede082cb1d034fdb84d1630736dc char** argv = g_newa(char*, nargs); unsigned i = 0; -@@ -213,6 +220,10 @@ void ProcessLauncher::launchProcess() +@@ -192,6 +199,10 @@ void ProcessLauncher::launchProcess() if (configureJSCForTesting) argv[i++] = const_cast("--configure-jsc-for-testing"); #endif @@ -16051,7 +16147,7 @@ index fac881d7c3d44758591d7a9f392a3992ce9f9a72..35eba5a0b31fc6e2d6e5c05c9f866c03 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 a2e5f12221607f68257a2bea47442decc4f3bba7..5c5330abce8839d9ebb0f90853199094458b9f5a 100644 +index 1c2e1038c2a00264eebac03c1e89e6d5a5d247a0..714e4d09ab152330bc281e7c9e8e43e9131af27e 100644 --- a/Source/WebKit/UIProcess/Media/RemoteMediaSessionCoordinatorProxy.cpp +++ b/Source/WebKit/UIProcess/Media/RemoteMediaSessionCoordinatorProxy.cpp @@ -30,6 +30,7 @@ @@ -16063,10 +16159,10 @@ index a2e5f12221607f68257a2bea47442decc4f3bba7..5c5330abce8839d9ebb0f90853199094 #include "RemoteMediaSessionCoordinatorProxyMessages.h" #include "WebPageProxy.h" diff --git a/Source/WebKit/UIProcess/PageClient.h b/Source/WebKit/UIProcess/PageClient.h -index 46a5ef93ae5d51029f3d037f9f0917f315c6386a..a52ad99dd1cb9401d42cbe8f06d9ecf0c65b5778 100644 +index 960043d7db4e4898380e11300e73e6fe52c6da07..9a5cedfce7dfe331a71ecb10d4dc08845db512d6 100644 --- a/Source/WebKit/UIProcess/PageClient.h +++ b/Source/WebKit/UIProcess/PageClient.h -@@ -72,6 +72,11 @@ +@@ -74,6 +74,11 @@ #include #endif @@ -16078,7 +16174,7 @@ index 46a5ef93ae5d51029f3d037f9f0917f315c6386a..a52ad99dd1cb9401d42cbe8f06d9ecf0 OBJC_CLASS AVPlayerViewController; OBJC_CLASS CALayer; OBJC_CLASS NSFileWrapper; -@@ -93,6 +98,12 @@ OBJC_CLASS WKView; +@@ -95,6 +100,12 @@ OBJC_CLASS WKView; #endif #endif @@ -16091,7 +16187,7 @@ index 46a5ef93ae5d51029f3d037f9f0917f315c6386a..a52ad99dd1cb9401d42cbe8f06d9ecf0 namespace WebKit { class PageClient; } -@@ -374,7 +385,20 @@ public: +@@ -377,7 +388,20 @@ public: virtual void selectionDidChange() = 0; #endif @@ -16239,7 +16335,7 @@ index 0000000000000000000000000000000000000000..3c8fd0549f1847515d35092f0f49b060 + +#endif // ENABLE(FULLSCREEN_API) diff --git a/Source/WebKit/UIProcess/ProvisionalFrameProxy.cpp b/Source/WebKit/UIProcess/ProvisionalFrameProxy.cpp -index 5fcfd69c72a7bf369d1c043e3cfd26cbfed7f023..92c638d01d397fc39f654caed5b6f87a8b6ead99 100644 +index 924718f62be57635f13afd3edb3f079906b31540..81d5cb24004311941063610aa4830d92fa3633bc 100644 --- a/Source/WebKit/UIProcess/ProvisionalFrameProxy.cpp +++ b/Source/WebKit/UIProcess/ProvisionalFrameProxy.cpp @@ -25,6 +25,7 @@ @@ -16553,7 +16649,7 @@ index 0000000000000000000000000000000000000000..6d04f9290135069359ce6bf872654648 + +#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 +index a91f8ca1dabd76b41632ea2d5d4223a7c657dc19..1c9de7acb15fa190a08ab4dc9d30772766a06989 100644 --- a/Source/WebKit/UIProcess/RemoteLayerTree/mac/RemoteLayerTreeEventDispatcher.h +++ b/Source/WebKit/UIProcess/RemoteLayerTree/mac/RemoteLayerTreeEventDispatcher.h @@ -30,6 +30,7 @@ @@ -16565,7 +16661,7 @@ index d499ee31f32b9dcdb456ba0b476d211fba115673..43b349887d18e21162b59fa8174df32c #include #include @@ -41,6 +42,11 @@ - #include + #include #include #include +#include @@ -16577,29 +16673,29 @@ index d499ee31f32b9dcdb456ba0b476d211fba115673..43b349887d18e21162b59fa8174df32c namespace WebCore { class PlatformWheelEvent; diff --git a/Source/WebKit/UIProcess/RemotePageProxy.cpp b/Source/WebKit/UIProcess/RemotePageProxy.cpp -index f08f1ae907d39f75ec5043921c44dfeb1c581511..a892f5050b0f7a37c1231c9ca41dfb6030249aba 100644 +index ba2898874c785f21fb68b77b5a15fd18ce9d68fd..9e0094660772ee3985b6f05700992104ba870e6d 100644 --- a/Source/WebKit/UIProcess/RemotePageProxy.cpp +++ b/Source/WebKit/UIProcess/RemotePageProxy.cpp -@@ -43,6 +43,7 @@ - #include "WebPageProxyMessages.h" +@@ -44,6 +44,7 @@ + #include "WebProcessActivityState.h" #include "WebProcessMessages.h" #include "WebProcessProxy.h" +#include "WebProcessMessages.h" #include + #include - namespace WebKit { diff --git a/Source/WebKit/UIProcess/RemotePageProxy.h b/Source/WebKit/UIProcess/RemotePageProxy.h -index b2019b6e792c58c9aa258d571f24dbe35c5eb926..bac988e367c158292f6e5dab957bdafcd23d91de 100644 +index 9fef5ebf4661c8aa1df77907ff7c3f077c6bf001..e1ee1fd8ea17b03ca3fcedc8b5d920d67bf90373 100644 --- a/Source/WebKit/UIProcess/RemotePageProxy.h +++ b/Source/WebKit/UIProcess/RemotePageProxy.h -@@ -73,7 +73,6 @@ class WebProcessProxy; +@@ -76,7 +76,6 @@ class WebProcessProxy; struct FrameInfoData; struct FrameTreeCreationParameters; -struct NavigationActionData; class RemotePageProxy : public IPC::MessageReceiver { - WTF_MAKE_FAST_ALLOCATED; + WTF_MAKE_TZONE_ALLOCATED(RemotePageProxy); diff --git a/Source/WebKit/UIProcess/WebAuthentication/fido/U2fAuthenticator.cpp b/Source/WebKit/UIProcess/WebAuthentication/fido/U2fAuthenticator.cpp index 40531b866fda1c35dbddb90f2ac1027688b2a09c..82003f78d7d2c9fbf2d393187636cf8b0bcf228f 100644 --- a/Source/WebKit/UIProcess/WebAuthentication/fido/U2fAuthenticator.cpp @@ -16637,7 +16733,7 @@ index e2ded3c65b9680346be2534a3e970e2f425a83a8..b0c006c1dcbfae4b33530f8eae04f986 WebPageProxy* page() const { return m_page.get(); } diff --git a/Source/WebKit/UIProcess/WebFrameProxy.cpp b/Source/WebKit/UIProcess/WebFrameProxy.cpp -index e0b661cc8a30d93db78ab5763cedb178d1507c51..663a0bb5984163a95f059dfb6cba0f9453f80222 100644 +index 1cbf04be848366e881fd8ceec3de82628786548b..03ba18dcd9eb7b8c9ad95b5546adbcf2e8b76e4a 100644 --- a/Source/WebKit/UIProcess/WebFrameProxy.cpp +++ b/Source/WebKit/UIProcess/WebFrameProxy.cpp @@ -31,6 +31,7 @@ @@ -16657,18 +16753,18 @@ index e0b661cc8a30d93db78ab5763cedb178d1507c51..663a0bb5984163a95f059dfb6cba0f94 #include "WebPageProxy.h" #include "WebPageProxyMessages.h" diff --git a/Source/WebKit/UIProcess/WebNavigationState.h b/Source/WebKit/UIProcess/WebNavigationState.h -index 0968d688b613c7112dd243083b839242b95cb308..b05d1f71a641bfacc27965b2c78725575840b583 100644 +index 26077dc941a14d58e6a07182d650abb48cc8b62c..77ed2b05ded42183b8274e46c69957f7b6dc2eae 100644 --- a/Source/WebKit/UIProcess/WebNavigationState.h +++ b/Source/WebKit/UIProcess/WebNavigationState.h -@@ -29,6 +29,7 @@ - #include +@@ -31,6 +31,7 @@ #include + #include #include +#include "WebPageProxy.h" namespace WebKit { class WebNavigationState; -@@ -52,7 +53,6 @@ enum class FrameLoadType : uint8_t; +@@ -54,7 +55,6 @@ enum class FrameLoadType : uint8_t; namespace WebKit { @@ -16678,7 +16774,7 @@ index 0968d688b613c7112dd243083b839242b95cb308..b05d1f71a641bfacc27965b2c7872557 class WebNavigationState : public CanMakeWeakPtr { diff --git a/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.cpp b/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.cpp new file mode 100644 -index 0000000000000000000000000000000000000000..0eec34c12082631d2d07a7a2b96ed189bd52a518 +index 0000000000000000000000000000000000000000..0a8d10ae990997684766df46719c65aa8dd77f28 --- /dev/null +++ b/Source/WebKit/UIProcess/WebPageInspectorEmulationAgent.cpp @@ -0,0 +1,159 @@ @@ -16755,9 +16851,9 @@ index 0000000000000000000000000000000000000000..0eec34c12082631d2d07a7a2b96ed189 +#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)); + }); @@ -17417,13 +17513,13 @@ index 0000000000000000000000000000000000000000..26a2a3c0791c334f811ec99a630314f8 + +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/WebPageProxy.cpp b/Source/WebKit/UIProcess/WebPageProxy.cpp -index 4dad8418faa1a7fcc734d5813f3a9b550a8fba21..c598c65d2ef9e6421611f5e56362dcd9b455598a 100644 +index dc95df8cd29f53622308310d998c3659a0190a71..f11fde5085cd28fe011372dcdf42681697b2ed14 100644 --- a/Source/WebKit/UIProcess/WebPageProxy.cpp +++ b/Source/WebKit/UIProcess/WebPageProxy.cpp -@@ -190,12 +190,14 @@ - #include +@@ -195,12 +195,14 @@ #include #include + #include +#include #include #include @@ -17435,7 +17531,7 @@ index 4dad8418faa1a7fcc734d5813f3a9b550a8fba21..c598c65d2ef9e6421611f5e56362dcd9 #include #include #include -@@ -216,6 +218,7 @@ +@@ -222,6 +224,7 @@ #include #include #include @@ -17443,7 +17539,7 @@ index 4dad8418faa1a7fcc734d5813f3a9b550a8fba21..c598c65d2ef9e6421611f5e56362dcd9 #include #include #include -@@ -223,12 +226,15 @@ +@@ -229,12 +232,15 @@ #include #include #include @@ -17459,17 +17555,17 @@ index 4dad8418faa1a7fcc734d5813f3a9b550a8fba21..c598c65d2ef9e6421611f5e56362dcd9 #include #include #include -@@ -310,6 +316,9 @@ +@@ -319,6 +325,9 @@ + #if USE(GBM) #include "AcceleratedBackingStoreDMABuf.h" #endif - #include "GtkSettingsManager.h" +#endif + +#if PLATFORM(GTK) || PLATFORM(WPE) #include #endif -@@ -432,6 +441,8 @@ static constexpr Seconds tryCloseTimeoutDelay = 50_ms; +@@ -443,6 +452,8 @@ static constexpr Seconds tryCloseTimeoutDelay = 50_ms; static constexpr Seconds audibleActivityClearDelay = 10_s; #endif @@ -17478,9 +17574,9 @@ index 4dad8418faa1a7fcc734d5813f3a9b550a8fba21..c598c65d2ef9e6421611f5e56362dcd9 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, webPageProxyCounter, ("WebPageProxy")); #if PLATFORM(COCOA) -@@ -846,6 +857,10 @@ WebPageProxy::~WebPageProxy() +@@ -868,6 +879,10 @@ WebPageProxy::~WebPageProxy() if (preferences->mediaSessionCoordinatorEnabled()) - GroupActivitiesSessionNotifier::sharedNotifier().removeWebPage(*this); + GroupActivitiesSessionNotifier::singleton().removeWebPage(*this); #endif + +#if PLATFORM(COCOA) @@ -17488,16 +17584,16 @@ index 4dad8418faa1a7fcc734d5813f3a9b550a8fba21..c598c65d2ef9e6421611f5e56362dcd9 +#endif } - void WebPageProxy::addAllMessageReceivers() -@@ -1408,6 +1423,7 @@ void WebPageProxy::finishAttachingToWebProcess(ProcessLaunchReason reason) - - protectedPageClient()->didRelaunchProcess(); + Ref WebPageProxy::Internals::protectedPage() const +@@ -1429,6 +1444,7 @@ void WebPageProxy::finishAttachingToWebProcess(const Site& site, ProcessLaunchRe + if (RefPtr pageClient = this->pageClient()) + pageClient->didRelaunchProcess(); internals().pageLoadState.didSwapWebProcesses(); + m_inspectorController->didFinishAttachingToWebProcess(); } void WebPageProxy::didAttachToRunningProcess() -@@ -1416,7 +1432,7 @@ void WebPageProxy::didAttachToRunningProcess() +@@ -1437,7 +1453,7 @@ void WebPageProxy::didAttachToRunningProcess() #if ENABLE(FULLSCREEN_API) ASSERT(!m_fullScreenManager); @@ -17506,7 +17602,7 @@ index 4dad8418faa1a7fcc734d5813f3a9b550a8fba21..c598c65d2ef9e6421611f5e56362dcd9 #endif #if ENABLE(VIDEO_PRESENTATION_MODE) ASSERT(!m_playbackSessionManager); -@@ -1817,6 +1833,21 @@ WebProcessProxy& WebPageProxy::ensureRunningProcess() +@@ -1877,6 +1893,21 @@ WebProcessProxy& WebPageProxy::ensureRunningProcess() return m_legacyMainFrameProcess; } @@ -17521,14 +17617,14 @@ index 4dad8418faa1a7fcc734d5813f3a9b550a8fba21..c598c65d2ef9e6421611f5e56362dcd9 + loadParameters.request = WTFMove(request); + loadParameters.shouldOpenExternalURLsPolicy = WebCore::ShouldOpenExternalURLsPolicy::ShouldNotAllow; + loadParameters.shouldTreatAsContinuingLoad = ShouldTreatAsContinuingLoad::No; -+ m_legacyMainFrameProcess->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, IsPerformingHTTPFallback isPerformingHTTPFallback) + RefPtr WebPageProxy::loadRequest(ResourceRequest&& request, ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy, IsPerformingHTTPFallback isPerformingHTTPFallback, API::Object* userData) { if (m_isClosed) -@@ -2418,6 +2449,61 @@ void WebPageProxy::setControlledByAutomation(bool controlled) +@@ -2507,6 +2538,61 @@ void WebPageProxy::setControlledByAutomation(bool controlled) websiteDataStore().protectedNetworkProcess()->send(Messages::NetworkProcess::SetSessionIsControlledByAutomation(m_websiteDataStore->sessionID(), m_controlledByAutomation), 0); } @@ -17589,10 +17685,10 @@ index 4dad8418faa1a7fcc734d5813f3a9b550a8fba21..c598c65d2ef9e6421611f5e56362dcd9 + void WebPageProxy::createInspectorTarget(IPC::Connection& connection, const String& targetId, Inspector::InspectorTargetType type) { - MESSAGE_CHECK_BASE(!targetId.isEmpty(), &connection); -@@ -2659,6 +2745,24 @@ void WebPageProxy::updateActivityState(OptionSet flagsToUpdate) + MESSAGE_CHECK_BASE(!targetId.isEmpty(), connection); +@@ -2756,6 +2842,24 @@ void WebPageProxy::updateActivityState(OptionSet flagsToUpdate) bool wasVisible = isViewVisible(); - Ref pageClient = this->pageClient(); + RefPtr pageClient = this->pageClient(); internals().activityState.remove(flagsToUpdate); + + if (m_activeForAutomation) { @@ -17615,37 +17711,37 @@ index 4dad8418faa1a7fcc734d5813f3a9b550a8fba21..c598c65d2ef9e6421611f5e56362dcd9 if (flagsToUpdate & ActivityState::IsFocused && pageClient->isViewFocused()) internals().activityState.add(ActivityState::IsFocused); if (flagsToUpdate & ActivityState::WindowIsActive && pageClient->isViewWindowActive()) -@@ -3397,7 +3501,7 @@ void WebPageProxy::performDragOperation(DragData& dragData, const String& dragSt - grantAccessToCurrentPasteboardData(dragStorageName); - #endif +@@ -3522,7 +3626,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()) -@@ -3414,6 +3518,8 @@ void WebPageProxy::performDragControllerAction(DragControllerAction action, Drag + URL url { dragData.asURL() }; + if (url.protocolIsFile()) + protectedLegacyMainFrameProcess()->assumeReadAccessToBaseURL(*this, url.string(), [] { }); +@@ -3550,6 +3654,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); -@@ -3423,7 +3529,7 @@ void WebPageProxy::performDragControllerAction(DragControllerAction action, Drag + if (!m_pageClient) + return; +@@ -3561,7 +3667,7 @@ void WebPageProxy::performDragControllerAction(DragControllerAction action, Drag + dragData.setClientPosition(remoteUserInputEventData->transformedPoint); performDragControllerAction(action, dragData, remoteUserInputEventData->targetFrameID); }; - -#if PLATFORM(GTK) +#if PLATFORM(GTK) || PLATFORM(WPE) - UNUSED_PARAM(frameID); - String url = dragData.asURL(); - if (!url.isEmpty()) -@@ -3445,14 +3551,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(); @@ -17655,32 +17751,34 @@ index 4dad8418faa1a7fcc734d5813f3a9b550a8fba21..c598c65d2ef9e6421611f5e56362dcd9 +#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 -@@ -3473,6 +3599,24 @@ void WebPageProxy::dragEnded(const IntPoint& clientPosition, const IntPoint& glo +@@ -3624,6 +3751,24 @@ void WebPageProxy::dragEnded(const IntPoint& clientPosition, const IntPoint& glo setDragCaretRect({ }); } @@ -17705,24 +17803,34 @@ index 4dad8418faa1a7fcc734d5813f3a9b550a8fba21..c598c65d2ef9e6421611f5e56362dcd9 void WebPageProxy::didStartDrag() { if (!hasRunningProcess()) -@@ -3480,6 +3624,16 @@ void WebPageProxy::didStartDrag() +@@ -3631,6 +3776,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); ++ 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); ++ dragEntered(dragData); ++ } ++ ++ { ++#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 ++ dragUpdated(dragData); ++ } + } } void WebPageProxy::dragCancelled() -@@ -3622,26 +3776,47 @@ void WebPageProxy::processNextQueuedMouseEvent() +@@ -3778,26 +3943,47 @@ void WebPageProxy::processNextQueuedMouseEvent() process->startResponsivenessTimer(); } @@ -17782,7 +17890,7 @@ index 4dad8418faa1a7fcc734d5813f3a9b550a8fba21..c598c65d2ef9e6421611f5e56362dcd9 } void WebPageProxy::doAfterProcessingAllPendingMouseEvents(WTF::Function&& action) -@@ -3812,6 +3987,8 @@ void WebPageProxy::wheelEventHandlingCompleted(bool wasHandled) +@@ -3965,6 +4151,8 @@ void WebPageProxy::wheelEventHandlingCompleted(bool wasHandled) if (RefPtr automationSession = configuration().processPool().automationSession()) automationSession->wheelEventsFlushedForPage(*this); @@ -17791,7 +17899,7 @@ index 4dad8418faa1a7fcc734d5813f3a9b550a8fba21..c598c65d2ef9e6421611f5e56362dcd9 } void WebPageProxy::cacheWheelEventScrollingAccelerationCurve(const NativeWebWheelEvent& nativeWheelEvent) -@@ -3950,7 +4127,7 @@ static TrackingType mergeTrackingTypes(TrackingType a, TrackingType b) +@@ -4100,7 +4288,7 @@ static TrackingType mergeTrackingTypes(TrackingType a, TrackingType b) void WebPageProxy::updateTouchEventTracking(const WebTouchEvent& touchStartEvent) { @@ -17800,45 +17908,45 @@ index 4dad8418faa1a7fcc734d5813f3a9b550a8fba21..c598c65d2ef9e6421611f5e56362dcd9 for (auto& touchPoint : touchStartEvent.touchPoints()) { auto location = touchPoint.location(); auto update = [this, location](TrackingType& trackingType, EventTrackingRegions::EventType eventType) { -@@ -4557,6 +4734,7 @@ void WebPageProxy::receivedNavigationActionPolicyDecision(WebProcessProxy& proce +@@ -4723,6 +4911,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 { }); -@@ -5488,6 +5666,12 @@ void WebPageProxy::pageScaleFactorDidChange(IPC::Connection& connection, double +@@ -5671,6 +5860,12 @@ void WebPageProxy::pageScaleFactorDidChange(IPC::Connection& connection, double m_pageScaleFactor = scaleFactor; } +void WebPageProxy::viewScaleFactorDidChange(IPC::Connection& connection, double scaleFactor) +{ -+ MESSAGE_CHECK_BASE(scaleFactorIsValid(scaleFactor), &connection); ++ MESSAGE_CHECK_BASE(scaleFactorIsValid(scaleFactor), connection); + m_viewScaleFactor = scaleFactor; +} + void WebPageProxy::pluginScaleFactorDidChange(IPC::Connection& connection, double pluginScaleFactor) { - MESSAGE_CHECK_BASE(scaleFactorIsValid(pluginScaleFactor), &connection); -@@ -6063,6 +6247,7 @@ void WebPageProxy::didDestroyNavigationShared(Ref&& process, ui - Ref protectedPageClient { pageClient() }; + MESSAGE_CHECK_BASE(scaleFactorIsValid(pluginScaleFactor), connection); +@@ -6283,6 +6478,7 @@ void WebPageProxy::didDestroyNavigationShared(Ref&& process, We + RefPtr protectedPageClient { pageClient() }; m_navigationState->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) -@@ -6367,6 +6552,8 @@ void WebPageProxy::didFailProvisionalLoadForFrameShared(Ref&& p + void WebPageProxy::didStartProvisionalLoadForFrame(FrameIdentifier frameID, FrameInfoData&& frameInfo, ResourceRequest&& request, std::optional navigationID, URL&& url, URL&& unreachableURL, const UserData& userData, WallTime timestamp) +@@ -6603,6 +6799,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; -@@ -7692,6 +7879,7 @@ void WebPageProxy::createNewPage(IPC::Connection& connection, WindowFeatures&& w +@@ -7966,6 +8164,7 @@ void WebPageProxy::createNewPage(IPC::Connection& connection, WindowFeatures&& w if (RefPtr page = originatingFrameInfo->page()) openerAppInitiatedState = page->lastNavigationWasAppInitiated(); @@ -17846,7 +17954,7 @@ index 4dad8418faa1a7fcc734d5813f3a9b550a8fba21..c598c65d2ef9e6421611f5e56362dcd9 auto completionHandler = [ this, protectedThis = Ref { *this }, -@@ -7764,6 +7952,7 @@ void WebPageProxy::createNewPage(IPC::Connection& connection, WindowFeatures&& w +@@ -8043,6 +8242,7 @@ void WebPageProxy::createNewPage(IPC::Connection& connection, WindowFeatures&& w void WebPageProxy::showPage() { m_uiClient->showPage(this); @@ -17854,7 +17962,7 @@ index 4dad8418faa1a7fcc734d5813f3a9b550a8fba21..c598c65d2ef9e6421611f5e56362dcd9 } bool WebPageProxy::hasOpenedPage() const -@@ -7874,6 +8063,10 @@ void WebPageProxy::closePage() +@@ -8157,6 +8357,10 @@ void WebPageProxy::closePage() if (isClosed()) return; @@ -17863,9 +17971,9 @@ index 4dad8418faa1a7fcc734d5813f3a9b550a8fba21..c598c65d2ef9e6421611f5e56362dcd9 + m_activeContextMenu->hide(); +#endif WEBPAGEPROXY_RELEASE_LOG(Process, "closePage:"); - protectedPageClient()->clearAllEditCommands(); - m_uiClient->close(this); -@@ -7910,6 +8103,8 @@ void WebPageProxy::runJavaScriptAlert(IPC::Connection& connection, FrameIdentifi + if (RefPtr pageClient = this->pageClient()) + pageClient->clearAllEditCommands(); +@@ -8194,6 +8398,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 { @@ -17874,7 +17982,7 @@ index 4dad8418faa1a7fcc734d5813f3a9b550a8fba21..c598c65d2ef9e6421611f5e56362dcd9 page.m_uiClient->runJavaScriptAlert(page, message, frame, WTFMove(frameInfo), [reply = WTFMove(reply), completion = WTFMove(completion)]() mutable { reply(); completion(); -@@ -7931,6 +8126,8 @@ void WebPageProxy::runJavaScriptConfirm(IPC::Connection& connection, FrameIdenti +@@ -8215,6 +8421,8 @@ void WebPageProxy::runJavaScriptConfirm(IPC::Connection& connection, FrameIdenti if (RefPtr automationSession = configuration().processPool().automationSession()) automationSession->willShowJavaScriptDialog(*this); } @@ -17883,7 +17991,7 @@ index 4dad8418faa1a7fcc734d5813f3a9b550a8fba21..c598c65d2ef9e6421611f5e56362dcd9 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 { -@@ -7954,6 +8151,8 @@ void WebPageProxy::runJavaScriptPrompt(IPC::Connection& connection, FrameIdentif +@@ -8238,6 +8446,8 @@ void WebPageProxy::runJavaScriptPrompt(IPC::Connection& connection, FrameIdentif if (RefPtr automationSession = configuration().processPool().automationSession()) automationSession->willShowJavaScriptDialog(*this); } @@ -17892,7 +18000,7 @@ index 4dad8418faa1a7fcc734d5813f3a9b550a8fba21..c598c65d2ef9e6421611f5e56362dcd9 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 { -@@ -8070,6 +8269,8 @@ void WebPageProxy::runBeforeUnloadConfirmPanel(IPC::Connection& connection, Fram +@@ -8366,6 +8576,8 @@ void WebPageProxy::runBeforeUnloadConfirmPanel(IPC::Connection& connection, Fram return; } } @@ -17901,7 +18009,7 @@ index 4dad8418faa1a7fcc734d5813f3a9b550a8fba21..c598c65d2ef9e6421611f5e56362dcd9 // Since runBeforeUnloadConfirmPanel() can spin a nested run loop we need to turn off the responsiveness timer and the tryClose timer. protectedLegacyMainFrameProcess()->stopResponsivenessTimer(); -@@ -8564,6 +8765,11 @@ void WebPageProxy::resourceLoadDidCompleteWithError(ResourceLoadInfo&& loadInfo, +@@ -8936,6 +9148,11 @@ void WebPageProxy::resourceLoadDidCompleteWithError(ResourceLoadInfo&& loadInfo, } #if ENABLE(FULLSCREEN_API) @@ -17913,7 +18021,7 @@ index 4dad8418faa1a7fcc734d5813f3a9b550a8fba21..c598c65d2ef9e6421611f5e56362dcd9 WebFullScreenManagerProxy* WebPageProxy::fullScreenManager() { return m_fullScreenManager.get(); -@@ -8669,6 +8875,17 @@ void WebPageProxy::requestDOMPasteAccess(DOMPasteAccessCategory pasteAccessCateg +@@ -9041,6 +9258,17 @@ void WebPageProxy::requestDOMPasteAccess(DOMPasteAccessCategory pasteAccessCateg } } @@ -17922,7 +18030,7 @@ index 4dad8418faa1a7fcc734d5813f3a9b550a8fba21..c598c65d2ef9e6421611f5e56362dcd9 + 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; @@ -17931,7 +18039,7 @@ index 4dad8418faa1a7fcc734d5813f3a9b550a8fba21..c598c65d2ef9e6421611f5e56362dcd9 m_pageClient->requestDOMPasteAccess(pasteAccessCategory, requiresInteraction, elementRect, originIdentifier, WTFMove(completionHandler)); } -@@ -9550,6 +9767,8 @@ void WebPageProxy::mouseEventHandlingCompleted(std::optional event +@@ -9979,6 +10207,8 @@ void WebPageProxy::mouseEventHandlingCompleted(std::optional event if (RefPtr automationSession = configuration().processPool().automationSession()) automationSession->mouseEventsFlushedForPage(*this); didFinishProcessingAllPendingMouseEvents(); @@ -17940,7 +18048,7 @@ index 4dad8418faa1a7fcc734d5813f3a9b550a8fba21..c598c65d2ef9e6421611f5e56362dcd9 } } -@@ -9584,6 +9803,7 @@ void WebPageProxy::keyEventHandlingCompleted(std::optional eventTy +@@ -10014,6 +10244,7 @@ void WebPageProxy::keyEventHandlingCompleted(std::optional eventTy if (!canProcessMoreKeyEvents) { if (RefPtr automationSession = configuration().processPool().automationSession()) automationSession->keyboardEventsFlushedForPage(*this); @@ -17948,7 +18056,7 @@ index 4dad8418faa1a7fcc734d5813f3a9b550a8fba21..c598c65d2ef9e6421611f5e56362dcd9 } } -@@ -10000,7 +10220,10 @@ void WebPageProxy::dispatchProcessDidTerminate(ProcessTerminationReason reason) +@@ -10431,7 +10662,10 @@ void WebPageProxy::dispatchProcessDidTerminate(ProcessTerminationReason reason) { WEBPAGEPROXY_RELEASE_LOG_ERROR(Loading, "dispatchProcessDidTerminate: reason=%" PUBLIC_LOG_STRING, processTerminationReasonToString(reason).characters()); @@ -17960,15 +18068,7 @@ index 4dad8418faa1a7fcc734d5813f3a9b550a8fba21..c598c65d2ef9e6421611f5e56362dcd9 if (m_loaderClient) handledByClient = reason != ProcessTerminationReason::RequestedByClient && m_loaderClient->processDidCrash(*this); else -@@ -10390,6 +10613,7 @@ bool WebPageProxy::useGPUProcessForDOMRenderingEnabled() const - - WebPageCreationParameters WebPageProxy::creationParameters(WebProcessProxy& process, DrawingAreaProxy& drawingArea, std::optional&& remotePageParameters, bool isProcessSwap, RefPtr&& websitePolicies, std::optional&& mainFrameIdentifier) - { -+ - WebPageCreationParameters parameters; - - parameters.processDisplayName = configuration().processDisplayName(); -@@ -10618,6 +10842,8 @@ WebPageCreationParameters WebPageProxy::creationParameters(WebProcessProxy& proc +@@ -11065,6 +11299,8 @@ WebPageCreationParameters WebPageProxy::creationParameters(WebProcessProxy& proc parameters.httpsUpgradeEnabled = preferences().upgradeKnownHostsToHTTPSEnabled() ? m_configuration->httpsUpgradeEnabled() : false; @@ -17977,7 +18077,7 @@ index 4dad8418faa1a7fcc734d5813f3a9b550a8fba21..c598c65d2ef9e6421611f5e56362dcd9 #if PLATFORM(IOS) || PLATFORM(VISION) // FIXME: This is also being passed over the to WebProcess via the PreferencesStore. parameters.allowsDeprecatedSynchronousXMLHttpRequestDuringUnload = allowsDeprecatedSynchronousXMLHttpRequestDuringUnload(); -@@ -10778,8 +11004,42 @@ void WebPageProxy::allowGamepadAccess() +@@ -11229,8 +11465,42 @@ void WebPageProxy::allowGamepadAccess() #endif // ENABLE(GAMEPAD) @@ -18020,7 +18120,7 @@ index 4dad8418faa1a7fcc734d5813f3a9b550a8fba21..c598c65d2ef9e6421611f5e56362dcd9 if (negotiatedLegacyTLS == NegotiatedLegacyTLS::Yes) { m_navigationClient->shouldAllowLegacyTLS(*this, authenticationChallenge.get(), [this, protectedThis = Ref { *this }, authenticationChallenge] (bool shouldAllowLegacyTLS) { if (shouldAllowLegacyTLS) -@@ -10874,6 +11134,12 @@ void WebPageProxy::requestGeolocationPermissionForFrame(IPC::Connection& connect +@@ -11324,6 +11594,12 @@ void WebPageProxy::requestGeolocationPermissionForFrame(IPC::Connection& connect request->deny(); }; @@ -18033,7 +18133,7 @@ index 4dad8418faa1a7fcc734d5813f3a9b550a8fba21..c598c65d2ef9e6421611f5e56362dcd9 // 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 -@@ -10936,6 +11202,12 @@ void WebPageProxy::queryPermission(const ClientOrigin& clientOrigin, const Permi +@@ -11386,6 +11662,12 @@ void WebPageProxy::queryPermission(const ClientOrigin& clientOrigin, const Permi shouldChangeDeniedToPrompt = false; if (sessionID().isEphemeral()) { @@ -18046,7 +18146,7 @@ index 4dad8418faa1a7fcc734d5813f3a9b550a8fba21..c598c65d2ef9e6421611f5e56362dcd9 completionHandler(shouldChangeDeniedToPrompt ? PermissionState::Prompt : PermissionState::Denied); return; } -@@ -10950,6 +11222,12 @@ void WebPageProxy::queryPermission(const ClientOrigin& clientOrigin, const Permi +@@ -11400,6 +11682,12 @@ void WebPageProxy::queryPermission(const ClientOrigin& clientOrigin, const Permi return; } @@ -18060,7 +18160,7 @@ index 4dad8418faa1a7fcc734d5813f3a9b550a8fba21..c598c65d2ef9e6421611f5e56362dcd9 completionHandler(shouldChangeDeniedToPrompt ? PermissionState::Prompt : PermissionState::Denied); return; diff --git a/Source/WebKit/UIProcess/WebPageProxy.h b/Source/WebKit/UIProcess/WebPageProxy.h -index f0894c9608a72aeb87c5f5e76db60c2d740a7706..5d3b23739725b914f7eabfa6fdf62eb50a43950b 100644 +index 22132a82fb63a08f4f18a9b7b915d81f930429c8..880a013168f401f85aa1215a0fd0f61bdef5c20e 100644 --- a/Source/WebKit/UIProcess/WebPageProxy.h +++ b/Source/WebKit/UIProcess/WebPageProxy.h @@ -26,6 +26,7 @@ @@ -18070,8 +18170,8 @@ index f0894c9608a72aeb87c5f5e76db60c2d740a7706..5d3b23739725b914f7eabfa6fdf62eb5 +#include "APIWebsitePolicies.h" #include "MessageReceiver.h" #include - #include -@@ -37,6 +38,20 @@ + #include +@@ -38,6 +39,20 @@ #include #include #include @@ -18092,15 +18192,15 @@ index f0894c9608a72aeb87c5f5e76db60c2d740a7706..5d3b23739725b914f7eabfa6fdf62eb5 #if USE(DICTATION_ALTERNATIVES) #include -@@ -112,6 +127,7 @@ class DestinationColorSpace; - class DragData; +@@ -119,6 +134,7 @@ class DragData; + class Exception; class FloatPoint; class FloatQuad; +typedef HashMap> DragDataMap; class FloatRect; class FloatSize; class FontAttributeChanges; -@@ -448,6 +464,7 @@ class WebExtensionController; +@@ -461,6 +477,7 @@ class WebExtensionController; class WebFramePolicyListenerProxy; class WebFrameProxy; class WebFullScreenManagerProxy; @@ -18108,7 +18208,7 @@ index f0894c9608a72aeb87c5f5e76db60c2d740a7706..5d3b23739725b914f7eabfa6fdf62eb5 class WebInspectorUIProxy; class WebKeyboardEvent; class WebMouseEvent; -@@ -669,6 +686,8 @@ public: +@@ -684,6 +701,8 @@ public: void setControlledByAutomation(bool); WebPageInspectorController& inspectorController() { return *m_inspectorController; } @@ -18117,7 +18217,7 @@ index f0894c9608a72aeb87c5f5e76db60c2d740a7706..5d3b23739725b914f7eabfa6fdf62eb5 #if PLATFORM(IOS_FAMILY) void showInspectorIndication(); -@@ -702,6 +721,7 @@ public: +@@ -717,6 +736,7 @@ public: bool hasSleepDisabler() const; #if ENABLE(FULLSCREEN_API) @@ -18125,7 +18225,7 @@ index f0894c9608a72aeb87c5f5e76db60c2d740a7706..5d3b23739725b914f7eabfa6fdf62eb5 WebFullScreenManagerProxy* fullScreenManager(); API::FullscreenClient& fullscreenClient() const { return *m_fullscreenClient; } -@@ -790,6 +810,12 @@ public: +@@ -805,6 +825,12 @@ public: void setPageLoadStateObserver(std::unique_ptr&&); @@ -18135,26 +18235,26 @@ index f0894c9608a72aeb87c5f5e76db60c2d740a7706..5d3b23739725b914f7eabfa6fdf62eb5 + void setActiveForAutomation(std::optional active); + void logToStderr(const String& str); + - void initializeWebPage(); + void initializeWebPage(const WebCore::Site&, WebCore::SandboxFlags); void setDrawingArea(std::unique_ptr&&); -@@ -817,6 +843,7 @@ public: - void addPlatformLoadParameters(WebProcessProxy&, LoadParameters&); - RefPtr loadRequest(WebCore::ResourceRequest&&, IsPerformingHTTPFallback = IsPerformingHTTPFallback::No); - RefPtr loadRequest(WebCore::ResourceRequest&&, WebCore::ShouldOpenExternalURLsPolicy, API::Object* userData = nullptr, IsPerformingHTTPFallback = IsPerformingHTTPFallback::No); +@@ -832,6 +858,7 @@ public: + RefPtr loadRequest(WebCore::ResourceRequest&&); + RefPtr loadRequest(WebCore::ResourceRequest&&, WebCore::ShouldOpenExternalURLsPolicy); + RefPtr loadRequest(WebCore::ResourceRequest&&, WebCore::ShouldOpenExternalURLsPolicy, WebCore::IsPerformingHTTPFallback, 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); -@@ -884,6 +911,7 @@ public: - PageClient& pageClient() const; - Ref protectedPageClient() const; - RefPtr optionalProtectedPageClient() const; + 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); +@@ -898,6 +925,7 @@ public: + + 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); -@@ -1412,6 +1440,7 @@ public: +@@ -1427,6 +1455,7 @@ public: #endif void pageScaleFactorDidChange(IPC::Connection&, double); @@ -18162,7 +18262,7 @@ index f0894c9608a72aeb87c5f5e76db60c2d740a7706..5d3b23739725b914f7eabfa6fdf62eb5 void pluginScaleFactorDidChange(IPC::Connection&, double); void pluginZoomFactorDidChange(IPC::Connection&, double); -@@ -1496,14 +1525,20 @@ public: +@@ -1511,14 +1540,20 @@ public: void didStartDrag(); void dragCancelled(); void setDragCaretRect(const WebCore::IntRect&); @@ -18184,7 +18284,7 @@ index f0894c9608a72aeb87c5f5e76db60c2d740a7706..5d3b23739725b914f7eabfa6fdf62eb5 #endif void processDidBecomeUnresponsive(); -@@ -1737,6 +1772,7 @@ public: +@@ -1757,6 +1792,7 @@ public: void setViewportSizeForCSSViewportUnits(const WebCore::FloatSize&); WebCore::FloatSize viewportSizeForCSSViewportUnits() const; @@ -18192,17 +18292,16 @@ index f0894c9608a72aeb87c5f5e76db60c2d740a7706..5d3b23739725b914f7eabfa6fdf62eb5 void didReceiveAuthenticationChallengeProxy(Ref&&, NegotiatedLegacyTLS); void negotiatedLegacyTLS(); void didNegotiateModernTLS(const URL&); -@@ -1770,6 +1806,9 @@ public: +@@ -1790,6 +1826,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; } -+ RefPtr takeViewSnapshot(std::optional&&, ForceSoftwareCapturingViewportSnapshot) { return nullptr; } #endif void wrapCryptoKey(Vector&&, CompletionHandler>&&)>&&); -@@ -2676,6 +2715,7 @@ private: +@@ -2722,6 +2760,7 @@ private: RefPtr launchProcessForReload(); void requestNotificationPermission(const String& originString, CompletionHandler&&); @@ -18210,7 +18309,7 @@ index f0894c9608a72aeb87c5f5e76db60c2d740a7706..5d3b23739725b914f7eabfa6fdf62eb5 void didChangeContentSize(const WebCore::IntSize&); void didChangeIntrinsicContentSize(const WebCore::IntSize&); -@@ -3196,8 +3236,10 @@ private: +@@ -3237,8 +3276,10 @@ private: String m_overrideContentSecurityPolicy; RefPtr m_inspector; @@ -18221,7 +18320,7 @@ index f0894c9608a72aeb87c5f5e76db60c2d740a7706..5d3b23739725b914f7eabfa6fdf62eb5 std::unique_ptr m_fullScreenManager; std::unique_ptr m_fullscreenClient; #endif -@@ -3389,6 +3431,22 @@ private: +@@ -3433,6 +3474,22 @@ private: std::optional m_currentDragOperation; bool m_currentDragIsOverFileInput { false }; unsigned m_currentDragNumberOfFilesToBeAccepted { 0 }; @@ -18244,7 +18343,7 @@ index f0894c9608a72aeb87c5f5e76db60c2d740a7706..5d3b23739725b914f7eabfa6fdf62eb5 #endif bool m_mainFrameHasHorizontalScrollbar { false }; -@@ -3560,6 +3618,10 @@ private: +@@ -3604,6 +3661,10 @@ private: RefPtr messageBody; }; Vector m_pendingInjectedBundleMessages; @@ -18256,10 +18355,10 @@ index f0894c9608a72aeb87c5f5e76db60c2d740a7706..5d3b23739725b914f7eabfa6fdf62eb5 #if PLATFORM(IOS_FAMILY) && ENABLE(DEVICE_ORIENTATION) std::unique_ptr m_webDeviceOrientationUpdateProviderProxy; diff --git a/Source/WebKit/UIProcess/WebPageProxy.messages.in b/Source/WebKit/UIProcess/WebPageProxy.messages.in -index 445e6ec6cef315615499ef3d80e7490e142e33b2..ac73b9c7ec5380a0922a6622f8b3ebc983665332 100644 +index d5a3dbad2866cfb6980f2f47764eba902be9b60c..4872ea89b4d92649cef4681685239cf49b2bb30e 100644 --- a/Source/WebKit/UIProcess/WebPageProxy.messages.in +++ b/Source/WebKit/UIProcess/WebPageProxy.messages.in -@@ -29,6 +29,7 @@ messages -> WebPageProxy { +@@ -30,6 +30,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) @@ -18267,7 +18366,7 @@ index 445e6ec6cef315615499ef3d80e7490e142e33b2..ac73b9c7ec5380a0922a6622f8b3ebc9 DidChangeViewportProperties(struct WebCore::ViewportAttributes attributes) DidReceiveEvent(enum:uint8_t WebKit::WebEventType eventType, bool handled, struct std::optional remoteUserInputEventData) -@@ -182,6 +183,7 @@ messages -> WebPageProxy { +@@ -186,6 +187,7 @@ messages -> WebPageProxy { #endif PageScaleFactorDidChange(double scaleFactor) @@ -18275,7 +18374,7 @@ index 445e6ec6cef315615499ef3d80e7490e142e33b2..ac73b9c7ec5380a0922a6622f8b3ebc9 PluginScaleFactorDidChange(double zoomFactor) PluginZoomFactorDidChange(double zoomFactor) -@@ -305,10 +307,14 @@ messages -> WebPageProxy { +@@ -316,10 +318,14 @@ messages -> WebPageProxy { StartDrag(struct WebCore::DragItem dragItem, WebCore::ShareableBitmapHandle dragImage) SetPromisedDataForImage(String pasteboardName, WebCore::SharedMemory::Handle imageHandle, String filename, String extension, String title, String url, String visibleURL, WebCore::SharedMemory::Handle archiveHandle, String originIdentifier) #endif @@ -18292,10 +18391,10 @@ index 445e6ec6cef315615499ef3d80e7490e142e33b2..ac73b9c7ec5380a0922a6622f8b3ebc9 DidHandleDragStartRequest(bool started) DidHandleAdditionalDragItemsRequest(bool added) diff --git a/Source/WebKit/UIProcess/WebProcessCache.cpp b/Source/WebKit/UIProcess/WebProcessCache.cpp -index aaf99c896c32e6d886c1cc4d463a5979587f6d11..840d239c3eef0cbc020c98fdef57a2a57cddfd65 100644 +index 0bf66ef96022b16fe27cff481b41ebb369b5803a..9e3092647e880a75f7df26c361e220b8c89a603e 100644 --- a/Source/WebKit/UIProcess/WebProcessCache.cpp +++ b/Source/WebKit/UIProcess/WebProcessCache.cpp -@@ -88,6 +88,10 @@ bool WebProcessCache::canCacheProcess(WebProcessProxy& process) const +@@ -92,6 +92,10 @@ bool WebProcessCache::canCacheProcess(WebProcessProxy& process) const return false; } @@ -18307,10 +18406,10 @@ index aaf99c896c32e6d886c1cc4d463a5979587f6d11..840d239c3eef0cbc020c98fdef57a2a5 } diff --git a/Source/WebKit/UIProcess/WebProcessPool.cpp b/Source/WebKit/UIProcess/WebProcessPool.cpp -index a2b18816d8f78c04ac44a72090ef7a20fa9c5082..20d02d9cce0bea10a8f026b60c5109eb56031e33 100644 +index b5a8f1b2da36d5c53d46d3b6e0a63e34d41db5d3..4df997597541f123cbd3f7e0b2016a26223b9b8e 100644 --- a/Source/WebKit/UIProcess/WebProcessPool.cpp +++ b/Source/WebKit/UIProcess/WebProcessPool.cpp -@@ -426,10 +426,10 @@ void WebProcessPool::setAutomationClient(std::unique_ptr& +@@ -439,10 +439,10 @@ void WebProcessPool::setAutomationClient(std::unique_ptr& void WebProcessPool::setOverrideLanguages(Vector&& languages) { @@ -18323,7 +18422,7 @@ index a2b18816d8f78c04ac44a72090ef7a20fa9c5082..20d02d9cce0bea10a8f026b60c5109eb #if ENABLE(GPU_PROCESS) if (RefPtr gpuProcess = GPUProcessProxy::singletonIfCreated()) -@@ -437,9 +437,10 @@ void WebProcessPool::setOverrideLanguages(Vector&& languages) +@@ -450,9 +450,10 @@ void WebProcessPool::setOverrideLanguages(Vector&& languages) #endif #if USE(SOUP) for (Ref networkProcess : NetworkProcessProxy::allNetworkProcesses()) @@ -18335,7 +18434,7 @@ index a2b18816d8f78c04ac44a72090ef7a20fa9c5082..20d02d9cce0bea10a8f026b60c5109eb void WebProcessPool::fullKeyboardAccessModeChanged(bool fullKeyboardAccessEnabled) { -@@ -911,7 +912,7 @@ void WebProcessPool::initializeNewWebProcess(WebProcessProxy& process, WebsiteDa +@@ -926,7 +927,7 @@ void WebProcessPool::initializeNewWebProcess(WebProcessProxy& process, WebsiteDa #endif parameters.cacheModel = LegacyGlobalSettings::singleton().cacheModel(); @@ -18345,10 +18444,10 @@ index a2b18816d8f78c04ac44a72090ef7a20fa9c5082..20d02d9cce0bea10a8f026b60c5109eb parameters.urlSchemesRegisteredAsEmptyDocument = copyToVector(m_schemesToRegisterAsEmptyDocument); diff --git a/Source/WebKit/UIProcess/WebProcessProxy.cpp b/Source/WebKit/UIProcess/WebProcessProxy.cpp -index 1e5dbc576d4e79e5cab593ff9feba893784d9a26..b5fa55a4619cadd950d17ac8ff57b927ebbae98a 100644 +index a508a91e3659c59614314d0f8abf559cf36818d2..866887ee5dfd6bacc12ab2068411270daae0d43e 100644 --- a/Source/WebKit/UIProcess/WebProcessProxy.cpp +++ b/Source/WebKit/UIProcess/WebProcessProxy.cpp -@@ -185,6 +185,11 @@ Vector> WebProcessProxy::allProcesses() +@@ -190,6 +190,11 @@ Vector> WebProcessProxy::allProcesses() }); } @@ -18360,8 +18459,8 @@ index 1e5dbc576d4e79e5cab593ff9feba893784d9a26..b5fa55a4619cadd950d17ac8ff57b927 RefPtr WebProcessProxy::processForIdentifier(ProcessIdentifier identifier) { return allProcessMap().get(identifier); -@@ -541,6 +546,26 @@ void WebProcessProxy::getLaunchOptions(ProcessLauncher::LaunchOptions& launchOpt - if (WebKit::isInspectorProcessPool(processPool())) +@@ -548,6 +553,26 @@ void WebProcessProxy::getLaunchOptions(ProcessLauncher::LaunchOptions& launchOpt + if (WebKit::isInspectorProcessPool(protectedProcessPool())) launchOptions.extraInitializationData.add("inspector-process"_s, "1"_s); + /* playwright revert fb205fb, 50f8fee */ @@ -18388,10 +18487,10 @@ index 1e5dbc576d4e79e5cab593ff9feba893784d9a26..b5fa55a4619cadd950d17ac8ff57b927 if (isPrewarmed()) diff --git a/Source/WebKit/UIProcess/WebProcessProxy.h b/Source/WebKit/UIProcess/WebProcessProxy.h -index b575feaff2252c1de2421038368bf22e818ff1c3..5927617a280bc1663896944e8fe57dacda21aa8e 100644 +index 1b3c5b61e3e3a175632f2a92ca6947b05f05defc..38011071cef8dc662c617a18b16777956bad3868 100644 --- a/Source/WebKit/UIProcess/WebProcessProxy.h +++ b/Source/WebKit/UIProcess/WebProcessProxy.h -@@ -178,6 +178,7 @@ public: +@@ -170,6 +170,7 @@ public: static void forWebPagesWithOrigin(PAL::SessionID, const WebCore::SecurityOriginData&, const Function&); static Vector> allowedFirstPartiesForCookies(); @@ -18399,24 +18498,23 @@ index b575feaff2252c1de2421038368bf22e818ff1c3..5927617a280bc1663896944e8fe57dac void initializeWebProcess(WebProcessCreationParameters&&); -diff --git a/Source/WebKit/UIProcess/WebsiteData/Cocoa/WebsiteDataStoreCocoa.mm b/Source/WebKit/UIProcess/WebsiteData/Cocoa/WebsiteDataStoreCocoa.mm -index a36b8f78e0570ab44a9d908c52a75815433282f5..dde5ed6e8e54b2095ac77780a5f73233ca91ddbc 100644 ---- a/Source/WebKit/UIProcess/WebsiteData/Cocoa/WebsiteDataStoreCocoa.mm -+++ b/Source/WebKit/UIProcess/WebsiteData/Cocoa/WebsiteDataStoreCocoa.mm -@@ -228,7 +228,7 @@ std::optional WebsiteDataStore::useNetworkLoader() +diff --git a/Source/WebKit/UIProcess/WebScreenOrientationManagerProxy.h b/Source/WebKit/UIProcess/WebScreenOrientationManagerProxy.h +index ed7f2f625f8dad92c3cfc8f5eff8a8acee9d1b1d..5aac771624649e0d9ccb4e52754dfac1d6228c71 100644 +--- a/Source/WebKit/UIProcess/WebScreenOrientationManagerProxy.h ++++ b/Source/WebKit/UIProcess/WebScreenOrientationManagerProxy.h +@@ -26,6 +26,7 @@ + #pragma once - [[maybe_unused]] const auto isSafari = - #if PLATFORM(MAC) -- MacApplication::isSafari(); -+ WebCore::MacApplication::isSafari(); - #elif PLATFORM(IOS_FAMILY) - WebCore::IOSApplication::isMobileSafari() || WebCore::IOSApplication::isSafariViewService(); - #else + #include "MessageReceiver.h" ++#include "SharedPreferencesForWebProcess.h" + #include + #include + #include diff --git a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp -index 47fd107d304bdea638572b4fa15f5e7aad7be221..060f1d96972861ec8a59ec9d857769942c1773b3 100644 +index a4a20ceb0dec282cebb7bf7d5f901c8ab8acfe0f..1780fd157b48474a63b5a6a5a583f57b64789ff0 100644 --- a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp +++ b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp -@@ -306,7 +306,8 @@ SOAuthorizationCoordinator& WebsiteDataStore::soAuthorizationCoordinator(const W +@@ -311,7 +311,8 @@ SOAuthorizationCoordinator& WebsiteDataStore::soAuthorizationCoordinator(const W static Ref networkProcessForSession(PAL::SessionID sessionID) { @@ -18426,7 +18524,7 @@ index 47fd107d304bdea638572b4fa15f5e7aad7be221..060f1d96972861ec8a59ec9d85776994 if (sessionID.isEphemeral()) { // Reuse a previous persistent session network process for ephemeral sessions. for (auto& dataStore : allDataStores().values()) { -@@ -2295,6 +2296,12 @@ void WebsiteDataStore::originDirectoryForTesting(WebCore::ClientOrigin&& origin, +@@ -2324,6 +2325,12 @@ void WebsiteDataStore::originDirectoryForTesting(WebCore::ClientOrigin&& origin, protectedNetworkProcess()->websiteDataOriginDirectoryForTesting(m_sessionID, WTFMove(origin), type, WTFMove(completionHandler)); } @@ -18440,7 +18538,7 @@ index 47fd107d304bdea638572b4fa15f5e7aad7be221..060f1d96972861ec8a59ec9d85776994 void WebsiteDataStore::hasAppBoundSession(CompletionHandler&& completionHandler) const { diff --git a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h -index 849d9901ab75a80f2e919ec67c5c7b1de76e6bb4..85772ed50988e4b16cfbe975f8be725cb3b4cc6e 100644 +index fa85e9ad259588bb309c98c9550d4e46a487cbf1..092417a3e98eeddeea29b3d9b1c0131bac503386 100644 --- a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h +++ b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h @@ -97,6 +97,7 @@ class DeviceIdHashSaltStorage; @@ -18488,7 +18586,7 @@ index 849d9901ab75a80f2e919ec67c5c7b1de76e6bb4..85772ed50988e4b16cfbe975f8be725c void setNetworkProxySettings(WebCore::SoupNetworkProxySettings&&); const WebCore::SoupNetworkProxySettings& networkProxySettings() const { return m_networkProxySettings; } void setCookiePersistentStorage(const String&, SoupCookiePersistentStorageType); -@@ -394,6 +406,12 @@ public: +@@ -396,6 +408,12 @@ public: static const String& defaultBaseDataDirectory(); #endif @@ -18501,7 +18599,7 @@ index 849d9901ab75a80f2e919ec67c5c7b1de76e6bb4..85772ed50988e4b16cfbe975f8be725c void resetQuota(CompletionHandler&&); void resetStoragePersistedState(CompletionHandler&&); #if PLATFORM(IOS_FAMILY) -@@ -568,9 +586,11 @@ private: +@@ -570,9 +588,11 @@ private: WebCore::CurlProxySettings m_proxySettings; #endif @@ -18514,7 +18612,7 @@ index 849d9901ab75a80f2e919ec67c5c7b1de76e6bb4..85772ed50988e4b16cfbe975f8be725c WebCore::SoupNetworkProxySettings m_networkProxySettings; String m_cookiePersistentStoragePath; SoupCookiePersistentStorageType m_cookiePersistentStorageType { SoupCookiePersistentStorageType::SQLite }; -@@ -597,6 +617,10 @@ private: +@@ -599,6 +619,10 @@ private: RefPtr m_cookieStore; RefPtr m_networkProcess; @@ -18526,10 +18624,10 @@ index 849d9901ab75a80f2e919ec67c5c7b1de76e6bb4..85772ed50988e4b16cfbe975f8be725c std::unique_ptr m_soAuthorizationCoordinator; #endif diff --git a/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.cpp b/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.cpp -index 7c6139c6b0d8c7c3cddd08164317794a519a7b53..027d05bdd0e4bf94d70797ab195e656f81541300 100644 +index 351268d32fc4f25fe63021d1e6de62d0f2784ddb..0b8b0830a516085f0666dd04fa6be3c3dbde2e7c 100644 --- a/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.cpp +++ b/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.cpp -@@ -102,6 +102,14 @@ void GeoclueGeolocationProvider::stop() +@@ -105,6 +105,14 @@ void GeoclueGeolocationProvider::stop() } m_sourceType = LocationProviderSource::Unknown; @@ -18544,7 +18642,7 @@ index 7c6139c6b0d8c7c3cddd08164317794a519a7b53..027d05bdd0e4bf94d70797ab195e656f } void GeoclueGeolocationProvider::setEnableHighAccuracy(bool enabled) -@@ -374,6 +382,8 @@ void GeoclueGeolocationProvider::createGeoclueClient(const char* clientPath) +@@ -377,6 +385,8 @@ void GeoclueGeolocationProvider::createGeoclueClient(const char* clientPath) return; } @@ -18554,10 +18652,10 @@ index 7c6139c6b0d8c7c3cddd08164317794a519a7b53..027d05bdd0e4bf94d70797ab195e656f "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; @@ -18569,7 +18667,7 @@ 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..379d57818019b28afa25c9ca3de32fde8e6b5e67 +index 0000000000000000000000000000000000000000..ac01ad1653b22a0f22c45a196659e68fc22d7f32 --- /dev/null +++ b/Source/WebKit/UIProcess/glib/InspectorPlaywrightAgentClientGLib.cpp @@ -0,0 +1,201 @@ @@ -18744,7 +18842,7 @@ index 0000000000000000000000000000000000000000..379d57818019b28afa25c9ca3de32fde +{ + page.callAfterNextPresentationUpdate([protectedPage = Ref{ page }, clip = WTFMove(clip), nominalResolution, completionHandler = WTFMove(completionHandler)]() mutable { +#if PLATFORM(GTK) -+ RefPtr viewSnapshot = protectedPage->pageClient().takeViewSnapshot(WTFMove(clip), nominalResolution); ++ RefPtr viewSnapshot = protectedPage->pageClient()->takeViewSnapshot(WTFMove(clip), nominalResolution); + if (viewSnapshot) { + std::optional data = WebAutomationSession::platformGetBase64EncodedPNGData(*viewSnapshot); + if (data) { @@ -18754,11 +18852,11 @@ index 0000000000000000000000000000000000000000..379d57818019b28afa25c9ca3de32fde + } +#elif PLATFORM(WPE) +#if USE(SKIA) -+ sk_sp protectPtr = protectedPage->pageClient().takeViewSnapshot(WTFMove(clip), nominalResolution); ++ sk_sp protectPtr = protectedPage->pageClient()->takeViewSnapshot(WTFMove(clip), nominalResolution); + SkImage* surface = protectPtr.get(); +#elif USE(CAIRO) + cairo_surface_t* surface = nullptr; -+ RefPtr protectPtr = protectedPage->pageClient().takeViewSnapshot(WTFMove(clip), nominalResolution); ++ RefPtr protectPtr = protectedPage->pageClient()->takeViewSnapshot(WTFMove(clip), nominalResolution); + surface = protectPtr.get(); +#endif + if (surface) { @@ -18842,18 +18940,18 @@ index 0000000000000000000000000000000000000000..394f07e1754be52b7d503d5720cba5d3 + +#endif // ENABLE(REMOTE_INSPECTOR) diff --git a/Source/WebKit/UIProcess/gtk/AcceleratedBackingStore.h b/Source/WebKit/UIProcess/gtk/AcceleratedBackingStore.h -index b02c70d85fe1a93899640a8b909b0cf734d28b18..b1dc8e89eb265be81e083bf337109561e08cbf45 100644 +index ce120bac5e1c6018ec637181d4b9d08cf85a1f32..2fe169f2f2976a73d275cc089d0df32541dbdec3 100644 --- a/Source/WebKit/UIProcess/gtk/AcceleratedBackingStore.h +++ b/Source/WebKit/UIProcess/gtk/AcceleratedBackingStore.h -@@ -29,6 +29,7 @@ - #include +@@ -30,6 +30,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: +@@ -59,6 +60,8 @@ public: #else virtual bool paint(cairo_t*, const WebCore::IntRect&) = 0; #endif @@ -18863,10 +18961,10 @@ 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 85f211458d14702ca123c7926fadff016e1e5c87..668209bc4d8e2673f1abb1793ccf6d553a8a7da7 100644 +index 95f8f8a3cc14be838e5170a94ec4b2328afde62f..0a4af599d5e711b9c4eaa1c27cd7442121e07627 100644 --- a/Source/WebKit/UIProcess/gtk/AcceleratedBackingStoreDMABuf.cpp +++ b/Source/WebKit/UIProcess/gtk/AcceleratedBackingStoreDMABuf.cpp -@@ -686,4 +686,30 @@ RendererBufferFormat AcceleratedBackingStoreDMABuf::bufferFormat() const +@@ -707,4 +707,30 @@ RendererBufferFormat AcceleratedBackingStoreDMABuf::bufferFormat() const return buffer ? buffer->format() : RendererBufferFormat { }; } @@ -18898,10 +18996,10 @@ index 85f211458d14702ca123c7926fadff016e1e5c87..668209bc4d8e2673f1abb1793ccf6d55 + } // namespace WebKit diff --git a/Source/WebKit/UIProcess/gtk/AcceleratedBackingStoreDMABuf.h b/Source/WebKit/UIProcess/gtk/AcceleratedBackingStoreDMABuf.h -index ddf0af2e1f27561386fc734a300c18261d249a2e..7272fabe8b10e4ec1ccabf68cb7ce3dc671cc11b 100644 +index 8fa631f95a39298a9b4876b7d1b52bcacc3dc4af..d8c15d27ad8210739da490f32999b395fae9b65b 100644 --- a/Source/WebKit/UIProcess/gtk/AcceleratedBackingStoreDMABuf.h +++ b/Source/WebKit/UIProcess/gtk/AcceleratedBackingStoreDMABuf.h -@@ -92,6 +92,7 @@ private: +@@ -94,6 +94,7 @@ private: #else bool paint(cairo_t*, const WebCore::IntRect&) override; #endif @@ -18909,7 +19007,7 @@ index ddf0af2e1f27561386fc734a300c18261d249a2e..7272fabe8b10e4ec1ccabf68cb7ce3dc void unrealize() override; void update(const LayerTreeContext&) override; RendererBufferFormat bufferFormat() const override; -@@ -240,6 +241,9 @@ private: +@@ -242,6 +243,9 @@ private: RefPtr m_committedBuffer; WebCore::Region m_pendingDamageRegion; HashMap> m_buffers; @@ -18921,7 +19019,7 @@ index ddf0af2e1f27561386fc734a300c18261d249a2e..7272fabe8b10e4ec1ccabf68cb7ce3dc } // namespace WebKit diff --git a/Source/WebKit/UIProcess/gtk/InspectorTargetProxyGtk.cpp b/Source/WebKit/UIProcess/gtk/InspectorTargetProxyGtk.cpp new file mode 100644 -index 0000000000000000000000000000000000000000..5a255b0389470c4fd1baaff5e8e4882ea0218e27 +index 0000000000000000000000000000000000000000..bf78de1915940c2d3292514cf0fe4e682b636f70 --- /dev/null +++ b/Source/WebKit/UIProcess/gtk/InspectorTargetProxyGtk.cpp @@ -0,0 +1,48 @@ @@ -18962,9 +19060,9 @@ index 0000000000000000000000000000000000000000..5a255b0389470c4fd1baaff5e8e4882e +void InspectorTargetProxy::platformActivate(String& error) const +{ +#if USE(GTK4) -+ GtkWidget* parent = GTK_WIDGET(gtk_widget_get_root(m_page.viewWidget())); ++ GtkWidget* parent = GTK_WIDGET(gtk_widget_get_root(m_page->viewWidget())); +#else -+ GtkWidget* parent = gtk_widget_get_toplevel(m_page.viewWidget()); ++ GtkWidget* parent = gtk_widget_get_toplevel(m_page->viewWidget()); +#endif + if (WebCore::widgetIsOnscreenToplevelWindow(parent)) + gtk_window_present(GTK_WINDOW(parent)); @@ -19209,10 +19307,10 @@ index 2a17b59c9be6ecc76b0ec0a16d9f4866dffa0bf4..0d5c58a88b0e5197254d0eb5bd6eee04 m_primarySelectionOwner = frame; } diff --git a/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm b/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm -index 971ef8a8fccf3a4f3b9f40daece51ecd5e98dac8..67d19358c322c120ba40069af47695d089b0f90d 100644 +index fa78d12c9cbc8c3d0d3957afb98536d2a411e241..f13c49a59ba14eec2f1d345f2837f47dd62bc049 100644 --- a/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm +++ b/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm -@@ -503,6 +503,8 @@ IntRect PageClientImpl::rootViewToAccessibilityScreen(const IntRect& rect) +@@ -495,6 +495,8 @@ IntRect PageClientImpl::rootViewToAccessibilityScreen(const IntRect& rect) void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent& event, bool eventWasHandled) { @@ -19282,7 +19380,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..a5c8b963636b24d4bb8ad090e4a19aedecbf56c3 --- /dev/null +++ b/Source/WebKit/UIProcess/mac/InspectorPlaywrightAgentClientMac.mm @@ -0,0 +1,96 @@ @@ -19369,7 +19467,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; @@ -19384,7 +19482,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 @@ @@ -19423,7 +19521,7 @@ index 0000000000000000000000000000000000000000..721826c8c98fc85b68a4f45deaee69c1 + +void InspectorTargetProxy::platformActivate(String& error) const +{ -+ NSWindow* window = m_page.platformWindow(); ++ NSWindow* window = m_page->platformWindow(); + [window makeKeyAndOrderFront:nil]; +} + @@ -19431,19 +19529,19 @@ index 0000000000000000000000000000000000000000..721826c8c98fc85b68a4f45deaee69c1 + +#endif diff --git a/Source/WebKit/UIProcess/mac/PageClientImplMac.h b/Source/WebKit/UIProcess/mac/PageClientImplMac.h -index d41785036b86264bb2cecfdf6e9ee898caff55fa..4889dd4ddd0945760f457719e5b2917a2cd88ec7 100644 +index 48c64d82d9cb1274d4127b5b719a5a80d711c54c..5f27aafbb74af7b42aa7096b25e388bce43dec24 100644 --- a/Source/WebKit/UIProcess/mac/PageClientImplMac.h +++ b/Source/WebKit/UIProcess/mac/PageClientImplMac.h -@@ -54,6 +54,8 @@ class PageClientImpl final : public PageClientImplCocoa +@@ -58,6 +58,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: +@@ -174,6 +176,9 @@ private: void updateAcceleratedCompositingMode(const LayerTreeContext&) override; void didFirstLayerFlush(const LayerTreeContext&) override; @@ -19453,7 +19551,7 @@ index d41785036b86264bb2cecfdf6e9ee898caff55fa..4889dd4ddd0945760f457719e5b2917a RefPtr takeViewSnapshot(std::optional&&) override; RefPtr takeViewSnapshot(std::optional&&, ForceSoftwareCapturingViewportSnapshot) override; void wheelEventWasNotHandledByWebCore(const NativeWebWheelEvent&) override; -@@ -225,6 +230,10 @@ private: +@@ -229,6 +234,10 @@ private: void beganExitFullScreen(const WebCore::IntRect& initialFrame, const WebCore::IntRect& finalFrame) override; #endif @@ -19465,7 +19563,7 @@ index d41785036b86264bb2cecfdf6e9ee898caff55fa..4889dd4ddd0945760f457719e5b2917a 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 f07db2bb97f3ef841743b320644d1abfe1550071..759cadff7141386874e931d212fbbcd3b2a4544c 100644 +index 8af5332c0d74f1b6e057c142f830cfae4274c81a..e452dfa8ba0bf97770f091f1f69d6dc01ac03358 100644 --- a/Source/WebKit/UIProcess/mac/PageClientImplMac.mm +++ b/Source/WebKit/UIProcess/mac/PageClientImplMac.mm @@ -110,6 +110,13 @@ namespace WebKit { @@ -19522,7 +19620,7 @@ index f07db2bb97f3ef841743b320644d1abfe1550071..759cadff7141386874e931d212fbbcd3 } void PageClientImpl::toolTipChanged(const String& oldToolTip, const String& newToolTip) -@@ -479,6 +496,8 @@ IntRect PageClientImpl::rootViewToAccessibilityScreen(const IntRect& rect) +@@ -482,6 +499,8 @@ IntRect PageClientImpl::rootViewToAccessibilityScreen(const IntRect& rect) void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent& event, bool eventWasHandled) { @@ -19531,7 +19629,7 @@ index f07db2bb97f3ef841743b320644d1abfe1550071..759cadff7141386874e931d212fbbcd3 m_impl->doneWithKeyEvent(event.nativeEvent(), eventWasHandled); } -@@ -498,6 +517,8 @@ void PageClientImpl::computeHasVisualSearchResults(const URL& imageURL, Shareabl +@@ -501,6 +520,8 @@ void PageClientImpl::computeHasVisualSearchResults(const URL& imageURL, Shareabl RefPtr PageClientImpl::createPopupMenuProxy(WebPageProxy& page) { @@ -19540,7 +19638,7 @@ index f07db2bb97f3ef841743b320644d1abfe1550071..759cadff7141386874e931d212fbbcd3 return WebPopupMenuProxyMac::create(m_view, page.popupMenuClient()); } -@@ -639,6 +660,12 @@ CALayer *PageClientImpl::footerBannerLayer() const +@@ -642,6 +663,12 @@ CALayer *PageClientImpl::footerBannerLayer() const return m_impl->footerBannerLayer(); } @@ -19553,7 +19651,7 @@ index f07db2bb97f3ef841743b320644d1abfe1550071..759cadff7141386874e931d212fbbcd3 RefPtr PageClientImpl::takeViewSnapshot(std::optional&&) { return m_impl->takeViewSnapshot(); -@@ -834,6 +861,13 @@ void PageClientImpl::beganExitFullScreen(const IntRect& initialFrame, const IntR +@@ -837,6 +864,13 @@ void PageClientImpl::beganExitFullScreen(const IntRect& initialFrame, const IntR #endif // ENABLE(FULLSCREEN_API) @@ -19567,7 +19665,7 @@ index f07db2bb97f3ef841743b320644d1abfe1550071..759cadff7141386874e931d212fbbcd3 void PageClientImpl::navigationGestureDidBegin() { m_impl->dismissContentRelativeChildWindowsWithAnimation(true); -@@ -1022,6 +1056,9 @@ void PageClientImpl::requestScrollToRect(const WebCore::FloatRect& targetRect, c +@@ -1020,6 +1054,9 @@ void PageClientImpl::requestScrollToRect(const WebCore::FloatRect& targetRect, c bool PageClientImpl::windowIsFrontWindowUnderMouse(const NativeWebMouseEvent& event) { @@ -19608,7 +19706,7 @@ index e34faa8ae2933154efdbf0492a2f17af7a46f83b..54b509837bb767ac3ab28d1d7059462c bool showAfterPostProcessingContextData(); diff --git a/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.mm b/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.mm -index bb4822a1ca6c0b209baed338f267f366424f61c6..aaffc9579deda3a1f5c8fe71747833a5d0e2e8bf 100644 +index fa0104e2bf2d81e0c1d9a4f4765033dd84cc94db..a073c9203099f024dad99156582a20996065d019 100644 --- a/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.mm +++ b/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.mm @@ -504,6 +504,12 @@ void WebContextMenuProxyMac::getShareMenuItem(CompletionHandler +#import +#import "NativeWebKeyboardEvent.h" @@ -19790,7 +19892,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, @@ -19811,10 +19914,10 @@ index 0000000000000000000000000000000000000000..4ec25daff6a0c75e378eb25b2f2638e2 + +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/mac/WebViewImpl.h b/Source/WebKit/UIProcess/mac/WebViewImpl.h -index 70af75657e9db68616a0504c1e83b8b5add4d183..74da3138861a68d2f96f65692dacd976ed811558 100644 +index 6f9f2473b1722fb9f12e1f442aabc799181bd01e..d6f1e0984db6e8238d4bc66b04235d3bd20921ac 100644 --- a/Source/WebKit/UIProcess/mac/WebViewImpl.h +++ b/Source/WebKit/UIProcess/mac/WebViewImpl.h -@@ -535,6 +535,9 @@ public: +@@ -538,6 +538,9 @@ public: void provideDataForPasteboard(NSPasteboard *, NSString *type); NSArray *namesOfPromisedFilesDroppedAtDestination(NSURL *dropDestination); @@ -19825,10 +19928,10 @@ index 70af75657e9db68616a0504c1e83b8b5add4d183..74da3138861a68d2f96f65692dacd976 RefPtr takeViewSnapshot(ForceSoftwareCapturingViewportSnapshot); void saveBackForwardSnapshotForCurrentItem(); diff --git a/Source/WebKit/UIProcess/mac/WebViewImpl.mm b/Source/WebKit/UIProcess/mac/WebViewImpl.mm -index ce26b2abd67c28d0b562d8ba6d6df161f2677513..4f6b7ae5aad058e9b5378824576aa849341ea86a 100644 +index 5775c9c17409f13c967b0fdb2030e4bb65982c50..35f3e6bcd38f93066c5d54e906431ae1ba23fa9f 100644 --- a/Source/WebKit/UIProcess/mac/WebViewImpl.mm +++ b/Source/WebKit/UIProcess/mac/WebViewImpl.mm -@@ -2407,6 +2407,11 @@ WebCore::DestinationColorSpace WebViewImpl::colorSpace() +@@ -2416,6 +2416,11 @@ WebCore::DestinationColorSpace WebViewImpl::colorSpace() if (!m_colorSpace) m_colorSpace = [NSColorSpace sRGBColorSpace]; } @@ -19840,8 +19943,8 @@ index ce26b2abd67c28d0b562d8ba6d6df161f2677513..4f6b7ae5aad058e9b5378824576aa849 ASSERT(m_colorSpace); return WebCore::DestinationColorSpace { [m_colorSpace CGColorSpace] }; -@@ -4533,6 +4538,17 @@ ALLOW_DEPRECATED_DECLARATIONS_BEGIN - ALLOW_DEPRECATED_DECLARATIONS_END +@@ -4554,6 +4559,17 @@ static RetainPtr takeWindowSnapshot(CGSWindowID windowID, bool captu + return adoptCF(WebCore::cgWindowListCreateImage(CGRectNull, kCGWindowListOptionIncludingWindow, windowID, imageOptions)); } +// Paywright begin @@ -20216,10 +20319,10 @@ index 0000000000000000000000000000000000000000..8b474c730139b44a13c9d5b2d13ee204 + +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/win/WebView.cpp b/Source/WebKit/UIProcess/win/WebView.cpp -index 00961624b18e46877bbcaff5a4b7b07f616768d0..20a411eb20685f4b4c9fda3f0883b58681bb02ce 100644 +index 2946296119ea0f551f02d37c41a8e5cec5b74249..68501ee0817ce21f48300a74f05726882630b23c 100644 --- a/Source/WebKit/UIProcess/win/WebView.cpp +++ b/Source/WebKit/UIProcess/win/WebView.cpp -@@ -552,9 +552,8 @@ LRESULT WebView::onSizeEvent(HWND hwnd, UINT, WPARAM, LPARAM lParam, bool& handl +@@ -556,9 +556,8 @@ LRESULT WebView::onSizeEvent(HWND hwnd, UINT, WPARAM, LPARAM lParam, bool& handl { if (m_page) m_page->setIntrinsicDeviceScaleFactor(deviceScaleFactorForWindow(hwnd)); @@ -20233,7 +20336,7 @@ index 00961624b18e46877bbcaff5a4b7b07f616768d0..20a411eb20685f4b4c9fda3f0883b586 // 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 @@ @@ -20272,7 +20375,7 @@ 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); +} + @@ -20634,32 +20737,32 @@ index 0000000000000000000000000000000000000000..a7d88f8c745f95af21db71dcfce368ba + +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/wpe/WebPageProxyWPE.cpp b/Source/WebKit/UIProcess/wpe/WebPageProxyWPE.cpp -index ff2377628995b6095d7cd75f447d904847da0dc0..345aebe075a5b710303eeb8d46f94cf9dc901706 100644 +index 33c5c1918e7496f08166a168e9ba6b091515e547..bdc4976cb290ff608c6bcae37a2ec2addd59b221 100644 --- a/Source/WebKit/UIProcess/wpe/WebPageProxyWPE.cpp +++ b/Source/WebKit/UIProcess/wpe/WebPageProxyWPE.cpp -@@ -30,6 +30,7 @@ - #include "InputMethodState.h" +@@ -31,6 +31,7 @@ #include "PageClientImpl.h" + #include "UserMessage.h" #include "WebProcessProxy.h" +#include #include #if USE(ATK) diff --git a/Source/WebKit/UIProcess/wpe/WebPreferencesWPE.cpp b/Source/WebKit/UIProcess/wpe/WebPreferencesWPE.cpp -index 41307f5fe61b92785a493f68aeca475521708d55..f02e9d93c96ac6c0abedba9ced97b02f9250ac82 100644 +index 9b688ad328317fea4fd96ce66e9714bad8f0f937..402a36a9c565e13ec298aa7f014f0d9208ebddb7 100644 --- a/Source/WebKit/UIProcess/wpe/WebPreferencesWPE.cpp +++ b/Source/WebKit/UIProcess/wpe/WebPreferencesWPE.cpp -@@ -34,6 +34,10 @@ void WebPreferences::platformInitializeStore() +@@ -33,6 +33,10 @@ void WebPreferences::platformInitializeStore() + setAcceleratedCompositingEnabled(true); setForceCompositingMode(true); setThreadedScrollingEnabled(true); - -+ // Playwright override begin -+ setThreadedScrollingEnabled(false); -+ // Playwright override end + - #if USE(SKIA) - // FIXME: Expose this as a setting when we switch to Skia. - static const char* disableAccelerated2DCanvas = getenv("WEBKIT_DISABLE_ACCELERATED_2D_CANVAS"); ++ // Playwright override begin ++ setThreadedScrollingEnabled(false); ++ // Playwright override end + } + + } // namespace WebKit diff --git a/Source/WebKit/WPEPlatform/CMakeLists.txt b/Source/WebKit/WPEPlatform/CMakeLists.txt index 2b64d1b5b013d53b18b7757fe3b3f3d9a0501571..e8f28808f5ef0532319a4462fd285c0770d7ce52 100644 --- a/Source/WebKit/WPEPlatform/CMakeLists.txt @@ -20673,10 +20776,10 @@ index 2b64d1b5b013d53b18b7757fe3b3f3d9a0501571..e8f28808f5ef0532319a4462fd285c07 ${GLIB_GIO_LIBRARIES} ${GLIB_GOBJECT_LIBRARIES} diff --git a/Source/WebKit/WebKit.xcodeproj/project.pbxproj b/Source/WebKit/WebKit.xcodeproj/project.pbxproj -index 646a31824197a9354c3540d7c4cd7ec5bd837b83..796f8caad19b511e8aca49b41bf24079163a021f 100644 +index 9c88c517a12bbf6f81717d698754ddd2e93c0147..07c80602d45db2139cf7c2d651212e5171783467 100644 --- a/Source/WebKit/WebKit.xcodeproj/project.pbxproj +++ b/Source/WebKit/WebKit.xcodeproj/project.pbxproj -@@ -1572,6 +1572,7 @@ +@@ -1585,6 +1585,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 */; }; @@ -20684,7 +20787,7 @@ index 646a31824197a9354c3540d7c4cd7ec5bd837b83..796f8caad19b511e8aca49b41bf24079 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 */; }; -@@ -2403,6 +2404,18 @@ +@@ -2407,6 +2408,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 */; }; @@ -20703,7 +20806,7 @@ index 646a31824197a9354c3540d7c4cd7ec5bd837b83..796f8caad19b511e8aca49b41bf24079 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, ); }; }; -@@ -2491,6 +2504,8 @@ +@@ -2500,6 +2513,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 */; }; @@ -20712,9 +20815,9 @@ index 646a31824197a9354c3540d7c4cd7ec5bd837b83..796f8caad19b511e8aca49b41bf24079 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 */; }; -@@ -2511,6 +2526,9 @@ - EBA8D3B627A5E33F00CB7900 /* MockPushServiceConnection.mm in Sources */ = {isa = PBXBuildFile; fileRef = EBA8D3B027A5E33F00CB7900 /* MockPushServiceConnection.mm */; }; +@@ -2523,6 +2538,9 @@ EBA8D3B727A5E33F00CB7900 /* PushServiceConnection.mm in Sources */ = {isa = PBXBuildFile; fileRef = EBA8D3B127A5E33F00CB7900 /* PushServiceConnection.mm */; }; + EBDF51D12C8FBC4700EA1376 /* WebsitePushAndNotificationsEnabledPolicy.h in Headers */ = {isa = PBXBuildFile; fileRef = EBDF51CF2C8FBC4700EA1376 /* WebsitePushAndNotificationsEnabledPolicy.h */; }; ED82A7F2128C6FAF004477B3 /* WKBundlePageOverlay.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A22F0FF1289FCD90085E74F /* WKBundlePageOverlay.h */; settings = {ATTRIBUTES = (Private, ); }; }; + F303B849249A8D640031DE5C /* ScreencastEncoder.h in Headers */ = {isa = PBXBuildFile; fileRef = F303B848249A8D3A0031DE5C /* ScreencastEncoder.h */; }; + F33C7AC7249AD79C0018BE41 /* libwebrtc.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = F33C7AC6249AD79C0018BE41 /* libwebrtc.dylib */; }; @@ -20722,7 +20825,7 @@ index 646a31824197a9354c3540d7c4cd7ec5bd837b83..796f8caad19b511e8aca49b41bf24079 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 */; }; F416F1C02C5C3E360085D8DD /* WKScrollViewTrackingTapGestureRecognizer.h in Headers */ = {isa = PBXBuildFile; fileRef = F416F1BE2C5C3E360085D8DD /* WKScrollViewTrackingTapGestureRecognizer.h */; }; -@@ -6291,6 +6309,7 @@ +@@ -6282,6 +6300,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 = ""; }; @@ -20730,7 +20833,7 @@ index 646a31824197a9354c3540d7c4cd7ec5bd837b83..796f8caad19b511e8aca49b41bf24079 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 = ""; }; -@@ -7988,6 +8007,19 @@ +@@ -7969,6 +7988,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 = ""; }; @@ -20750,7 +20853,7 @@ index 646a31824197a9354c3540d7c4cd7ec5bd837b83..796f8caad19b511e8aca49b41bf24079 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 = ""; }; -@@ -8140,6 +8172,8 @@ +@@ -8129,6 +8161,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 = ""; }; @@ -20759,7 +20862,7 @@ index 646a31824197a9354c3540d7c4cd7ec5bd837b83..796f8caad19b511e8aca49b41bf24079 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 = ""; }; -@@ -8169,6 +8203,14 @@ +@@ -8162,6 +8196,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 = ""; }; @@ -20774,7 +20877,7 @@ index 646a31824197a9354c3540d7c4cd7ec5bd837b83..796f8caad19b511e8aca49b41bf24079 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 = ""; }; -@@ -8486,6 +8528,7 @@ +@@ -8487,6 +8529,7 @@ 3766F9EE189A1241003CF19B /* JavaScriptCore.framework in Frameworks */, 3766F9F1189A1254003CF19B /* libicucore.dylib in Frameworks */, 7B9FC5BB28A5233B007570E7 /* libWebKitPlatform.a in Frameworks */, @@ -20782,7 +20885,7 @@ index 646a31824197a9354c3540d7c4cd7ec5bd837b83..796f8caad19b511e8aca49b41bf24079 3766F9EF189A1244003CF19B /* QuartzCore.framework in Frameworks */, 37694525184FC6B600CDE21F /* Security.framework in Frameworks */, 37BEC4DD1948FC6A008B4286 /* WebCore.framework in Frameworks */, -@@ -11397,6 +11440,7 @@ +@@ -11435,6 +11478,7 @@ 99788ACA1F421DCA00C08000 /* _WKAutomationSessionConfiguration.mm */, 990D28A81C6404B000986977 /* _WKAutomationSessionDelegate.h */, 990D28AF1C65203900986977 /* _WKAutomationSessionInternal.h */, @@ -20790,7 +20893,7 @@ index 646a31824197a9354c3540d7c4cd7ec5bd837b83..796f8caad19b511e8aca49b41bf24079 5C4609E222430E4C009943C2 /* _WKContentRuleListAction.h */, 5C4609E322430E4D009943C2 /* _WKContentRuleListAction.mm */, 5C4609E422430E4D009943C2 /* _WKContentRuleListActionInternal.h */, -@@ -12714,6 +12758,7 @@ +@@ -12785,6 +12829,7 @@ E34B110C27C46BC6006D2F2E /* libWebCoreTestShim.dylib */, E34B110F27C46D09006D2F2E /* libWebCoreTestSupport.dylib */, DDE992F4278D06D900F60D26 /* libWebKitAdditions.a */, @@ -20798,7 +20901,7 @@ index 646a31824197a9354c3540d7c4cd7ec5bd837b83..796f8caad19b511e8aca49b41bf24079 57A9FF15252C6AEF006A2040 /* libWTF.a */, 5750F32A2032D4E500389347 /* LocalAuthentication.framework */, 570DAAB0230273D200E8FC04 /* NearField.framework */, -@@ -13286,6 +13331,12 @@ +@@ -13359,6 +13404,12 @@ children = ( 9197940423DBC4BB00257892 /* InspectorBrowserAgent.cpp */, 9197940323DBC4BB00257892 /* InspectorBrowserAgent.h */, @@ -20811,7 +20914,7 @@ index 646a31824197a9354c3540d7c4cd7ec5bd837b83..796f8caad19b511e8aca49b41bf24079 ); path = Agents; sourceTree = ""; -@@ -13294,6 +13345,7 @@ +@@ -13367,6 +13418,7 @@ isa = PBXGroup; children = ( A5D3504D1D78F0D2005124A9 /* RemoteWebInspectorUIProxyMac.mm */, @@ -20819,7 +20922,7 @@ index 646a31824197a9354c3540d7c4cd7ec5bd837b83..796f8caad19b511e8aca49b41bf24079 1CA8B935127C774E00576C2B /* WebInspectorUIProxyMac.mm */, 99A7ACE326012919006D57FD /* WKInspectorResourceURLSchemeHandler.h */, 99A7ACE42601291A006D57FD /* WKInspectorResourceURLSchemeHandler.mm */, -@@ -14013,6 +14065,7 @@ +@@ -14074,6 +14126,7 @@ E1513C65166EABB200149FCB /* AuxiliaryProcessProxy.h */, 46A2B6061E5675A200C3DEDA /* BackgroundProcessResponsivenessTimer.cpp */, 46A2B6071E5675A200C3DEDA /* BackgroundProcessResponsivenessTimer.h */, @@ -20827,7 +20930,7 @@ index 646a31824197a9354c3540d7c4cd7ec5bd837b83..796f8caad19b511e8aca49b41bf24079 5C6D69352AC3935D0099BDAF /* BrowsingContextGroup.cpp */, 5C6D69362AC3935D0099BDAF /* BrowsingContextGroup.h */, 5CA98549210BEB5A0057EB6B /* BrowsingWarning.h */, -@@ -14037,6 +14090,8 @@ +@@ -14098,6 +14151,8 @@ BC06F43912DBCCFB002D78DE /* GeolocationPermissionRequestProxy.cpp */, BC06F43812DBCCFB002D78DE /* GeolocationPermissionRequestProxy.h */, 2DD5A72A1EBF09A7009BA597 /* HiddenPageThrottlingAutoIncreasesCounter.h */, @@ -20836,7 +20939,7 @@ index 646a31824197a9354c3540d7c4cd7ec5bd837b83..796f8caad19b511e8aca49b41bf24079 5CEABA2B2333251400797797 /* LegacyGlobalSettings.cpp */, 5CEABA2A2333247700797797 /* LegacyGlobalSettings.h */, 31607F3819627002009B87DA /* LegacySessionStateCoding.h */, -@@ -14070,6 +14125,7 @@ +@@ -14131,6 +14186,7 @@ 1A0C227D2451130A00ED614D /* QuickLookThumbnailingSoftLink.mm */, 1AEE57232409F142002005D6 /* QuickLookThumbnailLoader.h */, 1AEE57242409F142002005D6 /* QuickLookThumbnailLoader.mm */, @@ -20844,16 +20947,16 @@ index 646a31824197a9354c3540d7c4cd7ec5bd837b83..796f8caad19b511e8aca49b41bf24079 5CCB54DC2A4FEA6A0005FAA8 /* RemotePageDrawingAreaProxy.cpp */, 5CCB54DB2A4FEA6A0005FAA8 /* RemotePageDrawingAreaProxy.h */, 5C907E9A294D507100B3402D /* RemotePageProxy.cpp */, -@@ -14170,6 +14226,8 @@ +@@ -14231,6 +14287,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 */, -@@ -14338,6 +14396,7 @@ +@@ -14406,6 +14464,7 @@ BC646C1911DD399F006455B0 /* WKBackForwardListItemRef.h */, BC646C1611DD399F006455B0 /* WKBackForwardListRef.cpp */, BC646C1711DD399F006455B0 /* WKBackForwardListRef.h */, @@ -20861,7 +20964,7 @@ index 646a31824197a9354c3540d7c4cd7ec5bd837b83..796f8caad19b511e8aca49b41bf24079 BCB9E24A1120E15C00A137E0 /* WKContext.cpp */, BCB9E2491120E15C00A137E0 /* WKContext.h */, 1AE52F9319201F6B00A1FA37 /* WKContextConfigurationRef.cpp */, -@@ -14915,6 +14974,9 @@ +@@ -14980,6 +15039,9 @@ 07EF07592745A8160066EA04 /* DisplayCaptureSessionManager.h */, 07EF07582745A8160066EA04 /* DisplayCaptureSessionManager.mm */, 7AFA6F682A9F57C50055322A /* DisplayLinkMac.cpp */, @@ -20871,7 +20974,7 @@ index 646a31824197a9354c3540d7c4cd7ec5bd837b83..796f8caad19b511e8aca49b41bf24079 1AFDE65B1954E8D500C48FFA /* LegacySessionStateCoding.cpp */, 0FCB4E5818BBE3D9000FCFC9 /* PageClientImplMac.h */, 0FCB4E5918BBE3D9000FCFC9 /* PageClientImplMac.mm */, -@@ -14938,6 +15000,8 @@ +@@ -15003,6 +15065,8 @@ E568B92120A3AC6A00E3C856 /* WebDataListSuggestionsDropdownMac.mm */, E55CD20124D09F1F0042DB9C /* WebDateTimePickerMac.h */, E55CD20224D09F1F0042DB9C /* WebDateTimePickerMac.mm */, @@ -20880,7 +20983,7 @@ index 646a31824197a9354c3540d7c4cd7ec5bd837b83..796f8caad19b511e8aca49b41bf24079 BC857E8512B71EBB00EDEB2E /* WebPageProxyMac.mm */, BC5750951268F3C6006F0F12 /* WebPopupMenuProxyMac.h */, BC5750961268F3C6006F0F12 /* WebPopupMenuProxyMac.mm */, -@@ -15969,6 +16033,7 @@ +@@ -16050,6 +16114,7 @@ 99788ACB1F421DDA00C08000 /* _WKAutomationSessionConfiguration.h in Headers */, 990D28AC1C6420CF00986977 /* _WKAutomationSessionDelegate.h in Headers */, 990D28B11C65208D00986977 /* _WKAutomationSessionInternal.h in Headers */, @@ -20888,7 +20991,7 @@ index 646a31824197a9354c3540d7c4cd7ec5bd837b83..796f8caad19b511e8aca49b41bf24079 5C4609E7224317B4009943C2 /* _WKContentRuleListAction.h in Headers */, 5C4609E8224317BB009943C2 /* _WKContentRuleListActionInternal.h in Headers */, 1A5704F81BE01FF400874AF1 /* _WKContextMenuElementInfo.h in Headers */, -@@ -16265,6 +16330,7 @@ +@@ -16355,6 +16420,7 @@ E170876C16D6CA6900F99226 /* BlobRegistryProxy.h in Headers */, 4F601432155C5AA2001FBDE0 /* BlockingResponseMap.h in Headers */, 1A5705111BE410E600874AF1 /* BlockSPI.h in Headers */, @@ -20896,7 +20999,7 @@ index 646a31824197a9354c3540d7c4cd7ec5bd837b83..796f8caad19b511e8aca49b41bf24079 5CA9854A210BEB640057EB6B /* BrowsingWarning.h in Headers */, A7E69BCC2B2117A100D43D3F /* BufferAndBackendInfo.h in Headers */, BC3065FA1259344E00E71278 /* CacheModel.h in Headers */, -@@ -16445,7 +16511,11 @@ +@@ -16537,7 +16603,11 @@ BC14DF77120B5B7900826C0C /* InjectedBundleScriptWorld.h in Headers */, CE550E152283752200D28791 /* InsertTextOptions.h in Headers */, 9197940523DBC4BB00257892 /* InspectorBrowserAgent.h in Headers */, @@ -20908,7 +21011,7 @@ index 646a31824197a9354c3540d7c4cd7ec5bd837b83..796f8caad19b511e8aca49b41bf24079 A5E391FD2183C1F800C8FB31 /* InspectorTargetProxy.h in Headers */, C5BCE5DF1C50766A00CDE3FA /* InteractionInformationAtPosition.h in Headers */, 2D4D2C811DF60BF3002EB10C /* InteractionInformationRequest.h in Headers */, -@@ -16706,6 +16776,7 @@ +@@ -16797,6 +16867,7 @@ 0F6E7C532C4C386800F1DB85 /* RemoteDisplayListRecorderMessages.h in Headers */, F451C0FE2703B263002BA03B /* RemoteDisplayListRecorderProxy.h in Headers */, A78A5FE42B0EB39E005036D3 /* RemoteImageBufferSetIdentifier.h in Headers */, @@ -20916,15 +21019,15 @@ index 646a31824197a9354c3540d7c4cd7ec5bd837b83..796f8caad19b511e8aca49b41bf24079 2D47B56D1810714E003A3AEE /* RemoteLayerBackingStore.h in Headers */, 2DDF731518E95060004F5A66 /* RemoteLayerBackingStoreCollection.h in Headers */, 1AB16AEA164B3A8800290D62 /* RemoteLayerTreeContext.h in Headers */, -@@ -16759,6 +16830,7 @@ +@@ -16850,6 +16921,7 @@ E1E552C516AE065F004ED653 /* SandboxInitializationParameters.h in Headers */, E36FF00327F36FBD004BE21A /* SandboxStateVariables.h in Headers */, 7BAB111025DD02B3008FC479 /* ScopedActiveMessageReceiveQueue.h in Headers */, + F303B849249A8D640031DE5C /* ScreencastEncoder.h in Headers */, 463BB93A2B9D08D80098C5C3 /* ScriptMessageHandlerIdentifier.h in Headers */, + F4E28A362C923814008120DD /* ScriptTelemetry.h in Headers */, E4D54D0421F1D72D007E3C36 /* ScrollingTreeFrameScrollingNodeRemoteIOS.h in Headers */, - 0F931C1C18C5711900DBA7C3 /* ScrollingTreeOverflowScrollingNodeIOS.h in Headers */, -@@ -17108,6 +17180,8 @@ +@@ -17203,6 +17275,8 @@ 939EF87029D112EE00F23AEE /* WebPageInlines.h in Headers */, 9197940823DBC4CB00257892 /* WebPageInspectorAgentBase.h in Headers */, A513F5402154A5D700662841 /* WebPageInspectorController.h in Headers */, @@ -20933,7 +21036,7 @@ index 646a31824197a9354c3540d7c4cd7ec5bd837b83..796f8caad19b511e8aca49b41bf24079 A543E30C215C8A8D00279CD9 /* WebPageInspectorTarget.h in Headers */, A543E30D215C8A9000279CD9 /* WebPageInspectorTargetController.h in Headers */, A543E307215AD13700279CD9 /* WebPageInspectorTargetFrontendChannel.h in Headers */, -@@ -19549,6 +19623,8 @@ +@@ -19623,6 +19697,8 @@ 522F792928D50EBB0069B45B /* HidService.mm in Sources */, 2749F6442146561B008380BF /* InjectedBundleNodeHandle.cpp in Sources */, 2749F6452146561E008380BF /* InjectedBundleRangeHandle.cpp in Sources */, @@ -20942,7 +21045,7 @@ index 646a31824197a9354c3540d7c4cd7ec5bd837b83..796f8caad19b511e8aca49b41bf24079 1CC94E532AC92F190045F269 /* JSWebExtensionAPIAction.mm in Sources */, 1C2B4D4B2A819D0D00C528A1 /* JSWebExtensionAPIAlarms.mm in Sources */, 1C8ECFEA2AFC7DCB007BAA62 /* JSWebExtensionAPICommands.mm in Sources */, -@@ -19994,6 +20070,8 @@ +@@ -20069,6 +20145,8 @@ E3816B3D27E2463A005EAFC0 /* WebMockContentFilterManager.cpp in Sources */, 31BA924D148831260062EDB5 /* WebNotificationManagerMessageReceiver.cpp in Sources */, 2DF6FE52212E110900469030 /* WebPage.cpp in Sources */, @@ -20952,10 +21055,10 @@ index 646a31824197a9354c3540d7c4cd7ec5bd837b83..796f8caad19b511e8aca49b41bf24079 BCBD3914125BB1A800D2C29F /* WebPageProxyMessageReceiver.cpp in Sources */, C0CE72A01B47E71D00BC0EC4 /* WebPageTestingMessageReceiver.cpp in Sources */, diff --git a/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp b/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp -index a3444c240790680684a09a929f5ba07d6e68e793..6167b8d1fb42bef261aed6bb3e9581447decb1a9 100644 +index d2b9d07144dab5d57cf91942d55a2b140a802d7f..4ad2d136a352af588c2c3efa8e470d9143afd03a 100644 --- a/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp +++ b/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp -@@ -233,6 +233,11 @@ void WebLoaderStrategy::scheduleLoad(ResourceLoader& resourceLoader, CachedResou +@@ -236,6 +236,11 @@ void WebLoaderStrategy::scheduleLoad(ResourceLoader& resourceLoader, CachedResou } #endif @@ -20967,7 +21070,7 @@ index a3444c240790680684a09a929f5ba07d6e68e793..6167b8d1fb42bef261aed6bb3e958144 #if ENABLE(PDFJS) if (tryLoadingUsingPDFJSHandler(resourceLoader, trackingParameters)) return; -@@ -242,12 +247,16 @@ void WebLoaderStrategy::scheduleLoad(ResourceLoader& resourceLoader, CachedResou +@@ -245,12 +250,16 @@ void WebLoaderStrategy::scheduleLoad(ResourceLoader& resourceLoader, CachedResou return; if (InspectorInstrumentationWebKit::shouldInterceptRequest(resourceLoader)) { @@ -20990,7 +21093,7 @@ index a3444c240790680684a09a929f5ba07d6e68e793..6167b8d1fb42bef261aed6bb3e958144 } WEBLOADERSTRATEGY_RELEASE_LOG("scheduleLoad: URL will be scheduled with the NetworkProcess"); -@@ -366,7 +375,8 @@ static void addParametersShared(const LocalFrame* frame, NetworkResourceLoadPara +@@ -369,7 +378,8 @@ static void addParametersShared(const LocalFrame* frame, NetworkResourceLoadPara parameters.linkPreconnectEarlyHintsEnabled = mainFrame->settings().linkPreconnectEarlyHintsEnabled(); } @@ -20998,9 +21101,9 @@ index a3444c240790680684a09a929f5ba07d6e68e793..6167b8d1fb42bef261aed6bb3e958144 +// 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); -@@ -382,7 +392,7 @@ void WebLoaderStrategy::scheduleLoadFromNetworkProcess(ResourceLoader& resourceL + auto identifier = *resourceLoader.identifier(); + +@@ -384,7 +394,7 @@ void WebLoaderStrategy::scheduleLoadFromNetworkProcess(ResourceLoader& resourceL RunLoop::main().dispatch([resourceLoader = Ref { resourceLoader }, error = blockedError(request)] { resourceLoader->didFail(error); }); @@ -21009,7 +21112,7 @@ index a3444c240790680684a09a929f5ba07d6e68e793..6167b8d1fb42bef261aed6bb3e958144 } } -@@ -392,7 +402,6 @@ void WebLoaderStrategy::scheduleLoadFromNetworkProcess(ResourceLoader& resourceL +@@ -394,7 +404,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); @@ -21017,7 +21120,7 @@ index a3444c240790680684a09a929f5ba07d6e68e793..6167b8d1fb42bef261aed6bb3e958144 loadParameters.identifier = identifier; loadParameters.webPageProxyID = trackingParameters.webPageProxyID; loadParameters.webPageID = trackingParameters.pageID; -@@ -482,14 +491,11 @@ void WebLoaderStrategy::scheduleLoadFromNetworkProcess(ResourceLoader& resourceL +@@ -484,14 +493,11 @@ void WebLoaderStrategy::scheduleLoadFromNetworkProcess(ResourceLoader& resourceL if (loadParameters.options.mode != FetchOptions::Mode::Navigate) { ASSERT(loadParameters.sourceOrigin); @@ -21035,7 +21138,7 @@ index a3444c240790680684a09a929f5ba07d6e68e793..6167b8d1fb42bef261aed6bb3e958144 loadParameters.isMainFrameNavigation = isMainFrameNavigation; if (loadParameters.isMainFrameNavigation && document) -@@ -529,6 +535,17 @@ void WebLoaderStrategy::scheduleLoadFromNetworkProcess(ResourceLoader& resourceL +@@ -532,6 +538,17 @@ void WebLoaderStrategy::scheduleLoadFromNetworkProcess(ResourceLoader& resourceL } ASSERT((loadParameters.webPageID && loadParameters.webFrameID) || loadParameters.clientCredentialPolicy == ClientCredentialPolicy::CannotAskClientForCredentials); @@ -21053,16 +21156,16 @@ index a3444c240790680684a09a929f5ba07d6e68e793..6167b8d1fb42bef261aed6bb3e958144 std::optional existingNetworkResourceLoadIdentifierToResume; if (loadParameters.isMainFrameNavigation) -@@ -544,7 +561,7 @@ void WebLoaderStrategy::scheduleLoadFromNetworkProcess(ResourceLoader& resourceL +@@ -547,7 +564,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) -@@ -954,7 +971,7 @@ void WebLoaderStrategy::didFinishPreconnection(WebCore::ResourceLoaderIdentifier +@@ -957,7 +974,7 @@ void WebLoaderStrategy::didFinishPreconnection(WebCore::ResourceLoaderIdentifier bool WebLoaderStrategy::isOnLine() const { @@ -21071,7 +21174,7 @@ index a3444c240790680684a09a929f5ba07d6e68e793..6167b8d1fb42bef261aed6bb3e958144 } void WebLoaderStrategy::addOnlineStateChangeListener(Function&& listener) -@@ -981,6 +998,11 @@ void WebLoaderStrategy::isResourceLoadFinished(CachedResource& resource, Complet +@@ -984,6 +1001,11 @@ void WebLoaderStrategy::isResourceLoadFinished(CachedResource& resource, Complet void WebLoaderStrategy::setOnLineState(bool isOnLine) { @@ -21083,7 +21186,7 @@ index a3444c240790680684a09a929f5ba07d6e68e793..6167b8d1fb42bef261aed6bb3e958144 if (m_isOnLine == isOnLine) return; -@@ -989,6 +1011,12 @@ void WebLoaderStrategy::setOnLineState(bool isOnLine) +@@ -992,6 +1014,12 @@ void WebLoaderStrategy::setOnLineState(bool isOnLine) listener(isOnLine); } @@ -21097,10 +21200,10 @@ index a3444c240790680684a09a929f5ba07d6e68e793..6167b8d1fb42bef261aed6bb3e958144 { 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 1a106f701e2756b5b5e19f828f97a7c0b838ae19..3ccc019ea234c414129f6c1209574f3b0387aa9f 100644 --- a/Source/WebKit/WebProcess/Network/WebLoaderStrategy.h +++ b/Source/WebKit/WebProcess/Network/WebLoaderStrategy.h -@@ -42,6 +42,7 @@ struct FetchOptions; +@@ -43,6 +43,7 @@ struct FetchOptions; namespace WebKit { class NetworkProcessConnection; @@ -21108,7 +21211,7 @@ index 3ef86cc236b8acee2fbe5d0b9c3fd755fcc9f06f..75951fc0fc5e4ef566582c0a49482793 class WebFrame; class WebPage; class WebURLSchemeTaskProxy; -@@ -89,6 +90,9 @@ public: +@@ -91,6 +92,9 @@ public: bool isOnLine() const final; void addOnlineStateChangeListener(Function&&) final; void setOnLineState(bool); @@ -21118,7 +21221,7 @@ index 3ef86cc236b8acee2fbe5d0b9c3fd755fcc9f06f..75951fc0fc5e4ef566582c0a49482793 void setExistingNetworkResourceLoadIdentifierToResume(std::optional existingNetworkResourceLoadIdentifierToResume) { m_existingNetworkResourceLoadIdentifierToResume = existingNetworkResourceLoadIdentifierToResume; } -@@ -141,6 +145,7 @@ private: +@@ -143,6 +147,7 @@ private: Vector> m_onlineStateChangeListeners; std::optional m_existingNetworkResourceLoadIdentifierToResume; bool m_isOnLine { true }; @@ -21127,10 +21230,10 @@ index 3ef86cc236b8acee2fbe5d0b9c3fd755fcc9f06f..75951fc0fc5e4ef566582c0a49482793 } // namespace WebKit diff --git a/Source/WebKit/WebProcess/Network/WebResourceLoader.cpp b/Source/WebKit/WebProcess/Network/WebResourceLoader.cpp -index 17a0fe5d7a30883febe90e9984d36d8ea222872a..c3804fd499bdd3663e32318012f507af6b434aa7 100644 +index c28454bdba0426c66f1f24c854761b2ddd0354a0..ee73825ca10881ebd8099af5382b7cb5c7efc882 100644 --- a/Source/WebKit/WebProcess/Network/WebResourceLoader.cpp +++ b/Source/WebKit/WebProcess/Network/WebResourceLoader.cpp -@@ -190,9 +190,6 @@ void WebResourceLoader::didReceiveResponse(ResourceResponse&& response, PrivateR +@@ -189,9 +189,6 @@ void WebResourceLoader::didReceiveResponse(ResourceResponse&& response, PrivateR } m_coreLoader->didReceiveResponse(inspectorResponse, [this, protectedThis = WTFMove(protectedThis), interceptedRequestIdentifier, policyDecisionCompletionHandler = WTFMove(policyDecisionCompletionHandler), overrideData = WTFMove(overrideData)]() mutable { @@ -21140,7 +21243,7 @@ index 17a0fe5d7a30883febe90e9984d36d8ea222872a..c3804fd499bdd3663e32318012f507af if (!m_coreLoader || !m_coreLoader->identifier()) { m_interceptController.continueResponse(interceptedRequestIdentifier); return; -@@ -210,6 +207,8 @@ void WebResourceLoader::didReceiveResponse(ResourceResponse&& response, PrivateR +@@ -209,6 +206,8 @@ void WebResourceLoader::didReceiveResponse(ResourceResponse&& response, PrivateR } }); }); @@ -21163,10 +21266,10 @@ index e314c2987e348a0abee8b655caff3a1c3b3c4564..882746d581bd8db6f2fad5944f09ee9f auto permissionHandlers = m_requestsPerOrigin.take(securityOrigin); diff --git a/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp b/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp -index 32407cfa8d0448e781c7255900558cee1d33f517..755a40c173a2b6a171dda45c21c4bc6867d070d9 100644 +index 39cd00b233c10fc167feed68802b9930bf88e7ca..0e1cd22bdebf9d57074d264104843ca76e820b98 100644 --- a/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp +++ b/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp -@@ -472,6 +472,8 @@ void WebChromeClient::addMessageToConsole(MessageSource source, MessageLevel lev +@@ -476,6 +476,8 @@ void WebChromeClient::addMessageToConsole(MessageSource source, MessageLevel lev { // Notify the bundle client. auto page = protectedPage(); @@ -21176,20 +21279,20 @@ index 32407cfa8d0448e781c7255900558cee1d33f517..755a40c173a2b6a171dda45c21c4bc68 } diff --git a/Source/WebKit/WebProcess/WebCoreSupport/WebDragClient.cpp b/Source/WebKit/WebProcess/WebCoreSupport/WebDragClient.cpp -index 2eb0886f13ed035a53b8eaa60605de4dfe53fbe3..c3a216415ab588cde1f1e524e0a232efa425717e 100644 +index dd03326b1ad54e1d363d722cfe86bb779fbeead1..71ab72cdff9870dbf9fc017e8e61ab73e1437262 100644 --- a/Source/WebKit/WebProcess/WebCoreSupport/WebDragClient.cpp +++ b/Source/WebKit/WebProcess/WebCoreSupport/WebDragClient.cpp -@@ -29,6 +29,9 @@ - #if ENABLE(DRAG_SUPPORT) +@@ -30,6 +30,9 @@ #include "WebPage.h" + #include +#include +#include +#include namespace WebKit { using namespace WebCore; -@@ -50,7 +53,7 @@ OptionSet WebDragClient::dragSourceActionMaskForPoint(const In +@@ -53,7 +56,7 @@ OptionSet WebDragClient::dragSourceActionMaskForPoint(const In return m_page->allowedDragSourceActions(); } @@ -21199,10 +21302,10 @@ index 2eb0886f13ed035a53b8eaa60605de4dfe53fbe3..c3a216415ab588cde1f1e524e0a232ef { } diff --git a/Source/WebKit/WebProcess/WebCoreSupport/WebLocalFrameLoaderClient.cpp b/Source/WebKit/WebProcess/WebCoreSupport/WebLocalFrameLoaderClient.cpp -index 1fbb60e23b8d338f05ff0daa284724afafe29282..a15410b5b492254634e1aa300af405ba12ae8e80 100644 +index 698a9701706dc8d6772f6565ae39c454fe8bf641..cafbb07349e175f786e3450a2132683e80273217 100644 --- a/Source/WebKit/WebProcess/WebCoreSupport/WebLocalFrameLoaderClient.cpp +++ b/Source/WebKit/WebProcess/WebCoreSupport/WebLocalFrameLoaderClient.cpp -@@ -1588,14 +1588,6 @@ void WebLocalFrameLoaderClient::transitionToCommittedForNewPage(InitializingIfra +@@ -1581,14 +1581,6 @@ void WebLocalFrameLoaderClient::transitionToCommittedForNewPage(InitializingIfra if (initializingIframe == InitializingIframe::No) webPage->scheduleFullEditorStateUpdate(); @@ -21358,7 +21461,7 @@ index 0000000000000000000000000000000000000000..226b3bf6bd83d2606a0aeb627ae9302f + +#endif // ENABLE(DRAG_SUPPORT) diff --git a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp -index c0dd11d1a720907b1e2d863302a483eea1d39765..a4ad1b5acc545d98aea99c58fc5a5ca3b3cc0bd9 100644 +index 3faeacda3c578ef2fd86e4a04b09315017dc47f1..174c8d565a00a519e12510c77fff4cfb63cc7a8a 100644 --- a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp +++ b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp @@ -39,6 +39,7 @@ @@ -21386,7 +21489,7 @@ index c0dd11d1a720907b1e2d863302a483eea1d39765..a4ad1b5acc545d98aea99c58fc5a5ca3 m_layerTreeHost->scrollNonCompositedContents(scrollRect); return; } -@@ -562,6 +573,11 @@ void DrawingAreaCoordinatedGraphics::enterAcceleratedCompositingMode(GraphicsLay +@@ -566,6 +577,11 @@ void DrawingAreaCoordinatedGraphics::enterAcceleratedCompositingMode(GraphicsLay m_scrollOffset = IntSize(); m_displayTimer.stop(); m_isWaitingForDidUpdate = false; @@ -21398,7 +21501,7 @@ index c0dd11d1a720907b1e2d863302a483eea1d39765..a4ad1b5acc545d98aea99c58fc5a5ca3 } void DrawingAreaCoordinatedGraphics::sendEnterAcceleratedCompositingModeIfNeeded() -@@ -619,6 +635,11 @@ void DrawingAreaCoordinatedGraphics::exitAcceleratedCompositingMode() +@@ -623,6 +639,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))); } @@ -21411,10 +21514,10 @@ index c0dd11d1a720907b1e2d863302a483eea1d39765..a4ad1b5acc545d98aea99c58fc5a5ca3 void DrawingAreaCoordinatedGraphics::scheduleDisplay() diff --git a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp -index dd57fd13ef1f45cd17192d6161f78b26cac68450..4723d7affc4a15b0cbb67f07dbfb35def9277465 100644 +index cc48ff93f937051121c38776e3c5c74ed6d70e8a..722dbdb4a881404f00a7e65e3e092f4873bde093 100644 --- a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp +++ b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp -@@ -202,8 +202,16 @@ void LayerTreeHost::scrollNonCompositedContents(const IntRect& rect) +@@ -205,8 +205,16 @@ void LayerTreeHost::scrollNonCompositedContents(const IntRect& rect) m_scrolledSinceLastFrame = true; auto* frameView = m_webPage.localMainFrameView(); @@ -21431,7 +21534,7 @@ index dd57fd13ef1f45cd17192d6161f78b26cac68450..4723d7affc4a15b0cbb67f07dbfb35de m_viewportController.didScroll(rect.location()); didChangeViewport(); -@@ -324,6 +332,10 @@ void LayerTreeHost::didChangeViewport() +@@ -327,6 +335,10 @@ void LayerTreeHost::didChangeViewport() if (!view->useFixedLayout()) view->notifyScrollPositionChanged(m_lastScrollPosition); @@ -21443,10 +21546,10 @@ index dd57fd13ef1f45cd17192d6161f78b26cac68450..4723d7affc4a15b0cbb67f07dbfb35de if (m_lastPageScaleFactor != pageScale) { diff --git a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.h b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.h -index 468d6f8c574ea3298e502ce5776b624e295d863d..7039d3b26db1586e8c2a693b8cf5daa36088dd33 100644 +index ea6ae1b9beff5a6bd4cbc7d52bcfa6da71a5b86b..efcdea566c836bcee32ff93546ee8a845dbe176b 100644 --- a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.h +++ b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.h -@@ -116,6 +116,13 @@ public: +@@ -117,6 +117,13 @@ public: #if PLATFORM(WPE) && USE(GBM) && ENABLE(WPE_PLATFORM) void preferredBufferFormatsDidChange(); #endif @@ -21461,7 +21564,7 @@ index 468d6f8c574ea3298e502ce5776b624e295d863d..7039d3b26db1586e8c2a693b8cf5daa3 #if USE(COORDINATED_GRAPHICS) void layerFlushTimerFired(); diff --git a/Source/WebKit/WebProcess/WebPage/DrawingArea.cpp b/Source/WebKit/WebProcess/WebPage/DrawingArea.cpp -index 94bbead87936ab599f79c3c08b260cad939aea62..5099d3d7bdf220aa5c8f3729a04397ec38cfed05 100644 +index 98f4dbab8521e1677047713093614d5ff6cb886f..e24a67b67bf9f1af419c98ecfb3e7ae034751c32 100644 --- a/Source/WebKit/WebProcess/WebPage/DrawingArea.cpp +++ b/Source/WebKit/WebProcess/WebPage/DrawingArea.cpp @@ -27,6 +27,7 @@ @@ -21472,7 +21575,7 @@ index 94bbead87936ab599f79c3c08b260cad939aea62..5099d3d7bdf220aa5c8f3729a04397ec #include "Logging.h" #include "WebPage.h" #include "WebPageCreationParameters.h" -@@ -112,6 +113,13 @@ void DrawingArea::tryMarkLayersVolatile(CompletionHandler&& completi +@@ -115,6 +116,13 @@ void DrawingArea::tryMarkLayersVolatile(CompletionHandler&& completi completionFunction(true); } @@ -21487,10 +21590,10 @@ index 94bbead87936ab599f79c3c08b260cad939aea62..5099d3d7bdf220aa5c8f3729a04397ec { if (m_hasRemovedMessageReceiver) diff --git a/Source/WebKit/WebProcess/WebPage/DrawingArea.h b/Source/WebKit/WebProcess/WebPage/DrawingArea.h -index 20749934a7fb69de11b85858e8e53f33b059d056..1818cb1fa27e7f3b66e4d17132f9c1ad062a2b9a 100644 +index c93d6787d88298575059259d2d45826e9d23c44b..3d42c0d9625e6c976f7cacda4bffcdf5c65b7217 100644 --- a/Source/WebKit/WebProcess/WebPage/DrawingArea.h +++ b/Source/WebKit/WebProcess/WebPage/DrawingArea.h -@@ -164,6 +164,9 @@ public: +@@ -165,6 +165,9 @@ public: virtual bool enterAcceleratedCompositingModeIfNeeded() = 0; virtual void backgroundColorDidChange() { }; #endif @@ -21501,7 +21604,7 @@ index 20749934a7fb69de11b85858e8e53f33b059d056..1818cb1fa27e7f3b66e4d17132f9c1ad #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 2a79682f5d837df439d4b18805a695d48341bd56..6423f2a8aa1fe0af5e2a4073f96538fde67b765c 100644 --- a/Source/WebKit/WebProcess/WebPage/WebCookieJar.cpp +++ b/Source/WebKit/WebProcess/WebPage/WebCookieJar.cpp @@ -44,6 +44,7 @@ @@ -21509,10 +21612,10 @@ index 935edefd61482ee2b268415ed24f7e2639bdbe35..8ec21eb117958c455ea4772907dd4e3a #include #include +#include + #include #include #include - #include -@@ -393,6 +394,12 @@ void WebCookieJar::removeChangeListener(const String& host, const WebCore::Cooki +@@ -429,6 +430,12 @@ void WebCookieJar::removeChangeListener(const String& host, const WebCore::Cooki } #endif @@ -21526,7 +21629,7 @@ 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 a050f15e1a9295ffccb46cb1b4fd801750f8ac33..49e28dceccb19d15149e54913fcc00b0544e9a7a 100644 --- a/Source/WebKit/WebProcess/WebPage/WebCookieJar.h +++ b/Source/WebKit/WebProcess/WebPage/WebCookieJar.h @@ -74,6 +74,8 @@ public: @@ -21539,10 +21642,10 @@ index b6e5283f51db82b60091320df44ef0bbf20c33c6..0d82fbb98b93e760cecf5fa7a41327d0 WebCookieJar(); diff --git a/Source/WebKit/WebProcess/WebPage/WebPage.cpp b/Source/WebKit/WebProcess/WebPage/WebPage.cpp -index ecf0f78a6a8eca46a535c512f6271bb0feb1806c..935fb837c97e2e9981a24375a8931e077c8e3e33 100644 +index f37c00d9bdbdc7754ce8bd75c1be645617a3e019..9242983dfaccb87fb55e8126a1c903c042cb480d 100644 --- a/Source/WebKit/WebProcess/WebPage/WebPage.cpp +++ b/Source/WebKit/WebProcess/WebPage/WebPage.cpp -@@ -234,6 +234,7 @@ +@@ -236,6 +236,7 @@ #include #include #include @@ -21550,7 +21653,7 @@ index ecf0f78a6a8eca46a535c512f6271bb0feb1806c..935fb837c97e2e9981a24375a8931e07 #include #include #include -@@ -1060,6 +1061,9 @@ WebPage::WebPage(PageIdentifier pageID, WebPageCreationParameters&& parameters) +@@ -1078,6 +1079,9 @@ WebPage::WebPage(PageIdentifier pageID, WebPageCreationParameters&& parameters) #endif #endif // HAVE(SANDBOX_STATE_FLAGS) @@ -21560,7 +21663,7 @@ index ecf0f78a6a8eca46a535c512f6271bb0feb1806c..935fb837c97e2e9981a24375a8931e07 updateThrottleState(); #if ENABLE(ACCESSIBILITY_ANIMATION_CONTROL) updateImageAnimationEnabled(); -@@ -2025,6 +2029,22 @@ void WebPage::loadDidCommitInAnotherProcess(WebCore::FrameIdentifier frameID, st +@@ -2043,6 +2047,22 @@ void WebPage::loadDidCommitInAnotherProcess(WebCore::FrameIdentifier frameID, st frame->loadDidCommitInAnotherProcess(layerHostingContextIdentifier); } @@ -21568,7 +21671,7 @@ index ecf0f78a6a8eca46a535c512f6271bb0feb1806c..935fb837c97e2e9981a24375a8931e07 +{ + WebFrame* frame = WebProcess::singleton().webFrame(frameID); + if (!frame) { -+ send(Messages::WebPageProxy::DidDestroyNavigation(loadParameters.navigationID)); ++ send(Messages::WebPageProxy::DidDestroyNavigation(*loadParameters.navigationID)); + return; + } + @@ -21582,8 +21685,8 @@ index ecf0f78a6a8eca46a535c512f6271bb0feb1806c..935fb837c97e2e9981a24375a8931e07 + 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()); -@@ -2209,7 +2229,9 @@ void WebPage::stopLoading() + WEBPAGE_RELEASE_LOG(Loading, "loadRequest: navigationID=%" PRIu64 ", shouldTreatAsContinuingLoad=%u, lastNavigationWasAppInitiated=%d, existingNetworkResourceLoadIdentifierToResume=%" PRIu64, loadParameters.navigationID ? loadParameters.navigationID->toUInt64() : 0, static_cast(loadParameters.shouldTreatAsContinuingLoad), loadParameters.request.isAppInitiated(), valueOrDefault(loadParameters.existingNetworkResourceLoadIdentifierToResume).toUInt64()); +@@ -2238,7 +2258,9 @@ void WebPage::stopLoading() void WebPage::stopLoadingDueToProcessSwap() { SetForScope isStoppingLoadingDueToProcessSwap(m_isStoppingLoadingDueToProcessSwap, true); @@ -21593,7 +21696,7 @@ index ecf0f78a6a8eca46a535c512f6271bb0feb1806c..935fb837c97e2e9981a24375a8931e07 } bool WebPage::defersLoading() const -@@ -2310,17 +2332,14 @@ void WebPage::setSize(const WebCore::IntSize& viewSize) +@@ -2339,17 +2361,14 @@ void WebPage::setSize(const WebCore::IntSize& viewSize) view->resize(viewSize); m_drawingArea->setNeedsDisplay(); @@ -21611,7 +21714,7 @@ index ecf0f78a6a8eca46a535c512f6271bb0feb1806c..935fb837c97e2e9981a24375a8931e07 void WebPage::sendViewportAttributesChanged(const ViewportArguments& viewportArguments) { RefPtr localMainFrame = dynamicDowncast(m_page->mainFrame()); -@@ -2345,20 +2364,18 @@ void WebPage::sendViewportAttributesChanged(const ViewportArguments& viewportArg +@@ -2374,20 +2393,18 @@ void WebPage::sendViewportAttributesChanged(const ViewportArguments& viewportArg ViewportAttributes attr = computeViewportAttributes(viewportArguments, minimumLayoutFallbackWidth, deviceWidth, deviceHeight, 1, m_viewSize); @@ -21639,7 +21742,7 @@ index ecf0f78a6a8eca46a535c512f6271bb0feb1806c..935fb837c97e2e9981a24375a8931e07 #if USE(COORDINATED_GRAPHICS) m_drawingArea->didChangeViewportAttributes(WTFMove(attr)); -@@ -2366,7 +2383,6 @@ void WebPage::sendViewportAttributesChanged(const ViewportArguments& viewportArg +@@ -2395,7 +2412,6 @@ void WebPage::sendViewportAttributesChanged(const ViewportArguments& viewportArg send(Messages::WebPageProxy::DidChangeViewportProperties(attr)); #endif } @@ -21647,7 +21750,7 @@ index ecf0f78a6a8eca46a535c512f6271bb0feb1806c..935fb837c97e2e9981a24375a8931e07 void WebPage::drawRect(GraphicsContext& graphicsContext, const IntRect& rect) { -@@ -2644,6 +2660,7 @@ void WebPage::scaleView(double scale) +@@ -2686,6 +2702,7 @@ void WebPage::scaleView(double scale) } m_page->setViewScaleFactor(scale); @@ -21655,7 +21758,7 @@ index ecf0f78a6a8eca46a535c512f6271bb0feb1806c..935fb837c97e2e9981a24375a8931e07 scalePage(pageScale, scrollPositionAtNewScale); } -@@ -2823,18 +2840,14 @@ void WebPage::viewportPropertiesDidChange(const ViewportArguments& viewportArgum +@@ -2865,18 +2882,14 @@ void WebPage::viewportPropertiesDidChange(const ViewportArguments& viewportArgum viewportConfigurationChanged(); #endif @@ -21675,7 +21778,7 @@ index ecf0f78a6a8eca46a535c512f6271bb0feb1806c..935fb837c97e2e9981a24375a8931e07 } #if !PLATFORM(IOS_FAMILY) -@@ -3556,6 +3569,13 @@ void WebPage::setLastKnownMousePosition(WebCore::FrameIdentifier frameID, IntPoi +@@ -3594,6 +3607,13 @@ void WebPage::setLastKnownMousePosition(WebCore::FrameIdentifier frameID, IntPoi frame->coreLocalFrame()->eventHandler().setLastKnownMousePosition(eventPoint, globalPoint); } @@ -21689,7 +21792,7 @@ index ecf0f78a6a8eca46a535c512f6271bb0feb1806c..935fb837c97e2e9981a24375a8931e07 void WebPage::flushDeferredDidReceiveMouseEvent() { if (auto info = std::exchange(m_deferredDidReceiveMouseEvent, std::nullopt)) -@@ -3840,6 +3860,97 @@ void WebPage::touchEvent(const WebTouchEvent& touchEvent, CompletionHandlersendMessageToTargetBackend(targetId, message); } @@ -21799,7 +21902,7 @@ index ecf0f78a6a8eca46a535c512f6271bb0feb1806c..935fb837c97e2e9981a24375a8931e07 void WebPage::insertNewlineInQuotedContent() { RefPtr frame = m_page->checkedFocusController()->focusedOrMainFrame(); -@@ -4163,6 +4279,7 @@ void WebPage::didCompletePageTransition() +@@ -4206,6 +4322,7 @@ void WebPage::didCompletePageTransition() void WebPage::show() { send(Messages::WebPageProxy::ShowPage()); @@ -21807,7 +21910,7 @@ index ecf0f78a6a8eca46a535c512f6271bb0feb1806c..935fb837c97e2e9981a24375a8931e07 } void WebPage::setIsTakingSnapshotsForApplicationSuspension(bool isTakingSnapshotsForApplicationSuspension) -@@ -5315,7 +5432,7 @@ NotificationPermissionRequestManager* WebPage::notificationPermissionRequestMana +@@ -5364,7 +5481,7 @@ NotificationPermissionRequestManager* WebPage::notificationPermissionRequestMana #if ENABLE(DRAG_SUPPORT) @@ -21816,7 +21919,7 @@ index ecf0f78a6a8eca46a535c512f6271bb0feb1806c..935fb837c97e2e9981a24375a8931e07 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) -@@ -7702,6 +7819,10 @@ void WebPage::didCommitLoad(WebFrame* frame) +@@ -7764,6 +7881,10 @@ void WebPage::didCommitLoad(WebFrame* frame) #endif flushDeferredDidReceiveMouseEvent(); @@ -21827,18 +21930,18 @@ index ecf0f78a6a8eca46a535c512f6271bb0feb1806c..935fb837c97e2e9981a24375a8931e07 } void WebPage::didFinishDocumentLoad(WebFrame& frame) -@@ -7983,6 +8104,9 @@ Ref WebPage::createDocumentLoader(LocalFrame& frame, const Resou +@@ -8047,6 +8168,9 @@ Ref WebPage::createDocumentLoader(LocalFrame& frame, const Resou WebsitePoliciesData::applyToDocumentLoader(WTFMove(*m_pendingWebsitePolicies), documentLoader); m_pendingWebsitePolicies = std::nullopt; } + } 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 1aeb8babedd2e3cd1524e910735564eb33f0aee3..abd8773409d4f2919d9477976b8e7fdb36a46d64 100644 +index dfee35656503c64f8f31ab52756aefdeef38b676..bd0d0408d17d0f4c1ff9352866e80c1ce27a19cd 100644 --- a/Source/WebKit/WebProcess/WebPage/WebPage.h +++ b/Source/WebKit/WebProcess/WebPage/WebPage.h @@ -71,6 +71,7 @@ @@ -21849,7 +21952,7 @@ index 1aeb8babedd2e3cd1524e910735564eb33f0aee3..abd8773409d4f2919d9477976b8e7fdb #include #include #include -@@ -1171,11 +1172,11 @@ public: +@@ -1178,11 +1179,11 @@ public: void clearSelection(); void restoreSelectionInFocusedEditableElement(); @@ -21863,7 +21966,7 @@ index 1aeb8babedd2e3cd1524e910735564eb33f0aee3..abd8773409d4f2919d9477976b8e7fdb 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&&); #endif -@@ -1190,6 +1191,9 @@ public: +@@ -1197,6 +1198,9 @@ public: void didStartDrag(); void dragCancelled(); OptionSet allowedDragSourceActions() const { return m_allowedDragSourceActions; } @@ -21873,7 +21976,7 @@ index 1aeb8babedd2e3cd1524e910735564eb33f0aee3..abd8773409d4f2919d9477976b8e7fdb #endif void beginPrinting(WebCore::FrameIdentifier, const PrintInfo&); -@@ -1265,8 +1269,11 @@ public: +@@ -1272,8 +1276,11 @@ public: void gestureEvent(WebCore::FrameIdentifier, const WebGestureEvent&, CompletionHandler, bool, std::optional)>&&); #endif @@ -21886,7 +21989,7 @@ index 1aeb8babedd2e3cd1524e910735564eb33f0aee3..abd8773409d4f2919d9477976b8e7fdb void dynamicViewportSizeUpdate(const DynamicViewportSizeUpdate&); bool scaleWasSetByUIProcess() const { return m_scaleWasSetByUIProcess; } void willStartUserTriggeredZooming(); -@@ -1415,6 +1422,7 @@ public: +@@ -1423,6 +1430,7 @@ public: void connectInspector(const String& targetId, Inspector::FrontendChannel::ConnectionType); void disconnectInspector(const String& targetId); void sendMessageToTargetBackend(const String& targetId, const String& message); @@ -21894,7 +21997,7 @@ index 1aeb8babedd2e3cd1524e910735564eb33f0aee3..abd8773409d4f2919d9477976b8e7fdb void insertNewlineInQuotedContent(); -@@ -1932,6 +1940,7 @@ private: +@@ -1940,6 +1948,7 @@ private: void createProvisionalFrame(ProvisionalFrameCreationParameters&&, WebCore::FrameIdentifier); void destroyProvisionalFrame(WebCore::FrameIdentifier); void loadDidCommitInAnotherProcess(WebCore::FrameIdentifier, std::optional); @@ -21902,7 +22005,7 @@ index 1aeb8babedd2e3cd1524e910735564eb33f0aee3..abd8773409d4f2919d9477976b8e7fdb void loadRequest(LoadParameters&&); [[noreturn]] void loadRequestWaitingForProcessLaunch(LoadParameters&&, URL&&, WebPageProxyIdentifier, bool); void loadData(LoadParameters&&); -@@ -1973,6 +1982,7 @@ private: +@@ -1981,6 +1990,7 @@ private: void updatePotentialTapSecurityOrigin(const WebTouchEvent&, bool wasHandled); #elif ENABLE(TOUCH_EVENTS) void touchEvent(const WebTouchEvent&, CompletionHandler, bool)>&&); @@ -21910,8 +22013,8 @@ index 1aeb8babedd2e3cd1524e910735564eb33f0aee3..abd8773409d4f2919d9477976b8e7fdb #endif void cancelPointer(WebCore::PointerID, const WebCore::IntPoint&); -@@ -2118,9 +2128,7 @@ private: - void addLayerForFindOverlay(CompletionHandler&&); +@@ -2126,9 +2136,7 @@ private: + void addLayerForFindOverlay(CompletionHandler)>&&); void removeLayerForFindOverlay(CompletionHandler&&); -#if USE(COORDINATED_GRAPHICS) @@ -21920,19 +22023,19 @@ index 1aeb8babedd2e3cd1524e910735564eb33f0aee3..abd8773409d4f2919d9477976b8e7fdb void didChangeSelectedIndexForActivePopupMenu(int32_t newIndex); void setTextForActivePopupMenu(int32_t index); -@@ -2723,6 +2731,7 @@ private: +@@ -2732,6 +2740,7 @@ private: UserActivity m_userActivity; - uint64_t m_pendingNavigationID { 0 }; -+ uint64_t m_pendingFrameNavigationID { 0 }; + Markable m_pendingNavigationID; ++ Markable m_pendingFrameNavigationID; std::optional m_pendingWebsitePolicies; bool m_mainFrameProgressCompleted { false }; diff --git a/Source/WebKit/WebProcess/WebPage/WebPage.messages.in b/Source/WebKit/WebProcess/WebPage/WebPage.messages.in -index b6eb40da55551bade5a33be56b4efa39d63446a9..543573bd1963d21aa209635524ae4fc1ccd32dde 100644 +index fbfdfdff9c550c9becb8ed9243755926450a9566..61d5056d4ef7d079cfdabc6d31c5a31e58cac907 100644 --- a/Source/WebKit/WebProcess/WebPage/WebPage.messages.in +++ b/Source/WebKit/WebProcess/WebPage/WebPage.messages.in -@@ -53,10 +53,13 @@ messages -> WebPage LegacyReceiver { +@@ -53,10 +53,13 @@ messages -> WebPage WantsAsyncDispatchMessage { MouseEvent(WebCore::FrameIdentifier frameID, WebKit::WebMouseEvent event, std::optional> sandboxExtensions) SetLastKnownMousePosition(WebCore::FrameIdentifier frameID, WebCore::IntPoint eventPoint, WebCore::IntPoint globalPoint); @@ -21971,7 +22074,7 @@ index b6eb40da55551bade5a33be56b4efa39d63446a9..543573bd1963d21aa209635524ae4fc1 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 +359,10 @@ GenerateSyntheticEditingCommand(enum:uint8_t WebKit::SyntheticEditingCommandType +@@ -354,10 +360,10 @@ GenerateSyntheticEditingCommand(enum:uint8_t WebKit::SyntheticEditingCommandType RemoveLayerForFindOverlay() -> () # Drag and drop. @@ -21984,7 +22087,7 @@ index b6eb40da55551bade5a33be56b4efa39d63446a9..543573bd1963d21aa209635524ae4fc1 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) PerformDragOperation(WebCore::DragData dragData, WebKit::SandboxExtensionHandle sandboxExtensionHandle, Vector sandboxExtensionsForUpload) -> (bool handled) #endif -@@ -366,6 +372,10 @@ GenerateSyntheticEditingCommand(enum:uint8_t WebKit::SyntheticEditingCommandType +@@ -367,6 +373,10 @@ GenerateSyntheticEditingCommand(enum:uint8_t WebKit::SyntheticEditingCommandType DragCancelled() #endif @@ -21996,10 +22099,10 @@ index b6eb40da55551bade5a33be56b4efa39d63446a9..543573bd1963d21aa209635524ae4fc1 RequestDragStart(WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, OptionSet allowedActionsMask) RequestAdditionalItemsForDragSession(WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, OptionSet allowedActionsMask) diff --git a/Source/WebKit/WebProcess/WebPage/mac/WebPageMac.mm b/Source/WebKit/WebProcess/WebPage/mac/WebPageMac.mm -index ab66a4946761a0219f7baede1ffeefb2c83a0e23..b4332b26fae11cd3ace28df86122e52dfe168727 100644 +index 51c574b2a235066fae685d32f10d06b4a5ae824f..6993e6d3e2e886dc97c0614841dd827655253c42 100644 --- a/Source/WebKit/WebProcess/WebPage/mac/WebPageMac.mm +++ b/Source/WebKit/WebProcess/WebPage/mac/WebPageMac.mm -@@ -802,21 +802,37 @@ String WebPage::platformUserAgent(const URL&) const +@@ -803,21 +803,37 @@ String WebPage::platformUserAgent(const URL&) const bool WebPage::hoverSupportedByPrimaryPointingDevice() const { @@ -22088,7 +22191,7 @@ index f17f5d719d892309ed9c7093384945866b5117b9..1dba47bbf0dbd0362548423a74b38034 } diff --git a/Source/WebKit/WebProcess/WebProcess.cpp b/Source/WebKit/WebProcess/WebProcess.cpp -index 7dac4718f46e365ce73a78f3c3a70a7170d74a6b..11568fefb3c9b5b54870f9fb1dd9142649cf2d29 100644 +index 095d4e45286cf0c9ffd5fc35c0de32bd0126b53b..4cf1db20e4c51777a443d3109227b7e4155a8145 100644 --- a/Source/WebKit/WebProcess/WebProcess.cpp +++ b/Source/WebKit/WebProcess/WebProcess.cpp @@ -89,6 +89,7 @@ @@ -22099,7 +22202,7 @@ index 7dac4718f46e365ce73a78f3c3a70a7170d74a6b..11568fefb3c9b5b54870f9fb1dd91426 #include #include #include -@@ -365,6 +366,14 @@ void WebProcess::initializeProcess(const AuxiliaryProcessInitializationParameter +@@ -367,6 +368,14 @@ void WebProcess::initializeProcess(const AuxiliaryProcessInitializationParameter { JSC::Options::AllowUnfinalizedAccessScope scope; JSC::Options::allowNonSPTagging() = false; @@ -22114,7 +22217,7 @@ index 7dac4718f46e365ce73a78f3c3a70a7170d74a6b..11568fefb3c9b5b54870f9fb1dd91426 JSC::Options::notifyOptionsChanged(); } -@@ -372,6 +381,8 @@ void WebProcess::initializeProcess(const AuxiliaryProcessInitializationParameter +@@ -374,6 +383,8 @@ void WebProcess::initializeProcess(const AuxiliaryProcessInitializationParameter platformInitializeProcess(parameters); updateCPULimit(); @@ -22137,10 +22240,10 @@ index d694170887445e2eed73340666bc4847aef4f9a6..6ced22d0953a39582285201e0946d68f - (void)touch:(WebEvent *)event { diff --git a/Source/WebKitLegacy/mac/WebView/WebView.mm b/Source/WebKitLegacy/mac/WebView/WebView.mm -index 66f631f8ccec43cb2d43843708370b4d7be950d3..9b99f45f670a37d223377718dc7b146d81c22608 100644 +index 016c97818b87a5205b1eebce2350c2d7bfb02975..4fe0109484f571bf1cfe53afb57bdf69a4fb295c 100644 --- a/Source/WebKitLegacy/mac/WebView/WebView.mm +++ b/Source/WebKitLegacy/mac/WebView/WebView.mm -@@ -3978,7 +3978,7 @@ + (void)_doNotStartObservingNetworkReachability +@@ -3983,7 +3983,7 @@ + (void)_doNotStartObservingNetworkReachability } #endif // PLATFORM(IOS_FAMILY) @@ -22149,7 +22252,7 @@ index 66f631f8ccec43cb2d43843708370b4d7be950d3..9b99f45f670a37d223377718dc7b146d - (NSArray *)_touchEventRegions { -@@ -4020,7 +4020,7 @@ - (NSArray *)_touchEventRegions +@@ -4025,7 +4025,7 @@ - (NSArray *)_touchEventRegions }).autorelease(); } @@ -22190,15 +22293,11 @@ index 0000000000000000000000000000000000000000..dd6a53e2d57318489b7e49dd7373706d + LIBVPX_LIBRARIES +) diff --git a/Source/cmake/OptionsGTK.cmake b/Source/cmake/OptionsGTK.cmake -index d2800f8a5bcdbd7521d47a591acfccb7d964bbaa..b761bbc3137ebc27d97aefdbf85ec4efc327bb37 100644 +index 4785f6f0c833e7fe5f9cefd586364ccebf41ec32..e77686f25ea59b03c68de4178532496d97898d46 100644 --- a/Source/cmake/OptionsGTK.cmake +++ b/Source/cmake/OptionsGTK.cmake -@@ -5,8 +5,13 @@ WEBKIT_OPTION_BEGIN() +@@ -7,6 +7,9 @@ SET_PROJECT_VERSION(2 47 0) - SET_PROJECT_VERSION(2 45 6) - -+set(ENABLE_WEBKIT_LEGACY OFF) -+ set(USER_AGENT_BRANDING "" CACHE STRING "Branding to add to user agent string") +set(CMAKE_THREAD_PREFER_PTHREAD TRUE) @@ -22207,7 +22306,7 @@ index d2800f8a5bcdbd7521d47a591acfccb7d964bbaa..b761bbc3137ebc27d97aefdbf85ec4ef find_package(Cairo 1.16.0 REQUIRED) find_package(LibGcrypt 1.7.0 REQUIRED) find_package(Libtasn1 REQUIRED) -@@ -23,6 +28,10 @@ find_package(ZLIB REQUIRED) +@@ -22,6 +25,10 @@ find_package(ZLIB REQUIRED) find_package(WebP REQUIRED COMPONENTS demux) find_package(ATSPI 2.5.3) @@ -22218,71 +22317,57 @@ index d2800f8a5bcdbd7521d47a591acfccb7d964bbaa..b761bbc3137ebc27d97aefdbf85ec4ef include(GStreamerDefinitions) include(FindGLibCompileResources) -@@ -82,14 +91,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) +@@ -64,6 +71,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) +@@ -148,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) -@@ -113,7 +122,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) -@@ -125,7 +134,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 ON) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_OFFSCREEN_CANVAS_IN_WORKERS PRIVATE ON) --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) -@@ -143,6 +152,14 @@ else () - WEBKIT_OPTION_DEFAULT_PORT_VALUE(USE_SKIA PRIVATE OFF) - 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_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/OptionsMSVC.cmake b/Source/cmake/OptionsMSVC.cmake +index 5828bf9ef028ea200a73f973937d610a8771f85f..27f9a084eb0eecd67287c14dc4c363d3042cf965 100644 +--- a/Source/cmake/OptionsMSVC.cmake ++++ b/Source/cmake/OptionsMSVC.cmake +@@ -45,6 +45,9 @@ string(REGEX REPLACE "/W3" "" CMAKE_C_FLAGS ${CMAKE_C_FLAGS}) + string(REGEX REPLACE "/W3" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) + WEBKIT_PREPEND_GLOBAL_COMPILER_FLAGS(/W4) + ++# Not apply class-level dllexport and dllimport attributes to inline member functions ++WEBKIT_PREPEND_GLOBAL_COMPILER_FLAGS(/Zc:dllexportInlines-) ++ + # Make sure incremental linking is turned off, as it creates unacceptably long link times. + string(REPLACE "/INCREMENTAL[:A-Z]+" "" CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS}) + string(REPLACE "/INCREMENTAL[:A-Z]+" "" CMAKE_EXE_LINKER_FLAGS_DEBUG ${CMAKE_EXE_LINKER_FLAGS_DEBUG}) diff --git a/Source/cmake/OptionsWPE.cmake b/Source/cmake/OptionsWPE.cmake -index 15000fb45706e5ed73137d21db2705645bc05f33..23889c60d34262f4eb9119e42b0685af2d9ecff1 100644 +index fc5429ddf2701ba46e4283a40392903b45400d1f..2c3aebacb3b12dad50d70aed66dc3ba25d91ba29 100644 --- a/Source/cmake/OptionsWPE.cmake +++ b/Source/cmake/OptionsWPE.cmake -@@ -3,6 +3,8 @@ include(VersioningUtils) - - SET_PROJECT_VERSION(2 45 3) - -+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) -@@ -21,6 +23,9 @@ find_package(WebP REQUIRED COMPONENTS demux) +@@ -21,6 +21,9 @@ find_package(WebP REQUIRED COMPONENTS demux) find_package(WPE REQUIRED) find_package(ZLIB REQUIRED) @@ -22292,43 +22377,15 @@ index 15000fb45706e5ed73137d21db2705645bc05f33..23889c60d34262f4eb9119e42b0685af WEBKIT_OPTION_BEGIN() SET_AND_EXPOSE_TO_BUILD(ENABLE_DEVELOPER_MODE ${DEVELOPER_MODE}) -@@ -32,11 +37,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) -+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) -@@ -52,7 +57,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) -@@ -66,7 +71,7 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_OFFSCREEN_CANVAS_IN_WORKERS PRIVATE ON) - 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) -@@ -85,6 +90,23 @@ if (WPE_VERSION VERSION_GREATER_EQUAL 1.13.90) +@@ -83,6 +86,28 @@ if (WPE_VERSION VERSION_GREATER_EQUAL 1.13.90) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_GAMEPAD PUBLIC ON) endif () -+# Playwright ++# Playwright begin. ++WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_PDFJS PUBLIC OFF) ++WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MEDIA_RECORDER PRIVATE OFF) ++WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_THUNDER PRIVATE OFF) ++ +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) @@ -22344,37 +22401,39 @@ index 15000fb45706e5ed73137d21db2705645bc05f33..23889c60d34262f4eb9119e42b0685af +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. -@@ -94,7 +116,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 Qt/QML plugin" PUBLIC ${ENABLE_DEVELOPER_MODE}) -+WEBKIT_OPTION_DEFINE(ENABLE_WPE_QT_API "Whether to enable support for the Qt/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) +@@ -112,6 +137,11 @@ WEBKIT_OPTION_CONFLICT(ENABLE_WPE_PLATFORM ENABLE_WPE_1_1_API) + WEBKIT_OPTION_DEPEND(ENABLE_DOCUMENTATION ENABLE_INTROSPECTION) + 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 b45a4ed539b8081010e3ed75f57943a07b37cb1c..65487ff4f95441d870b098e56392c760fa1649d8 100644 +index a09700bfc69078e82e426ea5cd13fd3d8e84d3ec..52055ce7362d4283a333e5a50f73a12c9b2fa5e2 100644 --- a/Source/cmake/OptionsWin.cmake +++ b/Source/cmake/OptionsWin.cmake -@@ -67,6 +67,29 @@ find_package(ZLIB 1.2.11 REQUIRED) +@@ -71,6 +71,27 @@ 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() ++set(LIBVPX_PACKAGE_PATH "C:\\vcpkg\\packages\\libvpx_x64-windows") +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 ++ REQUIRED + NO_DEFAULT_PATH +) +message(STATUS "Found LIBVPX_CUSTOM_LIBRARY = ${LIBVPX_CUSTOM_LIBRARY}") @@ -22391,7 +22450,7 @@ index b45a4ed539b8081010e3ed75f57943a07b37cb1c..65487ff4f95441d870b098e56392c760 WEBKIT_OPTION_BEGIN() # FIXME: Most of these options should not be public. -@@ -133,6 +156,14 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_FTPDIR PRIVATE OFF) +@@ -136,6 +157,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) @@ -22407,7 +22466,7 @@ index b45a4ed539b8081010e3ed75f57943a07b37cb1c..65487ff4f95441d870b098e56392c760 set(USE_ANGLE_EGL ON) diff --git a/Source/cmake/WebKitCompilerFlags.cmake b/Source/cmake/WebKitCompilerFlags.cmake -index edac4df57e4da23a7cdf234eefc3879c35c607c2..c80f8e1c80715cadfb8e64d055ef70c3a3da9f7c 100644 +index c3c683b650cbbbc882aad6d7f2202abe367af7f6..c3447733a57a09089f178f1c7c7763816252e94c 100644 --- a/Source/cmake/WebKitCompilerFlags.cmake +++ b/Source/cmake/WebKitCompilerFlags.cmake @@ -122,7 +122,7 @@ macro(WEBKIT_ADD_TARGET_CXX_FLAGS _target) @@ -22419,26 +22478,6 @@ index edac4df57e4da23a7cdf234eefc3879c35c607c2..c80f8e1c80715cadfb8e64d055ef70c3 if (DEVELOPER_MODE AND DEVELOPER_MODE_FATAL_WARNINGS) if (MSVC) set(FATAL_WARNINGS_FLAG /WX) -@@ -460,6 +460,19 @@ int main() { - unset(CMAKE_REQUIRED_FLAGS) - endif () - -+if (NOT WTF_PLATFORM_COCOA) -+ set(FLOAT16_TEST_SOURCE " -+int main() { -+ _Float16 f; -+ -+ f += static_cast<_Float16>(1.0); -+ -+ return 0; -+} -+ ") -+ check_cxx_source_compiles("${FLOAT16_TEST_SOURCE}" HAVE_FLOAT16) -+endif () -+ - if (CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND WTF_CPU_MIPS) - # Work around https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78176. - # This only manifests when executing 32-bit code on a 64-bit diff --git a/Tools/DumpRenderTree/DerivedSources.make b/Tools/DumpRenderTree/DerivedSources.make index 576835410df6deac60f0158f1d2d1ef1e5f4c78d..9b492cfe5fef8de340a80f2af70a7d68672ef2e4 100644 --- a/Tools/DumpRenderTree/DerivedSources.make @@ -22838,7 +22877,7 @@ index 8433f5360dc4a5f43b68b67192fb3d9bf5064cf1..9fa8f53e90fe5a32be1c8e7a9daa6404 g_clear_object(&interfaceSettings); diff --git a/Tools/MiniBrowser/wpe/main.cpp b/Tools/MiniBrowser/wpe/main.cpp -index 61760f3b78402bb79f68a4cbd20c5b96c038596c..7effb73d8b2f233bd7cb9aa27227af674eaee3f6 100644 +index f94a8a96c313860ef01de37108acc7c462d13795..f95494c1923c6a3fff562a4da73fa4be432ab3ec 100644 --- a/Tools/MiniBrowser/wpe/main.cpp +++ b/Tools/MiniBrowser/wpe/main.cpp @@ -49,6 +49,9 @@ static gboolean headlessMode; @@ -22947,7 +22986,7 @@ index 61760f3b78402bb79f68a4cbd20c5b96c038596c..7effb73d8b2f233bd7cb9aa27227af67 return newWebView; } -@@ -383,13 +431,101 @@ static WebKitFeature* findFeature(WebKitFeatureList* featureList, const char* id +@@ -395,13 +443,101 @@ static WebKitFeature* findFeature(WebKitFeatureList* featureList, const char* id return nullptr; } @@ -23050,7 +23089,7 @@ index 61760f3b78402bb79f68a4cbd20c5b96c038596c..7effb73d8b2f233bd7cb9aa27227af67 webkit_network_session_set_itp_enabled(networkSession, enableITP); if (proxy) { -@@ -416,10 +552,18 @@ static void activate(GApplication* application, WPEToolingBackends::ViewBackend* +@@ -428,10 +564,18 @@ static void activate(GApplication* application, WPEToolingBackends::ViewBackend* webkit_cookie_manager_set_persistent_storage(cookieManager, cookiesFile, storageType); } } @@ -23071,7 +23110,7 @@ index 61760f3b78402bb79f68a4cbd20c5b96c038596c..7effb73d8b2f233bd7cb9aa27227af67 webkit_website_data_manager_set_itp_enabled(manager, enableITP); if (proxy) { -@@ -450,6 +594,7 @@ static void activate(GApplication* application, WPEToolingBackends::ViewBackend* +@@ -462,6 +606,7 @@ static void activate(GApplication* application, WPEToolingBackends::ViewBackend* } #endif @@ -23079,7 +23118,7 @@ index 61760f3b78402bb79f68a4cbd20c5b96c038596c..7effb73d8b2f233bd7cb9aa27227af67 WebKitUserContentManager* userContentManager = nullptr; if (contentFilter) { GFile* contentFilterFile = g_file_new_for_commandline_arg(contentFilter); -@@ -528,6 +673,15 @@ static void activate(GApplication* application, WPEToolingBackends::ViewBackend* +@@ -540,6 +685,15 @@ static void activate(GApplication* application, WPEToolingBackends::ViewBackend* "autoplay", WEBKIT_AUTOPLAY_ALLOW, nullptr); @@ -23095,7 +23134,7 @@ index 61760f3b78402bb79f68a4cbd20c5b96c038596c..7effb73d8b2f233bd7cb9aa27227af67 auto* webView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW, "backend", viewBackend, "web-context", webContext, -@@ -572,8 +726,6 @@ static void activate(GApplication* application, WPEToolingBackends::ViewBackend* +@@ -584,8 +738,6 @@ static void activate(GApplication* application, WPEToolingBackends::ViewBackend* } #endif @@ -23104,7 +23143,7 @@ index 61760f3b78402bb79f68a4cbd20c5b96c038596c..7effb73d8b2f233bd7cb9aa27227af67 g_signal_connect(webContext, "automation-started", G_CALLBACK(automationStartedCallback), webView); g_signal_connect(webView, "permission-request", G_CALLBACK(decidePermissionRequest), nullptr); g_signal_connect(webView, "create", G_CALLBACK(createWebView), application); -@@ -585,16 +737,11 @@ static void activate(GApplication* application, WPEToolingBackends::ViewBackend* +@@ -597,16 +749,11 @@ static void activate(GApplication* application, WPEToolingBackends::ViewBackend* webkit_web_view_set_background_color(webView, &color); if (uriArguments) { @@ -23126,7 +23165,7 @@ index 61760f3b78402bb79f68a4cbd20c5b96c038596c..7effb73d8b2f233bd7cb9aa27227af67 webkit_web_view_load_uri(webView, "https://wpewebkit.org"); g_object_unref(webContext); -@@ -690,8 +837,14 @@ int main(int argc, char *argv[]) +@@ -702,8 +849,14 @@ int main(int argc, char *argv[]) } } @@ -23166,6 +23205,43 @@ index 470dcf1f4440f3db350fc416150a2e792a2777c7..31cbc0d22e63d054cf6edcc220a1c6b4 # WebInspectorUI must come after JavaScriptCore and WebCore but before WebKit and WebKit2 my $webKitIndex = first { $projects[$_] eq "Source/WebKitLegacy" } 0..$#projects; +diff --git a/Tools/Scripts/generate-bundle b/Tools/Scripts/generate-bundle +index 297e7d7b3d0889235e621f5c48c1f1480d9685ce..7a7eab25ec0f14ed53f8e688ec9916f2eb7b584e 100755 +--- a/Tools/Scripts/generate-bundle ++++ b/Tools/Scripts/generate-bundle +@@ -677,8 +677,6 @@ class BundleCreator(object): + # bunddle WebKit libraries + objects_to_copy.extend(self._get_webkit_binaries()) + objects_to_copy.append(self._get_webkit_lib('InjectedBundle')) +- if self._platform == 'wpe': +- objects_to_copy.append(self._get_webkit_lib('InspectorResources')) + # Bundle extra system related libraries + gio_modules = self._get_gio_modules() + objects_to_copy.extend(gio_modules) +@@ -766,6 +764,9 @@ class BundleCreator(object): + if needs_to_create_wpe_backend_symlink: + self._ensure_wpe_backend_symlink() + ++ if self._platform == 'wpe': ++ self._bundler.copy(os.path.join(self._buildpath, 'WebInspectorUI', 'DerivedSources', 'inspector.gresource')) ++ + # Now copy data files to share dir (only needed when bunding all for MiniBrowser). + # We assume that the system uses standard paths at /usr/share and /etc for this resources + # Every path should be checked and if some one is not found, then it will raise an error. +diff --git a/Tools/Scripts/webkitpy/binary_bundling/bundle.py b/Tools/Scripts/webkitpy/binary_bundling/bundle.py +index 2d0faab03b2376f3edd20bb2c727ed425ef1aec5..e315434a61800d102e2bac75ac651c3f9e77d3e7 100644 +--- a/Tools/Scripts/webkitpy/binary_bundling/bundle.py ++++ b/Tools/Scripts/webkitpy/binary_bundling/bundle.py +@@ -49,6 +49,9 @@ class BinaryBundler: + def set_use_sys_lib_directory(self, should_use_sys_lib_directory): + self._should_use_sys_lib_directory = should_use_sys_lib_directory + ++ def copy(self, orig_file): ++ shutil.copy(orig_file, self._destination_dir) ++ + def copy_and_maybe_strip_patchelf(self, orig_file, type='bin', strip=True, patchelf_removerpath=True, patchelf_nodefaultlib=False, patchelf_setinterpreter_relativepath=None, object_final_destination_dir=None): + """ This does the following: + 1. Copies the binary/lib (object) diff --git a/Tools/WebKitTestRunner/CMakeLists.txt b/Tools/WebKitTestRunner/CMakeLists.txt index 9e53f459e444b9c10fc5248f0e8059df6c1e0041..c17c875a7dd3ca05c4489578ab32378bca45a7c9 100644 --- a/Tools/WebKitTestRunner/CMakeLists.txt @@ -23182,10 +23258,10 @@ 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 c0cf0ce74772ae0a4bd20f7e0f48f94e0c689e52..4efa6437372b6ba4afd6a3e246ba118832337307 100644 +index c1212470ee2e66c2113958894fce3245bbedda5a..1a4ae8ce2386e07267445dbca6f46b5d4a7d26ac 100644 --- a/Tools/WebKitTestRunner/TestController.cpp +++ b/Tools/WebKitTestRunner/TestController.cpp -@@ -964,6 +964,7 @@ void TestController::createWebViewWithOptions(const TestOptions& options) +@@ -983,6 +983,7 @@ void TestController::createWebViewWithOptions(const TestOptions& options) 0, // requestStorageAccessConfirm shouldAllowDeviceOrientationAndMotionAccess, runWebAuthenticationPanel, @@ -23250,86 +23326,35 @@ index c1381b06b378a5121be926b1dfda3e5509bcd051..773e5882b6f2269201ca49433d0b6986 + } // namespace WTR diff --git a/Tools/glib/dependencies/apt b/Tools/glib/dependencies/apt -index 75ba644cfef7cc80b1520802e149dbc1246d9061..f8ed0d79ec83a2ad4362bf3d6b08a7584c8bc763 100644 +index 65f8c1ff14a68b7961328fcc284a837c92d4f205..a2731ce34b12b0de7b476a69f906244390cf0cce 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) +@@ -68,6 +68,7 @@ PACKAGES=( + libwebp-dev + libwoff-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..71cf6b873863e06d908c924e545eb9d94be52ab6 100644 ---- a/Tools/gtk/jhbuild.modules -+++ b/Tools/gtk/jhbuild.modules -@@ -252,10 +252,10 @@ - - - -- -+ hash="sha256:291c67725f36ed90ea43efff25064b69c5a2d1981488477c05c481a3b4b0c5aa"> - - - -@@ -378,9 +378,9 @@ - - libdrm.pc - - - diff --git a/Tools/jhbuild/jhbuild-minimal.modules b/Tools/jhbuild/jhbuild-minimal.modules -index 056c4052b8ee34b35262f7f24b11dae4168d3a02..4455a928333323afeff87f56a4ab983ecac7f2b6 100644 +index 9b006a3700330c89bfbb14906acb5cbaa160b8b2..74d34b7f90ac6bd444cf444e6911d53418aec901 100644 --- a/Tools/jhbuild/jhbuild-minimal.modules +++ b/Tools/jhbuild/jhbuild-minimal.modules -@@ -32,7 +32,6 @@ +@@ -10,6 +10,7 @@ + + + ++ + + + +@@ -28,11 +29,11 @@ + + + ++ + @@ -23337,17 +23362,91 @@ index 056c4052b8ee34b35262f7f24b11dae4168d3a02..4455a928333323afeff87f56a4ab983e -@@ -121,23 +120,22 @@ +@@ -40,40 +41,22 @@ + + + ++ ++ ++ ++ + ++ ++ + +- + +- +- +- +- +- +- +- +- +- +- +- +- +- + + + +@@ -117,6 +100,32 @@ + + + ++ ++ ++ ++ ++ ++ libaom.pc ++ ++ ++ ++ ++ libavif.pc ++ ++ ++ ++ ++ ++ ++ + libdrm.pc - +@@ -128,7 +137,6 @@ @@ -23355,35 +23454,6 @@ index 056c4052b8ee34b35262f7f24b11dae4168d3a02..4455a928333323afeff87f56a4ab983e - - -- -+ hash="sha256:291c67725f36ed90ea43efff25064b69c5a2d1981488477c05c481a3b4b0c5aa"> - - - -@@ -233,6 +231,16 @@ - - - -+ -+ -+ libdrm.pc -+ -+ -+ - - - - -- -+ hash="sha256:291c67725f36ed90ea43efff25064b69c5a2d1981488477c05c481a3b4b0c5aa"> - - - -@@ -161,9 +161,9 @@ - - libdrm.pc - - - -@@ -334,6 +334,16 @@ - hash="sha256:c625a83b4838befc8cafcd54e3619946515d9e44d63d61c4adf7f5513ddfbebf"/> - - -+ -+ -+ libdrm.pc -+ -+ -+ - - +- `name` <[string]|[RegExp]|[Array]<[string]|[RegExp]>> Expected accessible name. @@ -2109,7 +2109,7 @@ Expected options currently selected. * langs: - alias-java: matchesAriaSnapshot -Asserts that the target element matches the given accessibility snapshot. +Asserts that the target element matches the given [accessibility snapshot](../aria-snapshots.md). **Usage** @@ -2159,3 +2159,6 @@ assertThat(page.locator("body")).matchesAriaSnapshot(""" ### option: LocatorAssertions.toMatchAriaSnapshot.timeout = %%-js-assertions-timeout-%% * since: v1.49 + +### option: LocatorAssertions.toMatchAriaSnapshot.timeout = %%-csharp-java-python-assertions-timeout-%% +* since: v1.49 diff --git a/docs/src/api/class-tracing.md b/docs/src/api/class-tracing.md index 065896925f..5a89dbdac1 100644 --- a/docs/src/api/class-tracing.md +++ b/docs/src/api/class-tracing.md @@ -281,6 +281,80 @@ given name prefix inside the [`option: BrowserType.launch.tracesDir`] directory To specify the final trace zip file name, you need to pass `path` option to [`method: Tracing.stopChunk`] instead. +## async method: Tracing.group +* since: v1.49 + +:::caution +Use `test.step` instead when available. +::: + +Creates a new group within the trace, assigning any subsequent API calls to this group, until [`method: Tracing.groupEnd`] is called. Groups can be nested and will be visible in the trace viewer. + +**Usage** + +```js +// use test.step instead +await test.step('Log in', async () => { + // ... +}); +``` + +```java +// All actions between group and groupEnd +// will be shown in the trace viewer as a group. +page.context().tracing.group("Open Playwright.dev > API"); +page.navigate("https://playwright.dev/"); +page.getByRole(AriaRole.LINK, new Page.GetByRoleOptions().setName("API")).click(); +page.context().tracing.groupEnd(); +``` + +```python sync +# All actions between group and group_end +# will be shown in the trace viewer as a group. +page.context.tracing.group("Open Playwright.dev > API") +page.goto("https://playwright.dev/") +page.get_by_role("link", name="API").click() +page.context.tracing.group_end() +``` + +```python async +# All actions between group and group_end +# will be shown in the trace viewer as a group. +await page.context.tracing.group("Open Playwright.dev > API") +await page.goto("https://playwright.dev/") +await page.get_by_role("link", name="API").click() +await page.context.tracing.group_end() +``` + +```csharp +// All actions between GroupAsync and GroupEndAsync +// will be shown in the trace viewer as a group. +await Page.Context().Tracing.GroupAsync("Open Playwright.dev > API"); +await Page.GotoAsync("https://playwright.dev/"); +await Page.GetByRole(AriaRole.Link, new() { Name = "API" }).ClickAsync(); +await Page.Context().Tracing.GroupEndAsync(); +``` + +### param: Tracing.group.name +* since: v1.49 +- `name` <[string]> + +Group name shown in the trace viewer. + +### option: Tracing.group.location +* since: v1.49 +- `location` ?<[Object]> + - `file` <[string]> + - `line` ?<[int]> + - `column` ?<[int]> + +Specifies a custom location for the group to be shown in the trace viewer. Defaults to the location of the [`method: Tracing.group`] call. + +## async method: Tracing.groupEnd +* since: v1.49 + +Closes the last group created by [`method: Tracing.group`]. + ## async method: Tracing.stop * since: v1.12 diff --git a/docs/src/aria-snapshots.md b/docs/src/aria-snapshots.md new file mode 100644 index 0000000000..d781907c0a --- /dev/null +++ b/docs/src/aria-snapshots.md @@ -0,0 +1,392 @@ +--- +id: aria-snapshots +title: "Aria snapshots" +--- + +## Overview + +In Playwright, aria snapshots provide a YAML representation of the accessibility tree of a page. +These snapshots can be stored and compared later to verify if the page structure remains consistent or meets defined +expectations. + +The YAML format describes the hierarchical structure of accessible elements on the page, detailing **roles**, **attributes**, **values**, and **text content**. +The structure follows a tree-like syntax, where each node represents an accessible element, and indentation indicates +nested elements. + +Following is a simple example of an aria snapshot for the playwright.dev homepage: + +```yaml +- banner: + - heading /Playwright enables reliable/ [level=1] + - link "Get started" + - link "Star microsoft/playwright on GitHub" +- main: + - img "Browsers (Chromium, Firefox, WebKit)" + - heading "Any browser • Any platform • One API" +``` + +Each accessible element in the tree is represented as a YAML node: + +```yaml +- role "name" [attribute=value] +``` + +- **role**: Specifies the ARIA or HTML role of the element (e.g., `heading`, `list`, `listitem`, `button`). +- **"name"**: Accessible name of the element. Quoted strings indicate exact values, `/patterns/` are used for regular expression. +- **[attribute=value]**: Attributes and values, in square brackets, represent specific ARIA attributes, such + as `checked`, `disabled`, `expanded`, `level`, `pressed`, or `selected`. + +These values are derived from ARIA attributes or calculated based on HTML semantics. To inspect the accessibility tree +structure of a page, use the [Chrome DevTools Accessibility Pane](https://developer.chrome.com/docs/devtools/accessibility/reference#pane). + + +## Snapshot matching + +The [`method: LocatorAssertions.toMatchAriaSnapshot`] assertion method in Playwright compares the accessible +structure of the locator scope with a predefined aria snapshot template, helping validate the page's state against +testing requirements. + +For the following DOM: + +```html +

title

+``` + +You can match it using the following snapshot template: + +```js +await expect(page.locator('body')).toMatchAriaSnapshot(` + - heading "title" +`); +``` + +```python sync +page.locator("body").to_match_aria_snapshot(""" + - heading "title" +""") +``` + +```python async +await page.locator("body").to_match_aria_snapshot(""" + - heading "title" +""") +``` + +```java +page.locator("body").expect().toMatchAriaSnapshot(""" + - heading "title" +"""); +``` + +```csharp +await Expect(page.Locator("body")).ToMatchAriaSnapshotAsync(@" + - heading ""title"" +"); +``` + +When matching, the snapshot template is compared to the current accessibility tree of the page: + +* If the tree structure matches the template, the test passes; otherwise, it fails, indicating a mismatch between + expected and actual accessibility states. +* The comparison is case-sensitive and collapses whitespace, so indentation and line breaks are ignored. +* The comparison is order-sensitive, meaning the order of elements in the snapshot template must match the order in the + page's accessibility tree. + + +### Partial matching + +You can perform partial matches on nodes by omitting attributes or accessible names, enabling verification of specific +parts of the accessibility tree without requiring exact matches. This flexibility is helpful for dynamic or irrelevant +attributes. + +```html + +``` + +*aria snapshot* + +```yaml +- button +``` + +In this example, the button role is matched, but the accessible name ("Submit") is not specified, allowing the test to +pass regardless of the button’s label. + +
+ +For elements with ARIA attributes like `checked` or `disabled`, omitting these attributes allows partial matching, +focusing solely on role and hierarchy. + +```html + +``` + +*aria snapshot for partial match* + +```yaml +- checkbox +``` + +In this partial match, the `checked` attribute is ignored, so the test will pass regardless of the checkbox state. + +
+ +Similarly, you can partially match children in lists or groups by omitting specific list items or nested elements. + +```html +
    +
  • Feature A
  • +
  • Feature B
  • +
  • Feature C
  • +
+``` + +*aria snapshot for partial match* + +```yaml +- list + - listitem: Feature B +``` + +Partial matches let you create flexible snapshot tests that verify essential page structure without enforcing +specific content or attributes. + +### Matching with regular expressions + +Regular expressions allow flexible matching for elements with dynamic or variable text. Accessible names and text can +support regex patterns. + +```html +

Issues 12

+``` + +*aria snapshot with regular expression* + +```yaml +- heading /Issues \d+/ +``` + +## Generating snapshots + +Creating aria snapshots in Playwright helps ensure and maintain your application’s structure. +You can generate snapshots in various ways depending on your testing setup and workflow. + +### 1. Generating snapshots with the Playwright code generator + +If you’re using Playwright’s [Code Generator](./codegen.md), generating aria snapshots is streamlined with its +interactive interface: + +- **"Assert snapshot" Action**: In the code generator, you can use the "Assert snapshot" action to automatically create +a snapshot assertion for the selected elements. This is a quick way to capture the aria snapshot as part of your +recorded test flow. + +- **"Aria snapshot" Tab**: The "Aria snapshot" tab within the code generator interface visually represents the +aria snapshot for a selected locator, letting you explore, inspect, and verify element roles, attributes, and +accessible names to aid snapshot creation and review. + +### 2. Updating snapshots with `@playwright/test` and the `--update-snapshots` flag + +When using the Playwright test runner (`@playwright/test`), you can automatically update snapshots by running tests with +the `--update-snapshots` flag: + +```bash +npx playwright test --update-snapshots +``` + +This command regenerates snapshots for assertions, including aria snapshots, replacing outdated ones. It’s +useful when application structure changes require new snapshots as a baseline. Note that Playwright will wait for the +maximum expect timeout specified in the test runner configuration to ensure the +page is settled before taking the snapshot. It might be necessary to adjust the `--timeout` if the test hits the timeout +while generating snapshots. + +#### Empty template for snapshot generation + +Passing an empty string as the template in an assertion generates a snapshot on-the-fly: + +```js +await expect(locator).toMatchAriaSnapshot(''); +``` + +Note that Playwright will wait for the maximum expect timeout specified in the test runner configuration to ensure the +page is settled before taking the snapshot. It might be necessary to adjust the `--timeout` if the test hits the timeout +while generating snapshots. + +#### Snapshot patch files + +When updating snapshots, Playwright creates patch files that capture differences. These patch files can be reviewed, +applied, and committed to source control, allowing teams to track structural changes over time and ensure updates are +consistent with application requirements. + +### 3. Using the `Locator.ariaSnapshot` method + +The [`method: Locator.ariaSnapshot`] method allows you to programmatically create a YAML representation of accessible +elements within a locator’s scope, especially helpful for generating snapshots dynamically during test execution. + +**Example**: + +```js +const snapshot = await page.locator('body').ariaSnapshot(); +console.log(snapshot); +``` + +```python sync +snapshot = page.locator("body").aria_snapshot() +print(snapshot) +``` + +```python async +snapshot = await page.locator("body").aria_snapshot() +print(snapshot) +``` + +```java +String snapshot = page.locator("body").ariaSnapshot(); +System.out.println(snapshot); +``` + +```csharp +var snapshot = await page.Locator("body").AriaSnapshotAsync(); +Console.WriteLine(snapshot); +``` + +This command outputs the aria snapshot within the specified locator’s scope in YAML format, which you can validate +or store as needed. + +## Accessibility tree examples + +### Headings with level attributes + +Headings can include a `level` attribute indicating their heading level. + +```html +

Title

+

Subtitle

+``` + +*aria snapshot* + +```yaml +- heading "Title" [level=1] +- heading "Subtitle" [level=2] +``` + +### Text nodes + +Standalone or descriptive text elements appear as text nodes. + +```html +
Sample accessible name
+``` + +*aria snapshot* + +```yaml +- text: Sample accessible name +``` + +### Inline multiline text + +Multiline text, such as paragraphs, is normalized in the aria snapshot. + +```html +

Line 1
Line 2

+``` + +*aria snapshot* + +```yaml +- paragraph: Line 1 Line 2 +``` + +### Links + +Links display their text or composed content from pseudo-elements. + +```html +Read more about Accessibility +``` + +*aria snapshot* + +```yaml +- link "Read more about Accessibility" +``` + +### Text boxes + +Input elements of type `text` show their `value` attribute content. + +```html + +``` + +*aria snapshot* + +```yaml +- textbox: Enter your name +``` + +### Lists with items + +Ordered and unordered lists include their list items. + +```html +
    +
  • Feature 1
  • +
  • Feature 2
  • +
+``` + +*aria snapshot* + +```yaml +- list "Main Features": + - listitem: Feature 1 + - listitem: Feature 2 +``` + +### Grouped elements + +Groups capture nested elements, such as `
` elements with summary content. + +```html +
+ Summary +

Detail content here

+
+``` + +*aria snapshot* + +```yaml +- group: Summary +``` + +### Attributes and states + +Commonly used ARIA attributes, like `checked`, `disabled`, `expanded`, `level`, `pressed`, and `selected`, represent +control states. + +#### Checkbox with `checked` attribute + +```html + +``` + +*aria snapshot* + +```yaml +- checkbox [checked] +``` + +#### Button with `pressed` attribute + +```html + +``` + +*aria snapshot* + +```yaml +- button "Toggle" [pressed=true] +``` diff --git a/docs/src/best-practices-js.md b/docs/src/best-practices-js.md index 20f55c61d0..c1d06f8b13 100644 --- a/docs/src/best-practices-js.md +++ b/docs/src/best-practices-js.md @@ -475,6 +475,21 @@ Setup CI/CD and run your tests frequently. The more often you run your tests the Use Linux when running your tests on CI as it is cheaper. Developers can use whatever environment when running locally but use linux on CI. Consider setting up [Sharding](./test-sharding.md) to make CI faster. + +#### Optimize browser downloads on CI + +Only install the browsers that you actually need, especially on CI. For example, if you're only testing with Chromium, install just Chromium. + +```bash title=".github/workflows/playwright.yml" +# Instead of installing all browsers +npx playwright install --with-deps + +# Install only Chromium +npx playwright install chromium --with-deps +``` + +This saves both download time and disk space on your CI machines. + ### Lint your tests We recommend TypeScript and linting with ESLint for your tests to catch errors early. Use [`@typescript-eslint/no-floating-promises`](https://typescript-eslint.io/rules/no-floating-promises/) [ESLint](https://eslint.org) rule to make sure there are no missing awaits before the asynchronous calls to the Playwright API. On your CI you can run `tsc --noEmit` to ensure that functions are called with the right signature. diff --git a/docs/src/browsers.md b/docs/src/browsers.md index fc3dfb38a1..1321ed8549 100644 --- a/docs/src/browsers.md +++ b/docs/src/browsers.md @@ -338,6 +338,87 @@ dotnet test --settings:webkit.runsettings For Google Chrome, Microsoft Edge and other Chromium-based browsers, by default, Playwright uses open source Chromium builds. Since the Chromium project is ahead of the branded browsers, when the world is on Google Chrome N, Playwright already supports Chromium N+1 that will be released in Google Chrome and Microsoft Edge a few weeks later. +Playwright ships a regular Chromium build for headed operations and a separate [chromium headless shell](https://developer.chrome.com/blog/chrome-headless-shell) for headless mode. See [issue #33566](https://github.com/microsoft/playwright/issues/33566) for details. + +#### Optimize download size on CI + +If you are only running tests in headless mode, for example on CI, you can avoid downloading a regular version of Chromium by passing `--only-shell` during installation. + +```bash js +# only running tests headlessly +npx playwright install --with-deps --only-shell +``` + +```bash java +# only running tests headlessly +mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI -D exec.args="install --with-deps --only-shell" +``` + +```bash python +# only running tests headlessly +playwright install --with-deps --only-shell +``` + +```bash csharp +# only running tests headlessly +pwsh bin/Debug/netX/playwright.ps1 install --with-deps --only-shell +``` + +#### Opt-in to new headless mode + +You can opt into the new headless mode by using `'chromium'` channel. As [official Chrome documentation puts it](https://developer.chrome.com/blog/chrome-headless-shell): + +> New Headless on the other hand is the real Chrome browser, and is thus more authentic, reliable, and offers more features. This makes it more suitable for high-accuracy end-to-end web app testing or browser extension testing. + +See [issue #33566](https://github.com/microsoft/playwright/issues/33566) for details. + +```js +import { defineConfig, devices } from '@playwright/test'; + +export default defineConfig({ + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'], channel: 'chromium' }, + }, + ], +}); +``` + +```java +import com.microsoft.playwright.*; + +public class Example { + public static void main(String[] args) { + try (Playwright playwright = Playwright.create()) { + Browser browser = playwright.chromium().launch(new BrowserType.LaunchOptions().setChannel("chromium")); + Page page = browser.newPage(); + // ... + } + } +} +``` + +```bash python +pytest test_login.py --browser-channel chromium +``` + +```xml csharp + + + + chromium + + chromium + + + +``` + +```bash csharp +dotnet test -- Playwright.BrowserName=chromium Playwright.LaunchOptions.Channel=chromium +``` + ### Google Chrome & Microsoft Edge While Playwright can download and use the recent Chromium build, it can operate against the branded Google Chrome and Microsoft Edge browsers available on the machine (note that Playwright doesn't install them by default). In particular, the current Playwright version will support Stable and Beta channels of these browsers. @@ -348,6 +429,10 @@ Available channels are `chrome`, `msedge`, `chrome-beta`, `msedge-beta` or `msed Certain Enterprise Browser Policies may impact Playwright's ability to launch and control Google Chrome and Microsoft Edge. Running in an environment with browser policies is outside of the Playwright project's scope. ::: +:::warning +Google Chrome and Microsoft Edge have switched to a [new headless mode](https://developer.chrome.com/docs/chromium/headless) implementation that is closer to a regular headed mode. This differs from [chromium headless shell](https://developer.chrome.com/blog/chrome-headless-shell) that is used in Playwright by default when running headless, so expect different behavior in some cases. See [issue #33566](https://github.com/microsoft/playwright/issues/33566) fore details. +::: + ```js import { defineConfig, devices } from '@playwright/test'; diff --git a/docs/src/chrome-extensions-js-python.md b/docs/src/chrome-extensions-js-python.md index e34236ab5b..f34ecf8e9d 100644 --- a/docs/src/chrome-extensions-js-python.md +++ b/docs/src/chrome-extensions-js-python.md @@ -214,10 +214,6 @@ def test_popup_page(page: Page, extension_id: str) -> None: ## Headless mode -:::danger -`headless=new` mode is not officially supported by Playwright and might result in unexpected behavior. -::: - By default, Chrome's headless mode in Playwright does not support Chrome extensions. To overcome this limitation, you can run Chrome's persistent context with a new headless mode by using the following code: ```js title="fixtures.ts" diff --git a/docs/src/ci-intro.md b/docs/src/ci-intro.md index 9e0ee0eb4f..ed7e2208fc 100644 --- a/docs/src/ci-intro.md +++ b/docs/src/ci-intro.md @@ -21,7 +21,7 @@ Playwright tests can be run on any CI provider. This guide covers one way of run ## Introduction * langs: python, java, csharp -Playwright tests can be ran on any CI provider. In this section we will cover running tests on GitHub using GitHub actions. If you would like to see how to configure other CI providers check out our detailed doc on Continuous Integration. +Playwright tests can be run on any CI provider. In this section we will cover running tests on GitHub using GitHub actions. If you would like to see how to configure other CI providers check out our detailed doc on Continuous Integration. #### You will learn * langs: python, java, csharp diff --git a/docs/src/clock.md b/docs/src/clock.md index ea14941d82..2f846e4fd3 100644 --- a/docs/src/clock.md +++ b/docs/src/clock.md @@ -164,11 +164,11 @@ await Page.GotoAsync("http://localhost:3333"); await Page.Clock.PauseAtAsync(new DateTime(2024, 2, 2, 10, 0, 0)); // Assert the page state. -await Expect(Page.GetByTestId("current-time")).ToHaveText("2/2/2024, 10:00:00 AM"); +await Expect(Page.GetByTestId("current-time")).ToHaveTextAsync("2/2/2024, 10:00:00 AM"); // Close the laptop lid again and open it at 10:30am. await Page.Clock.FastForwardAsync("30:00"); -await Expect(Page.GetByTestId("current-time")).ToHaveText("2/2/2024, 10:30:00 AM"); +await Expect(Page.GetByTestId("current-time")).ToHaveTextAsync("2/2/2024, 10:30:00 AM"); ``` ## Test inactivity monitoring diff --git a/docs/src/intro-js.md b/docs/src/intro-js.md index 8c29641bd9..321629662b 100644 --- a/docs/src/intro-js.md +++ b/docs/src/intro-js.md @@ -80,7 +80,7 @@ The `tests` folder contains a basic example test to help you get started with te ## Running the Example Test -By default tests will be run on all 3 browsers, chromium, firefox and webkit using 3 workers. This can be configured in the [playwright.config file](./test-configuration.md). Tests are run in headless mode meaning no browser will open up when running the tests. Results of the tests and test logs will be shown in the terminal. +By default tests will be run on all 3 browsers, Chromium, Firefox and WebKit using 3 workers. This can be configured in the [playwright.config file](./test-configuration.md). Tests are run in headless mode meaning no browser will open up when running the tests. Results of the tests and test logs will be shown in the terminal. New Headless on the other hand is the real Chrome browser, and is thus more authentic, reliable, and offers more features. This makes it more suitable for high-accuracy end-to-end web app testing or browser extension testing. + +See [issue #33566](https://github.com/microsoft/playwright/issues/33566) for the list of possible breakages you could encounter and more details on Chromium headless. Please file an issue if you see any problems after opting in. + +```js +import { defineConfig, devices } from '@playwright/test'; + +export default defineConfig({ + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'], channel: 'chromium' }, + }, + ], +}); +``` + +### Miscellaneous + +- `` elements inside a snapshot now draw a preview. +- New method [`method: Tracing.group`] to visually group actions in the trace. +- Playwright docker images switched from Node.js v20 to Node.js v22 LTS. + +### Browser Versions + +- Chromium 131.0.6778.33 +- Mozilla Firefox 132.0 +- WebKit 18.2 + +This version was also tested against the following stable channels: + +- Google Chrome 130 +- Microsoft Edge 130 + + ## Version 1.48 + +Maximum time in milliseconds for the step to finish. Defaults to `0` (no timeout). + ## method: Test.use * since: v1.10 diff --git a/docs/src/test-assertions-js.md b/docs/src/test-assertions-js.md index defbc3a293..162d0351eb 100644 --- a/docs/src/test-assertions-js.md +++ b/docs/src/test-assertions-js.md @@ -254,7 +254,7 @@ Note that by default `toPass` has timeout 0 and does not respect custom [expect You can extend Playwright assertions by providing custom matchers. These matchers will be available on the `expect` object. -In this example we add a custom `toHaveAmount` function. Custom matcher should return a `message` callback and a `pass` flag indicating whether the assertion passed. +In this example we add a custom `toHaveAmount` function. Custom matcher should return a `pass` flag indicating whether the assertion passed, and a `message` callback that's used when the assertion fails. ```js title="fixtures.ts" import { expect as baseExpect } from '@playwright/test'; @@ -279,7 +279,7 @@ export const expect = baseExpect.extend({ ? () => this.utils.matcherHint(assertionName, undefined, undefined, { isNot: this.isNot }) + '\n\n' + `Locator: ${locator}\n` + - `Expected: ${this.isNot ? 'not' : ''}${this.utils.printExpected(expected)}\n` + + `Expected: not ${this.utils.printExpected(expected)}\n` + (matcherResult ? `Received: ${this.utils.printReceived(matcherResult.actual)}` : '') : () => this.utils.matcherHint(assertionName, undefined, undefined, { isNot: this.isNot }) + '\n\n' + diff --git a/docs/src/test-components-js.md b/docs/src/test-components-js.md index e4f19d6fc2..9a28edd40e 100644 --- a/docs/src/test-components-js.md +++ b/docs/src/test-components-js.md @@ -40,7 +40,7 @@ test('event should work', async ({ mount }) => { ## How to get started -Adding Playwright Test to an existing project is easy. Below are the steps to enable Playwright Test for a React, Vue, Svelte or Solid project. +Adding Playwright Test to an existing project is easy. Below are the steps to enable Playwright Test for a React, Vue or Svelte project. ### Step 1: Install Playwright Test for components for your respective framework @@ -106,7 +106,6 @@ component is mounted using this script. It can be either a `.js`, `.ts`, `.jsx` defaultValue="react" values={[ {label: 'React', value: 'react'}, - {label: 'Solid', value: 'solid'}, {label: 'Svelte', value: 'svelte'}, {label: 'Vue', value: 'vue'}, ] @@ -168,20 +167,6 @@ test('should work', async ({ mount }) => { - - -```js title="app.spec.tsx" -import { test, expect } from '@playwright/experimental-ct-solid'; -import App from './App'; - -test('should work', async ({ mount }) => { - const component = await mount(); - await expect(component).toContainText('Learn Solid'); -}); -``` - - - ### Step 3. Run the tests @@ -309,7 +294,6 @@ Provide props to a component when mounted. defaultValue="react" values={[ {label: 'React', value: 'react'}, - {label: 'Solid', value: 'solid'}, {label: 'Svelte', value: 'svelte'}, {label: 'Vue', value: 'vue'}, ] @@ -325,17 +309,6 @@ test('props', async ({ mount }) => { }); ``` - - - -```js title="component.spec.tsx" -import { test } from '@playwright/experimental-ct-solid'; - -test('props', async ({ mount }) => { - const component = await mount(); -}); -``` - @@ -379,7 +352,6 @@ Provide callbacks/events to a component when mounted. defaultValue="react" values={[ {label: 'React', value: 'react'}, - {label: 'Solid', value: 'solid'}, {label: 'Svelte', value: 'svelte'}, {label: 'Vue', value: 'vue'}, ] @@ -395,17 +367,6 @@ test('callback', async ({ mount }) => { }); ``` - - - -```js title="component.spec.tsx" -import { test } from '@playwright/experimental-ct-solid'; - -test('callback', async ({ mount }) => { - const component = await mount( {}} />); -}); -``` - @@ -449,7 +410,6 @@ Provide children/slots to a component when mounted. defaultValue="react" values={[ {label: 'React', value: 'react'}, - {label: 'Solid', value: 'solid'}, {label: 'Svelte', value: 'svelte'}, {label: 'Vue', value: 'vue'}, ] @@ -465,17 +425,6 @@ test('children', async ({ mount }) => { }); ``` - - - -```js title="component.spec.tsx" -import { test } from '@playwright/experimental-ct-solid'; - -test('children', async ({ mount }) => { - const component = await mount(Child); -}); -``` - @@ -519,7 +468,6 @@ You can use `beforeMount` and `afterMount` hooks to configure your app. This let defaultValue="react" values={[ {label: 'React', value: 'react'}, - {label: 'Solid', value: 'solid'}, {label: 'Vue3', value: 'vue3'}, ] }> @@ -554,37 +502,6 @@ You can use `beforeMount` and `afterMount` hooks to configure your app. This let - - - ```js title="playwright/index.tsx" - import { beforeMount, afterMount } from '@playwright/experimental-ct-solid/hooks'; - import { Router } from '@solidjs/router'; - - export type HooksConfig = { - enableRouting?: boolean; - } - - beforeMount(async ({ App, hooksConfig }) => { - if (hooksConfig?.enableRouting) - return ; - }); - ``` - - ```js title="src/pages/ProductsPage.spec.tsx" - import { test, expect } from '@playwright/experimental-ct-solid'; - import type { HooksConfig } from '../playwright'; - import { ProductsPage } from './pages/ProductsPage'; - - test('configure routing through hooks config', async ({ page, mount }) => { - const component = await mount(, { - hooksConfig: { enableRouting: true }, - }); - await expect(component.getByRole('link')).toHaveAttribute('href', '/products/42'); - }); - ``` - - - ```js title="playwright/index.ts" @@ -626,7 +543,6 @@ Unmount the mounted component from the DOM. This is useful for testing the compo defaultValue="react" values={[ {label: 'React', value: 'react'}, - {label: 'Solid', value: 'solid'}, {label: 'Svelte', value: 'svelte'}, {label: 'Vue', value: 'vue'}, ] @@ -643,18 +559,6 @@ test('unmount', async ({ mount }) => { }); ``` - - - -```js title="component.spec.tsx" -import { test } from '@playwright/experimental-ct-solid'; - -test('unmount', async ({ mount }) => { - const component = await mount(); - await component.unmount(); -}); -``` - @@ -700,7 +604,6 @@ Update props, slots/children, and/or events/callbacks of a mounted component. Th defaultValue="react" values={[ {label: 'React', value: 'react'}, - {label: 'Solid', value: 'solid'}, {label: 'Svelte', value: 'svelte'}, {label: 'Vue', value: 'vue'}, ] @@ -719,20 +622,6 @@ test('update', async ({ mount }) => { }); ``` - - - -```js title="component.spec.tsx" -import { test } from '@playwright/experimental-ct-solid'; - -test('update', async ({ mount }) => { - const component = await mount(); - await component.update( - {}}>Child - ); -}); -``` - @@ -820,7 +709,7 @@ test('example test', async ({ mount, router }) => { ## Frequently asked questions -### What's the difference between `@playwright/test` and `@playwright/experimental-ct-{react,svelte,vue,solid}`? +### What's the difference between `@playwright/test` and `@playwright/experimental-ct-{react,svelte,vue}`? ```js test('…', async ({ mount, page, context }) => { @@ -828,13 +717,12 @@ test('…', async ({ mount, page, context }) => { }); ``` -`@playwright/experimental-ct-{react,svelte,vue,solid}` wrap `@playwright/test` to provide an additional built-in component-testing specific fixture called `mount`: +`@playwright/experimental-ct-{react,svelte,vue}` wrap `@playwright/test` to provide an additional built-in component-testing specific fixture called `mount`: { - - -```js -import { test, expect } from '@playwright/experimental-ct-solid'; -import HelloWorld from './HelloWorld'; - -test.use({ viewport: { width: 500, height: 500 } }); - -test('should work', async ({ mount }) => { - const component = await mount(); - await expect(component).toContainText('Greetings'); -}); -``` - - - Additionally, it adds some config options you can use in your `playwright-ct.config.{ts,js}`. diff --git a/docs/src/test-snapshots-js.md b/docs/src/test-snapshots-js.md index d2c7606adf..a1ece1a6e5 100644 --- a/docs/src/test-snapshots-js.md +++ b/docs/src/test-snapshots-js.md @@ -16,6 +16,10 @@ test('example test', async ({ page }) => { }); ``` +:::warning +Browser rendering can vary based on the host OS, version, settings, hardware, power source (battery vs. power adapter), headless mode, and other factors. For consistent screenshots, run tests in the same environment where the baseline screenshots were generated. +::: + ## Generating screenshots When you run above for the first time, test runner will say: diff --git a/docs/src/trace-viewer-intro-js.md b/docs/src/trace-viewer-intro-js.md index a950689468..3042b3721d 100644 --- a/docs/src/trace-viewer-intro-js.md +++ b/docs/src/trace-viewer-intro-js.md @@ -45,7 +45,7 @@ npx playwright test --trace on ## Opening the HTML report -The HTML report shows you a report of all your tests that have been ran and on which browsers as well as how long they took. Tests can be filtered by passed tests, failed, flakey or skipped tests. You can also search for a particular test. Clicking on a test will open the detailed view where you can see more information on your tests such as the errors, the test steps and the trace. +The HTML report shows you a report of all your tests that have been run and on which browsers as well as how long they took. Tests can be filtered by passed tests, failed, flaky or skipped tests. You can also search for a particular test. Clicking on a test will open the detailed view where you can see more information on your tests such as the errors, the test steps and the trace. ```bash npx playwright show-report diff --git a/package-lock.json b/package-lock.json index 3bc7c072e9..c216b1281c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "playwright-internal", - "version": "1.49.0-next", + "version": "1.50.0-next", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "playwright-internal", - "version": "1.49.0-next", + "version": "1.50.0-next", "license": "Apache-2.0", "workspaces": [ "packages/*" @@ -64,7 +64,7 @@ "vite": "^5.4.6", "ws": "^8.17.1", "xml2js": "^0.5.0", - "yaml": "^2.5.1" + "yaml": "^2.6.0" }, "engines": { "node": ">=18" @@ -207,6 +207,7 @@ "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", + "dev": true, "dependencies": { "@babel/types": "^7.22.5" }, @@ -233,6 +234,7 @@ "version": "7.23.7", "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.23.7.tgz", "integrity": "sha512-xCoqR/8+BoNnXOY7RVSgv6X+o7pmT5q1d+gGcRlXYkI+9B31glE4jeejhKVpA04O1AtzOt7OSQ6VYKP5FcRl9g==", + "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", "@babel/helper-environment-visitor": "^7.22.20", @@ -286,6 +288,7 @@ "version": "7.23.0", "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", + "dev": true, "dependencies": { "@babel/types": "^7.23.0" }, @@ -326,6 +329,7 @@ "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", + "dev": true, "dependencies": { "@babel/types": "^7.22.5" }, @@ -345,6 +349,7 @@ "version": "7.22.20", "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz", "integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==", + "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-member-expression-to-functions": "^7.22.15", @@ -372,6 +377,7 @@ "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", + "dev": true, "dependencies": { "@babel/types": "^7.22.5" }, @@ -467,6 +473,7 @@ "version": "7.23.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz", "integrity": "sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -517,6 +524,7 @@ "version": "7.23.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz", "integrity": "sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -579,6 +587,7 @@ "version": "7.23.3", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.3.tgz", "integrity": "sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA==", + "dev": true, "dependencies": { "@babel/helper-module-transforms": "^7.23.3", "@babel/helper-plugin-utils": "^7.22.5", @@ -721,6 +730,7 @@ "version": "7.23.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.23.6.tgz", "integrity": "sha512-6cBG5mBvUu4VUD04OHKnYzbuHNP8huDsD3EDqqpIpsswTDoqHCjLoHb6+QgsV1WsT2nipRqCPgxD3LXnEO7XfA==", + "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", "@babel/helper-create-class-features-plugin": "^7.23.6", @@ -754,24 +764,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/preset-typescript": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.23.3.tgz", - "integrity": "sha512-17oIGVlqz6CchO9RFYn5U6ZpWRZIngayYCtrPRSgANSwC2V1Jb+iP74nVxzzXJte8b8BYxrL1yY96xfhTBrNNQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-option": "^7.22.15", - "@babel/plugin-syntax-jsx": "^7.23.3", - "@babel/plugin-transform-modules-commonjs": "^7.23.3", - "@babel/plugin-transform-typescript": "^7.23.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/runtime": { "version": "7.23.8", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.8.tgz", @@ -1496,10 +1488,6 @@ "resolved": "packages/playwright-ct-react17", "link": true }, - "node_modules/@playwright/experimental-ct-solid": { - "resolved": "packages/playwright-ct-solid", - "link": true - }, "node_modules/@playwright/experimental-ct-svelte": { "resolved": "packages/playwright-ct-svelte", "link": true @@ -2616,43 +2604,6 @@ "dequal": "^2.0.3" } }, - "node_modules/babel-plugin-jsx-dom-expressions": { - "version": "0.37.13", - "resolved": "https://registry.npmjs.org/babel-plugin-jsx-dom-expressions/-/babel-plugin-jsx-dom-expressions-0.37.13.tgz", - "integrity": "sha512-oAEMMIgU0h1DmHn4ZDaBBFc08nsVJciLq9pF7g0ZdpeIDKfY4zXjXr8+/oBjKhXG8nyomhnTodPjeG+/ZXcWXQ==", - "dependencies": { - "@babel/helper-module-imports": "7.18.6", - "@babel/plugin-syntax-jsx": "^7.18.6", - "@babel/types": "^7.20.7", - "html-entities": "2.3.3", - "validate-html-nesting": "^1.2.1" - }, - "peerDependencies": { - "@babel/core": "^7.20.12" - } - }, - "node_modules/babel-plugin-jsx-dom-expressions/node_modules/@babel/helper-module-imports": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", - "dependencies": { - "@babel/types": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/babel-preset-solid": { - "version": "1.8.9", - "resolved": "https://registry.npmjs.org/babel-preset-solid/-/babel-preset-solid-1.8.9.tgz", - "integrity": "sha512-1awR1QCoryXtAdnjsrx/eVBTYz+tpHUDOdBXqG9oVV7S0ojf2MV/woR0+8BG+LMXVzIr60oKYzCZ9UZGafxmpg==", - "dependencies": { - "babel-plugin-jsx-dom-expressions": "^0.37.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -2910,10 +2861,11 @@ "periscopic": "^3.1.0" } }, - "node_modules/codemirror-shadow-1": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/codemirror-shadow-1/-/codemirror-shadow-1-0.0.1.tgz", - "integrity": "sha512-kD3OZpCCHr3LHRKfbGx5IogHTWq4Uo9jH2bXPVa7/n6ppkgI66rx4tniQY1BpqWp/JNhQmQsXhQoaZ1TH6t0xQ==" + "node_modules/codemirror": { + "version": "5.65.18", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.18.tgz", + "integrity": "sha512-Gaz4gHnkbHMGgahNt3CA5HBk5lLQBqmD/pBgeB4kQU6OedZmqMBjlRF0LSrp2tJ4wlLNPm2FfaUd1pDy0mdlpA==", + "license": "MIT" }, "node_modules/color-convert": { "version": "1.9.3", @@ -3050,10 +3002,11 @@ } }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -4564,11 +4517,6 @@ "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, - "node_modules/html-entities": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.3.tgz", - "integrity": "sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==" - }, "node_modules/html-reporter": { "resolved": "packages/html-reporter", "link": true @@ -5037,17 +4985,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-what": { - "version": "4.1.16", - "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.16.tgz", - "integrity": "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==", - "engines": { - "node": ">=12.13" - }, - "funding": { - "url": "https://github.com/sponsors/mesqueeb" - } - }, "node_modules/isarray": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", @@ -5361,20 +5298,6 @@ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==" }, - "node_modules/merge-anything": { - "version": "5.1.7", - "resolved": "https://registry.npmjs.org/merge-anything/-/merge-anything-5.1.7.tgz", - "integrity": "sha512-eRtbOb1N5iyH0tkQDAoQ4Ipsp/5qSR79Dzrz8hEPxRX10RWWR/iQXdoKmBSRCThY1Fh5EhISDtpSc93fpxUniQ==", - "dependencies": { - "is-what": "^4.1.8" - }, - "engines": { - "node": ">=12.13" - }, - "funding": { - "url": "https://github.com/sponsors/mesqueeb" - } - }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -6421,25 +6344,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/seroval": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/seroval/-/seroval-1.0.4.tgz", - "integrity": "sha512-qQs/N+KfJu83rmszFQaTxcoJoPn6KNUruX4KmnmyD0oZkUoiNvJ1rpdYKDf4YHM05k+HOgCxa3yvf15QbVijGg==", - "engines": { - "node": ">=10" - } - }, - "node_modules/seroval-plugins": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/seroval-plugins/-/seroval-plugins-1.0.4.tgz", - "integrity": "sha512-DQ2IK6oQVvy8k+c2V5x5YCtUa/GGGsUwUBNN9UqohrZ0rWdUapBFpNMYP1bCyRHoxOJjdKGl+dieacFIpU/i1A==", - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "seroval": "^1.0" - } - }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -6529,29 +6433,6 @@ "node": "*" } }, - "node_modules/solid-js": { - "version": "1.8.11", - "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.8.11.tgz", - "integrity": "sha512-WdwmER+TwBJiN4rVQTVBxocg+9pKlOs41KzPYntrC86xO5sek8TzBYozPEZPL1IRWDouf2lMrvSbIs3CanlPvQ==", - "dependencies": { - "csstype": "^3.1.0", - "seroval": "^1.0.3", - "seroval-plugins": "^1.0.3" - } - }, - "node_modules/solid-refresh": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/solid-refresh/-/solid-refresh-0.6.3.tgz", - "integrity": "sha512-F3aPsX6hVw9ttm5LYlth8Q15x6MlI/J3Dn+o3EQyRTtTxidepSTwAYdozt01/YA+7ObcciagGEyXIopGZzQtbA==", - "dependencies": { - "@babel/generator": "^7.23.6", - "@babel/helper-module-imports": "^7.22.15", - "@babel/types": "^7.23.6" - }, - "peerDependencies": { - "solid-js": "^1.3" - } - }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -7119,11 +7000,6 @@ "uuid": "dist/bin/uuid" } }, - "node_modules/validate-html-nesting": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/validate-html-nesting/-/validate-html-nesting-1.2.2.tgz", - "integrity": "sha512-hGdgQozCsQJMyfK5urgFcWEqsSSrK63Awe0t/IMR0bZ0QMtnuaiHzThW81guu3qx9abLi99NEuiaN6P9gVYsNg==" - }, "node_modules/validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -7192,24 +7068,6 @@ } } }, - "node_modules/vite-plugin-solid": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/vite-plugin-solid/-/vite-plugin-solid-2.8.2.tgz", - "integrity": "sha512-HcvMs6DTxBaO4kE3psnirPQBCUUdYeQkCNKuB2TpEkJsxb6BGP6/7qkbbCSMxn25PyNdjvzVi1WXi0ou8KPgHw==", - "dependencies": { - "@babel/core": "^7.23.3", - "@babel/preset-typescript": "^7.23.3", - "@types/babel__core": "^7.20.4", - "babel-preset-solid": "^1.8.4", - "merge-anything": "^5.1.7", - "solid-refresh": "^0.6.3", - "vitefu": "^0.2.5" - }, - "peerDependencies": { - "solid-js": "^1.7.2", - "vite": "^3.0.0 || ^4.0.0 || ^5.0.0" - } - }, "node_modules/vite/node_modules/@esbuild/android-arm": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", @@ -7803,10 +7661,10 @@ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" }, "node_modules/yaml": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", - "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", - "dev": true, + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", + "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", + "license": "ISC", "bin": { "yaml": "bin.mjs" }, @@ -7876,10 +7734,10 @@ "version": "0.0.0" }, "packages/playwright": { - "version": "1.49.0-next", + "version": "1.50.0-next", "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.49.0-next" + "playwright-core": "1.50.0-next" }, "bin": { "playwright": "cli.js" @@ -7893,11 +7751,11 @@ }, "packages/playwright-browser-chromium": { "name": "@playwright/browser-chromium", - "version": "1.49.0-next", + "version": "1.50.0-next", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.49.0-next" + "playwright-core": "1.50.0-next" }, "engines": { "node": ">=18" @@ -7905,11 +7763,11 @@ }, "packages/playwright-browser-firefox": { "name": "@playwright/browser-firefox", - "version": "1.49.0-next", + "version": "1.50.0-next", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.49.0-next" + "playwright-core": "1.50.0-next" }, "engines": { "node": ">=18" @@ -7917,22 +7775,22 @@ }, "packages/playwright-browser-webkit": { "name": "@playwright/browser-webkit", - "version": "1.49.0-next", + "version": "1.50.0-next", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.49.0-next" + "playwright-core": "1.50.0-next" }, "engines": { "node": ">=18" } }, "packages/playwright-chromium": { - "version": "1.49.0-next", + "version": "1.50.0-next", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.49.0-next" + "playwright-core": "1.50.0-next" }, "bin": { "playwright": "cli.js" @@ -7942,7 +7800,7 @@ } }, "packages/playwright-core": { - "version": "1.49.0-next", + "version": "1.50.0-next", "license": "Apache-2.0", "bin": { "playwright-core": "cli.js" @@ -7953,11 +7811,11 @@ }, "packages/playwright-ct-core": { "name": "@playwright/experimental-ct-core", - "version": "1.49.0-next", + "version": "1.50.0-next", "license": "Apache-2.0", "dependencies": { - "playwright": "1.49.0-next", - "playwright-core": "1.49.0-next", + "playwright": "1.50.0-next", + "playwright-core": "1.50.0-next", "vite": "^5.2.8" }, "engines": { @@ -7966,10 +7824,10 @@ }, "packages/playwright-ct-react": { "name": "@playwright/experimental-ct-react", - "version": "1.49.0-next", + "version": "1.50.0-next", "license": "Apache-2.0", "dependencies": { - "@playwright/experimental-ct-core": "1.49.0-next", + "@playwright/experimental-ct-core": "1.50.0-next", "@vitejs/plugin-react": "^4.2.1" }, "bin": { @@ -7981,10 +7839,10 @@ }, "packages/playwright-ct-react17": { "name": "@playwright/experimental-ct-react17", - "version": "1.49.0-next", + "version": "1.50.0-next", "license": "Apache-2.0", "dependencies": { - "@playwright/experimental-ct-core": "1.49.0-next", + "@playwright/experimental-ct-core": "1.50.0-next", "@vitejs/plugin-react": "^4.2.1" }, "bin": { @@ -7994,30 +7852,12 @@ "node": ">=18" } }, - "packages/playwright-ct-solid": { - "name": "@playwright/experimental-ct-solid", - "version": "1.49.0-next", - "license": "Apache-2.0", - "dependencies": { - "@playwright/experimental-ct-core": "1.49.0-next", - "vite-plugin-solid": "^2.7.0" - }, - "bin": { - "playwright": "cli.js" - }, - "devDependencies": { - "solid-js": "^1.7.0" - }, - "engines": { - "node": ">=18" - } - }, "packages/playwright-ct-svelte": { "name": "@playwright/experimental-ct-svelte", - "version": "1.49.0-next", + "version": "1.50.0-next", "license": "Apache-2.0", "dependencies": { - "@playwright/experimental-ct-core": "1.49.0-next", + "@playwright/experimental-ct-core": "1.50.0-next", "@sveltejs/vite-plugin-svelte": "^3.0.1" }, "bin": { @@ -8032,10 +7872,10 @@ }, "packages/playwright-ct-vue": { "name": "@playwright/experimental-ct-vue", - "version": "1.49.0-next", + "version": "1.50.0-next", "license": "Apache-2.0", "dependencies": { - "@playwright/experimental-ct-core": "1.49.0-next", + "@playwright/experimental-ct-core": "1.50.0-next", "@vitejs/plugin-vue": "^4.2.1" }, "bin": { @@ -8046,11 +7886,11 @@ } }, "packages/playwright-firefox": { - "version": "1.49.0-next", + "version": "1.50.0-next", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.49.0-next" + "playwright-core": "1.50.0-next" }, "bin": { "playwright": "cli.js" @@ -8061,10 +7901,10 @@ }, "packages/playwright-test": { "name": "@playwright/test", - "version": "1.49.0-next", + "version": "1.50.0-next", "license": "Apache-2.0", "dependencies": { - "playwright": "1.49.0-next" + "playwright": "1.50.0-next" }, "bin": { "playwright": "cli.js" @@ -8074,11 +7914,11 @@ } }, "packages/playwright-webkit": { - "version": "1.49.0-next", + "version": "1.50.0-next", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.49.0-next" + "playwright-core": "1.50.0-next" }, "bin": { "playwright": "cli.js" @@ -8101,7 +7941,10 @@ } }, "packages/recorder": { - "version": "0.0.0" + "version": "0.0.0", + "dependencies": { + "yaml": "^2.6.0" + } }, "packages/trace-viewer": { "version": "0.0.0" @@ -8109,7 +7952,7 @@ "packages/web": { "version": "0.0.0", "dependencies": { - "codemirror-shadow-1": "0.0.1", + "codemirror": "5.65.18", "xterm": "^5.1.0", "xterm-addon-fit": "^0.7.0" } diff --git a/package.json b/package.json index 0e14d12e3e..f36e9039e3 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "playwright-internal", "private": true, - "version": "1.49.0-next", + "version": "1.50.0-next", "description": "A high-level API to automate web browsers", "repository": { "type": "git", @@ -103,6 +103,6 @@ "vite": "^5.4.6", "ws": "^8.17.1", "xml2js": "^0.5.0", - "yaml": "^2.5.1" + "yaml": "^2.6.0" } } diff --git a/packages/html-reporter/src/chip.tsx b/packages/html-reporter/src/chip.tsx index 0965a40888..f94dcbc6d6 100644 --- a/packages/html-reporter/src/chip.tsx +++ b/packages/html-reporter/src/chip.tsx @@ -20,6 +20,7 @@ import './colors.css'; import './common.css'; import * as icons from './icons'; import { clsx } from '@web/uiUtils'; +import { useAnchor } from './links'; export const Chip: React.FC<{ header: JSX.Element | string, @@ -28,10 +29,9 @@ export const Chip: React.FC<{ setExpanded?: (expanded: boolean) => void, children?: any, dataTestId?: string, - targetRef?: React.RefObject, -}> = ({ header, expanded, setExpanded, children, noInsets, dataTestId, targetRef }) => { +}> = ({ header, expanded, setExpanded, children, noInsets, dataTestId }) => { const id = React.useId(); - return
+ return
, -}> = ({ header, initialExpanded, noInsets, children, dataTestId, targetRef }) => { - const [expanded, setExpanded] = React.useState(initialExpanded || initialExpanded === undefined); + revealOnAnchorId?: string, +}> = ({ header, initialExpanded, noInsets, children, dataTestId, revealOnAnchorId }) => { + const [expanded, setExpanded] = React.useState(initialExpanded ?? true); + const onReveal = React.useCallback(() => setExpanded(true), []); + useAnchor(revealOnAnchorId, onReveal); return {children} ; diff --git a/packages/html-reporter/src/common.css b/packages/html-reporter/src/common.css index 02e01a103b..12241fd861 100644 --- a/packages/html-reporter/src/common.css +++ b/packages/html-reporter/src/common.css @@ -46,6 +46,10 @@ svg { position: relative; } +.hidden { + visibility: hidden; +} + .d-flex { display: flex !important; } diff --git a/packages/html-reporter/src/index.tsx b/packages/html-reporter/src/index.tsx index 43b4f5bb9e..0c3f0a6dc0 100644 --- a/packages/html-reporter/src/index.tsx +++ b/packages/html-reporter/src/index.tsx @@ -55,7 +55,14 @@ class ZipReport implements LoadedReport { private _json!: HTMLReport; async load() { - const zipReader = new zipjs.ZipReader(new zipjs.Data64URIReader(window.playwrightReportBase64!), { useWebWorkers: false }); + const zipURI = await new Promise(resolve => { + if (window.playwrightReportBase64) + return resolve(window.playwrightReportBase64); + window.addEventListener('message', event => event.source === window.opener && resolve(event.data), { once: true }); + window.opener.postMessage('ready', '*'); + }); + + const zipReader = new zipjs.ZipReader(new zipjs.Data64URIReader(zipURI), { useWebWorkers: false }); for (const entry of await zipReader.getEntries()) this._entries.set(entry.filename, entry); this._json = await this.entry('report.json') as HTMLReport; diff --git a/packages/html-reporter/src/links.tsx b/packages/html-reporter/src/links.tsx index 4b48090e0a..4beb7b65e0 100644 --- a/packages/html-reporter/src/links.tsx +++ b/packages/html-reporter/src/links.tsx @@ -113,3 +113,32 @@ export function generateTraceUrl(traces: TestAttachment[]) { } const kMissingContentType = 'x-playwright/missing'; + +type AnchorID = string | ((id: string | null) => boolean) | undefined; + +export function useAnchor(id: AnchorID, onReveal: () => void) { + React.useEffect(() => { + if (typeof id === 'undefined') + return; + + const listener = () => { + const params = new URLSearchParams(window.location.hash.slice(1)); + const anchor = params.get('anchor'); + const isRevealed = typeof id === 'function' ? id(anchor) : anchor === id; + if (isRevealed) + onReveal(); + }; + window.addEventListener('popstate', listener); + return () => window.removeEventListener('popstate', listener); + }, [id, onReveal]); +} + +export function Anchor({ id, children }: React.PropsWithChildren<{ id: AnchorID }>) { + const ref = React.useRef(null); + const onAnchorReveal = React.useCallback(() => { + requestAnimationFrame(() => ref.current?.scrollIntoView({ block: 'start', inline: 'start' })); + }, []); + useAnchor(id, onAnchorReveal); + + return
{children}
; +} diff --git a/packages/html-reporter/src/reportView.tsx b/packages/html-reporter/src/reportView.tsx index e8a5c3b250..cf0f5e5e56 100644 --- a/packages/html-reporter/src/reportView.tsx +++ b/packages/html-reporter/src/reportView.tsx @@ -101,7 +101,6 @@ const TestCaseViewLoader: React.FC<{ const searchParams = React.useContext(SearchParamsContext); const [test, setTest] = React.useState(); const testId = searchParams.get('testId'); - const anchor = (searchParams.get('anchor') || '') as 'video' | 'diff' | ''; const run = +(searchParams.get('run') || '0'); const { prev, next } = React.useMemo(() => { @@ -133,7 +132,6 @@ const TestCaseViewLoader: React.FC<{ next={next} prev={prev} test={test} - anchor={anchor} run={run} />; }; diff --git a/packages/html-reporter/src/testCaseView.spec.tsx b/packages/html-reporter/src/testCaseView.spec.tsx index a8ad110887..b7a9f9405b 100644 --- a/packages/html-reporter/src/testCaseView.spec.tsx +++ b/packages/html-reporter/src/testCaseView.spec.tsx @@ -63,7 +63,7 @@ const testCase: TestCase = { }; test('should render test case', async ({ mount }) => { - const component = await mount(); + const component = await mount(); await expect(component.getByText('Annotation text', { exact: false }).first()).toBeVisible(); await expect(component.getByText('Hidden annotation')).toBeHidden(); await component.getByText('Annotations').click(); @@ -79,7 +79,7 @@ test('should render test case', async ({ mount }) => { test('should render copy buttons for annotations', async ({ mount, page, context }) => { await context.grantPermissions(['clipboard-read', 'clipboard-write']); - const component = await mount(); + const component = await mount(); await expect(component.getByText('Annotation text', { exact: false }).first()).toBeVisible(); await component.getByText('Annotation text', { exact: false }).first().hover(); await expect(component.locator('.test-case-annotation').getByLabel('Copy to clipboard').first()).toBeVisible(); @@ -108,7 +108,7 @@ const annotationLinkRenderingTestCase: TestCase = { }; test('should correctly render links in annotations', async ({ mount }) => { - const component = await mount(); + const component = await mount(); const firstLink = await component.getByText('https://playwright.dev/docs/intro').first(); await expect(firstLink).toBeVisible(); @@ -154,7 +154,7 @@ const resultWithAttachment: TestResult = { const attachmentLinkRenderingTestCase: TestCase = { testId: 'testid', title: 'My test', - path: [], + path: ['group'], projectName: 'chromium', location: { file: 'test.spec.ts', line: 42, column: 0 }, tags: [], @@ -181,7 +181,7 @@ const testCaseSummary: TestCaseSummary = { test('should correctly render links in attachments', async ({ mount }) => { - const component = await mount(); + const component = await mount(); await component.getByText('first attachment').click(); const body = await component.getByText('The body with https://playwright.dev/docs/intro link'); await expect(body).toBeVisible(); @@ -194,7 +194,7 @@ test('should correctly render links in attachments', async ({ mount }) => { }); test('should correctly render links in attachment name', async ({ mount }) => { - const component = await mount(); + const component = await mount(); const link = component.getByText('attachment with inline link').locator('a'); await expect(link).toHaveAttribute('href', 'https://github.com/microsoft/playwright/issues/31284'); await expect(link).toHaveText('https://github.com/microsoft/playwright/issues/31284'); @@ -204,8 +204,9 @@ test('should correctly render links in attachment name', async ({ mount }) => { }); test('should correctly render prev and next', async ({ mount }) => { - const component = await mount(); + const component = await mount(); await expect(component).toMatchAriaSnapshot(` + - text: group - link "« previous" - link "next »" - text: "My test test.spec.ts:42 10ms" diff --git a/packages/html-reporter/src/testCaseView.tsx b/packages/html-reporter/src/testCaseView.tsx index cb3cc95cef..4e9785ad8a 100644 --- a/packages/html-reporter/src/testCaseView.tsx +++ b/packages/html-reporter/src/testCaseView.tsx @@ -33,9 +33,8 @@ export const TestCaseView: React.FC<{ test: TestCase | undefined, next: TestCaseSummary | undefined, prev: TestCaseSummary | undefined, - anchor: 'video' | 'diff' | '', run: number, -}> = ({ projectNames, test, run, anchor, next, prev }) => { +}> = ({ projectNames, test, run, next, prev }) => { const [selectedResultIndex, setSelectedResultIndex] = React.useState(run); const searchParams = React.useContext(SearchParamsContext); const filterParam = searchParams.has('q') ? '&q=' + searchParams.get('q') : ''; @@ -51,12 +50,13 @@ export const TestCaseView: React.FC<{ }, [test?.annotations]); return
-
- {prev && « previous} + {test &&
+
{test.path.join(' › ')}
- {next && next »} -
- {test &&
{test.path.join(' › ')}
} +
« previous
+
+
next »
+
} {test &&
{test?.title}
} {test &&
@@ -78,7 +78,7 @@ export const TestCaseView: React.FC<{ test.results.map((result, index) => ({ id: String(index), title:
{statusIcon(result.status)} {retryLabel(index)}
, - render: () => + render: () => })) || []} selectedTab={String(selectedResultIndex)} setSelectedTab={id => setSelectedResultIndex(+id)} />}
; }; diff --git a/packages/html-reporter/src/testErrorView.tsx b/packages/html-reporter/src/testErrorView.tsx index d63f5d7945..ea402106a8 100644 --- a/packages/html-reporter/src/testErrorView.tsx +++ b/packages/html-reporter/src/testErrorView.tsx @@ -25,7 +25,7 @@ export const TestErrorView: React.FC<{ testId?: string; }> = ({ error, testId }) => { const html = React.useMemo(() => ansiErrorToHtml(error), [error]); - return
; + return
; }; export const TestScreenshotErrorView: React.FC<{ diff --git a/packages/html-reporter/src/testFileView.tsx b/packages/html-reporter/src/testFileView.tsx index 4d6890ad33..6b31d2ebe2 100644 --- a/packages/html-reporter/src/testFileView.tsx +++ b/packages/html-reporter/src/testFileView.tsx @@ -75,12 +75,12 @@ function imageDiffBadge(test: TestCaseSummary): JSX.Element | undefined { const resultWithImageDiff = test.results.find(result => result.attachments.some(attachment => { return attachment.contentType.startsWith('image/') && !!attachment.name.match(/-(expected|actual|diff)/); })); - return resultWithImageDiff ? {image()} : undefined; + return resultWithImageDiff ? {image()} : undefined; } function videoBadge(test: TestCaseSummary): JSX.Element | undefined { const resultWithVideo = test.results.find(result => result.attachments.some(attachment => attachment.name === 'video')); - return resultWithVideo ? {video()} : undefined; + return resultWithVideo ? {video()} : undefined; } function traceBadge(test: TestCaseSummary): JSX.Element | undefined { diff --git a/packages/html-reporter/src/testResultView.tsx b/packages/html-reporter/src/testResultView.tsx index 3a562f3fcf..9170f2023d 100644 --- a/packages/html-reporter/src/testResultView.tsx +++ b/packages/html-reporter/src/testResultView.tsx @@ -20,7 +20,7 @@ import { TreeItem } from './treeItem'; import { msToString } from './utils'; import { AutoChip } from './chip'; import { traceImage } from './images'; -import { AttachmentLink, generateTraceUrl } from './links'; +import { Anchor, AttachmentLink, generateTraceUrl } from './links'; import { statusIcon } from './statusIcon'; import type { ImageDiff } from '@web/shared/imageDiffView'; import { ImageDiffView } from '@web/shared/imageDiffView'; @@ -64,9 +64,7 @@ function groupImageDiffs(screenshots: Set): ImageDiff[] { export const TestResultView: React.FC<{ test: TestCase, result: TestResult, - anchor: 'video' | 'diff' | '', -}> = ({ result, anchor }) => { - +}> = ({ result }) => { const { screenshots, videos, traces, otherAttachments, diffs, errors, htmls } = React.useMemo(() => { const attachments = result?.attachments || []; const screenshots = new Set(attachments.filter(a => a.contentType.startsWith('image/'))); @@ -80,20 +78,6 @@ export const TestResultView: React.FC<{ return { screenshots: [...screenshots], videos, traces, otherAttachments, diffs, errors, htmls }; }, [result]); - const videoRef = React.useRef(null); - const imageDiffRef = React.useRef(null); - - const [scrolled, setScrolled] = React.useState(false); - React.useEffect(() => { - if (scrolled) - return; - setScrolled(true); - if (anchor === 'video') - videoRef.current?.scrollIntoView({ block: 'start', inline: 'start' }); - if (anchor === 'diff') - imageDiffRef.current?.scrollIntoView({ block: 'start', inline: 'start' }); - }, [scrolled, anchor, setScrolled, videoRef]); - return
{!!errors.length && {errors.map((error, index) => { @@ -107,9 +91,11 @@ export const TestResultView: React.FC<{ } {diffs.map((diff, index) => - - - + + + + + )} {!!screenshots.length && @@ -123,23 +109,23 @@ export const TestResultView: React.FC<{ })} } - {!!traces.length && + {!!traces.length && {
{traces.map((a, i) => )}
} -
} +
} - {!!videos.length && + {!!videos.length && {videos.map((a, i) =>
)} -
} +
} {!!(otherAttachments.size + htmls.length) && {[...htmls].map((a, i) => ( diff --git a/packages/playwright-browser-chromium/install.js b/packages/playwright-browser-chromium/install.js index 8ceef68b95..5f725bb2c9 100644 --- a/packages/playwright-browser-chromium/install.js +++ b/packages/playwright-browser-chromium/install.js @@ -24,4 +24,4 @@ try { } if (install) - install(['chromium', 'ffmpeg']); + install(['chromium', 'chromium-headless-shell', 'ffmpeg']); diff --git a/packages/playwright-browser-chromium/package.json b/packages/playwright-browser-chromium/package.json index 917150ade7..909d5d3261 100644 --- a/packages/playwright-browser-chromium/package.json +++ b/packages/playwright-browser-chromium/package.json @@ -1,6 +1,6 @@ { "name": "@playwright/browser-chromium", - "version": "1.49.0-next", + "version": "1.50.0-next", "description": "Playwright package that automatically installs Chromium", "repository": { "type": "git", @@ -27,6 +27,6 @@ "install": "node install.js" }, "dependencies": { - "playwright-core": "1.49.0-next" + "playwright-core": "1.50.0-next" } } diff --git a/packages/playwright-browser-firefox/package.json b/packages/playwright-browser-firefox/package.json index 98f0332b71..635cfd6811 100644 --- a/packages/playwright-browser-firefox/package.json +++ b/packages/playwright-browser-firefox/package.json @@ -1,6 +1,6 @@ { "name": "@playwright/browser-firefox", - "version": "1.49.0-next", + "version": "1.50.0-next", "description": "Playwright package that automatically installs Firefox", "repository": { "type": "git", @@ -27,6 +27,6 @@ "install": "node install.js" }, "dependencies": { - "playwright-core": "1.49.0-next" + "playwright-core": "1.50.0-next" } } diff --git a/packages/playwright-browser-webkit/package.json b/packages/playwright-browser-webkit/package.json index 09574a266c..61811e3684 100644 --- a/packages/playwright-browser-webkit/package.json +++ b/packages/playwright-browser-webkit/package.json @@ -1,6 +1,6 @@ { "name": "@playwright/browser-webkit", - "version": "1.49.0-next", + "version": "1.50.0-next", "description": "Playwright package that automatically installs WebKit", "repository": { "type": "git", @@ -27,6 +27,6 @@ "install": "node install.js" }, "dependencies": { - "playwright-core": "1.49.0-next" + "playwright-core": "1.50.0-next" } } diff --git a/packages/playwright-chromium/install.js b/packages/playwright-chromium/install.js index 8ceef68b95..5f725bb2c9 100644 --- a/packages/playwright-chromium/install.js +++ b/packages/playwright-chromium/install.js @@ -24,4 +24,4 @@ try { } if (install) - install(['chromium', 'ffmpeg']); + install(['chromium', 'chromium-headless-shell', 'ffmpeg']); diff --git a/packages/playwright-chromium/package.json b/packages/playwright-chromium/package.json index 3390def41c..22cabe176c 100644 --- a/packages/playwright-chromium/package.json +++ b/packages/playwright-chromium/package.json @@ -1,6 +1,6 @@ { "name": "playwright-chromium", - "version": "1.49.0-next", + "version": "1.50.0-next", "description": "A high-level API to automate Chromium", "repository": { "type": "git", @@ -30,6 +30,6 @@ "install": "node install.js" }, "dependencies": { - "playwright-core": "1.49.0-next" + "playwright-core": "1.50.0-next" } } diff --git a/packages/playwright-core/ThirdPartyNotices.txt b/packages/playwright-core/ThirdPartyNotices.txt index 71ac7d1bed..89a6418ab8 100644 --- a/packages/playwright-core/ThirdPartyNotices.txt +++ b/packages/playwright-core/ThirdPartyNotices.txt @@ -10,13 +10,13 @@ This project incorporates components from the projects listed below. The origina - balanced-match@1.0.2 (https://github.com/juliangruber/balanced-match) - brace-expansion@1.1.11 (https://github.com/juliangruber/brace-expansion) - buffer-crc32@0.2.13 (https://github.com/brianloveswords/buffer-crc32) -- codemirror-shadow-1@0.0.1 (https://github.com/codemirror/CodeMirror) +- codemirror@5.65.18 (https://github.com/codemirror/CodeMirror) - colors@1.4.0 (https://github.com/Marak/colors.js) - commander@8.3.0 (https://github.com/tj/commander.js) - concat-map@0.0.1 (https://github.com/substack/node-concat-map) - debug@4.3.4 (https://github.com/debug-js/debug) - define-lazy-prop@2.0.0 (https://github.com/sindresorhus/define-lazy-prop) -- diff-match-patch@1.0.5 (https://github.com/JackuB/diff-match-patch) +- diff@7.0.0 (https://github.com/kpdecker/jsdiff) - dotenv@16.4.5 (https://github.com/motdotla/dotenv) - end-of-stream@1.4.4 (https://github.com/mafintosh/end-of-stream) - escape-string-regexp@2.0.0 (https://github.com/sindresorhus/escape-string-regexp) @@ -208,7 +208,7 @@ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEAL ========================================= END OF buffer-crc32@0.2.13 AND INFORMATION -%% codemirror-shadow-1@0.0.1 NOTICES AND INFORMATION BEGIN HERE +%% codemirror@5.65.18 NOTICES AND INFORMATION BEGIN HERE ========================================= MIT License @@ -232,7 +232,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ========================================= -END OF codemirror-shadow-1@0.0.1 AND INFORMATION +END OF codemirror@5.65.18 AND INFORMATION %% colors@1.4.0 NOTICES AND INFORMATION BEGIN HERE ========================================= @@ -352,211 +352,39 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI ========================================= END OF define-lazy-prop@2.0.0 AND INFORMATION -%% diff-match-patch@1.0.5 NOTICES AND INFORMATION BEGIN HERE +%% diff@7.0.0 NOTICES AND INFORMATION BEGIN HERE ========================================= -Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ +BSD 3-Clause License - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION +Copyright (c) 2009-2015, Kevin Decker +All rights reserved. - 1. Definitions. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. +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. - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ========================================= -END OF diff-match-patch@1.0.5 AND INFORMATION +END OF diff@7.0.0 AND INFORMATION %% dotenv@16.4.5 NOTICES AND INFORMATION BEGIN HERE ========================================= diff --git a/packages/playwright-core/bin/reinstall_chrome_beta_linux.sh b/packages/playwright-core/bin/reinstall_chrome_beta_linux.sh index 14c684599c..0451bda3ef 100755 --- a/packages/playwright-core/bin/reinstall_chrome_beta_linux.sh +++ b/packages/playwright-core/bin/reinstall_chrome_beta_linux.sh @@ -7,15 +7,17 @@ if [[ $(arch) == "aarch64" ]]; then exit 1 fi -if [[ ! -f "/etc/os-release" ]]; then - echo "ERROR: cannot install on unknown linux distribution (/etc/os-release is missing)" - exit 1 -fi +if [ -z "$PLAYWRIGHT_HOST_PLATFORM_OVERRIDE" ]; then + if [[ ! -f "/etc/os-release" ]]; then + echo "ERROR: cannot install on unknown linux distribution (/etc/os-release is missing)" + exit 1 + fi -ID=$(bash -c 'source /etc/os-release && echo $ID') -if [[ "${ID}" != "ubuntu" && "${ID}" != "debian" ]]; then - echo "ERROR: cannot install on $ID distribution - only Ubuntu and Debian are supported" - exit 1 + ID=$(bash -c 'source /etc/os-release && echo $ID') + if [[ "${ID}" != "ubuntu" && "${ID}" != "debian" ]]; then + echo "ERROR: cannot install on $ID distribution - only Ubuntu and Debian are supported" + exit 1 + fi fi # 1. make sure to remove old beta if any. diff --git a/packages/playwright-core/bin/reinstall_chrome_stable_linux.sh b/packages/playwright-core/bin/reinstall_chrome_stable_linux.sh index 28a19699df..78f1d41397 100755 --- a/packages/playwright-core/bin/reinstall_chrome_stable_linux.sh +++ b/packages/playwright-core/bin/reinstall_chrome_stable_linux.sh @@ -7,15 +7,17 @@ if [[ $(arch) == "aarch64" ]]; then exit 1 fi -if [[ ! -f "/etc/os-release" ]]; then - echo "ERROR: cannot install on unknown linux distribution (/etc/os-release is missing)" - exit 1 -fi +if [ -z "$PLAYWRIGHT_HOST_PLATFORM_OVERRIDE" ]; then + if [[ ! -f "/etc/os-release" ]]; then + echo "ERROR: cannot install on unknown linux distribution (/etc/os-release is missing)" + exit 1 + fi -ID=$(bash -c 'source /etc/os-release && echo $ID') -if [[ "${ID}" != "ubuntu" && "${ID}" != "debian" ]]; then - echo "ERROR: cannot install on $ID distribution - only Ubuntu and Debian are supported" - exit 1 + ID=$(bash -c 'source /etc/os-release && echo $ID') + if [[ "${ID}" != "ubuntu" && "${ID}" != "debian" ]]; then + echo "ERROR: cannot install on $ID distribution - only Ubuntu and Debian are supported" + exit 1 + fi fi # 1. make sure to remove old stable if any. diff --git a/packages/playwright-core/bin/reinstall_msedge_beta_linux.sh b/packages/playwright-core/bin/reinstall_msedge_beta_linux.sh index ff8c3c9f89..ececd05ace 100755 --- a/packages/playwright-core/bin/reinstall_msedge_beta_linux.sh +++ b/packages/playwright-core/bin/reinstall_msedge_beta_linux.sh @@ -8,15 +8,17 @@ if [[ $(arch) == "aarch64" ]]; then exit 1 fi -if [[ ! -f "/etc/os-release" ]]; then - echo "ERROR: cannot install on unknown linux distribution (/etc/os-release is missing)" - exit 1 -fi +if [ -z "$PLAYWRIGHT_HOST_PLATFORM_OVERRIDE" ]; then + if [[ ! -f "/etc/os-release" ]]; then + echo "ERROR: cannot install on unknown linux distribution (/etc/os-release is missing)" + exit 1 + fi -ID=$(bash -c 'source /etc/os-release && echo $ID') -if [[ "${ID}" != "ubuntu" && "${ID}" != "debian" ]]; then - echo "ERROR: cannot install on $ID distribution - only Ubuntu and Debian are supported" - exit 1 + ID=$(bash -c 'source /etc/os-release && echo $ID') + if [[ "${ID}" != "ubuntu" && "${ID}" != "debian" ]]; then + echo "ERROR: cannot install on $ID distribution - only Ubuntu and Debian are supported" + exit 1 + fi fi # 1. make sure to remove old beta if any. diff --git a/packages/playwright-core/bin/reinstall_msedge_dev_linux.sh b/packages/playwright-core/bin/reinstall_msedge_dev_linux.sh index 6a026722b1..6ab84c3100 100755 --- a/packages/playwright-core/bin/reinstall_msedge_dev_linux.sh +++ b/packages/playwright-core/bin/reinstall_msedge_dev_linux.sh @@ -8,15 +8,17 @@ if [[ $(arch) == "aarch64" ]]; then exit 1 fi -if [[ ! -f "/etc/os-release" ]]; then - echo "ERROR: cannot install on unknown linux distribution (/etc/os-release is missing)" - exit 1 -fi +if [ -z "$PLAYWRIGHT_HOST_PLATFORM_OVERRIDE" ]; then + if [[ ! -f "/etc/os-release" ]]; then + echo "ERROR: cannot install on unknown linux distribution (/etc/os-release is missing)" + exit 1 + fi -ID=$(bash -c 'source /etc/os-release && echo $ID') -if [[ "${ID}" != "ubuntu" && "${ID}" != "debian" ]]; then - echo "ERROR: cannot install on $ID distribution - only Ubuntu and Debian are supported" - exit 1 + ID=$(bash -c 'source /etc/os-release && echo $ID') + if [[ "${ID}" != "ubuntu" && "${ID}" != "debian" ]]; then + echo "ERROR: cannot install on $ID distribution - only Ubuntu and Debian are supported" + exit 1 + fi fi # 1. make sure to remove old dev if any. diff --git a/packages/playwright-core/bin/reinstall_msedge_stable_linux.sh b/packages/playwright-core/bin/reinstall_msedge_stable_linux.sh index 1f2c9bf382..e66f85bbba 100755 --- a/packages/playwright-core/bin/reinstall_msedge_stable_linux.sh +++ b/packages/playwright-core/bin/reinstall_msedge_stable_linux.sh @@ -8,15 +8,17 @@ if [[ $(arch) == "aarch64" ]]; then exit 1 fi -if [[ ! -f "/etc/os-release" ]]; then - echo "ERROR: cannot install on unknown linux distribution (/etc/os-release is missing)" - exit 1 -fi +if [ -z "$PLAYWRIGHT_HOST_PLATFORM_OVERRIDE" ]; then + if [[ ! -f "/etc/os-release" ]]; then + echo "ERROR: cannot install on unknown linux distribution (/etc/os-release is missing)" + exit 1 + fi -ID=$(bash -c 'source /etc/os-release && echo $ID') -if [[ "${ID}" != "ubuntu" && "${ID}" != "debian" ]]; then - echo "ERROR: cannot install on $ID distribution - only Ubuntu and Debian are supported" - exit 1 + ID=$(bash -c 'source /etc/os-release && echo $ID') + if [[ "${ID}" != "ubuntu" && "${ID}" != "debian" ]]; then + echo "ERROR: cannot install on $ID distribution - only Ubuntu and Debian are supported" + exit 1 + fi fi # 1. make sure to remove old stable if any. diff --git a/packages/playwright-core/browsers.json b/packages/playwright-core/browsers.json index c18df4aef3..32d5e3b375 100644 --- a/packages/playwright-core/browsers.json +++ b/packages/playwright-core/browsers.json @@ -3,31 +3,37 @@ "browsers": [ { "name": "chromium", - "revision": "1146", + "revision": "1149", "installByDefault": true, - "browserVersion": "131.0.6778.24" + "browserVersion": "132.0.6834.6" + }, + { + "name": "chromium-headless-shell", + "revision": "1149", + "installByDefault": true, + "browserVersion": "132.0.6834.6" }, { "name": "chromium-tip-of-tree", - "revision": "1271", + "revision": "1279", "installByDefault": false, - "browserVersion": "132.0.6791.0" + "browserVersion": "133.0.6846.0" }, { "name": "firefox", - "revision": "1465", + "revision": "1466", "installByDefault": true, - "browserVersion": "131.0" + "browserVersion": "132.0" }, { "name": "firefox-beta", - "revision": "1465", + "revision": "1466", "installByDefault": false, - "browserVersion": "132.0b8" + "browserVersion": "133.0b9" }, { "name": "webkit", - "revision": "2102", + "revision": "2104", "installByDefault": true, "revisionOverrides": { "mac10.14": "1446", @@ -39,7 +45,7 @@ "ubuntu20.04-x64": "2092", "ubuntu20.04-arm64": "2092" }, - "browserVersion": "18.0" + "browserVersion": "18.2" }, { "name": "ffmpeg", diff --git a/packages/playwright-core/bundles/utils/package-lock.json b/packages/playwright-core/bundles/utils/package-lock.json index e31dbe6209..6d9b0562e3 100644 --- a/packages/playwright-core/bundles/utils/package-lock.json +++ b/packages/playwright-core/bundles/utils/package-lock.json @@ -11,7 +11,7 @@ "colors": "1.4.0", "commander": "8.3.0", "debug": "^4.3.4", - "diff-match-patch": "^1.0.5", + "diff": "^7.0.0", "dotenv": "^16.4.5", "graceful-fs": "4.2.10", "https-proxy-agent": "7.0.5", @@ -27,11 +27,11 @@ "socks-proxy-agent": "8.0.4", "stack-utils": "2.0.5", "ws": "8.17.1", - "yaml": "^2.5.1" + "yaml": "^2.6.0" }, "devDependencies": { "@types/debug": "^4.1.7", - "@types/diff-match-patch": "^1.0.36", + "@types/diff": "^6.0.0", "@types/mime": "^2.0.3", "@types/minimatch": "^3.0.5", "@types/pngjs": "^6.0.1", @@ -51,11 +51,12 @@ "@types/ms": "*" } }, - "node_modules/@types/diff-match-patch": { - "version": "1.0.36", - "resolved": "https://registry.npmjs.org/@types/diff-match-patch/-/diff-match-patch-1.0.36.tgz", - "integrity": "sha512-xFdR6tkm0MWvBfO8xXCSsinYxHcqkQUlcHeSpMC2ukzOb6lwQAfDmW+Qt0AvlGd8HpsS28qKsB+oPeJn9I39jg==", - "dev": true + "node_modules/@types/diff": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@types/diff/-/diff-6.0.0.tgz", + "integrity": "sha512-dhVCYGv3ZSbzmQaBSagrv1WJ6rXCdkyTcDyoNu1MD8JohI7pR7k8wdZEm+mvdxRKXyHVwckFzWU1vJc+Z29MlA==", + "dev": true, + "license": "MIT" }, "node_modules/@types/mime": { "version": "2.0.3", @@ -209,10 +210,14 @@ "node": ">=8" } }, - "node_modules/diff-match-patch": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.5.tgz", - "integrity": "sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==" + "node_modules/diff": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", + "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } }, "node_modules/dotenv": { "version": "16.4.5", @@ -469,10 +474,10 @@ "@types/ms": "*" } }, - "@types/diff-match-patch": { - "version": "1.0.36", - "resolved": "https://registry.npmjs.org/@types/diff-match-patch/-/diff-match-patch-1.0.36.tgz", - "integrity": "sha512-xFdR6tkm0MWvBfO8xXCSsinYxHcqkQUlcHeSpMC2ukzOb6lwQAfDmW+Qt0AvlGd8HpsS28qKsB+oPeJn9I39jg==", + "@types/diff": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@types/diff/-/diff-6.0.0.tgz", + "integrity": "sha512-dhVCYGv3ZSbzmQaBSagrv1WJ6rXCdkyTcDyoNu1MD8JohI7pR7k8wdZEm+mvdxRKXyHVwckFzWU1vJc+Z29MlA==", "dev": true }, "@types/mime": { @@ -606,10 +611,10 @@ "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==" }, - "diff-match-patch": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.5.tgz", - "integrity": "sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==" + "diff": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", + "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==" }, "dotenv": { "version": "16.4.5", diff --git a/packages/playwright-core/bundles/utils/package.json b/packages/playwright-core/bundles/utils/package.json index d8f6b7a481..1900d423f5 100644 --- a/packages/playwright-core/bundles/utils/package.json +++ b/packages/playwright-core/bundles/utils/package.json @@ -12,7 +12,7 @@ "colors": "1.4.0", "commander": "8.3.0", "debug": "^4.3.4", - "diff-match-patch": "^1.0.5", + "diff": "^7.0.0", "dotenv": "^16.4.5", "graceful-fs": "4.2.10", "https-proxy-agent": "7.0.5", @@ -28,11 +28,11 @@ "socks-proxy-agent": "8.0.4", "stack-utils": "2.0.5", "ws": "8.17.1", - "yaml": "^2.5.1" + "yaml": "^2.6.0" }, "devDependencies": { "@types/debug": "^4.1.7", - "@types/diff-match-patch": "^1.0.36", + "@types/diff": "^6.0.0", "@types/mime": "^2.0.3", "@types/minimatch": "^3.0.5", "@types/pngjs": "^6.0.1", diff --git a/packages/playwright-core/bundles/utils/src/utilsBundleImpl.ts b/packages/playwright-core/bundles/utils/src/utilsBundleImpl.ts index ba8bc8d90b..5c8434f907 100644 --- a/packages/playwright-core/bundles/utils/src/utilsBundleImpl.ts +++ b/packages/playwright-core/bundles/utils/src/utilsBundleImpl.ts @@ -20,8 +20,8 @@ export const colors = colorsLibrary; import debugLibrary from 'debug'; export const debug = debugLibrary; -import diffMatchPatchLibrary from 'diff-match-patch'; -export const diffMatchPatch = diffMatchPatchLibrary; +import * as diffLibrary from 'diff'; +export const diff = diffLibrary; import dotenvLibrary from 'dotenv'; export const dotenv = dotenvLibrary; diff --git a/packages/playwright-core/package.json b/packages/playwright-core/package.json index d55a652b57..9b484085dd 100644 --- a/packages/playwright-core/package.json +++ b/packages/playwright-core/package.json @@ -1,6 +1,6 @@ { "name": "playwright-core", - "version": "1.49.0-next", + "version": "1.50.0-next", "description": "A high-level API to automate web browsers", "repository": { "type": "git", diff --git a/packages/playwright-core/src/cli/program.ts b/packages/playwright-core/src/cli/program.ts index 59ad0cd9f8..6cf0403446 100644 --- a/packages/playwright-core/src/cli/program.ts +++ b/packages/playwright-core/src/cli/program.ts @@ -96,16 +96,42 @@ function suggestedBrowsersToInstall() { return registry.executables().filter(e => e.installType !== 'none' && e.type !== 'tool').map(e => e.name).join(', '); } -function checkBrowsersToInstall(args: string[]): Executable[] { +function defaultBrowsersToInstall(options: { noShell?: boolean, onlyShell?: boolean }): Executable[] { + let executables = registry.defaultExecutables(); + if (options.noShell) + executables = executables.filter(e => e.name !== 'chromium-headless-shell'); + if (options.onlyShell) + executables = executables.filter(e => e.name !== 'chromium'); + return executables; +} + +function checkBrowsersToInstall(args: string[], options: { noShell?: boolean, onlyShell?: boolean }): Executable[] { + if (options.noShell && options.onlyShell) + throw new Error(`Only one of --no-shell and --only-shell can be specified`); + const faultyArguments: string[] = []; const executables: Executable[] = []; - for (const arg of args) { + const handleArgument = (arg: string) => { const executable = registry.findExecutable(arg); if (!executable || executable.installType === 'none') faultyArguments.push(arg); else executables.push(executable); + if (executable?.browserName === 'chromium') + executables.push(registry.findExecutable('ffmpeg')!); + }; + + for (const arg of args) { + if (arg === 'chromium') { + if (!options.onlyShell) + handleArgument('chromium'); + if (!options.noShell) + handleArgument('chromium-headless-shell'); + } else { + handleArgument(arg); + } } + if (faultyArguments.length) throw new Error(`Invalid installation targets: ${faultyArguments.map(name => `'${name}'`).join(', ')}. Expecting one of: ${suggestedBrowsersToInstall()}`); return executables; @@ -118,7 +144,12 @@ program .option('--with-deps', 'install system dependencies for browsers') .option('--dry-run', 'do not execute installation, only print information') .option('--force', 'force reinstall of stable browser channels') - .action(async function(args: string[], options: { withDeps?: boolean, force?: boolean, dryRun?: boolean }) { + .option('--only-shell', 'only install headless shell when installing chromium') + .option('--no-shell', 'do not install chromium headless shell') + .action(async function(args: string[], options: { withDeps?: boolean, force?: boolean, dryRun?: boolean, shell?: boolean, noShell?: boolean, onlyShell?: boolean }) { + // For '--no-shell' option, commander sets `shell: false` instead. + if (options.shell === false) + options.noShell = true; if (isLikelyNpxGlobal()) { console.error(wrapInASCIIBox([ `WARNING: It looks like you are running 'npx playwright install' without first`, @@ -141,7 +172,7 @@ program } try { const hasNoArguments = !args.length; - const executables = hasNoArguments ? registry.defaultExecutables() : checkBrowsersToInstall(args); + const executables = hasNoArguments ? defaultBrowsersToInstall(options) : checkBrowsersToInstall(args, options); if (options.withDeps) await registry.installDeps(executables, !!options.dryRun); if (options.dryRun) { @@ -199,9 +230,9 @@ program .action(async function(args: string[], options: { dryRun?: boolean }) { try { if (!args.length) - await registry.installDeps(registry.defaultExecutables(), !!options.dryRun); + await registry.installDeps(defaultBrowsersToInstall({}), !!options.dryRun); else - await registry.installDeps(checkBrowsersToInstall(args), !!options.dryRun); + await registry.installDeps(checkBrowsersToInstall(args, {}), !!options.dryRun); } catch (e) { console.log(`Failed to install browser dependencies\n${e}`); gracefullyProcessExitDoNotHang(1); diff --git a/packages/playwright-core/src/client/channelOwner.ts b/packages/playwright-core/src/client/channelOwner.ts index 89f3edced3..a5d753507b 100644 --- a/packages/playwright-core/src/client/channelOwner.ts +++ b/packages/playwright-core/src/client/channelOwner.ts @@ -168,7 +168,7 @@ export abstract class ChannelOwner(func: (apiZone: ApiZone) => Promise, isInternal = false): Promise { + async _wrapApiCall(func: (apiZone: ApiZone) => Promise, isInternal?: boolean): Promise { const logger = this._logger; const apiZone = zones.zoneData('apiZone'); if (apiZone) @@ -178,7 +178,8 @@ export abstract class ChannelOwner, frames: StackFrame[], userData: any, out: { stepId?: string }): void; onApiCallEnd(userData: any, error?: Error): void; - onWillPause(): void; + onWillPause(options: { keepTestTimeout: boolean }): void; runAfterCreateBrowserContext(context: BrowserContext): Promise; runAfterCreateRequestContext(context: APIRequestContext): Promise; @@ -35,7 +35,7 @@ export interface ClientInstrumentation { export interface ClientInstrumentationListener { onApiCallBegin?(apiName: string, params: Record, frames: StackFrame[], userData: any, out: { stepId?: string }): void; onApiCallEnd?(userData: any, error?: Error): void; - onWillPause?(): void; + onWillPause?(options: { keepTestTimeout: boolean }): void; runAfterCreateBrowserContext?(context: BrowserContext): Promise; runAfterCreateRequestContext?(context: APIRequestContext): Promise; diff --git a/packages/playwright-core/src/client/network.ts b/packages/playwright-core/src/client/network.ts index f3b066c171..cb18681ccf 100644 --- a/packages/playwright-core/src/client/network.ts +++ b/packages/playwright-core/src/client/network.ts @@ -22,14 +22,14 @@ import { Worker } from './worker'; import type { Headers, RemoteAddr, SecurityDetails, WaitForEventOptions } from './types'; import fs from 'fs'; import { mime } from '../utilsBundle'; -import { assert, isString, headersObjectToArray, isRegExp, rewriteErrorMessage } from '../utils'; +import { assert, isString, headersObjectToArray, isRegExp, rewriteErrorMessage, MultiMap, urlMatches, zones } from '../utils'; +import type { URLMatch, Zone } from '../utils'; import { ManualPromise, LongStandingScope } from '../utils/manualPromise'; import { Events } from './events'; import type { Page } from './page'; import { Waiter } from './waiter'; import type * as api from '../../types/types'; import type { HeadersArray } from '../common/types'; -import { MultiMap, urlMatches, type URLMatch } from '../utils'; import { APIResponse } from './fetch'; import type { Serializable } from '../../types/structs'; import type { BrowserContext } from './browserContext'; @@ -97,6 +97,7 @@ export class Request extends ChannelOwner implements ap constructor(parent: ChannelOwner, type: string, guid: string, initializer: channels.RequestInitializer) { super(parent, type, guid, initializer); + this.markAsInternalType(); this._redirectedFrom = Request.fromNullable(initializer.redirectedFrom); if (this._redirectedFrom) this._redirectedFrom._redirectedTo = this; @@ -645,6 +646,7 @@ export class Response extends ChannelOwner implements constructor(parent: ChannelOwner, type: string, guid: string, initializer: channels.ResponseInitializer) { super(parent, type, guid, initializer); + this.markAsInternalType(); this._provisionalHeaders = new RawHeaders(initializer.headers); this._request = Request.from(this._initializer.request); Object.assign(this._request._timing, this._initializer.timing); @@ -811,12 +813,14 @@ export class RouteHandler { readonly handler: RouteHandlerCallback; private _ignoreException: boolean = false; private _activeInvocations: Set<{ complete: Promise, route: Route }> = new Set(); + private _svedZone: Zone; constructor(baseURL: string | undefined, url: URLMatch, handler: RouteHandlerCallback, times: number = Number.MAX_SAFE_INTEGER) { this._baseURL = baseURL; this._times = times; this.url = url; this.handler = handler; + this._svedZone = zones.currentZone(); } static prepareInterceptionPatterns(handlers: RouteHandler[]) { @@ -840,6 +844,10 @@ export class RouteHandler { } public async handle(route: Route): Promise { + return await this._svedZone.run(async () => this._handleImpl(route)); + } + + private async _handleImpl(route: Route): Promise { const handlerInvocation = { complete: new ManualPromise(), route } ; this._activeInvocations.add(handlerInvocation); try { diff --git a/packages/playwright-core/src/client/page.ts b/packages/playwright-core/src/client/page.ts index c8d816f62a..f1d90fece2 100644 --- a/packages/playwright-core/src/client/page.ts +++ b/packages/playwright-core/src/client/page.ts @@ -786,14 +786,14 @@ export class Page extends ChannelOwner implements api.Page return [...this._workers]; } - async pause() { + async pause(_options?: { __testHookKeepTestTimeout: boolean }) { if (require('inspector').url()) return; const defaultNavigationTimeout = this._browserContext._timeoutSettings.defaultNavigationTimeout(); const defaultTimeout = this._browserContext._timeoutSettings.defaultTimeout(); this._browserContext.setDefaultNavigationTimeout(0); this._browserContext.setDefaultTimeout(0); - this._instrumentation?.onWillPause(); + this._instrumentation?.onWillPause({ keepTestTimeout: !!_options?.__testHookKeepTestTimeout }); await this._closedOrCrashedScope.safeRace(this.context()._channel.pause()); this._browserContext.setDefaultNavigationTimeout(defaultNavigationTimeout); this._browserContext.setDefaultTimeout(defaultTimeout); diff --git a/packages/playwright-core/src/client/tracing.ts b/packages/playwright-core/src/client/tracing.ts index b5c411cc65..2481741e3e 100644 --- a/packages/playwright-core/src/client/tracing.ts +++ b/packages/playwright-core/src/client/tracing.ts @@ -51,6 +51,18 @@ export class Tracing extends ChannelOwner implements ap await this._startCollectingStacks(traceName); } + async group(name: string, options: { location?: { file: string, line?: number, column?: number } } = {}) { + await this._wrapApiCall(async () => { + await this._channel.tracingGroup({ name, location: options.location }); + }, false); + } + + async groupEnd() { + await this._wrapApiCall(async () => { + await this._channel.tracingGroupEnd(); + }, false); + } + private async _startCollectingStacks(traceName: string) { if (!this._isTracing) { this._isTracing = true; diff --git a/packages/playwright-core/src/client/waiter.ts b/packages/playwright-core/src/client/waiter.ts index 1b3ffbe78d..7b57fe8960 100644 --- a/packages/playwright-core/src/client/waiter.ts +++ b/packages/playwright-core/src/client/waiter.ts @@ -17,7 +17,8 @@ import type { EventEmitter } from 'events'; import { rewriteErrorMessage } from '../utils/stackTrace'; import { TimeoutError } from './errors'; -import { createGuid } from '../utils'; +import { createGuid, zones } from '../utils'; +import type { Zone } from '../utils'; import type * as channels from '@protocol/channels'; import type { ChannelOwner } from './channelOwner'; @@ -29,10 +30,13 @@ export class Waiter { private _channelOwner: ChannelOwner; private _waitId: string; private _error: string | undefined; + private _savedZone: Zone; constructor(channelOwner: ChannelOwner, event: string) { this._waitId = createGuid(); this._channelOwner = channelOwner; + this._savedZone = zones.currentZone(); + this._channelOwner._channel.waitForEventInfo({ info: { waitId: this._waitId, phase: 'before', event } }).catch(() => {}); this._dispose = [ () => this._channelOwner._wrapApiCall(async () => { @@ -46,12 +50,12 @@ export class Waiter { } async waitForEvent(emitter: EventEmitter, event: string, predicate?: (arg: T) => boolean | Promise): Promise { - const { promise, dispose } = waitForEvent(emitter, event, predicate); + const { promise, dispose } = waitForEvent(emitter, event, this._savedZone, predicate); return await this.waitForPromise(promise, dispose); } rejectOnEvent(emitter: EventEmitter, event: string, error: Error | (() => Error), predicate?: (arg: T) => boolean | Promise) { - const { promise, dispose } = waitForEvent(emitter, event, predicate); + const { promise, dispose } = waitForEvent(emitter, event, this._savedZone, predicate); this._rejectOn(promise.then(() => { throw (typeof error === 'function' ? error() : error); }), dispose); } @@ -103,19 +107,21 @@ export class Waiter { } } -function waitForEvent(emitter: EventEmitter, event: string, predicate?: (arg: T) => boolean | Promise): { promise: Promise, dispose: () => void } { +function waitForEvent(emitter: EventEmitter, event: string, savedZone: Zone, predicate?: (arg: T) => boolean | Promise): { promise: Promise, dispose: () => void } { let listener: (eventArg: any) => void; const promise = new Promise((resolve, reject) => { listener = async (eventArg: any) => { - try { - if (predicate && !(await predicate(eventArg))) - return; - emitter.removeListener(event, listener); - resolve(eventArg); - } catch (e) { - emitter.removeListener(event, listener); - reject(e); - } + await savedZone.run(async () => { + try { + if (predicate && !(await predicate(eventArg))) + return; + emitter.removeListener(event, listener); + resolve(eventArg); + } catch (e) { + emitter.removeListener(event, listener); + reject(e); + } + }); }; emitter.addListener(event, listener); }); diff --git a/packages/playwright-core/src/protocol/validator.ts b/packages/playwright-core/src/protocol/validator.ts index 13dbeaa362..7fe92a7947 100644 --- a/packages/playwright-core/src/protocol/validator.ts +++ b/packages/playwright-core/src/protocol/validator.ts @@ -422,7 +422,8 @@ scheme.DebugControllerSetRecorderModeParams = tObject({ }); scheme.DebugControllerSetRecorderModeResult = tOptional(tObject({})); scheme.DebugControllerHighlightParams = tObject({ - selector: tString, + selector: tOptional(tString), + ariaTemplate: tOptional(tString), }); scheme.DebugControllerHighlightResult = tOptional(tObject({})); scheme.DebugControllerHideHighlightParams = tOptional(tObject({})); @@ -2297,6 +2298,17 @@ scheme.TracingTracingStartChunkParams = tObject({ scheme.TracingTracingStartChunkResult = tObject({ traceName: tString, }); +scheme.TracingTracingGroupParams = tObject({ + name: tString, + location: tOptional(tObject({ + file: tString, + line: tOptional(tNumber), + column: tOptional(tNumber), + })), +}); +scheme.TracingTracingGroupResult = tOptional(tObject({})); +scheme.TracingTracingGroupEndParams = tOptional(tObject({})); +scheme.TracingTracingGroupEndResult = tOptional(tObject({})); scheme.TracingTracingStopChunkParams = tObject({ mode: tEnum(['archive', 'discard', 'entries']), }); diff --git a/packages/playwright-core/src/server/ariaSnapshot.ts b/packages/playwright-core/src/server/ariaSnapshot.ts index 744167048a..516688fef3 100644 --- a/packages/playwright-core/src/server/ariaSnapshot.ts +++ b/packages/playwright-core/src/server/ariaSnapshot.ts @@ -14,246 +14,17 @@ * limitations under the License. */ -import type { AriaTemplateNode, AriaTemplateRoleNode } from './injected/ariaSnapshot'; +import { parseYamlTemplate } from '../utils/isomorphic/ariaSnapshot'; +import type { AriaTemplateNode, ParsedYaml } from '@isomorphic/ariaSnapshot'; import { yaml } from '../utilsBundle'; -import { assert } from '../utils'; export function parseAriaSnapshot(text: string): AriaTemplateNode { - const fragment = yaml.parse(text) as any[]; - const result: AriaTemplateNode = { kind: 'role', role: 'fragment' }; - populateNode(result, fragment); - return result; + return parseYamlTemplate(parseYamlForAriaSnapshot(text)); } -function populateNode(node: AriaTemplateRoleNode, container: any[]) { - for (const object of container) { - if (typeof object === 'string') { - const childNode = KeyParser.parse(object); - node.children = node.children || []; - node.children.push(childNode); - continue; - } - - for (const key of Object.keys(object)) { - node.children = node.children || []; - const value = object[key]; - - if (key === 'text') { - node.children.push({ - kind: 'text', - text: valueOrRegex(value) - }); - continue; - } - - const childNode = KeyParser.parse(key); - if (childNode.kind === 'text') { - node.children.push({ - kind: 'text', - text: valueOrRegex(value) - }); - continue; - } - - if (typeof value === 'string') { - node.children.push({ - ...childNode, children: [{ - kind: 'text', - text: valueOrRegex(value) - }] - }); - continue; - } - - node.children.push(childNode); - populateNode(childNode, value); - } - } -} - -function applyAttribute(node: AriaTemplateRoleNode, key: string, value: string) { - if (key === 'checked') { - assert(value === 'true' || value === 'false' || value === 'mixed', 'Value of "disabled" attribute must be a boolean or "mixed"'); - node.checked = value === 'true' ? true : value === 'false' ? false : 'mixed'; - return; - } - if (key === 'disabled') { - assert(value === 'true' || value === 'false', 'Value of "disabled" attribute must be a boolean'); - node.disabled = value === 'true'; - return; - } - if (key === 'expanded') { - assert(value === 'true' || value === 'false', 'Value of "expanded" attribute must be a boolean'); - node.expanded = value === 'true'; - return; - } - if (key === 'level') { - assert(!isNaN(Number(value)), 'Value of "level" attribute must be a number'); - node.level = Number(value); - return; - } - if (key === 'pressed') { - assert(value === 'true' || value === 'false' || value === 'mixed', 'Value of "pressed" attribute must be a boolean or "mixed"'); - node.pressed = value === 'true' ? true : value === 'false' ? false : 'mixed'; - return; - } - if (key === 'selected') { - assert(value === 'true' || value === 'false', 'Value of "selected" attribute must be a boolean'); - node.selected = value === 'true'; - return; - } - throw new Error(`Unsupported attribute [${key}] `); -} - -function normalizeWhitespace(text: string) { - return text.replace(/[\r\n\s\t]+/g, ' ').trim(); -} - -function valueOrRegex(value: string): string | RegExp { - return value.startsWith('/') && value.endsWith('/') ? new RegExp(value.slice(1, -1)) : normalizeWhitespace(value); -} - -export class KeyParser { - private _input: string; - private _pos: number; - private _length: number; - - static parse(input: string): AriaTemplateNode { - return new KeyParser(input)._parse(); - } - - constructor(input: string) { - this._input = input; - this._pos = 0; - this._length = input.length; - } - - private _peek() { - return this._input[this._pos] || ''; - } - - private _next() { - if (this._pos < this._length) - return this._input[this._pos++]; - return null; - } - - private _eof() { - return this._pos >= this._length; - } - - private _skipWhitespace() { - while (!this._eof() && /\s/.test(this._peek())) - this._pos++; - } - - private _readIdentifier(): string { - if (this._eof()) - throw new Error('Unexpected end of input when expecting identifier'); - const start = this._pos; - while (!this._eof() && /[a-zA-Z]/.test(this._peek())) - this._pos++; - return this._input.slice(start, this._pos); - } - - private _readString(): string { - let result = ''; - let escaped = false; - while (!this._eof()) { - const ch = this._next(); - if (escaped) { - result += ch; - escaped = false; - } else if (ch === '\\') { - escaped = true; - result += ch; - } else if (ch === '"') { - return result; - } else { - result += ch; - } - } - throw new Error('Unterminated string starting at position ' + this._pos); - } - - private _readRegex(): string { - let result = ''; - let escaped = false; - while (!this._eof()) { - const ch = this._next(); - if (escaped) { - result += ch; - escaped = false; - } else if (ch === '\\') { - escaped = true; - result += ch; - } else if (ch === '/') { - return result; - } else { - result += ch; - } - } - throw new Error('Unterminated regex starting at position ' + this._pos); - } - - private _readStringOrRegex(): string | RegExp | null { - const ch = this._peek(); - if (ch === '"') { - this._next(); - return this._readString(); - } - - if (ch === '/') { - this._next(); - return new RegExp(this._readRegex()); - } - - return null; - } - - private _readFlags(): Map { - const flags = new Map(); - while (true) { - this._skipWhitespace(); - if (this._peek() === '[') { - this._next(); - this._skipWhitespace(); - const flagName = this._readIdentifier(); - this._skipWhitespace(); - let flagValue = ''; - if (this._peek() === '=') { - this._next(); - this._skipWhitespace(); - while (this._peek() !== ']' && !this._eof()) - flagValue += this._next(); - } - this._skipWhitespace(); - if (this._peek() !== ']') - throw new Error('Expected ] at position ' + this._pos); - - this._next(); // Consume ']' - flags.set(flagName, flagValue || 'true'); - } else { - break; - } - } - return flags; - } - - _parse(): AriaTemplateNode { - this._skipWhitespace(); - - const role = this._readIdentifier() as AriaTemplateRoleNode['role']; - this._skipWhitespace(); - const name = this._readStringOrRegex() || ''; - const result: AriaTemplateRoleNode = { kind: 'role', role, name }; - const flags = this._readFlags(); - for (const [name, value] of flags) - applyAttribute(result, name, value); - this._skipWhitespace(); - if (!this._eof()) - throw new Error('Unexpected input at position ' + this._pos); - - return result; - } +export function parseYamlForAriaSnapshot(text: string): ParsedYaml { + const parsed = yaml.parse(text); + if (!Array.isArray(parsed)) + throw new Error('Expected object key starting with "- ":\n\n' + text + '\n'); + return parsed; } diff --git a/packages/playwright-core/src/server/bidi/bidiChromium.ts b/packages/playwright-core/src/server/bidi/bidiChromium.ts index 32751bd51a..9572ac71ed 100644 --- a/packages/playwright-core/src/server/bidi/bidiChromium.ts +++ b/packages/playwright-core/src/server/bidi/bidiChromium.ts @@ -112,10 +112,7 @@ export class BidiChromium extends BrowserType { if (options.devtools) chromeArguments.push('--auto-open-devtools-for-tabs'); if (options.headless) { - if (process.env.PLAYWRIGHT_CHROMIUM_USE_HEADLESS_NEW) - chromeArguments.push('--headless=new'); - else - chromeArguments.push('--headless=old'); + chromeArguments.push('--headless'); chromeArguments.push( '--hide-scrollbars', diff --git a/packages/playwright-core/src/server/browserType.ts b/packages/playwright-core/src/server/browserType.ts index ec8524c247..128b80a352 100644 --- a/packages/playwright-core/src/server/browserType.ts +++ b/packages/playwright-core/src/server/browserType.ts @@ -208,7 +208,7 @@ export abstract class BrowserType extends SdkObject { throw new Error(`Failed to launch ${this._name} because executable doesn't exist at ${executablePath}`); executable = executablePath; } else { - const registryExecutable = registry.findExecutable(options.channel || this._name); + const registryExecutable = registry.findExecutable(this.getExecutableName(options)); if (!registryExecutable || registryExecutable.browserName !== this._name) throw new Error(`Unsupported ${this._name} channel "${options.channel}"`); executable = registryExecutable.executablePathOrDie(this.attribution.playwright.options.sdkLanguage); @@ -332,6 +332,10 @@ export abstract class BrowserType extends SdkObject { async prepareUserDataDir(options: types.LaunchOptions, userDataDir: string): Promise { } + getExecutableName(options: types.LaunchOptions): string { + return options.channel || this._name; + } + abstract defaultArgs(options: types.LaunchOptions, isPersistent: boolean, userDataDir: string): string[]; abstract connectToTransport(transport: ConnectionTransport, options: BrowserOptions): Promise; abstract amendEnvironment(env: Env, userDataDir: string, executable: string, browserArguments: string[]): Env; diff --git a/packages/playwright-core/src/server/chromium/chromium.ts b/packages/playwright-core/src/server/chromium/chromium.ts index 023ee0b7d1..8fce8f51ca 100644 --- a/packages/playwright-core/src/server/chromium/chromium.ts +++ b/packages/playwright-core/src/server/chromium/chromium.ts @@ -294,25 +294,20 @@ export class Chromium extends BrowserType { throw new Error('Playwright manages remote debugging connection itself.'); if (args.find(arg => !arg.startsWith('-'))) throw new Error('Arguments can not specify page to be opened'); - if (!options.headless && options.channel === 'chromium-headless-shell') - throw new Error('Cannot launch headed Chromium with `chromium-headless-shell` channel. Consider using regular Chromium instead.'); const chromeArguments = [...chromiumSwitches]; if (os.platform() === 'darwin') { // See https://github.com/microsoft/playwright/issues/7362 chromeArguments.push('--enable-use-zoom-for-dsf=false'); // See https://bugs.chromium.org/p/chromium/issues/detail?id=1407025. - if (options.headless) + if (options.headless && (!options.channel || options.channel === 'chromium-headless-shell')) chromeArguments.push('--use-angle'); } if (options.devtools) chromeArguments.push('--auto-open-devtools-for-tabs'); if (options.headless) { - if (process.env.PLAYWRIGHT_CHROMIUM_USE_HEADLESS_NEW) - chromeArguments.push('--headless=new'); - else - chromeArguments.push('--headless=old'); + chromeArguments.push('--headless'); chromeArguments.push( '--hide-scrollbars', @@ -352,6 +347,12 @@ export class Chromium extends BrowserType { return new ChromiumReadyState(); return undefined; } + + override getExecutableName(options: types.LaunchOptions): string { + if (options.channel) + return options.channel; + return options.headless ? 'chromium-headless-shell' : 'chromium'; + } } class ChromiumReadyState extends BrowserReadyState { diff --git a/packages/playwright-core/src/server/chromium/protocol.d.ts b/packages/playwright-core/src/server/chromium/protocol.d.ts index 35aa6f2eb9..3a61fbca59 100644 --- a/packages/playwright-core/src/server/chromium/protocol.d.ts +++ b/packages/playwright-core/src/server/chromium/protocol.d.ts @@ -112,7 +112,7 @@ export module Protocol { - from 'checked' to 'selected': states which apply to widgets - from 'activedescendant' to 'owns' - relationships between elements other than parent/child/sibling. */ - export type AXPropertyName = "busy"|"disabled"|"editable"|"focusable"|"focused"|"hidden"|"hiddenRoot"|"invalid"|"keyshortcuts"|"settable"|"roledescription"|"live"|"atomic"|"relevant"|"root"|"autocomplete"|"hasPopup"|"level"|"multiselectable"|"orientation"|"multiline"|"readonly"|"required"|"valuemin"|"valuemax"|"valuetext"|"checked"|"expanded"|"modal"|"pressed"|"selected"|"activedescendant"|"controls"|"describedby"|"details"|"errormessage"|"flowto"|"labelledby"|"owns"|"url"; + export type AXPropertyName = "actions"|"busy"|"disabled"|"editable"|"focusable"|"focused"|"hidden"|"hiddenRoot"|"invalid"|"keyshortcuts"|"settable"|"roledescription"|"live"|"atomic"|"relevant"|"root"|"autocomplete"|"hasPopup"|"level"|"multiselectable"|"orientation"|"multiline"|"readonly"|"required"|"valuemin"|"valuemax"|"valuetext"|"checked"|"expanded"|"modal"|"pressed"|"selected"|"activedescendant"|"controls"|"describedby"|"details"|"errormessage"|"flowto"|"labelledby"|"owns"|"url"; /** * A node in the accessibility tree. */ @@ -694,7 +694,7 @@ percentage [0 - 100] for scroll driven animations export interface AffectedFrame { frameId: Page.FrameId; } - export type CookieExclusionReason = "ExcludeSameSiteUnspecifiedTreatedAsLax"|"ExcludeSameSiteNoneInsecure"|"ExcludeSameSiteLax"|"ExcludeSameSiteStrict"|"ExcludeInvalidSameParty"|"ExcludeSamePartyCrossPartyContext"|"ExcludeDomainNonASCII"|"ExcludeThirdPartyCookieBlockedInFirstPartySet"|"ExcludeThirdPartyPhaseout"; + export type CookieExclusionReason = "ExcludeSameSiteUnspecifiedTreatedAsLax"|"ExcludeSameSiteNoneInsecure"|"ExcludeSameSiteLax"|"ExcludeSameSiteStrict"|"ExcludeInvalidSameParty"|"ExcludeSamePartyCrossPartyContext"|"ExcludeDomainNonASCII"|"ExcludeThirdPartyCookieBlockedInFirstPartySet"|"ExcludeThirdPartyPhaseout"|"ExcludePortMismatch"|"ExcludeSchemeMismatch"; export type CookieWarningReason = "WarnSameSiteUnspecifiedCrossSiteContext"|"WarnSameSiteNoneInsecure"|"WarnSameSiteUnspecifiedLaxAllowUnsafe"|"WarnSameSiteStrictLaxDowngradeStrict"|"WarnSameSiteStrictCrossDowngradeStrict"|"WarnSameSiteStrictCrossDowngradeLax"|"WarnSameSiteLaxCrossDowngradeStrict"|"WarnSameSiteLaxCrossDowngradeLax"|"WarnAttributeValueExceedsMaxSize"|"WarnDomainNonASCII"|"WarnThirdPartyPhaseout"|"WarnCrossSiteRedirectDowngradeChangesInclusion"|"WarnDeprecationTrialMetadata"|"WarnThirdPartyCookieHeuristic"; export type CookieOperation = "SetCookie"|"ReadCookie"; /** @@ -2183,12 +2183,17 @@ The array enumerates @scope at-rules starting with the innermost one, going outw * The array keeps the types of ancestor CSSRules from the innermost going outwards. */ ruleTypes?: CSSRuleType[]; + /** + * @starting-style CSS at-rule array. +The array enumerates @starting-style at-rules starting with the innermost one, going outwards. + */ + startingStyles?: CSSStartingStyle[]; } /** * Enum indicating the type of a CSS rule, used to represent the order of a style rule's ancestors. This list only contains rule types that are collected during the ancestor rule collection. */ - export type CSSRuleType = "MediaRule"|"SupportsRule"|"ContainerRule"|"LayerRule"|"ScopeRule"|"StyleRule"; + export type CSSRuleType = "MediaRule"|"SupportsRule"|"ContainerRule"|"LayerRule"|"ScopeRule"|"StyleRule"|"StartingStyleRule"; /** * CSS coverage information. */ @@ -2424,6 +2429,10 @@ available). * Optional logical axes queried for the container. */ logicalAxes?: DOM.LogicalAxes; + /** + * true if the query contains scroll-state() queries. + */ + queriesScrollState?: boolean; } /** * CSS Supports at-rule descriptor. @@ -2475,6 +2484,20 @@ available). text: string; /** * The associated rule header range in the enclosing stylesheet (if +available). + */ + range?: SourceRange; + /** + * Identifier of the stylesheet containing this object (if exists). + */ + styleSheetId?: StyleSheetId; + } + /** + * CSS Starting Style at-rule descriptor. + */ + export interface CSSStartingStyle { + /** + * The associated rule header range in the enclosing stylesheet (if available). */ range?: SourceRange; @@ -2779,6 +2802,12 @@ resized.) The current implementation considers only viewport-dependent media fea */ styleSheetId: StyleSheetId; } + export type computedStyleUpdatedPayload = { + /** + * The node id that has updated computed styles. + */ + nodeId: DOM.NodeId; + } /** * Inserts a new rule with the given `ruleText` in a stylesheet with given `styleSheetId`, at the @@ -3039,6 +3068,19 @@ returns an array of locations of the CSS selector in the style sheet. export type getLocationForSelectorReturnValue = { ranges: SourceRange[]; } + /** + * Starts tracking the given node for the computed style updates +and whenever the computed style is updated for node, it queues +a `computedStyleUpdated` event with throttling. +There can only be 1 node tracked for computed style updates +so passing a new node id removes tracking from the previous node. +Pass `undefined` to disable tracking. + */ + export type trackComputedStyleUpdatesForNodeParameters = { + nodeId?: DOM.NodeId; + } + export type trackComputedStyleUpdatesForNodeReturnValue = { + } /** * Starts tracking the given computed styles for updates. The specified array of properties replaces the one previously specified. Pass empty array to disable tracking. @@ -3561,7 +3603,7 @@ front-end. /** * Pseudo element type. */ - export type PseudoType = "first-line"|"first-letter"|"before"|"after"|"marker"|"backdrop"|"column"|"selection"|"search-text"|"target-text"|"spelling-error"|"grammar-error"|"highlight"|"first-line-inherited"|"scroll-marker"|"scroll-marker-group"|"scroll-next-button"|"scroll-prev-button"|"scrollbar"|"scrollbar-thumb"|"scrollbar-button"|"scrollbar-track"|"scrollbar-track-piece"|"scrollbar-corner"|"resizer"|"input-list-button"|"view-transition"|"view-transition-group"|"view-transition-image-pair"|"view-transition-old"|"view-transition-new"|"placeholder"|"file-selector-button"|"details-content"|"select-fallback-button"|"select-fallback-button-text"|"picker"; + export type PseudoType = "first-line"|"first-letter"|"check"|"before"|"after"|"select-arrow"|"marker"|"backdrop"|"column"|"selection"|"search-text"|"target-text"|"spelling-error"|"grammar-error"|"highlight"|"first-line-inherited"|"scroll-marker"|"scroll-marker-group"|"scroll-next-button"|"scroll-prev-button"|"scrollbar"|"scrollbar-thumb"|"scrollbar-button"|"scrollbar-track"|"scrollbar-track-piece"|"scrollbar-corner"|"resizer"|"input-list-button"|"view-transition"|"view-transition-group"|"view-transition-image-pair"|"view-transition-old"|"view-transition-new"|"placeholder"|"file-selector-button"|"details-content"|"picker"; /** * Shadow root type. */ @@ -4876,15 +4918,17 @@ $x functions). } /** * Returns the query container of the given node based on container query -conditions: containerName, physical, and logical axes. If no axes are -provided, the style container is returned, which is the direct parent or the -closest element with a matching container-name. +conditions: containerName, physical and logical axes, and whether it queries +scroll-state. If no axes are provided and queriesScrollState is false, the +style container is returned, which is the direct parent or the closest +element with a matching container-name. */ export type getContainerForNodeParameters = { nodeId: NodeId; containerName?: string; physicalAxes?: PhysicalAxes; logicalAxes?: LogicalAxes; + queriesScrollState?: boolean; } export type getContainerForNodeReturnValue = { /** @@ -8255,7 +8299,9 @@ file, data and other requests and responses, their headers, bodies, timing, etc. */ export type LoaderId = string; /** - * Unique request identifier. + * Unique network request identifier. +Note that this does not identify individual HTTP requests that are part of +a network request. */ export type RequestId = string; /** @@ -8830,6 +8876,7 @@ If the opcode isn't 1, then payloadData is a base64 encoded string representing type: "parser"|"script"|"preload"|"SignedExchange"|"preflight"|"other"; /** * Initiator JavaScript stack trace, set for Script only. +Requires the Debugger domain to be enabled. */ stack?: Runtime.StackTrace; /** @@ -8944,7 +8991,7 @@ This is a temporary ability and it will be removed in the future. /** * Types of reasons why a cookie may not be sent with a request. */ - export type CookieBlockedReason = "SecureOnly"|"NotOnPath"|"DomainMismatch"|"SameSiteStrict"|"SameSiteLax"|"SameSiteUnspecifiedTreatedAsLax"|"SameSiteNoneInsecure"|"UserPreferences"|"ThirdPartyPhaseout"|"ThirdPartyBlockedInFirstPartySet"|"UnknownError"|"SchemefulSameSiteStrict"|"SchemefulSameSiteLax"|"SchemefulSameSiteUnspecifiedTreatedAsLax"|"SamePartyFromCrossPartyContext"|"NameValuePairExceedsMaxSize"; + export type CookieBlockedReason = "SecureOnly"|"NotOnPath"|"DomainMismatch"|"SameSiteStrict"|"SameSiteLax"|"SameSiteUnspecifiedTreatedAsLax"|"SameSiteNoneInsecure"|"UserPreferences"|"ThirdPartyPhaseout"|"ThirdPartyBlockedInFirstPartySet"|"UnknownError"|"SchemefulSameSiteStrict"|"SchemefulSameSiteLax"|"SchemefulSameSiteUnspecifiedTreatedAsLax"|"SamePartyFromCrossPartyContext"|"NameValuePairExceedsMaxSize"|"PortMismatch"|"SchemeMismatch"; /** * Types of reasons why a cookie should have been blocked by 3PCD but is exempted for the request. */ @@ -11498,7 +11545,7 @@ as an ad. * All Permissions Policy features. This enum should match the one defined in third_party/blink/renderer/core/permissions_policy/permissions_policy_features.json5. */ - export type PermissionsPolicyFeature = "accelerometer"|"all-screens-capture"|"ambient-light-sensor"|"attribution-reporting"|"autoplay"|"bluetooth"|"browsing-topics"|"camera"|"captured-surface-control"|"ch-dpr"|"ch-device-memory"|"ch-downlink"|"ch-ect"|"ch-prefers-color-scheme"|"ch-prefers-reduced-motion"|"ch-prefers-reduced-transparency"|"ch-rtt"|"ch-save-data"|"ch-ua"|"ch-ua-arch"|"ch-ua-bitness"|"ch-ua-platform"|"ch-ua-model"|"ch-ua-mobile"|"ch-ua-form-factors"|"ch-ua-full-version"|"ch-ua-full-version-list"|"ch-ua-platform-version"|"ch-ua-wow64"|"ch-viewport-height"|"ch-viewport-width"|"ch-width"|"clipboard-read"|"clipboard-write"|"compute-pressure"|"controlled-frame"|"cross-origin-isolated"|"deferred-fetch"|"digital-credentials-get"|"direct-sockets"|"direct-sockets-private"|"display-capture"|"document-domain"|"encrypted-media"|"execution-while-out-of-viewport"|"execution-while-not-rendered"|"focus-without-user-activation"|"fullscreen"|"frobulate"|"gamepad"|"geolocation"|"gyroscope"|"hid"|"identity-credentials-get"|"idle-detection"|"interest-cohort"|"join-ad-interest-group"|"keyboard-map"|"local-fonts"|"magnetometer"|"media-playback-while-not-visible"|"microphone"|"midi"|"otp-credentials"|"payment"|"picture-in-picture"|"popins"|"private-aggregation"|"private-state-token-issuance"|"private-state-token-redemption"|"publickey-credentials-create"|"publickey-credentials-get"|"run-ad-auction"|"screen-wake-lock"|"serial"|"shared-autofill"|"shared-storage"|"shared-storage-select-url"|"smart-card"|"speaker-selection"|"storage-access"|"sub-apps"|"sync-xhr"|"unload"|"usb"|"usb-unrestricted"|"vertical-scroll"|"web-app-installation"|"web-printing"|"web-share"|"window-management"|"xr-spatial-tracking"; + export type PermissionsPolicyFeature = "accelerometer"|"all-screens-capture"|"ambient-light-sensor"|"attribution-reporting"|"autoplay"|"bluetooth"|"browsing-topics"|"camera"|"captured-surface-control"|"ch-dpr"|"ch-device-memory"|"ch-downlink"|"ch-ect"|"ch-prefers-color-scheme"|"ch-prefers-reduced-motion"|"ch-prefers-reduced-transparency"|"ch-rtt"|"ch-save-data"|"ch-ua"|"ch-ua-arch"|"ch-ua-bitness"|"ch-ua-platform"|"ch-ua-model"|"ch-ua-mobile"|"ch-ua-form-factors"|"ch-ua-full-version"|"ch-ua-full-version-list"|"ch-ua-platform-version"|"ch-ua-wow64"|"ch-viewport-height"|"ch-viewport-width"|"ch-width"|"clipboard-read"|"clipboard-write"|"compute-pressure"|"controlled-frame"|"cross-origin-isolated"|"deferred-fetch"|"digital-credentials-get"|"direct-sockets"|"direct-sockets-private"|"display-capture"|"document-domain"|"encrypted-media"|"execution-while-out-of-viewport"|"execution-while-not-rendered"|"fenced-unpartitioned-storage-read"|"focus-without-user-activation"|"fullscreen"|"frobulate"|"gamepad"|"geolocation"|"gyroscope"|"hid"|"identity-credentials-get"|"idle-detection"|"interest-cohort"|"join-ad-interest-group"|"keyboard-map"|"local-fonts"|"magnetometer"|"media-playback-while-not-visible"|"microphone"|"midi"|"otp-credentials"|"payment"|"picture-in-picture"|"popins"|"private-aggregation"|"private-state-token-issuance"|"private-state-token-redemption"|"publickey-credentials-create"|"publickey-credentials-get"|"run-ad-auction"|"screen-wake-lock"|"serial"|"shared-autofill"|"shared-storage"|"shared-storage-select-url"|"smart-card"|"speaker-selection"|"storage-access"|"sub-apps"|"sync-xhr"|"unload"|"usb"|"usb-unrestricted"|"vertical-scroll"|"web-app-installation"|"web-printing"|"web-share"|"window-management"|"xr-spatial-tracking"; /** * Reason for a permissions policy feature to be disabled. */ @@ -12384,7 +12431,8 @@ the page execution. Execution can be resumed via calling Page.handleJavaScriptDi defaultPrompt?: string; } /** - * Fired for top level page lifecycle events such as navigation, load, paint, etc. + * Fired for lifecycle events (navigation, load, paint, etc) in the current +target (including local frames). */ export type lifecycleEventPayload = { /** @@ -14339,6 +14387,7 @@ int destinationLimitPriority: SignedInt64AsBase10; aggregatableDebugReportingConfig: AttributionReportingAggregatableDebugReportingConfig; scopesData?: AttributionScopesData; + maxEventLevelReports: number; } export type AttributionReportingSourceRegistrationResult = "success"|"internalError"|"insufficientSourceCapacity"|"insufficientUniqueDestinationCapacity"|"excessiveReportingOrigins"|"prohibitedByBrowserPolicy"|"successNoised"|"destinationReportingLimitReached"|"destinationGlobalLimitReached"|"destinationBothLimitsReached"|"reportingOriginsPerSiteLimitReached"|"exceedsMaxChannelCapacity"|"exceedsMaxScopesChannelCapacity"|"exceedsMaxTriggerStateCardinality"|"exceedsMaxEventStatesLimit"|"destinationPerDayReportingLimitReached"; export type AttributionReportingSourceRegistrationTimeConfig = "include"|"exclude"; @@ -14386,7 +14435,7 @@ int scopes: string[]; } export type AttributionReportingEventLevelResult = "success"|"successDroppedLowerPriority"|"internalError"|"noCapacityForAttributionDestination"|"noMatchingSources"|"deduplicated"|"excessiveAttributions"|"priorityTooLow"|"neverAttributedSource"|"excessiveReportingOrigins"|"noMatchingSourceFilterData"|"prohibitedByBrowserPolicy"|"noMatchingConfigurations"|"excessiveReports"|"falselyAttributedSource"|"reportWindowPassed"|"notRegistered"|"reportWindowNotStarted"|"noMatchingTriggerData"; - export type AttributionReportingAggregatableResult = "success"|"internalError"|"noCapacityForAttributionDestination"|"noMatchingSources"|"excessiveAttributions"|"excessiveReportingOrigins"|"noHistograms"|"insufficientBudget"|"noMatchingSourceFilterData"|"notRegistered"|"prohibitedByBrowserPolicy"|"deduplicated"|"reportWindowPassed"|"excessiveReports"; + export type AttributionReportingAggregatableResult = "success"|"internalError"|"noCapacityForAttributionDestination"|"noMatchingSources"|"excessiveAttributions"|"excessiveReportingOrigins"|"noHistograms"|"insufficientBudget"|"insufficientNamedBudget"|"noMatchingSourceFilterData"|"notRegistered"|"prohibitedByBrowserPolicy"|"deduplicated"|"reportWindowPassed"|"excessiveReports"; /** * A single Related Website Set object. */ @@ -15920,6 +15969,8 @@ are ignored. export module Fetch { /** * Unique request identifier. +Note that this does not identify individual HTTP requests that are part of +a network request. */ export type RequestId = string; /** @@ -16302,7 +16353,7 @@ https://webaudio.github.io/web-audio-api/ /** * Enum of AudioContextState from the spec */ - export type ContextState = "suspended"|"running"|"closed"; + export type ContextState = "suspended"|"running"|"closed"|"interrupted"; /** * Enum of AudioNode types */ @@ -20213,6 +20264,7 @@ Error was thrown. "CSS.styleSheetAdded": CSS.styleSheetAddedPayload; "CSS.styleSheetChanged": CSS.styleSheetChangedPayload; "CSS.styleSheetRemoved": CSS.styleSheetRemovedPayload; + "CSS.computedStyleUpdated": CSS.computedStyleUpdatedPayload; "Cast.sinksUpdated": Cast.sinksUpdatedPayload; "Cast.issueUpdated": Cast.issueUpdatedPayload; "DOM.attributeModified": DOM.attributeModifiedPayload; @@ -20464,6 +20516,7 @@ Error was thrown. "CSS.getStyleSheetText": CSS.getStyleSheetTextParameters; "CSS.getLayersForNode": CSS.getLayersForNodeParameters; "CSS.getLocationForSelector": CSS.getLocationForSelectorParameters; + "CSS.trackComputedStyleUpdatesForNode": CSS.trackComputedStyleUpdatesForNodeParameters; "CSS.trackComputedStyleUpdates": CSS.trackComputedStyleUpdatesParameters; "CSS.takeComputedStyleUpdates": CSS.takeComputedStyleUpdatesParameters; "CSS.setEffectivePropertyValueForNode": CSS.setEffectivePropertyValueForNodeParameters; @@ -21075,6 +21128,7 @@ Error was thrown. "CSS.getStyleSheetText": CSS.getStyleSheetTextReturnValue; "CSS.getLayersForNode": CSS.getLayersForNodeReturnValue; "CSS.getLocationForSelector": CSS.getLocationForSelectorReturnValue; + "CSS.trackComputedStyleUpdatesForNode": CSS.trackComputedStyleUpdatesForNodeReturnValue; "CSS.trackComputedStyleUpdates": CSS.trackComputedStyleUpdatesReturnValue; "CSS.takeComputedStyleUpdates": CSS.takeComputedStyleUpdatesReturnValue; "CSS.setEffectivePropertyValueForNode": CSS.setEffectivePropertyValueForNodeReturnValue; diff --git a/packages/playwright-core/src/server/codegen/csharp.ts b/packages/playwright-core/src/server/codegen/csharp.ts index 2e4526d0a2..f9166c2a91 100644 --- a/packages/playwright-core/src/server/codegen/csharp.ts +++ b/packages/playwright-core/src/server/codegen/csharp.ts @@ -171,6 +171,8 @@ export class CSharpLanguageGenerator implements LanguageGenerator { using var playwright = await Playwright.CreateAsync(); await using var browser = await playwright.${toPascal(options.browserName)}.LaunchAsync(${formatObject(options.launchOptions, ' ', 'BrowserTypeLaunchOptions')}); var context = await browser.NewContextAsync(${formatContextOptions(options.contextOptions, options.deviceName)});`); + if (options.contextOptions.recordHar) + formatter.add(` await context.RouteFromHARAsync(${quote(options.contextOptions.recordHar.path)});`); formatter.newLine(); return formatter.format(); } @@ -196,6 +198,8 @@ export class CSharpLanguageGenerator implements LanguageGenerator { formatter.add(` [${this._mode === 'nunit' ? 'Test' : 'TestMethod'}] public async Task MyTest() {`); + if (options.contextOptions.recordHar) + formatter.add(` await context.RouteFromHARAsync(${quote(options.contextOptions.recordHar.path)});`); return formatter.format(); } @@ -261,32 +265,22 @@ function toPascal(value: string): string { return value[0].toUpperCase() + value.slice(1); } -function convertContextOptions(options: BrowserContextOptions): any { - const result: any = { ...options }; - if (options.recordHar) { - result['recordHarPath'] = options.recordHar.path; - result['recordHarContent'] = options.recordHar.content; - result['recordHarMode'] = options.recordHar.mode; - result['recordHarOmitContent'] = options.recordHar.omitContent; - result['recordHarUrlFilter'] = options.recordHar.urlFilter; - delete result.recordHar; - } - return result; -} - -function formatContextOptions(options: BrowserContextOptions, deviceName: string | undefined): string { +function formatContextOptions(contextOptions: BrowserContextOptions, deviceName: string | undefined): string { + let options = { ...contextOptions }; + // recordHAR is replaced with routeFromHAR in the generated code. + delete options.recordHar; const device = deviceName && deviceDescriptors[deviceName]; if (!device) { if (!Object.entries(options).length) return ''; - return formatObject(convertContextOptions(options), ' ', 'BrowserNewContextOptions'); + return formatObject(options, ' ', 'BrowserNewContextOptions'); } options = sanitizeDeviceOptions(device, options); if (!Object.entries(options).length) return `playwright.Devices[${quote(deviceName!)}]`; - return formatObject(convertContextOptions(options), ' ', `BrowserNewContextOptions(playwright.Devices[${quote(deviceName!)}])`); + return formatObject(options, ' ', `BrowserNewContextOptions(playwright.Devices[${quote(deviceName!)}])`); } class CSharpFormatter { diff --git a/packages/playwright-core/src/server/codegen/java.ts b/packages/playwright-core/src/server/codegen/java.ts index c6d41e607b..1fafa0642c 100644 --- a/packages/playwright-core/src/server/codegen/java.ts +++ b/packages/playwright-core/src/server/codegen/java.ts @@ -170,6 +170,8 @@ export class JavaLanguageGenerator implements LanguageGenerator { try (Playwright playwright = Playwright.create()) { Browser browser = playwright.${options.browserName}().launch(${formatLaunchOptions(options.launchOptions)}); BrowserContext context = browser.newContext(${formatContextOptions(options.contextOptions, options.deviceName)});`); + if (options.contextOptions.recordHar) + formatter.add(` context.routeFromHAR(${quote(options.contextOptions.recordHar.path)});`); return formatter.format(); } @@ -240,16 +242,6 @@ function formatContextOptions(contextOptions: BrowserContextOptions, deviceName: lines.push(` .setLocale(${quote(options.locale)})`); if (options.proxy) lines.push(` .setProxy(new Proxy(${quote(options.proxy.server)}))`); - if (options.recordHar?.content) - lines.push(` .setRecordHarContent(HarContentPolicy.${options.recordHar?.content.toUpperCase()})`); - if (options.recordHar?.mode) - lines.push(` .setRecordHarMode(HarMode.${options.recordHar?.mode.toUpperCase()})`); - if (options.recordHar?.omitContent) - lines.push(` .setRecordHarOmitContent(true)`); - if (options.recordHar?.path) - lines.push(` .setRecordHarPath(Paths.get(${quote(options.recordHar.path)}))`); - if (options.recordHar?.urlFilter) - lines.push(` .setRecordHarUrlFilter(${quote(options.recordHar.urlFilter as string)})`); if (options.serviceWorkers) lines.push(` .setServiceWorkers(ServiceWorkerPolicy.${options.serviceWorkers.toUpperCase()})`); if (options.storageState) diff --git a/packages/playwright-core/src/server/codegen/javascript.ts b/packages/playwright-core/src/server/codegen/javascript.ts index 7a4b637a06..e5f72ce122 100644 --- a/packages/playwright-core/src/server/codegen/javascript.ts +++ b/packages/playwright-core/src/server/codegen/javascript.ts @@ -117,8 +117,10 @@ export class JavaScriptLanguageGenerator implements LanguageGenerator { const assertion = action.value ? `toHaveValue(${quote(action.value)})` : `toBeEmpty()`; return `${this._isTest ? '' : '// '}await expect(${subject}.${this._asLocator(action.selector)}).${assertion};`; } - case 'assertSnapshot': - return `${this._isTest ? '' : '// '}await expect(${subject}.${this._asLocator(action.selector)}).toMatchAriaSnapshot(${quoteMultiline(action.snapshot)});`; + case 'assertSnapshot': { + const commentIfNeeded = this._isTest ? '' : '// '; + return `${commentIfNeeded}await expect(${subject}.${this._asLocator(action.selector)}).toMatchAriaSnapshot(${quoteMultiline(action.snapshot, `${commentIfNeeded} `)});`; + } } } @@ -145,6 +147,8 @@ export class JavaScriptLanguageGenerator implements LanguageGenerator { import { test, expect${options.deviceName ? ', devices' : ''} } from '@playwright/test'; ${useText ? '\ntest.use(' + useText + ');\n' : ''} test('test', async ({ page }) => {`); + if (options.contextOptions.recordHar) + formatter.add(` await page.routeFromHAR(${quote(options.contextOptions.recordHar.path)});`); return formatter.format(); } @@ -160,6 +164,8 @@ ${useText ? '\ntest.use(' + useText + ');\n' : ''} (async () => { const browser = await ${options.browserName}.launch(${formatObjectOrVoid(options.launchOptions)}); const context = await browser.newContext(${formatContextOptions(options.contextOptions, options.deviceName, false)});`); + if (options.contextOptions.recordHar) + formatter.add(` await context.routeFromHAR(${quote(options.contextOptions.recordHar.path)});`); return formatter.format(); } @@ -203,10 +209,8 @@ function formatObjectOrVoid(value: any, indent = ' '): string { function formatContextOptions(options: BrowserContextOptions, deviceName: string | undefined, isTest: boolean): string { const device = deviceName && deviceDescriptors[deviceName]; - if (isTest) { - // No recordHAR fixture in test. - options = { ...options, recordHar: undefined }; - } + // recordHAR is replaced with routeFromHAR in the generated code. + options = { ...options, recordHar: undefined }; if (!device) return formatObjectOrVoid(options); // Filter out all the properties from the device descriptor. diff --git a/packages/playwright-core/src/server/codegen/python.ts b/packages/playwright-core/src/server/codegen/python.ts index 50afe1b1a5..8d4ea7659d 100644 --- a/packages/playwright-core/src/server/codegen/python.ts +++ b/packages/playwright-core/src/server/codegen/python.ts @@ -151,6 +151,8 @@ from playwright.sync_api import Page, expect ${fixture} def test_example(page: Page) -> None {`); + if (options.contextOptions.recordHar) + formatter.add(` page.route_from_har(${quote(options.contextOptions.recordHar.path)})`); } else if (this._isAsync) { formatter.add(` import asyncio @@ -161,6 +163,8 @@ from playwright.async_api import Playwright, async_playwright, expect async def run(playwright: Playwright) -> None { browser = await playwright.${options.browserName}.launch(${formatOptions(options.launchOptions, false)}) context = await browser.new_context(${formatContextOptions(options.contextOptions, options.deviceName)})`); + if (options.contextOptions.recordHar) + formatter.add(` await page.route_from_har(${quote(options.contextOptions.recordHar.path)})`); } else { formatter.add(` import re @@ -170,6 +174,8 @@ from playwright.sync_api import Playwright, sync_playwright, expect def run(playwright: Playwright) -> None { browser = playwright.${options.browserName}.launch(${formatOptions(options.launchOptions, false)}) context = browser.new_context(${formatContextOptions(options.contextOptions, options.deviceName)})`); + if (options.contextOptions.recordHar) + formatter.add(` context.route_from_har(${quote(options.contextOptions.recordHar.path)})`); } return formatter.format(); } @@ -232,24 +238,13 @@ function formatOptions(value: any, hasArguments: boolean, asDict?: boolean): str }).join(', '); } -function convertContextOptions(options: BrowserContextOptions): any { - const result: any = { ...options }; - if (options.recordHar) { - result['record_har_path'] = options.recordHar.path; - result['record_har_content'] = options.recordHar.content; - result['record_har_mode'] = options.recordHar.mode; - result['record_har_omit_content'] = options.recordHar.omitContent; - result['record_har_url_filter'] = options.recordHar.urlFilter; - delete result.recordHar; - } - return result; -} - function formatContextOptions(options: BrowserContextOptions, deviceName: string | undefined, asDict?: boolean): string { + // recordHAR is replaced with routeFromHAR in the generated code. + options = { ...options, recordHar: undefined }; const device = deviceName && deviceDescriptors[deviceName]; if (!device) - return formatOptions(convertContextOptions(options), false, asDict); - return `**playwright.devices[${quote(deviceName!)}]` + formatOptions(convertContextOptions(sanitizeDeviceOptions(device, options)), true, asDict); + return formatOptions(options, false, asDict); + return `**playwright.devices[${quote(deviceName!)}]` + formatOptions(sanitizeDeviceOptions(device, options), true, asDict); } class PythonFormatter { diff --git a/packages/playwright-core/src/server/debugController.ts b/packages/playwright-core/src/server/debugController.ts index a9a79a49e2..251dce7e03 100644 --- a/packages/playwright-core/src/server/debugController.ts +++ b/packages/playwright-core/src/server/debugController.ts @@ -24,6 +24,7 @@ import type { Playwright } from './playwright'; import { Recorder } from './recorder'; import { EmptyRecorderApp } from './recorder/recorderApp'; import { asLocator, type Language } from '../utils'; +import { parseYamlForAriaSnapshot } from './ariaSnapshot'; const internalMetadata = serverSideCallMetadata(); @@ -142,9 +143,13 @@ export class DebugController extends SdkObject { this._autoCloseTimer = setTimeout(heartBeat, 30000); } - async highlight(selector: string) { - for (const recorder of await this._allRecorders()) - recorder.setHighlightedSelector(this._sdkLanguage, selector); + async highlight(params: { selector?: string, ariaTemplate?: string }) { + for (const recorder of await this._allRecorders()) { + if (params.ariaTemplate) + recorder.setHighlightedAriaTemplate(parseYamlForAriaSnapshot(params.ariaTemplate)); + else if (params.selector) + recorder.setHighlightedSelector(this._sdkLanguage, params.selector); + } } async hideHighlight() { diff --git a/packages/playwright-core/src/server/deviceDescriptorsSource.json b/packages/playwright-core/src/server/deviceDescriptorsSource.json index 47544dc1fe..e82744b73c 100644 --- a/packages/playwright-core/src/server/deviceDescriptorsSource.json +++ b/packages/playwright-core/src/server/deviceDescriptorsSource.json @@ -1,6 +1,6 @@ { "Blackberry PlayBook": { - "userAgent": "Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML like Gecko) Version/18.0 Safari/536.2+", + "userAgent": "Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML like Gecko) Version/18.2 Safari/536.2+", "viewport": { "width": 600, "height": 1024 @@ -11,7 +11,7 @@ "defaultBrowserType": "webkit" }, "Blackberry PlayBook landscape": { - "userAgent": "Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML like Gecko) Version/18.0 Safari/536.2+", + "userAgent": "Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML like Gecko) Version/18.2 Safari/536.2+", "viewport": { "width": 1024, "height": 600 @@ -22,7 +22,7 @@ "defaultBrowserType": "webkit" }, "BlackBerry Z30": { - "userAgent": "Mozilla/5.0 (BB10; Touch) AppleWebKit/537.10+ (KHTML, like Gecko) Version/18.0 Mobile Safari/537.10+", + "userAgent": "Mozilla/5.0 (BB10; Touch) AppleWebKit/537.10+ (KHTML, like Gecko) Version/18.2 Mobile Safari/537.10+", "viewport": { "width": 360, "height": 640 @@ -33,7 +33,7 @@ "defaultBrowserType": "webkit" }, "BlackBerry Z30 landscape": { - "userAgent": "Mozilla/5.0 (BB10; Touch) AppleWebKit/537.10+ (KHTML, like Gecko) Version/18.0 Mobile Safari/537.10+", + "userAgent": "Mozilla/5.0 (BB10; Touch) AppleWebKit/537.10+ (KHTML, like Gecko) Version/18.2 Mobile Safari/537.10+", "viewport": { "width": 640, "height": 360 @@ -44,7 +44,7 @@ "defaultBrowserType": "webkit" }, "Galaxy Note 3": { - "userAgent": "Mozilla/5.0 (Linux; U; Android 4.3; en-us; SM-N900T Build/JSS15J) AppleWebKit/534.30 (KHTML, like Gecko) Version/18.0 Mobile Safari/534.30", + "userAgent": "Mozilla/5.0 (Linux; U; Android 4.3; en-us; SM-N900T Build/JSS15J) AppleWebKit/534.30 (KHTML, like Gecko) Version/18.2 Mobile Safari/534.30", "viewport": { "width": 360, "height": 640 @@ -55,7 +55,7 @@ "defaultBrowserType": "webkit" }, "Galaxy Note 3 landscape": { - "userAgent": "Mozilla/5.0 (Linux; U; Android 4.3; en-us; SM-N900T Build/JSS15J) AppleWebKit/534.30 (KHTML, like Gecko) Version/18.0 Mobile Safari/534.30", + "userAgent": "Mozilla/5.0 (Linux; U; Android 4.3; en-us; SM-N900T Build/JSS15J) AppleWebKit/534.30 (KHTML, like Gecko) Version/18.2 Mobile Safari/534.30", "viewport": { "width": 640, "height": 360 @@ -66,7 +66,7 @@ "defaultBrowserType": "webkit" }, "Galaxy Note II": { - "userAgent": "Mozilla/5.0 (Linux; U; Android 4.1; en-us; GT-N7100 Build/JRO03C) AppleWebKit/534.30 (KHTML, like Gecko) Version/18.0 Mobile Safari/534.30", + "userAgent": "Mozilla/5.0 (Linux; U; Android 4.1; en-us; GT-N7100 Build/JRO03C) AppleWebKit/534.30 (KHTML, like Gecko) Version/18.2 Mobile Safari/534.30", "viewport": { "width": 360, "height": 640 @@ -77,7 +77,7 @@ "defaultBrowserType": "webkit" }, "Galaxy Note II landscape": { - "userAgent": "Mozilla/5.0 (Linux; U; Android 4.1; en-us; GT-N7100 Build/JRO03C) AppleWebKit/534.30 (KHTML, like Gecko) Version/18.0 Mobile Safari/534.30", + "userAgent": "Mozilla/5.0 (Linux; U; Android 4.1; en-us; GT-N7100 Build/JRO03C) AppleWebKit/534.30 (KHTML, like Gecko) Version/18.2 Mobile Safari/534.30", "viewport": { "width": 640, "height": 360 @@ -88,7 +88,7 @@ "defaultBrowserType": "webkit" }, "Galaxy S III": { - "userAgent": "Mozilla/5.0 (Linux; U; Android 4.0; en-us; GT-I9300 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/18.0 Mobile Safari/534.30", + "userAgent": "Mozilla/5.0 (Linux; U; Android 4.0; en-us; GT-I9300 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/18.2 Mobile Safari/534.30", "viewport": { "width": 360, "height": 640 @@ -99,7 +99,7 @@ "defaultBrowserType": "webkit" }, "Galaxy S III landscape": { - "userAgent": "Mozilla/5.0 (Linux; U; Android 4.0; en-us; GT-I9300 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/18.0 Mobile Safari/534.30", + "userAgent": "Mozilla/5.0 (Linux; U; Android 4.0; en-us; GT-I9300 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/18.2 Mobile Safari/534.30", "viewport": { "width": 640, "height": 360 @@ -110,7 +110,7 @@ "defaultBrowserType": "webkit" }, "Galaxy S5": { - "userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Mobile Safari/537.36", "viewport": { "width": 360, "height": 640 @@ -121,7 +121,7 @@ "defaultBrowserType": "chromium" }, "Galaxy S5 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Mobile Safari/537.36", "viewport": { "width": 640, "height": 360 @@ -132,7 +132,7 @@ "defaultBrowserType": "chromium" }, "Galaxy S8": { - "userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Mobile Safari/537.36", "viewport": { "width": 360, "height": 740 @@ -143,7 +143,7 @@ "defaultBrowserType": "chromium" }, "Galaxy S8 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Mobile Safari/537.36", "viewport": { "width": 740, "height": 360 @@ -154,7 +154,7 @@ "defaultBrowserType": "chromium" }, "Galaxy S9+": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Mobile Safari/537.36", "viewport": { "width": 320, "height": 658 @@ -165,7 +165,7 @@ "defaultBrowserType": "chromium" }, "Galaxy S9+ landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Mobile Safari/537.36", "viewport": { "width": 658, "height": 320 @@ -176,7 +176,7 @@ "defaultBrowserType": "chromium" }, "Galaxy Tab S4": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Safari/537.36", "viewport": { "width": 712, "height": 1138 @@ -187,7 +187,7 @@ "defaultBrowserType": "chromium" }, "Galaxy Tab S4 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Safari/537.36", "viewport": { "width": 1138, "height": 712 @@ -198,7 +198,7 @@ "defaultBrowserType": "chromium" }, "iPad (gen 5)": { - "userAgent": "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "viewport": { "width": 768, "height": 1024 @@ -209,7 +209,7 @@ "defaultBrowserType": "webkit" }, "iPad (gen 5) landscape": { - "userAgent": "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "viewport": { "width": 1024, "height": 768 @@ -220,7 +220,7 @@ "defaultBrowserType": "webkit" }, "iPad (gen 6)": { - "userAgent": "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "viewport": { "width": 768, "height": 1024 @@ -231,7 +231,7 @@ "defaultBrowserType": "webkit" }, "iPad (gen 6) landscape": { - "userAgent": "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "viewport": { "width": 1024, "height": 768 @@ -242,7 +242,7 @@ "defaultBrowserType": "webkit" }, "iPad (gen 7)": { - "userAgent": "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "viewport": { "width": 810, "height": 1080 @@ -253,7 +253,7 @@ "defaultBrowserType": "webkit" }, "iPad (gen 7) landscape": { - "userAgent": "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "viewport": { "width": 1080, "height": 810 @@ -264,7 +264,7 @@ "defaultBrowserType": "webkit" }, "iPad Mini": { - "userAgent": "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "viewport": { "width": 768, "height": 1024 @@ -275,7 +275,7 @@ "defaultBrowserType": "webkit" }, "iPad Mini landscape": { - "userAgent": "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "viewport": { "width": 1024, "height": 768 @@ -286,7 +286,7 @@ "defaultBrowserType": "webkit" }, "iPad Pro 11": { - "userAgent": "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "viewport": { "width": 834, "height": 1194 @@ -297,7 +297,7 @@ "defaultBrowserType": "webkit" }, "iPad Pro 11 landscape": { - "userAgent": "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "viewport": { "width": 1194, "height": 834 @@ -308,7 +308,7 @@ "defaultBrowserType": "webkit" }, "iPhone 6": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/18.0 Mobile/15A372 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/18.2 Mobile/15A372 Safari/604.1", "viewport": { "width": 375, "height": 667 @@ -319,7 +319,7 @@ "defaultBrowserType": "webkit" }, "iPhone 6 landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/18.0 Mobile/15A372 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/18.2 Mobile/15A372 Safari/604.1", "viewport": { "width": 667, "height": 375 @@ -330,7 +330,7 @@ "defaultBrowserType": "webkit" }, "iPhone 6 Plus": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/18.0 Mobile/15A372 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/18.2 Mobile/15A372 Safari/604.1", "viewport": { "width": 414, "height": 736 @@ -341,7 +341,7 @@ "defaultBrowserType": "webkit" }, "iPhone 6 Plus landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/18.0 Mobile/15A372 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/18.2 Mobile/15A372 Safari/604.1", "viewport": { "width": 736, "height": 414 @@ -352,7 +352,7 @@ "defaultBrowserType": "webkit" }, "iPhone 7": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/18.0 Mobile/15A372 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/18.2 Mobile/15A372 Safari/604.1", "viewport": { "width": 375, "height": 667 @@ -363,7 +363,7 @@ "defaultBrowserType": "webkit" }, "iPhone 7 landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/18.0 Mobile/15A372 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/18.2 Mobile/15A372 Safari/604.1", "viewport": { "width": 667, "height": 375 @@ -374,7 +374,7 @@ "defaultBrowserType": "webkit" }, "iPhone 7 Plus": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/18.0 Mobile/15A372 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/18.2 Mobile/15A372 Safari/604.1", "viewport": { "width": 414, "height": 736 @@ -385,7 +385,7 @@ "defaultBrowserType": "webkit" }, "iPhone 7 Plus landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/18.0 Mobile/15A372 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/18.2 Mobile/15A372 Safari/604.1", "viewport": { "width": 736, "height": 414 @@ -396,7 +396,7 @@ "defaultBrowserType": "webkit" }, "iPhone 8": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/18.0 Mobile/15A372 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/18.2 Mobile/15A372 Safari/604.1", "viewport": { "width": 375, "height": 667 @@ -407,7 +407,7 @@ "defaultBrowserType": "webkit" }, "iPhone 8 landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/18.0 Mobile/15A372 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/18.2 Mobile/15A372 Safari/604.1", "viewport": { "width": 667, "height": 375 @@ -418,7 +418,7 @@ "defaultBrowserType": "webkit" }, "iPhone 8 Plus": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/18.0 Mobile/15A372 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/18.2 Mobile/15A372 Safari/604.1", "viewport": { "width": 414, "height": 736 @@ -429,7 +429,7 @@ "defaultBrowserType": "webkit" }, "iPhone 8 Plus landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/18.0 Mobile/15A372 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/18.2 Mobile/15A372 Safari/604.1", "viewport": { "width": 736, "height": 414 @@ -440,7 +440,7 @@ "defaultBrowserType": "webkit" }, "iPhone SE": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/18.0 Mobile/14E304 Safari/602.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/18.2 Mobile/14E304 Safari/602.1", "viewport": { "width": 320, "height": 568 @@ -451,7 +451,7 @@ "defaultBrowserType": "webkit" }, "iPhone SE landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/18.0 Mobile/14E304 Safari/602.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/18.2 Mobile/14E304 Safari/602.1", "viewport": { "width": 568, "height": 320 @@ -462,7 +462,7 @@ "defaultBrowserType": "webkit" }, "iPhone X": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/18.0 Mobile/15A372 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/18.2 Mobile/15A372 Safari/604.1", "viewport": { "width": 375, "height": 812 @@ -473,7 +473,7 @@ "defaultBrowserType": "webkit" }, "iPhone X landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/18.0 Mobile/15A372 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/18.2 Mobile/15A372 Safari/604.1", "viewport": { "width": 812, "height": 375 @@ -484,7 +484,7 @@ "defaultBrowserType": "webkit" }, "iPhone XR": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "viewport": { "width": 414, "height": 896 @@ -495,7 +495,7 @@ "defaultBrowserType": "webkit" }, "iPhone XR landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "viewport": { "width": 896, "height": 414 @@ -506,7 +506,7 @@ "defaultBrowserType": "webkit" }, "iPhone 11": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "screen": { "width": 414, "height": 896 @@ -521,7 +521,7 @@ "defaultBrowserType": "webkit" }, "iPhone 11 landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "screen": { "width": 414, "height": 896 @@ -536,7 +536,7 @@ "defaultBrowserType": "webkit" }, "iPhone 11 Pro": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "screen": { "width": 375, "height": 812 @@ -551,7 +551,7 @@ "defaultBrowserType": "webkit" }, "iPhone 11 Pro landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "screen": { "width": 375, "height": 812 @@ -566,7 +566,7 @@ "defaultBrowserType": "webkit" }, "iPhone 11 Pro Max": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "screen": { "width": 414, "height": 896 @@ -581,7 +581,7 @@ "defaultBrowserType": "webkit" }, "iPhone 11 Pro Max landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "screen": { "width": 414, "height": 896 @@ -596,7 +596,7 @@ "defaultBrowserType": "webkit" }, "iPhone 12": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "screen": { "width": 390, "height": 844 @@ -611,7 +611,7 @@ "defaultBrowserType": "webkit" }, "iPhone 12 landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "screen": { "width": 390, "height": 844 @@ -626,7 +626,7 @@ "defaultBrowserType": "webkit" }, "iPhone 12 Pro": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "screen": { "width": 390, "height": 844 @@ -641,7 +641,7 @@ "defaultBrowserType": "webkit" }, "iPhone 12 Pro landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "screen": { "width": 390, "height": 844 @@ -656,7 +656,7 @@ "defaultBrowserType": "webkit" }, "iPhone 12 Pro Max": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "screen": { "width": 428, "height": 926 @@ -671,7 +671,7 @@ "defaultBrowserType": "webkit" }, "iPhone 12 Pro Max landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "screen": { "width": 428, "height": 926 @@ -686,7 +686,7 @@ "defaultBrowserType": "webkit" }, "iPhone 12 Mini": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "screen": { "width": 375, "height": 812 @@ -701,7 +701,7 @@ "defaultBrowserType": "webkit" }, "iPhone 12 Mini landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "screen": { "width": 375, "height": 812 @@ -716,7 +716,7 @@ "defaultBrowserType": "webkit" }, "iPhone 13": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "screen": { "width": 390, "height": 844 @@ -731,7 +731,7 @@ "defaultBrowserType": "webkit" }, "iPhone 13 landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "screen": { "width": 390, "height": 844 @@ -746,7 +746,7 @@ "defaultBrowserType": "webkit" }, "iPhone 13 Pro": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "screen": { "width": 390, "height": 844 @@ -761,7 +761,7 @@ "defaultBrowserType": "webkit" }, "iPhone 13 Pro landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "screen": { "width": 390, "height": 844 @@ -776,7 +776,7 @@ "defaultBrowserType": "webkit" }, "iPhone 13 Pro Max": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "screen": { "width": 428, "height": 926 @@ -791,7 +791,7 @@ "defaultBrowserType": "webkit" }, "iPhone 13 Pro Max landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "screen": { "width": 428, "height": 926 @@ -806,7 +806,7 @@ "defaultBrowserType": "webkit" }, "iPhone 13 Mini": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "screen": { "width": 375, "height": 812 @@ -821,7 +821,7 @@ "defaultBrowserType": "webkit" }, "iPhone 13 Mini landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "screen": { "width": 375, "height": 812 @@ -836,7 +836,7 @@ "defaultBrowserType": "webkit" }, "iPhone 14": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "screen": { "width": 390, "height": 844 @@ -851,7 +851,7 @@ "defaultBrowserType": "webkit" }, "iPhone 14 landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "screen": { "width": 390, "height": 844 @@ -866,7 +866,7 @@ "defaultBrowserType": "webkit" }, "iPhone 14 Plus": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "screen": { "width": 428, "height": 926 @@ -881,7 +881,7 @@ "defaultBrowserType": "webkit" }, "iPhone 14 Plus landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "screen": { "width": 428, "height": 926 @@ -896,7 +896,7 @@ "defaultBrowserType": "webkit" }, "iPhone 14 Pro": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "screen": { "width": 393, "height": 852 @@ -911,7 +911,7 @@ "defaultBrowserType": "webkit" }, "iPhone 14 Pro landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "screen": { "width": 393, "height": 852 @@ -926,7 +926,7 @@ "defaultBrowserType": "webkit" }, "iPhone 14 Pro Max": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "screen": { "width": 430, "height": 932 @@ -941,7 +941,7 @@ "defaultBrowserType": "webkit" }, "iPhone 14 Pro Max landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "screen": { "width": 430, "height": 932 @@ -956,7 +956,7 @@ "defaultBrowserType": "webkit" }, "iPhone 15": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "screen": { "width": 393, "height": 852 @@ -971,7 +971,7 @@ "defaultBrowserType": "webkit" }, "iPhone 15 landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "screen": { "width": 393, "height": 852 @@ -986,7 +986,7 @@ "defaultBrowserType": "webkit" }, "iPhone 15 Plus": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "screen": { "width": 430, "height": 932 @@ -1001,7 +1001,7 @@ "defaultBrowserType": "webkit" }, "iPhone 15 Plus landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "screen": { "width": 430, "height": 932 @@ -1016,7 +1016,7 @@ "defaultBrowserType": "webkit" }, "iPhone 15 Pro": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "screen": { "width": 393, "height": 852 @@ -1031,7 +1031,7 @@ "defaultBrowserType": "webkit" }, "iPhone 15 Pro landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "screen": { "width": 393, "height": 852 @@ -1046,7 +1046,7 @@ "defaultBrowserType": "webkit" }, "iPhone 15 Pro Max": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "screen": { "width": 430, "height": 932 @@ -1061,7 +1061,7 @@ "defaultBrowserType": "webkit" }, "iPhone 15 Pro Max landscape": { - "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1", "screen": { "width": 430, "height": 932 @@ -1098,7 +1098,7 @@ "defaultBrowserType": "webkit" }, "LG Optimus L70": { - "userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/131.0.6778.24 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/132.0.6834.6 Mobile Safari/537.36", "viewport": { "width": 384, "height": 640 @@ -1109,7 +1109,7 @@ "defaultBrowserType": "chromium" }, "LG Optimus L70 landscape": { - "userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/131.0.6778.24 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/132.0.6834.6 Mobile Safari/537.36", "viewport": { "width": 640, "height": 384 @@ -1120,7 +1120,7 @@ "defaultBrowserType": "chromium" }, "Microsoft Lumia 550": { - "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Mobile Safari/537.36 Edge/14.14263", + "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Mobile Safari/537.36 Edge/14.14263", "viewport": { "width": 640, "height": 360 @@ -1131,7 +1131,7 @@ "defaultBrowserType": "chromium" }, "Microsoft Lumia 550 landscape": { - "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Mobile Safari/537.36 Edge/14.14263", + "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Mobile Safari/537.36 Edge/14.14263", "viewport": { "width": 360, "height": 640 @@ -1142,7 +1142,7 @@ "defaultBrowserType": "chromium" }, "Microsoft Lumia 950": { - "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Mobile Safari/537.36 Edge/14.14263", + "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Mobile Safari/537.36 Edge/14.14263", "viewport": { "width": 360, "height": 640 @@ -1153,7 +1153,7 @@ "defaultBrowserType": "chromium" }, "Microsoft Lumia 950 landscape": { - "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Mobile Safari/537.36 Edge/14.14263", + "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Mobile Safari/537.36 Edge/14.14263", "viewport": { "width": 640, "height": 360 @@ -1164,7 +1164,7 @@ "defaultBrowserType": "chromium" }, "Nexus 10": { - "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Safari/537.36", "viewport": { "width": 800, "height": 1280 @@ -1175,7 +1175,7 @@ "defaultBrowserType": "chromium" }, "Nexus 10 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Safari/537.36", "viewport": { "width": 1280, "height": 800 @@ -1186,7 +1186,7 @@ "defaultBrowserType": "chromium" }, "Nexus 4": { - "userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Mobile Safari/537.36", "viewport": { "width": 384, "height": 640 @@ -1197,7 +1197,7 @@ "defaultBrowserType": "chromium" }, "Nexus 4 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Mobile Safari/537.36", "viewport": { "width": 640, "height": 384 @@ -1208,7 +1208,7 @@ "defaultBrowserType": "chromium" }, "Nexus 5": { - "userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Mobile Safari/537.36", "viewport": { "width": 360, "height": 640 @@ -1219,7 +1219,7 @@ "defaultBrowserType": "chromium" }, "Nexus 5 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Mobile Safari/537.36", "viewport": { "width": 640, "height": 360 @@ -1230,7 +1230,7 @@ "defaultBrowserType": "chromium" }, "Nexus 5X": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Mobile Safari/537.36", "viewport": { "width": 412, "height": 732 @@ -1241,7 +1241,7 @@ "defaultBrowserType": "chromium" }, "Nexus 5X landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Mobile Safari/537.36", "viewport": { "width": 732, "height": 412 @@ -1252,7 +1252,7 @@ "defaultBrowserType": "chromium" }, "Nexus 6": { - "userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Mobile Safari/537.36", "viewport": { "width": 412, "height": 732 @@ -1263,7 +1263,7 @@ "defaultBrowserType": "chromium" }, "Nexus 6 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Mobile Safari/537.36", "viewport": { "width": 732, "height": 412 @@ -1274,7 +1274,7 @@ "defaultBrowserType": "chromium" }, "Nexus 6P": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Mobile Safari/537.36", "viewport": { "width": 412, "height": 732 @@ -1285,7 +1285,7 @@ "defaultBrowserType": "chromium" }, "Nexus 6P landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Mobile Safari/537.36", "viewport": { "width": 732, "height": 412 @@ -1296,7 +1296,7 @@ "defaultBrowserType": "chromium" }, "Nexus 7": { - "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Safari/537.36", "viewport": { "width": 600, "height": 960 @@ -1307,7 +1307,7 @@ "defaultBrowserType": "chromium" }, "Nexus 7 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Safari/537.36", "viewport": { "width": 960, "height": 600 @@ -1362,7 +1362,7 @@ "defaultBrowserType": "webkit" }, "Pixel 2": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Mobile Safari/537.36", "viewport": { "width": 411, "height": 731 @@ -1373,7 +1373,7 @@ "defaultBrowserType": "chromium" }, "Pixel 2 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Mobile Safari/537.36", "viewport": { "width": 731, "height": 411 @@ -1384,7 +1384,7 @@ "defaultBrowserType": "chromium" }, "Pixel 2 XL": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Mobile Safari/537.36", "viewport": { "width": 411, "height": 823 @@ -1395,7 +1395,7 @@ "defaultBrowserType": "chromium" }, "Pixel 2 XL landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Mobile Safari/537.36", "viewport": { "width": 823, "height": 411 @@ -1406,7 +1406,7 @@ "defaultBrowserType": "chromium" }, "Pixel 3": { - "userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Mobile Safari/537.36", "viewport": { "width": 393, "height": 786 @@ -1417,7 +1417,7 @@ "defaultBrowserType": "chromium" }, "Pixel 3 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Mobile Safari/537.36", "viewport": { "width": 786, "height": 393 @@ -1428,7 +1428,7 @@ "defaultBrowserType": "chromium" }, "Pixel 4": { - "userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Mobile Safari/537.36", "viewport": { "width": 353, "height": 745 @@ -1439,7 +1439,7 @@ "defaultBrowserType": "chromium" }, "Pixel 4 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Mobile Safari/537.36", "viewport": { "width": 745, "height": 353 @@ -1450,7 +1450,7 @@ "defaultBrowserType": "chromium" }, "Pixel 4a (5G)": { - "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Mobile Safari/537.36", "screen": { "width": 412, "height": 892 @@ -1465,7 +1465,7 @@ "defaultBrowserType": "chromium" }, "Pixel 4a (5G) landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Mobile Safari/537.36", "screen": { "height": 892, "width": 412 @@ -1480,7 +1480,7 @@ "defaultBrowserType": "chromium" }, "Pixel 5": { - "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Mobile Safari/537.36", "screen": { "width": 393, "height": 851 @@ -1495,7 +1495,7 @@ "defaultBrowserType": "chromium" }, "Pixel 5 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Mobile Safari/537.36", "screen": { "width": 851, "height": 393 @@ -1510,7 +1510,7 @@ "defaultBrowserType": "chromium" }, "Pixel 7": { - "userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Mobile Safari/537.36", "screen": { "width": 412, "height": 915 @@ -1525,7 +1525,7 @@ "defaultBrowserType": "chromium" }, "Pixel 7 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Mobile Safari/537.36", "screen": { "width": 915, "height": 412 @@ -1540,7 +1540,7 @@ "defaultBrowserType": "chromium" }, "Moto G4": { - "userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Mobile Safari/537.36", "viewport": { "width": 360, "height": 640 @@ -1551,7 +1551,7 @@ "defaultBrowserType": "chromium" }, "Moto G4 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Mobile Safari/537.36", "viewport": { "width": 640, "height": 360 @@ -1562,7 +1562,7 @@ "defaultBrowserType": "chromium" }, "Desktop Chrome HiDPI": { - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Safari/537.36", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Safari/537.36", "screen": { "width": 1792, "height": 1120 @@ -1577,7 +1577,7 @@ "defaultBrowserType": "chromium" }, "Desktop Edge HiDPI": { - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Safari/537.36 Edg/131.0.6778.24", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Safari/537.36 Edg/132.0.6834.6", "screen": { "width": 1792, "height": 1120 @@ -1592,7 +1592,7 @@ "defaultBrowserType": "chromium" }, "Desktop Firefox HiDPI": { - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:131.0) Gecko/20100101 Firefox/131.0", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:132.0) Gecko/20100101 Firefox/132.0", "screen": { "width": 1792, "height": 1120 @@ -1607,7 +1607,7 @@ "defaultBrowserType": "firefox" }, "Desktop Safari": { - "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Safari/605.1.15", + "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Safari/605.1.15", "screen": { "width": 1792, "height": 1120 @@ -1622,7 +1622,7 @@ "defaultBrowserType": "webkit" }, "Desktop Chrome": { - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Safari/537.36", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Safari/537.36", "screen": { "width": 1920, "height": 1080 @@ -1637,7 +1637,7 @@ "defaultBrowserType": "chromium" }, "Desktop Edge": { - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.24 Safari/537.36 Edg/131.0.6778.24", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.6 Safari/537.36 Edg/132.0.6834.6", "screen": { "width": 1920, "height": 1080 @@ -1652,7 +1652,7 @@ "defaultBrowserType": "chromium" }, "Desktop Firefox": { - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:131.0) Gecko/20100101 Firefox/131.0", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:132.0) Gecko/20100101 Firefox/132.0", "screen": { "width": 1920, "height": 1080 diff --git a/packages/playwright-core/src/server/dispatchers/debugControllerDispatcher.ts b/packages/playwright-core/src/server/dispatchers/debugControllerDispatcher.ts index 34c4d3b4ca..77d7b503ab 100644 --- a/packages/playwright-core/src/server/dispatchers/debugControllerDispatcher.ts +++ b/packages/playwright-core/src/server/dispatchers/debugControllerDispatcher.ts @@ -68,7 +68,7 @@ export class DebugControllerDispatcher extends Dispatcher { + const { name, location } = params; + await this._object.group(name, location, metadata); + } + + async tracingGroupEnd(params: channels.TracingTracingGroupEndParams): Promise { + await this._object.groupEnd(); + } + async tracingStopChunk(params: channels.TracingTracingStopChunkParams): Promise { const { artifact, entries } = await this._object.stopChunk(params); return { artifact: artifact ? ArtifactDispatcher.from(this, artifact) : undefined, entries }; diff --git a/packages/playwright-core/src/server/dom.ts b/packages/playwright-core/src/server/dom.ts index dea4a52e78..8e65c7c67f 100644 --- a/packages/playwright-core/src/server/dom.ts +++ b/packages/playwright-core/src/server/dom.ts @@ -266,14 +266,22 @@ export class ElementHandle extends js.JSHandle { const filtered = quads.map(quad => intersectQuadWithViewport(quad)).filter(quad => computeQuadArea(quad) > 0.99); if (!filtered.length) return 'error:notinviewport'; - // Return the middle point of the first quad. - const result = { x: 0, y: 0 }; - for (const point of filtered[0]) { - result.x += point.x / 4; - result.y += point.y / 4; + if (this._page._browserContext._browser.options.name === 'firefox') { + // Firefox internally uses integer coordinates, so 8.x is converted to 8 or 9 when clicking. + // + // This does not work nicely for small elements. For example, 1x1 square with corners + // (8;8) and (9;9) is targeted when clicking at (8;8) but not when clicking at (9;9). + // So, clicking at (8.x;8.y) will sometimes click at (9;9) and miss the target. + // + // Therefore, we try to find an integer point within a quad to make sure we click inside the element. + for (const quad of filtered) { + const integerPoint = findIntegerPointInsideQuad(quad); + if (integerPoint) + return integerPoint; + } } - compensateHalfIntegerRoundingError(result); - return result; + // Return the middle point of the first quad. + return quadMiddlePoint(filtered[0]); } private async _offsetPoint(offset: types.Point): Promise { @@ -920,24 +928,47 @@ function roundPoint(point: types.Point): types.Point { }; } -function compensateHalfIntegerRoundingError(point: types.Point) { - // Firefox internally uses integer coordinates, so 8.5 is converted to 9 when clicking. - // - // This does not work nicely for small elements. For example, 1x1 square with corners - // (8;8) and (9;9) is targeted when clicking at (8;8) but not when clicking at (9;9). - // So, clicking at (8.5;8.5) will effectively click at (9;9) and miss the target. - // - // Therefore, we skew half-integer values from the interval (8.49, 8.51) towards - // (8.47, 8.49) that is rounded towards 8. This means clicking at (8.5;8.5) will - // be replaced with (8.48;8.48) and will effectively click at (8;8). - // - // Other browsers use float coordinates, so this change should not matter. - const remainderX = point.x - Math.floor(point.x); - if (remainderX > 0.49 && remainderX < 0.51) - point.x -= 0.02; - const remainderY = point.y - Math.floor(point.y); - if (remainderY > 0.49 && remainderY < 0.51) - point.y -= 0.02; +function quadMiddlePoint(quad: types.Quad): types.Point { + const result = { x: 0, y: 0 }; + for (const point of quad) { + result.x += point.x / 4; + result.y += point.y / 4; + } + return result; +} + +function triangleArea(p1: types.Point, p2: types.Point, p3: types.Point): number { + return Math.abs(p1.x * (p2.y - p3.y) + p2.x * (p3.y - p1.y) + p3.x * (p1.y - p2.y)) / 2; +} + +function isPointInsideQuad(point: types.Point, quad: types.Quad): boolean { + const area1 = triangleArea(point, quad[0], quad[1]) + triangleArea(point, quad[1], quad[2]) + triangleArea(point, quad[2], quad[3]) + triangleArea(point, quad[3], quad[0]); + const area2 = triangleArea(quad[0], quad[1], quad[2]) + triangleArea(quad[1], quad[2], quad[3]); + // Check that point is inside the quad. + if (Math.abs(area1 - area2) > 0.1) + return false; + // Check that point is not on the right/bottom edge, because clicking + // there does not actually click the element. + return point.x < Math.max(quad[0].x, quad[1].x, quad[2].x, quad[3].x) && + point.y < Math.max(quad[0].y, quad[1].y, quad[2].y, quad[3].y); +} + +function findIntegerPointInsideQuad(quad: types.Quad): types.Point | undefined { + // Try all four rounding directions of the middle point. + const point = quadMiddlePoint(quad); + point.x = Math.floor(point.x); + point.y = Math.floor(point.y); + if (isPointInsideQuad(point, quad)) + return point; + point.x += 1; + if (isPointInsideQuad(point, quad)) + return point; + point.y += 1; + if (isPointInsideQuad(point, quad)) + return point; + point.x -= 1; + if (isPointInsideQuad(point, quad)) + return point; } export const kUnableToAdoptErrorMessage = 'Unable to adopt element handle from a different document'; diff --git a/packages/playwright-core/src/server/frames.ts b/packages/playwright-core/src/server/frames.ts index 129484a027..81f04d94eb 100644 --- a/packages/playwright-core/src/server/frames.ts +++ b/packages/playwright-core/src/server/frames.ts @@ -296,7 +296,8 @@ export class FrameManager { if (request._documentId) frame.setPendingDocument({ documentId: request._documentId, request }); if (request._isFavicon) { - route?.continue({ isFallback: true }).catch(() => {}); + // Abort favicon requests to avoid network access in case of interception. + route?.abort('aborted').catch(() => {}); return; } this._page.emitOnContext(BrowserContext.Events.Request, request); @@ -1828,5 +1829,7 @@ function renderUnexpectedValue(expression: string, received: any): string { return received ? 'empty' : 'not empty'; if (expression === 'to.be.focused') return received ? 'focused' : 'not focused'; + if (expression === 'to.match.aria') + return received ? received.raw : received; return received; } diff --git a/packages/playwright-core/src/server/index.ts b/packages/playwright-core/src/server/index.ts index 439febfe18..31e177a219 100644 --- a/packages/playwright-core/src/server/index.ts +++ b/packages/playwright-core/src/server/index.ts @@ -19,7 +19,6 @@ export { registry, registryDirectory, Registry, - installDefaultBrowsersForNpmInstall, installBrowsersForNpmInstall, writeDockerVersion } from './registry'; diff --git a/packages/playwright-core/src/server/injected/ariaSnapshot.ts b/packages/playwright-core/src/server/injected/ariaSnapshot.ts index fa0f14343c..d541646f0e 100644 --- a/packages/playwright-core/src/server/injected/ariaSnapshot.ts +++ b/packages/playwright-core/src/server/injected/ariaSnapshot.ts @@ -16,41 +16,40 @@ import * as roleUtils from './roleUtils'; import { getElementComputedStyle } from './domUtils'; -import type { AriaRole } from './roleUtils'; import { escapeRegExp, longestCommonSubstring } from '@isomorphic/stringUtils'; -import { yamlEscapeKeyIfNeeded, yamlEscapeValueIfNeeded, yamlQuoteFragment } from './yaml'; +import { yamlEscapeKeyIfNeeded, yamlEscapeValueIfNeeded } from './yaml'; +import type { AriaProps, AriaRole, AriaTemplateNode, AriaTemplateRoleNode, AriaTemplateTextNode } from '@isomorphic/ariaSnapshot'; -type AriaProps = { - checked?: boolean | 'mixed'; - disabled?: boolean; - expanded?: boolean; - level?: number; - pressed?: boolean | 'mixed'; - selected?: boolean; -}; - -type AriaNode = AriaProps & { +export type AriaNode = AriaProps & { role: AriaRole | 'fragment'; name: string; children: (AriaNode | string)[]; + element: Element; }; -export type AriaTemplateTextNode = { - kind: 'text'; - text: RegExp | string; +export type AriaSnapshot = { + root: AriaNode; + elements: Map; + ids: Map; }; -export type AriaTemplateRoleNode = AriaProps & { - kind: 'role'; - role: AriaRole | 'fragment'; - name?: RegExp | string; - children?: AriaTemplateNode[]; -}; - -export type AriaTemplateNode = AriaTemplateRoleNode | AriaTemplateTextNode; - -export function generateAriaTree(rootElement: Element): AriaNode { +export function generateAriaTree(rootElement: Element): AriaSnapshot { const visited = new Set(); + + const snapshot: AriaSnapshot = { + root: { role: 'fragment', name: '', children: [], element: rootElement }, + elements: new Map(), + ids: new Map(), + }; + + const addElement = (element: Element) => { + const id = snapshot.elements.size + 1; + snapshot.elements.set(id, element); + snapshot.ids.set(element, id); + }; + + addElement(rootElement); + const visit = (ariaNode: AriaNode, node: Node) => { if (visited.has(node)) return; @@ -80,6 +79,7 @@ export function generateAriaTree(rootElement: Element): AriaNode { } } + addElement(element); const childAriaNode = toAriaNode(element); if (childAriaNode) ariaNode.children.push(childAriaNode); @@ -122,15 +122,14 @@ export function generateAriaTree(rootElement: Element): AriaNode { } roleUtils.beginAriaCaches(); - const ariaRoot: AriaNode = { role: 'fragment', name: '', children: [] }; try { - visit(ariaRoot, rootElement); + visit(snapshot.root, rootElement); } finally { roleUtils.endAriaCaches(); } - normalizeStringChildren(ariaRoot); - return ariaRoot; + normalizeStringChildren(snapshot.root); + return snapshot; } function toAriaNode(element: Element): AriaNode | null { @@ -139,7 +138,7 @@ function toAriaNode(element: Element): AriaNode | null { return null; const name = roleUtils.getElementAccessibleName(element, false) || ''; - const result: AriaNode = { role, name, children: [] }; + const result: AriaNode = { role, name, children: [], element }; if (roleUtils.kAriaCheckedRoles.includes(role)) result.checked = roleUtils.getAriaChecked(element); @@ -165,10 +164,6 @@ function toAriaNode(element: Element): AriaNode | null { return result; } -export function renderedAriaTree(rootElement: Element, options?: { mode?: 'raw' | 'regex' }): string { - return renderAriaTree(generateAriaTree(rootElement), options); -} - function normalizeStringChildren(rootA11yNode: AriaNode) { const flushChildren = (buffer: string[], normalizedChildren: (AriaNode | string)[]) => { if (!buffer.length) @@ -224,9 +219,9 @@ export type MatcherReceived = { regex: string; }; -export function matchesAriaTree(rootElement: Element, template: AriaTemplateNode): { matches: boolean, received: MatcherReceived } { - const root = generateAriaTree(rootElement); - const matches = matchesNodeDeep(root, template); +export function matchesAriaTree(rootElement: Element, template: AriaTemplateNode): { matches: AriaNode[], received: MatcherReceived } { + const root = generateAriaTree(rootElement).root; + const matches = matchesNodeDeep(root, template, false); return { matches, received: { @@ -236,6 +231,12 @@ export function matchesAriaTree(rootElement: Element, template: AriaTemplateNode }; } +export function getAllByAria(rootElement: Element, template: AriaTemplateNode): Element[] { + const root = generateAriaTree(rootElement).root; + const matches = matchesNodeDeep(root, template, true); + return matches.map(n => n.element); +} + function matchesNode(node: AriaNode | string, template: AriaTemplateNode, depth: number): boolean { if (typeof node === 'string' && template.kind === 'text') return matchesTextNode(node, template); @@ -282,12 +283,12 @@ function containsList(children: (AriaNode | string)[], template: AriaTemplateNod return true; } -function matchesNodeDeep(root: AriaNode, template: AriaTemplateNode): boolean { - const results: (AriaNode | string)[] = []; +function matchesNodeDeep(root: AriaNode, template: AriaTemplateNode, collectAll: boolean): AriaNode[] { + const results: AriaNode[] = []; const visit = (node: AriaNode | string): boolean => { if (matchesNode(node, template, 0)) { - results.push(node); - return true; + results.push(node as AriaNode); + return !collectAll; } if (typeof node === 'string') return false; @@ -298,10 +299,10 @@ function matchesNodeDeep(root: AriaNode, template: AriaTemplateNode): boolean { return false; }; visit(root); - return !!results.length; + return results; } -export function renderAriaTree(ariaNode: AriaNode, options?: { mode?: 'raw' | 'regex' }): string { +export function renderAriaTree(ariaNode: AriaNode, options?: { mode?: 'raw' | 'regex', ids?: Map }): string { const lines: string[] = []; const includeText = options?.mode === 'regex' ? textContributesInfo : () => true; const renderString = options?.mode === 'regex' ? convertToBestGuessRegex : (str: string) => str; @@ -309,17 +310,20 @@ export function renderAriaTree(ariaNode: AriaNode, options?: { mode?: 'raw' | 'r if (typeof ariaNode === 'string') { if (parentAriaNode && !includeText(parentAriaNode, ariaNode)) return; - const text = renderString(ariaNode); + const text = yamlEscapeValueIfNeeded(renderString(ariaNode)); if (text) lines.push(indent + '- text: ' + text); return; } let key = ariaNode.role; - if (ariaNode.name) { + // Yaml has a limit of 1024 characters per key, and we leave some space for role and attributes. + if (ariaNode.name && ariaNode.name.length <= 900) { const name = renderString(ariaNode.name); - if (name) - key += ' ' + (name.startsWith('/') && name.endsWith('/') ? name : yamlQuoteFragment(name)); + if (name) { + const stringifiedName = name.startsWith('/') && name.endsWith('/') ? name : JSON.stringify(name); + key += ' ' + stringifiedName; + } } if (ariaNode.checked === 'mixed') key += ` [checked=mixed]`; @@ -337,6 +341,11 @@ export function renderAriaTree(ariaNode: AriaNode, options?: { mode?: 'raw' | 'r key += ` [pressed]`; if (ariaNode.selected === true) key += ` [selected]`; + if (options?.ids) { + const id = options?.ids.get(ariaNode.element); + if (id) + key += ` [id=${id}]`; + } const escapedKey = indent + '- ' + yamlEscapeKeyIfNeeded(key); if (!ariaNode.children.length) { @@ -414,8 +423,8 @@ function textContributesInfo(node: AriaNode, text: string): boolean { if (node.name.length > text.length) return false; - // Figure out if text adds any value. - const substr = longestCommonSubstring(text, node.name); + // Figure out if text adds any value. "longestCommonSubstring" is expensive, so limit strings length. + const substr = (text.length <= 200 && node.name.length <= 200) ? longestCommonSubstring(text, node.name) : ''; let filtered = text; while (substr && filtered.includes(substr)) filtered = filtered.replace(substr, ''); diff --git a/packages/playwright-core/src/server/injected/highlight.ts b/packages/playwright-core/src/server/injected/highlight.ts index c06e58f529..5720ffc539 100644 --- a/packages/playwright-core/src/server/injected/highlight.ts +++ b/packages/playwright-core/src/server/injected/highlight.ts @@ -90,7 +90,8 @@ export class Highlight { } install() { - if (!this._injectedScript.document.documentElement.contains(this._glassPaneElement)) + // NOTE: document.documentElement can be null: https://github.com/microsoft/TypeScript/issues/50078 + if (this._injectedScript.document.documentElement && !this._injectedScript.document.documentElement.contains(this._glassPaneElement)) this._injectedScript.document.documentElement.appendChild(this._glassPaneElement); } diff --git a/packages/playwright-core/src/server/injected/injectedScript.ts b/packages/playwright-core/src/server/injected/injectedScript.ts index 6f0d8ee473..aa0eb1004f 100644 --- a/packages/playwright-core/src/server/injected/injectedScript.ts +++ b/packages/playwright-core/src/server/injected/injectedScript.ts @@ -34,7 +34,10 @@ import { kLayoutSelectorNames, type LayoutSelectorName, layoutSelectorScore } fr import { asLocator } from '../../utils/isomorphic/locatorGenerators'; import type { Language } from '../../utils/isomorphic/locatorGenerators'; import { cacheNormalizedWhitespaces, normalizeWhiteSpace, trimStringWithEllipsis } from '../../utils/isomorphic/stringUtils'; -import { matchesAriaTree, renderedAriaTree } from './ariaSnapshot'; +import { matchesAriaTree, getAllByAria, generateAriaTree, renderAriaTree } from './ariaSnapshot'; +import type { AriaNode, AriaSnapshot } from './ariaSnapshot'; +import type { AriaTemplateNode } from '@isomorphic/ariaSnapshot'; +import { parseYamlTemplate } from '@isomorphic/ariaSnapshot'; export type FrameExpectParams = Omit & { expectedValue?: any }; @@ -82,6 +85,7 @@ export class InjectedScript { isElementVisible, isInsideScope, normalizeWhiteSpace, + parseYamlTemplate, }; // eslint-disable-next-line no-restricted-globals @@ -212,10 +216,31 @@ export class InjectedScript { return new Set(result.map(r => r.element)); } - ariaSnapshot(node: Node, options?: { mode?: 'raw' | 'regex' }): string { + ariaSnapshot(node: Node, options?: { mode?: 'raw' | 'regex', id?: boolean }): string { if (node.nodeType !== Node.ELEMENT_NODE) throw this.createStacklessError('Can only capture aria snapshot of Element nodes.'); - return renderedAriaTree(node as Element, options); + const ariaSnapshot = generateAriaTree(node as Element); + return renderAriaTree(ariaSnapshot.root, options); + } + + ariaSnapshotAsObject(node: Node): AriaSnapshot { + return generateAriaTree(node as Element); + } + + ariaSnapshotElement(snapshot: AriaSnapshot, elementId: number): Element | null { + return snapshot.elements.get(elementId) || null; + } + + renderAriaTree(ariaNode: AriaNode, options?: { mode?: 'raw' | 'regex', id?: boolean}): string { + return renderAriaTree(ariaNode, options); + } + + renderAriaSnapshotWithIds(ariaSnapshot: AriaSnapshot): string { + return renderAriaTree(ariaSnapshot.root, { ids: ariaSnapshot.ids }); + } + + getAllByAria(document: Document, template: AriaTemplateNode): Element[] { + return getAllByAria(document.documentElement, template); } querySelectorAll(selector: ParsedSelector, root: Node): Element[] { @@ -1263,8 +1288,13 @@ export class InjectedScript { } { - if (expression === 'to.match.aria') - return matchesAriaTree(element, options.expectedValue); + if (expression === 'to.match.aria') { + const result = matchesAriaTree(element, options.expectedValue); + return { + received: result.received, + matches: !!result.matches.length, + }; + } } { @@ -1324,6 +1354,8 @@ export class InjectedScript { received = elements.map(e => options.useInnerText ? (e as HTMLElement).innerText : elementText(new Map(), e).full); else if (expression === 'to.have.class.array') received = elements.map(e => e.classList.toString()); + else if (expression === 'to.have.accessible.name.array') + received = elements.map(e => getElementAccessibleName(e, false)); if (received && options.expectedText) { // "To match an array" is "to contain an array" + "equal length" diff --git a/packages/playwright-core/src/server/injected/recorder/recorder.ts b/packages/playwright-core/src/server/injected/recorder/recorder.ts index 389ec04276..ddfb0386d9 100644 --- a/packages/playwright-core/src/server/injected/recorder/recorder.ts +++ b/packages/playwright-core/src/server/injected/recorder/recorder.ts @@ -207,9 +207,9 @@ class InspectTool implements RecorderTool { class RecordActionTool implements RecorderTool { private _recorder: Recorder; private _performingActions = new Set(); - private _hoveredModel: HighlightModel | null = null; + private _hoveredModel: HighlightModelWithSelector | null = null; private _hoveredElement: HTMLElement | null = null; - private _activeModel: HighlightModel | null = null; + private _activeModel: HighlightModelWithSelector | null = null; private _expectProgrammaticKeyUp = false; private _pendingClickAction: { action: actions.ClickAction, timeout: number } | undefined; @@ -492,9 +492,10 @@ class RecordActionTool implements RecorderTool { return; const result = activeElement ? this._recorder.injectedScript.generateSelector(activeElement, { testIdAttributeName: this._recorder.state.testIdAttributeName }) : null; this._activeModel = result && result.selector ? result : null; - if (userGesture) + if (userGesture) { this._hoveredElement = activeElement as HTMLElement | null; - this._updateModelForHoveredElement(); + this._updateModelForHoveredElement(); + } } private _shouldIgnoreMouseEvent(event: MouseEvent): boolean { @@ -589,6 +590,8 @@ class RecordActionTool implements RecorderTool { } private _updateModelForHoveredElement() { + if (this._performingActions.size) + return; if (!this._hoveredElement || !this._hoveredElement.isConnected) { this._hoveredModel = null; this._hoveredElement = null; @@ -605,7 +608,7 @@ class RecordActionTool implements RecorderTool { class TextAssertionTool implements RecorderTool { private _recorder: Recorder; - private _hoverHighlight: HighlightModel | null = null; + private _hoverHighlight: HighlightModelWithSelector | null = null; private _action: actions.AssertAction | null = null; private _dialog: Dialog; private _textCache = new Map(); @@ -1018,7 +1021,8 @@ export class Recorder { private _listeners: (() => void)[] = []; private _currentTool: RecorderTool; private _tools: Record; - private _actionSelectorModel: HighlightModel | null = null; + private _lastHighlightedSelector: string | undefined = undefined; + private _lastHighlightedAriaTemplateJSON: string = 'undefined'; readonly highlight: Highlight; readonly overlay: Overlay | undefined; private _stylesheet: CSSStyleSheet; @@ -1128,13 +1132,28 @@ export class Recorder { this._switchCurrentTool(); this.overlay?.setUIState(state); - // Race or scroll. - if (this._actionSelectorModel?.selector && !this._actionSelectorModel?.elements.length) - this._actionSelectorModel = null; - if (state.actionSelector !== this._actionSelectorModel?.selector) - this._actionSelectorModel = state.actionSelector ? querySelector(this.injectedScript, state.actionSelector, this.document) : null; - if (this.state.mode === 'none' || this.state.mode === 'standby') - this.updateHighlight(this._actionSelectorModel, false); + let highlight: HighlightModel | 'clear' | 'noop' = 'noop'; + if (state.actionSelector !== this._lastHighlightedSelector) { + this._lastHighlightedSelector = state.actionSelector; + const model = state.actionSelector ? querySelector(this.injectedScript, state.actionSelector, this.document) : null; + highlight = model?.elements.length ? model : 'clear'; + } + + const ariaTemplateJSON = JSON.stringify(state.ariaTemplate); + if (this._lastHighlightedAriaTemplateJSON !== ariaTemplateJSON) { + this._lastHighlightedAriaTemplateJSON = ariaTemplateJSON; + const template = state.ariaTemplate ? this.injectedScript.utils.parseYamlTemplate(state.ariaTemplate) : undefined; + const elements = template ? this.injectedScript.getAllByAria(this.document, template) : []; + if (elements.length) + highlight = { elements }; + else + highlight = 'clear'; + } + + if (highlight === 'clear') + this.clearHighlight(); + else if (highlight !== 'noop') + this.updateHighlight(highlight, false); } clearHighlight() { @@ -1249,6 +1268,8 @@ export class Recorder { private _onScroll(event: Event) { if (!event.isTrusted) return; + this._lastHighlightedSelector = undefined; + this._lastHighlightedAriaTemplateJSON = 'undefined'; this.highlight.hideActionPoint(); this._currentTool.onScroll?.(event); } @@ -1439,10 +1460,14 @@ function consumeEvent(e: Event) { } type HighlightModel = HighlightOptions & { - selector: string; + selector?: string; elements: Element[]; }; +type HighlightModelWithSelector = HighlightModel & { + selector: string; +}; + function asCheckbox(node: Node | null): HTMLInputElement | null { if (!node || node.nodeName !== 'INPUT') return null; diff --git a/packages/playwright-core/src/server/injected/roleUtils.ts b/packages/playwright-core/src/server/injected/roleUtils.ts index df52329b1e..25035b6998 100644 --- a/packages/playwright-core/src/server/injected/roleUtils.ts +++ b/packages/playwright-core/src/server/injected/roleUtils.ts @@ -14,6 +14,7 @@ * limitations under the License. */ +import type { AriaRole } from '@isomorphic/ariaSnapshot'; import { closestCrossShadow, elementSafeTagName, enclosingShadowRootOrDocument, getElementComputedStyle, isElementStyleVisibilityVisible, isVisibleTextNode, parentElementOrShadowHost } from './domUtils'; function hasExplicitAccessibleName(e: Element) { @@ -211,18 +212,6 @@ function getImplicitAriaRole(element: Element): AriaRole | null { return implicitRole; } -// https://www.w3.org/TR/wai-aria-1.2/#role_definitions -// https://www.w3.org/TR/wai-aria-1.2/#abstract_roles -// type AbstractRoles = 'command' | 'composite' | 'input' | 'landmark' | 'range' | 'roletype' | 'section' | 'sectionhead' | 'select' | 'structure' | 'widget' | 'window'; - -export type AriaRole = 'alert' | 'alertdialog' | 'application' | 'article' | 'banner' | 'blockquote' | 'button' | 'caption' | 'cell' | 'checkbox' | 'code' | 'columnheader' | 'combobox' | - 'complementary' | 'contentinfo' | 'definition' | 'deletion' | 'dialog' | 'directory' | 'document' | 'emphasis' | 'feed' | 'figure' | 'form' | 'generic' | 'grid' | - 'gridcell' | 'group' | 'heading' | 'img' | 'insertion' | 'link' | 'list' | 'listbox' | 'listitem' | 'log' | 'main' | 'mark' | 'marquee' | 'math' | 'meter' | 'menu' | - 'menubar' | 'menuitem' | 'menuitemcheckbox' | 'menuitemradio' | 'navigation' | 'none' | 'note' | 'option' | 'paragraph' | 'presentation' | 'progressbar' | 'radio' | 'radiogroup' | - 'region' | 'row' | 'rowgroup' | 'rowheader' | 'scrollbar' | 'search' | 'searchbox' | 'separator' | 'slider' | - 'spinbutton' | 'status' | 'strong' | 'subscript' | 'superscript' | 'switch' | 'tab' | 'table' | 'tablist' | 'tabpanel' | 'term' | 'textbox' | 'time' | 'timer' | - 'toolbar' | 'tooltip' | 'tree' | 'treegrid' | 'treeitem'; - const validRoles: AriaRole[] = ['alert', 'alertdialog', 'application', 'article', 'banner', 'blockquote', 'button', 'caption', 'cell', 'checkbox', 'code', 'columnheader', 'combobox', 'complementary', 'contentinfo', 'definition', 'deletion', 'dialog', 'directory', 'document', 'emphasis', 'feed', 'figure', 'form', 'generic', 'grid', 'gridcell', 'group', 'heading', 'img', 'insertion', 'link', 'list', 'listbox', 'listitem', 'log', 'main', 'mark', 'marquee', 'math', 'meter', 'menu', @@ -394,7 +383,11 @@ export function getAriaLabelledByElements(element: Element): Element[] | null { const ref = element.getAttribute('aria-labelledby'); if (ref === null) return null; - return getIdRefs(element, ref); + const refs = getIdRefs(element, ref); + // step 2b: + // "if the current node has an aria-labelledby attribute that contains at least one valid IDREF" + // Therefore, if none of the refs match an element, we consider aria-labelledby to be missing. + return refs.length ? refs : null; } function allowsNameFromContent(role: string, targetDescendant: boolean) { diff --git a/packages/playwright-core/src/server/injected/webSocketMock.ts b/packages/playwright-core/src/server/injected/webSocketMock.ts index 7a4742bac3..6ca09ede93 100644 --- a/packages/playwright-core/src/server/injected/webSocketMock.ts +++ b/packages/playwright-core/src/server/injected/webSocketMock.ts @@ -331,6 +331,13 @@ export function inject(globalThis: GlobalThis) { _ensureOpened() { if (this.readyState !== WebSocketMock.CONNECTING) return; + this.extensions = this._ws?.extensions || ''; + if (this._ws) + this.protocol = this._ws.protocol; + else if (Array.isArray(this._protocols)) + this.protocol = this._protocols[0] || ''; + else + this.protocol = this._protocols || ''; this.readyState = WebSocketMock.OPEN; this.dispatchEvent(new Event('open', { cancelable: true })); } diff --git a/packages/playwright-core/src/server/injected/yaml.ts b/packages/playwright-core/src/server/injected/yaml.ts index 97bf3a070d..977591c1cc 100644 --- a/packages/playwright-core/src/server/injected/yaml.ts +++ b/packages/playwright-core/src/server/injected/yaml.ts @@ -46,19 +46,6 @@ export function yamlEscapeValueIfNeeded(str: string): string { }) + '"'; } -export function yamlQuoteFragment(str: string, quote = '"'): string { - return quote + str.replace(/['"]/g, c => { - switch (c) { - case '"': - return quote === '"' ? '\\"' : '"'; - case '\'': - return quote === '\'' ? '\\\'' : '\''; - default: - return c; - } - }) + quote; -} - function yamlStringNeedsQuotes(str: string): boolean { if (str.length === 0) return true; @@ -99,6 +86,10 @@ function yamlStringNeedsQuotes(str: string): boolean { if (/^[>|]/.test(str)) return true; + // Strings starting with quotes need quotes + if (/^["']/.test(str)) + return true; + // Strings containing special characters that could cause ambiguity if (/[{}`]/.test(str)) return true; diff --git a/packages/playwright-core/src/server/launchApp.ts b/packages/playwright-core/src/server/launchApp.ts index 3d119f9d46..d8c81a3169 100644 --- a/packages/playwright-core/src/server/launchApp.ts +++ b/packages/playwright-core/src/server/launchApp.ts @@ -43,12 +43,12 @@ export async function launchApp(browserType: BrowserType, options: { } const context = await browserType.launchPersistentContext(serverSideCallMetadata(), '', { - channel: !options.persistentContextOptions?.executablePath ? findChromiumChannel(options.sdkLanguage) : undefined, - noDefaultViewport: true, ignoreDefaultArgs: ['--enable-automation'], - colorScheme: 'no-override', - acceptDownloads: isUnderTest() ? 'accept' : 'internal-browser-default', ...options?.persistentContextOptions, + channel: options.persistentContextOptions?.channel ?? (!options.persistentContextOptions?.executablePath ? findChromiumChannel(options.sdkLanguage) : undefined), + noDefaultViewport: options.persistentContextOptions?.noDefaultViewport ?? true, + acceptDownloads: options?.persistentContextOptions?.acceptDownloads ?? (isUnderTest() ? 'accept' : 'internal-browser-default'), + colorScheme: options?.persistentContextOptions?.colorScheme ?? 'no-override', args, }); const [page] = context.pages(); diff --git a/packages/playwright-core/src/server/recorder.ts b/packages/playwright-core/src/server/recorder.ts index a2be2992e6..16f9d791e1 100644 --- a/packages/playwright-core/src/server/recorder.ts +++ b/packages/playwright-core/src/server/recorder.ts @@ -30,6 +30,9 @@ import type { IRecorderAppFactory, IRecorderApp, IRecorder } from './recorder/re import { metadataToCallLog } from './recorder/recorderUtils'; import type * as actions from '@recorder/actions'; import { buildFullSelector } from '../utils/isomorphic/recorderUtils'; +import { stringifySelector } from '../utils/isomorphic/selectorParser'; +import type { Frame } from './frames'; +import type { ParsedYaml } from '@isomorphic/ariaSnapshot'; const recorderSymbol = Symbol('recorderSymbol'); @@ -37,7 +40,7 @@ export class Recorder implements InstrumentationListener, IRecorder { readonly handleSIGINT: boolean | undefined; private _context: BrowserContext; private _mode: Mode; - private _highlightedSelector = ''; + private _highlightedElement: { selector?: string, ariaTemplate?: ParsedYaml } = {}; private _overlayState: OverlayState = { offsetX: 0 }; private _recorderApp: IRecorderApp | null = null; private _currentCallsMetadata = new Map(); @@ -101,8 +104,11 @@ export class Recorder implements InstrumentationListener, IRecorder { this.setMode(data.params.mode); return; } - if (data.event === 'selectorUpdated') { - this.setHighlightedSelector(this._currentLanguage, data.params.selector); + if (data.event === 'highlightRequested') { + if (data.params.selector) + this.setHighlightedSelector(this._currentLanguage, data.params.selector); + if (data.params.ariaTemplate) + this.setHighlightedAriaTemplate(data.params.ariaTemplate); return; } if (data.event === 'step') { @@ -126,6 +132,10 @@ export class Recorder implements InstrumentationListener, IRecorder { this._contextRecorder.clearScript(); return; } + if (data.event === 'runTask') { + this._contextRecorder.runTask(data.params.task); + return; + } }); await Promise.all([ @@ -146,12 +156,12 @@ export class Recorder implements InstrumentationListener, IRecorder { this._pushAllSources(); }); - await this._context.exposeBinding('__pw_recorderState', false, source => { - let actionSelector = ''; + await this._context.exposeBinding('__pw_recorderState', false, async source => { + let actionSelector: string | undefined; let actionPoint: Point | undefined; const hasActiveScreenshotCommand = [...this._currentCallsMetadata.keys()].some(isScreenshotCommand); if (!hasActiveScreenshotCommand) { - actionSelector = this._highlightedSelector; + actionSelector = await this._scopeHighlightedSelectorToFrame(source.frame); for (const [metadata, sdkObject] of this._currentCallsMetadata) { if (source.page === sdkObject.attribution.page) { actionPoint = metadata.point || actionPoint; @@ -163,6 +173,7 @@ export class Recorder implements InstrumentationListener, IRecorder { mode: this._mode, actionPoint, actionSelector, + ariaTemplate: this._highlightedElement.ariaTemplate, language: this._currentLanguage, testIdAttributeName: this._contextRecorder.testIdAttributeName(), overlay: this._overlayState, @@ -215,11 +226,11 @@ export class Recorder implements InstrumentationListener, IRecorder { setMode(mode: Mode) { if (this._mode === mode) return; - this._highlightedSelector = ''; + this._highlightedElement = {}; this._mode = mode; this._recorderApp?.setMode(this._mode); - this._contextRecorder.setEnabled(this._mode === 'recording' || this._mode === 'assertingText' || this._mode === 'assertingVisibility' || this._mode === 'assertingValue' || this._mode === 'assertingSnapshot'); - this._debugger.setMuted(this._mode === 'recording' || this._mode === 'assertingText' || this._mode === 'assertingVisibility' || this._mode === 'assertingValue'); + this._contextRecorder.setEnabled(this._isRecording()); + this._debugger.setMuted(this._isRecording()); if (this._mode !== 'none' && this._mode !== 'standby' && this._context.pages().length === 1) this._context.pages()[0].bringToFront().catch(() => {}); this._refreshOverlay(); @@ -234,26 +245,58 @@ export class Recorder implements InstrumentationListener, IRecorder { } setHighlightedSelector(language: Language, selector: string) { - this._highlightedSelector = locatorOrSelectorAsSelector(language, selector, this._context.selectors().testIdAttributeName()); + this._highlightedElement = { selector: locatorOrSelectorAsSelector(language, selector, this._context.selectors().testIdAttributeName()) }; + this._refreshOverlay(); + } + + setHighlightedAriaTemplate(ariaTemplate: ParsedYaml) { + this._highlightedElement = { ariaTemplate }; this._refreshOverlay(); } hideHighlightedSelector() { - this._highlightedSelector = ''; + this._highlightedElement = {}; this._refreshOverlay(); } + private async _scopeHighlightedSelectorToFrame(frame: Frame): Promise { + if (!this._highlightedElement.selector) + return; + try { + const mainFrame = frame._page.mainFrame(); + const resolved = await mainFrame.selectors.resolveFrameForSelector(this._highlightedElement.selector); + // selector couldn't be found, don't highlight anything + if (!resolved) + return ''; + + // selector points to no specific frame, highlight in all frames + if (resolved?.frame === mainFrame) + return stringifySelector(resolved.info.parsed); + + // selector points to this frame, highlight it + if (resolved?.frame === frame) + return stringifySelector(resolved.info.parsed); + + // selector points to a different frame, highlight nothing + return ''; + } catch { + return ''; + } + } + setOutput(codegenId: string, outputFile: string | undefined) { this._contextRecorder.setOutput(codegenId, outputFile); } private _refreshOverlay() { - for (const page of this._context.pages()) - page.mainFrame().evaluateExpression('window.__pw_refreshOverlay()').catch(() => {}); + for (const page of this._context.pages()) { + for (const frame of page.frames()) + frame.evaluateExpression('window.__pw_refreshOverlay()').catch(() => {}); + } } async onBeforeCall(sdkObject: SdkObject, metadata: CallMetadata) { - if (this._omitCallTracking || this._mode === 'recording' || this._mode === 'assertingText' || this._mode === 'assertingVisibility' || this._mode === 'assertingValue') + if (this._omitCallTracking || this._isRecording()) return; this._currentCallsMetadata.set(metadata, sdkObject); this._updateUserSources(); @@ -261,11 +304,11 @@ export class Recorder implements InstrumentationListener, IRecorder { if (isScreenshotCommand(metadata)) this.hideHighlightedSelector(); else if (metadata.params && metadata.params.selector) - this._highlightedSelector = metadata.params.selector; + this._highlightedElement = { selector: metadata.params.selector }; } async onAfterCall(sdkObject: SdkObject, metadata: CallMetadata) { - if (this._omitCallTracking || this._mode === 'recording' || this._mode === 'assertingText' || this._mode === 'assertingVisibility' || this._mode === 'assertingValue') + if (this._omitCallTracking || this._isRecording()) return; if (!metadata.error) this._currentCallsMetadata.delete(metadata); @@ -315,7 +358,7 @@ export class Recorder implements InstrumentationListener, IRecorder { } updateCallLog(metadatas: CallMetadata[]) { - if (this._mode === 'recording' || this._mode === 'assertingText' || this._mode === 'assertingVisibility' || this._mode === 'assertingValue') + if (this._isRecording()) return; const logs: CallLog[] = []; for (const metadata of metadatas) { @@ -331,6 +374,10 @@ export class Recorder implements InstrumentationListener, IRecorder { this._recorderApp?.updateCallLogs(logs); } + private _isRecording() { + return ['recording', 'assertingText', 'assertingVisibility', 'assertingValue', 'assertingSnapshot'].includes(this._mode); + } + private _readSource(fileName: string): string { try { return fs.readFileSync(fileName, 'utf-8'); diff --git a/packages/playwright-core/src/server/recorder/chat.ts b/packages/playwright-core/src/server/recorder/chat.ts new file mode 100644 index 0000000000..5b3917c735 --- /dev/null +++ b/packages/playwright-core/src/server/recorder/chat.ts @@ -0,0 +1,184 @@ +/** + * 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 { WebSocketTransport } from '../transport'; +import type { ConnectionTransport, ProtocolResponse } from '../transport'; + +export type ChatMessage = { + content: string; + user: 'user' | 'assistant'; +}; + +export class Chat { + private _history: ChatMessage[] = []; + private _connectionPromise: Promise | undefined; + private _chatSinks = new Map void>(); + private _wsEndpoint: string; + + constructor(wsEndpoint: string) { + this._wsEndpoint = wsEndpoint; + } + + clearHistory() { + this._history = []; + } + + async post(prompt: string): Promise { + await this._append('user', prompt); + let text = await asString(await this._post()); + if (text.startsWith('```json') && text.endsWith('```')) + text = text.substring('```json'.length, text.length - '```'.length); + for (let i = 0; i < 3; ++i) { + try { + return JSON.parse(text); + } catch (e) { + await this._append('user', String(e)); + } + } + throw new Error('Failed to parse response: ' + text); + } + + private async _append(user: ChatMessage['user'], content: string) { + this._history.push({ user, content }); + } + + private async _connection(): Promise { + if (!this._connectionPromise) { + this._connectionPromise = WebSocketTransport.connect(undefined, this._wsEndpoint).then(transport => { + return new Connection(transport, (method, params) => this._dispatchEvent(method, params), () => {}); + }); + } + return this._connectionPromise; + } + + private _dispatchEvent(method: string, params: any) { + if (method === 'chatChunk') { + const { chatId, chunk } = params; + const chunkSink = this._chatSinks.get(chatId)!; + chunkSink(chunk); + if (!chunk) + this._chatSinks.delete(chatId); + } + } + + private async _post(): Promise> { + const connection = await this._connection(); + const result = await connection.send('chat', { history: this._history }); + const { chatId } = result; + const { iterable, addChunk } = iterablePump(); + this._chatSinks.set(chatId, addChunk); + return iterable; + } +} + +export async function asString(stream: AsyncIterable): Promise { + let result = ''; + for await (const chunk of stream) + result += chunk; + return result; +} + +type ChunkIterator = { + iterable: AsyncIterable; + addChunk: (chunk: string) => void; +}; + +function iterablePump(): ChunkIterator { + let controller: ReadableStreamDefaultController; + const stream = new ReadableStream({ start: c => controller = c }); + + const iterable = (async function* () { + const reader = stream.getReader(); + while (true) { + const { done, value } = await reader.read(); + if (done) + break; + yield value!; + } + })(); + + return { + iterable, + addChunk: chunk => { + if (chunk) + controller.enqueue(chunk); + else + controller.close(); + } + }; +} + +class Connection { + private readonly _transport: ConnectionTransport; + private _lastId = 0; + private _closed = false; + private _pending = new Map void; reject: (error: any) => void; }>(); + private _onEvent: (method: string, params: any) => void; + private _onClose: () => void; + + constructor(transport: ConnectionTransport, onEvent: (method: string, params: any) => void, onClose: () => void) { + this._transport = transport; + this._onEvent = onEvent; + this._onClose = onClose; + this._transport.onmessage = this._dispatchMessage.bind(this); + this._transport.onclose = this._close.bind(this); + } + + send(method: string, params: any): Promise { + const id = this._lastId++; + const message = { id, method, params }; + this._transport.send(message); + return new Promise((resolve, reject) => { + this._pending.set(id, { resolve, reject }); + }); + } + + private _dispatchMessage(message: ProtocolResponse) { + if (message.id === undefined) { + this._onEvent(message.method!, message.params); + return; + } + + const callback = this._pending.get(message.id); + this._pending.delete(message.id); + if (!callback) + return; + + if (message.error) { + callback.reject(new Error(message.error.message)); + return; + } + callback.resolve(message.result); + } + + _close() { + this._closed = true; + this._transport.onmessage = undefined; + this._transport.onclose = undefined; + for (const { reject } of this._pending.values()) + reject(new Error('Connection closed')); + this._onClose(); + } + + isClosed() { + return this._closed; + } + + close() { + if (!this._closed) + this._transport.close(); + } +} diff --git a/packages/playwright-core/src/server/recorder/contextRecorder.ts b/packages/playwright-core/src/server/recorder/contextRecorder.ts index 933a036233..d7a3c908e8 100644 --- a/packages/playwright-core/src/server/recorder/contextRecorder.ts +++ b/packages/playwright-core/src/server/recorder/contextRecorder.ts @@ -208,6 +208,10 @@ export class ContextRecorder extends EventEmitter { } } + runTask(task: string): void { + // TODO: implement + } + private _describeMainFrame(page: Page): actions.FrameDescription { return { pageAlias: this._pageAliases.get(page)!, diff --git a/packages/playwright-core/src/server/recorder/recorderApp.ts b/packages/playwright-core/src/server/recorder/recorderApp.ts index 6b6b73e241..f8971531cf 100644 --- a/packages/playwright-core/src/server/recorder/recorderApp.ts +++ b/packages/playwright-core/src/server/recorder/recorderApp.ts @@ -88,7 +88,7 @@ export class RecorderApp extends EventEmitter implements IRecorderApp { }); const mainFrame = this._page.mainFrame(); - await mainFrame.goto(serverSideCallMetadata(), 'https://playwright/index.html'); + await mainFrame.goto(serverSideCallMetadata(), process.env.PW_HMR ? 'http://localhost:44225' : 'https://playwright/index.html'); } static factory(context: BrowserContext): IRecorderAppFactory { diff --git a/packages/playwright-core/src/server/recorder/recorderUtils.ts b/packages/playwright-core/src/server/recorder/recorderUtils.ts index c40a6ac201..990ba959d6 100644 --- a/packages/playwright-core/src/server/recorder/recorderUtils.ts +++ b/packages/playwright-core/src/server/recorder/recorderUtils.ts @@ -72,11 +72,11 @@ export async function frameForAction(pageAliases: Map, actionInCon export function callMetadataForAction(pageAliases: Map, actionInContext: actions.ActionInContext): { callMetadata: CallMetadata, mainFrame: Frame } { const mainFrame = mainFrameForAction(pageAliases, actionInContext); - const { method, params } = traceParamsForAction(actionInContext); + const { method, apiName, params } = traceParamsForAction(actionInContext); const callMetadata: CallMetadata = { id: `call@${createGuid()}`, - apiName: 'page.' + method, + apiName, objectId: mainFrame.guid, pageId: mainFrame._page.guid, frameId: mainFrame.guid, diff --git a/packages/playwright-core/src/server/registry/browserFetcher.ts b/packages/playwright-core/src/server/registry/browserFetcher.ts index 6f8da6e825..3a6e36b42d 100644 --- a/packages/playwright-core/src/server/registry/browserFetcher.ts +++ b/packages/playwright-core/src/server/registry/browserFetcher.ts @@ -36,7 +36,7 @@ export async function downloadBrowserWithProgressBar(title: string, browserDirec const zipPath = path.join(os.tmpdir(), downloadFileName); try { - const retryCount = 3; + const retryCount = 5; for (let attempt = 1; attempt <= retryCount; ++attempt) { debugLogger.log('install', `downloading ${title} - attempt #${attempt}`); const url = downloadURLs[(attempt - 1) % downloadURLs.length]; diff --git a/packages/playwright-core/src/server/registry/index.ts b/packages/playwright-core/src/server/registry/index.ts index 2c94b7f381..cd2f2f1d32 100644 --- a/packages/playwright-core/src/server/registry/index.ts +++ b/packages/playwright-core/src/server/registry/index.ts @@ -37,16 +37,23 @@ const PACKAGE_PATH = path.join(__dirname, '..', '..', '..'); const BIN_PATH = path.join(__dirname, '..', '..', '..', 'bin'); const PLAYWRIGHT_CDN_MIRRORS = [ + 'https://playwright.azureedge.net/dbazure/download/playwright', // ESRP CDN + 'https://playwright.download.prss.microsoft.com/dbazure/download/playwright', // Directly hit ESRP CDN + + // Old endpoints which hit the Storage Bucket directly: 'https://playwright.azureedge.net', - 'https://playwright-akamai.azureedge.net', - 'https://playwright-verizon.azureedge.net', + 'https://playwright-akamai.azureedge.net', // Actually Edgio which will be retired Q4 2025. + 'https://playwright-verizon.azureedge.net', // Actually Edgio which will be retired Q4 2025. ]; if (process.env.PW_TEST_CDN_THAT_SHOULD_WORK) { for (let i = 0; i < PLAYWRIGHT_CDN_MIRRORS.length; i++) { const cdn = PLAYWRIGHT_CDN_MIRRORS[i]; - if (cdn !== process.env.PW_TEST_CDN_THAT_SHOULD_WORK) - PLAYWRIGHT_CDN_MIRRORS[i] = cdn + '.does-not-resolve.playwright.dev'; + if (cdn !== process.env.PW_TEST_CDN_THAT_SHOULD_WORK) { + const parsedCDN = new URL(cdn); + parsedCDN.hostname = parsedCDN.hostname + '.does-not-resolve.playwright.dev'; + PLAYWRIGHT_CDN_MIRRORS[i] = parsedCDN.toString(); + } } } @@ -352,7 +359,7 @@ export const registryDirectory = (() => { function isBrowserDirectory(browserDirectory: string): boolean { const baseName = path.basename(browserDirectory); for (const browserName of allDownloadable) { - if (baseName.startsWith(browserName + '-')) + if (baseName.startsWith(browserName.replace(/-/g, '_') + '-')) return true; } return false; @@ -403,10 +410,10 @@ function readDescriptors(browsersJSON: BrowsersJSON): BrowsersJSONDescriptor[] { } export type BrowserName = 'chromium' | 'firefox' | 'webkit' | 'bidi'; -type InternalTool = 'ffmpeg' | 'firefox-beta' | 'chromium-tip-of-tree' | 'chromium-headless-shell' |'android'; +type InternalTool = 'ffmpeg' | 'firefox-beta' | 'chromium-tip-of-tree' | 'chromium-headless-shell' | 'android'; type BidiChannel = 'bidi-firefox-stable' | 'bidi-firefox-beta' | 'bidi-firefox-nightly' | 'bidi-chrome-canary' | 'bidi-chrome-stable' | 'bidi-chromium'; type ChromiumChannel = 'chrome' | 'chrome-beta' | 'chrome-dev' | 'chrome-canary' | 'msedge' | 'msedge-beta' | 'msedge-dev' | 'msedge-canary'; -const allDownloadable = ['chromium', 'firefox', 'webkit', 'ffmpeg', 'firefox-beta', 'chromium-tip-of-tree', 'chromium-headless-shell']; +const allDownloadable = ['android', 'chromium', 'firefox', 'webkit', 'ffmpeg', 'firefox-beta', 'chromium-tip-of-tree', 'chromium-headless-shell']; export interface Executable { type: 'browser' | 'tool' | 'channel'; @@ -489,27 +496,20 @@ export class Registry { _isHermeticInstallation: true, }); - const chromiumHeadlessShellDescriptor: BrowsersJSONDescriptor = { - name: 'chromium-headless-shell', - revision: chromium.revision, - browserVersion: chromium.browserVersion, - dir: chromium.dir.replace(/(.*)(-\d+)$/, '$1-headless-shell$2'), - installByDefault: false, - hasRevisionOverride: false, - }; - const chromiumHeadlessShellExecutable = findExecutablePath(chromiumHeadlessShellDescriptor.dir, 'chromium-headless-shell'); + const chromiumHeadlessShell = descriptors.find(d => d.name === 'chromium-headless-shell')!; + const chromiumHeadlessShellExecutable = findExecutablePath(chromiumHeadlessShell.dir, 'chromium-headless-shell'); this._executables.push({ - type: 'tool', + type: 'channel', name: 'chromium-headless-shell', browserName: 'chromium', - directory: chromiumHeadlessShellDescriptor.dir, + directory: chromiumHeadlessShell.dir, executablePath: () => chromiumHeadlessShellExecutable, - executablePathOrDie: (sdkLanguage: string) => executablePathOrDie('chromium-headless-shell', chromiumHeadlessShellExecutable, false, sdkLanguage), - installType: 'download-on-demand', - _validateHostRequirements: (sdkLanguage: string) => this._validateHostRequirements(sdkLanguage, chromiumHeadlessShellDescriptor.dir, ['chrome-linux'], [], ['chrome-win']), - downloadURLs: this._downloadURLs(chromiumHeadlessShellDescriptor), + executablePathOrDie: (sdkLanguage: string) => executablePathOrDie('chromium', chromiumHeadlessShellExecutable, chromiumHeadlessShell.installByDefault, sdkLanguage), + installType: chromiumHeadlessShell.installByDefault ? 'download-by-default' : 'download-on-demand', + _validateHostRequirements: (sdkLanguage: string) => this._validateHostRequirements(sdkLanguage, chromiumHeadlessShell.dir, ['chrome-linux'], [], ['chrome-win']), + downloadURLs: this._downloadURLs(chromiumHeadlessShell), browserVersion: chromium.browserVersion, - _install: () => this._downloadExecutable(chromiumHeadlessShellDescriptor, chromiumHeadlessShellExecutable), + _install: () => this._downloadExecutable(chromiumHeadlessShell, chromiumHeadlessShellExecutable), _dependencyGroup: 'chromium', _isHermeticInstallation: true, }); @@ -886,14 +886,8 @@ export class Registry { return this._executables.filter(e => e.installType === 'download-by-default'); } - private _addRequirementsAndDedupe(executables: Executable[]): ExecutableImpl[] { - const set = new Set(); - for (const executable of executables as ExecutableImpl[]) { - set.add(executable); - if (executable.browserName === 'chromium') - set.add(this.findExecutable('ffmpeg')!); - } - return Array.from(set); + private _dedupe(executables: Executable[]): ExecutableImpl[] { + return Array.from(new Set(executables as ExecutableImpl[])); } private async _validateHostRequirements(sdkLanguage: string, browserDirectory: string, linuxLddDirectories: string[], dlOpenLibraries: string[], windowsExeAndDllDirectories: string[]) { @@ -904,7 +898,7 @@ export class Registry { } async installDeps(executablesToInstallDeps: Executable[], dryRun: boolean) { - const executables = this._addRequirementsAndDedupe(executablesToInstallDeps); + const executables = this._dedupe(executablesToInstallDeps); const targets = new Set(); for (const executable of executables) { if (executable._dependencyGroup) @@ -918,7 +912,7 @@ export class Registry { } async install(executablesToInstall: Executable[], forceReinstall: boolean) { - const executables = this._addRequirementsAndDedupe(executablesToInstall); + const executables = this._dedupe(executablesToInstall); await fs.promises.mkdir(registryDirectory, { recursive: true }); const lockfilePath = path.join(registryDirectory, '__dirlock'); const linksDir = path.join(registryDirectory, '.links'); @@ -1214,11 +1208,6 @@ export function buildPlaywrightCLICommand(sdkLanguage: string, parameters: strin } } -export async function installDefaultBrowsersForNpmInstall() { - const defaultBrowserNames = registry.defaultExecutables().map(e => e.name); - return installBrowsersForNpmInstall(defaultBrowserNames); -} - export async function installBrowsersForNpmInstall(browsers: string[]) { // PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD should have a value of 0 or 1 if (getAsBooleanFromENV('PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD')) { diff --git a/packages/playwright-core/src/server/trace/recorder/snapshotterInjected.ts b/packages/playwright-core/src/server/trace/recorder/snapshotterInjected.ts index 47385c8323..0400c6deaf 100644 --- a/packages/playwright-core/src/server/trace/recorder/snapshotterInjected.ts +++ b/packages/playwright-core/src/server/trace/recorder/snapshotterInjected.ts @@ -47,6 +47,7 @@ export function frameSnapshotStreamer(snapshotStreamer: string, removeNoScript: const kTargetAttribute = '__playwright_target__'; const kCustomElementsAttribute = '__playwright_custom_elements__'; const kCurrentSrcAttribute = '__playwright_current_src__'; + const kBoundingRectAttribute = '__playwright_bounding_rect__'; // Symbols for our own info on Nodes/StyleSheets. const kSnapshotFrameId = Symbol('__playwright_snapshot_frameid_'); @@ -436,6 +437,18 @@ export function frameSnapshotStreamer(snapshotStreamer: string, removeNoScript: expectValue(value); attrs[kSelectedAttribute] = value; } + if (nodeName === 'CANVAS') { + const boundingRect = (element as HTMLCanvasElement).getBoundingClientRect(); + const value = JSON.stringify({ + left: boundingRect.left / window.innerWidth, + top: boundingRect.top / window.innerHeight, + right: boundingRect.right / window.innerWidth, + bottom: boundingRect.bottom / window.innerHeight + }); + expectValue(kBoundingRectAttribute); + expectValue(value); + attrs[kBoundingRectAttribute] = value; + } if (element.scrollTop) { expectValue(kScrollTopAttribute); expectValue(element.scrollTop); diff --git a/packages/playwright-core/src/server/trace/recorder/tracing.ts b/packages/playwright-core/src/server/trace/recorder/tracing.ts index 97476d4b31..c19c0a33d9 100644 --- a/packages/playwright-core/src/server/trace/recorder/tracing.ts +++ b/packages/playwright-core/src/server/trace/recorder/tracing.ts @@ -18,7 +18,7 @@ import fs from 'fs'; import os from 'os'; import path from 'path'; import type { NameValue } from '../../../common/types'; -import type { TracingTracingStopChunkParams } from '@protocol/channels'; +import type { TracingTracingStopChunkParams, StackFrame } from '@protocol/channels'; import { commandsWithTracingSnapshots } from '../../../protocol/debug'; import { assert, createGuid, monotonicTime, SerializedFS, removeFolders, eventsHelper, type RegisteredListener } from '../../../utils'; import { Artifact } from '../../artifact'; @@ -61,6 +61,7 @@ type RecordingState = { traceSha1s: Set, recording: boolean; callIds: Set; + groupStack: string[]; }; const kScreencastOptions = { width: 800, height: 600, quality: 90 }; @@ -148,6 +149,7 @@ export class Tracing extends SdkObject implements InstrumentationListener, Snaps networkSha1s: new Set(), recording: false, callIds: new Set(), + groupStack: [], }; this._fs.mkdir(this._state.resourcesDir); this._fs.writeFile(this._state.networkFile, ''); @@ -194,6 +196,53 @@ export class Tracing extends SdkObject implements InstrumentationListener, Snaps return { traceName: this._state.traceName }; } + private _currentGroupId(): string | undefined { + return this._state?.groupStack.length ? this._state.groupStack[this._state.groupStack.length - 1] : undefined; + } + + async group(name: string, location: { file: string, line?: number, column?: number } | undefined, metadata: CallMetadata): Promise { + if (!this._state) + return; + const stackFrames: StackFrame[] = []; + const { file, line, column } = location ?? metadata.location ?? {}; + if (file) { + stackFrames.push({ + file, + line: line ?? 0, + column: column ?? 0, + }); + } + const event: trace.BeforeActionTraceEvent = { + type: 'before', + callId: metadata.id, + startTime: metadata.startTime, + apiName: name, + class: 'Tracing', + method: 'tracingGroup', + params: { }, + stepId: metadata.stepId, + stack: stackFrames, + }; + if (this._currentGroupId()) + event.parentId = this._currentGroupId(); + this._state.groupStack.push(event.callId); + this._appendTraceEvent(event); + } + + groupEnd() { + if (!this._state) + return; + const callId = this._state.groupStack.pop(); + if (!callId) + return; + const event: trace.AfterActionTraceEvent = { + type: 'after', + callId, + endTime: monotonicTime(), + }; + this._appendTraceEvent(event); + } + private _startScreencast() { if (!(this._context instanceof BrowserContext)) return; @@ -236,6 +285,7 @@ export class Tracing extends SdkObject implements InstrumentationListener, Snaps throw new Error(`Tracing is already stopping`); if (this._state.recording) throw new Error(`Must stop trace file before stopping tracing`); + this._closeAllGroups(); this._harTracer.stop(); this.flushHarEntries(); await this._fs.syncAndGetError(); @@ -264,6 +314,11 @@ export class Tracing extends SdkObject implements InstrumentationListener, Snaps await this._fs.syncAndGetError(); } + private _closeAllGroups() { + while (this._currentGroupId()) + this.groupEnd(); + } + async stopChunk(params: TracingTracingStopChunkParams): Promise<{ artifact?: Artifact, entries?: NameValue[] }> { if (this._isStopping) throw new Error(`Tracing is already stopping`); @@ -276,6 +331,8 @@ export class Tracing extends SdkObject implements InstrumentationListener, Snaps return {}; } + this._closeAllGroups(); + this._context.instrumentation.removeListener(this); eventsHelper.removeEventListeners(this._eventListeners); if (this._state.options.screenshots) @@ -354,7 +411,7 @@ export class Tracing extends SdkObject implements InstrumentationListener, Snaps onBeforeCall(sdkObject: SdkObject, metadata: CallMetadata) { // IMPORTANT: no awaits before this._appendTraceEvent in this method. - const event = createBeforeActionTraceEvent(metadata); + const event = createBeforeActionTraceEvent(metadata, this._currentGroupId()); if (!event) return Promise.resolve(); sdkObject.attribution.page?.temporarilyDisableTracingScreencastThrottling(); @@ -571,10 +628,10 @@ export function shouldCaptureSnapshot(metadata: CallMetadata): boolean { return commandsWithTracingSnapshots.has(metadata.type + '.' + metadata.method); } -function createBeforeActionTraceEvent(metadata: CallMetadata): trace.BeforeActionTraceEvent | null { +function createBeforeActionTraceEvent(metadata: CallMetadata, parentId?: string): trace.BeforeActionTraceEvent | null { if (metadata.internal || metadata.method.startsWith('tracing')) return null; - return { + const event: trace.BeforeActionTraceEvent = { type: 'before', callId: metadata.id, startTime: metadata.startTime, @@ -585,6 +642,9 @@ function createBeforeActionTraceEvent(metadata: CallMetadata): trace.BeforeActio stepId: metadata.stepId, pageId: metadata.pageId, }; + if (parentId) + event.parentId = parentId; + return event; } function createInputActionTraceEvent(metadata: CallMetadata): trace.InputActionTraceEvent | null { diff --git a/packages/playwright-core/src/server/webkit/wkBrowser.ts b/packages/playwright-core/src/server/webkit/wkBrowser.ts index c9bda10ddd..f4f9f732a5 100644 --- a/packages/playwright-core/src/server/webkit/wkBrowser.ts +++ b/packages/playwright-core/src/server/webkit/wkBrowser.ts @@ -31,8 +31,8 @@ import { WKPage } from './wkPage'; import { TargetClosedError } from '../errors'; import type { SdkObject } from '../instrumentation'; -const DEFAULT_USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Safari/605.1.15'; -const BROWSER_VERSION = '18.0'; +const DEFAULT_USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Safari/605.1.15'; +const BROWSER_VERSION = '18.2'; export class WKBrowser extends Browser { private readonly _connection: WKConnection; diff --git a/packages/playwright-core/src/server/webkit/wkPage.ts b/packages/playwright-core/src/server/webkit/wkPage.ts index 0bd82ed338..13096075f7 100644 --- a/packages/playwright-core/src/server/webkit/wkPage.ts +++ b/packages/playwright-core/src/server/webkit/wkPage.ts @@ -16,7 +16,6 @@ */ import path from 'path'; -import os from 'os'; import { PNG, jpegjs } from '../../utilsBundle'; import { splitErrorMessage } from '../../utils/stackTrace'; import { assert, createGuid, debugAssert, headersArrayToObject } from '../../utils'; @@ -715,12 +714,7 @@ export class WKPage implements PageDelegate { ]; if (options.isMobile) { const angle = viewportSize.width > viewportSize.height ? 90 : 0; - // Special handling for macOS 12. - const useLegacySetOrientationOverrideMethod = os.platform() === 'darwin' && parseInt(os.release().split('.')[0], 10) <= 21; - if (useLegacySetOrientationOverrideMethod) - promises.push(this._session.send('Page.setOrientationOverride' as any, { angle })); - else - promises.push(this._pageProxySession.send('Emulation.setOrientationOverride', { angle })); + promises.push(this._pageProxySession.send('Emulation.setOrientationOverride', { angle })); } await Promise.all(promises); } diff --git a/packages/playwright-core/src/utils/comparators.ts b/packages/playwright-core/src/utils/comparators.ts index da707e20c4..acf897af49 100644 --- a/packages/playwright-core/src/utils/comparators.ts +++ b/packages/playwright-core/src/utils/comparators.ts @@ -16,9 +16,10 @@ */ import { colors, jpegjs } from '../utilsBundle'; -const pixelmatch = require('../third_party/pixelmatch'); +// @ts-ignore +import pixelmatch from '../third_party/pixelmatch'; import { compare } from '../image_tools/compare'; -const { diffMatchPatch } = require('../utilsBundle'); +import { diff } from '../utilsBundle'; import { PNG } from '../utilsBundle'; export type ImageComparatorOptions = { threshold?: number, maxDiffPixels?: number, maxDiffPixelRatio?: number, comparator?: string }; @@ -106,40 +107,28 @@ function validateBuffer(buffer: Buffer, mimeType: string): void { } function compareText(actual: Buffer | string, expectedBuffer: Buffer): ComparatorResult { - const { diff_match_patch } = diffMatchPatch; if (typeof actual !== 'string') return { errorMessage: 'Actual result should be a string' }; const expected = expectedBuffer.toString('utf-8'); if (expected === actual) return null; - const dmp = new diff_match_patch(); - const d = dmp.diff_main(expected, actual); - dmp.diff_cleanupSemantic(d); + const diffs = diff.diffChars(expected, actual); return { - errorMessage: diff_prettyTerminal(d) + errorMessage: diff_prettyTerminal(diffs), }; } -function diff_prettyTerminal(diffs: [number, string][]) { - const { DIFF_INSERT, DIFF_DELETE, DIFF_EQUAL } = diffMatchPatch; - const html = []; - for (let x = 0; x < diffs.length; x++) { - const op = diffs[x][0]; // Operation (insert, delete, equal) - const data = diffs[x][1]; // Text of change. - const text = data; - switch (op) { - case DIFF_INSERT: - html[x] = colors.green(text); - break; - case DIFF_DELETE: - html[x] = colors.reset(colors.strikethrough(colors.red(text))); - break; - case DIFF_EQUAL: - html[x] = text; - break; - } - } - return html.join(''); +function diff_prettyTerminal(diffs: Diff.Change[]): string { + const result = diffs.map(part => { + const text = part.value; + if (part.added) + return colors.green(text); + else if (part.removed) + return colors.reset(colors.strikethrough(colors.red(text))); + else + return text; + }); + return result.join(''); } function resizeImage(image: ImageData, size: { width: number, height: number }): ImageData { diff --git a/packages/playwright-core/src/utils/debugLogger.ts b/packages/playwright-core/src/utils/debugLogger.ts index a5196da896..d50180a2ed 100644 --- a/packages/playwright-core/src/utils/debugLogger.ts +++ b/packages/playwright-core/src/utils/debugLogger.ts @@ -29,7 +29,8 @@ const debugLoggerColorMap = { 'channel': 33, // blue 'server': 45, // cyan 'server:channel': 34, // green - 'server:metadata': 33, // blue + 'server:metadata': 33, // blue, + 'recorder': 45, // cyan }; export type LogName = keyof typeof debugLoggerColorMap; diff --git a/packages/playwright-core/src/utils/hostPlatform.ts b/packages/playwright-core/src/utils/hostPlatform.ts index 9664418e3d..7d81f39da3 100644 --- a/packages/playwright-core/src/utils/hostPlatform.ts +++ b/packages/playwright-core/src/utils/hostPlatform.ts @@ -35,6 +35,12 @@ export type HostPlatform = 'win64' | ''; function calculatePlatform(): { hostPlatform: HostPlatform, isOfficiallySupportedPlatform: boolean } { + if (process.env.PLAYWRIGHT_HOST_PLATFORM_OVERRIDE) { + return { + hostPlatform: process.env.PLAYWRIGHT_HOST_PLATFORM_OVERRIDE as HostPlatform, + isOfficiallySupportedPlatform: false + }; + } const platform = os.platform(); if (platform === 'darwin') { const ver = os.release().split('.').map((a: string) => parseInt(a, 10)); diff --git a/packages/playwright-core/src/utils/index.ts b/packages/playwright-core/src/utils/index.ts index c570e7b32e..0bc7a75b08 100644 --- a/packages/playwright-core/src/utils/index.ts +++ b/packages/playwright-core/src/utils/index.ts @@ -33,7 +33,6 @@ export * from './isomorphic/stringUtils'; export * from './isomorphic/urlMatch'; export * from './multimap'; export * from './network'; -export * from './patch'; export * from './processLauncher'; export * from './profiler'; export * from './rtti'; diff --git a/packages/playwright-core/src/utils/isomorphic/ariaSnapshot.ts b/packages/playwright-core/src/utils/isomorphic/ariaSnapshot.ts new file mode 100644 index 0000000000..67db465149 --- /dev/null +++ b/packages/playwright-core/src/utils/isomorphic/ariaSnapshot.ts @@ -0,0 +1,324 @@ +/** + * 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. + */ + +// https://www.w3.org/TR/wai-aria-1.2/#role_definitions + +export type AriaRole = 'alert' | 'alertdialog' | 'application' | 'article' | 'banner' | 'blockquote' | 'button' | 'caption' | 'cell' | 'checkbox' | 'code' | 'columnheader' | 'combobox' | + 'complementary' | 'contentinfo' | 'definition' | 'deletion' | 'dialog' | 'directory' | 'document' | 'emphasis' | 'feed' | 'figure' | 'form' | 'generic' | 'grid' | + 'gridcell' | 'group' | 'heading' | 'img' | 'insertion' | 'link' | 'list' | 'listbox' | 'listitem' | 'log' | 'main' | 'mark' | 'marquee' | 'math' | 'meter' | 'menu' | + 'menubar' | 'menuitem' | 'menuitemcheckbox' | 'menuitemradio' | 'navigation' | 'none' | 'note' | 'option' | 'paragraph' | 'presentation' | 'progressbar' | 'radio' | 'radiogroup' | + 'region' | 'row' | 'rowgroup' | 'rowheader' | 'scrollbar' | 'search' | 'searchbox' | 'separator' | 'slider' | + 'spinbutton' | 'status' | 'strong' | 'subscript' | 'superscript' | 'switch' | 'tab' | 'table' | 'tablist' | 'tabpanel' | 'term' | 'textbox' | 'time' | 'timer' | + 'toolbar' | 'tooltip' | 'tree' | 'treegrid' | 'treeitem'; + +export type ParsedYaml = Array; + +export type AriaProps = { + checked?: boolean | 'mixed'; + disabled?: boolean; + expanded?: boolean; + level?: number; + pressed?: boolean | 'mixed'; + selected?: boolean; +}; + +export type AriaTemplateTextNode = { + kind: 'text'; + text: RegExp | string; +}; + +export type AriaTemplateRoleNode = AriaProps & { + kind: 'role'; + role: AriaRole | 'fragment'; + name?: RegExp | string; + children?: AriaTemplateNode[]; +}; + +export type AriaTemplateNode = AriaTemplateRoleNode | AriaTemplateTextNode; + +export function parseYamlTemplate(fragment: ParsedYaml): AriaTemplateNode { + const result: AriaTemplateNode = { kind: 'role', role: 'fragment' }; + populateNode(result, fragment); + if (result.children && result.children.length === 1) + return result.children[0]; + return result; +} + +function populateNode(node: AriaTemplateRoleNode, container: ParsedYaml) { + for (const object of container) { + if (typeof object === 'string') { + const childNode = KeyParser.parse(object); + node.children = node.children || []; + node.children.push(childNode); + continue; + } + + for (const key of Object.keys(object)) { + node.children = node.children || []; + const value = object[key]; + + if (key === 'text') { + node.children.push({ + kind: 'text', + text: valueOrRegex(value) + }); + continue; + } + + const childNode = KeyParser.parse(key); + if (childNode.kind === 'text') { + node.children.push({ + kind: 'text', + text: valueOrRegex(value) + }); + continue; + } + + if (typeof value === 'string') { + node.children.push({ + ...childNode, children: [{ + kind: 'text', + text: valueOrRegex(value) + }] + }); + continue; + } + + node.children.push(childNode); + populateNode(childNode, value); + } + } +} + +function normalizeWhitespace(text: string) { + return text.replace(/[\r\n\s\t]+/g, ' ').trim(); +} + +function valueOrRegex(value: string): string | RegExp { + return value.startsWith('/') && value.endsWith('/') ? new RegExp(value.slice(1, -1)) : normalizeWhitespace(value); +} + +class KeyParser { + private _input: string; + private _pos: number; + private _length: number; + + static parse(input: string): AriaTemplateNode { + return new KeyParser(input)._parse(); + } + + constructor(input: string) { + this._input = input; + this._pos = 0; + this._length = input.length; + } + + private _peek() { + return this._input[this._pos] || ''; + } + + private _next() { + if (this._pos < this._length) + return this._input[this._pos++]; + return null; + } + + private _eof() { + return this._pos >= this._length; + } + + private _isWhitespace() { + return !this._eof() && /\s/.test(this._peek()); + } + + private _skipWhitespace() { + while (this._isWhitespace()) + this._pos++; + } + + private _readIdentifier(type: 'role' | 'attribute'): string { + if (this._eof()) + this._throwError(`Unexpected end of input when expecting ${type}`); + const start = this._pos; + while (!this._eof() && /[a-zA-Z]/.test(this._peek())) + this._pos++; + return this._input.slice(start, this._pos); + } + + private _readString(): string { + let result = ''; + let escaped = false; + while (!this._eof()) { + const ch = this._next(); + if (escaped) { + result += ch; + escaped = false; + } else if (ch === '\\') { + escaped = true; + } else if (ch === '"') { + return result; + } else { + result += ch; + } + } + this._throwError('Unterminated string'); + } + + private _throwError(message: string, pos?: number): never { + throw new AriaKeyError(message, this._input, pos || this._pos); + } + + private _readRegex(): string { + let result = ''; + let escaped = false; + let insideClass = false; + while (!this._eof()) { + const ch = this._next(); + if (escaped) { + result += ch; + escaped = false; + } else if (ch === '\\') { + escaped = true; + result += ch; + } else if (ch === '/' && !insideClass) { + return result; + } else if (ch === '[') { + insideClass = true; + result += ch; + } else if (ch === ']' && insideClass) { + result += ch; + insideClass = false; + } else { + result += ch; + } + } + this._throwError('Unterminated regex'); + } + + private _readStringOrRegex(): string | RegExp | null { + const ch = this._peek(); + if (ch === '"') { + this._next(); + return this._readString(); + } + + if (ch === '/') { + this._next(); + return new RegExp(this._readRegex()); + } + + return null; + } + + private _readAttributes(result: AriaTemplateRoleNode) { + let errorPos = this._pos; + while (true) { + this._skipWhitespace(); + if (this._peek() === '[') { + this._next(); + this._skipWhitespace(); + errorPos = this._pos; + const flagName = this._readIdentifier('attribute'); + this._skipWhitespace(); + let flagValue = ''; + if (this._peek() === '=') { + this._next(); + this._skipWhitespace(); + errorPos = this._pos; + while (this._peek() !== ']' && !this._isWhitespace() && !this._eof()) + flagValue += this._next(); + } + this._skipWhitespace(); + if (this._peek() !== ']') + this._throwError('Expected ]'); + + this._next(); // Consume ']' + this._applyAttribute(result, flagName, flagValue || 'true', errorPos); + } else { + break; + } + } + } + + _parse(): AriaTemplateNode { + this._skipWhitespace(); + + const role = this._readIdentifier('role') as AriaTemplateRoleNode['role']; + this._skipWhitespace(); + const name = this._readStringOrRegex() || ''; + const result: AriaTemplateRoleNode = { kind: 'role', role, name }; + this._readAttributes(result); + this._skipWhitespace(); + if (!this._eof()) + this._throwError('Unexpected input'); + return result; + } + + private _applyAttribute(node: AriaTemplateRoleNode, key: string, value: string, errorPos: number) { + if (key === 'checked') { + this._assert(value === 'true' || value === 'false' || value === 'mixed', 'Value of "checked\" attribute must be a boolean or "mixed"', errorPos); + node.checked = value === 'true' ? true : value === 'false' ? false : 'mixed'; + return; + } + if (key === 'disabled') { + this._assert(value === 'true' || value === 'false', 'Value of "disabled" attribute must be a boolean', errorPos); + node.disabled = value === 'true'; + return; + } + if (key === 'expanded') { + this._assert(value === 'true' || value === 'false', 'Value of "expanded" attribute must be a boolean', errorPos); + node.expanded = value === 'true'; + return; + } + if (key === 'level') { + this._assert(!isNaN(Number(value)), 'Value of "level" attribute must be a number', errorPos); + node.level = Number(value); + return; + } + if (key === 'pressed') { + this._assert(value === 'true' || value === 'false' || value === 'mixed', 'Value of "pressed" attribute must be a boolean or "mixed"', errorPos); + node.pressed = value === 'true' ? true : value === 'false' ? false : 'mixed'; + return; + } + if (key === 'selected') { + this._assert(value === 'true' || value === 'false', 'Value of "selected" attribute must be a boolean', errorPos); + node.selected = value === 'true'; + return; + } + this._assert(false, `Unsupported attribute [${key}]`, errorPos); + } + + private _assert(value: any, message: string, valuePos: number): asserts value { + if (!value) + this._throwError(message || 'Assertion error', valuePos); + } +} + +export function parseAriaKey(key: string) { + return KeyParser.parse(key); +} + +export class AriaKeyError extends Error { + readonly shortMessage: string; + readonly pos: number; + + constructor(message: string, input: string, pos: number) { + super(message + ':\n\n' + input + '\n' + ' '.repeat(pos) + '^\n'); + this.shortMessage = message; + this.pos = pos; + this.stack = undefined; + } +} diff --git a/packages/playwright-core/src/utils/isomorphic/recorderUtils.ts b/packages/playwright-core/src/utils/isomorphic/recorderUtils.ts index b859edf11d..7ef45e5ece 100644 --- a/packages/playwright-core/src/utils/isomorphic/recorderUtils.ts +++ b/packages/playwright-core/src/utils/isomorphic/recorderUtils.ts @@ -24,7 +24,7 @@ export function buildFullSelector(framePath: string[], selector: string) { const kDefaultTimeout = 5_000; -export function traceParamsForAction(actionInContext: recorderActions.ActionInContext): { method: string, params: any } { +export function traceParamsForAction(actionInContext: recorderActions.ActionInContext): { method: string, apiName: string, params: any } { const { action } = actionInContext; switch (action.name) { @@ -32,7 +32,7 @@ export function traceParamsForAction(actionInContext: recorderActions.ActionInCo const params: channels.FrameGotoParams = { url: action.url, }; - return { method: 'goto', params }; + return { method: 'goto', apiName: 'page.goto', params }; } case 'openPage': case 'closePage': @@ -50,7 +50,7 @@ export function traceParamsForAction(actionInContext: recorderActions.ActionInCo clickCount: action.clickCount, position: action.position, }; - return { method: 'click', params }; + return { method: 'click', apiName: 'locator.click', params }; } case 'press': { const params: channels.FramePressParams = { @@ -58,7 +58,7 @@ export function traceParamsForAction(actionInContext: recorderActions.ActionInCo strict: true, key: [...toKeyboardModifiers(action.modifiers), action.key].join('+'), }; - return { method: 'press', params }; + return { method: 'press', apiName: 'locator.press', params }; } case 'fill': { const params: channels.FrameFillParams = { @@ -66,7 +66,7 @@ export function traceParamsForAction(actionInContext: recorderActions.ActionInCo strict: true, value: action.text, }; - return { method: 'fill', params }; + return { method: 'fill', apiName: 'locator.fill', params }; } case 'setInputFiles': { const params: channels.FrameSetInputFilesParams = { @@ -74,21 +74,21 @@ export function traceParamsForAction(actionInContext: recorderActions.ActionInCo strict: true, localPaths: action.files, }; - return { method: 'setInputFiles', params }; + return { method: 'setInputFiles', apiName: 'locator.setInputFiles', params }; } case 'check': { const params: channels.FrameCheckParams = { selector, strict: true, }; - return { method: 'check', params }; + return { method: 'check', apiName: 'locator.check', params }; } case 'uncheck': { const params: channels.FrameUncheckParams = { selector, strict: true, }; - return { method: 'uncheck', params }; + return { method: 'uncheck', apiName: 'locator.uncheck', params }; } case 'select': { const params: channels.FrameSelectOptionParams = { @@ -96,7 +96,7 @@ export function traceParamsForAction(actionInContext: recorderActions.ActionInCo strict: true, options: action.options.map(option => ({ value: option })), }; - return { method: 'selectOption', params }; + return { method: 'selectOption', apiName: 'locator.selectOption', params }; } case 'assertChecked': { const params: channels.FrameExpectParams = { @@ -105,7 +105,7 @@ export function traceParamsForAction(actionInContext: recorderActions.ActionInCo isNot: !action.checked, timeout: kDefaultTimeout, }; - return { method: 'expect', params }; + return { method: 'expect', apiName: 'expect.toBeChecked', params }; } case 'assertText': { const params: channels.FrameExpectParams = { @@ -115,7 +115,7 @@ export function traceParamsForAction(actionInContext: recorderActions.ActionInCo isNot: false, timeout: kDefaultTimeout, }; - return { method: 'expect', params }; + return { method: 'expect', apiName: 'expect.toContainText', params }; } case 'assertValue': { const params: channels.FrameExpectParams = { @@ -125,7 +125,7 @@ export function traceParamsForAction(actionInContext: recorderActions.ActionInCo isNot: false, timeout: kDefaultTimeout, }; - return { method: 'expect', params }; + return { method: 'expect', apiName: 'expect.toHaveValue', params }; } case 'assertVisible': { const params: channels.FrameExpectParams = { @@ -134,7 +134,7 @@ export function traceParamsForAction(actionInContext: recorderActions.ActionInCo isNot: false, timeout: kDefaultTimeout, }; - return { method: 'expect', params }; + return { method: 'expect', apiName: 'expect.toBeVisible', params }; } case 'assertSnapshot': { const params: channels.FrameExpectParams = { @@ -144,7 +144,7 @@ export function traceParamsForAction(actionInContext: recorderActions.ActionInCo isNot: false, timeout: kDefaultTimeout, }; - return { method: 'expect', params }; + return { method: 'expect', apiName: 'expect.toMatchAriaSnapshot', params }; } } } diff --git a/packages/playwright-core/src/utils/isomorphic/urlMatch.ts b/packages/playwright-core/src/utils/isomorphic/urlMatch.ts index b20d47d220..f5d6efb70d 100644 --- a/packages/playwright-core/src/utils/isomorphic/urlMatch.ts +++ b/packages/playwright-core/src/utils/isomorphic/urlMatch.ts @@ -97,8 +97,12 @@ export function urlMatchesEqual(match1: URLMatch, match2: URLMatch) { export function urlMatches(baseURL: string | undefined, urlString: string, match: URLMatch | undefined): boolean { if (match === undefined || match === '') return true; - if (isString(match) && !match.startsWith('*')) + if (isString(match) && !match.startsWith('*')) { + // Allow http(s) baseURL to match ws(s) urls. + if (baseURL && /^https?:\/\//.test(baseURL) && /^wss?:\/\//.test(urlString)) + baseURL = baseURL.replace(/^http/, 'ws'); match = constructURLBasedOnBaseURL(baseURL, match); + } if (isString(match)) match = globToRegex(match); if (isRegExp(match)) diff --git a/packages/playwright-core/src/utils/patch.ts b/packages/playwright-core/src/utils/patch.ts deleted file mode 100644 index 91fa31b8f3..0000000000 --- a/packages/playwright-core/src/utils/patch.ts +++ /dev/null @@ -1,127 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { diffMatchPatch } from '../utilsBundle'; - -type Hunk = { - lines: string[]; - startNew: number; - startOld: number; - contextBefore: number; - contextAfter: number; -}; - -export function generateUnifiedDiff(text1: string, text2: string, relativeName: string = 'file'): string { - const { diff_match_patch, DIFF_EQUAL, DIFF_DELETE, DIFF_INSERT } = diffMatchPatch; - const dmp = new diff_match_patch(); - - const a = text1.replace(/\r\n/g, '\n'); - const b = text2.replace(/\r\n/g, '\n'); - - const { chars1, chars2, lineArray } = dmp.diff_linesToChars_(a, b); - const diffs = dmp.diff_main(chars1, chars2, false); - dmp.diff_charsToLines_(diffs, lineArray); - - const contextSize = 3; - const hunks: Hunk[] = []; - let lineOld = 1; - let lineNew = 1; - let hunk: Hunk | null = null; - let contextBuffer: string[] = []; - - for (const diff of diffs) { - const op = diff[0]; - const data = diff[1]; - const lines = data.split('\n'); - - // Remove the last empty line if data ends with '\n' - if (lines[lines.length - 1] === '') - lines.pop(); - - for (const line of lines) { - if (op === DIFF_EQUAL) { - if (hunk) { - hunk.lines.push(' ' + line); - hunk.contextAfter++; - - if (hunk.contextAfter >= contextSize) { - // Close the hunk - hunks.push(hunk); - hunk = null; - contextBuffer = []; - } - } else { - contextBuffer.push(' ' + line); - if (contextBuffer.length > contextSize) - contextBuffer.shift(); - } - lineOld++; - lineNew++; - } else { - if (!hunk) { - // Start a new hunk - const hunkStartOld = lineOld - contextBuffer.length; - const hunkStartNew = lineNew - contextBuffer.length; - hunk = { - startOld: hunkStartOld, - startNew: hunkStartNew, - lines: [...contextBuffer], - contextBefore: contextBuffer.length, - contextAfter: 0, - }; - } - hunk.contextAfter = 0; - - if (op === DIFF_DELETE) { - hunk.lines.push('-' + line); - lineOld++; - } else if (op === DIFF_INSERT) { - hunk.lines.push('+' + line); - lineNew++; - } - } - } - } - - if (hunk) - hunks.push(hunk); - - // Build the unified diff text - let diffText = `--- a/${relativeName}\n+++ b/${relativeName}\n`; - for (const hunk of hunks) { - // Calculate hunk ranges - const oldRangeStart = hunk.startOld; - const newRangeStart = hunk.startNew; - let oldRangeLines = 0; - let newRangeLines = 0; - - for (const line of hunk.lines) { - if (line.startsWith('-') || line.startsWith(' ')) - oldRangeLines++; - if (line.startsWith('+') || line.startsWith(' ')) - newRangeLines++; - } - - // Adjust starting line numbers when range is empty - const oldStartLine = oldRangeLines === 0 ? oldRangeStart - 1 : oldRangeStart; - const newStartLine = newRangeLines === 0 ? newRangeStart - 1 : newRangeStart; - - diffText += `@@ -${oldStartLine},${oldRangeLines} +${newStartLine},${newRangeLines} @@\n`; - diffText += hunk.lines.map(line => line + '\n').join(''); - } - - return diffText; -} diff --git a/packages/playwright-core/src/utils/zones.ts b/packages/playwright-core/src/utils/zones.ts index e6fabac0f1..15487d3595 100644 --- a/packages/playwright-core/src/utils/zones.ts +++ b/packages/playwright-core/src/utils/zones.ts @@ -19,49 +19,55 @@ import { AsyncLocalStorage } from 'async_hooks'; export type ZoneType = 'apiZone' | 'expectZone' | 'stepZone'; class ZoneManager { - private readonly _asyncLocalStorage = new AsyncLocalStorage|undefined>(); + private readonly _asyncLocalStorage = new AsyncLocalStorage(); run(type: ZoneType, data: T, func: () => R): R { - const previous = this._asyncLocalStorage.getStore(); - const zone = new Zone(previous, type, data); + const zone = Zone._createWithData(this._asyncLocalStorage, type, data); return this._asyncLocalStorage.run(zone, func); } zoneData(type: ZoneType): T | undefined { - for (let zone = this._asyncLocalStorage.getStore(); zone; zone = zone.previous) { - if (zone.type === type) - return zone.data as T; - } - return undefined; + const zone = this._asyncLocalStorage.getStore(); + return zone?.get(type); + } + + currentZone(): Zone { + return this._asyncLocalStorage.getStore() ?? Zone._createEmpty(this._asyncLocalStorage); } exitZones(func: () => R): R { return this._asyncLocalStorage.run(undefined, func); } - - printZones() { - const zones = []; - for (let zone = this._asyncLocalStorage.getStore(); zone; zone = zone.previous) { - let str = zone.type; - if (zone.type === 'apiZone') - str += `(${(zone.data as any).apiName})`; - zones.push(str); - - } - // eslint-disable-next-line no-console - console.log('zones: ', zones.join(' -> ')); - } } -class Zone { - readonly type: ZoneType; - readonly data: T; - readonly previous: Zone | undefined; +export class Zone { + private readonly _asyncLocalStorage: AsyncLocalStorage; + private readonly _data: Map; - constructor(previous: Zone | undefined, type: ZoneType, data: T) { - this.type = type; - this.data = data; - this.previous = previous; + static _createWithData(asyncLocalStorage: AsyncLocalStorage, type: ZoneType, data: unknown) { + const store = new Map(asyncLocalStorage.getStore()?._data); + store.set(type, data); + return new Zone(asyncLocalStorage, store); + } + + static _createEmpty(asyncLocalStorage: AsyncLocalStorage) { + return new Zone(asyncLocalStorage, new Map()); + } + + private constructor(asyncLocalStorage: AsyncLocalStorage, store: Map) { + this._asyncLocalStorage = asyncLocalStorage; + this._data = store; + } + + run(func: () => R): R { + // Reset apiZone and expectZone, but restore stepZone. + const entries = [...this._data.entries()].filter(([type]) => (type !== 'apiZone' && type !== 'expectZone')); + const resetZone = new Zone(this._asyncLocalStorage, new Map(entries)); + return this._asyncLocalStorage.run(resetZone, func); + } + + get(type: ZoneType): T | undefined { + return this._data.get(type) as T | undefined; } } diff --git a/packages/playwright-core/src/utilsBundle.ts b/packages/playwright-core/src/utilsBundle.ts index f57a6346f7..72bcee397e 100644 --- a/packages/playwright-core/src/utilsBundle.ts +++ b/packages/playwright-core/src/utilsBundle.ts @@ -19,7 +19,7 @@ import path from 'path'; export const colors: typeof import('../bundles/utils/node_modules/colors/safe') = require('./utilsBundleImpl').colors; export const debug: typeof import('../bundles/utils/node_modules/@types/debug') = require('./utilsBundleImpl').debug; -export const diffMatchPatch: typeof import('../bundles/utils/node_modules/@types/diff-match-patch') = require('./utilsBundleImpl').diffMatchPatch; +export const diff: typeof import('../bundles/utils/node_modules/@types/diff') = require('./utilsBundleImpl').diff; export const dotenv: typeof import('../bundles/utils/node_modules/dotenv') = require('./utilsBundleImpl').dotenv; export const getProxyForUrl: typeof import('../bundles/utils/node_modules/@types/proxy-from-env').getProxyForUrl = require('./utilsBundleImpl').getProxyForUrl; export const HttpsProxyAgent: typeof import('../bundles/utils/node_modules/https-proxy-agent').HttpsProxyAgent = require('./utilsBundleImpl').HttpsProxyAgent; diff --git a/packages/playwright-core/types/protocol.d.ts b/packages/playwright-core/types/protocol.d.ts index 35aa6f2eb9..3a61fbca59 100644 --- a/packages/playwright-core/types/protocol.d.ts +++ b/packages/playwright-core/types/protocol.d.ts @@ -112,7 +112,7 @@ export module Protocol { - from 'checked' to 'selected': states which apply to widgets - from 'activedescendant' to 'owns' - relationships between elements other than parent/child/sibling. */ - export type AXPropertyName = "busy"|"disabled"|"editable"|"focusable"|"focused"|"hidden"|"hiddenRoot"|"invalid"|"keyshortcuts"|"settable"|"roledescription"|"live"|"atomic"|"relevant"|"root"|"autocomplete"|"hasPopup"|"level"|"multiselectable"|"orientation"|"multiline"|"readonly"|"required"|"valuemin"|"valuemax"|"valuetext"|"checked"|"expanded"|"modal"|"pressed"|"selected"|"activedescendant"|"controls"|"describedby"|"details"|"errormessage"|"flowto"|"labelledby"|"owns"|"url"; + export type AXPropertyName = "actions"|"busy"|"disabled"|"editable"|"focusable"|"focused"|"hidden"|"hiddenRoot"|"invalid"|"keyshortcuts"|"settable"|"roledescription"|"live"|"atomic"|"relevant"|"root"|"autocomplete"|"hasPopup"|"level"|"multiselectable"|"orientation"|"multiline"|"readonly"|"required"|"valuemin"|"valuemax"|"valuetext"|"checked"|"expanded"|"modal"|"pressed"|"selected"|"activedescendant"|"controls"|"describedby"|"details"|"errormessage"|"flowto"|"labelledby"|"owns"|"url"; /** * A node in the accessibility tree. */ @@ -694,7 +694,7 @@ percentage [0 - 100] for scroll driven animations export interface AffectedFrame { frameId: Page.FrameId; } - export type CookieExclusionReason = "ExcludeSameSiteUnspecifiedTreatedAsLax"|"ExcludeSameSiteNoneInsecure"|"ExcludeSameSiteLax"|"ExcludeSameSiteStrict"|"ExcludeInvalidSameParty"|"ExcludeSamePartyCrossPartyContext"|"ExcludeDomainNonASCII"|"ExcludeThirdPartyCookieBlockedInFirstPartySet"|"ExcludeThirdPartyPhaseout"; + export type CookieExclusionReason = "ExcludeSameSiteUnspecifiedTreatedAsLax"|"ExcludeSameSiteNoneInsecure"|"ExcludeSameSiteLax"|"ExcludeSameSiteStrict"|"ExcludeInvalidSameParty"|"ExcludeSamePartyCrossPartyContext"|"ExcludeDomainNonASCII"|"ExcludeThirdPartyCookieBlockedInFirstPartySet"|"ExcludeThirdPartyPhaseout"|"ExcludePortMismatch"|"ExcludeSchemeMismatch"; export type CookieWarningReason = "WarnSameSiteUnspecifiedCrossSiteContext"|"WarnSameSiteNoneInsecure"|"WarnSameSiteUnspecifiedLaxAllowUnsafe"|"WarnSameSiteStrictLaxDowngradeStrict"|"WarnSameSiteStrictCrossDowngradeStrict"|"WarnSameSiteStrictCrossDowngradeLax"|"WarnSameSiteLaxCrossDowngradeStrict"|"WarnSameSiteLaxCrossDowngradeLax"|"WarnAttributeValueExceedsMaxSize"|"WarnDomainNonASCII"|"WarnThirdPartyPhaseout"|"WarnCrossSiteRedirectDowngradeChangesInclusion"|"WarnDeprecationTrialMetadata"|"WarnThirdPartyCookieHeuristic"; export type CookieOperation = "SetCookie"|"ReadCookie"; /** @@ -2183,12 +2183,17 @@ The array enumerates @scope at-rules starting with the innermost one, going outw * The array keeps the types of ancestor CSSRules from the innermost going outwards. */ ruleTypes?: CSSRuleType[]; + /** + * @starting-style CSS at-rule array. +The array enumerates @starting-style at-rules starting with the innermost one, going outwards. + */ + startingStyles?: CSSStartingStyle[]; } /** * Enum indicating the type of a CSS rule, used to represent the order of a style rule's ancestors. This list only contains rule types that are collected during the ancestor rule collection. */ - export type CSSRuleType = "MediaRule"|"SupportsRule"|"ContainerRule"|"LayerRule"|"ScopeRule"|"StyleRule"; + export type CSSRuleType = "MediaRule"|"SupportsRule"|"ContainerRule"|"LayerRule"|"ScopeRule"|"StyleRule"|"StartingStyleRule"; /** * CSS coverage information. */ @@ -2424,6 +2429,10 @@ available). * Optional logical axes queried for the container. */ logicalAxes?: DOM.LogicalAxes; + /** + * true if the query contains scroll-state() queries. + */ + queriesScrollState?: boolean; } /** * CSS Supports at-rule descriptor. @@ -2475,6 +2484,20 @@ available). text: string; /** * The associated rule header range in the enclosing stylesheet (if +available). + */ + range?: SourceRange; + /** + * Identifier of the stylesheet containing this object (if exists). + */ + styleSheetId?: StyleSheetId; + } + /** + * CSS Starting Style at-rule descriptor. + */ + export interface CSSStartingStyle { + /** + * The associated rule header range in the enclosing stylesheet (if available). */ range?: SourceRange; @@ -2779,6 +2802,12 @@ resized.) The current implementation considers only viewport-dependent media fea */ styleSheetId: StyleSheetId; } + export type computedStyleUpdatedPayload = { + /** + * The node id that has updated computed styles. + */ + nodeId: DOM.NodeId; + } /** * Inserts a new rule with the given `ruleText` in a stylesheet with given `styleSheetId`, at the @@ -3039,6 +3068,19 @@ returns an array of locations of the CSS selector in the style sheet. export type getLocationForSelectorReturnValue = { ranges: SourceRange[]; } + /** + * Starts tracking the given node for the computed style updates +and whenever the computed style is updated for node, it queues +a `computedStyleUpdated` event with throttling. +There can only be 1 node tracked for computed style updates +so passing a new node id removes tracking from the previous node. +Pass `undefined` to disable tracking. + */ + export type trackComputedStyleUpdatesForNodeParameters = { + nodeId?: DOM.NodeId; + } + export type trackComputedStyleUpdatesForNodeReturnValue = { + } /** * Starts tracking the given computed styles for updates. The specified array of properties replaces the one previously specified. Pass empty array to disable tracking. @@ -3561,7 +3603,7 @@ front-end. /** * Pseudo element type. */ - export type PseudoType = "first-line"|"first-letter"|"before"|"after"|"marker"|"backdrop"|"column"|"selection"|"search-text"|"target-text"|"spelling-error"|"grammar-error"|"highlight"|"first-line-inherited"|"scroll-marker"|"scroll-marker-group"|"scroll-next-button"|"scroll-prev-button"|"scrollbar"|"scrollbar-thumb"|"scrollbar-button"|"scrollbar-track"|"scrollbar-track-piece"|"scrollbar-corner"|"resizer"|"input-list-button"|"view-transition"|"view-transition-group"|"view-transition-image-pair"|"view-transition-old"|"view-transition-new"|"placeholder"|"file-selector-button"|"details-content"|"select-fallback-button"|"select-fallback-button-text"|"picker"; + export type PseudoType = "first-line"|"first-letter"|"check"|"before"|"after"|"select-arrow"|"marker"|"backdrop"|"column"|"selection"|"search-text"|"target-text"|"spelling-error"|"grammar-error"|"highlight"|"first-line-inherited"|"scroll-marker"|"scroll-marker-group"|"scroll-next-button"|"scroll-prev-button"|"scrollbar"|"scrollbar-thumb"|"scrollbar-button"|"scrollbar-track"|"scrollbar-track-piece"|"scrollbar-corner"|"resizer"|"input-list-button"|"view-transition"|"view-transition-group"|"view-transition-image-pair"|"view-transition-old"|"view-transition-new"|"placeholder"|"file-selector-button"|"details-content"|"picker"; /** * Shadow root type. */ @@ -4876,15 +4918,17 @@ $x functions). } /** * Returns the query container of the given node based on container query -conditions: containerName, physical, and logical axes. If no axes are -provided, the style container is returned, which is the direct parent or the -closest element with a matching container-name. +conditions: containerName, physical and logical axes, and whether it queries +scroll-state. If no axes are provided and queriesScrollState is false, the +style container is returned, which is the direct parent or the closest +element with a matching container-name. */ export type getContainerForNodeParameters = { nodeId: NodeId; containerName?: string; physicalAxes?: PhysicalAxes; logicalAxes?: LogicalAxes; + queriesScrollState?: boolean; } export type getContainerForNodeReturnValue = { /** @@ -8255,7 +8299,9 @@ file, data and other requests and responses, their headers, bodies, timing, etc. */ export type LoaderId = string; /** - * Unique request identifier. + * Unique network request identifier. +Note that this does not identify individual HTTP requests that are part of +a network request. */ export type RequestId = string; /** @@ -8830,6 +8876,7 @@ If the opcode isn't 1, then payloadData is a base64 encoded string representing type: "parser"|"script"|"preload"|"SignedExchange"|"preflight"|"other"; /** * Initiator JavaScript stack trace, set for Script only. +Requires the Debugger domain to be enabled. */ stack?: Runtime.StackTrace; /** @@ -8944,7 +8991,7 @@ This is a temporary ability and it will be removed in the future. /** * Types of reasons why a cookie may not be sent with a request. */ - export type CookieBlockedReason = "SecureOnly"|"NotOnPath"|"DomainMismatch"|"SameSiteStrict"|"SameSiteLax"|"SameSiteUnspecifiedTreatedAsLax"|"SameSiteNoneInsecure"|"UserPreferences"|"ThirdPartyPhaseout"|"ThirdPartyBlockedInFirstPartySet"|"UnknownError"|"SchemefulSameSiteStrict"|"SchemefulSameSiteLax"|"SchemefulSameSiteUnspecifiedTreatedAsLax"|"SamePartyFromCrossPartyContext"|"NameValuePairExceedsMaxSize"; + export type CookieBlockedReason = "SecureOnly"|"NotOnPath"|"DomainMismatch"|"SameSiteStrict"|"SameSiteLax"|"SameSiteUnspecifiedTreatedAsLax"|"SameSiteNoneInsecure"|"UserPreferences"|"ThirdPartyPhaseout"|"ThirdPartyBlockedInFirstPartySet"|"UnknownError"|"SchemefulSameSiteStrict"|"SchemefulSameSiteLax"|"SchemefulSameSiteUnspecifiedTreatedAsLax"|"SamePartyFromCrossPartyContext"|"NameValuePairExceedsMaxSize"|"PortMismatch"|"SchemeMismatch"; /** * Types of reasons why a cookie should have been blocked by 3PCD but is exempted for the request. */ @@ -11498,7 +11545,7 @@ as an ad. * All Permissions Policy features. This enum should match the one defined in third_party/blink/renderer/core/permissions_policy/permissions_policy_features.json5. */ - export type PermissionsPolicyFeature = "accelerometer"|"all-screens-capture"|"ambient-light-sensor"|"attribution-reporting"|"autoplay"|"bluetooth"|"browsing-topics"|"camera"|"captured-surface-control"|"ch-dpr"|"ch-device-memory"|"ch-downlink"|"ch-ect"|"ch-prefers-color-scheme"|"ch-prefers-reduced-motion"|"ch-prefers-reduced-transparency"|"ch-rtt"|"ch-save-data"|"ch-ua"|"ch-ua-arch"|"ch-ua-bitness"|"ch-ua-platform"|"ch-ua-model"|"ch-ua-mobile"|"ch-ua-form-factors"|"ch-ua-full-version"|"ch-ua-full-version-list"|"ch-ua-platform-version"|"ch-ua-wow64"|"ch-viewport-height"|"ch-viewport-width"|"ch-width"|"clipboard-read"|"clipboard-write"|"compute-pressure"|"controlled-frame"|"cross-origin-isolated"|"deferred-fetch"|"digital-credentials-get"|"direct-sockets"|"direct-sockets-private"|"display-capture"|"document-domain"|"encrypted-media"|"execution-while-out-of-viewport"|"execution-while-not-rendered"|"focus-without-user-activation"|"fullscreen"|"frobulate"|"gamepad"|"geolocation"|"gyroscope"|"hid"|"identity-credentials-get"|"idle-detection"|"interest-cohort"|"join-ad-interest-group"|"keyboard-map"|"local-fonts"|"magnetometer"|"media-playback-while-not-visible"|"microphone"|"midi"|"otp-credentials"|"payment"|"picture-in-picture"|"popins"|"private-aggregation"|"private-state-token-issuance"|"private-state-token-redemption"|"publickey-credentials-create"|"publickey-credentials-get"|"run-ad-auction"|"screen-wake-lock"|"serial"|"shared-autofill"|"shared-storage"|"shared-storage-select-url"|"smart-card"|"speaker-selection"|"storage-access"|"sub-apps"|"sync-xhr"|"unload"|"usb"|"usb-unrestricted"|"vertical-scroll"|"web-app-installation"|"web-printing"|"web-share"|"window-management"|"xr-spatial-tracking"; + export type PermissionsPolicyFeature = "accelerometer"|"all-screens-capture"|"ambient-light-sensor"|"attribution-reporting"|"autoplay"|"bluetooth"|"browsing-topics"|"camera"|"captured-surface-control"|"ch-dpr"|"ch-device-memory"|"ch-downlink"|"ch-ect"|"ch-prefers-color-scheme"|"ch-prefers-reduced-motion"|"ch-prefers-reduced-transparency"|"ch-rtt"|"ch-save-data"|"ch-ua"|"ch-ua-arch"|"ch-ua-bitness"|"ch-ua-platform"|"ch-ua-model"|"ch-ua-mobile"|"ch-ua-form-factors"|"ch-ua-full-version"|"ch-ua-full-version-list"|"ch-ua-platform-version"|"ch-ua-wow64"|"ch-viewport-height"|"ch-viewport-width"|"ch-width"|"clipboard-read"|"clipboard-write"|"compute-pressure"|"controlled-frame"|"cross-origin-isolated"|"deferred-fetch"|"digital-credentials-get"|"direct-sockets"|"direct-sockets-private"|"display-capture"|"document-domain"|"encrypted-media"|"execution-while-out-of-viewport"|"execution-while-not-rendered"|"fenced-unpartitioned-storage-read"|"focus-without-user-activation"|"fullscreen"|"frobulate"|"gamepad"|"geolocation"|"gyroscope"|"hid"|"identity-credentials-get"|"idle-detection"|"interest-cohort"|"join-ad-interest-group"|"keyboard-map"|"local-fonts"|"magnetometer"|"media-playback-while-not-visible"|"microphone"|"midi"|"otp-credentials"|"payment"|"picture-in-picture"|"popins"|"private-aggregation"|"private-state-token-issuance"|"private-state-token-redemption"|"publickey-credentials-create"|"publickey-credentials-get"|"run-ad-auction"|"screen-wake-lock"|"serial"|"shared-autofill"|"shared-storage"|"shared-storage-select-url"|"smart-card"|"speaker-selection"|"storage-access"|"sub-apps"|"sync-xhr"|"unload"|"usb"|"usb-unrestricted"|"vertical-scroll"|"web-app-installation"|"web-printing"|"web-share"|"window-management"|"xr-spatial-tracking"; /** * Reason for a permissions policy feature to be disabled. */ @@ -12384,7 +12431,8 @@ the page execution. Execution can be resumed via calling Page.handleJavaScriptDi defaultPrompt?: string; } /** - * Fired for top level page lifecycle events such as navigation, load, paint, etc. + * Fired for lifecycle events (navigation, load, paint, etc) in the current +target (including local frames). */ export type lifecycleEventPayload = { /** @@ -14339,6 +14387,7 @@ int destinationLimitPriority: SignedInt64AsBase10; aggregatableDebugReportingConfig: AttributionReportingAggregatableDebugReportingConfig; scopesData?: AttributionScopesData; + maxEventLevelReports: number; } export type AttributionReportingSourceRegistrationResult = "success"|"internalError"|"insufficientSourceCapacity"|"insufficientUniqueDestinationCapacity"|"excessiveReportingOrigins"|"prohibitedByBrowserPolicy"|"successNoised"|"destinationReportingLimitReached"|"destinationGlobalLimitReached"|"destinationBothLimitsReached"|"reportingOriginsPerSiteLimitReached"|"exceedsMaxChannelCapacity"|"exceedsMaxScopesChannelCapacity"|"exceedsMaxTriggerStateCardinality"|"exceedsMaxEventStatesLimit"|"destinationPerDayReportingLimitReached"; export type AttributionReportingSourceRegistrationTimeConfig = "include"|"exclude"; @@ -14386,7 +14435,7 @@ int scopes: string[]; } export type AttributionReportingEventLevelResult = "success"|"successDroppedLowerPriority"|"internalError"|"noCapacityForAttributionDestination"|"noMatchingSources"|"deduplicated"|"excessiveAttributions"|"priorityTooLow"|"neverAttributedSource"|"excessiveReportingOrigins"|"noMatchingSourceFilterData"|"prohibitedByBrowserPolicy"|"noMatchingConfigurations"|"excessiveReports"|"falselyAttributedSource"|"reportWindowPassed"|"notRegistered"|"reportWindowNotStarted"|"noMatchingTriggerData"; - export type AttributionReportingAggregatableResult = "success"|"internalError"|"noCapacityForAttributionDestination"|"noMatchingSources"|"excessiveAttributions"|"excessiveReportingOrigins"|"noHistograms"|"insufficientBudget"|"noMatchingSourceFilterData"|"notRegistered"|"prohibitedByBrowserPolicy"|"deduplicated"|"reportWindowPassed"|"excessiveReports"; + export type AttributionReportingAggregatableResult = "success"|"internalError"|"noCapacityForAttributionDestination"|"noMatchingSources"|"excessiveAttributions"|"excessiveReportingOrigins"|"noHistograms"|"insufficientBudget"|"insufficientNamedBudget"|"noMatchingSourceFilterData"|"notRegistered"|"prohibitedByBrowserPolicy"|"deduplicated"|"reportWindowPassed"|"excessiveReports"; /** * A single Related Website Set object. */ @@ -15920,6 +15969,8 @@ are ignored. export module Fetch { /** * Unique request identifier. +Note that this does not identify individual HTTP requests that are part of +a network request. */ export type RequestId = string; /** @@ -16302,7 +16353,7 @@ https://webaudio.github.io/web-audio-api/ /** * Enum of AudioContextState from the spec */ - export type ContextState = "suspended"|"running"|"closed"; + export type ContextState = "suspended"|"running"|"closed"|"interrupted"; /** * Enum of AudioNode types */ @@ -20213,6 +20264,7 @@ Error was thrown. "CSS.styleSheetAdded": CSS.styleSheetAddedPayload; "CSS.styleSheetChanged": CSS.styleSheetChangedPayload; "CSS.styleSheetRemoved": CSS.styleSheetRemovedPayload; + "CSS.computedStyleUpdated": CSS.computedStyleUpdatedPayload; "Cast.sinksUpdated": Cast.sinksUpdatedPayload; "Cast.issueUpdated": Cast.issueUpdatedPayload; "DOM.attributeModified": DOM.attributeModifiedPayload; @@ -20464,6 +20516,7 @@ Error was thrown. "CSS.getStyleSheetText": CSS.getStyleSheetTextParameters; "CSS.getLayersForNode": CSS.getLayersForNodeParameters; "CSS.getLocationForSelector": CSS.getLocationForSelectorParameters; + "CSS.trackComputedStyleUpdatesForNode": CSS.trackComputedStyleUpdatesForNodeParameters; "CSS.trackComputedStyleUpdates": CSS.trackComputedStyleUpdatesParameters; "CSS.takeComputedStyleUpdates": CSS.takeComputedStyleUpdatesParameters; "CSS.setEffectivePropertyValueForNode": CSS.setEffectivePropertyValueForNodeParameters; @@ -21075,6 +21128,7 @@ Error was thrown. "CSS.getStyleSheetText": CSS.getStyleSheetTextReturnValue; "CSS.getLayersForNode": CSS.getLayersForNodeReturnValue; "CSS.getLocationForSelector": CSS.getLocationForSelectorReturnValue; + "CSS.trackComputedStyleUpdatesForNode": CSS.trackComputedStyleUpdatesForNodeReturnValue; "CSS.trackComputedStyleUpdates": CSS.trackComputedStyleUpdatesReturnValue; "CSS.takeComputedStyleUpdates": CSS.takeComputedStyleUpdatesReturnValue; "CSS.setEffectivePropertyValueForNode": CSS.setEffectivePropertyValueForNodeReturnValue; diff --git a/packages/playwright-core/types/types.d.ts b/packages/playwright-core/types/types.d.ts index 2d4ecc2b7c..85dd2d50a6 100644 --- a/packages/playwright-core/types/types.d.ts +++ b/packages/playwright-core/types/types.d.ts @@ -12425,7 +12425,7 @@ export interface Locator { and(locator: Locator): Locator; /** - * Captures the aria snapshot of the given element. See + * Captures the aria snapshot of the given element. Read more about [aria snapshots](https://playwright.dev/docs/aria-snapshots) and * [expect(locator).toMatchAriaSnapshot(expected[, options])](https://playwright.dev/docs/api/class-locatorassertions#locator-assertions-to-match-aria-snapshot) * for the corresponding assertion. * @@ -21055,6 +21055,45 @@ export interface Touchscreen { * */ export interface Tracing { + /** + * **NOTE** Use `test.step` instead when available. + * + * Creates a new group within the trace, assigning any subsequent API calls to this group, until + * [tracing.groupEnd()](https://playwright.dev/docs/api/class-tracing#tracing-group-end) is called. Groups can be + * nested and will be visible in the trace viewer. + * + * **Usage** + * + * ```js + * // use test.step instead + * await test.step('Log in', async () => { + * // ... + * }); + * ``` + * + * @param name Group name shown in the trace viewer. + * @param options + */ + group(name: string, options?: { + /** + * Specifies a custom location for the group to be shown in the trace viewer. Defaults to the location of the + * [tracing.group(name[, options])](https://playwright.dev/docs/api/class-tracing#tracing-group) call. + */ + location?: { + file: string; + + line?: number; + + column?: number; + }; + }): Promise; + + /** + * Closes the last group created by + * [tracing.group(name[, options])](https://playwright.dev/docs/api/class-tracing#tracing-group). + */ + groupEnd(): Promise; + /** * Start tracing. * diff --git a/packages/playwright-ct-core/package.json b/packages/playwright-ct-core/package.json index 93b45c19e0..60144fa7c3 100644 --- a/packages/playwright-ct-core/package.json +++ b/packages/playwright-ct-core/package.json @@ -1,6 +1,6 @@ { "name": "@playwright/experimental-ct-core", - "version": "1.49.0-next", + "version": "1.50.0-next", "description": "Playwright Component Testing Helpers", "repository": { "type": "git", @@ -26,8 +26,8 @@ } }, "dependencies": { - "playwright-core": "1.49.0-next", + "playwright-core": "1.50.0-next", "vite": "^5.2.8", - "playwright": "1.49.0-next" + "playwright": "1.50.0-next" } } diff --git a/packages/playwright-ct-core/src/router.ts b/packages/playwright-ct-core/src/router.ts index 50adf8c573..5ff746ddf2 100644 --- a/packages/playwright-ct-core/src/router.ts +++ b/packages/playwright-ct-core/src/router.ts @@ -37,10 +37,20 @@ async function executeRequestHandlers(request: Request, handlers: RequestHandler } } +function isMswRequestPassthrough(headers: Headers): boolean { + if (headers.get('x-msw-intention') === 'bypass') + return true; + // After MSW v2.6.4 + // https://github.com/mswjs/msw/commit/2fa98c327acc51189f87789d9155c4ec57be2299 + if (headers.get('accept')?.includes('msw/passthrough')) + return true; + return false; +} + async function globalFetch(...args: Parameters) { if (args[0] && args[0] instanceof Request) { const request = args[0]; - if (request.headers.get('x-msw-intention') === 'bypass') { + if (isMswRequestPassthrough(request.headers)) { const cookieHeaders = await Promise.all([...currentlyInterceptingInContexts.keys()].map(async context => { const cookies = await context.cookies(request.url); if (!cookies.length) @@ -56,7 +66,16 @@ async function globalFetch(...args: Parameters) { const headers = new Headers(request.headers); headers.set('cookie', cookieHeaders[0]!); - headers.delete('x-msw-intention'); + { + // pre 2.6.4 + headers.delete('x-msw-intention'); + // post 2.6.4 + const accept = headers.get('accept')?.split(',').filter(h => !h.includes('msw/')).join(','); + if (accept) + headers.set('accept', accept); + else + headers.delete('accept'); + } args[0] = new Request(request.clone(), { headers }); } } diff --git a/packages/playwright-ct-react/package.json b/packages/playwright-ct-react/package.json index 02ce2fc3c3..39a8e98a15 100644 --- a/packages/playwright-ct-react/package.json +++ b/packages/playwright-ct-react/package.json @@ -1,6 +1,6 @@ { "name": "@playwright/experimental-ct-react", - "version": "1.49.0-next", + "version": "1.50.0-next", "description": "Playwright Component Testing for React", "repository": { "type": "git", @@ -30,7 +30,7 @@ "./package.json": "./package.json" }, "dependencies": { - "@playwright/experimental-ct-core": "1.49.0-next", + "@playwright/experimental-ct-core": "1.50.0-next", "@vitejs/plugin-react": "^4.2.1" }, "bin": { diff --git a/packages/playwright-ct-react17/package.json b/packages/playwright-ct-react17/package.json index 92bf481f6a..41665bfb9b 100644 --- a/packages/playwright-ct-react17/package.json +++ b/packages/playwright-ct-react17/package.json @@ -1,6 +1,6 @@ { "name": "@playwright/experimental-ct-react17", - "version": "1.49.0-next", + "version": "1.50.0-next", "description": "Playwright Component Testing for React", "repository": { "type": "git", @@ -30,7 +30,7 @@ "./package.json": "./package.json" }, "dependencies": { - "@playwright/experimental-ct-core": "1.49.0-next", + "@playwright/experimental-ct-core": "1.50.0-next", "@vitejs/plugin-react": "^4.2.1" }, "bin": { diff --git a/packages/playwright-ct-solid/.npmignore b/packages/playwright-ct-solid/.npmignore deleted file mode 100644 index 62701eb493..0000000000 --- a/packages/playwright-ct-solid/.npmignore +++ /dev/null @@ -1,12 +0,0 @@ -**/* - -!README.md -!LICENSE -!cli.js -!register.d.ts -!register.mjs -!registerSource.mjs -!index.d.ts -!index.js -!hooks.d.ts -!hooks.mjs diff --git a/packages/playwright-ct-solid/README.md b/packages/playwright-ct-solid/README.md deleted file mode 100644 index 23ae82312d..0000000000 --- a/packages/playwright-ct-solid/README.md +++ /dev/null @@ -1,3 +0,0 @@ -> **BEWARE** This package is EXPERIMENTAL and does not respect semver. - -Read more at https://playwright.dev/docs/test-components diff --git a/packages/playwright-ct-solid/cli.js b/packages/playwright-ct-solid/cli.js deleted file mode 100755 index 9cc834ee95..0000000000 --- a/packages/playwright-ct-solid/cli.js +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env node -/** - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -const { program } = require('@playwright/experimental-ct-core/lib/program'); - -program.parse(process.argv); diff --git a/packages/playwright-ct-solid/hooks.d.ts b/packages/playwright-ct-solid/hooks.d.ts deleted file mode 100644 index 097c8cf11f..0000000000 --- a/packages/playwright-ct-solid/hooks.d.ts +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { JSXElement } from 'solid-js'; - -export declare function beforeMount( - callback: (params: { hooksConfig?: HooksConfig, App: () => JSXElement }) => Promise -): void; -export declare function afterMount( - callback: (params: { hooksConfig?: HooksConfig }) => Promise -): void; diff --git a/packages/playwright-ct-solid/hooks.mjs b/packages/playwright-ct-solid/hooks.mjs deleted file mode 100644 index b7cea242c4..0000000000 --- a/packages/playwright-ct-solid/hooks.mjs +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -const __pw_hooks_before_mount = []; -const __pw_hooks_after_mount = []; - -window.__pw_hooks_before_mount = __pw_hooks_before_mount; -window.__pw_hooks_after_mount = __pw_hooks_after_mount; - -export const beforeMount = callback => { - __pw_hooks_before_mount.push(callback); -}; - -export const afterMount = callback => { - __pw_hooks_after_mount.push(callback); -}; diff --git a/packages/playwright-ct-solid/index.d.ts b/packages/playwright-ct-solid/index.d.ts deleted file mode 100644 index c5e6d6d2da..0000000000 --- a/packages/playwright-ct-solid/index.d.ts +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import type { TestType, Locator } from '@playwright/experimental-ct-core'; - -export interface MountOptions { - hooksConfig?: HooksConfig; -} - -export interface MountResult extends Locator { - unmount(): Promise; - update(component: JSX.Element): Promise; -} - -export const test: TestType<{ - mount( - component: JSX.Element, - options?: MountOptions - ): Promise; -}>; - -export { defineConfig, PlaywrightTestConfig, expect, devices } from '@playwright/experimental-ct-core'; diff --git a/packages/playwright-ct-solid/index.js b/packages/playwright-ct-solid/index.js deleted file mode 100644 index c2feef7455..0000000000 --- a/packages/playwright-ct-solid/index.js +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -const { test, expect, devices, defineConfig: originalDefineConfig } = require('@playwright/experimental-ct-core'); -const path = require('path'); - -const defineConfig = (config, ...configs) => { - return originalDefineConfig({ - ...config, - '@playwright/test': { - packageJSON: require.resolve('./package.json'), - }, - '@playwright/experimental-ct-core': { - registerSourceFile: path.join(__dirname, 'registerSource.mjs'), - frameworkPluginFactory: () => import('vite-plugin-solid').then(plugin => plugin.default()), - }, - }, ...configs); -}; - -module.exports = { test, expect, devices, defineConfig }; diff --git a/packages/playwright-ct-solid/package.json b/packages/playwright-ct-solid/package.json deleted file mode 100644 index 518e070e17..0000000000 --- a/packages/playwright-ct-solid/package.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "name": "@playwright/experimental-ct-solid", - "version": "1.49.0-next", - "description": "Playwright Component Testing for Solid", - "repository": { - "type": "git", - "url": "git+https://github.com/microsoft/playwright.git" - }, - "homepage": "https://playwright.dev", - "engines": { - "node": ">=18" - }, - "author": { - "name": "Microsoft Corporation" - }, - "license": "Apache-2.0", - "exports": { - ".": { - "types": "./index.d.ts", - "default": "./index.js" - }, - "./register": { - "types": "./register.d.ts", - "default": "./register.mjs" - }, - "./hooks": { - "types": "./hooks.d.ts", - "default": "./hooks.mjs" - }, - "./package.json": "./package.json" - }, - "dependencies": { - "@playwright/experimental-ct-core": "1.49.0-next", - "vite-plugin-solid": "^2.7.0" - }, - "devDependencies": { - "solid-js": "^1.7.0" - }, - "bin": { - "playwright": "cli.js" - } -} diff --git a/packages/playwright-ct-solid/register.d.ts b/packages/playwright-ct-solid/register.d.ts deleted file mode 100644 index 1f44530ed6..0000000000 --- a/packages/playwright-ct-solid/register.d.ts +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export default function pwRegister(components: Record): void; diff --git a/packages/playwright-ct-solid/register.mjs b/packages/playwright-ct-solid/register.mjs deleted file mode 100644 index ca6a6a12d9..0000000000 --- a/packages/playwright-ct-solid/register.mjs +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { pwRegister } from './registerSource.mjs'; - -export default components => { - pwRegister(components); -}; diff --git a/packages/playwright-ct-solid/registerSource.mjs b/packages/playwright-ct-solid/registerSource.mjs deleted file mode 100644 index d0077dd494..0000000000 --- a/packages/playwright-ct-solid/registerSource.mjs +++ /dev/null @@ -1,84 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// @ts-check -// This file is injected into the registry as text, no dependencies are allowed. - -import { render as __pwSolidRender, createComponent as __pwSolidCreateComponent } from 'solid-js/web'; -import __pwH from 'solid-js/h'; -/** @typedef {import('../playwright-ct-core/types/component').JsxComponent} JsxComponent */ - -/** - * @param {any} component - * @returns {component is JsxComponent} - */ -function isJsxComponent(component) { - return typeof component === 'object' && component && component.__pw_type === 'jsx'; -} - -/** - * @param {any} value - */ -function __pwCreateComponent(value) { - return window.__pwTransformObject(value, v => { - if (isJsxComponent(v)) { - const component = v; - const props = component.props ? __pwCreateComponent(component.props) : {}; - if (typeof component.type === 'string') { - const { children, ...propsWithoutChildren } = props; - return { result: __pwH(component.type, propsWithoutChildren, children) }; - } - return { result: __pwSolidCreateComponent(component.type, props) }; - } - }); -} - -const __pwUnmountKey = Symbol('unmountKey'); - -window.playwrightMount = async (component, rootElement, hooksConfig) => { - if (!isJsxComponent(component)) - throw new Error('Object mount notation is not supported'); - - let App = () => __pwCreateComponent(component); - for (const hook of window.__pw_hooks_before_mount || []) { - const wrapper = await hook({ App, hooksConfig }); - if (wrapper) - App = () => wrapper; - } - - const unmount = __pwSolidRender(App, rootElement); - rootElement[__pwUnmountKey] = unmount; - - for (const hook of window.__pw_hooks_after_mount || []) - await hook({ hooksConfig }); -}; - -window.playwrightUnmount = async rootElement => { - const unmount = rootElement[__pwUnmountKey]; - if (!unmount) - throw new Error('Component was not mounted'); - - unmount(); - delete rootElement[__pwUnmountKey]; -}; - -window.playwrightUpdate = async (rootElement, component) => { - if (!isJsxComponent(component)) - throw new Error('Object mount notation is not supported'); - - window.playwrightUnmount(rootElement); - window.playwrightMount(component, rootElement, {}); -}; diff --git a/packages/playwright-ct-svelte/package.json b/packages/playwright-ct-svelte/package.json index 57129d4651..7afba03632 100644 --- a/packages/playwright-ct-svelte/package.json +++ b/packages/playwright-ct-svelte/package.json @@ -1,6 +1,6 @@ { "name": "@playwright/experimental-ct-svelte", - "version": "1.49.0-next", + "version": "1.50.0-next", "description": "Playwright Component Testing for Svelte", "repository": { "type": "git", @@ -30,7 +30,7 @@ "./package.json": "./package.json" }, "dependencies": { - "@playwright/experimental-ct-core": "1.49.0-next", + "@playwright/experimental-ct-core": "1.50.0-next", "@sveltejs/vite-plugin-svelte": "^3.0.1" }, "devDependencies": { diff --git a/packages/playwright-ct-vue/package.json b/packages/playwright-ct-vue/package.json index 82a5968568..4849ca1ccb 100644 --- a/packages/playwright-ct-vue/package.json +++ b/packages/playwright-ct-vue/package.json @@ -1,6 +1,6 @@ { "name": "@playwright/experimental-ct-vue", - "version": "1.49.0-next", + "version": "1.50.0-next", "description": "Playwright Component Testing for Vue", "repository": { "type": "git", @@ -30,7 +30,7 @@ "./package.json": "./package.json" }, "dependencies": { - "@playwright/experimental-ct-core": "1.49.0-next", + "@playwright/experimental-ct-core": "1.50.0-next", "@vitejs/plugin-vue": "^4.2.1" }, "bin": { diff --git a/packages/playwright-firefox/package.json b/packages/playwright-firefox/package.json index 8949b1eccc..44832c5532 100644 --- a/packages/playwright-firefox/package.json +++ b/packages/playwright-firefox/package.json @@ -1,6 +1,6 @@ { "name": "playwright-firefox", - "version": "1.49.0-next", + "version": "1.50.0-next", "description": "A high-level API to automate Firefox", "repository": { "type": "git", @@ -30,6 +30,6 @@ "install": "node install.js" }, "dependencies": { - "playwright-core": "1.49.0-next" + "playwright-core": "1.50.0-next" } } diff --git a/packages/playwright-test/package.json b/packages/playwright-test/package.json index c3067c5f7e..dcf74e1111 100644 --- a/packages/playwright-test/package.json +++ b/packages/playwright-test/package.json @@ -1,6 +1,6 @@ { "name": "@playwright/test", - "version": "1.49.0-next", + "version": "1.50.0-next", "description": "A high-level API to automate web browsers", "repository": { "type": "git", @@ -30,6 +30,6 @@ }, "scripts": {}, "dependencies": { - "playwright": "1.49.0-next" + "playwright": "1.50.0-next" } } diff --git a/packages/playwright-webkit/package.json b/packages/playwright-webkit/package.json index 9de034f93b..9fd72b1c84 100644 --- a/packages/playwright-webkit/package.json +++ b/packages/playwright-webkit/package.json @@ -1,6 +1,6 @@ { "name": "playwright-webkit", - "version": "1.49.0-next", + "version": "1.50.0-next", "description": "A high-level API to automate WebKit", "repository": { "type": "git", @@ -30,6 +30,6 @@ "install": "node install.js" }, "dependencies": { - "playwright-core": "1.49.0-next" + "playwright-core": "1.50.0-next" } } diff --git a/packages/playwright/ThirdPartyNotices.txt b/packages/playwright/ThirdPartyNotices.txt index 2931da55c9..c572f8daee 100644 --- a/packages/playwright/ThirdPartyNotices.txt +++ b/packages/playwright/ThirdPartyNotices.txt @@ -97,7 +97,7 @@ This project incorporates components from the projects listed below. The origina - chalk@4.1.2 (https://github.com/chalk/chalk) - chokidar@3.6.0 (https://github.com/paulmillr/chokidar) - ci-info@3.9.0 (https://github.com/watson/ci-info) -- codemirror-shadow-1@0.0.1 (https://github.com/codemirror/CodeMirror) +- codemirror@5.65.18 (https://github.com/codemirror/CodeMirror) - color-convert@1.9.3 (https://github.com/Qix-/color-convert) - color-convert@2.0.1 (https://github.com/Qix-/color-convert) - color-name@1.1.3 (https://github.com/dfcreative/color-name) @@ -3103,7 +3103,7 @@ SOFTWARE. ========================================= END OF ci-info@3.9.0 AND INFORMATION -%% codemirror-shadow-1@0.0.1 NOTICES AND INFORMATION BEGIN HERE +%% codemirror@5.65.18 NOTICES AND INFORMATION BEGIN HERE ========================================= MIT License @@ -3127,7 +3127,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ========================================= -END OF codemirror-shadow-1@0.0.1 AND INFORMATION +END OF codemirror@5.65.18 AND INFORMATION %% color-convert@1.9.3 NOTICES AND INFORMATION BEGIN HERE ========================================= diff --git a/packages/playwright/bundles/babel/src/babelBundleImpl.ts b/packages/playwright/bundles/babel/src/babelBundleImpl.ts index 78c3c0403e..54822134ea 100644 --- a/packages/playwright/bundles/babel/src/babelBundleImpl.ts +++ b/packages/playwright/bundles/babel/src/babelBundleImpl.ts @@ -27,7 +27,9 @@ import traverseFunction from '@babel/traverse'; export const traverse = traverseFunction; function babelTransformOptions(isTypeScript: boolean, isModule: boolean, pluginsPrologue: [string, any?][], pluginsEpilogue: [string, any?][]): TransformOptions { - const plugins = []; + const plugins = [ + [require('@babel/plugin-syntax-import-attributes'), { deprecatedAssertSyntax: true }], + ]; if (isTypeScript) { plugins.push( @@ -45,7 +47,6 @@ function babelTransformOptions(isTypeScript: boolean, isModule: boolean, plugins [require('@babel/plugin-syntax-async-generators')], [require('@babel/plugin-syntax-object-rest-spread')], [require('@babel/plugin-transform-export-namespace-from')], - [require('@babel/plugin-syntax-import-attributes'), { deprecatedAssertSyntax: true }], [ // From https://github.com/G-Rath/babel-plugin-replace-ts-export-assignment/blob/8dfdca32c8aa428574b0cae341444fc5822f2dc6/src/index.ts ( diff --git a/packages/playwright/package.json b/packages/playwright/package.json index 1d196e253b..a525d5deee 100644 --- a/packages/playwright/package.json +++ b/packages/playwright/package.json @@ -1,6 +1,6 @@ { "name": "playwright", - "version": "1.49.0-next", + "version": "1.50.0-next", "description": "A high-level API to automate web browsers", "repository": { "type": "git", @@ -56,7 +56,7 @@ }, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.49.0-next" + "playwright-core": "1.50.0-next" }, "optionalDependencies": { "fsevents": "2.3.2" diff --git a/packages/playwright/src/common/testType.ts b/packages/playwright/src/common/testType.ts index f22fd159d8..d3c2f1c23a 100644 --- a/packages/playwright/src/common/testType.ts +++ b/packages/playwright/src/common/testType.ts @@ -21,7 +21,8 @@ import { wrapFunctionWithLocation } from '../transform/transform'; import type { FixturesWithLocation } from './config'; import type { Fixtures, TestType, TestDetails } from '../../types/test'; import type { Location } from '../../types/testReporter'; -import { getPackageManagerExecCommand, zones } from 'playwright-core/lib/utils'; +import { getPackageManagerExecCommand, monotonicTime, raceAgainstDeadline, zones } from 'playwright-core/lib/utils'; +import { errors } from 'playwright-core'; const testTypeSymbol = Symbol('testType'); @@ -256,16 +257,18 @@ export class TestTypeImpl { suite._use.push({ fixtures, location }); } - async _step(title: string, body: () => Promise, options: {box?: boolean, location?: Location } = {}): Promise { + async _step(title: string, body: () => T | Promise, options: {box?: boolean, location?: Location, timeout?: number } = {}): Promise { const testInfo = currentTestInfo(); if (!testInfo) throw new Error(`test.step() can only be called from a test`); const step = testInfo._addStep({ category: 'test.step', title, location: options.location, box: options.box }); return await zones.run('stepZone', step, async () => { try { - const result = await body(); + const result = await raceAgainstDeadline(async () => body(), options.timeout ? monotonicTime() + options.timeout : 0); + if (result.timedOut) + throw new errors.TimeoutError(`Step timeout ${options.timeout}ms exceeded.`); step.complete({}); - return result; + return result.result; } catch (error) { step.complete({ error }); throw error; diff --git a/packages/playwright/src/index.ts b/packages/playwright/src/index.ts index c2c9596b6e..27f1e9320b 100644 --- a/packages/playwright/src/index.ts +++ b/packages/playwright/src/index.ts @@ -20,7 +20,7 @@ import type { APIRequestContext, BrowserContext, Browser, BrowserContextOptions, import * as playwrightLibrary from 'playwright-core'; import { createGuid, debugMode, addInternalStackPrefix, isString, asLocator, jsonStringifyForceASCII } from 'playwright-core/lib/utils'; import type { Fixtures, PlaywrightTestArgs, PlaywrightTestOptions, PlaywrightWorkerArgs, PlaywrightWorkerOptions, ScreenshotMode, TestInfo, TestType, VideoMode } from '../types/test'; -import type { TestInfoImpl } from './worker/testInfo'; +import type { TestInfoImpl, TestStepInternal } from './worker/testInfo'; import { rootTestType } from './common/testType'; import type { ContextReuseMode } from './common/config'; import type { ClientInstrumentation, ClientInstrumentationListener } from '../../playwright-core/src/client/clientInstrumentation'; @@ -255,27 +255,41 @@ const playwrightFixtures: Fixtures = ({ const artifactsRecorder = new ArtifactsRecorder(playwright, tracing().artifactsDir(), screenshot); await artifactsRecorder.willStartTest(testInfo as TestInfoImpl); + + const tracingGroupSteps: TestStepInternal[] = []; const csiListener: ClientInstrumentationListener = { onApiCallBegin: (apiName: string, params: Record, frames: StackFrame[], userData: any, out: { stepId?: string }) => { + userData.apiName = apiName; const testInfo = currentTestInfo(); - if (!testInfo || apiName.includes('setTestIdAttribute')) - return { userObject: null }; + if (!testInfo || apiName.includes('setTestIdAttribute') || apiName === 'tracing.groupEnd') + return; const step = testInfo._addStep({ location: frames[0] as any, category: 'pw:api', title: renderApiCall(apiName, params), apiName, params, - }); - userData.userObject = step; + }, tracingGroupSteps[tracingGroupSteps.length - 1]); + userData.step = step; out.stepId = step.stepId; + if (apiName === 'tracing.group') + tracingGroupSteps.push(step); }, onApiCallEnd: (userData: any, error?: Error) => { - const step = userData.userObject; + // "tracing.group" step will end later, when "tracing.groupEnd" finishes. + if (userData.apiName === 'tracing.group') + return; + if (userData.apiName === 'tracing.groupEnd') { + const step = tracingGroupSteps.pop(); + step?.complete({ error }); + return; + } + const step = userData.step; step?.complete({ error }); }, - onWillPause: () => { - currentTestInfo()?._setDebugMode(); + onWillPause: ({ keepTestTimeout }) => { + if (!keepTestTimeout) + currentTestInfo()?._setDebugMode(); }, runAfterCreateBrowserContext: async (context: BrowserContext) => { await artifactsRecorder?.didCreateBrowserContext(context); @@ -604,9 +618,10 @@ class ArtifactsRecorder { if (captureScreenshots) await this._screenshotOnTestFailure(); - const leftoverContexts: BrowserContext[] = []; + let leftoverContexts: BrowserContext[] = []; for (const browserType of [this._playwright.chromium, this._playwright.firefox, this._playwright.webkit]) leftoverContexts.push(...(browserType as any)._contexts); + leftoverContexts = leftoverContexts.filter(context => !this._reusedContexts.has(context)); const leftoverApiRequests: APIRequestContext[] = Array.from((this._playwright.request as any)._contexts as Set); // Collect traces/screenshots for remaining contexts. @@ -699,6 +714,8 @@ class ArtifactsRecorder { const paramsToRender = ['url', 'selector', 'text', 'key']; function renderApiCall(apiName: string, params: any) { + if (apiName === 'tracing.group') + return params.name; const paramsArray = []; if (params) { for (const name of paramsToRender) { diff --git a/packages/playwright/src/matchers/matchers.ts b/packages/playwright/src/matchers/matchers.ts index f7c68b4544..8a8089e91e 100644 --- a/packages/playwright/src/matchers/matchers.ts +++ b/packages/playwright/src/matchers/matchers.ts @@ -181,7 +181,7 @@ export function toHaveAccessibleDescription( options?: { timeout?: number, ignoreCase?: boolean }, ) { return toMatchText.call(this, 'toHaveAccessibleDescription', locator, 'Locator', async (isNot, timeout) => { - const expectedText = serializeExpectedTextValues([expected], { ignoreCase: options?.ignoreCase }); + const expectedText = serializeExpectedTextValues([expected], { ignoreCase: options?.ignoreCase, normalizeWhiteSpace: true }); return await locator._expect('to.have.accessible.description', { expectedText, isNot, timeout }); }, expected, options); } @@ -189,13 +189,20 @@ export function toHaveAccessibleDescription( export function toHaveAccessibleName( this: ExpectMatcherState, locator: LocatorEx, - expected: string | RegExp, - options?: { timeout?: number, ignoreCase?: boolean }, + expected: string | RegExp | (string | RegExp)[], + options: { timeout?: number, ignoreCase?: boolean, normalizeWhiteSpace?: boolean } = {} ) { - return toMatchText.call(this, 'toHaveAccessibleName', locator, 'Locator', async (isNot, timeout) => { - const expectedText = serializeExpectedTextValues([expected], { ignoreCase: options?.ignoreCase }); - return await locator._expect('to.have.accessible.name', { expectedText, isNot, timeout }); - }, expected, options); + if (Array.isArray(expected)) { + return toEqual.call(this, 'toHaveAccessibleName', locator, 'Locator', async (isNot, timeout) => { + const expectedText = serializeExpectedTextValues(expected, { ignoreCase: options?.ignoreCase, normalizeWhiteSpace: true }); + return await locator._expect('to.have.accessible.name.array', { expectedText, isNot, timeout }); + }, expected, options); + } else { + return toMatchText.call(this, 'toHaveAccessibleName', locator, 'Locator', async (isNot, timeout) => { + const expectedText = serializeExpectedTextValues([expected], { ignoreCase: options?.ignoreCase, normalizeWhiteSpace: true }); + return await locator._expect('to.have.accessible.name', { expectedText, isNot, timeout }); + }, expected, options); + } } export function toHaveAttribute( diff --git a/packages/playwright/src/matchers/toEqual.ts b/packages/playwright/src/matchers/toEqual.ts index bb0f4e147e..4296444a7b 100644 --- a/packages/playwright/src/matchers/toEqual.ts +++ b/packages/playwright/src/matchers/toEqual.ts @@ -19,6 +19,7 @@ import { matcherHint } from './matcherHint'; import type { MatcherResult } from './matcherHint'; import type { ExpectMatcherState } from '../../types/test'; import type { Locator } from 'playwright-core'; +import { isRegExp } from 'playwright-core/lib/utils'; // Omit colon and one or more spaces, so can call getLabelPrinter. const EXPECTED_LABEL = 'Expected'; @@ -59,6 +60,21 @@ export async function toEqual( if (pass) { printedExpected = `Expected: not ${this.utils.printExpected(expected)}`; printedReceived = `Received: ${this.utils.printReceived(received)}`; + } else if (Array.isArray(expected) && Array.isArray(received)) { + const normalizedExpected = expected.map((exp, index) => { + const rec = received[index]; + if (isRegExp(exp)) + return exp.test(rec) ? rec : exp; + + return exp; + }); + printedDiff = this.utils.printDiffOrStringify( + normalizedExpected, + received, + EXPECTED_LABEL, + RECEIVED_LABEL, + false, + ); } else { printedDiff = this.utils.printDiffOrStringify( expected, diff --git a/packages/playwright/src/matchers/toMatchAriaSnapshot.ts b/packages/playwright/src/matchers/toMatchAriaSnapshot.ts index a475ec39d8..0bb600f7b0 100644 --- a/packages/playwright/src/matchers/toMatchAriaSnapshot.ts +++ b/packages/playwright/src/matchers/toMatchAriaSnapshot.ts @@ -79,25 +79,24 @@ export async function toMatchAriaSnapshot( if (notFound) { return { pass: this.isNot, - message: () => messagePrefix + `Expected: ${this.utils.printExpected(expected)}\nReceived: ${EXPECTED_COLOR('not found')}` + callLogText(log), + message: () => messagePrefix + `Expected: ${this.utils.printExpected(expected)}\nReceived: ${EXPECTED_COLOR('')}` + callLogText(log), name: 'toMatchAriaSnapshot', expected, }; } - const escapedExpected = escapePrivateUsePoints(expected); - const escapedReceived = escapePrivateUsePoints(typedReceived.raw); + const receivedText = typedReceived.raw; const message = () => { if (pass) { if (notFound) - return messagePrefix + `Expected: not ${this.utils.printExpected(escapedExpected)}\nReceived: ${escapedReceived}` + callLogText(log); - const printedReceived = printReceivedStringContainExpectedSubstring(escapedReceived, escapedReceived.indexOf(escapedExpected), escapedExpected.length); - return messagePrefix + `Expected: not ${this.utils.printExpected(escapedExpected)}\nReceived: ${printedReceived}` + callLogText(log); + return messagePrefix + `Expected: not ${this.utils.printExpected(expected)}\nReceived: ${receivedText}` + callLogText(log); + const printedReceived = printReceivedStringContainExpectedSubstring(receivedText, receivedText.indexOf(expected), expected.length); + return messagePrefix + `Expected: not ${this.utils.printExpected(expected)}\nReceived: ${printedReceived}` + callLogText(log); } else { const labelExpected = `Expected`; if (notFound) - return messagePrefix + `${labelExpected}: ${this.utils.printExpected(escapedExpected)}\nReceived: ${escapedReceived}` + callLogText(log); - return messagePrefix + this.utils.printDiffOrStringify(escapedExpected, escapedReceived, labelExpected, 'Received', false) + callLogText(log); + return messagePrefix + `${labelExpected}: ${this.utils.printExpected(expected)}\nReceived: ${receivedText}` + callLogText(log); + return messagePrefix + this.utils.printDiffOrStringify(expected, receivedText, labelExpected, 'Received', false) + callLogText(log); } }; @@ -118,10 +117,6 @@ export async function toMatchAriaSnapshot( }; } -function escapePrivateUsePoints(str: string) { - return escapeTemplateString(str).replace(/[\uE000-\uF8FF]/g, char => `\\u${char.charCodeAt(0).toString(16).padStart(4, '0')}`); -} - function unshift(snapshot: string): string { const lines = snapshot.split('\n'); let whitespacePrefixLength = 100; @@ -131,7 +126,6 @@ function unshift(snapshot: string): string { const match = line.match(/^(\s*)/); if (match && match[1].length < whitespacePrefixLength) whitespacePrefixLength = match[1].length; - break; } return lines.filter(t => t.trim()).map(line => line.substring(whitespacePrefixLength)).join('\n'); } diff --git a/packages/playwright/src/reporters/base.ts b/packages/playwright/src/reporters/base.ts index 3e452d6c44..9317e4e1bc 100644 --- a/packages/playwright/src/reporters/base.ts +++ b/packages/playwright/src/reporters/base.ts @@ -383,8 +383,9 @@ export function formatTestTitle(config: FullConfig, test: TestCase, step?: TestS else location = `${relativeTestPath(config, test)}:${step?.location?.line ?? test.location.line}:${step?.location?.column ?? test.location.column}`; const projectTitle = projectName ? `[${projectName}] › ` : ''; - const tags = test.tags.length > 0 ? ` ${test.tags.join(' ')}` : ''; - return `${projectTitle}${location} › ${titles.join(' › ')}${stepSuffix(step)}${tags}`; + const testTitle = `${projectTitle}${location} › ${titles.join(' › ')}`; + const extraTags = test.tags.filter(t => !testTitle.includes(t)); + return `${testTitle}${stepSuffix(step)}${extraTags.length ? ' ' + extraTags.join(' ') : ''}`; } export function formatTestHeader(config: FullConfig, test: TestCase, options: { indent?: string, index?: number, mode?: 'default' | 'error' } = {}): string { diff --git a/packages/playwright/src/reporters/html.ts b/packages/playwright/src/reporters/html.ts index 584c11bae8..a5c9e31798 100644 --- a/packages/playwright/src/reporters/html.ts +++ b/packages/playwright/src/reporters/html.ts @@ -310,6 +310,33 @@ class HtmlBuilder { this._addDataFile('report.json', htmlReport); + let singleTestId: string | undefined; + if (htmlReport.stats.total === 1) { + const testFile: TestFile = data.values().next().value.testFile; + singleTestId = testFile.tests[0].testId; + } + + if (process.env.PW_HMR === '1') { + const redirectFile = path.join(this._reportFolder, 'index.html'); + + await this._writeReportData(redirectFile); + + async function redirect() { + const hmrURL = new URL('http://localhost:44224'); // dev server, port is harcoded in build.js + const popup = window.open(hmrURL); + window.addEventListener('message', evt => { + if (evt.source === popup && evt.data === 'ready') { + popup!.postMessage((window as any).playwrightReportBase64, hmrURL.origin); + window.close(); + } + }, { once: true }); + } + + fs.appendFileSync(redirectFile, ``); + + return { ok, singleTestId }; + } + // Copy app. const appFolder = path.join(require.resolve('playwright-core'), '..', 'lib', 'vite', 'htmlReport'); await copyFileAndMakeWritable(path.join(appFolder, 'index.html'), path.join(this._reportFolder, 'index.html')); @@ -332,25 +359,22 @@ class HtmlBuilder { } } - // Inline report data. - const indexFile = path.join(this._reportFolder, 'index.html'); - fs.appendFileSync(indexFile, ''); - - let singleTestId: string | undefined; - if (htmlReport.stats.total === 1) { - const testFile: TestFile = data.values().next().value.testFile; - singleTestId = testFile.tests[0].testId; - } - - return { ok, singleTestId }; + fs.appendFileSync(filePath, '";'); } private _addDataFile(fileName: string, data: any) { diff --git a/packages/playwright/src/reporters/merge.ts b/packages/playwright/src/reporters/merge.ts index 5eedcac136..102335cceb 100644 --- a/packages/playwright/src/reporters/merge.ts +++ b/packages/playwright/src/reporters/merge.ts @@ -18,7 +18,7 @@ import fs from 'fs'; import path from 'path'; import type { ReporterDescription } from '../../types/test'; import type { FullConfigInternal } from '../common/config'; -import type { JsonConfig, JsonEvent, JsonFullResult, JsonLocation, JsonProject, JsonSuite, JsonTestCase, JsonTestResultEnd, JsonTestStepStart } from '../isomorphic/teleReceiver'; +import type { JsonConfig, JsonEvent, JsonFullResult, JsonLocation, JsonProject, JsonSuite, JsonTestCase, JsonTestResultEnd, JsonTestStepStart, JsonTestStepEnd } from '../isomorphic/teleReceiver'; import { TeleReporterReceiver } from '../isomorphic/teleReceiver'; import { JsonStringInternalizer, StringInternPool } from '../isomorphic/stringInternPool'; import { createReporters } from '../runner/reporters'; @@ -471,7 +471,7 @@ class PathSeparatorPatcher { } if (jsonEvent.method === 'onTestEnd') { const testResult = jsonEvent.params.result as JsonTestResultEnd; - testResult.errors.forEach(error => this._updateLocation(error.location)); + testResult.errors.forEach(error => this._updateErrorLocations(error)); testResult.attachments.forEach(attachment => { if (attachment.path) attachment.path = this._updatePath(attachment.path); @@ -483,6 +483,11 @@ class PathSeparatorPatcher { this._updateLocation(step.location); return; } + if (jsonEvent.method === 'onStepEnd') { + const step = jsonEvent.params.step as JsonTestStepEnd; + this._updateErrorLocations(step.error); + return; + } } private _updateProject(project: JsonProject) { @@ -504,6 +509,13 @@ class PathSeparatorPatcher { } } + private _updateErrorLocations(error: TestError | undefined) { + while (error) { + this._updateLocation(error.location); + error = error.cause; + } + } + private _updateLocation(location?: JsonLocation) { if (location) location.file = this._updatePath(location.file); diff --git a/packages/playwright/src/runner/rebase.ts b/packages/playwright/src/runner/rebase.ts index 7558ea0800..bc59e8374a 100644 --- a/packages/playwright/src/runner/rebase.ts +++ b/packages/playwright/src/runner/rebase.ts @@ -19,10 +19,10 @@ import fs from 'fs'; import type { T } from '../transform/babelBundle'; import { types, traverse, babelParse } from '../transform/babelBundle'; import { MultiMap } from 'playwright-core/lib/utils'; -import { generateUnifiedDiff } from 'playwright-core/lib/utils'; -import { colors } from 'playwright-core/lib/utilsBundle'; +import { colors, diff } from 'playwright-core/lib/utilsBundle'; import type { FullConfigInternal } from '../common/config'; import { filterProjects } from './projectUtils'; +import type { InternalReporter } from '../reporters/internalReporter'; const t: typeof T = types; type Location = { @@ -43,7 +43,7 @@ export function addSuggestedRebaseline(location: Location, suggestedRebaseline: suggestedRebaselines.set(location.file, { location, code: suggestedRebaseline }); } -export async function applySuggestedRebaselines(config: FullConfigInternal) { +export async function applySuggestedRebaselines(config: FullConfigInternal, reporter: InternalReporter) { if (config.config.updateSnapshots !== 'all' && config.config.updateSnapshots !== 'missing') return; if (!suggestedRebaselines.size) @@ -83,6 +83,10 @@ export async function applySuggestedRebaselines(config: FullConfigInternal) { const indent = lines[matcher.loc!.start.line - 1].match(/^\s*/)![0]; const newText = replacement.code.replace(/\{indent\}/g, indent); ranges.push({ start: matcher.start!, end: node.end!, oldText: source.substring(matcher.start!, node.end!), newText }); + // We can have multiple, hopefully equal, replacements for the same location, + // for example when a single test runs multiple times because of projects or retries. + // Do not apply multiple replacements for the same assertion. + break; } } }); @@ -94,7 +98,7 @@ export async function applySuggestedRebaselines(config: FullConfigInternal) { const relativeName = path.relative(process.cwd(), fileName); files.push(relativeName); - patches.push(generateUnifiedDiff(source, result, relativeName.replace(/\\/g, '/'))); + patches.push(createPatch(relativeName, source, result)); } const patchFile = path.join(project.project.outputDir, 'rebaselines.patch'); @@ -102,6 +106,16 @@ export async function applySuggestedRebaselines(config: FullConfigInternal) { await fs.promises.writeFile(patchFile, patches.join('\n')); const fileList = files.map(file => ' ' + colors.dim(file)).join('\n'); - // eslint-disable-next-line no-console - console.log(`New baselines created for:\n\n${fileList}\n\n ` + colors.cyan('git apply ' + path.relative(process.cwd(), patchFile)) + '\n'); + reporter.onStdErr(`\nNew baselines created for:\n\n${fileList}\n\n ` + colors.cyan('git apply ' + path.relative(process.cwd(), patchFile)) + '\n'); +} + +function createPatch(fileName: string, before: string, after: string) { + const file = fileName.replace(/\\/g, '/'); + const text = diff.createPatch(file, before, after, undefined, undefined, { context: 3 }); + return [ + 'diff --git a/' + file + ' b/' + file, + '--- a/' + file, + '+++ b/' + file, + ...text.split('\n').slice(4) + ].join('\n'); } diff --git a/packages/playwright/src/runner/runner.ts b/packages/playwright/src/runner/runner.ts index 966fb13e92..5a015ec755 100644 --- a/packages/playwright/src/runner/runner.ts +++ b/packages/playwright/src/runner/runner.ts @@ -19,12 +19,11 @@ import type { FullResult, TestError } from '../../types/testReporter'; import { webServerPluginsForConfig } from '../plugins/webServerPlugin'; import { collectFilesForProject, filterProjects } from './projectUtils'; import { createErrorCollectingReporter, createReporters } from './reporters'; -import { TestRun, createClearCacheTask, createGlobalSetupTasks, createLoadTask, createPluginSetupTasks, createReportBeginTask, createRunTestsTasks, createStartDevServerTask, runTasks } from './tasks'; +import { TestRun, createApplyRebaselinesTask, createClearCacheTask, createGlobalSetupTasks, createLoadTask, createPluginSetupTasks, createReportBeginTask, createRunTestsTasks, createStartDevServerTask, runTasks } from './tasks'; import type { FullConfigInternal } from '../common/config'; import { affectedTestFiles } from '../transform/compilationCache'; import { InternalReporter } from '../reporters/internalReporter'; import { LastRunReporter } from './lastRun'; -import { applySuggestedRebaselines } from './rebase'; type ProjectConfigWithFiles = { name: string; @@ -83,14 +82,13 @@ export class Runner { createLoadTask('in-process', { failOnLoadErrors: true, filterOnly: false }), createReportBeginTask(), ] : [ + createApplyRebaselinesTask(), ...createGlobalSetupTasks(config), createLoadTask('in-process', { filterOnly: true, failOnLoadErrors: true }), ...createRunTestsTasks(config), ]; const status = await runTasks(new TestRun(config, reporter), tasks, config.config.globalTimeout); - await applySuggestedRebaselines(config); - // Calling process.exit() might truncate large stdout/stderr output. // See https://github.com/nodejs/node/issues/6456. // See https://github.com/nodejs/node/issues/12921 diff --git a/packages/playwright/src/runner/tasks.ts b/packages/playwright/src/runner/tasks.ts index 528cac47cd..84cffac573 100644 --- a/packages/playwright/src/runner/tasks.ts +++ b/packages/playwright/src/runner/tasks.ts @@ -34,6 +34,7 @@ import { detectChangedTestFiles } from './vcs'; import type { InternalReporter } from '../reporters/internalReporter'; import { cacheDir } from '../transform/compilationCache'; import type { FullResult } from '../../types/testReporter'; +import { applySuggestedRebaselines } from './rebase'; const readDirAsync = promisify(fs.readdir); @@ -97,12 +98,11 @@ export function createGlobalSetupTasks(config: FullConfigInternal) { const tasks: Task[] = []; if (!config.configCLIOverrides.preserveOutputDir && !process.env.PW_TEST_NO_REMOVE_OUTPUT_DIRS) tasks.push(createRemoveOutputDirsTask()); - tasks.push(...createPluginSetupTasks(config)); - if (config.globalSetups.length || config.globalTeardowns.length) { - const length = Math.max(config.globalSetups.length, config.globalTeardowns.length); - for (let i = 0; i < length; i++) - tasks.push(createGlobalSetupTask(i, length)); - } + tasks.push( + ...createPluginSetupTasks(config), + ...config.globalTeardowns.map(file => createGlobalTeardownTask(file, config)).reverse(), + ...config.globalSetups.map(file => createGlobalSetupTask(file, config)), + ); return tasks; } @@ -164,28 +164,35 @@ function createPluginBeginTask(plugin: TestRunnerPluginRegistration): Task { - let globalSetupResult: any; - let globalSetupFinished = false; - let teardownHook: any; - +function createGlobalSetupTask(file: string, config: FullConfigInternal): Task { let title = 'global setup'; - if (length > 1) - title += ` #${index}`; + if (config.globalSetups.length > 1) + title += ` (${file})`; + let globalSetupResult: any; return { title, setup: async ({ config }) => { - const setupHook = config.globalSetups[index] ? await loadGlobalHook(config, config.globalSetups[index]) : undefined; - teardownHook = config.globalTeardowns[index] ? await loadGlobalHook(config, config.globalTeardowns[index]) : undefined; - globalSetupResult = setupHook ? await setupHook(config.config) : undefined; - globalSetupFinished = true; + const setupHook = await loadGlobalHook(config, file); + globalSetupResult = await setupHook(config.config); }, - teardown: async ({ config }) => { + teardown: async () => { if (typeof globalSetupResult === 'function') await globalSetupResult(); - if (globalSetupFinished) - await teardownHook?.(config.config); + }, + }; +} + +function createGlobalTeardownTask(file: string, config: FullConfigInternal): Task { + let title = 'global teardown'; + if (config.globalTeardowns.length > 1) + title += ` (${file})`; + + return { + title, + teardown: async ({ config }) => { + const teardownHook = await loadGlobalHook(config, file); + await teardownHook(config.config); }, }; } @@ -274,6 +281,15 @@ export function createLoadTask(mode: 'out-of-process' | 'in-process', options: { }; } +export function createApplyRebaselinesTask(): Task { + return { + title: 'apply rebaselines', + teardown: async ({ config, reporter }) => { + await applySuggestedRebaselines(config, reporter); + }, + }; +} + function createPhasesTask(): Task { return { title: 'create phases', diff --git a/packages/playwright/src/runner/testServer.ts b/packages/playwright/src/runner/testServer.ts index ff37da717c..981a1580f0 100644 --- a/packages/playwright/src/runner/testServer.ts +++ b/packages/playwright/src/runner/testServer.ts @@ -23,7 +23,7 @@ import type * as reporterTypes from '../../types/testReporter'; import { affectedTestFiles, collectAffectedTestFiles, dependenciesForTestFile } from '../transform/compilationCache'; import type { ConfigLocation, FullConfigInternal } from '../common/config'; import { createErrorCollectingReporter, createReporterForTestServer, createReporters } from './reporters'; -import { TestRun, runTasks, createLoadTask, createRunTestsTasks, createReportBeginTask, createListFilesTask, runTasksDeferCleanup, createClearCacheTask, createGlobalSetupTasks, createStartDevServerTask } from './tasks'; +import { TestRun, runTasks, createLoadTask, createRunTestsTasks, createReportBeginTask, createListFilesTask, runTasksDeferCleanup, createClearCacheTask, createGlobalSetupTasks, createStartDevServerTask, createApplyRebaselinesTask } from './tasks'; import { open } from 'playwright-core/lib/utilsBundle'; import ListReporter from '../reporters/list'; import { SigIntWatcher } from './sigIntWatcher'; @@ -336,6 +336,7 @@ export class TestServerDispatcher implements TestServerInterface { const reporter = new InternalReporter([...configReporters, wireReporter]); const stop = new ManualPromise(); const tasks = [ + createApplyRebaselinesTask(), createLoadTask('out-of-process', { filterOnly: true, failOnLoadErrors: false, doNotRunDepsOutsideProjectFilter: true }), ...createRunTestsTasks(config), ]; diff --git a/packages/playwright/src/worker/testInfo.ts b/packages/playwright/src/worker/testInfo.ts index b5b1010ff2..8b965e0a14 100644 --- a/packages/playwright/src/worker/testInfo.ts +++ b/packages/playwright/src/worker/testInfo.ts @@ -238,15 +238,15 @@ export class TestInfoImpl implements TestInfo { } } - _addStep(data: Omit): TestStepInternal { + _addStep(data: Omit, parentStep?: TestStepInternal): TestStepInternal { const stepId = `${data.category}@${++this._lastStepId}`; - let parentStep: TestStepInternal | undefined; if (data.isStage) { // Predefined stages form a fixed hierarchy - use the current one as parent. parentStep = this._findLastStageStep(this._steps); } else { - parentStep = zones.zoneData('stepZone'); + if (!parentStep) + parentStep = zones.zoneData('stepZone'); if (!parentStep) { // If no parent step on stack, assume the current stage as parent. parentStep = this._findLastStageStep(this._steps); diff --git a/packages/playwright/types/test.d.ts b/packages/playwright/types/test.d.ts index 706d567dcb..715762cffe 100644 --- a/packages/playwright/types/test.d.ts +++ b/packages/playwright/types/test.d.ts @@ -5536,7 +5536,7 @@ export interface TestType(title: string, body: () => T | Promise, options?: { box?: boolean, location?: Location }): Promise; + step(title: string, body: () => T | Promise, options?: { box?: boolean, location?: Location, timeout?: number }): Promise; /** * `expect` function can be used to create test assertions. Read more about [test assertions](https://playwright.dev/docs/test-assertions). * @@ -7899,7 +7899,7 @@ interface LocatorAssertions { * @param name Expected accessible name. * @param options */ - toHaveAccessibleName(name: string|RegExp, options?: { + toHaveAccessibleName(name: string|RegExp|ReadonlyArray, options?: { /** * Whether to perform case-insensitive match. * [`ignoreCase`](https://playwright.dev/docs/api/class-locatorassertions#locator-assertions-to-have-accessible-name-option-ignore-case) @@ -8414,7 +8414,7 @@ interface LocatorAssertions { }): Promise; /** - * Asserts that the target element matches the given accessibility snapshot. + * Asserts that the target element matches the given [accessibility snapshot](https://playwright.dev/docs/aria-snapshots). * * **Usage** * diff --git a/packages/protocol/src/channels.ts b/packages/protocol/src/channels.ts index 5b37b33bcf..27c4242fe5 100644 --- a/packages/protocol/src/channels.ts +++ b/packages/protocol/src/channels.ts @@ -741,10 +741,12 @@ export type DebugControllerSetRecorderModeOptions = { }; export type DebugControllerSetRecorderModeResult = void; export type DebugControllerHighlightParams = { - selector: string, + selector?: string, + ariaTemplate?: string, }; export type DebugControllerHighlightOptions = { - + selector?: string, + ariaTemplate?: string, }; export type DebugControllerHighlightResult = void; export type DebugControllerHideHighlightParams = {}; @@ -4086,6 +4088,8 @@ export interface TracingChannel extends TracingEventTarget, Channel { _type_Tracing: boolean; tracingStart(params: TracingTracingStartParams, metadata?: CallMetadata): Promise; tracingStartChunk(params: TracingTracingStartChunkParams, metadata?: CallMetadata): Promise; + tracingGroup(params: TracingTracingGroupParams, metadata?: CallMetadata): Promise; + tracingGroupEnd(params?: TracingTracingGroupEndParams, metadata?: CallMetadata): Promise; tracingStopChunk(params: TracingTracingStopChunkParams, metadata?: CallMetadata): Promise; tracingStop(params?: TracingTracingStopParams, metadata?: CallMetadata): Promise; } @@ -4113,6 +4117,25 @@ export type TracingTracingStartChunkOptions = { export type TracingTracingStartChunkResult = { traceName: string, }; +export type TracingTracingGroupParams = { + name: string, + location?: { + file: string, + line?: number, + column?: number, + }, +}; +export type TracingTracingGroupOptions = { + location?: { + file: string, + line?: number, + column?: number, + }, +}; +export type TracingTracingGroupResult = void; +export type TracingTracingGroupEndParams = {}; +export type TracingTracingGroupEndOptions = {}; +export type TracingTracingGroupEndResult = void; export type TracingTracingStopChunkParams = { mode: 'archive' | 'discard' | 'entries', }; diff --git a/packages/protocol/src/protocol.yml b/packages/protocol/src/protocol.yml index 82de53be24..d9597c2295 100644 --- a/packages/protocol/src/protocol.yml +++ b/packages/protocol/src/protocol.yml @@ -791,7 +791,8 @@ DebugController: highlight: parameters: - selector: string + selector: string? + ariaTemplate: string? hideHighlight: @@ -3198,6 +3199,18 @@ Tracing: returns: traceName: string + tracingGroup: + parameters: + name: string + location: + type: object? + properties: + file: string + line: number? + column: number? + + tracingGroupEnd: + tracingStopChunk: parameters: mode: diff --git a/packages/recorder/package.json b/packages/recorder/package.json index 8482a7a7db..0bad170fee 100644 --- a/packages/recorder/package.json +++ b/packages/recorder/package.json @@ -7,5 +7,8 @@ "dev": "vite", "build": "vite build && tsc", "preview": "vite preview" + }, + "dependencies": { + "yaml": "^2.6.0" } } diff --git a/packages/recorder/src/recorder.tsx b/packages/recorder/src/recorder.tsx index 2e05b65f6e..a34131a2c8 100644 --- a/packages/recorder/src/recorder.tsx +++ b/packages/recorder/src/recorder.tsx @@ -16,6 +16,7 @@ import type { CallLog, ElementInfo, Mode, Source } from './recorderTypes'; import { CodeMirrorWrapper } from '@web/components/codeMirrorWrapper'; +import type { SourceHighlight } from '@web/components/codeMirrorWrapper'; import { SplitView } from '@web/components/splitView'; import { TabbedPane } from '@web/components/tabbedPane'; import { Toolbar } from '@web/components/toolbar'; @@ -26,7 +27,10 @@ import { CallLogView } from './callLog'; import './recorder.css'; import { asLocator } from '@isomorphic/locatorGenerators'; import { toggleTheme } from '@web/theme'; -import { copy } from '@web/uiUtils'; +import { copy, useSetting } from '@web/uiUtils'; +import yaml from 'yaml'; +import { parseAriaKey } from '@isomorphic/ariaSnapshot'; +import type { AriaKeyError, ParsedYaml } from '@isomorphic/ariaSnapshot'; export interface RecorderProps { sources: Source[], @@ -43,8 +47,9 @@ export const Recorder: React.FC = ({ }) => { const [selectedFileId, setSelectedFileId] = React.useState(); const [runningFileId, setRunningFileId] = React.useState(); - const [selectedTab, setSelectedTab] = React.useState('log'); + const [selectedTab, setSelectedTab] = useSetting('recorderPropertiesTab', 'log'); const [ariaSnapshot, setAriaSnapshot] = React.useState(); + const [ariaSnapshotErrors, setAriaSnapshotErrors] = React.useState(); const fileId = selectedFileId || runningFileId || sources[0]?.id; @@ -62,6 +67,7 @@ export const Recorder: React.FC = ({ const language = source.language; setLocator(asLocator(language, elementInfo.selector)); setAriaSnapshot(elementInfo.ariaSnapshot); + setAriaSnapshotErrors([]); if (userGesture && selectedTab !== 'locator' && selectedTab !== 'aria') setSelectedTab('locator'); @@ -105,7 +111,17 @@ export const Recorder: React.FC = ({ if (mode === 'none' || mode === 'inspecting') window.dispatch({ event: 'setMode', params: { mode: 'standby' } }); setLocator(selector); - window.dispatch({ event: 'selectorUpdated', params: { selector } }); + window.dispatch({ event: 'highlightRequested', params: { selector } }); + }, [mode]); + + const onAriaEditorChange = React.useCallback((ariaSnapshot: string) => { + if (mode === 'none' || mode === 'inspecting') + window.dispatch({ event: 'setMode', params: { mode: 'standby' } }); + const { fragment, errors } = parseAriaSnapshot(ariaSnapshot); + setAriaSnapshotErrors(errors); + setAriaSnapshot(ariaSnapshot); + if (!errors.length) + window.dispatch({ event: 'highlightRequested', params: { ariaTemplate: fragment } }); }, [mode]); return
@@ -137,6 +153,9 @@ export const Recorder: React.FC = ({ { window.dispatch({ event: 'setMode', params: { mode: mode === 'assertingValue' ? 'recording' : 'assertingValue' } }); }}> + { + window.dispatch({ event: 'setMode', params: { mode: mode === 'assertingSnapshot' ? 'recording' : 'assertingSnapshot' } }); + }}> { copy(source.text); @@ -170,7 +189,7 @@ export const Recorder: React.FC = ({ { id: 'locator', title: 'Locator', - render: () => + render: () => }, { id: 'log', @@ -179,8 +198,8 @@ export const Recorder: React.FC = ({ }, { id: 'aria', - title: 'Accessibility', - render: () => + title: 'Aria', + render: () => }, ]} selectedTab={selectedTab} @@ -189,3 +208,57 @@ export const Recorder: React.FC = ({ />
; }; + +function parseAriaSnapshot(ariaSnapshot: string): { fragment?: ParsedYaml, errors: SourceHighlight[] } { + const lineCounter = new yaml.LineCounter(); + const yamlDoc = yaml.parseDocument(ariaSnapshot, { + keepSourceTokens: true, + lineCounter, + prettyErrors: false, + }); + + const errors: SourceHighlight[] = []; + for (const error of yamlDoc.errors) { + errors.push({ + line: lineCounter.linePos(error.pos[0]).line, + type: 'subtle-error', + message: error.message, + }); + } + + if (yamlDoc.errors.length) + return { errors }; + + const handleKey = (key: yaml.Scalar) => { + try { + parseAriaKey(key.value); + } catch (e) { + const keyError = e as AriaKeyError; + const linePos = lineCounter.linePos(key.srcToken!.offset + keyError.pos); + errors.push({ + message: keyError.shortMessage, + line: linePos.line, + column: linePos.col, + type: 'subtle-error', + }); + } + }; + const visitSeq = (seq: yaml.YAMLSeq) => { + for (const item of seq.items) { + if (item instanceof yaml.YAMLMap) { + const map = item as yaml.YAMLMap; + for (const entry of map.items) { + if (entry.key instanceof yaml.Scalar) + handleKey(entry.key); + if (entry.value instanceof yaml.YAMLSeq) + visitSeq(entry.value); + } + continue; + } + if (item instanceof yaml.Scalar) + handleKey(item); + } + }; + visitSeq(yamlDoc.contents as yaml.YAMLSeq); + return errors.length ? { errors } : { fragment: yamlDoc.toJSON(), errors }; +} diff --git a/packages/recorder/src/recorderTypes.ts b/packages/recorder/src/recorderTypes.ts index 22afde3dad..4822dda46f 100644 --- a/packages/recorder/src/recorderTypes.ts +++ b/packages/recorder/src/recorderTypes.ts @@ -15,6 +15,7 @@ */ import type { Language } from '../../playwright-core/src/utils/isomorphic/locatorGenerators'; +import type { ParsedYaml } from '@isomorphic/ariaSnapshot'; export type Point = { x: number; y: number }; @@ -41,7 +42,7 @@ export type EventData = { | 'step' | 'pause' | 'setMode' - | 'selectorUpdated' + | 'highlightRequested' | 'fileChanged'; params: any; }; @@ -54,6 +55,7 @@ export type UIState = { mode: Mode; actionPoint?: Point; actionSelector?: string; + ariaTemplate?: ParsedYaml; language: Language; testIdAttributeName: string; overlay: OverlayState; diff --git a/packages/trace-viewer/.gitignore b/packages/trace-viewer/.gitignore index a547bf36d8..9c0fa8b116 100644 --- a/packages/trace-viewer/.gitignore +++ b/packages/trace-viewer/.gitignore @@ -22,3 +22,5 @@ dist-ssr *.njsproj *.sln *.sw? + +public/sw.bundle.js diff --git a/packages/trace-viewer/embedded.html b/packages/trace-viewer/embedded.html deleted file mode 100644 index 7d0fd2f175..0000000000 --- a/packages/trace-viewer/embedded.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - Playwright Trace Viewer for VS Code - - -
- - - diff --git a/packages/trace-viewer/src/embedded.tsx b/packages/trace-viewer/src/embedded.tsx deleted file mode 100644 index 4f1503dcf2..0000000000 --- a/packages/trace-viewer/src/embedded.tsx +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import '@web/common.css'; -import { applyTheme } from '@web/theme'; -import '@web/third_party/vscode/codicon.css'; -import * as ReactDOM from 'react-dom/client'; -import { EmbeddedWorkbenchLoader } from './ui/embeddedWorkbenchLoader'; - -(async () => { - applyTheme(); - - // workaround to send keystrokes back to vscode webview to keep triggering key bindings there - const handleKeyEvent = (e: KeyboardEvent) => { - if (!e.isTrusted) - return; - window.parent?.postMessage({ - type: e.type, - key: e.key, - keyCode: e.keyCode, - code: e.code, - shiftKey: e.shiftKey, - altKey: e.altKey, - ctrlKey: e.ctrlKey, - metaKey: e.metaKey, - repeat: e.repeat, - }, '*'); - }; - window.addEventListener('keydown', handleKeyEvent); - window.addEventListener('keyup', handleKeyEvent); - - if (window.location.protocol !== 'file:') { - if (!navigator.serviceWorker) - throw new Error(`Service workers are not supported.\nMake sure to serve the Trace Viewer (${window.location}) via HTTPS or localhost.`); - navigator.serviceWorker.register('sw.bundle.js'); - if (!navigator.serviceWorker.controller) { - await new Promise(f => { - navigator.serviceWorker.oncontrollerchange = () => f(); - }); - } - - // Keep SW running. - setInterval(function() { fetch('ping'); }, 10000); - } - - ReactDOM.createRoot(document.querySelector('#root')!).render(); -})(); diff --git a/packages/trace-viewer/src/sw/main.ts b/packages/trace-viewer/src/sw/main.ts index 6fcb08daa7..4d01ef2a61 100644 --- a/packages/trace-viewer/src/sw/main.ts +++ b/packages/trace-viewer/src/sw/main.ts @@ -18,7 +18,7 @@ import { splitProgress } from './progress'; import { unwrapPopoutUrl } from './snapshotRenderer'; import { SnapshotServer } from './snapshotServer'; import { TraceModel } from './traceModel'; -import { FetchTraceModelBackend, ZipTraceModelBackend } from './traceModelBackends'; +import { FetchTraceModelBackend, TraceViewerServer, ZipTraceModelBackend } from './traceModelBackends'; import { TraceVersionError } from './traceModernizer'; // @ts-ignore @@ -36,13 +36,18 @@ const scopePath = new URL(self.registration.scope).pathname; const loadedTraces = new Map(); -const clientIdToTraceUrls = new Map }>(); +const clientIdToTraceUrls = new Map, traceViewerServer: TraceViewerServer }>(); -async function loadTrace(traceUrl: string, traceFileName: string | null, clientId: string, limit: number | undefined, progress: (done: number, total: number) => undefined): Promise { +async function loadTrace(traceUrl: string, traceFileName: string | null, client: any | undefined, limit: number | undefined, progress: (done: number, total: number) => undefined): Promise { await gc(); + const clientId = client?.id ?? ''; let data = clientIdToTraceUrls.get(clientId); if (!data) { - data = { limit, traceUrls: new Set() }; + let traceViewerServerBaseUrl = new URL('../', client?.url ?? self.registration.scope); + if (traceViewerServerBaseUrl.searchParams.has('server')) + traceViewerServerBaseUrl = new URL(traceViewerServerBaseUrl.searchParams.get('server')!, traceViewerServerBaseUrl); + + data = { limit, traceUrls: new Set(), traceViewerServer: new TraceViewerServer(traceViewerServerBaseUrl) }; clientIdToTraceUrls.set(clientId, data); } data.traceUrls.add(traceUrl); @@ -51,7 +56,7 @@ async function loadTrace(traceUrl: string, traceFileName: string | null, clientI try { // Allow 10% to hop from sw to page. const [fetchProgress, unzipProgress] = splitProgress(progress, [0.5, 0.4, 0.1]); - const backend = traceUrl.endsWith('json') ? new FetchTraceModelBackend(traceUrl) : new ZipTraceModelBackend(traceUrl, fetchProgress); + const backend = traceUrl.endsWith('json') ? new FetchTraceModelBackend(traceUrl, data.traceViewerServer) : new ZipTraceModelBackend(traceUrl, data.traceViewerServer, fetchProgress); await traceModel.load(backend, unzipProgress); } catch (error: any) { // eslint-disable-next-line no-console @@ -98,7 +103,7 @@ async function doFetch(event: FetchEvent): Promise { if (relativePath === '/contexts') { try { const limit = url.searchParams.has('limit') ? +url.searchParams.get('limit')! : undefined; - const traceModel = await loadTrace(traceUrl!, url.searchParams.get('traceFileName'), event.clientId, limit, (done: number, total: number) => { + const traceModel = await loadTrace(traceUrl!, url.searchParams.get('traceFileName'), client, limit, (done: number, total: number) => { client.postMessage({ method: 'progress', params: { done, total } }); }); return new Response(JSON.stringify(traceModel!.contextEntries), { @@ -148,7 +153,18 @@ async function doFetch(event: FetchEvent): Promise { return new Response(null, { status: 404 }); } - // Fallback to network. + if (relativePath.startsWith('/file/')) { + const path = url.searchParams.get('path')!; + const traceViewerServer = clientIdToTraceUrls.get(event.clientId ?? '')?.traceViewerServer; + if (!traceViewerServer) + throw new Error('client is not initialized'); + const response = await traceViewerServer.readFile(path); + if (!response) + return new Response(null, { status: 404 }); + return response; + } + + // Fallback for static assets. return fetch(event.request); } diff --git a/packages/trace-viewer/src/sw/snapshotRenderer.ts b/packages/trace-viewer/src/sw/snapshotRenderer.ts index a9f89ba273..f4e9d908fb 100644 --- a/packages/trace-viewer/src/sw/snapshotRenderer.ts +++ b/packages/trace-viewer/src/sw/snapshotRenderer.ts @@ -427,14 +427,20 @@ function snapshotScript(...targetIds: (string | undefined)[]) { for (const canvas of canvasElements) { const context = canvas.getContext('2d')!; - const boundingRect = canvas.getBoundingClientRect(); - const xStart = boundingRect.left / window.innerWidth; - const yStart = boundingRect.top / window.innerHeight; - const xEnd = boundingRect.right / window.innerWidth; - const yEnd = boundingRect.bottom / window.innerHeight; + const boundingRectAttribute = canvas.getAttribute('__playwright_bounding_rect__'); + canvas.removeAttribute('__playwright_bounding_rect__'); + if (!boundingRectAttribute) + continue; - const partiallyUncaptured = xEnd > 1 || yEnd > 1; - const fullyUncaptured = xStart > 1 || yStart > 1; + let boundingRect: { left: number, top: number, right: number, bottom: number }; + try { + boundingRect = JSON.parse(boundingRectAttribute); + } catch (e) { + continue; + } + + const partiallyUncaptured = boundingRect.right > 1 || boundingRect.bottom > 1; + const fullyUncaptured = boundingRect.left > 1 || boundingRect.top > 1; if (fullyUncaptured) { canvas.title = `Playwright couldn't capture canvas contents because it's located outside the viewport.`; continue; @@ -442,10 +448,10 @@ function snapshotScript(...targetIds: (string | undefined)[]) { drawCheckerboard(context, canvas); - context.drawImage(img, xStart * img.width, yStart * img.height, (xEnd - xStart) * img.width, (yEnd - yStart) * img.height, 0, 0, canvas.width, canvas.height); + context.drawImage(img, boundingRect.left * img.width, boundingRect.top * img.height, (boundingRect.right - boundingRect.left) * img.width, (boundingRect.bottom - boundingRect.top) * img.height, 0, 0, canvas.width, canvas.height); if (isUnderTest) // eslint-disable-next-line no-console - console.log(`canvas drawn:`, JSON.stringify([xStart, yStart, xEnd, yEnd].map(v => Math.floor(v * 100)))); + console.log(`canvas drawn:`, JSON.stringify([boundingRect.left, boundingRect.top, (boundingRect.right - boundingRect.left), (boundingRect.bottom - boundingRect.top)].map(v => Math.floor(v * 100)))); if (partiallyUncaptured) canvas.title = `Playwright couldn't capture full canvas contents because it's located partially outside the viewport.`; diff --git a/packages/trace-viewer/src/sw/traceModelBackends.ts b/packages/trace-viewer/src/sw/traceModelBackends.ts index 19c5fc2dee..95efffd502 100644 --- a/packages/trace-viewer/src/sw/traceModelBackends.ts +++ b/packages/trace-viewer/src/sw/traceModelBackends.ts @@ -28,11 +28,11 @@ export class ZipTraceModelBackend implements TraceModelBackend { private _entriesPromise: Promise>; private _traceURL: string; - constructor(traceURL: string, progress: Progress) { + constructor(traceURL: string, server: TraceViewerServer, progress: Progress) { this._traceURL = traceURL; zipjs.configure({ baseURL: self.location.href } as any); this._zipReader = new zipjs.ZipReader( - new zipjs.HttpReader(formatUrl(traceURL), { mode: 'cors', preventHeadRequest: true } as any), + new zipjs.HttpReader(formatUrl(traceURL, server), { mode: 'cors', preventHeadRequest: true } as any), { useWebWorkers: false }); this._entriesPromise = this._zipReader.getEntries({ onprogress: progress }).then(entries => { const map = new Map(); @@ -83,12 +83,16 @@ export class ZipTraceModelBackend implements TraceModelBackend { export class FetchTraceModelBackend implements TraceModelBackend { private _entriesPromise: Promise>; - private _traceURL: string; + private _path: string; + private _server: TraceViewerServer; - constructor(traceURL: string) { - this._traceURL = traceURL; - this._entriesPromise = fetch('/trace/file?path=' + encodeURIComponent(traceURL)).then(async response => { - const json = JSON.parse(await response.text()); + constructor(path: string, server: TraceViewerServer) { + this._path = path; + this._server = server; + this._entriesPromise = server.readFile(path).then(async response => { + if (!response) + throw new Error('File not found'); + const json = await response.json(); const entries = new Map(); for (const entry of json.entries) entries.set(entry.name, entry.path); @@ -101,7 +105,7 @@ export class FetchTraceModelBackend implements TraceModelBackend { } traceURL(): string { - return this._traceURL; + return this._path; } async entryNames(): Promise { @@ -129,14 +133,31 @@ export class FetchTraceModelBackend implements TraceModelBackend { const fileName = entries.get(entryName); if (!fileName) return; - return fetch('/trace/file?path=' + encodeURIComponent(fileName)); + return this._server.readFile(fileName); } } -function formatUrl(trace: string) { - let url = trace.startsWith('http') || trace.startsWith('blob') ? trace : `file?path=${encodeURIComponent(trace)}`; +function formatUrl(trace: string, server: TraceViewerServer) { + let url = trace.startsWith('http') || trace.startsWith('blob') ? trace : server.getFileURL(trace).toString(); // Dropbox does not support cors. if (url.startsWith('https://www.dropbox.com/')) url = 'https://dl.dropboxusercontent.com/' + url.substring('https://www.dropbox.com/'.length); return url; } + +export class TraceViewerServer { + constructor(private readonly baseUrl: URL) {} + + getFileURL(path: string): URL { + const url = new URL('trace/file', this.baseUrl); + url.searchParams.set('path', path); + return url; + } + + async readFile(path: string): Promise { + const response = await fetch(this.getFileURL(path)); + if (response.status === 404) + return; + return response; + } +} \ No newline at end of file diff --git a/packages/trace-viewer/src/ui/actionList.tsx b/packages/trace-viewer/src/ui/actionList.tsx index d369aeede3..101c532aea 100644 --- a/packages/trace-viewer/src/ui/actionList.tsx +++ b/packages/trace-viewer/src/ui/actionList.tsx @@ -14,7 +14,7 @@ limitations under the License. */ -import type { ActionTraceEvent } from '@trace/trace'; +import type { ActionTraceEvent, AfterActionTraceEventAttachment } from '@trace/trace'; import { msToString } from '@web/uiUtils'; import * as React from 'react'; import './actionList.css'; @@ -25,6 +25,7 @@ import type { TreeState } from '@web/components/treeView'; import { TreeView } from '@web/components/treeView'; import type { ActionTraceEventInContext, ActionTreeItem } from './modelUtil'; import type { Boundaries } from './geometry'; +import { ToolbarButton } from '@web/components/toolbarButton'; export interface ActionListProps { actions: ActionTraceEventInContext[], @@ -35,6 +36,7 @@ export interface ActionListProps { onSelected?: (action: ActionTraceEventInContext) => void, onHighlighted?: (action: ActionTraceEventInContext | undefined) => void, revealConsole?: () => void, + revealAttachment(attachment: AfterActionTraceEventAttachment): void, isLive?: boolean, } @@ -49,6 +51,7 @@ export const ActionList: React.FC = ({ onSelected, onHighlighted, revealConsole, + revealAttachment, isLive, }) => { const [treeState, setTreeState] = React.useState({ expandedItems: new Map() }); @@ -68,8 +71,8 @@ export const ActionList: React.FC = ({ }, [setSelectedTime]); const render = React.useCallback((item: ActionTreeItem) => { - return renderAction(item.action!, { sdkLanguage, revealConsole, isLive, showDuration: true, showBadges: true }); - }, [isLive, revealConsole, sdkLanguage]); + return renderAction(item.action!, { sdkLanguage, revealConsole, revealAttachment, isLive, showDuration: true, showBadges: true }); + }, [isLive, revealConsole, revealAttachment, sdkLanguage]); const isVisible = React.useCallback((item: ActionTreeItem) => { return !selectedTime || !item.action || (item.action!.startTime <= selectedTime.maximum && item.action!.endTime >= selectedTime.minimum); @@ -106,13 +109,15 @@ export const renderAction = ( options: { sdkLanguage?: Language, revealConsole?: () => void, + revealAttachment?(attachment: AfterActionTraceEventAttachment): void, isLive?: boolean, showDuration?: boolean, showBadges?: boolean, }) => { - const { sdkLanguage, revealConsole, isLive, showDuration, showBadges } = options; + const { sdkLanguage, revealConsole, revealAttachment, isLive, showDuration, showBadges } = options; const { errors, warnings } = modelUtil.stats(action); const locator = action.params.selector ? asLocator(sdkLanguage || 'javascript', action.params.selector) : undefined; + const showAttachments = !!action.attachments?.length && !!revealAttachment; let time: string = ''; if (action.endTime) @@ -128,7 +133,8 @@ export const renderAction = ( {action.method === 'goto' && action.params.url &&
{action.params.url}
} {action.class === 'APIRequestContext' && action.params.url &&
{excludeOrigin(action.params.url)}
}
- {(showDuration || showBadges) &&
} + {(showDuration || showBadges || showAttachments) &&
} + {showAttachments && revealAttachment(action.attachments![0])} />} {showDuration &&
{time || }
} {showBadges &&
revealConsole?.()}> {!!errors &&
{errors}
} diff --git a/packages/trace-viewer/src/ui/attachmentsTab.css b/packages/trace-viewer/src/ui/attachmentsTab.css index db22a72f5d..c2455fc3c5 100644 --- a/packages/trace-viewer/src/ui/attachmentsTab.css +++ b/packages/trace-viewer/src/ui/attachmentsTab.css @@ -40,6 +40,11 @@ margin: 4px 8px; } +.attachment-title-highlight { + text-decoration: underline var(--vscode-terminal-findMatchBackground); + text-decoration-thickness: 1.5px; +} + .attachment-item img { flex: none; min-width: 200px; diff --git a/packages/trace-viewer/src/ui/attachmentsTab.tsx b/packages/trace-viewer/src/ui/attachmentsTab.tsx index 69bfcd68cc..cf9ed2e681 100644 --- a/packages/trace-viewer/src/ui/attachmentsTab.tsx +++ b/packages/trace-viewer/src/ui/attachmentsTab.tsx @@ -17,28 +17,37 @@ import * as React from 'react'; import './attachmentsTab.css'; import { ImageDiffView } from '@web/shared/imageDiffView'; -import type { MultiTraceModel } from './modelUtil'; +import type { ActionTraceEventInContext, MultiTraceModel } from './modelUtil'; import { PlaceholderPanel } from './placeholderPanel'; import type { AfterActionTraceEventAttachment } from '@trace/trace'; import { CodeMirrorWrapper, lineHeight } from '@web/components/codeMirrorWrapper'; import { isTextualMimeType } from '@isomorphic/mimeType'; import { Expandable } from '@web/components/expandable'; import { linkifyText } from '@web/renderUtils'; +import { clsx } from '@web/uiUtils'; type Attachment = AfterActionTraceEventAttachment & { traceUrl: string }; type ExpandableAttachmentProps = { attachment: Attachment; + reveal: boolean; + highlight: boolean; }; -const ExpandableAttachment: React.FunctionComponent = ({ attachment }) => { +const ExpandableAttachment: React.FunctionComponent = ({ attachment, reveal, highlight }) => { const [expanded, setExpanded] = React.useState(false); const [attachmentText, setAttachmentText] = React.useState(null); const [placeholder, setPlaceholder] = React.useState(null); + const ref = React.useRef(null); const isTextAttachment = isTextualMimeType(attachment.contentType); const hasContent = !!attachment.sha1 || !!attachment.path; + React.useEffect(() => { + if (reveal) + ref.current?.scrollIntoView({ behavior: 'smooth' }); + }, [reveal]); + React.useEffect(() => { if (expanded && attachmentText === null && placeholder === null) { setPlaceholder('Loading ...'); @@ -56,8 +65,9 @@ const ExpandableAttachment: React.FunctionComponent = return Math.min(Math.max(5, lineCount), 20) * lineHeight; }, [attachmentText]); - const title = - {linkifyText(attachment.name)} {hasContent && download} + const title = + {linkifyText(attachment.name)} + {hasContent && download} ; if (!isTextAttachment || !hasContent) @@ -82,7 +92,9 @@ const ExpandableAttachment: React.FunctionComponent = export const AttachmentsTab: React.FunctionComponent<{ model: MultiTraceModel | undefined, -}> = ({ model }) => { + selectedAction: ActionTraceEventInContext | undefined, + revealedAttachment?: AfterActionTraceEventAttachment, +}> = ({ model, selectedAction, revealedAttachment }) => { const { diffMap, screenshots, attachments } = React.useMemo(() => { const attachments = new Set(); const screenshots = new Set(); @@ -139,12 +151,20 @@ export const AttachmentsTab: React.FunctionComponent<{ {attachments.size ?
Attachments
: undefined} {[...attachments.values()].map((a, i) => { return
- + isEqualAttachment(a, selected)) ?? false} + reveal={!!revealedAttachment && isEqualAttachment(a, revealedAttachment)} + />
; })}
; }; +function isEqualAttachment(a: Attachment, b: AfterActionTraceEventAttachment): boolean { + return a.name === b.name && a.path === b.path && a.sha1 === b.sha1; +} + function attachmentURL(attachment: Attachment, queryParams: Record = {}) { const params = new URLSearchParams(queryParams); if (attachment.sha1) { diff --git a/packages/trace-viewer/src/ui/embeddedWorkbenchLoader.css b/packages/trace-viewer/src/ui/embeddedWorkbenchLoader.css deleted file mode 100644 index 2274355322..0000000000 --- a/packages/trace-viewer/src/ui/embeddedWorkbenchLoader.css +++ /dev/null @@ -1,68 +0,0 @@ -/* - Copyright (c) Microsoft Corporation. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -.empty-state { - display: flex; - align-items: center; - justify-content: center; - flex: auto; - flex-direction: column; - background-color: var(--vscode-editor-background); - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 100; - line-height: 24px; -} - -body .empty-state { - background: rgba(255, 255, 255, 0.8); -} - -body.dark-mode .empty-state { - background: rgba(0, 0, 0, 0.8); -} - -.empty-state .title { - font-size: 24px; - font-weight: bold; - margin-bottom: 30px; -} - -.progress { - flex: none; - width: 100%; - height: 3px; - z-index: 10; -} - -.inner-progress { - background-color: var(--vscode-progressBar-background); - height: 100%; -} - -.workbench-loader { - contain: size; -} - -/* Limit to a reasonable minimum viewport */ -html, body { - min-width: 550px; - min-height: 450px; - overflow: auto; -} diff --git a/packages/trace-viewer/src/ui/embeddedWorkbenchLoader.tsx b/packages/trace-viewer/src/ui/embeddedWorkbenchLoader.tsx deleted file mode 100644 index c8b8aa216c..0000000000 --- a/packages/trace-viewer/src/ui/embeddedWorkbenchLoader.tsx +++ /dev/null @@ -1,102 +0,0 @@ -/* - Copyright (c) Microsoft Corporation. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -import * as React from 'react'; -import type { ContextEntry } from '../types/entries'; -import { MultiTraceModel } from './modelUtil'; -import './embeddedWorkbenchLoader.css'; -import { Workbench } from './workbench'; -import { currentTheme, toggleTheme } from '@web/theme'; -import type { SourceLocation } from './modelUtil'; - -function openPage(url: string, target?: string) { - if (url) - window.parent!.postMessage({ method: 'openExternal', params: { url, target } }, '*'); -} - -function openSourceLocation({ file, line, column }: SourceLocation) { - window.parent!.postMessage({ method: 'openSourceLocation', params: { file, line, column } }, '*'); -} - -export const EmbeddedWorkbenchLoader: React.FunctionComponent = () => { - const [traceURLs, setTraceURLs] = React.useState([]); - const [model, setModel] = React.useState(emptyModel); - const [progress, setProgress] = React.useState<{ done: number, total: number }>({ done: 0, total: 0 }); - const [processingErrorMessage, setProcessingErrorMessage] = React.useState(null); - - React.useEffect(() => { - window.addEventListener('message', async ({ data: { method, params } }) => { - if (method === 'loadTraceRequested') { - setTraceURLs(params.traceUrl ? [params.traceUrl] : []); - setProcessingErrorMessage(null); - } else if (method === 'applyTheme') { - if (currentTheme() !== params.theme) - toggleTheme(); - } - }); - // notify vscode that it is now listening to its messages - window.parent!.postMessage({ type: 'loaded' }, '*'); - }, []); - - React.useEffect(() => { - (async () => { - if (traceURLs.length) { - const swListener = (event: any) => { - if (event.data.method === 'progress') - setProgress(event.data.params); - }; - navigator.serviceWorker.addEventListener('message', swListener); - setProgress({ done: 0, total: 1 }); - const contextEntries: ContextEntry[] = []; - for (let i = 0; i < traceURLs.length; i++) { - const url = traceURLs[i]; - const params = new URLSearchParams(); - params.set('trace', url); - params.set('limit', String(traceURLs.length)); - const response = await fetch(`contexts?${params.toString()}`); - if (!response.ok) { - setProcessingErrorMessage((await response.json()).error); - return; - } - contextEntries.push(...(await response.json())); - } - navigator.serviceWorker.removeEventListener('message', swListener); - const model = new MultiTraceModel(contextEntries); - setProgress({ done: 0, total: 0 }); - setModel(model); - } else { - setModel(emptyModel); - } - })(); - }, [traceURLs]); - - React.useEffect(() => { - if (processingErrorMessage) - window.parent?.postMessage({ method: 'showErrorMessage', params: { message: processingErrorMessage } }, '*'); - }, [processingErrorMessage]); - - return
-
-
-
- - {!traceURLs.length &&
-
Select test to see the trace
-
} -
; -}; - -export const emptyModel = new MultiTraceModel([]); diff --git a/packages/trace-viewer/src/ui/recorder/actionListView.tsx b/packages/trace-viewer/src/ui/recorder/actionListView.tsx index a68df255ea..8e9fa0df45 100644 --- a/packages/trace-viewer/src/ui/recorder/actionListView.tsx +++ b/packages/trace-viewer/src/ui/recorder/actionListView.tsx @@ -49,10 +49,9 @@ export const ActionListView: React.FC<{ }; export const renderAction = (sdkLanguage: Language, action: actionTypes.ActionInContext) => { - const { method, params } = traceParamsForAction(action); + const { method, apiName, params } = traceParamsForAction(action); const locator = params.selector ? asLocator(sdkLanguage || 'javascript', params.selector) : undefined; - const apiName = `page.${method}`; return <>
{apiName} diff --git a/packages/trace-viewer/src/ui/settingsView.tsx b/packages/trace-viewer/src/ui/settingsView.tsx index 883e4abca5..0a4340b2b6 100644 --- a/packages/trace-viewer/src/ui/settingsView.tsx +++ b/packages/trace-viewer/src/ui/settingsView.tsx @@ -30,7 +30,7 @@ export const SettingsView: React.FunctionComponent<{ {settings.map(({ value, set, title }) => { return
; diff --git a/packages/trace-viewer/src/ui/snapshotTab.tsx b/packages/trace-viewer/src/ui/snapshotTab.tsx index bbf0e763da..8383890a2e 100644 --- a/packages/trace-viewer/src/ui/snapshotTab.tsx +++ b/packages/trace-viewer/src/ui/snapshotTab.tsx @@ -40,8 +40,7 @@ export const SnapshotTabsView: React.FunctionComponent<{ setIsInspecting: (isInspecting: boolean) => void, highlightedLocator: string, setHighlightedLocator: (locator: string) => void, - openPage?: (url: string, target?: string) => Window | any, -}> = ({ action, sdkLanguage, testIdAttributeName, isInspecting, setIsInspecting, highlightedLocator, setHighlightedLocator, openPage }) => { +}> = ({ action, sdkLanguage, testIdAttributeName, isInspecting, setIsInspecting, highlightedLocator, setHighlightedLocator }) => { const [snapshotTab, setSnapshotTab] = React.useState<'action'|'before'|'after'>('action'); const snapshots = React.useMemo(() => { @@ -66,9 +65,7 @@ export const SnapshotTabsView: React.FunctionComponent<{ })}
{ - if (!openPage) - openPage = window.open; - const win = openPage(snapshotUrls?.popoutUrl || '', '_blank'); + const win = window.open(snapshotUrls?.popoutUrl || '', '_blank'); win?.addEventListener('DOMContentLoaded', () => { const injectedScript = new InjectedScript(win as any, false, sdkLanguage, testIdAttributeName, 1, 'chromium', []); new ConsoleAPI(injectedScript); @@ -328,6 +325,7 @@ export function collectSnapshots(action: ActionTraceEvent | undefined): Snapshot } const isUnderTest = new URLSearchParams(window.location.search).has('isUnderTest'); +const serverParam = new URLSearchParams(window.location.search).get('server'); export function extendSnapshot(snapshot: Snapshot): SnapshotUrls { const params = new URLSearchParams(); @@ -346,6 +344,7 @@ export function extendSnapshot(snapshot: Snapshot): SnapshotUrls { const popoutParams = new URLSearchParams(); popoutParams.set('r', snapshotUrl); + popoutParams.set('server', serverParam ?? ''); popoutParams.set('trace', context(snapshot.action).traceUrl); if (snapshot.point) { popoutParams.set('pointX', String(snapshot.point.x)); diff --git a/packages/trace-viewer/src/ui/uiModeFiltersView.tsx b/packages/trace-viewer/src/ui/uiModeFiltersView.tsx index 314fce3a96..8ed0f47982 100644 --- a/packages/trace-viewer/src/ui/uiModeFiltersView.tsx +++ b/packages/trace-viewer/src/ui/uiModeFiltersView.tsx @@ -62,7 +62,7 @@ export const FiltersView: React.FC<{ {[...statusFilters.entries()].map(([status, value]) => { return