Title: [276861] branches/safari-612.1.12-branch
Revision
276861
Author
repst...@apple.com
Date
2021-04-30 16:04:06 -0700 (Fri, 30 Apr 2021)

Log Message

Cherry-pick r276744. rdar://problem/77402549

    experiment with averaging sampling colors across the top of the page as the scroll area background
    https://bugs.webkit.org/show_bug.cgi?id=224987
    <rdar://problem/76251889>

    Reviewed by Darin Adler.

    Source/WebCore:

    Tests: SampledPageTopColor.ZeroMaxDifference
           SampledPageTopColor.NegativeMaxDifference
           SampledPageTopColor.SolidColor
           SampledPageTopColor.DifferentColorsWithoutOutlierBelowMaxDifference
           SampledPageTopColor.DifferentColorsWithLeftOutlierAboveMaxDifference
           SampledPageTopColor.DifferentColorsWithMiddleOutlierAboveMaxDifference
           SampledPageTopColor.DifferentColorsWithRightOutlierAboveMaxDifference
           SampledPageTopColor.DifferentColorsIndividuallyAboveMaxDifference
           SampledPageTopColor.DifferentColorsCumulativelyAboveMaxDifference
           SampledPageTopColor.DisplayP3
           SampledPageTopColor.ExperimentalUseSampledPageTopColorForScrollAreaBackgroundColor

    * dom/Document.h:
    (WebCore::Document::sampledPageTopColor const): Added.
    * dom/Document.cpp:
    (WebCore::Document::enqueuePaintTimingEntryIfNeeded):
    (WebCore::colorDifference): Added.
    (WebCore::averageColor): Added.
    (WebCore::Document::determineSampledPageTopColor): Added.
    Wait until the first contentful paint before sampling. Don't sample if that location would
    fall into a 3rd-party `<iframe>`. Currently use 5 snapshots across the top of the page,
    allowing for one of either the first or last snapshot to be an outlier, which is not
    included in the average of the other snapshots that's used as the final color value. If the
    Lab color difference between any two snapshots (unless it's the first or last snapshot as
    described above) or across all the (non-outlier) snapshots is too large, bail. Only enabled
    if the `SampledPageTopColorMaxDifference` setting is greater than 0.

    * page/Page.h:
    * page/Page.cpp:
    (WebCore::Page::sampledPageTopColor const): Added.
    * page/ChromeClient.h:
    (WebCore::ChromeClient::didSamplePageTopColor const): Added.
    Pass along the `sampledPageTopColor` to the UIProcess after it's determined or if the above
    logic bails (so that the `WKWebView` can adjust `_sampledPageTopColor` to `nil`).

    * rendering/RenderLayerCompositor.cpp:
    (WebCore::RenderLayerCompositor::rootBackgroundColorOrTransparencyChanged):
    Use the `sampledPageTopColor` if the `UseSampledPageTopColorForScrollAreaBackgroundColor`
    internal preference is enabled instead of the CSS `background-color` of the `<html>`/`<body>`.

    Source/WebKit:

    * WebProcess/WebCoreSupport/WebChromeClient.h:
    * WebProcess/WebCoreSupport/WebChromeClient.cpp:
    (WebKit::WebChromeClient::didSamplePageTopColor const): Added.
    * WebProcess/WebPage/WebPage.h:
    * WebProcess/WebPage/WebPage.cpp:
    (WebKit::WebPage::didSamplePageTopColor): Added.
    Pass along the `sampledPageTopColor` to the UIProcess.

    * UIProcess/WebPageProxy.messages.in:
    * UIProcess/WebPageProxy.h:
    (WebKit::WebPageProxy::sampledPageTopColor): Added.
    * UIProcess/WebPageProxy.cpp:
    (WebKit::WebPageProxy::scrollAreaBackgroundColor const):
    (WebKit::WebPageProxy::didSamplePageTopColor): Added.
    Use the `sampledPageTopColor` if the `UseSampledPageTopColorForScrollAreaBackgroundColor`
    internal preference is enabled instead of the CSS `background-color` of the `<html>`/`<body>`.

    * UIProcess/PageClient.h:
    (WebKit::PageClient::sampledPageTopColorWillChange): Added.
    (WebKit::PageClient::sampledPageTopColorDidChange): Added.
    * UIProcess/Cocoa/PageClientImplCocoa.h:
    * UIProcess/Cocoa/PageClientImplCocoa.mm:
    (WebKit::PageClientImplCocoa::sampledPageTopColorWillChange): Added.
    (WebKit::PageClientImplCocoa::sampledPageTopColorDidChange): Added.
    Add ObjC KVO support for `-[WKWebView _sampledPageTopColor]`.

    * UIProcess/API/Cocoa/WKWebViewPrivate.h:
    * UIProcess/API/Cocoa/WKWebView.mm:
    (-[WKWebView _setupPageConfiguration:]):
    (-[WKWebView _sampledPageTopColor]): Added.
    * UIProcess/API/Cocoa/WKWebViewConfigurationPrivate.h:
    * UIProcess/API/Cocoa/WKWebViewConfiguration.mm:
    (-[WKWebViewConfiguration init]):
    (-[WKWebViewConfiguration copyWithZone:]):
    (-[WKWebViewConfiguration _setSampledPageTopColorMaxDifference:]): Added.
    (-[WKWebViewConfiguration _sampledPageTopColorMaxDifference]): Added.
    Provide SPI to configure the `SampledPageTopColorMaxDifference` preference when
    creating the `WKWebView`. Expose the result as `_sampledPageTopColor` SPI.

    Source/WTF:

    * Scripts/Preferences/WebPreferences.yaml:
    Add a `SampledPageTopColorMaxDifference` setting that controls both whether or not to sample
    colors from the top of the page (only if value > 0) and the max Lab color difference allowed
    across all samples.

    * Scripts/Preferences/WebPreferencesInternal.yaml:
    Add a `UseSampledPageTopColorForScrollAreaBackgroundColor` internal setting that controls
    whether the sampled page top color can be used as the overscroll area background color.

    Tools:

    * TestWebKitAPI/Tests/WebKitCocoa/SampledPageTopColor.mm: Added.
    (-[TestKVOWrapper initWithObservable:keyPath:callback:]):
    (-[TestKVOWrapper dealloc]):
    (-[TestKVOWrapper observeValueForKeyPath:ofObject:change:context:]):
    (createWebViewWithSampledPageTopColorMaxDifference):
    (waitForSampledPageTopColorToChangeForHTML):
    (createHTMLGradientWithColorStops):
    (TEST.SampledPageTopColor.ZeroMaxDifference):
    (TEST.SampledPageTopColor.NegativeMaxDifference):
    (TEST.SampledPageTopColor.SolidColor):
    (TEST.SampledPageTopColor.DifferentColorsWithoutOutlierBelowMaxDifference):
    (TEST.SampledPageTopColor.DifferentColorsWithLeftOutlierAboveMaxDifference):
    (TEST.SampledPageTopColor.DifferentColorsWithMiddleOutlierAboveMaxDifference):
    (TEST.SampledPageTopColor.DifferentColorsWithRightOutlierAboveMaxDifference):
    (TEST.SampledPageTopColor.DifferentColorsIndividuallyAboveMaxDifference):
    (TEST.SampledPageTopColor.DifferentColorsCumulativelyAboveMaxDifference):
    (TEST.SampledPageTopColor.DisplayP3):
    (TEST.SampledPageTopColor.ExperimentalUseSampledPageTopColorForScrollAreaBackgroundColor):

    * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:

    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@276744 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Modified Paths

Added Paths

Diff

Modified: branches/safari-612.1.12-branch/Source/WTF/ChangeLog (276860 => 276861)


--- branches/safari-612.1.12-branch/Source/WTF/ChangeLog	2021-04-30 23:01:10 UTC (rev 276860)
+++ branches/safari-612.1.12-branch/Source/WTF/ChangeLog	2021-04-30 23:04:06 UTC (rev 276861)
@@ -1,3 +1,150 @@
+2021-04-30  Russell Epstein  <repst...@apple.com>
+
+        Cherry-pick r276744. rdar://problem/77402549
+
+    experiment with averaging sampling colors across the top of the page as the scroll area background
+    https://bugs.webkit.org/show_bug.cgi?id=224987
+    <rdar://problem/76251889>
+    
+    Reviewed by Darin Adler.
+    
+    Source/WebCore:
+    
+    Tests: SampledPageTopColor.ZeroMaxDifference
+           SampledPageTopColor.NegativeMaxDifference
+           SampledPageTopColor.SolidColor
+           SampledPageTopColor.DifferentColorsWithoutOutlierBelowMaxDifference
+           SampledPageTopColor.DifferentColorsWithLeftOutlierAboveMaxDifference
+           SampledPageTopColor.DifferentColorsWithMiddleOutlierAboveMaxDifference
+           SampledPageTopColor.DifferentColorsWithRightOutlierAboveMaxDifference
+           SampledPageTopColor.DifferentColorsIndividuallyAboveMaxDifference
+           SampledPageTopColor.DifferentColorsCumulativelyAboveMaxDifference
+           SampledPageTopColor.DisplayP3
+           SampledPageTopColor.ExperimentalUseSampledPageTopColorForScrollAreaBackgroundColor
+    
+    * dom/Document.h:
+    (WebCore::Document::sampledPageTopColor const): Added.
+    * dom/Document.cpp:
+    (WebCore::Document::enqueuePaintTimingEntryIfNeeded):
+    (WebCore::colorDifference): Added.
+    (WebCore::averageColor): Added.
+    (WebCore::Document::determineSampledPageTopColor): Added.
+    Wait until the first contentful paint before sampling. Don't sample if that location would
+    fall into a 3rd-party `<iframe>`. Currently use 5 snapshots across the top of the page,
+    allowing for one of either the first or last snapshot to be an outlier, which is not
+    included in the average of the other snapshots that's used as the final color value. If the
+    Lab color difference between any two snapshots (unless it's the first or last snapshot as
+    described above) or across all the (non-outlier) snapshots is too large, bail. Only enabled
+    if the `SampledPageTopColorMaxDifference` setting is greater than 0.
+    
+    * page/Page.h:
+    * page/Page.cpp:
+    (WebCore::Page::sampledPageTopColor const): Added.
+    * page/ChromeClient.h:
+    (WebCore::ChromeClient::didSamplePageTopColor const): Added.
+    Pass along the `sampledPageTopColor` to the UIProcess after it's determined or if the above
+    logic bails (so that the `WKWebView` can adjust `_sampledPageTopColor` to `nil`).
+    
+    * rendering/RenderLayerCompositor.cpp:
+    (WebCore::RenderLayerCompositor::rootBackgroundColorOrTransparencyChanged):
+    Use the `sampledPageTopColor` if the `UseSampledPageTopColorForScrollAreaBackgroundColor`
+    internal preference is enabled instead of the CSS `background-color` of the `<html>`/`<body>`.
+    
+    Source/WebKit:
+    
+    * WebProcess/WebCoreSupport/WebChromeClient.h:
+    * WebProcess/WebCoreSupport/WebChromeClient.cpp:
+    (WebKit::WebChromeClient::didSamplePageTopColor const): Added.
+    * WebProcess/WebPage/WebPage.h:
+    * WebProcess/WebPage/WebPage.cpp:
+    (WebKit::WebPage::didSamplePageTopColor): Added.
+    Pass along the `sampledPageTopColor` to the UIProcess.
+    
+    * UIProcess/WebPageProxy.messages.in:
+    * UIProcess/WebPageProxy.h:
+    (WebKit::WebPageProxy::sampledPageTopColor): Added.
+    * UIProcess/WebPageProxy.cpp:
+    (WebKit::WebPageProxy::scrollAreaBackgroundColor const):
+    (WebKit::WebPageProxy::didSamplePageTopColor): Added.
+    Use the `sampledPageTopColor` if the `UseSampledPageTopColorForScrollAreaBackgroundColor`
+    internal preference is enabled instead of the CSS `background-color` of the `<html>`/`<body>`.
+    
+    * UIProcess/PageClient.h:
+    (WebKit::PageClient::sampledPageTopColorWillChange): Added.
+    (WebKit::PageClient::sampledPageTopColorDidChange): Added.
+    * UIProcess/Cocoa/PageClientImplCocoa.h:
+    * UIProcess/Cocoa/PageClientImplCocoa.mm:
+    (WebKit::PageClientImplCocoa::sampledPageTopColorWillChange): Added.
+    (WebKit::PageClientImplCocoa::sampledPageTopColorDidChange): Added.
+    Add ObjC KVO support for `-[WKWebView _sampledPageTopColor]`.
+    
+    * UIProcess/API/Cocoa/WKWebViewPrivate.h:
+    * UIProcess/API/Cocoa/WKWebView.mm:
+    (-[WKWebView _setupPageConfiguration:]):
+    (-[WKWebView _sampledPageTopColor]): Added.
+    * UIProcess/API/Cocoa/WKWebViewConfigurationPrivate.h:
+    * UIProcess/API/Cocoa/WKWebViewConfiguration.mm:
+    (-[WKWebViewConfiguration init]):
+    (-[WKWebViewConfiguration copyWithZone:]):
+    (-[WKWebViewConfiguration _setSampledPageTopColorMaxDifference:]): Added.
+    (-[WKWebViewConfiguration _sampledPageTopColorMaxDifference]): Added.
+    Provide SPI to configure the `SampledPageTopColorMaxDifference` preference when
+    creating the `WKWebView`. Expose the result as `_sampledPageTopColor` SPI.
+    
+    Source/WTF:
+    
+    * Scripts/Preferences/WebPreferences.yaml:
+    Add a `SampledPageTopColorMaxDifference` setting that controls both whether or not to sample
+    colors from the top of the page (only if value > 0) and the max Lab color difference allowed
+    across all samples.
+    
+    * Scripts/Preferences/WebPreferencesInternal.yaml:
+    Add a `UseSampledPageTopColorForScrollAreaBackgroundColor` internal setting that controls
+    whether the sampled page top color can be used as the overscroll area background color.
+    
+    Tools:
+    
+    * TestWebKitAPI/Tests/WebKitCocoa/SampledPageTopColor.mm: Added.
+    (-[TestKVOWrapper initWithObservable:keyPath:callback:]):
+    (-[TestKVOWrapper dealloc]):
+    (-[TestKVOWrapper observeValueForKeyPath:ofObject:change:context:]):
+    (createWebViewWithSampledPageTopColorMaxDifference):
+    (waitForSampledPageTopColorToChangeForHTML):
+    (createHTMLGradientWithColorStops):
+    (TEST.SampledPageTopColor.ZeroMaxDifference):
+    (TEST.SampledPageTopColor.NegativeMaxDifference):
+    (TEST.SampledPageTopColor.SolidColor):
+    (TEST.SampledPageTopColor.DifferentColorsWithoutOutlierBelowMaxDifference):
+    (TEST.SampledPageTopColor.DifferentColorsWithLeftOutlierAboveMaxDifference):
+    (TEST.SampledPageTopColor.DifferentColorsWithMiddleOutlierAboveMaxDifference):
+    (TEST.SampledPageTopColor.DifferentColorsWithRightOutlierAboveMaxDifference):
+    (TEST.SampledPageTopColor.DifferentColorsIndividuallyAboveMaxDifference):
+    (TEST.SampledPageTopColor.DifferentColorsCumulativelyAboveMaxDifference):
+    (TEST.SampledPageTopColor.DisplayP3):
+    (TEST.SampledPageTopColor.ExperimentalUseSampledPageTopColorForScrollAreaBackgroundColor):
+    
+    * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+    
+    
+    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@276744 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+    2021-04-28  Devin Rousso  <drou...@apple.com>
+
+            experiment with averaging sampling colors across the top of the page as the scroll area background
+            https://bugs.webkit.org/show_bug.cgi?id=224987
+            <rdar://problem/76251889>
+
+            Reviewed by Darin Adler.
+
+            * Scripts/Preferences/WebPreferences.yaml:
+            Add a `SampledPageTopColorMaxDifference` setting that controls both whether or not to sample
+            colors from the top of the page (only if value > 0) and the max Lab color difference allowed
+            across all samples.
+
+            * Scripts/Preferences/WebPreferencesInternal.yaml:
+            Add a `UseSampledPageTopColorForScrollAreaBackgroundColor` internal setting that controls
+            whether the sampled page top color can be used as the overscroll area background color.
+
 2021-04-27  Ruben Turcios  <rubent...@apple.com>
 
         Cherry-pick r276652. rdar://problem/77235499

