Title: [293729] trunk
Revision
293729
Author
yu...@chromium.org
Date
2022-05-03 10:06:02 -0700 (Tue, 03 May 2022)

Log Message

[WK2] Add API to allow embedder to set a timezone override
https://bugs.webkit.org/show_bug.cgi?id=213884

Source/_javascript_Core:

Reviewed by Yusuke Suzuki.

* runtime/DateConstructor.cpp:
(JSC::JSC_DEFINE_HOST_FUNCTION):
* runtime/DateConversion.cpp:
(JSC::formatDateTime): Format the overridden timezone if it's enabled.
* runtime/DateConversion.h:
* runtime/DatePrototype.cpp:
(JSC::formateDateInstance):
* runtime/JSDateMath.cpp:
(JSC::toICUTimeZone):
(JSC::toOpaqueICUTimeZone):
(JSC::OpaqueICUTimeZoneDeleter::operator()):
(JSC::DateCache::calculateLocalTimeOffset):
(JSC::DateCache::defaultTimeZone):
(JSC::DateCache::timeZoneDisplayNameOverride):
(JSC::DateCache::timeZoneCacheSlow): Apply timezone override if it is set.
(JSC::DateCache::resetIfNecessary):
* runtime/JSDateMath.h:

Source/WebKit:

Reviewed by Yusuke Suzuki.

This patch adds:

- new Cocoa API
- new Glib API (targetting both WPE and GTK ports)
- new C API (for the win port)

that allows the embedder to set a timezone override for the underlying PageConfiguration.
Since this API is not exposed in glib ports, a new contruct-time-only property was added to
the WebKitWebContext API. It would also allow fine-grained control over multiple pages, for
instance it's not possible currently to have two pages in different timezones.

No new layout tests, this change is covered by new API tests.

* Shared/WebProcessCreationParameters.cpp:
(WebKit::WebProcessCreationParameters::encode const):
(WebKit::WebProcessCreationParameters::decode):
* Shared/WebProcessCreationParameters.h:
* UIProcess/API/APIProcessPoolConfiguration.cpp:
(API::ProcessPoolConfiguration::copy):
* UIProcess/API/APIProcessPoolConfiguration.h:
* UIProcess/API/C/WKContextConfigurationRef.cpp:
(WKContextConfigurationCopyTimeZoneOverride):
(WKContextConfigurationSetTimeZoneOverride):
* UIProcess/API/C/WKContextConfigurationRef.h:
* UIProcess/API/Cocoa/_WKProcessPoolConfiguration.h:
* UIProcess/API/Cocoa/_WKProcessPoolConfiguration.mm:
(-[_WKProcessPoolConfiguration timeZoneOverride]):
(-[_WKProcessPoolConfiguration setTimeZoneOverride:]):
* UIProcess/API/glib/WebKitWebContext.cpp:
(webkitWebContextGetProperty):
(webkitWebContextSetProperty):
(webkitWebContextConstructed):
(webkit_web_context_class_init):
(webkit_web_context_set_time_zone_override):
(webkit_web_context_get_time_zone_override):
* UIProcess/API/gtk/WebKitWebContext.h:
* UIProcess/API/wpe/WebKitWebContext.h:
* UIProcess/WebProcessPool.cpp:
(WebKit::WebProcessPool::initializeNewWebProcess):
* WebProcess/WebProcess.cpp:
(WebKit::WebProcess::initializeWebProcess): Apply timezone override if any on process start.

Source/WTF:

Reviewed by Yusuke Suzuki.

* wtf/DateMath.cpp: New APIs to control and query the timezone override.
(WTF::innerTimeZoneOverride): Static storage of the override informations.
(WTF::WTF_REQUIRES_LOCK):
(WTF::validateTimeZone): New function allowing to check if a timezone identifier is valid according to ICU's database and covert it
to UChar buffer suitable for passing to ucal.
(WTF::isTimeZoneValid):
(WTF::setTimeZoneOverride): New API to set the timezone override, this is meant to be
used on newly created WebProcesses. In addition to providing alternative name for the code
that calls into ICU library, on POSIX systems writes new timezone to "TZ" environement
variable to adjust result of strftime (called in formatDateTime).
(WTF::getTimeZoneOverride): Query the timezone override.
* wtf/DateMath.h:

Tools:

Reviewed by Yusuke Suzuki.

Add API tests for the timezone configuration API. The GTK and WPE MiniBrowsers also gained
new runtime options allowing to exercise this new API.

* MiniBrowser/gtk/main.c:
(activate):
* MiniBrowser/wpe/main.cpp:
(main):
* TestWebKitAPI/SourcesCocoa.txt:
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebKitCocoa/TimeZoneOverride.mm: Added.
(TimeZoneOverrideTest::runScriptAndExecuteCallback):
(TimeZoneOverrideTest::callAsyncFunctionBody):
(TEST_F):
* TestWebKitAPI/Tests/WebKitGLib/TestWebKitWebContext.cpp:
(testWebContextTimeZoneOverride):
(testWebContextTimeZoneOverrideInWorker):
(beforeAll):
* TestWebKitAPI/glib/WebKitGLib/TestMain.cpp:
(main):
* TestWebKitAPI/glib/WebKitGLib/WebViewTest.cpp:
(runJavaScriptReadyCallback):
(WebViewTest::runJavaScriptAndWaitUntilFinished):
* TestWebKitAPI/glib/WebKitGLib/WebViewTest.h:
* flatpak/flatpakutils.py:
(WebkitFlatpak.run_in_sandbox):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (293728 => 293729)


--- trunk/Source/_javascript_Core/ChangeLog	2022-05-03 16:09:40 UTC (rev 293728)
+++ trunk/Source/_javascript_Core/ChangeLog	2022-05-03 17:06:02 UTC (rev 293729)
@@ -1,3 +1,29 @@
+2022-05-03  Philippe Normand  <pnorm...@igalia.com> and Pavel Feldman <pavel.feld...@gmail.com> and Yury Semikhatsky <yu...@chromium.org>
+
+        [WK2] Add API to allow embedder to set a timezone override
+        https://bugs.webkit.org/show_bug.cgi?id=213884
+
+        Reviewed by Yusuke Suzuki.
+
+        * runtime/DateConstructor.cpp:
+        (JSC::JSC_DEFINE_HOST_FUNCTION):
+        * runtime/DateConversion.cpp:
+        (JSC::formatDateTime): Format the overridden timezone if it's enabled.
+        * runtime/DateConversion.h:
+        * runtime/DatePrototype.cpp:
+        (JSC::formateDateInstance):
+        * runtime/JSDateMath.cpp:
+        (JSC::toICUTimeZone):
+        (JSC::toOpaqueICUTimeZone):
+        (JSC::OpaqueICUTimeZoneDeleter::operator()):
+        (JSC::DateCache::calculateLocalTimeOffset):
+        (JSC::DateCache::defaultTimeZone):
+        (JSC::DateCache::timeZoneDisplayNameOverride):
+        (JSC::DateCache::timeZoneCacheSlow): Apply timezone override if it is set.
+        (JSC::DateCache::resetIfNecessary):
+        * runtime/JSDateMath.h:
+
+
 2022-04-29  Yusuke Suzuki  <ysuz...@apple.com>
 
         [JSC] Introduce unlinked version of invalidation

