- Post History
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
on 03-04-2021 11:29 AM
Hi All,
If you are impatient like me and can't wait to see how your extension works, today is the day. By end of this article, you will have your own simple custom chrome extension. You can keep following the series to decode other functionalities of chrome extensions for ServiceNow and/or modify this extension as per your needs.
So let's start.
Step 1) Create a new file in our directory and name it as 'content_script.js' or whatever name you like. Now our directory will look something like this :
Step 2) Add the following code to our new file :
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
insertMyCode(request.snippet);
});
function insertMyCode(text) {
var el = document.activeElement;
var val = el.value;
var endIndex;
var range;
var doc = el.ownerDocument;
if (typeof el.selectionStart === 'number' &&
typeof el.selectionEnd === 'number') {
endIndex = el.selectionEnd;
el.value = val.slice(0, endIndex) + text + val.slice(endIndex);
el.selectionStart = el.selectionEnd = endIndex + text.length;
} else if (doc.selection !== 'undefined' && doc.selection.createRange) {
el.focus();
range = doc.selection.createRange();
range.collapse(false);
range.text = text;
range.select();
}
}
Now let us understand this content script :
In part one we have added the following code in our manifest file,
"content_scripts": [
{
"matches": ["https://*.service-now.com/*"],
"js": ["jquery-3.6.0.min.js", "content_script.js"],
"all_frames": true
}
],
Content scripts are files that run in the context of web pages. By using the standard Document Object Model (DOM), they are able to read details of the web pages the browser visits, make changes to them and pass information to their parent extension.
Content scripts can access Chrome APIs used by their parent extension by exchanging messages with the extension. Additionally, content script can access the following chrome APIs directly: i18n,storage,runtime.
Content scripts live in an isolated world, allowing a content script to makes changes to its JavaScript environment without conflicting with the page or additional content scripts. Isolated worlds do not allow for content scripts, the extension, and the web page to access any variables or functions created by the others. This also gives content scripts the ability to enable functionality that should not be accessible to the web page.
Content Scripts can be programmatically or declaratively injected.
Use programmatic injection for content scripts that need to run on specific occasions.
To inject a programmatic content script, provide the activeTab permission in the manifest. This grants secure access to the active site's host and temporary access to the tabs permission, enabling the content script to run on the current active tab without specifying cross-origin permissions.
"permissions": [
"activeTab"
],
Use declarative injection for content scripts that should be automatically run on specified pages.
Declaratively injected scripts are registered in the manifest under the "content_scripts" field. They can include JavaScript files, CSS files or both. All auto-run content scripts must specify match patterns.
"content_scripts": [
{
"matches": ["http://*.nytimes.com/*"],
"css": ["myStyles.css"],
"js": ["contentScript.js"]
}
],
matches - Specifies which pages this content script will be injected into.
js - The list of JavaScript files to be injected into matching pages. These are injected in the order they appear in this array.
all_frames - The "all_frames" field allows the extension to specify if JavaScript and CSS files should be injected into all frames matching the specified URL requirements or only into the topmost frame in a tab.
"content_scripts": [
{
"matches": ["http://*.nytimes.com/*"],
"all_frames": true,
"js": ["contentScript.js"]
}
],
Host permissions and content script matching are based on a set of URLs defined by match patterns. A match pattern is essentially a URL that begins with a permitted scheme (http, https, file, or ftp, and that can contain '*' characters. The special pattern <all_urls> matches any URL that starts with a permitted scheme.
Each match pattern has 3 parts:
- scheme—for example, http or file or *
- host—for example, www.google.com or *.google.com or *; if the scheme is file, there is no host part
- path—for example, /*, /foo*, or /foo/bar. The path must be present in a host permission, but is always treated as /*.
The meaning of '*' depends on whether it's in the scheme, host, or path part. If the scheme is *, then it matches either http or https, and not file, ftp, or urn. If the host is just *, then it matches any host. If the host is *._hostname_, then it matches the specified host or any of its subdomains. In the path section, each '*' matches 0 or more characters.
Since content scripts run in the context of a web page and not the extension, they often need some way of communicating with the rest of the extension.
Communication between extensions and their content scripts works by using message passing. Either side can listen for messages sent from the other end, and respond on the same channel. A message can contain any valid JSON object (null, boolean, number, string, array, or object).
If you only need to send a single message to another part of your extension (and optionally get a response back), you should use the simplified runtime.sendMessage or tabs.sendMessage . This lets you send a one-time JSON-serializable message from a content script to extension , or vice versa, respectively .
Sending a request from a content script looks like this:
chrome.runtime.sendMessage({greeting: "hello"}, function(response) {
console.log(response.farewell);
});
Sending a request from the extension to a content script looks very similar, except that you need to specify which tab to send it to. This example demonstrates sending a message to the content script in the selected tab.
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {greeting: "hello"}, function(response) {
console.log(response.farewell);
});
});
On the receiving end, you need to set up an runtime.onMessage event listener to handle the message. This looks the same from a content script or extension page.
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
console.log(sender.tab ?
"from a content script:" + sender.tab.url :
"from the extension");
if (request.greeting == "hello")
sendResponse({farewell: "goodbye"});
}
);
In the background script we created in part two, we have used tabs.sendMessage APIs :
function insertSnippet(e, f) {
chrome.tabs.query({
active: true,
currentWindow: true
}, function (tabs) {
chrome.tabs.sendMessage(tabs[0].id, {
"snippet": snippets[e.menuItemId][2]
});
});
}
tabs.sendMessage API Sends a single message to the content script(s) in the specified tab, with an optional callback to run when a response is sent back.
In the content script, we created today as part of this article, we have used runtime.onMessage
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
insertMyCode(request.snippet);
});
onMessage - Fired when a message is sent from either an extension process (by sendMessage) or a content script (by tabs.sendMessage).
Use the chrome.runtime API to retrieve the background page, return details about the manifest, and listen for and respond to events in the app or extension lifecycle. You can also use this API to convert the relative path of URLs to fully-qualified URLs.
The activeElement property returns the currently focused element in the document.
document.activeElement
The activeElement read-only property of the Document interface returns the Element within the DOM that currently has focus.
Often activeElement will return a HTMLInputElement or HTMLTextAreaElement object if it has the text selection at the time. If so, you can get more detail by using the object's selectionStart and selectionEnd properties.
So, as I had promised, we have created a simple extension and understood the working of it. And now It's time to test.
Step 3) Open the Extension Management page by navigating to chrome://extensions.
- Alternatively, open this page by clicking on the Extensions menu button and selecting Manage Extensions at the bottom of the menu.
- Alternatively, open this page by clicking on the Chrome menu, hovering over More Tools then selecting Extensions
Step 5) Click the Load unpacked button and select the extension directory.
Thank you.
Vishal Ingle,
DxSherpa Technologies Pvt. Ltd., Pune.
Other Articles in the Series till Now :
Decoding Chrome Extensions for ServiceNow : Part 1 (manifest.json)
Decoding Chrome Extensions for ServiceNow : Part 2 (background.js)
Decoding Chrome Extensions for ServiceNow : Part 3 (Content Scripts)