Skip to content
This repository has been archived by the owner on May 10, 2024. It is now read-only.

Commit

Permalink
Adding ability to detect media element's information based on tagId.
Browse files Browse the repository at this point in the history
  • Loading branch information
Brandon-T committed Aug 9, 2021
1 parent 30d171f commit 1347936
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 6 deletions.
20 changes: 20 additions & 0 deletions Client/Frontend/Browser/PlaylistHelper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -198,3 +198,23 @@ extension PlaylistHelper: UIGestureRecognizerDelegate {
return false
}
}

extension PlaylistHelper {
static func getCurrentTime(webView: WKWebView, nodeTag: String, completion: @escaping (Double) -> Void) {
let token = UserScriptManager.securityTokenString
let javascript = String(format: "window.mediaCurrentTimeFromTag_%@('%s')", token, nodeTag)

// swiftlint:disable:next safe_javascript
webView.evaluateJavaScript(javascript, completionHandler: { value, error in
if let error = error {
log.error("Error Retrieving Playlist Page Media Current Time: \(error)")
}

if let value = value as? Double {
completion(value)
} else {
completion(0.0)
}
})
}
}
4 changes: 4 additions & 0 deletions Client/Frontend/Browser/UserScriptManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -281,12 +281,16 @@ class UserScriptManager {
let replacements = [
"$<Playlist>": "Playlist_\(token)",
"$<security_token>": "\(token)",
"$<tagNode>": "tagNode_\(token)",
"$<tagUUID>": "tagUUID_\(token)",
"$<mediaCurrentTimeFromTag>": "mediaCurrentTimeFromTag_\(token)",
"$<sendMessage>": "playlistHelper_sendMessage_\(token)",
"$<handler>": "playlistHelper_\(messageHandlerTokenString)",
"$<notify>": "notify_\(token)",
"$<onLongPressActivated>": "onLongPressActivated_\(token)",
"$<setupLongPress>": "setupLongPress_\(token)",
"$<setupDetector>": "setupDetector_\(token)",
"$<setupTagNode>": "setupTagNode_\(token)",
"$<notifyNodeSource>": "notifyNodeSource_\(token)",
"$<notifyNode>": "notifyNode_\(token)",
"$<observeNode>": "observeNode_\(token)",
Expand Down
74 changes: 69 additions & 5 deletions Client/Frontend/UserContent/UserScripts/Playlist.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,21 @@ window.__firefox__.includeOnce("$<Playlist>", function() {
return value;
}

function uuid_v4() {
// JS cryptographically secure UUIDv4.
return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
);
}

function $<tagNode>(node) {
if (node) {
if (!node.$<tagUUID>) {
node.$<tagUUID> = uuid_v4();
}
}
}

function $<sendMessage>(message) {
if (window.webkit.messageHandlers.$<handler>) {
window.webkit.messageHandlers.$<handler>.postMessage(message);
Expand All @@ -53,6 +68,7 @@ window.__firefox__.includeOnce("$<Playlist>", function() {
}

if (target.src && target.src !== "") {
$<tagNode>(target);
$<sendMessage>({
"securitytoken": "$<security_token>",
"name": name,
Expand All @@ -62,12 +78,14 @@ window.__firefox__.includeOnce("$<Playlist>", function() {
"mimeType": type,
"duration": clamp_duration(target.duration),
"detected": false,
"tagId": target.$<tagUUID>
});
}
else {
target.querySelectorAll('source').forEach(function(node) {
if (node.src && node.src !== "") {
if (node.closest('video') === target) {
$<tagNode>(target);
$<sendMessage>({
"securitytoken": "$<security_token>",
"name": name,
Expand All @@ -77,10 +95,12 @@ window.__firefox__.includeOnce("$<Playlist>", function() {
"mimeType": type,
"duration": clamp_duration(target.duration),
"detected": false,
"tagId": target.$<tagUUID>
});
}

if (node.closest('audio') === target) {
$<tagNode>(target);
$<sendMessage>({
"securitytoken": "$<security_token>",
"name": name,
Expand All @@ -90,6 +110,7 @@ window.__firefox__.includeOnce("$<Playlist>", function() {
"mimeType": type,
"duration": clamp_duration(target.duration),
"detected": false,
"tagId": target.$<tagUUID>
});
}
}
Expand All @@ -100,7 +121,9 @@ window.__firefox__.includeOnce("$<Playlist>", function() {

function $<setupLongPress>() {
Object.defineProperty(window, '$<onLongPressActivated>', {
value:
enumerable: false,
configurable: false,
value:
function(localX, localY) {
function execute(page, offsetX, offsetY) {
var target = page.document.elementFromPoint(localX - offsetX, localY - offsetY);
Expand Down Expand Up @@ -151,10 +174,12 @@ window.__firefox__.includeOnce("$<Playlist>", function() {

// Elements found
if (targetVideo) {
$<tagNode>(targetVideo);
$<notify>(targetVideo, 'video');
}

if (targetAudio) {
$<tagNode>(targetAudio);
$<notify>(targetAudio, 'audio');
}
}
Expand Down Expand Up @@ -204,6 +229,7 @@ window.__firefox__.includeOnce("$<Playlist>", function() {
}

if (src !== "") {
$<tagNode>(node);
$<sendMessage>({
"securitytoken": "$<security_token>",
"name": name,
Expand All @@ -212,13 +238,15 @@ window.__firefox__.includeOnce("$<Playlist>", function() {
"pageTitle": document.title,
"mimeType": mimeType,
"duration": clamp_duration(node.duration),
"detected": true
"detected": true,
"tagId": node.$<tagUUID>
});
} else {
var target = node;
document.querySelectorAll('source').forEach(function(node) {
if (node.src !== "") {
if (node.closest('video') === target) {
$<tagNode>(target);
$<sendMessage>({
"securitytoken": "$<security_token>",
"name": name,
Expand All @@ -227,11 +255,13 @@ window.__firefox__.includeOnce("$<Playlist>", function() {
"pageTitle": document.title,
"mimeType": mimeType,
"duration": clamp_duration(target.duration),
"detected": true
"detected": true,
"tagId": target.$<tagUUID>
});
}

if (node.closest('audio') === target) {
$<tagNode>(target);
$<sendMessage>({
"securitytoken": "$<security_token>",
"name": name,
Expand All @@ -240,7 +270,8 @@ window.__firefox__.includeOnce("$<Playlist>", function() {
"pageTitle": document.title,
"mimeType": mimeType,
"duration": clamp_duration(target.duration),
"detected": true
"detected": true,
"tagId": target.$<tagUUID>
});
}
}
Expand Down Expand Up @@ -269,7 +300,14 @@ window.__firefox__.includeOnce("$<Playlist>", function() {
}

function $<observePage>() {
Object.defineProperty(HTMLVideoElement.prototype, 'src', {
Object.defineProperty(HTMLMediaElement.prototype, '$<tagUUID>', {
enumerable: false,
configurable: false,
writable: true,
value: null
});

Object.defineProperty(HTMLMediaElement.prototype, 'src', {
enumerable: true,
configurable: false,
get: function(){
Expand Down Expand Up @@ -317,9 +355,35 @@ window.__firefox__.includeOnce("$<Playlist>", function() {
$<observePage>();
}

function $<setupTagNode>() {
Object.defineProperty(window, '$<mediaCurrentTimeFromTag>', {
enumerable: false,
configurable: false,
value:
function(tag) {
for (element of document.querySelectorAll('video')) {
if (element.$<tagUUID> == tag) {
return clamp_duration(element.currentTime);
}
}

for (element of document.querySelectorAll('audio')) {
if (element.$<tagUUID> == tag) {
return clamp_duration(element.currentTime);
}
}

return 0.0;
}
});


}


// MARK: -----------------------------

$<setupLongPress>();
$<setupDetector>();
$<setupTagNode>();
});
7 changes: 6 additions & 1 deletion Data/models/PlaylistInfo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public struct PlaylistInfo: Codable {
public let duration: TimeInterval
public let detected: Bool
public let dateAdded: Date
public let tagId: String

public init(item: PlaylistItem) {
self.name = item.name ?? ""
Expand All @@ -28,9 +29,10 @@ public struct PlaylistInfo: Codable {
self.duration = item.duration
self.dateAdded = item.dateAdded ?? Date()
self.detected = false
self.tagId = ""
}

public init(name: String, src: String, pageSrc: String, pageTitle: String, mimeType: String, duration: TimeInterval, detected: Bool, dateAdded: Date) {
public init(name: String, src: String, pageSrc: String, pageTitle: String, mimeType: String, duration: TimeInterval, detected: Bool, dateAdded: Date, tagId: String) {
self.name = name
self.src = src
self.pageSrc = pageSrc
Expand All @@ -39,6 +41,7 @@ public struct PlaylistInfo: Codable {
self.duration = duration
self.detected = detected
self.dateAdded = dateAdded
self.tagId = tagId
}

public init(from decoder: Decoder) throws {
Expand All @@ -50,6 +53,7 @@ public struct PlaylistInfo: Codable {
self.mimeType = try container.decodeIfPresent(String.self, forKey: .mimeType) ?? ""
self.duration = try container.decodeIfPresent(TimeInterval.self, forKey: .duration) ?? 0.0
self.detected = try container.decodeIfPresent(Bool.self, forKey: .detected) ?? false
self.tagId = try container.decodeIfPresent(String.self, forKey: .tagId) ?? ""
self.dateAdded = Date()
}

Expand All @@ -76,6 +80,7 @@ public struct PlaylistInfo: Codable {
case mimeType
case duration
case detected
case tagId
case dateAdded
}
}

0 comments on commit 1347936

Please sign in to comment.