LCOV - code coverage report
Current view: top level - dom/audiochannel - AudioChannelAgent.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 29 158 18.4 %
Date: 2017-07-14 16:53:18 Functions: 6 28 21.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "AudioChannelAgent.h"
       8             : #include "AudioChannelService.h"
       9             : #include "mozilla/Preferences.h"
      10             : #include "nsContentUtils.h"
      11             : #include "nsIDocument.h"
      12             : #include "nsIDOMWindow.h"
      13             : #include "nsPIDOMWindow.h"
      14             : #include "nsIURI.h"
      15             : 
      16             : using namespace mozilla::dom;
      17             : 
      18             : NS_IMPL_CYCLE_COLLECTION_CLASS(AudioChannelAgent)
      19             : 
      20           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(AudioChannelAgent)
      21           0 :   tmp->Shutdown();
      22           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
      23           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mCallback)
      24           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
      25             : 
      26           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(AudioChannelAgent)
      27           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
      28           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCallback)
      29           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
      30             : 
      31           1 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AudioChannelAgent)
      32           0 :   NS_INTERFACE_MAP_ENTRY(nsIAudioChannelAgent)
      33           0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
      34           0 : NS_INTERFACE_MAP_END
      35             : 
      36           1 : NS_IMPL_CYCLE_COLLECTING_ADDREF(AudioChannelAgent)
      37           0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(AudioChannelAgent)
      38             : 
      39           1 : AudioChannelAgent::AudioChannelAgent()
      40             :   : mAudioChannelType(AUDIO_AGENT_CHANNEL_ERROR)
      41             :   , mInnerWindowID(0)
      42           1 :   , mIsRegToService(false)
      43             : {
      44             :   // Init service in the begining, it can help us to know whether there is any
      45             :   // created media component via AudioChannelService::IsServiceStarted().
      46           1 :   RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
      47           1 : }
      48             : 
      49           0 : AudioChannelAgent::~AudioChannelAgent()
      50             : {
      51           0 :   Shutdown();
      52           0 : }
      53             : 
      54             : void
      55           0 : AudioChannelAgent::Shutdown()
      56             : {
      57           0 :   if (mIsRegToService) {
      58           0 :     NotifyStoppedPlaying();
      59             :   }
      60           0 : }
      61             : 
      62           0 : NS_IMETHODIMP AudioChannelAgent::GetAudioChannelType(int32_t *aAudioChannelType)
      63             : {
      64           0 :   *aAudioChannelType = mAudioChannelType;
      65           0 :   return NS_OK;
      66             : }
      67             : 
      68             : NS_IMETHODIMP
      69           1 : AudioChannelAgent::Init(mozIDOMWindow* aWindow, int32_t aChannelType,
      70             :                         nsIAudioChannelAgentCallback *aCallback)
      71             : {
      72           1 :   return InitInternal(nsPIDOMWindowInner::From(aWindow), aChannelType,
      73           1 :                       aCallback, /* useWeakRef = */ false);
      74             : }
      75             : 
      76             : NS_IMETHODIMP
      77           0 : AudioChannelAgent::InitWithWeakCallback(mozIDOMWindow* aWindow,
      78             :                                         int32_t aChannelType,
      79             :                                         nsIAudioChannelAgentCallback *aCallback)
      80             : {
      81           0 :   return InitInternal(nsPIDOMWindowInner::From(aWindow), aChannelType,
      82           0 :                       aCallback, /* useWeakRef = */ true);
      83             : }
      84             : 
      85             : nsresult
      86           1 : AudioChannelAgent::FindCorrectWindow(nsPIDOMWindowInner* aWindow)
      87             : {
      88           1 :   MOZ_ASSERT(aWindow->IsInnerWindow());
      89             : 
      90           1 :   mWindow = aWindow->GetScriptableTop();
      91           1 :   if (NS_WARN_IF(!mWindow)) {
      92           0 :     return NS_OK;
      93             :   }
      94             : 
      95             :   // From here we do an hack for nested iframes.
      96             :   // The system app doesn't have access to the nested iframe objects so it
      97             :   // cannot control the volume of the agents running in nested apps. What we do
      98             :   // here is to assign those Agents to the top scriptable window of the parent
      99             :   // iframe (what is controlled by the system app).
     100             :   // For doing this we go recursively back into the chain of windows until we
     101             :   // find apps that are not the system one.
     102           2 :   nsCOMPtr<nsPIDOMWindowOuter> outerParent = mWindow->GetParent();
     103           1 :   if (!outerParent || outerParent == mWindow) {
     104           1 :     return NS_OK;
     105             :   }
     106             : 
     107           0 :   nsCOMPtr<nsPIDOMWindowInner> parent = outerParent->GetCurrentInnerWindow();
     108           0 :   if (!parent) {
     109           0 :     return NS_OK;
     110             :   }
     111             : 
     112           0 :   nsCOMPtr<nsIDocument> doc = parent->GetExtantDoc();
     113           0 :   if (!doc) {
     114           0 :     return NS_OK;
     115             :   }
     116             : 
     117           0 :   if (nsContentUtils::IsChromeDoc(doc)) {
     118           0 :     return NS_OK;
     119             :   }
     120             : 
     121             :   nsAdoptingCString systemAppUrl =
     122           0 :     mozilla::Preferences::GetCString("b2g.system_startup_url");
     123           0 :   if (!systemAppUrl) {
     124           0 :     return NS_OK;
     125             :   }
     126             : 
     127           0 :   nsCOMPtr<nsIPrincipal> principal = doc->NodePrincipal();
     128           0 :   nsCOMPtr<nsIURI> uri;
     129           0 :   principal->GetURI(getter_AddRefs(uri));
     130             : 
     131           0 :   if (uri) {
     132           0 :     nsAutoCString spec;
     133           0 :     uri->GetSpec(spec);
     134             : 
     135           0 :     if (spec.Equals(systemAppUrl)) {
     136           0 :       return NS_OK;
     137             :     }
     138             :   }
     139             : 
     140           0 :   return FindCorrectWindow(parent);
     141             : }
     142             : 
     143             : nsresult
     144           1 : AudioChannelAgent::InitInternal(nsPIDOMWindowInner* aWindow,
     145             :                                 int32_t aChannelType,
     146             :                                 nsIAudioChannelAgentCallback *aCallback,
     147             :                                 bool aUseWeakRef)
     148             : {
     149             :   // We syncd the enum of channel type between nsIAudioChannelAgent.idl and
     150             :   // AudioChannelBinding.h the same.
     151             :   MOZ_ASSERT(int(AUDIO_AGENT_CHANNEL_NORMAL) == int(AudioChannel::Normal) &&
     152             :              int(AUDIO_AGENT_CHANNEL_CONTENT) == int(AudioChannel::Content) &&
     153             :              int(AUDIO_AGENT_CHANNEL_NOTIFICATION) == int(AudioChannel::Notification) &&
     154             :              int(AUDIO_AGENT_CHANNEL_ALARM) == int(AudioChannel::Alarm) &&
     155             :              int(AUDIO_AGENT_CHANNEL_TELEPHONY) == int(AudioChannel::Telephony) &&
     156             :              int(AUDIO_AGENT_CHANNEL_RINGER) == int(AudioChannel::Ringer) &&
     157             :              int(AUDIO_AGENT_CHANNEL_SYSTEM) == int(AudioChannel::System) &&
     158             :              int(AUDIO_AGENT_CHANNEL_PUBLICNOTIFICATION) == int(AudioChannel::Publicnotification),
     159             :              "Enum of channel on nsIAudioChannelAgent.idl should be the same with AudioChannelBinding.h");
     160             : 
     161           1 :   if (mAudioChannelType != AUDIO_AGENT_CHANNEL_ERROR ||
     162           1 :       aChannelType > AUDIO_AGENT_CHANNEL_SYSTEM ||
     163             :       aChannelType < AUDIO_AGENT_CHANNEL_NORMAL) {
     164           0 :     return NS_ERROR_FAILURE;
     165             :   }
     166             : 
     167           1 :   if (NS_WARN_IF(!aWindow)) {
     168           0 :     return NS_ERROR_FAILURE;
     169             :   }
     170             : 
     171           1 :   MOZ_ASSERT(aWindow->IsInnerWindow());
     172           1 :   mInnerWindowID = aWindow->WindowID();
     173             : 
     174           1 :   nsresult rv = FindCorrectWindow(aWindow);
     175           1 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     176           0 :     return rv;
     177             :   }
     178             : 
     179           1 :   mAudioChannelType = aChannelType;
     180             : 
     181           1 :   if (aUseWeakRef) {
     182           0 :     mWeakCallback = do_GetWeakReference(aCallback);
     183             :   } else {
     184           1 :     mCallback = aCallback;
     185             :   }
     186             : 
     187           1 :   MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
     188             :          ("AudioChannelAgent, InitInternal, this = %p, type = %d, "
     189             :           "owner = %p, hasCallback = %d\n", this, mAudioChannelType,
     190             :           mWindow.get(), (!!mCallback || !!mWeakCallback)));
     191             : 
     192           1 :   return NS_OK;
     193             : }
     194             : 
     195             : NS_IMETHODIMP
     196           0 : AudioChannelAgent::NotifyStartedPlaying(AudioPlaybackConfig* aConfig,
     197             :                                         uint8_t aAudible)
     198             : {
     199           0 :   if (NS_WARN_IF(!aConfig)) {
     200           0 :     return NS_ERROR_FAILURE;
     201             :   }
     202             : 
     203           0 :   RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
     204           0 :   if (mAudioChannelType == AUDIO_AGENT_CHANNEL_ERROR ||
     205           0 :       service == nullptr || mIsRegToService) {
     206           0 :     return NS_ERROR_FAILURE;
     207             :   }
     208             : 
     209             :   MOZ_ASSERT(AudioChannelService::AudibleState::eNotAudible == 0 &&
     210             :              AudioChannelService::AudibleState::eMaybeAudible == 1 &&
     211             :              AudioChannelService::AudibleState::eAudible == 2);
     212           0 :   service->RegisterAudioChannelAgent(this,
     213           0 :     static_cast<AudioChannelService::AudibleState>(aAudible));
     214             : 
     215             :   AudioPlaybackConfig config = service->GetMediaConfig(mWindow,
     216           0 :                                                        mAudioChannelType);
     217             : 
     218           0 :   MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
     219             :          ("AudioChannelAgent, NotifyStartedPlaying, this = %p, "
     220             :           "audible = %s, mute = %s, volume = %f, suspend = %s\n", this,
     221             :           AudibleStateToStr(static_cast<AudioChannelService::AudibleState>(aAudible)),
     222             :           config.mMuted ? "true" : "false", config.mVolume,
     223             :           SuspendTypeToStr(config.mSuspend)));
     224             : 
     225           0 :   aConfig->SetConfig(config.mVolume, config.mMuted, config.mSuspend);
     226           0 :   mIsRegToService = true;
     227           0 :   return NS_OK;
     228             : }
     229             : 
     230             : NS_IMETHODIMP
     231           0 : AudioChannelAgent::NotifyStoppedPlaying()
     232             : {
     233           0 :   if (mAudioChannelType == AUDIO_AGENT_CHANNEL_ERROR ||
     234           0 :       !mIsRegToService) {
     235           0 :     return NS_ERROR_FAILURE;
     236             :   }
     237             : 
     238           0 :   MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
     239             :          ("AudioChannelAgent, NotifyStoppedPlaying, this = %p\n", this));
     240             : 
     241           0 :   RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
     242           0 :   if (service) {
     243           0 :     service->UnregisterAudioChannelAgent(this);
     244             :   }
     245             : 
     246           0 :   mIsRegToService = false;
     247           0 :   return NS_OK;
     248             : }
     249             : 
     250             : NS_IMETHODIMP
     251           0 : AudioChannelAgent::NotifyStartedAudible(uint8_t aAudible, uint32_t aReason)
     252             : {
     253           0 :   MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
     254             :          ("AudioChannelAgent, NotifyStartedAudible, this = %p, "
     255             :           "audible = %s, reason = %s\n", this,
     256             :           AudibleStateToStr(static_cast<AudioChannelService::AudibleState>(aAudible)),
     257             :           AudibleChangedReasonToStr(static_cast<AudioChannelService::AudibleChangedReasons>(aReason))));
     258             : 
     259           0 :   RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
     260           0 :   if (NS_WARN_IF(!service)) {
     261           0 :     return NS_ERROR_FAILURE;
     262             :   }
     263             : 
     264           0 :   service->AudioAudibleChanged(
     265             :     this,
     266             :     static_cast<AudioChannelService::AudibleState>(aAudible),
     267           0 :     static_cast<AudioChannelService::AudibleChangedReasons>(aReason));
     268           0 :   return NS_OK;
     269             : }
     270             : 
     271             : already_AddRefed<nsIAudioChannelAgentCallback>
     272           0 : AudioChannelAgent::GetCallback()
     273             : {
     274           0 :   nsCOMPtr<nsIAudioChannelAgentCallback> callback = mCallback;
     275           0 :   if (!callback) {
     276           0 :     callback = do_QueryReferent(mWeakCallback);
     277             :   }
     278           0 :   return callback.forget();
     279             : }
     280             : 
     281             : void
     282           0 : AudioChannelAgent::WindowVolumeChanged()
     283             : {
     284           0 :   nsCOMPtr<nsIAudioChannelAgentCallback> callback = GetCallback();
     285           0 :   if (!callback) {
     286           0 :     return;
     287             :   }
     288             : 
     289           0 :   AudioPlaybackConfig config = GetMediaConfig();
     290           0 :   MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
     291             :          ("AudioChannelAgent, WindowVolumeChanged, this = %p, mute = %s, "
     292             :           "volume = %f\n",
     293             :           this, config.mMuted ? "true" : "false", config.mVolume));
     294             : 
     295           0 :   callback->WindowVolumeChanged(config.mVolume, config.mMuted);
     296             : }
     297             : 
     298             : void
     299           0 : AudioChannelAgent::WindowSuspendChanged(nsSuspendedTypes aSuspend)
     300             : {
     301           0 :   nsCOMPtr<nsIAudioChannelAgentCallback> callback = GetCallback();
     302           0 :   if (!callback) {
     303           0 :     return;
     304             :   }
     305             : 
     306           0 :   if (!IsDisposableSuspend(aSuspend)) {
     307           0 :     aSuspend = GetMediaConfig().mSuspend;
     308             :   }
     309             : 
     310           0 :   MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
     311             :          ("AudioChannelAgent, WindowSuspendChanged, this = %p, "
     312             :           "suspended = %s\n", this, SuspendTypeToStr(aSuspend)));
     313             : 
     314           0 :   callback->WindowSuspendChanged(aSuspend);
     315             : }
     316             : 
     317             : AudioPlaybackConfig
     318           0 : AudioChannelAgent::GetMediaConfig()
     319             : {
     320           0 :   RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
     321           0 :   AudioPlaybackConfig config(1.0, false, nsISuspendedTypes::NONE_SUSPENDED);
     322           0 :   if (service) {
     323           0 :     config = service->GetMediaConfig(mWindow, mAudioChannelType);
     324             :   }
     325           0 :   return config;
     326             : }
     327             : 
     328             : bool
     329           0 : AudioChannelAgent::IsDisposableSuspend(nsSuspendedTypes aSuspend) const
     330             : {
     331           0 :   return (aSuspend == nsISuspendedTypes::SUSPENDED_PAUSE_DISPOSABLE ||
     332           0 :           aSuspend == nsISuspendedTypes::SUSPENDED_STOP_DISPOSABLE);
     333             : }
     334             : 
     335             : uint64_t
     336           0 : AudioChannelAgent::WindowID() const
     337             : {
     338           0 :   return mWindow ? mWindow->WindowID() : 0;
     339             : }
     340             : 
     341             : uint64_t
     342           0 : AudioChannelAgent::InnerWindowID() const
     343             : {
     344           0 :   return mInnerWindowID;
     345             : }
     346             : 
     347             : void
     348           0 : AudioChannelAgent::WindowAudioCaptureChanged(uint64_t aInnerWindowID,
     349             :                                              bool aCapture)
     350             : {
     351           0 :   if (aInnerWindowID != mInnerWindowID) {
     352           0 :     return;
     353             :   }
     354             : 
     355           0 :   nsCOMPtr<nsIAudioChannelAgentCallback> callback = GetCallback();
     356           0 :   if (!callback) {
     357           0 :     return;
     358             :   }
     359             : 
     360           0 :   MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
     361             :          ("AudioChannelAgent, WindowAudioCaptureChanged, this = %p, "
     362             :           "capture = %d\n", this, aCapture));
     363             : 
     364           0 :   callback->WindowAudioCaptureChanged(aCapture);
     365             : }
     366             : 
     367             : bool
     368           0 : AudioChannelAgent::IsPlayingStarted() const
     369             : {
     370           0 :   return mIsRegToService;
     371             : }
     372             : 
     373             : bool
     374           0 : AudioChannelAgent::ShouldBlockMedia() const
     375             : {
     376           0 :   return mWindow ?
     377           0 :     mWindow->GetMediaSuspend() == nsISuspendedTypes::SUSPENDED_BLOCK : false;
     378             : }

Generated by: LCOV version 1.13