Modified: branches/safari-612.1.12-branch/Source/WTF/Scripts/Preferences/WebPreferences.yaml (276860 => 276861)


--- branches/safari-612.1.12-branch/Source/WTF/Scripts/Preferences/WebPreferences.yaml	2021-04-30 23:01:10 UTC (rev 276860)
+++ branches/safari-612.1.12-branch/Source/WTF/Scripts/Preferences/WebPreferences.yaml	2021-04-30 23:04:06 UTC (rev 276861)
@@ -1823,6 +1823,16 @@
     WebKit:
       default: true
 
+SampledPageTopColorMaxDifference:
+  type: double
+  defaultValue:
+    WebKitLegacy:
+      default: 0
+    WebKit:
+      default: 0
+    WebCore:
+      default: 0
+
 SansSerifFontFamily:
   type: String
   webKitLegacyPreferenceKey: WebKitSansSerifFont

Modified: branches/safari-612.1.12-branch/Source/WTF/Scripts/Preferences/WebPreferencesInternal.yaml (276860 => 276861)


--- branches/safari-612.1.12-branch/Source/WTF/Scripts/Preferences/WebPreferencesInternal.yaml	2021-04-30 23:01:10 UTC (rev 276860)
+++ branches/safari-612.1.12-branch/Source/WTF/Scripts/Preferences/WebPreferencesInternal.yaml	2021-04-30 23:04:06 UTC (rev 276861)
@@ -750,6 +750,18 @@
     WebKit:
       default: defaultUseGPUProcessForWebGLEnabled()
 
+UseSampledPageTopColorForScrollAreaBackgroundColor:
+  type: bool
+  humanReadableName: "Use sampled page top color for scroll area background color"
+  humanReadableDescription: "Use sampled page top color for scroll area background color"
+  defaultValue:
+    WebKitLegacy:
+      default: false
+    WebKit:
+      default: false
+    WebCore:
+      default: false
+
 UseThemeColorForScrollAreaBackgroundColor:
   type: bool
   humanReadableName: "Use theme-color for scroll area background color"

Modified: branches/safari-612.1.12-branch/Source/WebCore/ChangeLog (276860 => 276861)


--- branches/safari-612.1.12-branch/Source/WebCore/ChangeLog	2021-04-30 23:01:10 UTC (rev 276860)
+++ branches/safari-612.1.12-branch/Source/WebCore/ChangeLog	2021-04-30 23:04:06 UTC (rev 276861)
@@ -1,3 +1,181 @@
+2021-04-30  Russell Epstein  <repst...@apple.com>
+
+        Cherry-pick r276744. rdar://problem/77402549
+
+    experiment with averaging sampling colors across the top of the page as the scroll area background
+    https://bugs.webkit.org/show_bug.cgi?id=224987
+    <rdar://problem/76251889>
+    
+    Reviewed by Darin Adler.
+    
+    Source/WebCore:
+    
+    Tests: SampledPageTopColor.ZeroMaxDifference
+           SampledPageTopColor.NegativeMaxDifference
+           SampledPageTopColor.SolidColor
+           SampledPageTopColor.DifferentColorsWithoutOutlierBelowMaxDifference
+           SampledPageTopColor.DifferentColorsWithLeftOutlierAboveMaxDifference
+           SampledPageTopColor.DifferentColorsWithMiddleOutlierAboveMaxDifference
+           SampledPageTopColor.DifferentColorsWithRightOutlierAboveMaxDifference
+           SampledPageTopColor.DifferentColorsIndividuallyAboveMaxDifference
+           SampledPageTopColor.DifferentColorsCumulativelyAboveMaxDifference
+           SampledPageTopColor.DisplayP3
+           SampledPageTopColor.ExperimentalUseSampledPageTopColorForScrollAreaBackgroundColor
+    
+    * dom/Document.h:
+    (WebCore::Document::sampledPageTopColor const): Added.
+    * dom/Document.cpp:
+    (WebCore::Document::enqueuePaintTimingEntryIfNeeded):
+    (WebCore::colorDifference): Added.
+    (WebCore::averageColor): Added.
+    (WebCore::Document::determineSampledPageTopColor): Added.
+    Wait until the first contentful paint before sampling. Don't sample if that location would
+    fall into a 3rd-party `<iframe>`. Currently use 5 snapshots across the top of the page,
+    allowing for one of either the first or last snapshot to be an outlier, which is not
+    included in the average of the other snapshots that's used as the final color value. If the
+    Lab color difference between any two snapshots (unless it's the first or last snapshot as
+    described above) or across all the (non-outlier) snapshots is too large, bail. Only enabled
+    if the `SampledPageTopColorMaxDifference` setting is greater than 0.
+    
+    * page/Page.h:
+    * page/Page.cpp:
+    (WebCore::Page::sampledPageTopColor const): Added.
+    * page/ChromeClient.h:
+    (WebCore::ChromeClient::didSamplePageTopColor const): Added.
+    Pass along the `sampledPageTopColor` to the UIProcess after it's determined or if the above
+    logic bails (so that the `WKWebView` can adjust `_sampledPageTopColor` to `nil`).
+    
+    * rendering/RenderLayerCompositor.cpp:
+    (WebCore::RenderLayerCompositor::rootBackgroundColorOrTransparencyChanged):
+    Use the `sampledPageTopColor` if the `UseSampledPageTopColorForScrollAreaBackgroundColor`
+    internal preference is enabled instead of the CSS `background-color` of the `<html>`/`<body>`.
+    
+    Source/WebKit:
+    
+    * WebProcess/WebCoreSupport/WebChromeClient.h:
+    * WebProcess/WebCoreSupport/WebChromeClient.cpp:
+    (WebKit::WebChromeClient::didSamplePageTopColor const): Added.
+    * WebProcess/WebPage/WebPage.h:
+    * WebProcess/WebPage/WebPage.cpp:
+    (WebKit::WebPage::didSamplePageTopColor): Added.
+    Pass along the `sampledPageTopColor` to the UIProcess.
+    
+    * UIProcess/WebPageProxy.messages.in:
+    * UIProcess/WebPageProxy.h:
+    (WebKit::WebPageProxy::sampledPageTopColor): Added.
+    * UIProcess/WebPageProxy.cpp:
+    (WebKit::WebPageProxy::scrollAreaBackgroundColor const):
+    (WebKit::WebPageProxy::didSamplePageTopColor): Added.
+    Use the `sampledPageTopColor` if the `UseSampledPageTopColorForScrollAreaBackgroundColor`
+    internal preference is enabled instead of the CSS `background-color` of the `<html>`/`<body>`.
+    
+    * UIProcess/PageClient.h:
+    (WebKit::PageClient::sampledPageTopColorWillChange): Added.
+    (WebKit::PageClient::sampledPageTopColorDidChange): Added.
+    * UIProcess/Cocoa/PageClientImplCocoa.h:
+    * UIProcess/Cocoa/PageClientImplCocoa.mm:
+    (WebKit::PageClientImplCocoa::sampledPageTopColorWillChange): Added.
+    (WebKit::PageClientImplCocoa::sampledPageTopColorDidChange): Added.
+    Add ObjC KVO support for `-[WKWebView _sampledPageTopColor]`.
+    
+    * UIProcess/API/Cocoa/WKWebViewPrivate.h:
+    * UIProcess/API/Cocoa/WKWebView.mm:
+    (-[WKWebView _setupPageConfiguration:]):
+    (-[WKWebView _sampledPageTopColor]): Added.
+    * UIProcess/API/Cocoa/WKWebViewConfigurationPrivate.h:
+    * UIProcess/API/Cocoa/WKWebViewConfiguration.mm:
+    (-[WKWebViewConfiguration init]):
+    (-[WKWebViewConfiguration copyWithZone:]):
+    (-[WKWebViewConfiguration _setSampledPageTopColorMaxDifference:]): Added.
+    (-[WKWebViewConfiguration _sampledPageTopColorMaxDifference]): Added.
+    Provide SPI to configure the `SampledPageTopColorMaxDifference` preference when
+    creating the `WKWebView`. Expose the result as `_sampledPageTopColor` SPI.
+    
+    Source/WTF:
+    
+    * Scripts/Preferences/WebPreferences.yaml:
+    Add a `SampledPageTopColorMaxDifference` setting that controls both whether or not to sample
+    colors from the top of the page (only if value > 0) and the max Lab color difference allowed
+    across all samples.
+    
+    * Scripts/Preferences/WebPreferencesInternal.yaml:
+    Add a `UseSampledPageTopColorForScrollAreaBackgroundColor` internal setting that controls
+    whether the sampled page top color can be used as the overscroll area background color.
+    
+    Tools:
+    
+    * TestWebKitAPI/Tests/WebKitCocoa/SampledPageTopColor.mm: Added.
+    (-[TestKVOWrapper initWithObservable:keyPath:callback:]):
+    (-[TestKVOWrapper dealloc]):
+    (-[TestKVOWrapper observeValueForKeyPath:ofObject:change:context:]):
+    (createWebViewWithSampledPageTopColorMaxDifference):
+    (waitForSampledPageTopColorToChangeForHTML):
+    (createHTMLGradientWithColorStops):
+    (TEST.SampledPageTopColor.ZeroMaxDifference):
+    (TEST.SampledPageTopColor.NegativeMaxDifference):
+    (TEST.SampledPageTopColor.SolidColor):
+    (TEST.SampledPageTopColor.DifferentColorsWithoutOutlierBelowMaxDifference):
+    (TEST.SampledPageTopColor.DifferentColorsWithLeftOutlierAboveMaxDifference):
+    (TEST.SampledPageTopColor.DifferentColorsWithMiddleOutlierAboveMaxDifference):
+    (TEST.SampledPageTopColor.DifferentColorsWithRightOutlierAboveMaxDifference):
+    (TEST.SampledPageTopColor.DifferentColorsIndividuallyAboveMaxDifference):
+    (TEST.SampledPageTopColor.DifferentColorsCumulativelyAboveMaxDifference):
+    (TEST.SampledPageTopColor.DisplayP3):
+    (TEST.SampledPageTopColor.ExperimentalUseSampledPageTopColorForScrollAreaBackgroundColor):
+    
+    * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+    
+    
+    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@276744 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+    2021-04-28  Devin Rousso  <drou...@apple.com>
+
+            experiment with averaging sampling colors across the top of the page as the scroll area background
+            https://bugs.webkit.org/show_bug.cgi?id=224987
+            <rdar://problem/76251889>
+
+            Reviewed by Darin Adler.
+
+            Tests: SampledPageTopColor.ZeroMaxDifference
+                   SampledPageTopColor.NegativeMaxDifference
+                   SampledPageTopColor.SolidColor
+                   SampledPageTopColor.DifferentColorsWithoutOutlierBelowMaxDifference
+                   SampledPageTopColor.DifferentColorsWithLeftOutlierAboveMaxDifference
+                   SampledPageTopColor.DifferentColorsWithMiddleOutlierAboveMaxDifference
+                   SampledPageTopColor.DifferentColorsWithRightOutlierAboveMaxDifference
+                   SampledPageTopColor.DifferentColorsIndividuallyAboveMaxDifference
+                   SampledPageTopColor.DifferentColorsCumulativelyAboveMaxDifference
+                   SampledPageTopColor.DisplayP3
+                   SampledPageTopColor.ExperimentalUseSampledPageTopColorForScrollAreaBackgroundColor
+
+            * dom/Document.h:
+            (WebCore::Document::sampledPageTopColor const): Added.
+            * dom/Document.cpp:
+            (WebCore::Document::enqueuePaintTimingEntryIfNeeded):
+            (WebCore::colorDifference): Added.
+            (WebCore::averageColor): Added.
+            (WebCore::Document::determineSampledPageTopColor): Added.
+            Wait until the first contentful paint before sampling. Don't sample if that location would
+            fall into a 3rd-party `<iframe>`. Currently use 5 snapshots across the top of the page,
+            allowing for one of either the first or last snapshot to be an outlier, which is not
+            included in the average of the other snapshots that's used as the final color value. If the
+            Lab color difference between any two snapshots (unless it's the first or last snapshot as
+            described above) or across all the (non-outlier) snapshots is too large, bail. Only enabled
+            if the `SampledPageTopColorMaxDifference` setting is greater than 0.
+
+            * page/Page.h:
+            * page/Page.cpp:
+            (WebCore::Page::sampledPageTopColor const): Added.
+            * page/ChromeClient.h:
+            (WebCore::ChromeClient::didSamplePageTopColor const): Added.
+            Pass along the `sampledPageTopColor` to the UIProcess after it's determined or if the above
+            logic bails (so that the `WKWebView` can adjust `_sampledPageTopColor` to `nil`).
+
+            * rendering/RenderLayerCompositor.cpp:
+            (WebCore::RenderLayerCompositor::rootBackgroundColorOrTransparencyChanged):
+            Use the `sampledPageTopColor` if the `UseSampledPageTopColorForScrollAreaBackgroundColor`
+            internal preference is enabled instead of the CSS `background-color` of the `<html>`/`<body>`.
+
 2021-04-25  Ryosuke Niwa  <rn...@webkit.org>
 
         Make more IndexedDB objects iso-heap'ed

