Skip to content

Instantly share code, notes, and snippets.

@Eloston
Created January 23, 2017 19:55
Show Gist options
  • Save Eloston/7a62f50dd91de6dbe6af1af50bd6ed5b to your computer and use it in GitHub Desktop.
Save Eloston/7a62f50dd91de6dbe6af1af50bd6ed5b to your computer and use it in GitHub Desktop.
Messy and rough notes for the Disable HTML5 Autoplay rewrite for version 0.7.
Useful documentation:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/observe
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/preventExtensions
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/seal
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptor
Stuff for weak references:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/WeakMap
Override HTMLMediaElement constructor to hook into creation of new elements
Could replace need for MutationObserver, which is slow and not synchronous
Remove need for storing elements as undelegated initially
Can detect orphaned elements earlier
If using this approach, need to find a way to get reference count for different elements so I can remove a reference to it when it is not used in the page anymore
Or maybe it's not even necessary to keep a reference
Can use Object.getOwnPropertyDescriptor to replace things
e.g. Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, "paused") works!
Replacing the get method for HTMLMedia.prototype.paused via Object.defineProperty with this:
function() { console.log("HELLO WORLD"); return orig_get.apply(this, arguments); }
will cause all subsequent gets to "paused" for any existing or new object to log "HELLO WORLD" to the console
------------------------------------
Popup refactoring
------------------------------------
UI changes:
-Add link to options page
-Change mode switch appearance:
-Use flat colors and box outline (remove fancy gradient)
-Place radio buttons next to the text
-Remove animations?
------------------------------------
Background script cleanup
------------------------------------
-Switch to "use strict";
-Define classes to manage different components:
-PopupsDelegate
-Manages popups
this._popup_ports = new Map()
-PageFramesDelegate
-Manage content script and frame script messaging
-TabManager
-Adds callbacks to other Managers, and can also accept event listeners (if needed)
-Manage browser action
-Manage page statistics
-Manage tab mode
-StorageManager
-Manages reading, writing, and upgrading of storage
-Handles storage events
-OptionsManager
-Manages options for storage
-Constructors just set variables
-All managers have initialize() where they register event listeners
-Need system to allow easy two-way communication between managers
-Event registration
------------------------------------
The content script redesign for 0.7:
------------------------------------
-Use long-lived channel connections (chrome.runtime.Port) for instantiating and communication between frame script and background script
-Use manifest.json content scripts
-Revamp delegate system
-Delegates now control when play is authorized, and what data is faked
-Methods (can add more as time goes on):
[constructor function](media_element): Called when delegate is initialized. Storing media_element is okay, quick tests show that the garbage collector will clean it up.
Will also load options for the element.
_cleanup(): "Private" method called when the delegate no longer applies to the current element.
on_dom_add(media_element): Fired by MutationObserver when the element is added to the DOM
on_dom_change(media_element, mutation_record): Fired by MutationObserver when the element is changed in the DOM
on_dom_remove(media_element): Fired by MutationObserver when the element is removed from the DOM
get_autoplay(media_element):
set_autoplay(media_element, new_value):
get_paused(media_element):
get_played(media_element):
call_play(media_element): Called by play() wrapper when play() is called
call_load(media_element): Called by load() wrapper when load() is called
-Options will become more sophisticated, so try to keep one delegate
-Alternatively, allow for delegate plug-ins(?!)
-It will be just one class named "Delegate"
-register_delegate_for_element(media_element) will pick the delegate to use for the media element
-Delegate system:
MediaElementDelegate (handles all HTMLMediaElement derivatives)
If necessary, create VideoElementDelegate which inherits from MediaElementDelegate
(Try to keep only GenericDelegate because specific behaviors should be customizable via Options Page)
-MutationObserver can be used to notify delegates when the element has been added, changed, or removed from the DOM
-Use WeakMap with key of the media element object and the value is a reference to a delegate object
-Need to also intercept event firing
-Each property accession and function call will do a check to make sure the element is in the WeakMap already
-(New Chromium 51 feature) Consider adding support for Intersection Observer API
-Will need to worry about Shadow DOMs in the future
Some other ideas:
-For elements in the DOM, detect input events in or around(?) the element and use them for authorizing
-Use a dedicated user input event monitor to track and record input events, and let the delegates access this to determine whether it should allow playing or not
-Two types of user input events:
-One is one in or around(?) a media element. The user input event monitor will track this and then notify the corresponding media element about the event.
-Another is an event elsewhere in the page. The event objects will be stored in an array (to keep track of some useful properties such as target) so media elements not in the DOM can read this array. Undelegated elements will have their API used by the page somehow, so the hooks into say the play() function can read this array to determine whether to allow playing or not.
-After each access to the array, there will be garbage collecting to remove events that have "expired" (gone past the 1.5 second timeout to be considered an event that is supposed to trigger media playing) so the array doesn't get infinitely long. There may be periodic cleaning too (on some clock when there are elements in the array). Or possibly after a few input events that fall into this category.
-----------------------------------
Replacing "Modes", "Mode Rules", "Mode Rules List" with UNTITLED
-----------------------------------
-Replace current Mode Rules and Mode Rules List with this new idea
-Popup will now configure this new thing
-Each "rule" has two components: criteria followed by options
-Criteria should be flexible:
-Criterion for any part of the current tab's URL (regex style)
-Or current frame's URL
-Criterion can check any element's properties or attributes
-Criteria can also match parent or child elements
-Special class selector to make it easier to match any number of classes
-Any other attribute will have regex-style matching for values
-Properties will have type checking (for any type) and value checking
-Specify number of matches expecting, -1 for at least 1
-Criteria can check for element type (i.e. Audio or Video)
-Criteria can check for XPath
-Also need to create a special value for not having a path (e.g. not in DOM) if XPath doesn't allow that syntax.
-Options should be flexible
-Specify mode for element
-Specify selection box area that will authenticate play()
-Or specific element to control play()
-Specify whether to block only initial play or subsequent play calls
-Maybe add "trusted sites" where autoplay is less aggressive for dummy users (suggestion https://github.com/Eloston/disable-html5-autoplay/issues/35#issuecomment-165348885)
-Always allow autoplay from the video element when authenticated for the first time, regardless of "src" attribute changes
-Or make this an option in the sophisticated criterion-option model.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment