Merge m-i to m-c, a=merge
authorPhil Ringnalda <philringnalda@gmail.com>
Sat, 29 Nov 2014 08:48:14 -0800
changeset 243917 8bc6a1522933ac2c849b9d975f3b7667278dd9c7
parent 243905 54b831a0ce00b113b13f8c038d7807ec96b997cf (current diff)
parent 243916 187125e5da1021293bfa1b8d19022da2d40ff7d0 (diff)
child 243925 1e024ddabbb3f7e4685c82347891923216875480
push id4489
push userraliiev@mozilla.com
push dateMon, 23 Feb 2015 15:17:55 +0000
treeherdermozilla-beta@fd7c3dc24146 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone37.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-i to m-c, a=merge
--- a/b2g/components/AlertsHelper.jsm
+++ b/b2g/components/AlertsHelper.jsm
@@ -265,17 +265,17 @@ let AlertsHelper = {
     if (currentListener && currentListener.observer) {
       currentListener.observer.observe(null, kTopicAlertFinished, currentListener.cookie);
     }
 
     let dataObj = this.deserializeStructuredClone(data.dataStr);
     this.registerListener(data.name, data.cookie, data.alertListener);
     this.showNotification(data.imageURL, data.title, data.text,
                           data.textClickable, data.cookie, data.name, data.bidi,
-                          data.lang, dataObj, null);
+                          data.lang, dataObj, null, data.inPrivateBrowsing);
   },
 
   showAppNotification: function(aMessage) {
     let data = aMessage.data;
     let details = data.details;
     let dataObject = this.deserializeStructuredClone(details.data);
     let listener = {
       mm: aMessage.target,
--- a/b2g/components/AlertsService.js
+++ b/b2g/components/AlertsService.js
@@ -63,28 +63,30 @@ AlertsService.prototype = {
         cpmm.removeMessageListener(kMessageAppNotificationReturn, this);
         break;
     }
   },
 
   // nsIAlertsService
   showAlertNotification: function(aImageUrl, aTitle, aText, aTextClickable,
                                   aCookie, aAlertListener, aName, aBidi,
-                                  aLang, aDataStr) {
+                                  aLang, aDataStr, aPrincipal,
+                                  aInPrivateBrowsing) {
     cpmm.sendAsyncMessage(kMessageAlertNotificationSend, {
       imageURL: aImageUrl,
       title: aTitle,
       text: aText,
       clickable: aTextClickable,
       cookie: aCookie,
       listener: aAlertListener,
       id: aName,
       dir: aBidi,
       lang: aLang,
-      dataStr: aDataStr
+      dataStr: aDataStr,
+      inPrivateBrowsing: aInPrivateBrowsing
     });
   },
 
   closeAlert: function(aName) {
     cpmm.sendAsyncMessage(kMessageAlertNotificationClose, {
       name: aName
     });
   },
--- a/browser/devtools/webconsole/test/browser_console_addonsdk_loader_exception.js
+++ b/browser/devtools/webconsole/test/browser_console_addonsdk_loader_exception.js
@@ -23,34 +23,34 @@ function test()
     ok(webconsole, "web console opened");
 
     browserconsole = yield HUDService.toggleBrowserConsole();
     ok(browserconsole, "browser console opened");
 
     // Cause an exception in a script loaded with the addon-sdk loader.
     let toolbox = gDevTools.getToolbox(webconsole.target);
     let oldPanels = toolbox._toolPanels;
-    toolbox._toolPanels = null;
+    toolbox._toolPanels = {}; // non-iterable
 
     function fixToolbox() {
       toolbox._toolPanels = oldPanels;
     }
 
     info("generate exception and wait for message");
 
     executeSoon(() => {
       executeSoon(fixToolbox);
       expectUncaughtException();
       toolbox.getToolPanels();
     });
 
     let [result] = yield waitForMessages({
       webconsole: browserconsole,
       messages: [{
-        text: "TypeError: can't convert null to object",
+        text: "TypeError: this._toolPanels is not iterable",
         category: CATEGORY_JS,
         severity: SEVERITY_ERROR,
       }],
     });
 
     fixToolbox();
 
     let msg = [...result.matched][0];
--- a/browser/modules/WebappManager.jsm
+++ b/browser/modules/WebappManager.jsm
@@ -9,16 +9,17 @@ let Cc = Components.classes;
 let Cu = Components.utils;
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Webapps.jsm");
 Cu.import("resource://gre/modules/AppsUtils.jsm");
 Cu.import("resource://gre/modules/Task.jsm");
 Cu.import("resource://gre/modules/Promise.jsm");
+Cu.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "NativeApp",
   "resource://gre/modules/NativeApp.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "WebappOSUtils",
   "resource://gre/modules/WebappOSUtils.jsm");
 
 XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
@@ -145,17 +146,18 @@ this.WebappManager = {
 
         let manifestURL = aData.app.manifestURL;
 
         let nativeApp = new NativeApp(aData.app, jsonManifest,
                                       aData.app.categories);
 
         this.installations[manifestURL] = Promise.defer();
         this.installations[manifestURL].promise.then(() => {
-          notifyInstallSuccess(aData.app, nativeApp, bundle);
+          notifyInstallSuccess(aData.app, nativeApp, bundle,
+                               PrivateBrowsingUtils.isWindowPrivate(aWindow));
         }, (error) => {
           Cu.reportError("Error installing webapp: " + error);
         }).then(() => {
           popupProgressContent.removeChild(progressMeter);
           delete this.installations[manifestURL];
           if (Object.getOwnPropertyNames(this.installations).length == 0) {
             notification.remove();
           }
@@ -243,27 +245,28 @@ this.WebappManager = {
 
     notification = chromeWin.PopupNotifications.show(
                      browser, "webapps-uninstall", message,
                      "webapps-notification-icon",
                      mainAction, [secondaryAction]);
   }
 }
 
-function notifyInstallSuccess(aApp, aNativeApp, aBundle) {
+function notifyInstallSuccess(aApp, aNativeApp, aBundle, aInPrivateBrowsing) {
   let launcher = {
     observe: function(aSubject, aTopic) {
       if (aTopic == "alertclickcallback") {
         WebappOSUtils.launch(aApp);
       }
     }
   };
 
   try {
     let notifier = Cc["@mozilla.org/alerts-service;1"].
                    getService(Ci.nsIAlertsService);
 
     notifier.showAlertNotification(aNativeApp.iconURI.spec,
                                    aBundle.getString("webapps.install.success"),
                                    aNativeApp.appNameAsFilename,
-                                   true, null, launcher);
+                                   true, null, launcher, "", "", "", "", null,
+                                   aInPrivateBrowsing);
   } catch (ex) {}
 }
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -3652,31 +3652,32 @@ ContentParent::RecvLoadURIExternal(const
 }
 
 bool
 ContentParent::RecvShowAlertNotification(const nsString& aImageUrl, const nsString& aTitle,
                                          const nsString& aText, const bool& aTextClickable,
                                          const nsString& aCookie, const nsString& aName,
                                          const nsString& aBidi, const nsString& aLang,
                                          const nsString& aData,
-                                         const IPC::Principal& aPrincipal)
+                                         const IPC::Principal& aPrincipal,
+                                         const bool& aInPrivateBrowsing)
 {
 #ifdef MOZ_CHILD_PERMISSIONS
     uint32_t permission = mozilla::CheckPermission(this, aPrincipal,
                                                    "desktop-notification");
     if (permission != nsIPermissionManager::ALLOW_ACTION) {
         return true;
     }
 #endif /* MOZ_CHILD_PERMISSIONS */
 
     nsCOMPtr<nsIAlertsService> sysAlerts(do_GetService(NS_ALERTSERVICE_CONTRACTID));
     if (sysAlerts) {
         sysAlerts->ShowAlertNotification(aImageUrl, aTitle, aText, aTextClickable,
                                          aCookie, this, aName, aBidi, aLang,
-                                         aData, aPrincipal);
+                                         aData, aPrincipal, aInPrivateBrowsing);
     }
     return true;
 }
 
 bool
 ContentParent::RecvCloseAlert(const nsString& aName,
                               const IPC::Principal& aPrincipal)
 {
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -597,17 +597,18 @@ private:
     virtual bool RecvSetURITitle(const URIParams& uri,
                                  const nsString& title) MOZ_OVERRIDE;
 
     virtual bool RecvShowAlertNotification(const nsString& aImageUrl, const nsString& aTitle,
                                            const nsString& aText, const bool& aTextClickable,
                                            const nsString& aCookie, const nsString& aName,
                                            const nsString& aBidi, const nsString& aLang,
                                            const nsString& aData,
-                                           const IPC::Principal& aPrincipal) MOZ_OVERRIDE;
+                                           const IPC::Principal& aPrincipal,
+                                           const bool& aInPrivateBrowsing) MOZ_OVERRIDE;
 
     virtual bool RecvCloseAlert(const nsString& aName,
                                 const IPC::Principal& aPrincipal) MOZ_OVERRIDE;
 
     virtual bool RecvLoadURIExternal(const URIParams& uri) MOZ_OVERRIDE;
 
     virtual bool RecvSyncMessage(const nsString& aMsg,
                                  const ClonedMessageData& aData,
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -648,17 +648,18 @@ parent:
                           nsString title,
                           nsString text,
                           bool textClickable,
                           nsString cookie,
                           nsString name,
                           nsString bidi,
                           nsString lang,
                           nsString data,
-                          Principal principal);
+                          Principal principal,
+                          bool inPrivateBrowsing);
 
     CloseAlert(nsString name, Principal principal);
 
     PExternalHelperApp(OptionalURIParams uri,
                        nsCString aMimeContentType,
                        nsCString aContentDisposition,
                        uint32_t aContentDispositionHint,
                        nsString aContentDispositionFilename,
--- a/dom/media/webaudio/AudioContext.cpp
+++ b/dom/media/webaudio/AudioContext.cpp
@@ -627,27 +627,31 @@ AudioContext::GetGlobalJSObject() const
   if (!parentObject) {
     return nullptr;
   }
 
   // This can also return null.
   return parentObject->GetGlobalJSObject();
 }
 
