Bug 987064 - Remove AudioChannelType. r=roc, r=mchen, r=bent
authorAndrea Marchesini <amarchesini@mozilla.com>
Thu, 10 Apr 2014 18:39:20 +0100
changeset 196786 f31e8f1f24b94ef983174f68ff8cb07bc6fc0c9e
parent 196785 86a669ce515af21bd13a09d8fc17dbf2b69231d5
child 196787 261fbd3fd655782abe2a72c8e7ab5ba482dfcaa8
push id3624
push userasasaki@mozilla.com
push dateMon, 09 Jun 2014 21:49:01 +0000
treeherdermozilla-beta@b1a5da15899a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc, mchen, bent
bugs987064
milestone31.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
Bug 987064 - Remove AudioChannelType. r=roc, r=mchen, r=bent
content/base/src/nsAttrValue.h
content/html/content/public/HTMLMediaElement.h
content/html/content/src/HTMLMediaElement.cpp
content/media/AudioStream.cpp
content/media/AudioStream.h
content/media/MediaDecoder.cpp
content/media/MediaDecoder.h
content/media/MediaDecoderStateMachine.cpp
content/media/MediaStreamGraph.cpp
content/media/omx/MediaOmxDecoder.cpp
content/media/omx/MediaOmxReader.cpp
content/media/omx/MediaOmxReader.h
content/media/webaudio/AudioDestinationNode.cpp
content/svg/content/src/SVGAttrValueWrapper.h
dom/audiochannel/AudioChannelAgent.cpp
dom/audiochannel/AudioChannelCommon.h
dom/audiochannel/AudioChannelService.cpp
dom/audiochannel/AudioChannelService.h
dom/audiochannel/AudioChannelServiceChild.cpp
dom/audiochannel/AudioChannelServiceChild.h
dom/audiochannel/tests/TestAudioChannelService.cpp
dom/audiochannel/tests/moz.build
dom/camera/DOMCameraControl.cpp
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/PContent.ipdl
dom/ipc/TabMessageUtils.h
dom/system/gonk/AudioChannelManager.cpp
dom/system/gonk/AudioChannelManager.h
dom/system/gonk/AudioManager.cpp
--- a/content/base/src/nsAttrValue.h
+++ b/content/base/src/nsAttrValue.h
@@ -7,17 +7,17 @@
  * A struct that represents the value (type and actual data) of an
  * attribute.
  */
 
 #ifndef nsAttrValue_h___
 #define nsAttrValue_h___
 
 #include "nscore.h"
-#include "nsString.h"
+#include "nsStringGlue.h"
 #include "nsStringBuffer.h"
 #include "nsColor.h"
 #include "nsCaseTreatment.h"
 #include "nsMargin.h"
 #include "nsCOMPtr.h"
 #include "SVGAttrValueWrapper.h"
 #include "nsTArrayForwardDeclare.h"
 #include "nsIAtom.h"
--- a/content/html/content/public/HTMLMediaElement.h
+++ b/content/html/content/public/HTMLMediaElement.h
@@ -491,17 +491,21 @@ public:
   {
     return mAudioCaptured;
   }
 
   JSObject* MozGetMetadata(JSContext* aCx, ErrorResult& aRv);
 
   double MozFragmentEnd();
 
-  AudioChannel MozAudioChannelType() const;
+  AudioChannel MozAudioChannelType() const
+  {
+    return mAudioChannel;
+  }
+
   void SetMozAudioChannelType(AudioChannel aValue, ErrorResult& aRv);
 
   TextTrackList* TextTracks();
 
   already_AddRefed<TextTrack> AddTextTrack(TextTrackKind aKind,
                                            const nsAString& aLabel,
                                            const nsAString& aLanguage);
 
@@ -1117,18 +1121,18 @@ protected:
   CORSMode mCORSMode;
 
   // True if the media has an audio track
   bool mHasAudio;
 
   // True if the media's channel's download has been suspended.
   bool mDownloadSuspendedByCache;
 
-  // Audio Channel Type.
-  AudioChannelType mAudioChannelType;
+  // Audio Channel.
+  AudioChannel mAudioChannel;
 
   // The audio channel has been faded.
   bool mAudioChannelFaded;
 
   // Is this media element playing?
   bool mPlayingThroughTheAudioChannel;
 
   // An agent used to join audio channel service.
