Source/JavaScriptCore/ChangeLog

 12022-04-13 Philippe Normand <pnormand@igalia.com> and Pavel Feldman <pavel.feldman@gmail.com> and Yury Semikhatsky <yurys@chromium.org>
 2
 3 [WK2] Add API to allow embedder to set a timezone override
 4 https://bugs.webkit.org/show_bug.cgi?id=213884
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 * runtime/DateConversion.cpp:
 9 (JSC::formatDateTime): Format the overridden timezone if it's enabled.
 10 * runtime/JSDateMath.cpp:
 11 (JSC::DateCache::defaultTimeZone): Return the overridden timezone if it's enabled.
 12 (JSC::DateCache::timeZoneCacheSlow): Apply timezone override if it is set.
 13
1142022-04-14 Caitlin Potter <caitp@igalia.com>
215
316 [JSC] ShadowRealm global object has a mutable prototype

Source/WTF/ChangeLog

 12022-04-13 Philippe Normand <pnormand@igalia.com> and Pavel Feldman <pavel.feldman@gmail.com> and Yury Semikhatsky <yurys@chromium.org>
 2
 3 [WK2] Add API to allow embedder to set a timezone override
 4 https://bugs.webkit.org/show_bug.cgi?id=213884
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 * wtf/DateMath.cpp: Add new APIs to control and query the timezone override.
 9 (WTF::innerTimeZoneOverride): Static storage of the override informations.
 10 (WTF::calculateLocalTimeOffset): Calculate offset for overridden timezone, if it's present.
 11 (WTF::isTimeZoneValid): New function allowing to check if a timezone identifier is valid according to ICU's database.
 12 (WTF::setTimeZoneOverride): New API to set the timezone override, this is meant to be
 13 used on newly created WebProcesses.
 14 (WTF::timeZoneOverride):Query the timezone override.
 15 (WTF::timeZoneDisplayNameOverride): Get the timezone name of the overridden timezone.
 16 * wtf/DateMath.h:
 17
1182022-04-15 Zan Dobersek <zdobersek@igalia.com>
219
320 [GTK][WPE] Remove exclusive build guards around GPU process preferences, code

Source/WebKit/ChangeLog

 12022-04-13 Philippe Normand <pnormand@igalia.com> and Yury Semikhatsky <yurys@chromium.org>
 2
 3 [WK2] Add API to allow embedder to set a timezone override
 4 https://bugs.webkit.org/show_bug.cgi?id=213884
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 This patch adds:
 9
 10 - new Cocoa API
 11 - new Glib API (targetting both WPE and GTK ports)
 12 - new C API (for the win port)
 13
 14 that allows the embedder to set a timezone override for the underlying PageConfiguration.
 15 Since this API is not exposed in glib ports, a new contruct-time-only property was added to
 16 the WebKitWebContext API. It would also allow fine-grained control over multiple pages, for
 17 instance it's not possible currently to have two pages in different timezones.
 18
 19 No new layout tests, this change is covered by new API tests.
 20
 21 * Shared/WebPageCreationParameters.cpp:
 22 (WebKit::WebPageCreationParameters::encode const):
 23 (WebKit::WebPageCreationParameters::decode):
 24 * Shared/WebPageCreationParameters.h:
 25 * UIProcess/API/APIPageConfiguration.cpp:
 26 (API::PageConfiguration::copy const):
 27 * UIProcess/API/APIPageConfiguration.h:
 28 (API::PageConfiguration::setTimeZoneOverride):
 29 (API::PageConfiguration::timeZoneOverride const):
 30 * UIProcess/API/Cocoa/WKWebViewConfiguration.mm:
 31 (-[WKWebViewConfiguration _timeZoneOverride]):
 32 (-[WKWebViewConfiguration _setTimeZoneOverride:]):
 33 * UIProcess/API/Cocoa/WKWebViewConfigurationPrivate.h:
 34 * UIProcess/API/glib/WebKitWebContext.cpp:
 35 (webkitWebContextGetProperty):
 36 (webkitWebContextSetProperty):
 37 (webkit_web_context_class_init):
 38 (webkitWebContextCreatePageForWebView):
 39 * UIProcess/WebPageProxy.cpp:
 40 (WebKit::WebPageProxy::creationParameters):
 41 * WebProcess/WebPage/WebPage.cpp:
 42 (WebKit::m_limitsNavigationsToAppBoundDomains):
 43
1442022-04-15 Youenn Fablet <youenn@apple.com>
245
346 ServiceWorker.postMessage() doesn't work from inside iframe

Source/JavaScriptCore/runtime/DateConversion.cpp

