зеркало из https://github.com/mozilla/gecko-dev.git
Bug 820704 - AudioChannelService must handle children quitting unexpectedly. r=jlebar
This commit is contained in:
Родитель
cf876bebea
Коммит
6b0a7ece90
|
@ -68,35 +68,33 @@ NS_IMPL_ISUPPORTS0(AudioChannelService)
|
|||
AudioChannelService::AudioChannelService()
|
||||
: mCurrentHigherChannel(AUDIO_CHANNEL_NORMAL)
|
||||
{
|
||||
mChannelCounters = new int32_t[AUDIO_CHANNEL_PUBLICNOTIFICATION+1];
|
||||
|
||||
for (int i = AUDIO_CHANNEL_NORMAL;
|
||||
i <= AUDIO_CHANNEL_PUBLICNOTIFICATION;
|
||||
++i) {
|
||||
mChannelCounters[i] = 0;
|
||||
}
|
||||
|
||||
// Creation of the hash table.
|
||||
mAgents.Init();
|
||||
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Default) {
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (obs) {
|
||||
obs->AddObserver(this, "ipc:content-shutdown", false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AudioChannelService::~AudioChannelService()
|
||||
{
|
||||
delete [] mChannelCounters;
|
||||
}
|
||||
|
||||
void
|
||||
AudioChannelService::RegisterAudioChannelAgent(AudioChannelAgent* aAgent,
|
||||
AudioChannelType aType)
|
||||
AudioChannelType aType)
|
||||
{
|
||||
mAgents.Put(aAgent, aType);
|
||||
RegisterType(aType);
|
||||
RegisterType(aType, CONTENT_PARENT_UNKNOWN_CHILD_ID);
|
||||
}
|
||||
|
||||
void
|
||||
AudioChannelService::RegisterType(AudioChannelType aType)
|
||||
AudioChannelService::RegisterType(AudioChannelType aType, uint64_t aChildID)
|
||||
{
|
||||
mChannelCounters[aType]++;
|
||||
mChannelCounters[aType].AppendElement(aChildID);
|
||||
|
||||
// In order to avoid race conditions, it's safer to notify any existing
|
||||
// agent any time a new one is registered.
|
||||
|
@ -112,20 +110,21 @@ AudioChannelService::UnregisterAudioChannelAgent(AudioChannelAgent* aAgent)
|
|||
}
|
||||
|
||||
mAgents.Remove(aAgent);
|
||||
UnregisterType(type);
|
||||
UnregisterType(type, CONTENT_PARENT_UNKNOWN_CHILD_ID);
|
||||
}
|
||||
|
||||
void
|
||||
AudioChannelService::UnregisterType(AudioChannelType aType)
|
||||
AudioChannelService::UnregisterType(AudioChannelType aType, uint64_t aChildID)
|
||||
{
|
||||
mChannelCounters[aType]--;
|
||||
MOZ_ASSERT(mChannelCounters[aType] >= 0);
|
||||
// The array may contain multiple occurrence of this appId but
|
||||
// this should remove only the first one.
|
||||
mChannelCounters[aType].RemoveElement(aChildID);
|
||||
|
||||
bool isNoChannelUsed = true;
|
||||
for (int32_t type = AUDIO_CHANNEL_NORMAL;
|
||||
type <= AUDIO_CHANNEL_PUBLICNOTIFICATION;
|
||||
++type) {
|
||||
if (mChannelCounters[type]) {
|
||||
if (!mChannelCounters[type].IsEmpty()) {
|
||||
isNoChannelUsed = false;
|
||||
break;
|
||||
}
|
||||
|
@ -153,7 +152,7 @@ AudioChannelService::GetMuted(AudioChannelType aType, bool aElementHidden)
|
|||
|
||||
case AUDIO_CHANNEL_CONTENT:
|
||||
// TODO: this should work per apps
|
||||
if (mChannelCounters[AUDIO_CHANNEL_CONTENT] > 1)
|
||||
if (mChannelCounters[AUDIO_CHANNEL_CONTENT].Length() > 1)
|
||||
return true;
|
||||
break;
|
||||
|
||||
|
@ -177,11 +176,11 @@ AudioChannelService::GetMuted(AudioChannelType aType, bool aElementHidden)
|
|||
switch (aType) {
|
||||
case AUDIO_CHANNEL_NORMAL:
|
||||
case AUDIO_CHANNEL_CONTENT:
|
||||
muted = !!mChannelCounters[AUDIO_CHANNEL_NOTIFICATION] ||
|
||||
!!mChannelCounters[AUDIO_CHANNEL_ALARM] ||
|
||||
!!mChannelCounters[AUDIO_CHANNEL_TELEPHONY] ||
|
||||
!!mChannelCounters[AUDIO_CHANNEL_RINGER] ||
|
||||
!!mChannelCounters[AUDIO_CHANNEL_PUBLICNOTIFICATION];
|
||||
muted = !mChannelCounters[AUDIO_CHANNEL_NOTIFICATION].IsEmpty() ||
|
||||
!mChannelCounters[AUDIO_CHANNEL_ALARM].IsEmpty() ||
|
||||
!mChannelCounters[AUDIO_CHANNEL_TELEPHONY].IsEmpty() ||
|
||||
!mChannelCounters[AUDIO_CHANNEL_RINGER].IsEmpty() ||
|
||||
!mChannelCounters[AUDIO_CHANNEL_PUBLICNOTIFICATION].IsEmpty();
|
||||
break;
|
||||
|
||||
case AUDIO_CHANNEL_NOTIFICATION:
|
||||
|
@ -207,7 +206,7 @@ AudioChannelService::GetMuted(AudioChannelType aType, bool aElementHidden)
|
|||
for (int32_t type = AUDIO_CHANNEL_NORMAL;
|
||||
type <= AUDIO_CHANNEL_PUBLICNOTIFICATION;
|
||||
++type) {
|
||||
if (mChannelCounters[type]) {
|
||||
if (!mChannelCounters[type].IsEmpty()) {
|
||||
higher = (AudioChannelType)type;
|
||||
}
|
||||
}
|
||||
|
@ -226,7 +225,6 @@ AudioChannelService::GetMuted(AudioChannelType aType, bool aElementHidden)
|
|||
return muted;
|
||||
}
|
||||
|
||||
|
||||
static PLDHashOperator
|
||||
NotifyEnumerator(AudioChannelAgent* aAgent,
|
||||
AudioChannelType aType, void* aData)
|
||||
|
@ -262,7 +260,7 @@ AudioChannelService::ChannelsActiveWithHigherPriorityThan(AudioChannelType aType
|
|||
return false;
|
||||
}
|
||||
|
||||
if (mChannelCounters[i]) {
|
||||
if (!mChannelCounters[i].IsEmpty()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -298,3 +296,37 @@ AudioChannelService::ChannelName(AudioChannelType aType)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
AudioChannelService::Observe(nsISupports* aSubject, const char* aTopic, const PRUnichar* data)
|
||||
{
|
||||
MOZ_ASSERT(!strcmp(aTopic, "ipc:content-shutdown"));
|
||||
|
||||
nsCOMPtr<nsIPropertyBag2> props = do_QueryInterface(aSubject);
|
||||
if (!props) {
|
||||
NS_WARNING("ipc:content-shutdown message without property bag as subject");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
uint64_t childID = 0;
|
||||
nsresult rv = props->GetPropertyAsUint64(NS_LITERAL_STRING("childID"),
|
||||
&childID);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
for (int32_t type = AUDIO_CHANNEL_NORMAL;
|
||||
type <= AUDIO_CHANNEL_PUBLICNOTIFICATION;
|
||||
++type) {
|
||||
int32_t index;
|
||||
while ((index = mChannelCounters[type].IndexOf(childID)) != -1) {
|
||||
mChannelCounters[type].RemoveElementAt(index);
|
||||
}
|
||||
}
|
||||
|
||||
// We don't have to remove the agents from the mAgents hashtable because if
|
||||
// that table contains only agents running on the same process.
|
||||
|
||||
Notify();
|
||||
} else {
|
||||
NS_WARNING("ipc:content-shutdown message without childID property");
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#define mozilla_dom_audiochannelservice_h__
|
||||
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsIObserver.h"
|
||||
|
||||
#include "AudioChannelCommon.h"
|
||||
#include "AudioChannelAgent.h"
|
||||
|
@ -17,10 +17,11 @@
|
|||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class AudioChannelService : public nsISupports
|
||||
class AudioChannelService : public nsIObserver
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
/**
|
||||
* Returns the AudioChannelServce singleton. Only to be called from main thread.
|
||||
|
@ -56,8 +57,8 @@ protected:
|
|||
void Notify();
|
||||
|
||||
/* Register/Unregister IPC types: */
|
||||
void RegisterType(AudioChannelType aType);
|
||||
void UnregisterType(AudioChannelType aType);
|
||||
void RegisterType(AudioChannelType aType, uint64_t aChildID);
|
||||
void UnregisterType(AudioChannelType aType, uint64_t aChildID);
|
||||
|
||||
AudioChannelService();
|
||||
virtual ~AudioChannelService();
|
||||
|
@ -68,7 +69,7 @@ protected:
|
|||
|
||||
nsDataHashtable< nsPtrHashKey<AudioChannelAgent>, AudioChannelType > mAgents;
|
||||
|
||||
int32_t* mChannelCounters;
|
||||
nsTArray<uint64_t> mChannelCounters[AUDIO_CHANNEL_PUBLICNOTIFICATION+1];
|
||||
|
||||
AudioChannelType mCurrentHigherChannel;
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ AudioChannelServiceChild::GetMuted(AudioChannelType aType, bool aMozHidden)
|
|||
|
||||
void
|
||||
AudioChannelServiceChild::RegisterAudioChannelAgent(AudioChannelAgent* aAgent,
|
||||
AudioChannelType aType)
|
||||
AudioChannelType aType)
|
||||
{
|
||||
AudioChannelService::RegisterAudioChannelAgent(aAgent, aType);
|
||||
|
||||
|
|
|
@ -775,7 +775,7 @@ ContentParent::ContentParent(const nsAString& aAppManifestURL,
|
|||
ChildOSPrivileges aOSPrivileges)
|
||||
: mSubprocess(nullptr)
|
||||
, mOSPrivileges(aOSPrivileges)
|
||||
, mChildID(-1)
|
||||
, mChildID(CONTENT_PARENT_UNKNOWN_CHILD_ID)
|
||||
, mGeolocationWatchID(-1)
|
||||
, mRunToCompletionDepth(0)
|
||||
, mShouldCallUnblockChild(false)
|
||||
|
@ -1103,7 +1103,7 @@ ContentParent::RecvAudioChannelRegisterType(const AudioChannelType& aType)
|
|||
nsRefPtr<AudioChannelService> service =
|
||||
AudioChannelService::GetAudioChannelService();
|
||||
if (service) {
|
||||
service->RegisterType(aType);
|
||||
service->RegisterType(aType, mChildID);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -1114,7 +1114,7 @@ ContentParent::RecvAudioChannelUnregisterType(const AudioChannelType& aType)
|
|||
nsRefPtr<AudioChannelService> service =
|
||||
AudioChannelService::GetAudioChannelService();
|
||||
if (service) {
|
||||
service->UnregisterType(aType);
|
||||
service->UnregisterType(aType, mChildID);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
|
||||
#define CHILD_PROCESS_SHUTDOWN_MESSAGE NS_LITERAL_STRING("child-process-shutdown")
|
||||
|
||||
#define CONTENT_PARENT_UNKNOWN_CHILD_ID -1
|
||||
|
||||
class mozIApplication;
|
||||
class nsConsoleService;
|
||||
class nsIDOMBlob;
|
||||
|
@ -132,6 +134,8 @@ public:
|
|||
*/
|
||||
void KillHard();
|
||||
|
||||
uint64_t ChildID() { return mChildID; }
|
||||
|
||||
protected:
|
||||
void OnChannelConnected(int32_t pid);
|
||||
virtual void ActorDestroy(ActorDestroyReason why);
|
||||
|
|
Загрузка…
Ссылка в новой задаче