From 43a97878ce14b72f0981164f87f2e35e14151312 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 11:22:09 +0200 Subject: Adding upstream version 110.0.1. Signed-off-by: Daniel Baumann --- toolkit/content/widgets/videocontrols.js | 3374 ++++++++++++++++++++++++++++++ 1 file changed, 3374 insertions(+) create mode 100644 toolkit/content/widgets/videocontrols.js (limited to 'toolkit/content/widgets/videocontrols.js') diff --git a/toolkit/content/widgets/videocontrols.js b/toolkit/content/widgets/videocontrols.js new file mode 100644 index 0000000000..ef66a0a102 --- /dev/null +++ b/toolkit/content/widgets/videocontrols.js @@ -0,0 +1,3374 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +// This is a UA widget. It runs in per-origin UA widget scope, +// to be loaded by UAWidgetsChild.jsm. + +/* + * This is the class of entry. It will construct the actual implementation + * according to the value of the "controls" property. + */ +this.VideoControlsWidget = class { + constructor(shadowRoot, prefs) { + this.shadowRoot = shadowRoot; + this.prefs = prefs; + this.element = shadowRoot.host; + this.document = this.element.ownerDocument; + this.window = this.document.defaultView; + + this.isMobile = this.window.navigator.appVersion.includes("Android"); + } + + /* + * Callback called by UAWidgets right after constructor. + */ + onsetup() { + this.switchImpl(); + } + + /* + * Callback called by UAWidgets when the "controls" property changes. + */ + onchange() { + this.switchImpl(); + } + + /* + * Actually switch the implementation. + * - With "controls" set, the VideoControlsImplWidget controls should load. + * - Without it, on mobile, the NoControlsMobileImplWidget should load, so + * the user could see the click-to-play button when the video/audio is blocked. + * - Without it, on desktop, the NoControlsPictureInPictureImpleWidget should load + * if the video is being viewed in Picture-in-Picture. + */ + switchImpl() { + let newImpl; + let pageURI = this.document.documentURI; + if (this.element.controls) { + newImpl = VideoControlsImplWidget; + } else if (this.isMobile) { + newImpl = NoControlsMobileImplWidget; + } else if (VideoControlsWidget.isPictureInPictureVideo(this.element)) { + newImpl = NoControlsPictureInPictureImplWidget; + } else if ( + pageURI.startsWith("http://") || + pageURI.startsWith("https://") + ) { + newImpl = NoControlsDesktopImplWidget; + } + + // Skip if we are asked to load the same implementation, and + // the underlying element state hasn't changed in ways that we + // care about. This can happen if the property is set again + // without a value change. + if ( + this.impl && + this.impl.constructor == newImpl && + this.impl.elementStateMatches(this.element) + ) { + return; + } + if (this.impl) { + this.impl.teardown(); + this.shadowRoot.firstChild.remove(); + } + if (newImpl) { + this.impl = new newImpl(this.shadowRoot, this.prefs); + + this.mDirection = "ltr"; + let intlUtils = this.window.intlUtils; + if (intlUtils) { + this.mDirection = intlUtils.isAppLocaleRTL() ? "rtl" : "ltr"; + } + + this.impl.onsetup(this.mDirection); + } else { + this.impl = undefined; + } + } + + teardown() { + if (!this.impl) { + return; + } + this.impl.teardown(); + this.shadowRoot.firstChild.remove(); + delete this.impl; + } + + onPrefChange(prefName, prefValue) { + this.prefs[prefName] = prefValue; + + if (!this.impl) { + return; + } + + this.impl.onPrefChange(prefName, prefValue); + } + + // If you change this, also change SEEK_TIME_SECS in PictureInPictureChild.sys.mjs + static SEEK_TIME_SECS = 5; + + static isPictureInPictureVideo(someVideo) { + return someVideo.isCloningElementVisually; + } + + /** + * Returns true if a