From 59dc806d31cf6d0b4e7eaf02ba2b1ed69d572ebf Mon Sep 17 00:00:00 2001 From: hensm Date: Fri, 15 Apr 2022 07:50:57 +0100 Subject: [PATCH] Remove experimental media overlay --- ext/bin/build.js | 2 - ext/src/_locales/de/messages.json | 24 - ext/src/_locales/en/messages.json | 24 - ext/src/_locales/es/messages.json | 24 - ext/src/_locales/nl/messages.json | 22 - ext/src/_locales/no/messages.json | 23 - ext/src/background/background.ts | 43 -- ext/src/defaultOptions.ts | 1 - ext/src/lib/options.ts | 1 - ext/src/manifest.json | 3 - ext/src/senders/media/index.ts | 4 - .../senders/media/overlay/AirPlay_Audio.svg | 6 - .../senders/media/overlay/AirPlay_Video.svg | 3 - .../senders/media/overlay/descriptorUtils.ts | 75 ---- .../senders/media/overlay/overlayContent.ts | 418 ------------------ .../media/overlay/overlayContentLoader.ts | 37 -- ext/src/ui/options/index.tsx | 15 - 17 files changed, 725 deletions(-) delete mode 100644 ext/src/senders/media/overlay/AirPlay_Audio.svg delete mode 100644 ext/src/senders/media/overlay/AirPlay_Video.svg delete mode 100644 ext/src/senders/media/overlay/descriptorUtils.ts delete mode 100644 ext/src/senders/media/overlay/overlayContent.ts delete mode 100644 ext/src/senders/media/overlay/overlayContentLoader.ts diff --git a/ext/bin/build.js b/ext/bin/build.js index 78be7d9..72d162b 100644 --- a/ext/bin/build.js +++ b/ext/bin/build.js @@ -74,8 +74,6 @@ const buildOpts = { `${srcPath}/background/background.ts`, // Media sender `${srcPath}/senders/media/index.ts`, - `${srcPath}/senders/media/overlay/overlayContent.ts`, - `${srcPath}/senders/media/overlay/overlayContentLoader.ts`, // Mirroring sender `${srcPath}/senders/mirroring.ts`, // Cast diff --git a/ext/src/_locales/de/messages.json b/ext/src/_locales/de/messages.json index 9400f26..825bac6 100644 --- a/ext/src/_locales/de/messages.json +++ b/ext/src/_locales/de/messages.json @@ -92,18 +92,6 @@ } } - - , "mediaOverlayTitle": { - "message": "Wiedergabe auf $receiverName$" - , "description": "Main title for overlay displayed on media elements whilst casting." - , "placeholders": { - "receiverName": { - "content": "$1" - , "example": "Living Room TV" - } - } - } - , "optionsBridgeLoading": { "message": "Lade Bridge-Informationen..." , "description": "Loading placeholder text for bridge section on options page." @@ -226,18 +214,6 @@ "message": "Streamen von Medien aktivieren" , "description": "Media casting enabled checkbox label." } - , "optionsMediaOverlayEnabled": { - "message": "Aktiviere Medien-Overlay" - , "description": "Media element overlay checkbox label." - } - , "optionsMediaOverlayEnabledTemp": { - "message": "Aktiviere Medien-Overlay (experimentell)" - , "description": "Experimental-labelled version of above." - } - , "optionsMediaOverlayEnabledDescription": { - "message": "Overlay auf Medien, das, wenn verbunden, Informationen über die aktuelle Sitzung anzeigt." - , "description": "Media element overlay option description." - } , "optionsMediaSyncElement": { "message": "Empfängerstatus mit Media-Element synchronisieren" , "description": "Media casting sync checkbox label." diff --git a/ext/src/_locales/en/messages.json b/ext/src/_locales/en/messages.json index 9e739f5..a9f8ec9 100755 --- a/ext/src/_locales/en/messages.json +++ b/ext/src/_locales/en/messages.json @@ -97,18 +97,6 @@ } - , "mediaOverlayTitle": { - "message": "Playing on $receiverName$" - , "description": "Main title for overlay displayed on media elements whilst casting." - , "placeholders": { - "receiverName": { - "content": "$1" - , "example": "Living Room TV" - } - } - } - - , "optionsBridgeLoading": { "message": "Loading bridge info..." , "description": "Loading placeholder text for bridge section on options page." @@ -231,18 +219,6 @@ "message": "Enable media casting" , "description": "Media casting enabled checkbox label." } - , "optionsMediaOverlayEnabled": { - "message": "Enable media element overlay" - , "description": "Media element overlay checkbox label." - } - , "optionsMediaOverlayEnabledTemp": { - "message": "Enable media element overlay (experimental)" - , "description": "Experimental-labelled version of above." - } - , "optionsMediaOverlayEnabledDescription": { - "message": "Overlay on media elements displaying information about the current session if connected." - , "description": "Media element overlay option description." - } , "optionsMediaSyncElement": { "message": "Sync receiver state with media element" , "description": "Media casting sync checkbox label." diff --git a/ext/src/_locales/es/messages.json b/ext/src/_locales/es/messages.json index a7e7108..85bea49 100644 --- a/ext/src/_locales/es/messages.json +++ b/ext/src/_locales/es/messages.json @@ -97,18 +97,6 @@ } - , "mediaOverlayTitle": { - "message": "Reproduciendo en $receiverName$" - , "description": "Main title for overlay displayed on media elements whilst casting." - , "placeholders": { - "receiverName": { - "content": "$1" - , "example": "Living Room TV" - } - } - } - - , "optionsBridgeLoading": { "message": "Cargando información de la aplicación puente..." , "description": "Loading placeholder text for bridge section on options page." @@ -231,18 +219,6 @@ "message": "Activar transmisión de contenidos" , "description": "Media casting enabled checkbox label." } - , "optionsMediaOverlayEnabled": { - "message": "Activar sobreposición en el elemento de medios" - , "description": "Media element overlay checkbox label." - } - , "optionsMediaOverlayEnabledTemp": { - "message": "Activar sobreposición en el elemento de medios (experimental)" - , "description": "Experimental-labelled version of above." - } - , "optionsMediaOverlayEnabledDescription": { - "message": "Sobreposición en elementos de medios mostrando información acerca de la sesión actual si está conectado." - , "description": "Media element overlay option description." - } , "optionsMediaSyncElement": { "message": "Sincronizar estado del receptor con el contenido" , "description": "Media casting sync checkbox label." diff --git a/ext/src/_locales/nl/messages.json b/ext/src/_locales/nl/messages.json index b79d30a..c5f04f5 100755 --- a/ext/src/_locales/nl/messages.json +++ b/ext/src/_locales/nl/messages.json @@ -85,16 +85,6 @@ } } }, - "mediaOverlayTitle": { - "message": "Speelt af op $receiverName$", - "description": "Main title for overlay displayed on media elements whilst casting.", - "placeholders": { - "receiverName": { - "content": "$1", - "example": "Living Room TV" - } - } - }, "optionsBridgeLoading": { "message": "Bezig met laden van bridge-informatie...", "description": "Loading placeholder text for bridge section on options page." @@ -209,18 +199,6 @@ "message": "Mediacasten ingeschakeld", "description": "Media casting enabled checkbox label." }, - "optionsMediaOverlayEnabled": { - "message": "Inschakelen overlay media element", - "description": "Media element overlay checkbox label." - }, - "optionsMediaOverlayEnabledTemp": { - "message": "Inschakelen overlay media element (Experimenteel)", - "description": "Experimental-labelled version of above." - }, - "optionsMediaOverlayEnabledDescription": { - "message": "Een overlay over media elementen die informatie weergeeft over de huidige sessie indien verbonden.", - "description": "Media element overlay option description." - }, "optionsMediaSyncElement": { "message": "Ontvangerstatus synchroniseren met media-element", "description": "Media casting sync checkbox label." diff --git a/ext/src/_locales/no/messages.json b/ext/src/_locales/no/messages.json index 72e4321..ba1b521 100644 --- a/ext/src/_locales/no/messages.json +++ b/ext/src/_locales/no/messages.json @@ -97,17 +97,6 @@ } - , "mediaOverlayTitle": { - "message": "Spiller på $receiverName$" - , "description": "Main title for overlay displayed on media elements whilst casting." - , "placeholders": { - "receiverName": { - "content": "$1" - , "example": "Living Room TV" - } - } - } - , "optionsBridgeLoading": { "message": "Laster bro-info" , "description": "Loading placeholder text for bridge section on options page." @@ -230,18 +219,6 @@ "message": "Skru på media-casting" , "description": "Media casting enabled checkbox label." } - , "optionsMediaOverlayEnabled": { - "message": "Skru på element-overlegg (eksperimentell)" - , "description": "Media element overlay checkbox label." - } - , "optionsMediaOverlayEnabledTemp": { - "message": "Skru på element-overlegg (eksperimentell)" - , "description": "Experimental-labelled version of above." - } - , "optionsMediaOverlayEnabledDescription": { - "message": "mediaelementer " - , "description": "Media element overlay option description." - } , "optionsMediaSyncElement": { "message": "Synkroniser mottager med mediaelement" , "description": "Media casting sync checkbox label." diff --git a/ext/src/background/background.ts b/ext/src/background/background.ts index 6d5c5c3..f9d66cf 100755 --- a/ext/src/background/background.ts +++ b/ext/src/background/background.ts @@ -41,48 +41,6 @@ browser.runtime.onInstalled.addListener(async details => { } }); -/** - * Sets up media overlay content script and handles toggling - * on options change. - */ -async function initMediaOverlay() { - logger.info("init (media overlay)"); - - let contentScript: browser.contentScripts.RegisteredContentScript; - - async function registerMediaOverlayContentScript() { - if (!(await options.get("mediaOverlayEnabled"))) { - return; - } - - try { - contentScript = await browser.contentScripts.register({ - allFrames: true, - js: [{ file: "senders/media/overlay/overlayContentLoader.js" }], - matches: [""], - runAt: "document_start" - }); - } catch (err) { - logger.error("Failed to register media overlay"); - } - } - - async function unregisterMediaOverlayContentScript() { - await contentScript?.unregister(); - } - - registerMediaOverlayContentScript(); - - // Update if toggled - options.addEventListener("changed", async ev => { - const alteredOpts = ev.detail; - - if (alteredOpts.includes("mediaOverlayEnabled")) { - await unregisterMediaOverlayContentScript(); - await registerMediaOverlayContentScript(); - } - }); -} /** * Checks whether the bridge can be reached and is compatible @@ -153,7 +111,6 @@ async function init() { await initMenus(); await initWhitelist(); - await initMediaOverlay(); /** * When the browser action is clicked, open a receiver diff --git a/ext/src/defaultOptions.ts b/ext/src/defaultOptions.ts index a1c0a31..90913cc 100644 --- a/ext/src/defaultOptions.ts +++ b/ext/src/defaultOptions.ts @@ -8,7 +8,6 @@ export default { bridgeBackupHost: "localhost", bridgeBackupPort: 9556, mediaEnabled: true, - mediaOverlayEnabled: false, mediaSyncElement: false, mediaStopOnUnload: false, localMediaEnabled: true, diff --git a/ext/src/lib/options.ts b/ext/src/lib/options.ts index 6a57221..03dc7fb 100644 --- a/ext/src/lib/options.ts +++ b/ext/src/lib/options.ts @@ -17,7 +17,6 @@ export interface Options { bridgeBackupHost: string; bridgeBackupPort: number; mediaEnabled: boolean; - mediaOverlayEnabled: boolean; mediaSyncElement: boolean; mediaStopOnUnload: boolean; localMediaEnabled: boolean; diff --git a/ext/src/manifest.json b/ext/src/manifest.json index dbda0ac..0f551cd 100755 --- a/ext/src/manifest.json +++ b/ext/src/manifest.json @@ -66,8 +66,5 @@ ] , "web_accessible_resources": [ "cast/index.js" - , "senders/media/overlay/overlayContent.js" - , "senders/media/overlay/AirPlay_Audio.svg" - , "senders/media/overlay/AirPlay_Video.svg" ] } diff --git a/ext/src/senders/media/index.ts b/ext/src/senders/media/index.ts index 6c6a408..1e41f89 100644 --- a/ext/src/senders/media/index.ts +++ b/ext/src/senders/media/index.ts @@ -362,10 +362,6 @@ export async function init(opts: InitOptions) { if (targetElement instanceof HTMLMediaElement) { registerMediaElementListeners(targetElement); - - if (await options.get("mediaOverlayEnabled")) { - // TODO: Un-hide overlay here - } } window.addEventListener("beforeunload", async () => { diff --git a/ext/src/senders/media/overlay/AirPlay_Audio.svg b/ext/src/senders/media/overlay/AirPlay_Audio.svg deleted file mode 100644 index 4992c91..0000000 --- a/ext/src/senders/media/overlay/AirPlay_Audio.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/ext/src/senders/media/overlay/AirPlay_Video.svg b/ext/src/senders/media/overlay/AirPlay_Video.svg deleted file mode 100644 index 51aa7fa..0000000 --- a/ext/src/senders/media/overlay/AirPlay_Video.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/ext/src/senders/media/overlay/descriptorUtils.ts b/ext/src/senders/media/overlay/descriptorUtils.ts deleted file mode 100644 index ff7afa5..0000000 --- a/ext/src/senders/media/overlay/descriptorUtils.ts +++ /dev/null @@ -1,75 +0,0 @@ -"use strict"; - -/** - * Walk up the prototype chain until the specified property - * descriptor is found, otherwise return undefined. - */ -export function getPropertyDescriptor( - target: any, - prop: string | number | symbol -): PropertyDescriptor | undefined { - let desc: PropertyDescriptor | undefined; - while (!desc && target !== null) { - desc = Object.getOwnPropertyDescriptor(target, prop); - if (!desc) target = Object.getPrototypeOf(target); - } - - return desc; -} - -/** - * Bind either the getter/setter functions or the value function - * to a target object. - */ -export function bindPropertyDescriptor( - desc: PropertyDescriptor, - target: any -): PropertyDescriptor { - if (typeof desc.value === "function") { - desc.value = desc.value.bind(target); - } else { - if (desc.get) desc.get = desc.get.bind(target); - if (desc.set) desc.set = desc.set.bind(target); - } - - return desc; -} - -/** - * For each attribute handler, fetch the property descriptor (which may - * be further up in the prototype chain), re-bind it to the target - * element and collect them into a property descriptor map. - */ -export function clonePropsDescriptor( - target: T, - props: any[] -): PropertyDescriptorMap { - return props.reduce((descriptorMap, prop) => { - const desc = getPropertyDescriptor(target, prop); - if (desc) { - bindPropertyDescriptor(desc, target); - descriptorMap[prop as any] = desc; - } - - return descriptorMap; - }, {}); -} - -export function makeGetterDescriptor(val: any): PropertyDescriptor { - return { - enumerable: true, - configurable: true, - get() { - return val; - } - }; -} - -export function makeValueDescriptor(val: any): PropertyDescriptor { - return { - enumerable: true, - configurable: true, - writable: true, - value: val - }; -} diff --git a/ext/src/senders/media/overlay/overlayContent.ts b/ext/src/senders/media/overlay/overlayContent.ts deleted file mode 100644 index b885997..0000000 --- a/ext/src/senders/media/overlay/overlayContent.ts +++ /dev/null @@ -1,418 +0,0 @@ -"use strict"; - -import logger from "../../../lib/logger"; - -import { - bindPropertyDescriptor, - clonePropsDescriptor, - getPropertyDescriptor, - makeGetterDescriptor, - makeValueDescriptor -} from "./descriptorUtils"; - -// Injected by content loader -declare const iconAirPlayAudio: string; -declare const iconAirPlayVideo: string; -declare const mediaOverlayTitle: string; - -/** - * Intercept and store references to shadow root nodes created by - * calls to `attachShadow`. Used to reference shadow roots, even when - * created in closed mode without exposing them to other page scripts. - */ -const internalShadowRoots = new WeakMap(); -const _attachShadow = Element.prototype.attachShadow; -Element.prototype.attachShadow = function (init) { - const shadowRoot = _attachShadow.call(this, init); - internalShadowRoots.set(this, shadowRoot); - return shadowRoot; -}; - -function getShadowRootFromNode(node: Node): ShadowRoot | undefined { - // Don't touch our custom element - if (node instanceof PlayerElement) { - return; - } - - return internalShadowRoots.get(node as Element); -} - -const DQS_XPATH_EXPRESSION = `//*[contains(name(), "-")]`; - -/** - * Return the first matching querySelector result on any ShadowRoot - * nodes present in the document. - */ -function deepQuerySelector(selector: string): Element | null { - const result = document.evaluate( - DQS_XPATH_EXPRESSION, - document, - null, - XPathResult.ORDERED_NODE_ITERATOR_TYPE - ); - - let node: Node | null; - // eslint-disable-next-line no-cond-assign - while ((node = result.iterateNext())) { - const shadowRoot = getShadowRootFromNode(node); - if (!shadowRoot) { - continue; - } - - const queryResult = shadowRoot.querySelector(selector); - if (queryResult) { - return queryResult; - } - } - - return null; -} - -/** - * Collect and return the results of querySelectorAll on any - * ShadowRoot nodes present in the document. - */ -function deepQuerySelectorAll(selector: string): Node[] { - const result = document.evaluate( - DQS_XPATH_EXPRESSION, - document, - null, - XPathResult.ORDERED_NODE_ITERATOR_TYPE - ); - - const nodes: Node[] = []; - - let node: Node | null; - // eslint-disable-next-line no-cond-assign - while ((node = result.iterateNext())) { - const shadowRoot = getShadowRootFromNode(node); - if (shadowRoot) { - nodes.push(...shadowRoot.querySelectorAll(selector)); - } - } - - return nodes; -} - -const mediaElementTypes = [ - HTMLMediaElement, - HTMLVideoElement, - HTMLAudioElement -]; - -const mediaElementEvents = [ - "abort", - "canplay", - "canplaythrough", - "durationchange", - "emptied", - "encrypted", - "ended", - "error", - "interruptbegin", - "interruptend", - "loadeddata", - "loadedmetadata", - "loadstart", - "mozaudioavailable", - "pause", - "play", - "playing", - "progress", - "ratechange", - "seeked", - "seeking", - "stalled", - "suspend", - "timeupdate", - "volumechange", - "waiting" -]; - -const mediaElementAttributes = mediaElementTypes - .flatMap(type => Object.getOwnPropertyNames(type.prototype)) - .concat(mediaElementEvents.map(ev => `on${ev}`)); - -/** - * Opaque wrapper around the media element to provide an overlay without - * author interference. Relevant properties, attributes, events and - * functions are proxied to the internal media element. - */ -class PlayerElement extends HTMLElement { - constructor() { - super(); - - const shadowRoot = this.attachShadow({ mode: "closed" }); - const { host } = shadowRoot; - - let iconUrl; - switch (this.constructor) { - // URL variables injected ahead of current script - - case AudioPlayerElement: { - iconUrl = iconAirPlayAudio; - break; - } - case VideoPlayerElement: { - iconUrl = iconAirPlayVideo; - break; - } - } - - shadowRoot.innerHTML = ` - - - - `; - - const videoElement = _createElement.call(document, "video"); - - for (const attr of mediaElementAttributes) { - if (host.hasOwnProperty(attr)) { - // @ts-ignore - videoElement[attr] = host[attr]; - } - } - - /** - * Page scripts need to be able to read/write attributes, event - * listeners, etc... on the media element, but since it's hidden - * within the shadow DOM, these properties must be proxied. - */ - Object.defineProperties( - host, - clonePropsDescriptor(videoElement, [ - "attributes", - "setAttribute", - "removeAttribute", - "setAttribute", - "addEventListener", - "removeEventListener", - "hasEventListener", - ...(mediaElementAttributes as any) - ]) - ); - - shadowRoot.prepend(videoElement); - } -} - -class AudioPlayerElement extends PlayerElement {} -class VideoPlayerElement extends PlayerElement { - set overlayHidden(val: boolean) { - const shadowRoot = internalShadowRoots.get(this); - (shadowRoot?.querySelector(".overlay") as HTMLDivElement).hidden = val; - } - get overlayHidden() { - const shadowRoot = internalShadowRoots.get(this); - return (shadowRoot?.querySelector(".overlay") as HTMLDivElement).hidden; - } -} - -try { - customElements.define("audio-player-element", AudioPlayerElement); - customElements.define("video-player-element", VideoPlayerElement); -} catch (err) { - if ( - err instanceof DOMException && - err.code === DOMException.NOT_SUPPORTED_ERR - ) { - // Script already injected - } -} - -// Original functions -const _createElement = document.createElement; -const _createElementNS = document.createElementNS; - -/** - * Intercepts `