User:Ehsan/PrivateBrowsingForExtensions

< User:Ehsan
Revision as of 07:43, 13 September 2008 by Ehsan (talk | contribs) (→‎Private Browsing notifications: Add a description of private-browsing-query)

Introduction

Many extensions may store data which can reveal information about user's browsing history. For example, and extension may record the last visit date for all the websites that the user visits. There is currently no reliable way for us to disable storing such data by extensions, therefore it is very important to provide simple to use APIs as well as code samples which extension developers can use to integrate the Private Browsing mode with their extensions.

APIs for Extensions

The Private Browsing service

The Private Browsing service can be used in order to get and set the current status of private browsing. The contract ID for this service is @mozilla.org/browser/privatebrowsing;1. It supports the nsIPrivateBrowsingService interface:

[scriptable, uuid(d2943870-c781-11dc-95ff-0800200c9a66)]
interface nsIPrivateBrowsingService : nsISupports
{
    // Whether or not the private browsing mode is currently active.
    attribute boolean privateBrowsing;
};

The privateBrowsing attribute is key to the functionality of this service. By setting it to true, private browsing mode will be initiated. Likewise, by setting it to false, the private browsing mode will be terminated. The current status of the private browsing mode can be queried by reading the value of this attribute.

Private Browsing notifications

Extensions can be notified of private browsing status changes, i.e., when the user enters or leaves the private browsing mode. This is done via standard XPCOM observer service mechanisms. The notification's name is browser:private-browsing. The data parameter can be either enter (indicating that the private browsing mode has been initiated) or exit (indicating that the private browsing mode has been terminated).

The second code sample below implements a full blown listener for the private browsing mode, which can both be used to query its current status, and set a watcher to watch for entering and/or leaving the private mode.

If for some reason, you don't want to make your extension dependent on nsIPrivateBrowsingService (for example, when developing an extension to support both Firefox and Thunderbird, where the private browsing service is not available), you can use the private-browsing-query notification to query the current status of the private browsing mode. In order to use this notification, a nsISupportsPRBool object must be passed as the subject parameter. The private browsing service, if available, will handle this notification and return the status as a boolean value in the subject parameter. If the private browsing service is not available, the boolean value remains false. A sample of using this notification appears in the code samples below.

Code Samples

Extensions that want to check the status of the Private Browsing mode

var pbs = Components.classes["@mozilla.org/browser/privatebrowsing;1"]
                    .getService(Components.interfaces.nsIPrivateBrowsingService);

// are we currently in the Private Browsing mode?
var inPrivateBrowsingMode = pbs.privateBrowsing;

Extensions that want to listen to the Private Browsing mode changes

function PrivateBrowsingListener() {
  this.init();
}

PrivateBrowsingListener.prototype = {
  _os: null,
  _inPrivateBrowsing: false, // whether we are in private browsing mode
  _inited: false,
  _watcher: null, // the watcher object

  QueryInterface : function (iid) {
    if (iid.equals(Components.interfaces.nsISupports) ||
        iid.equals(Components.interfaces.nsIObserver))
      return this;

    throw Components.results.NS_ERROR_NO_INTERFACE;
  },

  init : function () {
    if (!this._inited) {
      this._inited = true;
      this._os = Components.classes["@mozilla.org/observer-service;1"]
                           .getService(Components.interfaces.nsIObserverService);
      this._os.addObserver(this, "browser:private-browsing", false);
      this._os.addObserver(this, "quit-application", false);
    }
  },

  observe : function (aSubject, aTopic, aData) {
    if (aTopic == "browser:private-browsing") {
      if (aData == "enter") {
        this._inPrivateBrowsing = true;
        if (this.watcher &&
            "onEnterPrivateBrowsing" in this._watcher) {
          this.watcher.onEnterPrivateBrowsing();
        }
      } else if (aData == "exit") {
        this._inPrivateBrowsing = false;
        if (this.watcher &&
            "onExitPrivateBrowsing" in this._watcher) {
          this.watcher.onExitPrivateBrowsing();
        }
      }
    } else if (aTopic == "quit-application") {
      this._os.removeObserver(this, "quit-application");
      this._os.removeObserver(this, "browser:private-browsing");
    }
  },

  get inPrivateBrowsing() {
    return this._inPrivateBrowsing;
  },

  get watcher() {
    return this._watcher;
  },

  set watcher(val) {
    this._watcher = val;
  }
};

var listener = PrivateBrowsingListener();

if (listener.inPrivateBrowsing) {
  // we are in the private mode!
} else {
  // we are not in the private mode!
}

listener.watcher = {
  onEnterPrivateBrowsing : function() {
    // we have just entered the private browsing mode!
  },

  onExitPrivateBrowsing : function() {
    // we have just left the private browsing mode!
  }
};

Extensions that want to initiate or terminate a Private Browsing session

var pbs = Components.classes["@mozilla.org/browser/privatebrowsing;1"]
                    .getService(Components.interfaces.nsIPrivateBrowsingService);

// enter the Private Browsing mode
pbs.privateBrowsing = true;

// now, whatever we do remains private!

// exit the Private Browsing mode
pbs.privateBrowsing = false;