Modified: trunk/Source/_javascript_Core/runtime/JSDateMath.cpp (293728 => 293729)


--- trunk/Source/_javascript_Core/runtime/JSDateMath.cpp	2022-05-03 16:09:40 UTC (rev 293728)
+++ trunk/Source/_javascript_Core/runtime/JSDateMath.cpp	2022-05-03 17:06:02 UTC (rev 293729)
@@ -433,12 +433,18 @@
 void DateCache::timeZoneCacheSlow()
 {
     ASSERT(!m_timeZoneCache);
+
+    Vector<UChar, 32> timeZoneID;
+    getTimeZoneOverride(timeZoneID);
 #if HAVE(ICU_C_TIMEZONE_API)
     auto* cache = new OpaqueICUTimeZone;
 
     String canonical;
-    Vector<UChar, 32> timeZoneID;
-    auto status = callBufferProducingFunction(ucal_getHostTimeZone, timeZoneID);
+    UErrorCode status = U_ZERO_ERROR;
+    if (timeZoneID.isEmpty()) {
+        status = callBufferProducingFunction(ucal_getHostTimeZone, timeZoneID);
+        ASSERT_UNUSED(status, U_SUCCESS(status));
+    }
     if (U_SUCCESS(status)) {
         Vector<UChar, 32> canonicalBuffer;
         auto status = callBufferProducingFunction(ucal_getCanonicalTimeZoneID, timeZoneID.data(), timeZoneID.size(), canonicalBuffer, nullptr);
@@ -455,6 +461,10 @@
     ucal_setGregorianChange(cache->m_calendar.get(), minECMAScriptTime, &status); // Ignore "unsupported" error.
     m_timeZoneCache = std::unique_ptr<OpaqueICUTimeZone, OpaqueICUTimeZoneDeleter>(cache);
 #else
+    if (!timeZoneID.isEmpty()) {
+        m_timeZoneCache = std::unique_ptr<OpaqueICUTimeZone, OpaqueICUTimeZoneDeleter>(toOpaqueICUTimeZone(icu::TimeZone::createTimeZone(icu::UnicodeString(timeZoneID.data(), timeZoneID.size()))));
+        return;
+    }
     // Do not use icu::TimeZone::createDefault. ICU internally has a cache for timezone and createDefault returns this cached value.
     m_timeZoneCache = std::unique_ptr<OpaqueICUTimeZone, OpaqueICUTimeZoneDeleter>(toOpaqueICUTimeZone(icu::TimeZone::detectHostTimeZone()));
 #endif

Modified: trunk/Source/WTF/ChangeLog (293728 => 293729)


--- trunk/Source/WTF/ChangeLog	2022-05-03 16:09:40 UTC (rev 293728)
+++ trunk/Source/WTF/ChangeLog	2022-05-03 17:06:02 UTC (rev 293729)
@@ -1,3 +1,23 @@
+2022-05-03  Philippe Normand  <pnorm...@igalia.com> and Pavel Feldman <pavel.feld...@gmail.com> and Yury Semikhatsky <yu...@chromium.org>
+
+        [WK2] Add API to allow embedder to set a timezone override
+        https://bugs.webkit.org/show_bug.cgi?id=213884
+
+        Reviewed by Yusuke Suzuki.
+
+        * wtf/DateMath.cpp: New APIs to control and query the timezone override.
+        (WTF::innerTimeZoneOverride): Static storage of the override informations.
+        (WTF::WTF_REQUIRES_LOCK):
+        (WTF::validateTimeZone): New function allowing to check if a timezone identifier is valid according to ICU's database and covert it
+        to UChar buffer suitable for passing to ucal.
+        (WTF::isTimeZoneValid):
+        (WTF::setTimeZoneOverride): New API to set the timezone override, this is meant to be
+        used on newly created WebProcesses. In addition to providing alternative name for the code
+        that calls into ICU library, on POSIX systems writes new timezone to "TZ" environement
+        variable to adjust result of strftime (called in formatDateTime).
+        (WTF::getTimeZoneOverride): Query the timezone override.
+        * wtf/DateMath.h:
+
 2022-05-02  Justin Michaud  <justin_mich...@apple.com>
 
         Add option to JSC shell to wait for a USR2 signal before exiting to aid in collection of vmmaps

Modified: trunk/Source/WTF/wtf/DateMath.cpp (293728 => 293729)


--- trunk/Source/WTF/wtf/DateMath.cpp	2022-05-03 16:09:40 UTC (rev 293728)
+++ trunk/Source/WTF/wtf/DateMath.cpp	2022-05-03 17:06:02 UTC (rev 293729)
@@ -76,9 +76,15 @@
 #include <limits>
 #include <stdint.h>
 #include <time.h>
+#include <unicode/ucal.h>
 #include <wtf/Assertions.h>
 #include <wtf/ASCIICType.h>
+#include <wtf/Language.h>
+#include <wtf/NeverDestroyed.h>
+#include <wtf/ThreadSpecific.h>
 #include <wtf/text/StringBuilder.h>
+#include <wtf/unicode/UTF8Conversion.h>
+#include <wtf/unicode/icu/ICUHelpers.h>
 
 #if OS(WINDOWS)
 #include <windows.h>
@@ -92,6 +98,13 @@
     return equalLettersIgnoringASCIICase(string, lowercaseLetters, length - 1);
 }
 
+static Lock innerTimeZoneOverrideLock;
+static Vector<UChar>& innerTimeZoneOverride() WTF_REQUIRES_LOCK(innerTimeZoneOverrideLock)
+{
+    static NeverDestroyed<Vector<UChar>> timeZoneOverride;
+    return timeZoneOverride;
+}
+
 /* Constants */
 
 const ASCIILiteral weekdayName[7] = { "Mon"_s, "Tue"_s, "Wed"_s, "Thu"_s, "Fri"_s, "Sat"_s, "Sun"_s };
@@ -1016,4 +1029,46 @@
     return stringBuilder.toString();
 }
 
+static std::optional<Vector<UChar, 32>> validateTimeZone(StringView timeZone)
+{
+    Vector<UChar, 32> buffer(timeZone.length());
+    timeZone.getCharactersWithUpconvert(buffer.data());
+
+    Vector<UChar, 32> canonicalBuffer;
+    auto status = callBufferProducingFunction(ucal_getCanonicalTimeZoneID, buffer.data(), buffer.size(), canonicalBuffer, nullptr);
+    if (!U_SUCCESS(status))
+        return std::nullopt;
+    return WTFMove(canonicalBuffer);
+}
+
+bool isTimeZoneValid(StringView timeZone)
+{
+    return validateTimeZone(timeZone).has_value();
+}
+
+bool setTimeZoneOverride(StringView timeZone)
+{
+    if (timeZone.isEmpty()) {
+        Locker locker { innerTimeZoneOverrideLock };
+        innerTimeZoneOverride().clear();
+        return true;
+    }
+
+    auto canonicalBuffer = validateTimeZone(timeZone);
+    if (!canonicalBuffer)
+        return false;
+
+    {
+        Locker locker { innerTimeZoneOverrideLock };
+        innerTimeZoneOverride() = WTFMove(*canonicalBuffer);
+    }
+    return true;
+}
+
+void getTimeZoneOverride(Vector<UChar, 32>& timeZoneID)
+{
+    Locker locker { innerTimeZoneOverrideLock };
+    timeZoneID = innerTimeZoneOverride();
+}
+
 } // namespace WTF