@@String formatDateTime(const GregorianDateTime& t, DateTimeFormat format, bool as
9797 appendNumber<2>(builder, offset / 60);
9898 appendNumber<2>(builder, offset % 60);
9999
 100 String timeZoneName;
 101 String timeZoneOverride = WTF::timeZoneDisplayNameOverride();
 102 if (!timeZoneOverride.isEmpty())
 103 timeZoneName = timeZoneOverride;
 104 else {
100105#if OS(WINDOWS)
101  TIME_ZONE_INFORMATION timeZoneInformation;
102  GetTimeZoneInformation(&timeZoneInformation);
103  const WCHAR* winTimeZoneName = t.isDST() ? timeZoneInformation.DaylightName : timeZoneInformation.StandardName;
104  String timeZoneName(winTimeZoneName);
 106 TIME_ZONE_INFORMATION timeZoneInformation;
 107 GetTimeZoneInformation(&timeZoneInformation);
 108 const WCHAR* winTimeZoneName = t.isDST() ? timeZoneInformation.DaylightName : timeZoneInformation.StandardName;
 109 timeZoneName = String(winTimeZoneName);
105110#else
106  struct tm gtm = t;
107  char timeZoneName[70];
108  strftime(timeZoneName, sizeof(timeZoneName), "%Z", &gtm);
 111 struct tm gtm = t;
 112 char tzName[70];
 113 strftime(tzName, sizeof(tzName), "%Z", &gtm);
 114 timeZoneName = String::fromUTF8(tzName);
109115#endif
110  if (timeZoneName[0])
 116 }
 117 if (!timeZoneName.isEmpty())
111118 builder.append(" (", timeZoneName, ')');
112119 }
113120 }

Source/JavaScriptCore/runtime/JSDateMath.cpp

