* documentElement may be overwritten right after iframe was initialized with contentDocument.write() and due to this change being external it's not reported in our existing rewrite observer so we enqueue an additional check using setTimeout(0).
* match_about_blank in manifest.json is back
* iframes with src = about: or javascript: don't have a proper URL when our content script runs so we get the real URL from the parent window
* minor refactoring
To prevent cross-page leaks we need to create/copy prefs and cachedStyles inside the background page context.
* storage.js is now used only in the background page
* messaging.js now contains less bg-specific methods and more common methods. Added saveStyleSafe, deleteStyleSafe which automatically invoke onRuntimeMessage of the current page or just handleUpdate/handleDelete when notify:false
* prefs.js with 'prefs' for background and UI pages: separate objects because a UI page may load before the background page and it can read prefs from localStorage/sync/defaults
Previously prefs.set broadcast many messages per each changed pref value to all open tabs, background page, popups. This lead to repeated and needless updates of various things like the toolbar icon, reapplying of styles, and whatnot. It could easily take more than 100ms on an average computer with many tabs open.
Now we debounce the broadcast & sync.set and coalesce all values in one object which is then sent just once per destination.
Popup:
* Enforce 200-800px range for the popup width option
Manage:
* faster search via cachedStyles.byId
* faster restoration of search results on history nav
* style name is clickable and opens the editor
* animated highlight of style element on update/add/save
* expandable extra applies-to targets
* remember scroll position on normal history navigation
* boz-sizing in #header, also in editor
* applies-to targets use structured markup
* get*Tab*, enableStyle and deleteStyle are promisified
Previously, when a cache was invalidated and every tab/iframe issued a getStyles request, we previous needlessly accessed IndexedDB for each of these requests. It happened because 1) the global cachedStyles was created only at the end of the async DB-reading, 2) and each style record is retrieved asynchronously so the single threaded JS engine interleaved all these operations. It could easily span a few seconds when many tabs are open and you have like 100 styles.
Now, in getStyles: all requests issued while cachedStyles is being populated are queued and invoked at the end.
Now, in filterStyles: all requests are cached using the request's options combined in a string as a key. It also helps on each navigation because we monitor page loading process at different stages: before, when committed, history traversal, requesting applicable styles by a content script. Icon badge update also may issue a copy of the just issued request by one of the navigation listeners.
Now, the caches are invalidated smartly: style add/update/delete/toggle only purges filtering cache, and modifies style cache in-place without re-reading the entire IndexedDB.
Now, code:false mode for manage page that only needs style meta. It reduces the transferred message size 10-100 times thus reducing the overhead caused by to internal JSON-fication in the extensions API.
Also fast&direct getStylesSafe for own pages; code cosmetics
The injection code also runs outside of onInstalled event so we check first if a content script belonging to our execution context "generation" is already injected. This can happen on browser startup: the background page is loaded in several seconds after the normal web page tabs are loaded with our content script(s) already injected. The check itself is simply a "ping" message to each tab that should return true if the content script is alive and kicking.
* hotkey to open Manage styles
* hotkey to enable/disable all styles
No default hotkeys are provided, to customize go to "Keyboard shortcuts" on the Extensions page