Bug 806685 - Port browser_privatebrowsing_downloadLastDir.js and its friends to the new per-window PB APIs; r=ehsan
authorAndres Hernandez <andres@appcoast.com>
Mon, 12 Nov 2012 21:20:32 -0600
changeset 117723 45f947bf554ae2fabd1c4065e4c5358741a5a545
parent 117722 0e14d8bd8aed42b63d3719323e7ef7f3bad7e4f7
child 117724 400d7b156d2fa2b189dafce8dae9e00c9feba484
push idunknown
push userunknown
push dateunknown
reviewersehsan
bugs806685
milestone19.0a1
Bug 806685 - Port browser_privatebrowsing_downloadLastDir.js and its friends to the new per-window PB APIs; r=ehsan
browser/components/privatebrowsing/test/browser/perwindow/Makefile.in
browser/components/privatebrowsing/test/browser/perwindow/browser_privatebrowsing_DownloadLastDirWithCPS.js
browser/components/privatebrowsing/test/browser/perwindow/browser_privatebrowsing_downloadLastDir.js
browser/components/privatebrowsing/test/browser/perwindow/browser_privatebrowsing_downloadLastDir_c.js
browser/components/privatebrowsing/test/browser/perwindow/browser_privatebrowsing_downloadLastDir_toggle.js
browser/components/privatebrowsing/test/browser/perwindow/head.js
--- a/browser/components/privatebrowsing/test/browser/perwindow/Makefile.in
+++ b/browser/components/privatebrowsing/test/browser/perwindow/Makefile.in
@@ -13,13 +13,17 @@ include $(DEPTH)/config/autoconf.mk
 MOCHITEST_BROWSER_FILES =  \
 		head.js \
 		browser_privatebrowsing_certexceptionsui.js \
 		browser_privatebrowsing_concurrent.js \
 		browser_privatebrowsing_concurrent_page.html \
 		browser_privatebrowsing_cookieacceptdialog.js \
 		browser_privatebrowsing_crh.js \
 		browser_privatebrowsing_lastpbcontextexited.js \
+		browser_privatebrowsing_downloadLastDir.js \
+		browser_privatebrowsing_downloadLastDir_c.js \
+		browser_privatebrowsing_downloadLastDir_toggle.js \
+		browser_privatebrowsing_DownloadLastDirWithCPS.js \
 		browser_privatebrowsing_opendir.js \
 		browser_privatebrowsing_theming.js \
 		$(NULL)
 
 include $(topsrcdir)/config/rules.mk