Modified: trunk/Source/WTF/wtf/DateMath.h (293728 => 293729)


--- trunk/Source/WTF/wtf/DateMath.h	2022-05-03 16:09:40 UTC (rev 293728)
+++ trunk/Source/WTF/wtf/DateMath.h	2022-05-03 17:06:02 UTC (rev 293729)
@@ -393,15 +393,25 @@
     return (((hour * WTF::minutesPerHour + min) * WTF::secondsPerMinute + sec) * WTF::msPerSecond + ms);
 }
 
+WTF_EXPORT_PRIVATE bool isTimeZoneValid(StringView);
+WTF_EXPORT_PRIVATE bool setTimeZoneOverride(StringView);
+WTF_EXPORT_PRIVATE void getTimeZoneOverride(Vector<UChar, 32>& timeZoneID);
+
 // Returns combined offset in millisecond (UTC + DST).
 WTF_EXPORT_PRIVATE LocalTimeOffset calculateLocalTimeOffset(double utcInMilliseconds, TimeType = UTCTime);
 
 } // namespace WTF
 
-using WTF::isLeapYear;
+using WTF::calculateLocalTimeOffset;
 using WTF::dateToDaysFrom1970;
 using WTF::dayInMonthFromDayInYear;
 using WTF::dayInYear;
+using WTF::getTimeZoneOverride;
+using WTF::isLeapYear;
+using WTF::isTimeZoneValid;
+using WTF::jsCurrentTime;
+using WTF::LocalTimeOffset;
+using WTF::makeRFC2822DateString;
 using WTF::minutesPerHour;
 using WTF::monthFromDayInYear;
 using WTF::msPerDay;
@@ -408,16 +418,13 @@
 using WTF::msPerHour;
 using WTF::msPerMinute;
 using WTF::msPerSecond;
-using WTF::msToYear;
 using WTF::msToDays;
+using WTF::msToHours;
 using WTF::msToMinutes;
-using WTF::msToHours;
+using WTF::msToYear;
+using WTF::parseDateFromNullTerminatedCharacters;
 using WTF::secondsPerDay;
 using WTF::secondsPerMinute;
-using WTF::parseDateFromNullTerminatedCharacters;
+using WTF::setTimeZoneOverride;
+using WTF::timeClip;
 using WTF::timeToMS;
-using WTF::makeRFC2822DateString;
-using WTF::LocalTimeOffset;
-using WTF::calculateLocalTimeOffset;
-using WTF::timeClip;
-using WTF::jsCurrentTime;

Modified: trunk/Source/WebKit/ChangeLog (293728 => 293729)


--- trunk/Source/WebKit/ChangeLog	2022-05-03 16:09:40 UTC (rev 293728)
+++ trunk/Source/WebKit/ChangeLog	2022-05-03 17:06:02 UTC (rev 293729)
@@ -1,3 +1,52 @@
+2022-05-03  Philippe Normand  <pnorm...@igalia.com> and Yury Semikhatsky <yu...@chromium.org>
+
+        [WK2] Add API to allow embedder to set a timezone override
+        https://bugs.webkit.org/show_bug.cgi?id=213884
+
+        Reviewed by Yusuke Suzuki.
+
+        This patch adds:
+
+        - new Cocoa API
+        - new Glib API (targetting both WPE and GTK ports)
+        - new C API (for the win port)
+
+        that allows the embedder to set a timezone override for the underlying PageConfiguration.
+        Since this API is not exposed in glib ports, a new contruct-time-only property was added to
+        the WebKitWebContext API. It would also allow fine-grained control over multiple pages, for
+        instance it's not possible currently to have two pages in different timezones.
+
+        No new layout tests, this change is covered by new API tests.
+
+        * Shared/WebProcessCreationParameters.cpp:
+        (WebKit::WebProcessCreationParameters::encode const):
+        (WebKit::WebProcessCreationParameters::decode):
+        * Shared/WebProcessCreationParameters.h:
+        * UIProcess/API/APIProcessPoolConfiguration.cpp:
+        (API::ProcessPoolConfiguration::copy):
+        * UIProcess/API/APIProcessPoolConfiguration.h:
+        * UIProcess/API/C/WKContextConfigurationRef.cpp:
+        (WKContextConfigurationCopyTimeZoneOverride):
+        (WKContextConfigurationSetTimeZoneOverride):
+        * UIProcess/API/C/WKContextConfigurationRef.h:
+        * UIProcess/API/Cocoa/_WKProcessPoolConfiguration.h:
+        * UIProcess/API/Cocoa/_WKProcessPoolConfiguration.mm:
+        (-[_WKProcessPoolConfiguration timeZoneOverride]):
+        (-[_WKProcessPoolConfiguration setTimeZoneOverride:]):
+        * UIProcess/API/glib/WebKitWebContext.cpp:
+        (webkitWebContextGetProperty):
+        (webkitWebContextSetProperty):
+        (webkitWebContextConstructed):
+        (webkit_web_context_class_init):
+        (webkit_web_context_set_time_zone_override):
+        (webkit_web_context_get_time_zone_override):
+        * UIProcess/API/gtk/WebKitWebContext.h:
+        * UIProcess/API/wpe/WebKitWebContext.h:
+        * UIProcess/WebProcessPool.cpp:
+        (WebKit::WebProcessPool::initializeNewWebProcess):
+        * WebProcess/WebProcess.cpp:
+        (WebKit::WebProcess::initializeWebProcess): Apply timezone override if any on process start.
+
 2022-05-03  Kimmo Kinnunen  <kkinnu...@apple.com>
 
         IPC stream connection sends should fail immediately when connection closes

Modified: trunk/Source/WebKit/Shared/WebProcessCreationParameters.cpp (293728 => 293729)


--- trunk/Source/WebKit/Shared/WebProcessCreationParameters.cpp	2022-05-03 16:09:40 UTC (rev 293728)
+++ trunk/Source/WebKit/Shared/WebProcessCreationParameters.cpp	2022-05-03 17:06:02 UTC (rev 293729)
@@ -214,6 +214,8 @@
 #if USE(ATSPI)
     encoder << accessibilityBusAddress;
 #endif
+
+    encoder << timeZoneOverride;
 }
 
 bool WebProcessCreationParameters::decode(IPC::Decoder& decoder, WebProcessCreationParameters& parameters)
@@ -571,6 +573,12 @@
     parameters.accessibilityBusAddress = WTFMove(*accessibilityBusAddress);
 #endif
 
+    std::optional<String> timeZoneOverride;
+    decoder >> timeZoneOverride;
+    if (!timeZoneOverride)
+        return false;
+    parameters.timeZoneOverride = WTFMove(*timeZoneOverride);
+
     return true;
 }
 

Modified: trunk/Source/WebKit/Shared/WebProcessCreationParameters.h (293728 => 293729)