Modified: branches/safari-612.1.12-branch/Source/WebCore/dom/Document.cpp (276860 => 276861)


--- branches/safari-612.1.12-branch/Source/WebCore/dom/Document.cpp	2021-04-30 23:01:10 UTC (rev 276860)
+++ branches/safari-612.1.12-branch/Source/WebCore/dom/Document.cpp	2021-04-30 23:04:06 UTC (rev 276861)
@@ -82,6 +82,7 @@
 #include "Frame.h"
 #include "FrameLoader.h"
 #include "FrameLoaderClient.h"
+#include "FrameSnapshotting.h"
 #include "FrameView.h"
 #include "FullscreenManager.h"
 #include "GCReachableRef.h"
@@ -123,6 +124,7 @@
 #include "IDBOpenDBRequest.h"
 #include "IdleCallbackController.h"
 #include "ImageBitmapRenderingContext.h"
+#include "ImageBuffer.h"
 #include "ImageLoader.h"
 #include "ImageOverlayController.h"
 #include "InspectorInstrumentation.h"
@@ -3276,6 +3278,8 @@
 
     domWindow()->performance().reportFirstContentfulPaint();
     m_didEnqueueFirstContentfulPaint = true;
+
+    determineSampledPageTopColor();
 }
 
 ExceptionOr<void> Document::write(Document* responsibleDocument, SegmentedString&& text)
@@ -3879,6 +3883,140 @@
 #endif // ENABLE(RUBBER_BANDING)
 }
 
+static double colorDifference(Lab<float>& lhs, Lab<float>& rhs)
+{
+    return sqrt(pow(rhs.lightness - lhs.lightness, 2) + pow(rhs.a - lhs.a, 2) + pow(rhs.b - lhs.b, 2));
+}
+
+static Lab<float> averageColor(Lab<float> colors[], size_t count)
+{
+    float totalLightness = 0;
+    float totalA = 0;
+    float totalB = 0;
+    for (size_t i = 0; i < count; ++i) {
+        totalLightness += colors[i].lightness;
+        totalA += colors[i].a;
+        totalB += colors[i].b;
+    }
+    return {
+        totalLightness / count,
+        totalA / count,
+        totalB / count,
+        1,
+    };
+}
+
+void Document::determineSampledPageTopColor()
+{
+    if (m_sampledPageTopColor.isValid())
+        return;
+
+    auto maxDifference = settings().sampledPageTopColorMaxDifference();
+    if (maxDifference <= 0)
+        return;
+
+    if (!isTopDocument())
+        return;
+
+    auto* frameView = view();
+    if (!frameView)
+        return;
+
+    auto notifyDidSamplePageTopColorOnScopeExit = makeScopeExit([&] {
+        if (auto* page = this->page())
+            page->chrome().client().didSamplePageTopColor();
+    });
+
+    // FIXME: <https://webkit.org/b/225167> (Sampled Page Top Color: hook into painting logic instead of taking snapshots)
+    auto pixelColorAtTopX = [&] (int x) -> Optional<Lab<float>> {
+        IntPoint location(x, 0);
+        IntSize size(1, 1);
+
+        if (isHitTestLocationThirdPartyFrame(LayoutPoint(location)))
+            return WTF::nullopt;
+
+        auto snapshot = snapshotFrameRect(frameView->frame(), IntRect(location, size), SnapshotOptionsExcludeSelectionHighlighting | SnapshotOptionsPaintEverythingExcludingSelection);
+        if (!snapshot)
+            return WTF::nullopt;
+
+        auto snapshotData = snapshot->toBGRAData();
+        return convertColor<Lab<float>>(SRGBA<uint8_t> { snapshotData[2], snapshotData[1], snapshotData[0], snapshotData[3] });
+    };
+
+    // Decrease the width by one pixel so that the last snapshot is within bounds and not off-by-one.
+    auto frameWidth = frameView->contentsWidth() - 1;
+
+    constexpr auto numSnapshots = 5;
+    size_t nonMatchingColorIndex = numSnapshots;
+
+    Lab<float> snapshots[numSnapshots];
+    double differences[numSnapshots - 1];
+
+    auto shouldStopAfterFindingNonMatchingColor = [&] (size_t i) -> bool {
+        // Bail if the non-matching color is not the first or last snapshot, or there already is an non-matching color.
+        if ((i && i < numSnapshots - 1) || nonMatchingColorIndex != numSnapshots)
+            return true;
+
+        nonMatchingColorIndex = i;
+        return false;
+    };
+
+    for (size_t i = 0; i < numSnapshots; ++i) {
+        auto snapshot = pixelColorAtTopX(frameWidth * i / (numSnapshots - 1));
+        if (!snapshot && !shouldStopAfterFindingNonMatchingColor(i))
+            return;
+
+        snapshots[i] = *snapshot;
+
+        if (i) {
+            // Each `difference` item compares `i` with `i - 1` so if the first comparison (`i == 1`)
+            // is too large of a difference, we should treat `i - 1` (i.e. `0`) as the problem since
+            // we only allow for non-matching colors being the first or last sampled color.
+            auto effectiveNonMatchingColorIndex = i == 1 ? 0 : i;
+
+            differences[i - 1] = colorDifference(snapshots[i - 1], snapshots[i]);
+            if (differences[i - 1] > maxDifference) {
+                if (shouldStopAfterFindingNonMatchingColor(effectiveNonMatchingColorIndex))
+                    return;
+                continue;
+            }
+
+            double cumuluativeDifference = 0;
+            for (size_t j = 0; j < i; ++j) {
+                if (j == nonMatchingColorIndex)
+                    continue;
+                cumuluativeDifference += differences[j];
+            }
+            if (cumuluativeDifference > maxDifference) {
+                if (shouldStopAfterFindingNonMatchingColor(effectiveNonMatchingColorIndex)) {
+                    // If we haven't already identified a non-matching snapshot and the difference between the first
+                    // and second snapshots or the second-to-last and last snapshots is less than the maximum, mark
+                    // the first/last snapshot as non-matching to give a chance for the rest of the snapshots to match.
+                    if (nonMatchingColorIndex == numSnapshots && (!i || i == numSnapshots - 1) && cumuluativeDifference - differences[i - 1] <= maxDifference) {
+                        nonMatchingColorIndex = effectiveNonMatchingColorIndex;
+                        continue;
+                    }
+                    return;
+                }
+                continue;
+            }
+        }
+    }
+
+    auto snapshotsToAverage = snapshots;
+    auto validSnapshotCount = numSnapshots;
+    if (!nonMatchingColorIndex) {
+        // Skip the first snapshot by moving the pointer that indicates where the snapshot array
+        // starts and decreasing the count of snapshots to average.
+        ++snapshotsToAverage;
+        --validSnapshotCount;
+    } else if (nonMatchingColorIndex == numSnapshots - 1) {
+        // Skip the last snapshot by decreasing the count of snapshots to average.
+        --validSnapshotCount;
+    }
+    m_sampledPageTopColor = averageColor(snapshotsToAverage, validSnapshotCount);
+}
+
 #if ENABLE(DARK_MODE_CSS)
 static void processColorSchemeString(StringView colorScheme, const WTF::Function<void(StringView key)>& callback)
 {
@@ -8608,6 +8746,22 @@
     return resultLayer;
 }
 
+bool Document::isHitTestLocationThirdPartyFrame(const HitTestLocation& location)
+{
+    constexpr OptionSet<HitTestRequest::RequestType> hitTestRequestTypes { HitTestRequest::ReadOnly, HitTestRequest::DisallowUserAgentShadowContent };
+    HitTestResult hitTestResult(location);
+    hitTest(hitTestRequestTypes, hitTestResult);
+
+    auto hitTestNode = makeRefPtr(hitTestResult.innerNode());
+    if (!hitTestNode)
+        return false;
+
+    if (!is<HTMLIFrameElement>(hitTestNode))
+        return false;
+
+    return areRegistrableDomainsEqual(downcast<HTMLIFrameElement>(*hitTestNode).location(), m_url);
+}
+
 ElementIdentifier Document::identifierForElement(Element& element)
 {
     ASSERT(&element.document() == this);

Modified: branches/safari-612.1.12-branch/Source/WebCore/dom/Document.h (276860 => 276861)


--- branches/safari-612.1.12-branch/Source/WebCore/dom/Document.h	2021-04-30 23:01:10 UTC (rev 276860)
+++ branches/safari-612.1.12-branch/Source/WebCore/dom/Document.h	2021-04-30 23:04:06 UTC (rev 276861)
@@ -743,6 +743,8 @@
 
     const Color& themeColor() const { return m_metaElementThemeColor.isValid() ? m_metaElementThemeColor : m_applicationManifestThemeColor; }
 
+    const Color& sampledPageTopColor() const { return m_sampledPageTopColor; }
+
     void setTextColor(const Color& color) { m_textColor = color; }
     const Color& textColor() const { return m_textColor; }
 
@@ -1566,6 +1568,7 @@
 
     WEBCORE_EXPORT bool hitTest(const HitTestRequest&, HitTestResult&);
     bool hitTest(const HitTestRequest&, const HitTestLocation&, HitTestResult&);
+    bool isHitTestLocationThirdPartyFrame(const HitTestLocation&);
 #if ASSERT_ENABLED
     bool inHitTesting() const { return m_inHitTesting; }
 #endif
@@ -1677,6 +1680,8 @@
 
     void themeColorChanged();
 
+    void determineSampledPageTopColor();
+
     void invalidateAccessKeyCacheSlowCase();
     void buildAccessKeyCache();
 
@@ -1800,6 +1805,8 @@
     Color m_metaElementThemeColor;
     Color m_applicationManifestThemeColor;
 
+    Color m_sampledPageTopColor;
+
     Color m_textColor { Color::black };
     Color m_linkColor;
     Color m_visitedLinkColor;

Modified: branches/safari-612.1.12-branch/Source/WebCore/page/ChromeClient.h (276860 => 276861)


--- branches/safari-612.1.12-branch/Source/WebCore/page/ChromeClient.h	2021-04-30 23:01:10 UTC (rev 276860)
+++ branches/safari-612.1.12-branch/Source/WebCore/page/ChromeClient.h	2021-04-30 23:04:06 UTC (rev 276861)
@@ -233,6 +233,7 @@
 
     virtual void themeColorChanged() const { }
     virtual void pageExtendedBackgroundColorDidChange() const { }
+    virtual void didSamplePageTopColor() const { }
 
     virtual void exceededDatabaseQuota(Frame&, const String& databaseName, DatabaseDetails) = 0;
 

Modified: branches/safari-612.1.12-branch/Source/WebCore/page/Page.cpp (276860 => 276861)


--- branches/safari-612.1.12-branch/Source/WebCore/page/Page.cpp	2021-04-30 23:01:10 UTC (rev 276860)
+++ branches/safari-612.1.12-branch/Source/WebCore/page/Page.cpp	2021-04-30 23:04:06 UTC (rev 276861)
@@ -2554,6 +2554,15 @@
     return renderView->compositor().rootExtendedBackgroundColor();
 }
 
+Color Page::sampledPageTopColor() const
+{
+    auto* document = mainFrame().document();
+    if (!document)
+        return { };
+
+    return document->sampledPageTopColor();
+}
+
 // These are magical constants that might be tweaked over time.
 static const double gMinimumPaintedAreaRatio = 0.1;
 static const double gMaximumUnpaintedAreaRatio = 0.04;

Modified: branches/safari-612.1.12-branch/Source/WebCore/page/Page.h (276860 => 276861)


--- branches/safari-612.1.12-branch/Source/WebCore/page/Page.h	2021-04-30 23:01:10 UTC (rev 276860)
+++ branches/safari-612.1.12-branch/Source/WebCore/page/Page.h	2021-04-30 23:04:06 UTC (rev 276861)
@@ -621,6 +621,7 @@
 
     WEBCORE_EXPORT Color themeColor() const;
     WEBCORE_EXPORT Color pageExtendedBackgroundColor() const;
+    WEBCORE_EXPORT Color sampledPageTopColor() const;
 
     bool isCountingRelevantRepaintedObjects() const;
     void setIsCountingRelevantRepaintedObjects(bool isCounting) { m_isCountingRelevantRepaintedObjects = isCounting; }

Modified: branches/safari-612.1.12-branch/Source/WebCore/rendering/RenderLayerCompositor.cpp (276860 => 276861)


--- branches/safari-612.1.12-branch/Source/WebCore/rendering/RenderLayerCompositor.cpp	2021-04-30 23:01:10 UTC (rev 276860)
+++ branches/safari-612.1.12-branch/Source/WebCore/rendering/RenderLayerCompositor.cpp	2021-04-30 23:04:06 UTC (rev 276861)
@@ -3926,6 +3926,8 @@
     Color backgroundColor;
     if (page().settings().useThemeColorForScrollAreaBackgroundColor())
         backgroundColor = page().themeColor();
+    if (page().settings().useSampledPageTopColorForScrollAreaBackgroundColor() && !backgroundColor.isValid())
+        backgroundColor = page().sampledPageTopColor();
     if (!backgroundColor.isValid())
         backgroundColor = m_rootExtendedBackgroundColor;
 

Modified: branches/safari-612.1.12-branch/Source/WebKit/ChangeLog (276860 => 276861)


--- branches/safari-612.1.12-branch/Source/WebKit/ChangeLog	2021-04-30 23:01:10 UTC (rev 276860)
+++ branches/safari-612.1.12-branch/Source/WebKit/ChangeLog	2021-04-30 23:04:06 UTC (rev 276861)
@@ -1,3 +1,180 @@
+2021-04-30  Russell Epstein  <repst...@apple.com>
+
+        Cherry-pick r276744. rdar://problem/77402549
+
+    experiment with averaging sampling colors across the top of the page as the scroll area background
+    https://bugs.webkit.org/show_bug.cgi?id=224987
+    <rdar://problem/76251889>
+    
+    Reviewed by Darin Adler.
+    
+    Source/WebCore:
+    
+    Tests: SampledPageTopColor.ZeroMaxDifference
+           SampledPageTopColor.NegativeMaxDifference
+           SampledPageTopColor.SolidColor
+           SampledPageTopColor.DifferentColorsWithoutOutlierBelowMaxDifference
+           SampledPageTopColor.DifferentColorsWithLeftOutlierAboveMaxDifference
+           SampledPageTopColor.DifferentColorsWithMiddleOutlierAboveMaxDifference
+           SampledPageTopColor.DifferentColorsWithRightOutlierAboveMaxDifference
+           SampledPageTopColor.DifferentColorsIndividuallyAboveMaxDifference
+           SampledPageTopColor.DifferentColorsCumulativelyAboveMaxDifference
+           SampledPageTopColor.DisplayP3
+           SampledPageTopColor.ExperimentalUseSampledPageTopColorForScrollAreaBackgroundColor
+    
+    * dom/Document.h:
+    (WebCore::Document::sampledPageTopColor const): Added.
+    * dom/Document.cpp:
+    (WebCore::Document::enqueuePaintTimingEntryIfNeeded):
+    (WebCore::colorDifference): Added.
+    (WebCore::averageColor): Added.
+    (WebCore::Document::determineSampledPageTopColor): Added.
+    Wait until the first contentful paint before sampling. Don't sample if that location would
+    fall into a 3rd-party `<iframe>`. Currently use 5 snapshots across the top of the page,
+    allowing for one of either the first or last snapshot to be an outlier, which is not
+    included in the average of the other snapshots that's used as the final color value. If the
+    Lab color difference between any two snapshots (unless it's the first or last snapshot as
+    described above) or across all the (non-outlier) snapshots is too large, bail. Only enabled
+    if the `SampledPageTopColorMaxDifference` setting is greater than 0.
+    
+    * page/Page.h:
+    * page/Page.cpp:
+    (WebCore::Page::sampledPageTopColor const): Added.
+    * page/ChromeClient.h:
+    (WebCore::ChromeClient::didSamplePageTopColor const): Added.
+    Pass along the `sampledPageTopColor` to the UIProcess after it's determined or if the above
+    logic bails (so that the `WKWebView` can adjust `_sampledPageTopColor` to `nil`).
+    
+    * rendering/RenderLayerCompositor.cpp:
+    (WebCore::RenderLayerCompositor::rootBackgroundColorOrTransparencyChanged):
+    Use the `sampledPageTopColor` if the `UseSampledPageTopColorForScrollAreaBackgroundColor`
+    internal preference is enabled instead of the CSS `background-color` of the `<html>`/`<body>`.
+    
+    Source/WebKit:
+    
+    * WebProcess/WebCoreSupport/WebChromeClient.h:
+    * WebProcess/WebCoreSupport/WebChromeClient.cpp:
+    (WebKit::WebChromeClient::didSamplePageTopColor const): Added.
+    * WebProcess/WebPage/WebPage.h:
+    * WebProcess/WebPage/WebPage.cpp:
+    (WebKit::WebPage::didSamplePageTopColor): Added.
+    Pass along the `sampledPageTopColor` to the UIProcess.
+    
+    * UIProcess/WebPageProxy.messages.in:
+    * UIProcess/WebPageProxy.h:
+    (WebKit::WebPageProxy::sampledPageTopColor): Added.
+    * UIProcess/WebPageProxy.cpp:
+    (WebKit::WebPageProxy::scrollAreaBackgroundColor const):
+    (WebKit::WebPageProxy::didSamplePageTopColor): Added.
+    Use the `sampledPageTopColor` if the `UseSampledPageTopColorForScrollAreaBackgroundColor`
+    internal preference is enabled instead of the CSS `background-color` of the `<html>`/`<body>`.
+    
+    * UIProcess/PageClient.h:
+    (WebKit::PageClient::sampledPageTopColorWillChange): Added.
+    (WebKit::PageClient::sampledPageTopColorDidChange): Added.
+    * UIProcess/Cocoa/PageClientImplCocoa.h:
+    * UIProcess/Cocoa/PageClientImplCocoa.mm:
+    (WebKit::PageClientImplCocoa::sampledPageTopColorWillChange): Added.
+    (WebKit::PageClientImplCocoa::sampledPageTopColorDidChange): Added.
+    Add ObjC KVO support for `-[WKWebView _sampledPageTopColor]`.
+    
+    * UIProcess/API/Cocoa/WKWebViewPrivate.h:
+    * UIProcess/API/Cocoa/WKWebView.mm:
+    (-[WKWebView _setupPageConfiguration:]):
+    (-[WKWebView _sampledPageTopColor]): Added.
+    * UIProcess/API/Cocoa/WKWebViewConfigurationPrivate.h:
+    * UIProcess/API/Cocoa/WKWebViewConfiguration.mm:
+    (-[WKWebViewConfiguration init]):
+    (-[WKWebViewConfiguration copyWithZone:]):
+    (-[WKWebViewConfiguration _setSampledPageTopColorMaxDifference:]): Added.
+    (-[WKWebViewConfiguration _sampledPageTopColorMaxDifference]): Added.
+    Provide SPI to configure the `SampledPageTopColorMaxDifference` preference when
+    creating the `WKWebView`. Expose the result as `_sampledPageTopColor` SPI.
+    
+    Source/WTF:
+    
+    * Scripts/Preferences/WebPreferences.yaml:
+    Add a `SampledPageTopColorMaxDifference` setting that controls both whether or not to sample
+    colors from the top of the page (only if value > 0) and the max Lab color difference allowed
+    across all samples.
+    
+    * Scripts/Preferences/WebPreferencesInternal.yaml:
+    Add a `UseSampledPageTopColorForScrollAreaBackgroundColor` internal setting that controls
+    whether the sampled page top color can be used as the overscroll area background color.
+    
+    Tools:
+    
+    * TestWebKitAPI/Tests/WebKitCocoa/SampledPageTopColor.mm: Added.
+    (-[TestKVOWrapper initWithObservable:keyPath:callback:]):
+    (-[TestKVOWrapper dealloc]):
+    (-[TestKVOWrapper observeValueForKeyPath:ofObject:change:context:]):
+    (createWebViewWithSampledPageTopColorMaxDifference):
+    (waitForSampledPageTopColorToChangeForHTML):
+    (createHTMLGradientWithColorStops):
+    (TEST.SampledPageTopColor.ZeroMaxDifference):
+    (TEST.SampledPageTopColor.NegativeMaxDifference):
+    (TEST.SampledPageTopColor.SolidColor):
+    (TEST.SampledPageTopColor.DifferentColorsWithoutOutlierBelowMaxDifference):
+    (TEST.SampledPageTopColor.DifferentColorsWithLeftOutlierAboveMaxDifference):
+    (TEST.SampledPageTopColor.DifferentColorsWithMiddleOutlierAboveMaxDifference):
+    (TEST.SampledPageTopColor.DifferentColorsWithRightOutlierAboveMaxDifference):
+    (TEST.SampledPageTopColor.DifferentColorsIndividuallyAboveMaxDifference):
+    (TEST.SampledPageTopColor.DifferentColorsCumulativelyAboveMaxDifference):
+    (TEST.SampledPageTopColor.DisplayP3):
+    (TEST.SampledPageTopColor.ExperimentalUseSampledPageTopColorForScrollAreaBackgroundColor):
+    
+    * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+    
+    
+    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@276744 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+    2021-04-28  Devin Rousso  <drou...@apple.com>
+
+            experiment with averaging sampling colors across the top of the page as the scroll area background
+            https://bugs.webkit.org/show_bug.cgi?id=224987
+            <rdar://problem/76251889>
+
+            Reviewed by Darin Adler.
+
+            * WebProcess/WebCoreSupport/WebChromeClient.h:
+            * WebProcess/WebCoreSupport/WebChromeClient.cpp:
+            (WebKit::WebChromeClient::didSamplePageTopColor const): Added.
+            * WebProcess/WebPage/WebPage.h:
+            * WebProcess/WebPage/WebPage.cpp:
+            (WebKit::WebPage::didSamplePageTopColor): Added.
+            Pass along the `sampledPageTopColor` to the UIProcess.
+
+            * UIProcess/WebPageProxy.messages.in:
+            * UIProcess/WebPageProxy.h:
+            (WebKit::WebPageProxy::sampledPageTopColor): Added.
+            * UIProcess/WebPageProxy.cpp:
+            (WebKit::WebPageProxy::scrollAreaBackgroundColor const):
+            (WebKit::WebPageProxy::didSamplePageTopColor): Added.
+            Use the `sampledPageTopColor` if the `UseSampledPageTopColorForScrollAreaBackgroundColor`
+            internal preference is enabled instead of the CSS `background-color` of the `<html>`/`<body>`.
+
+            * UIProcess/PageClient.h:
+            (WebKit::PageClient::sampledPageTopColorWillChange): Added.
+            (WebKit::PageClient::sampledPageTopColorDidChange): Added.
+            * UIProcess/Cocoa/PageClientImplCocoa.h:
+            * UIProcess/Cocoa/PageClientImplCocoa.mm:
+            (WebKit::PageClientImplCocoa::sampledPageTopColorWillChange): Added.
+            (WebKit::PageClientImplCocoa::sampledPageTopColorDidChange): Added.
+            Add ObjC KVO support for `-[WKWebView _sampledPageTopColor]`.
+
+            * UIProcess/API/Cocoa/WKWebViewPrivate.h:
+            * UIProcess/API/Cocoa/WKWebView.mm:
+            (-[WKWebView _setupPageConfiguration:]):
+            (-[WKWebView _sampledPageTopColor]): Added.
+            * UIProcess/API/Cocoa/WKWebViewConfigurationPrivate.h:
+            * UIProcess/API/Cocoa/WKWebViewConfiguration.mm:
+            (-[WKWebViewConfiguration init]):
+            (-[WKWebViewConfiguration copyWithZone:]):
+            (-[WKWebViewConfiguration _setSampledPageTopColorMaxDifference:]): Added.
+            (-[WKWebViewConfiguration _sampledPageTopColorMaxDifference]): Added.
+            Provide SPI to configure the `SampledPageTopColorMaxDifference` preference when
+            creating the `WKWebView`. Expose the result as `_sampledPageTopColor` SPI.
+
 2021-04-29  Ruben Turcios  <rubent...@apple.com>
 
         Cherry-pick r276671. rdar://problem/77324338