copy from browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_DownloadLastDirWithCPS.js
copy to browser/components/privatebrowsing/test/browser/perwindow/browser_privatebrowsing_DownloadLastDirWithCPS.js
--- a/browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_DownloadLastDirWithCPS.js
+++ b/browser/components/privatebrowsing/test/browser/perwindow/browser_privatebrowsing_DownloadLastDirWithCPS.js
@@ -13,247 +13,240 @@ function test() {
 function moveAlong() {
   try {
     gTests.next();
   } catch (x if x instanceof StopIteration) {
     finish();
   }
 }
 
-function waitForPB() {
-  function observer(aSubject, aTopic, aData) {
-    Services.obs.removeObserver(observer, "last-pb-context-exited", false);
-    executeSoon(moveAlong);
-  }
-  Services.obs.addObserver(observer, "last-pb-context-exited", false);
-}
-
 function runTest() {
-  let tmpScope = {};
-  Cu.import("resource://gre/modules/DownloadLastDir.jsm", tmpScope);
-  let gDownloadLastDir = new tmpScope.DownloadLastDir(window);
-  Cu.import("resource://gre/modules/Services.jsm");
-  Cu.import("resource://gre/modules/FileUtils.jsm", tmpScope);
-  let FileUtils = tmpScope.FileUtils;
-
-  let pb = Cc["@mozilla.org/privatebrowsing;1"].
-           getService(Ci.nsIPrivateBrowsingService);
-
-  function clearHistory() {
-    // simulate clearing the private data
-    Services.obs.notifyObservers(null, "browser:purge-session-history", "");
-  }
-
-  is(typeof gDownloadLastDir, "object", "gDownloadLastDir should be a valid object");
-  is(gDownloadLastDir.file, null, "LastDir pref should be null to start with");
+  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);
 
-  function newDir() {
-    let dir = tmpDir.clone();
-    dir.append("testdir");
-    dir.createUnique(Ci.nsIFile.DIRECTORY_TYPE, 0700);
-    return dir;
+  // cleanup functions registration
+  registerCleanupFunction(function () {
+    Services.prefs.clearUserPref("browser.download.lastDir.savePerSite");
+    Services.prefs.clearUserPref("browser.download.lastDir");
+    [dir1, dir2, dir3].forEach(function(dir) dir.remove(true));
+  });
+
+  function testOnWindow(aPrivate, aCallback) {
+    whenNewWindowLoaded({private: aPrivate}, function(win) {
+      let gDownloadLastDir = new DownloadLastDir(win);
+      aCallback(win, gDownloadLastDir);
+      gDownloadLastDir.cleanupPrivateFile();
+      win.close();
+      executeSoon(moveAlong);
+    });
+  }
+
+  function checkInit(aWin, gDownloadLastDir) {
+    is(typeof gDownloadLastDir, "object",
+       "gDownloadLastDir should be a valid object");
+    is(gDownloadLastDir.file, null,
+       "LastDir pref should be null to start with");
+
+    // set up last dir
+    gDownloadLastDir.setFile(null, tmpDir);
+    is(gDownloadLastDir.file.path, tmpDir.path,
+       "LastDir should point to the tmpDir");
+    isnot(gDownloadLastDir.file, tmpDir,
+          "gDownloadLastDir.file should not be pointing to tmpDir");
+
+    // set uri1 to dir1, all should now return dir1
+    // also check that a new object is returned
+    gDownloadLastDir.setFile(uri1, dir1);
+    is(gDownloadLastDir.file.path, dir1.path,
+       "gDownloadLastDir should return dir1");
+    isnot(gDownloadLastDir.file, dir1,
+          "gDownloadLastDir.file should not return dir1");
+    is(gDownloadLastDir.getFile(uri1).path, dir1.path,
+       "uri1 should return dir1"); // set in CPS
+    isnot(gDownloadLastDir.getFile(uri1), dir1,
+          "getFile on uri1 should not return dir1");
+    is(gDownloadLastDir.getFile(uri2).path, dir1.path,
+       "uri2 should return dir1"); // fallback
+    isnot(gDownloadLastDir.getFile(uri2), dir1,
+          "getFile on uri2 should not return dir1");
+    is(gDownloadLastDir.getFile(uri3).path, dir1.path,
+       "uri3 should return dir1"); // fallback
+    isnot(gDownloadLastDir.getFile(uri3), dir1,
+          "getFile on uri3 should not return dir1");
+    is(gDownloadLastDir.getFile(uri4).path, dir1.path,
+       "uri4 should return dir1"); // fallback
+    isnot(gDownloadLastDir.getFile(uri4), dir1,
+          "getFile on uri4 should not return dir1");
+
+    // set uri2 to dir2, all except uri1 should now return dir2
+    gDownloadLastDir.setFile(uri2, dir2);
+    is(gDownloadLastDir.file.path, dir2.path,
+       "gDownloadLastDir should point to dir2");
+    is(gDownloadLastDir.getFile(uri1).path, dir1.path,
+       "uri1 should return dir1"); // set in CPS
+    is(gDownloadLastDir.getFile(uri2).path, dir2.path,
+       "uri2 should return dir2"); // set in CPS
+    is(gDownloadLastDir.getFile(uri3).path, dir2.path,
+       "uri3 should return dir2"); // fallback
+    is(gDownloadLastDir.getFile(uri4).path, dir2.path,
+       "uri4 should return dir2"); // fallback
+
+    // set uri3 to dir3, all except uri1 and uri2 should now return dir3
+    gDownloadLastDir.setFile(uri3, dir3);
+    is(gDownloadLastDir.file.path, dir3.path,
+       "gDownloadLastDir should point to dir3");
+    is(gDownloadLastDir.getFile(uri1).path, dir1.path,
+       "uri1 should return dir1"); // set in CPS
+    is(gDownloadLastDir.getFile(uri2).path, dir2.path,
+       "uri2 should return dir2"); // set in CPS
+    is(gDownloadLastDir.getFile(uri3).path, dir3.path,
+       "uri3 should return dir3"); // set in CPS
+    is(gDownloadLastDir.getFile(uri4).path, dir3.path,
+       "uri4 should return dir4"); // fallback
+
+    // set uri1 to dir2, all except uri3 should now return dir2
+    gDownloadLastDir.setFile(uri1, dir2);
+    is(gDownloadLastDir.file.path, dir2.path,
+       "gDownloadLastDir should point to dir2");
+    is(gDownloadLastDir.getFile(uri1).path, dir2.path,
+       "uri1 should return dir2"); // set in CPS
+    is(gDownloadLastDir.getFile(uri2).path, dir2.path,
+       "uri2 should return dir2"); // set in CPS
+    is(gDownloadLastDir.getFile(uri3).path, dir3.path,
+       "uri3 should return dir3"); // set in CPS
+    is(gDownloadLastDir.getFile(uri4).path, dir2.path,
+       "uri4 should return dir2"); // fallback
+
+    // check clearHistory removes all data
+    clearHistory();
+    is(gDownloadLastDir.file, null, "clearHistory removes all data");
+    is(Services.contentPrefs.hasPref(uri1, "browser.download.lastDir", null),
+       false, "LastDir preference should be absent");
+    is(gDownloadLastDir.getFile(uri1), null, "uri1 should point to null");
+    is(gDownloadLastDir.getFile(uri2), null, "uri2 should point to null");
+    is(gDownloadLastDir.getFile(uri3), null, "uri3 should point to null");
+    is(gDownloadLastDir.getFile(uri4), null, "uri4 should point to null");
   }
 
-  let dir1 = newDir();
-  let dir2 = newDir();
-  let dir3 = newDir();
-  try {
-    { // set up last dir
-      gDownloadLastDir.setFile(null, tmpDir);
-      is(gDownloadLastDir.file.path, tmpDir.path, "LastDir should point to the tmpDir");
-      isnot(gDownloadLastDir.file, tmpDir, "gDownloadLastDir.file should not be pointing to tmpDir");
-    }
+  function checkDownloadLastDir(aWin, gDownloadLastDir, aLastDir) {
+    is(gDownloadLastDir.file.path, aLastDir.path,
+       "gDownloadLastDir should point to the expected last directory");
+    is(gDownloadLastDir.getFile(uri1).path, aLastDir.path,
+       "uri1 should return the expected last directory");
+  }
 
-    { // set uri1 to dir1, all should now return dir1
-      // also check that a new object is returned
-      gDownloadLastDir.setFile(uri1, dir1);
-      is(gDownloadLastDir.file.path, dir1.path, "gDownloadLastDir should return dir1");
-      isnot(gDownloadLastDir.file, dir1, "gDownloadLastDir.file should not return dir1");
-      is(gDownloadLastDir.getFile(uri1).path, dir1.path, "uri1 should return dir1"); // set in CPS
-      isnot(gDownloadLastDir.getFile(uri1), dir1, "getFile on uri1 should not return dir1");
-      is(gDownloadLastDir.getFile(uri2).path, dir1.path, "uri2 should return dir1"); // fallback
-      isnot(gDownloadLastDir.getFile(uri2), dir1, "getFile on uri2 should not return dir1");
-      is(gDownloadLastDir.getFile(uri3).path, dir1.path, "uri3 should return dir1"); // fallback
-      isnot(gDownloadLastDir.getFile(uri3), dir1, "getFile on uri3 should not return dir1");
-      is(gDownloadLastDir.getFile(uri4).path, dir1.path, "uri4 should return dir1"); // fallback
-      isnot(gDownloadLastDir.getFile(uri4), dir1, "getFile on uri4 should not return dir1");
-    }
+  function checkDownloadLastDirNull(aWin, gDownloadLastDir) {
+    is(gDownloadLastDir.file, null, "gDownloadLastDir should be null");
+    is(gDownloadLastDir.getFile(uri1), null, "uri1 should return null");
+  }
 
-    { // set uri2 to dir2, all except uri1 should now return dir2
-      gDownloadLastDir.setFile(uri2, dir2);
-      is(gDownloadLastDir.file.path, dir2.path, "gDownloadLastDir should point to dir2");
-      is(gDownloadLastDir.getFile(uri1).path, dir1.path, "uri1 should return dir1"); // set in CPS
-      is(gDownloadLastDir.getFile(uri2).path, dir2.path, "uri2 should return dir2"); // set in CPS
-      is(gDownloadLastDir.getFile(uri3).path, dir2.path, "uri3 should return dir2"); // fallback
-      is(gDownloadLastDir.getFile(uri4).path, dir2.path, "uri4 should return dir2"); // fallback
-    }
+  function checkSetFile(gDownloadLastDir, aDir1, aDir2, aDir3) {
+    // check that disabling CPS works
+    Services.prefs.setBoolPref("browser.download.lastDir.savePerSite", false);
 
-    { // set uri3 to dir3, all except uri1 and uri2 should now return dir3
-      gDownloadLastDir.setFile(uri3, dir3);
-      is(gDownloadLastDir.file.path, dir3.path, "gDownloadLastDir should point to dir3");
-      is(gDownloadLastDir.getFile(uri1).path, dir1.path, "uri1 should return dir1"); // set in CPS
-      is(gDownloadLastDir.getFile(uri2).path, dir2.path, "uri2 should return dir2"); // set in CPS
-      is(gDownloadLastDir.getFile(uri3).path, dir3.path, "uri3 should return dir3"); // set in CPS
-      is(gDownloadLastDir.getFile(uri4).path, dir3.path, "uri4 should return dir4"); // fallback
-    }
+    gDownloadLastDir.setFile(uri1, aDir1);
+    is(gDownloadLastDir.file.path, aDir1.path, "LastDir should be set to dir1");
+    is(gDownloadLastDir.getFile(uri1).path, aDir1.path, "uri1 should return dir1");
+    is(gDownloadLastDir.getFile(uri2).path, aDir1.path, "uri2 should return dir1");
+    is(gDownloadLastDir.getFile(uri3).path, aDir1.path, "uri3 should return dir1");
+    is(gDownloadLastDir.getFile(uri4).path, aDir1.path, "uri4 should return dir1");
 
-    { // set uri1 to dir2, all except uri3 should now return dir2
-      gDownloadLastDir.setFile(uri1, dir2);
-      is(gDownloadLastDir.file.path, dir2.path, "gDownloadLastDir should point to dir2");
-      is(gDownloadLastDir.getFile(uri1).path, dir2.path, "uri1 should return dir2"); // set in CPS
-      is(gDownloadLastDir.getFile(uri2).path, dir2.path, "uri2 should return dir2"); // set in CPS
-      is(gDownloadLastDir.getFile(uri3).path, dir3.path, "uri3 should return dir3"); // set in CPS
-      is(gDownloadLastDir.getFile(uri4).path, dir2.path, "uri4 should return dir2"); // fallback
-    }
+    gDownloadLastDir.setFile(uri2, aDir2);
+    is(gDownloadLastDir.file.path, aDir2.path, "LastDir should be set to dir2");
+    is(gDownloadLastDir.getFile(uri1).path, aDir2.path, "uri1 should return dir2");
+    is(gDownloadLastDir.getFile(uri2).path, aDir2.path, "uri2 should return dir2");
+    is(gDownloadLastDir.getFile(uri3).path, aDir2.path, "uri3 should return dir2");
+    is(gDownloadLastDir.getFile(uri4).path, aDir2.path, "uri4 should return dir2");
 
-    { // check clearHistory removes all data
-      clearHistory();
-      is(gDownloadLastDir.file, null, "clearHistory removes all data");
-      is(Services.contentPrefs.hasPref(uri1, "browser.download.lastDir", null), false, "LastDir preference should be absent");
-      is(gDownloadLastDir.getFile(uri1), null, "uri1 should point to null");
-      is(gDownloadLastDir.getFile(uri2), null, "uri2 should point to null");
-      is(gDownloadLastDir.getFile(uri3), null, "uri3 should point to null");
-      is(gDownloadLastDir.getFile(uri4), null, "uri4 should point to null");
-    }
-
-    Services.prefs.setBoolPref("browser.privatebrowsing.keep_current_session", true);
+    Services.prefs.clearUserPref("browser.download.lastDir.savePerSite");
 
-    { // check data set outside PB mode is remembered
-      gDownloadLastDir.setFile(null, tmpDir);
-      pb.privateBrowsingEnabled = true;
-      is(gDownloadLastDir.file.path, tmpDir.path, "LastDir should point to tmpDir inside PB mode");
-      is(gDownloadLastDir.getFile(uri1).path, tmpDir.path, "uri1 should return tmpDir inside PB mode");
-
-      waitForPB();
-      pb.privateBrowsingEnabled = false;
-      yield;
-      is(gDownloadLastDir.file.path, tmpDir.path, "LastDir should point to tmpDir outside PB mode");
-      is(gDownloadLastDir.getFile(uri1).path, tmpDir.path, "uri1 should return tmpDir outside PB mode");
-
-      clearHistory();
-    }
+    // check that passing null to setFile clears the stored value
+    gDownloadLastDir.setFile(uri3, aDir3);
+    is(gDownloadLastDir.getFile(uri3).path, aDir3.path, "LastDir should be set to dir3");
+    gDownloadLastDir.setFile(uri3, null);
+    is(gDownloadLastDir.getFile(uri3), null, "uri3 should return null");
+  }
 
-    { // check data set using CPS outside PB mode is remembered
-      gDownloadLastDir.setFile(uri1, dir1);
-      pb.privateBrowsingEnabled = true;
-      is(gDownloadLastDir.file.path, dir1.path, "LastDir should point to dir1 inside PB mode");
-      is(gDownloadLastDir.getFile(uri1).path, dir1.path, "uri1 should return dir1 inside PB mode");
+  yield testOnWindow(false, function(win, downloadDir) {
+    checkInit(win, downloadDir);
+    downloadDir.setFile(null, tmpDir);
+  });
 
-      waitForPB();
-      pb.privateBrowsingEnabled = false;
-      yield;
-      is(gDownloadLastDir.file.path, dir1.path, "LastDir should point to dir1 outside PB mode");
-      is(gDownloadLastDir.getFile(uri1).path, dir1.path, "uri1 should return dir1 outside PB mode");
-
-      clearHistory();
-    }
+  // check data set outside PB mode is remembered
+  yield testOnWindow(true, function(win, downloadDir) {
+    checkDownloadLastDir(win, downloadDir, tmpDir);
+  });
+  yield testOnWindow(false, function(win, downloadDir) {
+    checkDownloadLastDir(win, downloadDir, tmpDir);
+    clearHistory();
+    downloadDir.setFile(uri1, dir1);
+  });
 
-    { // check data set inside PB mode is forgotten
-      pb.privateBrowsingEnabled = true;
-      gDownloadLastDir.setFile(null, tmpDir);
-      is(gDownloadLastDir.file.path, tmpDir.path, "LastDir should return tmpDir inside PB mode");
-      is(gDownloadLastDir.getFile(uri1).path, tmpDir.path, "uri1 should return tmpDir inside PB mode");
-
-      waitForPB();
-      pb.privateBrowsingEnabled = false;
-      yield;
-      is(gDownloadLastDir.file, null, "LastDir should be null outside PB mode");
-      is(gDownloadLastDir.getFile(uri1), null, "uri1 should return null outside PB mode");
-
-      clearHistory();
-    }
-
-    { // check data set using CPS inside PB mode is forgotten
-      pb.privateBrowsingEnabled = true;
-      gDownloadLastDir.setFile(uri1, dir1);
-      is(gDownloadLastDir.file.path, dir1.path, "LastDir should point to dir1 inside PB mode");
-      is(gDownloadLastDir.getFile(uri1).path, dir1.path, "uri1 should return dir1 inside PB mode");
+  // check data set using CPS outside PB mode is remembered
+  yield testOnWindow(true, function(win, downloadDir) {
+    checkDownloadLastDir(win, downloadDir, dir1);
+  });
+  yield testOnWindow(false, function(win, downloadDir) {
+    checkDownloadLastDir(win, downloadDir, dir1);
+    clearHistory();
+  });
 
-      waitForPB();
-      pb.privateBrowsingEnabled = false;
-      yield;
-      is(gDownloadLastDir.file, null, "LastDir should point to null outside PB mode");
-      is(gDownloadLastDir.getFile(uri1), null, "uri1 should return null outside PB mode");
-
-      clearHistory();
-    }
-
-    { // check data set outside PB mode but changed inside is remembered correctly
-      gDownloadLastDir.setFile(uri1, dir1);
-      pb.privateBrowsingEnabled = true;
-      gDownloadLastDir.setFile(uri1, dir2);
-      is(gDownloadLastDir.file.path, dir2.path, "LastDir should point to dir2 inside PB mode");
-      is(gDownloadLastDir.getFile(uri1).path, dir2.path, "uri1 should return dir2 inside PB mode");
-
-      waitForPB();
-      pb.privateBrowsingEnabled = false;
-      yield;
-      is(gDownloadLastDir.file.path, dir1.path, "LastDir should point to dir1 outside PB mode");
-      is(gDownloadLastDir.getFile(uri1).path, dir1.path, "uri1 should return dir1 outside PB mode");
-
-      // check that the last dir store got cleared
-      pb.privateBrowsingEnabled = true;
-      is(gDownloadLastDir.file.path, dir1.path, "LastDir should be cleared");
-      is(gDownloadLastDir.getFile(uri1).path, dir1.path, "uri1 should return dir1");
+  // check data set inside PB mode is forgotten
+  yield testOnWindow(true, function(win, downloadDir) {
+    downloadDir.setFile(null, tmpDir);
+    checkDownloadLastDir(win, downloadDir, tmpDir);
+  });
+  yield testOnWindow(false, function(win, downloadDir) {
+    checkDownloadLastDirNull(win, downloadDir);
+    clearHistory();
+  });
 
-      waitForPB();
-      pb.privateBrowsingEnabled = false;
-      yield;
-      clearHistory();
-    }
-
-    { // check clearHistory inside PB mode clears data outside PB mode
-      pb.privateBrowsingEnabled = true;
-      gDownloadLastDir.setFile(uri1, dir2);
+  // check data set using CPS inside PB mode is forgotten
+  yield testOnWindow(true, function(win, downloadDir) {
+    downloadDir.setFile(uri1, dir1);
+    checkDownloadLastDir(win, downloadDir, dir1);
+  });
+  yield testOnWindow(false, function(win, downloadDir) {
+    checkDownloadLastDirNull(win, downloadDir);
+    clearHistory();
+    downloadDir.setFile(uri1, dir1);
+  });
 
-      clearHistory();
-      is(gDownloadLastDir.file, null, "LastDir should be null afer clearing history");
-      is(gDownloadLastDir.getFile(uri1), null, "uri1 should return null");
-
-      waitForPB();
-      pb.privateBrowsingEnabled = false;
-      yield;
-      is(gDownloadLastDir.file, null, "LastDir should be null");
-      is(gDownloadLastDir.getFile(uri1), null, "uri1 should return null");
-    }
-
-    { // check that disabling CPS works
-      Services.prefs.setBoolPref("browser.download.lastDir.savePerSite", false);
+  // check data set outside PB mode but changed inside is remembered correctly
+  yield testOnWindow(true, function(win, downloadDir) {
+    downloadDir.setFile(uri1, dir2);
+    checkDownloadLastDir(win, downloadDir, dir2);
+  });
+  yield testOnWindow(false, function(win, downloadDir) {
+    checkDownloadLastDir(win, downloadDir, dir1);
+  });
 
-      gDownloadLastDir.setFile(uri1, dir1);
-      is(gDownloadLastDir.file.path, dir1.path, "LastDir should be set to dir1");
-      is(gDownloadLastDir.getFile(uri1).path, dir1.path, "uri1 should return dir1");
-      is(gDownloadLastDir.getFile(uri2).path, dir1.path, "uri2 should return dir1");
-      is(gDownloadLastDir.getFile(uri3).path, dir1.path, "uri3 should return dir1");
-      is(gDownloadLastDir.getFile(uri4).path, dir1.path, "uri4 should return dir1");
-
-      gDownloadLastDir.setFile(uri2, dir2);
-      is(gDownloadLastDir.file.path, dir2.path, "LastDir should be set to dir2");
-      is(gDownloadLastDir.getFile(uri1).path, dir2.path, "uri1 should return dir2");
-      is(gDownloadLastDir.getFile(uri2).path, dir2.path, "uri2 should return dir2");
-      is(gDownloadLastDir.getFile(uri3).path, dir2.path, "uri3 should return dir2");
-      is(gDownloadLastDir.getFile(uri4).path, dir2.path, "uri4 should return dir2");
+  // check that the last dir store got cleared
+  yield testOnWindow(true, function(win, downloadDir) {
+    checkDownloadLastDir(win, downloadDir, dir1);
+  });
+  yield testOnWindow(false, function(win, downloadDir) {
+    clearHistory();
+  });
 
-      Services.prefs.clearUserPref("browser.download.lastDir.savePerSite");
-    }
-
-    { // check that passing null to setFile clears the stored value
-      gDownloadLastDir.setFile(uri3, dir3);
-      is(gDownloadLastDir.getFile(uri3).path, dir3.path, "LastDir should be set to dir3");
-      gDownloadLastDir.setFile(uri3, null);
-      is(gDownloadLastDir.getFile(uri3), null, "uri3 should return null");
-    }
-  } finally {
-      dir1.remove(true);
-      dir2.remove(true);
-      dir3.remove(true);
-      Services.prefs.clearUserPref("browser.download.lastDir.savePerSite");
-      Services.prefs.clearUserPref("browser.download.lastDir");
-      gDownloadLastDir.cleanupPrivateFile();
-  }
+  // check clearHistory inside PB mode clears data outside PB mode
+  yield testOnWindow(true, function(win, downloadDir) {
+    downloadDir.setFile(uri1, dir2);
+    clearHistory();
+    checkDownloadLastDirNull(win, downloadDir);
+  });
+  yield testOnWindow(false, function(win, downloadDir) {
+    checkDownloadLastDirNull(win, downloadDir);
+    checkSetFile(downloadDir, dir1, dir2, dir3);
+  });
 }
copy from browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_downloadLastDir.js
copy to browser/components/privatebrowsing/test/browser/perwindow/browser_privatebrowsing_downloadLastDir.js
--- a/browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_downloadLastDir.js
+++ b/browser/components/privatebrowsing/test/browser/perwindow/browser_privatebrowsing_downloadLastDir.js
@@ -1,99 +1,91 @@
 /* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 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() {
-  let tempScope = {};
-  let downloadModule = {};
-  Cu.import("resource://gre/modules/Services.jsm");
-  Cu.import("resource://gre/modules/DownloadLastDir.jsm", downloadModule);
-  Cu.import("resource://gre/modules/FileUtils.jsm", tempScope);
-  let FileUtils = tempScope.FileUtils;
+  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 gDownloadLastDir = new downloadModule.DownloadLastDir(window);
-
   let launcher = {
     source: Services.io.newURI("http://test1.com/file", null, null)
   };
-  let pb = Cc["@mozilla.org/privatebrowsing;1"].
-           getService(Ci.nsIPrivateBrowsingService);
 
   MockFilePicker.init();
-   MockFilePicker.returnValue = Ci.nsIFilePicker.returnOK;
+  MockFilePicker.returnValue = Ci.nsIFilePicker.returnOK;
 
-  Services.prefs.setBoolPref("browser.privatebrowsing.keep_current_session", true);
   let prefs = Services.prefs.getBranch("browser.download.");
-  let launcherDialog = Cc["@mozilla.org/helperapplauncherdialog;1"].
-                       getService(Ci.nsIHelperAppLauncherDialog);
+  let launcherDialog =
+    Cc["@mozilla.org/helperapplauncherdialog;1"].
+    getService(Ci.nsIHelperAppLauncherDialog);
   let tmpDir = FileUtils.getDir("TmpD", [], true);
-  function newDirectory() {
-    let dir = tmpDir.clone();
-    dir.append("testdir");
-    dir.createUnique(Ci.nsIFile.DIRECTORY_TYPE, 0700);
-    return dir;
-  }
-  function newFileInDirectory(dir) {
-    let file = dir.clone();
-    file.append("testfile");
-    file.createUnique(Ci.nsIFile.DIRECTORY_TYPE, 0600);
-    return file;
-  }
-
   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.privatebrowsing.keep_current_session");
     Services.prefs.clearUserPref("browser.download.lastDir");
     [dir1, dir2, dir3].forEach(function(dir) dir.remove(true));
     MockFilePicker.cleanup();
-    gDownloadLastDir.cleanupPrivateFile();
-    delete FileUtils;
   });
-
-  let context = gBrowser.selectedBrowser.contentWindow;
-
   prefs.setComplexValue("lastDir", Ci.nsIFile, tmpDir);
-  MockFilePicker.returnFiles = [file1];
-  let file = launcherDialog.promptForSaveToFile(launcher, context, null, null, null);
-  ok(!!file, "promptForSaveToFile correctly returned a file");
-  // file picker should start with browser.download.lastDir
-  is(MockFilePicker.displayDirectory.path, tmpDir.path, "File picker should start with browser.download.lastDir");
-  // browser.download.lastDir should be modified before entering the private browsing mode
-  is(prefs.getComplexValue("lastDir", Ci.nsIFile).path, dir1.path, "LastDir should be modified before entering the PB mode");
-  // gDownloadLastDir should be usable outside of the private browsing mode
-  is(gDownloadLastDir.file.path, dir1.path, "gDownloadLastDir should be usable outside of the PB mode");
+
+  function testOnWindow(aPrivate, aCallback) {
+    whenNewWindowLoaded({private: aPrivate}, function(win) {
+      let gDownloadLastDir = new DownloadLastDir(win);
+      aCallback(win, gDownloadLastDir);
+      gDownloadLastDir.cleanupPrivateFile();
+      win.close();
+    });
+  }
+
+  function testDownloadDir(aWin, gDownloadLastDir, aFile, aDisplayDir, aLastDir,
+                           aGlobalLastDir, aCallback) {
+    let context = aWin.gBrowser.selectedBrowser.contentWindow;
+
+    // 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");
 
-  pb.privateBrowsingEnabled = true;
-  is(prefs.getComplexValue("lastDir", Ci.nsIFile).path, dir1.path, "LastDir should be that set before entering PB mode");
-  MockFilePicker.returnFiles = [file2];
-  MockFilePicker.displayDirectory = null;
-  file = launcherDialog.promptForSaveToFile(launcher, context, null, null, null);
-  ok(!!file, "promptForSaveToFile correctly returned a file");
-  // file picker should start with browser.download.lastDir as set before entering the private browsing mode
-  is(MockFilePicker.displayDirectory.path, dir1.path, "Start with LastDir as set before entering the PB mode");
-  // browser.download.lastDir should not be modified inside the private browsing mode
-  is(prefs.getComplexValue("lastDir", Ci.nsIFile).path, dir1.path, "LastDir should not be modified inside the PB mode");
-  // but gDownloadLastDir should be modified
-  is(gDownloadLastDir.file.path, dir2.path, "gDownloadLastDir should be modified inside PB mode");
+    MockFilePicker.returnFiles = [aFile];
+    MockFilePicker.displayDirectory = null;
+    let file =
+      launcherDialog.promptForSaveToFile(launcher, context, null, null, null);
+    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");
 
-  pb.privateBrowsingEnabled = false;
-  // gDownloadLastDir should be cleared after leaving the private browsing mode
-  is(gDownloadLastDir.file.path, dir1.path, "gDownloadLastDir should be cleared after leaving the PB mode");
-  MockFilePicker.returnFiles = [file3];
-  MockFilePicker.displayDirectory = null;
-  file = launcherDialog.promptForSaveToFile(launcher, context, null, null, null);
-  ok(!!file, "promptForSaveToFile correctly returned a file");
-  // file picker should start with browser.download.lastDir as set before entering the private browsing mode
-  is(MockFilePicker.displayDirectory.path, dir1.path, "Start with LastDir as set before entering the PB mode");
-  // browser.download.lastDir should be modified after leaving the private browsing mode
-  is(prefs.getComplexValue("lastDir", Ci.nsIFile).path, dir3.path, "LastDir should be modified after leaving the PB mode");
-  // gDownloadLastDir should be usable after leaving the private browsing mode
-  is(gDownloadLastDir.file.path, dir3.path, "gDownloadLastDir should be usable after leaving the PB mode");
+    aCallback();
+  }
+
+  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);
+          });
+        });
+      });
+    });
+  });
 }
copy from browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_downloadLastDir_c.js
copy to browser/components/privatebrowsing/test/browser/perwindow/browser_privatebrowsing_downloadLastDir_c.js
--- a/browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_downloadLastDir_c.js
+++ b/browser/components/privatebrowsing/test/browser/perwindow/browser_privatebrowsing_downloadLastDir_c.js
@@ -1,114 +1,96 @@
 /* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 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() {
-  let tmpScope = {};
-  let downloadModule = {};
-  Cu.import("resource://gre/modules/DownloadLastDir.jsm", downloadModule);
-  Cu.import("resource://gre/modules/FileUtils.jsm", tmpScope);
-  let FileUtils = tmpScope.FileUtils;
-  Cu.import("resource://gre/modules/Services.jsm");
+  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 gDownloadLastDir = new downloadModule.DownloadLastDir(window);
-
-  let pb = Cc["@mozilla.org/privatebrowsing;1"].
-           getService(Ci.nsIPrivateBrowsingService);
 
   MockFilePicker.init();
   MockFilePicker.returnValue = Ci.nsIFilePicker.returnOK;
 
-  //let stringBundleToRestore = ContentAreaUtils.stringBundle;
   let validateFileNameToRestore = validateFileName;
-
-  Services.prefs.setBoolPref("browser.privatebrowsing.keep_current_session", true);
   let prefs = Services.prefs.getBranch("browser.download.");
   let tmpDir = FileUtils.getDir("TmpD", [], true);
-  function newDirectory() {
-    let dir = tmpDir.clone();
-    dir.append("testdir");
-    dir.createUnique(Ci.nsIFile.DIRECTORY_TYPE, 0700);
-    return dir;
-  }
-
-  function newFileInDirectory(dir) {
-    let file = dir.clone();
-    file.append("testfile");
-    file.createUnique(Ci.nsIFile.DIRECTORY_TYPE, 0600);
-    return file;
-  }
-
   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.privatebrowsing.keep_current_session");
     Services.prefs.clearUserPref("browser.download.lastDir");
     [dir1, dir2, dir3].forEach(function(dir) dir.remove(true));
     MockFilePicker.cleanup();
-    //ContentAreaUtils.stringBundle = stringBundleToRestore;
     validateFileName = validateFileNameToRestore;
-    gDownloadLastDir.cleanupPrivateFile();
-    delete FileUtils;
   });
 
-  // Overwrite stringBundle to return an object masquerading as a string bundle
-  /*delete ContentAreaUtils.stringBundle;
-  ContentAreaUtils.stringBundle = {
-    GetStringFromName: function() ""
-  };*/
-
   // Overwrite validateFileName to validate everything
   validateFileName = function(foo) foo;
 
   let params = {
-    //fpTitleKey: "test",
     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);
-  MockFilePicker.returnFiles = [file1];
-  MockFilePicker.displayDirectory = null;
-  ok(getTargetFile(params), "Show the file picker dialog with given params");
-  // file picker should start with browser.download.lastDir
-  is(MockFilePicker.displayDirectory.path, tmpDir.path, "file picker should start with browser.download.lastDir");
-  // browser.download.lastDir should be modified before entering the private browsing mode
-  is(prefs.getComplexValue("lastDir", Ci.nsIFile).path, dir1.path, "LastDir should be modified before entering PB mode");
-  // gDownloadLastDir should be usable outside of the private browsing mode
-  is(gDownloadLastDir.file.path, dir1.path, "gDownloadLastDir should be usable outside of the PB mode");
+
+  function testOnWindow(aPrivate, aCallback) {
+    whenNewWindowLoaded({private: aPrivate}, function(win) {
+      let gDownloadLastDir = new DownloadLastDir(win);
+      aCallback(win, gDownloadLastDir);
+      gDownloadLastDir.cleanupPrivateFile();
+      win.close();
+    });
+  }
+
+  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;
+    ok(aWin.getTargetFile(params),
+       "Show the file picker dialog with given params");
 
-  pb.privateBrowsingEnabled = true;
-  is(prefs.getComplexValue("lastDir", Ci.nsIFile).path, dir1.path, "LastDir should be that set before PB mode");
-  MockFilePicker.returnFiles = [file2];
-  MockFilePicker.displayDirectory = null;
-  ok(getTargetFile(params), "Show the file picker dialog with the given params");
-  // file picker should start with browser.download.lastDir as set before entering the private browsing mode
-  is(MockFilePicker.displayDirectory.path, dir1.path, "File picker should start with LastDir set before entering PB mode");
-  // browser.download.lastDir should not be modified inside the private browsing mode
-  is(prefs.getComplexValue("lastDir", Ci.nsIFile).path, dir1.path, "LastDir should not be modified inside PB mode");
-  // but gDownloadLastDir should be modified
-  is(gDownloadLastDir.file.path, dir2.path, "gDownloadLastDir should be modified");
+    // 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");
+
+    aCallback();
+  }
 
