Chrome Extensions have been around for a long time. I believe they are a very under-explored technology - and if you’re a traditional web developer, there’s a very small learning curve since Chrome Extensions are comprised of HTML, JavaScript and CSS. Bonus - you don’t have to worry about every browser under the sun, just Chrome! (though Firefox is becoming extension-friendly, it might be a good idea to not include Chrome-only web features).
So, let’s get started - the first thing you’ll need is a folder containing the basics:
This is the manifest for the Extension. It contains basic information like name, version, description, icons, scripts, action type. Our example:
{
"manifest_version": 2,
"name": "Code Checker",
"version": "1.0.6",
"description": "This extension verifies the code exists somewhere on this page",
"icons": {
"128": "icon128.png",
"32": "icon32.png",
"48": "icon.png"
},
"browser_action": {
"default_icon": {
"16": "icon16.png",
"32": "icon32.png"
},
"default_popup": "popup.html",
"default_title": "Check to see if our code is on this page"
},
"content_scripts": [{
"matches": ["<all_urls>"],
"js": ["content.js"],
"run_at": "document_end"
} ]
}
This manifest specifies popup.html as our default page… That HTML file contains the markup of the popup that will display when our Chrome Extension is clicked. Note: this page cannot contain any JavaScript, only links to separate .js files. (CSS is allowed, so we’ll just use inline CSS to keep it simple).
<!doctype html>
<html>
<head>
<title>Tag Assistant</title>
<script src="popup.js"></script>
</head>
<body style="background-color:#0F0;width:160px;height:90px;">
<div id="status">
<button id="getResults">Get Results</button>
<h4 id="results"></h4>
</div>
</body>
</html>
//Wire up event event handlers
document.addEventListener("DOMContentLoaded", function(event) {
var resultsButton = document.getElementById("getResults");
resultsButton.onclick = getResults();
});
function getResults(){ alert('Hello World') }
We’re going to create a Chrome Extension that checks to see if a certain script exists on the current active page. But first, let’s just deploy an Extension locally that displays a “Hello World” alert as a sanity check that we have a basic valid Extension.
Open a Chrome browser, and go to chrome:\\extensions. (Make sure “Developer mode” in the upper right is turned on). Click Load Unpacked and navigate to the folder containing our files in the local file system. That’s it!… You should now see a new extension in the extension bar.
Pretty easy right? We have a functional Chrome extension with only about 5 minutes effort.
But right now, our code only operates within popup.html. Lets look at what it takes to access, say, the currently active tab.
In order to do this, we’ll need to find the currently active tab using chrome.tabs.query
specifying the active tab:
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
//...
});
After we get a handle to that tab we want to then send a message to that document specifying the function to invoke, and process the results.
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
chrome.tabs.sendMessage(tabs[0].id, { action: "checkForWord" }, function (response) {
showResults(response.results);
});
});
So now here’s the complete code for popup.js:
document.addEventListener("DOMContentLoaded", function(event) {
var resultsButton = document.getElementById("getResults");
resultsButton.onclick = getResults();
});
function getResults(){
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
chrome.tabs.sendMessage(tabs[0].id, { action: "checkForWord" }, function (response) {
showResults(response.results);
});
});
}
function showResults(results) {
var resultsElement = document.getElementById("results");
resultsElement.innerText = results ? "This page uses jQuery" : "This page does NOT use jQuery";
}
But we’re looking for a function called checkForWord
on an external webpage we don’t own, how do we inject it? That’s where content scripts come in. In our manifest.json file we’ll need to add a content_scripts
block:
"content_scripts": [{
"matches": ["<all_urls>"],
"js": ["content.js"],
"run_at": "document_end"
}]
Now, we just need to add a content.js file to our project that operates on the external page, and returns the information we need.
// listen for checkForWord request, call getTags which includes callback to sendResponse
chrome.runtime.onMessage.addListener(
function (request, sender, sendResponse) {
if (request.action === "checkForWord") {
checkForWord(request, sender, sendResponse);
// this is required to use sendResponse asynchronously
return true;
}
}
);
//Returns the index of the first instance of the desired word on the page.
function checkForWord(request, sender, sendResponse){
var scripts = document.getElementsByTagName("script");
for (var i=0;i<scripts.length;i++) {
if (scripts[i].src.toLowerCase().indexOf("jquery")>-1){
return sendResponse(true);
}
}
return sendResponse(false);
}
So now we have a fully functioning Chrome extension that determines whether or not jQuery exists on the page. Let’s try it out and see if it works.
Should you need to do any debugging in Chrome Developer Tools, you can right-click the popup window and select Inspect just like any other web page.
This will bring up the Dev Tools allowing you to step through popup.js. (You can also manually reload the Extension code by entering location.reload()
in the console, to avoid constantly re-opening the extension and Dev Tools).
Stepping through the content.js file is a little different - remember, we injected into the actual web page itself. You can open an instance of Chrome Dev Tools from the page itself, but you won’t see our content.js in the usual place, under Sources. The Page tab is the default sub-tab under sources, but if you look to the right of it, there’s a Content Scripts tab. That’s where we can see our content.js file if you expand the Top element in the tree, then expand our Code Checker node.
One last note about Content Scripts is that they run in the “Isolated World” mode used by Chrome Extensions, meaning they can access the DOM of web pages within tabs, but don’t have access to any JavaScript objects that may exist on that page.
So that’s a very simple Chrome Extension in a nutshell. Go explore the many other features - It’s a great, unique tool for your tool belt!