<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Voldzilla</title>
    <link href="http://work.erikvold.com/atom.xml" rel="self" type="application/atom+xml" />
    <link href="http://work.erikvold.com" rel="alternate" type="text/html" />
    <id>http://work.erikvold.com</id>
    <updated>2013-05-16T14:03:12-07:00</updated>
    
        <entry>
            <title>Old School To Jetpack Part 2 - XUL Bashing</title>
            <author>
                <name>Erik Vold</name>
                <email>evold@mozilla.com</email>
            </author>
            <link href="http://work.erikvold.com/jetpack/2013/05/16/old-school-to-jetpack-xul.html" rel="alternate" type="text/html" />
            <updated>2013-05-16T00:00:00-07:00</updated>
            <id>http://work.erikvold.com/jetpack/2013/05/16/old-school-to-jetpack-xul</id>
            <content type="html">&lt;p&gt;In &lt;a href='http://work.erikvold.com/jetpack/2013/05/12/old-school-to-jetpack-retrofit.html'&gt;Old School to Jetpack Part 1&lt;/a&gt; I briefly mentioned that xul overlays are not supported with Jetpacks, so today I want to talk about how to convert old school XUL overlays.&lt;/p&gt;

&lt;p&gt;A typical overlay would look something like lke this &lt;code&gt;addon-browser-overlay.xul&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;
&amp;lt;overlay xmlns=&amp;quot;http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul&amp;quot;&amp;gt;
  &amp;lt;toolbar id=&amp;quot;addon-bar&amp;quot;&amp;gt;
    &amp;lt;textbox id=&amp;quot;test-status-bar-message&amp;quot; insertbefore=&amp;quot;addonbar-closebutton&amp;quot; value=&amp;quot;Hi!&amp;quot;&amp;gt;&amp;lt;/textbox&amp;gt;
  &amp;lt;/toolbar&amp;gt;
&amp;lt;/overlay&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This overlay, would then be associated to &lt;code&gt;browser.xul&lt;/code&gt; in the &lt;code&gt;chrome.manifest&lt;/code&gt; file with an entry like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;overlay    chrome://browser/content/browser.xul chrome://{add-on name here}/content/addon-browser-overlay.xul&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Finally, the overlay would produce this in Firefox&amp;#8217;s addon-bar:&lt;/p&gt;
&lt;img src='/images/xul-jplib-ss.png' alt='Screen Shot' /&gt;
&lt;p&gt;With Jetpacks however the latter step cannot be done, because these overlay entries are ignored for restartless add-ons. One could manually force the overlay with a call to &lt;a href='https://developer.mozilla.org/en-US/docs/DOM/document.loadOverlay'&gt;&lt;code&gt;document.loadOverlay&lt;/code&gt;&lt;/a&gt;, but there is no way to undo this, that is why overlay&amp;#8217;s are not supported for restartless add-ons at the moment.&lt;/p&gt;

&lt;p&gt;So what is needed here is a module that will add the desired XUL elements to the desired XUL documents.&lt;/p&gt;

&lt;p&gt;This is why I wrote a &lt;a href='https://github.com/erikvold/xul-jplib/'&gt;XUL package for Jetpack&lt;/a&gt;, it is very raw at the moment, and very simple, so you&amp;#8217;ve been warned!&lt;/p&gt;

&lt;h2 id='xul_package_for_jetpack'&gt;XUL Package for Jetpack&lt;/h2&gt;

&lt;h3 id='about'&gt;About&lt;/h3&gt;

&lt;p&gt;The &lt;a href='https://github.com/erikvold/xul-jplib/'&gt;source code can be found on github here&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id='pros'&gt;Pros&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Quick easy solution for coverting XUL overlays for use with Jetpacks&lt;/li&gt;

&lt;li&gt;Handles unloads&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id='cons'&gt;Cons&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Only works on Firefox (or other applications made with XUL)&lt;/li&gt;