-void
+already_AddRefed<Promise>
 AudioContext::StartRendering(ErrorResult& aRv)
 {
+  nsCOMPtr<nsIGlobalObject> parentObject = do_QueryInterface(GetParentObject());
+
   MOZ_ASSERT(mIsOffline, "This should only be called on OfflineAudioContext");
   if (mIsStarted) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
-    return;
+    return nullptr;
   }
 
   mIsStarted = true;
-  mDestination->StartRendering();
+  nsRefPtr<Promise> promise = Promise::Create(parentObject, aRv);
+  mDestination->StartRendering(promise);
+  return promise.forget();
 }
 
 void
 AudioContext::Mute() const
 {
   MOZ_ASSERT(!mIsOffline);
   if (mDestination) {
     mDestination->Mute();
--- a/dom/media/webaudio/AudioContext.h
+++ b/dom/media/webaudio/AudioContext.h
@@ -186,17 +186,17 @@ public:
                      ErrorResult& aRv);
 
   already_AddRefed<Promise>
   DecodeAudioData(const ArrayBuffer& aBuffer,
                   const Optional<OwningNonNull<DecodeSuccessCallback> >& aSuccessCallback,
                   const Optional<OwningNonNull<DecodeErrorCallback> >& aFailureCallback);
 
   // OfflineAudioContext methods
-  void StartRendering(ErrorResult& aRv);
+  already_AddRefed<Promise> StartRendering(ErrorResult& aRv);
   IMPL_EVENT_HANDLER(complete)
 
   bool IsOffline() const { return mIsOffline; }
 
   MediaStreamGraph* Graph() const;
   MediaStream* DestinationStream() const;
 
   // Nodes register here if they will produce sound even if they have silent
--- a/dom/media/webaudio/AudioDestinationNode.cpp
+++ b/dom/media/webaudio/AudioDestinationNode.cpp
@@ -17,16 +17,17 @@
 #include "OfflineAudioCompletionEvent.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIDocShell.h"
 #include "nsIPermissionManager.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIAppShell.h"
 #include "nsWidgetsCID.h"
+#include "mozilla/dom/Promise.h"
 
 namespace mozilla {
 namespace dom {
 
 static uint8_t gWebAudioOutputKey;
 
 class OfflineDestinationNodeEngine : public AudioNodeEngine
 {
@@ -121,16 +122,38 @@ public:
       NS_ASSERTION(mWriteIndex == mLength, "Overshot length");
       // Go to finished state. When the graph's current time eventually reaches
       // the end of the stream, then the main thread will be notified and we'll
       // shut down the AudioContext.
       *aFinished = true;
     }
   }
 
+  class OnCompleteTask MOZ_FINAL : public nsRunnable
+  {
+  public:
+    OnCompleteTask(AudioContext* aAudioContext, AudioBuffer* aRenderedBuffer)
+      : mAudioContext(aAudioContext)
+      , mRenderedBuffer(aRenderedBuffer)
+    {}
+
+    NS_IMETHOD Run()
+    {
+      nsRefPtr<OfflineAudioCompletionEvent> event =
+          new OfflineAudioCompletionEvent(mAudioContext, nullptr, nullptr);
+      event->InitEvent(mRenderedBuffer);
+      mAudioContext->DispatchTrustedEvent(event);
+
+      return NS_OK;
+    }
+  private:
+    nsRefPtr<AudioContext> mAudioContext;
+    nsRefPtr<AudioBuffer> mRenderedBuffer;
+  };
+
   void FireOfflineCompletionEvent(AudioDestinationNode* aNode)
   {
     AudioContext* context = aNode->Context();
     context->Shutdown();
     // Shutdown drops self reference, but the context is still referenced by aNode,
     // which is strongly referenced by the runnable that called
     // AudioDestinationNode::FireOfflineCompletionEvent.
 
@@ -147,20 +170,21 @@ public:
                           mLength, mSampleRate, cx, rv);
     if (rv.Failed()) {
       return;
     }
     for (uint32_t i = 0; i < mInputChannels.Length(); ++i) {
       renderedBuffer->SetRawChannelContents(i, mInputChannels[i]);
     }
 
-    nsRefPtr<OfflineAudioCompletionEvent> event =
-        new OfflineAudioCompletionEvent(context, nullptr, nullptr);
-    event->InitEvent(renderedBuffer);
-    context->DispatchTrustedEvent(event);
+    aNode->ResolvePromise(renderedBuffer);
+
+    nsRefPtr<OnCompleteTask> task =
+      new OnCompleteTask(context, renderedBuffer);
+    NS_DispatchToMainThread(task);
   }
 
   virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE
   {
     size_t amount = AudioNodeEngine::SizeOfExcludingThis(aMallocSizeOf);
     amount += mInputChannels.SizeOfExcludingThis(aMallocSizeOf);
     return amount;
   }
@@ -296,17 +320,18 @@ private:
   { }
 
   nsWeakPtr mWeakNode;
 };
 
 NS_IMPL_ISUPPORTS(EventProxyHandler, nsIDOMEventListener)
 
 NS_IMPL_CYCLE_COLLECTION_INHERITED(AudioDestinationNode, AudioNode,
-                                   mAudioChannelAgent, mEventProxyHelper)
+                                   mAudioChannelAgent, mEventProxyHelper,
+                                   mOfflineRenderingPromise)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(AudioDestinationNode)
   NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
   NS_INTERFACE_MAP_ENTRY(nsIAudioChannelAgentCallback)
 NS_INTERFACE_MAP_END_INHERITING(AudioNode)
 
 NS_IMPL_ADDREF_INHERITED(AudioDestinationNode, AudioNode)
 NS_IMPL_RELEASE_INHERITED(AudioDestinationNode, AudioNode)
@@ -410,16 +435,24 @@ void
 AudioDestinationNode::FireOfflineCompletionEvent()
 {
   AudioNodeStream* stream = static_cast<AudioNodeStream*>(Stream());
   OfflineDestinationNodeEngine* engine =
     static_cast<OfflineDestinationNodeEngine*>(stream->Engine());
   engine->FireOfflineCompletionEvent(this);
 }
 
+void
+AudioDestinationNode::ResolvePromise(AudioBuffer* aRenderedBuffer)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(mIsOffline);
+  mOfflineRenderingPromise->MaybeResolve(aRenderedBuffer);
+}
+
 uint32_t
 AudioDestinationNode::MaxChannelCount() const
 {
   return Context()->MaxChannelCount();
 }
 
 void
 AudioDestinationNode::SetChannelCount(uint32_t aChannelCount, ErrorResult& aRv)
@@ -458,18 +491,19 @@ AudioDestinationNode::OfflineShutdown()
 
 JSObject*
 AudioDestinationNode::WrapObject(JSContext* aCx)
 {
   return AudioDestinationNodeBinding::Wrap(aCx, this);
 }
 
 void
