To follow this tutorial you'll need to have learned the basics of jpm
.
To modify the page hosted by a particular tab, load one or more content scripts into it using attach()
method of tab object. The job of these scripts is to interact with web content.
Here's a simple example:
var button = require("sdk/ui/button/action").ActionButton({ id: "style-tab", label: "Style Tab", icon: "./icon-16.png", onClick: function() { require("sdk/tabs").activeTab.attach({ contentScript: 'document.body.style.border = "5px solid red";' }); } });
To run this example, save an icon file named "icon-16.png" in add-on's "data" directory. You could download this icon: .
This add-on creates a button with Mozilla favicon as an icon. It has a click handler which fetches the active tab and loads a script into the page hosted by the active tab. The script is specified using the contentScript
option, and just draws a red border around the page.
Then open any web page in the browser window, and click the button . You should see a red border appear around the page, like this:
Keeping Content Scripts in a Separate File
In the example above, we've passed in content script as a string.
Unless script is extremely simple, maintain the script as a separate file in add-on's data
directory. This makes the code easier to maintain, debug, and review. To do this, provide option contentScriptFile
not contentScript
, whose value is a URL pointing to one or more content script files.
For example, if we save the script above under the add-on's data
directory in a file called my-script.js
:
var self = require("sdk/self"); var button = require("sdk/ui/button/action").ActionButton({ id: "style-tab", label: "Style Tab", icon: "./icon-16.png", onClick: function() { require("sdk/tabs").activeTab.attach({ contentScriptFile: self.data.url("my-script.js") }); } });
You can load more than one script, and the scripts can interact directly with each other. So you can load jQuery, and then your content script can use that.
Loading several content script files
The data assigned to contentScriptFile
can be a vector. Scripts will be loaded in the same order as the vector.
In the following example, we are loading two scripts, first.js
& second.js
. Both scripts will be executed in the same context, so everything publicly defined in first.js
will be accessible from second.js
.
// index.js var self = require("sdk/self"); var tabs = require("sdk/tabs"); require("sdk/ui/button/action").ActionButton({ id: "load-several", label: "load several scripts", icon: "./icon-16.png", onClick: function () { tabs.activeTab.attach({ contentScriptFile: [self.data.url('first.js'), self.data.url('second.js')] }); } });
Communicating With the Content Scripts
Your add-on script and content scripts can't directly access each other's variables or call each other's functions, but they can send each other messages.
To send a message from one side to the other, sender calls port.emit()
and receiver listens using port.on()
.
- In the content script,
port
is a property of the globalself
object. - In the add-on script,
tab.attach()
returns a worker object containing theport
property you use to send messages to the content script.
Let's rewrite the example above to pass a message from the add-on to the content script.
The content script now needs to look like this:
// "self" is a global object in content scripts // Listen for a "drawBorder" self.port.on("drawBorder", function(color) { document.body.style.border = "5px solid " + color; });
In the add-on script, we'll send the content script a "drawBorder" message using the object returned from attach()
:
var self = require("sdk/self"); var tabs = require("sdk/tabs"); var button = require("sdk/ui/button/action").ActionButton({ id: "style-tab", label: "Style Tab", icon: "./icon-16.png", onClick: function() { var worker = tabs.activeTab.attach({ contentScriptFile: self.data.url("my-script.js") }); worker.port.emit("drawBorder", "red"); } });
The drawBorder
message isn't a built-in message, it's one that this add-on defines in the port.emit()
call.
Injecting CSS
Unlike the page-mod
API, tab.attach()
doesn't enable you to inject CSS directly into a page.
To modify the style of a page, you have to use JavaScript, as in the example above.
Learning More
To learn more about working with tabs in the SDK, see the Open a Web Page tutorial, the List Open Tabs tutorial, and the tabs
API reference.
To learn more about content scripts, see the content scripts guide.