Sunday, August 28, 2016

Writing a Chrome Extension - My First Attempt

I decided that I want to learn how to write an Extension for Chrome that will hopefully block those annoying modal dialogs. There are plenty of popup blockers that block the "traditional" new window, but this is trickier.

What is a modal dialog and how do they work?


A modal dialog or modal popup is nothing more than a chunk of HTML that starts out as "hidden", but then is shown - usually when it's visible, access to the page is disabled. Many times, the page is grayed out. The end result is that the user has to take some action to close the dialog, at a minimum, the user needs to click a close button. Sometimes the user will need to sign up for something. Whatever, it's annoying.

My Extension


So, I (we) are going to learn, from scratch, how to create a plugin. My design is sketchy right now, but I'm envisioning that the extension will:

  1. When a user is presented with a modal dialog, (s)he can activate the plugin, click on the popup and add it to a list.
  2. The extension will save the page URL and the web component that is the offending popup. 
  3. The app will save this information to localStorage
  4. Next time the user navigates to a saved URL, the app will find the component and (what should I do, delete it? I could set up a MutationObserver which will listen for the element's change in hidden status and change it to hidden again before it can show itself. ).
  5. I *could* also create an option to disable all iframes.
  6. I could also implement some pre-existing blockers for popular sites that have popups, for example, Youtube.  
My thoughts on this design: 
  1. This extension will only "remember" settings for each browser. I could maybe (in V2) add an export/import feature.
  2. User must have localStorage enabled. 
  3. A concern with localStorage is DOM blocking because the API is synchronous. I'm not worried about this because the write operation is done when the user clicks off of a page. The read is a little trickier. I could read the data into memory asynchronously, but seriously, we are talking about, at most, 3 items per page.

Let's Start!


Since this is a relatively simple project, you can use pretty much any text editor, well except for the icon. I'm using VS Code from Microsoft. It's free and lightweight. It understands HTML, Javascript, JSON, etc. 

I created a branch in GitHub for this step. Mustering all my creativity, I decided to call this branch "Step-1".  Go ahead and download it now.

Here are a few things about extensions:
  1. The icon must be a PNG. 
  2. The manifest_version must be 2.
  3. You cannot use CDNs to reference tools like jQuery. You need to download a copy.
  4. No JavaScript can exist in an html file. (This is good practice anyway.)
manifest.json file:
1:  {  
2:   "manifest_version": 2,  
3:   "name": "Rich Modal Dialog Blocker",  
4:   "version": "0.1.0",  
5:   "description": "Rich Modal Dialog Blocker",  
6:   "browser_action": {  
7:    "default_icon" : "rmb.png",  
8:    "default_popup": "main.html"  
9:   },  
10:   "permissions": [  
11:      "tabs",  
12:      "notifications",  
13:      "http://*/",  
14:      "https://*/"  
15:    ]  
16:  }  

To create an extension, open Chrome and navigate to chrome://extensions/. Or click the top right menu | more tools | extensions. Check the checkbox that says Developer Mode. This lets you upload extension code from your machine.  Click the "Lost Unpacked Extension" button, navigate to your folder where the manifest.json exists and OK. If the planets aligned, then you should see a new extension. Look in the upper right of the browser and you should see my beautiful icon. (OK, I'm really not an artist.)

This is a Hello, World level project at this point. Very simple. While it's certainly not required, I included jquery2.2.4.js because I really like how jQuery makes JavaScript simpler. Right now, we have 5 code files and a README.md.

The manifest is straightforward right now.  Main.html (noted in the browser_action | default_popup item) is the popup page we see when we click on the extension's icon. The content.js file just has some simple test code. Right now, all it does is change the inner html of the h2#heading element to "After click". 

If you decide to make some modifications to test it, hit ctrl-r after saving and the extension will refresh. There's also a little Reload (ctrl-r) link on the extension page. It's a wonderful world when we have choices!

If you want to play with this a bit, go ahead. Otherwise, let's do something more interesting - let's modify the html of an active page. Stand by for Part 2.