--- trunk/Source/WebKit/Shared/WebProcessCreationParameters.h	2022-05-03 16:09:40 UTC (rev 293728)
+++ trunk/Source/WebKit/Shared/WebProcessCreationParameters.h	2022-05-03 17:06:02 UTC (rev 293729)
@@ -255,6 +255,8 @@
 #if USE(ATSPI)
     String accessibilityBusAddress;
 #endif
+
+    String timeZoneOverride;
 };
 
 } // namespace WebKit

Modified: trunk/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.cpp (293728 => 293729)


--- trunk/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.cpp	2022-05-03 16:09:40 UTC (rev 293728)
+++ trunk/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.cpp	2022-05-03 17:06:02 UTC (rev 293729)
@@ -84,6 +84,7 @@
 #if HAVE(AUDIT_TOKEN)
     copy->m_presentingApplicationProcessToken = this->m_presentingApplicationProcessToken;
 #endif
+    copy->m_timeZoneOverride = this->m_timeZoneOverride;
     return copy;
 }
 

Modified: trunk/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.h (293728 => 293729)


--- trunk/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.h	2022-05-03 16:09:40 UTC (rev 293728)
+++ trunk/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.h	2022-05-03 17:06:02 UTC (rev 293729)
@@ -164,6 +164,9 @@
     const std::optional<MemoryPressureHandler::Configuration>& memoryPressureHandlerConfiguration() const { return m_memoryPressureHandlerConfiguration; }
 #endif
 
+    void setTimeZoneOverride(const WTF::String& timeZoneOverride) { m_timeZoneOverride = timeZoneOverride; }
+    const WTF::String& timeZoneOverride() const { return m_timeZoneOverride; }
+
 private:
     WTF::String m_injectedBundlePath;
     Vector<WTF::String> m_customClassesForParameterCoder;
@@ -206,6 +209,7 @@
 #if HAVE(AUDIT_TOKEN)
     std::optional<audit_token_t> m_presentingApplicationProcessToken;
 #endif
+    WTF::String m_timeZoneOverride;
 };
 
 } // namespace API

Modified: trunk/Source/WebKit/UIProcess/API/C/WKContextConfigurationRef.cpp (293728 => 293729)


--- trunk/Source/WebKit/UIProcess/API/C/WKContextConfigurationRef.cpp	2022-05-03 16:09:40 UTC (rev 293728)
+++ trunk/Source/WebKit/UIProcess/API/C/WKContextConfigurationRef.cpp	2022-05-03 17:06:02 UTC (rev 293729)
@@ -222,3 +222,13 @@
 {
     toImpl(configuration)->setShouldConfigureJSCForTesting(value);
 }
+
+WKStringRef WKContextConfigurationCopyTimeZoneOverride(WKContextConfigurationRef configuration)
+{
+    return toCopiedAPI(toImpl(configuration)->timeZoneOverride());
+}
+
+void WKContextConfigurationSetTimeZoneOverride(WKContextConfigurationRef configuration, WKStringRef timeZoneOverride)
+{
+    toImpl(configuration)->setTimeZoneOverride(toImpl(timeZoneOverride)->string());
+}

Modified: trunk/Source/WebKit/UIProcess/API/C/WKContextConfigurationRef.h (293728 => 293729)


--- trunk/Source/WebKit/UIProcess/API/C/WKContextConfigurationRef.h	2022-05-03 16:09:40 UTC (rev 293728)
+++ trunk/Source/WebKit/UIProcess/API/C/WKContextConfigurationRef.h	2022-05-03 17:06:02 UTC (rev 293729)
@@ -95,6 +95,9 @@
     
 WK_EXPORT void WKContextConfigurationSetShouldConfigureJSCForTesting(WKContextConfigurationRef configuration, bool value);
 
+WK_EXPORT WKStringRef WKContextConfigurationCopyTimeZoneOverride(WKContextConfigurationRef configuration);
+WK_EXPORT void WKContextConfigurationSetTimeZoneOverride(WKContextConfigurationRef configuration, WKStringRef timeZoneOverride);
+
 #ifdef __cplusplus
 }
 #endif

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.h (293728 => 293729)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.h	2022-05-03 16:09:40 UTC (rev 293728)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.h	2022-05-03 17:06:02 UTC (rev 293729)
@@ -24,6 +24,7 @@
  */
 
 #import <Foundation/Foundation.h>
+#import <WebKit/WKBase.h>
 #import <WebKit/WKFoundation.h>
 
 NS_ASSUME_NONNULL_BEGIN
@@ -77,6 +78,8 @@
 
 @property (nonatomic) BOOL configureJSCForTesting WK_API_AVAILABLE(macos(10.15.4), ios(13.4));
 
+@property (nonatomic, nullable, copy) NSString *timeZoneOverride WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
+
 @end
 
 NS_ASSUME_NONNULL_END

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.mm (293728 => 293729)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.mm	2022-05-03 16:09:40 UTC (rev 293728)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.mm	2022-05-03 17:06:02 UTC (rev 293729)
@@ -403,6 +403,16 @@
     _processPoolConfiguration->setShouldConfigureJSCForTesting(value);
 }
 
+- (NSString *)timeZoneOverride
+{
+    return _processPoolConfiguration->timeZoneOverride();
+}
+
+- (void)setTimeZoneOverride:(NSString *)timeZone
+{
+    _processPoolConfiguration->setTimeZoneOverride(timeZone);
+}
+
 #pragma mark WKObject protocol implementation
 
 - (API::Object&)_apiObject

Modified: trunk/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp (293728 => 293729)


--- trunk/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp	2022-05-03 16:09:40 UTC (rev 293728)
+++ trunk/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp	2022-05-03 17:06:02 UTC (rev 293729)
@@ -65,6 +65,7 @@
 #include <libintl.h>
 #include <memory>
 #include <pal/HysteresisActivity.h>
+#include <wtf/DateMath.h>
 #include <wtf/FileSystem.h>
 #include <wtf/HashMap.h>
 #include <wtf/HashSet.h>
@@ -127,6 +128,7 @@
 #endif
 #endif
     PROP_MEMORY_PRESSURE_SETTINGS,
+    PROP_TIME_ZONE_OVERRIDE,
     N_PROPERTIES,
 };
 
@@ -245,6 +247,8 @@
     PAL::HysteresisActivity dnsPrefetchHystereris;
 
     WebKitMemoryPressureSettings* memoryPressureSettings;
+
+    String timeZoneOverride;
 };
 
 static guint signals[LAST_SIGNAL] = { 0, };
@@ -350,6 +354,9 @@
         break;
 #endif
 #endif
+    case PROP_TIME_ZONE_OVERRIDE:
+        g_value_set_string(value, webkit_web_context_get_time_zone_override(context));
+        break;
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propID, paramSpec);
     }
@@ -385,6 +392,11 @@
         context->priv->memoryPressureSettings = settings ? webkit_memory_pressure_settings_copy(static_cast<WebKitMemoryPressureSettings*>(settings)) : nullptr;
         break;
     }
