Commit 3f6bfaa4 authored by Frank Tang's avatar Frank Tang Committed by Commit Bot

Prototype of add timezonechange event

Add a "timezonechange" event and add ontimezonechange event handler
to WindowEventHandlers and WorkerGlobalScope interface.

Design Doc https://docs.google.com/document/d/1gu-HAVIjVxfPQEE0uQg9Y4tJwYl33Y54DKTA9hfDyic/edit#
I2I: https://groups.google.com/a/chromium.org/forum/#!searchin/blink-dev/timezonechange%7Csort:date/blink-dev/4BUSE2aTQEc/bahW7wniCAAJ
Behind the blink feature flag TimeZoneChangeEvent

Bug: 908550
Change-Id: I582d43ac2c1335cb5443979b3f1019a715dc35fa
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1994529
Commit-Queue: Frank Tang <ftang@chromium.org>
Reviewed-by: default avatarMason Freed <masonfreed@chromium.org>
Reviewed-by: default avatarHiroki Nakagawa <nhiroki@chromium.org>
Reviewed-by: default avatarKent Tamura <tkent@chromium.org>
Cr-Commit-Position: refs/heads/master@{#737841}
parent 7d566e60
...@@ -281,6 +281,7 @@ ...@@ -281,6 +281,7 @@
"textformatupdate", "textformatupdate",
"timeout", "timeout",
"timeupdate", "timeupdate",
"timezonechange",
"toggle", "toggle",
"tonechange", "tonechange",
"touchcancel", "touchcancel",
......
...@@ -55,6 +55,7 @@ class WindowEventHandlers { ...@@ -55,6 +55,7 @@ class WindowEventHandlers {
DEFINE_STATIC_WINDOW_ATTRIBUTE_EVENT_LISTENER(rejectionhandled, DEFINE_STATIC_WINDOW_ATTRIBUTE_EVENT_LISTENER(rejectionhandled,
kRejectionhandled) kRejectionhandled)
DEFINE_STATIC_WINDOW_ATTRIBUTE_EVENT_LISTENER(storage, kStorage) DEFINE_STATIC_WINDOW_ATTRIBUTE_EVENT_LISTENER(storage, kStorage)
DEFINE_STATIC_WINDOW_ATTRIBUTE_EVENT_LISTENER(timezonechange, kTimezonechange)
DEFINE_STATIC_WINDOW_ATTRIBUTE_EVENT_LISTENER(unhandledrejection, DEFINE_STATIC_WINDOW_ATTRIBUTE_EVENT_LISTENER(unhandledrejection,
kUnhandledrejection) kUnhandledrejection)
DEFINE_STATIC_WINDOW_ATTRIBUTE_EVENT_LISTENER(unload, kUnload) DEFINE_STATIC_WINDOW_ATTRIBUTE_EVENT_LISTENER(unload, kUnload)
......
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
[RuntimeEnabled=Portals] attribute EventHandler onportalactivate; [RuntimeEnabled=Portals] attribute EventHandler onportalactivate;
attribute EventHandler onrejectionhandled; attribute EventHandler onrejectionhandled;
attribute EventHandler onstorage; attribute EventHandler onstorage;
[RuntimeEnabled=TimeZoneChangeEvent] attribute EventHandler ontimezonechange;
attribute EventHandler onunhandledrejection; attribute EventHandler onunhandledrejection;
attribute EventHandler onunload; attribute EventHandler onunload;
}; };
...@@ -248,6 +248,7 @@ ...@@ -248,6 +248,7 @@
"onsuspend", "onsuspend",
"onsubmit", "onsubmit",
"ontimeupdate", "ontimeupdate",
"ontimezonechange",
"ontoggle", "ontoggle",
"ontouchstart", "ontouchstart",
"ontouchmove", "ontouchmove",
......
...@@ -220,6 +220,11 @@ void HTMLBodyElement::ParseAttribute( ...@@ -220,6 +220,11 @@ void HTMLBodyElement::ParseAttribute(
GetDocument().SetWindowAttributeEventListener( GetDocument().SetWindowAttributeEventListener(
event_type_names::kPortalactivate, event_type_names::kPortalactivate,
CreateAttributeEventListener(GetDocument().GetFrame(), name, value)); CreateAttributeEventListener(GetDocument().GetFrame(), name, value));
} else if (RuntimeEnabledFeatures::TimeZoneChangeEventEnabled() &&
name == html_names::kOntimezonechangeAttr) {
GetDocument().SetWindowAttributeEventListener(
event_type_names::kTimezonechange,
CreateAttributeEventListener(GetDocument().GetFrame(), name, value));
} else { } else {
HTMLElement::ParseAttribute(params); HTMLElement::ParseAttribute(params);
} }
......
...@@ -207,6 +207,11 @@ void HTMLFrameSetElement::ParseAttribute( ...@@ -207,6 +207,11 @@ void HTMLFrameSetElement::ParseAttribute(
GetDocument().SetWindowAttributeEventListener( GetDocument().SetWindowAttributeEventListener(
event_type_names::kPortalactivate, event_type_names::kPortalactivate,
CreateAttributeEventListener(GetDocument().GetFrame(), name, value)); CreateAttributeEventListener(GetDocument().GetFrame(), name, value));
} else if (RuntimeEnabledFeatures::TimeZoneChangeEventEnabled() &&
name == html_names::kOntimezonechangeAttr) {
GetDocument().SetWindowAttributeEventListener(
event_type_names::kTimezonechange,
CreateAttributeEventListener(GetDocument().GetFrame(), name, value));
} else { } else {
HTMLElement::ParseAttribute(params); HTMLElement::ParseAttribute(params);
} }
......
...@@ -157,6 +157,7 @@ ...@@ -157,6 +157,7 @@
#include "third_party/blink/renderer/core/testing/static_selection.h" #include "third_party/blink/renderer/core/testing/static_selection.h"
#include "third_party/blink/renderer/core/testing/type_conversions.h" #include "third_party/blink/renderer/core/testing/type_conversions.h"
#include "third_party/blink/renderer/core/testing/union_types_test.h" #include "third_party/blink/renderer/core/testing/union_types_test.h"
#include "third_party/blink/renderer/core/timezone/timezone_controller.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h" #include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
#include "third_party/blink/renderer/core/workers/worker_thread.h" #include "third_party/blink/renderer/core/workers/worker_thread.h"
#include "third_party/blink/renderer/platform/bindings/exception_messages.h" #include "third_party/blink/renderer/platform/bindings/exception_messages.h"
...@@ -1739,6 +1740,10 @@ void Internals::setUserPreferredLanguages(const Vector<String>& languages) { ...@@ -1739,6 +1740,10 @@ void Internals::setUserPreferredLanguages(const Vector<String>& languages) {
OverrideUserPreferredLanguagesForTesting(atomic_languages); OverrideUserPreferredLanguagesForTesting(atomic_languages);
} }
void Internals::setSystemTimeZone(const String& timezone) {
blink::TimeZoneController::ChangeTimeZoneForTesting(timezone);
}
unsigned Internals::mediaKeysCount() { unsigned Internals::mediaKeysCount() {
return InstanceCounters::CounterValue(InstanceCounters::kMediaKeysCounter); return InstanceCounters::CounterValue(InstanceCounters::kMediaKeysCounter);
} }
......
...@@ -279,6 +279,7 @@ class Internals final : public ScriptWrappable { ...@@ -279,6 +279,7 @@ class Internals final : public ScriptWrappable {
Vector<AtomicString> userPreferredLanguages() const; Vector<AtomicString> userPreferredLanguages() const;
void setUserPreferredLanguages(const Vector<String>&); void setUserPreferredLanguages(const Vector<String>&);
void setSystemTimeZone(const String&);
unsigned mediaKeysCount(); unsigned mediaKeysCount();
unsigned mediaKeySessionCount(); unsigned mediaKeySessionCount();
......
...@@ -150,6 +150,7 @@ ...@@ -150,6 +150,7 @@
sequence<DOMString> userPreferredLanguages(); sequence<DOMString> userPreferredLanguages();
void setUserPreferredLanguages(sequence<DOMString> languages); void setUserPreferredLanguages(sequence<DOMString> languages);
void setSystemTimeZone(DOMString timezone);
unsigned long mediaKeysCount(); unsigned long mediaKeysCount();
unsigned long mediaKeySessionCount(); unsigned long mediaKeySessionCount();
......
...@@ -10,11 +10,17 @@ ...@@ -10,11 +10,17 @@
#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h" #include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
#include "third_party/blink/public/platform/platform.h" #include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/task_type.h" #include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/blink/renderer/core/frame/frame.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/workers/worker_backing_thread.h" #include "third_party/blink/renderer/core/workers/worker_backing_thread.h"
#include "third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h" #include "third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h"
#include "third_party/blink/renderer/core/workers/worker_thread.h" #include "third_party/blink/renderer/core/workers/worker_thread.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h" #include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
#include "third_party/blink/renderer/platform/mojo/mojo_helper.h" #include "third_party/blink/renderer/platform/mojo/mojo_helper.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/icu/source/common/unicode/char16ptr.h" #include "third_party/icu/source/common/unicode/char16ptr.h"
#include "third_party/icu/source/i18n/unicode/timezone.h" #include "third_party/icu/source/i18n/unicode/timezone.h"
#include "v8/include/v8.h" #include "v8/include/v8.h"
...@@ -32,6 +38,11 @@ void NotifyTimezoneChangeToV8(v8::Isolate* isolate) { ...@@ -32,6 +38,11 @@ void NotifyTimezoneChangeToV8(v8::Isolate* isolate) {
void NotifyTimezoneChangeOnWorkerThread(WorkerThread* worker_thread) { void NotifyTimezoneChangeOnWorkerThread(WorkerThread* worker_thread) {
DCHECK(worker_thread->IsCurrentThread()); DCHECK(worker_thread->IsCurrentThread());
NotifyTimezoneChangeToV8(worker_thread->GlobalScope()->GetIsolate()); NotifyTimezoneChangeToV8(worker_thread->GlobalScope()->GetIsolate());
if (RuntimeEnabledFeatures::TimeZoneChangeEventEnabled() &&
worker_thread->GlobalScope()->IsWorkerGlobalScope()) {
worker_thread->GlobalScope()->DispatchEvent(
*Event::Create(event_type_names::kTimezonechange));
}
} }
String GetTimezoneId(const icu::TimeZone& timezone) { String GetTimezoneId(const icu::TimeZone& timezone) {
...@@ -47,6 +58,21 @@ String GetCurrentTimezoneId() { ...@@ -47,6 +58,21 @@ String GetCurrentTimezoneId() {
return GetTimezoneId(*timezone.get()); return GetTimezoneId(*timezone.get());
} }
void DispatchTimeZoneChangeEventToFrames() {
if (!RuntimeEnabledFeatures::TimeZoneChangeEventEnabled())
return;
for (const Page* page : Page::OrdinaryPages()) {
for (Frame* frame = page->MainFrame(); frame;
frame = frame->Tree().TraverseNext()) {
if (auto* main_local_frame = DynamicTo<LocalFrame>(frame)) {
main_local_frame->DomWindow()->DispatchEvent(
*Event::Create(event_type_names::kTimezonechange));
}
}
}
}
bool SetIcuTimeZoneAndNotifyV8(const String& timezone_id) { bool SetIcuTimeZoneAndNotifyV8(const String& timezone_id) {
DCHECK(!timezone_id.IsEmpty()); DCHECK(!timezone_id.IsEmpty());
std::unique_ptr<icu::TimeZone> timezone(icu::TimeZone::createTimeZone( std::unique_ptr<icu::TimeZone> timezone(icu::TimeZone::createTimeZone(
...@@ -61,6 +87,7 @@ bool SetIcuTimeZoneAndNotifyV8(const String& timezone_id) { ...@@ -61,6 +87,7 @@ bool SetIcuTimeZoneAndNotifyV8(const String& timezone_id) {
NotifyTimezoneChangeToV8(V8PerIsolateData::MainThreadIsolate()); NotifyTimezoneChangeToV8(V8PerIsolateData::MainThreadIsolate());
WorkerThread::CallOnAllWorkerThreads(&NotifyTimezoneChangeOnWorkerThread, WorkerThread::CallOnAllWorkerThreads(&NotifyTimezoneChangeOnWorkerThread,
TaskType::kInternalDefault); TaskType::kInternalDefault);
DispatchTimeZoneChangeEventToFrames();
return true; return true;
} }
...@@ -106,7 +133,6 @@ TimeZoneController::SetTimeZoneOverride(const String& timezone_id) { ...@@ -106,7 +133,6 @@ TimeZoneController::SetTimeZoneOverride(const String& timezone_id) {
VLOG(1) << "Invalid override timezone id: " << timezone_id; VLOG(1) << "Invalid override timezone id: " << timezone_id;
return nullptr; return nullptr;
} }
instance().has_timezone_id_override_ = true; instance().has_timezone_id_override_ = true;
return std::unique_ptr<TimeZoneOverride>(new TimeZoneOverride()); return std::unique_ptr<TimeZoneOverride>(new TimeZoneOverride());
...@@ -138,4 +164,9 @@ void TimeZoneController::OnTimeZoneChange(const String& timezone_id) { ...@@ -138,4 +164,9 @@ void TimeZoneController::OnTimeZoneChange(const String& timezone_id) {
SetIcuTimeZoneAndNotifyV8(timezone_id); SetIcuTimeZoneAndNotifyV8(timezone_id);
} }
// static
void TimeZoneController::ChangeTimeZoneForTesting(const String& timezone) {
instance().OnTimeZoneChange(timezone);
}
} // namespace blink } // namespace blink
...@@ -43,6 +43,8 @@ class CORE_EXPORT TimeZoneController final ...@@ -43,6 +43,8 @@ class CORE_EXPORT TimeZoneController final
static bool HasTimeZoneOverride(); static bool HasTimeZoneOverride();
static void ChangeTimeZoneForTesting(const String&);
private: private:
TimeZoneController(); TimeZoneController();
static TimeZoneController& instance(); static TimeZoneController& instance();
......
...@@ -100,6 +100,7 @@ class CORE_EXPORT WorkerGlobalScope ...@@ -100,6 +100,7 @@ class CORE_EXPORT WorkerGlobalScope
DEFINE_ATTRIBUTE_EVENT_LISTENER(error, kError) DEFINE_ATTRIBUTE_EVENT_LISTENER(error, kError)
DEFINE_ATTRIBUTE_EVENT_LISTENER(languagechange, kLanguagechange) DEFINE_ATTRIBUTE_EVENT_LISTENER(languagechange, kLanguagechange)
DEFINE_ATTRIBUTE_EVENT_LISTENER(rejectionhandled, kRejectionhandled) DEFINE_ATTRIBUTE_EVENT_LISTENER(rejectionhandled, kRejectionhandled)
DEFINE_ATTRIBUTE_EVENT_LISTENER(timezonechange, kTimezonechange)
DEFINE_ATTRIBUTE_EVENT_LISTENER(unhandledrejection, kUnhandledrejection) DEFINE_ATTRIBUTE_EVENT_LISTENER(unhandledrejection, kUnhandledrejection)
// WorkerUtils // WorkerUtils
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
// TODO(foolip): onerror should be an OnErrorEventHandler. // TODO(foolip): onerror should be an OnErrorEventHandler.
attribute EventHandler onerror; attribute EventHandler onerror;
attribute EventHandler onlanguagechange; attribute EventHandler onlanguagechange;
[RuntimeEnabled=TimeZoneChangeEvent] attribute EventHandler ontimezonechange;
// attribute EventHandler onoffline; // attribute EventHandler onoffline;
// attribute EventHandler ononline; // attribute EventHandler ononline;
......
...@@ -1656,6 +1656,10 @@ ...@@ -1656,6 +1656,10 @@
name: "TimerThrottlingForHiddenFrames", name: "TimerThrottlingForHiddenFrames",
status: "stable", status: "stable",
}, },
{
name: "TimeZoneChangeEvent",
status: "experimental",
},
// Many websites disable mouse support when touch APIs are available. We'd // Many websites disable mouse support when touch APIs are available. We'd
// like to enable this always but can't until more websites fix this bug. // like to enable this always but can't until more websites fix this bug.
// Chromium sets this conditionally (eg. based on the presence of a // Chromium sets this conditionally (eg. based on the presence of a
......
...@@ -171,6 +171,7 @@ PASS oldChildWindow.onstorage is newChildWindow.onstorage ...@@ -171,6 +171,7 @@ PASS oldChildWindow.onstorage is newChildWindow.onstorage
PASS oldChildWindow.onsubmit is newChildWindow.onsubmit PASS oldChildWindow.onsubmit is newChildWindow.onsubmit
PASS oldChildWindow.onsuspend is newChildWindow.onsuspend PASS oldChildWindow.onsuspend is newChildWindow.onsuspend
PASS oldChildWindow.ontimeupdate is newChildWindow.ontimeupdate PASS oldChildWindow.ontimeupdate is newChildWindow.ontimeupdate
PASS oldChildWindow.ontimezonechange is newChildWindow.ontimezonechange
PASS oldChildWindow.ontoggle is newChildWindow.ontoggle PASS oldChildWindow.ontoggle is newChildWindow.ontoggle
PASS oldChildWindow.ontouchcancel is newChildWindow.ontouchcancel PASS oldChildWindow.ontouchcancel is newChildWindow.ontouchcancel
PASS oldChildWindow.ontouchend is newChildWindow.ontouchend PASS oldChildWindow.ontouchend is newChildWindow.ontouchend
......
...@@ -132,6 +132,7 @@ PASS childWindow.onstorage is null ...@@ -132,6 +132,7 @@ PASS childWindow.onstorage is null
PASS childWindow.onsubmit is null PASS childWindow.onsubmit is null
PASS childWindow.onsuspend is null PASS childWindow.onsuspend is null
PASS childWindow.ontimeupdate is null PASS childWindow.ontimeupdate is null
PASS childWindow.ontimezonechange is null
PASS childWindow.ontoggle is null PASS childWindow.ontoggle is null
PASS childWindow.ontouchcancel is null PASS childWindow.ontouchcancel is null
PASS childWindow.ontouchend is null PASS childWindow.ontouchend is null
......
...@@ -132,6 +132,7 @@ PASS childWindow.onstorage is null ...@@ -132,6 +132,7 @@ PASS childWindow.onstorage is null
PASS childWindow.onsubmit is null PASS childWindow.onsubmit is null
PASS childWindow.onsuspend is null PASS childWindow.onsuspend is null
PASS childWindow.ontimeupdate is null PASS childWindow.ontimeupdate is null
PASS childWindow.ontimezonechange is null
PASS childWindow.ontoggle is null PASS childWindow.ontoggle is null
PASS childWindow.ontouchcancel is null PASS childWindow.ontouchcancel is null
PASS childWindow.ontouchend is null PASS childWindow.ontouchend is null
......
...@@ -3714,6 +3714,7 @@ interface WorkerGlobalScope : EventTarget ...@@ -3714,6 +3714,7 @@ interface WorkerGlobalScope : EventTarget
getter onerror getter onerror
getter onlanguagechange getter onlanguagechange
getter onrejectionhandled getter onrejectionhandled
getter ontimezonechange
getter onunhandledrejection getter onunhandledrejection
getter origin getter origin
getter performance getter performance
...@@ -3732,6 +3733,7 @@ interface WorkerGlobalScope : EventTarget ...@@ -3732,6 +3733,7 @@ interface WorkerGlobalScope : EventTarget
setter onerror setter onerror
setter onlanguagechange setter onlanguagechange
setter onrejectionhandled setter onrejectionhandled
setter ontimezonechange
setter onunhandledrejection setter onunhandledrejection
setter origin setter origin
setter performance setter performance
......
self.addEventListener('message', function(e) {
const message = e.data;
if ('port' in message) {
const port = message.port;
self.addEventListener('timezonechange', function(evt) {
port.postMessage('SUCCESS');
});
port.postMessage('READY');
}
});
<!DOCTYPE html>
<title>Service Worker: timezonechange event</title>
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<script src="../serviceworker/resources/test-helpers.js"></script>
<script>
promise_test(t => {
const script = 'resources/service-worker-timezonechange.js';
const scope = 'resources/blank.html';
let worker;
let port;
return service_worker_unregister_and_register(t, script, scope)
.then(registration => {
t.add_cleanup(() => registration.unregister());
worker = registration.installing;
const messageChannel = new MessageChannel();
port = messageChannel.port1;
return new Promise(resolve => {
port.onmessage = resolve;
worker.postMessage({port: messageChannel.port2},
[messageChannel.port2]);
});
})
.then(e => {
assert_equals(e.data, 'READY');
// Change the timezone once the service worker is ready.
internals.setSystemTimeZone('Asia/Taipei');
return new Promise(resolve => { port.onmessage = resolve; });
})
.then(e => {
assert_equals(e.data, 'SUCCESS');
});
}, 'timezonechange event work in ServiceWorker');
</script>
onconnect = connectEvent => {
const port = connectEvent.ports[0];
ontimezonechange = () => port.postMessage("SUCCESS");
port.postMessage("READY"); // (the html will change the timezone)
}
ontimezonechange = evt => {
postMessage("SUCCESS");
}
postMessage("READY");
<!DOCTYPE html>
<title>Test shared worker handle ontimezonechange event.</title>
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>
<script>
promise_test(async t => {
const worker = new SharedWorker('resources/shared-worker-timezonechange.js', 'name');
const msg1 = await new Promise(r => worker.port.onmessage = r);
assert_equals(msg1.data, "READY");
// Once we know the worker is ready, we change the timezone.
internals.setSystemTimeZone("Asia/Taipei");
const msg2 = await new Promise(r => worker.port.onmessage = r);
assert_equals(msg2.data, "SUCCESS");
}, "Test a shared worker handles ontimezonechange event.");
</script>
<!DOCTYPE html>
<html>
<body>
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>
<script>
var timezone = ["Asia/Taipei", "America/Chicago"];
var i = 0;;
test(function() {
assert_true('ontimezonechange' in window);
}, "Test that timezonechange event handler API is present in window");
test(function() {
var received = false;
window.ontimezonechange = function() {
received = true;
}
internals.setSystemTimeZone(timezone[i++ % timezone.length]);
assert_true(received);
}, "Test that the timezonechange event fires on window.ontimezonechange");
test(function() {
var received = false;
window.addEventListener('timezonechange', function() {
received = true;
});
internals.setSystemTimeZone(timezone[i++ % timezone.length]);
assert_true(received);
}, "Test that the timezonechange event fires on window.addEventListener('timezonechange')");
test(function() {
window.received = false; // We need a global variable here.
document.body.setAttribute('ontimezonechange', 'window.received = true;');
internals.setSystemTimeZone(timezone[i++ % timezone.length]);
assert_true(window.received);
}, "Test that the timezonechange event fires on body ontimezonechange attribute");
test(function() {
window.received = 0; // We need a global variable here.
var fromWindowHandler = false;
document.body.setAttribute('ontimezonechange', 'window.received++;');
window.ontimezonechange = function() {
received++;
fromWindowHandler = true;
}
internals.setSystemTimeZone(timezone[i++ % timezone.length]);
assert_equals(window.received, 1);
assert_true(fromWindowHandler);
window.received = 0;
fromWindowHandler = false;
window.ontimezonechange = function() {
received++;
fromWindowHandler = true;
}
document.body.setAttribute('ontimezonechange', 'window.received++;');
internals.setSystemTimeZone(timezone[i++ % timezone.length]);
assert_equals(window.received, 1);
assert_false(fromWindowHandler);
}, "Test that the timezonechange event fires on body ontimezonechange attribute XOR window.ontimezonechange");
test(function() {
window.addEventListener('timezonechange', function(e) {
assert_false(e.cancelable);
assert_false(e.bubbles);
});
internals.setSystemTimeZone(timezone[i++ % timezone.length]);
}, "Test properties of the fired event.");
</script>
</body>
</html>
<!DOCTYPE html>
<title>Test worker handle ontimezonechange event.</title>
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>
<script>
promise_test(async t => {
const worker = new Worker('resources/worker-timezonechange.js');
const msg1 = await new Promise(r => worker.onmessage = r);
assert_equals(msg1.data, "READY");
// Once we know the worker is ready, we change the timezone.
internals.setSystemTimeZone("Asia/Taipei");
const msg2 = await new Promise(r => worker.onmessage = r);
assert_equals(msg2.data, "SUCCESS");
}, "Test a dedicated worker handles ontimezonechange event.");
</script>
...@@ -462,6 +462,7 @@ html element body ...@@ -462,6 +462,7 @@ html element body
property onportalactivate property onportalactivate
property onrejectionhandled property onrejectionhandled
property onstorage property onstorage
property ontimezonechange
property onunhandledrejection property onunhandledrejection
property onunload property onunload
property text property text
...@@ -614,6 +615,7 @@ html element frameset ...@@ -614,6 +615,7 @@ html element frameset
property onportalactivate property onportalactivate
property onrejectionhandled property onrejectionhandled
property onstorage property onstorage
property ontimezonechange
property onunhandledrejection property onunhandledrejection
property onunload property onunload
property rows property rows
......
...@@ -3766,6 +3766,7 @@ Starting worker: resources/global-interface-listing-worker.js ...@@ -3766,6 +3766,7 @@ Starting worker: resources/global-interface-listing-worker.js
[Worker] getter onerror [Worker] getter onerror
[Worker] getter onlanguagechange [Worker] getter onlanguagechange
[Worker] getter onrejectionhandled [Worker] getter onrejectionhandled
[Worker] getter ontimezonechange
[Worker] getter onunhandledrejection [Worker] getter onunhandledrejection
[Worker] getter origin [Worker] getter origin
[Worker] getter performance [Worker] getter performance
...@@ -3784,6 +3785,7 @@ Starting worker: resources/global-interface-listing-worker.js ...@@ -3784,6 +3785,7 @@ Starting worker: resources/global-interface-listing-worker.js
[Worker] setter onerror [Worker] setter onerror
[Worker] setter onlanguagechange [Worker] setter onlanguagechange
[Worker] setter onrejectionhandled [Worker] setter onrejectionhandled
[Worker] setter ontimezonechange
[Worker] setter onunhandledrejection [Worker] setter onunhandledrejection
[Worker] setter origin [Worker] setter origin
[Worker] setter performance [Worker] setter performance
......
...@@ -2827,6 +2827,7 @@ interface HTMLBodyElement : HTMLElement ...@@ -2827,6 +2827,7 @@ interface HTMLBodyElement : HTMLElement
getter onresize getter onresize
getter onscroll getter onscroll
getter onstorage getter onstorage
getter ontimezonechange
getter onunhandledrejection getter onunhandledrejection
getter onunload getter onunload
getter text getter text
...@@ -2857,6 +2858,7 @@ interface HTMLBodyElement : HTMLElement ...@@ -2857,6 +2858,7 @@ interface HTMLBodyElement : HTMLElement
setter onresize setter onresize
setter onscroll setter onscroll
setter onstorage setter onstorage
setter ontimezonechange
setter onunhandledrejection setter onunhandledrejection
setter onunload setter onunload
setter text setter text
...@@ -3315,6 +3317,7 @@ interface HTMLFrameSetElement : HTMLElement ...@@ -3315,6 +3317,7 @@ interface HTMLFrameSetElement : HTMLElement
getter onresize getter onresize
getter onscroll getter onscroll
getter onstorage getter onstorage
getter ontimezonechange
getter onunhandledrejection getter onunhandledrejection
getter onunload getter onunload
getter rows getter rows
...@@ -3341,6 +3344,7 @@ interface HTMLFrameSetElement : HTMLElement ...@@ -3341,6 +3344,7 @@ interface HTMLFrameSetElement : HTMLElement
setter onresize setter onresize
setter onscroll setter onscroll
setter onstorage setter onstorage
setter ontimezonechange
setter onunhandledrejection setter onunhandledrejection
setter onunload setter onunload
setter rows setter rows
...@@ -11749,6 +11753,7 @@ interface webkitURL ...@@ -11749,6 +11753,7 @@ interface webkitURL
getter onsubmit getter onsubmit
getter onsuspend getter onsuspend
getter ontimeupdate getter ontimeupdate
getter ontimezonechange
getter ontoggle getter ontoggle
getter ontouchcancel getter ontouchcancel
getter ontouchend getter ontouchend
...@@ -11949,6 +11954,7 @@ interface webkitURL ...@@ -11949,6 +11954,7 @@ interface webkitURL
setter onsubmit setter onsubmit
setter onsuspend setter onsuspend
setter ontimeupdate setter ontimeupdate
setter ontimezonechange
setter ontoggle setter ontoggle
setter ontouchcancel setter ontouchcancel
setter ontouchend setter ontouchend
......
...@@ -3608,6 +3608,7 @@ Starting worker: resources/global-interface-listing-worker.js ...@@ -3608,6 +3608,7 @@ Starting worker: resources/global-interface-listing-worker.js
[Worker] getter onerror [Worker] getter onerror
[Worker] getter onlanguagechange [Worker] getter onlanguagechange
[Worker] getter onrejectionhandled [Worker] getter onrejectionhandled
[Worker] getter ontimezonechange
[Worker] getter onunhandledrejection [Worker] getter onunhandledrejection
[Worker] getter origin [Worker] getter origin
[Worker] getter performance [Worker] getter performance
...@@ -3626,6 +3627,7 @@ Starting worker: resources/global-interface-listing-worker.js ...@@ -3626,6 +3627,7 @@ Starting worker: resources/global-interface-listing-worker.js
[Worker] setter onerror [Worker] setter onerror
[Worker] setter onlanguagechange [Worker] setter onlanguagechange
[Worker] setter onrejectionhandled [Worker] setter onrejectionhandled
[Worker] setter ontimezonechange
[Worker] setter onunhandledrejection [Worker] setter onunhandledrejection
[Worker] setter origin [Worker] setter origin
[Worker] setter performance [Worker] setter performance
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment