diff --git a/accessible/src/base/ARIAStateMap.cpp b/accessible/src/base/ARIAStateMap.cpp index 66948d2d71f..91d07cc0a5b 100644 --- a/accessible/src/base/ARIAStateMap.cpp +++ b/accessible/src/base/ARIAStateMap.cpp @@ -6,6 +6,7 @@ #include "ARIAStateMap.h" +#include "nsARIAMap.h" #include "States.h" #include "mozilla/dom/Element.h" @@ -221,11 +222,23 @@ aria::MapToState(EStateRule aRule, dom::Element* aElement, PRUint64* aState) case eARIAOrientation: { - static const EnumTypeData data( - nsGkAtoms::aria_orientation, states::HORIZONTAL, - &nsGkAtoms::vertical, states::VERTICAL); + if (aElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::aria_orientation, + NS_LITERAL_STRING("horizontal"), eCaseMatters)) { + *aState &= ~states::VERTICAL; + *aState |= states::HORIZONTAL; + } else if (aElement->AttrValueIs(kNameSpaceID_None, + nsGkAtoms::aria_orientation, + NS_LITERAL_STRING("vertical"), + eCaseMatters)) { + *aState &= ~states::HORIZONTAL; + *aState |= states::VERTICAL; + } else { + NS_ASSERTION(!(*aState & (states::HORIZONTAL | states::VERTICAL)), + "orientation state on role with default aria-orientation!"); + *aState |= GetRoleMap(aElement)->Is(nsGkAtoms::scrollbar) ? + states::VERTICAL : states::HORIZONTAL; + } - MapEnumType(aElement, aState, data); return true; } diff --git a/accessible/src/base/NotificationController.cpp b/accessible/src/base/NotificationController.cpp index 48275dbf1bd..282e90ace79 100644 --- a/accessible/src/base/NotificationController.cpp +++ b/accessible/src/base/NotificationController.cpp @@ -21,7 +21,9 @@ #endif #include "mozilla/dom/Element.h" +#include "mozilla/Telemetry.h" +using namespace mozilla; using namespace mozilla::a11y; // Defines the number of selection add/remove events in the queue when they @@ -174,6 +176,8 @@ NotificationController::IsUpdatePending() void NotificationController::WillRefresh(mozilla::TimeStamp aTime) { + Telemetry::AutoTimer updateTimer(); + // If the document accessible that notification collector was created for is // now shut down, don't process notifications anymore. NS_ASSERTION(mDocument, diff --git a/accessible/src/generic/Accessible.cpp b/accessible/src/generic/Accessible.cpp index 0f20cbd8721..5a3ea8b109f 100644 --- a/accessible/src/generic/Accessible.cpp +++ b/accessible/src/generic/Accessible.cpp @@ -680,10 +680,20 @@ Accessible::NativeState() state |= states::FLOATING; // Check if a XUL element has the popup attribute (an attached popup menu). - if (mContent->IsXUL()) + if (mContent->IsXUL()) { if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::popup)) state |= states::HASPOPUP; + const nsStyleXUL *xulStyle = frame->GetStyleXUL(); + if (xulStyle && frame->IsBoxFrame()) { + // In XUL all boxes are either vertical or horizontal + if (xulStyle->mBoxOrient == NS_STYLE_BOX_ORIENT_VERTICAL) + state |= states::VERTICAL; + else + state |= states::HORIZONTAL; + } + } + // Bypass the link states specialization for non links. if (!mRoleMapEntry || mRoleMapEntry->roleRule == kUseNativeRole || mRoleMapEntry->role == roles::LINK) @@ -1510,17 +1520,6 @@ Accessible::State() state |= states::OPAQUE1; } - const nsStyleXUL *xulStyle = frame->GetStyleXUL(); - if (xulStyle) { - // In XUL all boxes are either vertical or horizontal - if (xulStyle->mBoxOrient == NS_STYLE_BOX_ORIENT_VERTICAL) { - state |= states::VERTICAL; - } - else { - state |= states::HORIZONTAL; - } - } - return state; } diff --git a/accessible/tests/mochitest/hyperlink/test_general.html b/accessible/tests/mochitest/hyperlink/test_general.html index cc3635e9178..202b61c77c2 100644 --- a/accessible/tests/mochitest/hyperlink/test_general.html +++ b/accessible/tests/mochitest/hyperlink/test_general.html @@ -75,7 +75,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=418368 "Mozilla Foundation", true, 17, 18); is(normalHyperlinkAcc.getURI(0).spec, "http://www.mozilla.org/", "URI wrong for normalHyperlinkElement!"); - testStates(normalHyperlinkAcc, STATE_LINKED, EXT_STATE_HORIZONTAL); + testStates(normalHyperlinkAcc, STATE_LINKED, 0); ////////////////////////////////////////////////////////////////////////// // ARIA hyperlink @@ -83,7 +83,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=418368 [nsIAccessibleHyperLink]); testThis("AriaHyperlink", ariaHyperlinkAcc, ROLE_LINK, 1, "Mozilla Foundation Home", true, 30, 31); - testStates(ariaHyperlinkAcc, STATE_LINKED, EXT_STATE_HORIZONTAL); + testStates(ariaHyperlinkAcc, STATE_LINKED, 0); testAction("AriaHyperlink", ariaHyperlinkAcc, "click"); ////////////////////////////////////////////////////////////////////////// @@ -91,7 +91,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=418368 var invalidAriaHyperlinkAcc = getAccessible("InvalidAriaHyperlink", [nsIAccessibleHyperLink]); is(invalidAriaHyperlinkAcc.valid, false, "Should not be valid!"); - testStates(invalidAriaHyperlinkAcc, STATE_LINKED, EXT_STATE_HORIZONTAL); + testStates(invalidAriaHyperlinkAcc, STATE_LINKED, 0); ////////////////////////////////////////////////////////////////////////// // image map and its link children @@ -104,9 +104,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=418368 "http://www.bbc.co.uk/radio4/atoz/index.shtml#b", "URI wrong!"); is(imageMapHyperlinkAcc.getURI(1).spec, "http://www.bbc.co.uk/radio4/atoz/index.shtml#a", "URI wrong!"); - testStates(imageMapHyperlinkAcc, - (0), - (EXT_STATE_HORIZONTAL)); + testStates(imageMapHyperlinkAcc, 0, 0); var area1 = getAccessible(imageMapHyperlinkAcc.firstChild, [nsIAccessibleHyperLink]); @@ -127,9 +125,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=418368 var EmptyHLAcc = getAccessible("emptyLink", [nsIAccessibleHyperLink]); testThis("emptyLink", EmptyHLAcc, ROLE_LINK, 1, null, true, 93, 94); - testStates(EmptyHLAcc, - (STATE_FOCUSABLE | STATE_LINKED), - (EXT_STATE_HORIZONTAL)); + testStates(EmptyHLAcc, (STATE_FOCUSABLE | STATE_LINKED), 0); testAction("emptyLink", EmptyHLAcc, "jump"); ////////////////////////////////////////////////////////////////////////// @@ -140,7 +136,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=418368 "Heise Online", true, 119, 120); is(hyperlinkWithSpanAcc.getURI(0).spec, "http://www.heise.de/", "URI wrong for hyperlinkElementWithSpan!"); - testStates(hyperlinkWithSpanAcc, STATE_LINKED, EXT_STATE_HORIZONTAL); + testStates(hyperlinkWithSpanAcc, STATE_LINKED, 0); testAction("LinkWithSpan", hyperlinkWithSpanAcc, "jump"); ////////////////////////////////////////////////////////////////////////// @@ -149,9 +145,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=418368 [nsIAccessibleHyperLink]); testThis("namedAnchor", namedAnchorAcc, ROLE_LINK, 1, "This should never be of state_linked", true, 196, 197); - testStates(namedAnchorAcc, - (STATE_SELECTABLE), - (EXT_STATE_HORIZONTAL), (STATE_FOCUSABLE | STATE_LINKED)); + testStates(namedAnchorAcc, STATE_SELECTABLE, + 0, (STATE_FOCUSABLE | STATE_LINKED)); testAction("namedAnchor", namedAnchorAcc, ""); ////////////////////////////////////////////////////////////////////////// @@ -160,9 +155,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=418368 [nsIAccessibleHyperLink]); testThis("noLink", noLinkAcc, ROLE_LINK, 1, "This should never be of state_linked", true, 254, 255); - testStates(noLinkAcc, - 0, - (EXT_STATE_HORIZONTAL), (STATE_FOCUSABLE | STATE_LINKED)); + testStates(noLinkAcc, 0, 0, (STATE_FOCUSABLE | STATE_LINKED)); testAction("noLink", noLinkAcc, ""); ////////////////////////////////////////////////////////////////////////// @@ -171,9 +164,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=418368 [nsIAccessibleHyperLink]); testThis("linkWithClick", linkWithClickAcc, ROLE_LINK, 1, "This should have state_linked", true, 292, 293); - testStates(linkWithClickAcc, - (STATE_LINKED), - (EXT_STATE_HORIZONTAL)); + testStates(linkWithClickAcc, STATE_LINKED, 0); testAction("linkWithClick", linkWithClickAcc, "click"); ////////////////////////////////////////////////////////////////////////// @@ -185,9 +176,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=418368 var id = "linkWithTitleNoNameFromSubtree"; var linkAcc = getAccessible(id, [nsIAccessibleHyperLink]); testThis(id, linkAcc, ROLE_LINK, 1, "Link with title", true, 344, 345); - testStates(linkAcc, - (STATE_LINKED), - (EXT_STATE_HORIZONTAL)); + testStates(linkAcc, STATE_LINKED, 0); testAction(id, linkAcc, "jump"); ////////////////////////////////////////////////////////////////////////// @@ -197,9 +186,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=418368 linkAcc = getAccessible(id, [nsIAccessibleHyperLink]); testThis(id, linkAcc, ROLE_LINK, 1, "the name from subtree", true, 393, 394); - testStates(linkAcc, - (STATE_LINKED), - (EXT_STATE_HORIZONTAL)); + testStates(linkAcc, STATE_LINKED, 0); testAction(id, linkAcc, "jump"); ////////////////////////////////////////////////////////////////////////// @@ -208,9 +195,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=418368 linkAcc = getAccessible(id, [nsIAccessibleHyperLink]); testThis(id, linkAcc, ROLE_LINK, 1, "The title for link", true, 447, 448); - testStates(linkAcc, - (STATE_LINKED), - (EXT_STATE_HORIZONTAL)); + testStates(linkAcc, STATE_LINKED, 0); testAction(id, linkAcc, "jump"); ////////////////////////////////////////////////////////////////////////// @@ -219,9 +204,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=418368 linkAcc = getAccessible(id, [nsIAccessibleHyperLink]); testThis(id, linkAcc, ROLE_LINK, 1, "Link with label and nested image:", true, 450, 451); - testStates(linkAcc, - (STATE_LINKED), - (EXT_STATE_HORIZONTAL)); + testStates(linkAcc, STATE_LINKED, 0); testAction(id, linkAcc, "jump"); ////////////////////////////////////////////////////////////////////////// diff --git a/accessible/tests/mochitest/hyperlink/test_general.xul b/accessible/tests/mochitest/hyperlink/test_general.xul index 94b323ca540..c7b838a15fb 100644 --- a/accessible/tests/mochitest/hyperlink/test_general.xul +++ b/accessible/tests/mochitest/hyperlink/test_general.xul @@ -45,7 +45,7 @@ testThis("linkedLabel", linkedLabelAcc, ROLE_LINK, 1, "Mozilla Foundation home", "http://www.mozilla.org/", 1, 2, true); - testStates(linkedLabelAcc, STATE_LINKED, EXT_STATE_HORIZONTAL); + testStates(linkedLabelAcc, STATE_LINKED, 0); var labelWithValueAcc = getAccessible("linkLabelWithValue", [nsIAccessibleHyperLink]); diff --git a/accessible/tests/mochitest/states/test_aria.html b/accessible/tests/mochitest/states/test_aria.html index b891931fa00..34fa17c852f 100644 --- a/accessible/tests/mochitest/states/test_aria.html +++ b/accessible/tests/mochitest/states/test_aria.html @@ -153,15 +153,15 @@ testStates("aria_navigation_anchor", STATE_SELECTABLE); // aria-orientation (applied to scrollbar, separator, slider) - testStates("aria_scrollbar", 0, EXT_STATE_HORIZONTAL); - testStates("aria_hscrollbar", 0, EXT_STATE_HORIZONTAL); - testStates("aria_vscrollbar", 0, EXT_STATE_VERTICAL); - testStates("aria_separator", 0, EXT_STATE_HORIZONTAL); - testStates("aria_hseparator", 0, EXT_STATE_HORIZONTAL); - testStates("aria_vseparator", 0, EXT_STATE_VERTICAL); - testStates("aria_slider", 0, EXT_STATE_HORIZONTAL); - testStates("aria_hslider", 0, EXT_STATE_HORIZONTAL); - testStates("aria_vslider", 0, EXT_STATE_VERTICAL); + testStates("aria_scrollbar", 0, EXT_STATE_VERTICAL, 0, EXT_STATE_HORIZONTAL); + testStates("aria_hscrollbar", 0, EXT_STATE_HORIZONTAL, 0, EXT_STATE_VERTICAL); + testStates("aria_vscrollbar", 0, EXT_STATE_VERTICAL, 0, EXT_STATE_HORIZONTAL); + testStates("aria_separator", 0, EXT_STATE_HORIZONTAL, 0, EXT_STATE_VERTICAL); + testStates("aria_hseparator", 0, EXT_STATE_HORIZONTAL, 0, EXT_STATE_VERTICAL); + testStates("aria_vseparator", 0, EXT_STATE_VERTICAL, 0, EXT_STATE_HORIZONTAL); + testStates("aria_slider", 0, EXT_STATE_HORIZONTAL, 0, EXT_STATE_VERTICAL); + testStates("aria_hslider", 0, EXT_STATE_HORIZONTAL, 0, EXT_STATE_VERTICAL); + testStates("aria_vslider", 0, EXT_STATE_VERTICAL, 0, EXT_STATE_HORIZONTAL); // indeterminate ARIA progressbars (no aria-valuenow or aria-valuetext attribute) // should expose mixed state @@ -225,6 +225,11 @@ title="ARIA undetermined progressmeters should expose mixed state"> Mozilla Bug 740851 + + Mozilla Bug 762876 +

diff --git a/b2g/chrome/content/shell.js b/b2g/chrome/content/shell.js
index 0e339b72327..f79bfe82961 100644
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -246,8 +246,8 @@ var shell = {
           if (!manifest)
             return;
 
-          let documentURI = contentWindow.document.documentURIObject;
-          if (!Services.perms.testPermission(documentURI, 'offline-app')) {
+          let principal = contentWindow.document.nodePrincipal;
+          if (Services.perms.testPermissionFromPrincipal(principal, 'offline-app') == Ci.nsIPermissionManager.UNKNOWN_ACTION) {
             if (Services.prefs.getBoolPref('browser.offline-apps.notify')) {
               // FIXME Bug 710729 - Add a UI for offline cache notifications
               return;
@@ -255,8 +255,8 @@ var shell = {
             return;
           }
 
-          Services.perms.add(documentURI, 'offline-app',
-                             Ci.nsIPermissionManager.ALLOW_ACTION);
+          Services.perms.addFromPrincipal(principal, 'offline-app',
+                                          Ci.nsIPermissionManager.ALLOW_ACTION);
 
           let manifestURI = Services.io.newURI(manifest, null, documentURI);
           let updateService = Cc['@mozilla.org/offlinecacheupdate-service;1']
diff --git a/b2g/components/CameraContent.js b/b2g/components/CameraContent.js
index 711db38982a..2a06d07f6b7 100644
--- a/b2g/components/CameraContent.js
+++ b/b2g/components/CameraContent.js
@@ -59,7 +59,7 @@ CameraContent.prototype = {
     let principal = aWindow.document.nodePrincipal;
     let secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager);
 
-    let perm = principal == secMan.getSystemPrincipal() ? Ci.nsIPermissionManager.ALLOW_ACTION : Services.perms.testExactPermission(principal.URI, "content-camera");
+    let perm = Services.perms.testExactPermissionFromPrincipal(principal, "content-camera");
 
     //only pages with perm set and chrome pages can use the camera in content
     this.hasPrivileges = perm == Ci.nsIPermissionManager.ALLOW_ACTION;
diff --git a/browser/components/privatebrowsing/test/browser/Makefile.in b/browser/components/privatebrowsing/test/browser/Makefile.in
index 02377ab8ddc..bdc591d3227 100644
--- a/browser/components/privatebrowsing/test/browser/Makefile.in
+++ b/browser/components/privatebrowsing/test/browser/Makefile.in
@@ -20,6 +20,10 @@ MOCHITEST_BROWSER_FILES =  \
 		browser_privatebrowsing_concurrent.js \
 		browser_privatebrowsing_concurrent_page.html \
 		browser_privatebrowsing_crh.js \
+		browser_privatebrowsing_downloadLastDir.js \
+		browser_privatebrowsing_downloadLastDir_c.js \
+		browser_privatebrowsing_downloadLastDir_toggle.js \
+		browser_privatebrowsing_DownloadLastDirWithCPS.js \
 		browser_privatebrowsing_fastswitch.js \
 		browser_privatebrowsing_findbar.js \
 		browser_privatebrowsing_forgetthissite.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 00000000000..029b427e5e0
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_DownloadLastDirWithCPS.js
@@ -0,0 +1,222 @@
+/* -*- 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/. */
+
+let downloadModule = {};
+Cu.import("resource://gre/modules/DownloadLastDir.jsm", downloadModule);
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/FileUtils.jsm");
+
+let gDownloadLastDir = new downloadModule.DownloadLastDir(window);
+let pb = Cc["@mozilla.org/privatebrowsing;1"].
+         getService(Ci.nsIPrivateBrowsingService);
+
+function test() {
+  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 tmpDir = FileUtils.getDir("TmpD", [], true);
+
+  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;
+  }
+
+  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");
+    }
+
+    { // 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"), 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);
+
+    { // 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");
+
+      pb.privateBrowsingEnabled = false;
+      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 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");
+
+      pb.privateBrowsingEnabled = false;
+      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 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");
+
+      pb.privateBrowsingEnabled = false;
+      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");
+
+      pb.privateBrowsingEnabled = false;
+      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");
+
+      pb.privateBrowsingEnabled = false;
+      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");
+
+      pb.privateBrowsingEnabled = false;
+      clearHistory();
+    }
+
+    { // check clearHistory inside PB mode clears data outside PB mode
+      pb.privateBrowsingEnabled = true;
+      gDownloadLastDir.setFile(uri1, dir2);
+
+      clearHistory();
+      is(gDownloadLastDir.file, null, "LastDir should be null afer clearing history");
+      is(gDownloadLastDir.getFile(uri1), null, "uri1 should return null");
+
+      pb.privateBrowsingEnabled = false;
+      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);
+
+      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");
+
+      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();
+      delete FileUtils;
+  }
+}
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 00000000000..3a00f673f3b
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadLastDir.js
@@ -0,0 +1,98 @@
+/* -*- 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/. */
+
+let downloadModule = {};
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/DownloadLastDir.jsm", downloadModule);
+Cu.import("resource://gre/modules/FileUtils.jsm");
+Cu.import("resource://mochikit/MockFilePicker.jsm");
+
+let launcher = {
+  source: Services.io.newURI("http://test1.com/file", null, null)
+};
+let pb = Cc["@mozilla.org/privatebrowsing;1"].
+         getService(Ci.nsIPrivateBrowsingService);
+let gDownloadLastDir = new downloadModule.DownloadLastDir(window);
+
+MockFilePicker.init();
+MockFilePicker.returnValue = Ci.nsIFilePicker.returnOK;
+
+function test() {
+  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 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");
+
+  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");
+
+  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");
+}
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 00000000000..976b4801e3e
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadLastDir_c.js
@@ -0,0 +1,112 @@
+/* -*- 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/. */
+
+let downloadModule = {};
+Cu.import("resource://gre/modules/DownloadLastDir.jsm", downloadModule);
+Cu.import("resource://gre/modules/FileUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://mochikit/MockFilePicker.jsm");
+
+let pb = Cc["@mozilla.org/privatebrowsing;1"].
+         getService(Ci.nsIPrivateBrowsingService);
+let gDownloadLastDir = new downloadModule.DownloadLastDir(window);
+
+MockFilePicker.init();
+MockFilePicker.returnValue = Ci.nsIFilePicker.returnOK;
+
+function test() {
+  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");
+
+  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");
+
+  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");
+}
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 00000000000..bd1148c6310
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadLastDir_toggle.js
@@ -0,0 +1,74 @@
+/* -*- 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/. */
+
+let downloadModule = {};
+Cu.import("resource://gre/modules/DownloadLastDir.jsm", downloadModule);
+Cu.import("resource://gre/modules/FileUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+
+let gDownloadLastDir = new downloadModule.DownloadLastDir(window);
+let pb = Cc["@mozilla.org/privatebrowsing;1"].
+         getService(Ci.nsIPrivateBrowsingService);
+
+function test() {
+  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();
+
+  registerCleanupFunction(function () {
+    Services.prefs.clearUserPref("browser.privatebrowsing.keep_current_session");
+    Services.prefs.clearUserPref("browser.download.lastDir");
+    newDir.remove(true);
+    gDownloadLastDir.cleanupPrivateFile();
+    delete FileUtils;
+  });
+
+  newDir.append("testdir");
+  newDir.createUnique(Ci.nsIFile.DIRECTORY_TYPE, 0700);
+
+  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;
+
+  Services.prefs.setBoolPref("browser.privatebrowsing.keep_current_session", true);
+
+  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");
+
+  pb.privateBrowsingEnabled = false;
+  is(gDownloadLastDir.file.path, tmpDir.path, "LastDir should point to the tmpDir");
+  pb.privateBrowsingEnabled = true;
+
+  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");
+
+  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");
+}
diff --git a/dom/alarm/AlarmsManager.js b/dom/alarm/AlarmsManager.js
index dd58638de2b..e384969a544 100644
--- a/dom/alarm/AlarmsManager.js
+++ b/dom/alarm/AlarmsManager.js
@@ -134,8 +134,7 @@ AlarmsManager.prototype = {
     let principal = aWindow.document.nodePrincipal;
     let secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager);
 
-    let perm = principal == secMan.getSystemPrincipal() ? 
-      Ci.nsIPermissionManager.ALLOW_ACTION : Services.perms.testExactPermission(principal.URI, "alarms");
+    let perm = Services.perms.testExactPermissionFromPrincipal(principal, "alarms");
 
     // Only pages with perm set can use the alarms.
     this.hasPrivileges = perm == Ci.nsIPermissionManager.ALLOW_ACTION;
diff --git a/dom/system/gonk/VolumeServiceTest.cpp b/dom/system/gonk/VolumeServiceTest.cpp
index 4c3745c5408..e228b8251f8 100644
--- a/dom/system/gonk/VolumeServiceTest.cpp
+++ b/dom/system/gonk/VolumeServiceTest.cpp
@@ -25,7 +25,7 @@ using namespace mozilla::services;
 namespace mozilla {
 namespace system {
 
-#define TEST_NSVOLUME_OBSERVER  1
+#define TEST_NSVOLUME_OBSERVER  0
 
 #if TEST_NSVOLUME_OBSERVER
 
diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp
index 787ed7eb9de..31fe12f38d1 100644
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -5128,7 +5128,6 @@ CompExprTransplanter::transplant(ParseNode *pn)
             if (genexp && !BumpStaticLevel(pn, tc))
                 return false;
         } else if (pn->isUsed()) {
-            JS_ASSERT(!pn->isOp(JSOP_NOP));
             JS_ASSERT(pn->pn_cookie.isFree());
 
             Definition *dn = pn->pn_lexdef;
diff --git a/js/src/jit-test/tests/basic/bug632778-1.js b/js/src/jit-test/tests/basic/bug632778-1.js
index b0aaaaa6511..1a46e9fd970 100644
--- a/js/src/jit-test/tests/basic/bug632778-1.js
+++ b/js/src/jit-test/tests/basic/bug632778-1.js
@@ -1,7 +1,6 @@
-load(libdir + "asserts.js");
+// |jit-test| error: TypeError
 function f() {
     "use strict";
 }
 g = wrap(f);
-assertThrowsInstanceOf(function () { Object.defineProperty(g, "arguments", {set: function(){}}); }, TypeError);
-
+Object.defineProperty(g, "arguments", {set: function(){}});
diff --git a/js/src/jit-test/tests/basic/bug632778-2.js b/js/src/jit-test/tests/basic/bug632778-2.js
index 907dae0e709..2ef9b11527a 100644
--- a/js/src/jit-test/tests/basic/bug632778-2.js
+++ b/js/src/jit-test/tests/basic/bug632778-2.js
@@ -1,4 +1,3 @@
-load(libdir + "asserts.js");
+// |jit-test| error: TypeError
 obj = wrap(Number.bind());
-assertThrowsInstanceOf(function () { Object.defineProperty(obj, "caller", {set: function(){}}); }, TypeError);
-
+Object.defineProperty(obj, "caller", {set: function () {}});
diff --git a/js/src/jit-test/tests/basic/bug633828.js b/js/src/jit-test/tests/basic/bug633828.js
new file mode 100644
index 00000000000..8db6d0fc701
--- /dev/null
+++ b/js/src/jit-test/tests/basic/bug633828.js
@@ -0,0 +1,6 @@
+// |jit-test| error: SyntaxError
+(function() {
+  function a() {}
+  function a() {}
+}
+for
diff --git a/js/src/jit-test/tests/basic/bug770952.js b/js/src/jit-test/tests/basic/bug770952.js
new file mode 100644
index 00000000000..64143284373
--- /dev/null
+++ b/js/src/jit-test/tests/basic/bug770952.js
@@ -0,0 +1,5 @@
+// |jit-test| error: TypeError
+eval("var x; typeof x")
+Array.prototype.iterator = function () { for(y in x); };
+for (var v of ['a', 'b', 'c', 'd'])
+    s = v;
diff --git a/js/src/jit-test/tests/basic/testBug775807.js b/js/src/jit-test/tests/basic/testBug775807.js
new file mode 100644
index 00000000000..78b7025f819
--- /dev/null
+++ b/js/src/jit-test/tests/basic/testBug775807.js
@@ -0,0 +1,19 @@
+// |jit-test| dump-bytecode;error:SyntaxError
+
+(function() {
+    const x = ((function() {
+        return {
+            e: function() {
+                (function() {
+                    for (e in x) {}
+                })()
+            }
+        }
+    }(function() {
+        return {
+            t: {
+                c
+            }
+        }
+    })))
+})()
diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp
index f7aa76b48b4..c35e5a7a6f4 100644
--- a/js/src/jsdbgapi.cpp
+++ b/js/src/jsdbgapi.cpp
@@ -1780,8 +1780,10 @@ JS_DumpCompartmentBytecode(JSContext *cx)
     ScriptsToDump scripts;
     IterateCells(cx->runtime, cx->compartment, gc::FINALIZE_SCRIPT, &scripts, DumpBytecodeScriptCallback);
 
-    for (size_t i = 0; i < scripts.length(); i++)
-        JS_DumpBytecode(cx, scripts[i]);
+    for (size_t i = 0; i < scripts.length(); i++) {
+        if (scripts[i]->enclosingScriptsCompiledSuccessfully())
+            JS_DumpBytecode(cx, scripts[i]);
+    }
 }
 
 JS_PUBLIC_API(void)
@@ -1789,7 +1791,7 @@ JS_DumpCompartmentPCCounts(JSContext *cx)
 {
     for (CellIter i(cx->compartment, gc::FINALIZE_SCRIPT); !i.done(); i.next()) {
         JSScript *script = i.get();
-        if (script->hasScriptCounts)
+        if (script->hasScriptCounts && script->enclosingScriptsCompiledSuccessfully())
             JS_DumpPCCounts(cx, script);
     }
 }
diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp
index f1627876185..a67ab7d3c3a 100644
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -1860,6 +1860,30 @@ JSScript::numNotes()
     return sn - notes_ + 1;    /* +1 for the terminator */
 }
 
+bool
+JSScript::enclosingScriptsCompiledSuccessfully() const
+{
+    /*
+     * When a nested script is succesfully compiled, it is eagerly given the
+     * static JSFunction of its enclosing script. The enclosing function's
+     * 'script' field will be NULL until the enclosing script successfully
+     * compiles. Thus, we can detect failed compilation by looking for
+     * JSFunctions in the enclosingScope chain without scripts.
+     */
+    JSObject *enclosing = enclosingScope_;
+    while (enclosing) {
+        if (enclosing->isFunction()) {
+            JSFunction *fun = enclosing->toFunction();
+            if (!fun->script())
+                return false;
+            enclosing = fun->script()->enclosingScope_;
+        } else {
+            enclosing = enclosing->asStaticBlock().enclosingStaticScope();
+        }
+    }
+    return true;
+}
+
 JS_FRIEND_API(void)
 js_CallNewScriptHook(JSContext *cx, JSScript *script, JSFunction *fun)
 {
diff --git a/js/src/jsscript.h b/js/src/jsscript.h
index 90cdabd13b3..c58447cc87b 100644
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -653,7 +653,22 @@ struct JSScript : public js::gc::Cell
     inline js::GlobalObject &global() const;
 
     /* See StaticScopeIter comment. */
-    JSObject *enclosingStaticScope() const { return enclosingScope_; }
+    JSObject *enclosingStaticScope() const {
+        JS_ASSERT(enclosingScriptsCompiledSuccessfully());
+        return enclosingScope_;
+    }
+
+    /*
+     * If a compile error occurs in an enclosing function after parsing a
+     * nested function, the enclosing function's JSFunction, which appears on
+     * the nested function's enclosingScope chain, will be invalid. Normal VM
+     * operation only sees scripts where all enclosing scripts have been
+     * successfully compiled. Any path that may look at scripts left over from
+     * unsuccessful compilation (e.g., by iterating over all scripts in the
+     * compartment) should check this predicate before doing any operation that
+     * uses enclosingScope (e.g., ScopeCoordinateName).
+     */
+    bool enclosingScriptsCompiledSuccessfully() const;
 
   private:
     bool makeTypes(JSContext *cx);
diff --git a/services/aitc/modules/browserid.js b/services/aitc/modules/browserid.js
index a0edf14ee08..41d82271ba6 100644
--- a/services/aitc/modules/browserid.js
+++ b/services/aitc/modules/browserid.js
@@ -212,12 +212,11 @@ BrowserIDService.prototype = {
     // We're executing navigator.id.get as a content script in win.
     // This results in a popup that we will temporarily unblock.
     let pm = Services.perms;
-    let origin = Services.io.newURI(
-      win.wrappedJSObject.location.toString(), null, null
-    );
-    let oldPerm = pm.testExactPermission(origin, "popup");
+    let principal = win.document.nodePrincipal;
+
+    let oldPerm = pm.testExactPermissionFromPrincipal(principal, "popup");
     try {
-      pm.add(origin, "popup", pm.ALLOW_ACTION);
+      pm.addFromPrincipal(principal, "popup", pm.ALLOW_ACTION);
     } catch(e) {
       this._log.warn("Setting popup blocking to false failed " + e);
     }
@@ -232,7 +231,7 @@ BrowserIDService.prototype = {
     function callback(val) {
       // Set popup blocker permission to original value.
       try {
-        pm.add(origin, "popup", oldPerm);
+        pm.addFromPrincipal(principal, "popup", oldPerm);
       } catch(e) {
         this._log.warn("Setting popup blocking to original value failed " + e);
       }
diff --git a/toolkit/components/telemetry/TelemetryHistograms.h b/toolkit/components/telemetry/TelemetryHistograms.h
index 59c6fb0dfa8..11220cc49bc 100644
--- a/toolkit/components/telemetry/TelemetryHistograms.h
+++ b/toolkit/components/telemetry/TelemetryHistograms.h
@@ -32,6 +32,7 @@ HISTOGRAM_ENUMERATED_VALUES(A11Y_CONSUMERS, 11, "Accessibility client by enum id
 HISTOGRAM_FLAG(A11Y_ISIMPLEDOM_USAGE_FLAG, "have the ISimpleDOM* accessibility interfaces been used")
 HISTOGRAM_FLAG(A11Y_IATABLE_USAGE_FLAG, "has the IAccessibleTable accessibility interface been used")
 HISTOGRAM_FLAG(A11Y_XFORMS_USAGE_FLAG, "has XForms accessibility been instantiated")
+HISTOGRAM(A11Y_UPDATE_TIME, 1, 10000, 50, EXPONENTIAL, "time spent updating accessibility (ms)")
 
 /**
  * Cycle collector telemetry
diff --git a/toolkit/content/contentAreaUtils.js b/toolkit/content/contentAreaUtils.js
index 1fb00c90f0b..4489954161c 100644
--- a/toolkit/content/contentAreaUtils.js
+++ b/toolkit/content/contentAreaUtils.js
@@ -1,4 +1,4 @@
-# -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- 
+# -*- 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/.
@@ -431,7 +431,7 @@ function internalPersist(persistArgs)
  * Structure for holding info about automatically supplied parameters for
  * internalSave(...). This allows parameters to be supplied so the user does not
  * need to be prompted for file info.
- * @param aFileAutoChosen This is an nsILocalFile object that has been
+ * @param aFileAutoChosen This is an nsIFile object that has been
  *        pre-determined as the filename for the target to save to
  * @param aUriAutoChosen  This is the nsIURI object for the target
  */
@@ -525,13 +525,13 @@ function initFileInfo(aFI, aURL, aURLCharset, aDocument,
  */
 function getTargetFile(aFpP, /* optional */ aSkipPrompt, /* optional */ aRelatedURI)
 {
-  if (!getTargetFile.gDownloadLastDir)
-    Components.utils.import("resource://gre/modules/DownloadLastDir.jsm", getTargetFile);
-  var gDownloadLastDir = getTargetFile.gDownloadLastDir;
+  let downloadModule = {};
+  Components.utils.import("resource://gre/modules/DownloadLastDir.jsm", downloadModule);
+  var gDownloadLastDir = new downloadModule.DownloadLastDir(window);
 
   var prefs = getPrefsBrowserDownload("browser.download.");
   var useDownloadDir = prefs.getBoolPref("useDownloadDir");
-  const nsILocalFile = Components.interfaces.nsILocalFile;
+  const nsIFile = Components.interfaces.nsIFile;
 
   if (!aSkipPrompt)
     useDownloadDir = false;
@@ -568,7 +568,7 @@ function getTargetFile(aFpP, /* optional */ aSkipPrompt, /* optional */ aRelated
     // Default to desktop.
     var fileLocator = Components.classes["@mozilla.org/file/directory_service;1"]
                                 .getService(Components.interfaces.nsIProperties);
-    dir = fileLocator.get("Desk", nsILocalFile);
+    dir = fileLocator.get("Desk", nsIFile);
   }
 
   var fp = makeFilePicker();
@@ -600,11 +600,11 @@ function getTargetFile(aFpP, /* optional */ aSkipPrompt, /* optional */ aRelated
     prefs.setIntPref("save_converter_index", fp.filterIndex);
 
   // Do not store the last save directory as a pref inside the private browsing mode
-  var directory = fp.file.parent.QueryInterface(nsILocalFile);
+  var directory = fp.file.parent.QueryInterface(nsIFile);
   gDownloadLastDir.setFile(aRelatedURI, directory);
 
   fp.file.leafName = validateFileName(fp.file.leafName);
-  
+
   aFpP.saveAsType = fp.filterIndex;
   aFpP.file = fp.file;
   aFpP.fileURL = fp.fileURL;
diff --git a/toolkit/content/tests/unit/test_privatebrowsing_downloadLastDir_c.js b/toolkit/content/tests/unit/test_privatebrowsing_downloadLastDir_c.js
deleted file mode 100644
index 56564130df8..00000000000
--- a/toolkit/content/tests/unit/test_privatebrowsing_downloadLastDir_c.js
+++ /dev/null
@@ -1,130 +0,0 @@
-/* -*- Mode: C++; 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/. */
-
-const Ci = Components.interfaces;
-const Cc = Components.classes;
-
-function loadUtilsScript() {
-  let loader = Cc["@mozilla.org/moz/jssubscript-loader;1"].
-               getService(Ci.mozIJSSubScriptLoader);
-  loader.loadSubScript("chrome://global/content/contentAreaUtils.js");
-  Components.utils.import("resource://gre/modules/DownloadLastDir.jsm");
-}
-
-do_get_profile();
-
-let window = {};
-function run_test()
-{
-  let pb;
-  try {
-    pb = Cc["@mozilla.org/privatebrowsing;1"].
-         getService(Ci.nsIPrivateBrowsingService);
-  } catch (e) {
-    print("PB service is not available, bail out");
-    return;
-  }
-
-  loadUtilsScript();
-
-  let prefsService = Cc["@mozilla.org/preferences-service;1"].
-                     getService(Ci.nsIPrefService).
-                     QueryInterface(Ci.nsIPrefBranch);
-  prefsService.setBoolPref("browser.privatebrowsing.keep_current_session", true);
-  let prefs = prefsService.getBranch("browser.download.");
-  let dirSvc = Cc["@mozilla.org/file/directory_service;1"].
-               getService(Ci.nsIProperties);
-  let tmpDir = dirSvc.get("TmpD", Ci.nsILocalFile);
-  function newDirectory() {
-    let dir = tmpDir.clone();
-    dir.append("testdir" + Math.floor(Math.random() * 10000));
-    dir.createUnique(Ci.nsIFile.DIRECTORY_TYPE, 0700);
-    return dir;
-  }
-  function newFileInDirectory(dir) {
-    let file = dir.clone();
-    file.append("testfile" + Math.floor(Math.random() * 10000));
-    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);
-
-  // overwrite makeFilePicker, as we don't want to create a real filepicker object
-  let fp = {
-    appendFilter: function() {},
-    appendFilters: function() {},
-    init: function() {},
-    show: function() Ci.nsIFilePicker.returnOK,
-    displayDirectory: null,
-    file: file1
-  };
-  makeFilePicker = function() fp;
-
-  // 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.nsILocalFile, tmpDir);
-
-  do_check_true(getTargetFile(params));
-  // file picker should start with browser.download.lastDir
-  do_check_eq(fp.displayDirectory.path, tmpDir.path);
-  // browser.download.lastDir should be modified before entering the private browsing mode
-  do_check_eq(prefs.getComplexValue("lastDir", Ci.nsILocalFile).path, dir1.path);
-  // gDownloadLastDir should be usable outside of the private browsing mode
-  do_check_eq(gDownloadLastDir.file.path, dir1.path);
-
-  pb.privateBrowsingEnabled = true;
-  do_check_eq(prefs.getComplexValue("lastDir", Ci.nsILocalFile).path, dir1.path);
-  fp.file = file2;
-  fp.displayDirectory = null;
-  do_check_true(getTargetFile(params));
-  // file picker should start with browser.download.lastDir as set before entering the private browsing mode
-  do_check_eq(fp.displayDirectory.path, dir1.path);
-  // browser.download.lastDir should not be modified inside the private browsing mode
-  do_check_eq(prefs.getComplexValue("lastDir", Ci.nsILocalFile).path, dir1.path);
-  // but gDownloadLastDir should be modified
-  do_check_eq(gDownloadLastDir.file.path, dir2.path);
-
-  pb.privateBrowsingEnabled = false;
-  // gDownloadLastDir should be cleared after leaving the private browsing mode
-  do_check_eq(gDownloadLastDir.file.path, dir1.path);
-  fp.file = file3;
-  fp.displayDirectory = null;
-  do_check_true(getTargetFile(params));
-  // file picker should start with browser.download.lastDir as set before entering the private browsing mode
-  do_check_eq(fp.displayDirectory.path, dir1.path);
-  // browser.download.lastDir should be modified after leaving the private browsing mode
-  do_check_eq(prefs.getComplexValue("lastDir", Ci.nsILocalFile).path, dir3.path);
-  // gDownloadLastDir should be usable after leaving the private browsing mode
-  do_check_eq(gDownloadLastDir.file.path, dir3.path);
-
-  // cleanup
-  Cc["@mozilla.org/observer-service;1"]
-    .getService(Ci.nsIObserverService)
-    .notifyObservers(null, "quit-application", null);
-
-  prefsService.clearUserPref("browser.privatebrowsing.keep_current_session");
-  [dir1, dir2, dir3].forEach(function(dir) dir.remove(true));
-}
diff --git a/toolkit/content/tests/unit/xpcshell.ini b/toolkit/content/tests/unit/xpcshell.ini
index 6efc4cc46a6..eb32f5d3e07 100644
--- a/toolkit/content/tests/unit/xpcshell.ini
+++ b/toolkit/content/tests/unit/xpcshell.ini
@@ -4,5 +4,4 @@ tail =
 
 [test_contentAreaUtils.js]
 [test_dict.js]
-[test_privatebrowsing_downloadLastDir_c.js]
 [test_propertyListsUtils.js]
diff --git a/toolkit/mozapps/downloads/DownloadLastDir.jsm b/toolkit/mozapps/downloads/DownloadLastDir.jsm
index ee97b97416c..72ccf1b1d68 100644
--- a/toolkit/mozapps/downloads/DownloadLastDir.jsm
+++ b/toolkit/mozapps/downloads/DownloadLastDir.jsm
@@ -1,3 +1,4 @@
+/* -*- 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/. */
@@ -25,18 +26,12 @@
 
 const LAST_DIR_PREF = "browser.download.lastDir";
 const SAVE_PER_SITE_PREF = LAST_DIR_PREF + ".savePerSite";
-const PBSVC_CID = "@mozilla.org/privatebrowsing;1";
-const nsILocalFile = Components.interfaces.nsILocalFile;
+const nsIFile = Components.interfaces.nsIFile;
 
-var EXPORTED_SYMBOLS = [ "gDownloadLastDir" ];
+var EXPORTED_SYMBOLS = [ "DownloadLastDir" ];
 
 Components.utils.import("resource://gre/modules/Services.jsm");
-
-let pbSvc = null;
-if (PBSVC_CID in Components.classes) {
-  pbSvc = Components.classes[PBSVC_CID]
-                    .getService(Components.interfaces.nsIPrivateBrowsingService);
-}
+Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
 
 let observer = {
   QueryInterface: function (aIID) {
@@ -48,12 +43,8 @@ let observer = {
   },
   observe: function (aSubject, aTopic, aData) {
     switch (aTopic) {
-      case "private-browsing":
-        if (aData == "enter")
-          gDownloadLastDirFile = readLastDirPref();
-        else if (aData == "exit") {
-          gDownloadLastDirFile = null;
-        }
+      case "last-pb-context-exited":
+        gDownloadLastDirFile = null;
         break;
       case "browser:purge-session-history":
         gDownloadLastDirFile = null;
@@ -67,12 +58,12 @@ let observer = {
 
 let os = Components.classes["@mozilla.org/observer-service;1"]
                    .getService(Components.interfaces.nsIObserverService);
-os.addObserver(observer, "private-browsing", true);
+os.addObserver(observer, "last-pb-context-exited", true);
 os.addObserver(observer, "browser:purge-session-history", true);
 
 function readLastDirPref() {
   try {
-    return Services.prefs.getComplexValue(LAST_DIR_PREF, nsILocalFile);
+    return Services.prefs.getComplexValue(LAST_DIR_PREF, nsIFile);
   }
   catch (e) {
     return null;
@@ -82,23 +73,34 @@ function readLastDirPref() {
 function isContentPrefEnabled() {
   try {
     return Services.prefs.getBoolPref(SAVE_PER_SITE_PREF);
-  } 
+  }
   catch (e) {
     return true;
   }
 }
 
 let gDownloadLastDirFile = readLastDirPref();
-let gDownloadLastDir = {
+
+function DownloadLastDir(aWindow) {
+  this.window = aWindow;
+}
+
+DownloadLastDir.prototype = {
+  isPrivate: function DownloadLastDir_isPrivate() {
+    return PrivateBrowsingUtils.isWindowPrivate(this.window);
+  },
   // compat shims
   get file() { return this.getFile(); },
   set file(val) { this.setFile(null, val); },
+  cleanupPrivateFile: function () {
+    gDownloadLastDirFile = null;
+  },
   getFile: function (aURI) {
     if (aURI && isContentPrefEnabled()) {
       let lastDir = Services.contentPrefs.getPref(aURI, LAST_DIR_PREF);
       if (lastDir) {
         var lastDirFile = Components.classes["@mozilla.org/file/local;1"]
-                                    .createInstance(Components.interfaces.nsILocalFile);
+                                    .createInstance(Components.interfaces.nsIFile);
         lastDirFile.initWithPath(lastDir);
         return lastDirFile;
       }
@@ -106,8 +108,11 @@ let gDownloadLastDir = {
     if (gDownloadLastDirFile && !gDownloadLastDirFile.exists())
       gDownloadLastDirFile = null;
 
-    if (pbSvc && pbSvc.privateBrowsingEnabled)
+    if (this.isPrivate()) {
+      if (!gDownloadLastDirFile)
+        gDownloadLastDirFile = readLastDirPref();
       return gDownloadLastDirFile;
+    }
     else
       return readLastDirPref();
   },
@@ -118,14 +123,14 @@ let gDownloadLastDir = {
       else
         Services.contentPrefs.removePref(aURI, LAST_DIR_PREF);
     }
-    if (pbSvc && pbSvc.privateBrowsingEnabled) {
+    if (this.isPrivate()) {
       if (aFile instanceof Components.interfaces.nsIFile)
         gDownloadLastDirFile = aFile.clone();
       else
         gDownloadLastDirFile = null;
     } else {
       if (aFile instanceof Components.interfaces.nsIFile)
-        Services.prefs.setComplexValue(LAST_DIR_PREF, nsILocalFile, aFile);
+        Services.prefs.setComplexValue(LAST_DIR_PREF, nsIFile, aFile);
       else if (Services.prefs.prefHasUserValue(LAST_DIR_PREF))
         Services.prefs.clearUserPref(LAST_DIR_PREF);
     }
diff --git a/toolkit/mozapps/downloads/nsHelperAppDlg.js b/toolkit/mozapps/downloads/nsHelperAppDlg.js
index 11436fcf89c..c2699aef2bb 100644
--- a/toolkit/mozapps/downloads/nsHelperAppDlg.js
+++ b/toolkit/mozapps/downloads/nsHelperAppDlg.js
@@ -1,4 +1,4 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* -*- Mode: javascript; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=2 et sw=2 tw=80: */
 /*
 # This Source Code Form is subject to the terms of the Mozilla Public
@@ -97,8 +97,9 @@ nsUnknownContentTypeDialogProgressListener.prototype = {
 const PREF_BD_USEDOWNLOADDIR = "browser.download.useDownloadDir";
 const nsITimer = Components.interfaces.nsITimer;
 
+let downloadModule = {};
 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
-Components.utils.import("resource://gre/modules/DownloadLastDir.jsm");
+Components.utils.import("resource://gre/modules/DownloadLastDir.jsm", downloadModule);
 Components.utils.import("resource://gre/modules/DownloadPaths.jsm");
 Components.utils.import("resource://gre/modules/DownloadUtils.jsm");
 
@@ -245,6 +246,8 @@ nsUnknownContentTypeDialog.prototype = {
     picker.init(parent, windowTitle, nsIFilePicker.modeSave);
     picker.defaultString = aDefaultFile;
 
+    let gDownloadLastDir = new downloadModule.DownloadLastDir(parent);
+
     if (aSuggestedFileExtension) {
       // aSuggestedFileExtension includes the period, so strip it
       picker.defaultExtension = aSuggestedFileExtension.substring(1);
diff --git a/toolkit/mozapps/downloads/tests/unit/test_DownloadLastDir.js b/toolkit/mozapps/downloads/tests/unit/test_DownloadLastDir.js
deleted file mode 100644
index 771ecd23d5f..00000000000
--- a/toolkit/mozapps/downloads/tests/unit/test_DownloadLastDir.js
+++ /dev/null
@@ -1,82 +0,0 @@
-/* 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 run_test()
-{
-  let Cc = Components.classes;
-  let Ci = Components.interfaces;
-  let Cu = Components.utils;
-  do_get_profile();
-  Cu.import("resource://gre/modules/DownloadLastDir.jsm");
-
-  function clearHistory() {
-    // simulate clearing the private data
-    Cc["@mozilla.org/observer-service;1"].
-    getService(Ci.nsIObserverService).
-    notifyObservers(null, "browser:purge-session-history", "");
-  }
-
-  do_check_eq(typeof gDownloadLastDir, "object");
-  do_check_eq(gDownloadLastDir.file, null);
-
-  let dirSvc = Cc["@mozilla.org/file/directory_service;1"].
-               getService(Ci.nsIProperties);
-  let tmpDir = dirSvc.get("TmpD", Ci.nsILocalFile);
-  let newDir = tmpDir.clone();
-  newDir.append("testdir" + Math.floor(Math.random() * 10000));
-  newDir.QueryInterface(Ci.nsILocalFile);
-  newDir.createUnique(Ci.nsIFile.DIRECTORY_TYPE, 0700);
-
-  gDownloadLastDir.file = tmpDir;
-  do_check_eq(gDownloadLastDir.file.path, tmpDir.path);
-  do_check_neq(gDownloadLastDir.file, tmpDir);
-
-  gDownloadLastDir.file = 1; // not an nsIFile
-  do_check_eq(gDownloadLastDir.file, null);
-  gDownloadLastDir.file = tmpDir;
-
-  clearHistory();
-  do_check_eq(gDownloadLastDir.file, null);
-  gDownloadLastDir.file = tmpDir;
-
-  let pb;
-  try {
-    pb = Cc["@mozilla.org/privatebrowsing;1"].
-         getService(Ci.nsIPrivateBrowsingService);
-  } catch (e) {
-    print("PB service is not available, bail out");
-    return;
-  }
-
-  let prefs = Cc["@mozilla.org/preferences-service;1"].
-              getService(Ci.nsIPrefBranch);
-  prefs.setBoolPref("browser.privatebrowsing.keep_current_session", true);
-
-  pb.privateBrowsingEnabled = true;
-  do_check_eq(gDownloadLastDir.file.path, tmpDir.path);
-  do_check_neq(gDownloadLastDir.file, tmpDir);
-
-  pb.privateBrowsingEnabled = false;
-  do_check_eq(gDownloadLastDir.file.path, tmpDir.path);
-  pb.privateBrowsingEnabled = true;
-
-  gDownloadLastDir.file = newDir;
-  do_check_eq(gDownloadLastDir.file.path, newDir.path);
-  do_check_neq(gDownloadLastDir.file, newDir);
-
-  pb.privateBrowsingEnabled = false;
-  do_check_eq(gDownloadLastDir.file.path, tmpDir.path);
-  do_check_neq(gDownloadLastDir.file, tmpDir);
-
-  pb.privateBrowsingEnabled = true;
-  do_check_neq(gDownloadLastDir.file, null);
-  clearHistory();
-  do_check_eq(gDownloadLastDir.file, null);
-
-  pb.privateBrowsingEnabled = false;
-  do_check_eq(gDownloadLastDir.file, null);
-
-  prefs.clearUserPref("browser.privatebrowsing.keep_current_session");
-  newDir.remove(true);
-}
diff --git a/toolkit/mozapps/downloads/tests/unit/test_DownloadLastDirWithCPS.js b/toolkit/mozapps/downloads/tests/unit/test_DownloadLastDirWithCPS.js
deleted file mode 100644
index 983ae9dc332..00000000000
--- a/toolkit/mozapps/downloads/tests/unit/test_DownloadLastDirWithCPS.js
+++ /dev/null
@@ -1,228 +0,0 @@
-/* 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/. */
-
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const Cu = Components.utils;
-
-Cu.import("resource://gre/modules/DownloadLastDir.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-
-do_get_profile();
-
-function run_test() {
-  function clearHistory() {
-    // simulate clearing the private data
-    Services.obs.notifyObservers(null, "browser:purge-session-history", "");
-  }
-
-  do_check_eq(typeof gDownloadLastDir, "object");
-  do_check_eq(gDownloadLastDir.file, null);
-  
-  let tmpDir = Services.dirsvc.get("TmpD", Ci.nsILocalFile);
-  
-  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" + Math.floor(Math.random() * 10000));
-    dir.QueryInterface(Ci.nsILocalFile);
-    dir.createUnique(Ci.nsIFile.DIRECTORY_TYPE, 0700);
-    return dir;
-  }
-  
-  let dir1 = newDir();
-  let dir2 = newDir();
-  let dir3 = newDir();
-
-  try {
-    { // set up last dir
-      gDownloadLastDir.setFile(null, tmpDir);
-      do_check_eq(gDownloadLastDir.file.path, tmpDir.path);
-      do_check_neq(gDownloadLastDir.file, tmpDir);
-    }
-
-    { // set uri1 to dir1, all should now return dir1
-      // also check that a new object is returned
-      gDownloadLastDir.setFile(uri1, dir1);
-      do_check_eq(gDownloadLastDir.file.path, dir1.path);
-      do_check_neq(gDownloadLastDir.file, dir1);
-      do_check_eq(gDownloadLastDir.getFile(uri1).path, dir1.path); // set in CPS
-      do_check_neq(gDownloadLastDir.getFile(uri1), dir1);
-      do_check_eq(gDownloadLastDir.getFile(uri2).path, dir1.path); // fallback
-      do_check_neq(gDownloadLastDir.getFile(uri2), dir1);
-      do_check_eq(gDownloadLastDir.getFile(uri3).path, dir1.path); // fallback
-      do_check_neq(gDownloadLastDir.getFile(uri3), dir1);
-      do_check_eq(gDownloadLastDir.getFile(uri4).path, dir1.path); // fallback
-      do_check_neq(gDownloadLastDir.getFile(uri4), dir1);
-    }
-
-    { // set uri2 to dir2, all except uri1 should now return dir2
-      gDownloadLastDir.setFile(uri2, dir2);
-      do_check_eq(gDownloadLastDir.file.path, dir2.path);
-      do_check_eq(gDownloadLastDir.getFile(uri1).path, dir1.path); // set in CPS
-      do_check_eq(gDownloadLastDir.getFile(uri2).path, dir2.path); // set in CPS
-      do_check_eq(gDownloadLastDir.getFile(uri3).path, dir2.path); // fallback
-      do_check_eq(gDownloadLastDir.getFile(uri4).path, dir2.path); // fallback
-    }
-
-    { // set uri3 to dir3, all except uri1 and uri2 should now return dir3
-      gDownloadLastDir.setFile(uri3, dir3);
-      do_check_eq(gDownloadLastDir.file.path, dir3.path);
-      do_check_eq(gDownloadLastDir.getFile(uri1).path, dir1.path); // set in CPS
-      do_check_eq(gDownloadLastDir.getFile(uri2).path, dir2.path); // set in CPS
-      do_check_eq(gDownloadLastDir.getFile(uri3).path, dir3.path); // set in CPS
-      do_check_eq(gDownloadLastDir.getFile(uri4).path, dir3.path); // fallback
-    }
-
-    { // set uri1 to dir2, all except uri3 should now return dir2
-      gDownloadLastDir.setFile(uri1, dir2);
-      do_check_eq(gDownloadLastDir.file.path, dir2.path);
-      do_check_eq(gDownloadLastDir.getFile(uri1).path, dir2.path); // set in CPS
-      do_check_eq(gDownloadLastDir.getFile(uri2).path, dir2.path); // set in CPS
-      do_check_eq(gDownloadLastDir.getFile(uri3).path, dir3.path); // set in CPS
-      do_check_eq(gDownloadLastDir.getFile(uri4).path, dir2.path); // fallback
-    }
-
-    { // check clearHistory removes all data
-      clearHistory();
-      do_check_eq(gDownloadLastDir.file, null);
-      do_check_eq(Services.contentPrefs.hasPref(uri1, "browser.download.lastDir"), false);
-      do_check_eq(gDownloadLastDir.getFile(uri1), null);
-      do_check_eq(gDownloadLastDir.getFile(uri2), null);
-      do_check_eq(gDownloadLastDir.getFile(uri3), null);
-      do_check_eq(gDownloadLastDir.getFile(uri4), null);
-    }
-
-    let pb;
-    try {
-      pb = Cc["@mozilla.org/privatebrowsing;1"].getService(Ci.nsIPrivateBrowsingService);
-    } catch (e) {
-      print("PB service is not available, bail out");
-      return;
-    }
-
-    Services.prefs.setBoolPref("browser.privatebrowsing.keep_current_session", true);
-    
-    { // check data set outside PB mode is remembered
-      gDownloadLastDir.setFile(null, tmpDir);
-      pb.privateBrowsingEnabled = true;
-      do_check_eq(gDownloadLastDir.file.path, tmpDir.path);
-      do_check_eq(gDownloadLastDir.getFile(uri1).path, tmpDir.path);
-
-      pb.privateBrowsingEnabled = false;
-      do_check_eq(gDownloadLastDir.file.path, tmpDir.path);
-      do_check_eq(gDownloadLastDir.getFile(uri1).path, tmpDir.path);
-      
-      clearHistory();
-    }
-
-    { // check data set using CPS outside PB mode is remembered
-      gDownloadLastDir.setFile(uri1, dir1);
-      pb.privateBrowsingEnabled = true;
-      do_check_eq(gDownloadLastDir.file.path, dir1.path);
-      do_check_eq(gDownloadLastDir.getFile(uri1).path, dir1.path);
-
-      pb.privateBrowsingEnabled = false;
-      do_check_eq(gDownloadLastDir.file.path, dir1.path);
-      do_check_eq(gDownloadLastDir.getFile(uri1).path, dir1.path);
-
-      clearHistory();
-    }
-    
-    { // check data set inside PB mode is forgotten
-      pb.privateBrowsingEnabled = true;
-      gDownloadLastDir.setFile(null, tmpDir);
-      do_check_eq(gDownloadLastDir.file.path, tmpDir.path);
-      do_check_eq(gDownloadLastDir.getFile(uri1).path, tmpDir.path);
-
-      pb.privateBrowsingEnabled = false;
-      do_check_eq(gDownloadLastDir.file, null);
-      do_check_eq(gDownloadLastDir.getFile(uri1), null);
-      
-      clearHistory();
-    }
-    
-    { // check data set using CPS inside PB mode is forgotten
-      pb.privateBrowsingEnabled = true;
-      gDownloadLastDir.setFile(uri1, dir1);
-      do_check_eq(gDownloadLastDir.file.path, dir1.path);
-      do_check_eq(gDownloadLastDir.getFile(uri1).path, dir1.path);
-
-      pb.privateBrowsingEnabled = false;
-      do_check_eq(gDownloadLastDir.file, null);
-      do_check_eq(gDownloadLastDir.getFile(uri1), null);
-
-      clearHistory();
-    }
-
-    { // check data set outside PB mode but changed inside is remembered correctly
-      gDownloadLastDir.setFile(uri1, dir1);
-      pb.privateBrowsingEnabled = true;
-      gDownloadLastDir.setFile(uri1, dir2);
-      do_check_eq(gDownloadLastDir.file.path, dir2.path);
-      do_check_eq(gDownloadLastDir.getFile(uri1).path, dir2.path);
-
-      pb.privateBrowsingEnabled = false;
-      do_check_eq(gDownloadLastDir.file.path, dir1.path);
-      do_check_eq(gDownloadLastDir.getFile(uri1).path, dir1.path);
-
-      // check that the last dir store got cleared
-      pb.privateBrowsingEnabled = true;
-      do_check_eq(gDownloadLastDir.file.path, dir1.path);
-      do_check_eq(gDownloadLastDir.getFile(uri1).path, dir1.path);
-      
-      pb.privateBrowsingEnabled = false;
-      clearHistory();
-    }
-    
-    { // check clearHistory inside PB mode clears data outside PB mode
-      pb.privateBrowsingEnabled = true;
-      gDownloadLastDir.setFile(uri1, dir2);
-
-      clearHistory();
-      do_check_eq(gDownloadLastDir.file, null);
-      do_check_eq(gDownloadLastDir.getFile(uri1), null);
-
-      pb.privateBrowsingEnabled = false;
-      do_check_eq(gDownloadLastDir.file, null);
-      do_check_eq(gDownloadLastDir.getFile(uri1), null);
-    }
-
-    { // check that disabling CPS works
-      Services.prefs.setBoolPref("browser.download.lastDir.savePerSite", false);
-
-      gDownloadLastDir.setFile(uri1, dir1);
-      do_check_eq(gDownloadLastDir.file.path, dir1.path);
-      do_check_eq(gDownloadLastDir.getFile(uri1).path, dir1.path);
-      do_check_eq(gDownloadLastDir.getFile(uri2).path, dir1.path);
-      do_check_eq(gDownloadLastDir.getFile(uri3).path, dir1.path);
-      do_check_eq(gDownloadLastDir.getFile(uri4).path, dir1.path);
-
-      gDownloadLastDir.setFile(uri2, dir2);
-      do_check_eq(gDownloadLastDir.file.path, dir2.path);
-      do_check_eq(gDownloadLastDir.getFile(uri1).path, dir2.path);
-      do_check_eq(gDownloadLastDir.getFile(uri2).path, dir2.path);
-      do_check_eq(gDownloadLastDir.getFile(uri3).path, dir2.path);
-      do_check_eq(gDownloadLastDir.getFile(uri4).path, dir2.path);
-
-      Services.prefs.clearUserPref("browser.download.lastDir.savePerSite");
-    }
-
-    { // check that passing null to setFile clears the stored value
-      gDownloadLastDir.setFile(uri3, dir3);
-      do_check_eq(gDownloadLastDir.getFile(uri3).path, dir3.path);
-      gDownloadLastDir.setFile(uri3, null);
-      do_check_eq(gDownloadLastDir.getFile(uri3), null);
-    }
-  } finally {
-    dir1.remove(true);
-    dir2.remove(true);
-    dir3.remove(true);
-    Services.prefs.clearUserPref("browser.download.lastDir.savePerSite");
-  }
-}
diff --git a/toolkit/mozapps/downloads/tests/unit/test_privatebrowsing_downloadLastDir.js b/toolkit/mozapps/downloads/tests/unit/test_privatebrowsing_downloadLastDir.js
deleted file mode 100644
index 6248f82c5b2..00000000000
--- a/toolkit/mozapps/downloads/tests/unit/test_privatebrowsing_downloadLastDir.js
+++ /dev/null
@@ -1,114 +0,0 @@
-/* -*- Mode: C++; 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/. */
-
-const Ci = Components.interfaces;
-const Cc = Components.classes;
-const Cu = Components.utils;
-const Cr = Components.results;
-
-do_get_profile();
-
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/DownloadLastDir.jsm");
-
-let context = {
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsIInterfaceRequestor]),
-  getInterface: XPCOMUtils.generateQI([Ci.nsIDOMWindow])
-};
-
-let launcher = {
-  source: Services.io.newURI("http://test1.com/file", null, null)
-};
-
-Cu.import("resource://test/MockFilePicker.jsm");
-MockFilePicker.init();
-MockFilePicker.returnValue = Ci.nsIFilePicker.returnOK;
-
-function run_test()
-{
-  let pb;
-  try {
-    pb = Cc["@mozilla.org/privatebrowsing;1"].
-         getService(Ci.nsIPrivateBrowsingService);
-  } catch (e) {
-    print("PB service is not available, bail out");
-    return;
-  }
-
-  let prefsService = Cc["@mozilla.org/preferences-service;1"].
-                     getService(Ci.nsIPrefService).
-                     QueryInterface(Ci.nsIPrefBranch);
-  prefsService.setBoolPref("browser.privatebrowsing.keep_current_session", true);
-  let prefs = prefsService.getBranch("browser.download.");
-  let launcherDialog = Cc["@mozilla.org/helperapplauncherdialog;1"].
-                       getService(Ci.nsIHelperAppLauncherDialog);
-  let dirSvc = Cc["@mozilla.org/file/directory_service;1"].
-               getService(Ci.nsIProperties);
-  let tmpDir = dirSvc.get("TmpD", Ci.nsILocalFile);
-  function newDirectory() {
-    let dir = tmpDir.clone();
-    dir.append("testdir" + Math.floor(Math.random() * 10000));
-    dir.createUnique(Ci.nsIFile.DIRECTORY_TYPE, 0700);
-    return dir;
-  }
-  function newFileInDirectory(dir) {
-    let file = dir.clone();
-    file.append("testfile" + Math.floor(Math.random() * 10000));
-    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);
-
-  prefs.setComplexValue("lastDir", Ci.nsILocalFile, tmpDir);
-
-  MockFilePicker.returnFiles = [file1];
-  let file = launcherDialog.promptForSaveToFile(launcher, context, null, null, null);
-  do_check_true(!!file);
-  // file picker should start with browser.download.lastDir
-  do_check_eq(MockFilePicker.displayDirectory.path, tmpDir.path);
-  // browser.download.lastDir should be modified before entering the private browsing mode
-  do_check_eq(prefs.getComplexValue("lastDir", Ci.nsILocalFile).path, dir1.path);
-  // gDownloadLastDir should be usable outside of the private browsing mode
-  do_check_eq(gDownloadLastDir.file.path, dir1.path);
-
-  pb.privateBrowsingEnabled = true;
-  do_check_eq(prefs.getComplexValue("lastDir", Ci.nsILocalFile).path, dir1.path);
-  MockFilePicker.returnFiles = [file2];
-  MockFilePicker.displayDirectory = null;
-  file = launcherDialog.promptForSaveToFile(launcher, context, null, null, null);
-  do_check_true(!!file);
-  // file picker should start with browser.download.lastDir as set before entering the private browsing mode
-  do_check_eq(MockFilePicker.displayDirectory.path, dir1.path);
-  // browser.download.lastDir should not be modified inside the private browsing mode
-  do_check_eq(prefs.getComplexValue("lastDir", Ci.nsILocalFile).path, dir1.path);
-  // but gDownloadLastDir should be modified
-  do_check_eq(gDownloadLastDir.file.path, dir2.path);
-
-  pb.privateBrowsingEnabled = false;
-  // gDownloadLastDir should be cleared after leaving the private browsing mode
-  do_check_eq(gDownloadLastDir.file.path, dir1.path);
-  MockFilePicker.returnFiles = [file3];
-  MockFilePicker.displayDirectory = null;
-  file = launcherDialog.promptForSaveToFile(launcher, context, null, null, null);
-  do_check_true(!!file);
-  // file picker should start with browser.download.lastDir as set before entering the private browsing mode
-  do_check_eq(MockFilePicker.displayDirectory.path, dir1.path);
-  // browser.download.lastDir should be modified after leaving the private browsing mode
-  do_check_eq(prefs.getComplexValue("lastDir", Ci.nsILocalFile).path, dir3.path);
-  // gDownloadLastDir should be usable after leaving the private browsing mode
-  do_check_eq(gDownloadLastDir.file.path, dir3.path);
-
-  // cleanup
-  prefsService.clearUserPref("browser.privatebrowsing.keep_current_session");
-  [dir1, dir2, dir3].forEach(function(dir) dir.remove(true));
-
-  MockFilePicker.cleanup();
-}
diff --git a/toolkit/mozapps/downloads/tests/unit/xpcshell.ini b/toolkit/mozapps/downloads/tests/unit/xpcshell.ini
index 558d009bbf0..8dae3c54e6b 100644
--- a/toolkit/mozapps/downloads/tests/unit/xpcshell.ini
+++ b/toolkit/mozapps/downloads/tests/unit/xpcshell.ini
@@ -2,11 +2,8 @@
 head = head_downloads.js
 tail = 
 
-[test_DownloadLastDir.js]
-[test_DownloadLastDirWithCPS.js]
 [test_DownloadPaths.js]
 [test_DownloadUtils.js]
 [test_lowMinutes.js]
-[test_privatebrowsing_downloadLastDir.js]
 [test_syncedDownloadUtils.js]
 [test_unspecified_arguments.js]