+    case PROP_TIME_ZONE_OVERRIDE: {
+        if (const auto* override = g_value_get_string(value))
+            webkit_web_context_set_time_zone_override(context, override);
+        break;
+    }
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propID, paramSpec);
     }
@@ -413,6 +425,7 @@
         // Once the settings have been passed to the ProcessPoolConfiguration, we don't need them anymore so we can free them.
         g_clear_pointer(&priv->memoryPressureSettings, webkit_memory_pressure_settings_free);
     }
+    configuration.setTimeZoneOverride(priv->timeZoneOverride);
 
     if (!priv->websiteDataManager)
         priv->websiteDataManager = adoptGRef(webkit_website_data_manager_new("local-storage-directory", priv->localStorageDirectory.data(), nullptr));
@@ -572,6 +585,28 @@
             WEBKIT_TYPE_MEMORY_PRESSURE_SETTINGS,
             static_cast<GParamFlags>(WEBKIT_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
 
+    /**
+     * WebKitWebContext:time-zone-override:
+     *
+     * The timezone override for this web context. Setting this property provides a better
+     * alternative to configure the timezone information for all webviews managed by the WebContext.
+     * The other, less optimal, approach is to globally set the TZ environment variable in the
+     * process before creating the context. However this approach might not be very convenient and
+     * can have side-effects in your application.
+     *
+     * The expected values for this property are defined in the IANA timezone database. See this
+     * wikipedia page for instance, https://en.wikipedia.org/wiki/List_of_tz_database_time_zones.
+     *
+     * Since: 2.38
+     */
+    sObjProperties[PROP_TIME_ZONE_OVERRIDE] =
+        g_param_spec_string(
+            "time-zone-override",
+            _("Time Zone Override"),
+            _("The time zone to use instead of the system one"),
+            nullptr,
+            static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
     g_object_class_install_properties(gObjectClass, N_PROPERTIES, sObjProperties);
 
     /**
@@ -1835,6 +1870,39 @@
 }
 #endif
 
+/**
+ * webkit_web_context_set_time_zone_override:
+ * @context: a #WebKitWebContext
+ * @time_zone_override: value to set
+ *
+ * Set the #WebKitWebContext:time-zone-override property. Refer to the IANA database for valid
+ * specifiers, https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
+ *
+ * Since: 2.38
+ */
+void webkit_web_context_set_time_zone_override(WebKitWebContext* context, const gchar* timeZoneOverride)
+{
+    g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context));
+    g_return_if_fail(isTimeZoneValid(timeZoneOverride));
+
+    context->priv->timeZoneOverride = String::fromUTF8(timeZoneOverride);
+}
+
+/**
+ * webkit_web_context_get_time_zone_override:
+ * @context: a #WebKitWebContext
+ *
+ * Get the #WebKitWebContext:time-zone-override property.
+ *
+ * Since: 2.38
+ */
+const gchar* webkit_web_context_get_time_zone_override(WebKitWebContext* context)
+{
+    g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), nullptr);
+
+    return context->priv->timeZoneOverride.utf8().data();
+}
+
 void webkitWebContextInitializeNotificationPermissions(WebKitWebContext* context)
 {
     g_signal_emit(context, signals[INITIALIZE_NOTIFICATION_PERMISSIONS], 0);

Modified: trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebContext.h (293728 => 293729)


--- trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebContext.h	2022-05-03 16:09:40 UTC (rev 293728)
+++ trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebContext.h	2022-05-03 17:06:02 UTC (rev 293729)
@@ -302,6 +302,13 @@
 WEBKIT_API gboolean
 webkit_web_context_get_use_system_appearance_for_scrollbars (WebKitWebContext      *context);
 
+WEBKIT_API void
+webkit_web_context_set_time_zone_override           (WebKitWebContext              *context,
+                                                     const gchar                   *time_zone_override);
+
+WEBKIT_API const gchar*
+webkit_web_context_get_time_zone_override           (WebKitWebContext              *context);
+
 G_END_DECLS
 
 #endif

Modified: trunk/Source/WebKit/UIProcess/API/wpe/WebKitWebContext.h (293728 => 293729)


--- trunk/Source/WebKit/UIProcess/API/wpe/WebKitWebContext.h	2022-05-03 16:09:40 UTC (rev 293728)
+++ trunk/Source/WebKit/UIProcess/API/wpe/WebKitWebContext.h	2022-05-03 17:06:02 UTC (rev 293729)
@@ -291,6 +291,13 @@
 webkit_web_context_send_message_to_all_extensions   (WebKitWebContext              *context,
                                                      WebKitUserMessage             *message);
 
+WEBKIT_API void
+webkit_web_context_set_time_zone_override           (WebKitWebContext              *context,
+                                                     const gchar                   *time_zone_override);
+
+WEBKIT_API const gchar*
+webkit_web_context_get_time_zone_override           (WebKitWebContext              *context);
+
 G_END_DECLS
 
 #endif

Modified: trunk/Source/WebKit/UIProcess/WebProcessPool.cpp (293728 => 293729)


--- trunk/Source/WebKit/UIProcess/WebProcessPool.cpp	2022-05-03 16:09:40 UTC (rev 293728)
+++ trunk/Source/WebKit/UIProcess/WebProcessPool.cpp	2022-05-03 17:06:02 UTC (rev 293729)
@@ -913,6 +913,8 @@
 
     parameters.presentingApplicationPID = m_configuration->presentingApplicationPID();
 
+    parameters.timeZoneOverride = m_configuration->timeZoneOverride();
+
     // Add any platform specific parameters
     platformInitializeWebProcess(process, parameters);
 

Modified: trunk/Source/WebKit/WebProcess/WebProcess.cpp (293728 => 293729)


--- trunk/Source/WebKit/WebProcess/WebProcess.cpp	2022-05-03 16:09:40 UTC (rev 293728)
+++ trunk/Source/WebKit/WebProcess/WebProcess.cpp	2022-05-03 17:06:02 UTC (rev 293729)
@@ -143,6 +143,7 @@
 #include <pal/Logging.h>
 #include <wtf/Algorithms.h>
 #include <wtf/CallbackAggregator.h>
+#include <wtf/DateMath.h>
 #include <wtf/Language.h>
 #include <wtf/ProcessPrivilege.h>
 #include <wtf/RunLoop.h>
@@ -506,6 +507,9 @@
 
     setCacheModel(parameters.cacheModel);
 
+    if (!parameters.timeZoneOverride.isEmpty())
+        setTimeZoneOverride(parameters.timeZoneOverride);
+
     if (!parameters.overrideLanguages.isEmpty()) {
         LOG_WITH_STREAM(Language, stream << "Web Process initialization is setting overrideLanguages: " << parameters.overrideLanguages);
         overrideUserPreferredLanguages(parameters.overrideLanguages);

Modified: trunk/Tools/ChangeLog (293728 => 293729)


--- trunk/Tools/ChangeLog	2022-05-03 16:09:40 UTC (rev 293728)
+++ trunk/Tools/ChangeLog	2022-05-03 17:06:02 UTC (rev 293729)
@@ -1,3 +1,36 @@
+2022-05-03  Philippe Normand  <pnorm...@igalia.com> and Yury Semikhatsky <yu...@chromium.org>
+
+        [WK2] Add API to allow embedder to set a timezone override
+        https://bugs.webkit.org/show_bug.cgi?id=213884
+
+        Reviewed by Yusuke Suzuki.
+
+        Add API tests for the timezone configuration API. The GTK and WPE MiniBrowsers also gained
+        new runtime options allowing to exercise this new API.
+
+        * MiniBrowser/gtk/main.c:
+        (activate):
+        * MiniBrowser/wpe/main.cpp:
+        (main):
+        * TestWebKitAPI/SourcesCocoa.txt:
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WebKitCocoa/TimeZoneOverride.mm: Added.
+        (TimeZoneOverrideTest::runScriptAndExecuteCallback):
+        (TimeZoneOverrideTest::callAsyncFunctionBody):
+        (TEST_F):
+        * TestWebKitAPI/Tests/WebKitGLib/TestWebKitWebContext.cpp:
+        (testWebContextTimeZoneOverride):
+        (testWebContextTimeZoneOverrideInWorker):
+        (beforeAll):
+        * TestWebKitAPI/glib/WebKitGLib/TestMain.cpp:
+        (main):
+        * TestWebKitAPI/glib/WebKitGLib/WebViewTest.cpp:
+        (runJavaScriptReadyCallback):
+        (WebViewTest::runJavaScriptAndWaitUntilFinished):
+        * TestWebKitAPI/glib/WebKitGLib/WebViewTest.h:
+        * flatpak/flatpakutils.py:
+        (WebkitFlatpak.run_in_sandbox):
+
 2022-05-02  Wenson Hsieh  <wenson_hs...@apple.com>
 
         [macOS] The "Markup Image" services menu item should be gated on image analysis results

Modified: trunk/Tools/MiniBrowser/gtk/main.c (293728 => 293729)


--- trunk/Tools/MiniBrowser/gtk/main.c	2022-05-03 16:09:40 UTC (rev 293728)
+++ trunk/Tools/MiniBrowser/gtk/main.c	2022-05-03 17:06:02 UTC (rev 293729)
@@ -52,6 +52,7 @@
 static const char *cookiesPolicy;
 static const char *proxy;
 static gboolean darkMode;
+static char* timeZone;
 static gboolean enableITP;
 static gboolean enableSandbox;
 static gboolean exitAfterLoad;
@@ -149,6 +150,7 @@
     { "enable-itp", 0, 0, G_OPTION_ARG_NONE, &enableITP, "Enable Intelligent Tracking Prevention (ITP)", NULL },
     { "enable-sandbox", 0, 0, G_OPTION_ARG_NONE, &enableSandbox, "Enable web process sandbox support", NULL },
     { "exit-after-load", 0, 0, G_OPTION_ARG_NONE, &exitAfterLoad, "Quit the browser after the load finishes", NULL },
+    { "time-zone", 't', 0, G_OPTION_ARG_STRING, &timeZone, "Set time zone", "TIMEZONE" },
     { "version", 'v', 0, G_OPTION_ARG_NONE, &printVersion, "Print the WebKitGTK version", NULL },
     { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &uriArguments, 0, "[URL…]" },
     { 0, 0, 0, 0, 0, 0, 0 }
@@ -674,6 +676,7 @@
 #if !GTK_CHECK_VERSION(3, 98, 0)
         "use-system-appearance-for-scrollbars", FALSE,
 #endif
+        "time-zone-override", timeZone,
         NULL);
     g_object_unref(manager);
 

Modified: trunk/Tools/MiniBrowser/wpe/main.cpp (293728 => 293729)


--- trunk/Tools/MiniBrowser/wpe/main.cpp	2022-05-03 16:09:40 UTC (rev 293728)
+++ trunk/Tools/MiniBrowser/wpe/main.cpp	2022-05-03 17:06:02 UTC (rev 293729)
@@ -46,6 +46,7 @@
 static const char* cookiesPolicy;
 static const char* proxy;
 const char* bgColor;
+static char* timeZone;
 static gboolean enableITP;
 static gboolean printVersion;
 static GHashTable* openViews;
@@ -63,6 +64,7 @@
     { "content-filter", 0, 0, G_OPTION_ARG_FILENAME, &contentFilter, "JSON with content filtering rules", "FILE" },
     { "bg-color", 0, 0, G_OPTION_ARG_STRING, &bgColor, "Window background color. Default: white", "COLOR" },
     { "enable-itp", 0, 0, G_OPTION_ARG_NONE, &enableITP, "Enable Intelligent Tracking Prevention (ITP)", nullptr },
+    { "time-zone", 't', 0, G_OPTION_ARG_STRING, &timeZone, "Set time zone", "TIMEZONE" },
     { "version", 'v', 0, G_OPTION_ARG_NONE, &printVersion, "Print the WPE version", nullptr },
     { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &uriArguments, nullptr, "[URL]" },
     { nullptr, 0, 0, G_OPTION_ARG_NONE, nullptr, nullptr, nullptr }
@@ -229,7 +231,7 @@
     if (ignoreTLSErrors)
         webkit_website_data_manager_set_tls_errors_policy(manager, WEBKIT_TLS_ERRORS_POLICY_IGNORE);
 
-    auto* webContext = webkit_web_context_new_with_website_data_manager(manager);
+    auto* webContext = WEBKIT_WEB_CONTEXT(g_object_new(WEBKIT_TYPE_WEB_CONTEXT, "website-data-manager", manager, "time-zone-override", timeZone, nullptr));
     g_object_unref(manager);
 
     if (cookiesPolicy) {

Modified: trunk/Tools/TestWebKitAPI/SourcesCocoa.txt (293728 => 293729)


--- trunk/Tools/TestWebKitAPI/SourcesCocoa.txt	2022-05-03 16:09:40 UTC (rev 293728)
+++ trunk/Tools/TestWebKitAPI/SourcesCocoa.txt	2022-05-03 17:06:02 UTC (rev 293729)
@@ -240,6 +240,7 @@
 Tests/WebKitCocoa/TextManipulation.mm
 Tests/WebKitCocoa/TextSize.mm
 Tests/WebKitCocoa/TextWidth.mm
+Tests/WebKitCocoa/TimeZoneOverride.mm
 Tests/WebKitCocoa/TopContentInset.mm
 Tests/WebKitCocoa/UIDelegate.mm
 Tests/WebKitCocoa/UploadDirectory.mm

Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (293728 => 293729)


--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2022-05-03 16:09:40 UTC (rev 293728)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2022-05-03 17:06:02 UTC (rev 293729)
@@ -3032,6 +3032,7 @@
 		EBA75C48275ED7BE00D6D31C /* PushMessageCrypto.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PushMessageCrypto.cpp; sourceTree = "<group>"; };
 		EC79F168BE454E579E417B05 /* Markable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Markable.cpp; sourceTree = "<group>"; };
 		ECA680CD1E68CC0900731D20 /* StringUtilities.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = StringUtilities.mm; sourceTree = "<group>"; };
+		F3CEF6B82808F2D3001E23A5 /* TimeZoneOverride.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = TimeZoneOverride.mm; sourceTree = "<group>"; };
 		F3FC3EE213678B7300126A65 /* libgtest.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgtest.a; sourceTree = BUILT_PRODUCTS_DIR; };
 		F4010B7F24DA24AC00A876E2 /* NavigationSwipeTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = NavigationSwipeTests.mm; sourceTree = "<group>"; };
 		F4010B8124DA267F00A876E2 /* PoseAsClass.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = PoseAsClass.mm; path = ../TestRunnerShared/cocoa/PoseAsClass.mm; sourceTree = "<group>"; };
@@ -3704,6 +3705,7 @@
 				9B02E0D5235FA47D004044B2 /* TextManipulation.mm */,
 				5C16F8FB230C942B0074C4A8 /* TextSize.mm */,
 				C22FA32A228F8708009D7988 /* TextWidth.mm */,
+				F3CEF6B82808F2D3001E23A5 /* TimeZoneOverride.mm */,
 				5C73A81A2323059800DEA85A /* TLSDeprecation.mm */,
 				CDE195B31CFE0ADE0053D256 /* TopContentInset.mm */,
 				5CB40B4D1F4B98BE007DC7B9 /* UIDelegate.mm */,

Added: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/TimeZoneOverride.mm (0 => 293729)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/TimeZoneOverride.mm	                        (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/TimeZoneOverride.mm	2022-05-03 17:06:02 UTC (rev 293729)
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2022 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+
+#if PLATFORM(COCOA)
+
+#import "PlatformUtilities.h"
+#import "Test.h"
+#import "TestWKWebView.h"
+#import <WebKit/WKWebViewConfigurationPrivate.h>
+#import <WebKit/WKWebViewPrivate.h>
+#import <WebKit/_WKProcessPoolConfiguration.h>
+#import <wtf/Function.h>
+#import <wtf/text/WTFString.h>
+
+class TimeZoneOverrideTest : public testing::Test {
+public:
+    void SetUp() override
+    {
+        auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+        auto processPoolConfig = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
+        [processPoolConfig setTimeZoneOverride:@"Europe/Berlin"];
+
+        _webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 300, 300) configuration:configuration.get() processPoolConfiguration:processPoolConfig.get()]);
+    }
+
+    void runScriptAndExecuteCallback(const String& script, Function<void(id)>&& callback)
+    {
+        bool complete = false;
+        [_webView evaluateJavaScript:script completionHandler:[&] (id result, NSError *error) {
+            EXPECT_NULL(error);
+            callback(result);
+            complete = true;
+        }];
+        TestWebKitAPI::Util::run(&complete);
+    }
+
+    void callAsyncFunctionBody(const String& functionBody, Function<void(id)>&& callback)
+    {
+        bool complete = false;
+        [_webView callAsyncJavaScript:functionBody arguments:nil inFrame:nil inContentWorld:WKContentWorld.pageWorld completionHandler:[&] (id result, NSError *error) {
+            EXPECT_NULL(error);
+            callback(result);
+            complete = true;
+        }];
+        TestWebKitAPI::Util::run(&complete);
+    }
+
+
+private:
+    RetainPtr<TestWKWebView> _webView;
+};
+
+TEST_F(TimeZoneOverrideTest, TimeZoneOverride)
+{
+    runScriptAndExecuteCallback("let now = new Date(1651511226050); now.getTimezoneOffset()"_s, [](id result) {
+        EXPECT_WK_STREQ([result stringValue], "-120");
+    });
+}
+
+TEST_F(TimeZoneOverrideTest, TimeZoneOverrideInWorkers)
+{
+    String functionBody =
+        "return new Promise(fulfill => {"
+        "  const results = [Intl.DateTimeFormat().resolvedOptions().timeZone];"
+        "  for (let i = 0; i < 3; i++) {"
+        "    const worker = new Worker('data:text/_javascript_,self.postMessage(Intl.DateTimeFormat().resolvedOptions().timeZone)');"
+        "    worker._onmessage_ = message => {"
+        "      results.push(message.data);"
+        "      if (results.length === 4)"
+        "        fulfill(results.join(', '));"
+        "    };"
+        "  }"
+        "});"_s;
+    callAsyncFunctionBody(functionBody, [](id result) {
+        EXPECT_TRUE([result isKindOfClass:[NSString class]]);
+        EXPECT_WK_STREQ(result, @"Europe/Berlin, Europe/Berlin, Europe/Berlin, Europe/Berlin");
+    });
+}
+
+#endif

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitGLib/TestWebKitWebContext.cpp (293728 => 293729)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitGLib/TestWebKitWebContext.cpp	2022-05-03 16:09:40 UTC (rev 293728)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitGLib/TestWebKitWebContext.cpp	2022-05-03 17:06:02 UTC (rev 293729)
@@ -991,6 +991,58 @@
     g_assert_cmpuint(test->m_terminationReason, ==, WEBKIT_WEB_PROCESS_EXCEEDED_MEMORY_LIMIT);
 }
 
