Using Chrome's API, you can do a lot of things in your extension. One of them is registering a keyword in Chrome's address bar, also knows as the Omnibox, to handle the user's input when the user uses the keyword.

In this tutorial, we'll go over how to register a keyword with Chrome's address bar or Omnibox in your extension to handle the user's input. The extension we're creating will register the keyword color, then when the user uses this keyword in the Omnibox, they can enter a hex color of 6 characters. Once the user enters the hex, the extension will use COLOURlovers' API to get information about the color and give the user the RGB equivalent of the color.

It should be noted that this tutorial will create a manifest V2 extension instead of V3. This is due to an error that occurs with the Omnibox API in manifest V3 at the time of writing this article.

You can find the full code of the extension in this article in this GitHub repository.

Create the Extension

We'll first create the extension. First, create the directory that will hold the extension. Then, inside the directory, create manifest.json with the following content:

{
    "name": "hex-to-rgb",
    "description": "Convert Hexadecimal colors to RGB right from Chrome's Omnibox",
    "version": "0.0.1",
    "manifest_version": 2,
    "icons": {
        "16": "images/icon16.png",
        "32": "images/icon32.png",
        "48": "images/icon48.png",
        "128": "images/icon128.png"
    }
}

Note that for the icons I'm using an icon by Thalita Torres on Iconscout. Make sure to download it either from the website or from the GitHub repository and place them just like detailed in the manifest.json.

Next, open Chrome and go to chrome://extensions. Then, enable Developer Mode from the top right if it's not enabled. After that, click on Load Unpacked and choose the directory that you just created for the extension. You should see the extension after that in the list of extensions.

Register Omnibox Keyword

To register a keyword in your extension, you'll need to add a new key omnibox in your manifest.json. The value of omnibox is an object with the key keyword. In our extension, we'll use the keyword color. Add the following in your manifest.json:

"omnibox": {
	"keyword": "color"
}

Next, we'll need to add a background script that will listen to when the user enters the keyword and then handle the user's input. Add the following in your manifest.json to add a background script:

"background": {
    "persistent": false,
	"scripts": ["background.js"]
}

For now, create an empty file background.js in the root of the directory.

Then, go to chrome://extensions again and click on the refresh button for your extension. You should see a new background page registered.

Let's test out the keyword we just added. Open a new tab, then enter in the address bar (the Omnibox) color. You should see a suggestion for hex-to-rgb which is the extension we just created.

If you press TAB, you'll see that the extension's name is now added on the left in the Omnibox with the extension's icon. This means that now the extension will start receiving the input being entered. As we still haven't added listeners to handle the user's input, nothing will happen at the moment if you enter anything.

Add a Default Suggestion

When using the Omnibox API, you can specify a default suggestion that will appear regardless of what the user enters. To do that, you can use the method chrome.omnibox.setDefaultSuggestion. This method accepts an object with one property description.

The description property accepts XML styling. This means you can use XML tags to apply minimal styling to the suggestion you're showing to the user. These tags are:

  1. <url>: shows the text inside it styled as a link.
  2. <match>: shows the text inside it highlighted.
  3. <dim>: shows the text inside it dimmed.

It should be noted that you can also nest the XML tags. For example, you can make a URL also highlighted.

At the beginning of our background script, we'll add a default suggestion that will let the user know what they need to enter to get a result. Add the following at the beginning of background.js:

chrome.omnibox.setDefaultSuggestion({
    description: 'Enter a hex code of 6 characters to convert to RGB (for example, <match>ffffff</match>)'
});

Notice that in the description, we've used the XML tag <match>ffffff</match>. This means that the suggestion ffffff will be highlighted.

Let's test it. First, refresh the extension from chrome://extensions like we did before. Then, type color in a new tab and hit TAB. Try entering a character and you'll see the suggestion we just defined in background.js. Note that the default suggestion does not appear until at least one character is entered.

Handle Input

In this section, we'll handle the input the user enters after entering the keyword. To do that, we'll add an event listener to the event chrome.omnibox.onInputChanged. The listener will receive 2 parameters, text which is the text the user entered, and suggest which is a callback function we should use to send our suggestions that we want to show the user back to Chrome. This event is triggered every time the user enters a character.

Add the following to background.js:

chrome.omnibox.onInputChanged.addListener((text, suggest) => {
    //check that the length of the text is 6 characters
    if (text.length !== 6) {
        suggest([]);
        return;
    }
    
    //TODO send the text to the API
});

In our listener, for now, we're just checking if the text's length is not 6, then we're calling the suggest callback passing it an empty array.

Next, we'll send a request to the COLOURlovers API and retrieve the color's information. But before we do that, we need to add the API's URL in the permissions array in manifest.json so that requests to the API will be allowed. Add the following to manifest.json:

"permissions": [
   "http://www.colourlovers.com/*"
 ]

Back to our background script, we'll send a request to the endpoint http://www.colourlovers.com/api/color/ using the Fetch API. This endpoint accepts the color as a parameter, then returns an array. The array is either empty if the color is not found (for example, if it's an invalid color) or an array that will hold an object with details about the color. For example, try opening the URL http://www.colourlovers.com/api/color/ffffff?format=json in your browser and see how the response will look like.

Add the following to your background script inside the listener:

//send text to API
fetch('http://www.colourlovers.com/api/color/' + text + '?format=json')
    .then((response) => response.json())
    .then((data) => {
    	if (!data.length) {
            //no color was found
            suggest([]);
        } else {
            //TODO send suggestion when color exists
        }
})

In case no color was found, we're sending back an empty array to the suggest callback. We'll need to handle the case that color was found next and how the suggestion should be sent.

The suggestion object has 3 properties:

  1. content: Holds the text that will be placed inside the Omnibox when the user points at the suggestion.
  2. deletable: Whether the user can delete the suggestion from the suggestions history. This property is optional.
  3. description: similar to the description property we used in setDefaultSuggestion, this will be the text that the user will see in the list of suggestions. It can be styled using the XML tags just as we mentioned in the previous section.

When a color is received, we'll set the content inside the Omnibox to be the RGB value and the URL to the color in case the user wants to see additional information. We'll set the description to the color's name, the hex code, and the URL to see more information.

Add the following code in place of the TODO we added in the previous code block:

suggest([
    {
        content: `${data[0].rgb.red}, ${data[0].rgb.green}, ${data[0].rgb.blue} url: ${data[0].url}`,
        deletable: true,
        description: `Color name: ${data[0].title}, hex: <match>${data[0].hex}</match>, more information: <url>${data[0].url}</url> `
    }
])

Our code to convert the hex to RGB is done. Again, refresh the extension from chrome://extensions, open a new tab, type color in the Omnibox, and hit TAB. Then, enter a hex color. For example, enter f5f5f5. You should see a new suggestion below. Try pointing at the suggestion using the keyboard up and down arrows, and you'll see that the content of the Omnibox has changed to the text we set in content.

Handle Choosing Suggestion

The last event we need to handle is when the user selects the suggestion either by clicking on it or hitting enter. This event is chrome.omnibox.onInputEntered. The listener to this event receives two parameters: the text which is the text inside the Omnibox, and OnInputEnteredDisposition, which suggests if the new URL should be opened (if that's the action to be performed by the extension) in the currentTab, newForegroundTab or newBackgroundTab.

What we'll do is extract the URL from the text, then if OnInputEnteredDisposition is currentTab, we'll replace the URL of the current tab with the URL extracted. Else, we'll open a new tab with the URL.

In background.js add the following:

chrome.omnibox.onInputEntered.addListener((text, OnInputEnteredDisposition) => {
    const prefixIndex = text.indexOf('url: ');
    if (prefixIndex !== -1) {
        const url = text.substring(prefixIndex + 'url: '.length)
        console.log(url);
        if (OnInputEnteredDisposition === 'currentTab') {
            chrome.tabs.create({url});
        } else {
            chrome.tabs.update({url});
        }
    }
});

As explained earlier, we're extracting the URL from text based on the format we wrote in content. Then, we're opening the URL based on the value of OnInputEnteredDisposition.

Let's test it out. Again, refresh the extension from chrome://extensions, open a new tab, type color in the Omnibox, and hit TAB. Then, enter a hex color. For example, enter f5f5f5. Click on the suggestion shown for the color, or point at it with the up and down arrows on your keyboard and hit enter. You'll be taken to the page in COLOURlovers with the information about the color.

Conclusion

Using Chrome's Omnibox API, you can add functionalities to your extension to make it easier for your user to find something or perform certain tasks. Make sure to check out the full API reference to know more about what you can do with this API.