@@double DateCache::parseDate(JSGlobalObject* globalObject, VM& vm, const String&
332332// https://tc39.es/ecma402/#sec-defaulttimezone
333333String DateCache::defaultTimeZone()
334334{
 335 String tz = WTF::timeZoneOverride();
 336 if (!tz.isEmpty())
 337 return tz;
 338
335339#if HAVE(ICU_C_TIMEZONE_API)
336340 return timeZoneCache()->m_canonicalTimeZoneID;
337341#else

@@Ref<DateInstanceData> DateCache::cachedDateInstanceData(double millisecondsFromE
383387void DateCache::timeZoneCacheSlow()
384388{
385389 ASSERT(!m_timeZoneCache);
 390
 391 String override = WTF::timeZoneOverride();
386392#if HAVE(ICU_C_TIMEZONE_API)
387393 auto* cache = new OpaqueICUTimeZone;
388394
389395 String canonical;
 396 UErrorCode status = U_ZERO_ERROR;
390397 Vector<UChar, 32> timeZoneID;
391  auto status = callBufferProducingFunction(ucal_getHostTimeZone, timeZoneID);
 398 if (override.isEmpty()) {
 399 status = callBufferProducingFunction(ucal_getHostTimeZone, timeZoneID);
 400 ASSERT_UNUSED(status, U_SUCCESS(status));
 401 } else
 402 timeZoneID = override.charactersWithoutNullTermination();
392403 if (U_SUCCESS(status)) {
393404 Vector<UChar, 32> canonicalBuffer;
394405 auto status = callBufferProducingFunction(ucal_getCanonicalTimeZoneID, timeZoneID.data(), timeZoneID.size(), canonicalBuffer, nullptr);

@@void DateCache::timeZoneCacheSlow()
405416 ucal_setGregorianChange(cache->m_calendar.get(), minECMAScriptTime, &status); // Ignore "unsupported" error.
406417 m_timeZoneCache = std::unique_ptr<OpaqueICUTimeZone, OpaqueICUTimeZoneDeleter>(cache);
407418#else
 419 if (!override.isEmpty()) {
 420 auto* timezone = icu::TimeZone::createTimeZone(override.utf8().data());
 421 m_timeZoneCache = std::unique_ptr<OpaqueICUTimeZone, OpaqueICUTimeZoneDeleter>(bitwise_cast<OpaqueICUTimeZone*>(timezone));
 422 return;
 423 }
408424 // Do not use icu::TimeZone::createDefault. ICU internally has a cache for timezone and createDefault returns this cached value.
409425 m_timeZoneCache = std::unique_ptr<OpaqueICUTimeZone, OpaqueICUTimeZoneDeleter>(bitwise_cast<OpaqueICUTimeZone*>(icu::TimeZone::detectHostTimeZone()));
410426#endif

Source/WTF/wtf/DateMath.cpp

7676#include <limits>
7777#include <stdint.h>
7878#include <time.h>
 79#include <unicode/ucal.h>
7980#include <wtf/Assertions.h>
8081#include <wtf/ASCIICType.h>
 82#include <wtf/Language.h>
 83#include <wtf/NeverDestroyed.h>
 84#include <wtf/ThreadSpecific.h>
8185#include <wtf/text/StringBuilder.h>
 86#include <wtf/unicode/UTF8Conversion.h>
8287
8388#if OS(WINDOWS)
8489#include <windows.h>

@@template<unsigned length> inline bool startsWithLettersIgnoringASCIICase(const c
9297 return equalLettersIgnoringASCIICase(string, lowercaseLetters, length - 1);
9398}
9499
 100struct TimeZoneOverride {
 101 UCalendar* cal { nullptr };
 102 String id;
 103 String displayName;
 104};
 105
 106static TimeZoneOverride& innerTimeZoneOverride()
 107{
 108 static NeverDestroyed<TimeZoneOverride> timeZoneOverride;
 109 return timeZoneOverride;
 110}
 111
95112/* Constants */
96113
97114const ASCIILiteral weekdayName[7] = { "Mon"_s, "Tue"_s, "Wed"_s, "Thu"_s, "Fri"_s, "Sat"_s, "Sun"_s };

@@static double calculateDSTOffset(time_t localTime, double utcOffset)
318335// Returns combined offset in millisecond (UTC + DST).
319336LocalTimeOffset calculateLocalTimeOffset(double ms, TimeType inputTimeType)
320337{
 338 auto& tz = innerTimeZoneOverride();
 339 if (tz.cal) {
 340 UErrorCode status = U_ZERO_ERROR;
 341 ucal_setMillis(tz.cal, ms, &status);
 342 int32_t offset = ucal_get(tz.cal, UCAL_ZONE_OFFSET, &status);
 343 int32_t dstOffset = ucal_get(tz.cal, UCAL_DST_OFFSET, &status);
 344 return LocalTimeOffset(dstOffset, offset + dstOffset);
 345 }
321346#if HAVE(TM_GMTOFF)
322347 double localToUTCTimeOffset = inputTimeType == LocalTime ? calculateUTCOffset() : 0;
323348#else

@@String makeRFC2822DateString(unsigned dayOfWeek, unsigned day, unsigned month, u
10161041 return stringBuilder.toString();
10171042}
10181043
 1044std::optional<Vector<UChar, 32>> isTimeZoneValid(const String& timeZone)
 1045{
 1046 // Timezone is ascii.
 1047 Vector<UChar> buffer(timeZone.length());
 1048 UChar* bufferStart = buffer.data();
 1049 CString ctz = timeZone.utf8();
 1050 if (!Unicode::convertUTF8ToUTF16(ctz.data(), ctz.data() + ctz.length(), &bufferStart, bufferStart + timeZone.length()))
 1051 return std::nullopt;
 1052
 1053 Vector<UChar, 32> canonicalBuffer(32);
 1054 UErrorCode status = U_ZERO_ERROR;
 1055 auto canonicalLength = ucal_getCanonicalTimeZoneID(buffer.data(), buffer.size(), canonicalBuffer.data(), canonicalBuffer.size(), nullptr, &status);
 1056 if (status == U_BUFFER_OVERFLOW_ERROR) {
 1057 status = U_ZERO_ERROR;
 1058 canonicalBuffer.grow(canonicalLength);
 1059 ucal_getCanonicalTimeZoneID(buffer.data(), buffer.size(), canonicalBuffer.data(), canonicalLength, nullptr, &status);
 1060 } else
 1061 canonicalBuffer.resize(canonicalLength);
 1062 return canonicalBuffer;
 1063}
 1064
 1065bool setTimeZoneOverride(const String& timeZone)
 1066{
 1067 innerTimeZoneOverride().displayName = String();
 1068 if (innerTimeZoneOverride().cal) {
 1069 ucal_close(innerTimeZoneOverride().cal);
 1070 innerTimeZoneOverride().cal = nullptr;
 1071 }
 1072
 1073 if (timeZone.isEmpty()) {
 1074 innerTimeZoneOverride().id = String();
 1075 return true;
 1076 }
 1077
 1078 auto canonicalBuffer = isTimeZoneValid(timeZone);
 1079 if (!canonicalBuffer)
 1080 return false;
 1081
 1082 auto canonicalLength = canonicalBuffer->size();
 1083 UErrorCode status = U_ZERO_ERROR;
 1084 UCalendar* cal = ucal_open(canonicalBuffer->data(), canonicalLength, nullptr, UCAL_TRADITIONAL, &status);
 1085 if (!U_SUCCESS(status))
 1086 return false;
 1087
 1088 Vector<UChar, 32> displayNameBuffer(32);
 1089 auto displayNameLength = ucal_getTimeZoneDisplayName(cal, UCAL_STANDARD, defaultLanguage().utf8().data(), displayNameBuffer.data(), displayNameBuffer.size(), &status);
 1090 if (status == U_BUFFER_OVERFLOW_ERROR) {
 1091 status = U_ZERO_ERROR;
 1092 displayNameBuffer.grow(displayNameLength);
 1093 ucal_getTimeZoneDisplayName(cal, UCAL_STANDARD, defaultLanguage().utf8().data(), displayNameBuffer.data(), displayNameLength, &status);
 1094 }
 1095 if (!U_SUCCESS(status))
 1096 return false;
 1097
 1098 auto& timeZoneOverride = innerTimeZoneOverride();
 1099 timeZoneOverride.cal = cal;
 1100 timeZoneOverride.id = String(canonicalBuffer->data(), canonicalLength);
 1101 timeZoneOverride.displayName = String(displayNameBuffer.data(), displayNameLength);
 1102 return true;
 1103}
 1104
 1105String& timeZoneOverride()
 1106{
 1107 return innerTimeZoneOverride().id;
 1108}
 1109
 1110String& timeZoneDisplayNameOverride()
 1111{
 1112 return innerTimeZoneOverride().displayName;
 1113}
 1114
10191115} // namespace WTF

Source/WTF/wtf/DateMath.h

@@inline double timeToMS(double hour, double min, double sec, double ms)
393393 return (((hour * WTF::minutesPerHour + min) * WTF::secondsPerMinute + sec) * WTF::msPerSecond + ms);
394394}
395395
 396WTF_EXPORT_PRIVATE std::optional<Vector<UChar, 32>> isTimeZoneValid(const String&);
 397WTF_EXPORT_PRIVATE bool setTimeZoneOverride(const String&);
 398WTF_EXPORT_PRIVATE String& timeZoneOverride();
 399WTF_EXPORT_PRIVATE String& timeZoneDisplayNameOverride();
 400
396401// Returns combined offset in millisecond (UTC + DST).
397402WTF_EXPORT_PRIVATE LocalTimeOffset calculateLocalTimeOffset(double utcInMilliseconds, TimeType = UTCTime);
398403

Source/WebKit/Shared/WebProcessCreationParameters.cpp

@@void WebProcessCreationParameters::encode(IPC::Encoder& encoder) const
214214#if USE(ATSPI)
215215 encoder << accessibilityBusAddress;
216216#endif
 217
 218 encoder << timeZoneOverride;
217219}
218220
219221bool WebProcessCreationParameters::decode(IPC::Decoder& decoder, WebProcessCreationParameters& parameters)

@@bool WebProcessCreationParameters::decode(IPC::Decoder& decoder, WebProcessCreat
571573 parameters.accessibilityBusAddress = WTFMove(*accessibilityBusAddress);
572574#endif
573575
 576 std::optional<std::optional<String>> timeZoneOverride;
 577 decoder >> timeZoneOverride;
 578 if (!timeZoneOverride)
 579 return false;
 580 parameters.timeZoneOverride = WTFMove(*timeZoneOverride);
 581
574582 return true;
575583}
576584

Source/WebKit/Shared/WebProcessCreationParameters.h

@@struct WebProcessCreationParameters {
255255#if USE(ATSPI)
256256 String accessibilityBusAddress;
257257#endif
 258
 259 std::optional<String> timeZoneOverride;
258260};
259261
260262} // namespace WebKit

Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.cpp

@@Ref<ProcessPoolConfiguration> ProcessPoolConfiguration::copy()
8484#if HAVE(AUDIT_TOKEN)
8585 copy->m_presentingApplicationProcessToken = this->m_presentingApplicationProcessToken;
8686#endif
 87 copy->m_timeZoneOverride = this->m_timeZoneOverride;
8788 return copy;
8889}
8990

Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.h

@@public:
164164 const std::optional<MemoryPressureHandler::Configuration>& memoryPressureHandlerConfiguration() const { return m_memoryPressureHandlerConfiguration; }
165165#endif
166166
 167 void setTimeZoneOverride(const WTF::String& timeZoneOverride) { m_timeZoneOverride = timeZoneOverride; }
 168 const WTF::String& timeZoneOverride() const { return m_timeZoneOverride; }
 169
167170private:
168171 WTF::String m_injectedBundlePath;
169172 Vector<WTF::String> m_customClassesForParameterCoder;

@@private:
206209#if HAVE(AUDIT_TOKEN)
207210 std::optional<audit_token_t> m_presentingApplicationProcessToken;
208211#endif
 212 WTF::String m_timeZoneOverride;
209213};
210214
211215} // namespace API

Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.h

