This commit is contained in:
Ryan VanderMeulen 2014-08-17 15:15:55 -04:00
Родитель 65df1a024e eb9d8f131b
Коммит 81292f7f5e
8 изменённых файлов: 83 добавлений и 30 удалений

Просмотреть файл

@ -2471,6 +2471,32 @@ SourceMediaStream::NotifyDirectConsumers(TrackData *aTrack,
} }
} }
// These handle notifying all the listeners of an event
void
SourceMediaStream::NotifyListenersEventImpl(MediaStreamListener::MediaStreamGraphEvent aEvent)
{
for (uint32_t j = 0; j < mListeners.Length(); ++j) {
MediaStreamListener* l = mListeners[j];
l->NotifyEvent(GraphImpl(), aEvent);
}
}
void
SourceMediaStream::NotifyListenersEvent(MediaStreamListener::MediaStreamGraphEvent aNewEvent)
{
class Message : public ControlMessage {
public:
Message(SourceMediaStream* aStream, MediaStreamListener::MediaStreamGraphEvent aEvent) :
ControlMessage(aStream), mEvent(aEvent) {}
virtual void Run()
{
mStream->AsSourceStream()->NotifyListenersEventImpl(mEvent);
}
MediaStreamListener::MediaStreamGraphEvent mEvent;
};
GraphImpl()->AppendMessage(new Message(this, aNewEvent));
}
void void
SourceMediaStream::AddDirectListener(MediaStreamDirectListener* aListener) SourceMediaStream::AddDirectListener(MediaStreamDirectListener* aListener)
{ {
@ -2482,10 +2508,8 @@ SourceMediaStream::AddDirectListener(MediaStreamDirectListener* aListener)
} }
if (wasEmpty) { if (wasEmpty) {
for (uint32_t j = 0; j < mListeners.Length(); ++j) { // Async
MediaStreamListener* l = mListeners[j]; NotifyListenersEvent(MediaStreamListener::EVENT_HAS_DIRECT_LISTENERS);
l->NotifyEvent(GraphImpl(), MediaStreamListener::EVENT_HAS_DIRECT_LISTENERS);
}
} }
} }
@ -2500,10 +2524,8 @@ SourceMediaStream::RemoveDirectListener(MediaStreamDirectListener* aListener)
} }
if (isEmpty) { if (isEmpty) {
for (uint32_t j = 0; j < mListeners.Length(); ++j) { // Async
MediaStreamListener* l = mListeners[j]; NotifyListenersEvent(MediaStreamListener::EVENT_HAS_NO_DIRECT_LISTENERS);
l->NotifyEvent(GraphImpl(), MediaStreamListener::EVENT_HAS_NO_DIRECT_LISTENERS);
}
} }
} }

Просмотреть файл

@ -716,6 +716,13 @@ public:
*/ */
void SetPullEnabled(bool aEnabled); void SetPullEnabled(bool aEnabled);
/**
* These add/remove DirectListeners, which allow bypassing the graph and any
* synchronization delays for e.g. PeerConnection, which wants the data ASAP
* and lets the far-end handle sync and playout timing.
*/
void NotifyListenersEventImpl(MediaStreamListener::MediaStreamGraphEvent aEvent);
void NotifyListenersEvent(MediaStreamListener::MediaStreamGraphEvent aEvent);
void AddDirectListener(MediaStreamDirectListener* aListener); void AddDirectListener(MediaStreamDirectListener* aListener);
void RemoveDirectListener(MediaStreamDirectListener* aListener); void RemoveDirectListener(MediaStreamDirectListener* aListener);

Просмотреть файл

