Building a chrome extension to search bookmarks

Having moved to use Rider for .NET development, I have found Jetbrain’s trademark feature “Search Everything” to be very handy.

Jetbrains’s Search Everything feature in Rider.

I thought to myself, how cool would it be if something like this existed for chrome to search through all bookmarks/history or even downloads. Since I had some past experiences with building chrome extensions, I decided I would give it a try.

Extensionizr — Start a chrome extension in 15 seconds!

While searching for some boilerplate code, to begin with, I stumbled across this tool — Extensionizr and boy it was impressive!

  1. Extension Type — Page action or Browser action. Page action should be used when your extension is supposed to be used on a specific page or a set of pages & browser action is to be used if your extension is supposed to work on any website. We want our extension to work from any website so I chose Browser action.
  2. Background Page — I selected background.js, as we will need to read bookmarks in chrome, something which is only allowed in background.js (which I learned the hard way). chrome.bookmarks.getTree returns a list of bookmarks with title, URL and a bunch of other information.
  3. Content Script — This is the heart of our application, here we opted to inject both JS & CSS, these are scripts that would be injected into each page using which would show our bookmark search popup.
  4. URL Permissions — Leave empty
  5. Permissions — Only bookmarks


Now that you have your base ready, we can add our business logic in inject.js.

Event Listeners

There are a couple of events that we would want to listen and act on. They are

  1. ATL + B — Our shortcut to fire up the bookmark search popup.
  2. Escape — To close the bookmark search popup
  3. Enter — To select a search bookmark and redirect to that page.

(KeyCode.Info is a useful site to check and set up a more complex shortcut.)

const addEventListeners = function() {
document.addEventListener("keyup", function(e) {
if (e.code === "KeyB" && e.altKey) {
// Show the bookmark search window
if (e.code === "Escape") {
// Hide the bookmark search window
if (e.code === "NumpadEnter" || e.code === "Enter") {
// Redirect user to the selected url

Background Scripts vs Content Scripts

Background page/script in Chrome is something that runs in the background and can access ALL chrome APIs and also maintain state your app etc, it, however, cannot access or modify the content of any pages.

To do that, you have to use Content scripts, but Content scripts can only access a small subset of the chrome APIs.

In my case, I want to access the chrome.bookmarks API which only Background Script has access to and show the search bookmark popup which only Content Script has access to, hence I have to use both as shown in the following example —

// IN inject.js i.e CONTENT SCRIPT
const searchBookmarks = function(searchTerm) {
action: "get-bookmarks"
}, function(
) {
// ...
// IN background.js i.e BACKGROUND SCRIPT
chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
if (request.action === "get-bookmarks") {
chrome.bookmarks.getTree(function(tree) {
bookmarks: flatennedBookmarks

Search Logic

For the first version, the search logic is very straight forward. For every search term entered, I do indexOf(searchTerm)on every bookmark’s URL and title, if its found I return that bookmark as results. In future I hope to add more advanced logic for searching bookmarks.

if (
bookmark.url.indexOf(searchTerm) !== -1 ||
bookmark.title.indexOf(searchTerm) !== -1
) {
// return as part of result.

And that is more or less the core logic I have for the bookmark search, if you are interested you can fork and play around here —

Publishing extension to Chrome Store

The last step would be to publish this extension on the Chrome store so that other people can easily download & use this extension. To publish, you need to go to the Chrome Developer Dashboard, log in with your developer account and click the “Add New Item” button and follow the steps shown by the wizard. (It is super straight forward.)

In our case we are requesting a very broad permission scope i.e `<all_urls>` vs running the extension on few specific URLs, in such cases, Google would do a more in-depth review of your extension, which would typically take a week or more.

Extension got published after 6 days.

Download & Use 🙂

The extension can be downloaded from the chrome store by searching for this name — “Chrome Bookmark Spotlight Search” or simply click the link below. Cheers!