2424 */
2525
2626#import <Foundation/Foundation.h>
 27#import <WebKit/WKBase.h>
2728#import <WebKit/WKFoundation.h>
2829
2930NS_ASSUME_NONNULL_BEGIN

@@WK_CLASS_AVAILABLE(macos(10.10), ios(8.0))
7778
7879@property (nonatomic) BOOL configureJSCForTesting WK_API_AVAILABLE(macos(10.15.4), ios(13.4));
7980
 81@property (nonatomic, nullable, copy) NSString *timeZoneOverride WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
 82
8083@end
8184
8285NS_ASSUME_NONNULL_END

Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.mm

403403 _processPoolConfiguration->setShouldConfigureJSCForTesting(value);
404404}
405405
 406- (NSString *)timeZoneOverride
 407{
 408 return _processPoolConfiguration->timeZoneOverride();
 409}
 410
 411- (void)setTimeZoneOverride:(NSString *)timeZone
 412{
 413 _processPoolConfiguration->setTimeZoneOverride(timeZone);
 414}
 415
406416#pragma mark WKObject protocol implementation
407417
408418- (API::Object&)_apiObject

Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp

6565#include <libintl.h>
6666#include <memory>
6767#include <pal/HysteresisActivity.h>
 68#include <wtf/DateMath.h>
6869#include <wtf/FileSystem.h>
6970#include <wtf/HashMap.h>
7071#include <wtf/HashSet.h>

@@enum {
127128#endif
128129#endif
129130 PROP_MEMORY_PRESSURE_SETTINGS,
 131 PROP_TIME_ZONE_OVERRIDE,
130132 N_PROPERTIES,
131133};
132134

@@struct _WebKitWebContextPrivate {
245247 PAL::HysteresisActivity dnsPrefetchHystereris;
246248
247249 WebKitMemoryPressureSettings* memoryPressureSettings;
 250
 251 CString timeZoneOverride;
248252};
249253
250254static guint signals[LAST_SIGNAL] = { 0, };

@@static void webkitWebContextGetProperty(GObject* object, guint propID, GValue* v
350354 break;
351355#endif
352356#endif
 357 case PROP_TIME_ZONE_OVERRIDE:
 358 g_value_set_string(value, webkit_web_context_get_time_zone_override(context));
 359 break;
353360 default:
354361 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propID, paramSpec);
355362 }

@@static void webkitWebContextSetProperty(GObject* object, guint propID, const GVa
385392 context->priv->memoryPressureSettings = settings ? webkit_memory_pressure_settings_copy(static_cast<WebKitMemoryPressureSettings*>(settings)) : nullptr;
386393 break;
387394 }
 395 case PROP_TIME_ZONE_OVERRIDE: {
 396 const char* timeZoneOverride = g_value_get_string(value);
 397 if (timeZoneOverride)
 398 webkit_web_context_set_time_zone_override(context, timeZoneOverride);
 399 break;
 400 }