@ -143,6 +143,11 @@ PluginModuleChild::Init(const std::string& aPluginFilename,
GetIPCChannel()->SetAbortOnError(true); GetIPCChannel()->SetAbortOnError(true);
// Request Windows message deferral behavior on our channel. This
// applies to the top level and all sub plugin protocols since they
// all share the same channel.
GetIPCChannel()->SetChannelFlags(MessageChannel::REQUIRE_DEFERRED_MESSAGE_PROTECTION);
#ifdef XP_WIN #ifdef XP_WIN
COMMessageFilter::Initialize(this); COMMessageFilter::Initialize(this);
#endif #endif

Просмотреть файл

@ -103,6 +103,11 @@ PluginModuleParent::LoadModule(const char* aFilePath)
parent->Open(parent->mSubprocess->GetChannel(), parent->Open(parent->mSubprocess->GetChannel(),
parent->mSubprocess->GetChildProcessHandle()); parent->mSubprocess->GetChildProcessHandle());
// Request Windows message deferral behavior on our channel. This
// applies to the top level and all sub plugin protocols since they
// all share the same channel.
parent->GetIPCChannel()->SetChannelFlags(MessageChannel::REQUIRE_DEFERRED_MESSAGE_PROTECTION);
TimeoutChanged(CHILD_TIMEOUT_PREF, parent); TimeoutChanged(CHILD_TIMEOUT_PREF, parent);
#ifdef MOZ_CRASHREPORTER #ifdef MOZ_CRASHREPORTER

Просмотреть файл

@ -234,7 +234,8 @@ MessageChannel::MessageChannel(MessageListener *aListener)
mRemoteStackDepthGuess(false), mRemoteStackDepthGuess(false),
mSawInterruptOutMsg(false), mSawInterruptOutMsg(false),
mAbortOnError(false), mAbortOnError(false),
mBlockScripts(false) mBlockScripts(false),
mFlags(REQUIRE_DEFAULT)
{ {
MOZ_COUNT_CTOR(ipc::MessageChannel); MOZ_COUNT_CTOR(ipc::MessageChannel);

Просмотреть файл

@ -63,13 +63,13 @@ class MessageChannel : HasResultCodes
// "Open" from the perspective of the transport layer; the underlying // "Open" from the perspective of the transport layer; the underlying
// socketpair/pipe should already be created. // socketpair/pipe should already be created.
// //
// Returns true iff the transport layer was successfully connected, // Returns true if the transport layer was successfully connected,
// i.e., mChannelState == ChannelConnected. // i.e., mChannelState == ChannelConnected.
bool Open(Transport* aTransport, MessageLoop* aIOLoop=0, Side aSide=UnknownSide); bool Open(Transport* aTransport, MessageLoop* aIOLoop=0, Side aSide=UnknownSide);
// "Open" a connection to another thread in the same process. // "Open" a connection to another thread in the same process.
// //
// Returns true iff the transport layer was successfully connected, // Returns true if the transport layer was successfully connected,
// i.e., mChannelState == ChannelConnected. // i.e., mChannelState == ChannelConnected.
// //
// For more details on the process of opening a channel between // For more details on the process of opening a channel between
@ -89,6 +89,19 @@ class MessageChannel : HasResultCodes
mAbortOnError = true; mAbortOnError = true;
} }
// Misc. behavioral traits consumers can request for this channel
enum ChannelFlags {
REQUIRE_DEFAULT = 0,
// Windows: if this channel operates on the UI thread, indicates
// WindowsMessageLoop code should enable deferred native message
// handling to prevent deadlocks. Should only be used for protocols
// that manage child processes which might create native UI, like
// plugins.
REQUIRE_DEFERRED_MESSAGE_PROTECTION = 1 << 0
};
void SetChannelFlags(ChannelFlags aFlags) { mFlags = aFlags; }
ChannelFlags GetChannelFlags() { return mFlags; }
void BlockScripts(); void BlockScripts();
bool ShouldBlockScripts() const bool ShouldBlockScripts() const
@ -649,6 +662,9 @@ class MessageChannel : HasResultCodes
// Should we prevent scripts from running while dispatching urgent messages? // Should we prevent scripts from running while dispatching urgent messages?
bool mBlockScripts; bool mBlockScripts;
// See SetChannelFlags
ChannelFlags mFlags;
}; };
bool bool

Просмотреть файл