+static void testWebContextTimeZoneOverride(WebViewTest* test, gconstpointer)
+{
+    GUniqueOutPtr<GError> error;
+    WebKitJavascriptResult* _javascript_Result = test->runJavaScriptAndWaitUntilFinished("const date = new Date(1651511226050); date.getTimezoneOffset()", &error.outPtr());
+    g_assert_nonnull(_javascript_Result);
+    g_assert_no_error(error.get());
+    // By default the test harness uses the Pacific/Los_Angeles timezone which is 7 hours (420 minutes) compared to GMT.
+    g_assert_cmpint(WebViewTest::_javascript_ResultToNumber(_javascript_Result), ==, 420);
+
+    // Create a new context configured with time zone overide set to Berlin which is 120 minutes ahead of the GMT offset.
+    auto webContext = adoptGRef(WEBKIT_WEB_CONTEXT(g_object_new(WEBKIT_TYPE_WEB_CONTEXT,
+        "time-zone-override", "Europe/Berlin", nullptr)));
+    g_assert_cmpstr(webkit_web_context_get_time_zone_override(webContext.get()), ==, "Europe/Berlin");
+    auto webView = Test::adoptView(Test::createWebView(webContext.get()));
+    _javascript_Result = test->runJavaScriptAndWaitUntilFinished("const date = new Date(1651511226050); date.getTimezoneOffset()", &error.outPtr(), webView.get());
+    g_assert_nonnull(_javascript_Result);
+    g_assert_no_error(error.get());
+    g_assert_cmpint(WebViewTest::_javascript_ResultToNumber(_javascript_Result), ==, -120);
+}
+
+static void testWebContextTimeZoneOverrideInWorker(WebViewTest* test, gconstpointer)
+{
+    GUniqueOutPtr<GError> error;
+    WebKitJavascriptResult* _javascript_Result = test->runJavaScriptAndWaitUntilFinished("Intl.DateTimeFormat().resolvedOptions().timeZone", &error.outPtr());
+    g_assert_nonnull(_javascript_Result);
+    g_assert_no_error(error.get());
+    // By default the test harness uses the Pacific/Los_Angeles.
+    g_assert_cmpstr(WebViewTest::_javascript_ResultToCString(_javascript_Result), ==, "America/Los_Angeles");
+    // Create a new context configured with time zone overide set to Berlin which is 120 minutes ahead of the GMT offset.
+    auto webContext = adoptGRef(WEBKIT_WEB_CONTEXT(g_object_new(WEBKIT_TYPE_WEB_CONTEXT,
+        "time-zone-override", "Europe/Berlin", nullptr)));
+    g_assert_cmpstr(webkit_web_context_get_time_zone_override(webContext.get()), ==, "Europe/Berlin");
+    auto webView = Test::adoptView(Test::createWebView(webContext.get()));
+
+    test->runJavaScriptAndWaitUntilFinished(
+        "window.results = [Intl.DateTimeFormat().resolvedOptions().timeZone];"
+        "for (let i = 0; i < 3; i++) {"
+        "  const worker = new Worker('data:text/_javascript_,self.postMessage(Intl.DateTimeFormat().resolvedOptions().timeZone)');"
+        "  worker._onmessage_ = message => results.push(message.data);"
+        "}", &error.outPtr(), webView.get());
+    do {
+        _javascript_Result = test->runJavaScriptAndWaitUntilFinished("results.length", &error.outPtr(), webView.get());
+        g_assert_nonnull(_javascript_Result);
+        g_assert_no_error(error.get());
+    } while (WebViewTest::_javascript_ResultToNumber(_javascript_Result) < 4);
+
+    _javascript_Result = test->runJavaScriptAndWaitUntilFinished("results.join(', ')", &error.outPtr(), webView.get());
+    g_assert_nonnull(_javascript_Result);
+    g_assert_no_error(error.get());
+    g_assert_cmpstr(WebViewTest::_javascript_ResultToCString(_javascript_Result), ==, "Europe/Berlin, Europe/Berlin, Europe/Berlin, Europe/Berlin");
+}
+
 void beforeAll()
 {
     kServer = new WebKitTestServer();
@@ -1008,6 +1060,8 @@
     WebViewTest::add("WebKitSecurityManager", "file-xhr", testWebContextSecurityFileXHR);
     ProxyTest::add("WebKitWebContext", "proxy", testWebContextProxySettings);
     MemoryPressureTest::add("WebKitWebContext", "memory-pressure", testMemoryPressureSettings);
+    WebViewTest::add("WebKitWebContext", "timezone", testWebContextTimeZoneOverride);
+    WebViewTest::add("WebKitWebContext", "timezone-worker", testWebContextTimeZoneOverrideInWorker);
 }
 
 void afterAll()