Modified: branches/safari-612.1.12-branch/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm (276860 => 276861)


--- branches/safari-612.1.12-branch/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm	2021-04-30 23:01:10 UTC (rev 276860)
+++ branches/safari-612.1.12-branch/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm	2021-04-30 23:04:06 UTC (rev 276861)
@@ -559,6 +559,8 @@
     pageConfiguration->preferences()->setServiceWorkerEntitlementDisabledForTesting(!![_configuration preferences]._serviceWorkerEntitlementDisabledForTesting);
 #endif
 
+    pageConfiguration->preferences()->setSampledPageTopColorMaxDifference([_configuration _sampledPageTopColorMaxDifference]);
+
     if (!linkedOnOrAfter(WebCore::SDKVersion::FirstWhereSiteSpecificQuirksAreEnabledByDefault))
         pageConfiguration->preferences()->setNeedsSiteSpecificQuirks(false);
 }
@@ -3030,6 +3032,14 @@
     return WebCore::platformColor(pageExtendedBackgroundColor);
 }
 
+- (CocoaColor *)_sampledPageTopColor
+{
+    auto sampledPageTopColor = _page->sampledPageTopColor();
+    if (!sampledPageTopColor.isValid())
+        return nil;
+    return WebCore::platformColor(sampledPageTopColor);
+}
+
 - (id <_WKInputDelegate>)_inputDelegate
 {
     return _inputDelegate.getAutoreleased();

Modified: branches/safari-612.1.12-branch/Source/WebKit/UIProcess/API/Cocoa/WKWebViewConfiguration.mm (276860 => 276861)


--- branches/safari-612.1.12-branch/Source/WebKit/UIProcess/API/Cocoa/WKWebViewConfiguration.mm	2021-04-30 23:01:10 UTC (rev 276860)
+++ branches/safari-612.1.12-branch/Source/WebKit/UIProcess/API/Cocoa/WKWebViewConfiguration.mm	2021-04-30 23:04:06 UTC (rev 276861)
@@ -177,6 +177,7 @@
 #if ENABLE(APP_HIGHLIGHTS)
     BOOL _appHighlightsEnabled;
 #endif
+    double _sampledPageTopColorMaxDifference;
 
     RetainPtr<NSString> _mediaContentTypesRequiringHardwareSupport;
     RetainPtr<NSArray<NSString *>> _additionalSupportedImageTypes;
@@ -275,6 +276,9 @@
 #if ENABLE(APP_HIGHLIGHTS)
     _appHighlightsEnabled = DEFAULT_VALUE_FOR_AppHighlightsEnabled;
 #endif
+
+    _sampledPageTopColorMaxDifference = DEFAULT_VALUE_FOR_SampledPageTopColorMaxDifference;
+
     return self;
 }
 
@@ -453,6 +457,8 @@
     configuration->_appHighlightsEnabled = self->_appHighlightsEnabled;
 #endif
 
+    configuration->_sampledPageTopColorMaxDifference = self->_sampledPageTopColorMaxDifference;
+
     return configuration;
 }
 
@@ -1273,6 +1279,16 @@
     _pageConfiguration->setProcessDisplayName(lsDisplayName);
 }
 
+- (void)_setSampledPageTopColorMaxDifference:(double)value
+{
+    _sampledPageTopColorMaxDifference = value;
+}
+
+- (double)_sampledPageTopColorMaxDifference
+{
+    return _sampledPageTopColorMaxDifference;
+}
+
 @end
 
 @implementation WKWebViewConfiguration (WKDeprecated)

Modified: branches/safari-612.1.12-branch/Source/WebKit/UIProcess/API/Cocoa/WKWebViewConfigurationPrivate.h (276860 => 276861)


--- branches/safari-612.1.12-branch/Source/WebKit/UIProcess/API/Cocoa/WKWebViewConfigurationPrivate.h	2021-04-30 23:01:10 UTC (rev 276860)
+++ branches/safari-612.1.12-branch/Source/WebKit/UIProcess/API/Cocoa/WKWebViewConfigurationPrivate.h	2021-04-30 23:04:06 UTC (rev 276861)
@@ -123,6 +123,10 @@
 
 @property (nonatomic, setter=_setAppHighlightsEnabled:) BOOL _appHighlightsEnabled WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
 
+// The maximum Lab color difference allowed between two consecutive page top snapshots.
+// Expects 0 (disables page top color sampling entirely) or any positive number.
+@property (nonatomic, setter=_setSampledPageTopColorMaxDifference:) double _sampledPageTopColorMaxDifference WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
+
 @end
 
 #if TARGET_OS_IPHONE

Modified: branches/safari-612.1.12-branch/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h (276860 => 276861)


--- branches/safari-612.1.12-branch/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h	2021-04-30 23:01:10 UTC (rev 276860)
+++ branches/safari-612.1.12-branch/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h	2021-04-30 23:04:06 UTC (rev 276861)
@@ -384,6 +384,13 @@
 @property (nonatomic, readonly) NSColor *_pageExtendedBackgroundColor;
 #endif
 
+// Only set if `-[WKWebViewConfiguration _sampledPageTopColorMaxDifference]` is a positive number.
+#if TARGET_OS_IPHONE
+@property (nonatomic, readonly) UIColor *_sampledPageTopColor WK_API_AVAILABLE(ios(WK_IOS_TBA));
+#else
+@property (nonatomic, readonly) NSColor *_sampledPageTopColor WK_API_AVAILABLE(macos(WK_MAC_TBA));
+#endif
+
 - (void)_grantAccessToAssetServices WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(14.0));
 - (void)_revokeAccessToAssetServices WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(14.0));
 

Modified: branches/safari-612.1.12-branch/Source/WebKit/UIProcess/Cocoa/PageClientImplCocoa.h (276860 => 276861)


--- branches/safari-612.1.12-branch/Source/WebKit/UIProcess/Cocoa/PageClientImplCocoa.h	2021-04-30 23:01:10 UTC (rev 276860)
+++ branches/safari-612.1.12-branch/Source/WebKit/UIProcess/Cocoa/PageClientImplCocoa.h	2021-04-30 23:04:06 UTC (rev 276861)
@@ -55,6 +55,8 @@
     void themeColorDidChange() final;
     void pageExtendedBackgroundColorWillChange() final;
     void pageExtendedBackgroundColorDidChange() final;
+    void sampledPageTopColorWillChange() final;
+    void sampledPageTopColorDidChange() final;
     void isPlayingAudioWillChange() final;
     void isPlayingAudioDidChange() final;
 

Modified: branches/safari-612.1.12-branch/Source/WebKit/UIProcess/Cocoa/PageClientImplCocoa.mm (276860 => 276861)


--- branches/safari-612.1.12-branch/Source/WebKit/UIProcess/Cocoa/PageClientImplCocoa.mm	2021-04-30 23:01:10 UTC (rev 276860)
+++ branches/safari-612.1.12-branch/Source/WebKit/UIProcess/Cocoa/PageClientImplCocoa.mm	2021-04-30 23:04:06 UTC (rev 276861)
@@ -66,6 +66,16 @@
     [m_webView didChangeValueForKey:@"_pageExtendedBackgroundColor"];
 }
 
+void PageClientImplCocoa::sampledPageTopColorWillChange()
+{
+    [m_webView willChangeValueForKey:@"_sampledPageTopColor"];
+}
+
+void PageClientImplCocoa::sampledPageTopColorDidChange()
+{
+    [m_webView didChangeValueForKey:@"_sampledPageTopColor"];
+}
+
 void PageClientImplCocoa::isPlayingAudioWillChange()
 {
     [m_webView willChangeValueForKey:NSStringFromSelector(@selector(_isPlayingAudio))];

Modified: branches/safari-612.1.12-branch/Source/WebKit/UIProcess/PageClient.h (276860 => 276861)


--- branches/safari-612.1.12-branch/Source/WebKit/UIProcess/PageClient.h	2021-04-30 23:01:10 UTC (rev 276860)
+++ branches/safari-612.1.12-branch/Source/WebKit/UIProcess/PageClient.h	2021-04-30 23:04:06 UTC (rev 276861)
@@ -509,6 +509,8 @@
     virtual void themeColorDidChange() { }
     virtual void pageExtendedBackgroundColorWillChange() { }
     virtual void pageExtendedBackgroundColorDidChange() { }
+    virtual void sampledPageTopColorWillChange() { }
+    virtual void sampledPageTopColorDidChange() { }
     virtual void didChangeBackgroundColor() = 0;
     virtual void isPlayingAudioWillChange() = 0;
     virtual void isPlayingAudioDidChange() = 0;

Modified: branches/safari-612.1.12-branch/Source/WebKit/UIProcess/WebPageProxy.cpp (276860 => 276861)


--- branches/safari-612.1.12-branch/Source/WebKit/UIProcess/WebPageProxy.cpp	2021-04-30 23:01:10 UTC (rev 276860)
+++ branches/safari-612.1.12-branch/Source/WebKit/UIProcess/WebPageProxy.cpp	2021-04-30 23:04:06 UTC (rev 276861)
@@ -1917,6 +1917,9 @@
     if (m_preferences->useThemeColorForScrollAreaBackgroundColor() && m_themeColor.isValid())
         return m_themeColor;
 
+    if (m_preferences->useSampledPageTopColorForScrollAreaBackgroundColor() && m_sampledPageTopColor.isValid())
+        return m_sampledPageTopColor;
+
     return m_pageExtendedBackgroundColor;
 }
 
