Bug 1411504. P1 - always require MediaCache to have a thread to run Update() loops.
MozReview-Commit-ID: AYVWuN9CU55
--- a/dom/media/ChannelMediaResource.cpp
+++ b/dom/media/ChannelMediaResource.cpp
@@ -298,17 +298,17 @@ ChannelMediaResource::OnStartRequest(nsI
mSuspendAgent.UpdateSuspendedStatusIfNeeded();
// Fires an initial progress event.
owner->DownloadProgressed();
// TODO: Don't turn this on until we fix all data races.
nsCOMPtr<nsIThreadRetargetableRequest> retarget;
if (Preferences::GetBool("media.omt_data_delivery.enabled", false) &&
- (retarget = do_QueryInterface(aRequest)) && mCacheStream.OwnerThread()) {
+ (retarget = do_QueryInterface(aRequest))) {
// Note this will not always succeed. We need to handle the case where
// all resources sharing the same cache might run their data callbacks
// on different threads.
retarget->RetargetDeliveryTo(mCacheStream.OwnerThread());
}
return NS_OK;
}
--- a/dom/media/MediaCache.cpp
+++ b/dom/media/MediaCache.cpp
@@ -285,28 +285,16 @@ protected:
, mUpdateQueued(false)
#ifdef DEBUG
, mInUpdate(false)
#endif
{
NS_ASSERTION(NS_IsMainThread(), "Only construct MediaCache on main thread");
MOZ_COUNT_CTOR(MediaCache);
MediaCacheFlusher::RegisterMediaCache(this);
-
- if (!sThreadInit) {
- sThreadInit = true;
- nsCOMPtr<nsIThread> thread;
- nsresult rv = NS_NewNamedThread("MediaCache", getter_AddRefs(thread));
- if (NS_FAILED(rv)) {
- NS_WARNING("Failed to create a thread for MediaCache.");
- return;
- }
- sThread = thread.forget();
- ClearOnShutdown(this, ShutdownPhase::ShutdownThreads);
- }
}
~MediaCache()
{
NS_ASSERTION(NS_IsMainThread(), "Only destroy MediaCache on main thread");
if (this == gMediaCache) {
LOG("~MediaCache(Global file-backed MediaCache)");
// This is the file-backed MediaCache, reset the global pointer.
@@ -457,18 +445,17 @@ protected:
// True if an event to run Update() has been queued but not processed
bool mUpdateQueued;
#ifdef DEBUG
bool mInUpdate;
#endif
// A list of resource IDs to notify about the change in suspended status.
nsTArray<int64_t> mSuspendedStatusToNotify;
// The thread on which we will run data callbacks from the channels.
- // Could be null if failing to create the thread. Note this thread is shared
- // among all MediaCache instances.
+ // Note this thread is shared among all MediaCache instances.
static StaticRefPtr<nsIThread> sThread;
// True if we've tried to init sThread. Note we try once only so it is safe
// to access sThread on all threads.
static bool sThreadInit;
};
// Initialized to nullptr by non-local static initialization.
/* static */ MediaCache* MediaCache::gMediaCache;
@@ -724,16 +711,36 @@ MediaCache::CloseStreamsForPrivateBrowsi
}
}
}
/* static */ RefPtr<MediaCache>
MediaCache::GetMediaCache(int64_t aContentLength)
{
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
+
+ if (!sThreadInit) {
+ sThreadInit = true;
+ nsCOMPtr<nsIThread> thread;
+ nsresult rv = NS_NewNamedThread("MediaCache", getter_AddRefs(thread));
+ if (NS_FAILED(rv)) {
+ NS_WARNING("Failed to create a thread for MediaCache.");
+ return nullptr;
+ }
+ sThread = thread.forget();
+ // Note it is safe to pass an invalid pointer for operator=(std::nullptr_t)
+ // is non-virtual and it will not access |this|.
+ ClearOnShutdown(reinterpret_cast<MediaCache*>(0x1),
+ ShutdownPhase::ShutdownThreads);
+ }
+
+ if (!sThread) {
+ return nullptr;
+ }
+
if (aContentLength > 0 &&
aContentLength <= int64_t(MediaPrefs::MediaMemoryCacheMaxSize()) * 1024) {
// Small-enough resource, use a new memory-backed MediaCache.
RefPtr<MediaBlockCacheBase> bc = new MemoryBlockCache(aContentLength);
nsresult rv = bc->Init();
if (NS_SUCCEEDED(rv)) {
RefPtr<MediaCache> mc = new MediaCache(bc);
LOG("GetMediaCache(%" PRIi64 ") -> Memory MediaCache %p",