&lt;li&gt;At the moment this package only works for adding xul to &lt;code&gt;browser.xul&lt;/code&gt; (although it won&amp;#8217;t be hard to extend)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id='alternatives'&gt;Alternatives&lt;/h3&gt;

&lt;p&gt;Before I go in to this module I want to take a moment to point out that there are many &lt;a href='https://github.com/mozilla/addon-sdk/wiki/Community-developed-modules'&gt;third party packages&lt;/a&gt; which handle most of the use cases that overlays for &lt;code&gt;browser.xul&lt;/code&gt; support; they don&amp;#8217;t cover everything though, like the example above, so this is why I wrote this general purpose package.&lt;/p&gt;

&lt;h3 id='usage'&gt;Usage&lt;/h3&gt;

&lt;p&gt;To implement the example above using this module, one would simply need to do the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;const { XUL, getXULById } = require(&amp;#39;xul/browser&amp;#39;);
getXULById(&amp;#39;addon-bar&amp;#39;).insertBefore(XUL(&amp;#39;textbox&amp;#39;, {
  id: &amp;#39;test-status-bar-message&amp;#39;,
  value: &amp;#39;Hi!&amp;#39;
}), &amp;#39;addonbar-closebutton&amp;#39;);&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And this code is restartless!&lt;/p&gt;</content>
        </entry>
    
        <entry>
            <title>Old School To Jetpack Part 1 - The Retrofit</title>
            <author>
                <name>Erik Vold</name>
                <email>evold@mozilla.com</email>
            </author>
            <link href="http://work.erikvold.com/jetpack/2013/05/12/old-school-to-jetpack-retrofit.html" rel="alternate" type="text/html" />
            <updated>2013-05-12T00:00:00-07:00</updated>
            <id>http://work.erikvold.com/jetpack/2013/05/12/old-school-to-jetpack-retrofit</id>
            <content type="html">&lt;p&gt;Old school add-ons were developed with a similar mindset, which is that creating new windows is ok, and using XUL this became an easy to-do common practice. The times have changed, and opening new windows is no longer considered acceptable practice, opening tabs is now the preferred user experience.&lt;/p&gt;

&lt;p&gt;Now, Firefox has a huge cast of popular, restart addled, old school mannered add-ons, which is a problem. So how do we retrofit these geezers?&lt;/p&gt;

&lt;p&gt;I see three parts that need to be addressed:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;New XUL windows (windows created by the add-on)&lt;/li&gt;

&lt;li&gt;XUL overlays (content added to windows created by Fx or another add-on)&lt;/li&gt;

&lt;li&gt;Back-end logic&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I plan to write more about all three topics later, because the real solutions require more words and work than the shortcuts will.&lt;/p&gt;

&lt;h2 id='shortcuts'&gt;Shortcuts&lt;/h2&gt;

&lt;h3 id='chromemanifest'&gt;Chrome.manifest&lt;/h3&gt;

&lt;p&gt;Because of &lt;a href='https://bugzilla.mozilla.org/show_bug.cgi?id=559306'&gt;Bug 559306&lt;/a&gt; we can now include the old school add-on&amp;#8217;s &lt;code&gt;chrome.manifest&lt;/code&gt; file in jetpacks. There are some limitations however, for more information on that see &lt;a href='https://developer.mozilla.org/en-US/docs/Extensions/Bootstrapped_extensions#chrome.manifest_in_bootstrapped_add-ons'&gt;this page on the chrome.manifest in restartless add-ons&lt;/a&gt;. For instance, overlays will not be regestered, resource uris, components, and more. One can register a chrome uri however, with a &lt;code&gt;skin&lt;/code&gt; and &lt;code&gt;locale&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This means that add-ons which implement XUL windows can continue to use them as a Jetpack.&lt;/p&gt;

&lt;p&gt;These windows should be redesigned however, but this is no longer a bar to entry, and the resdesign of these windows can be done in a separate step from the conversion to Jetpack.&lt;/p&gt;

&lt;p&gt;Also, remember that any windows open which are associated to an add-on should be closed when the add-on unloads, if you do not do this then your add-on will not pass a full review on &lt;a href='https://addons.mozilla.org'&gt;addons.mozilla.org&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id='browser_ui'&gt;Browser UI&lt;/h3&gt;

&lt;p&gt;Again, there are a few &lt;a href='https://github.com/mozilla/addon-sdk/wiki/Community-developed-modules'&gt;useful third party modules&lt;/a&gt; which handle most common use cases, and if they do not cover your use case then they should provide some direction how to implement them.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve got a module in mind that should help with converting overlays, it&amp;#8217;s a messy prototype right now though, so we&amp;#8217;ll see how that goes..&lt;/p&gt;

&lt;h3 id='components'&gt;Components&lt;/h3&gt;

&lt;p&gt;There are a few &lt;a href='https://github.com/mozilla/addon-sdk/wiki/Community-developed-modules'&gt;useful third party modules&lt;/a&gt; out already which handle things like registering &lt;a href='https://github.com/Gozala/jetpack-protocol'&gt;custom uris&lt;/a&gt; (this includes &lt;code&gt;about:&lt;/code&gt; uris, &lt;code&gt;resource:&lt;/code&gt; uris, and &lt;code&gt;whatever:&lt;/code&gt;), &lt;a href='https://github.com/erikvold/content-policy-jplib'&gt;content policies&lt;/a&gt;, and in many cases there are better alternatives. For instance I&amp;#8217;ve seen quite a few add-ons register components just in order to hear their &amp;#8216;startup&amp;#8217; event, this is no longer necessary, with a Jetpack you can simply call &lt;code&gt;require(&amp;#39;self&amp;#39;).loadReason&lt;/code&gt; in &lt;code&gt;main.js&lt;/code&gt;.&lt;/p&gt;</content>
        </entry>
    
        <entry>
            <title>Blocking Content With Jetpacks</title>
            <author>
                <name>Erik Vold</name>
                <email>evold@mozilla.com</email>
            </author>
            <link href="http://work.erikvold.com/jetpack/2013/05/11/content-policy-jetpack-module.html" rel="alternate" type="text/html" />
            <updated>2013-05-11T00:00:00-07:00</updated>
            <id>http://work.erikvold.com/jetpack/2013/05/11/content-policy-jetpack-module</id>
            <content type="html">&lt;p&gt;Many of the most popular add-ons have a common function, they block content. &lt;a href='https://addons.mozilla.org/firefox/addon/adblock-plus/'&gt;Adblock Plus&lt;/a&gt; blocks ads, &lt;a href='https://addons.mozilla.org/firefox/addon/noscript/'&gt;NoScript&lt;/a&gt; blocks scripts, and &lt;a href='https://addons.mozilla.org/firefox/addon/ghostery/'&gt;Ghostry&lt;/a&gt; blocks tracking software which uses images, scripts and other means to do their business.&lt;/p&gt;

&lt;p&gt;This is why I wrote a &lt;a href='https://github.com/erikvold/content-policy-jplib'&gt;content-policy module&lt;/a&gt; for Mozilla&amp;#8217;s Add-on SDK. The API is rough at the moment, and I plan to change that quite a bit. For the moment though we can take the &lt;a href='https://addons.mozilla.org/firefox/addon/no-google-analytics/'&gt;No Google Analytics&lt;/a&gt; add-on as an example &lt;a href='https://github.com/erikvold/no-ga'&gt;source here&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;lib/main.js&lt;/code&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;const { ContentPolicy } = require(&amp;#39;content-policy&amp;#39;);
const GA_REGEX = /(.*\.)?google-analytics\.com$/i;
const { URL } = require(&amp;#39;sdk/url&amp;#39;);

ContentPolicy({
  shouldLoad: function({ location }) {
    // if the hist is google-analytics.com then block it
    if (URL(location).host.match(GA_REGEX))
      return false; // returning false rejects the request before it starts
    return true; // returning true does not reject the request
  }
});&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I&amp;#8217;ll improve the match later, but you can see how easy that is, and I promise I&amp;#8217;ll make it easier.&lt;/p&gt;</content>
        </entry>
    
        <entry>
            <title>The Per-Tab Private Browsing Plan</title>
            <author>
                <name>Erik Vold</name>
                <email>evold@mozilla.com</email>
            </author>
            <link href="http://work.erikvold.com/jetpack/2013/03/06/per-tab-private-browsing.html" rel="alternate" type="text/html" />
            <updated>2013-03-06T00:00:00-08:00</updated>
            <id>http://work.erikvold.com/jetpack/2013/03/06/per-tab-private-browsing</id>
            <content type="html">&lt;p&gt;Will Bamberg wrote about &lt;a href='https://blog.mozilla.org/addons/2013/02/26/per-window-private-browsing-and-the-add-on-sdk/'&gt;Per-window private browsing and the Add-on SDK&lt;/a&gt; recently, and I wanted to follow up with a quick note about Per-tab private browsing on Fennec.&lt;/p&gt;

&lt;p&gt;The situation is almost identical to Firefox&amp;#8217;s, except that Fennec never had global private browsing implemented which is basically the same as having global browsing off, so the transition to per-tab private browsing is essentially the same as that for per-window private browsing.&lt;/p&gt;

&lt;p&gt;You will have to repack in order to support Firefox 20 for mobile (aka Fennec 20), and you will have to request &lt;code&gt;private-browsing&lt;/code&gt; permission (as Will outlines in his post) in order to be aware of private tabs. If you don&amp;#8217;t opt-in for &lt;code&gt;private-browsing&lt;/code&gt; permission, then you will not see private tabs in the &lt;code&gt;tabs&lt;/code&gt; module and you will not be able to add a &lt;code&gt;page-mod&lt;/code&gt; to private tabs for example. If you do request &lt;code&gt;private-browsing&lt;/code&gt; permission then you will need to check if the tabs that you handle are private like so:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;require(&amp;#39;sdk/private-browsing&amp;#39;).isPrivate(tab)  // returns true if the tab is private and false otherwise&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The code examples that Will provides are jsut as relevent to per-tab private browsing as the are to per-window private browsing, so give his post a read!!&lt;/p&gt;

&lt;p&gt;Also if you have &lt;code&gt;private-browsing&lt;/code&gt; permission, then you can open a private tab like so:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;require(&amp;#39;sdk/tabs&amp;#39;).open({
  url: &amp;quot;https://mozilla.org&amp;quot;,
  isPrivate: true
})&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you use the above example on Fennec, a new private tab is opened, if you use the example code on Firefox then the tab will be opened in a private window, which may not be the most recent active window.&lt;/p&gt;

&lt;p&gt;If you don&amp;#8217;t have &lt;code&gt;private-browsing&lt;/code&gt; permission, then using the &lt;code&gt;isPrivate&lt;/code&gt; flag when opening a tab or window, then it will be ignored.&lt;/p&gt;</content>
        </entry>
    
        <entry>
            <title>No Google Analytics For Firefox</title>
            <author>
                <name>Erik Vold</name>
                <email>evold@mozilla.com</email>
            </author>
            <link href="http://work.erikvold.com/addons/2013/02/16/no-google-analytics.html" rel="alternate" type="text/html" />
            <updated>2013-02-16T00:00:00-08:00</updated>
            <id>http://work.erikvold.com/addons/2013/02/16/no-google-analytics</id>
            <content type="html">&lt;p&gt;Sometime during the last weekend I managed to spend a night trying to use &lt;a href='https://developer.mozilla.org/docs/XPCOM_Interface_Reference/nsIContentPolicy'&gt;nsIContentPolicy&lt;/a&gt; (which allows one to observe network requests before they start and possibly reject/block them) in a jetpack for Firefox.&lt;/p&gt;

&lt;h2 id='no_google_analytics'&gt;NO Google Analytics&lt;/h2&gt;

&lt;p&gt;In a strange flash of inspiration I made &lt;a href='https://addons.mozilla.org/firefox/addon/no-google-analytics'&gt;NO Google Analytics&lt;/a&gt;, which is using nsIContentPolicy to block requests for the &lt;code&gt;ga.js&lt;/code&gt; javascript file that collects your information and stores it in cookies, and this add-on will block requests for Google Analytics &lt;code&gt;__utm.gif&lt;/code&gt; which is used to transport the tracking information to Google. Often this &lt;code&gt;__utm.gif&lt;/code&gt; image is referred to as &amp;#8220;the invisible gif&amp;#8221; because it is only 1 transparent pixel, and it can be used to track users even without &lt;code&gt;ga.js&lt;/code&gt; which many users of &lt;a href='https://addons.mozilla.org/firefox/addon/noscript/'&gt;NoScript&lt;/a&gt; already block thinking that does something, and &lt;a href='http://code.google.com/p/php-ga/'&gt;webdevs have long ago worked around&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href='https://github.com/erikvold/no-ga'&gt;The source code and issue tracker for this add-on is on github&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id='comparison_to_google_analytics_optout_addon'&gt;Comparison to Google Analytics Opt-out add-on&lt;/h3&gt;

&lt;p&gt;Google provides a Google Analytics Opt-out add-on, which they claim will do the following:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The add-on instructs the Google Analytics JavaScript not to send any information about the website visit to Google Analytics.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The problem with this is that their code is not open source, and it is not reviewed by anyone because Google doesn&amp;#8217;t want it to be. They just want you to trust them, so do you?&lt;/p&gt;

&lt;p&gt;Anyhow Google doesn&amp;#8217;t even claim to block anything, so webdevs can still work around this opt-out add-on so far as I can tell.&lt;/p&gt;

&lt;h1 id='thanks_alex_and_loic'&gt;Thanks Alex and Loic&lt;/h1&gt;

&lt;p&gt;I big thanks needs to go out to &lt;a href='http://blog.techno-barje.fr'&gt;Alex Poirot&lt;/a&gt; and &lt;a href='http://lduros.net'&gt;Loic Duros&lt;/a&gt;, their previous exploration using nsIContentPolicy meant I had to do very little to get this add-on working.&lt;/p&gt;

&lt;p&gt;On that note I&amp;#8217;ve started a &lt;code&gt;content-policy&lt;/code&gt; module to expand on the work Loic and Alex have done and make it easier to reuse, &lt;a href='https://github.com/erikvold/content-policy-jplib/blob/master/lib/content-policy.js'&gt;the module can be found on github as usual&lt;/a&gt;, and I will be blogging about it more after I write some tests and documentation for it.&lt;/p&gt;</content>
        </entry>
    
        <entry>
            <title>The Per-Window Private Browsing Plan</title>
            <author>
                <name>Erik Vold</name>
                <email>evold@mozilla.com</email>
            </author>
            <link href="http://work.erikvold.com/jetpack/2013/01/30/per-window-private-browsing.html" rel="alternate" type="text/html" />
            <updated>2013-01-30T00:00:00-08:00</updated>
            <id>http://work.erikvold.com/jetpack/2013/01/30/per-window-private-browsing</id>
            <content type="html">&lt;p&gt;Due to &lt;a href='https://blog.mozilla.org/futurereleases/2012/12/11/per-window-private-browsing-in-nightly/'&gt;Per-Window Private Browsing&lt;/a&gt; (&lt;a href='https://bugzilla.mozilla.org/show_bug.cgi?id=463027'&gt;Bug 463027&lt;/a&gt;) there will need to be substantial changes to the Add-on SDK.&lt;/p&gt;

&lt;p&gt;The Add-on SDK team is tasked with making it easy to make add-ons. One way we achieve this is by abstracting away the Gecko platform&amp;#8217;s complexity, and saving add-on developers from platform changes from one version of Firefox to the next, but this won&amp;#8217;t always be possible and per-window private browsing is one of those changes that we won&amp;#8217;t be able to abstract away to the point that upgrading an add-on that was based on version 1.13 or earlier to v1.14 would be possible.&lt;/p&gt;

&lt;p&gt;To put the change simply, before with global private browsing a add-on developer need only know if the mode was active or not and when that state changed, now with per-window private browsing none of that information is available because it no longer exists. With per-window private browsing a add-on developer will need to know if the information they are handling came from a private-browsing window and either ignore it, handle it sensitively, and possibly do some extra cleanup work for the sensitive data when the associated window is closed, or when the last private browsing window is closed. The best approach to take depends on the use case.&lt;/p&gt;

&lt;p&gt;For the Add-on SDK this means the &lt;a href='https://addons.mozilla.org/en-US/developers/docs/sdk/1.13/modules/sdk/private-browsing.html'&gt;private-browsing module&amp;#8217;s&lt;/a&gt; old events (&lt;code&gt;start&lt;/code&gt; and &lt;code&gt;stop&lt;/code&gt;), methods (&lt;code&gt;activate&lt;/code&gt; and &lt;code&gt;deactivate&lt;/code&gt;), and attribute (&lt;code&gt;isActive&lt;/code&gt;) won&amp;#8217;t do anything. The latter two will be around and simply throw depcrecation errors if one tries to use them. There will also be a new event &lt;code&gt;exited&lt;/code&gt; which will fire when the last private browsing window is closed, and a new method &lt;code&gt;isPrivate&lt;/code&gt; which one can pass a tab, window, page-mod worker instance, and perhaps some other argument types will need to be supported as well to make development life easier. For intance one could get the tab for a page-mod worker instance and call &lt;code&gt;isPrivate(worker.tab)&lt;/code&gt; instead of &lt;code&gt;isPrivate(worker)&lt;/code&gt; but the latter is clearly easier to understand.&lt;/p&gt;

&lt;p&gt;The big problem lies in the fact that we can&amp;#8217;t simply upgrade add-ons from the SDK v1.13 to v1.14 but we still don&amp;#8217;t want to be in a situation where developers are either forced to do a bunch of work to support the SDK v1.14 and Firefox 20+ in turn, or their add-on no longer works on the latest version of Firefox! So we&amp;#8217;ve decided that by default add-ons made with SDK will no longer work in private windows, and inorder to support private browsing windows a developer will have to include a &lt;code&gt;&amp;quot;private-browsing&amp;quot;: true&lt;/code&gt; flag in their add-on&amp;#8217;s &lt;code&gt;package.json&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;This way we still can upgrade add-ons, and give developers some time to support this new feature.&lt;/p&gt;

&lt;p&gt;Watch for these changes in our weekly beta releases!&lt;/p&gt;</content>
        </entry>
    
        <entry>
            <title>Per-Window Private Browsing for Add-ons</title>
            <author>
                <name>Erik Vold</name>
                <email>evold@mozilla.com</email>
            </author>
            <link href="http://work.erikvold.com/2013/01/18/per-window-private-browsing.html" rel="alternate" type="text/html" />
            <updated>2013-01-18T00:00:00-08:00</updated>
            <id>http://work.erikvold.com/2013/01/18/per-window-private-browsing</id>
            <content type="html">&lt;p&gt;&lt;a href='http://ehsanakhgari.org/blog/2012-11-30/per-window-private-browsing-ready-for-testing-now-2'&gt;Per-Window Private Browsing is coming&lt;/a&gt; &lt;a href='https://blog.mozilla.org/futurereleases/2012/12/11/per-window-private-browsing-in-nightly/'&gt;soon&lt;/a&gt; (&lt;a href='https://bugzilla.mozilla.org/show_bug.cgi?id=463027'&gt;Bug 463027&lt;/a&gt;), and for addon developers this is going to mean a lot of work.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m going to be writting about the work being done for the Addon SDK soon, but for now I wanted to write some notes down for old school developers, because I think the change is going to be a painful one for some of us. When I think about the changes that I&amp;#8217;m going to have to make to &lt;a href='http://scriptish.org/'&gt;Scriptish&lt;/a&gt; I get a bit queasy.&lt;/p&gt;

&lt;p&gt;First of all, the global private browsing service, &lt;a href='https://developer.mozilla.org/en-US/docs/XPCOM_Interface_Reference/nsIPrivateBrowsingService'&gt;nsIPrivateBrowsingService&lt;/a&gt;, is being deprecated, so a dummy service will still exist in it&amp;#8217;s place for a few versions of Firefox. This is mainly because I didn&amp;#8217;t see this change coming a long time ago when the SDK team would have needed to in order to correct older versions of the Add-on SDK (before they were released) so that they wouldn&amp;#8217;t break when &lt;code&gt;nsIPrivateBrowsingService&lt;/code&gt; is ripped out.. It turns out there are some important add-ons that are mainly used on Firefox nightly builds, and they all broke when &lt;code&gt;nsIPrivateBrowsingService&lt;/code&gt; was removed. So would any other add-on using &lt;code&gt;nsIPrivateBrowsingService&lt;/code&gt; too though of course.&lt;/p&gt;

&lt;p&gt;Alas, here we are with a dummy service, which means that add-ons developers have 3 options:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Raise their add-on&amp;#8217;s menVersion supported to Firefox 20, remove the old &lt;code&gt;nsIPrivateBrowsingService&lt;/code&gt; code and only &lt;a href='https://developer.mozilla.org/en-US/docs/Supporting_per-window_private_browsing'&gt;support per-window private browsing&lt;/a&gt;.&lt;/li&gt;

&lt;li&gt;Support both global private browsing and per-window private browisng via code forks by Firefox version.&lt;/li&gt;

&lt;li&gt;Support both global private browsing and per-window private browisng via feature detection.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The first two are easy to understand how to do so I won&amp;#8217;t bother explaining those, the latter I have a code snippet for:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;let pbService;
let PrivateBrowsingUtils;

// get the nsIPrivateBrowsingService if it exists
try {
	pbService = Cc[&amp;quot;@mozilla.org/privatebrowsing;1&amp;quot;].
	          getService(Ci.nsIPrivateBrowsingService);

	// a dummy service exists for the moment (Fx20 atleast), but will be removed eventually
	// ie: the service will exist, but it won&amp;#39;t do anything and the global private browing
	//     feature is not really active.  See Bug 818800 and Bug 826037
	if (!(&amp;#39;privateBrowsingEnabled&amp;#39; in pbService))
	  pbService = undefined;
} catch(e) { /* Private Browsing Service has been removed (Bug 818800) */ }

try {
	PrivateBrowsingUtils = Cu.import(&amp;#39;resource://gre/modules/PrivateBrowsingUtils.jsm&amp;#39;, {}).PrivateBrowsingUtils;
}
catch(e) { /* if this file DNE then an error will be thrown */ }

// checks that global private browsing is implemented
// if the global private browsing service dne here then it dne at all or it is a dummy
let isGlobalPBSupported = !!pbService;

// checks that per-window private browsing is implemented
// if the global pb service dne but the PrivateBrowsingUtils.jsm exists then assume
// is enabled.
let isWindowPBSupported = !isGlobalPBSupported &amp;amp;&amp;amp; !!PrivateBrowsingUtils;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The last two variables defined here namely &lt;code&gt;isGlobalPBSupported&lt;/code&gt; and &lt;code&gt;isWindowPBSupported&lt;/code&gt; will tell you what is supported.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m sure a lot of people will say option 1 or 2 is the way to go, but I have to update &lt;a href='http://scriptish.org'&gt;Scriptish&lt;/a&gt; soon and I know that for me option 3 is really the only option for the short term, long term I&amp;#8217;ll do option 1.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ll be writing about the changes that will be required for the Add-on SDK soon too.&lt;/p&gt;</content>
        </entry>
    
        <entry>
            <title>Floating Scrollbar Jetpack</title>
            <author>
                <name>Erik Vold</name>
                <email>evold@mozilla.com</email>
            </author>
            <link href="http://work.erikvold.com/2012/10/02/floating-scrollbar.html" rel="alternate" type="text/html" />
            <updated>2012-10-02T00:00:00-07:00</updated>
            <id>http://work.erikvold.com/2012/10/02/floating-scrollbar</id>
            <content type="html">&lt;p&gt;&lt;a href='http://paulrouget.com/e/floatingScrollbars/'&gt;Paul Rouget created a little hack to finally give us floating scrollbars in Firefox today&lt;/a&gt;, so it was easy to convert that into a Jetpack for all to enjoy!&lt;/p&gt;

&lt;p&gt;&lt;a href='https://addons.mozilla.org/firefox/addon/floaty-scrollbar/'&gt;Floaty Scrollbar for Firefox&lt;/a&gt;&lt;/p&gt;</content>
        </entry>
    
        <entry>
            <title>SU.12</title>
            <author>
                <name>Erik Vold</name>
                <email>evold@mozilla.com</email>
            </author>
            <link href="http://work.erikvold.com/status-update/2012/09/30/status-update.html" rel="alternate" type="text/html" />
            <updated>2012-09-30T00:00:00-07:00</updated>
            <id>http://work.erikvold.com/status-update/2012/09/30/status-update</id>
            <content type="html">&lt;h2 id='this_week'&gt;This Week&lt;/h2&gt;

&lt;h3 id='bugs'&gt;Bugs&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href='https://bugzilla.mozilla.org/show_bug.cgi?id=798090'&gt;bug 798090&lt;/a&gt; - Started work on this while reviewing &lt;a href='https://bugzilla.mozilla.org/show_bug.cgi?id=791577'&gt;Bug 791577&lt;/a&gt;. I&amp;#8217;m looking forward to completing this because it will allow me to get back to work on the &lt;code&gt;simple-prefs&lt;/code&gt; module. There have been a few feature requests piling up for that module which would be very nice to finally closed.&lt;/li&gt;

&lt;li&gt;&lt;a href='https://bugzilla.mozilla.org/show_bug.cgi?id=794310'&gt;bug 794310&lt;/a&gt; - Implement &lt;code&gt;contentType&lt;/code&gt; for tabs on Fennec&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id='reviews'&gt;Reviews&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href='https://bugzilla.mozilla.org/show_bug.cgi?id=791577'&gt;Bug 791577&lt;/a&gt; - Support &amp;#8220;test&amp;#8221; add-ons&lt;/li&gt;

&lt;li&gt;&lt;a href='https://bugzilla.mozilla.org/show_bug.cgi?id=788245'&gt;Bug 788245&lt;/a&gt; - Document &lt;code&gt;simple-prefs&lt;/code&gt; localization&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id='misc'&gt;Misc&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Setup Windows and Ubuntu VMs for testing.&lt;/li&gt;

&lt;li&gt;More work on Next add-on which basically works now but it needs some styling.&lt;/li&gt;

&lt;li&gt;Wrote a blog post &lt;a href='http://work.erikvold.com/jetpack/2012/09/24/windows-tabs-fennec.html'&gt;on the &lt;code&gt;windows&lt;/code&gt; and &lt;code&gt;tabs&lt;/code&gt; implementation for Fennec&lt;/a&gt;.&lt;/li&gt;

&lt;li&gt;Wrote an example add-on using the &lt;code&gt;tabs&lt;/code&gt; module for Fennec, which is called &lt;a href='https://addons.mozilla.org/en-US/firefox/addon/tab-usage-jetpack/'&gt;Tab Usage Stats&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content>
        </entry>
    
        <entry>
            <title>Windows And Tabs In Fennec</title>
            <author>
                <name>Erik Vold</name>
                <email>evold@mozilla.com</email>
            </author>
            <link href="http://work.erikvold.com/jetpack/2012/09/24/windows-tabs-fennec.html" rel="alternate" type="text/html" />
            <updated>2012-09-24T00:00:00-07:00</updated>
            <id>http://work.erikvold.com/jetpack/2012/09/24/windows-tabs-fennec</id>
            <content type="html">&lt;p&gt;My work on the &lt;code&gt;windows&lt;/code&gt; and &lt;code&gt;tabs&lt;/code&gt; module support for Fennec has &lt;a href='https://github.com/mozilla/addon-sdk/commit/8f9df63e632275c4a75850c40e459fdbe8ff7897'&gt;landed&lt;/a&gt;! finally.&lt;/p&gt;

&lt;p&gt;There are many differences between the two platforms related to windows and tabs, so that&amp;#8217;s worth writing about, but most of these things are minor and I&amp;#8217;m guessing that most use cases for the &lt;code&gt;windows&lt;/code&gt; and &lt;code&gt;tabs&lt;/code&gt; modules are covered for Fennec now!&lt;/p&gt;

&lt;h2 id='what_works'&gt;What Works&lt;/h2&gt;

&lt;h3 id='windows'&gt;windows&lt;/h3&gt;

&lt;p&gt;Typically one wants a reference to the &lt;code&gt;activeWindow&lt;/code&gt;, that works. Why do they want a reference to the &lt;code&gt;activeWindow&lt;/code&gt;? Well, probably to see what tabs it has, &lt;code&gt;activeWindow.tabs&lt;/code&gt;, that works. One might also want to loop through the open windows &lt;code&gt;for each (let window in require(&amp;#39;windows&amp;#39;).browserWindows)&lt;/code&gt; that works as well.&lt;/p&gt;

&lt;h3 id='tabs'&gt;tabs&lt;/h3&gt;

&lt;p&gt;Tabs are more interesting than windows. On Fennec, you can&amp;#8217;t open windows, so tabs are the next option, and it is the better option anyhow, so forget about using &lt;code&gt;windows&lt;/code&gt; in any add-on that you develop, please.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var tabs = require(&amp;#39;tabs&amp;#39;);
tabs.open(&amp;#39;https://mozilla.org&amp;#39;) // works&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Opening tabs works.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;tabs.open({
  url: &amp;#39;https://mozilla.org&amp;#39;,
  inBackground: true,
  onReady: function(tab) {
    tab.attach({
      contentScript: &amp;#39;alert(&amp;quot;hello tab ;)&amp;quot;)&amp;#39;
    });
  }
});&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Opening tabs, and saying hi via content script when the tab is ready, works.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;for each (let tab in tabs) {
  tab.url = &amp;#39;https://mozilla.org&amp;#39;;
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Sending all open tabs to &lt;a href='https://mozilla.org'&gt;mozilla.org&lt;/a&gt; works!&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;tabs.on(&amp;#39;activate&amp;#39;, function(tab) {
  borg.consume({
    url: tab.url,
    index: tab.index,
    title: tab.title,
    isPinned: tab.isPinned
  })

  tab.close();
});&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Sending the Borg all of the data on the pages you read, works!&lt;/p&gt;

&lt;p&gt;Oops.&lt;/p&gt;

&lt;h2 id='what_doesnt_work'&gt;What Doesn&amp;#8217;t Work&lt;/h2&gt;

&lt;h3 id='windows'&gt;windows&lt;/h3&gt;

&lt;p&gt;Since Fennec only has a single window, attempts to open new windows, and closing the only available open window had to be prevented. This means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;require(&amp;#39;windows&amp;#39;).activeWindow.close()&lt;/code&gt; won&amp;#8217;t do anything.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;code&gt;require(&amp;#39;windows&amp;#39;).open(URL)&lt;/code&gt; won&amp;#8217;t do anything.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I thought long and hard about this. It was suggested that &lt;code&gt;open&lt;/code&gt; would open a tab instead, then I thought about making fake windows, with fake tab collections consisting of a tab subset based on how the window was created. In this latter case, &lt;code&gt;require(&amp;#39;windows&amp;#39;).open({url: URL, onOpen: function(window) window})&lt;/code&gt;, The &lt;code&gt;window&lt;/code&gt; would be a fake window object, the &lt;code&gt;window.tabs&lt;/code&gt; would be a subset of &lt;code&gt;require(&amp;#39;windows&amp;#39;).activateWindow.tabs&lt;/code&gt;. This would mean that &lt;code&gt;window.close()&lt;/code&gt; would only close the tab for &lt;code&gt;URL&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It wasn&amp;#8217;t a easy picture to paint, and in general opening a tab instead of a window would increase the amount of effort it would take one to understand the complexity of the API, which would be important in this case. Also it was clear that &lt;code&gt;tabs&lt;/code&gt; is the more important module of the two, so it would be better to promote that module.&lt;/p&gt;

&lt;h3 id='tabs'&gt;tabs&lt;/h3&gt;

&lt;p&gt;There are a number of minor things that don&amp;#8217;t work here, and we have bugs for.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Setting the &lt;code&gt;tab.index&lt;/code&gt; like &lt;code&gt;tab.index = 1&lt;/code&gt; doesn&amp;#8217;t work, it&amp;#8217;s not yet possible to change the order of the tabs, &lt;a href='https://bugzilla.mozilla.org/show_bug.cgi?id=782461'&gt;bug 782461&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Pinning tabs is not possible, that is &lt;a href='https://bugzilla.mozilla.org/show_bug.cgi?id=782819'&gt;bug 782819&lt;/a&gt;, which means opening a pinned tab does not work either.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Finally, &lt;code&gt;tab.favicon&lt;/code&gt; and &lt;code&gt;tab.getThumbnail()&lt;/code&gt; both don&amp;#8217;t work because they would need to be async methods, so &lt;a href='https://bugzilla.mozilla.org/show_bug.cgi?id=794320'&gt;bug 794320&lt;/a&gt; is for &lt;code&gt;tab.favicon&lt;/code&gt; and &lt;span&gt;bug 791098&lt;/span&gt; is for &lt;code&gt;tab.getThumbnail()&lt;/code&gt;. I think these methods should be deprecated in favor of separate async module(s), but we&amp;#8217;ll see.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id='example_tab_usage'&gt;Example: Tab Usage&lt;/h2&gt;

&lt;p&gt;Somewhere on the internet there is a video of &lt;a href='http://www.azarask.in/'&gt;Aza Raskin&lt;/a&gt; talking about a simple little Jetpack called &amp;#8220;Tab Usage Statistics&amp;#8221; if I recall correct. It was a simple demo for the &lt;a href='https://addons.mozilla.org/firefox/addon/mozilla-labs-jetpack-prototype/'&gt;Jetpack prototype&lt;/a&gt;, and since I needed a simple example for the &lt;code&gt;tabs&lt;/code&gt; module that would work for Firefox and Fennec, I decided to rip the idea off :)&lt;/p&gt;

&lt;p&gt;Sadly I could not just take and code and morph it for the sdk because I couldn&amp;#8217;t find the epic source anywhere. So I moved forward and recreated it.&lt;/p&gt;

&lt;p&gt;This add-on is called &lt;a href='https://addons.mozilla.org/firefox/addon/tab-usage-jetpack/'&gt;Tab Usage&lt;/a&gt;, it displays a graph of the number of tabs you have open over time. T0 starts when you open the graph. You open the graph via a button in the preferences for the add-on, because that was a place I could depend on for Fennec and Firefox.&lt;/p&gt;

&lt;p&gt;&lt;img src='https://addons.cdn.mozilla.net/img/uploads/previews/full/78/78894.png' alt='Graph' /&gt; &lt;img src='https://addons.cdn.mozilla.net/img/uploads/previews/full/78/78896.png' alt='Preferences' /&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;main.js&lt;/code&gt; file here is simple&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var tabs = require(&amp;quot;tabs&amp;quot;);
var { setTimeout, clearTimeout } = require(&amp;quot;timers&amp;quot;);
var sp = require(&amp;quot;simple-prefs&amp;quot;);
var { data } = require(&amp;quot;self&amp;quot;);
var { PageMod } = require(&amp;quot;page-mod&amp;quot;);
var URL = data.url(&amp;quot;page.html&amp;quot;);

function updateTabCount() {
  this.port.emit(&amp;quot;update&amp;quot;, tabs.length);
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The function above will send the total number of tabs to the graph with a &lt;code&gt;&amp;quot;update&amp;quot;&lt;/code&gt; event.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sp.on(&amp;quot;open-page&amp;quot;, function() {
  tabs.open({
    url: URL,
    onReady: function(tab) {
      var mod = tab.attach({
        contentScriptFile: data.url(&amp;quot;page.js&amp;quot;),
      });

      var update = updateTabCount.bind(mod);
      tabs.on(&amp;quot;open&amp;quot;, update);
      tabs.on(&amp;quot;close&amp;quot;, update);
      mod.on(&amp;quot;detach&amp;quot;, function() {
        tabs.removeListener(&amp;quot;open&amp;quot;, update);
        tabs.removeListener(&amp;quot;close&amp;quot;, update);
      });
      update();
    }
  });
});&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This &lt;code&gt;simple-prefs&lt;/code&gt; listener is waiting for the &amp;#8220;Open&amp;#8221; button to be pressed, at which point it opens a new tab for the graph, when that page has loaded a content script is attached to the page which will hear the &lt;code&gt;&amp;quot;update&amp;quot;&lt;/code&gt; event mentioned above and do the graph updates.&lt;/p&gt;

&lt;h2 id='summary'&gt;Summary&lt;/h2&gt;

&lt;p&gt;I hope you enjoy! It should be pretty easy to make add-ons such as &lt;a href='https://addons.mozilla.org/firefox/addon/tab-usage-jetpack/'&gt;Tab Usage&lt;/a&gt; for Firefox on Android now. I have a few more add-ons in mind which will be using &lt;code&gt;tabs&lt;/code&gt; and they will be coming out soon!&lt;/p&gt;

&lt;p&gt;This change will be released with v1.12 of the Add-on SDK.&lt;/p&gt;</content>
        </entry>
    
</feed>