-AudioDestinationNode::StartRendering()
+AudioDestinationNode::StartRendering(Promise* aPromise)
 {
+  mOfflineRenderingPromise = aPromise;
   mOfflineRenderingRef.Take(this);
   mStream->Graph()->StartNonRealtimeProcessing(mFramesToProduce);
 }
 
 void
 AudioDestinationNode::SetCanPlay(bool aCanPlay)
 {
   mStream->SetTrackEnabled(AudioNodeStream::AUDIO_TRACK, aCanPlay);
--- a/dom/media/webaudio/AudioDestinationNode.h
+++ b/dom/media/webaudio/AudioDestinationNode.h
@@ -49,17 +49,17 @@ public:
 
   uint32_t MaxChannelCount() const;
   virtual void SetChannelCount(uint32_t aChannelCount,
                                ErrorResult& aRv) MOZ_OVERRIDE;
 
   void Mute();
   void Unmute();
 
-  void StartRendering();
+  void StartRendering(Promise* aPromise);
 
   void OfflineShutdown();
 
   // nsIDOMEventListener - by proxy
   NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
 
   AudioChannel MozAudioChannelType() const;
   void SetMozAudioChannelType(AudioChannel aValue, ErrorResult& aRv);
@@ -80,16 +80,17 @@ public:
   {
     return "AudioDestinationNode";
   }
 
   virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE;
   virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE;
 
   void InputMuted(bool aInputMuted);
+  void ResolvePromise(AudioBuffer* aRenderedBuffer);
 
 protected:
   virtual ~AudioDestinationNode();
 
 private:
   bool CheckAudioChannelPermissions(AudioChannel aValue);
 
   void SetCanPlay(bool aCanPlay);
@@ -98,16 +99,17 @@ private:
   void ScheduleStableStateNotification();
 
   SelfReference<AudioDestinationNode> mOfflineRenderingRef;
   uint32_t mFramesToProduce;
 
   nsCOMPtr<nsIAudioChannelAgent> mAudioChannelAgent;
 
   nsRefPtr<EventProxyHandler> mEventProxyHelper;
+  nsRefPtr<Promise> mOfflineRenderingPromise;
 
   // Audio Channel Type.
   AudioChannel mAudioChannel;
   bool mIsOffline;
   bool mHasFinished;
   bool mAudioChannelAgentPlaying;
 
   TimeStamp mStartedBlockingDueToBeingOnlyNode;
--- a/dom/media/webaudio/test/test_OfflineAudioContext.html
+++ b/dom/media/webaudio/test/test_OfflineAudioContext.html
@@ -5,16 +5,35 @@
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="webaudio.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
+var renderedBuffer = null;
+var finished = 0;
+
+function finish() {
+  finished++;
+  if (finished == 2) {
+    SimpleTest.finish();
+  }
+}
+
+function setOrCompareRenderedBuffer(aRenderedBuffer) {
+  if (renderedBuffer) {
+    is(renderedBuffer, aRenderedBuffer, "Rendered buffers from the event and the promise should be the same");
+    finish();
+  } else {
+    renderedBuffer = aRenderedBuffer;
+  }
+}
+
 SimpleTest.waitForExplicitFinish();
 addLoadEvent(function() {
   var ctx = new OfflineAudioContext(2, 100, 22050);
   ok(ctx instanceof EventTarget, "OfflineAudioContexts must be EventTargets");
 
   var buf = ctx.createBuffer(2, 100, ctx.sampleRate);
   for (var i = 0; i < 2; ++i) {
     for (var j = 0; j < 100; ++j) {
@@ -42,26 +61,41 @@ addLoadEvent(function() {
   expectException(function() {
     new OfflineAudioContext(2, 0, 44100);
   }, DOMException.NOT_SUPPORTED_ERR);
 
   var src = ctx.createBufferSource();
   src.buffer = buf;
   src.start(0);
   src.connect(ctx.destination);
-  ctx.startRendering();
+
   ctx.addEventListener("complete", function(e) {
     ok(e instanceof OfflineAudioCompletionEvent, "Correct event received");
     is(e.renderedBuffer.numberOfChannels, 2, "Correct expected number of buffers");
+    ok(renderedBuffer != null, "The event should be fired after the promise callback.");
+    expectNoException(function() {
+      ctx.startRendering().then(function() {
+        ok(false, "Promise should not resolve when startRendering is called a second time on an OfflineAudioContext")
+        finish();
+      }).catch(function(err) {
+        ok(true, "Promise should reject when startRendering is called a second time on an OfflineAudioContext")
+        finish();
+      });
+    });
     compareBuffers(e.renderedBuffer, buf);
+    setOrCompareRenderedBuffer(e.renderedBuffer);
 
-    expectException(function() {
-      ctx.startRendering();
-    }, DOMException.INVALID_STATE_ERR);
+  }, false);
 
-    SimpleTest.finish();
-  }, false);
+  expectNoException(function() {
+    ctx.startRendering().then(function(b) {
+      is(renderedBuffer, null, "The promise callback should be called first.");
+      setOrCompareRenderedBuffer(b);
+    }).catch(function (error) {
+       ok(false, "The promise from OfflineAudioContext.startRendering should never be rejected");
+    });
+  });
 });
 
 </script>
 </pre>
 </body>
 </html>
--- a/dom/notification/DesktopNotification.cpp
+++ b/dom/notification/DesktopNotification.cpp
@@ -10,16 +10,17 @@
 #include "mozilla/dom/PBrowserChild.h"
 #include "nsIDOMDesktopNotification.h"
 #include "mozilla/Preferences.h"
 #include "nsGlobalWindow.h"
 #include "nsIAppsService.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsServiceManagerUtils.h"
 #include "PermissionMessageUtils.h"
+#include "nsILoadContext.h"
 
 namespace mozilla {
 namespace dom {
 
 /*
  * Simple Request
  */
 class DesktopNotificationRequest : public nsIContentPermissionRequest
@@ -98,26 +99,30 @@ DesktopNotification::PostDesktopNotifica
   }
 
   // Generate a unique name (which will also be used as a cookie) because
   // the nsIAlertsService will coalesce notifications with the same name.
   // In the case of IPC, the parent process will use the cookie to map
   // to nsIObservers, thus cookies must be unique to differentiate observers.
   nsString uniqueName = NS_LITERAL_STRING("desktop-notification:");
   uniqueName.AppendInt(sCount++);
-  nsIPrincipal* principal = GetOwner()->GetDoc()->NodePrincipal();
+  nsCOMPtr<nsIDocument> doc = GetOwner()->GetDoc();
+  nsIPrincipal* principal = doc->NodePrincipal();
+  nsCOMPtr<nsILoadContext> loadContext = doc->GetLoadContext();
+  bool inPrivateBrowsing = loadContext && loadContext->UsePrivateBrowsing();
   return alerts->ShowAlertNotification(mIconURL, mTitle, mDescription,
                                        true,
                                        uniqueName,
                                        mObserver,
                                        uniqueName,
                                        NS_LITERAL_STRING("auto"),
                                        EmptyString(),
                                        EmptyString(),
-                                       principal);
+                                       principal,
+                                       inPrivateBrowsing);
 }
 
 DesktopNotification::DesktopNotification(const nsAString & title,
                                          const nsAString & description,
                                          const nsAString & iconURL,
                                          nsPIDOMWindow *aWindow,
                                          nsIPrincipal* principal)
   : DOMEventTargetHelper(aWindow)
--- a/dom/notification/Notification.cpp
+++ b/dom/notification/Notification.cpp
@@ -22,16 +22,17 @@
 #include "nsGlobalWindow.h"
 #include "nsDOMJSUtils.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIXPConnect.h"
 #include "mozilla/dom/PermissionMessageUtils.h"
 #include "mozilla/dom/Event.h"
 #include "mozilla/Services.h"
 #include "nsContentPermissionHelper.h"
+#include "nsILoadContext.h"
 #ifdef MOZ_B2G
 #include "nsIDOMDesktopNotification.h"
 #endif
 
 namespace mozilla {
 namespace dom {
 
 class NotificationStorageCallback MOZ_FINAL : public nsINotificationStorageCallback
@@ -672,20 +673,26 @@ Notification::ShowInternal()
     }
   }
 #endif
 
   // In the case of IPC, the parent process uses the cookie to map to
   // nsIObserver. Thus the cookie must be unique to differentiate observers.
   nsString uniqueCookie = NS_LITERAL_STRING("notification:");
   uniqueCookie.AppendInt(sCount++);
+  bool inPrivateBrowsing = false;
+  if (doc) {
+    nsCOMPtr<nsILoadContext> loadContext = doc->GetLoadContext();
+    inPrivateBrowsing = loadContext && loadContext->UsePrivateBrowsing();
+  }
   alertService->ShowAlertNotification(absoluteUrl, mTitle, mBody, true,
                                       uniqueCookie, observer, mAlertName,
                                       DirectionToString(mDir), mLang,
-                                      dataStr, GetPrincipal());
+                                      dataStr, GetPrincipal(),
+                                      inPrivateBrowsing);
 }
 
 void
 Notification::RequestPermission(const GlobalObject& aGlobal,
                                 const Optional<OwningNonNull<NotificationPermissionCallback> >& aCallback,
                                 ErrorResult& aRv)
 {
   // Get principal from global to make permission request for notifications.
--- a/dom/webidl/OfflineAudioContext.webidl
+++ b/dom/webidl/OfflineAudioContext.webidl
@@ -11,13 +11,13 @@
  */
 
 callback OfflineRenderSuccessCallback = void (AudioBuffer renderedData);
 
 [Constructor(unsigned long numberOfChannels, unsigned long length, float sampleRate)]
 interface OfflineAudioContext : AudioContext {
 
     [Throws]
-    void startRendering();
+    Promise<AudioBuffer> startRendering();
 
     attribute EventHandler oncomplete;
 
 };
--- a/js/src/builtin/MapObject.cpp
+++ b/js/src/builtin/MapObject.cpp
@@ -1231,17 +1231,17 @@ MapObject::finalize(FreeOp *fop, JSObjec
 bool
 MapObject::construct(JSContext *cx, unsigned argc, Value *vp)
 {
     Rooted<MapObject*> obj(cx, MapObject::create(cx));
     if (!obj)
         return false;
 
     CallArgs args = CallArgsFromVp(argc, vp);
-    if (args.hasDefined(0)) {
+    if (!args.get(0).isNullOrUndefined()) {
         ForOfIterator iter(cx);
         if (!iter.init(args[0]))
             return false;
         RootedValue pairVal(cx);
         RootedObject pairObj(cx);
         ValueMap *map = obj->getData();
         while (true) {
             bool done;
@@ -1795,17 +1795,17 @@ SetObject::finalize(FreeOp *fop, JSObjec
 bool
 SetObject::construct(JSContext *cx, unsigned argc, Value *vp)
 {
     Rooted<SetObject*> obj(cx, SetObject::create(cx));
     if (!obj)
         return false;
 
     CallArgs args = CallArgsFromVp(argc, vp);
-    if (args.hasDefined(0)) {
+    if (!args.get(0).isNullOrUndefined()) {
         RootedValue keyVal(cx);
         ForOfIterator iter(cx);
         if (!iter.init(args[0]))
             return false;
         AutoHashableValueRooter key(cx);
         ValueSet *set = obj->getData();
         while (true) {
             bool done;
--- a/js/src/builtin/WeakSetObject.cpp
+++ b/js/src/builtin/WeakSetObject.cpp
@@ -90,17 +90,17 @@ WeakSetObject::construct(JSContext *cx, 
     // Based on our "Set" implementation instead of the more general ES6 steps.
     CallArgs args = CallArgsFromVp(argc, vp);
 
     if (!args.isConstructing()) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_NOT_FUNCTION, "WeakSet");
         return false;
     }
 
-    if (args.hasDefined(0)) {
+    if (!args.get(0).isNullOrUndefined()) {
         RootedObject map(cx, &obj->getReservedSlot(WEAKSET_MAP_SLOT).toObject());
 
         JS::ForOfIterator iter(cx);
         if (!iter.init(args[0]))
             return false;
 
         RootedValue keyVal(cx);
         RootedObject keyObject(cx);
--- a/js/src/jit-test/tests/collections/Map-constructor-1.js
+++ b/js/src/jit-test/tests/collections/Map-constructor-1.js
@@ -1,6 +1,7 @@
 // The Map constructor creates an empty Map by default.
 
 assertEq(Map().size, 0);
 assertEq((new Map).size, 0);
 assertEq(Map(undefined).size, 0);
 assertEq(new Map(undefined).size, 0);
+assertEq(new Map(null).size, 0);
--- a/js/src/jit-test/tests/collections/Map-constructor-4.js
+++ b/js/src/jit-test/tests/collections/Map-constructor-4.js
@@ -1,6 +1,6 @@
 // Map(x) throws if x is not iterable (unless x is undefined).
 
 load(libdir + "asserts.js");
-var nonIterables = [null, true, 1, -0, 3.14, NaN, {}, Math, this];
+var nonIterables = [true, 1, -0, 3.14, NaN, {}, Math, this];
 for (let k of nonIterables)
     assertThrowsInstanceOf(function () { Map(k); }, TypeError);
--- a/js/src/jit-test/tests/collections/Set-constructor-1.js
+++ b/js/src/jit-test/tests/collections/Set-constructor-1.js
@@ -1,6 +1,7 @@
 // The Set constructor creates an empty Set by default.
 
 assertEq(Set().size, 0);
 assertEq((new Set).size, 0);
 assertEq(Set(undefined).size, 0);
 assertEq(new Set(undefined).size, 0);
+assertEq(new Set(null).size, 0);
--- a/js/src/jit-test/tests/collections/WeakMap-constructor-1.js
+++ b/js/src/jit-test/tests/collections/WeakMap-constructor-1.js
@@ -1,15 +1,12 @@
 // The WeakMap constructor creates an empty WeakMap by default.
 
 load(libdir + "asserts.js");
 
 new WeakMap();
 new WeakMap(undefined);
-
-// FIXME: bug 1092538
-// new WeakMap(null);
+new WeakMap(null);
 
 // FIXME: bug 1062075
 // assertThrowsInstanceOf(() => WeakMap(), TypeError);
 // assertThrowsInstanceOf(() => WeakMap(undefined), TypeError);
-// WeakMap(null) throws TypeError, but it's because of bug 1092538.
 // assertThrowsInstanceOf(() => WeakMap(null), TypeError);
--- a/js/src/jit-test/tests/collections/WeakMap-constructor-4.js
+++ b/js/src/jit-test/tests/collections/WeakMap-constructor-4.js
@@ -1,8 +1,6 @@
 // WeakMap(x) throws if x is not iterable (unless x is undefined).
 
 load(libdir + "asserts.js");
-// FIXME: bug 1092538
-// `new WeapMap(null)` should not throw.
-var nonIterables = [null, true, 1, -0, 3.14, NaN, {}, Math, this];
+var nonIterables = [true, 1, -0, 3.14, NaN, {}, Math, this];
 for (let k of nonIterables)
     assertThrowsInstanceOf(function () { new WeakMap(k); }, TypeError);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/collections/WeakSet-constructor-1.js
@@ -0,0 +1,11 @@
+// The WeakSet constructor creates an empty WeakSet by default.
+
+load(libdir + "asserts.js");
+
+new WeakSet();
+new WeakSet(undefined);
+new WeakSet(null);
+
+assertThrowsInstanceOf(() => WeakSet(), TypeError);
+assertThrowsInstanceOf(() => WeakSet(undefined), TypeError);
+assertThrowsInstanceOf(() => WeakSet(null), TypeError);
--- a/js/src/jit-test/tests/collections/constructor-errors.js
+++ b/js/src/jit-test/tests/collections/constructor-errors.js
@@ -3,17 +3,16 @@
 load(libdir + "asserts.js");
 
 function argsobj() { return arguments; }
 
 var misc = [
     {}, {x: 1}, Math, isNaN,
     Object.create(null),
     argsobj(0, 1, 2),
-    null,
     true, 0, 3.1416,
     new Boolean(true), new Number(0),
     {iterator: function () { return undefined; }},
     {iterator: function () { return null; }},
     {iterator: function () { return true; }},
     {iterator: function () { return 17; }},
 ];
 
--- a/js/src/jit/x64/CodeGenerator-x64.cpp
+++ b/js/src/jit/x64/CodeGenerator-x64.cpp
@@ -82,21 +82,20 @@ CodeGeneratorX64::visitBox(LBox *box)
         masm.boxValue(ValueTypeFromMIRType(box->type()), ToRegister(in), ToRegister(result));
     }
     return true;
 }
 
 bool
 CodeGeneratorX64::visitUnbox(LUnbox *unbox)
 {
-    const ValueOperand value = ToValue(unbox, LUnbox::Input);
-    const LDefinition *result = unbox->output();
     MUnbox *mir = unbox->mir();
 
     if (mir->fallible()) {
+        const ValueOperand value = ToValue(unbox, LUnbox::Input);
         Assembler::Condition cond;
         switch (mir->type()) {
           case MIRType_Int32:
             cond = masm.testInt32(Assembler::NotEqual, value);
             break;
           case MIRType_Boolean:
             cond = masm.testBoolean(Assembler::NotEqual, value);
             break;
@@ -111,31 +110,33 @@ CodeGeneratorX64::visitUnbox(LUnbox *unb
             break;
           default:
             MOZ_CRASH("Given MIRType cannot be unboxed.");
         }
         if (!bailoutIf(cond, unbox->snapshot()))
             return false;
     }
 
+    Operand input = ToOperand(unbox->getOperand(LUnbox::Input));
+    Register result = ToRegister(unbox->output());
     switch (mir->type()) {
       case MIRType_Int32:
-        masm.unboxInt32(value, ToRegister(result));
+        masm.unboxInt32(input, result);
         break;
       case MIRType_Boolean:
-        masm.unboxBoolean(value, ToRegister(result));
+        masm.unboxBoolean(input, result);
         break;
       case MIRType_Object:
-        masm.unboxObject(value, ToRegister(result));
+        masm.unboxObject(input, result);
         break;
       case MIRType_String:
-        masm.unboxString(value, ToRegister(result));
+        masm.unboxString(input, result);
         break;
       case MIRType_Symbol:
-        masm.unboxSymbol(value, ToRegister(result));
+        masm.unboxSymbol(input, result);
         break;
       default:
         MOZ_CRASH("Given MIRType cannot be unboxed.");
     }
 
     return true;
 }
 
--- a/js/src/jit/x64/Lowering-x64.cpp
+++ b/js/src/jit/x64/Lowering-x64.cpp
@@ -79,20 +79,25 @@ LIRGeneratorX64::visitBox(MBox *box)
 
 bool
 LIRGeneratorX64::visitUnbox(MUnbox *unbox)
 {
     MDefinition *box = unbox->getOperand(0);
     MOZ_ASSERT(box->type() == MIRType_Value);
 
     LUnboxBase *lir;
-    if (IsFloatingPointType(unbox->type()))
+    if (IsFloatingPointType(unbox->type())) {
         lir = new(alloc()) LUnboxFloatingPoint(useRegisterAtStart(box), unbox->type());
-    else
+    } else if (unbox->fallible()) {
+        // If the unbox is fallible, load the Value in a register first to
+        // avoid multiple loads.
         lir = new(alloc()) LUnbox(useRegisterAtStart(box));
+    } else {
+        lir = new(alloc()) LUnbox(useAtStart(box));
+    }
 
     if (unbox->fallible() && !assignSnapshot(lir, unbox->bailoutKind()))
         return false;
 
     return define(lir, unbox);
 }
 
 bool
--- a/js/src/jsweakmap.cpp
+++ b/js/src/jsweakmap.cpp
@@ -522,17 +522,17 @@ static bool
 WeakMap_construct(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     RootedObject obj(cx, NewBuiltinClassInstance(cx, &WeakMapObject::class_));
     if (!obj)
         return false;
 
     // ES6 23.3.1.1 steps 5-6, 11.
-    if (args.hasDefined(0)) {
+    if (!args.get(0).isNullOrUndefined()) {
         // Steps 7d-e.
         JS::ForOfIterator iter(cx);
         if (!iter.init(args[0]))
             return false;
 
         RootedValue pairVal(cx);
         RootedObject pairObject(cx);
         RootedValue keyVal(cx);
--- a/js/src/vm/Opcodes.h
+++ b/js/src/vm/Opcodes.h
@@ -59,17 +59,17 @@ 1234567890123456789012345678901234567890
  *     Variables
  *     Free Variables
  *     Local Variables
  *     Aliased Variables
  *     Intrinsics
  *     Block-local Scope
  *     This
  *     Arguments
- *   [Operator]
+ *   [Operators]
  *     Comparison Operators
  *     Arithmetic Operators
  *     Bitwise Logical Operators
  *     Bitwise Shift Operators
  *     Logical Operators
  *     Special Operators
  *     Stack Operations
  *     Debugger
@@ -175,44 +175,44 @@ 1234567890123456789012345678901234567890
      *   Operands:
      *   Stack: => arguments
      */ \
     macro(JSOP_ARGUMENTS, 9,  "arguments",  NULL,         1,  0,  1, JOF_BYTE) \
     \
     /*
      * Swaps the top two values on the stack. This is useful for things like
      * post-increment/decrement.
-     *   Category: Operator
+     *   Category: Operators
      *   Type: Stack Operations
      *   Operands:
      *   Stack: v1, v2 => v2, v1
      */ \
     macro(JSOP_SWAP,      10, "swap",       NULL,         1,  2,  2, JOF_BYTE) \
     /*
      * Pops the top 'n' values from the stack.
-     *   Category: Operator
+     *   Category: Operators
      *   Type: Stack Operations
      *   Operands: uint16_t n
      *   Stack: v[n-1], ..., v[1], v[0] =>
      *   nuses: n
      */ \
     macro(JSOP_POPN,      11, "popn",       NULL,         3, -1,  0, JOF_UINT16) \
     \
     /* More long-standing bytecodes. */ \
     /*
      * Pushes a copy of the top value on the stack.
-     *   Category: Operator
+     *   Category: Operators
      *   Type: Stack Operations
      *   Operands:
      *   Stack: v => v, v
      */ \
     macro(JSOP_DUP,       12, "dup",        NULL,         1,  1,  2, JOF_BYTE) \
     /*
      * Duplicates the top two values on the stack.
-     *   Category: Operator
+     *   Category: Operators
      *   Type: Stack Operations
      *   Operands:
      *   Stack: v1, v2 => v1, v2, v1, v2
      */ \
     macro(JSOP_DUP2,      13, "dup2",       NULL,         1,  2,  4, JOF_BYTE) \
     /*
      * Defines a readonly property on the frame's current variables-object (the
      * scope object on the scope chain designated to receive new variables).
@@ -221,106 +221,106 @@ 1234567890123456789012345678901234567890
      *   Operands: uint32_t nameIndex
      *   Stack: val => val
      */ \
     macro(JSOP_SETCONST,  14, "setconst",   NULL,         5,  1,  1, JOF_ATOM|JOF_NAME|JOF_SET) \
     /*
      * Pops the top two values 'lval' and 'rval' from the stack, then pushes
      * the result of the operation applied to the two operands, converting
      * both to 32-bit signed integers if necessary.
-     *   Category: Operator
+     *   Category: Operators
      *   Type: Bitwise Logical Operators
      *   Operands:
      *   Stack: lval, rval => (lval OP rval)
      */ \
     macro(JSOP_BITOR,     15, "bitor",      "|",          1,  2,  1, JOF_BYTE|JOF_LEFTASSOC|JOF_ARITH) \
     macro(JSOP_BITXOR,    16, "bitxor",     "^",          1,  2,  1, JOF_BYTE|JOF_LEFTASSOC|JOF_ARITH) \
     macro(JSOP_BITAND,    17, "bitand",     "&",          1,  2,  1, JOF_BYTE|JOF_LEFTASSOC|JOF_ARITH) \
     /*
      * Pops the top two values from the stack and pushes the result of
      * comparing them.
-     *   Category: Operator
+     *   Category: Operators
      *   Type: Comparison Operators
      *   Operands:
      *   Stack: lval, rval => (lval OP rval)
      */ \
     macro(JSOP_EQ,        18, "eq",         "==",         1,  2,  1, JOF_BYTE|JOF_LEFTASSOC|JOF_ARITH|JOF_DETECTING) \
     macro(JSOP_NE,        19, "ne",         "!=",         1,  2,  1, JOF_BYTE|JOF_LEFTASSOC|JOF_ARITH|JOF_DETECTING) \
     macro(JSOP_LT,        20, "lt",         "<",          1,  2,  1, JOF_BYTE|JOF_LEFTASSOC|JOF_ARITH) \
     macro(JSOP_LE,        21, "le",         "<=",         1,  2,  1, JOF_BYTE|JOF_LEFTASSOC|JOF_ARITH) \
     macro(JSOP_GT,        22, "gt",         ">",          1,  2,  1, JOF_BYTE|JOF_LEFTASSOC|JOF_ARITH) \
     macro(JSOP_GE,        23, "ge",         ">=",         1,  2,  1, JOF_BYTE|JOF_LEFTASSOC|JOF_ARITH) \
     /*
      * Pops the top two values 'lval' and 'rval' from the stack, then pushes
      * the result of the operation applied to the operands.
-     *   Category: Operator
+     *   Category: Operators
      *   Type: Bitwise Shift Operators
      *   Operands:
      *   Stack: lval, rval => (lval OP rval)
      */ \
     macro(JSOP_LSH,       24, "lsh",        "<<",         1,  2,  1, JOF_BYTE|JOF_LEFTASSOC|JOF_ARITH) \
     macro(JSOP_RSH,       25, "rsh",        ">>",         1,  2,  1, JOF_BYTE|JOF_LEFTASSOC|JOF_ARITH) \
     /*
      * Pops the top two values 'lval' and 'rval' from the stack, then pushes
      * 'lval >>> rval'.
-     *   Category: Operator
+     *   Category: Operators
      *   Type: Bitwise Shift Operators
      *   Operands:
      *   Stack: lval, rval => (lval >>> rval)
      */ \
     macro(JSOP_URSH,      26, "ursh",       ">>>",        1,  2,  1, JOF_BYTE|JOF_LEFTASSOC|JOF_ARITH) \
     /*
      * Pops the top two values 'lval' and 'rval' from the stack, then pushes
      * the result of 'lval + rval'.
-     *   Category: Operator
+     *   Category: Operators
      *   Type: Arithmetic Operators
      *   Operands:
      *   Stack: lval, rval => (lval + rval)
      */ \
     macro(JSOP_ADD,       27, "add",        "+",          1,  2,  1, JOF_BYTE|JOF_LEFTASSOC|JOF_ARITH) \
     /*
      * Pops the top two values 'lval' and 'rval' from the stack, then pushes
      * the result of applying the arithmetic operation to them.
-     *   Category: Operator
+     *   Category: Operators
      *   Type: Arithmetic Operators
      *   Operands:
      *   Stack: lval, rval => (lval OP rval)
      */ \
     macro(JSOP_SUB,       28, "sub",        "-",          1,  2,  1, JOF_BYTE|JOF_LEFTASSOC|JOF_ARITH) \
     macro(JSOP_MUL,       29, "mul",        "*",          1,  2,  1, JOF_BYTE|JOF_LEFTASSOC|JOF_ARITH) \
     macro(JSOP_DIV,       30, "div",        "/",          1,  2,  1, JOF_BYTE|JOF_LEFTASSOC|JOF_ARITH) \
     macro(JSOP_MOD,       31, "mod",        "%",          1,  2,  1, JOF_BYTE|JOF_LEFTASSOC|JOF_ARITH) \
     /*
      * Pops the value 'val' from the stack, then pushes '!val'.
-     *   Category: Operator
+     *   Category: Operators
      *   Type: Logical Operators
      *   Operands:
      *   Stack: val => (!val)
      */ \
     macro(JSOP_NOT,       32, "not",        "!",          1,  1,  1, JOF_BYTE|JOF_ARITH|JOF_DETECTING) \
     /*
      * Pops the value 'val' from the stack, then pushes '~val'.
-     *   Category: Operator
+     *   Category: Operators
      *   Type: Bitwise Logical Operators
      *   Operands:
      *   Stack: val => (~val)
      */ \
     macro(JSOP_BITNOT,    33, "bitnot",     "~",          1,  1,  1, JOF_BYTE|JOF_ARITH) \
     /*
      * Pops the value 'val' from the stack, then pushes '-val'.
-     *   Category: Operator
+     *   Category: Operators
      *   Type: Arithmetic Operators
      *   Operands:
      *   Stack: val => (-val)
      */ \
     macro(JSOP_NEG,       34, "neg",        "- ",         1,  1,  1, JOF_BYTE|JOF_ARITH) \
     /*
      * Pops the value 'val' from the stack, then pushes '+val'.
      * ('+val' is the value converted to a number.)
-     *   Category: Operator
+     *   Category: Operators
      *   Type: Arithmetic Operators
      *   Operands:
      *   Stack: val => (+val)
      */ \
     macro(JSOP_POS,       35, "pos",        "+ ",         1,  1,  1, JOF_BYTE|JOF_ARITH) \
     /*
      * Looks up name on the scope chain and deletes it, pushes 'true' onto the
      * stack if succeeded (if the property was present and deleted or if the
@@ -349,25 +349,25 @@ 1234567890123456789012345678901234567890
      *   Category: Operators
      *   Type: Special Operators
      *   Operands:
      *   Stack: obj, propval => succeeded
      */ \
     macro(JSOP_DELELEM,   38, "delelem",    NULL,         1,  2,  1, JOF_BYTE |JOF_ELEM|JOF_CHECKSLOPPY) \
     /*
      * Pops the value 'val' from the stack, then pushes 'typeof val'.
-     *   Category: Operator
+     *   Category: Operators
      *   Type: Special Operators
      *   Operands:
      *   Stack: val => (typeof val)
      */ \
     macro(JSOP_TYPEOF,    39, js_typeof_str,NULL,         1,  1,  1, JOF_BYTE|JOF_DETECTING) \
     /*
      * Pops the top value on the stack and pushes 'undefined'.
-     *   Category: Operator
+     *   Category: Operators
      *   Type: Special Operators
      *   Operands:
      *   Stack: val => undefined
      */ \
     macro(JSOP_VOID,      40, js_void_str,  NULL,         1,  1,  1, JOF_BYTE) \
     \
     /*
      * spreadcall variant of JSOP_CALL.
@@ -404,17 +404,17 @@ 1234567890123456789012345678901234567890
      *   Type: Function
      *   Operands:
      *   Stack: callee, this, args => rval
      */ \
     macro(JSOP_SPREADEVAL,43, "spreadeval", NULL,         1,  3,  1, JOF_BYTE|JOF_INVOKE|JOF_TYPESET|JOF_CHECKSLOPPY) \
     \
     /*
      * Duplicates the Nth value from the top onto the stack.
-     *   Category: Operator
+     *   Category: Operators
      *   Type: Stack Operations
      *   Operands: uint24_t n
      *   Stack: v[n], v[n-1], ..., v[1], v[0] =>
      *          v[n], v[n-1], ..., v[1], v[0], v[n]
      */ \
     macro(JSOP_DUPAT,     44, "dupat",      NULL,         4,  0,  1,  JOF_UINT24) \
     \
     /*
@@ -648,17 +648,17 @@ 1234567890123456789012345678901234567890
      *   Stack: =>
      */ \
     macro(JSOP_RUNONCE,   71, "runonce",    NULL,         1,  0,  0,  JOF_BYTE) \
     \
     /* New, infallible/transitive identity ops. */ \
     /*
      * Pops the top two values from the stack, then pushes the result of
      * applying the operator to the two values.
-     *   Category: Operator
+     *   Category: Operators
      *   Type: Comparison Operators
      *   Operands:
      *   Stack: lval, rval => (lval OP rval)
      */ \
     macro(JSOP_STRICTEQ,  72, "stricteq",   "===",        1,  2,  1, JOF_BYTE|JOF_DETECTING|JOF_LEFTASSOC|JOF_ARITH) \
     macro(JSOP_STRICTNE,  73, "strictne",   "!==",        1,  2,  1, JOF_BYTE|JOF_DETECTING|JOF_LEFTASSOC|JOF_ARITH) \
     \
     /*
@@ -731,17 +731,17 @@ 1234567890123456789012345678901234567890
      *   Type: Object
      *   Operands: uint32_t objectIndex
      *   Stack: => obj
      */ \
     macro(JSOP_OBJECT,    80, "object",     NULL,         5,  0,  1,  JOF_OBJECT) \
     \
     /*
      * Pops the top value off the stack.
-     *   Category: Operator
+     *   Category: Operators
      *   Type: Stack Operations
      *   Operands:
      *   Stack: v =>
      */ \
     macro(JSOP_POP,       81, "pop",        NULL,         1,  1,  0,  JOF_BYTE) \
     \
     /*
      * Invokes 'callee' as a constructor with 'this' and 'args', pushes return
@@ -1038,27 +1038,27 @@ 1234567890123456789012345678901234567890
      */ \
     macro(JSOP_THROW,     112,js_throw_str, NULL,         1,  1,  0,  JOF_BYTE) \
     \
     /*
      * Pops the top two values 'id' and 'obj' from the stack, then pushes
      * 'id in obj'.  This will throw a 'TypeError' if 'obj' is not an object.
      *
      * Note that 'obj' is the top value.
-     *   Category: Operator
+     *   Category: Operators
      *   Type: Special Operators
      *   Operands:
      *   Stack: id, obj => (id in obj)
      */ \
     macro(JSOP_IN,        113,js_in_str,    js_in_str,    1,  2,  1, JOF_BYTE|JOF_LEFTASSOC) \
     /*
      * Pops the top two values 'obj' and 'ctor' from the stack, then pushes
      * 'obj instanceof ctor'.  This will throw a 'TypeError' if 'obj' is not an
      * object.
-     *   Category: Operator
+     *   Category: Operators
      *   Type: Special Operators
      *   Operands:
      *   Stack: obj, ctor => (obj instanceof ctor)
      */ \
     macro(JSOP_INSTANCEOF,114,js_instanceof_str,js_instanceof_str,1,2,1,JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT) \
     \
     /*
      * Invokes debugger.
@@ -1265,17 +1265,17 @@ 1234567890123456789012345678901234567890
      *   Operands:
      *   Stack: => callee
      */ \
     macro(JSOP_CALLEE,    132, "callee",    NULL,         1,  0,  1, JOF_BYTE) \
     \
     /*
      * Picks the nth element from the stack and moves it to the top of the
      * stack.
-     *   Category: Operator
+     *   Category: Operators
      *   Type: Stack Operations
      *   Operands: uint8_t n
      *   Stack: v[n], v[n-1], ..., v[1], v[0] => v[n-1], ..., v[1], v[0], v[n]
      */ \
     macro(JSOP_PICK,        133, "pick",      NULL,       2,  0,  0,  JOF_UINT8|JOF_TMPSLOT2) \
     \
     /*
      * This no-op appears at the top of the bytecode for a 'TryStatement'.
@@ -1596,17 +1596,17 @@ 1234567890123456789012345678901234567890
     \
     macro(JSOP_UNUSED196,     196,"unused196",   NULL,    1,  0,  0, JOF_BYTE) \
     \
     /*
      * Pops the top stack value as 'val' and pushes 'typeof val'.  Note that
      * this opcode isn't used when, in the original source code, 'val' is a
      * name -- see 'JSOP_TYPEOF' for that.
      * (This is because 'typeof undefinedName === "undefined"'.)
-     *   Category: Operator
+     *   Category: Operators
      *   Type: Special Operators
      *   Operands:
      *   Stack: val => (typeof val)
      */ \
     macro(JSOP_TYPEOFEXPR,    197,"typeofexpr",  NULL,    1,  1,  1, JOF_BYTE|JOF_DETECTING) \
     \
     /* Block-local scope support. */ \
     /*
@@ -1701,17 +1701,17 @@ 1234567890123456789012345678901234567890
      *   Stack: =>
      */ \
     macro(JSOP_FORCEINTERPRETER, 207, "forceinterpreter", NULL,  1,  0,  0,  JOF_BYTE) \
     \
     /*
      * Bytecode emitted after 'yield' expressions to help the Debugger
      * fix up the frame in the JITs. No-op in the interpreter.
      *
-     *   Category: Operator
+     *   Category: Operators
      *   Type: Debugger
      *   Operands:
      *   Stack: =>
      */ \
     macro(JSOP_DEBUGAFTERYIELD,  208, "debugafteryield",  NULL,  1,  0,  0,  JOF_BYTE) \
     macro(JSOP_UNUSED209,     209, "unused209",    NULL,  1,  0,  0,  JOF_BYTE) \
     macro(JSOP_UNUSED210,     210, "unused210",    NULL,  1,  0,  0,  JOF_BYTE) \
     macro(JSOP_UNUSED211,     211, "unused211",    NULL,  1,  0,  0,  JOF_BYTE) \
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -3477,16 +3477,23 @@ nsRect nsDisplayWrapList::GetComponentAl
 }
 
 void
 nsDisplayWrapList::SetVisibleRect(const nsRect& aRect)
 {
   mVisibleRect = aRect;
 }
 
+void
+nsDisplayWrapList::SetReferenceFrame(const nsIFrame* aFrame)
+{
+  mReferenceFrame = aFrame;
+  mToReferenceFrame = mFrame->GetOffsetToCrossDoc(mReferenceFrame);
+}
+
 static nsresult
 WrapDisplayList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                 nsDisplayList* aList, nsDisplayWrapper* aWrapper) {
   if (!aList->GetTop())
     return NS_OK;
   nsDisplayItem* item = aWrapper->WrapList(aBuilder, aFrame, aList);
   if (!item)
     return NS_ERROR_OUT_OF_MEMORY;
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -2738,16 +2738,18 @@ public:
   void SetOverrideZIndex(int32_t aZIndex)
   {
     mHasZIndexOverride = true;
     mOverrideZIndex = aZIndex;
   }
 
   void SetVisibleRect(const nsRect& aRect);
 
+  void SetReferenceFrame(const nsIFrame* aFrame);
+
   /**
    * This creates a copy of this item, but wrapping aItem instead of
    * our existing list. Only gets called if this item returned nullptr
    * for GetUnderlyingFrame(). aItem is guaranteed to return non-null from
    * GetUnderlyingFrame().
    */
   virtual nsDisplayWrapList* WrapWithClone(nsDisplayListBuilder* aBuilder,
                                            nsDisplayItem* aItem) {
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -1791,16 +1791,17 @@ WrapPreserve3DListInternal(nsIFrame* aFr
     // and then flush this list into aOutput by wrapping the whole lot with a single
     // nsDisplayTransform.
 
     if (childFrame->GetParent() &&
         (childFrame->GetParent()->Preserves3DChildren() || childFrame == aFrame)) {
       switch (item->GetType()) {
         case nsDisplayItem::TYPE_TRANSFORM: {
           if (!aTemp->IsEmpty()) {
+            // Flush current aTemp contents
             aOutput->AppendToTop(new (aBuilder) nsDisplayTransform(aBuilder,
                 aFrame, aTemp, aTemp->GetVisibleRect(), aIndex++));
           }
           // Override item's clipping with our current clip state (if any). Since we're
           // bubbling up a preserve-3d transformed child to a preserve-3d parent,
           // we can be sure the child doesn't have clip state of its own.
           NS_ASSERTION(!item->GetClip().HasClip(), "Unexpected clip on item");
           const DisplayItemClip* clip = aBuilder->ClipState().GetCurrentCombinedClip(aBuilder);
@@ -1814,30 +1815,34 @@ WrapPreserve3DListInternal(nsIFrame* aFr
           nsDisplayWrapList *list = static_cast<nsDisplayWrapList*>(item);
           rv = WrapPreserve3DListInternal(aFrame, aBuilder,
               list->GetChildren(), aOutput, aIndex, aTemp);
           list->~nsDisplayWrapList();
           break;
         }
         case nsDisplayItem::TYPE_OPACITY: {
           if (!aTemp->IsEmpty()) {
+            // Flush current aTemp contents
             aOutput->AppendToTop(new (aBuilder) nsDisplayTransform(aBuilder,
                 aFrame, aTemp, aTemp->GetVisibleRect(), aIndex++));
           }
           nsDisplayOpacity *opacity = static_cast<nsDisplayOpacity*>(item);
           nsDisplayList output;
           // Call GetChildren, not GetSameCoordinateSystemChildren, because
           // the preserve-3d children of 'opacity' are temporarily not in the
           // same coordinate system as the opacity --- until this wrapping is done.
           rv = WrapPreserve3DListInternal(aFrame, aBuilder,
               opacity->GetChildren(), &output, aIndex, aTemp);
           if (!aTemp->IsEmpty()) {
             output.AppendToTop(new (aBuilder) nsDisplayTransform(aBuilder,
                 aFrame, aTemp, aTemp->GetVisibleRect(), aIndex++));
           }
+
+          opacity->SetVisibleRect(output.GetVisibleRect());
+          opacity->SetReferenceFrame(output.GetBottom()->ReferenceFrame());
           opacity->GetChildren()->AppendToTop(&output);
           opacity->UpdateBounds(aBuilder);
           aOutput->AppendToTop(item);
           break;
         }
         default: {
           if (childFrame->StyleDisplay()->BackfaceIsHidden()) {
             if (!aTemp->IsEmpty()) {
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1098266-1-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<body>
+<div style="position: absolute; transform-style: preserve-3d; transform: perspective(600px) scale(0.166667); opacity:0.3">
+  <div style="position: absolute; background: yellow; width:900px; height:100px; transform: translate3d(0, 3000px, 0px) rotateZ(90deg) scale(5); transform-style: preserve-3d;">
+  </div>
+</div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1098266-1.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<body>
+<div style="position: absolute; transform-style: preserve-3d; transform: perspective(600px) scale(0.166667); ">
+  <div style="position: absolute; background: yellow; width:900px; height:100px; transform: translate3d(0, 3000px, 0px) rotateZ(90deg) scale(5); transform-style: preserve-3d; opacity:0.3">
+  </div>
+</div>
+</body>
+</html>
--- a/testing/testsuite-targets.mk
+++ b/testing/testsuite-targets.mk
@@ -515,21 +515,21 @@ endif
 ifdef STRIP_CPP_TESTS
 	$(OBJCOPY) $(or $(STRIP_FLAGS),--strip-unneeded) $(DIST)/bin/jsapi-tests$(BIN_SUFFIX) $(PKG_STAGE)/cppunittests/jsapi-tests$(BIN_SUFFIX)
 else
 	cp -RL $(DIST)/bin/jsapi-tests$(BIN_SUFFIX) $(PKG_STAGE)/cppunittests
 endif
 
 stage-jittest: make-stage-dir
 	$(NSINSTALL) -D $(PKG_STAGE)/jit-test/tests
-	cp -RL $(topsrcdir)/js/src/jsapi.h $(PKG_STAGE)/jit-test
-	cp -RL $(topsrcdir)/js/src/jit-test $(PKG_STAGE)/jit-test/jit-test
-	cp -RL $(topsrcdir)/js/src/tests/ecma_6 $(PKG_STAGE)/jit-test/tests/ecma_6
-	cp -RL $(topsrcdir)/js/src/tests/js1_8_5 $(PKG_STAGE)/jit-test/tests/js1_8_5
-	cp -RL $(topsrcdir)/js/src/tests/lib $(PKG_STAGE)/jit-test/tests/lib
+	cp -RL $(topsrcdir)/js/src/jsapi.h $(PKG_STAGE)/jit-test/
+	cp -RL $(topsrcdir)/js/src/jit-test $(PKG_STAGE)/jit-test/
+	cp -RL $(topsrcdir)/js/src/tests/ecma_6 $(PKG_STAGE)/jit-test/tests/
+	cp -RL $(topsrcdir)/js/src/tests/js1_8_5 $(PKG_STAGE)/jit-test/tests/
+	cp -RL $(topsrcdir)/js/src/tests/lib $(PKG_STAGE)/jit-test/tests/
 
 stage-steeplechase: make-stage-dir
 	$(NSINSTALL) -D $(PKG_STAGE)/steeplechase/
 	cp -RL $(DEPTH)/_tests/steeplechase $(PKG_STAGE)/steeplechase/tests
 	cp -RL $(DIST)/xpi-stage/specialpowers $(PKG_STAGE)/steeplechase
 	cp -RL $(topsrcdir)/testing/profiles/prefs_general.js $(PKG_STAGE)/steeplechase
 
 MARIONETTE_DIR=$(PKG_STAGE)/marionette
--- a/toolkit/components/alerts/nsAlertsService.cpp
+++ b/toolkit/components/alerts/nsAlertsService.cpp
@@ -65,65 +65,68 @@ bool nsAlertsService::ShouldShowAlert()
 NS_IMETHODIMP nsAlertsService::ShowAlertNotification(const nsAString & aImageUrl, const nsAString & aAlertTitle, 
                                                      const nsAString & aAlertText, bool aAlertTextClickable,
                                                      const nsAString & aAlertCookie,
                                                      nsIObserver * aAlertListener,
                                                      const nsAString & aAlertName,
                                                      const nsAString & aBidi,
                                                      const nsAString & aLang,
                                                      const nsAString & aData,
-                                                     nsIPrincipal * aPrincipal)
+                                                     nsIPrincipal * aPrincipal,
+                                                     bool aInPrivateBrowsing)
 {
   if (XRE_GetProcessType() == GeckoProcessType_Content) {
     ContentChild* cpc = ContentChild::GetSingleton();
 
     if (aAlertListener)
       cpc->AddRemoteAlertObserver(PromiseFlatString(aAlertCookie), aAlertListener);
 
     cpc->SendShowAlertNotification(PromiseFlatString(aImageUrl),
                                    PromiseFlatString(aAlertTitle),
                                    PromiseFlatString(aAlertText),
                                    aAlertTextClickable,
                                    PromiseFlatString(aAlertCookie),
                                    PromiseFlatString(aAlertName),
                                    PromiseFlatString(aBidi),
                                    PromiseFlatString(aLang),
                                    PromiseFlatString(aData),
-                                   IPC::Principal(aPrincipal));
+                                   IPC::Principal(aPrincipal),
+                                   aInPrivateBrowsing);
     return NS_OK;
   }
 
 #ifdef MOZ_WIDGET_ANDROID
   mozilla::AndroidBridge::Bridge()->ShowAlertNotification(aImageUrl, aAlertTitle, aAlertText, aAlertCookie,
                                                           aAlertListener, aAlertName);
   return NS_OK;
 #else
   // Check if there is an optional service that handles system-level notifications
   nsCOMPtr<nsIAlertsService> sysAlerts(do_GetService(NS_SYSTEMALERTSERVICE_CONTRACTID));
   nsresult rv;
   if (sysAlerts) {
     rv = sysAlerts->ShowAlertNotification(aImageUrl, aAlertTitle, aAlertText, aAlertTextClickable,
                                           aAlertCookie, aAlertListener, aAlertName,
                                           aBidi, aLang, aData,
-                                          IPC::Principal(aPrincipal));
+                                          IPC::Principal(aPrincipal),
+                                          aInPrivateBrowsing);
     if (NS_SUCCEEDED(rv))
       return NS_OK;
   }
 
   if (!ShouldShowAlert()) {
     // Do not display the alert. Instead call alertfinished and get out.
     if (aAlertListener)
       aAlertListener->Observe(nullptr, "alertfinished", PromiseFlatString(aAlertCookie).get());
     return NS_OK;
   }
 
   // Use XUL notifications as a fallback if above methods have failed.
   rv = mXULAlerts.ShowAlertNotification(aImageUrl, aAlertTitle, aAlertText, aAlertTextClickable,
                                         aAlertCookie, aAlertListener, aAlertName,
-                                        aBidi, aLang);
+                                        aBidi, aLang, aInPrivateBrowsing);
   return rv;
 #endif // !MOZ_WIDGET_ANDROID
 }
 
 NS_IMETHODIMP nsAlertsService::CloseAlert(const nsAString& aAlertName,
                                           nsIPrincipal* aPrincipal)
 {
   if (XRE_GetProcessType() == GeckoProcessType_Content) {
--- a/toolkit/components/alerts/nsIAlertsService.idl
+++ b/toolkit/components/alerts/nsIAlertsService.idl
@@ -4,17 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 
 #include "nsISupports.idl"
 #include "nsIObserver.idl"
 
 interface nsIPrincipal;
 
-[scriptable, uuid(d446bede-fcf7-403d-b6b6-5fd67b19ba58)]
+[scriptable, uuid(9d0284bf-db40-42da-8f0d-c2769dbde7aa)]
 interface nsIAlertsService : nsISupports
 {
    /**
     * Displays a sliding notification window.
     *
     * @param imageUrl       A URL identifying the image to put in the alert.
     *                       The OS X implemenation limits the amount of time it
     *                       will wait for an icon to load to six seconds. After
@@ -32,16 +32,18 @@ interface nsIAlertsService : nsISupports
     *                       used on Android and OS X. On Android the name is
     *                       hashed and used as a notification ID. Notifications
     *                       will replace previous notifications with the same name.
     * @param dir            Bidi override for the title. Valid values are
     *                       "auto", "ltr" or "rtl". Only available on supported
     *                       platforms.
     * @param lang           Language of title and text of the alert. Only available
     *                       on supported platforms.
+    * @param inPrivateBrowsing If set to true, imageUrl will be loaded in private
+    *                          browsing mode.
     * @throws NS_ERROR_NOT_AVAILABLE If the notification cannot be displayed.
     *
     * The following arguments will be passed to the alertListener's observe() 
     * method:
     *   subject - null
     *   topic   - "alertfinished" when the alert goes away
     *             "alertclickcallback" when the text is clicked
     *             "alertshow" when the alert is shown
@@ -57,17 +59,18 @@ interface nsIAlertsService : nsISupports
                               in AString  text,
                               [optional] in boolean textClickable,
                               [optional] in AString cookie,
                               [optional] in nsIObserver alertListener,
                               [optional] in AString name,
                               [optional] in AString dir,
                               [optional] in AString lang,
                               [optional] in AString data,
-                              [optional] in nsIPrincipal principal);
+                              [optional] in nsIPrincipal principal,
+                              [optional] in boolean inPrivateBrowsing);
 
    /**
     * Close alerts created by the service.
     *
     * @param name           The name of the notification to close. If no name
     *                       is provided then only a notification created with
     *                       no name (if any) will be closed.
     */
--- a/toolkit/components/alerts/nsXULAlerts.cpp
+++ b/toolkit/components/alerts/nsXULAlerts.cpp
@@ -39,17 +39,17 @@ nsXULAlertObserver::Observe(nsISupports*
   return rv;
 }
 
 nsresult
 nsXULAlerts::ShowAlertNotification(const nsAString& aImageUrl, const nsAString& aAlertTitle,
                                    const nsAString& aAlertText, bool aAlertTextClickable,
                                    const nsAString& aAlertCookie, nsIObserver* aAlertListener,
                                    const nsAString& aAlertName, const nsAString& aBidi,
-                                   const nsAString& aLang)
+                                   const nsAString& aLang, bool aInPrivateBrowsing)
 {
   nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
 
   nsCOMPtr<nsISupportsArray> argsArray;
   nsresult rv = NS_NewISupportsArray(getter_AddRefs(argsArray));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // create scriptable versions of our strings that we can store in our nsISupportsArray....
@@ -130,19 +130,22 @@ nsXULAlerts::ShowAlertNotification(const
   nsRefPtr<nsXULAlertObserver> alertObserver = new nsXULAlertObserver(this, aAlertName, aAlertListener);
   nsCOMPtr<nsISupports> iSupports(do_QueryInterface(alertObserver));
   ifptr->SetData(iSupports);
   ifptr->SetDataIID(&NS_GET_IID(nsIObserver));
   rv = argsArray->AppendElement(ifptr);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIDOMWindow> newWindow;
-  rv = wwatch->OpenWindow(0, ALERT_CHROME_URL, "_blank",
-                          "chrome,dialog=yes,titlebar=no,popup=yes", argsArray,
-                          getter_AddRefs(newWindow));
+  nsAutoCString features("chrome,dialog=yes,titlebar=no,popup=yes");
+  if (aInPrivateBrowsing) {
+    features.AppendLiteral(",private");
+  }
+  rv = wwatch->OpenWindow(0, ALERT_CHROME_URL, "_blank", features.get(),
+                          argsArray, getter_AddRefs(newWindow));
   NS_ENSURE_SUCCESS(rv, rv);
 
   mNamedWindows.Put(aAlertName, newWindow);
   alertObserver->SetAlertWindow(newWindow);
 
   return NS_OK;
 }
 
--- a/toolkit/components/alerts/nsXULAlerts.h
+++ b/toolkit/components/alerts/nsXULAlerts.h
@@ -20,17 +20,17 @@ public:
   }
 
   virtual ~nsXULAlerts() {}
 
   nsresult ShowAlertNotification(const nsAString& aImageUrl, const nsAString& aAlertTitle,
                                  const nsAString& aAlertText, bool aAlertTextClickable,
                                  const nsAString& aAlertCookie, nsIObserver* aAlertListener,
                                  const nsAString& aAlertName, const nsAString& aBidi,
-                                 const nsAString& aLang);
+                                 const nsAString& aLang, bool aInPrivateBrowsing);
 
   nsresult CloseAlert(const nsAString& aAlertName);
 protected:
   nsInterfaceHashtable<nsStringHashKey, nsIDOMWindow> mNamedWindows;
 };
 
 /**
  * This class wraps observers for alerts and watches
--- a/toolkit/components/downloads/nsDownloadManager.cpp
+++ b/toolkit/components/downloads/nsDownloadManager.cpp
@@ -2751,17 +2751,17 @@ nsDownload::SetState(DownloadState aStat
               // retention policy, there's no reason to make the text clickable
               // because if it is, they'll click open the download manager and
               // the items they downloaded will have been removed.
               alerts->ShowAlertNotification(
                   NS_LITERAL_STRING(DOWNLOAD_MANAGER_ALERT_ICON), title,
                   message, !removeWhenDone,
                   mPrivate ? NS_LITERAL_STRING("private") : NS_LITERAL_STRING("non-private"),
                   mDownloadManager, EmptyString(), NS_LITERAL_STRING("auto"),
-                  EmptyString(), EmptyString(), nullptr);
+                  EmptyString(), EmptyString(), nullptr, mPrivate);
             }
         }
       }
 
 #if defined(XP_WIN) || defined(XP_MACOSX) || defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GTK)
       nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(mTarget);
       nsCOMPtr<nsIFile> file;
       nsAutoString path;
--- a/toolkit/system/gnome/nsAlertsIconListener.cpp
+++ b/toolkit/system/gnome/nsAlertsIconListener.cpp
@@ -195,17 +195,17 @@ nsAlertsIconListener::ShowAlert(GdkPixbu
 
   if (result && mAlertListener)
     mAlertListener->Observe(nullptr, "alertshow", mAlertCookie.get());
 
   return result ? NS_OK : NS_ERROR_FAILURE;
 }
 
 nsresult
-nsAlertsIconListener::StartRequest(const nsAString & aImageUrl)
+nsAlertsIconListener::StartRequest(const nsAString & aImageUrl, bool aInPrivateBrowsing)
 {
   if (mIconRequest) {
     // Another icon request is already in flight.  Kill it.
     mIconRequest->Cancel(NS_BINDING_ABORTED);
     mIconRequest = nullptr;
   }
 
   nsCOMPtr<nsIURI> imageUri;
@@ -214,18 +214,21 @@ nsAlertsIconListener::StartRequest(const
     return ShowAlert(nullptr);
 
   nsCOMPtr<imgILoader> il(do_GetService("@mozilla.org/image/loader;1"));
   if (!il)
     return ShowAlert(nullptr);
 
   nsresult rv = il->LoadImageXPCOM(imageUri, nullptr, nullptr,
                                    NS_LITERAL_STRING("default"), nullptr, nullptr,
-                                   this, nullptr, nsIRequest::LOAD_NORMAL, nullptr,
-                                   0 /* use default */, getter_AddRefs(mIconRequest));
+                                   this, nullptr,
+                                   aInPrivateBrowsing ? nsIRequest::LOAD_ANONYMOUS :
+                                                        nsIRequest::LOAD_NORMAL,
+                                   nullptr, 0 /* use default */,
+                                   getter_AddRefs(mIconRequest));
   if (NS_FAILED(rv))
     return rv;
 
   mIconRequest->StartDecoding();
 
   return NS_OK;
 }
 
@@ -262,17 +265,18 @@ nsAlertsIconListener::Observe(nsISupport
 }
 
 nsresult
 nsAlertsIconListener::InitAlertAsync(const nsAString & aImageUrl,
                                      const nsAString & aAlertTitle, 
                                      const nsAString & aAlertText,
                                      bool aAlertTextClickable,
                                      const nsAString & aAlertCookie,
-                                     nsIObserver * aAlertListener)
+                                     nsIObserver * aAlertListener,
+                                     bool aInPrivateBrowsing)
 {
   if (!libNotifyHandle)
     return NS_ERROR_FAILURE;
 
   if (!notify_is_initted()) {
     // Give the name of this application to libnotify
     nsCOMPtr<nsIStringBundleService> bundleService = 
       do_GetService(NS_STRINGBUNDLE_CONTRACTID);
@@ -336,10 +340,10 @@ nsAlertsIconListener::InitAlertAsync(con
   }
 
   mAlertText = NS_ConvertUTF16toUTF8(aAlertText);
   mAlertHasAction = aAlertTextClickable;
 
   mAlertListener = aAlertListener;
   mAlertCookie = aAlertCookie;
 
-  return StartRequest(aImageUrl);
+  return StartRequest(aImageUrl, aInPrivateBrowsing);
 }
--- a/toolkit/system/gnome/nsAlertsIconListener.h
+++ b/toolkit/system/gnome/nsAlertsIconListener.h
@@ -29,17 +29,18 @@ public:
 
   nsAlertsIconListener();
 
   nsresult InitAlertAsync(const nsAString & aImageUrl,
                           const nsAString & aAlertTitle, 
                           const nsAString & aAlertText,
                           bool aAlertTextClickable,
                           const nsAString & aAlertCookie,
-                          nsIObserver * aAlertListener);
+                          nsIObserver * aAlertListener,
+                          bool aInPrivateBrowsing);
 
   void SendCallback();
   void SendClosed();
 
 protected:
   virtual ~nsAlertsIconListener();
 
   nsresult OnLoadComplete(imgIRequest* aRequest);
@@ -77,13 +78,13 @@ protected:
   static notify_get_server_caps_t notify_get_server_caps;
   static notify_notification_new_t notify_notification_new;
   static notify_notification_show_t notify_notification_show;
   static notify_notification_set_icon_from_pixbuf_t notify_notification_set_icon_from_pixbuf;
   static notify_notification_add_action_t notify_notification_add_action;
   NotifyNotification* mNotification;
   gulong mClosureHandler;
 
-  nsresult StartRequest(const nsAString & aImageUrl);
+  nsresult StartRequest(const nsAString & aImageUrl, bool aInPrivateBrowsing);
   nsresult ShowAlert(GdkPixbuf* aPixbuf);
 };
 
 #endif
--- a/toolkit/system/gnome/nsSystemAlertsService.cpp
+++ b/toolkit/system/gnome/nsSystemAlertsService.cpp
@@ -32,23 +32,24 @@ nsSystemAlertsService::Init()
 NS_IMETHODIMP nsSystemAlertsService::ShowAlertNotification(const nsAString & aImageUrl, const nsAString & aAlertTitle, 
                                                            const nsAString & aAlertText, bool aAlertTextClickable,
                                                            const nsAString & aAlertCookie,
                                                            nsIObserver * aAlertListener,
                                                            const nsAString & aAlertName,
                                                            const nsAString & aBidi,
                                                            const nsAString & aLang,
                                                            const nsAString & aData,
-                                                           nsIPrincipal * aPrincipal)
+                                                           nsIPrincipal * aPrincipal,
+                                                           bool aInPrivateBrowsing)
 {
   nsRefPtr<nsAlertsIconListener> alertListener = new nsAlertsIconListener();
   if (!alertListener)
     return NS_ERROR_OUT_OF_MEMORY;
 
   return alertListener->InitAlertAsync(aImageUrl, aAlertTitle, aAlertText, aAlertTextClickable,
-                                       aAlertCookie, aAlertListener);
+                                       aAlertCookie, aAlertListener, aInPrivateBrowsing);
 }
 
 NS_IMETHODIMP nsSystemAlertsService::CloseAlert(const nsAString& aAlertName,
                                                 nsIPrincipal* aPrincipal)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
--- a/widget/cocoa/OSXNotificationCenter.mm
+++ b/widget/cocoa/OSXNotificationCenter.mm
@@ -199,17 +199,18 @@ NS_IMETHODIMP
 OSXNotificationCenter::ShowAlertNotification(const nsAString & aImageUrl, const nsAString & aAlertTitle,
                                              const nsAString & aAlertText, bool aAlertTextClickable,
                                              const nsAString & aAlertCookie,
                                              nsIObserver * aAlertListener,
                                              const nsAString & aAlertName,
                                              const nsAString & aBidi,
                                              const nsAString & aLang,
                                              const nsAString & aData,
-                                             nsIPrincipal * aPrincipal)
+                                             nsIPrincipal * aPrincipal,
+                                             bool aInPrivateBrowsing)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
   Class unClass = NSClassFromString(@"NSUserNotification");
   id<FakeNSUserNotification> notification = [[unClass alloc] init];
   notification.title = [NSString stringWithCharacters:(const unichar *)aAlertTitle.BeginReading()
                                                length:aAlertTitle.Length()];
   notification.informativeText = [NSString stringWithCharacters:(const unichar *)aAlertText.BeginReading()
@@ -241,18 +242,21 @@ OSXNotificationCenter::ShowAlertNotifica
     nsRefPtr<imgLoader> il = imgLoader::GetInstance();
     if (il) {
       nsCOMPtr<nsIURI> imageUri;
       NS_NewURI(getter_AddRefs(imageUri), aImageUrl);
       if (imageUri) {
         nsresult rv = il->LoadImage(imageUri, nullptr, nullptr,
                                     mozilla::net::RP_Default,
                                     aPrincipal, nullptr,
-                                    this, nullptr, nsIRequest::LOAD_NORMAL, nullptr,
-                                    nsIContentPolicy::TYPE_IMAGE, EmptyString(),
+                                    this, nullptr,
+                                    aInPrivateBrowsing ? nsIRequest::LOAD_ANONYMOUS :
+                                                         nsIRequest::LOAD_NORMAL,
+                                    nullptr, nsIContentPolicy::TYPE_IMAGE,
+                                    EmptyString(),
                                     getter_AddRefs(osxni->mIconRequest));
         if (NS_SUCCEEDED(rv)) {
           // Set a timer for six seconds. If we don't have an icon by the time this
           // goes off then we go ahead without an icon.
           nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID);
           osxni->mIconTimeoutTimer = timer;
           timer->InitWithCallback(this, 6000, nsITimer::TYPE_ONE_SHOT);
           return NS_OK;