Modified: trunk/Tools/TestWebKitAPI/glib/WebKitGLib/TestMain.cpp (293728 => 293729)


--- trunk/Tools/TestWebKitAPI/glib/WebKitGLib/TestMain.cpp	2022-05-03 16:09:40 UTC (rev 293728)
+++ trunk/Tools/TestWebKitAPI/glib/WebKitGLib/TestMain.cpp	2022-05-03 17:06:02 UTC (rev 293729)
@@ -132,6 +132,7 @@
     g_setenv("GSETTINGS_BACKEND", "memory", TRUE);
     // Get rid of runtime warnings about deprecated properties and signals, since they break the tests.
     g_setenv("G_ENABLE_DIAGNOSTIC", "0", TRUE);
+    g_setenv("TZ", "America/Los_Angeles", TRUE);
     g_test_bug_base("https://bugs.webkit.org/");
 
     registerGResource();

Modified: trunk/Tools/TestWebKitAPI/glib/WebKitGLib/WebViewTest.cpp (293728 => 293729)


--- trunk/Tools/TestWebKitAPI/glib/WebKitGLib/WebViewTest.cpp	2022-05-03 16:09:40 UTC (rev 293728)
+++ trunk/Tools/TestWebKitAPI/glib/WebKitGLib/WebViewTest.cpp	2022-05-03 17:06:02 UTC (rev 293729)
@@ -306,9 +306,9 @@
     return m_resourceData.get();
 }
 
