Merge mozilla-central into mozilla-inbound
authorEhsan Akhgari <ehsan@mozilla.com>
Thu, 06 Dec 2012 01:08:07 -0500
changeset 120756 d5a465367a8e7fa3e91c5f22808153c3cb8a68c0
parent 120755 a16704573ef7215df3b21a865e1e1c4787d1e782 (current diff)
parent 120670 7dcc0be8d4aa8d113092e30599b4e6e0cacd8d89 (diff)
child 120757 2971c45877a749edd9e43f645e7259800d6f97f5
push idunknown
push userunknown
push dateunknown
milestone20.0a1
Merge mozilla-central into mozilla-inbound
security/manager/ssl/tests/unit/xpcshell.ini
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -923,16 +923,25 @@ window.addEventListener('ContentStart', 
   Services.obs.addObserver(function(aSubject, aTopic, aData) {
     shell.sendChromeEvent({
       type: 'headphones-status-changed',
       state: aData
     });
 }, "headphones-status-changed", false);
 })();
 
+(function audioChannelChangedTracker() {
+  Services.obs.addObserver(function(aSubject, aTopic, aData) {
+    shell.sendChromeEvent({
+      type: 'audio-channel-changed',
+      channel: aData
+    });
+}, "audio-channel-changed", false);
+})();
+
 (function recordingStatusTracker() {
   let gRecordingActiveCount = 0;
 
   Services.obs.addObserver(function(aSubject, aTopic, aData) {
     let oldCount = gRecordingActiveCount;
     if (aData == "starting") {
       gRecordingActiveCount += 1;
     } else if (aData == "shutdown") {
--- a/browser/components/tabview/test/Makefile.in
+++ b/browser/components/tabview/test/Makefile.in
@@ -143,17 +143,16 @@ include $(topsrcdir)/config/rules.mk
                  browser_tabview_click_group.js \
                  browser_tabview_dragdrop.js \
                  browser_tabview_exit_button.js \
                  browser_tabview_expander.js \
                  browser_tabview_firstrun_pref.js \
                  browser_tabview_group.js \
                  browser_tabview_launch.js \
                  browser_tabview_multiwindow_search.js \
-                 browser_tabview_privatebrowsing.js \
                  browser_tabview_rtl.js \
                  browser_tabview_search.js \
                  browser_tabview_snapping.js \
                  browser_tabview_startup_transitions.js \
                  browser_tabview_undo_group.js \
                  dummy_page.html \
                  head.js \
                  search1.html \
@@ -170,16 +169,17 @@ ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
                  browser_tabview_bug624727_perwindowpb.js \
                  browser_tabview_bug650280_perwindowpb.js \
                  $(NULL)
 else
 _BROWSER_FILES += \
                  browser_tabview_bug624265.js \
                  browser_tabview_bug624727.js \
                  browser_tabview_bug650280.js \
+                 browser_tabview_privatebrowsing.js \
                  $(NULL)
 endif
 
 
 # browser_tabview_bug597980.js is disabled for leaking, see bug 711907
 
 libs::	$(_BROWSER_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
--- a/dom/audiochannel/AudioChannelCommon.h
+++ b/dom/audiochannel/AudioChannelCommon.h
@@ -13,16 +13,17 @@ namespace dom {
 // The audio channel. Read the nsIHTMLMediaElement.idl for a description
 // about this attribute.
 enum AudioChannelType {
   AUDIO_CHANNEL_NORMAL = 0,
   AUDIO_CHANNEL_CONTENT,
   AUDIO_CHANNEL_NOTIFICATION,
   AUDIO_CHANNEL_ALARM,
   AUDIO_CHANNEL_TELEPHONY,
-  AUDIO_CHANNEL_PUBLICNOTIFICATION
+  AUDIO_CHANNEL_PUBLICNOTIFICATION,
+  AUDIO_CHANNEL_LAST
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif
 
--- a/dom/audiochannel/AudioChannelService.cpp
+++ b/dom/audiochannel/AudioChannelService.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
 /* vim: set ts=2 et sw=2 tw=80: */
 /* 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/. */
 
 #include "AudioChannelService.h"
+#include "AudioChannelServiceChild.h"
 
 #include "base/basictypes.h"
 
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/unused.h"
 #include "mozilla/Util.h"
 
@@ -25,41 +26,50 @@ using namespace mozilla::dom;
 StaticRefPtr<AudioChannelService> gAudioChannelService;
 
 // static
 AudioChannelService*
 AudioChannelService::GetAudioChannelService()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
+  if (XRE_GetProcessType() != GeckoProcessType_Default) {
+    return AudioChannelServiceChild::GetAudioChannelService();
+  }
+
   // If we already exist, exit early
   if (gAudioChannelService) {
     return gAudioChannelService;
   }
 
   // Create new instance, register, return
   nsRefPtr<AudioChannelService> service = new AudioChannelService();
   NS_ENSURE_TRUE(service, nullptr);
 
   gAudioChannelService = service;
   return gAudioChannelService;
 }
 
 void
 AudioChannelService::Shutdown()
 {
+  if (XRE_GetProcessType() != GeckoProcessType_Default) {
+    return AudioChannelServiceChild::Shutdown();
+  }
+
   if (gAudioChannelService) {
     delete gAudioChannelService;
     gAudioChannelService = nullptr;
   }
 }
 
 NS_IMPL_ISUPPORTS0(AudioChannelService)
 
 AudioChannelService::AudioChannelService()
+: mCurrentHigherChannel(AUDIO_CHANNEL_NORMAL)
 {
   mChannelCounters = new int32_t[AUDIO_CHANNEL_PUBLICNOTIFICATION+1];
 
   for (int i = AUDIO_CHANNEL_NORMAL;
        i <= AUDIO_CHANNEL_PUBLICNOTIFICATION;
        ++i) {
     mChannelCounters[i] = 0;
   }
@@ -73,35 +83,46 @@ AudioChannelService::~AudioChannelServic
   delete [] mChannelCounters;
 }
 
 void
 AudioChannelService::RegisterMediaElement(nsHTMLMediaElement* aMediaElement,
                                           AudioChannelType aType)
 {
   mMediaElements.Put(aMediaElement, aType);
+  RegisterType(aType);
+}
+
+void
+AudioChannelService::RegisterType(AudioChannelType aType)
+{
   mChannelCounters[aType]++;
 
   // In order to avoid race conditions, it's safer to notify any existing
   // media element any time a new one is registered.
   Notify();
 }
 
 void
 AudioChannelService::UnregisterMediaElement(nsHTMLMediaElement* aMediaElement)
 {
   AudioChannelType type;
   if (!mMediaElements.Get(aMediaElement, &type)) {
     return;
   }
 
   mMediaElements.Remove(aMediaElement);
+  UnregisterType(type);
+}
 
-  mChannelCounters[type]--;
-  MOZ_ASSERT(mChannelCounters[type] >= 0);
+void
+AudioChannelService::UnregisterType(AudioChannelType aType)
+{
+  mChannelCounters[aType]--;
+  MOZ_ASSERT(mChannelCounters[aType] >= 0);
 
   // In order to avoid race conditions, it's safer to notify any existing
   // media element any time a new one is registered.
   Notify();
 }
 
 bool
 AudioChannelService::GetMuted(AudioChannelType aType, bool aElementHidden)
@@ -119,38 +140,72 @@ AudioChannelService::GetMuted(AudioChann
         break;
 
       case AUDIO_CHANNEL_NOTIFICATION:
       case AUDIO_CHANNEL_ALARM:
       case AUDIO_CHANNEL_TELEPHONY:
       case AUDIO_CHANNEL_PUBLICNOTIFICATION:
         // Nothing to do
         break;
+
+      case AUDIO_CHANNEL_LAST:
+        MOZ_NOT_REACHED();
+        return false;
     }
   }
 
+  bool muted = false;
+
   // Priorities:
   switch (aType) {
     case AUDIO_CHANNEL_NORMAL:
     case AUDIO_CHANNEL_CONTENT:
-      return !!mChannelCounters[AUDIO_CHANNEL_NOTIFICATION] ||
-             !!mChannelCounters[AUDIO_CHANNEL_ALARM] ||
-             !!mChannelCounters[AUDIO_CHANNEL_TELEPHONY] ||
-             !!mChannelCounters[AUDIO_CHANNEL_PUBLICNOTIFICATION];
+      muted = !!mChannelCounters[AUDIO_CHANNEL_NOTIFICATION] ||
+              !!mChannelCounters[AUDIO_CHANNEL_ALARM] ||
+              !!mChannelCounters[AUDIO_CHANNEL_TELEPHONY] ||
+              !!mChannelCounters[AUDIO_CHANNEL_PUBLICNOTIFICATION];
 
     case AUDIO_CHANNEL_NOTIFICATION:
     case AUDIO_CHANNEL_ALARM:
     case AUDIO_CHANNEL_TELEPHONY:
-      return ChannelsActiveWithHigherPriorityThan(aType);
+      muted = ChannelsActiveWithHigherPriorityThan(aType);
 
     case AUDIO_CHANNEL_PUBLICNOTIFICATION:
+      break;
+
+    case AUDIO_CHANNEL_LAST:
+      MOZ_NOT_REACHED();
       return false;
   }
 
-  return false;
+  // Notification if needed.
+  if (!muted) {
+
+    // Calculating the most important unmuted channel:
+    AudioChannelType higher = AUDIO_CHANNEL_NORMAL;
+    for (int32_t type = AUDIO_CHANNEL_NORMAL;
+         type <= AUDIO_CHANNEL_PUBLICNOTIFICATION;
+         ++type) {
+      if (mChannelCounters[type]) {
+        higher = (AudioChannelType)type;
+      }
+    }
+
+    if (higher != mCurrentHigherChannel) {
+      mCurrentHigherChannel = higher;
+
+      nsString channelName;
+      channelName.AssignASCII(ChannelName(mCurrentHigherChannel));
+
+      nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
+      obs->NotifyObservers(nullptr, "audio-channel-changed", channelName.get());
+    }
+  }
+
+  return muted;
 }
 
 
 static PLDHashOperator
 NotifyEnumerator(nsHTMLMediaElement* aElement,
                  AudioChannelType aType, void* aData)
 {
   if (aElement) {
@@ -161,16 +216,23 @@ NotifyEnumerator(nsHTMLMediaElement* aEl
 
 void
 AudioChannelService::Notify()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   // Notify any media element for the main process.
   mMediaElements.EnumerateRead(NotifyEnumerator, nullptr);
+
+  // Notify for the child processes.
+  nsTArray<ContentParent*> children;
+  ContentParent::GetAll(children);
+  for (uint32_t i = 0; i < children.Length(); i++) {
+    unused << children[i]->SendAudioChannelNotify();
+  }
 }
 
 bool
 AudioChannelService::ChannelsActiveWithHigherPriorityThan(AudioChannelType aType)
 {
   for (int i = AUDIO_CHANNEL_PUBLICNOTIFICATION;
        i != AUDIO_CHANNEL_CONTENT; --i) {
     if (i == aType) {
@@ -179,8 +241,35 @@ AudioChannelService::ChannelsActiveWithH
 
     if (mChannelCounters[i]) {
       return true;
     }
   }
 
   return false;
 }
+
+const char*
+AudioChannelService::ChannelName(AudioChannelType aType)
+{
+  static struct {
+    int32_t type;
+    const char* value;
+  } ChannelNameTable[] = {
+    { AUDIO_CHANNEL_NORMAL,             "normal" },
+    { AUDIO_CHANNEL_CONTENT,            "normal" },
+    { AUDIO_CHANNEL_NOTIFICATION,       "notification" },
+    { AUDIO_CHANNEL_ALARM,              "alarm" },
+    { AUDIO_CHANNEL_TELEPHONY,          "telephony" },
+    { AUDIO_CHANNEL_PUBLICNOTIFICATION, "publicnotification" },
+    { -1,                               "unknown" }
+  };
+
+  for (int i = AUDIO_CHANNEL_NORMAL; ; ++i) {
+    if (ChannelNameTable[i].type == aType ||
+        ChannelNameTable[i].type == -1) {
+      return ChannelNameTable[i].value;
+    }
+  }
+
+  NS_NOTREACHED("Execution should not reach here!");
+  return nullptr;
+}
--- a/dom/audiochannel/AudioChannelService.h
+++ b/dom/audiochannel/AudioChannelService.h
@@ -32,39 +32,52 @@ public:
    * Shutdown the singleton.
    */
   static void Shutdown();
 
   /**
    * Any MediaElement that starts playing should register itself to
    * this service, sharing the AudioChannelType.
    */
-  void RegisterMediaElement(nsHTMLMediaElement* aMediaElement,
-                            AudioChannelType aType);
+  virtual void RegisterMediaElement(nsHTMLMediaElement* aMediaElement,
+                                    AudioChannelType aType);
 
   /**
    * Any MediaElement that stops playing should unregister itself to
    * this service.
    */
-  void UnregisterMediaElement(nsHTMLMediaElement* aMediaElement);
+  virtual void UnregisterMediaElement(nsHTMLMediaElement* aMediaElement);
 
   /**
    * Return true if this type should be muted.
    */
   virtual bool GetMuted(AudioChannelType aType, bool aElementHidden);
 
+protected:
   void Notify();
 
-protected:
+  /* Register/Unregister IPC types: */
+  void RegisterType(AudioChannelType aType);
+  void UnregisterType(AudioChannelType aType);
+
   AudioChannelService();
   virtual ~AudioChannelService();
 
   bool ChannelsActiveWithHigherPriorityThan(AudioChannelType aType);
 
+  const char* ChannelName(AudioChannelType aType);
+
   nsDataHashtable< nsPtrHashKey<nsHTMLMediaElement>, AudioChannelType > mMediaElements;
 
   int32_t* mChannelCounters;
+
+  AudioChannelType mCurrentHigherChannel;
+
+  // This is needed for IPC comunication between
+  // AudioChannelServiceChild and this class.
+  friend class ContentParent;
+  friend class ContentChild;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif
new file mode 100644
--- /dev/null
+++ b/dom/audiochannel/AudioChannelServiceChild.cpp
@@ -0,0 +1,103 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* 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/. */
+
+#include "AudioChannelServiceChild.h"
+
+#include "base/basictypes.h"
+
+#include "mozilla/Services.h"
+#include "mozilla/StaticPtr.h"
+#include "mozilla/unused.h"
+#include "mozilla/Util.h"
+
+#include "mozilla/dom/ContentChild.h"
+
+#include "base/basictypes.h"
+
+#include "nsThreadUtils.h"
+
+using namespace mozilla;
+using namespace mozilla::dom;
+
+StaticRefPtr<AudioChannelServiceChild> gAudioChannelServiceChild;
+
+// static
+AudioChannelService*
+AudioChannelServiceChild::GetAudioChannelService()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  // If we already exist, exit early
+  if (gAudioChannelServiceChild) {
+    return gAudioChannelServiceChild;
+  }
+
+  // Create new instance, register, return
+  nsRefPtr<AudioChannelServiceChild> service = new AudioChannelServiceChild();
+  NS_ENSURE_TRUE(service, nullptr);
+
+  gAudioChannelServiceChild = service;
+  return gAudioChannelServiceChild;
+}
+
+void
+AudioChannelServiceChild::Shutdown()
+{
+  if (gAudioChannelServiceChild) {
+    delete gAudioChannelServiceChild;
+    gAudioChannelServiceChild = nullptr;
+  }
+}
+
+AudioChannelServiceChild::AudioChannelServiceChild()
+{
+}
+
+AudioChannelServiceChild::~AudioChannelServiceChild()
+{
+}
+
+bool
+AudioChannelServiceChild::GetMuted(AudioChannelType aType, bool aMozHidden)
+{
+  ContentChild *cc = ContentChild::GetSingleton();
+  bool muted = false;
+
+  if (cc) {
+    cc->SendAudioChannelGetMuted(aType, aMozHidden, &muted);
+  }
+
+  return muted;
+}
+
+void
+AudioChannelServiceChild::RegisterMediaElement(nsHTMLMediaElement* aMediaElement,
+                                               AudioChannelType aType)
+{
+  AudioChannelService::RegisterMediaElement(aMediaElement, aType);
+
+  ContentChild *cc = ContentChild::GetSingleton();
+  if (cc) {
+    cc->SendAudioChannelRegisterType(aType);
+  }
+}
+
+void
+AudioChannelServiceChild::UnregisterMediaElement(nsHTMLMediaElement* aMediaElement)
+{
+  AudioChannelType type;
+  if (!mMediaElements.Get(aMediaElement, &type)) {
+    return;
+  }
+
+  AudioChannelService::UnregisterMediaElement(aMediaElement);
+
+  ContentChild *cc = ContentChild::GetSingleton();
+  if (cc) {
+    cc->SendAudioChannelUnregisterType(type);
+  }
+}
+
new file mode 100644
--- /dev/null
+++ b/dom/audiochannel/AudioChannelServiceChild.h
@@ -0,0 +1,51 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* 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/. */
+
+#ifndef mozilla_dom_audiochannelservicechild_h__
+#define mozilla_dom_audiochannelservicechild_h__
+
+#include "nsAutoPtr.h"
+#include "nsISupports.h"
+
+#include "AudioChannelService.h"
+#include "AudioChannelCommon.h"
+#include "nsHTMLMediaElement.h"
+
+namespace mozilla {
+namespace dom {
+
+class AudioChannelServiceChild : public AudioChannelService
+{
+public:
+
+  /**
+   * Returns the AudioChannelServce singleton. Only to be called from main thread.
+   * @return NS_OK on proper assignment, NS_ERROR_FAILURE otherwise.
+   */
+  static AudioChannelService*
+  GetAudioChannelService();
+
+  static void Shutdown();
+
+  virtual void RegisterMediaElement(nsHTMLMediaElement* aMediaElement,
+                                    AudioChannelType aType);
+  virtual void UnregisterMediaElement(nsHTMLMediaElement* aMediaElement);
+
+  /**
+   * Return true if this type + this mozHidden should be muted.
+   */
+  virtual bool GetMuted(AudioChannelType aType, bool aMozHidden);
+
+protected:
+  AudioChannelServiceChild();
+  virtual ~AudioChannelServiceChild();
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif
+
--- a/dom/audiochannel/Makefile.in
+++ b/dom/audiochannel/Makefile.in
@@ -27,18 +27,20 @@ FORCE_STATIC_LIB = 1
 EXPORT_LIBRARY = 1
 FAIL_ON_WARNINGS := 1
 
 EXPORTS_NAMESPACES = \
   mozilla/dom \
   $(NULL)
 
 EXPORTS = AudioChannelService.h \
+          AudioChannelServiceChild.h \
           AudioChannelCommon.h
 
 CPPSRCS += \
   AudioChannelService.cpp \
+  AudioChannelServiceChild.cpp \
   $(NULL)
 
 include $(topsrcdir)/config/config.mk
 include $(topsrcdir)/ipc/chromium/chromium-config.mk
 include $(topsrcdir)/config/rules.mk
 
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -93,16 +93,17 @@
 #include "nsIRemoteBlob.h"
 #include "ProcessUtils.h"
 #include "StructuredCloneUtils.h"
 #include "URIUtils.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsContentUtils.h"
 #include "nsIPrincipal.h"
 #include "nsDeviceStorage.h"
+#include "AudioChannelService.h"
 
 using namespace base;
 using namespace mozilla::docshell;
 using namespace mozilla::dom::bluetooth;
 using namespace mozilla::dom::devicestorage;
 using namespace mozilla::dom::sms;
 using namespace mozilla::dom::indexedDB;
 using namespace mozilla::hal_sandbox;
@@ -427,16 +428,27 @@ ContentChild::RecvPMemoryReportRequestCo
       r->CollectReports(cb, wrappedReports);
     }
 
     child->Send__delete__(child, reports);
     return true;
 }
 
 bool
+ContentChild::RecvAudioChannelNotify()
+{
+    nsRefPtr<AudioChannelService> service =
+        AudioChannelService::GetAudioChannelService();
+    if (service) {
+        service->Notify();
+    }
+    return true;
+}
+
+bool
 ContentChild::DeallocPMemoryReportRequest(PMemoryReportRequestChild* actor)
 {
     delete actor;
     return true;
 }
 
 bool
 ContentChild::RecvDumpMemoryReportsToFile(const nsString& aIdentifier,
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -107,16 +107,19 @@ public:
 
     virtual bool
     DeallocPMemoryReportRequest(PMemoryReportRequestChild* actor);
 
     virtual bool
     RecvPMemoryReportRequestConstructor(PMemoryReportRequestChild* child);
 
     virtual bool
+    RecvAudioChannelNotify();
+
+    virtual bool
     RecvDumpMemoryReportsToFile(const nsString& aIdentifier,
                                 const bool& aMinimizeMemoryUsage,
                                 const bool& aDumpChildProcesses);
     virtual bool
     RecvDumpGCAndCCLogsToFile(const nsString& aIdentifier,
                               const bool& aDumpChildProcesses);
 
     virtual PTestShellChild* AllocPTestShell();
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -11,16 +11,17 @@
 #if defined(ANDROID) || defined(LINUX)
 # include <sys/time.h>
 # include <sys/resource.h>
 #endif
 
 #include "chrome/common/process_watcher.h"
 
 #include "AppProcessPermissions.h"
+#include "AudioChannelService.h"
 #include "CrashReporterParent.h"
 #include "IHistory.h"
 #include "IDBFactory.h"
 #include "IndexedDBParent.h"
 #include "IndexedDatabaseManager.h"
 #include "mozIApplication.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/dom/ExternalHelperAppParent.h"
@@ -1006,16 +1007,52 @@ ContentParent::RecvFirstIdle()
     // When the ContentChild goes idle, it sends us a FirstIdle message
     // which we use as a good time to prelaunch another process. If we
     // prelaunch any sooner than this, then we'll be competing with the
     // child process and slowing it down.
     ScheduleDelayedPreallocateAppProcess();
     return true;
 }
 
+bool
+ContentParent::RecvAudioChannelGetMuted(const AudioChannelType& aType,
+                                        const bool& aMozHidden,
+                                        bool* aValue)
+{
+    nsRefPtr<AudioChannelService> service =
+        AudioChannelService::GetAudioChannelService();
+    *aValue = false;
+    if (service) {
+        *aValue = service->GetMuted(aType, aMozHidden);
+    }
+    return true;
+}
+
+bool
+ContentParent::RecvAudioChannelRegisterType(const AudioChannelType& aType)
+{
+    nsRefPtr<AudioChannelService> service =
+        AudioChannelService::GetAudioChannelService();
+    if (service) {
+        service->RegisterType(aType);
+    }
+    return true;
+}
+
+bool
+ContentParent::RecvAudioChannelUnregisterType(const AudioChannelType& aType)
+{
+    nsRefPtr<AudioChannelService> service =
+        AudioChannelService::GetAudioChannelService();
+    if (service) {
+        service->UnregisterType(aType);
+    }
+    return true;
+}
+
 NS_IMPL_THREADSAFE_ISUPPORTS3(ContentParent,
                               nsIObserver,
                               nsIThreadObserver,
                               nsIDOMGeoPositionCallback)
 
 NS_IMETHODIMP
 ContentParent::Observe(nsISupports* aSubject,
                        const char* aTopic,
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -256,29 +256,29 @@ private:
     virtual bool RecvStartVisitedQuery(const URIParams& uri);
 
     virtual bool RecvVisitURI(const URIParams& uri,
                               const OptionalURIParams& referrer,
                               const uint32_t& flags);
 
     virtual bool RecvSetURITitle(const URIParams& uri,
                                  const nsString& title);
-    
+
     virtual bool RecvShowFilePicker(const int16_t& mode,
                                     const int16_t& selectedType,
                                     const bool& addToRecentDocs,
                                     const nsString& title,
                                     const nsString& defaultFile,
                                     const nsString& defaultExtension,
                                     const InfallibleTArray<nsString>& filters,
                                     const InfallibleTArray<nsString>& filterNames,
                                     InfallibleTArray<nsString>* files,
                                     int16_t* retValue,
                                     nsresult* result);
- 
+
     virtual bool RecvShowAlertNotification(const nsString& aImageUrl, const nsString& aTitle,
                                            const nsString& aText, const bool& aTextClickable,
                                            const nsString& aCookie, const nsString& aName);
 
     virtual bool RecvLoadURIExternal(const URIParams& uri);
 
     virtual bool RecvSyncMessage(const nsString& aMsg,
                                  const ClonedMessageData& aData,
@@ -297,16 +297,23 @@ private:
                                  const uint32_t& aColNumber,
                                  const uint32_t& aFlags,
                                  const nsCString& aCategory);
 
     virtual bool RecvPrivateDocShellsExist(const bool& aExist);
 
     virtual bool RecvFirstIdle();
 
+    virtual bool RecvAudioChannelGetMuted(const AudioChannelType& aType,
+                                          const bool& aMozHidden,
+                                          bool* aValue);
+
+    virtual bool RecvAudioChannelRegisterType(const AudioChannelType& aType);
+    virtual bool RecvAudioChannelUnregisterType(const AudioChannelType& aType);
+
     virtual void ProcessingError(Result what) MOZ_OVERRIDE;
 
     GeckoChildProcessHost* mSubprocess;
     ChildOSPrivileges mOSPrivileges;
 
     uint64_t mChildID;
     int32_t mGeolocationWatchID;
     int mRunToCompletionDepth;
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -33,16 +33,17 @@ using GeoPosition;
 using PrefTuple;
 
 using ChromePackage;
 using ResourceMapping;
 using OverrideMapping;
 using IPC::Permission;
 using mozilla::null_t;
 using mozilla::void_t;
+using mozilla::dom::AudioChannelType;
 using mozilla::dom::NativeThreadId;
 using mozilla::layout::ScrollingBehavior;
 using gfxIntSize;
 
 namespace mozilla {
 namespace dom {
 
 // Data required to clone an existing DOMStorageImpl in the parent
@@ -260,16 +261,21 @@ both:
     async PBrowser(IPCTabContext context, uint32_t chromeFlags);
 
     async PBlob(BlobConstructorParams params);
 
 child:
     PMemoryReportRequest();
 
     /**
+     * Notify the AudioChannelService in the child processes.
+     */
+    async AudioChannelNotify();
+
+    /**
      * Dump the contents of about:memory to a file in our temp directory.
      *
      * For documentation on the args, see
      * MemoryInfoDumper::dumpMemoryReportsToFile.
      */
     async DumpMemoryReportsToFile(nsString identifier,
                                   bool minimizeMemoryUsage,
                                   bool dumpChildProcesses);
@@ -419,14 +425,21 @@ parent:
         returns (bool showPassword);
 
     // Notify the parent of the presence or absence of private docshells
     PrivateDocShellsExist(bool aExist);
 
     // Tell the parent that the child has gone idle for the first time
     async FirstIdle();
 
+    // Get Muted from the main AudioChannelService.
+    sync AudioChannelGetMuted(AudioChannelType aType, bool aMozHidden)
+        returns (bool value);
+
+    async AudioChannelRegisterType(AudioChannelType aType);
+    async AudioChannelUnregisterType(AudioChannelType aType);
+
 both:
      AsyncMessage(nsString aMessage, ClonedMessageData aData);
 };
 
 }
 }
--- a/dom/ipc/TabMessageUtils.h
+++ b/dom/ipc/TabMessageUtils.h
@@ -1,16 +1,17 @@
 /* -*- 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/. */
 
 #ifndef TABMESSAGE_UTILS_H
 #define TABMESSAGE_UTILS_H
 
+#include "AudioChannelCommon.h"
 #include "ipc/IPCMessageUtils.h"
 #include "nsIDOMEvent.h"
 #include "nsCOMPtr.h"
 
 #ifdef MOZ_CRASHREPORTER
 #include "nsExceptionHandler.h"
 #endif
 
@@ -51,12 +52,19 @@ struct ParamTraits<mozilla::dom::RemoteD
     return mozilla::dom::ReadRemoteEvent(aMsg, aIter, aResult);
   }
 
   static void Log(const paramType& aParam, std::wstring* aLog)
   {
   }
 };
 
+template <>
+struct ParamTraits<mozilla::dom::AudioChannelType>
+  : public EnumSerializer<mozilla::dom::AudioChannelType,
+                          mozilla::dom::AUDIO_CHANNEL_NORMAL,
+                          mozilla::dom::AUDIO_CHANNEL_LAST>
+{ };
+
 }
 
 
 #endif
--- a/dom/plugins/test/mochitest/Makefile.in
+++ b/dom/plugins/test/mochitest/Makefile.in
@@ -94,21 +94,26 @@ MOCHITEST_FILES += \
 # test_positioning.html \ disabled due to oddness, perhaps scrolling of the
 # mochitest window?
 endif
 
 MOCHITEST_CHROME_FILES = \
   utils.js \
   test_clear_site_data.html \
   test_npruntime.xul   \
-  test_privatemode.xul \
   test_wmode.xul \
   test_bug479979.xul \
   $(NULL)
 
+ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
+MOCHITEST_CHROME_FILES += \
+  test_privatemode.xul \
+  $(NULL)
+endif
+
 ifneq ($(MOZ_WIDGET_TOOLKIT),cocoa)
 MOCHITEST_FILES += \
   test_instance_re-parent-windowed.html \
   test_visibility.html \
   $(NULL)
 
 ifneq ($(OS_ARCH),WINNT)
 MOCHITEST_CHROME_FILES += \
--- a/dom/tests/browser/Makefile.in
+++ b/dom/tests/browser/Makefile.in
@@ -12,22 +12,27 @@ include $(DEPTH)/config/autoconf.mk
 
 MOCHITEST_BROWSER_FILES := \
   browser_focus_steal_from_chrome.js \
   browser_focus_steal_from_chrome_during_mousedown.js \
   browser_autofocus_background.js \
   browser_ConsoleAPITests.js \
   test-console-api.html \
   browser_ConsoleStorageAPITests.js \
-  browser_ConsoleStoragePBTest.js \
   browser_autofocus_preference.js \
   browser_bug396843.js \
   browser_xhr_sandbox.js \
   $(NULL)
 
+ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
+MOCHITEST_BROWSER_FILES += \
+  browser_ConsoleStoragePBTest.js \
+  $(NULL)
+endif
+
 ifeq (Linux,$(OS_ARCH))
 MOCHITEST_BROWSER_FILES += \
   browser_webapps_permissions.js \
   test-webapp.webapp \
   test-webapp-reinstall.webapp \
   test-webapp-original.webapp \
   test-webapps-permissions.html \
   $(NULL)
--- a/dom/tests/mochitest/localstorage/Makefile.in
+++ b/dom/tests/mochitest/localstorage/Makefile.in
@@ -34,34 +34,39 @@ MOCHITEST_FILES	= \
     test_bug746272-1.html \
     test_bug746272-2.html \
     test_cookieBlock.html \
     test_cookieSession-phase1.html \
     test_cookieSession-phase2.html \
     test_embededNulls.html \
     test_keySync.html \
     test_localStorageBase.html \
-    test_localStorageBasePrivateBrowsing.html \
     test_localStorageBaseSessionOnly.html \
     test_localStorageCookieSettings.html \
     test_localStorageEnablePref.html \
     test_localStorageOriginsEquals.html \
     test_localStorageOriginsDiff.html \
     test_localStorageOriginsPortDiffs.html \
     test_localStorageOriginsDomainDiffs.html \
     test_localStorageOriginsSchemaDiffs.html \
     test_localStorageReplace.html \
     test_localStorageQuota.html \
-    test_localStorageQuotaPrivateBrowsing.html \
     test_localStorageQuotaSessionOnly.html \
     test_localStorageQuotaSessionOnly2.html \
     test_localStorageKeyOrder.html \
     test_storageConstructor.html \
     $(NULL)
 
+ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
+MOCHITEST_FILES += \
+    test_localStorageBasePrivateBrowsing.html \
+    test_localStorageQuotaPrivateBrowsing.html \
+    $(NULL)
+endif
+
 MOCHITEST_CHROME_FILES = \
     test_localStorageFromChrome.xhtml \
     test_app_uninstall.html \
     test_clear_browser_data.html \
     frame_clear_browser_data.html \
     $(NULL)
 
 include $(topsrcdir)/config/rules.mk
--- a/extensions/cookie/test/unit/xpcshell.ini
+++ b/extensions/cookie/test/unit/xpcshell.ini
@@ -1,13 +1,14 @@
 [DEFAULT]
 head = head_cookies.js
 tail = 
 
 [test_bug468700.js]
+skip-if = perwindowprivatebrowsing
 [test_bug526789.js]
 [test_bug650522.js]
 [test_bug667087.js]
 [test_cookies_async_failure.js]
 [test_cookies_persistence.js]
 [test_cookies_privatebrowsing.js]
 [test_cookies_profile_close.js]
 [test_cookies_read.js]
--- a/layout/forms/test/Makefile.in
+++ b/layout/forms/test/Makefile.in
@@ -42,15 +42,20 @@ MOCHITEST_FILES =	test_bug231389.html \
 		test_bug620936.html \
 		test_bug595310.html \
 		test_bug644542.html \
 		test_bug672810.html \
 		test_bug704049.html \
 		$(NULL)
 
 MOCHITEST_CHROME_FILES = \
-		test_bug536567.html \
 		     bug536567_subframe.html \
 		test_bug665540.html \
 		     bug665540_window.xul \
 		$(NULL)
 
+ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
+MOCHITEST_CHROME_FILES += \
+                test_bug536567.html \
+                $(NULL)
+endif
+
 include $(topsrcdir)/config/rules.mk
--- a/security/manager/ssl/tests/mochitest/stricttransportsecurity/Makefile.in
+++ b/security/manager/ssl/tests/mochitest/stricttransportsecurity/Makefile.in
@@ -14,12 +14,17 @@ MOCHITEST_FILES = \
 	plain_bootstrap.html \
 	plain_bootstrap.html^headers^ \
 	subdom_bootstrap.html \
 	subdom_bootstrap.html^headers^ \
 	nosts_bootstrap.html \
 	nosts_bootstrap.html^headers^ \
 	verify.sjs \
 	test_stricttransportsecurity.html \
-	test_sts_privatebrowsing.html \
 	$(NULL)
 
+ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
+MOCHITEST_FILES += \
+        test_sts_privatebrowsing.html \
+        $(NULL)
+endif
+
 include $(topsrcdir)/config/rules.mk
--- a/security/manager/ssl/tests/unit/xpcshell.ini
+++ b/security/manager/ssl/tests/unit/xpcshell.ini
@@ -8,10 +8,12 @@ tail =
 skip-if = os == "android"
 [test_hash_algorithms.js]
 # Bug 676972: test hangs consistently on Android
 skip-if = os == "android"
 [test_hmac.js]
 # Bug 676972: test hangs consistently on Android
 skip-if = os == "android"
 [test_bug627234.js]
+skip-if = perwindowprivatebrowsing
 [test_sts_preloadlist.js]
+skip-if = perwindowprivatebrowsing
 [test_sts_preloadlist_selfdestruct.js]
--- a/toolkit/components/passwordmgr/test/Makefile.in
+++ b/toolkit/components/passwordmgr/test/Makefile.in
@@ -48,17 +48,16 @@ MOCHITEST_FILES = \
     test_bug_776171.html \
     test_master_password.html \
     test_master_password_cleanup.html \
     test_maxforms_1.html \
     test_maxforms_2.html \
     test_maxforms_3.html \
     test_notifications.html \
     test_notifications_popup.html \
-    test_privbrowsing.html \
     test_prompt_async.html \
     test_xhr.html \
     test_xml_load.html \
     test_zzz_finish.html \
     pwmgr_common.js \
     prompt_common.js \
     notification_common.js \
     authenticate.sjs \
@@ -78,19 +77,25 @@ MOCHITEST_FILES = \
     subtst_notifications_8.html \
     subtst_notifications_9.html \
     subtst_notifications_10.html \
     subtst_notifications_11.html \
     subtst_notifications_11_popup.html \
     subtst_prompt_async.html \
     $(NULL)
 
+ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
+MOCHITEST_FILES += \
+    test_privbrowsing.html \
+    $(NULL)
+
 ifneq ($(OS_TARGET),Linux)
 MOCHITEST_FILES += \
     test_prompt.html \
     $(NULL)
 endif
+endif
 
 # This test doesn't pass because we can't ensure a cross-platform
 # event that occurs between DOMContentLoaded and Pageload
 # test_bug_221634.html
 
 include $(topsrcdir)/config/rules.mk
--- a/toolkit/components/places/tests/Makefile.in
+++ b/toolkit/components/places/tests/Makefile.in
@@ -28,18 +28,23 @@ XPCSHELL_TESTS = \
 # Files in the main "tests" folder.
 XPCSHELL_TESTS_COMMON = \
   head_common.js \
   $(NULL)
 
 # Simple MochiTests
 MOCHITEST_FILES = \
 	mochitest/test_bug_411966.html \
+	$(NULL)
+
+ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
+MOCHITEST_FILES += \
 	mochitest/test_bug_461710.html \
 	$(NULL)
+endif
 
 DIRS = \
 	chrome \
 	mochitest/bug_411966 \
 	mochitest/bug_461710 \
 	browser \
 	$(NULL)
 
--- a/toolkit/components/places/tests/browser/Makefile.in
+++ b/toolkit/components/places/tests/browser/Makefile.in
@@ -17,28 +17,31 @@ MOCHITEST_BROWSER_FILES = \
 	browser_bug646422.js \
 	browser_bug680727.js \
 	browser_colorAnalyzer.js \
 	browser_favicon_privatebrowsing.js \
 	browser_notfound.js \
 	browser_redirect.js \
 	browser_visituri.js \
 	browser_visituri_nohistory.js \
-	browser_visituri_privatebrowsing.js \
 	browser_settitle.js \
 	colorAnalyzer/category-discover.png \
 	colorAnalyzer/dictionaryGeneric-16.png \
 	colorAnalyzer/extensionGeneric-16.png \
 	colorAnalyzer/localeGeneric.png \
 	$(NULL)
 
 ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
 MOCHITEST_BROWSER_FILES += \
 	browser_bug248970.js \
 	$(NULL)
+else
+MOCHITEST_BROWSER_FILES += \
+	browser_visituri_privatebrowsing.js \
+	$(NULL)
 endif
 
 # These are files that need to be loaded via the HTTP proxy server
 # Access them through http://example.com/
 MOCHITEST_FILES = \
 	bug_399606/399606-httprefresh.html \
 	bug_399606/399606-location.reload.html \
 	bug_399606/399606-location.replace.html \
--- a/toolkit/components/places/tests/favicons/xpcshell.ini
+++ b/toolkit/components/places/tests/favicons/xpcshell.ini
@@ -11,11 +11,13 @@ fail-if = os == "android"
 fail-if = os == "android"
 [test_getFaviconDataForPage.js]
 [test_getFaviconURLForPage.js]
 [test_moz-anno_favicon_mime_type.js]
 [test_query_result_favicon_changed_on_child.js]
 [test_replaceFaviconData.js]
 [test_replaceFaviconDataFromDataURL.js]
 [test_setAndFetchFaviconForPage.js]
+skip-if = perwindowprivatebrowsing
 [test_setAndFetchFaviconForPage_failures.js]
 # Bug 676989: test fails consistently on Android
 fail-if = os == "android"
+skip-if = perwindowprivatebrowsing
--- a/toolkit/components/satchel/test/Makefile.in
+++ b/toolkit/components/satchel/test/Makefile.in
@@ -20,16 +20,21 @@ XPCSHELL_TESTS = \
 MOCHITEST_FILES = \
 		test_bug_511615.html \
 		test_bug_787624.html \
 		test_form_autocomplete.html \
 		test_form_autocomplete_with_list.html \
 		test_form_submission.html \
 		test_form_submission_cap.html \
 		test_form_submission_cap2.html \
-		test_privbrowsing.html \
 		satchel_common.js \
 		subtst_form_submission_1.html \
 		subtst_privbrowsing.html \
 		$(NULL)
 
+ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
+MOCHITEST_FILES += \
+                test_privbrowsing.html \
+                $(NULL)
+endif
+
 include $(topsrcdir)/config/rules.mk
 
--- a/toolkit/mozapps/update/test/unit/xpcshell.ini
+++ b/toolkit/mozapps/update/test/unit/xpcshell.ini
@@ -22,10 +22,11 @@ tail =
 [include:xpcshell_updater.ini]
 skip-if = os == 'android'
 ; Platform-specific updater tests
 [include:xpcshell_updater_windows.ini]
 run-if = os == 'win'
 [include:xpcshell_updater_xp_unix.ini]
 run-if = os == 'linux' || os == 'mac' || os == 'sunos'
 [test_bug497578.js]
+skip-if = perwindowprivatebrowsing
 [test_bug595059.js]
 [test_bug794211.js]