388401 default:
389402 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propID, paramSpec);
390403 }

@@static void webkitWebContextConstructed(GObject* object)
413426 // Once the settings have been passed to the ProcessPoolConfiguration, we don't need them anymore so we can free them.
414427 g_clear_pointer(&priv->memoryPressureSettings, webkit_memory_pressure_settings_free);
415428 }
 429 configuration.setTimeZoneOverride(String::fromUTF8(priv->timeZoneOverride.data()));
416430
417431 if (!priv->websiteDataManager)
418432 priv->websiteDataManager = adoptGRef(webkit_website_data_manager_new("local-storage-directory", priv->localStorageDirectory.data(), nullptr));

@@static void webkit_web_context_class_init(WebKitWebContextClass* webContextClass
572586 WEBKIT_TYPE_MEMORY_PRESSURE_SETTINGS,
573587 static_cast<GParamFlags>(WEBKIT_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
574588
 589 /**
 590 * WebKitWebContext:time-zone-override:
 591 *
 592 * The timezone override for this web context. Setting this property provides a better
 593 * alternative to configure the timezone information for all webviews managed by the WebContext.
 594 * The other, less optimal, approach is to globally set the TZ environment variable in the
 595 * process before creating the context. However this approach might not be very convenient and
 596 * can have side-effects in your application.
 597 *
 598 * The expected values for this property are defined in the IANA timezone database. See this
 599 * wikipedia page for instance, https://en.wikipedia.org/wiki/List_of_tz_database_time_zones.
 600 *
 601 * Since: 2.38
 602 */
 603 sObjProperties[PROP_TIME_ZONE_OVERRIDE] =
 604 g_param_spec_string(
 605 "time-zone-override",
 606 _("Time Zone Override"),
 607 _("The time zone to use instead of the system one"),
 608 nullptr,
 609 static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 610
575611 g_object_class_install_properties(gObjectClass, N_PROPERTIES, sObjProperties);
576612
577613 /**

@@gboolean webkit_web_context_get_use_system_appearance_for_scrollbars(WebKitWebCo
18351871}
18361872#endif
18371873
 1874/**
 1875 * webkit_web_context_set_time_zone_override:
 1876 * @context: a #WebKitWebContext
 1877 * @time_zone_override: value to set
 1878 *
 1879 * Set the #WebKitWebContext:time-zone-override property. Refer to the IANA database for valid
 1880 * specifiers, https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
 1881 *
 1882 * Since: 2.38
 1883 */
 1884void webkit_web_context_set_time_zone_override(WebKitWebContext* context, const gchar* timeZoneOverride)
 1885{
 1886 g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context));
 1887 g_return_if_fail(WTF::isTimeZoneValid(String::fromUTF8(timeZoneOverride)));
 1888
 1889 context->priv->timeZoneOverride = timeZoneOverride;
 1890}
 1891
 1892/**
 1893 * webkit_web_context_get_time_zone_override:
 1894 * @context: a #WebKitWebContext
 1895 *
 1896 * Get the #WebKitWebContext:time-zone-override property.
 1897 *
 1898 * Since: 2.38
 1899 */
 1900const gchar* webkit_web_context_get_time_zone_override(WebKitWebContext* context)
 1901{
 1902 g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), nullptr);
 1903
 1904 return context->priv->timeZoneOverride.data();
 1905}
 1906
