What's a Script

In Cown Zoo, "script" actually refers to a collection of JavaScript files and / or stylesheets that are being applied to a certain group of web pages, defined by rules.

You can have no JavaScript at all, for CSS-only modifications, and of course you can have multiple JavaScript files so you don't need to put your dependencies in your code. This design also enables compatibility with the de facto user script standard, GreaseMonkey, which supports @require definitions to include other JS files.

There're also metadata included in a script, like name and description. If provided, the URL to the script will be persisted as well for updating.

To specify what web pages a script will apply to, page matching rules need to be specified. Currently Zoo supports WebExtension standard match and excludeMatches match patterns, but not globs. Options like runAt are also supported in Zoo.

Check extension permissions
If you didn't give Zoo full access to any webpages, Safari won't allow Cown to touch unauthorized pages, even the script should be applied to them.

JS Environment

All JavaScript are injected to page scope. Each JavaScript file will be wrapped in an IIFE with window, document and Zoo (Zoo's runtime API) are passed in as parameters.

JavaScript files are executed in order, one after another.

Compatibility with GreaseMonkey

First, it should be noted that Cown Zoo never intends to be fully GreaseMonkey-compatible. GreaseMonkey has came a long way from early days of Web, and many features and concepts it provides are not relevant on today's web any more, or is not achievable at all in modern browsers, especially on mobile platforms.

Also, other influential user script managers may have their own extension to GreaseMonkey's spec, or implementation quirks that are utilized by user script authors. Thus, when using "GreaseMonkey scripts" from web, your milage may vary. You may need to modify them to make them work.

Zoo currently supports those keys in GreaseMonkey metadata block specification:

  • @description
  • @match
  • @name
  • @noframes
  • @require
  • @run-at
  • @version
  • @grant

When no match rules were specified
Zoo will match no web page when no match rules were specified, instead of matching all pages (which is how GreaseMonkey work). You need to manually add <all_urls> to matches if you want this behavior.

In terms of GreaseMonkey runtime APIs, Zoo currently supports:

  • GM.setClipboard (alias of Zoo.clipboard.writeText)

We do expected to implement more of them later, more like a polyfill or alias on top of Zoo's own runtime API.

Also, the environment in which JavaScripts are evaluated is actually very different from GreaseMonkey's spec. It shouldn't be problematic for most scripts out there though.

@grant

Some runtime APIs have to be @granted first to be available to a script. For example, GM.setClipboard need to be @granted first. But if the capability is not limited to extensions (in this case, Web Clipboard API exists), and consider Zoo scripts are all injected into page scope, it doesn't make sense to actually bar it behind @grant.

In Cown Zoo, we have our own permission system, so GreaseMonkey API @grants are converted to Zoo permissions. Even some API @grants aren't relevant any more, we still have them as permissions, but they're makred with 🐒GM to indicate their extistence is merely some effort to be compatible with some GreaseMonkey scripts.

These marked permissions only control the availability of GM polyfills / aliases and won't affect its Web API / Zoo runtime API equivalent. Zoo.clipboard.writeText (and the Web Clipboard API) will be always exposed to any Zoo scripts, regardless of whether there's a @grant GM.setClipboard.


Copyright 2022 Inkwire Technology (Hangzhou) Co., Ltd.