gecko-dev/dom/audiochannel/AudioChannelAgent.cpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

282 строки
9.0 KiB
C++
Исходник Обычный вид История

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "AudioChannelAgent.h"
#include "AudioChannelService.h"
#include "mozilla/Preferences.h"
#include "nsContentUtils.h"
#include "mozilla/dom/Document.h"
#include "nsPIDOMWindow.h"
using namespace mozilla::dom;
NS_IMPL_CYCLE_COLLECTION_CLASS(AudioChannelAgent)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(AudioChannelAgent)
tmp->Shutdown();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCallback)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(AudioChannelAgent)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCallback)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AudioChannelAgent)
NS_INTERFACE_MAP_ENTRY(nsIAudioChannelAgent)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(AudioChannelAgent)
NS_IMPL_CYCLE_COLLECTING_RELEASE(AudioChannelAgent)
AudioChannelAgent::AudioChannelAgent()
: mInnerWindowID(0), mIsRegToService(false) {
// Init service in the begining, it can help us to know whether there is any
// created media component via AudioChannelService::IsServiceStarted().
RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
}
AudioChannelAgent::~AudioChannelAgent() { Shutdown(); }
void AudioChannelAgent::Shutdown() {
if (mIsRegToService) {
NotifyStoppedPlaying();
}
}
NS_IMETHODIMP
AudioChannelAgent::Init(mozIDOMWindow* aWindow,
nsIAudioChannelAgentCallback* aCallback) {
return InitInternal(nsPIDOMWindowInner::From(aWindow), aCallback,
/* useWeakRef = */ false);
}
NS_IMETHODIMP
AudioChannelAgent::InitWithWeakCallback(
mozIDOMWindow* aWindow, nsIAudioChannelAgentCallback* aCallback) {
return InitInternal(nsPIDOMWindowInner::From(aWindow), aCallback,
/* useWeakRef = */ true);
}
nsresult AudioChannelAgent::FindCorrectWindow(nsPIDOMWindowInner* aWindow) {
mWindow = aWindow->GetInProcessScriptableTop();
if (NS_WARN_IF(!mWindow)) {
return NS_OK;
}
// From here we do an hack for nested iframes.
// The system app doesn't have access to the nested iframe objects so it
// cannot control the volume of the agents running in nested apps. What we do
// here is to assign those Agents to the top scriptable window of the parent
// iframe (what is controlled by the system app).
// For doing this we go recursively back into the chain of windows until we
// find apps that are not the system one.
nsCOMPtr<nsPIDOMWindowOuter> outerParent = mWindow->GetInProcessParent();
if (!outerParent || outerParent == mWindow) {
return NS_OK;
}
nsCOMPtr<nsPIDOMWindowInner> parent = outerParent->GetCurrentInnerWindow();
if (!parent) {
return NS_OK;
}
nsCOMPtr<Document> doc = parent->GetExtantDoc();
if (!doc) {
return NS_OK;
}
if (nsContentUtils::IsChromeDoc(doc)) {
return NS_OK;
}
return FindCorrectWindow(parent);
}
nsresult AudioChannelAgent::InitInternal(
nsPIDOMWindowInner* aWindow, nsIAudioChannelAgentCallback* aCallback,
bool aUseWeakRef) {
if (NS_WARN_IF(!aWindow)) {
return NS_ERROR_FAILURE;
}
mInnerWindowID = aWindow->WindowID();
nsresult rv = FindCorrectWindow(aWindow);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (aUseWeakRef) {
mWeakCallback = do_GetWeakReference(aCallback);
} else {
mCallback = aCallback;
}
MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
("AudioChannelAgent, InitInternal, this = %p, "
"owner = %p, hasCallback = %d\n",
this, mWindow.get(), (!!mCallback || !!mWeakCallback)));
return NS_OK;
}
void AudioChannelAgent::PullInitialUpdate() {
RefPtr<AudioChannelService> service = AudioChannelService::Get();
MOZ_ASSERT(service);
MOZ_ASSERT(mIsRegToService);
AudioPlaybackConfig config = service->GetMediaConfig(mWindow);
MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
("AudioChannelAgent, PullInitialUpdate, this=%p, "
"mute=%s, volume=%f, suspend=%s, audioCapturing=%s\n",
this, config.mMuted ? "true" : "false", config.mVolume,
SuspendTypeToStr(config.mSuspend),
config.mCapturedAudio ? "true" : "false"));
WindowVolumeChanged(config.mVolume, config.mMuted);
WindowSuspendChanged(config.mSuspend);
WindowAudioCaptureChanged(InnerWindowID(), config.mCapturedAudio);
}
NS_IMETHODIMP
AudioChannelAgent::NotifyStartedPlaying(uint8_t aAudible) {
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 08:24:48 +03:00
RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
if (service == nullptr || mIsRegToService) {
return NS_ERROR_FAILURE;
}
MOZ_ASSERT(AudioChannelService::AudibleState::eNotAudible == 0 &&
AudioChannelService::AudibleState::eMaybeAudible == 1 &&
AudioChannelService::AudibleState::eAudible == 2);
service->RegisterAudioChannelAgent(
this, static_cast<AudioChannelService::AudibleState>(aAudible));
MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
("AudioChannelAgent, NotifyStartedPlaying, this = %p, audible = %s\n",
this,
AudibleStateToStr(
static_cast<AudioChannelService::AudibleState>(aAudible))));
mIsRegToService = true;
return NS_OK;
}
NS_IMETHODIMP
AudioChannelAgent::NotifyStoppedPlaying() {
if (!mIsRegToService) {
return NS_ERROR_FAILURE;
}
MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
("AudioChannelAgent, NotifyStoppedPlaying, this = %p\n", this));
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 08:24:48 +03:00
RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
if (service) {
service->UnregisterAudioChannelAgent(this);
}
mIsRegToService = false;
return NS_OK;
}
NS_IMETHODIMP
AudioChannelAgent::NotifyStartedAudible(uint8_t aAudible, uint32_t aReason) {
MOZ_LOG(
AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
("AudioChannelAgent, NotifyStartedAudible, this = %p, "
"audible = %s, reason = %s\n",
this,
AudibleStateToStr(
static_cast<AudioChannelService::AudibleState>(aAudible)),
AudibleChangedReasonToStr(
static_cast<AudioChannelService::AudibleChangedReasons>(aReason))));
RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
if (NS_WARN_IF(!service)) {
return NS_ERROR_FAILURE;
}
service->AudioAudibleChanged(
this, static_cast<AudioChannelService::AudibleState>(aAudible),
static_cast<AudioChannelService::AudibleChangedReasons>(aReason));
return NS_OK;
}
already_AddRefed<nsIAudioChannelAgentCallback>
AudioChannelAgent::GetCallback() {
nsCOMPtr<nsIAudioChannelAgentCallback> callback = mCallback;
if (!callback) {
callback = do_QueryReferent(mWeakCallback);
}
return callback.forget();
}
void AudioChannelAgent::WindowVolumeChanged(float aVolume, bool aMuted) {
nsCOMPtr<nsIAudioChannelAgentCallback> callback = GetCallback();
if (!callback) {
return;
}
MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
("AudioChannelAgent, WindowVolumeChanged, this = %p, mute = %s, "
"volume = %f\n",
this, aMuted ? "true" : "false", aVolume));
callback->WindowVolumeChanged(aVolume, aMuted);
}
void AudioChannelAgent::WindowSuspendChanged(nsSuspendedTypes aSuspend) {
nsCOMPtr<nsIAudioChannelAgentCallback> callback = GetCallback();
if (!callback) {
return;
}
MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
("AudioChannelAgent, WindowSuspendChanged, this = %p, "
"suspended = %s\n",
this, SuspendTypeToStr(aSuspend)));
callback->WindowSuspendChanged(aSuspend);
}
AudioPlaybackConfig AudioChannelAgent::GetMediaConfig() const {
RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
AudioPlaybackConfig config(1.0, false, nsISuspendedTypes::NONE_SUSPENDED);
if (service) {
config = service->GetMediaConfig(mWindow);
}
return config;
}
uint64_t AudioChannelAgent::WindowID() const {
return mWindow ? mWindow->WindowID() : 0;
}
uint64_t AudioChannelAgent::InnerWindowID() const { return mInnerWindowID; }
void AudioChannelAgent::WindowAudioCaptureChanged(uint64_t aInnerWindowID,
bool aCapture) {
if (aInnerWindowID != mInnerWindowID) {
return;
}
nsCOMPtr<nsIAudioChannelAgentCallback> callback = GetCallback();
if (!callback) {
return;
}
MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
("AudioChannelAgent, WindowAudioCaptureChanged, this = %p, "
"capture = %d\n",
this, aCapture));
callback->WindowAudioCaptureChanged(aCapture);
}
bool AudioChannelAgent::IsWindowAudioCapturingEnabled() const {
return GetMediaConfig().mCapturedAudio;
}
bool AudioChannelAgent::IsPlayingStarted() const { return mIsRegToService; }