Good day, dear habrazhiteli.
Today we will talk in more detail about the cross-browser user
scripting technology
mentioned above , namely the
packaging of the user script into the simplest extension for Google Chrome.
Below I will try to answer the questions "why?" And "how?".
Prelude
As you remember, Google Chrome browser supports scripts natively (without the
need to install third-party components). Script support is implemented at a fairly good level, but there is one
BUT : Google Chrome developers care about our security and limit everything that can be limited.
')
In view of these limitations, non-trivial scripts have to be wrapped into an extension.
What are the limitations?
The most important limitations are:
- The script should do cross-domain queries.
- The script needs access to window.frames [i]
- The script needs elevated localStorage limits
- Etc.
The above three restrictions can not be emulated and okostyleny. It is necessary to pack yuzerskript.
What do we get at the output?
If we speak strictly, then at the output we will get the
extension , not the user script. But given that:
- the installation and management processes of user scripts and extensions are the same;
- user scripts automatically install into an extension when installed;
- the wrapper is created once, and then we develop only the user script itself;
I allow myself to talk about user scripts.
Packaging
A simple extension consists of:
- Description file manifest.json
- Background page background.html
- User script file
manifest.json
This file describes the extension: permissions, constituting resources, launch method, etc.
As the name implies, the entire configuration is a json object.
More information about this file can be found in the
official dock .
I will consider the necessary minimum for turning user scripts into extensions:
{ "background_page" : "background.html", "content_scripts" : [ { "js":[ "my.user.js" ], "matches":[ "http://*/*" ], "run_at":"document_end" } ], "description" : "", "name" : "My Userscript", "permissions" : [ "http://*/*", "unlimitedStorage"], "version" : "1.3.0" }
Parameter | Purpose | Comment |
---|
background_page | Defines a background page file. | Appointment see below |
content_scripts | Content Script Connection Section | This is where the information is written. about our user script |
js | An array containing the name of the content script files | Here is the name our only script |
matches | Array containing url masks for running scripts | Each element of the array corresponds to by index of an array of content scripts. This parameter determines which pages corresponding scripts will be run. In our case, the mask indicates that the script runs on all pages, available on http. |
run_at | The order of launching content scripts | document_end means that the script will run after building a DOM tree |
description | Expansion Description | Free text describing our user script |
name | Extension name | The name of the script in any form |
permissions | Permissions for our extension | Security permissions required. The first parameter in the example - mask of domain requests http: // * / * . It allows the background page to send requests to any domains.
The second parameter sets non-limited localStorage . |
version | Extension version | Version in xxxx format |
background.html
The background page is a regular html page that is loaded into the “invisible tab” when the extension is launched and runs in the background during the entire life cycle of the extension.
Background page security restrictions are configured via the permissions parameter in the manifest file.
It is through the background page that user scripts are limited . The background page for packaged userscripts is a proxy, which can “communicate” with userscripts via
chrome.extension api (
Description ).
The theory is done, time to
hang out practice!
Let's take a closer
look at proxying
cross-domain requests from user scripts.
Code background.html:
<!DOCTYPE html> <html> <head> </head> <body> <script> /** * . * XMLHttpRequest CORP (Cross Origin Request Policy), * .. . * GET */ function get(url, callback) { var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function (data) { if (xhr.readyState == 4) { if (xhr.status == 200) { callback(data.srcElement.responseText); } else { callback(null); } } } // Note that any URL fetched here must be matched by a permission in // the manifest.json file! xhr.open('GET', url, true); xhr.send(); }; /** * chrome.extension api. * * @param request Object api-. * @param sender Object , . * @param callback Function , api-. * / function onRequest(request, sender, callback) { // xget. // RPC-c if (request.action == 'xget') { get(request.url, callback); } }; // . chrome.extension.onRequest.addListener(onRequest); // : // chrome.extension.sendRequest({'action' : 'xget', 'url':url}, callback); </scrip> <body></html>
The code with English comments is available on
pastebin.comCall from user script:
function get(url, callback) {& chrome.extension.sendRequest({ 'action':'xget', 'url':url}, callback); }
This method works in Google Chrome. Cross-domain queries from userscripts in other browsers will be covered in one of the following articles.We collect, we test
To build the extension we need:
- Create a separate folder (for convenience)
- Put manifest.js, background.html and user script file in it
- Pack an extension with Chrome (Settings - Extensions - Pack an extension. See screenshot)

For testing, we can install the unpacked extension (thanks to the
OnlyBoy tip). Instead of packing (item 3), click “Install unpacked extension”.
As a result, our extension will be installed like a regular packaged (plus there will be a nice and convenient Reload link for reloading the extension, see screenshot).
Conclusion
That's it for today, stay with us!
Waiting for questions, criticism and discussion in the comments.
List of articles:
- Learning to write userscript
- Userscripts. Go deep
- » Userscripts. We pack user scripts for Chrome
- Usersctripts. Cross Domain Queries