summaryrefslogtreecommitdiffstats
path: root/browser/components/privatebrowsing
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/privatebrowsing')
-rw-r--r--browser/components/privatebrowsing/content/aboutPrivateBrowsing.css10
-rw-r--r--browser/components/privatebrowsing/content/aboutPrivateBrowsing.js98
-rw-r--r--browser/components/privatebrowsing/content/aboutPrivateBrowsing.xhtml85
-rw-r--r--browser/components/privatebrowsing/jar.mn8
-rw-r--r--browser/components/privatebrowsing/moz.build14
-rw-r--r--browser/components/privatebrowsing/test/browser/.eslintrc.js7
-rw-r--r--browser/components/privatebrowsing/test/browser/browser.ini54
-rw-r--r--browser/components/privatebrowsing/test/browser/browser_privatebrowsing_DownloadLastDirWithCPS.js282
-rw-r--r--browser/components/privatebrowsing/test/browser/browser_privatebrowsing_about.js115
-rw-r--r--browser/components/privatebrowsing/test/browser/browser_privatebrowsing_aboutHomeButtonAfterWindowClose.js24
-rw-r--r--browser/components/privatebrowsing/test/browser/browser_privatebrowsing_aboutSessionRestore.js23
-rw-r--r--browser/components/privatebrowsing/test/browser/browser_privatebrowsing_blobUrl.js45
-rw-r--r--browser/components/privatebrowsing/test/browser/browser_privatebrowsing_cache.js138
-rw-r--r--browser/components/privatebrowsing/test/browser/browser_privatebrowsing_certexceptionsui.js53
-rw-r--r--browser/components/privatebrowsing/test/browser/browser_privatebrowsing_concurrent.js88
-rw-r--r--browser/components/privatebrowsing/test/browser/browser_privatebrowsing_concurrent_page.html33
-rw-r--r--browser/components/privatebrowsing/test/browser/browser_privatebrowsing_context_and_chromeFlags.js60
-rw-r--r--browser/components/privatebrowsing/test/browser/browser_privatebrowsing_crh.js42
-rw-r--r--browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadLastDir.js93
-rw-r--r--browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadLastDir_c.js95
-rw-r--r--browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadLastDir_toggle.js105
-rw-r--r--browser/components/privatebrowsing/test/browser/browser_privatebrowsing_favicon.js293
-rw-r--r--browser/components/privatebrowsing/test/browser/browser_privatebrowsing_geoprompt.js54
-rw-r--r--browser/components/privatebrowsing/test/browser/browser_privatebrowsing_geoprompt_page.html13
-rw-r--r--browser/components/privatebrowsing/test/browser/browser_privatebrowsing_lastpbcontextexited.js49
-rw-r--r--browser/components/privatebrowsing/test/browser/browser_privatebrowsing_localStorage.js25
-rw-r--r--browser/components/privatebrowsing/test/browser/browser_privatebrowsing_localStorage_before_after.js36
-rw-r--r--browser/components/privatebrowsing/test/browser/browser_privatebrowsing_localStorage_before_after_page.html11
-rw-r--r--browser/components/privatebrowsing/test/browser/browser_privatebrowsing_localStorage_before_after_page2.html10
-rw-r--r--browser/components/privatebrowsing/test/browser/browser_privatebrowsing_localStorage_page1.html10
-rw-r--r--browser/components/privatebrowsing/test/browser/browser_privatebrowsing_localStorage_page2.html10
-rw-r--r--browser/components/privatebrowsing/test/browser/browser_privatebrowsing_newtab_from_popup.js61
-rw-r--r--browser/components/privatebrowsing/test/browser/browser_privatebrowsing_noSessionRestoreMenuOption.js23
-rw-r--r--browser/components/privatebrowsing/test/browser/browser_privatebrowsing_nonbrowser.js19
-rw-r--r--browser/components/privatebrowsing/test/browser/browser_privatebrowsing_opendir.js133
-rw-r--r--browser/components/privatebrowsing/test/browser/browser_privatebrowsing_placesTitleNoUpdate.html8
-rw-r--r--browser/components/privatebrowsing/test/browser/browser_privatebrowsing_placesTitleNoUpdate.js72
-rw-r--r--browser/components/privatebrowsing/test/browser/browser_privatebrowsing_placestitle.js95
-rw-r--r--browser/components/privatebrowsing/test/browser/browser_privatebrowsing_popupblocker.js70
-rw-r--r--browser/components/privatebrowsing/test/browser/browser_privatebrowsing_protocolhandler.js47
-rw-r--r--browser/components/privatebrowsing/test/browser/browser_privatebrowsing_protocolhandler_page.html13
-rw-r--r--browser/components/privatebrowsing/test/browser/browser_privatebrowsing_sidebar.js92
-rw-r--r--browser/components/privatebrowsing/test/browser/browser_privatebrowsing_theming.js38
-rw-r--r--browser/components/privatebrowsing/test/browser/browser_privatebrowsing_ui.js82
-rw-r--r--browser/components/privatebrowsing/test/browser/browser_privatebrowsing_urlbarfocus.js43
-rw-r--r--browser/components/privatebrowsing/test/browser/browser_privatebrowsing_windowtitle.js77
-rw-r--r--browser/components/privatebrowsing/test/browser/browser_privatebrowsing_windowtitle_page.html9
-rw-r--r--browser/components/privatebrowsing/test/browser/browser_privatebrowsing_zoom.js37
-rw-r--r--browser/components/privatebrowsing/test/browser/browser_privatebrowsing_zoomrestore.js64
-rw-r--r--browser/components/privatebrowsing/test/browser/empty_file.html1
-rw-r--r--browser/components/privatebrowsing/test/browser/file_favicon.html11
-rw-r--r--browser/components/privatebrowsing/test/browser/file_favicon.pngbin0 -> 344 bytes
-rw-r--r--browser/components/privatebrowsing/test/browser/file_favicon.png^headers^1
-rw-r--r--browser/components/privatebrowsing/test/browser/head.js63
-rw-r--r--browser/components/privatebrowsing/test/browser/popup.html12
-rw-r--r--browser/components/privatebrowsing/test/browser/title.sjs22
56 files changed, 3076 insertions, 0 deletions
diff --git a/browser/components/privatebrowsing/content/aboutPrivateBrowsing.css b/browser/components/privatebrowsing/content/aboutPrivateBrowsing.css
new file mode 100644
index 000000000..29d7a843d
--- /dev/null
+++ b/browser/components/privatebrowsing/content/aboutPrivateBrowsing.css
@@ -0,0 +1,10 @@
+html.private .showNormal,
+html.normal .showPrivate,
+body[tpEnabled] .showTpDisabled,
+body:not([tpEnabled]) .showTpEnabled {
+ display: none !important;
+}
+
+.hide {
+ display: none;
+}
diff --git a/browser/components/privatebrowsing/content/aboutPrivateBrowsing.js b/browser/components/privatebrowsing/content/aboutPrivateBrowsing.js
new file mode 100644
index 000000000..31ce96347
--- /dev/null
+++ b/browser/components/privatebrowsing/content/aboutPrivateBrowsing.js
@@ -0,0 +1,98 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+var {classes: Cc, interfaces: Ci, utils: Cu} = Components;
+
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+const FAVICON_QUESTION = "chrome://global/skin/icons/question-32.png";
+const FAVICON_PRIVACY = "chrome://browser/skin/privatebrowsing/favicon.svg";
+
+var stringBundle = Services.strings.createBundle(
+ "chrome://browser/locale/aboutPrivateBrowsing.properties");
+
+var prefBranch = Services.prefs.getBranch("privacy.trackingprotection.");
+var prefObserver = {
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
+ Ci.nsISupportsWeakReference]),
+ observe: function () {
+ let tpSubHeader = document.getElementById("tpSubHeader");
+ let tpToggle = document.getElementById("tpToggle");
+ let tpButton = document.getElementById("tpButton");
+ let title = document.getElementById("title");
+ let titleTracking = document.getElementById("titleTracking");
+ let globalTrackingEnabled = prefBranch.getBoolPref("enabled");
+ let trackingEnabled = globalTrackingEnabled ||
+ prefBranch.getBoolPref("pbmode.enabled");
+
+ tpButton.classList.toggle("hide", globalTrackingEnabled);
+ tpToggle.checked = trackingEnabled;
+ title.classList.toggle("hide", trackingEnabled);
+ titleTracking.classList.toggle("hide", !trackingEnabled);
+ tpSubHeader.classList.toggle("tp-off", !trackingEnabled);
+ }
+};
+prefBranch.addObserver("pbmode.enabled", prefObserver, true);
+prefBranch.addObserver("enabled", prefObserver, true);
+
+function setFavIcon(url) {
+ document.getElementById("favicon").setAttribute("href", url);
+}
+
+document.addEventListener("DOMContentLoaded", function () {
+ if (!PrivateBrowsingUtils.isContentWindowPrivate(window)) {
+ document.documentElement.classList.remove("private");
+ document.documentElement.classList.add("normal");
+ document.title = stringBundle.GetStringFromName("title.normal");
+ document.getElementById("favicon")
+ .setAttribute("href", FAVICON_QUESTION);
+ document.getElementById("startPrivateBrowsing")
+ .addEventListener("command", openPrivateWindow);
+ return;
+ }
+
+ let tpToggle = document.getElementById("tpToggle");
+ document.getElementById("tpButton").addEventListener('click', () => {
+ tpToggle.click();
+ });
+
+ document.title = stringBundle.GetStringFromName("title.head");
+ document.getElementById("favicon")
+ .setAttribute("href", FAVICON_PRIVACY);
+ tpToggle.addEventListener("change", toggleTrackingProtection);
+ document.getElementById("startTour")
+ .addEventListener("click", dontShowIntroPanelAgain);
+
+ let formatURLPref = Cc["@mozilla.org/toolkit/URLFormatterService;1"]
+ .getService(Ci.nsIURLFormatter).formatURLPref;
+ document.getElementById("startTour").setAttribute("href",
+ formatURLPref("privacy.trackingprotection.introURL"));
+ document.getElementById("learnMore").setAttribute("href",
+ formatURLPref("app.support.baseURL") + "private-browsing");
+
+ // Update state that depends on preferences.
+ prefObserver.observe();
+}, false);
+
+function openPrivateWindow() {
+ // Ask chrome to open a private window
+ document.dispatchEvent(
+ new CustomEvent("AboutPrivateBrowsingOpenWindow", {bubbles:true}));
+}
+
+function toggleTrackingProtection() {
+ // Ask chrome to enable tracking protection
+ document.dispatchEvent(
+ new CustomEvent("AboutPrivateBrowsingToggleTrackingProtection",
+ {bubbles: true}));
+}
+
+function dontShowIntroPanelAgain() {
+ // Ask chrome to disable the doorhanger
+ document.dispatchEvent(
+ new CustomEvent("AboutPrivateBrowsingDontShowIntroPanelAgain",
+ {bubbles: true}));
+}
diff --git a/browser/components/privatebrowsing/content/aboutPrivateBrowsing.xhtml b/browser/components/privatebrowsing/content/aboutPrivateBrowsing.xhtml
new file mode 100644
index 000000000..fb5c4ac8e
--- /dev/null
+++ b/browser/components/privatebrowsing/content/aboutPrivateBrowsing.xhtml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<!DOCTYPE html [
+ <!ENTITY % htmlDTD PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">
+ %htmlDTD;
+ <!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd">
+ %globalDTD;
+ <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
+ %brandDTD;
+ <!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd">
+ %browserDTD;
+ <!ENTITY % aboutPrivateBrowsingDTD SYSTEM "chrome://browser/locale/aboutPrivateBrowsing.dtd">
+ %aboutPrivateBrowsingDTD;
+]>
+
+<html xmlns="http://www.w3.org/1999/xhtml" class="private">
+ <head>
+ <link id="favicon" rel="icon" type="image/png"/>
+ <link rel="stylesheet" href="chrome://browser/content/aboutPrivateBrowsing.css" type="text/css" media="all"/>
+ <link rel="stylesheet" href="chrome://browser/skin/privatebrowsing/aboutPrivateBrowsing.css" type="text/css" media="all"/>
+ <script type="application/javascript;version=1.7" src="chrome://browser/content/aboutPrivateBrowsing.js"></script>
+ </head>
+
+ <body dir="&locale.dir;">
+ <p class="showNormal">&aboutPrivateBrowsing.notPrivate;</p>
+ <button xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ id="startPrivateBrowsing"
+ class="showNormal"
+ label="&privatebrowsingpage.openPrivateWindow.label;"
+ accesskey="&privatebrowsingpage.openPrivateWindow.accesskey;"/>
+ <div class="showPrivate about-content-container">
+ <h1 class="title">
+ <span id="title">&privateBrowsing.title;</span>
+ <span id="titleTracking">&privateBrowsing.title.tracking;</span>
+ </h1>
+ <section class="section-main">
+ <p>&aboutPrivateBrowsing.info.notsaved.before;<strong>&aboutPrivateBrowsing.info.notsaved.emphasize;</strong>&aboutPrivateBrowsing.info.notsaved.after;</p>
+ <div class="list-row">
+ <ul>
+ <li>&aboutPrivateBrowsing.info.visited;</li>
+ <li>&aboutPrivateBrowsing.info.cookies;</li>
+ <li>&aboutPrivateBrowsing.info.searches;</li>
+ <li>&aboutPrivateBrowsing.info.temporaryFiles;</li>
+ </ul>
+ </div>
+ <p>&aboutPrivateBrowsing.info.saved.before;<strong>&aboutPrivateBrowsing.info.saved.emphasize;</strong>&aboutPrivateBrowsing.info.saved.after2;</p>
+ <div class="list-row">
+ <ul>
+ <li>&aboutPrivateBrowsing.info.bookmarks;</li>
+ <li>&aboutPrivateBrowsing.info.downloads;</li>
+ </ul>
+ </div>
+ <p>
+ &aboutPrivateBrowsing.note.before;
+ <strong>&aboutPrivateBrowsing.note.emphasize;</strong>
+ &aboutPrivateBrowsing.note.after;
+ </p>
+ </section>
+
+ <h2 id="tpSubHeader" class="about-subheader">
+ <span class="tpTitle">&trackingProtection.title;</span>
+ <input id="tpToggle" class="toggle toggle-input" type="checkbox"/>
+ <span id="tpButton" class="toggle-btn"></span>
+ </h2>
+
+ <section class="section-main">
+ <p>&trackingProtection.description2;</p>
+ <p>
+ <a id="startTour" class="button">&trackingProtection.startTour1;</a>
+ </p>
+ </section>
+
+ <section class="section-main">
+ <p class="about-info">&aboutPrivateBrowsing.learnMore2;
+ <a id="learnMore" target="_blank">&aboutPrivateBrowsing.learnMore2.title;</a>.
+ </p>
+ </section>
+
+ </div>
+ </body>
+</html>
diff --git a/browser/components/privatebrowsing/jar.mn b/browser/components/privatebrowsing/jar.mn
new file mode 100644
index 000000000..a98d65163
--- /dev/null
+++ b/browser/components/privatebrowsing/jar.mn
@@ -0,0 +1,8 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+browser.jar:
+ content/browser/aboutPrivateBrowsing.css (content/aboutPrivateBrowsing.css)
+ content/browser/aboutPrivateBrowsing.xhtml (content/aboutPrivateBrowsing.xhtml)
+ content/browser/aboutPrivateBrowsing.js (content/aboutPrivateBrowsing.js)
diff --git a/browser/components/privatebrowsing/moz.build b/browser/components/privatebrowsing/moz.build
new file mode 100644
index 000000000..486737a7f
--- /dev/null
+++ b/browser/components/privatebrowsing/moz.build
@@ -0,0 +1,14 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+BROWSER_CHROME_MANIFESTS += [
+ 'test/browser/browser.ini',
+]
+
+JAR_MANIFESTS += ['jar.mn']
+
+with Files('**'):
+ BUG_COMPONENT = ('Firefox', 'Private Browsing')
diff --git a/browser/components/privatebrowsing/test/browser/.eslintrc.js b/browser/components/privatebrowsing/test/browser/.eslintrc.js
new file mode 100644
index 000000000..7c8021192
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/.eslintrc.js
@@ -0,0 +1,7 @@
+"use strict";
+
+module.exports = {
+ "extends": [
+ "../../../../../testing/mochitest/browser.eslintrc.js"
+ ]
+};
diff --git a/browser/components/privatebrowsing/test/browser/browser.ini b/browser/components/privatebrowsing/test/browser/browser.ini
new file mode 100644
index 000000000..5efca4c0e
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser.ini
@@ -0,0 +1,54 @@
+[DEFAULT]
+tags = openwindow
+support-files =
+ browser_privatebrowsing_concurrent_page.html
+ browser_privatebrowsing_geoprompt_page.html
+ browser_privatebrowsing_localStorage_before_after_page.html
+ browser_privatebrowsing_localStorage_before_after_page2.html
+ browser_privatebrowsing_localStorage_page1.html
+ browser_privatebrowsing_localStorage_page2.html
+ browser_privatebrowsing_placesTitleNoUpdate.html
+ browser_privatebrowsing_protocolhandler_page.html
+ browser_privatebrowsing_windowtitle_page.html
+ head.js
+ popup.html
+ title.sjs
+ empty_file.html
+ file_favicon.html
+ file_favicon.png
+ file_favicon.png^headers^
+
+[browser_privatebrowsing_DownloadLastDirWithCPS.js]
+[browser_privatebrowsing_about.js]
+tags = trackingprotection
+[browser_privatebrowsing_aboutHomeButtonAfterWindowClose.js]
+[browser_privatebrowsing_aboutSessionRestore.js]
+[browser_privatebrowsing_cache.js]
+[browser_privatebrowsing_certexceptionsui.js]
+[browser_privatebrowsing_concurrent.js]
+[browser_privatebrowsing_context_and_chromeFlags.js]
+[browser_privatebrowsing_crh.js]
+[browser_privatebrowsing_downloadLastDir.js]
+[browser_privatebrowsing_downloadLastDir_c.js]
+[browser_privatebrowsing_downloadLastDir_toggle.js]
+[browser_privatebrowsing_favicon.js]
+[browser_privatebrowsing_geoprompt.js]
+[browser_privatebrowsing_lastpbcontextexited.js]
+[browser_privatebrowsing_localStorage.js]
+[browser_privatebrowsing_localStorage_before_after.js]
+[browser_privatebrowsing_noSessionRestoreMenuOption.js]
+[browser_privatebrowsing_nonbrowser.js]
+[browser_privatebrowsing_opendir.js]
+[browser_privatebrowsing_placesTitleNoUpdate.js]
+[browser_privatebrowsing_placestitle.js]
+[browser_privatebrowsing_popupblocker.js]
+[browser_privatebrowsing_protocolhandler.js]
+[browser_privatebrowsing_sidebar.js]
+[browser_privatebrowsing_theming.js]
+[browser_privatebrowsing_ui.js]
+[browser_privatebrowsing_urlbarfocus.js]
+[browser_privatebrowsing_windowtitle.js]
+[browser_privatebrowsing_zoom.js]
+[browser_privatebrowsing_zoomrestore.js]
+[browser_privatebrowsing_newtab_from_popup.js]
+[browser_privatebrowsing_blobUrl.js]
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_DownloadLastDirWithCPS.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_DownloadLastDirWithCPS.js
new file mode 100644
index 000000000..bcd19b192
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_DownloadLastDirWithCPS.js
@@ -0,0 +1,282 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+var gTests;
+function test() {
+ waitForExplicitFinish();
+ requestLongerTimeout(2);
+ gTests = runTest();
+ gTests.next();
+}
+
+/*
+ * ================
+ * Helper functions
+ * ================
+ */
+
+function moveAlong(aResult) {
+ try {
+ gTests.send(aResult);
+ } catch (x if x instanceof StopIteration) {
+ finish();
+ }
+}
+
+function createWindow(aOptions) {
+ whenNewWindowLoaded(aOptions, function(win) {
+ moveAlong(win);
+ });
+}
+
+function getFile(downloadLastDir, aURI) {
+ downloadLastDir.getFileAsync(aURI, function(result) {
+ moveAlong(result);
+ });
+}
+
+function setFile(downloadLastDir, aURI, aValue) {
+ downloadLastDir.setFile(aURI, aValue);
+ executeSoon(moveAlong);
+}
+
+function clearHistoryAndWait() {
+ clearHistory();
+ executeSoon(() => executeSoon(moveAlong));
+}
+
+/*
+ * ===================
+ * Function with tests
+ * ===================
+ */
+
+function runTest() {
+ let FileUtils =
+ Cu.import("resource://gre/modules/FileUtils.jsm", {}).FileUtils;
+ let DownloadLastDir =
+ Cu.import("resource://gre/modules/DownloadLastDir.jsm", {}).DownloadLastDir;
+
+ let tmpDir = FileUtils.getDir("TmpD", [], true);
+ let dir1 = newDirectory();
+ let dir2 = newDirectory();
+ let dir3 = newDirectory();
+
+ let uri1 = Services.io.newURI("http://test1.com/", null, null);
+ let uri2 = Services.io.newURI("http://test2.com/", null, null);
+ let uri3 = Services.io.newURI("http://test3.com/", null, null);
+ let uri4 = Services.io.newURI("http://test4.com/", null, null);
+
+ // cleanup functions registration
+ registerCleanupFunction(function () {
+ Services.prefs.clearUserPref("browser.download.lastDir.savePerSite");
+ Services.prefs.clearUserPref("browser.download.lastDir");
+ [dir1, dir2, dir3].forEach(dir => dir.remove(true));
+ win.close();
+ pbWin.close();
+ });
+
+ function checkDownloadLastDir(gDownloadLastDir, aLastDir) {
+ is(gDownloadLastDir.file.path, aLastDir.path,
+ "gDownloadLastDir should point to the expected last directory");
+ getFile(gDownloadLastDir, uri1);
+ }
+
+ function checkDownloadLastDirNull(gDownloadLastDir) {
+ is(gDownloadLastDir.file, null, "gDownloadLastDir should be null");
+ getFile(gDownloadLastDir, uri1);
+ }
+
+ /*
+ * ================================
+ * Create a regular and a PB window
+ * ================================
+ */
+
+ let win = yield createWindow({private: false});
+ let pbWin = yield createWindow({private: true});
+
+ let downloadLastDir = new DownloadLastDir(win);
+ let pbDownloadLastDir = new DownloadLastDir(pbWin);
+
+ /*
+ * ==================
+ * Beginning of tests
+ * ==================
+ */
+
+ is(typeof downloadLastDir, "object",
+ "downloadLastDir should be a valid object");
+ is(downloadLastDir.file, null,
+ "LastDir pref should be null to start with");
+
+ // set up last dir
+ yield setFile(downloadLastDir, null, tmpDir);
+ is(downloadLastDir.file.path, tmpDir.path,
+ "LastDir should point to the tmpDir");
+ isnot(downloadLastDir.file, tmpDir,
+ "downloadLastDir.file should not be pointing to tmpDir");
+
+ // set uri1 to dir1, all should now return dir1
+ // also check that a new object is returned
+ yield setFile(downloadLastDir, uri1, dir1);
+ is(downloadLastDir.file.path, dir1.path,
+ "downloadLastDir should return dir1");
+ isnot(downloadLastDir.file, dir1,
+ "downloadLastDir.file should not return dir1");
+ is((yield getFile(downloadLastDir, uri1)).path, dir1.path,
+ "uri1 should return dir1"); // set in CPS
+ isnot((yield getFile(downloadLastDir, uri1)), dir1,
+ "getFile on uri1 should not return dir1");
+ is((yield getFile(downloadLastDir, uri2)).path, dir1.path,
+ "uri2 should return dir1"); // fallback
+ isnot((yield getFile(downloadLastDir, uri2)), dir1,
+ "getFile on uri2 should not return dir1");
+ is((yield getFile(downloadLastDir, uri3)).path, dir1.path,
+ "uri3 should return dir1"); // fallback
+ isnot((yield getFile(downloadLastDir, uri3)), dir1,
+ "getFile on uri3 should not return dir1");
+ is((yield getFile(downloadLastDir, uri4)).path, dir1.path,
+ "uri4 should return dir1"); // fallback
+ isnot((yield getFile(downloadLastDir, uri4)), dir1,
+ "getFile on uri4 should not return dir1");
+
+ // set uri2 to dir2, all except uri1 should now return dir2
+ yield setFile(downloadLastDir, uri2, dir2);
+ is(downloadLastDir.file.path, dir2.path,
+ "downloadLastDir should point to dir2");
+ is((yield getFile(downloadLastDir, uri1)).path, dir1.path,
+ "uri1 should return dir1"); // set in CPS
+ is((yield getFile(downloadLastDir, uri2)).path, dir2.path,
+ "uri2 should return dir2"); // set in CPS
+ is((yield getFile(downloadLastDir, uri3)).path, dir2.path,
+ "uri3 should return dir2"); // fallback
+ is((yield getFile(downloadLastDir, uri4)).path, dir2.path,
+ "uri4 should return dir2"); // fallback
+
+ // set uri3 to dir3, all except uri1 and uri2 should now return dir3
+ yield setFile(downloadLastDir, uri3, dir3);
+ is(downloadLastDir.file.path, dir3.path,
+ "downloadLastDir should point to dir3");
+ is((yield getFile(downloadLastDir, uri1)).path, dir1.path,
+ "uri1 should return dir1"); // set in CPS
+ is((yield getFile(downloadLastDir, uri2)).path, dir2.path,
+ "uri2 should return dir2"); // set in CPS
+ is((yield getFile(downloadLastDir, uri3)).path, dir3.path,
+ "uri3 should return dir3"); // set in CPS
+ is((yield getFile(downloadLastDir, uri4)).path, dir3.path,
+ "uri4 should return dir4"); // fallback
+
+ // set uri1 to dir2, all except uri3 should now return dir2
+ yield setFile(downloadLastDir, uri1, dir2);
+ is(downloadLastDir.file.path, dir2.path,
+ "downloadLastDir should point to dir2");
+ is((yield getFile(downloadLastDir, uri1)).path, dir2.path,
+ "uri1 should return dir2"); // set in CPS
+ is((yield getFile(downloadLastDir, uri2)).path, dir2.path,
+ "uri2 should return dir2"); // set in CPS
+ is((yield getFile(downloadLastDir, uri3)).path, dir3.path,
+ "uri3 should return dir3"); // set in CPS
+ is((yield getFile(downloadLastDir, uri4)).path, dir2.path,
+ "uri4 should return dir2"); // fallback
+
+ yield clearHistoryAndWait();
+
+ // check clearHistory removes all data
+ is(downloadLastDir.file, null, "clearHistory removes all data");
+ //is(Services.contentPrefs.hasPref(uri1, "browser.download.lastDir", null),
+ // false, "LastDir preference should be absent");
+ is((yield getFile(downloadLastDir, uri1)), null, "uri1 should point to null");
+ is((yield getFile(downloadLastDir, uri2)), null, "uri2 should point to null");
+ is((yield getFile(downloadLastDir, uri3)), null, "uri3 should point to null");
+ is((yield getFile(downloadLastDir, uri4)), null, "uri4 should point to null");
+
+ yield setFile(downloadLastDir, null, tmpDir);
+
+ // check data set outside PB mode is remembered
+ is((yield checkDownloadLastDir(pbDownloadLastDir, tmpDir)).path, tmpDir.path, "uri1 should return the expected last directory");
+ is((yield checkDownloadLastDir(downloadLastDir, tmpDir)).path, tmpDir.path, "uri1 should return the expected last directory");
+ yield clearHistoryAndWait();
+
+ yield setFile(downloadLastDir, uri1, dir1);
+
+ // check data set using CPS outside PB mode is remembered
+ is((yield checkDownloadLastDir(pbDownloadLastDir, dir1)).path, dir1.path, "uri1 should return the expected last directory");
+ is((yield checkDownloadLastDir(downloadLastDir, dir1)).path, dir1.path, "uri1 should return the expected last directory");
+ yield clearHistoryAndWait();
+
+ // check data set inside PB mode is forgotten
+ yield setFile(pbDownloadLastDir, null, tmpDir);
+
+ is((yield checkDownloadLastDir(pbDownloadLastDir, tmpDir)).path, tmpDir.path, "uri1 should return the expected last directory");
+ is((yield checkDownloadLastDirNull(downloadLastDir)), null, "uri1 should return the expected last directory");
+
+ yield clearHistoryAndWait();
+
+ // check data set using CPS inside PB mode is forgotten
+ yield setFile(pbDownloadLastDir, uri1, dir1);
+
+ is((yield checkDownloadLastDir(pbDownloadLastDir, dir1)).path, dir1.path, "uri1 should return the expected last directory");
+ is((yield checkDownloadLastDirNull(downloadLastDir)), null, "uri1 should return the expected last directory");
+
+ // check data set outside PB mode but changed inside is remembered correctly
+ yield setFile(downloadLastDir, uri1, dir1);
+ yield setFile(pbDownloadLastDir, uri1, dir2);
+ is((yield checkDownloadLastDir(pbDownloadLastDir, dir2)).path, dir2.path, "uri1 should return the expected last directory");
+ is((yield checkDownloadLastDir(downloadLastDir, dir1)).path, dir1.path, "uri1 should return the expected last directory");
+
+ /*
+ * ====================
+ * Create new PB window
+ * ====================
+ */
+
+ // check that the last dir store got cleared in a new PB window
+ pbWin.close();
+ // And give it time to close
+ executeSoon(moveAlong);
+ yield;
+ pbWin = yield createWindow({private: true});
+ pbDownloadLastDir = new DownloadLastDir(pbWin);
+
+ is((yield checkDownloadLastDir(pbDownloadLastDir, dir1)).path, dir1.path, "uri1 should return the expected last directory");
+
+ yield clearHistoryAndWait();
+
+ // check clearHistory inside PB mode clears data outside PB mode
+ yield setFile(pbDownloadLastDir, uri1, dir2);
+
+ yield clearHistoryAndWait();
+
+ is((yield checkDownloadLastDirNull(downloadLastDir)), null, "uri1 should return the expected last directory");
+ is((yield checkDownloadLastDirNull(pbDownloadLastDir)), null, "uri1 should return the expected last directory");
+
+ // check that disabling CPS works
+ Services.prefs.setBoolPref("browser.download.lastDir.savePerSite", false);
+
+ yield setFile(downloadLastDir, uri1, dir1);
+ is(downloadLastDir.file.path, dir1.path, "LastDir should be set to dir1");
+ is((yield getFile(downloadLastDir, uri1)).path, dir1.path, "uri1 should return dir1");
+ is((yield getFile(downloadLastDir, uri2)).path, dir1.path, "uri2 should return dir1");
+ is((yield getFile(downloadLastDir, uri3)).path, dir1.path, "uri3 should return dir1");
+ is((yield getFile(downloadLastDir, uri4)).path, dir1.path, "uri4 should return dir1");
+
+ downloadLastDir.setFile(uri2, dir2);
+ is(downloadLastDir.file.path, dir2.path, "LastDir should be set to dir2");
+ is((yield getFile(downloadLastDir, uri1)).path, dir2.path, "uri1 should return dir2");
+ is((yield getFile(downloadLastDir, uri2)).path, dir2.path, "uri2 should return dir2");
+ is((yield getFile(downloadLastDir, uri3)).path, dir2.path, "uri3 should return dir2");
+ is((yield getFile(downloadLastDir, uri4)).path, dir2.path, "uri4 should return dir2");
+
+ Services.prefs.clearUserPref("browser.download.lastDir.savePerSite");
+
+ // check that passing null to setFile clears the stored value
+ yield setFile(downloadLastDir, uri3, dir3);
+ is((yield getFile(downloadLastDir, uri3)).path, dir3.path, "LastDir should be set to dir3");
+ yield setFile(downloadLastDir, uri3, null);
+ is((yield getFile(downloadLastDir, uri3)), null, "uri3 should return null");
+
+ yield clearHistoryAndWait();
+}
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_about.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_about.js
new file mode 100644
index 000000000..e00f3f67a
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_about.js
@@ -0,0 +1,115 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * Opens a new private window and loads "about:privatebrowsing" there.
+ */
+function* openAboutPrivateBrowsing() {
+ let win = yield BrowserTestUtils.openNewBrowserWindow({ private: true });
+ let tab = win.gBrowser.selectedBrowser;
+ tab.loadURI("about:privatebrowsing");
+ yield BrowserTestUtils.browserLoaded(tab);
+ return { win, tab };
+}
+
+/**
+ * Clicks the given link and checks this opens a new tab with the given URI.
+ */
+function* testLinkOpensTab({ win, tab, elementId, expectedUrl }) {
+ let newTabPromise = BrowserTestUtils.waitForNewTab(win.gBrowser, expectedUrl);
+ yield ContentTask.spawn(tab, { elementId }, function* ({ elementId }) {
+ content.document.getElementById(elementId).click();
+ });
+ let newTab = yield newTabPromise;
+ ok(true, `Clicking ${elementId} opened ${expectedUrl} in a new tab.`);
+ yield BrowserTestUtils.removeTab(newTab);
+}
+
+/**
+ * Clicks the given link and checks this opens the given URI in the same tab.
+ *
+ * This function does not return to the previous page.
+ */
+function* testLinkOpensUrl({ win, tab, elementId, expectedUrl }) {
+ let loadedPromise = BrowserTestUtils.browserLoaded(tab);
+ yield ContentTask.spawn(tab, { elementId }, function* ({ elementId }) {
+ content.document.getElementById(elementId).click();
+ });
+ yield loadedPromise;
+ is(tab.currentURI.spec, expectedUrl,
+ `Clicking ${elementId} opened ${expectedUrl} in the same tab.`);
+}
+
+/**
+ * Tests the links in "about:privatebrowsing".
+ */
+add_task(function* test_links() {
+ // Use full version and change the remote URLs to prevent network access.
+ Services.prefs.setCharPref("app.support.baseURL", "https://example.com/");
+ Services.prefs.setCharPref("privacy.trackingprotection.introURL",
+ "https://example.com/tour");
+ registerCleanupFunction(function () {
+ Services.prefs.clearUserPref("privacy.trackingprotection.introURL");
+ Services.prefs.clearUserPref("app.support.baseURL");
+ });
+
+ let { win, tab } = yield openAboutPrivateBrowsing();
+
+ yield testLinkOpensTab({ win, tab,
+ elementId: "learnMore",
+ expectedUrl: "https://example.com/private-browsing",
+ });
+
+ yield testLinkOpensUrl({ win, tab,
+ elementId: "startTour",
+ expectedUrl: "https://example.com/tour",
+ });
+
+ yield BrowserTestUtils.closeWindow(win);
+});
+
+/**
+ * Tests the action to disable and re-enable Tracking Protection in
+ * "about:privatebrowsing".
+ */
+add_task(function* test_toggleTrackingProtection() {
+ // Use tour version but disable Tracking Protection.
+ Services.prefs.setBoolPref("privacy.trackingprotection.pbmode.enabled",
+ true);
+ registerCleanupFunction(function () {
+ Services.prefs.clearUserPref("privacy.trackingprotection.pbmode.enabled");
+ });
+
+ let { win, tab } = yield openAboutPrivateBrowsing();
+
+ // Set up the observer for the preference change before triggering the action.
+ let prefBranch =
+ Services.prefs.getBranch("privacy.trackingprotection.pbmode.");
+ let waitForPrefChanged = () => new Promise(resolve => {
+ let prefObserver = {
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
+ observe: function () {
+ prefBranch.removeObserver("enabled", prefObserver);
+ resolve();
+ },
+ };
+ prefBranch.addObserver("enabled", prefObserver, false);
+ });
+
+ let promisePrefChanged = waitForPrefChanged();
+ yield ContentTask.spawn(tab, {}, function* () {
+ content.document.getElementById("tpButton").click();
+ });
+ yield promisePrefChanged;
+ ok(!prefBranch.getBoolPref("enabled"), "Tracking Protection is disabled.");
+
+ promisePrefChanged = waitForPrefChanged();
+ yield ContentTask.spawn(tab, {}, function* () {
+ content.document.getElementById("tpButton").click();
+ });
+ yield promisePrefChanged;
+ ok(prefBranch.getBoolPref("enabled"), "Tracking Protection is enabled.");
+
+ yield BrowserTestUtils.closeWindow(win);
+});
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_aboutHomeButtonAfterWindowClose.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_aboutHomeButtonAfterWindowClose.js
new file mode 100644
index 000000000..6f52f7719
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_aboutHomeButtonAfterWindowClose.js
@@ -0,0 +1,24 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// This test checks that the Session Restore "Restore Previous Session"
+// button on about:home is disabled in private mode
+add_task(function* test_no_sessionrestore_button() {
+ // Opening, then closing, a private window shouldn't create session data.
+ (yield BrowserTestUtils.openNewBrowserWindow({private: true})).close();
+
+ let win = yield BrowserTestUtils.openNewBrowserWindow({private: true});
+ let tab = win.gBrowser.addTab("about:home");
+ let browser = tab.linkedBrowser;
+
+ yield BrowserTestUtils.browserLoaded(browser);
+
+ yield ContentTask.spawn(browser, null, function* () {
+ let button = content.document.getElementById("restorePreviousSession");
+ Assert.equal(content.getComputedStyle(button).display, "none",
+ "The Session Restore about:home button should be disabled");
+ });
+
+ win.close();
+});
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_aboutSessionRestore.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_aboutSessionRestore.js
new file mode 100644
index 000000000..5f6a91836
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_aboutSessionRestore.js
@@ -0,0 +1,23 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// This test checks that the session restore button from about:sessionrestore
+// is disabled in private mode
+add_task(function* testNoSessionRestoreButton() {
+ // Opening, then closing, a private window shouldn't create session data.
+ (yield BrowserTestUtils.openNewBrowserWindow({private: true})).close();
+
+ let win = yield BrowserTestUtils.openNewBrowserWindow({private: true});
+ let tab = win.gBrowser.addTab("about:sessionrestore");
+ let browser = tab.linkedBrowser;
+
+ yield BrowserTestUtils.browserLoaded(browser);
+
+ yield ContentTask.spawn(browser, null, function* () {
+ Assert.ok(content.document.getElementById("errorTryAgain").disabled,
+ "The Restore about:sessionrestore button should be disabled");
+ });
+
+ win.close();
+});
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_blobUrl.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_blobUrl.js
new file mode 100644
index 000000000..2ceb1032b
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_blobUrl.js
@@ -0,0 +1,45 @@
+"use strict";
+
+// Here we want to test that blob URLs are not available between private and
+// non-private browsing.
+
+const BASE_URI = "http://mochi.test:8888/browser/browser/components/"
+ + "privatebrowsing/test/browser/empty_file.html";
+
+add_task(function* test() {
+ info("Creating a normal window...");
+ let win = yield BrowserTestUtils.openNewBrowserWindow();
+ let tab = win.gBrowser.selectedBrowser;
+ tab.loadURI(BASE_URI);
+ yield BrowserTestUtils.browserLoaded(tab);
+
+ let blobURL;
+
+ info("Creating a blob URL...");
+ yield ContentTask.spawn(tab, null, function() {
+ return Promise.resolve(content.window.URL.createObjectURL(new content.window.Blob([123])));
+ }).then(newURL => { blobURL = newURL });
+
+ info("Blob URL: " + blobURL);
+
+ info("Creating a private window...");
+ let privateWin = yield BrowserTestUtils.openNewBrowserWindow({ private: true });
+ let privateTab = privateWin.gBrowser.selectedBrowser;
+ privateTab.loadURI(BASE_URI);
+ yield BrowserTestUtils.browserLoaded(privateTab);
+
+ yield ContentTask.spawn(privateTab, blobURL, function(url) {
+ return new Promise(resolve => {
+ var xhr = new content.window.XMLHttpRequest();
+ xhr.onerror = function() { resolve("SendErrored"); }
+ xhr.onload = function() { resolve("SendLoaded"); }
+ xhr.open("GET", url);
+ xhr.send();
+ });
+ }).then(status => {
+ is(status, "SendErrored", "Using a blob URI from one user context id in another should not work");
+ });
+
+ yield BrowserTestUtils.closeWindow(win);
+ yield BrowserTestUtils.closeWindow(privateWin);
+});
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_cache.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_cache.js
new file mode 100644
index 000000000..4990f6d3b
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_cache.js
@@ -0,0 +1,138 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Check about:cache after private browsing
+// This test covers MozTrap test 6047
+// bug 880621
+
+var {LoadContextInfo} = Cu.import("resource://gre/modules/LoadContextInfo.jsm", null);
+
+var tmp = {};
+
+Cc["@mozilla.org/moz/jssubscript-loader;1"]
+ .getService(Ci.mozIJSSubScriptLoader)
+ .loadSubScript("chrome://browser/content/sanitize.js", tmp);
+
+var Sanitizer = tmp.Sanitizer;
+
+function test() {
+
+ waitForExplicitFinish();
+
+ sanitizeCache();
+
+ let nrEntriesR1 = getStorageEntryCount("regular", function(nrEntriesR1) {
+ is(nrEntriesR1, 0, "Disk cache reports 0KB and has no entries");
+
+ get_cache_for_private_window();
+ });
+}
+
+function cleanup() {
+ let prefs = Services.prefs.getBranch("privacy.cpd.");
+
+ prefs.clearUserPref("history");
+ prefs.clearUserPref("downloads");
+ prefs.clearUserPref("cache");
+ prefs.clearUserPref("cookies");
+ prefs.clearUserPref("formdata");
+ prefs.clearUserPref("offlineApps");
+ prefs.clearUserPref("passwords");
+ prefs.clearUserPref("sessions");
+ prefs.clearUserPref("siteSettings");
+}
+
+function sanitizeCache() {
+
+ let s = new Sanitizer();
+ s.ignoreTimespan = false;
+ s.prefDomain = "privacy.cpd.";
+
+ let prefs = gPrefService.getBranch(s.prefDomain);
+ prefs.setBoolPref("history", false);
+ prefs.setBoolPref("downloads", false);
+ prefs.setBoolPref("cache", true);
+ prefs.setBoolPref("cookies", false);
+ prefs.setBoolPref("formdata", false);
+ prefs.setBoolPref("offlineApps", false);
+ prefs.setBoolPref("passwords", false);
+ prefs.setBoolPref("sessions", false);
+ prefs.setBoolPref("siteSettings", false);
+
+ s.sanitize();
+}
+
+function get_cache_service() {
+ return Components.classes["@mozilla.org/netwerk/cache-storage-service;1"]
+ .getService(Components.interfaces.nsICacheStorageService);
+}
+
+function getStorageEntryCount(device, goon) {
+ var cs = get_cache_service();
+
+ var storage;
+ switch (device) {
+ case "private":
+ storage = cs.diskCacheStorage(LoadContextInfo.private, false);
+ break;
+ case "regular":
+ storage = cs.diskCacheStorage(LoadContextInfo.default, false);
+ break;
+ default:
+ throw "Unknown device " + device + " at getStorageEntryCount";
+ }
+
+ var visitor = {
+ entryCount: 0,
+ onCacheStorageInfo: function (aEntryCount, aConsumption) {
+ },
+ onCacheEntryInfo: function(uri)
+ {
+ var urispec = uri.asciiSpec;
+ info(device + ":" + urispec + "\n");
+ if (urispec.match(/^http:\/\/example.org\//))
+ ++this.entryCount;
+ },
+ onCacheEntryVisitCompleted: function()
+ {
+ goon(this.entryCount);
+ }
+ };
+
+ storage.asyncVisitStorage(visitor, true);
+}
+
+function get_cache_for_private_window () {
+ let win = whenNewWindowLoaded({private: true}, function() {
+
+ executeSoon(function() {
+
+ ok(true, "The private window got loaded");
+
+ let tab = win.gBrowser.addTab("http://example.org");
+ win.gBrowser.selectedTab = tab;
+ let newTabBrowser = win.gBrowser.getBrowserForTab(tab);
+
+ newTabBrowser.addEventListener("load", function eventHandler() {
+ newTabBrowser.removeEventListener("load", eventHandler, true);
+
+ executeSoon(function() {
+
+ getStorageEntryCount("private", function(nrEntriesP) {
+ ok(nrEntriesP >= 1, "Memory cache reports some entries from example.org domain");
+
+ getStorageEntryCount("regular", function(nrEntriesR2) {
+ is(nrEntriesR2, 0, "Disk cache reports 0KB and has no entries");
+
+ cleanup();
+
+ win.close();
+ finish();
+ });
+ });
+ });
+ }, true);
+ });
+ });
+}
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_certexceptionsui.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_certexceptionsui.js
new file mode 100644
index 000000000..519f43475
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_certexceptionsui.js
@@ -0,0 +1,53 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// This test makes sure that certificate exceptions UI behaves correctly
+// in private browsing windows, based on whether it's opened from the prefs
+// window or from the SSL error page (see bug 461627).
+
+function test() {
+ const EXCEPTIONS_DLG_URL = 'chrome://pippki/content/exceptionDialog.xul';
+ const EXCEPTIONS_DLG_FEATURES = 'chrome,centerscreen';
+ const INVALID_CERT_LOCATION = 'https://nocert.example.com/';
+ waitForExplicitFinish();
+
+ // open a private browsing window
+ var pbWin = OpenBrowserWindow({private: true});
+ pbWin.addEventListener("load", function onLoad() {
+ pbWin.removeEventListener("load", onLoad, false);
+ doTest();
+ }, false);
+
+ // Test the certificate exceptions dialog
+ function doTest() {
+ let params = {
+ exceptionAdded : false,
+ location: INVALID_CERT_LOCATION,
+ prefetchCert: true,
+ };
+ function testCheckbox() {
+ win.removeEventListener("load", testCheckbox, false);
+ Services.obs.addObserver(function onCertUI(aSubject, aTopic, aData) {
+ Services.obs.removeObserver(onCertUI, "cert-exception-ui-ready");
+ ok(win.gCert, "The certificate information should be available now");
+
+ let checkbox = win.document.getElementById("permanent");
+ ok(checkbox.hasAttribute("disabled"),
+ "the permanent checkbox should be disabled when handling the private browsing mode");
+ ok(!checkbox.hasAttribute("checked"),
+ "the permanent checkbox should not be checked when handling the private browsing mode");
+ win.close();
+ cleanup();
+ }, "cert-exception-ui-ready", false);
+ }
+ var win = pbWin.openDialog(EXCEPTIONS_DLG_URL, "", EXCEPTIONS_DLG_FEATURES, params);
+ win.addEventListener("load", testCheckbox, false);
+ }
+
+ function cleanup() {
+ // close the private browsing window
+ pbWin.close();
+ finish();
+ }
+}
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_concurrent.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_concurrent.js
new file mode 100644
index 000000000..b73bbf219
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_concurrent.js
@@ -0,0 +1,88 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Test opening two tabs that share a localStorage, but keep one in private mode.
+// Ensure that values from one don't leak into the other, and that values from
+// earlier private storage sessions aren't visible later.
+
+// Step 1: create new tab, load a page that sets test=value in non-private storage
+// Step 2: create a new tab, load a page that sets test2=value2 in private storage
+// Step 3: load a page in the tab from step 1 that checks the value of test2 is value2 and the total count in non-private storage is 1
+// Step 4: load a page in the tab from step 2 that checks the value of test is value and the total count in private storage is 1
+
+add_task(function* setup() {
+ yield SpecialPowers.pushPrefEnv({
+ set: [["dom.ipc.processCount", 1]]
+ });
+});
+
+add_task(function test() {
+ let prefix = 'http://mochi.test:8888/browser/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_concurrent_page.html';
+
+ function getElts(browser) {
+ return browser.contentTitle.split('|');
+ };
+
+ // Step 1
+ let non_private_browser = gBrowser.selectedBrowser;
+ non_private_browser.loadURI(prefix + '?action=set&name=test&value=value&initial=true');
+ yield BrowserTestUtils.browserLoaded(non_private_browser);
+
+
+ // Step 2
+ let private_window = yield BrowserTestUtils.openNewBrowserWindow({ private : true });
+ let private_browser = private_window.getBrowser().selectedBrowser;
+ private_browser.loadURI(prefix + '?action=set&name=test2&value=value2');
+ yield BrowserTestUtils.browserLoaded(private_browser);
+
+
+ // Step 3
+ non_private_browser.loadURI(prefix + '?action=get&name=test2');
+ yield BrowserTestUtils.browserLoaded(non_private_browser);
+ let elts = yield getElts(non_private_browser);
+ isnot(elts[0], 'value2', "public window shouldn't see private storage");
+ is(elts[1], '1', "public window should only see public items");
+
+
+ // Step 4
+ private_browser.loadURI(prefix + '?action=get&name=test');
+ yield BrowserTestUtils.browserLoaded(private_browser);
+ elts = yield getElts(private_browser);
+ isnot(elts[0], 'value', "private window shouldn't see public storage");
+ is(elts[1], '1', "private window should only see private items");
+
+
+ // Reopen the private window again, without privateBrowsing, which should clear the
+ // the private storage.
+ private_window.close();
+ private_window = yield BrowserTestUtils.openNewBrowserWindow({ private : false });
+ private_browser = null;
+ yield new Promise(resolve => Cu.schedulePreciseGC(resolve));
+ private_browser = private_window.getBrowser().selectedBrowser;
+
+ private_browser.loadURI(prefix + '?action=get&name=test2');
+ yield BrowserTestUtils.browserLoaded(private_browser);
+ elts = yield getElts(private_browser);
+ isnot(elts[0], 'value2', "public window shouldn't see cleared private storage");
+ is(elts[1], '1', "public window should only see public items");
+
+
+ // Making it private again should clear the storage and it shouldn't
+ // be able to see the old private storage as well.
+ private_window.close();
+ private_window = yield BrowserTestUtils.openNewBrowserWindow({ private : true });
+ private_browser = null;
+ yield new Promise(resolve => Cu.schedulePreciseGC(resolve));
+ private_browser = private_window.getBrowser().selectedBrowser;
+
+ private_browser.loadURI(prefix + '?action=set&name=test3&value=value3');
+ yield BrowserTestUtils.browserLoaded(private_browser);
+ elts = yield getElts(private_browser);
+ is(elts[1], '1', "private window should only see new private items");
+
+ // Cleanup.
+ non_private_browser.loadURI(prefix + '?final=true');
+ yield BrowserTestUtils.browserLoaded(non_private_browser);
+ private_window.close();
+});
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_concurrent_page.html b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_concurrent_page.html
new file mode 100644
index 000000000..db35b114d
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_concurrent_page.html
@@ -0,0 +1,33 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<script type="text/javascript">
+ var oGetVars = {};
+
+ if (window.location.search.length > 1) {
+ for (var aItKey, nKeyId = 0, aCouples = window.location.search.substr(1).split("&");
+ nKeyId < aCouples.length;
+ nKeyId++) {
+ aItKey = aCouples[nKeyId].split("=");
+ oGetVars[unescape(aItKey[0])] = aItKey.length > 1 ? unescape(aItKey[1]) : "";
+ }
+ }
+
+ if (oGetVars.initial == 'true') {
+ localStorage.clear();
+ }
+
+ if (oGetVars.action == 'set') {
+ localStorage.setItem(oGetVars.name, oGetVars.value);
+ document.title = localStorage.getItem(oGetVars.name) + "|" + localStorage.length;
+ } else if (oGetVars.action == 'get') {
+ document.title = localStorage.getItem(oGetVars.name) + "|" + localStorage.length;
+ }
+
+ if (oGetVars.final == 'true') {
+ localStorage.clear();
+ }
+</script>
+</head>
+<body>
+</body>
+</html>
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_context_and_chromeFlags.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_context_and_chromeFlags.js
new file mode 100644
index 000000000..30f7ee025
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_context_and_chromeFlags.js
@@ -0,0 +1,60 @@
+"use strict";
+
+/**
+ * Given some window in the parent process, ensure that
+ * the nsIXULWindow has the CHROME_PRIVATE_WINDOW chromeFlag,
+ * and that the usePrivateBrowsing property is set to true on
+ * both the window's nsILoadContext, as well as on the initial
+ * browser's content docShell nsILoadContext.
+ *
+ * @param win (nsIDOMWindow)
+ * An nsIDOMWindow in the parent process.
+ * @return Promise
+ */
+function assertWindowIsPrivate(win) {
+ let winDocShell = win.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIDocShell);
+ let chromeFlags = winDocShell.QueryInterface(Ci.nsIDocShellTreeItem)
+ .treeOwner
+ .QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIXULWindow)
+ .chromeFlags;
+
+ if (!win.gBrowser.selectedBrowser.hasContentOpener) {
+ Assert.ok(chromeFlags & Ci.nsIWebBrowserChrome.CHROME_PRIVATE_WINDOW,
+ "Should have the private window chrome flag");
+ }
+
+ let loadContext = winDocShell.QueryInterface(Ci.nsILoadContext);
+ Assert.ok(loadContext.usePrivateBrowsing,
+ "The parent window should be using private browsing");
+
+ return ContentTask.spawn(win.gBrowser.selectedBrowser, null, function*() {
+ let loadContext = docShell.QueryInterface(Ci.nsILoadContext);
+ Assert.ok(loadContext.usePrivateBrowsing,
+ "Content docShell should be using private browsing");
+ });
+}
+
+/**
+ * Tests that chromeFlags bits and the nsILoadContext.usePrivateBrowsing
+ * attribute are properly set when opening a new private browsing
+ * window.
+ */
+add_task(function* test_context_and_chromeFlags() {
+ let win = yield BrowserTestUtils.openNewBrowserWindow({ private: true });
+ yield assertWindowIsPrivate(win);
+
+ let browser = win.gBrowser.selectedBrowser;
+
+ let newWinPromise = BrowserTestUtils.waitForNewWindow();
+ yield ContentTask.spawn(browser, null, function*() {
+ content.open("http://example.com", "_blank", "width=100,height=100");
+ });
+
+ let win2 = yield newWinPromise;
+ yield assertWindowIsPrivate(win2);
+
+ yield BrowserTestUtils.closeWindow(win2);
+ yield BrowserTestUtils.closeWindow(win);
+});
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_crh.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_crh.js
new file mode 100644
index 000000000..cd316d1fb
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_crh.js
@@ -0,0 +1,42 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// This test makes sure that the Clear Recent History menu item and command
+// is disabled inside the private browsing mode.
+
+add_task(function test() {
+ function checkDisableOption(aPrivateMode, aWindow) {
+ let crhCommand = aWindow.document.getElementById("Tools:Sanitize");
+ ok(crhCommand, "The clear recent history command should exist");
+
+ is(PrivateBrowsingUtils.isWindowPrivate(aWindow), aPrivateMode,
+ "PrivateBrowsingUtils should report the correct per-window private browsing status");
+ is(crhCommand.hasAttribute("disabled"), aPrivateMode,
+ "Clear Recent History command should be disabled according to the private browsing mode");
+ };
+
+ let testURI = "http://mochi.test:8888/";
+
+ let privateWin = yield BrowserTestUtils.openNewBrowserWindow({private: true});
+ let privateBrowser = privateWin.gBrowser.selectedBrowser;
+ privateBrowser.loadURI(testURI);
+ yield BrowserTestUtils.browserLoaded(privateBrowser);
+
+ info("Test on private window");
+ checkDisableOption(true, privateWin);
+
+
+ let win = yield BrowserTestUtils.openNewBrowserWindow();
+ let browser = win.gBrowser.selectedBrowser;
+ browser.loadURI(testURI);
+ yield BrowserTestUtils.browserLoaded(browser);
+
+ info("Test on public window");
+ checkDisableOption(false, win);
+
+
+ // Cleanup
+ yield BrowserTestUtils.closeWindow(privateWin);
+ yield BrowserTestUtils.closeWindow(win);
+});
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadLastDir.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadLastDir.js
new file mode 100644
index 000000000..81b2943ee
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadLastDir.js
@@ -0,0 +1,93 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+function test() {
+ waitForExplicitFinish();
+
+ let FileUtils =
+ Cu.import("resource://gre/modules/FileUtils.jsm", {}).FileUtils;
+ let DownloadLastDir =
+ Cu.import("resource://gre/modules/DownloadLastDir.jsm", {}).DownloadLastDir;
+ let MockFilePicker = SpecialPowers.MockFilePicker;
+ let launcher = {
+ source: Services.io.newURI("http://test1.com/file", null, null)
+ };
+
+ MockFilePicker.init(window);
+ MockFilePicker.returnValue = Ci.nsIFilePicker.returnOK;
+
+ let prefs = Services.prefs.getBranch("browser.download.");
+ let launcherDialog =
+ Cc["@mozilla.org/helperapplauncherdialog;1"].
+ getService(Ci.nsIHelperAppLauncherDialog);
+ let tmpDir = FileUtils.getDir("TmpD", [], true);
+ let dir1 = newDirectory();
+ let dir2 = newDirectory();
+ let dir3 = newDirectory();
+ let file1 = newFileInDirectory(dir1);
+ let file2 = newFileInDirectory(dir2);
+ let file3 = newFileInDirectory(dir3);
+
+ // cleanup functions registration
+ registerCleanupFunction(function () {
+ Services.prefs.clearUserPref("browser.download.lastDir");
+ [dir1, dir2, dir3].forEach(dir => dir.remove(true));
+ MockFilePicker.cleanup();
+ });
+ prefs.setComplexValue("lastDir", Ci.nsIFile, tmpDir);
+
+ function testOnWindow(aPrivate, aCallback) {
+ whenNewWindowLoaded({private: aPrivate}, function(win) {
+ let gDownloadLastDir = new DownloadLastDir(win);
+ aCallback(win, gDownloadLastDir);
+ gDownloadLastDir.cleanupPrivateFile();
+ });
+ }
+
+ function testDownloadDir(aWin, gDownloadLastDir, aFile, aDisplayDir, aLastDir,
+ aGlobalLastDir, aCallback) {
+ // Check lastDir preference.
+ is(prefs.getComplexValue("lastDir", Ci.nsIFile).path, aDisplayDir.path,
+ "LastDir should be the expected display dir");
+ // Check gDownloadLastDir value.
+ is(gDownloadLastDir.file.path, aDisplayDir.path,
+ "gDownloadLastDir should be the expected display dir");
+
+ MockFilePicker.returnFiles = [aFile];
+ MockFilePicker.displayDirectory = null;
+
+ launcher.saveDestinationAvailable = function (file) {
+ ok(!!file, "promptForSaveToFile correctly returned a file");
+
+ // File picker should start with expected display dir.
+ is(MockFilePicker.displayDirectory.path, aDisplayDir.path,
+ "File picker should start with browser.download.lastDir");
+ // browser.download.lastDir should be modified on not private windows
+ is(prefs.getComplexValue("lastDir", Ci.nsIFile).path, aLastDir.path,
+ "LastDir should be the expected last dir");
+ // gDownloadLastDir should be usable outside of private windows
+ is(gDownloadLastDir.file.path, aGlobalLastDir.path,
+ "gDownloadLastDir should be the expected global last dir");
+
+ launcher.saveDestinationAvailable = null;
+ aWin.close();
+ aCallback();
+ };
+
+ launcherDialog.promptForSaveToFileAsync(launcher, aWin, null, null, null);
+ }
+
+ testOnWindow(false, function(win, downloadDir) {
+ testDownloadDir(win, downloadDir, file1, tmpDir, dir1, dir1, function() {
+ testOnWindow(true, function(win, downloadDir) {
+ testDownloadDir(win, downloadDir, file2, dir1, dir1, dir2, function() {
+ testOnWindow(false, function(win, downloadDir) {
+ testDownloadDir(win, downloadDir, file3, dir1, dir3, dir3, finish);
+ });
+ });
+ });
+ });
+ });
+}
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadLastDir_c.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadLastDir_c.js
new file mode 100644
index 000000000..5a04d1999
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadLastDir_c.js
@@ -0,0 +1,95 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+function test() {
+ waitForExplicitFinish();
+
+ let FileUtils =
+ Cu.import("resource://gre/modules/FileUtils.jsm", {}).FileUtils;
+ let DownloadLastDir =
+ Cu.import("resource://gre/modules/DownloadLastDir.jsm", {}).DownloadLastDir;
+ let MockFilePicker = SpecialPowers.MockFilePicker;
+
+ MockFilePicker.init(window);
+ MockFilePicker.returnValue = Ci.nsIFilePicker.returnOK;
+
+ let validateFileNameToRestore = validateFileName;
+ let prefs = Services.prefs.getBranch("browser.download.");
+ let tmpDir = FileUtils.getDir("TmpD", [], true);
+ let dir1 = newDirectory();
+ let dir2 = newDirectory();
+ let dir3 = newDirectory();
+ let file1 = newFileInDirectory(dir1);
+ let file2 = newFileInDirectory(dir2);
+ let file3 = newFileInDirectory(dir3);
+
+ // cleanup function registration
+ registerCleanupFunction(function () {
+ Services.prefs.clearUserPref("browser.download.lastDir");
+ [dir1, dir2, dir3].forEach(dir => dir.remove(true));
+ MockFilePicker.cleanup();
+ validateFileName = validateFileNameToRestore;
+ });
+
+ // Overwrite validateFileName to validate everything
+ validateFileName = foo => foo;
+
+ let params = {
+ fileInfo: new FileInfo("test.txt", "test.txt", "test", "txt", "http://mozilla.org/test.txt"),
+ contentType: "text/plain",
+ saveMode: SAVEMODE_FILEONLY,
+ saveAsType: kSaveAsType_Complete,
+ file: null
+ };
+
+ prefs.setComplexValue("lastDir", Ci.nsIFile, tmpDir);
+
+ function testOnWindow(aPrivate, aCallback) {
+ whenNewWindowLoaded({private: aPrivate}, function(win) {
+ let gDownloadLastDir = new DownloadLastDir(win);
+ aCallback(win, gDownloadLastDir);
+ });
+ }
+
+ function testDownloadDir(aWin, gDownloadLastDir, aFile, aDisplayDir, aLastDir,
+ aGlobalLastDir, aCallback) {
+ // Check lastDir preference.
+ is(prefs.getComplexValue("lastDir", Ci.nsIFile).path, aDisplayDir.path,
+ "LastDir should be the expected display dir");
+ // Check gDownloadLastDir value.
+ is(gDownloadLastDir.file.path, aDisplayDir.path,
+ "gDownloadLastDir should be the expected display dir");
+
+ MockFilePicker.returnFiles = [aFile];
+ MockFilePicker.displayDirectory = null;
+ aWin.promiseTargetFile(params).then(function() {
+ // File picker should start with expected display dir.
+ is(MockFilePicker.displayDirectory.path, aDisplayDir.path,
+ "File picker should start with browser.download.lastDir");
+ // browser.download.lastDir should be modified on not private windows
+ is(prefs.getComplexValue("lastDir", Ci.nsIFile).path, aLastDir.path,
+ "LastDir should be the expected last dir");
+ // gDownloadLastDir should be usable outside of private windows
+ is(gDownloadLastDir.file.path, aGlobalLastDir.path,
+ "gDownloadLastDir should be the expected global last dir");
+
+ gDownloadLastDir.cleanupPrivateFile();
+ aWin.close();
+ aCallback();
+ }).then(null, function() { ok(false); });
+ }
+
+ testOnWindow(false, function(win, downloadDir) {
+ testDownloadDir(win, downloadDir, file1, tmpDir, dir1, dir1, function() {
+ testOnWindow(true, function(win, downloadDir) {
+ testDownloadDir(win, downloadDir, file2, dir1, dir1, dir2, function() {
+ testOnWindow(false, function(win, downloadDir) {
+ testDownloadDir(win, downloadDir, file3, dir1, dir3, dir3, finish);
+ });
+ });
+ });
+ });
+ });
+}
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadLastDir_toggle.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadLastDir_toggle.js
new file mode 100644
index 000000000..b192c08f7
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadLastDir_toggle.js
@@ -0,0 +1,105 @@
+Cu.import("resource://gre/modules/FileUtils.jsm");
+Cu.import("resource://gre/modules/DownloadLastDir.jsm");
+
+/**
+ * Tests how the browser remembers the last download folder
+ * from download to download, with a particular emphasis
+ * on how it behaves when private browsing windows open.
+ */
+add_task(function* test_downloads_last_dir_toggle() {
+ let tmpDir = FileUtils.getDir("TmpD", [], true);
+ let dir1 = newDirectory();
+
+ registerCleanupFunction(function () {
+ Services.prefs.clearUserPref("browser.download.lastDir");
+ dir1.remove(true);
+ });
+
+ let win = yield BrowserTestUtils.openNewBrowserWindow();
+ let gDownloadLastDir = new DownloadLastDir(win);
+ is(typeof gDownloadLastDir, "object",
+ "gDownloadLastDir should be a valid object");
+ is(gDownloadLastDir.file, null,
+ "gDownloadLastDir.file should be null to start with");
+
+ gDownloadLastDir.file = tmpDir;
+ is(gDownloadLastDir.file.path, tmpDir.path,
+ "LastDir should point to the temporary directory");
+ isnot(gDownloadLastDir.file, tmpDir,
+ "gDownloadLastDir.file should not be pointing to the tmpDir");
+
+ gDownloadLastDir.file = 1; // not an nsIFile
+ is(gDownloadLastDir.file, null, "gDownloadLastDir.file should be null");
+
+ gDownloadLastDir.file = tmpDir;
+ clearHistory();
+ is(gDownloadLastDir.file, null, "gDownloadLastDir.file should be null");
+
+ gDownloadLastDir.file = tmpDir;
+ yield BrowserTestUtils.closeWindow(win);
+
+ info("Opening the first private window");
+ yield testHelper({ private: true, expectedDir: tmpDir });
+ info("Opening a non-private window");
+ yield testHelper({ private: false, expectedDir: tmpDir });
+ info("Opening a private window and setting download directory");
+ yield testHelper({ private: true, setDir: dir1, expectedDir: dir1 });
+ info("Opening a non-private window and checking download directory");
+ yield testHelper({ private: false, expectedDir: tmpDir });
+ info("Opening private window and clearing history");
+ yield testHelper({ private: true, clearHistory: true, expectedDir: null });
+ info("Opening a non-private window and checking download directory");
+ yield testHelper({ private: true, expectedDir: null });
+});
+
+/**
+ * Opens a new window and performs some test actions on it based
+ * on the options object that have been passed in.
+ *
+ * @param options (Object)
+ * An object with the following properties:
+ *
+ * clearHistory (bool, optional):
+ * Whether or not to simulate clearing session history.
+ * Defaults to false.
+ *
+ * setDir (nsIFile, optional):
+ * An nsIFile for setting the last download directory.
+ * If not set, the load download directory is not changed.
+ *
+ * expectedDir (nsIFile, expectedDir):
+ * An nsIFile for what we expect the last download directory
+ * should be. The nsIFile is not compared directly - only
+ * paths are compared. If expectedDir is not set, then the
+ * last download directory is expected to be null.
+ *
+ * @returns Promise
+ */
+function testHelper(options) {
+ return new Task.spawn(function() {
+ let win = yield BrowserTestUtils.openNewBrowserWindow(options);
+ let gDownloadLastDir = new DownloadLastDir(win);
+
+ if (options.clearHistory) {
+ clearHistory();
+ }
+
+ if (options.setDir) {
+ gDownloadLastDir.file = options.setDir;
+ }
+
+ let expectedDir = options.expectedDir;
+
+ if (expectedDir) {
+ is(gDownloadLastDir.file.path, expectedDir.path,
+ "gDownloadLastDir should point to the expected last directory");
+ isnot(gDownloadLastDir.file, expectedDir,
+ "gDownloadLastDir.file should not be pointing to the last directory");
+ } else {
+ is(gDownloadLastDir.file, null, "gDownloadLastDir should be null");
+ }
+
+ gDownloadLastDir.cleanupPrivateFile();
+ yield BrowserTestUtils.closeWindow(win);
+ });
+}
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_favicon.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_favicon.js
new file mode 100644
index 000000000..86f714082
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_favicon.js
@@ -0,0 +1,293 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// This test make sure that the favicon of the private browsing is isolated.
+
+const { classes: Cc, Constructor: CC, interfaces: Ci, utils: Cu } = Components;
+
+const TEST_SITE = "http://mochi.test:8888";
+const TEST_CACHE_SITE = "http://www.example.com";
+const TEST_DIRECTORY = "/browser/browser/components/privatebrowsing/test/browser/";
+
+const TEST_PAGE = TEST_SITE + TEST_DIRECTORY + "file_favicon.html";
+const TEST_CACHE_PAGE = TEST_CACHE_SITE + TEST_DIRECTORY + "file_favicon.html";
+const FAVICON_URI = TEST_SITE + TEST_DIRECTORY + "file_favicon.png";
+const FAVICON_CACHE_URI = TEST_CACHE_SITE + TEST_DIRECTORY + "file_favicon.png";
+
+let systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal();
+let makeURI = Cu.import("resource://gre/modules/BrowserUtils.jsm", {}).BrowserUtils.makeURI;
+
+function clearAllImageCaches() {
+ let tools = SpecialPowers.Cc["@mozilla.org/image/tools;1"]
+ .getService(SpecialPowers.Ci.imgITools);
+ let imageCache = tools.getImgCacheForDocument(window.document);
+ imageCache.clearCache(true); // true=chrome
+ imageCache.clearCache(false); // false=content
+}
+
+function clearAllPlacesFavicons() {
+ let faviconService = Cc["@mozilla.org/browser/favicon-service;1"]
+ .getService(Ci.nsIFaviconService);
+
+ return new Promise(resolve => {
+ let observer = {
+ observe(aSubject, aTopic, aData) {
+ if (aTopic === "places-favicons-expired") {
+ resolve();
+ Services.obs.removeObserver(observer, "places-favicons-expired", false);
+ }
+ }
+ };
+
+ Services.obs.addObserver(observer, "places-favicons-expired", false);
+ faviconService.expireAllFavicons();
+ });
+}
+
+function observeFavicon(aIsPrivate, aExpectedCookie, aPageURI) {
+ let faviconReqXUL = false;
+ let faviconReqPlaces = false;
+ let attr = {};
+
+ if (aIsPrivate) {
+ attr.privateBrowsingId = 1;
+ }
+
+ let expectedPrincipal = Services.scriptSecurityManager
+ .createCodebasePrincipal(aPageURI, attr);
+
+ return new Promise(resolve => {
+ let observer = {
+ observe(aSubject, aTopic, aData) {
+ // Make sure that the topic is 'http-on-modify-request'.
+ if (aTopic === "http-on-modify-request") {
+ // We check the privateBrowsingId for the originAttributes of the loading
+ // channel. All requests for the favicon should contain the correct
+ // privateBrowsingId. There are two requests for a favicon loading, one
+ // from the Places library and one from the XUL image. The difference
+ // of them is the loading principal. The Places will use the content
+ // principal and the XUL image will use the system principal.
+
+ let httpChannel = aSubject.QueryInterface(Ci.nsIHttpChannel);
+ let reqLoadInfo = httpChannel.loadInfo;
+ let loadingPrincipal = reqLoadInfo.loadingPrincipal;
+ let triggeringPrincipal = reqLoadInfo.triggeringPrincipal;
+
+ // Make sure this is a favicon request.
+ if (httpChannel.URI.spec !== FAVICON_URI) {
+ return;
+ }
+
+ // Check the privateBrowsingId.
+ if (aIsPrivate) {
+ is(reqLoadInfo.originAttributes.privateBrowsingId, 1, "The loadInfo has correct privateBrowsingId");
+ } else {
+ is(reqLoadInfo.originAttributes.privateBrowsingId, 0, "The loadInfo has correct privateBrowsingId");
+ }
+
+ if (loadingPrincipal.equals(systemPrincipal)) {
+ faviconReqXUL = true;
+ ok(triggeringPrincipal.equals(expectedPrincipal),
+ "The triggeringPrincipal of favicon loading from XUL should be the content principal.");
+ } else {
+ faviconReqPlaces = true;
+ ok(loadingPrincipal.equals(expectedPrincipal),
+ "The loadingPrincipal of favicon loading from Places should be the content prinicpal");
+ }
+
+ let faviconCookie = httpChannel.getRequestHeader("cookie");
+
+ is(faviconCookie, aExpectedCookie, "The cookie of the favicon loading is correct.");
+ } else {
+ ok(false, "Received unexpected topic: ", aTopic);
+ }
+
+ if (faviconReqXUL && faviconReqPlaces) {
+ resolve();
+ Services.obs.removeObserver(observer, "http-on-modify-request", false);
+ }
+ }
+ };
+
+ Services.obs.addObserver(observer, "http-on-modify-request", false);
+ });
+}
+
+function waitOnFaviconResponse(aFaviconURL) {
+ return new Promise(resolve => {
+ let observer = {
+ observe(aSubject, aTopic, aData) {
+ if (aTopic === "http-on-examine-response" ||
+ aTopic === "http-on-examine-cached-response") {
+
+ let httpChannel = aSubject.QueryInterface(Ci.nsIHttpChannel);
+ let loadInfo = httpChannel.loadInfo;
+
+ if (httpChannel.URI.spec !== aFaviconURL) {
+ return;
+ }
+
+ let result = {
+ topic: aTopic,
+ privateBrowsingId: loadInfo.originAttributes.privateBrowsingId
+ };
+
+ resolve(result);
+ Services.obs.removeObserver(observer, "http-on-examine-response", false);
+ Services.obs.removeObserver(observer, "http-on-examine-cached-response", false);
+ }
+ }
+ };
+
+ Services.obs.addObserver(observer, "http-on-examine-response", false);
+ Services.obs.addObserver(observer, "http-on-examine-cached-response", false);
+ });
+}
+
+function waitOnFaviconLoaded(aFaviconURL) {
+ return new Promise(resolve => {
+ let observer = {
+ onPageChanged(uri, attr, value, id) {
+
+ if (attr === Ci.nsINavHistoryObserver.ATTRIBUTE_FAVICON &&
+ value === aFaviconURL) {
+ resolve();
+ PlacesUtils.history.removeObserver(observer, false);
+ }
+ },
+ };
+
+ PlacesUtils.history.addObserver(observer, false);
+ });
+}
+
+function* assignCookies(aBrowser, aURL, aCookieValue){
+ let tabInfo = yield openTab(aBrowser, aURL);
+
+ yield ContentTask.spawn(tabInfo.browser, aCookieValue, function* (value) {
+ content.document.cookie = value;
+ });
+
+ yield BrowserTestUtils.removeTab(tabInfo.tab);
+}
+
+function* openTab(aBrowser, aURL) {
+ let tab = aBrowser.addTab(aURL);
+
+ // Select tab and make sure its browser is focused.
+ aBrowser.selectedTab = tab;
+ tab.ownerGlobal.focus();
+
+ let browser = aBrowser.getBrowserForTab(tab);
+ yield BrowserTestUtils.browserLoaded(browser);
+ return {tab, browser};
+}
+
+// A clean up function to prevent affecting other tests.
+registerCleanupFunction(() => {
+ // Clear all cookies.
+ let cookieMgr = Cc["@mozilla.org/cookiemanager;1"]
+ .getService(Ci.nsICookieManager);
+ cookieMgr.removeAll();
+
+ // Clear all image caches and network caches.
+ clearAllImageCaches();
+
+ let networkCache = Cc["@mozilla.org/netwerk/cache-storage-service;1"]
+ .getService(Ci.nsICacheStorageService);
+ networkCache.clear();
+});
+
+add_task(function* test_favicon_privateBrowsing() {
+ // Clear all image caches before running the test.
+ clearAllImageCaches();
+
+ // Clear all favicons in Places.
+ yield clearAllPlacesFavicons();
+
+ // Create a private browsing window.
+ let privateWindow = yield BrowserTestUtils.openNewBrowserWindow({ private: true });
+ let pageURI = makeURI(TEST_PAGE);
+
+ // Generate two random cookies for non-private window and private window
+ // respectively.
+ let cookies = [];
+ cookies.push(Math.random().toString());
+ cookies.push(Math.random().toString());
+
+ // Open a tab in private window and add a cookie into it.
+ yield assignCookies(privateWindow.gBrowser, TEST_SITE, cookies[0]);
+
+ // Open a tab in non-private window and add a cookie into it.
+ yield assignCookies(gBrowser, TEST_SITE, cookies[1]);
+
+ // Add the observer earlier in case we don't capture events in time.
+ let promiseObserveFavicon = observeFavicon(true, cookies[0], pageURI);
+
+ // Open a tab for the private window.
+ let tabInfo = yield openTab(privateWindow.gBrowser, TEST_PAGE);
+
+ // Waiting until favicon requests are all made.
+ yield promiseObserveFavicon;
+
+ // Close the tab.
+ yield BrowserTestUtils.removeTab(tabInfo.tab);
+
+ // Add the observer earlier in case we don't capture events in time.
+ promiseObserveFavicon = observeFavicon(false, cookies[1], pageURI);
+
+ // Open a tab for the non-private window.
+ tabInfo = yield openTab(gBrowser, TEST_PAGE);
+
+ // Waiting until favicon requests are all made.
+ yield promiseObserveFavicon;
+
+ // Close the tab.
+ yield BrowserTestUtils.removeTab(tabInfo.tab);
+ yield BrowserTestUtils.closeWindow(privateWindow);
+});
+
+add_task(function* test_favicon_cache_privateBrowsing() {
+ // Clear all image cahces and network cache before running the test.
+ clearAllImageCaches();
+
+ let networkCache = Cc["@mozilla.org/netwerk/cache-storage-service;1"]
+ .getService(Ci.nsICacheStorageService);
+ networkCache.clear();
+
+ // Clear all favicons in Places.
+ yield clearAllPlacesFavicons();
+
+ // Add an observer for making sure the favicon has been loaded and cached.
+ let promiseFaviconLoaded = waitOnFaviconLoaded(FAVICON_CACHE_URI);
+
+ // Open a tab for the non-private window.
+ let tabInfoNonPrivate = yield openTab(gBrowser, TEST_CACHE_PAGE);
+
+ let response = yield waitOnFaviconResponse(FAVICON_CACHE_URI);
+
+ yield promiseFaviconLoaded;
+
+ // Check that the favicon response has come from the network and it has the
+ // correct privateBrowsingId.
+ is(response.topic, "http-on-examine-response", "The favicon image should be loaded through network.");
+ is(response.privateBrowsingId, 0, "We should observe the network response for the non-private tab.");
+
+ // Create a private browsing window.
+ let privateWindow = yield BrowserTestUtils.openNewBrowserWindow({ private: true });
+
+ // Open a tab for the private window.
+ let tabInfoPrivate = yield openTab(privateWindow.gBrowser, TEST_CACHE_PAGE);
+
+ // Wait for the favicon response of the private tab.
+ response = yield waitOnFaviconResponse(FAVICON_CACHE_URI);
+
+ // Make sure the favicon is loaded through the network and its privateBrowsingId is correct.
+ is(response.topic, "http-on-examine-response", "The favicon image should be loaded through the network again.");
+ is(response.privateBrowsingId, 1, "We should observe the network response for the private tab.");
+
+ yield BrowserTestUtils.removeTab(tabInfoPrivate.tab);
+ yield BrowserTestUtils.removeTab(tabInfoNonPrivate.tab);
+ yield BrowserTestUtils.closeWindow(privateWindow);
+});
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_geoprompt.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_geoprompt.js
new file mode 100644
index 000000000..3a078ffc1
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_geoprompt.js
@@ -0,0 +1,54 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// This test makes sure that the geolocation prompt does not show a remember
+// control inside the private browsing mode.
+
+add_task(function* test() {
+ const testPageURL = "http://mochi.test:8888/browser/" +
+ "browser/components/privatebrowsing/test/browser/browser_privatebrowsing_geoprompt_page.html";
+
+ function checkGeolocation(aPrivateMode, aWindow) {
+ return Task.spawn(function* () {
+ aWindow.gBrowser.selectedTab = aWindow.gBrowser.addTab(testPageURL);
+ yield BrowserTestUtils.browserLoaded(aWindow.gBrowser.selectedBrowser);
+
+ let notification = aWindow.PopupNotifications.getNotification("geolocation");
+
+ // Wait until the notification is available.
+ while (!notification){
+ yield new Promise(resolve => { executeSoon(resolve); });
+ let notification = aWindow.PopupNotifications.getNotification("geolocation");
+ }
+
+ if (aPrivateMode) {
+ // Make sure the notification is correctly displayed without a remember control
+ is(notification.secondaryActions.length, 0, "Secondary actions shouldn't exist (always/never remember)");
+ } else {
+ ok(notification.secondaryActions.length > 1, "Secondary actions should exist (always/never remember)");
+ }
+ notification.remove();
+
+ aWindow.gBrowser.removeCurrentTab();
+ });
+ };
+
+ let win = yield BrowserTestUtils.openNewBrowserWindow();
+ let browser = win.gBrowser.selectedBrowser;
+ browser.loadURI(testPageURL);
+ yield BrowserTestUtils.browserLoaded(browser);
+
+ yield checkGeolocation(false, win);
+
+ let privateWin = yield BrowserTestUtils.openNewBrowserWindow({private: true});
+ let privateBrowser = privateWin.gBrowser.selectedBrowser;
+ privateBrowser.loadURI(testPageURL);
+ yield BrowserTestUtils.browserLoaded(privateBrowser);
+
+ yield checkGeolocation(true, privateWin);
+
+ // Cleanup
+ yield BrowserTestUtils.closeWindow(win);
+ yield BrowserTestUtils.closeWindow(privateWin);
+});
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_geoprompt_page.html b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_geoprompt_page.html
new file mode 100644
index 000000000..36d5e3cec
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_geoprompt_page.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<html>
+ <head>
+ <title>Geolocation invoker</title>
+ </head>
+ <body>
+ <script type="text/javascript">
+ navigator.geolocation.getCurrentPosition(function (pos) {
+ // ignore
+ });
+ </script>
+ </body>
+</html>
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_lastpbcontextexited.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_lastpbcontextexited.js
new file mode 100644
index 000000000..dbe8ed060
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_lastpbcontextexited.js
@@ -0,0 +1,49 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+function test() {
+ // We need to open a new window for this so that its docshell would get destroyed
+ // when clearing the PB mode flag.
+ function runTest(aCloseWindow, aCallback) {
+ let newWin = OpenBrowserWindow({private: true});
+ SimpleTest.waitForFocus(function() {
+ let expectedExiting = true;
+ let expectedExited = false;
+ let observerExiting = {
+ observe: function(aSubject, aTopic, aData) {
+ is(aTopic, "last-pb-context-exiting", "Correct topic should be dispatched (exiting)");
+ is(expectedExiting, true, "notification not expected yet (exiting)");
+ expectedExited = true;
+ Services.obs.removeObserver(observerExiting, "last-pb-context-exiting");
+ }
+ };
+ let observerExited = {
+ observe: function(aSubject, aTopic, aData) {
+ is(aTopic, "last-pb-context-exited", "Correct topic should be dispatched (exited)");
+ is(expectedExited, true, "notification not expected yet (exited)");
+ Services.obs.removeObserver(observerExited, "last-pb-context-exited");
+ aCallback();
+ }
+ };
+ Services.obs.addObserver(observerExiting, "last-pb-context-exiting", false);
+ Services.obs.addObserver(observerExited, "last-pb-context-exited", false);
+ expectedExiting = true;
+ aCloseWindow(newWin);
+ newWin = null;
+ SpecialPowers.forceGC();
+ }, newWin);
+ }
+
+ waitForExplicitFinish();
+
+ runTest(function(newWin) {
+ // Simulate pressing the window close button
+ newWin.document.getElementById("cmd_closeWindow").doCommand();
+ }, function () {
+ runTest(function(newWin) {
+ // Simulate closing the last tab
+ newWin.document.getElementById("cmd_close").doCommand();
+ }, finish);
+ });
+}
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_localStorage.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_localStorage.js
new file mode 100644
index 000000000..acccb5e2d
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_localStorage.js
@@ -0,0 +1,25 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+ add_task(function test() {
+ requestLongerTimeout(2);
+ const page1 = 'http://mochi.test:8888/browser/browser/components/privatebrowsing/test/browser/' +
+ 'browser_privatebrowsing_localStorage_page1.html'
+
+ let win = yield BrowserTestUtils.openNewBrowserWindow({private: true});
+
+ let tab = win.gBrowser.selectedTab = win.gBrowser.addTab(page1);
+ let browser = win.gBrowser.selectedBrowser;
+ yield BrowserTestUtils.browserLoaded(browser);
+
+ browser.loadURI(
+ 'http://mochi.test:8888/browser/browser/components/privatebrowsing/test/browser/' +
+ 'browser_privatebrowsing_localStorage_page2.html');
+ yield BrowserTestUtils.browserLoaded(browser);
+
+ is(browser.contentTitle, '2', "localStorage should contain 2 items");
+
+ // Cleanup
+ yield BrowserTestUtils.closeWindow(win);
+ });
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_localStorage_before_after.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_localStorage_before_after.js
new file mode 100644
index 000000000..3bcb6e5c9
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_localStorage_before_after.js
@@ -0,0 +1,36 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Ensure that a storage instance used by both private and public sessions at different times does not
+// allow any data to leak due to cached values.
+
+// Step 1: Load browser_privatebrowsing_localStorage_before_after_page.html in a private tab, causing a storage
+// item to exist. Close the tab.
+// Step 2: Load the same page in a non-private tab, ensuring that the storage instance reports only one item
+// existing.
+
+add_task(function test() {
+ let testURI = "about:blank";
+ let prefix = 'http://mochi.test:8888/browser/browser/components/privatebrowsing/test/browser/';
+
+ // Step 1.
+ let privateWin = yield BrowserTestUtils.openNewBrowserWindow({private: true});
+ let privateBrowser = privateWin.gBrowser.addTab(
+ prefix + 'browser_privatebrowsing_localStorage_before_after_page.html').linkedBrowser;
+ yield BrowserTestUtils.browserLoaded(privateBrowser);
+
+ is(privateBrowser.contentTitle, '1', "localStorage should contain 1 item");
+
+ // Step 2.
+ let win = yield BrowserTestUtils.openNewBrowserWindow();
+ let browser = win.gBrowser.addTab(
+ prefix + 'browser_privatebrowsing_localStorage_before_after_page2.html').linkedBrowser;
+ yield BrowserTestUtils.browserLoaded(browser);
+
+ is(browser.contentTitle, 'null|0', 'localStorage should contain 0 items');
+
+ // Cleanup
+ yield BrowserTestUtils.closeWindow(privateWin);
+ yield BrowserTestUtils.closeWindow(win);
+});
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_localStorage_before_after_page.html b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_localStorage_before_after_page.html
new file mode 100644
index 000000000..143fea4e7
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_localStorage_before_after_page.html
@@ -0,0 +1,11 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<script type="text/javascript">
+ localStorage.clear();
+ localStorage.setItem('zzztest', 'zzzvalue');
+ document.title = localStorage.length;
+</script>
+</head>
+<body>
+</body>
+</html>
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_localStorage_before_after_page2.html b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_localStorage_before_after_page2.html
new file mode 100644
index 000000000..9a7e2da63
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_localStorage_before_after_page2.html
@@ -0,0 +1,10 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<script type="text/javascript">
+ document.title = localStorage.getItem('zzztest', 'zzzvalue') + '|' + localStorage.length;
+ localStorage.clear();
+</script>
+</head>
+<body>
+</body>
+</html>
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_localStorage_page1.html b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_localStorage_page1.html
new file mode 100644
index 000000000..3e79a01bf
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_localStorage_page1.html
@@ -0,0 +1,10 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<script type="text/javascript">
+ localStorage.clear();
+ localStorage.setItem('test1', 'value1');
+</script>
+</head>
+<body>
+</body>
+</html>
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_localStorage_page2.html b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_localStorage_page2.html
new file mode 100644
index 000000000..8c9b28fd8
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_localStorage_page2.html
@@ -0,0 +1,10 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<script type="text/javascript">
+ localStorage.setItem('test2', 'value2');
+ document.title = localStorage.length;
+</script>
+</head>
+<body>
+</body>
+</html>
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_newtab_from_popup.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_newtab_from_popup.js
new file mode 100644
index 000000000..b09ec0368
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_newtab_from_popup.js
@@ -0,0 +1,61 @@
+/**
+ * Tests that a popup window in private browsing window opens
+ * new tab links in the original private browsing window as
+ * new tabs.
+ *
+ * This is a regression test for bug 1202634.
+ */
+
+// We're able to sidestep some quote-escaping issues when
+// nesting data URI's by encoding the second data URI in
+// base64.
+const POPUP_BODY_BASE64 = btoa(`<a href="http://example.com/" target="_blank"
+ id="second">
+ Now click this
+ </a>`);
+const POPUP_LINK = `data:text/html;charset=utf-8;base64,${POPUP_BODY_BASE64}`;
+const WINDOW_BODY = `data:text/html,
+ <a href="%23" id="first"
+ onclick="window.open('${POPUP_LINK}', '_blank',
+ 'width=630,height=500')">
+ First click this.
+ </a>`;
+
+add_task(function* test_private_popup_window_opens_private_tabs() {
+ let privWin = yield BrowserTestUtils.openNewBrowserWindow({ private: true });
+
+ // Sanity check - this browser better be private.
+ ok(PrivateBrowsingUtils.isWindowPrivate(privWin),
+ "Opened a private browsing window.");
+
+ // First, open a private browsing window, and load our
+ // testing page.
+ let privBrowser = privWin.gBrowser.selectedBrowser;
+ yield BrowserTestUtils.loadURI(privBrowser, WINDOW_BODY);
+ yield BrowserTestUtils.browserLoaded(privBrowser);
+
+ // Next, click on the link in the testing page, and ensure
+ // that a private popup window is opened.
+ let openedPromise = BrowserTestUtils.waitForNewWindow(true, POPUP_LINK);
+
+ yield BrowserTestUtils.synthesizeMouseAtCenter("#first", {}, privBrowser);
+ let popupWin = yield openedPromise;
+ ok(PrivateBrowsingUtils.isWindowPrivate(popupWin),
+ "Popup window was private.");
+
+ // Now click on the link in the popup, and ensure that a new
+ // tab is opened in the original private browsing window.
+ let newTabPromise = BrowserTestUtils.waitForNewTab(privWin.gBrowser);
+ let popupBrowser = popupWin.gBrowser.selectedBrowser;
+ yield BrowserTestUtils.synthesizeMouseAtCenter("#second", {}, popupBrowser);
+ let newPrivTab = yield newTabPromise;
+
+ // Ensure that the newly created tab's browser is private.
+ ok(PrivateBrowsingUtils.isBrowserPrivate(newPrivTab.linkedBrowser),
+ "Newly opened tab should be private.");
+
+ // Clean up
+ yield BrowserTestUtils.removeTab(newPrivTab);
+ yield BrowserTestUtils.closeWindow(popupWin);
+ yield BrowserTestUtils.closeWindow(privWin);
+});
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_noSessionRestoreMenuOption.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_noSessionRestoreMenuOption.js
new file mode 100644
index 000000000..ae6e8a6a3
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_noSessionRestoreMenuOption.js
@@ -0,0 +1,23 @@
+"use strict";
+
+/**
+ * Tests that if we open a tab within a private browsing window, and then
+ * close that private browsing window, that subsequent private browsing
+ * windows do not allow the command for restoring the last session.
+ */
+add_task(function* test_no_session_restore_menu_option() {
+ let win = yield BrowserTestUtils.openNewBrowserWindow({ private: true });
+ ok(true, "The first private window got loaded");
+ win.gBrowser.addTab("about:mozilla");
+ yield BrowserTestUtils.closeWindow(win);
+
+ win = yield BrowserTestUtils.openNewBrowserWindow({ private: true });
+ let srCommand = win.document.getElementById("Browser:RestoreLastSession");
+ ok(srCommand, "The Session Restore command should exist");
+ is(PrivateBrowsingUtils.isWindowPrivate(win), true,
+ "PrivateBrowsingUtils should report the correct per-window private browsing status");
+ is(srCommand.hasAttribute("disabled"), true,
+ "The Session Restore command should be disabled in private browsing mode");
+
+ yield BrowserTestUtils.closeWindow(win);
+});
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_nonbrowser.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_nonbrowser.js
new file mode 100644
index 000000000..d2a69dd4e
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_nonbrowser.js
@@ -0,0 +1,19 @@
+"use strict";
+
+/**
+ * Tests that we fire the last-pb-context-exited observer notification
+ * when the last private browsing window closes, even if a chrome window
+ * was opened from that private browsing window.
+ */
+add_task(function* () {
+ let win = yield BrowserTestUtils.openNewBrowserWindow({private: true});
+ let chromeWin = win.open("chrome://browser/content/places/places.xul", "_blank",
+ "chrome,extrachrome,menubar,resizable,scrollbars,status,toolbar");
+ yield BrowserTestUtils.waitForEvent(chromeWin, "load");
+ let obsPromise = TestUtils.topicObserved("last-pb-context-exited");
+ yield BrowserTestUtils.closeWindow(win);
+ yield obsPromise;
+ Assert.ok(true, "Got the last-pb-context-exited notification");
+ chromeWin.close();
+});
+
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_opendir.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_opendir.js
new file mode 100644
index 000000000..0b1369b11
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_opendir.js
@@ -0,0 +1,133 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// This test makes sure that the last open directory used inside the private
+// browsing mode is not remembered after leaving that mode.
+
+var windowsToClose = [];
+function testOnWindow(options, callback) {
+ var win = OpenBrowserWindow(options);
+ win.addEventListener("load", function onLoad() {
+ win.removeEventListener("load", onLoad, false);
+ windowsToClose.push(win);
+ callback(win);
+ }, false);
+}
+
+registerCleanupFunction(function() {
+ windowsToClose.forEach(function(win) {
+ win.close();
+ });
+});
+
+function test() {
+ // initialization
+ waitForExplicitFinish();
+ let ds = Cc["@mozilla.org/file/directory_service;1"].
+ getService(Ci.nsIProperties);
+ let dir1 = ds.get("ProfD", Ci.nsIFile);
+ let dir2 = ds.get("TmpD", Ci.nsIFile);
+ let file = dir2.clone();
+ file.append("pbtest.file");
+ file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600);
+
+ const kPrefName = "browser.open.lastDir";
+
+ function setupCleanSlate(win) {
+ win.gLastOpenDirectory.reset();
+ gPrefService.clearUserPref(kPrefName);
+ }
+
+ setupCleanSlate(window);
+
+ // open one regular and one private window
+ testOnWindow(undefined, function(nonPrivateWindow) {
+ setupCleanSlate(nonPrivateWindow);
+ testOnWindow({private: true}, function(privateWindow) {
+ setupCleanSlate(privateWindow);
+
+ // Test 1: general workflow test
+
+ // initial checks
+ ok(!nonPrivateWindow.gLastOpenDirectory.path,
+ "Last open directory path should be initially empty");
+ nonPrivateWindow.gLastOpenDirectory.path = dir2;
+ is(nonPrivateWindow.gLastOpenDirectory.path.path, dir2.path,
+ "The path should be successfully set");
+ nonPrivateWindow.gLastOpenDirectory.path = null;
+ is(nonPrivateWindow.gLastOpenDirectory.path.path, dir2.path,
+ "The path should be not change when assigning it to null");
+ nonPrivateWindow.gLastOpenDirectory.path = dir1;
+ is(nonPrivateWindow.gLastOpenDirectory.path.path, dir1.path,
+ "The path should be successfully outside of the private browsing mode");
+
+ // test the private window
+ is(privateWindow.gLastOpenDirectory.path.path, dir1.path,
+ "The path should not change when entering the private browsing mode");
+ privateWindow.gLastOpenDirectory.path = dir2;
+ is(privateWindow.gLastOpenDirectory.path.path, dir2.path,
+ "The path should successfully change inside the private browsing mode");
+
+ // test the non-private window
+ is(nonPrivateWindow.gLastOpenDirectory.path.path, dir1.path,
+ "The path should be reset to the same path as before entering the private browsing mode");
+
+ setupCleanSlate(nonPrivateWindow);
+ setupCleanSlate(privateWindow);
+
+ // Test 2: the user first tries to open a file inside the private browsing mode
+
+ // test the private window
+ ok(!privateWindow.gLastOpenDirectory.path,
+ "No original path should exist inside the private browsing mode");
+ privateWindow.gLastOpenDirectory.path = dir1;
+ is(privateWindow.gLastOpenDirectory.path.path, dir1.path,
+ "The path should be successfully set inside the private browsing mode");
+ // test the non-private window
+ ok(!nonPrivateWindow.gLastOpenDirectory.path,
+ "The path set inside the private browsing mode should not leak when leaving that mode");
+
+ setupCleanSlate(nonPrivateWindow);
+ setupCleanSlate(privateWindow);
+
+ // Test 3: the last open directory is set from a previous session, it should be used
+ // in normal mode
+
+ gPrefService.setComplexValue(kPrefName, Ci.nsILocalFile, dir1);
+ is(nonPrivateWindow.gLastOpenDirectory.path.path, dir1.path,
+ "The pref set from last session should take effect outside the private browsing mode");
+
+ setupCleanSlate(nonPrivateWindow);
+ setupCleanSlate(privateWindow);
+
+ // Test 4: the last open directory is set from a previous session, it should be used
+ // in private browsing mode mode
+
+ gPrefService.setComplexValue(kPrefName, Ci.nsILocalFile, dir1);
+ // test the private window
+ is(privateWindow.gLastOpenDirectory.path.path, dir1.path,
+ "The pref set from last session should take effect inside the private browsing mode");
+ // test the non-private window
+ is(nonPrivateWindow.gLastOpenDirectory.path.path, dir1.path,
+ "The pref set from last session should remain in effect after leaving the private browsing mode");
+
+ setupCleanSlate(nonPrivateWindow);
+ setupCleanSlate(privateWindow);
+
+ // Test 5: setting the path to a file shouldn't work
+
+ nonPrivateWindow.gLastOpenDirectory.path = file;
+ ok(!nonPrivateWindow.gLastOpenDirectory.path,
+ "Setting the path to a file shouldn't work when it's originally null");
+ nonPrivateWindow.gLastOpenDirectory.path = dir1;
+ nonPrivateWindow.gLastOpenDirectory.path = file;
+ is(nonPrivateWindow.gLastOpenDirectory.path.path, dir1.path,
+ "Setting the path to a file shouldn't work when it's not originally null");
+
+ // cleanup
+ file.remove(false);
+ finish();
+ });
+ });
+}
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_placesTitleNoUpdate.html b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_placesTitleNoUpdate.html
new file mode 100644
index 000000000..f5bb3212f
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_placesTitleNoUpdate.html
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<html>
+ <head>
+ <title>Title 1</title>
+ </head>
+ <body>
+ </body>
+</html>
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_placesTitleNoUpdate.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_placesTitleNoUpdate.js
new file mode 100644
index 000000000..32436b3cc
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_placesTitleNoUpdate.js
@@ -0,0 +1,72 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Test to make sure that the visited page titles do not get updated inside the
+// private browsing mode.
+"use strict";
+
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/PlacesUtils.jsm");
+
+add_task(function* test() {
+ const TEST_URL = "http://mochi.test:8888/browser/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_placesTitleNoUpdate.html"
+ const TEST_URI = Services.io.newURI(TEST_URL, null, null);
+ const TITLE_1 = "Title 1";
+ const TITLE_2 = "Title 2";
+
+ function waitForTitleChanged() {
+ return new Promise(resolve => {
+ let historyObserver = {
+ onTitleChanged: function(uri, pageTitle) {
+ PlacesUtils.history.removeObserver(historyObserver, false);
+ resolve({uri: uri, pageTitle: pageTitle});
+ },
+ onBeginUpdateBatch: function () {},
+ onEndUpdateBatch: function () {},
+ onVisit: function () {},
+ onDeleteURI: function () {},
+ onClearHistory: function () {},
+ onPageChanged: function () {},
+ onDeleteVisits: function() {},
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsINavHistoryObserver])
+ };
+
+ PlacesUtils.history.addObserver(historyObserver, false);
+ });
+ };
+
+ yield PlacesTestUtils.clearHistory();
+
+ let tabToClose = gBrowser.selectedTab = gBrowser.addTab(TEST_URL);
+ yield waitForTitleChanged();
+ is(PlacesUtils.history.getPageTitle(TEST_URI), TITLE_1, "The title matches the orignal title after first visit");
+
+ let place = {
+ uri: TEST_URI,
+ title: TITLE_2,
+ visits: [{
+ visitDate: Date.now() * 1000,
+ transitionType: Ci.nsINavHistoryService.TRANSITION_LINK
+ }]
+ };
+ PlacesUtils.asyncHistory.updatePlaces(place, {
+ handleError: () => ok(false, "Unexpected error in adding visit."),
+ handleResult: function () { },
+ handleCompletion: function () {}
+ });
+
+ yield waitForTitleChanged();
+ is(PlacesUtils.history.getPageTitle(TEST_URI), TITLE_2, "The title matches the updated title after updating visit");
+
+ let privateWin = yield BrowserTestUtils.openNewBrowserWindow({private:true});
+ yield BrowserTestUtils.browserLoaded(privateWin.gBrowser.addTab(TEST_URL).linkedBrowser);
+
+ is(PlacesUtils.history.getPageTitle(TEST_URI), TITLE_2, "The title remains the same after visiting in private window");
+ yield PlacesTestUtils.clearHistory();
+
+ // Cleanup
+ BrowserTestUtils.closeWindow(privateWin);
+ gBrowser.removeTab(tabToClose);
+});
+
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_placestitle.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_placestitle.js
new file mode 100644
index 000000000..a70019976
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_placestitle.js
@@ -0,0 +1,95 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// This test makes sure that the title of existing history entries does not
+// change inside a private window.
+
+add_task(function* test() {
+ const TEST_URL = "http://mochi.test:8888/browser/browser/components/" +
+ "privatebrowsing/test/browser/title.sjs";
+ let cm = Services.cookies;
+
+ function cleanup() {
+ // delete all cookies
+ cm.removeAll();
+ // delete all history items
+ return PlacesTestUtils.clearHistory();
+ }
+
+ yield cleanup();
+
+ let deferredFirst = PromiseUtils.defer();
+ let deferredSecond = PromiseUtils.defer();
+ let deferredThird = PromiseUtils.defer();
+
+ let testNumber = 0;
+ let historyObserver = {
+ onTitleChanged: function(aURI, aPageTitle) {
+ if (aURI.spec != TEST_URL)
+ return;
+ switch (++testNumber) {
+ case 1:
+ // The first time that the page is loaded
+ deferredFirst.resolve(aPageTitle);
+ break;
+ case 2:
+ // The second time that the page is loaded
+ deferredSecond.resolve(aPageTitle);
+ break;
+ case 3:
+ // After clean up
+ deferredThird.resolve(aPageTitle);
+ break;
+ default:
+ // Checks that opening the page in a private window should not fire a
+ // title change.
+ ok(false, "Title changed. Unexpected pass: " + testNumber);
+ }
+ },
+
+ onBeginUpdateBatch: function () {},
+ onEndUpdateBatch: function () {},
+ onVisit: function () {},
+ onDeleteURI: function () {},
+ onClearHistory: function () {},
+ onPageChanged: function () {},
+ onDeleteVisits: function() {},
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsINavHistoryObserver])
+ };
+ PlacesUtils.history.addObserver(historyObserver, false);
+
+
+ let win = yield BrowserTestUtils.openNewBrowserWindow();
+ win.gBrowser.selectedTab = win.gBrowser.addTab(TEST_URL);
+ let aPageTitle = yield deferredFirst.promise;
+ // The first time that the page is loaded
+ is(aPageTitle, "No Cookie",
+ "The page should be loaded without any cookie for the first time");
+
+ win.gBrowser.selectedTab = win.gBrowser.addTab(TEST_URL);
+ aPageTitle = yield deferredSecond.promise;
+ // The second time that the page is loaded
+ is(aPageTitle, "Cookie",
+ "The page should be loaded with a cookie for the second time");
+
+ yield cleanup();
+
+ win.gBrowser.selectedTab = win.gBrowser.addTab(TEST_URL);
+ aPageTitle = yield deferredThird.promise;
+ // After clean up
+ is(aPageTitle, "No Cookie",
+ "The page should be loaded without any cookie again");
+
+ let win2 = yield BrowserTestUtils.openNewBrowserWindow({private: true});
+
+ let private_tab = win2.gBrowser.addTab(TEST_URL);
+ win2.gBrowser.selectedTab = private_tab;
+ yield BrowserTestUtils.browserLoaded(private_tab.linkedBrowser);
+
+ // Cleanup
+ yield cleanup();
+ PlacesUtils.history.removeObserver(historyObserver);
+ yield BrowserTestUtils.closeWindow(win);
+ yield BrowserTestUtils.closeWindow(win2);
+});
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_popupblocker.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_popupblocker.js
new file mode 100644
index 000000000..71d85f296
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_popupblocker.js
@@ -0,0 +1,70 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// This test makes sure that private browsing mode disables the remember option
+// for the popup blocker menu.
+add_task(function* test() {
+ let testURI = "http://mochi.test:8888/browser/browser/components/privatebrowsing/test/browser/popup.html";
+ let oldPopupPolicy = gPrefService.getBoolPref("dom.disable_open_during_load");
+ gPrefService.setBoolPref("dom.disable_open_during_load", true);
+
+ registerCleanupFunction(() => {
+ gPrefService.setBoolPref("dom.disable_open_during_load", oldPopupPolicy);
+ });
+
+ function testPopupBlockerMenuItem(aExpectedDisabled, aWindow, aCallback) {
+
+ aWindow.gBrowser.addEventListener("DOMUpdatePageReport", function() {
+ aWindow.gBrowser.removeEventListener("DOMUpdatePageReport", arguments.callee, false);
+
+ executeSoon(function() {
+ let notification = aWindow.gBrowser.getNotificationBox().getNotificationWithValue("popup-blocked");
+ ok(notification, "The notification box should be displayed");
+
+ function checkMenuItem(callback) {
+ dump("CMI: in\n");
+ aWindow.document.addEventListener("popupshown", function(event) {
+ dump("CMI: popupshown\n");
+ aWindow.document.removeEventListener("popupshown", arguments.callee, false);
+
+ if (aExpectedDisabled)
+ is(aWindow.document.getElementById("blockedPopupAllowSite").getAttribute("disabled"), "true",
+ "The allow popups menu item should be disabled");
+
+ event.originalTarget.hidePopup();
+ dump("CMI: calling back\n");
+ callback();
+ dump("CMI: called back\n");
+ }, false);
+ dump("CMI: out\n");
+ }
+
+ checkMenuItem(function() {
+ aCallback();
+ });
+ notification.querySelector("button").doCommand();
+ });
+
+ }, false);
+
+ aWindow.gBrowser.selectedBrowser.loadURI(testURI);
+ }
+
+ let win1 = yield BrowserTestUtils.openNewBrowserWindow();
+ yield new Promise(resolve => waitForFocus(resolve, win1));
+ yield new Promise(resolve => testPopupBlockerMenuItem(false, win1, resolve));
+
+ let win2 = yield BrowserTestUtils.openNewBrowserWindow({private: true});
+ yield new Promise(resolve => waitForFocus(resolve, win2));
+ yield new Promise(resolve => testPopupBlockerMenuItem(true, win2, resolve));
+
+ let win3 = yield BrowserTestUtils.openNewBrowserWindow();
+ yield new Promise(resolve => waitForFocus(resolve, win3));
+ yield new Promise(resolve => testPopupBlockerMenuItem(false, win3, resolve));
+
+ // Cleanup
+ yield BrowserTestUtils.closeWindow(win1);
+ yield BrowserTestUtils.closeWindow(win2);
+ yield BrowserTestUtils.closeWindow(win3);
+});
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_protocolhandler.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_protocolhandler.js
new file mode 100644
index 000000000..fe69a2234
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_protocolhandler.js
@@ -0,0 +1,47 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// This test makes sure that the web pages can't register protocol handlers
+// inside the private browsing mode.
+
+add_task(function* test() {
+ let notificationValue = "Protocol Registration: testprotocol";
+ let testURI = "http://example.com/browser/" +
+ "browser/components/privatebrowsing/test/browser/browser_privatebrowsing_protocolhandler_page.html";
+
+ let doTest = Task.async(function* (aIsPrivateMode, aWindow) {
+ let tab = aWindow.gBrowser.selectedTab = aWindow.gBrowser.addTab(testURI);
+ yield BrowserTestUtils.browserLoaded(tab.linkedBrowser);
+
+ let promiseFinished = PromiseUtils.defer();
+ setTimeout(function() {
+ let notificationBox = aWindow.gBrowser.getNotificationBox();
+ let notification = notificationBox.getNotificationWithValue(notificationValue);
+
+ if (aIsPrivateMode) {
+ // Make sure the notification is correctly displayed without a remember control
+ ok(!notification, "Notification box should not be displayed inside of private browsing mode");
+ } else {
+ // Make sure the notification is correctly displayed with a remember control
+ ok(notification, "Notification box should be displaying outside of private browsing mode");
+ }
+
+ promiseFinished.resolve();
+ }, 100); // remember control is added in a setTimeout(0) call
+
+ yield promiseFinished.promise;
+ });
+
+ // test first when not on private mode
+ let win = yield BrowserTestUtils.openNewBrowserWindow();
+ yield doTest(false, win);
+
+ // then test when on private mode
+ let privateWin = yield BrowserTestUtils.openNewBrowserWindow({private: true});
+ yield doTest(true, privateWin);
+
+ // Cleanup
+ yield BrowserTestUtils.closeWindow(win);
+ yield BrowserTestUtils.closeWindow(privateWin);
+});
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_protocolhandler_page.html b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_protocolhandler_page.html
new file mode 100644
index 000000000..74f846d54
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_protocolhandler_page.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<html>
+ <head>
+ <title>Protocol registrar page</title>
+ </head>
+ <body>
+ <script type="text/javascript">
+ navigator.registerProtocolHandler("testprotocol",
+ "https://example.com/foobar?uri=%s",
+ "Test Protocol");
+ </script>
+ </body>
+</html>
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_sidebar.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_sidebar.js
new file mode 100644
index 000000000..dbd74029d
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_sidebar.js
@@ -0,0 +1,92 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// This test makes sure that Sidebars do not migrate across windows with
+// different privacy states
+
+// See Bug 885054: https://bugzilla.mozilla.org/show_bug.cgi?id=885054
+
+function test() {
+ waitForExplicitFinish();
+
+ let { utils: Cu } = Components;
+
+ let { Promise: { defer } } = Cu.import("resource://gre/modules/Promise.jsm", {});
+
+ // opens a sidebar
+ function openSidebar(win) {
+ let { promise, resolve } = defer();
+ let doc = win.document;
+
+ let sidebarID = 'viewBookmarksSidebar';
+
+ let sidebar = doc.getElementById('sidebar');
+
+ let sidebarurl = doc.getElementById(sidebarID).getAttribute('sidebarurl');
+
+ sidebar.addEventListener('load', function onSidebarLoad() {
+ if (sidebar.contentWindow.location.href != sidebarurl)
+ return;
+ sidebar.removeEventListener('load', onSidebarLoad, true);
+
+ resolve(win);
+ }, true);
+
+ win.SidebarUI.show(sidebarID);
+
+ return promise;
+ }
+
+ let windowCache = [];
+ function cacheWindow(w) {
+ windowCache.push(w);
+ return w;
+ }
+ function closeCachedWindows () {
+ windowCache.forEach(w => w.close());
+ }
+
+ // Part 1: NON PRIVATE WINDOW -> PRIVATE WINDOW
+ openWindow(window, {}, 1).
+ then(cacheWindow).
+ then(openSidebar).
+ then(win => openWindow(win, { private: true })).
+ then(cacheWindow).
+ then(function({ document }) {
+ let sidebarBox = document.getElementById("sidebar-box");
+ is(sidebarBox.hidden, true, 'Opening a private window from reg window does not open the sidebar');
+ }).
+ // Part 2: NON PRIVATE WINDOW -> NON PRIVATE WINDOW
+ then(() => openWindow(window)).
+ then(cacheWindow).
+ then(openSidebar).
+ then(win => openWindow(win)).
+ then(cacheWindow).
+ then(function({ document }) {
+ let sidebarBox = document.getElementById("sidebar-box");
+ is(sidebarBox.hidden, false, 'Opening a reg window from reg window does open the sidebar');
+ }).
+ // Part 3: PRIVATE WINDOW -> NON PRIVATE WINDOW
+ then(() => openWindow(window, { private: true })).
+ then(cacheWindow).
+ then(openSidebar).
+ then(win => openWindow(win)).
+ then(cacheWindow).
+ then(function({ document }) {
+ let sidebarBox = document.getElementById("sidebar-box");
+ is(sidebarBox.hidden, true, 'Opening a reg window from a private window does not open the sidebar');
+ }).
+ // Part 4: PRIVATE WINDOW -> PRIVATE WINDOW
+ then(() => openWindow(window, { private: true })).
+ then(cacheWindow).
+ then(openSidebar).
+ then(win => openWindow(win, { private: true })).
+ then(cacheWindow).
+ then(function({ document }) {
+ let sidebarBox = document.getElementById("sidebar-box");
+ is(sidebarBox.hidden, false, 'Opening a private window from private window does open the sidebar');
+ }).
+ then(closeCachedWindows).
+ then(finish);
+}
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_theming.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_theming.js
new file mode 100644
index 000000000..e2b8593d6
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_theming.js
@@ -0,0 +1,38 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// This test makes sure that privatebrowsingmode attribute of the window is correctly
+// adjusted based on whether the window is a private window.
+
+var windowsToClose = [];
+function testOnWindow(options, callback) {
+ var win = OpenBrowserWindow(options);
+ win.addEventListener("load", function onLoad() {
+ win.removeEventListener("load", onLoad, false);
+ windowsToClose.push(win);
+ executeSoon(() => callback(win));
+ }, false);
+}
+
+registerCleanupFunction(function() {
+ windowsToClose.forEach(function(win) {
+ win.close();
+ });
+});
+
+function test() {
+ // initialization
+ waitForExplicitFinish();
+
+ ok(!document.documentElement.hasAttribute("privatebrowsingmode"),
+ "privatebrowsingmode should not be present in normal mode");
+
+ // open a private window
+ testOnWindow({private: true}, function(win) {
+ is(win.document.documentElement.getAttribute("privatebrowsingmode"), "temporary",
+ "privatebrowsingmode should be \"temporary\" inside the private browsing mode");
+
+ finish();
+ });
+}
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_ui.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_ui.js
new file mode 100644
index 000000000..cbd2c60f8
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_ui.js
@@ -0,0 +1,82 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// This test makes sure that the gPrivateBrowsingUI object, the Private Browsing
+// menu item and its XUL <command> element work correctly.
+
+function test() {
+ // initialization
+ waitForExplicitFinish();
+ let windowsToClose = [];
+ let testURI = "about:blank";
+ let pbMenuItem;
+ let cmd;
+
+ function doTest(aIsPrivateMode, aWindow, aCallback) {
+ aWindow.gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
+ aWindow.gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
+
+ ok(aWindow.gPrivateBrowsingUI, "The gPrivateBrowsingUI object exists");
+
+ pbMenuItem = aWindow.document.getElementById("menu_newPrivateWindow");
+ ok(pbMenuItem, "The Private Browsing menu item exists");
+
+ cmd = aWindow.document.getElementById("Tools:PrivateBrowsing");
+ isnot(cmd, null, "XUL command object for the private browsing service exists");
+
+ is(pbMenuItem.getAttribute("label"), "New Private Window",
+ "The Private Browsing menu item should read \"New Private Window\"");
+ is(PrivateBrowsingUtils.isWindowPrivate(aWindow), aIsPrivateMode,
+ "PrivateBrowsingUtils should report the correct per-window private browsing status (privateBrowsing should be " +
+ aIsPrivateMode + ")");
+
+ aCallback();
+ }, true);
+
+ aWindow.gBrowser.selectedBrowser.loadURI(testURI);
+ };
+
+ function openPrivateBrowsingModeByUI(aWindow, aCallback) {
+ Services.obs.addObserver(function observer(aSubject, aTopic, aData) {
+ aSubject.addEventListener("load", function() {
+ aSubject.removeEventListener("load", arguments.callee);
+ Services.obs.removeObserver(observer, "domwindowopened");
+ windowsToClose.push(aSubject);
+ aCallback(aSubject);
+ }, false);
+ }, "domwindowopened", false);
+
+ cmd = aWindow.document.getElementById("Tools:PrivateBrowsing");
+ var func = new Function("", cmd.getAttribute("oncommand"));
+ func.call(cmd);
+ };
+
+ function testOnWindow(aOptions, aCallback) {
+ whenNewWindowLoaded(aOptions, function(aWin) {
+ windowsToClose.push(aWin);
+ // execute should only be called when need, like when you are opening
+ // web pages on the test. If calling executeSoon() is not necesary, then
+ // call whenNewWindowLoaded() instead of testOnWindow() on your test.
+ executeSoon(() => aCallback(aWin));
+ });
+ };
+
+ // this function is called after calling finish() on the test.
+ registerCleanupFunction(function() {
+ windowsToClose.forEach(function(aWin) {
+ aWin.close();
+ });
+ });
+
+ // test first when not on private mode
+ testOnWindow({}, function(aWin) {
+ doTest(false, aWin, function() {
+ // then test when on private mode, opening a new private window from the
+ // user interface.
+ openPrivateBrowsingModeByUI(aWin, function(aPrivateWin) {
+ doTest(true, aPrivateWin, finish);
+ });
+ });
+ });
+}
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_urlbarfocus.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_urlbarfocus.js
new file mode 100644
index 000000000..2be701bcd
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_urlbarfocus.js
@@ -0,0 +1,43 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// This test makes sure that the URL bar is focused when entering the private window.
+
+"use strict";
+Components.utils.import("resource://gre/modules/Promise.jsm", this);
+let aboutNewTabService = Components.classes["@mozilla.org/browser/aboutnewtab-service;1"]
+ .getService(Components.interfaces.nsIAboutNewTabService);
+
+function checkUrlbarFocus(win) {
+ let urlbar = win.gURLBar;
+ is(win.document.activeElement, urlbar.inputField, "URL Bar should be focused");
+ is(urlbar.value, "", "URL Bar should be empty");
+}
+
+function openNewPrivateWindow() {
+ let deferred = Promise.defer();
+ whenNewWindowLoaded({private: true}, win => {
+ executeSoon(() => deferred.resolve(win));
+ });
+ return deferred.promise;
+}
+
+add_task(function* () {
+ let win = yield openNewPrivateWindow();
+ checkUrlbarFocus(win);
+ win.close();
+});
+
+add_task(function* () {
+ aboutNewTabService.newTabURL = "about:blank";
+ registerCleanupFunction(() => {
+ aboutNewTabService.resetNewTabURL();
+ });
+
+ let win = yield openNewPrivateWindow();
+ checkUrlbarFocus(win);
+ win.close();
+
+ aboutNewTabService.resetNewTabURL();
+});
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_windowtitle.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_windowtitle.js
new file mode 100644
index 000000000..aca8d0c7b
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_windowtitle.js
@@ -0,0 +1,77 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// This test makes sure that the window title changes correctly while switching
+// from and to private browsing mode.
+
+add_task(function test() {
+ const testPageURL = "http://mochi.test:8888/browser/" +
+ "browser/components/privatebrowsing/test/browser/browser_privatebrowsing_windowtitle_page.html";
+ requestLongerTimeout(2);
+
+ // initialization of expected titles
+ let test_title = "Test title";
+ let app_name = document.documentElement.getAttribute("title");
+ const isOSX = ("nsILocalFileMac" in Ci);
+ let page_with_title;
+ let page_without_title;
+ let about_pb_title;
+ let pb_page_with_title;
+ let pb_page_without_title;
+ let pb_about_pb_title;
+ if (isOSX) {
+ page_with_title = test_title;
+ page_without_title = app_name;
+ about_pb_title = "Open a private window?";
+ pb_page_with_title = test_title + " - (Private Browsing)";
+ pb_page_without_title = app_name + " - (Private Browsing)";
+ pb_about_pb_title = "Private Browsing - (Private Browsing)";
+ }
+ else {
+ page_with_title = test_title + " - " + app_name;
+ page_without_title = app_name;
+ about_pb_title = "Open a private window?" + " - " + app_name;
+ pb_page_with_title = test_title + " - " + app_name + " (Private Browsing)";
+ pb_page_without_title = app_name + " (Private Browsing)";
+ pb_about_pb_title = "Private Browsing - " + app_name + " (Private Browsing)";
+ }
+
+ function* testTabTitle(aWindow, url, insidePB, expected_title) {
+ let tab = (yield BrowserTestUtils.openNewForegroundTab(aWindow.gBrowser));
+ yield BrowserTestUtils.loadURI(tab.linkedBrowser, url);
+ yield BrowserTestUtils.browserLoaded(tab.linkedBrowser);
+
+ yield BrowserTestUtils.waitForCondition(() => {
+ return aWindow.document.title === expected_title;
+ }, `Window title should be ${expected_title}, got ${aWindow.document.title}`);
+
+ is(aWindow.document.title, expected_title, "The window title for " + url +
+ " is correct (" + (insidePB ? "inside" : "outside") +
+ " private browsing mode)");
+
+ let win = aWindow.gBrowser.replaceTabWithWindow(tab);
+ yield BrowserTestUtils.waitForEvent(win, "load", false);
+
+ yield BrowserTestUtils.waitForCondition(() => {
+ return win.document.title === expected_title;
+ }, `Window title should be ${expected_title}, got ${aWindow.document.title}`);
+
+ is(win.document.title, expected_title, "The window title for " + url +
+ " detached tab is correct (" + (insidePB ? "inside" : "outside") +
+ " private browsing mode)");
+
+ yield Promise.all([ BrowserTestUtils.closeWindow(win),
+ BrowserTestUtils.closeWindow(aWindow) ]);
+ }
+
+ function openWin(private) {
+ return BrowserTestUtils.openNewBrowserWindow({ private });
+ }
+ yield Task.spawn(testTabTitle((yield openWin(false)), "about:blank", false, page_without_title));
+ yield Task.spawn(testTabTitle((yield openWin(false)), testPageURL, false, page_with_title));
+ yield Task.spawn(testTabTitle((yield openWin(false)), "about:privatebrowsing", false, about_pb_title));
+ yield Task.spawn(testTabTitle((yield openWin(true)), "about:blank", true, pb_page_without_title));
+ yield Task.spawn(testTabTitle((yield openWin(true)), testPageURL, true, pb_page_with_title));
+ yield Task.spawn(testTabTitle((yield openWin(true)), "about:privatebrowsing", true, pb_about_pb_title));
+});
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_windowtitle_page.html b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_windowtitle_page.html
new file mode 100644
index 000000000..760bde7d1
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_windowtitle_page.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<html>
+ <head>
+ <title>Test title</title>
+ </head>
+ <body>
+ Test page for the window title test
+ </body>
+</html>
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_zoom.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_zoom.js
new file mode 100644
index 000000000..f5afcbd61
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_zoom.js
@@ -0,0 +1,37 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// This test makes sure that private browsing turns off doesn't cause zoom
+// settings to be reset on tab switch (bug 464962)
+
+add_task(function* test() {
+ let win = (yield BrowserTestUtils.openNewBrowserWindow({ private: true }));
+ let tabAbout = (yield BrowserTestUtils.openNewForegroundTab(win.gBrowser, "about:"));
+ let tabMozilla = (yield BrowserTestUtils.openNewForegroundTab(win.gBrowser, "about:"));
+
+ let mozillaZoom = win.ZoomManager.zoom;
+
+ // change the zoom on the mozilla page
+ win.FullZoom.enlarge();
+ // make sure the zoom level has been changed
+ isnot(win.ZoomManager.zoom, mozillaZoom, "Zoom level can be changed");
+ mozillaZoom = win.ZoomManager.zoom;
+
+ // switch to about: tab
+ yield BrowserTestUtils.switchTab(win.gBrowser, tabAbout);
+
+ // switch back to mozilla tab
+ yield BrowserTestUtils.switchTab(win.gBrowser, tabMozilla);
+
+ // make sure the zoom level has not changed
+ is(win.ZoomManager.zoom, mozillaZoom,
+ "Entering private browsing should not reset the zoom on a tab");
+
+ // cleanup
+ win.FullZoom.reset();
+ yield Promise.all([ BrowserTestUtils.removeTab(tabMozilla),
+ BrowserTestUtils.removeTab(tabAbout) ]);
+
+ yield BrowserTestUtils.closeWindow(win);
+});
diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_zoomrestore.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_zoomrestore.js
new file mode 100644
index 000000000..b67bfc229
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_zoomrestore.js
@@ -0,0 +1,64 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// This test makes sure that about:privatebrowsing does not appear zoomed in
+// if there is already a zoom site pref for about:blank (bug 487656).
+
+add_task(function* test() {
+ // initialization
+ let windowsToClose = [];
+ let windowsToReset = [];
+
+ function promiseLocationChange() {
+ return new Promise(resolve => {
+ Services.obs.addObserver(function onLocationChange(subj, topic, data) {
+ Services.obs.removeObserver(onLocationChange, topic);
+ resolve();
+ }, "browser-fullZoom:location-change", false);
+ });
+ }
+
+ function promiseTestReady(aIsZoomedWindow, aWindow) {
+ // Need to wait on two things, the ordering of which is not guaranteed:
+ // (1) the page load, and (2) FullZoom's update to the new page's zoom
+ // level. FullZoom broadcasts "browser-fullZoom:location-change" when its
+ // update is done. (See bug 856366 for details.)
+
+
+ let browser = aWindow.gBrowser.selectedBrowser;
+ return BrowserTestUtils.loadURI(browser, "about:blank").then(() => {
+ return Promise.all([ BrowserTestUtils.browserLoaded(browser),
+ promiseLocationChange() ]);
+ }).then(() => doTest(aIsZoomedWindow, aWindow));
+ }
+
+ function doTest(aIsZoomedWindow, aWindow) {
+ if (aIsZoomedWindow) {
+ is(aWindow.ZoomManager.zoom, 1,
+ "Zoom level for freshly loaded about:blank should be 1");
+ // change the zoom on the blank page
+ aWindow.FullZoom.enlarge();
+ isnot(aWindow.ZoomManager.zoom, 1, "Zoom level for about:blank should be changed");
+ return;
+ }
+
+ // make sure the zoom level is set to 1
+ is(aWindow.ZoomManager.zoom, 1, "Zoom level for about:privatebrowsing should be reset");
+ }
+
+ function testOnWindow(options, callback) {
+ return BrowserTestUtils.openNewBrowserWindow(options).then((win) => {
+ windowsToClose.push(win);
+ windowsToReset.push(win);
+ return win;
+ });
+ }
+
+ yield testOnWindow({}).then(win => promiseTestReady(true, win));
+ yield testOnWindow({private: true}).then(win => promiseTestReady(false, win));
+
+ // cleanup
+ windowsToReset.forEach((win) => win.FullZoom.reset());
+ yield Promise.all(windowsToClose.map(win => BrowserTestUtils.closeWindow(win)));
+});
diff --git a/browser/components/privatebrowsing/test/browser/empty_file.html b/browser/components/privatebrowsing/test/browser/empty_file.html
new file mode 100644
index 000000000..42682b474
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/empty_file.html
@@ -0,0 +1 @@
+<html><body></body></html> \ No newline at end of file
diff --git a/browser/components/privatebrowsing/test/browser/file_favicon.html b/browser/components/privatebrowsing/test/browser/file_favicon.html
new file mode 100644
index 000000000..b571134e1
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/file_favicon.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <meta charset='utf-8'>
+ <title>Favicon Test for originAttributes</title>
+ <link rel="icon" type="image/png" href="file_favicon.png" />
+ </head>
+ <body>
+ Favicon!!
+ </body>
+</html> \ No newline at end of file
diff --git a/browser/components/privatebrowsing/test/browser/file_favicon.png b/browser/components/privatebrowsing/test/browser/file_favicon.png
new file mode 100644
index 000000000..5535363c9
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/file_favicon.png
Binary files differ
diff --git a/browser/components/privatebrowsing/test/browser/file_favicon.png^headers^ b/browser/components/privatebrowsing/test/browser/file_favicon.png^headers^
new file mode 100644
index 000000000..9e23c73b7
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/file_favicon.png^headers^
@@ -0,0 +1 @@
+Cache-Control: no-cache
diff --git a/browser/components/privatebrowsing/test/browser/head.js b/browser/components/privatebrowsing/test/browser/head.js
new file mode 100644
index 000000000..c822ba8d1
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/head.js
@@ -0,0 +1,63 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+var {PromiseUtils} = Cu.import("resource://gre/modules/PromiseUtils.jsm", {});
+XPCOMUtils.defineLazyModuleGetter(this, "PlacesTestUtils",
+ "resource://testing-common/PlacesTestUtils.jsm");
+
+function whenNewWindowLoaded(aOptions, aCallback) {
+ let win = OpenBrowserWindow(aOptions);
+ let focused = SimpleTest.promiseFocus(win);
+ let startupFinished = TestUtils.topicObserved("browser-delayed-startup-finished",
+ subject => subject == win).then(() => win);
+ Promise.all([focused, startupFinished])
+ .then(results => executeSoon(() => aCallback(results[1])));
+
+ return win;
+}
+
+function openWindow(aParent, aOptions, a3) {
+ let { Promise: { defer } } = Components.utils.import("resource://gre/modules/Promise.jsm", {});
+ let { promise, resolve } = defer();
+
+ let win = aParent.OpenBrowserWindow(aOptions);
+
+ win.addEventListener("load", function onLoad() {
+ win.removeEventListener("load", onLoad, false);
+ resolve(win);
+ }, false);
+
+ return promise;
+}
+
+function newDirectory() {
+ let FileUtils =
+ Cu.import("resource://gre/modules/FileUtils.jsm", {}).FileUtils;
+ let tmpDir = FileUtils.getDir("TmpD", [], true);
+ let dir = tmpDir.clone();
+ dir.append("testdir");
+ dir.createUnique(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
+ return dir;
+}
+
+function newFileInDirectory(aDir) {
+ let FileUtils =
+ Cu.import("resource://gre/modules/FileUtils.jsm", {}).FileUtils;
+ let file = aDir.clone();
+ file.append("testfile");
+ file.createUnique(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_FILE);
+ return file;
+}
+
+function clearHistory() {
+ // simulate clearing the private data
+ Services.obs.notifyObservers(null, "browser:purge-session-history", "");
+}
+
+function _initTest() {
+ // Don't use about:home as the homepage for new windows
+ Services.prefs.setIntPref("browser.startup.page", 0);
+ registerCleanupFunction(() => Services.prefs.clearUserPref("browser.startup.page"));
+}
+
+_initTest();
diff --git a/browser/components/privatebrowsing/test/browser/popup.html b/browser/components/privatebrowsing/test/browser/popup.html
new file mode 100644
index 000000000..68bbbfa26
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/popup.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>Page creating a popup</title>
+ </head>
+ <body>
+ <script type="text/javascript">
+ window.open("data:text/plain,test", "testwin");
+ </script>
+ </body>
+</html>
diff --git a/browser/components/privatebrowsing/test/browser/title.sjs b/browser/components/privatebrowsing/test/browser/title.sjs
new file mode 100644
index 000000000..568e235be
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/title.sjs
@@ -0,0 +1,22 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// This provides the tests with a page with different titles based on whether
+// a cookie is present or not.
+
+function handleRequest(request, response) {
+ response.setStatusLine(request.httpVersion, 200, "OK");
+ response.setHeader("Content-Type", "text/html", false);
+
+ var cookie = "name=value";
+ var title = "No Cookie";
+ if (request.hasHeader("Cookie") && request.getHeader("Cookie") == cookie)
+ title = "Cookie";
+ else
+ response.setHeader("Set-Cookie", cookie, false);
+
+ response.write("<html><head><title>");
+ response.write(title);
+ response.write("</title><body>test page</body></html>");
+}