-
Notifications
You must be signed in to change notification settings - Fork 0
Developing Browser Extensions
The purpose of this page is to collect all useful and helpful infromations for the development process of a browser extension. Either cross browser or only for one. The infromation is in no specific order, howerver can be searched easily and is sperated into smaller chunks or paragraphs. Also often code examples will be shown or further readings for specific themes. Feel free to enhance this page, but keep the style!!
doomsayer
It seems to be difficult to create a browser extension with Angular, however, it compiles anyway to plain js. The advantage is that we gain the modularity of Angular and the object-oriented programming experience with strong typechecks of Typescript. The use of Angular our life easier because the project acquires a well-defined structure. It can can be more easily maintained and enhanced due to the modularity of Angular. Also, TypeScript, brings the object-oriented programming experience with strict typing to the development.
A Chrome Extension can have three distinct front-end components:
- Extension icon – this is an icon that is displayed next to the browser’s Omnibox (the adress bar)
- Popup – This is a popup HTML page that is displayed when the icon is clicked. It can reference JavaScript and CSS files.
- Extension pages – these are HTML pages hosted by the extension. Each page can reference both JavaScript and CSS files.
While this frontend part is important for the user, the backend part is more important for our development. The following important parts need to be considered (taken from developers api):
-
Content script – a JavaScript file that runs in the context of a page displayed in the browser tab. It has limited access to Chrome extension API (eg. it cannot influence other tabs), but it can do a lot of things in context of the page, like:
- Explore DOM elements
- Inject new objects
- Read the page’s local storage and even expand it with permissions to unlimited storage
- Event page (background script) – a page that runs in the background, that is developed either as and HTML page or as a single JavaScript file. It has full access to the Chrome extension API. It is typically used to receive the requests and send replies to other extension elements. External requests (eg. to external APIs or servers like HTTP) should be executed there.
- Extension/popup page script – a JavaScript file referenced by the HTML page hosted by the extension. It has full access to Chrome extension API.
The configuration and all permissions needed, of our extension, needs to be defined in a special manifest.json file. In this file, we can define the different parts of our extension. It also allows us to specify what kind of premissions our extension requests. Below an example manifest structure:
{
"manifest_version": 1,
"name": "Simple Extension",
"version": "1.0.0",
"permissions": [ "tabs", "activeTab" ],
"content_scripts": [
{
"matches": [ "http*://*/*" ],
"js": [ "content-script.js" ]
}
],
"background": {
"page": "index.html#/event-page",
"persistent": false
},
"browser_action": {
"default_title": "Show Popup",
"default_popup": "index.html#/popup"
},
"default_icon": {
"19": "button/geo-19.png",
"38": "button/geo-38.png"
},
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"
}Of course there are numerous options for the configuration of such a manifest file and further attributes. All available keys and another example can be viewed here: Manifest.Json
However, some options in this example need further clarification maybe, which should be given here now:
- Most of the extensions need to have some permissions for access. In the example above we want to be able to open new browser tabs and access currently-opened ones. That’s why we have to define a
tabsand anactiveTabpermission request. - It is important to define the
matchesparameter for content script node, which will allow us to limit the number of pages the content script get's added. - The
persistentparameter of background script determines if we need our background script or page continuously. By setting this parameter tofalsethe script will be deactivated when not needed (eg. when the extension is not in use at the moment). - The
content_security_policykey is necessary in order to run compiled JavaScript files from Angular.
Normally, extensions are made available in the Extensions Store of either Chrome or Firefox for example. As we don't want to publish an unfished extension, we have to upload it locally. Once we have our manifest file, we can test how it is working locally by turning the developer-mode on in the Chrome://extensions browser page. Having done that, the browser allows us to install the extension by pointing to the location on our computer.
Because we point the path to the location where the manifest file is stored, our extension gets installed and an ID assigned. We can use it to navigate to HTML pages that are included with the extensi. The browsers or at least chrome is hosting its files. As an example, to open the popup.html page we need to go to the following address:
Chrome-extension://[extension-id]/popup.html
JavaScript and CSS files can be referenced in HTML files by relative paths, like this:
<link rel="stylesheet" type="text/CSS" href="style.css">
<script type="text/javascript" src="event-page.js"></script>As there is no out of the box support for Angular and browser extensions, we have to transcode them from typescript to javascript. Which is anway done by Angular, so we can use it. First of all we create our project normally as usual with ng create [projectname].
After building the project, the resulting files can be found normally in the dist folder, where also our manifest file should be located. However, it's not a good idea to place it there from start, as the CLI replaces the whole folder everytime we build it. So we move the manifest file to our src folder and enter it in the angular-cli.json at the assets key in order to bundle it with the other files:
// ...
"assets": [
"assets",
"favicon.ico",
"manifest.json"
],
// ...As Angular CLI is focused on building single-page applications, it produces a single HTML file, which is our start page in the extension. We can make use of routing in order to dynamically change the content on the page or popup as it's called, depending on the user interactions. First we need to setup some components, so we type the following commands in order to generate them:
ng g c homepage
ng g c event-page
ng g c popupIn our app-routing.module.ts we need to include the useHash setting if we want to route. The setting for the router module enables routing in old-fashioned way, using the # sign. So we can open our popup html the following way:
chrome-extension://[extension-id]/index.html#/popup
This is necessary as we have ot use the same method in the manifest file we include in the src folder.
Now we have the basic setup for the project and need to install the Chrome extensions API in order to use the typings, by performing the following command: npm install @types/chrome --save-dev
A good idea, though not needed directly will be to add the configuration to the types property of the tsconfig.app.json.
In order to let particular pieces of the extension we develop, communicate with each other, we need a kind of messaging system. Luckily Chrome Extensions API offers three messaging methods:
-
Chrome.tabs.connect - Opens a communication path to the selected browser tab and allow it to send the message:
- Communicate with single extension elements
- Declare Method to handle incoming Response Events
-
Chrome.tabs.sendMessage - Sends the message to the selected browser tab, e.g. the currently active one:
- Send message within currently executed extension (default behavior).
- Define an ID of the extension
- Define a method to handle an incoming response event
-
Chrome.runtime.sendMessage - Sends a message that can be received by any part of the extension, e.g. content script, event page. The characteristics are similar to the
tabsmethod above.
(C) University of applied sciences St.Pölten Austria