Google Chrome is an extensively used browser and is quite popular among developer too. A part of Chrome’s appeal is owed to its excellent extensions. Its not really hard to write simple extension for added convenience.
I am a Ruby on Rails developer and spend quite good amount of time using Google Chrome for development and testing Rails applications. I prefer some background music while working, it helps me cut out out the crap and concentrate better on my work.
Youtube is excellent music service for me. With youtube autoplay enabled, the game becomes even simpler.
Only problem now is, when I have to pause music I have to switch to youtube tab and then hit the pause button. And same when I want resume it. This is a pain.
Solution: Build a chrome extension to play/pause youtube without having to switch tabs.
All it needs is a little javascript, html and may be some css if you want things to be a little more pretty. Since we won’t do any user-interface here, we don’t need to think html/css.
How it Works ?
Extensions allow you to add functionality to Chrome without diving deeply into native code. You can create new extensions for Chrome with those core technologies that you're already familiar with from web development: HTML, CSS, and JavaScript.
We’ll do this by implementing a UI element Chrome calls browser action, which allows us to place a clickable icon right next to Chrome’s Omnibox for easy access. Clicking that icon will play/pause the youtube video irrespective of the current active tab.
Lets get started…
Every chrome extension needs to have a file named manifest.json
in extension root directory. Lets create one.
{ | |
"manifest_version": 2, | |
"name": "YTPP", | |
"short_name": "YTPP", | |
"version": "0.1", | |
"description": "YTPP: YouTube Play/Pause without switching tabs", | |
"icons": {"128": "icon.png", "48": "icon_48.png", "16": "icon_16.png" }, | |
"author": {"name": "spidergears", "twitter_handle": "spider_gears", "github": "http://github.com/spidergears"}, | |
"browser_action": { "default_icon": "icon.png", "default_title": "YTPP"}, | |
"permissions": [ | |
"tabs" | |
], | |
"background": { "scripts": ["ytpp_background_script.js"]}, | |
"content_scripts": [ {"matches": ["http://www.youtube.com/*", "https://www.youtube.com/*"%5D, "js": ["ytpp_content_script.js"]} ] | |
} |
manifest_version:2
We are using Chrome Extension menifest specification version 2.
name:YTPP
Name for extension
version:0.1
Release version number. We need to increment this with every future release.
description:"YTPP: YouTube Play/Pause without switching tabs"
Short description for out extension.
icons: {"128": "icon.png", "48": "icon_48.png", "16": "icon_16.png"}
Icon files for different sizes.
author: {"name": "spidergears", "twitter_handle": "spider_gears", "github": "http://github.com/spidergears"}
Author Info
browser_action: { "default_icon": "icon.png", "default_title": "YTPP"}
Specifications for browser action.
"permissions": ["tabs"]
List of browser permissions extension needs to be functional.
"background": {"scripts": ["ytpp_background_script.js"]}
Register javascript to be run background. Will call code from this script on click of the browser action button.
"content_scripts": [{"matches": ["http://www.youtube.com/*", "https://www.youtube.com/*"], "js": ["ytpp_content_script.js"]}]
Register javascript to be inject into page content. matches keys helps specify on which all websites will the script be injected.
We have manifest file ready. Lets bring in our content and background scripts.
Background Script
Background scripts are a part of background page that runs in the extension process. Background page exists for the lifetime of the extension, and only one instance of it at a time is active. (Exception: if your extension uses incognito “split” mode, a second instance is created for incognito windows.)
In a typical extension with a background page, the UI — browser action
button in our case is implemented by dumb views. When the view needs some state, it requests the state from the background page. When the background page notices a state change, the background page tells the views to update.
Now we want to play/pause youtube media when `browser action` button is clicked.
To accomplish this, we attach a click listener to our `action button` . On button click we loop through all open tabs and check if they are tabs running youtube. For all tabs running youtube, we send a message to our injected script. The inject script, on receipt of message will actually take action to play/pause youtube media.
chrome.browserAction.onClicked.addListener(function(tab) { | |
chrome.tabs.query({}, function(tabs){ | |
for (var i=0; i < tabs.length; i++) { | |
if (/https?:\/\/www\.youtube\.com/.test(tabs[i].url)) { | |
chrome.tabs.sendMessage(tabs[i].id, {action: "toggle_playback"}, function(response) {}); | |
} | |
} | |
}) | |
}); |
Content Script
Content scripts are JavaScript files that run in the context of web pages. By using the standard Document Object Model (DOM), they can read details of the web pages the browser visits, or make changes to them.
Here are some examples of what content scripts can do:
- Find unlinked URLs in web pages and convert them into hyperlinks
- Increase the font size to make text more legible
- Find and process microformat data in the DOM
However, content scripts have some limitations. They cannot:
- Use chrome.* APIs, with the exception of:
- extension ( getURL , inIncognitoContext , lastError , onRequest ,sendRequest )
- i18n
- runtime ( connect , getManifest , getURL , id , onConnect , onMessage , sendMessage )
- storage
- Use variables or functions defined by their extension’s pages
- Use variables or functions defined by web pages or by other content scripts
These limitations aren’t as bad as they sound. Content scripts can indirectly use the chrome.* APIs, get access to extension data, and request extension actions by exchanging messages with their parent extension. Content scripts can also make cross-site XMLHttpRequests to the same sites as their parent extensions, and they can communicate with web pages using the shared DOM.
Let’s setup our content script that will be injected into the page. Our script will listen for a message from our browser action button. On message receipt it will grab the youtube play/pause button and click it to toggle media playback.
chrome.extension.onMessage.addListener(function(message, sender, sendResponse) { | |
if(message.action == "toggle_playback"){ | |
play_pause_button = document.getElementsByClassName('ytp-play-button ytp-button')[0] | |
if(play_pause_button){ | |
play_pause_button.click(); | |
} | |
} | |
}); |
Easy!!!
Full source code is available in Github Repository.
Extension is published here.