@@ -8522,6 +8525,16 @@
     pageClient().pageExtendedBackgroundColorDidChange();
 }
 
+void WebPageProxy::didSamplePageTopColor(const Color& sampledPageTopColor)
+{
+    if (m_sampledPageTopColor == sampledPageTopColor)
+        return;
+
+    pageClient().sampledPageTopColorWillChange();
+    m_sampledPageTopColor = sampledPageTopColor;
+    pageClient().sampledPageTopColorDidChange();
+}
+
 #if ENABLE(NETSCAPE_PLUGIN_API)
 void WebPageProxy::didFailToInitializePlugin(const String& mimeType, const String& frameURLString, const String& pageURLString)
 {

Modified: branches/safari-612.1.12-branch/Source/WebKit/UIProcess/WebPageProxy.h (276860 => 276861)


--- branches/safari-612.1.12-branch/Source/WebKit/UIProcess/WebPageProxy.h	2021-04-30 23:01:10 UTC (rev 276860)
+++ branches/safari-612.1.12-branch/Source/WebKit/UIProcess/WebPageProxy.h	2021-04-30 23:04:06 UTC (rev 276861)
@@ -665,6 +665,8 @@
     // the message entirely.
     WebCore::Color pageExtendedBackgroundColor() const { return m_pageExtendedBackgroundColor; }
 
+    WebCore::Color sampledPageTopColor() const { return m_sampledPageTopColor; }
+
     WebCore::Color scrollAreaBackgroundColor() const;
 
     void viewWillStartLiveResize();
@@ -2096,6 +2098,7 @@
     void didChangePageCount(unsigned);
     void themeColorChanged(const WebCore::Color&);
     void pageExtendedBackgroundColorDidChange(const WebCore::Color&);
+    void didSamplePageTopColor(const WebCore::Color&);
 #if ENABLE(NETSCAPE_PLUGIN_API)
     void didFailToInitializePlugin(const String& mimeType, const String& frameURLString, const String& pageURLString);
     void didBlockInsecurePluginVersion(const String& mimeType, const String& pluginURLString, const String& frameURLString, const String& pageURLString, bool replacementObscured);
@@ -2641,6 +2644,7 @@
     WebCore::Color m_themeColor;
     WebCore::Color m_underlayColor;
     WebCore::Color m_pageExtendedBackgroundColor;
+    WebCore::Color m_sampledPageTopColor;
 
     bool m_useFixedLayout { false };
     WebCore::IntSize m_fixedLayoutSize;

Modified: branches/safari-612.1.12-branch/Source/WebKit/UIProcess/WebPageProxy.messages.in (276860 => 276861)


--- branches/safari-612.1.12-branch/Source/WebKit/UIProcess/WebPageProxy.messages.in	2021-04-30 23:01:10 UTC (rev 276860)
+++ branches/safari-612.1.12-branch/Source/WebKit/UIProcess/WebPageProxy.messages.in	2021-04-30 23:04:06 UTC (rev 276861)
@@ -79,6 +79,7 @@
     DidChangePageCount(unsigned pageCount)
     ThemeColorChanged(WebCore::Color themeColor)
     PageExtendedBackgroundColorDidChange(WebCore::Color backgroundColor)
+    DidSamplePageTopColor(WebCore::Color sampledPageTopColor)
 #if ENABLE(NETSCAPE_PLUGIN_API)
     DidFailToInitializePlugin(String mimeType, String frameURLString, String pageURLString)
     DidBlockInsecurePluginVersion(String mimeType, String pluginURLString, String frameURLString, String pageURLString, bool replacementObscured)

Modified: branches/safari-612.1.12-branch/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp (276860 => 276861)


--- branches/safari-612.1.12-branch/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp	2021-04-30 23:01:10 UTC (rev 276860)
+++ branches/safari-612.1.12-branch/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp	2021-04-30 23:04:06 UTC (rev 276861)
@@ -1164,6 +1164,11 @@
     m_page.pageExtendedBackgroundColorDidChange();
 }
 
+void WebChromeClient::didSamplePageTopColor() const
+{
+    m_page.didSamplePageTopColor();
+}
+
 void WebChromeClient::wheelEventHandlersChanged(bool hasHandlers)
 {
     m_page.wheelEventHandlersChanged(hasHandlers);

Modified: branches/safari-612.1.12-branch/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.h (276860 => 276861)


--- branches/safari-612.1.12-branch/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.h	2021-04-30 23:01:10 UTC (rev 276860)
+++ branches/safari-612.1.12-branch/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.h	2021-04-30 23:04:06 UTC (rev 276861)
@@ -330,6 +330,7 @@
 
     void themeColorChanged() const final;
     void pageExtendedBackgroundColorDidChange() const final;
+    void didSamplePageTopColor() const final;
     
     void wheelEventHandlersChanged(bool) final;
 

Modified: branches/safari-612.1.12-branch/Source/WebKit/WebProcess/WebPage/WebPage.cpp (276860 => 276861)


--- branches/safari-612.1.12-branch/Source/WebKit/WebProcess/WebPage/WebPage.cpp	2021-04-30 23:01:10 UTC (rev 276860)
+++ branches/safari-612.1.12-branch/Source/WebKit/WebProcess/WebPage/WebPage.cpp	2021-04-30 23:04:06 UTC (rev 276861)
@@ -6453,6 +6453,11 @@
     send(Messages::WebPageProxy::PageExtendedBackgroundColorDidChange(m_page->pageExtendedBackgroundColor()));
 }
 
