1 # ***** BEGIN LICENSE BLOCK *****
2 # Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 # The contents of this file are subject to the Mozilla Public License Version
5 # 1.1 (the "License"); you may not use this file except in compliance with
6 # the License. You may obtain a copy of the License at
7 # http://www.mozilla.org/MPL/
9 # Software distributed under the License is distributed on an "AS IS" basis,
10 # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 # for the specific language governing rights and limitations under the
14 # The Original Code is Private Browsing.
16 # The Initial Developer of the Original Code is
18 # Portions created by the Initial Developer are Copyright (C) 2008
19 # the Initial Developer. All Rights Reserved.
22 # Ehsan Akhgari <ehsan.akhgari@gmail.com> (Original Author)
23 # Simon Bünzli <zeniko@gmail.com>
25 # Alternatively, the contents of this file may be used under the terms of
26 # either the GNU General Public License Version 2 or later (the "GPL"), or
27 # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 # in which case the provisions of the GPL or the LGPL are applicable instead
29 # of those above. If you wish to allow use of your version of this file only
30 # under the terms of either the GPL or the LGPL, and not to allow others to
31 # use your version of this file under the terms of the MPL, indicate your
32 # decision by deleting the provisions above and replace them with the notice
33 # and other provisions required by the GPL or the LGPL. If you do not delete
34 # the provisions above, a recipient may use your version of this file under
35 # the terms of any one of the MPL, the GPL or the LGPL.
37 # ***** END LICENSE BLOCK *****
39 Components.utils.import(
"resource://gre/modules/XPCOMUtils.jsm");
52 let index = this.
indexOf(aDomain);
64 let prevChar =
this[index - 1];
65 return (index == (this.length - aDomain.length)) &&
66 (prevChar ==
"." || prevChar ==
"/");
72 const Cc = Components.classes;
73 const Ci = Components.interfaces;
74 const Cu = Components.utils;
75 const Cr = Components.results;
86 this.
_obs.addObserver(
this,
"profile-after-change",
true);
87 this.
_obs.addObserver(
this,
"quit-application-granted",
true);
88 this.
_obs.addObserver(
this,
"private-browsing",
true);
89 this.
_obs.addObserver(
this,
"command-line-startup",
true);
90 this.
_obs.addObserver(
this,
"sessionstore-browser-state-restored",
true);
98 this.__obs =
Cc[
"@mozilla.org/observer-service;1"].
107 this.__prefs =
Cc[
"@mozilla.org/preferences-service;1"].
113 _inPrivateBrowsing:
false,
116 _savedBrowserState:
null,
139 classID: Components.ID(
"{c31f4883-839b-45f6-82ad-a6a9bc5ad599}"),
141 { category:
"command-line-handler",
entry:
"m-privatebrowsing" },
142 { category:
"app-startup",
service:
true }
147 Ci.nsISupportsWeakReference,
148 Ci.nsICommandLineHandler]),
150 _unload:
function PBS__destroy() {
152 this._quitting =
true;
153 if (this._inPrivateBrowsing)
154 this.privateBrowsingEnabled =
false;
157 _onBeforePrivateBrowsingModeChange:
function PBS__onBeforePrivateBrowsingModeChange() {
159 if (!this._autoStarted) {
160 let ss =
Cc[
"@mozilla.org/browser/sessionstore;1"].
162 let blankState =
JSON.stringify({
173 if (this._inPrivateBrowsing) {
175 if (this._saveSession && !this._savedBrowserState) {
176 if (this._getBrowserWindow())
177 this._savedBrowserState = ss.getBrowserState();
179 this._savedBrowserState = blankState;
183 this._closePageInfoWindows();
186 let viewSrcWindowsEnum =
Cc[
"@mozilla.org/appshell/window-mediator;1"].
188 getEnumerator(
"navigator:view-source");
189 while (viewSrcWindowsEnum.hasMoreElements()) {
190 let
win = viewSrcWindowsEnum.getNext();
191 if (this._inPrivateBrowsing) {
192 let plainURL = win.getBrowser().currentURI.spec;
193 if (plainURL.indexOf(
"view-source:") == 0) {
194 plainURL = plainURL.substr(12);
195 this._viewSrcURLs.push(plainURL);
201 if (!this._quitting && this._saveSession) {
202 let browserWindow = this._getBrowserWindow();
208 ss.setBrowserState(blankState);
213 browserWindow = this._getBrowserWindow();
214 let
browser = browserWindow.gBrowser;
219 browser.getBrowserForTab(browser.tabContainer.firstChild).stop();
220 browser.removeTab(browser.tabContainer.firstChild);
221 browserWindow.getInterface(
Ci.nsIWebNavigation)
222 .QueryInterface(
Ci.nsIDocShellTreeItem)
224 .QueryInterface(
Ci.nsIInterfaceRequestor)
225 .getInterface(
Ci.nsIXULWindow)
226 .docShell.contentViewer.resetCloseWindow();
231 this._saveSession =
false;
234 _onAfterPrivateBrowsingModeChange:
function PBS__onAfterPrivateBrowsingModeChange() {
237 if (!this._autoStarted && this._saveSession) {
238 let ss =
Cc[
"@mozilla.org/browser/sessionstore;1"].
242 if (!this._inPrivateBrowsing) {
244 ss.setBrowserState(this._savedBrowserState);
245 this._savedBrowserState =
null;
247 this._closePageInfoWindows();
250 let windowWatcher =
Cc[
"@mozilla.org/embedcomp/window-watcher;1"].
252 this._viewSrcURLs.forEach(
function(
uri) {
253 let
args =
Cc[
"@mozilla.org/supports-array;1"].
255 let
str =
Cc[
"@mozilla.org/supports-string;1"].
258 args.AppendElement(str);
259 args.AppendElement(
null);
260 args.AppendElement(
null);
261 args.AppendElement(
null);
262 let forcedCharset =
Cc[
"@mozilla.org/supports-PRBool;1"].
264 forcedCharset.data =
false;
265 args.AppendElement(forcedCharset);
266 windowWatcher.openWindow(
null,
"chrome://global/content/viewSource.xul",
267 "_blank",
"all,dialog=no", args);
269 this._viewSrcURLs = [];
274 let privateBrowsingState = {
278 "url":
"about:privatebrowsing"
286 ss.setBrowserState(
JSON.stringify(privateBrowsingState));
291 _notifyIfTransitionComplete:
function PBS__notifyIfTransitionComplete() {
292 switch (this._currentStatus) {
298 this.
_obs.notifyObservers(
null,
"private-browsing-transition-complete",
"");
308 Cu.reportError(
"Unexpected private browsing status reached: " +
309 this._currentStatus);
314 _canEnterPrivateBrowsingMode:
function PBS__canEnterPrivateBrowsingMode() {
315 let cancelEnter =
Cc[
"@mozilla.org/supports-PRBool;1"].
317 cancelEnter.data =
false;
318 this.
_obs.notifyObservers(cancelEnter,
"private-browsing-cancel-vote",
"enter");
319 return !cancelEnter.data;
322 _canLeavePrivateBrowsingMode:
function PBS__canLeavePrivateBrowsingMode() {
323 let cancelLeave =
Cc[
"@mozilla.org/supports-PRBool;1"].
325 cancelLeave.data =
false;
326 this.
_obs.notifyObservers(cancelLeave,
"private-browsing-cancel-vote",
"exit");
327 return !cancelLeave.data;
330 _getBrowserWindow:
function PBS__getBrowserWindow() {
331 return Cc[
"@mozilla.org/appshell/window-mediator;1"].
336 _ensureCanCloseWindows:
function PBS__ensureCanCloseWindows() {
338 this._saveSession =
true;
340 if (this.
_prefs.getBoolPref(
"browser.privatebrowsing.keep_current_session")) {
341 this._saveSession =
false;
346 let windowMediator =
Cc[
"@mozilla.org/appshell/window-mediator;1"].
348 let
windowsEnum = windowMediator.getXULWindowEnumerator(
"navigator:browser");
350 while (windowsEnum.hasMoreElements()) {
351 let
win = windowsEnum.getNext().QueryInterface(
Ci.nsIXULWindow);
352 if (win.docShell.contentViewer.permitUnload(
true))
353 this._windowsToClose.push(win);
355 throw Cr.NS_ERROR_ABORT;
359 _closePageInfoWindows:
function PBS__closePageInfoWindows() {
360 let pageInfoEnum =
Cc[
"@mozilla.org/appshell/window-mediator;1"].
362 getEnumerator(
"Browser:page-info");
363 while (pageInfoEnum.hasMoreElements()) {
364 let
win = pageInfoEnum.getNext();
371 observe:
function PBS_observe(aSubject, aTopic,
aData) {
373 case "profile-after-change":
378 if (!this._autoStarted) {
379 this._autoStarted = this.
_prefs.getBoolPref(
"browser.privatebrowsing.autostart");
380 if (this._autoStarted)
381 this.privateBrowsingEnabled =
true;
383 this.
_obs.removeObserver(
this,
"profile-after-change");
385 case "quit-application-granted":
388 case "private-browsing":
390 let sdr =
Cc[
"@mozilla.org/security/sdr;1"].
392 sdr.logoutAndTeardown();
395 let authMgr =
Cc[
'@mozilla.org/network/http-auth-manager;1'].
400 this.
_prefs.deleteBranch(
"geo.wifi.access_token.");
403 if (!this._inPrivateBrowsing) {
405 let consoleService =
Cc[
"@mozilla.org/consoleservice;1"].
407 consoleService.logStringMessage(
null);
408 consoleService.reset();
411 case "command-line-startup":
412 this.
_obs.removeObserver(
this,
"command-line-startup");
413 aSubject.QueryInterface(
Ci.nsICommandLine);
416 case "sessionstore-browser-state-restored":
419 this._notifyIfTransitionComplete();
427 handle:
function PBS_handle(aCmdLine) {
428 if (aCmdLine.handleFlag(
"private",
false)) {
429 this.privateBrowsingEnabled =
true;
430 this._autoStarted =
true;
434 get helpInfo PBS_get_helpInfo() {
435 return " -private Enable private browsing mode.\n";
443 get privateBrowsingEnabled PBS_get_privateBrowsingEnabled() {
444 return this._inPrivateBrowsing;
450 set privateBrowsingEnabled PBS_set_privateBrowsingEnabled(
val) {
457 throw Cr.NS_ERROR_FAILURE;
462 if (
val != this._inPrivateBrowsing) {
464 if (!this._canEnterPrivateBrowsingMode())
468 if (!this._canLeavePrivateBrowsingMode())
472 this._ensureCanCloseWindows();
474 this._autoStarted = this.
_prefs.getBoolPref(
"browser.privatebrowsing.autostart");
475 this._inPrivateBrowsing =
val !=
false;
477 let
data =
val ?
"enter" :
"exit";
479 let quitting =
Cc[
"@mozilla.org/supports-PRBool;1"].
481 quitting.data = this._quitting;
484 this.
_obs.notifyObservers(quitting,
"private-browsing-change-granted", data);
487 this._onBeforePrivateBrowsingModeChange();
489 this.
_obs.notifyObservers(quitting,
"private-browsing", data);
492 this._onAfterPrivateBrowsingModeChange();
497 for (let
i = 0;
i < this._windowsToClose.length;
i++)
498 this._windowsToClose[
i].
docShell.contentViewer.resetCloseWindow();
500 if (ex !=
Cr.NS_ERROR_ABORT)
501 Cu.reportError(
"Exception thrown while processing the " +
502 "private browsing mode change request: " + ex.toString());
504 this._windowsToClose = [];
505 this._notifyIfTransitionComplete();
512 get autoStarted PBS_get_autoStarted() {
513 return this._inPrivateBrowsing && this._autoStarted;
516 removeDataFromDomain:
function PBS_removeDataFromDomain(aDomain)
521 this.
_prefs.deleteBranch(
"geo.wifi.access_token.");
525 let (
bh =
Cc[
"@mozilla.org/browser/global-history;2"].
527 bh.removePagesFromHost(aDomain,
true);
531 let (cs =
Cc[
"@mozilla.org/network/cache-service;1"].
536 cs.evictEntries(
Ci.nsICache.STORE_ANYWHERE);
538 Cu.reportError(
"Exception thrown while clearing the cache: " +
544 let (
cm =
Cc[
"@mozilla.org/cookiemanager;1"].
546 let enumerator =
cm.enumerator;
547 while (enumerator.hasMoreElements()) {
548 let cookie = enumerator.getNext().QueryInterface(
Ci.nsICookie);
549 if (cookie.host.hasRootDomain(aDomain))
550 cm.remove(cookie.host, cookie.name, cookie.path,
false);
555 let (
dm =
Cc[
"@mozilla.org/download-manager;1"].
558 let enumerator =
dm.activeDownloads;
559 while (enumerator.hasMoreElements()) {
560 let dl = enumerator.getNext().QueryInterface(
Ci.nsIDownload);
561 if (dl.source.host.hasRootDomain(aDomain)) {
562 dm.cancelDownload(dl.id);
563 dm.removeDownload(dl.id);
568 let db =
dm.DBConnection;
572 let stmt = db.createStatement(
573 "DELETE FROM moz_downloads " +
574 "WHERE source LIKE ?1 ESCAPE '/' " +
575 "AND state NOT IN (?2, ?3, ?4)"
577 let pattern = stmt.escapeStringForLIKE(aDomain,
"/");
578 stmt.bindStringParameter(0,
"%" + pattern +
"%");
579 stmt.bindInt32Parameter(1,
Ci.nsIDownloadManager.DOWNLOAD_DOWNLOADING);
580 stmt.bindInt32Parameter(2,
Ci.nsIDownloadManager.DOWNLOAD_PAUSED);
581 stmt.bindInt32Parameter(3,
Ci.nsIDownloadManager.DOWNLOAD_QUEUED);
591 let
os =
Cc[
"@mozilla.org/observer-service;1"].
593 os.notifyObservers(
null,
"download-manager-remove-download",
null);
597 let (lm =
Cc[
"@mozilla.org/login-manager;1"].
601 let logins = lm.getAllLogins({});
602 for (let
i = 0;
i < logins.length;
i++)
603 if (logins[
i].hostname.hasRootDomain(aDomain))
604 lm.removeLogin(logins[
i]);
608 catch (ex
if ex.message.indexOf(
"User canceled Master Password entry") != -1) { }
611 let disabledHosts = lm.getAllDisabledHosts({});
612 for (let
i = 0;
i < disabledHosts.length;
i++)
614 lm.setLoginSavingEnabled(disabledHosts,
true);
618 let (pm =
Cc[
"@mozilla.org/permissionmanager;1"].
621 let enumerator = pm.enumerator;
622 while (enumerator.hasMoreElements()) {
623 let perm = enumerator.getNext().QueryInterface(
Ci.nsIPermission);
624 if (perm.host.hasRootDomain(aDomain))
625 pm.remove(perm.host, perm.type);
630 let (cp =
Cc[
"@mozilla.org/content-pref/service;1"].
632 let db = cp.DBConnection;
635 let stmt = db.createStatement(
638 "WHERE name LIKE ?1 ESCAPE '/'"
640 let pattern = stmt.escapeStringForLIKE(aDomain,
"/");
641 stmt.bindStringParameter(0,
"%" + pattern);
643 while (stmt.executeStep())
644 if (stmt.getString(0).hasRootDomain(aDomain))
645 names.push(stmt.getString(0));
652 for (let
i = 0;
i < names.length;
i++) {
655 let
uri = { host: names[
i]};
656 let enumerator = cp.getPrefs(uri).enumerator;
657 while (enumerator.hasMoreElements()) {
658 let
pref = enumerator.getNext().QueryInterface(
Ci.nsIProperty);
659 cp.removePref(uri, pref.name);
665 this.
_obs.notifyObservers(
null,
"browser:purge-domain-data", aDomain);
const STATE_TRANSITION_STARTED
function PrivateBrowsingService()
sbDeviceFirmwareAutoCheckForUpdate prototype contractID
sbOSDControlService prototype QueryInterface
sbDeviceFirmwareAutoCheckForUpdate prototype classDescription
function handle(request, response)
getService(Ci.sbIFaceplateManager)
return elem filter &&elem filter indexOf("opacity=")>=0?(parseFloat(elem.filter.match(/opacity
function NSGetModule(compMgr, fileSpec) XPCOMUtils.generateModule([PrivateBrowsingService])
const STATE_RESTORE_FINISHED
this _dialogInput val(dateText)
String prototype hasRootDomain
sbDeviceFirmwareAutoCheckForUpdate prototype classID
sbWindowsAutoPlayServiceCfg _xpcom_categories
const STATE_WAITING_FOR_RESTORE
function getMostRecentWindow(aType)
_getSelectedPageStyle s i
_updateTextAndScrollDataForFrame aData
sbDeviceFirmwareAutoCheckForUpdate prototype observe