18381907void webkitWebContextInitializeNotificationPermissions(WebKitWebContext* context)
18391908{
18401909 g_signal_emit(context, signals[INITIALIZE_NOTIFICATION_PERMISSIONS], 0);

Source/WebKit/UIProcess/API/gtk/WebKitWebContext.h

@@webkit_web_context_set_use_system_appearance_for_scrollbars (WebKitWebContext
302302WEBKIT_API gboolean
303303webkit_web_context_get_use_system_appearance_for_scrollbars (WebKitWebContext *context);
304304
 305WEBKIT_API void
 306webkit_web_context_set_time_zone_override (WebKitWebContext *context,
 307 const gchar *time_zone_override);
 308
 309WEBKIT_API const gchar*
 310webkit_web_context_get_time_zone_override (WebKitWebContext *context);
 311
305312G_END_DECLS
306313
307314#endif

Source/WebKit/UIProcess/API/wpe/WebKitWebContext.h

@@WEBKIT_API void
291291webkit_web_context_send_message_to_all_extensions (WebKitWebContext *context,
292292 WebKitUserMessage *message);
293293
 294WEBKIT_API void
 295webkit_web_context_set_time_zone_override (WebKitWebContext *context,
 296 const gchar *time_zone_override);
 297
 298WEBKIT_API const gchar*
 299webkit_web_context_get_time_zone_override (WebKitWebContext *context);
 300
294301G_END_DECLS
295302
296303#endif

Source/WebKit/UIProcess/WebProcessPool.cpp

@@void WebProcessPool::initializeNewWebProcess(WebProcessProxy& process, WebsiteDa
874874
875875 parameters.presentingApplicationPID = m_configuration->presentingApplicationPID();
876876
 877 parameters.timeZoneOverride = m_configuration->timeZoneOverride();
 878
877879 // Add any platform specific parameters
878880 platformInitializeWebProcess(process, parameters);
879881

Source/WebKit/WebProcess/WebProcess.cpp

142142#include <pal/Logging.h>
143143#include <wtf/Algorithms.h>
144144#include <wtf/CallbackAggregator.h>
 145#include <wtf/DateMath.h>
145146#include <wtf/Language.h>
146147#include <wtf/ProcessPrivilege.h>
147148#include <wtf/RunLoop.h>

@@void WebProcess::initializeWebProcess(WebProcessCreationParameters&& parameters)
498499
499500 setCacheModel(parameters.cacheModel);
500501
 502 if (parameters.timeZoneOverride)
 503 WTF::setTimeZoneOverride(*parameters.timeZoneOverride);
 504 else
 505 WTF::setTimeZoneOverride({ });
 506
501507 if (!parameters.overrideLanguages.isEmpty()) {
502508 LOG_WITH_STREAM(Language, stream << "Web Process initialization is setting overrideLanguages: " << parameters.overrideLanguages);
503509 overrideUserPreferredLanguages(parameters.overrideLanguages);

Tools/ChangeLog

 12022-04-13 Philippe Normand <pnormand@igalia.com> and Yury Semikhatsky <yurys@chromium.org>
 2
 3 [WK2] Add API to allow embedder to set a timezone override
 4 https://bugs.webkit.org/show_bug.cgi?id=213884
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 Add API tests for the timezone configuration API. The GTK and WPE MiniBrowsers also gained
 9 new runtime options allowing to exercise this new API.
 10
 11 * MiniBrowser/gtk/main.c:
 12 (activate):
 13 * MiniBrowser/wpe/main.cpp:
 14 (main):
 15 * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
 16 * TestWebKitAPI/Tests/WebKitCocoa/TimeZoneOverride.mm: Added.
 17 (TimeZoneOverrideTest::runScriptAndExecuteCallback):
 18 (TEST_F):
 19 * TestWebKitAPI/Tests/WebKitGLib/TestWebKitWebContext.cpp:
 20 (testWebContextTimeZone):
 21 (testWebViewTimeZoneOverride):
 22 (beforeAll):
 23 * TestWebKitAPI/glib/WebKitGLib/TestMain.cpp:
 24 * TestWebKitAPI/glib/WebKitGLib/TestMain.h:
 25 (Test::Test):
 26 * flatpak/flatpakutils.py:
 27 (WebkitFlatpak.run_in_sandbox):
 28
1292022-04-14 Wenson Hsieh <wenson_hsieh@apple.com>
230
331 Undo option after invoking "Markup Image" says "Undo Paste"

Tools/MiniBrowser/gtk/main.c

@@static const char *cookiesFile;
5252static const char *cookiesPolicy;
5353static const char *proxy;
5454static gboolean darkMode;
 55static char* timeZone;
5556static gboolean enableITP;
5657static gboolean enableSandbox;
5758static gboolean exitAfterLoad;

@@static const GOptionEntry commandLineOptions[] =
149150 { "enable-itp", 0, 0, G_OPTION_ARG_NONE, &enableITP, "Enable Intelligent Tracking Prevention (ITP)", NULL },
150151 { "enable-sandbox", 0, 0, G_OPTION_ARG_NONE, &enableSandbox, "Enable web process sandbox support", NULL },
151152 { "exit-after-load", 0, 0, G_OPTION_ARG_NONE, &exitAfterLoad, "Quit the browser after the load finishes", NULL },
 153 { "time-zone", 't', 0, G_OPTION_ARG_STRING, &timeZone, "Set time zone", "TIMEZONE" },
152154 { "version", 'v', 0, G_OPTION_ARG_NONE, &printVersion, "Print the WebKitGTK version", NULL },
153155 { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &uriArguments, 0, "[URL…]" },
154156 { 0, 0, 0, 0, 0, 0, 0 }

@@static void activate(GApplication *application, WebKitSettings *webkitSettings)
674676#if !GTK_CHECK_VERSION(3, 98, 0)
675677 "use-system-appearance-for-scrollbars", FALSE,
676678#endif
 679 "time-zone-override", timeZone,
677680 NULL);
678681 g_object_unref(manager);
679682

Tools/MiniBrowser/wpe/main.cpp

@@static const char* cookiesFile;
4646static const char* cookiesPolicy;
4747static const char* proxy;
4848const char* bgColor;
 49static char* timeZone;
4950static gboolean enableITP;
5051static gboolean printVersion;
5152static GHashTable* openViews;

@@static const GOptionEntry commandLineOptions[] =
6364 { "content-filter", 0, 0, G_OPTION_ARG_FILENAME, &contentFilter, "JSON with content filtering rules", "FILE" },
6465 { "bg-color", 0, 0, G_OPTION_ARG_STRING, &bgColor, "Window background color. Default: white", "COLOR" },
6566 { "enable-itp", 0, 0, G_OPTION_ARG_NONE, &enableITP, "Enable Intelligent Tracking Prevention (ITP)", nullptr },
 67 { "time-zone", 't', 0, G_OPTION_ARG_STRING, &timeZone, "Set time zone", "TIMEZONE" },
6668 { "version", 'v', 0, G_OPTION_ARG_NONE, &printVersion, "Print the WPE version", nullptr },
6769 { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &uriArguments, nullptr, "[URL]" },
6870 { nullptr, 0, 0, G_OPTION_ARG_NONE, nullptr, nullptr, nullptr }

@@int main(int argc, char *argv[])
229231 if (ignoreTLSErrors)
230232 webkit_website_data_manager_set_tls_errors_policy(manager, WEBKIT_TLS_ERRORS_POLICY_IGNORE);
231233
232  auto* webContext = webkit_web_context_new_with_website_data_manager(manager);
 234 auto* webContext = WEBKIT_WEB_CONTEXT(g_object_new(WEBKIT_TYPE_WEB_CONTEXT, "website-data-manager", manager, "time-zone-override", timeZone, nullptr));
233235 g_object_unref(manager);
234236
235237 if (cookiesPolicy) {

Tools/TestWebKitAPI/SourcesCocoa.txt

@@Tests/WebKitCocoa/TestURLSchemeHandler.mm
240240Tests/WebKitCocoa/TextManipulation.mm
241241Tests/WebKitCocoa/TextSize.mm
242242Tests/WebKitCocoa/TextWidth.mm
 243Tests/WebKitCocoa/TimeZoneOverride.mm
243244Tests/WebKitCocoa/TopContentInset.mm
244245Tests/WebKitCocoa/UIDelegate.mm
245246Tests/WebKitCocoa/UploadDirectory.mm

Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj

30243024 EBA75C48275ED7BE00D6D31C /* PushMessageCrypto.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PushMessageCrypto.cpp; sourceTree = "<group>"; };
30253025 EC79F168BE454E579E417B05 /* Markable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Markable.cpp; sourceTree = "<group>"; };
30263026 ECA680CD1E68CC0900731D20 /* StringUtilities.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = StringUtilities.mm; sourceTree = "<group>"; };
 3027 F3CEF6B82808F2D3001E23A5 /* TimeZoneOverride.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = TimeZoneOverride.mm; sourceTree = "<group>"; };
30273028 F3FC3EE213678B7300126A65 /* libgtest.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgtest.a; sourceTree = BUILT_PRODUCTS_DIR; };
30283029 F4010B7F24DA24AC00A876E2 /* NavigationSwipeTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = NavigationSwipeTests.mm; sourceTree = "<group>"; };
30293030 F4010B8124DA267F00A876E2 /* PoseAsClass.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = PoseAsClass.mm; path = ../TestRunnerShared/cocoa/PoseAsClass.mm; sourceTree = "<group>"; };

36923693 9B02E0D5235FA47D004044B2 /* TextManipulation.mm */,
36933694 5C16F8FB230C942B0074C4A8 /* TextSize.mm */,
36943695 C22FA32A228F8708009D7988 /* TextWidth.mm */,
 3696 F3CEF6B82808F2D3001E23A5 /* TimeZoneOverride.mm */,
36953697 5C73A81A2323059800DEA85A /* TLSDeprecation.mm */,
36963698 CDE195B31CFE0ADE0053D256 /* TopContentInset.mm */,
36973699 5CB40B4D1F4B98BE007DC7B9 /* UIDelegate.mm */,

Tools/TestWebKitAPI/Tests/WebKitCocoa/TimeZoneOverride.mm

 1/*
 2 * Copyright (C) 2020 Igalia S.L.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#import "config.h"
 27
 28#if PLATFORM(MAC)
 29
 30#import "PlatformUtilities.h"
 31#import "TestWKWebView.h"
 32#import <WebKit/WKWebViewConfigurationPrivate.h>
 33#import <WebKit/WKWebViewPrivate.h>
 34#import <WebKit/_WKProcessPoolConfiguration.h>
 35#import <wtf/Function.h>
 36#import <wtf/text/WTFString.h>
 37
 38class TimeZoneOverrideTest : public testing::Test {
 39public:
 40 void SetUp() override
 41 {
 42 auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
 43 auto processPoolConfig = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
 44 [processPoolConfig setTimeZoneOverride:@"Europe/Berlin"];
 45
 46 _webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 300, 300) configuration:configuration.get() processPoolConfiguration:processPoolConfig.get()]);
 47 }
 48
 49 void runScriptAndExecuteCallback(const String& script, Function<void(id)>&& callback)
 50 {
 51 bool complete = false;
 52 [_webView evaluateJavaScript:script completionHandler:[&] (id result, NSError *) {
 53 callback(result);
 54 complete = true;
 55 }];
 56 TestWebKitAPI::Util::run(&complete);
 57 }
 58
 59private:
 60 RetainPtr<TestWKWebView> _webView;
 61};
 62
 63TEST_F(TimeZoneOverrideTest, TimeZoneOverride)
 64{
 65 runScriptAndExecuteCallback("let now = new Date(); now.getTimezoneOffset()"_s, [](id result) {
 66 EXPECT_WK_STREQ([result stringValue], "-120");
 67 });
 68}
 69
 70#endif

Tools/TestWebKitAPI/Tests/WebKitGLib/TestWebKitWebContext.cpp

@@static void testMemoryPressureSettings(MemoryPressureTest* test, gconstpointer)
991991 g_assert_cmpuint(test->m_terminationReason, ==, WEBKIT_WEB_PROCESS_EXCEEDED_MEMORY_LIMIT);
992992}
993993
 994static void testWebContextTimeZoneOverride(WebViewTest* test, gconstpointer)
 995{
 996 GUniqueOutPtr<GError> error;
 997 WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished("let now = new Date(); now.getTimezoneOffset()", &error.outPtr());
 998 g_assert_nonnull(javascriptResult);
 999 g_assert_no_error(error.get());
 1000 // By default the test harness uses the Pacific/Los_Angeles timezone which is 7 hours (420 minutes) compared to GMT.
 1001 g_assert_cmpint(WebViewTest::javascriptResultToNumber(javascriptResult), ==, 420);
 1002
 1003 // Create a new context configured with time zone overide set to Berlin which is 120 minutes ahead of the GMT offset.
 1004 auto webContext = adoptGRef(WEBKIT_WEB_CONTEXT(g_object_new(WEBKIT_TYPE_WEB_CONTEXT,
 1005 "time-zone-override", "Europe/Berlin", nullptr)));
 1006 g_assert_cmpstr(webkit_web_context_get_time_zone_override(webContext.get()), ==, "Europe/Berlin");
 1007 auto webView = Test::adoptView(Test::createWebView(webContext.get()));
 1008 javascriptResult = test->runJavaScriptAndWaitUntilFinished("let now = new Date(); now.getTimezoneOffset()", &error.outPtr(), webView.get());
 1009 g_assert_nonnull(javascriptResult);
 1010 g_assert_no_error(error.get());
 1011 g_assert_cmpint(WebViewTest::javascriptResultToNumber(javascriptResult), ==, -120);
 1012}
 1013
9941014void beforeAll()
9951015{
9961016 kServer = new WebKitTestServer();

@@void beforeAll()
10081028 WebViewTest::add("WebKitSecurityManager", "file-xhr", testWebContextSecurityFileXHR);
10091029 ProxyTest::add("WebKitWebContext", "proxy", testWebContextProxySettings);
10101030 MemoryPressureTest::add("WebKitWebContext", "memory-pressure", testMemoryPressureSettings);
 1031 WebViewTest::add("WebKitWebContext", "timezone", testWebContextTimeZoneOverride);
10111032}
10121033
10131034void afterAll()

Tools/TestWebKitAPI/glib/WebKitGLib/TestMain.cpp

@@int main(int argc, char** argv)
132132 g_setenv("GSETTINGS_BACKEND", "memory", TRUE);
133133 // Get rid of runtime warnings about deprecated properties and signals, since they break the tests.
134134 g_setenv("G_ENABLE_DIAGNOSTIC", "0", TRUE);
 135 g_setenv("TZ", "America/Los_Angeles", TRUE);
135136 g_test_bug_base("https://bugs.webkit.org/");
136137
137138 registerGResource();

Tools/TestWebKitAPI/glib/WebKitGLib/WebViewTest.cpp

@@const char* WebViewTest::mainResourceData(size_t& mainResourceDataSize)
306306 return m_resourceData.get();
307307}
308308
309 static void runJavaScriptReadyCallback(GObject*, GAsyncResult* result, WebViewTest* test)
 309static void runJavaScriptReadyCallback(GObject* object, GAsyncResult* result, WebViewTest* test)
310310{
311  test->m_javascriptResult = webkit_web_view_run_javascript_finish(test->m_webView, result, test->m_javascriptError);
 311 test->m_javascriptResult = webkit_web_view_run_javascript_finish(WEBKIT_WEB_VIEW(object), result, test->m_javascriptError);
312312 g_main_loop_quit(test->m_mainLoop);
313313}
314314

@@static void runJavaScriptInWorldReadyCallback(GObject*, GAsyncResult* result, We
324324 g_main_loop_quit(test->m_mainLoop);
325325}
326326
327 WebKitJavascriptResult* WebViewTest::runJavaScriptAndWaitUntilFinished(const char* javascript, GError** error)
 327WebKitJavascriptResult* WebViewTest::runJavaScriptAndWaitUntilFinished(const char* javascript, GError** error, WebKitWebView* webView)
328328{
329329 if (m_javascriptResult)
330330 webkit_javascript_result_unref(m_javascriptResult);
331331 m_javascriptResult = 0;
332332 m_javascriptError = error;
333  webkit_web_view_run_javascript(m_webView, javascript, 0, reinterpret_cast<GAsyncReadyCallback>(runJavaScriptReadyCallback), this);
 333 if (!webView)
 334 webView = m_webView;
 335 webkit_web_view_run_javascript(webView, javascript, 0, reinterpret_cast<GAsyncReadyCallback>(runJavaScriptReadyCallback), this);
334336 g_main_loop_run(m_mainLoop);
335337
336338 return m_javascriptResult;

Tools/TestWebKitAPI/glib/WebKitGLib/WebViewTest.h

@@public:
7373 void emitPopupMenuSignal();
7474#endif
7575
76  WebKitJavascriptResult* runJavaScriptAndWaitUntilFinished(const char* javascript, GError**);
 76 WebKitJavascriptResult* runJavaScriptAndWaitUntilFinished(const char* javascript, GError**, WebKitWebView* = nullptr);
7777 WebKitJavascriptResult* runJavaScriptFromGResourceAndWaitUntilFinished(const char* resource, GError**);
7878 WebKitJavascriptResult* runJavaScriptInWorldAndWaitUntilFinished(const char* javascript, const char* world, GError**);
7979 WebKitJavascriptResult* runJavaScriptWithoutForcedUserGesturesAndWaitUntilFinished(const char* javascript, GError**);

Tools/flatpak/flatpakutils.py

@@class WebkitFlatpak:
857857 ])
858858
859859 sandbox_environment.update({
860  "TZ": "PST8PDT",
 860 "TZ": "America/Los_Angeles",
861861 })
862862
863863 env_var_prefixes_to_keep = [