+void WebPage::didSamplePageTopColor()
+{
+    send(Messages::WebPageProxy::DidSamplePageTopColor(m_page->sampledPageTopColor()));
+}
+
 void WebPage::flushPendingEditorStateUpdate()
 {
     if (!m_hasPendingEditorStateUpdate)

Modified: branches/safari-612.1.12-branch/Source/WebKit/WebProcess/WebPage/WebPage.h (276860 => 276861)


--- branches/safari-612.1.12-branch/Source/WebKit/WebProcess/WebPage/WebPage.h	2021-04-30 23:01:10 UTC (rev 276860)
+++ branches/safari-612.1.12-branch/Source/WebKit/WebProcess/WebPage/WebPage.h	2021-04-30 23:04:06 UTC (rev 276861)
@@ -1240,6 +1240,8 @@
     void pageExtendedBackgroundColorDidChange() { m_pendingPageExtendedBackgroundColorChange = true; }
     void flushPendingPageExtendedBackgroundColorChange();
 
+    void didSamplePageTopColor();
+
     void flushPendingEditorStateUpdate();
 
 #if ENABLE(RESOURCE_LOAD_STATISTICS)

Modified: branches/safari-612.1.12-branch/Tools/ChangeLog (276860 => 276861)


--- branches/safari-612.1.12-branch/Tools/ChangeLog	2021-04-30 23:01:10 UTC (rev 276860)
+++ branches/safari-612.1.12-branch/Tools/ChangeLog	2021-04-30 23:04:06 UTC (rev 276861)
@@ -1,3 +1,162 @@
+2021-04-30  Russell Epstein  <repst...@apple.com>
+
+        Cherry-pick r276744. rdar://problem/77402549
+
+    experiment with averaging sampling colors across the top of the page as the scroll area background
+    https://bugs.webkit.org/show_bug.cgi?id=224987
+    <rdar://problem/76251889>
+    
+    Reviewed by Darin Adler.
+    
+    Source/WebCore:
+    
+    Tests: SampledPageTopColor.ZeroMaxDifference
+           SampledPageTopColor.NegativeMaxDifference
+           SampledPageTopColor.SolidColor
+           SampledPageTopColor.DifferentColorsWithoutOutlierBelowMaxDifference
+           SampledPageTopColor.DifferentColorsWithLeftOutlierAboveMaxDifference
+           SampledPageTopColor.DifferentColorsWithMiddleOutlierAboveMaxDifference
+           SampledPageTopColor.DifferentColorsWithRightOutlierAboveMaxDifference
+           SampledPageTopColor.DifferentColorsIndividuallyAboveMaxDifference
+           SampledPageTopColor.DifferentColorsCumulativelyAboveMaxDifference
+           SampledPageTopColor.DisplayP3
+           SampledPageTopColor.ExperimentalUseSampledPageTopColorForScrollAreaBackgroundColor
+    
+    * dom/Document.h:
+    (WebCore::Document::sampledPageTopColor const): Added.
+    * dom/Document.cpp:
+    (WebCore::Document::enqueuePaintTimingEntryIfNeeded):
+    (WebCore::colorDifference): Added.
+    (WebCore::averageColor): Added.
+    (WebCore::Document::determineSampledPageTopColor): Added.
+    Wait until the first contentful paint before sampling. Don't sample if that location would
+    fall into a 3rd-party `<iframe>`. Currently use 5 snapshots across the top of the page,
+    allowing for one of either the first or last snapshot to be an outlier, which is not
+    included in the average of the other snapshots that's used as the final color value. If the
+    Lab color difference between any two snapshots (unless it's the first or last snapshot as
+    described above) or across all the (non-outlier) snapshots is too large, bail. Only enabled
+    if the `SampledPageTopColorMaxDifference` setting is greater than 0.
+    
+    * page/Page.h:
+    * page/Page.cpp:
+    (WebCore::Page::sampledPageTopColor const): Added.
+    * page/ChromeClient.h:
+    (WebCore::ChromeClient::didSamplePageTopColor const): Added.
+    Pass along the `sampledPageTopColor` to the UIProcess after it's determined or if the above
+    logic bails (so that the `WKWebView` can adjust `_sampledPageTopColor` to `nil`).
+    
+    * rendering/RenderLayerCompositor.cpp:
+    (WebCore::RenderLayerCompositor::rootBackgroundColorOrTransparencyChanged):
+    Use the `sampledPageTopColor` if the `UseSampledPageTopColorForScrollAreaBackgroundColor`
+    internal preference is enabled instead of the CSS `background-color` of the `<html>`/`<body>`.
+    
+    Source/WebKit:
+    
+    * WebProcess/WebCoreSupport/WebChromeClient.h:
+    * WebProcess/WebCoreSupport/WebChromeClient.cpp:
+    (WebKit::WebChromeClient::didSamplePageTopColor const): Added.
+    * WebProcess/WebPage/WebPage.h:
+    * WebProcess/WebPage/WebPage.cpp:
+    (WebKit::WebPage::didSamplePageTopColor): Added.
+    Pass along the `sampledPageTopColor` to the UIProcess.
+    
+    * UIProcess/WebPageProxy.messages.in:
+    * UIProcess/WebPageProxy.h:
+    (WebKit::WebPageProxy::sampledPageTopColor): Added.
+    * UIProcess/WebPageProxy.cpp:
+    (WebKit::WebPageProxy::scrollAreaBackgroundColor const):
+    (WebKit::WebPageProxy::didSamplePageTopColor): Added.
+    Use the `sampledPageTopColor` if the `UseSampledPageTopColorForScrollAreaBackgroundColor`
+    internal preference is enabled instead of the CSS `background-color` of the `<html>`/`<body>`.
+    
+    * UIProcess/PageClient.h:
+    (WebKit::PageClient::sampledPageTopColorWillChange): Added.
+    (WebKit::PageClient::sampledPageTopColorDidChange): Added.
+    * UIProcess/Cocoa/PageClientImplCocoa.h:
+    * UIProcess/Cocoa/PageClientImplCocoa.mm:
+    (WebKit::PageClientImplCocoa::sampledPageTopColorWillChange): Added.
+    (WebKit::PageClientImplCocoa::sampledPageTopColorDidChange): Added.
+    Add ObjC KVO support for `-[WKWebView _sampledPageTopColor]`.
+    
+    * UIProcess/API/Cocoa/WKWebViewPrivate.h:
+    * UIProcess/API/Cocoa/WKWebView.mm:
+    (-[WKWebView _setupPageConfiguration:]):
+    (-[WKWebView _sampledPageTopColor]): Added.
+    * UIProcess/API/Cocoa/WKWebViewConfigurationPrivate.h:
+    * UIProcess/API/Cocoa/WKWebViewConfiguration.mm:
+    (-[WKWebViewConfiguration init]):
+    (-[WKWebViewConfiguration copyWithZone:]):
+    (-[WKWebViewConfiguration _setSampledPageTopColorMaxDifference:]): Added.
+    (-[WKWebViewConfiguration _sampledPageTopColorMaxDifference]): Added.
+    Provide SPI to configure the `SampledPageTopColorMaxDifference` preference when
+    creating the `WKWebView`. Expose the result as `_sampledPageTopColor` SPI.
+    
+    Source/WTF:
+    
+    * Scripts/Preferences/WebPreferences.yaml:
+    Add a `SampledPageTopColorMaxDifference` setting that controls both whether or not to sample
+    colors from the top of the page (only if value > 0) and the max Lab color difference allowed
+    across all samples.
+    
+    * Scripts/Preferences/WebPreferencesInternal.yaml:
+    Add a `UseSampledPageTopColorForScrollAreaBackgroundColor` internal setting that controls
+    whether the sampled page top color can be used as the overscroll area background color.
+    
+    Tools:
+    
+    * TestWebKitAPI/Tests/WebKitCocoa/SampledPageTopColor.mm: Added.
+    (-[TestKVOWrapper initWithObservable:keyPath:callback:]):
+    (-[TestKVOWrapper dealloc]):
+    (-[TestKVOWrapper observeValueForKeyPath:ofObject:change:context:]):
+    (createWebViewWithSampledPageTopColorMaxDifference):
+    (waitForSampledPageTopColorToChangeForHTML):
+    (createHTMLGradientWithColorStops):
+    (TEST.SampledPageTopColor.ZeroMaxDifference):
+    (TEST.SampledPageTopColor.NegativeMaxDifference):
+    (TEST.SampledPageTopColor.SolidColor):
+    (TEST.SampledPageTopColor.DifferentColorsWithoutOutlierBelowMaxDifference):
+    (TEST.SampledPageTopColor.DifferentColorsWithLeftOutlierAboveMaxDifference):
+    (TEST.SampledPageTopColor.DifferentColorsWithMiddleOutlierAboveMaxDifference):
+    (TEST.SampledPageTopColor.DifferentColorsWithRightOutlierAboveMaxDifference):
+    (TEST.SampledPageTopColor.DifferentColorsIndividuallyAboveMaxDifference):
+    (TEST.SampledPageTopColor.DifferentColorsCumulativelyAboveMaxDifference):
+    (TEST.SampledPageTopColor.DisplayP3):
+    (TEST.SampledPageTopColor.ExperimentalUseSampledPageTopColorForScrollAreaBackgroundColor):
+    
+    * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+    
+    
+    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@276744 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+    2021-04-28  Devin Rousso  <drou...@apple.com>
+
+            experiment with averaging sampling colors across the top of the page as the scroll area background
+            https://bugs.webkit.org/show_bug.cgi?id=224987
+            <rdar://problem/76251889>
+
+            Reviewed by Darin Adler.
+
+            * TestWebKitAPI/Tests/WebKitCocoa/SampledPageTopColor.mm: Added.
+            (-[TestKVOWrapper initWithObservable:keyPath:callback:]):
+            (-[TestKVOWrapper dealloc]):
+            (-[TestKVOWrapper observeValueForKeyPath:ofObject:change:context:]):
+            (createWebViewWithSampledPageTopColorMaxDifference):
+            (waitForSampledPageTopColorToChangeForHTML):
+            (createHTMLGradientWithColorStops):
+            (TEST.SampledPageTopColor.ZeroMaxDifference):
+            (TEST.SampledPageTopColor.NegativeMaxDifference):
+            (TEST.SampledPageTopColor.SolidColor):
+            (TEST.SampledPageTopColor.DifferentColorsWithoutOutlierBelowMaxDifference):
+            (TEST.SampledPageTopColor.DifferentColorsWithLeftOutlierAboveMaxDifference):
+            (TEST.SampledPageTopColor.DifferentColorsWithMiddleOutlierAboveMaxDifference):
+            (TEST.SampledPageTopColor.DifferentColorsWithRightOutlierAboveMaxDifference):
+            (TEST.SampledPageTopColor.DifferentColorsIndividuallyAboveMaxDifference):
+            (TEST.SampledPageTopColor.DifferentColorsCumulativelyAboveMaxDifference):
+            (TEST.SampledPageTopColor.DisplayP3):
+            (TEST.SampledPageTopColor.ExperimentalUseSampledPageTopColorForScrollAreaBackgroundColor):
+
+            * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+
 2021-04-27  Ruben Turcios  <rubent...@apple.com>
 
         Cherry-pick r276652. rdar://problem/77235499

Modified: branches/safari-612.1.12-branch/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (276860 => 276861)


--- branches/safari-612.1.12-branch/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2021-04-30 23:01:10 UTC (rev 276860)
+++ branches/safari-612.1.12-branch/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2021-04-30 23:04:06 UTC (rev 276861)
@@ -865,6 +865,7 @@
 		93F56DA71E5F9174003EDE84 /* libicucore.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 7C83E0331D0A5F2700FEBCF3 /* libicucore.dylib */; };
 		93F56DA91E5F919D003EDE84 /* WKWebViewSnapshot.mm in Sources */ = {isa = PBXBuildFile; fileRef = 93F56DA81E5F9181003EDE84 /* WKWebViewSnapshot.mm */; };
 		93F7E86F14DC8E5C00C84A99 /* NewFirstVisuallyNonEmptyLayoutFrames_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93F7E86E14DC8E5B00C84A99 /* NewFirstVisuallyNonEmptyLayoutFrames_Bundle.cpp */; };
+		95095F20262FFFA50000D920 /* SampledPageTopColor.mm in Sources */ = {isa = PBXBuildFile; fileRef = 95095F1F262FFFA50000D920 /* SampledPageTopColor.mm */; };
 		950E4CC1252E75240071659F /* iOSStylusSupport.mm in Sources */ = {isa = PBXBuildFile; fileRef = 950E4CC0252E75230071659F /* iOSStylusSupport.mm */; };
 		953ABB3525C0D682004C8B73 /* PageExtendedBackgroundColor.mm in Sources */ = {isa = PBXBuildFile; fileRef = 953ABB3425C0D681004C8B73 /* PageExtendedBackgroundColor.mm */; };
 		95A524952581A10D00461FE9 /* WKWebViewThemeColor.mm in Sources */ = {isa = PBXBuildFile; fileRef = 95A524942581A10D00461FE9 /* WKWebViewThemeColor.mm */; };
@@ -2555,6 +2556,7 @@
 		93F56DA81E5F9181003EDE84 /* WKWebViewSnapshot.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKWebViewSnapshot.mm; sourceTree = "<group>"; };
 		93F7E86B14DC8E4D00C84A99 /* NewFirstVisuallyNonEmptyLayoutFrames.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NewFirstVisuallyNonEmptyLayoutFrames.cpp; sourceTree = "<group>"; };
 		93F7E86E14DC8E5B00C84A99 /* NewFirstVisuallyNonEmptyLayoutFrames_Bundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NewFirstVisuallyNonEmptyLayoutFrames_Bundle.cpp; sourceTree = "<group>"; };
+		95095F1F262FFFA50000D920 /* SampledPageTopColor.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SampledPageTopColor.mm; sourceTree = "<group>"; };
 		950E4CC0252E75230071659F /* iOSStylusSupport.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = iOSStylusSupport.mm; sourceTree = "<group>"; };
 		953ABB3425C0D681004C8B73 /* PageExtendedBackgroundColor.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PageExtendedBackgroundColor.mm; sourceTree = "<group>"; };
 		95A524942581A10D00461FE9 /* WKWebViewThemeColor.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKWebViewThemeColor.mm; sourceTree = "<group>"; };
@@ -3525,6 +3527,7 @@
 				A180C0F91EE67DF000468F47 /* RunOpenPanel.mm */,
 				F4D2986D20FEE7370092D636 /* RunScriptAfterDocumentLoad.mm */,
 				5CA985512113CB8C0057EB6B /* SafeBrowsing.mm */,
+				95095F1F262FFFA50000D920 /* SampledPageTopColor.mm */,
 				CE0947362063223B003C9BA0 /* SchemeRegistry.mm */,
 				51EB12931FDF050500A5A1BD /* ServiceWorkerBasic.mm */,
 				5C683471235ACC7C0041E6B1 /* ServiceWorkerTCPServer.h */,
@@ -5636,6 +5639,7 @@
 				A180C0FA1EE67DF000468F47 /* RunOpenPanel.mm in Sources */,
 				F4D2986E20FEE7370092D636 /* RunScriptAfterDocumentLoad.mm in Sources */,
 				5CA985532113CF780057EB6B /* SafeBrowsing.mm in Sources */,
+				95095F20262FFFA50000D920 /* SampledPageTopColor.mm in Sources */,
 				CDCFA7AA1E45183200C2433D /* SampleMap.cpp in Sources */,
 				CE0947372063223B003C9BA0 /* SchemeRegistry.mm in Sources */,
 				CDC0932B21C872C10030C4B0 /* ScrollingDoesNotPauseMedia.mm in Sources */,

Added: branches/safari-612.1.12-branch/Tools/TestWebKitAPI/Tests/WebKitCocoa/SampledPageTopColor.mm (0 => 276861)


