| // Copyright 2024 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| import {CustomElement} from 'chrome://resources/js/custom_element.js'; |
| |
| import {getTemplate} from './mojo_timestamp.html.js'; |
| |
| class MojoTimestampElement extends CustomElement { |
| static observedAttributes = ['ts']; |
| |
| static override get template() { |
| return getTemplate(); |
| } |
| |
| mojoTsToJsDate(mojoTs: bigint) { |
| // The Javascript `Date()` is based off of the number of milliseconds since |
| // the UNIX epoch (1970-01-01 00::00:00 UTC), while `internalValue`` |
| // of the `base::Time` (represented in mojom.Time) represents the |
| // number of microseconds since the Windows FILETIME epoch |
| // (1601-01-01 00:00:00 UTC). This computes the final Javascript time by |
| // computing the epoch delta and the conversion from microseconds to |
| // milliseconds. |
| const windowsEpoch = Date.UTC(1601, 0, 1, 0, 0, 0, 0); |
| const unixEpoch = Date.UTC(1970, 0, 1, 0, 0, 0, 0); |
| // `epochDeltaInMs` is equal to `base::Time::kTimeTToMicrosecondsOffset`. |
| const epochDeltaInMs = unixEpoch - windowsEpoch; |
| const timeInMs = Number(mojoTs) / 1000; |
| return new Date(timeInMs - epochDeltaInMs); |
| } |
| |
| attributeChangedCallback(name: string, _oldValue: string, newValue: string) { |
| if (name === 'ts') { |
| const elem = this.shadowRoot!.querySelector<HTMLElement>('#time')!; |
| const ts: bigint = BigInt(newValue); |
| if (ts === BigInt(0)) { |
| elem.textContent = 'epoch'; |
| elem.classList.add('none'); |
| } else { |
| const date = this.mojoTsToJsDate(ts); |
| elem.textContent = date.toUTCString(); |
| elem.classList.remove('none'); |
| } |
| } |
| } |
| } |
| |
| declare global { |
| interface HTMLElementTagNameMap { |
| 'mojo-timestamp': MojoTimestampElement; |
| } |
| } |
| |
| customElements.define('mojo-timestamp', MojoTimestampElement); |