POSTS

Guide to Developing Chrome Context Menu Applications Part 2

Blog

Meta-Post

This post is really a meta-post. Here I’m going to document how I went about educating myself on a Google API. If you’re a seasoned hand at picking up API docs and making a product out of it, you might want to skip this post and move to the next part.

Getting Underway

Our starting point for documentation is the Chrome Extensions page. It serves as a table of contents for us and prompts us to first visit their tutorial page.

The first introduced type of user interface to an extension described is the browser action which: “…[allows] us to place a clickable icon right next to Chrome’s Omnibox for easy access.”

This is not what we want.

Nevertheless, let’s scan the rest of the doc to see if we can learn some fundamentals of all Extensions.

  • One of the critical files is the manifest.json which merits its own page.
    • The manifest defines permissions that the extension requires
    • Specific APIs are unlocked by the manifest declaring a dependency on that API universe
    • Two example permissions are activeTab and storage. The links to these permissions take you to the API documentation for each of these objects. You thusly can invoke methods like StorageArea.get() or chrome.pageAction.setTitle({tabId: int, string: "newTitle"}).

There are a few other interesting bits about browser_action dependencies, but those don’t concern us. Let’s move on.

We know a bit more about the general design of extensions, but we don’t want to make a browser action. We’re looking for a sub-species of extension that looks more like a page-based something. Let’s move to the next doc, the overview.

Moving to the Overview

Let’s move to the overview. Under Extension UIs there are 3 options listed with screenshots:

  1. Browser Action
  2. Page Action & Content Script
  3. Popup

None of these look like something launched from a menu.

Now here’s where I have to take Google documentation to task. We see:

"Extensions (and Chrome Apps) can also present a UI in other ways, such as adding to the Chrome context menu, providing an options page, or using a content script that changes how pages look. See the Developer's Guide for a complete list of extension features, with links to implementation details for each one."

Source

Wow! OK, context menu, that sounds like what we want. Let’s follow the Developer’s Guide page. I’d expect that I should be able to search “context menu” in that page and find something.

A search for “context” yields…nothing. “Content script” which was provided as another option is present; “options page” which was also mentioned on the previous page is present. So, where’s the mention of context menu? This is clearly a documentation bug. Let’s go back a page and see if we can derive another path.

ASIDE: This irritates the heck out of me. Teaching materials have to introduce vocabulary cautiously and trace continuity assiduously. Otherwise it needlessly hampers reader. I have reported this as a content bug to Google.

Since we’ve already ruled out Browser Action and Popup’s screenshot suggests a pop-up from the Omnibox drop down, by process of elimination I’m going to explore “Page Action.”

We’re then introduced to the files that comprise all extensions:

  • “A manifest file”
  • “One or more HTML files (unless the extension is a theme)”

We’re then introduced to a “background page” strictly named background.html that:

  • Holds the main logic of the extension
  • Can be subdivided into persistent background pages or Event Pages (the latter being preferred)
  • Extension DOMs are accessible by each others’ pages
  • Multiple JavaScript files can be referenced from this background.html file for convenient packaging

OK, so it seems we want a background page that holds the logic for setting up the UI of our extension. I’m open to discovering otherwise later, but given the structure of the documentation, that’s my most likely avenue.

Content Scripts: A Good Idea

The next section lit up my brain with the “Eureka” recognition:

If your extension needs to interact with web pages, then it needs a content
script. A content script is some JavaScript that executes in the context of a
page that's been loaded into the browser. Think of a content script as part of
that loaded page, not as part of the extension it was packaged with (its parent
extension).

That sounds like what we want! Further:

Content scripts can read details of the web pages the browser visits, and
they can make changes to the pages.

OK, I most definitely want this for updating DOM with the canned response. This is very promising…but content scripts:

...cannot, however, modify the DOM of its parent extension's background
page.

OK, sadness. But there seems to be some sort of workaround:

Content scripts aren't completely cut off from their parent extensions. A
content script can exchange messages with its parent extension, as the arrows
in the following figure show. For example, a content script might send a
message whenever it finds an RSS feed in a browser page. Or a background page
might send a message asking a content script to change the appearance of its
browser page.

OK, so it also seems that we want a content script.

Resolving our Architectural Hypothesis

So, the architecture’s going to be complicated, but we want a page action (background.html) with content script(s). I scan the rest of the page and see that there’s nothing revelatory or relevant, so I’m going to hop into the depths of exploring Content Scripts.

Get Educated

The “Content Script” page is required reading for the rest of this tutorial.

If you’re following this as a tutorial, you should read that page (and don’t get hung up on fine details) and come back. I’ll wait.

Back? Great. The document provided:

  • Extensive discussion about the security model that involves message-passing
  • How to invoke code on the page (“page action”)
  • How to send data from the page to the code (via the “content script”)
  • The content script modifies the DOM (unprivileged)
  • The content script needs to send messages to some “robust” JavaScript code to do heavier lifting / access the chrome.* APIs..this “page action page” is the “privileged user,” an agent, a go-between — the background script!.

If you didn’t get those take-aways, re-read and come back.

Rough Sketch Architecture

Let’s make a battle plan:

  • Make the manifest compliant to support a…
  • background page that sets up the UI context menus and contains the canned responses and sends those responses to…
  • a content script that updates the DOM

In our next post we’ll actually implement this architecture.