--- branches/safari-612.1.12-branch/Tools/TestWebKitAPI/Tests/WebKitCocoa/SampledPageTopColor.mm	                        (rev 0)
+++ branches/safari-612.1.12-branch/Tools/TestWebKitAPI/Tests/WebKitCocoa/SampledPageTopColor.mm	2021-04-30 23:04:06 UTC (rev 276861)
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+
+#import "TestCocoa.h"
+#import "TestWKWebView.h"
+#import "Utilities.h"
+#import <WebCore/Color.h>
+#import <WebKit/WKPreferencesPrivate.h>
+#import <WebKit/WKWebViewConfigurationPrivate.h>
+#import <WebKit/WKWebViewPrivate.h>
+#import <WebKit/_WKInternalDebugFeature.h>
+#import <wtf/Function.h>
+#import <wtf/RetainPtr.h>
+#import <wtf/text/StringBuilder.h>
+
+#define EXPECT_IN_RANGE(actual, min, max) \
+    EXPECT_GE(actual, min); \
+    EXPECT_LE(actual, max);
+
+@interface TestKVOWrapper : NSObject
+
+- (instancetype)initWithObservable:(NSObject *)observable keyPath:(NSString *)keyPath callback:(Function<void()>&&)callback;
+
+@end
+
+@implementation TestKVOWrapper {
+    RetainPtr<NSObject> _observable;
+    RetainPtr<NSString> _keyPath;
+    Function<void()> _callback;
+}
+
+- (instancetype)initWithObservable:(NSObject *)observable keyPath:(NSString *)keyPath callback:(Function<void()>&&)callback
+{
+    if (!(self = [super init]))
+        return nil;
+
+    _observable = observable;
+    _keyPath = keyPath;
+    _callback = WTFMove(callback);
+
+    [_observable addObserver:self forKeyPath:_keyPath.get() options:0 context:nil];
+
+    return self;
+}
+
+- (void)dealloc
+{
+    [_observable removeObserver:self forKeyPath:_keyPath.get() context:nullptr];
+
+    [super dealloc];
+}
+
+- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
+{
+    _callback();
+}
+
+@end
+
+enum class UseSampledPageTopColorForScrollAreaBackgroundColor : bool { Yes, No };
+static RetainPtr<TestWKWebView> createWebViewWithSampledPageTopColorMaxDifference(double sampledPageTopColorMaxDifference, UseSampledPageTopColorForScrollAreaBackgroundColor useSampledPageTopColorForScrollAreaBackgroundColor = UseSampledPageTopColorForScrollAreaBackgroundColor::No)
+{
+    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    [configuration _setSampledPageTopColorMaxDifference:sampledPageTopColorMaxDifference];
+
+    for (_WKInternalDebugFeature *feature in [WKPreferences _internalDebugFeatures]) {
+        if ([feature.key isEqualToString:@"UseSampledPageTopColorForScrollAreaBackgroundColor"]) {
+            [[configuration preferences] _setEnabled:(useSampledPageTopColorForScrollAreaBackgroundColor == UseSampledPageTopColorForScrollAreaBackgroundColor::Yes) forInternalDebugFeature:feature];
+            break;
+        }
+    }
+
+    return adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) configuration:configuration.get()]);
+}
+
+static void waitForSampledPageTopColorToChangeForHTML(TestWKWebView *webView, String&& html)
+{
+    bool done = false;
+    auto sampledPageTopColorObserver = adoptNS([[TestKVOWrapper alloc] initWithObservable:webView keyPath:@"_sampledPageTopColor" callback:[&] {
+        done = true;
+    }]);
+    [webView synchronouslyLoadHTMLStringAndWaitUntilAllImmediateChildFramesPaint:WTFMove(html)];
+    TestWebKitAPI::Util::run(&done);
+}
+
+static String createHTMLGradientWithColorStops(Vector<String>&& colorStops)
+{
+    EXPECT_GE(colorStops.size(), 2UL);
+
+    StringBuilder gradientBuilder;
+    gradientBuilder.append("<body style=\"background-image: linear-gradient(to right"_s);
+    for (auto&& colorStop : WTFMove(colorStops)) {
+        gradientBuilder.append(", "_s);
+        gradientBuilder.append(WTFMove(colorStop));
+    }
+    gradientBuilder.append(")\">Test"_s);
+    return gradientBuilder.toString();
+}
+
+TEST(SampledPageTopColor, ZeroMaxDifference)
+{
+    auto webView = createWebViewWithSampledPageTopColorMaxDifference(0);
+    EXPECT_NULL([webView _sampledPageTopColor]);
+
+    [webView synchronouslyLoadHTMLStringAndWaitUntilAllImmediateChildFramesPaint:createHTMLGradientWithColorStops({ "red", "red" })];
+    EXPECT_NULL([webView _sampledPageTopColor]);
+}
+
+TEST(SampledPageTopColor, NegativeMaxDifference)
+{
+    auto webView = createWebViewWithSampledPageTopColorMaxDifference(-5);
+    EXPECT_NULL([webView _sampledPageTopColor]);
+
+    [webView synchronouslyLoadHTMLStringAndWaitUntilAllImmediateChildFramesPaint:createHTMLGradientWithColorStops({ "red", "red" })];
+    EXPECT_NULL([webView _sampledPageTopColor]);
+}
+
+TEST(SampledPageTopColor, SolidColor)
+{
+    auto webView = createWebViewWithSampledPageTopColorMaxDifference(5);
+    EXPECT_NULL([webView _sampledPageTopColor]);
+
+    waitForSampledPageTopColorToChangeForHTML(webView.get(), createHTMLGradientWithColorStops({ "red", "red" }));
+    EXPECT_EQ(WebCore::Color([webView _sampledPageTopColor].CGColor), WebCore::Color::red);
+}
+
+TEST(SampledPageTopColor, DifferentColorsWithoutOutlierBelowMaxDifference)
+{
+    auto webView = createWebViewWithSampledPageTopColorMaxDifference(5);
+    EXPECT_NULL([webView _sampledPageTopColor]);
+
+    waitForSampledPageTopColorToChangeForHTML(webView.get(), createHTMLGradientWithColorStops({
+        "lab(1% 0 0)"_s,
+        "lab(2% 0 0)"_s,
+        "lab(3% 0 0)"_s,
+        "lab(4% 0 0)"_s,
+        "lab(5% 0 0)"_s,
+    }));
+
+    auto components = CGColorGetComponents([webView _sampledPageTopColor].CGColor);
+    EXPECT_IN_RANGE(components[0], 0.04, 0.05);
+    EXPECT_IN_RANGE(components[1], 0.04, 0.05);
+    EXPECT_IN_RANGE(components[2], 0.04, 0.05);
+    EXPECT_EQ(components[3], 1);
+}
+
+TEST(SampledPageTopColor, DifferentColorsWithLeftOutlierAboveMaxDifference)
+{
+    auto webView = createWebViewWithSampledPageTopColorMaxDifference(5);
+    EXPECT_NULL([webView _sampledPageTopColor]);
+
+    waitForSampledPageTopColorToChangeForHTML(webView.get(), createHTMLGradientWithColorStops({
+        "lab(100% 0 0)"_s, // outlier
+        "lab(1% 0 0)"_s,
+        "lab(2% 0 0)"_s,
+        "lab(3% 0 0)"_s,
+        "lab(4% 0 0)"_s,
+    }));
+
+    auto components = CGColorGetComponents([webView _sampledPageTopColor].CGColor);
+    EXPECT_IN_RANGE(components[0], 0.03, 0.04);
+    EXPECT_IN_RANGE(components[1], 0.03, 0.04);
+    EXPECT_IN_RANGE(components[2], 0.03, 0.04);
+    EXPECT_EQ(components[3], 1);
+}
+
+TEST(SampledPageTopColor, DifferentColorsWithMiddleOutlierAboveMaxDifference)
+{
+    auto webView = createWebViewWithSampledPageTopColorMaxDifference(5);
+    EXPECT_NULL([webView _sampledPageTopColor]);
+
+    [webView synchronouslyLoadHTMLStringAndWaitUntilAllImmediateChildFramesPaint:createHTMLGradientWithColorStops({
+        "lab(1% 0 0)"_s,
+        "lab(2% 0 0)"_s,
+        "lab(100% 0 0)"_s, // outlier
+        "lab(3% 0 0)"_s,
+        "lab(4% 0 0)"_s,
+    })];
+    EXPECT_NULL([webView _sampledPageTopColor]);
+}
+
+TEST(SampledPageTopColor, DifferentColorsWithRightOutlierAboveMaxDifference)
+{
+    auto webView = createWebViewWithSampledPageTopColorMaxDifference(5);
+    EXPECT_NULL([webView _sampledPageTopColor]);
+
+    waitForSampledPageTopColorToChangeForHTML(webView.get(), createHTMLGradientWithColorStops({
+        "lab(1% 0 0)"_s,
+        "lab(2% 0 0)"_s,
+        "lab(3% 0 0)"_s,
+        "lab(4% 0 0)"_s,
+        "lab(100% 0 0)"_s, // outlier
+    }));
+
+    auto components = CGColorGetComponents([webView _sampledPageTopColor].CGColor);
+    EXPECT_IN_RANGE(components[0], 0.03, 0.04);
+    EXPECT_IN_RANGE(components[1], 0.03, 0.04);
+    EXPECT_IN_RANGE(components[2], 0.03, 0.04);
+    EXPECT_EQ(components[3], 1);
+}
+
+TEST(SampledPageTopColor, DifferentColorsIndividuallyAboveMaxDifference)
+{
+    auto webView = createWebViewWithSampledPageTopColorMaxDifference(5);
+    EXPECT_NULL([webView _sampledPageTopColor]);
+
+    [webView synchronouslyLoadHTMLStringAndWaitUntilAllImmediateChildFramesPaint:createHTMLGradientWithColorStops({
+        "lab(10% 0 0)"_s,
+        "lab(20% 0 0)"_s,
+        "lab(30% 0 0)"_s,
+        "lab(40% 0 0)"_s,
+        "lab(50% 0 0)"_s,
+    })];
+    EXPECT_NULL([webView _sampledPageTopColor]);
+}
+
+TEST(SampledPageTopColor, DifferentColorsCumulativelyAboveMaxDifference)
+{
+    auto webView = createWebViewWithSampledPageTopColorMaxDifference(5);
+    EXPECT_NULL([webView _sampledPageTopColor]);
+
+    [webView synchronouslyLoadHTMLStringAndWaitUntilAllImmediateChildFramesPaint:createHTMLGradientWithColorStops({
+        "lab(1% 0 0)"_s,
+        "lab(3% 0 0)"_s,
+        "lab(5% 0 0)"_s,
+        "lab(7% 0 0)"_s,
+        "lab(9% 0 0)"_s,
+    })];
+    EXPECT_NULL([webView _sampledPageTopColor]);
+}
+
+// FIXME: <https://webkit.org/b/225167> (Sampled Page Top Color: hook into painting logic instead of taking snapshots)
+TEST(SampledPageTopColor, DISABLED_DisplayP3)
+{
+    auto webView = createWebViewWithSampledPageTopColorMaxDifference(5);
+    EXPECT_NULL([webView _sampledPageTopColor]);
+
+    [webView synchronouslyLoadHTMLStringAndWaitUntilAllImmediateChildFramesPaint:createHTMLGradientWithColorStops({
+        "color(display-p3 0.99 0 0)"_s,
+        "color(display-p3 0.98 0 0)"_s,
+        "color(display-p3 0.97 0 0)"_s,
+        "color(display-p3 0.96 0 0)"_s,
+        "color(display-p3 0.95 0 0)"_s,
+    })];
+
+    auto components = CGColorGetComponents([webView _sampledPageTopColor].CGColor);
+    EXPECT_IN_RANGE(components[0], 0.3, 0.4);
+    EXPECT_IN_RANGE(components[1], 1.00, 1.01);
+    EXPECT_IN_RANGE(components[2], 1.00, 1.01);
+    EXPECT_EQ(components[3], 1);
+}
+
+#if PLATFORM(IOS_FAMILY)
+
+// There's no API/SPI to get the background color of the scroll area on macOS.
+
+TEST(SampledPageTopColor, ExperimentalUseSampledPageTopColorForScrollAreaBackgroundColor)
+{
+    auto webViewWithoutThemeColorForScrollAreaBackgroundColor = createWebViewWithSampledPageTopColorMaxDifference(5, UseSampledPageTopColorForScrollAreaBackgroundColor::No);
+    EXPECT_NULL([webViewWithoutThemeColorForScrollAreaBackgroundColor _sampledPageTopColor]);
+
+    [webViewWithoutThemeColorForScrollAreaBackgroundColor synchronouslyLoadHTMLStringAndWaitUntilAllImmediateChildFramesPaint:createHTMLGradientWithColorStops({ "red", "blue" })];
+    EXPECT_NULL([webViewWithoutThemeColorForScrollAreaBackgroundColor _sampledPageTopColor]);
+    EXPECT_EQ(WebCore::Color([webViewWithoutThemeColorForScrollAreaBackgroundColor scrollView].backgroundColor.CGColor), WebCore::Color::white);
+
+    waitForSampledPageTopColorToChangeForHTML(webViewWithoutThemeColorForScrollAreaBackgroundColor.get(), createHTMLGradientWithColorStops({ "red", "red" }));
+    EXPECT_EQ(WebCore::Color([webViewWithoutThemeColorForScrollAreaBackgroundColor _sampledPageTopColor].CGColor), WebCore::Color::red);
+    EXPECT_EQ(WebCore::Color([webViewWithoutThemeColorForScrollAreaBackgroundColor scrollView].backgroundColor.CGColor), WebCore::Color::white);
+
+    auto webViewWithThemeColorForScrollAreaBackgroundColor = createWebViewWithSampledPageTopColorMaxDifference(5, UseSampledPageTopColorForScrollAreaBackgroundColor::Yes);
+    EXPECT_NULL([webViewWithThemeColorForScrollAreaBackgroundColor _sampledPageTopColor]);
+
+    [webViewWithThemeColorForScrollAreaBackgroundColor synchronouslyLoadHTMLStringAndWaitUntilAllImmediateChildFramesPaint:createHTMLGradientWithColorStops({ "red", "blue" })];
+    EXPECT_NULL([webViewWithThemeColorForScrollAreaBackgroundColor _sampledPageTopColor]);
+    EXPECT_EQ(WebCore::Color([webViewWithThemeColorForScrollAreaBackgroundColor scrollView].backgroundColor.CGColor), WebCore::Color::white);
+
+    waitForSampledPageTopColorToChangeForHTML(webViewWithThemeColorForScrollAreaBackgroundColor.get(), createHTMLGradientWithColorStops({ "red", "red" }));
+    EXPECT_EQ(WebCore::Color([webViewWithThemeColorForScrollAreaBackgroundColor _sampledPageTopColor].CGColor), WebCore::Color::red);
+    EXPECT_EQ(WebCore::Color([webViewWithThemeColorForScrollAreaBackgroundColor scrollView].backgroundColor.CGColor), WebCore::Color::red);
+}
+
+#endif // PLATFORM(IOS_FAMILY)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to