-  pb.privateBrowsingEnabled = false;
-  // gDownloadLastDir should be cleared after leaving the private browsing mode
-  is(gDownloadLastDir.file.path, dir1.path, "gDownloadLastDir should be cleared after leaving PB mode");
-  MockFilePicker.returnFiles = [file3];
-  MockFilePicker.displayDirectory = null;
-  ok(getTargetFile(params), "Show the file picker dialog with the given params");
-  // file picker should start with browser.download.lastDir as set before entering the private browsing mode
-  is(MockFilePicker.displayDirectory.path, dir1.path, "File picker should start with LastDir set before PB mode");
-  // browser.download.lastDir should be modified after leaving the private browsing mode
-  is(prefs.getComplexValue("lastDir", Ci.nsIFile).path, dir3.path, "LastDir should be modified after leaving PB mode");
-  // gDownloadLastDir should be usable after leaving the private browsing mode
-  is(gDownloadLastDir.file.path, dir3.path, "gDownloadLastDir should be usable after leaving PB mode");
+  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);
+          });
+        });
+      });
+    });
+  });
 }
copy from browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_downloadLastDir_toggle.js
copy to browser/components/privatebrowsing/test/browser/perwindow/browser_privatebrowsing_downloadLastDir_toggle.js
--- a/browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_downloadLastDir_toggle.js
+++ b/browser/components/privatebrowsing/test/browser/perwindow/browser_privatebrowsing_downloadLastDir_toggle.js
@@ -1,76 +1,97 @@
 /* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 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() {
-  var tmpScope = {};
-  let downloadModule = {};
-  Cu.import("resource://gre/modules/DownloadLastDir.jsm", downloadModule);
-  Cu.import("resource://gre/modules/FileUtils.jsm", tmpScope);
-  Cu.import("resource://gre/modules/Services.jsm");
-  let FileUtils = tmpScope.FileUtils;
-  let gDownloadLastDir = new downloadModule.DownloadLastDir(window);
+  waitForExplicitFinish();
 
-  let pb = Cc["@mozilla.org/privatebrowsing;1"].
-           getService(Ci.nsIPrivateBrowsingService);
+  let FileUtils =
+    Cu.import("resource://gre/modules/FileUtils.jsm", {}).FileUtils;
+  let DownloadLastDir =
+    Cu.import("resource://gre/modules/DownloadLastDir.jsm", {}).DownloadLastDir;
 
-  function clearHistory() {
-    // simulate clearing the private data
-    Services.obs.notifyObservers(null, "browser:purge-session-history", "");
-  }
-
-  is(typeof gDownloadLastDir, "object", "gDownloadLastDir should be a valid object");
-  is(gDownloadLastDir.file, null, "gDownloadLastDir.file should be null to start with");
   let tmpDir = FileUtils.getDir("TmpD", [], true);
-  let newDir = tmpDir.clone();
+  let dir1 = newDirectory();
 
   registerCleanupFunction(function () {
-    Services.prefs.clearUserPref("browser.privatebrowsing.keep_current_session");
     Services.prefs.clearUserPref("browser.download.lastDir");
-    newDir.remove(true);
-    gDownloadLastDir.cleanupPrivateFile();
-    delete FileUtils;
+    dir1.remove(true);
   });
 
-  newDir.append("testdir");
-  newDir.createUnique(Ci.nsIFile.DIRECTORY_TYPE, 0700);
+  function testOnWindow(aPrivate, aCallback) {
+    whenNewWindowLoaded({private: aPrivate}, function(win) {
+      let gDownloadLastDir = new DownloadLastDir(win);
+      aCallback(win, gDownloadLastDir);
+      gDownloadLastDir.cleanupPrivateFile();
+      win.close();
+    });
+  }
 
-  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");
+  function checkDownloadLastDirInit(aWin, gDownloadLastDir, aCallback) {
+    is(typeof gDownloadLastDir, "object",
+       "gDownloadLastDir should be a valid object");
+    is(gDownloadLastDir.file, null,
+       "gDownloadLastDir.file should be null to start with");
 
-  gDownloadLastDir.file = 1; // not an nsIFile
-  is(gDownloadLastDir.file, null, "gDownloadLastDir.file should be null");
-  gDownloadLastDir.file = tmpDir;
+    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");
 
-  clearHistory();
-  is(gDownloadLastDir.file, null, "gDownloadLastDir.file should be null");
-  gDownloadLastDir.file = tmpDir;
+    gDownloadLastDir.file = 1; // not an nsIFile
+    is(gDownloadLastDir.file, null, "gDownloadLastDir.file should be null");
 
-  Services.prefs.setBoolPref("browser.privatebrowsing.keep_current_session", true);
+    gDownloadLastDir.file = tmpDir;
+    clearHistory();
+    is(gDownloadLastDir.file, null, "gDownloadLastDir.file should be null");
 
-  pb.privateBrowsingEnabled = true;
-  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 = tmpDir;
+    aCallback();
+  }
 
-  pb.privateBrowsingEnabled = false;
-  is(gDownloadLastDir.file.path, tmpDir.path, "LastDir should point to the tmpDir");
-  pb.privateBrowsingEnabled = true;
+  function checkDownloadLastDir(aWin, gDownloadLastDir, aLastDir, aUpdate, aCallback) {
+    if (aUpdate)
+      gDownloadLastDir.file = aLastDir;
+    is(gDownloadLastDir.file.path, aLastDir.path,
+       "gDownloadLastDir should point to the expected last directory");
+    isnot(gDownloadLastDir.file, aLastDir,
+          "gDownloadLastDir.file should not be pointing to the last directory");
+    aCallback();
+  }
 
-  gDownloadLastDir.file = newDir;
-  is(gDownloadLastDir.file.path, newDir.path, "gDownloadLastDir should be modified in PB mode");
-  isnot(gDownloadLastDir.file, newDir, "gDownloadLastDir should not point to the newDir");
+  function checkDownloadLastDirNull(aWin, gDownloadLastDir, aCallback) {
+    is(gDownloadLastDir.file, null, "gDownloadLastDir should be null");
+    aCallback();
+  }
 
-  pb.privateBrowsingEnabled = false;
-  is(gDownloadLastDir.file.path, tmpDir.path, "gDownloadLastDir should point to the earlier directory outside PB mode");
-  isnot(gDownloadLastDir.file, tmpDir, "gDownloadLastDir should not be modifief outside PB mode");
-
-  pb.privateBrowsingEnabled = true;
-  isnot(gDownloadLastDir.file, null, "gDownloadLastDir should not be null inside PB mode");
-  clearHistory();
-  is(gDownloadLastDir.file, null, "gDownloadLastDir should be null after clearing history");
-
-  pb.privateBrowsingEnabled = false;
-  is(gDownloadLastDir.file, null, "gDownloadLastDir should be null outside PB mode");
+  testOnWindow(false, function(win, downloadDir) {
+    checkDownloadLastDirInit(win, downloadDir, function() {
+      testOnWindow(true, function(win, downloadDir) {
+        checkDownloadLastDir(win, downloadDir, tmpDir, false, function() {
+          testOnWindow(false, function(win, downloadDir) {
+            checkDownloadLastDir(win, downloadDir, tmpDir, false, function() {
+              testOnWindow(true, function(win, downloadDir) {
+                checkDownloadLastDir(win, downloadDir, dir1, true, function() {
+                  testOnWindow(false, function(win, downloadDir) {
+                    checkDownloadLastDir(win, downloadDir, tmpDir, false, function() {
+                      testOnWindow(true, function(win, downloadDir) {
+                        clearHistory();
+                        checkDownloadLastDirNull(win, downloadDir, function() {
+                          testOnWindow(false, function(win, downloadDir) {
+                            checkDownloadLastDirNull(win, downloadDir, finish);
+                          });
+                        });
+                      });
+                    });
+                  });
+                });
+              });
+            });
+          });
+        });
+      });
+    });
+  });
 }
--- a/browser/components/privatebrowsing/test/browser/perwindow/head.js
+++ b/browser/components/privatebrowsing/test/browser/perwindow/head.js
@@ -7,8 +7,40 @@ function setPrivateWindow(aWindow, aEnab
                  .getInterface(Ci.nsIWebNavigation)
                  .QueryInterface(Ci.nsIDocShellTreeItem)
                  .treeOwner
                  .QueryInterface(Ci.nsIInterfaceRequestor)
                  .getInterface(Ci.nsIXULWindow)
                  .docShell.QueryInterface(Ci.nsILoadContext)
                  .usePrivateBrowsing = aEnable;
 } 
+
+function whenNewWindowLoaded(aOptions, aCallback) {
+  let win = OpenBrowserWindow(aOptions);
+  win.addEventListener("load", function onLoad() {
+    win.removeEventListener("load", onLoad, false);
+    aCallback(win);
+  }, false);
+}
+
+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", "");
+}