User:Asqueella/JEP 107: Difference between revisions
(update for Myk's comments <http://groups.google.com/group/mozilla-labs-jetpack/msg/decd886a1ae37018>, except for "include" syntax) |
|||
Line 75: | Line 75: | ||
* [http://wiki.greasespot.net/Include_and_exclude_rules Greasemonkey scripts] specify include and exclude URLs, each may contain wildcards ("*") in any location and may use a special ".tld" domain. These rules get compiled to a regular expression (see [http://github.com/greasemonkey/greasemonkey/blob/master/content/convert2RegExp.js convert2RegExp]), which is then matched against every URL loaded in the browser. | * [http://wiki.greasespot.net/Include_and_exclude_rules Greasemonkey scripts] specify include and exclude URLs, each may contain wildcards ("*") in any location and may use a special ".tld" domain. These rules get compiled to a regular expression (see [http://github.com/greasemonkey/greasemonkey/blob/master/content/convert2RegExp.js convert2RegExp]), which is then matched against every URL loaded in the browser. | ||
* [http://code.google.com/chrome/extensions/match_patterns.html Match patterns for Google Chrome's content scripts] are similar to Greasemonkey's, but force to specify domain (either fully, any domain, or <code>*.domain</code>) and don't have the magic tld domain. | * [http://code.google.com/chrome/extensions/match_patterns.html Match patterns for Google Chrome's content scripts] are similar to Greasemonkey's, but force to specify domain (either fully, any domain, or <code>*.domain</code>) and don't have the magic tld domain. | ||
** Also of interest: [http://code.google.com/p/chromium/issues/detail?id=18259], [http://groups.google.com/a/chromium.org/group/chromium-extensions/browse_thread/thread/9e3903c0817b5837/3d305eb340f01763] | |||
* When specifying CSS styling [https://developer.mozilla.org/en/Using_the_Stylesheet_Service Using the Stylesheet Service], which is an easy and robust way to apply CSS to all content and is also what Stylish uses, you have to describe the filters using CSS, i.e. [https://developer.mozilla.org/index.php?title=En/CSS/%40-moz-document @-moz-document] rule. It allows to specify domain, exact URL, or the URL prefix. | * When specifying CSS styling [https://developer.mozilla.org/en/Using_the_Stylesheet_Service Using the Stylesheet Service], which is an easy and robust way to apply CSS to all content and is also what Stylish uses, you have to describe the filters using CSS, i.e. [https://developer.mozilla.org/index.php?title=En/CSS/%40-moz-document @-moz-document] rule. It allows to specify domain, exact URL, or the URL prefix. | ||
[http://groups.google.com/group/mozilla-labs-jetpack/msg/decd886a1ae37018 Myk's thoughts], "I need to take a closer look at this, but at first glance it looks like Chrome's format balances these goals best." | |||
===== Other issues ===== | ===== Other issues ===== |
Revision as of 22:34, 11 April 2010
This is an alternative version of Labs/Jetpack/Reboot/JEP/107 (page mods).
Here's in progress implementation (currently script mods).
There are two common ways to modify web pages from the browser:
- by specifying custom CSS to apply to specific pages, sites, or all web content. (This is what Stylish extension does.)
- by letting specified scripts run modify the web page (see Greasemonkey extension)
The CSS-only approach is less powerful, yet often simpler and allows to dynamically apply and cancel custom style modifications to the page.
The JavaScript-based approach allows virtually any changes to the page to be implemented, but requires special (and non-trivial) effort to implement instant application and undoing of these modifications.
This proposal focuses on the JavaScript-based approach.
Script Mods
Here's an example of how the ScriptMod API can be used in a jetpack:
var ScriptMod = require("page-mod").ScriptMod; var myMod = new ScriptMod({ include: ["*.example.com", "http://example.org/a/specific/url", "http://example.info/*"], onWindowCreate: function(wrappedWindow) { // this runs each time a new content document starts loading, but // before the page starts loading, so we can't interact with the // page's DOM here yet. wrappedWindow.wrappedJSObject.newExposedProperty = 1; }, onDOMReady: function(wrappedWindow) { // at this point we can work with the DOM wrappedWindow.document.body.innerHTML = "<h1>Jetpack Page Mods</h1>"; } });
In this proposal, a script mod specifies the pages it might modify, and the scripts to run on these pages.
The onWindowCreate
callback function gets called at the earliest possible moment (before the page even started loading, which is made possible by the notifications added in bug 549539).
The onDOMReady
callback is called as soon as the page's DOM is ready (on the DOMContentLoaded
event)
Dependencies
- This module requires bug 549539's fix, which (as of 2010-04-02) has only landed on mozilla-central (Firefox versions after 3.6.x). The plans are to land it on 3.6.x too, though.
- It's not clear to me where the dependencies in the original JEP come from, perhaps some of them apply to this case too.
ScriptMod
constructor
The ScriptMod
constructor takes a single options
parameter which is an object that may define the following properties:
include
: an optional parameter specifying the pages the scripts in this script mod should run on.- The default behavior is to run the mod's scripts on all pages.
- Providing a string value
str
is equivalent to providing a single-item array[str]
. - The mod's scripts run on pages, matching any of
include
rules. - Each
include
rule is a string using one of the following formats (see discussion below):*
(a single asterisk) - any page*.domain.name
- pages from the specified domain and all its subdomains, regardless of their scheme.http://example.com/*
- any URLs with the specified prefix.http://example.com/test
- the single specified URL
- TBD:
filter
function instead of (or in addition) toexclude
. onWindowCreate
,onDOMReady
: optional parameters specifying the code to run on the matched pages.- No code is run if these parameters are not specified.
- Providing a single function
func
is equivalent to providing a single-item array[func]
- When the provided value is an array, its items are expected to be functions. Non-function values are ignored.
- The specified functions are called in order:
- for
onWindowCreate
- when a page matching theinclude
rules starts to load (but before any content is loaded in the page -- i.e. when thecontent-document-global-created
notification implemented in bug 549539 is issued) - for
onDOMReady
- when aDOMContentLoaded
event fires for the matching page.
- for
- An exception thrown from one of the functions does not stop the rest of functions from executing.
- The specified callbacks are called with a single
wrappedWindow
parameter -- the content'swindow
object wrapped in an XPCNativeWrapper. The callback'sthis
is the page mod object (TBD not currently implemented). It goes without saying that with this syntax the callbacks are run in the calling module's scope, not in the content page's scope.
Creating a ScriptMod
instance automatically enables it.
ISSUE: What format should be chosen for include
rules?
First, a short survey of existing formats:
- Greasemonkey scripts specify include and exclude URLs, each may contain wildcards ("*") in any location and may use a special ".tld" domain. These rules get compiled to a regular expression (see convert2RegExp), which is then matched against every URL loaded in the browser.
- Match patterns for Google Chrome's content scripts are similar to Greasemonkey's, but force to specify domain (either fully, any domain, or
*.domain
) and don't have the magic tld domain. - When specifying CSS styling Using the Stylesheet Service, which is an easy and robust way to apply CSS to all content and is also what Stylish uses, you have to describe the filters using CSS, i.e. @-moz-document rule. It allows to specify domain, exact URL, or the URL prefix.
Myk's thoughts, "I need to take a closer look at this, but at first glance it looks like Chrome's format balances these goals best."
Other issues
- There's no easy way to clean up objects referenced from the web page (event listeners, exported APIs) when a jetpack using script mods is unloaded.
- Since the design makes a promise to let one module hosting the script mod to touch a random set of sites, it's not clear if this is going to work well in the out of process tabs world.
- Should provide an example of using jQuery in a script mod. It's likely possible, but not obvious, given that the script mod runs in a hosting module's scope.
ScriptMod
APIs
- Instance properties
scriptMod.disable()
. Call this to stop a script mod from running on further pages. This does not undo the mod's effects on already loaded pages.scriptMod.enable()
. Enabling a script mod makes it take effect on any matching pages that start to load after the script mod is enabled. Enabling a script mod does not apply it to existing matching pages.add/remove/empty
from the original proposal appear inessential, especially if the changes are not applied instantly, as in this proposal.
- Helper functions available as properties on the
ScriptMod
constructor.- TBD other helpers (insert <style>s, <script>s, etc.)
Style mods
TBD