@ -657,6 +657,7 @@ InitUIThread()
} // namespace ipc } // namespace ipc
} // namespace mozilla } // namespace mozilla
// See SpinInternalEventLoop below
MessageChannel::SyncStackFrame::SyncStackFrame(MessageChannel* channel, bool interrupt) MessageChannel::SyncStackFrame::SyncStackFrame(MessageChannel* channel, bool interrupt)
: mInterrupt(interrupt) : mInterrupt(interrupt)
, mSpinNestedEvents(false) , mSpinNestedEvents(false)
@ -665,8 +666,9 @@ MessageChannel::SyncStackFrame::SyncStackFrame(MessageChannel* channel, bool int
, mPrev(mChannel->mTopFrame) , mPrev(mChannel->mTopFrame)
, mStaticPrev(sStaticTopFrame) , mStaticPrev(sStaticTopFrame)
{ {
// Only track stack frames when we are on the gui thread. // Only track stack frames when Windows message deferral behavior
if (GetCurrentThreadId() != gUIThreadId) { // is request for the channel.
if (!(mChannel->GetChannelFlags() & REQUIRE_DEFERRED_MESSAGE_PROTECTION)) {
return; return;
} }
@ -682,7 +684,7 @@ MessageChannel::SyncStackFrame::SyncStackFrame(MessageChannel* channel, bool int
MessageChannel::SyncStackFrame::~SyncStackFrame() MessageChannel::SyncStackFrame::~SyncStackFrame()
{ {
if (GetCurrentThreadId() != gUIThreadId) { if (!(mChannel->GetChannelFlags() & REQUIRE_DEFERRED_MESSAGE_PROTECTION)) {
return; return;
} }
@ -809,11 +811,9 @@ MessageChannel::WaitForSyncNotify()
MOZ_ASSERT(gUIThreadId, "InitUIThread was not called!"); MOZ_ASSERT(gUIThreadId, "InitUIThread was not called!");
// We jump through a lot of unique hoops in dealing with Windows message // Use a blocking wait if this channel does not require
// trapping to prevent re-entrancy when we are blocked waiting on a sync // Windows message deferral behavior.
// reply or new rpc in-call. However none of this overhead is needed when if (!(mFlags & REQUIRE_DEFERRED_MESSAGE_PROTECTION)) {
// we aren't on the main (gui) thread.
if (GetCurrentThreadId() != gUIThreadId) {
PRIntervalTime timeout = (kNoTimeout == mTimeoutMs) ? PRIntervalTime timeout = (kNoTimeout == mTimeoutMs) ?
PR_INTERVAL_NO_TIMEOUT : PR_INTERVAL_NO_TIMEOUT :
PR_MillisecondsToInterval(mTimeoutMs); PR_MillisecondsToInterval(mTimeoutMs);
@ -837,9 +837,8 @@ MessageChannel::WaitForSyncNotify()
false : IsTimeoutExpired(waitStart, timeout)); false : IsTimeoutExpired(waitStart, timeout));
} }
NS_ASSERTION(GetCurrentThreadId() == gUIThreadId, NS_ASSERTION(mFlags & REQUIRE_DEFERRED_MESSAGE_PROTECTION,
"Shouldn't be on a non-main thread in here!"); "Shouldn't be here for channels that don't use message deferral!");
NS_ASSERTION(mTopFrame && !mTopFrame->mInterrupt, NS_ASSERTION(mTopFrame && !mTopFrame->mInterrupt,
"Top frame is not a sync frame!"); "Top frame is not a sync frame!");
@ -961,21 +960,19 @@ MessageChannel::WaitForInterruptNotify()
MOZ_ASSERT(gUIThreadId, "InitUIThread was not called!"); MOZ_ASSERT(gUIThreadId, "InitUIThread was not called!");
// Re-use sync notification wait code when we aren't on the // Re-use sync notification wait code if this channel does not require
// gui thread, which bypasses the gui thread hoops we jump // Windows message deferral behavior.
// through in dealing with Windows messaging. if (!(mFlags & REQUIRE_DEFERRED_MESSAGE_PROTECTION)) {
if (GetCurrentThreadId() != gUIThreadId) {
return WaitForSyncNotify(); return WaitForSyncNotify();
} }
NS_ASSERTION(GetCurrentThreadId() == gUIThreadId,
"Shouldn't be on a non-main thread in here!");
if (!InterruptStackDepth()) { if (!InterruptStackDepth()) {
// There is currently no way to recover from this condition. // There is currently no way to recover from this condition.
NS_RUNTIMEABORT("StackDepth() is 0 in call to MessageChannel::WaitForNotify!"); NS_RUNTIMEABORT("StackDepth() is 0 in call to MessageChannel::WaitForNotify!");
} }
NS_ASSERTION(mFlags & REQUIRE_DEFERRED_MESSAGE_PROTECTION,
"Shouldn't be here for channels that don't use message deferral!");
NS_ASSERTION(mTopFrame && mTopFrame->mInterrupt, NS_ASSERTION(mTopFrame && mTopFrame->mInterrupt,
"Top frame is not a sync frame!"); "Top frame is not a sync frame!");

Просмотреть файл

@ -756,7 +756,7 @@ class B2GOptions(MochitestOptions):
defaults["testPath"] = "" defaults["testPath"] = ""
defaults["extensionsToExclude"] = ["specialpowers"] defaults["extensionsToExclude"] = ["specialpowers"]
# See dependencies of bug 1038943. # See dependencies of bug 1038943.
defaults["leakThreshold"] = 4964 defaults["leakThreshold"] = 5012
self.set_defaults(**defaults) self.set_defaults(**defaults)
def verifyRemoteOptions(self, options): def verifyRemoteOptions(self, options):