-static void runJavaScriptReadyCallback(GObject*, GAsyncResult* result, WebViewTest* test)
+static void runJavaScriptReadyCallback(GObject* object, GAsyncResult* result, WebViewTest* test)
 {
-    test->m_javascriptResult = webkit_web_view_run_javascript_finish(test->m_webView, result, test->m_javascriptError);
+    test->m_javascriptResult = webkit_web_view_run_javascript_finish(WEBKIT_WEB_VIEW(object), result, test->m_javascriptError);
     g_main_loop_quit(test->m_mainLoop);
 }
 
@@ -324,13 +324,15 @@
     g_main_loop_quit(test->m_mainLoop);
 }
 
-WebKitJavascriptResult* WebViewTest::runJavaScriptAndWaitUntilFinished(const char* _javascript_, GError** error)
+WebKitJavascriptResult* WebViewTest::runJavaScriptAndWaitUntilFinished(const char* _javascript_, GError** error, WebKitWebView* webView)
 {
     if (m_javascriptResult)
         webkit_javascript_result_unref(m_javascriptResult);
     m_javascriptResult = 0;
     m_javascriptError = error;
-    webkit_web_view_run_javascript(m_webView, _javascript_, 0, reinterpret_cast<GAsyncReadyCallback>(runJavaScriptReadyCallback), this);
+    if (!webView)
+        webView = m_webView;
+    webkit_web_view_run_javascript(webView, _javascript_, 0, reinterpret_cast<GAsyncReadyCallback>(runJavaScriptReadyCallback), this);
     g_main_loop_run(m_mainLoop);
 
     return m_javascriptResult;

Modified: trunk/Tools/TestWebKitAPI/glib/WebKitGLib/WebViewTest.h (293728 => 293729)


--- trunk/Tools/TestWebKitAPI/glib/WebKitGLib/WebViewTest.h	2022-05-03 16:09:40 UTC (rev 293728)
+++ trunk/Tools/TestWebKitAPI/glib/WebKitGLib/WebViewTest.h	2022-05-03 17:06:02 UTC (rev 293729)
@@ -73,7 +73,7 @@
     void emitPopupMenuSignal();
 #endif
 
-    WebKitJavascriptResult* runJavaScriptAndWaitUntilFinished(const char* _javascript_, GError**);
+    WebKitJavascriptResult* runJavaScriptAndWaitUntilFinished(const char* _javascript_, GError**, WebKitWebView* = nullptr);
     WebKitJavascriptResult* runJavaScriptFromGResourceAndWaitUntilFinished(const char* resource, GError**);
     WebKitJavascriptResult* runJavaScriptInWorldAndWaitUntilFinished(const char* _javascript_, const char* world, GError**);
     WebKitJavascriptResult* runJavaScriptWithoutForcedUserGesturesAndWaitUntilFinished(const char* _javascript_, GError**);

Modified: trunk/Tools/flatpak/flatpakutils.py (293728 => 293729)


--- trunk/Tools/flatpak/flatpakutils.py	2022-05-03 16:09:40 UTC (rev 293728)
+++ trunk/Tools/flatpak/flatpakutils.py	2022-05-03 17:06:02 UTC (rev 293729)
@@ -857,7 +857,7 @@
             ])
 
             sandbox_environment.update({
-                "TZ": "PST8PDT",
+                "TZ": "America/Los_Angeles",
             })
 
         env_var_prefixes_to_keep = [
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to