--- a/content/html/content/src/HTMLMediaElement.cpp
+++ b/content/html/content/src/HTMLMediaElement.cpp
@@ -1999,29 +1999,30 @@ HTMLMediaElement::HTMLMediaElement(alrea
     mHasPlayedOrSeeked(false),
     mHasSelfReference(false),
     mShuttingDown(false),
     mSuspendedForPreloadNone(false),
     mMediaSecurityVerified(false),
     mCORSMode(CORS_NONE),
     mHasAudio(false),
     mDownloadSuspendedByCache(false),
-    mAudioChannelType(AUDIO_CHANNEL_NORMAL),
     mAudioChannelFaded(false),
     mPlayingThroughTheAudioChannel(false)
 {
 #ifdef PR_LOGGING
   if (!gMediaElementLog) {
     gMediaElementLog = PR_NewLogModule("nsMediaElement");
   }
   if (!gMediaElementEventsLog) {
     gMediaElementEventsLog = PR_NewLogModule("nsMediaElementEvents");
   }
 #endif
 
+  mAudioChannel = AudioChannelService::GetDefaultAudioChannel();
+
   mPaused.SetOuter(this);
 
   RegisterFreezableElement();
   NotifyOwnerDocumentActivityChanged();
 }
 
 HTMLMediaElement::~HTMLMediaElement()
 {
@@ -2277,53 +2278,44 @@ bool HTMLMediaElement::ParseAttribute(in
   static const nsAttrValue::EnumTable kPreloadTable[] = {
     { "",         HTMLMediaElement::PRELOAD_ATTR_EMPTY },
     { "none",     HTMLMediaElement::PRELOAD_ATTR_NONE },
     { "metadata", HTMLMediaElement::PRELOAD_ATTR_METADATA },
     { "auto",     HTMLMediaElement::PRELOAD_ATTR_AUTO },
     { 0 }
   };
 
-  // Mappings from 'mozaudiochannel' attribute strings to an enumeration.
-  static const nsAttrValue::EnumTable kMozAudioChannelAttributeTable[] = {
-    { "normal",             AUDIO_CHANNEL_NORMAL },
-    { "content",            AUDIO_CHANNEL_CONTENT },
-    { "notification",       AUDIO_CHANNEL_NOTIFICATION },
-    { "alarm",              AUDIO_CHANNEL_ALARM },
-    { "telephony",          AUDIO_CHANNEL_TELEPHONY },
-    { "ringer",             AUDIO_CHANNEL_RINGER },
-    { "publicnotification", AUDIO_CHANNEL_PUBLICNOTIFICATION },
-    { 0 }
-  };
-
   if (aNamespaceID == kNameSpaceID_None) {
     if (ParseImageAttribute(aAttribute, aValue, aResult)) {
       return true;
     }
     if (aAttribute == nsGkAtoms::crossorigin) {
       ParseCORSValue(aValue, aResult);
       return true;
     }
     if (aAttribute == nsGkAtoms::preload) {
       return aResult.ParseEnumValue(aValue, kPreloadTable, false);
     }
 
     if (aAttribute == nsGkAtoms::mozaudiochannel) {
-      bool parsed = aResult.ParseEnumValue(aValue, kMozAudioChannelAttributeTable, false,
-                                           &kMozAudioChannelAttributeTable[0]);
+      const nsAttrValue::EnumTable* table =
+        AudioChannelService::GetAudioChannelTable();
+      MOZ_ASSERT(table);
+
+      bool parsed = aResult.ParseEnumValue(aValue, table, false, &table[0]);
       if (!parsed) {
         return false;
       }
 
-      AudioChannelType audioChannelType = static_cast<AudioChannelType>(aResult.GetEnumValue());
-
-      if (audioChannelType != mAudioChannelType &&
+      AudioChannel audioChannel = static_cast<AudioChannel>(aResult.GetEnumValue());
+
+      if (audioChannel != mAudioChannel &&
           !mDecoder &&
           CheckAudioChannelPermissions(aValue)) {
-        mAudioChannelType = audioChannelType;
+        mAudioChannel = audioChannel;
       }
 
       return true;
     }
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
@@ -2599,17 +2591,17 @@ nsresult HTMLMediaElement::FinishDecoder
   mPendingEvents.Clear();
   // Set mDecoder now so if methods like GetCurrentSrc get called between
   // here and Load(), they work.
   mDecoder = aDecoder;
 
   // Tell the decoder about its MediaResource now so things like principals are
   // available immediately.
   mDecoder->SetResource(aStream);
-  mDecoder->SetAudioChannelType(mAudioChannelType);
+  aDecoder->SetAudioChannel(mAudioChannel);
   mDecoder->SetAudioCaptured(mAudioCaptured);
   mDecoder->SetVolume(mMuted ? 0.0 : mVolume);
   mDecoder->SetPreservesPitch(mPreservesPitch);
   mDecoder->SetPlaybackRate(mPlaybackRate);
 
   if (mPreloadAction == HTMLMediaElement::PRELOAD_METADATA) {
     mDecoder->SetMinimizePrerollUntilPlaybackStarts();
   }
@@ -3841,22 +3833,24 @@ void HTMLMediaElement::UpdateAudioChanne
     if (!mAudioChannelAgent) {
       nsresult rv;
       mAudioChannelAgent = do_CreateInstance("@mozilla.org/audiochannelagent;1", &rv);
       if (!mAudioChannelAgent) {
         return;
       }
       nsCOMPtr<nsIDOMHTMLVideoElement> video = do_QueryObject(this);
       // Use a weak ref so the audio channel agent can't leak |this|.
-      if (AUDIO_CHANNEL_NORMAL == mAudioChannelType && video) {
+      if (AudioChannel::Normal == mAudioChannel && video) {
         mAudioChannelAgent->InitWithVideo(OwnerDoc()->GetWindow(),
-                                          mAudioChannelType, this, true);
+                                          static_cast<int32_t>(mAudioChannel),
+                                          this, true);
       } else {
         mAudioChannelAgent->InitWithWeakCallback(OwnerDoc()->GetWindow(),
-                                                 mAudioChannelType, this);
+                                                 static_cast<int32_t>(mAudioChannel),
+                                                 this);
       }
       mAudioChannelAgent->SetVisibilityState(!OwnerDoc()->Hidden());
     }
 
     if (mPlayingThroughTheAudioChannel) {
       int32_t canPlay;
       mAudioChannelAgent->StartPlaying(&canPlay);
       CanPlayChanged(canPlay);
@@ -3927,43 +3921,16 @@ HTMLMediaElement::GetOrCreateTextTrackMa
 {
   if (!mTextTrackManager) {
     mTextTrackManager = new TextTrackManager(this);
     mTextTrackManager->AddListeners();
   }
   return mTextTrackManager;
 }
 
-AudioChannel
-HTMLMediaElement::MozAudioChannelType() const
-{
-  switch (mAudioChannelType) {
-    case AUDIO_CHANNEL_CONTENT:
-      return AudioChannel::Content;
-
-    case AUDIO_CHANNEL_NOTIFICATION:
-      return AudioChannel::Notification;
-
-    case AUDIO_CHANNEL_ALARM:
-      return AudioChannel::Alarm;
-
-    case AUDIO_CHANNEL_TELEPHONY:
-      return AudioChannel::Telephony;
-
-    case AUDIO_CHANNEL_RINGER:
-      return AudioChannel::Ringer;
-
-    case AUDIO_CHANNEL_PUBLICNOTIFICATION:
-      return AudioChannel::Publicnotification;
-
-    default:
-      return AudioChannelService::GetDefaultAudioChannel();
-  }
-}
-
 void
 HTMLMediaElement::SetMozAudioChannelType(AudioChannel aValue, ErrorResult& aRv)
 {
   nsString channel;
   channel.AssignASCII(AudioChannelValues::strings[uint32_t(aValue)].value,
                       AudioChannelValues::strings[uint32_t(aValue)].length);
   SetHTMLAttr(nsGkAtoms::mozaudiochannel, channel, aRv);
 }
--- a/content/media/AudioStream.cpp
+++ b/content/media/AudioStream.cpp
@@ -105,35 +105,35 @@ bool AudioStream::sCubebLatencyPrefSet;
 
 /*static*/ bool AudioStream::CubebLatencyPrefSet()
 {
   StaticMutexAutoLock lock(sMutex);
   return sCubebLatencyPrefSet;
 }
 
 #if defined(__ANDROID__) && defined(MOZ_B2G)
-static cubeb_stream_type ConvertChannelToCubebType(dom::AudioChannelType aType)
+static cubeb_stream_type ConvertChannelToCubebType(dom::AudioChannel aChannel)
 {
-  switch(aType) {
-    case dom::AUDIO_CHANNEL_NORMAL:
+  switch(aChannel) {
+    case dom::AudioChannel::Normal:
       return CUBEB_STREAM_TYPE_SYSTEM;
-    case dom::AUDIO_CHANNEL_CONTENT:
+    case dom::AudioChannel::Content:
       return CUBEB_STREAM_TYPE_MUSIC;
-    case dom::AUDIO_CHANNEL_NOTIFICATION:
+    case dom::AudioChannel::Notification:
       return CUBEB_STREAM_TYPE_NOTIFICATION;
-    case dom::AUDIO_CHANNEL_ALARM:
+    case dom::AudioChannel::Alarm:
       return CUBEB_STREAM_TYPE_ALARM;
-    case dom::AUDIO_CHANNEL_TELEPHONY:
+    case dom::AudioChannel::Telephony:
       return CUBEB_STREAM_TYPE_VOICE_CALL;
-    case dom::AUDIO_CHANNEL_RINGER:
+    case dom::AudioChannel::Ringer:
       return CUBEB_STREAM_TYPE_RING;
     // Currently Android openSLES library doesn't support FORCE_AUDIBLE yet.
-    case dom::AUDIO_CHANNEL_PUBLICNOTIFICATION:
+    case dom::AudioChannel::Publicnotification:
     default:
-      NS_ERROR("The value of AudioChannelType is invalid");
+      NS_ERROR("The value of AudioChannel is invalid");
       return CUBEB_STREAM_TYPE_MAX;
   }
 }
 #endif
 
 AudioStream::AudioStream()
   : mMonitor("AudioStream")
   , mInRate(0)
@@ -344,17 +344,17 @@ WriteDumpFile(FILE* aDumpFile, AudioStre
     SetUint16LE(output + i*2, int16_t(input[i]*32767.0f));
   }
   fwrite(output, 2, samples, aDumpFile);
   fflush(aDumpFile);
 }
 
 nsresult
 AudioStream::Init(int32_t aNumChannels, int32_t aRate,
-                  const dom::AudioChannelType aAudioChannelType,
+                  const dom::AudioChannel aAudioChannel,
                   LatencyRequest aLatencyRequest)
 {
   cubeb* cubebContext = GetCubebContext();
 
   if (!cubebContext || aNumChannels < 0 || aRate < 0) {
     return NS_ERROR_FAILURE;
   }
 
@@ -367,17 +367,17 @@ AudioStream::Init(int32_t aNumChannels, 
 
   mDumpFile = OpenDumpFile(this);
 
   cubeb_stream_params params;
   params.rate = aRate;
   params.channels = mOutChannels;
 #if defined(__ANDROID__)
 #if defined(MOZ_B2G)
-  params.stream_type = ConvertChannelToCubebType(aAudioChannelType);
+  params.stream_type = ConvertChannelToCubebType(aAudioChannel);
 #else
   params.stream_type = CUBEB_STREAM_TYPE_MUSIC;
 #endif
 
   if (params.stream_type == CUBEB_STREAM_TYPE_MAX) {
     return NS_ERROR_INVALID_ARG;
   }
 #endif
--- a/content/media/AudioStream.h
+++ b/content/media/AudioStream.h
@@ -2,21 +2,21 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* 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/. */
 #if !defined(AudioStream_h_)
 #define AudioStream_h_
 
 #include "AudioSampleFormat.h"
-#include "AudioChannelCommon.h"
 #include "nsAutoPtr.h"
 #include "nsAutoRef.h"
 #include "nsCOMPtr.h"
 #include "Latency.h"
+#include "mozilla/dom/AudioChannelBinding.h"
 #include "mozilla/StaticMutex.h"
 
 #include "cubeb/cubeb.h"
 
 template <>
 class nsAutoRefTraits<cubeb_stream> : public nsPointerRefTraits<cubeb_stream>
 {
 public:
@@ -193,17 +193,17 @@ public:
     HighLatency,
     LowLatency
   };
 
   // Initialize the audio stream. aNumChannels is the number of audio
   // channels (1 for mono, 2 for stereo, etc) and aRate is the sample rate
   // (22050Hz, 44100Hz, etc).
   nsresult Init(int32_t aNumChannels, int32_t aRate,
-                const dom::AudioChannelType aAudioStreamType,
+                const dom::AudioChannel aAudioStreamChannel,
                 LatencyRequest aLatencyRequest);
 
   // Closes the stream. All future use of the stream is an error.
   void Shutdown();
 
   // Write audio data to the audio hardware.  aBuf is an array of AudioDataValues
   // AudioDataValue of length aFrames*mChannels.  If aFrames is larger
   // than the result of Available(), the write will block until sufficient
--- a/content/media/MediaDecoder.cpp
+++ b/content/media/MediaDecoder.cpp
@@ -18,16 +18,17 @@
 #include "nsError.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/StaticPtr.h"
 #include "nsIMemoryReporter.h"
 #include "nsComponentManagerUtils.h"
 #include "nsITimer.h"
 #include <algorithm>
 #include "MediaShutdownManager.h"
+#include "AudioChannelService.h"
 
 #ifdef MOZ_WMF
 #include "WMFDecoder.h"
 #endif
 
 using namespace mozilla::layers;
 using namespace mozilla::dom;
 
@@ -422,27 +423,28 @@ MediaDecoder::MediaDecoder() :
   mNextState(PLAY_STATE_PAUSED),
   mCalledResourceLoaded(false),
   mIgnoreProgressData(false),
   mInfiniteStream(false),
   mOwner(nullptr),
   mPinnedForSeek(false),
   mShuttingDown(false),
   mPausedForPlaybackRateNull(false),
-  mAudioChannelType(AUDIO_CHANNEL_NORMAL),
   mMinimizePreroll(false)
 {
   MOZ_COUNT_CTOR(MediaDecoder);
   MOZ_ASSERT(NS_IsMainThread());
   MediaMemoryTracker::AddMediaDecoder(this);
 #ifdef PR_LOGGING
   if (!gMediaDecoderLog) {
     gMediaDecoderLog = PR_NewLogModule("MediaDecoder");
   }
 #endif
+
+  mAudioChannel = AudioChannelService::GetDefaultAudioChannel();
 }
 
 bool MediaDecoder::Init(MediaDecoderOwner* aOwner)
 {
   MOZ_ASSERT(NS_IsMainThread());
   mOwner = aOwner;
   mVideoFrameContainer = aOwner->GetVideoFrameContainer();
   MediaShutdownManager::Instance().Register(this);
--- a/content/media/MediaDecoder.h
+++ b/content/media/MediaDecoder.h
@@ -178,21 +178,21 @@ destroying the MediaDecoder object.
 #if !defined(MediaDecoder_h_)
 #define MediaDecoder_h_
 
 #include "nsISupports.h"
 #include "nsCOMPtr.h"
 #include "nsIObserver.h"
 #include "nsAutoPtr.h"
 #include "MediaResource.h"
+#include "mozilla/dom/AudioChannelBinding.h"
 #include "mozilla/gfx/Rect.h"
 #include "mozilla/ReentrantMonitor.h"
 #include "mozilla/TimeStamp.h"
 #include "MediaStreamGraph.h"
-#include "AudioChannelCommon.h"
 #include "AbstractMediaDecoder.h"
 #include "necko-config.h"
 
 class nsIStreamListener;
 class nsIPrincipal;
 class nsITimer;
 
 namespace mozilla {
@@ -734,18 +734,18 @@ public:
   bool CanPlayThrough();
 
   // Make the decoder state machine update the playback position. Called by
   // the reader on the decoder thread (Assertions for this checked by
   // mDecoderStateMachine). This must be called with the decode monitor
   // held.
   void UpdatePlaybackPosition(int64_t aTime) MOZ_FINAL MOZ_OVERRIDE;
 
-  void SetAudioChannelType(dom::AudioChannelType aType) { mAudioChannelType = aType; }
-  dom::AudioChannelType GetAudioChannelType() { return mAudioChannelType; }
+  void SetAudioChannel(dom::AudioChannel aChannel) { mAudioChannel = aChannel; }
+  dom::AudioChannel GetAudioChannel() { return mAudioChannel; }
 
   // Send a new set of metadata to the state machine, to be dispatched to the
   // main thread to be presented when the |currentTime| of the media is greater
   // or equal to aPublishTime.
   void QueueMetadata(int64_t aPublishTime,
                      int aChannels,
                      int aRate,
                      bool aHasAudio,
@@ -1200,17 +1200,17 @@ protected:
   // Read/Write from the main thread only.
   bool mShuttingDown;
 
   // True if the playback is paused because the playback rate member is 0.0.
   bool mPausedForPlaybackRateNull;
 
   // Be assigned from media element during the initialization and pass to
   // AudioStream Class.
-  dom::AudioChannelType mAudioChannelType;
+  dom::AudioChannel mAudioChannel;
 
   // True if the decoder has been directed to minimize its preroll before
   // playback starts. After the first time playback starts, we don't attempt
   // to minimize preroll, as we assume the user is likely to keep playing,
   // or play the media again.
   bool mMinimizePreroll;
 };
 
--- a/content/media/MediaDecoderStateMachine.cpp
+++ b/content/media/MediaDecoderStateMachine.cpp
@@ -758,38 +758,38 @@ void MediaDecoderStateMachine::AudioLoop
   int64_t audioStartTime = -1;
   uint32_t channels, rate;
   double volume = -1;
   bool setVolume;
   double playbackRate = -1;
   bool setPlaybackRate;
   bool preservesPitch;
   bool setPreservesPitch;
-  AudioChannelType audioChannelType;
+  AudioChannel audioChannel;
 
   {
     ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
     mAudioCompleted = false;
     audioStartTime = mAudioStartTime;
     NS_ASSERTION(audioStartTime != -1, "Should have audio start time by now");
     channels = mInfo.mAudio.mChannels;
     rate = mInfo.mAudio.mRate;
 
-    audioChannelType = mDecoder->GetAudioChannelType();
+    audioChannel = mDecoder->GetAudioChannel();
     volume = mVolume;
     preservesPitch = mPreservesPitch;
     playbackRate = mPlaybackRate;
   }
 
   {
     // AudioStream initialization can block for extended periods in unusual
     // circumstances, so we take care to drop the decoder monitor while
     // initializing.
     nsAutoPtr<AudioStream> audioStream(new AudioStream());
-    audioStream->Init(channels, rate, audioChannelType, AudioStream::HighLatency);
+    audioStream->Init(channels, rate, audioChannel, AudioStream::HighLatency);
     audioStream->SetVolume(volume);
     if (audioStream->SetPreservesPitch(preservesPitch) != NS_OK) {
       NS_WARNING("Setting the pitch preservation failed at AudioLoop start.");
     }
     if (playbackRate != 1.0) {
       NS_ASSERTION(playbackRate != 0,
                    "Don't set the playbackRate to 0 on an AudioStream.");
       if (audioStream->SetPlaybackRate(playbackRate) != NS_OK) {
--- a/content/media/MediaStreamGraph.cpp
+++ b/content/media/MediaStreamGraph.cpp
@@ -13,17 +13,17 @@
 #include "nsIAppShell.h"
 #include "nsIObserver.h"
 #include "nsServiceManagerUtils.h"
 #include "nsWidgetsCID.h"
 #include "prlog.h"
 #include "mozilla/Attributes.h"
 #include "TrackUnionStream.h"
 #include "ImageContainer.h"
-#include "AudioChannelCommon.h"
+#include "AudioChannelService.h"
 #include "AudioNodeEngine.h"
 #include "AudioNodeStream.h"
 #include "AudioNodeExternalInputStream.h"
 #include <algorithm>
 #include "DOMMediaStream.h"
 #include "GeckoProfiler.h"
 #include "mozilla/unused.h"
 #include "speex/speex_resampler.h"
@@ -836,17 +836,19 @@ MediaStreamGraphImpl::CreateOrDestroyAud
         MediaStream::AudioOutputStream* audioOutputStream =
           aStream->mAudioOutputStreams.AppendElement();
         audioOutputStream->mAudioPlaybackStartTime = aAudioOutputStartTime;
         audioOutputStream->mBlockedAudioTime = 0;
         audioOutputStream->mLastTickWritten = 0;
         audioOutputStream->mStream = new AudioStream();
         // XXX for now, allocate stereo output. But we need to fix this to
         // match the system's ideal channel configuration.
-        audioOutputStream->mStream->Init(2, IdealAudioRate(), AUDIO_CHANNEL_NORMAL, AudioStream::LowLatency);
+        audioOutputStream->mStream->Init(2, IdealAudioRate(),
+                                         AudioChannel::Normal,
+                                         AudioStream::LowLatency);
         audioOutputStream->mTrackID = tracks->GetID();
 
         LogLatency(AsyncLatencyLogger::AudioStreamCreate,
                    reinterpret_cast<uint64_t>(aStream),
                    reinterpret_cast<int64_t>(audioOutputStream->mStream.get()));
       }
     }
   }
--- a/content/media/omx/MediaOmxDecoder.cpp
+++ b/content/media/omx/MediaOmxDecoder.cpp
@@ -40,17 +40,17 @@ MediaOmxDecoder::MediaOmxDecoder() :
 MediaDecoder* MediaOmxDecoder::Clone()
 {
   return new MediaOmxDecoder();
 }
 
 MediaDecoderStateMachine* MediaOmxDecoder::CreateStateMachine()
 {
   mReader = new MediaOmxReader(this);
-  mReader->SetAudioChannelType(GetAudioChannelType());
+  mReader->SetAudioChannel(GetAudioChannel());
   return new MediaDecoderStateMachine(this, mReader);
 }
 
 void MediaOmxDecoder::SetCanOffloadAudio(bool aCanOffloadAudio)
 {
   ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
   mCanOffloadAudio = aCanOffloadAudio;
 }
--- a/content/media/omx/MediaOmxReader.cpp
+++ b/content/media/omx/MediaOmxReader.cpp
@@ -8,16 +8,17 @@
 
 #include "MediaDecoderStateMachine.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/dom/TimeRanges.h"
 #include "MediaResource.h"
 #include "VideoUtils.h"
 #include "MediaOmxDecoder.h"
 #include "AbstractMediaDecoder.h"
+#include "AudioChannelService.h"
 #include "OmxDecoder.h"
 #include "MPAPI.h"
 #include "gfx2DGlue.h"
 
 #ifdef MOZ_AUDIO_OFFLOAD
 #include <stagefright/Utils.h>
 #include <cutils/properties.h>
 #include <stagefright/MetaData.h>
@@ -40,24 +41,25 @@ extern PRLogModuleInfo* gMediaDecoderLog
 #endif
 
 MediaOmxReader::MediaOmxReader(AbstractMediaDecoder *aDecoder) :
   MediaDecoderReader(aDecoder),
   mHasVideo(false),
   mHasAudio(false),
   mVideoSeekTimeUs(-1),
   mAudioSeekTimeUs(-1),
-  mSkipCount(0),
-  mAudioChannelType(dom::AUDIO_CHANNEL_DEFAULT)
+  mSkipCount(0)
 {
 #ifdef PR_LOGGING
   if (!gMediaDecoderLog) {
     gMediaDecoderLog = PR_NewLogModule("MediaDecoder");
   }
 #endif
+
+  mAudioChannel = dom::AudioChannelService::GetDefaultAudioChannel();
 }
 
 MediaOmxReader::~MediaOmxReader()
 {
   ReleaseMediaResources();
   ReleaseDecoder();
   mOmxDecoder.clear();
 }
@@ -432,21 +434,21 @@ void MediaOmxReader::CheckAudioOffload()
 
   // Supporting audio offload only when there is no video, no streaming
   bool hasNoVideo = !mOmxDecoder->HasVideo();
   bool isNotStreaming
       = mDecoder->GetResource()->IsDataCachedToEndOfResource(0);
 
   // Not much benefit in trying to offload other channel types. Most of them
   // aren't supported and also duration would be less than a minute
-  bool isTypeMusic = mAudioChannelType == dom::AUDIO_CHANNEL_CONTENT;
+  bool isTypeMusic = mAudioChannel == dom::AudioChannel::Content;
 
   DECODER_LOG(PR_LOG_DEBUG, ("%s meta %p, no video %d, no streaming %d,"
       " channel type %d", __FUNCTION__, meta.get(), hasNoVideo,
-      isNotStreaming, mAudioChannelType));
+      isNotStreaming, mAudioChannel));
 
   if ((meta.get()) && hasNoVideo && isNotStreaming && isTypeMusic &&
       canOffloadStream(meta, false, false, AUDIO_STREAM_MUSIC)) {
     DECODER_LOG(PR_LOG_DEBUG, ("Can offload this audio stream"));
     mDecoder->SetCanOffloadAudio(true);
   }
 }
 #endif
--- a/content/media/omx/MediaOmxReader.h
+++ b/content/media/omx/MediaOmxReader.h
@@ -4,17 +4,17 @@
  * 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/. */
 #if !defined(MediaOmxReader_h_)
 #define MediaOmxReader_h_
 
 #include "MediaResource.h"
 #include "MediaDecoderReader.h"
 #include "nsRect.h"
-#include "AudioChannelCommon.h"
+#include "mozilla/dom/AudioChannelBinding.h"
 #include <ui/GraphicBuffer.h>
 #include <stagefright/MediaSource.h>
 
 namespace android {
 class OmxDecoder;
 class MediaExtractor;
 }
 
@@ -31,17 +31,17 @@ class MediaOmxReader : public MediaDecod
   nsCString mType;
   bool mHasVideo;
   bool mHasAudio;
   nsIntRect mPicture;
   nsIntSize mInitialFrame;
   int64_t mVideoSeekTimeUs;
   int64_t mAudioSeekTimeUs;
   int32_t mSkipCount;
-  dom::AudioChannelType mAudioChannelType;
+  dom::AudioChannel mAudioChannel;
   android::sp<android::MediaSource> mAudioOffloadTrack;
 
 protected:
   android::sp<android::OmxDecoder> mOmxDecoder;
   android::sp<android::MediaExtractor> mExtractor;
 
   // Called by ReadMetadata() during MediaDecoderStateMachine::DecodeMetadata()
   // on decode thread. It create and initialize the OMX decoder including
@@ -80,18 +80,18 @@ public:
 
   virtual nsresult ReadMetadata(MediaInfo* aInfo,
                                 MetadataTags** aTags);
   virtual nsresult Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime);
 
   virtual void SetIdle() MOZ_OVERRIDE;
   virtual void SetActive() MOZ_OVERRIDE;
 
-  void SetAudioChannelType(dom::AudioChannelType aAudioChannelType) {
-    mAudioChannelType = aAudioChannelType;
+  void SetAudioChannel(dom::AudioChannel aAudioChannel) {
+    mAudioChannel = aAudioChannel;
   }
 
   android::sp<android::MediaSource> GetAudioOffloadTrack() {
     return mAudioOffloadTrack;
   }
 
 #ifdef MOZ_AUDIO_OFFLOAD
   // Check whether it is possible to offload current audio track. This access
--- a/content/media/webaudio/AudioDestinationNode.cpp
+++ b/content/media/webaudio/AudioDestinationNode.cpp
@@ -472,50 +472,20 @@ AudioDestinationNode::CheckAudioChannelP
 
 void
 AudioDestinationNode::CreateAudioChannelAgent()
 {
   if (mAudioChannelAgent) {
     mAudioChannelAgent->StopPlaying();
   }
 
-  AudioChannelType type = AUDIO_CHANNEL_NORMAL;
-  switch(mAudioChannel) {
-    case AudioChannel::Normal:
-      type = AUDIO_CHANNEL_NORMAL;
-      break;
-
-    case AudioChannel::Content:
-      type = AUDIO_CHANNEL_CONTENT;
-      break;
-
-    case AudioChannel::Notification:
-      type = AUDIO_CHANNEL_NOTIFICATION;
-      break;
-
-    case AudioChannel::Alarm:
-      type = AUDIO_CHANNEL_ALARM;
-      break;
-
-    case AudioChannel::Telephony:
-      type = AUDIO_CHANNEL_TELEPHONY;
-      break;
-
-    case AudioChannel::Ringer:
-      type = AUDIO_CHANNEL_RINGER;
-      break;
-
-    case AudioChannel::Publicnotification:
-      type = AUDIO_CHANNEL_PUBLICNOTIFICATION;
-      break;
-
-  }
-
   mAudioChannelAgent = new AudioChannelAgent();
-  mAudioChannelAgent->InitWithWeakCallback(GetOwner(), type, this);
+  mAudioChannelAgent->InitWithWeakCallback(GetOwner(),
+                                           static_cast<int32_t>(mAudioChannel),
+                                           this);
 
   nsCOMPtr<nsIDocShell> docshell = do_GetInterface(GetOwner());
   if (docshell) {
     bool isActive = false;
     docshell->GetIsActive(&isActive);
     mAudioChannelAgent->SetVisibilityState(isActive);
   }
 
--- a/content/svg/content/src/SVGAttrValueWrapper.h
+++ b/content/svg/content/src/SVGAttrValueWrapper.h
@@ -7,17 +7,17 @@
 #ifndef MOZILLA_SVGATTRVALUEWRAPPER_H__
 #define MOZILLA_SVGATTRVALUEWRAPPER_H__
 
 /**
  * Utility wrapper for handling SVG types used inside nsAttrValue so that these
  * types don't need to be exported outside the SVG module.
  */
 
-#include "nsString.h"
+#include "nsStringGlue.h"
 
 class nsSVGAngle;
 class nsSVGIntegerPair;
 class nsSVGLength2;
 class nsSVGNumberPair;
 class nsSVGViewBox;
 
 namespace mozilla {
--- a/dom/audiochannel/AudioChannelAgent.cpp
+++ b/dom/audiochannel/AudioChannelAgent.cpp
@@ -79,32 +79,32 @@ nsresult
 AudioChannelAgent::InitInternal(nsIDOMWindow* aWindow, int32_t aChannelType,
                                 nsIAudioChannelAgentCallback *aCallback,
                                 bool aUseWeakRef, bool aWithVideo)
 {
   // We need the window only for IPC.
   MOZ_ASSERT(aWindow || XRE_GetProcessType() == GeckoProcessType_Default);
 
   // We syncd the enum of channel type between nsIAudioChannelAgent.idl and
-  // AudioChannelCommon.h the same.
-  static_assert(static_cast<AudioChannelType>(AUDIO_AGENT_CHANNEL_NORMAL) ==
-                AUDIO_CHANNEL_NORMAL &&
-                static_cast<AudioChannelType>(AUDIO_AGENT_CHANNEL_CONTENT) ==
-                AUDIO_CHANNEL_CONTENT &&
-                static_cast<AudioChannelType>(AUDIO_AGENT_CHANNEL_NOTIFICATION) ==
-                AUDIO_CHANNEL_NOTIFICATION &&
-                static_cast<AudioChannelType>(AUDIO_AGENT_CHANNEL_ALARM) ==
-                AUDIO_CHANNEL_ALARM &&
-                static_cast<AudioChannelType>(AUDIO_AGENT_CHANNEL_TELEPHONY) ==
-                AUDIO_CHANNEL_TELEPHONY &&
-                static_cast<AudioChannelType>(AUDIO_AGENT_CHANNEL_RINGER) ==
-                AUDIO_CHANNEL_RINGER &&
-                static_cast<AudioChannelType>(AUDIO_AGENT_CHANNEL_PUBLICNOTIFICATION) ==
-                AUDIO_CHANNEL_PUBLICNOTIFICATION,
-                "Enum of channel on nsIAudioChannelAgent.idl should be the same with AudioChannelCommon.h");
+  // AudioChannelBinding.h the same.
+  MOZ_ASSERT(static_cast<AudioChannel>(AUDIO_AGENT_CHANNEL_NORMAL) ==
+             AudioChannel::Normal &&
+             static_cast<AudioChannel>(AUDIO_AGENT_CHANNEL_CONTENT) ==
+             AudioChannel::Content &&
+             static_cast<AudioChannel>(AUDIO_AGENT_CHANNEL_NOTIFICATION) ==
+             AudioChannel::Notification &&
+             static_cast<AudioChannel>(AUDIO_AGENT_CHANNEL_ALARM) ==
+             AudioChannel::Alarm &&
+             static_cast<AudioChannel>(AUDIO_AGENT_CHANNEL_TELEPHONY) ==
+             AudioChannel::Telephony &&
+             static_cast<AudioChannel>(AUDIO_AGENT_CHANNEL_RINGER) ==
+             AudioChannel::Ringer &&
+             static_cast<AudioChannel>(AUDIO_AGENT_CHANNEL_PUBLICNOTIFICATION) ==
+             AudioChannel::Publicnotification,
+             "Enum of channel on nsIAudioChannelAgent.idl should be the same with AudioChannelBinding.h");
 
   if (mAudioChannelType != AUDIO_AGENT_CHANNEL_ERROR ||
       aChannelType > AUDIO_AGENT_CHANNEL_PUBLICNOTIFICATION ||
       aChannelType < AUDIO_AGENT_CHANNEL_NORMAL) {
     return NS_ERROR_FAILURE;
   }
 
   mWindow = aWindow;
@@ -126,17 +126,17 @@ NS_IMETHODIMP AudioChannelAgent::StartPl
 {
   AudioChannelService *service = AudioChannelService::GetAudioChannelService();
   if (mAudioChannelType == AUDIO_AGENT_CHANNEL_ERROR ||
       service == nullptr || mIsRegToService) {
     return NS_ERROR_FAILURE;
   }
 
   service->RegisterAudioChannelAgent(this,
-    static_cast<AudioChannelType>(mAudioChannelType), mWithVideo);
+    static_cast<AudioChannel>(mAudioChannelType), mWithVideo);
   *_retval = service->GetState(this, !mVisible);
   mIsRegToService = true;
   return NS_OK;
 }
 
 /* void stopPlaying (); */
 NS_IMETHODIMP AudioChannelAgent::StopPlaying(void)
 {
--- a/dom/audiochannel/AudioChannelCommon.h
+++ b/dom/audiochannel/AudioChannelCommon.h
@@ -5,30 +5,16 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_audiochannelcommon_h__
 #define mozilla_dom_audiochannelcommon_h__
 
 namespace mozilla {
 namespace dom {
 
-// The audio channel. Read the nsIHTMLMediaElement.idl for a description
-// about this attribute.
-enum AudioChannelType {
-  AUDIO_CHANNEL_DEFAULT = -1,
-  AUDIO_CHANNEL_NORMAL = 0,
-  AUDIO_CHANNEL_CONTENT,
-  AUDIO_CHANNEL_NOTIFICATION,
-  AUDIO_CHANNEL_ALARM,
-  AUDIO_CHANNEL_TELEPHONY,
-  AUDIO_CHANNEL_RINGER,
-  AUDIO_CHANNEL_PUBLICNOTIFICATION,
-  AUDIO_CHANNEL_LAST
-};
-
 enum AudioChannelState {
   AUDIO_CHANNEL_STATE_NORMAL = 0,
   AUDIO_CHANNEL_STATE_MUTED,
   AUDIO_CHANNEL_STATE_FADED,
   AUDIO_CHANNEL_STATE_LAST
 };
 
 } // namespace dom
--- a/dom/audiochannel/AudioChannelService.cpp
+++ b/dom/audiochannel/AudioChannelService.cpp
@@ -32,16 +32,28 @@
 #include "mozilla/Preferences.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::hal;
 
 StaticRefPtr<AudioChannelService> gAudioChannelService;
 
+// Mappings from 'mozaudiochannel' attribute strings to an enumeration.
+static const nsAttrValue::EnumTable kMozAudioChannelAttributeTable[] = {
+  { "normal",             (int16_t)AudioChannel::Normal },
+  { "content",            (int16_t)AudioChannel::Content },
+  { "notification",       (int16_t)AudioChannel::Notification },
+  { "alarm",              (int16_t)AudioChannel::Alarm },
+  { "telephony",          (int16_t)AudioChannel::Telephony },
+  { "ringer",             (int16_t)AudioChannel::Ringer },
+  { "publicnotification", (int16_t)AudioChannel::Publicnotification },
+  { nullptr }
+};
+
 // static
 AudioChannelService*
 AudioChannelService::GetAudioChannelService()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (XRE_GetProcessType() != GeckoProcessType_Default) {
     return AudioChannelServiceChild::GetAudioChannelService();
@@ -70,18 +82,18 @@ AudioChannelService::Shutdown()
   if (gAudioChannelService) {
     gAudioChannelService = nullptr;
   }
 }
 
 NS_IMPL_ISUPPORTS2(AudioChannelService, nsIObserver, nsITimerCallback)
 
 AudioChannelService::AudioChannelService()
-: mCurrentHigherChannel(AUDIO_CHANNEL_LAST)
-, mCurrentVisibleHigherChannel(AUDIO_CHANNEL_LAST)
+: mCurrentHigherChannel(INT32_MAX)
+, mCurrentVisibleHigherChannel(INT32_MAX)
 , mPlayableHiddenContentChildID(CONTENT_PROCESS_ID_UNKNOWN)
 , mDisabled(false)
 , mDefChannelChildID(CONTENT_PROCESS_ID_UNKNOWN)
 {
   if (XRE_GetProcessType() == GeckoProcessType_Default) {
     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
     if (obs) {
       obs->AddObserver(this, "ipc:content-shutdown", false);
@@ -95,62 +107,62 @@ AudioChannelService::AudioChannelService
 }
 
 AudioChannelService::~AudioChannelService()
 {
 }
 
 void
 AudioChannelService::RegisterAudioChannelAgent(AudioChannelAgent* aAgent,
-                                               AudioChannelType aType,
+                                               AudioChannel aChannel,
                                                bool aWithVideo)
 {
   if (mDisabled) {
     return;
   }
 
-  MOZ_ASSERT(aType != AUDIO_CHANNEL_DEFAULT);
-
-  AudioChannelAgentData* data = new AudioChannelAgentData(aType,
+  AudioChannelAgentData* data = new AudioChannelAgentData(aChannel,
                                 true /* aElementHidden */,
                                 AUDIO_CHANNEL_STATE_MUTED /* aState */,
                                 aWithVideo);
   mAgents.Put(aAgent, data);
-  RegisterType(aType, CONTENT_PROCESS_ID_MAIN, aWithVideo);
+  RegisterType(aChannel, CONTENT_PROCESS_ID_MAIN, aWithVideo);
 
   // If this is the first agent for this window, we must notify the observers.
   uint32_t count = CountWindow(aAgent->Window());
   if (count == 1) {
     nsCOMPtr<nsIObserverService> observerService =
       services::GetObserverService();
     if (observerService) {
       observerService->NotifyObservers(ToSupports(aAgent->Window()),
                                        "media-playback",
                                        NS_LITERAL_STRING("active").get());
     }
   }
 }
 
 void
-AudioChannelService::RegisterType(AudioChannelType aType, uint64_t aChildID, bool aWithVideo)
+AudioChannelService::RegisterType(AudioChannel aChannel, uint64_t aChildID,
+                                  bool aWithVideo)
 {
   if (mDisabled) {
     return;
   }
 
-  AudioChannelInternalType type = GetInternalType(aType, true);
+  AudioChannelInternalType type = GetInternalType(aChannel, true);
   mChannelCounters[type].AppendElement(aChildID);
 
   if (XRE_GetProcessType() == GeckoProcessType_Default) {
     // Since there is another telephony registered, we can unregister old one
     // immediately.
-    if (mDeferTelChannelTimer && aType == AUDIO_CHANNEL_TELEPHONY) {
+    if (mDeferTelChannelTimer && aChannel == AudioChannel::Telephony) {
       mDeferTelChannelTimer->Cancel();
       mDeferTelChannelTimer = nullptr;
-      UnregisterTypeInternal(aType, mTimerElementHidden, mTimerChildID, false);
+      UnregisterTypeInternal(aChannel, mTimerElementHidden, mTimerChildID,
+                             false);
     }
 
     if (aWithVideo) {
       mWithVideoChildIDs.AppendElement(aChildID);
     }
 
     // No hidden content channel can be playable if there is a content channel
     // in foreground (bug 855208), nor if there is a normal channel with video
@@ -181,17 +193,17 @@ AudioChannelService::UnregisterAudioChan
   if (mDisabled) {
     return;
   }
 
   nsAutoPtr<AudioChannelAgentData> data;
   mAgents.RemoveAndForget(aAgent, data);
 
   if (data) {
-    UnregisterType(data->mType, data->mElementHidden,
+    UnregisterType(data->mChannel, data->mElementHidden,
                    CONTENT_PROCESS_ID_MAIN, data->mWithVideo);
   }
 #ifdef MOZ_WIDGET_GONK
   bool active = AnyAudioChannelIsActive();
   for (uint32_t i = 0; i < mSpeakerManager.Length(); i++) {
     mSpeakerManager[i]->SetAudioChannelActive(active);
   }
 #endif
@@ -205,84 +217,84 @@ AudioChannelService::UnregisterAudioChan
       observerService->NotifyObservers(ToSupports(aAgent->Window()),
                                        "media-playback",
                                        NS_LITERAL_STRING("inactive").get());
     }
   }
 }
 
 void
-AudioChannelService::UnregisterType(AudioChannelType aType,
+AudioChannelService::UnregisterType(AudioChannel aChannel,
                                     bool aElementHidden,
                                     uint64_t aChildID,
                                     bool aWithVideo)
 {
   if (mDisabled) {
     return;
   }
 
   // There are two reasons to defer the decrease of telephony channel.
   // 1. User can have time to remove device from his ear before music resuming.
   // 2. Give BT SCO to be disconnected before starting to connect A2DP.
   if (XRE_GetProcessType() == GeckoProcessType_Default &&
-      aType == AUDIO_CHANNEL_TELEPHONY &&
+      aChannel == AudioChannel::Telephony &&
       (mChannelCounters[AUDIO_CHANNEL_INT_TELEPHONY_HIDDEN].Length() +
        mChannelCounters[AUDIO_CHANNEL_INT_TELEPHONY].Length()) == 1) {
     mTimerElementHidden = aElementHidden;
     mTimerChildID = aChildID;
     mDeferTelChannelTimer = do_CreateInstance("@mozilla.org/timer;1");
     mDeferTelChannelTimer->InitWithCallback(this, 1500, nsITimer::TYPE_ONE_SHOT);
     return;
   }
 
-  UnregisterTypeInternal(aType, aElementHidden, aChildID, aWithVideo);
+  UnregisterTypeInternal(aChannel, aElementHidden, aChildID, aWithVideo);
 }
 
 void
-AudioChannelService::UnregisterTypeInternal(AudioChannelType aType,
+AudioChannelService::UnregisterTypeInternal(AudioChannel aChannel,
                                             bool aElementHidden,
                                             uint64_t aChildID,
                                             bool aWithVideo)
 {
   // The array may contain multiple occurrence of this appId but
   // this should remove only the first one.
-  AudioChannelInternalType type = GetInternalType(aType, aElementHidden);
+  AudioChannelInternalType type = GetInternalType(aChannel, aElementHidden);
   MOZ_ASSERT(mChannelCounters[type].Contains(aChildID));
   mChannelCounters[type].RemoveElement(aChildID);
 
   // In order to avoid race conditions, it's safer to notify any existing
   // agent any time a new one is registered.
   if (XRE_GetProcessType() == GeckoProcessType_Default) {
     // No hidden content channel is playable if the original playable hidden
     // process does not need to play audio from background anymore.
-    if (aType == AUDIO_CHANNEL_CONTENT &&
+    if (aChannel == AudioChannel::Content &&
         mPlayableHiddenContentChildID == aChildID &&
         !mChannelCounters[AUDIO_CHANNEL_INT_CONTENT_HIDDEN].Contains(aChildID)) {
       mPlayableHiddenContentChildID = CONTENT_PROCESS_ID_UNKNOWN;
     }
 
     if (aWithVideo) {
       MOZ_ASSERT(mWithVideoChildIDs.Contains(aChildID));
       mWithVideoChildIDs.RemoveElement(aChildID);
     }
 
     SendAudioChannelChangedNotification(aChildID);
     Notify();
   }
 }
 
 void
-AudioChannelService::UpdateChannelType(AudioChannelType aType,
+AudioChannelService::UpdateChannelType(AudioChannel aChannel,
                                        uint64_t aChildID,
                                        bool aElementHidden,
                                        bool aElementWasHidden)
 {
   // Calculate the new and old internal type and update the hashtable if needed.
-  AudioChannelInternalType newType = GetInternalType(aType, aElementHidden);
-  AudioChannelInternalType oldType = GetInternalType(aType, aElementWasHidden);
+  AudioChannelInternalType newType = GetInternalType(aChannel, aElementHidden);
+  AudioChannelInternalType oldType = GetInternalType(aChannel, aElementWasHidden);
 
   if (newType != oldType) {
     mChannelCounters[newType].AppendElement(aChildID);
     MOZ_ASSERT(mChannelCounters[oldType].Contains(aChildID));
     mChannelCounters[oldType].RemoveElement(aChildID);
   }
 
   // No hidden content channel can be playable if there is a content channel
@@ -310,34 +322,36 @@ AudioChannelService::GetState(AudioChann
   if (!mAgents.Get(aAgent, &data)) {
     return AUDIO_CHANNEL_STATE_MUTED;
   }
 
   bool oldElementHidden = data->mElementHidden;
   // Update visibility.
   data->mElementHidden = aElementHidden;
 
-  data->mState = GetStateInternal(data->mType, CONTENT_PROCESS_ID_MAIN,
+  data->mState = GetStateInternal(data->mChannel, CONTENT_PROCESS_ID_MAIN,
                                 aElementHidden, oldElementHidden);
   return data->mState;
 }
 
 AudioChannelState
-AudioChannelService::GetStateInternal(AudioChannelType aType, uint64_t aChildID,
-                                      bool aElementHidden, bool aElementWasHidden)
+AudioChannelService::GetStateInternal(AudioChannel aChannel, uint64_t aChildID,
+                                      bool aElementHidden,
+                                      bool aElementWasHidden)
 {
-  UpdateChannelType(aType, aChildID, aElementHidden, aElementWasHidden);
+  UpdateChannelType(aChannel, aChildID, aElementHidden, aElementWasHidden);
 
   // Calculating the new and old type and update the hashtable if needed.
-  AudioChannelInternalType newType = GetInternalType(aType, aElementHidden);
-  AudioChannelInternalType oldType = GetInternalType(aType, aElementWasHidden);
+  AudioChannelInternalType newType = GetInternalType(aChannel, aElementHidden);
+  AudioChannelInternalType oldType = GetInternalType(aChannel,
+                                                     aElementWasHidden);
 
   if (newType != oldType &&
-      (aType == AUDIO_CHANNEL_CONTENT ||
-       (aType == AUDIO_CHANNEL_NORMAL &&
+      (aChannel == AudioChannel::Content ||
+       (aChannel == AudioChannel::Normal &&
         mWithVideoChildIDs.Contains(aChildID)))) {
     Notify();
   }
 
   SendAudioChannelChangedNotification(aChildID);
 
   // Let play any visible audio channel.
   if (!aElementHidden) {
@@ -422,40 +436,48 @@ bool
 AudioChannelService::ProcessContentOrNormalChannelIsActive(uint64_t aChildID)
 {
   return mChannelCounters[AUDIO_CHANNEL_INT_CONTENT].Contains(aChildID) ||
          mChannelCounters[AUDIO_CHANNEL_INT_CONTENT_HIDDEN].Contains(aChildID) ||
          mChannelCounters[AUDIO_CHANNEL_INT_NORMAL].Contains(aChildID);
 }
 
 void
-AudioChannelService::SetDefaultVolumeControlChannel(AudioChannelType aType,
+AudioChannelService::SetDefaultVolumeControlChannel(int32_t aChannel,
                                                     bool aHidden)
 {
-  SetDefaultVolumeControlChannelInternal(aType, aHidden, CONTENT_PROCESS_ID_MAIN);
+  SetDefaultVolumeControlChannelInternal(aChannel, aHidden,
+                                         CONTENT_PROCESS_ID_MAIN);
 }
 
 void
-AudioChannelService::SetDefaultVolumeControlChannelInternal(
-  AudioChannelType aType, bool aHidden, uint64_t aChildID)
+AudioChannelService::SetDefaultVolumeControlChannelInternal(int32_t aChannel,
+                                                            bool aHidden,
+                                                            uint64_t aChildID)
 {
   if (XRE_GetProcessType() != GeckoProcessType_Default) {
     return;
   }
 
   // If this child is in the background and mDefChannelChildID is set to
   // others then it means other child in the foreground already set it's
   // own default channel already.
   if (!aHidden && mDefChannelChildID != aChildID) {
     return;
   }
 
   mDefChannelChildID = aChildID;
   nsString channelName;
-  channelName.AssignASCII(ChannelName(aType));
+
+  if (aChannel == -1) {
+    channelName.AssignASCII("unknown");
+  } else {
+    GetAudioChannelString(static_cast<AudioChannel>(aChannel), channelName);
+  }
+
   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   if (obs) {
     obs->NotifyObservers(nullptr, "default-volume-channel-changed",
                          channelName.get());
   }
 }
 
 void
@@ -470,87 +492,94 @@ AudioChannelService::SendAudioChannelCha
 
   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   if (obs) {
     obs->NotifyObservers(static_cast<nsIWritablePropertyBag*>(props),
                          "audio-channel-process-changed", nullptr);
   }
 
   // Calculating the most important active channel.
-  AudioChannelType higher = AUDIO_CHANNEL_DEFAULT;
+  int32_t higher = -1;
 
   // Top-Down in the hierarchy for visible elements
   if (!mChannelCounters[AUDIO_CHANNEL_INT_PUBLICNOTIFICATION].IsEmpty()) {
-    higher = AUDIO_CHANNEL_PUBLICNOTIFICATION;
+    higher = static_cast<int32_t>(AudioChannel::Publicnotification);
   }
 
   else if (!mChannelCounters[AUDIO_CHANNEL_INT_RINGER].IsEmpty()) {
-    higher = AUDIO_CHANNEL_RINGER;
+    higher = static_cast<int32_t>(AudioChannel::Ringer);
   }
 
   else if (!mChannelCounters[AUDIO_CHANNEL_INT_TELEPHONY].IsEmpty()) {
-    higher = AUDIO_CHANNEL_TELEPHONY;
+    higher = static_cast<int32_t>(AudioChannel::Telephony);
   }
 
   else if (!mChannelCounters[AUDIO_CHANNEL_INT_ALARM].IsEmpty()) {
-    higher = AUDIO_CHANNEL_ALARM;
+    higher = static_cast<int32_t>(AudioChannel::Alarm);
   }
 
   else if (!mChannelCounters[AUDIO_CHANNEL_INT_NOTIFICATION].IsEmpty()) {
-    higher = AUDIO_CHANNEL_NOTIFICATION;
+    higher = static_cast<int32_t>(AudioChannel::Notification);
   }
 
   else if (!mChannelCounters[AUDIO_CHANNEL_INT_CONTENT].IsEmpty()) {
-    higher = AUDIO_CHANNEL_CONTENT;
+    higher = static_cast<int32_t>(AudioChannel::Content);
   }
 
   else if (!mChannelCounters[AUDIO_CHANNEL_INT_NORMAL].IsEmpty()) {
-    higher = AUDIO_CHANNEL_NORMAL;
+    higher = static_cast<int32_t>(AudioChannel::Normal);
   }
 
-  AudioChannelType visibleHigher = higher;
+  int32_t visibleHigher = higher;
 
   // Top-Down in the hierarchy for non-visible elements
   // And we can ignore normal channel because it can't play in the background.
-  for (int i = AUDIO_CHANNEL_LAST - 1;
-       i > higher && i > AUDIO_CHANNEL_NORMAL; i--) {
-    if (i == AUDIO_CHANNEL_CONTENT &&
+  int32_t index;
+  for (index = 0; kMozAudioChannelAttributeTable[index].tag; ++index);
+
+  for (--index;
+       kMozAudioChannelAttributeTable[index].value > higher &&
+       kMozAudioChannelAttributeTable[index].value > (int16_t)AudioChannel::Normal;
+       --index) {
+    if (kMozAudioChannelAttributeTable[index].value == (int16_t)AudioChannel::Content &&
       mPlayableHiddenContentChildID != CONTENT_PROCESS_ID_UNKNOWN) {
-      higher = static_cast<AudioChannelType>(i);
+      higher = kMozAudioChannelAttributeTable[index].value;
     }
 
     // Each channel type will be split to fg and bg for recording the state,
     // so here need to do a translation.
-    if (!mChannelCounters[i * 2 + 1].IsEmpty()) {
-      higher = static_cast<AudioChannelType>(i);
+    if (!mChannelCounters[index * 2 + 1].IsEmpty()) {
+      higher = kMozAudioChannelAttributeTable[index].value;
       break;
     }
   }
 
   if (higher != mCurrentHigherChannel) {
     mCurrentHigherChannel = higher;
 
     nsString channelName;
-    if (mCurrentHigherChannel != AUDIO_CHANNEL_DEFAULT) {
-      channelName.AssignASCII(ChannelName(mCurrentHigherChannel));
+    if (mCurrentHigherChannel != -1) {
+      GetAudioChannelString(static_cast<AudioChannel>(mCurrentHigherChannel),
+                            channelName);
     } else {
       channelName.AssignLiteral("none");
     }
 
     if (obs) {
       obs->NotifyObservers(nullptr, "audio-channel-changed", channelName.get());
     }
   }
 
   if (visibleHigher != mCurrentVisibleHigherChannel) {
     mCurrentVisibleHigherChannel = visibleHigher;
 
     nsString channelName;
-    if (mCurrentVisibleHigherChannel != AUDIO_CHANNEL_DEFAULT) {
-      channelName.AssignASCII(ChannelName(mCurrentVisibleHigherChannel));
+    if (mCurrentVisibleHigherChannel != -1) {
+      GetAudioChannelString(static_cast<AudioChannel>(mCurrentVisibleHigherChannel),
+                            channelName);
     } else {
       channelName.AssignLiteral("none");
     }
 
     if (obs) {
       obs->NotifyObservers(nullptr, "visible-audio-channel-changed", channelName.get());
     }
   }
@@ -579,17 +608,18 @@ AudioChannelService::Notify()
   for (uint32_t i = 0; i < children.Length(); i++) {
     unused << children[i]->SendAudioChannelNotify();
   }
 }
 
 NS_IMETHODIMP
 AudioChannelService::Notify(nsITimer* aTimer)
 {
-  UnregisterTypeInternal(AUDIO_CHANNEL_TELEPHONY, mTimerElementHidden, mTimerChildID, false);
+  UnregisterTypeInternal(AudioChannel::Telephony, mTimerElementHidden,
+                         mTimerChildID, false);
   mDeferTelChannelTimer = nullptr;
   return NS_OK;
 }
 
 bool
 AudioChannelService::AnyAudioChannelIsActive()
 {
   for (int i = AUDIO_CHANNEL_INT_LAST - 1;
@@ -615,44 +645,16 @@ AudioChannelService::ChannelsActiveWithH
     if (!mChannelCounters[i].IsEmpty()) {
       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,            "content" },
-    { AUDIO_CHANNEL_NOTIFICATION,       "notification" },
-    { AUDIO_CHANNEL_ALARM,              "alarm" },
-    { AUDIO_CHANNEL_TELEPHONY,          "telephony" },
-    { AUDIO_CHANNEL_RINGER,             "ringer" },
-    { 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;
-}
-
 NS_IMETHODIMP
 AudioChannelService::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData)
 {
   if (!strcmp(aTopic, "xpcom-shutdown")) {
     mDisabled = true;
   }
 
   if (!strcmp(aTopic, "ipc:content-shutdown")) {
@@ -688,18 +690,17 @@ AudioChannelService::Observe(nsISupports
 
       // We don't have to remove the agents from the mAgents hashtable because if
       // that table contains only agents running on the same process.
 
       SendAudioChannelChangedNotification(childID);
       Notify();
 
       if (mDefChannelChildID == childID) {
-        SetDefaultVolumeControlChannelInternal(AUDIO_CHANNEL_DEFAULT,
-                                               false, childID);
+        SetDefaultVolumeControlChannelInternal(-1, false, childID);
         mDefChannelChildID = CONTENT_PROCESS_ID_UNKNOWN;
       }
     } else {
       NS_WARNING("ipc:content-shutdown message without childID property");
     }
   }
 #ifdef MOZ_WIDGET_GONK
   // To process the volume control on each audio channel according to
@@ -734,83 +735,82 @@ AudioChannelService::Observe(nsISupports
       return NS_OK;
     }
 
     nsCOMPtr<nsIAudioManager> audioManager = do_GetService(NS_AUDIOMANAGER_CONTRACTID);
     NS_ENSURE_TRUE(audioManager, NS_OK);
 
     int32_t index = value.toInt32();
     if (keyStr.EqualsLiteral("audio.volume.content")) {
-      audioManager->SetAudioChannelVolume(AUDIO_CHANNEL_CONTENT, index);
+      audioManager->SetAudioChannelVolume((int32_t)AudioChannel::Content, index);
     } else if (keyStr.EqualsLiteral("audio.volume.notification")) {
-      audioManager->SetAudioChannelVolume(AUDIO_CHANNEL_NOTIFICATION, index);
+      audioManager->SetAudioChannelVolume((int32_t)AudioChannel::Notification, index);
     } else if (keyStr.EqualsLiteral("audio.volume.alarm")) {
-      audioManager->SetAudioChannelVolume(AUDIO_CHANNEL_ALARM, index);
+      audioManager->SetAudioChannelVolume((int32_t)AudioChannel::Alarm, index);
     } else if (keyStr.EqualsLiteral("audio.volume.telephony")) {
-      audioManager->SetAudioChannelVolume(AUDIO_CHANNEL_TELEPHONY, index);
+      audioManager->SetAudioChannelVolume((int32_t)AudioChannel::Telephony, index);
     } else if (!keyStr.EqualsLiteral("audio.volume.bt_sco")) {
       // bt_sco is not a valid audio channel so we manipulate it in
       // AudioManager.cpp. And the others should not be used.
       // We didn't use MOZ_ASSUME_UNREACHABLE here because any web content who
       // has permission of mozSettings can set any names then it can be easy to
       // crash the B2G.
       NS_WARNING("unexpected audio channel for volume control");
     }
   }
 #endif
 
   return NS_OK;
 }
 
 AudioChannelService::AudioChannelInternalType
-AudioChannelService::GetInternalType(AudioChannelType aType,
+AudioChannelService::GetInternalType(AudioChannel aChannel,
                                      bool aElementHidden)
 {
-  switch (aType) {
-    case AUDIO_CHANNEL_NORMAL:
+  switch (aChannel) {
+    case AudioChannel::Normal:
       return aElementHidden
                ? AUDIO_CHANNEL_INT_NORMAL_HIDDEN
                : AUDIO_CHANNEL_INT_NORMAL;
 
-    case AUDIO_CHANNEL_CONTENT:
+    case AudioChannel::Content:
       return aElementHidden
                ? AUDIO_CHANNEL_INT_CONTENT_HIDDEN
                : AUDIO_CHANNEL_INT_CONTENT;
 
-    case AUDIO_CHANNEL_NOTIFICATION:
+    case AudioChannel::Notification:
       return aElementHidden
                ? AUDIO_CHANNEL_INT_NOTIFICATION_HIDDEN
                : AUDIO_CHANNEL_INT_NOTIFICATION;
 
-    case AUDIO_CHANNEL_ALARM:
+    case AudioChannel::Alarm:
       return aElementHidden
                ? AUDIO_CHANNEL_INT_ALARM_HIDDEN
                : AUDIO_CHANNEL_INT_ALARM;
 
-    case AUDIO_CHANNEL_TELEPHONY:
+    case AudioChannel::Telephony:
       return aElementHidden
                ? AUDIO_CHANNEL_INT_TELEPHONY_HIDDEN
                : AUDIO_CHANNEL_INT_TELEPHONY;
 
-    case AUDIO_CHANNEL_RINGER:
+    case AudioChannel::Ringer:
       return aElementHidden
                ? AUDIO_CHANNEL_INT_RINGER_HIDDEN
                : AUDIO_CHANNEL_INT_RINGER;
 
-    case AUDIO_CHANNEL_PUBLICNOTIFICATION:
+    case AudioChannel::Publicnotification:
       return aElementHidden
                ? AUDIO_CHANNEL_INT_PUBLICNOTIFICATION_HIDDEN
                : AUDIO_CHANNEL_INT_PUBLICNOTIFICATION;
 
-    case AUDIO_CHANNEL_LAST:
     default:
       break;
   }
 
-  MOZ_CRASH("unexpected audio channel type");
+  MOZ_CRASH("unexpected audio channel");
 }
 
 struct RefreshAgentsVolumeData
 {
   RefreshAgentsVolumeData(nsPIDOMWindow* aWindow)
     : mWindow(aWindow)
   {}
 
@@ -878,56 +878,73 @@ AudioChannelService::CountWindowEnumerat
 uint32_t
 AudioChannelService::CountWindow(nsIDOMWindow* aWindow)
 {
   CountWindowData data(aWindow);
   mAgents.EnumerateRead(CountWindowEnumerator, &data);
   return data.mCount;
 }
 
-// Mappings from 'mozaudiochannel' attribute strings to an enumeration.
-static const struct AudioChannelTable
+/* static */ const nsAttrValue::EnumTable*
+AudioChannelService::GetAudioChannelTable()
+{
+  return kMozAudioChannelAttributeTable;
+}
+
+/* static */ AudioChannel
+AudioChannelService::GetAudioChannel(const nsAString& aChannel)
 {
-  const char* string;
-  AudioChannel value;
-} kMozAudioChannelAttributeTable[] = {
-  { "normal",             AudioChannel::Normal },
-  { "content",            AudioChannel::Content },
-  { "notification",       AudioChannel::Notification },
-  { "alarm",              AudioChannel::Alarm },
-  { "telephony",          AudioChannel::Telephony },
-  { "ringer",             AudioChannel::Ringer },
-  { "publicnotification", AudioChannel::Publicnotification },
-  { nullptr }
-};
+  for (uint32_t i = 0; kMozAudioChannelAttributeTable[i].tag; ++i) {
+    if (aChannel.EqualsASCII(kMozAudioChannelAttributeTable[i].tag)) {
+      return static_cast<AudioChannel>(kMozAudioChannelAttributeTable[i].value);
+    }
+  }
+
+  return AudioChannel::Normal;
+}
 
 /* static */ AudioChannel
 AudioChannelService::GetDefaultAudioChannel()
 {
   nsString audioChannel = Preferences::GetString("media.defaultAudioChannel");
   if (audioChannel.IsEmpty()) {
     return AudioChannel::Normal;
   }
 
-  for (uint32_t i = 0; kMozAudioChannelAttributeTable[i].string; ++i) {
-    if (audioChannel.EqualsASCII(kMozAudioChannelAttributeTable[i].string)) {
-      return kMozAudioChannelAttributeTable[i].value;
+  for (uint32_t i = 0; kMozAudioChannelAttributeTable[i].tag; ++i) {
+    if (audioChannel.EqualsASCII(kMozAudioChannelAttributeTable[i].tag)) {
+      return static_cast<AudioChannel>(kMozAudioChannelAttributeTable[i].value);
     }
   }
 
   return AudioChannel::Normal;
 }
 
 /* static */ void
-AudioChannelService::GetDefaultAudioChannelString(nsString& aString)
+AudioChannelService::GetAudioChannelString(AudioChannel aChannel,
+                                           nsAString& aString)
+{
+  aString.AssignASCII("normal");
+
+  for (uint32_t i = 0; kMozAudioChannelAttributeTable[i].tag; ++i) {
+    if (aChannel ==
+        static_cast<AudioChannel>(kMozAudioChannelAttributeTable[i].value)) {
+      aString.AssignASCII(kMozAudioChannelAttributeTable[i].tag);
+      break;
+    }
+  }
+}
+
+/* static */ void
+AudioChannelService::GetDefaultAudioChannelString(nsAString& aString)
 {
   aString.AssignASCII("normal");
 
   nsString audioChannel = Preferences::GetString("media.defaultAudioChannel");
   if (!audioChannel.IsEmpty()) {
-    for (uint32_t i = 0; kMozAudioChannelAttributeTable[i].string; ++i) {
-      if (audioChannel.EqualsASCII(kMozAudioChannelAttributeTable[i].string)) {
+    for (uint32_t i = 0; kMozAudioChannelAttributeTable[i].tag; ++i) {
+      if (audioChannel.EqualsASCII(kMozAudioChannelAttributeTable[i].tag)) {
         aString = audioChannel;
         break;
       }
     }
   }
 }
--- a/dom/audiochannel/AudioChannelService.h
+++ b/dom/audiochannel/AudioChannelService.h
@@ -9,16 +9,17 @@
 
 #include "nsAutoPtr.h"
 #include "nsIObserver.h"
 #include "nsTArray.h"
 #include "nsITimer.h"
 
 #include "AudioChannelCommon.h"
 #include "AudioChannelAgent.h"
+#include "nsAttrValue.h"
 #include "nsClassHashtable.h"
 #include "mozilla/dom/AudioChannelBinding.h"
 
 class nsPIDOMWindow;
 
 namespace mozilla {
 namespace dom {
 #ifdef MOZ_WIDGET_GONK
@@ -43,20 +44,20 @@ public:
 
   /**
    * Shutdown the singleton.
    */
   static void Shutdown();
 
   /**
    * Any audio channel agent that starts playing should register itself to
-   * this service, sharing the AudioChannelType.
+   * this service, sharing the AudioChannel.
    */
   virtual void RegisterAudioChannelAgent(AudioChannelAgent* aAgent,
-                                         AudioChannelType aType,
+                                         AudioChannel aChannel,
                                          bool aWithVideo);
 
   /**
    * Any audio channel agent that stops playing should unregister itself to
    * this service.
    */
   virtual void UnregisterAudioChannelAgent(AudioChannelAgent* aAgent);
 
@@ -76,19 +77,21 @@ public:
   /**
    * Return true if a normal or content channel is active for the given
    * process ID.
    */
   virtual bool ProcessContentOrNormalChannelIsActive(uint64_t aChildID);
 
   /***
    * AudioChannelManager calls this function to notify the default channel used
-   * to adjust volume when there is no any active channel.
+   * to adjust volume when there is no any active channel. if aChannel is -1,
+   * the default audio channel will be used. Otherwise aChannel is casted to
+   * AudioChannel enum.
    */
-  virtual void SetDefaultVolumeControlChannel(AudioChannelType aType,
+  virtual void SetDefaultVolumeControlChannel(int32_t aChannel,
                                               bool aHidden);
 
   bool AnyAudioChannelIsActive();
 
   void RefreshAgentsVolume(nsPIDOMWindow* aWindow);
 
 #ifdef MOZ_WIDGET_GONK
   void RegisterSpeakerManager(SpeakerManagerService* aSpeakerManager)
@@ -99,45 +102,48 @@ public:
   }
 
   void UnregisterSpeakerManager(SpeakerManagerService* aSpeakerManager)
   {
     mSpeakerManager.RemoveElement(aSpeakerManager);
   }
 #endif
 
+  static const nsAttrValue::EnumTable* GetAudioChannelTable();
+  static AudioChannel GetAudioChannel(const nsAString& aString);
   static AudioChannel GetDefaultAudioChannel();
-  static void GetDefaultAudioChannelString(nsString& aString);
+  static void GetAudioChannelString(AudioChannel aChannel, nsAString& aString);
+  static void GetDefaultAudioChannelString(nsAString& aString);
 
 protected:
   void Notify();
 
   /**
    * Send the audio-channel-changed notification for the given process ID if
    * needed.
    */
   void SendAudioChannelChangedNotification(uint64_t aChildID);
 
   /* Register/Unregister IPC types: */
-  void RegisterType(AudioChannelType aType, uint64_t aChildID, bool aWithVideo);
-  void UnregisterType(AudioChannelType aType, bool aElementHidden,
+  void RegisterType(AudioChannel aChannel, uint64_t aChildID, bool aWithVideo);
+  void UnregisterType(AudioChannel aChannel, bool aElementHidden,
                       uint64_t aChildID, bool aWithVideo);
-  void UnregisterTypeInternal(AudioChannelType aType, bool aElementHidden,
+  void UnregisterTypeInternal(AudioChannel aChannel, bool aElementHidden,
                               uint64_t aChildID, bool aWithVideo);
 
-  AudioChannelState GetStateInternal(AudioChannelType aType, uint64_t aChildID,
+  AudioChannelState GetStateInternal(AudioChannel aChannel, uint64_t aChildID,
                                      bool aElementHidden,
                                      bool aElementWasHidden);
 
   /* Update the internal type value following the visibility changes */
-  void UpdateChannelType(AudioChannelType aType, uint64_t aChildID,
+  void UpdateChannelType(AudioChannel aChannel, uint64_t aChildID,
                          bool aElementHidden, bool aElementWasHidden);
 
   /* Send the default-volume-channel-changed notification */
-  void SetDefaultVolumeControlChannelInternal(AudioChannelType aType,
+  void SetDefaultVolumeControlChannelInternal(int32_t aChannel,
                                               bool aHidden, uint64_t aChildID);
 
   AudioChannelService();
   virtual ~AudioChannelService();
 
   enum AudioChannelInternalType {
     AUDIO_CHANNEL_INT_NORMAL = 0,
     AUDIO_CHANNEL_INT_NORMAL_HIDDEN,
@@ -156,34 +162,32 @@ protected:
     AUDIO_CHANNEL_INT_LAST
   };
 
   bool ChannelsActiveWithHigherPriorityThan(AudioChannelInternalType aType);
 
   bool CheckVolumeFadedCondition(AudioChannelInternalType aType,
                                  bool aElementHidden);
 
-  const char* ChannelName(AudioChannelType aType);
-
-  AudioChannelInternalType GetInternalType(AudioChannelType aType,
+  AudioChannelInternalType GetInternalType(AudioChannel aChannel,
                                            bool aElementHidden);
 
   class AudioChannelAgentData {
   public:
-    AudioChannelAgentData(AudioChannelType aType,
+    AudioChannelAgentData(AudioChannel aChannel,
                           bool aElementHidden,
                           AudioChannelState aState,
                           bool aWithVideo)
-    : mType(aType)
+    : mChannel(aChannel)
     , mElementHidden(aElementHidden)
     , mState(aState)
     , mWithVideo(aWithVideo)
     {}
 
-    AudioChannelType mType;
+    AudioChannel mChannel;
     bool mElementHidden;
     AudioChannelState mState;
     const bool mWithVideo;
   };
 
   static PLDHashOperator
   NotifyEnumerator(AudioChannelAgent* aAgent,
                    AudioChannelAgentData* aData, void *aUnused);
@@ -202,18 +206,18 @@ protected:
   uint32_t CountWindow(nsIDOMWindow* aWindow);
 
   nsClassHashtable< nsPtrHashKey<AudioChannelAgent>, AudioChannelAgentData > mAgents;
 #ifdef MOZ_WIDGET_GONK
   nsTArray<SpeakerManagerService*>  mSpeakerManager;
 #endif
   nsTArray<uint64_t> mChannelCounters[AUDIO_CHANNEL_INT_LAST];
 
-  AudioChannelType mCurrentHigherChannel;
-  AudioChannelType mCurrentVisibleHigherChannel;
+  int32_t mCurrentHigherChannel;
+  int32_t mCurrentVisibleHigherChannel;
 
   nsTArray<uint64_t> mWithVideoChildIDs;
 
   // mPlayableHiddenContentChildID stores the ChildID of the process which can
   // play content channel(s) in the background.
   // A background process contained content channel(s) will become playable:
   //   1. When this background process registers its content channel(s) in
   //   AudioChannelService and there is no foreground process with registered
--- a/dom/audiochannel/AudioChannelServiceChild.cpp
+++ b/dom/audiochannel/AudioChannelServiceChild.cpp
@@ -67,39 +67,39 @@ AudioChannelServiceChild::GetState(Audio
   AudioChannelAgentData* data;
   if (!mAgents.Get(aAgent, &data)) {
     return AUDIO_CHANNEL_STATE_MUTED;
   }
 
   AudioChannelState state = AUDIO_CHANNEL_STATE_MUTED;
   bool oldElementHidden = data->mElementHidden;
 
-  UpdateChannelType(data->mType, CONTENT_PROCESS_ID_MAIN, aElementHidden, oldElementHidden);
+  UpdateChannelType(data->mChannel, CONTENT_PROCESS_ID_MAIN, aElementHidden,
+                    oldElementHidden);
 
   // Update visibility.
   data->mElementHidden = aElementHidden;
 
   ContentChild* cc = ContentChild::GetSingleton();
-  cc->SendAudioChannelGetState(data->mType, aElementHidden, oldElementHidden, &state);
+  cc->SendAudioChannelGetState(data->mChannel, aElementHidden, oldElementHidden,
+                               &state);
   data->mState = state;
   cc->SendAudioChannelChangedNotification();
 
   return state;
 }
 
 void
 AudioChannelServiceChild::RegisterAudioChannelAgent(AudioChannelAgent* aAgent,
-                                                    AudioChannelType aType,
+                                                    AudioChannel aChannel,
                                                     bool aWithVideo)
 {
-  MOZ_ASSERT(aType != AUDIO_CHANNEL_DEFAULT);
+  AudioChannelService::RegisterAudioChannelAgent(aAgent, aChannel, aWithVideo);
 
-  AudioChannelService::RegisterAudioChannelAgent(aAgent, aType, aWithVideo);
-
-  ContentChild::GetSingleton()->SendAudioChannelRegisterType(aType, aWithVideo);
+  ContentChild::GetSingleton()->SendAudioChannelRegisterType(aChannel, aWithVideo);
 
   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   if (obs) {
     obs->NotifyObservers(nullptr, "audio-channel-agent-changed", nullptr);
   }
 }
 
 void
@@ -112,31 +112,31 @@ AudioChannelServiceChild::UnregisterAudi
 
   // We need to keep a copy because unregister will remove the
   // AudioChannelAgentData object from the hashtable.
   AudioChannelAgentData data(*pData);
 
   AudioChannelService::UnregisterAudioChannelAgent(aAgent);
 
   ContentChild::GetSingleton()->SendAudioChannelUnregisterType(
-      data.mType, data.mElementHidden, data.mWithVideo);
+      data.mChannel, data.mElementHidden, data.mWithVideo);
 
   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   if (obs) {
     obs->NotifyObservers(nullptr, "audio-channel-agent-changed", nullptr);
   }
 #ifdef MOZ_WIDGET_GONK
   bool active = AnyAudioChannelIsActive();
   for (uint32_t i = 0; i < mSpeakerManager.Length(); i++) {
     mSpeakerManager[i]->SetAudioChannelActive(active);
   }
 #endif
 }
 
 void
-AudioChannelServiceChild::SetDefaultVolumeControlChannel(
-  AudioChannelType aType, bool aHidden)
+AudioChannelServiceChild::SetDefaultVolumeControlChannel(int32_t aChannel,
+                                                         bool aHidden)
 {
   ContentChild *cc = ContentChild::GetSingleton();
   if (cc) {
-    cc->SendAudioChannelChangeDefVolChannel(aType, aHidden);
+    cc->SendAudioChannelChangeDefVolChannel(aChannel, aHidden);
   }
 }
--- a/dom/audiochannel/AudioChannelServiceChild.h
+++ b/dom/audiochannel/AudioChannelServiceChild.h
@@ -26,28 +26,29 @@ public:
    *
    * @return NS_OK on proper assignment, NS_ERROR_FAILURE otherwise.
    */
   static AudioChannelService* GetAudioChannelService();
 
   static void Shutdown();
 
   virtual void RegisterAudioChannelAgent(AudioChannelAgent* aAgent,
-                                         AudioChannelType aType,
+                                         AudioChannel aChannel,
                                          bool aWithVideo);
   virtual void UnregisterAudioChannelAgent(AudioChannelAgent* aAgent);
 
   /**
    * Return the state to indicate this agent should keep playing/
    * fading volume/muted.
    */
   virtual AudioChannelState GetState(AudioChannelAgent* aAgent,
                                      bool aElementHidden);
 
-  virtual void SetDefaultVolumeControlChannel(AudioChannelType aType, bool aHidden);
+  virtual void SetDefaultVolumeControlChannel(int32_t aChannel,
+                                              bool aHidden);
 
 protected:
   AudioChannelServiceChild();
   virtual ~AudioChannelServiceChild();
 };
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/audiochannel/tests/TestAudioChannelService.cpp
+++ b/dom/audiochannel/tests/TestAudioChannelService.cpp
@@ -26,18 +26,18 @@
 using namespace mozilla::dom;
 
 class Agent : public nsIAudioChannelAgentCallback,
               public nsSupportsWeakReference
 {
 public:
   NS_DECL_ISUPPORTS
 
-  Agent(AudioChannelType aType)
-  : mType(aType)
+  Agent(AudioChannel aChannel)
+  : mChannel(aChannel)
   , mWaitCallback(false)
   , mRegistered(false)
   , mCanPlay(AUDIO_CHANNEL_STATE_MUTED)
   {
     mAgent = do_CreateInstance("@mozilla.org/audiochannelagent;1");
   }
 
   virtual ~Agent()
@@ -46,20 +46,22 @@ public:
       StopPlaying();
     }
   }
 
   nsresult Init(bool video=false)
   {
     nsresult rv = NS_OK;
     if (video) {
-      rv = mAgent->InitWithVideo(nullptr, mType, this, true);
+      rv = mAgent->InitWithVideo(nullptr, static_cast<int32_t>(mChannel),
+                                 this, true);
     }
     else {
-      rv = mAgent->InitWithWeakCallback(nullptr, mType, this);
+      rv = mAgent->InitWithWeakCallback(nullptr, static_cast<int32_t>(mChannel),
+                                        this);
     }
     NS_ENSURE_SUCCESS(rv, rv);
 
     return mAgent->SetVisibilityState(false);
   }
 
   nsresult StartPlaying(AudioChannelState *_ret)
   {
@@ -122,29 +124,29 @@ public:
         TEST_ENSURE_BASE(false, "GetCanPlay timeout");
       }
     }
     *_ret = mCanPlay;
     return NS_OK;
   }
 
   nsCOMPtr<nsIAudioChannelAgent> mAgent;
-  AudioChannelType mType;
+  AudioChannel mChannel;
   bool mWaitCallback;
   bool mRegistered;
   AudioChannelState mCanPlay;
 };
 
 NS_IMPL_ISUPPORTS2(Agent, nsIAudioChannelAgentCallback,
                    nsISupportsWeakReference)
 
 nsresult
 TestDoubleStartPlaying()
 {
-  nsRefPtr<Agent> agent = new Agent(AUDIO_CHANNEL_NORMAL);
+  nsRefPtr<Agent> agent = new Agent(AudioChannel::Normal);
 
   nsresult rv = agent->Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
   AudioChannelState playable;
   rv = agent->mAgent->StartPlaying((int32_t *)&playable);
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -153,17 +155,17 @@ TestDoubleStartPlaying()
     "Test0: StartPlaying calling twice must return error");
 
   return NS_OK;
 }
 
 nsresult
 TestOneNormalChannel()
 {
-  nsRefPtr<Agent> agent = new Agent(AUDIO_CHANNEL_NORMAL);
+  nsRefPtr<Agent> agent = new Agent(AudioChannel::Normal);
   nsresult rv = agent->Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
   AudioChannelState playable;
   rv = agent->StartPlaying(&playable);
   NS_ENSURE_SUCCESS(rv, rv);
   TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_MUTED,
     "Test1: A normal channel unvisible agent must be muted");
@@ -177,21 +179,21 @@ TestOneNormalChannel()
     "Test1: A normal channel visible agent must be playable");
 
   return rv;
 }
 
 nsresult
 TestTwoNormalChannels()
 {
-  nsRefPtr<Agent> agent1 = new Agent(AUDIO_CHANNEL_NORMAL);
+  nsRefPtr<Agent> agent1 = new Agent(AudioChannel::Normal);
   nsresult rv = agent1->Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsRefPtr<Agent> agent2 = new Agent(AUDIO_CHANNEL_NORMAL);
+  nsRefPtr<Agent> agent2 = new Agent(AudioChannel::Normal);
   rv = agent2->Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
   AudioChannelState playable;
   rv = agent1->StartPlaying(&playable);
   NS_ENSURE_SUCCESS(rv, rv);
   TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_MUTED,
     "Test2: A normal channel unvisible agent1 must be muted");
@@ -218,21 +220,21 @@ TestTwoNormalChannels()
     "Test2: A normal channel visible agent2 must be playable");
 
   return rv;
 }
 
 nsresult
 TestContentChannels()
 {
-  nsRefPtr<Agent> agent1 = new Agent(AUDIO_CHANNEL_CONTENT);
+  nsRefPtr<Agent> agent1 = new Agent(AudioChannel::Content);
   nsresult rv = agent1->Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsRefPtr<Agent> agent2 = new Agent(AUDIO_CHANNEL_CONTENT);
+  nsRefPtr<Agent> agent2 = new Agent(AudioChannel::Content);
   rv = agent2->Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
   // All content channels in the foreground can be allowed to play
   rv = agent1->SetVisibilityState(true);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = agent2->SetVisibilityState(true);
@@ -303,25 +305,25 @@ TestContentChannels()
     "from background state");
 
   return rv;
 }
 
 nsresult
 TestFadedState()
 {
-  nsRefPtr<Agent> normalAgent = new Agent(AUDIO_CHANNEL_NORMAL);
+  nsRefPtr<Agent> normalAgent = new Agent(AudioChannel::Normal);
   nsresult rv = normalAgent->Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsRefPtr<Agent> contentAgent = new Agent(AUDIO_CHANNEL_CONTENT);
+  nsRefPtr<Agent> contentAgent = new Agent(AudioChannel::Content);
   rv = contentAgent->Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsRefPtr<Agent> notificationAgent = new Agent(AUDIO_CHANNEL_NOTIFICATION);
+  nsRefPtr<Agent> notificationAgent = new Agent(AudioChannel::Notification);
   rv = notificationAgent->Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = normalAgent->SetVisibilityState(true);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = contentAgent->SetVisibilityState(true);
   NS_ENSURE_SUCCESS(rv, rv);
@@ -382,42 +384,42 @@ TestFadedState()
   NS_ENSURE_SUCCESS(rv, rv);
 
   return rv;
 }
 
 nsresult
 TestPriorities()
 {
-  nsRefPtr<Agent> normalAgent = new Agent(AUDIO_CHANNEL_NORMAL);
+  nsRefPtr<Agent> normalAgent = new Agent(AudioChannel::Normal);
   nsresult rv = normalAgent->Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsRefPtr<Agent> contentAgent = new Agent(AUDIO_CHANNEL_CONTENT);
+  nsRefPtr<Agent> contentAgent = new Agent(AudioChannel::Content);
   rv = contentAgent->Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsRefPtr<Agent> notificationAgent = new Agent(AUDIO_CHANNEL_NOTIFICATION);
+  nsRefPtr<Agent> notificationAgent = new Agent(AudioChannel::Notification);
   rv = notificationAgent->Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsRefPtr<Agent> alarmAgent = new Agent(AUDIO_CHANNEL_ALARM);
+  nsRefPtr<Agent> alarmAgent = new Agent(AudioChannel::Alarm);
   rv = alarmAgent->Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsRefPtr<Agent> telephonyAgent = new Agent(AUDIO_CHANNEL_TELEPHONY);
+  nsRefPtr<Agent> telephonyAgent = new Agent(AudioChannel::Telephony);
   rv = telephonyAgent->Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsRefPtr<Agent> ringerAgent = new Agent(AUDIO_CHANNEL_RINGER);
+  nsRefPtr<Agent> ringerAgent = new Agent(AudioChannel::Ringer);
   rv = ringerAgent->Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsRefPtr<Agent> pNotificationAgent =
-    new Agent(AUDIO_CHANNEL_PUBLICNOTIFICATION);
+    new Agent(AudioChannel::Publicnotification);
   rv = pNotificationAgent->Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
   AudioChannelState playable;
 
   rv = normalAgent->StartPlaying(&playable);
   NS_ENSURE_SUCCESS(rv, rv);
   TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_MUTED,
@@ -539,21 +541,21 @@ TestPriorities()
     "Test5: A pNotification channel visible agent must be playable");
 
   return rv;
 }
 
 nsresult
 TestOneVideoNormalChannel()
 {
-  nsRefPtr<Agent> agent1 = new Agent(AUDIO_CHANNEL_NORMAL);
+  nsRefPtr<Agent> agent1 = new Agent(AudioChannel::Normal);
   nsresult rv = agent1->Init(true);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsRefPtr<Agent> agent2 = new Agent(AUDIO_CHANNEL_CONTENT);
+  nsRefPtr<Agent> agent2 = new Agent(AudioChannel::Content);
   rv = agent2->Init(false);
   NS_ENSURE_SUCCESS(rv, rv);
 
   AudioChannelState playable;
   rv = agent1->StartPlaying(&playable);
   NS_ENSURE_SUCCESS(rv, rv);
   TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_MUTED,
     "Test6: A video normal channel invisible agent1 must be muted");
@@ -644,21 +646,21 @@ int main(int argc, char** argv)
   if (NS_FAILED(TestContentChannels())) {
     return 1;
   }
 
   if (NS_FAILED(TestFadedState())) {
     return 1;
   }
 
-  // Channel type with AUDIO_CHANNEL_TELEPHONY cannot be unregistered until the
+  // Channel type with AudioChannel::Telephony cannot be unregistered until the
   // main thread has chances to process 1500 millisecond timer. In order to
   // skip ambiguous return value of ChannelsActiveWithHigherPriorityThan(), new
   // test cases are added before any test case that registers the channel type
-  // with AUDIO_CHANNEL_TELEPHONY channel.
+  // with AudioChannel::Telephony channel.
   if (NS_FAILED(TestOneVideoNormalChannel())) {
     return 1;
   }
 
   if (NS_FAILED(TestPriorities())) {
     return 1;
   }
 
--- a/dom/audiochannel/tests/moz.build
+++ b/dom/audiochannel/tests/moz.build
@@ -3,10 +3,13 @@
 # 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/.
 
 CPP_UNIT_TESTS += [
     'TestAudioChannelService.cpp',
 ]
 
+if CONFIG['OS_ARCH'] == 'WINNT':
+    DEFINES['NOMINMAX'] = True
+
 FAIL_ON_WARNINGS = True
 
--- a/dom/camera/DOMCameraControl.cpp
+++ b/dom/camera/DOMCameraControl.cpp
@@ -722,17 +722,17 @@ nsDOMCameraControl::StartRecording(const
 
   NotifyRecordingStatusChange(NS_LITERAL_STRING("starting"));
 
 #ifdef MOZ_B2G
   if (!mAudioChannelAgent) {
     mAudioChannelAgent = do_CreateInstance("@mozilla.org/audiochannelagent;1");
     if (mAudioChannelAgent) {
       // Camera app will stop recording when it falls to the background, so no callback is necessary.
-      mAudioChannelAgent->Init(mWindow, AUDIO_CHANNEL_CONTENT, nullptr);
+      mAudioChannelAgent->Init(mWindow, (int32_t)AudioChannel::Content, nullptr);
       // Video recording doesn't output any sound, so it's not necessary to check canPlay.
       int32_t canPlay;
       mAudioChannelAgent->StartPlaying(&canPlay);
     }
   }
 #endif
 
   nsCOMPtr<nsIDOMDOMRequest> request;
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -1894,75 +1894,75 @@ ContentParent::RecvFirstIdle()
     // 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.
     PreallocatedProcessManager::AllocateAfterDelay();
     return true;
 }
 
 bool
-ContentParent::RecvAudioChannelGetState(const AudioChannelType& aType,
+ContentParent::RecvAudioChannelGetState(const AudioChannel& aChannel,
                                         const bool& aElementHidden,
                                         const bool& aElementWasHidden,
                                         AudioChannelState* aState)
 {
     nsRefPtr<AudioChannelService> service =
         AudioChannelService::GetAudioChannelService();
     *aState = AUDIO_CHANNEL_STATE_NORMAL;
     if (service) {
-        *aState = service->GetStateInternal(aType, mChildID,
+        *aState = service->GetStateInternal(aChannel, mChildID,
                                             aElementHidden, aElementWasHidden);
     }
     return true;
 }
 
 bool
-ContentParent::RecvAudioChannelRegisterType(const AudioChannelType& aType,
+ContentParent::RecvAudioChannelRegisterType(const AudioChannel& aChannel,
                                             const bool& aWithVideo)
 {
     nsRefPtr<AudioChannelService> service =
         AudioChannelService::GetAudioChannelService();
     if (service) {
-        service->RegisterType(aType, mChildID, aWithVideo);
+        service->RegisterType(aChannel, mChildID, aWithVideo);
     }
     return true;
 }
 
 bool
-ContentParent::RecvAudioChannelUnregisterType(const AudioChannelType& aType,
+ContentParent::RecvAudioChannelUnregisterType(const AudioChannel& aChannel,
                                               const bool& aElementHidden,
                                               const bool& aWithVideo)
 {
     nsRefPtr<AudioChannelService> service =
         AudioChannelService::GetAudioChannelService();
     if (service) {
-        service->UnregisterType(aType, aElementHidden, mChildID, aWithVideo);
+        service->UnregisterType(aChannel, aElementHidden, mChildID, aWithVideo);
     }
     return true;
 }
 
 bool
 ContentParent::RecvAudioChannelChangedNotification()
 {
     nsRefPtr<AudioChannelService> service =
         AudioChannelService::GetAudioChannelService();
     if (service) {
        service->SendAudioChannelChangedNotification(ChildID());
     }
     return true;
 }
 
 bool
-ContentParent::RecvAudioChannelChangeDefVolChannel(
-  const AudioChannelType& aType, const bool& aHidden)
+ContentParent::RecvAudioChannelChangeDefVolChannel(const int32_t& aChannel,
+                                                   const bool& aHidden)
 {
     nsRefPtr<AudioChannelService> service =
         AudioChannelService::GetAudioChannelService();
     if (service) {
-       service->SetDefaultVolumeControlChannelInternal(aType,
+       service->SetDefaultVolumeControlChannelInternal(aChannel,
                                                        aHidden, mChildID);
     }
     return true;
 }
 
 bool
 ContentParent::RecvBroadcastVolume(const nsString& aVolumeName)
 {
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -485,30 +485,30 @@ private:
                                  const uint32_t& aColNumber,
                                  const uint32_t& aFlags,
                                  const nsCString& aCategory) MOZ_OVERRIDE;
 
     virtual bool RecvPrivateDocShellsExist(const bool& aExist) MOZ_OVERRIDE;
 
     virtual bool RecvFirstIdle() MOZ_OVERRIDE;
 
-    virtual bool RecvAudioChannelGetState(const AudioChannelType& aType,
+    virtual bool RecvAudioChannelGetState(const AudioChannel& aChannel,
                                           const bool& aElementHidden,
                                           const bool& aElementWasHidden,
                                           AudioChannelState* aValue) MOZ_OVERRIDE;
 
-    virtual bool RecvAudioChannelRegisterType(const AudioChannelType& aType,
+    virtual bool RecvAudioChannelRegisterType(const AudioChannel& aChannel,
                                               const bool& aWithVideo) MOZ_OVERRIDE;
-    virtual bool RecvAudioChannelUnregisterType(const AudioChannelType& aType,
+    virtual bool RecvAudioChannelUnregisterType(const AudioChannel& aChannel,
                                                 const bool& aElementHidden,
                                                 const bool& aWithVideo) MOZ_OVERRIDE;
 
     virtual bool RecvAudioChannelChangedNotification() MOZ_OVERRIDE;
 
-    virtual bool RecvAudioChannelChangeDefVolChannel(const AudioChannelType& aType,
+    virtual bool RecvAudioChannelChangeDefVolChannel(const int32_t& aChannel,
                                                      const bool& aHidden) MOZ_OVERRIDE;
 
     virtual bool RecvBroadcastVolume(const nsString& aVolumeName) MOZ_OVERRIDE;
 
     virtual bool RecvSpeakerManagerGetSpeakerStatus(bool* aValue) MOZ_OVERRIDE;
 
     virtual bool RecvSpeakerManagerForceSpeaker(const bool& aEnable) MOZ_OVERRIDE;
 
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -41,17 +41,17 @@ using struct ResourceMapping from "mozil
 using struct OverrideMapping from "mozilla/chrome/RegistryMessageUtils.h";
 using base::ChildPrivileges from "base/process_util.h";
 using struct IPC::Permission from "mozilla/net/NeckoMessageUtils.h";
 using class IPC::Principal from "mozilla/dom/PermissionMessageUtils.h";
 using struct mozilla::null_t from "ipc/IPCMessageUtils.h";
 using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
 using mozilla::dom::asmjscache::OpenMode from "mozilla/dom/asmjscache/AsmJSCache.h";
 using mozilla::dom::asmjscache::WriteParams from "mozilla/dom/asmjscache/AsmJSCache.h";
-using mozilla::dom::AudioChannelType from "AudioChannelCommon.h";
+using mozilla::dom::AudioChannel from "mozilla/dom/AudioChannelBinding.h";
 using mozilla::dom::AudioChannelState from "AudioChannelCommon.h";
 using mozilla::dom::NativeThreadId from "mozilla/dom/TabMessageUtils.h";
 using mozilla::hal::ProcessPriority from "mozilla/HalTypes.h";
 using gfxIntSize from "nsSize.h";
 
 namespace mozilla {
 namespace dom {
 
@@ -510,28 +510,27 @@ parent:
 
     // 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 AudioChannelGetState(AudioChannelType aType, bool aElementHidden,
+    sync AudioChannelGetState(AudioChannel aChannel, bool aElementHidden,
                               bool aElementWasHidden)
         returns (AudioChannelState value);
 
-    sync AudioChannelRegisterType(AudioChannelType aType, bool aWithVideo);
-    sync AudioChannelUnregisterType(AudioChannelType aType,
+    sync AudioChannelRegisterType(AudioChannel aChannel, bool aWithVideo);
+    sync AudioChannelUnregisterType(AudioChannel aChannel,
                                     bool aElementHidden,
                                     bool aWithVideo);
 
     async AudioChannelChangedNotification();
-    async AudioChannelChangeDefVolChannel(AudioChannelType aType,
-                                          bool aHidden);
+    async AudioChannelChangeDefVolChannel(int32_t aChannel, bool aHidden);
 
     async FilePathUpdateNotify(nsString aType,
                                nsString aStorageName,
                                nsString aFilepath,
                                nsCString aReason);
     // get nsIVolumeService to broadcast volume information
     async BroadcastVolume(nsString volumeName);
 
--- a/dom/ipc/TabMessageUtils.h
+++ b/dom/ipc/TabMessageUtils.h
@@ -3,16 +3,17 @@
  * 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 "mozilla/dom/AudioChannelBinding.h"
 #include "nsIDOMEvent.h"
 #include "nsCOMPtr.h"
 
 #ifdef MOZ_CRASHREPORTER
 #include "nsExceptionHandler.h"
 #endif
 
 namespace mozilla {
@@ -53,26 +54,48 @@ 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_DEFAULT,
-                          mozilla::dom::AUDIO_CHANNEL_LAST>
-{ };
+template<>
+struct ParamTraits<mozilla::dom::AudioChannel>
+{
+  typedef mozilla::dom::AudioChannel paramType;
+
+  static bool IsLegalValue(const paramType &aValue) {
+    return aValue <= mozilla::dom::AudioChannel::Publicnotification;
+  }
+
+  static void Write(Message* aMsg, const paramType& aValue) {
+    MOZ_ASSERT(IsLegalValue(aValue));
+    WriteParam(aMsg, (uint32_t)aValue);
+  }
+
+  static bool Read(const Message* aMsg, void** aIter, paramType* aResult) {
+    uint32_t value;
+    if(!ReadParam(aMsg, aIter, &value) ||
+       !IsLegalValue(paramType(value))) {
+      return false;
+    }
+    *aResult = paramType(value);
+    return true;
+  }
+
+  static void Log(const paramType& aParam, std::wstring* aLog)
+  {
+  }
+};
 
 template <>
 struct ParamTraits<mozilla::dom::AudioChannelState>
   : public EnumSerializer<mozilla::dom::AudioChannelState,
-                           mozilla::dom::AUDIO_CHANNEL_STATE_NORMAL,
-                           mozilla::dom::AUDIO_CHANNEL_STATE_LAST>
+                          mozilla::dom::AUDIO_CHANNEL_STATE_NORMAL,
+                          mozilla::dom::AUDIO_CHANNEL_STATE_LAST>
 { };
 
 }
 
 
 #endif
--- a/dom/system/gonk/AudioChannelManager.cpp
+++ b/dom/system/gonk/AudioChannelManager.cpp
@@ -20,17 +20,17 @@ namespace system {
 
 NS_IMPL_QUERY_INTERFACE_INHERITED1(AudioChannelManager, DOMEventTargetHelper,
                                    nsIDOMEventListener)
 NS_IMPL_ADDREF_INHERITED(AudioChannelManager, DOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(AudioChannelManager, DOMEventTargetHelper)
 
 AudioChannelManager::AudioChannelManager()
   : mState(SWITCH_STATE_UNKNOWN)
-  , mVolumeChannel(AUDIO_CHANNEL_DEFAULT)
+  , mVolumeChannel(-1)
 {
   RegisterSwitchObserver(SWITCH_HEADPHONES, this);
   mState = GetCurrentSwitchState(SWITCH_HEADPHONES);
   SetIsDOMBinding();
 }
 
 AudioChannelManager::~AudioChannelManager()
 {
@@ -75,69 +75,51 @@ AudioChannelManager::Notify(const Switch
 
 bool
 AudioChannelManager::SetVolumeControlChannel(const nsAString& aChannel)
 {
   if (aChannel.EqualsASCII("publicnotification")) {
     return false;
   }
 
-  AudioChannelType oldVolumeChannel = mVolumeChannel;
+  AudioChannel newChannel = AudioChannelService::GetAudioChannel(aChannel);
+
   // Only normal channel doesn't need permission.
-  if (aChannel.EqualsASCII("normal")) {
-    mVolumeChannel = AUDIO_CHANNEL_NORMAL;
-  } else {
+  if (newChannel != AudioChannel::Normal) {
     nsCOMPtr<nsIPermissionManager> permissionManager =
       do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
     if (!permissionManager) {
       return false;
     }
     uint32_t perm = nsIPermissionManager::UNKNOWN_ACTION;
     permissionManager->TestPermissionFromWindow(GetOwner(),
       nsCString(NS_LITERAL_CSTRING("audio-channel-") +
       NS_ConvertUTF16toUTF8(aChannel)).get(), &perm);
     if (perm != nsIPermissionManager::ALLOW_ACTION) {
       return false;
     }
-
-    if (aChannel.EqualsASCII("content")) {
-      mVolumeChannel = AUDIO_CHANNEL_CONTENT;
-    } else if (aChannel.EqualsASCII("notification")) {
-      mVolumeChannel = AUDIO_CHANNEL_NOTIFICATION;
-    } else if (aChannel.EqualsASCII("alarm")) {
-      mVolumeChannel = AUDIO_CHANNEL_ALARM;
-    } else if (aChannel.EqualsASCII("telephony")) {
-      mVolumeChannel = AUDIO_CHANNEL_TELEPHONY;
-    } else if (aChannel.EqualsASCII("ringer")) {
-      mVolumeChannel = AUDIO_CHANNEL_RINGER;
-    }
   }
 
-  if (oldVolumeChannel == mVolumeChannel) {
+  if (mVolumeChannel == (int32_t)newChannel) {
     return true;
   }
+
+  mVolumeChannel = (int32_t)newChannel;
+
   NotifyVolumeControlChannelChanged();
   return true;
 }
 
 bool
 AudioChannelManager::GetVolumeControlChannel(nsAString & aChannel)
 {
-  if (mVolumeChannel == AUDIO_CHANNEL_NORMAL) {
-    aChannel.AssignASCII("normal");
-  } else if (mVolumeChannel == AUDIO_CHANNEL_CONTENT) {
-    aChannel.AssignASCII("content");
-  } else if (mVolumeChannel == AUDIO_CHANNEL_NOTIFICATION) {
-    aChannel.AssignASCII("notification");
-  } else if (mVolumeChannel == AUDIO_CHANNEL_ALARM) {
-    aChannel.AssignASCII("alarm");
-  } else if (mVolumeChannel == AUDIO_CHANNEL_TELEPHONY) {
-    aChannel.AssignASCII("telephony");
-  } else if (mVolumeChannel == AUDIO_CHANNEL_RINGER) {
-    aChannel.AssignASCII("ringer");
+  if (mVolumeChannel >= 0) {
+    AudioChannelService::GetAudioChannelString(
+                                      static_cast<AudioChannel>(mVolumeChannel),
+                                      aChannel);
   } else {
     aChannel.AssignASCII("");
   }
 
   return true;
 }
 
 void
@@ -148,17 +130,17 @@ AudioChannelManager::NotifyVolumeControl
 
   bool isActive = false;
   docshell->GetIsActive(&isActive);
 
   AudioChannelService* service = AudioChannelService::GetAudioChannelService();
   if (isActive) {
     service->SetDefaultVolumeControlChannel(mVolumeChannel, isActive);
   } else {
-    service->SetDefaultVolumeControlChannel(AUDIO_CHANNEL_DEFAULT, isActive);
+    service->SetDefaultVolumeControlChannel(-1, isActive);
   }
 }
 
 NS_IMETHODIMP
 AudioChannelManager::HandleEvent(nsIDOMEvent* aEvent)
 {
   nsAutoString type;
   aEvent->GetType(type);
--- a/dom/system/gonk/AudioChannelManager.h
+++ b/dom/system/gonk/AudioChannelManager.h
@@ -61,16 +61,16 @@ public:
   bool GetVolumeControlChannel(nsAString& aChannel);
 
   IMPL_EVENT_HANDLER(headphoneschange)
 
 private:
   void NotifyVolumeControlChannelChanged();
 
   hal::SwitchState mState;
-  AudioChannelType mVolumeChannel;
+  int32_t mVolumeChannel;
 };
 
 } // namespace system
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_system_AudioChannelManager_h
--- a/dom/system/gonk/AudioManager.cpp
+++ b/dom/system/gonk/AudioManager.cpp
@@ -124,24 +124,27 @@ public:
   NS_IMETHOD Handle(const nsAString& aName, JS::Handle<JS::Value> aResult)
   {
     nsCOMPtr<nsIAudioManager> audioManager =
       do_GetService(NS_AUDIOMANAGER_CONTRACTID);
     NS_ENSURE_TRUE(JSVAL_IS_INT(aResult), NS_OK);
 
     int32_t volIndex = JSVAL_TO_INT(aResult);
     if (aName.EqualsLiteral("audio.volume.content")) {
-      audioManager->SetAudioChannelVolume(AUDIO_CHANNEL_CONTENT, volIndex);
+      audioManager->SetAudioChannelVolume((int32_t)AudioChannel::Content,
+                                          volIndex);
     } else if (aName.EqualsLiteral("audio.volume.notification")) {
-      audioManager->SetAudioChannelVolume(AUDIO_CHANNEL_NOTIFICATION,
+      audioManager->SetAudioChannelVolume((int32_t)AudioChannel::Notification,
                                           volIndex);
     } else if (aName.EqualsLiteral("audio.volume.alarm")) {
-      audioManager->SetAudioChannelVolume(AUDIO_CHANNEL_ALARM, volIndex);
+      audioManager->SetAudioChannelVolume((int32_t)AudioChannel::Alarm,
+                                          volIndex);
     } else if (aName.EqualsLiteral("audio.volume.telephony")) {
-      audioManager->SetAudioChannelVolume(AUDIO_CHANNEL_TELEPHONY, volIndex);
+      audioManager->SetAudioChannelVolume((int32_t)AudioChannel::Telephony,
+                                          volIndex);
     } else if (aName.EqualsLiteral("audio.volume.bt_sco")) {
       static_cast<AudioManager *>(audioManager.get())->SetStreamVolumeIndex(
         AUDIO_STREAM_BLUETOOTH_SCO, volIndex);
     } else {
       MOZ_ASSUME_UNREACHABLE("unexpected audio channel for initializing "
                              "volume control");
     }
 
@@ -526,19 +529,19 @@ AudioManager::SetPhoneState(int32_t aSta
     mPhoneAudioAgent = nullptr;
   }
 
   if (aState == PHONE_STATE_IN_CALL || aState == PHONE_STATE_RINGTONE) {
     mPhoneAudioAgent = do_CreateInstance("@mozilla.org/audiochannelagent;1");
     MOZ_ASSERT(mPhoneAudioAgent);
     if (aState == PHONE_STATE_IN_CALL) {
       // Telephony doesn't be paused by any other channels.
-      mPhoneAudioAgent->Init(nullptr, AUDIO_CHANNEL_TELEPHONY, nullptr);
+      mPhoneAudioAgent->Init(nullptr, (int32_t)AudioChannel::Telephony, nullptr);
     } else {
-      mPhoneAudioAgent->Init(nullptr, AUDIO_CHANNEL_RINGER, nullptr);
+      mPhoneAudioAgent->Init(nullptr, (int32_t)AudioChannel::Ringer, nullptr);
     }
 
     // Telephony can always play.
     int32_t canPlay;
     mPhoneAudioAgent->StartPlaying(&canPlay);
   }
 
   return NS_OK;
@@ -603,97 +606,97 @@ AudioManager::SetFmRadioAudioEnabled(boo
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 }
 
 NS_IMETHODIMP
 AudioManager::SetAudioChannelVolume(int32_t aChannel, int32_t aIndex) {
   nsresult status;
 
-  switch (aChannel) {
-    case AUDIO_CHANNEL_CONTENT:
+  switch (static_cast<AudioChannel>(aChannel)) {
+    case AudioChannel::Content:
       // sync FMRadio's volume with content channel.
       if (IsDeviceOn(AUDIO_DEVICE_OUT_FM)) {
         status = SetStreamVolumeIndex(AUDIO_STREAM_FM, aIndex);
         NS_ENSURE_SUCCESS(status, status);
       }
       status = SetStreamVolumeIndex(AUDIO_STREAM_MUSIC, aIndex);
       NS_ENSURE_SUCCESS(status, status);
       status = SetStreamVolumeIndex(AUDIO_STREAM_SYSTEM, aIndex);
       break;
-    case AUDIO_CHANNEL_NOTIFICATION:
+    case AudioChannel::Notification:
       status = SetStreamVolumeIndex(AUDIO_STREAM_NOTIFICATION, aIndex);
       NS_ENSURE_SUCCESS(status, status);
       status = SetStreamVolumeIndex(AUDIO_STREAM_RING, aIndex);
       break;
-    case AUDIO_CHANNEL_ALARM:
+    case AudioChannel::Alarm:
       status = SetStreamVolumeIndex(AUDIO_STREAM_ALARM, aIndex);
       break;
-    case AUDIO_CHANNEL_TELEPHONY:
+    case AudioChannel::Telephony:
       status = SetStreamVolumeIndex(AUDIO_STREAM_VOICE_CALL, aIndex);
       break;
     default:
       return NS_ERROR_INVALID_ARG;
   }
 
   return status;
 }
 
 NS_IMETHODIMP
 AudioManager::GetAudioChannelVolume(int32_t aChannel, int32_t* aIndex) {
   if (!aIndex) {
     return NS_ERROR_NULL_POINTER;
   }
 
-  switch (aChannel) {
-    case AUDIO_CHANNEL_CONTENT:
+  switch (static_cast<AudioChannel>(aChannel)) {
+    case AudioChannel::Content:
       MOZ_ASSERT(mCurrentStreamVolumeTbl[AUDIO_STREAM_MUSIC] ==
                  mCurrentStreamVolumeTbl[AUDIO_STREAM_SYSTEM]);
       *aIndex = mCurrentStreamVolumeTbl[AUDIO_STREAM_MUSIC];
       break;
-    case AUDIO_CHANNEL_NOTIFICATION:
+    case AudioChannel::Notification:
       MOZ_ASSERT(mCurrentStreamVolumeTbl[AUDIO_STREAM_NOTIFICATION] ==
                  mCurrentStreamVolumeTbl[AUDIO_STREAM_RING]);
       *aIndex = mCurrentStreamVolumeTbl[AUDIO_STREAM_NOTIFICATION];
       break;
-    case AUDIO_CHANNEL_ALARM:
+    case AudioChannel::Alarm:
       *aIndex = mCurrentStreamVolumeTbl[AUDIO_STREAM_ALARM];
       break;
-    case AUDIO_CHANNEL_TELEPHONY:
+    case AudioChannel::Telephony:
       *aIndex = mCurrentStreamVolumeTbl[AUDIO_STREAM_VOICE_CALL];
       break;
     default:
       return NS_ERROR_INVALID_ARG;
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 AudioManager::GetMaxAudioChannelVolume(int32_t aChannel, int32_t* aMaxIndex) {
   if (!aMaxIndex) {
     return NS_ERROR_NULL_POINTER;
   }
 
   int32_t stream;
-  switch (aChannel) {
-    case AUDIO_CHANNEL_CONTENT:
+  switch (static_cast<AudioChannel>(aChannel)) {
+    case AudioChannel::Content:
       MOZ_ASSERT(sMaxStreamVolumeTbl[AUDIO_STREAM_MUSIC] ==
                  sMaxStreamVolumeTbl[AUDIO_STREAM_SYSTEM]);
       stream = AUDIO_STREAM_MUSIC;
       break;
-    case AUDIO_CHANNEL_NOTIFICATION:
+    case AudioChannel::Notification:
       MOZ_ASSERT(sMaxStreamVolumeTbl[AUDIO_STREAM_NOTIFICATION] ==
                  sMaxStreamVolumeTbl[AUDIO_STREAM_RING]);
       stream = AUDIO_STREAM_NOTIFICATION;
       break;
-    case AUDIO_CHANNEL_ALARM:
+    case AudioChannel::Alarm:
       stream = AUDIO_STREAM_ALARM;
       break;
-    case AUDIO_CHANNEL_TELEPHONY:
+    case AudioChannel::Telephony:
       stream = AUDIO_STREAM_VOICE_CALL;
       break;
     default:
       return NS_ERROR_INVALID_ARG;
   }
 
   *aMaxIndex = sMaxStreamVolumeTbl[stream];
    return NS_OK;