nsresult nsMemoryImpl::FlushMemory(const PRUnichar* aReason, bool aImmediate) { nsresult rv = NS_OK; if (aImmediate) { // They've asked us to run the flusher *immediately*. We've // got to be on the UI main thread for us to be able to do // that...are we? if (!NS_IsMainThread()) { NS_ERROR("can't synchronously flush memory: not on UI thread"); return NS_ERROR_FAILURE; } } int32_t lastVal = sIsFlushing.exchange(1); if (lastVal) return NS_OK; PRIntervalTime now = PR_IntervalNow(); // Run the flushers immediately if we can; otherwise, proxy to the // UI thread an run 'em asynchronously. if (aImmediate) { rv = RunFlushers(aReason); } else { // Don't broadcast more than once every 1000ms to avoid being noisy if (PR_IntervalToMicroseconds(now - sLastFlushTime) > 1000) { sFlushEvent.mReason = aReason; rv = NS_DispatchToMainThread(&sFlushEvent, NS_DISPATCH_NORMAL); } } sLastFlushTime = now; return rv; }
nsresult MediaEngineWebRTCVideoSource::Stop(SourceMediaStream *aSource, TrackID aID) { LOG((__FUNCTION__)); if (!mSources.RemoveElement(aSource)) { // Already stopped - this is allowed return NS_OK; } if (!mSources.IsEmpty()) { return NS_OK; } #ifdef MOZ_B2G_CAMERA ReentrantMonitorAutoEnter sync(mCallbackMonitor); #endif if (mState != kStarted) { return NS_ERROR_FAILURE; } { MonitorAutoLock lock(mMonitor); mState = kStopped; aSource->EndTrack(aID); // Drop any cached image so we don't start with a stale image on next // usage mImage = nullptr; } #ifdef MOZ_B2G_CAMERA NS_DispatchToMainThread(WrapRunnable(this, &MediaEngineWebRTCVideoSource::StopImpl)); #else mViERender->StopRender(mCaptureIndex); mViERender->RemoveRenderer(mCaptureIndex); mViECapture->StopCapture(mCaptureIndex); #endif return NS_OK; }
NS_IMETHOD Run() { NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread"); mManager = MediaManager::Get(); // Was a backend provided? if (!mBackendChosen) { mBackend = mManager->GetBackend(); } // Was a device provided? if (!mDeviceChosen) { nsresult rv = SelectDevice(); if (rv != NS_OK) { return rv; } } // It is an error if audio or video are requested along with picture. if (mPicture && (mAudio || mVideo)) { NS_DispatchToMainThread(new ErrorCallbackRunnable( mSuccess, mError, NS_LITERAL_STRING("NOT_SUPPORTED_ERR"), mWindowID )); return NS_OK; } if (mPicture) { ProcessGetUserMediaSnapshot(mVideoDevice->GetSource(), 0); return NS_OK; } ProcessGetUserMedia(mAudio ? mAudioDevice->GetSource() : nullptr, mVideo ? mVideoDevice->GetSource() : nullptr); return NS_OK; }
nsresult MediaEngineWebRTCVideoSource::Allocate(const MediaEnginePrefs &aPrefs) { LOG((__FUNCTION__)); #ifdef MOZ_B2G_CAMERA ReentrantMonitorAutoEnter sync(mCallbackMonitor); if (mState == kReleased && mInitDone) { ChooseCapability(aPrefs); NS_DispatchToMainThread(WrapRunnable(this, &MediaEngineWebRTCVideoSource::AllocImpl)); mCallbackMonitor.Wait(); if (mState != kAllocated) { return NS_ERROR_FAILURE; } } #else if (mState == kReleased && mInitDone) { // Note: if shared, we don't allow a later opener to affect the resolution. // (This may change depending on spec changes for Constraints/settings) ChooseCapability(aPrefs); if (mViECapture->AllocateCaptureDevice(NS_ConvertUTF16toUTF8(mUniqueId).get(), KMaxUniqueIdLength, mCaptureIndex)) { return NS_ERROR_FAILURE; } mState = kAllocated; LOG(("Video device %d allocated", mCaptureIndex)); } else if (mSources.IsEmpty()) { LOG(("Video device %d reallocated", mCaptureIndex)); } else { LOG(("Video device %d allocated shared", mCaptureIndex)); } #endif return NS_OK; }
/* boolean dispatchEvent (in sbIMediacoreEvent aEvent, [optional] PRBool aAsync); */ nsresult sbBaseMediacoreEventTarget::DispatchEvent(sbIMediacoreEvent *aEvent, PRBool aAsync, PRBool* _retval) { nsresult rv; // Note: in the async case, we need to make a new runnable, because // DispatchEvent has an out param, and XPCOM proxies can't deal with that. if (aAsync) { nsRefPtr<AsyncDispatchHelper> dispatchHelper = new AsyncDispatchHelper(static_cast<sbIMediacoreEventTarget*>(mTarget), aEvent); NS_ENSURE_TRUE(dispatchHelper, NS_ERROR_OUT_OF_MEMORY); rv = NS_DispatchToMainThread(dispatchHelper, NS_DISPATCH_NORMAL); NS_ENSURE_SUCCESS(rv, rv); return NS_OK; } if (!NS_IsMainThread()) { // we need to proxy to the main thread nsCOMPtr<sbIMediacoreEventTarget> proxiedSelf; { /* scope the monitor */ NS_ENSURE_TRUE(mMonitor, NS_ERROR_NOT_INITIALIZED); nsAutoMonitor mon(mMonitor); rv = do_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, NS_GET_IID(sbIMediacoreEventTarget), mTarget, NS_PROXY_SYNC | NS_PROXY_ALWAYS, getter_AddRefs(proxiedSelf)); NS_ENSURE_SUCCESS(rv, rv); } // don't have a return value if dispatching asynchronously // (since the variable is likely to be dead by that point) return proxiedSelf->DispatchEvent(aEvent, PR_FALSE, _retval); } return DispatchEventInternal(aEvent, _retval); }
bool NuwaParent::RecvNotifyReady() { #ifdef MOZ_NUWA_PROCESS if (!mContentParent || !mContentParent->IsNuwaProcess()) { NS_ERROR("Received NotifyReady() message from a non-Nuwa process."); return false; } // Creating a NonOwningRunnableMethod here is safe because refcount changes of // mContentParent have to go the the main thread. The mContentParent will // be alive when the runnable runs. nsCOMPtr<nsIRunnable> runnable = NS_NewNonOwningRunnableMethod(mContentParent.get(), &ContentParent::OnNuwaReady); MOZ_ASSERT(runnable); MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(runnable))); return true; #else NS_ERROR("NuwaParent::RecvNotifyReady() not implemented!"); return false; #endif }
NS_IMETHODIMP _OldCacheLoad::OnCacheEntryAvailable(nsICacheEntryDescriptor *entry, nsCacheAccessMode access, nsresult status) { LOG(("_OldCacheLoad::OnCacheEntryAvailable [this=%p, ent=%p, cb=%p, appcache=%p, access=%x]", this, entry, mCallback.get(), mAppCache.get(), access)); // XXX Bug 759805: Sometimes we will call this method directly from // HttpCacheQuery::Run when AsyncOpenCacheEntry fails, but // AsyncOpenCacheEntry will also call this method. As a workaround, we just // ensure we only execute this code once. NS_ENSURE_TRUE(mRunCount == 0, NS_ERROR_UNEXPECTED); ++mRunCount; mCacheEntry = entry ? new _OldCacheEntryWrapper(entry) : nullptr; mStatus = status; mNew = access == nsICache::ACCESS_WRITE; if (!mMainThreadOnly) Check(); return NS_DispatchToMainThread(this); }
nsresult MediaEngineGonkVideoSource::Deallocate(AllocationHandle* aHandle) { LOG((__FUNCTION__)); AssertIsOnOwningThread(); MOZ_ASSERT(!aHandle); bool empty; { MonitorAutoLock lock(mMonitor); empty = mSources.IsEmpty(); } if (empty) { ReentrantMonitorAutoEnter sync(mCallbackMonitor); if (mState != kStopped && mState != kAllocated) { return NS_ERROR_FAILURE; } // We do not register success callback here NS_DispatchToMainThread(WrapRunnable(RefPtr<MediaEngineGonkVideoSource>(this), &MediaEngineGonkVideoSource::DeallocImpl)); mCallbackMonitor.Wait(); if (mState != kReleased) { return NS_ERROR_FAILURE; } mState = kReleased; LOG(("Video device %d deallocated", mCaptureIndex)); } else { LOG(("Video device %d deallocated but still in use", mCaptureIndex)); } return NS_OK; }
void ClientLayerManager::Destroy() { // It's important to call ClearCachedResource before Destroy because the // former will early-return if the later has already run. ClearCachedResources(); LayerManager::Destroy(); if (mTransactionIdAllocator) { // Make sure to notify the refresh driver just in case it's waiting on a // pending transaction. Do this at the top of the event loop so we don't // cause a paint to occur during compositor shutdown. RefPtr<TransactionIdAllocator> allocator = mTransactionIdAllocator; uint64_t id = mLatestTransactionId; RefPtr<Runnable> task = NS_NewRunnableFunction([allocator, id] () -> void { allocator->NotifyTransactionCompleted(id); }); NS_DispatchToMainThread(task.forget()); } // Forget the widget pointer in case we outlive our owning widget. mWidget = nullptr; }
int VideoRenderer::DeliverFrame(unsigned char* buffer, int buffer_size, uint32_t time_stamp, int64_t render_time) { PRTime epoch_c = PR_Now(); PRFloat64 epoch = (PRFloat64)(epoch_c / MICROSECONDS); epoch += ((PRFloat64)(epoch_c % MICROSECONDS)) / MICROSECONDS; int fsize = width * height * 4; if (vCanvas) { /* Convert i420 to RGB32 to write on canvas */ nsAutoArrayPtr<PRUint8> rgb32(new PRUint8[fsize]); I420toRGB32(width, height, (const char *)buffer, (char *)rgb32.get() ); nsCOMPtr<nsIRunnable> render = new CanvasRenderer( vCanvas, width, height, rgb32, fsize ); NS_DispatchToMainThread(render); } return 0; }
void AudioContext::OnStateChanged(void* aPromise, AudioContextState aNewState) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT((mAudioContextState == AudioContextState::Suspended && aNewState == AudioContextState::Running) || (mAudioContextState == AudioContextState::Running && aNewState == AudioContextState::Suspended) || (mAudioContextState == AudioContextState::Running && aNewState == AudioContextState::Closed) || (mAudioContextState == AudioContextState::Suspended && aNewState == AudioContextState::Closed) || (mAudioContextState == aNewState), "Invalid AudioContextState transition"); MOZ_ASSERT( mIsOffline || aPromise || aNewState == AudioContextState::Running, "We should have a promise here if this is a real-time AudioContext." "Or this is the first time we switch to \"running\"."); if (aPromise) { Promise* promise = reinterpret_cast<Promise*>(aPromise); promise->MaybeResolve(JS::UndefinedHandleValue); DebugOnly<bool> rv = mPromiseGripArray.RemoveElement(promise); MOZ_ASSERT(rv, "Promise wasn't in the grip array?"); } if (mAudioContextState != aNewState) { nsRefPtr<OnStateChangeTask> onStateChangeTask = new OnStateChangeTask(this); NS_DispatchToMainThread(onStateChangeTask); } mAudioContextState = aNewState; }
NS_IMETHODIMP_(MozExternalRefCountType) SharedThreadPool::Release(void) { MOZ_ASSERT(sMonitor); ReentrantMonitorAutoEnter mon(*sMonitor); nsrefcnt count = --mRefCnt; NS_LOG_RELEASE(this, count, "SharedThreadPool"); if (count) { return count; } // Remove SharedThreadPool from table of pools. sPools->Remove(mName); MOZ_ASSERT(!sPools->Get(mName)); // Dispatch an event to the main thread to call Shutdown() on // the nsIThreadPool. The Runnable here will add a refcount to the pool, // and when the Runnable releases the nsIThreadPool it will be deleted. NS_DispatchToMainThread(NewRunnableMethod(mPool, &nsIThreadPool::Shutdown)); // Stabilize refcount, so that if something in the dtor QIs, it won't explode. mRefCnt = 1; delete this; return 0; }
nsresult MediaEngineGonkVideoSource::Stop(SourceMediaStream* aSource, TrackID aID) { LOG((__FUNCTION__)); { MonitorAutoLock lock(mMonitor); if (!mSources.RemoveElement(aSource)) { // Already stopped - this is allowed return NS_OK; } if (!mSources.IsEmpty()) { return NS_OK; } } ReentrantMonitorAutoEnter sync(mCallbackMonitor); if (mState != kStarted) { return NS_ERROR_FAILURE; } { MonitorAutoLock lock(mMonitor); mState = kStopped; aSource->EndTrack(aID); // Drop any cached image so we don't start with a stale image on next // usage mImage = nullptr; } NS_DispatchToMainThread(WrapRunnable(nsRefPtr<MediaEngineGonkVideoSource>(this), &MediaEngineGonkVideoSource::StopImpl)); return NS_OK; }
void CDMProxy::gmp_Init(uint32_t aPromiseId) { MOZ_ASSERT(IsOnGMPThread()); nsCOMPtr<mozIGeckoMediaPluginService> mps = do_GetService("@mozilla.org/gecko-media-plugin-service;1"); if (!mps) { RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR); return; } nsTArray<nsCString> tags; tags.AppendElement(NS_ConvertUTF16toUTF8(mKeySystem)); nsresult rv = mps->GetGMPDecryptor(&tags, GetOrigin(), &mCDM); if (NS_FAILED(rv) || !mCDM) { RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR); } else { mCallback = new CDMCallbackProxy(this); mCDM->Init(mCallback); nsRefPtr<nsIRunnable> task(NS_NewRunnableMethodWithArg<uint32_t>(this, &CDMProxy::OnCDMCreated, aPromiseId)); NS_DispatchToMainThread(task); } }
NS_IMETHODIMP EventSource::OnStopRequest(nsIRequest *aRequest, nsISupports *aContext, nsresult aStatusCode) { mWaitingForOnStopRequest = false; if (mReadyState == CLOSED) { return NS_ERROR_ABORT; } if (NS_FAILED(aStatusCode)) { DispatchFailConnection(); return aStatusCode; } nsresult rv; nsresult healthOfRequestResult = CheckHealthOfRequestCallback(aRequest); if (NS_SUCCEEDED(healthOfRequestResult) && mLastConvertionResult == NS_PARTIAL_MORE_INPUT) { // we had an incomplete UTF8 char at the end of the stream rv = ParseCharacter(REPLACEMENT_CHAR); NS_ENSURE_SUCCESS(rv, rv); } ClearFields(); nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(this, &EventSource::ReestablishConnection); NS_ENSURE_STATE(event); rv = NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); NS_ENSURE_SUCCESS(rv, rv); return healthOfRequestResult; }
bool WMFVideoMFTManager::InitializeDXVA() { // If we use DXVA but aren't running with a D3D layer manager then the // readback of decoded video frames from GPU to CPU memory grinds painting // to a halt, and makes playback performance *worse*. if (!mDXVAEnabled || (mLayersBackend != LayersBackend::LAYERS_D3D9 && mLayersBackend != LayersBackend::LAYERS_D3D10 && mLayersBackend != LayersBackend::LAYERS_D3D11)) { return false; } if (gfxWindowsPlatform::GetPlatform()->IsWARP()) { return false; } // The DXVA manager must be created on the main thread. nsRefPtr<CreateDXVAManagerEvent> event(new CreateDXVAManagerEvent()); NS_DispatchToMainThread(event, NS_DISPATCH_SYNC); mDXVA2Manager = event->mDXVA2Manager; return mDXVA2Manager != nullptr; }
void ContentProcessController::DispatchToRepaintThread(already_AddRefed<Runnable> aTask) { NS_DispatchToMainThread(Move(aTask)); }
template<class Super> bool Parent<Super>::RecvGetOriginKey(const uint32_t& aRequestId, const nsCString& aOrigin, const bool& aPrivateBrowsing, const bool& aPersist) { MOZ_ASSERT(NS_IsMainThread()); // First, get profile dir. MOZ_ASSERT(NS_IsMainThread()); nsCOMPtr<nsIFile> profileDir; nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(profileDir)); if (NS_WARN_IF(NS_FAILED(rv))) { return false; } // Then over to stream-transport thread to do the actual file io. // Stash a pledge to hold the answer and get an id for this request. RefPtr<Pledge<nsCString>> p = new Pledge<nsCString>(); uint32_t id = mOutstandingPledges.Append(*p); nsCOMPtr<nsIEventTarget> sts = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID); MOZ_ASSERT(sts); RefPtr<OriginKeyStore> store(mOriginKeyStore); bool sameProcess = mSameProcess; rv = sts->Dispatch(NewRunnableFrom([id, profileDir, store, sameProcess, aOrigin, aPrivateBrowsing, aPersist]() -> nsresult { MOZ_ASSERT(!NS_IsMainThread()); store->mOriginKeys.SetProfileDir(profileDir); nsCString result; if (aPrivateBrowsing) { store->mPrivateBrowsingOriginKeys.GetOriginKey(aOrigin, result); } else { store->mOriginKeys.GetOriginKey(aOrigin, result, aPersist); } // Pass result back to main thread. nsresult rv; rv = NS_DispatchToMainThread(NewRunnableFrom([id, store, sameProcess, result]() -> nsresult { Parent* parent = GccGetSingleton<Super>(); // GetSingleton(); if (!parent) { return NS_OK; } RefPtr<Pledge<nsCString>> p = parent->mOutstandingPledges.Remove(id); if (!p) { return NS_ERROR_UNEXPECTED; } p->Resolve(result); return NS_OK; }), NS_DISPATCH_NORMAL); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } return NS_OK; }), NS_DISPATCH_NORMAL); if (NS_WARN_IF(NS_FAILED(rv))) { return false; } p->Then([aRequestId, sameProcess](const nsCString& aKey) mutable { if (!sameProcess) { if (!sIPCServingParent) { return NS_OK; } Unused << sIPCServingParent->SendGetOriginKeyResponse(aRequestId, aKey); } else { RefPtr<MediaManager> mgr = MediaManager::GetInstance(); if (!mgr) { return NS_OK; } RefPtr<Pledge<nsCString>> pledge = mgr->mGetOriginKeyPledges.Remove(aRequestId); if (pledge) { pledge->Resolve(aKey); } } return NS_OK; }); return true; }
NS_IMETHODIMP OpenDatabaseHelper::Run() { NS_ASSERTION(mState != eCreated, "Dispatch was not called?!?"); if (NS_IsMainThread()) { // If we need to queue up a SetVersionHelper, do that here. if (mState == eSetVersionPending) { nsresult rv = StartSetVersion(); if (NS_SUCCEEDED(rv)) { return rv; } SetError(rv); // fall through and run the default error processing } // We've done whatever work we need to do on the DB thread, and any // SetVersion stuff is done by now. NS_ASSERTION(mState == eFiringEvents || mState == eSetVersionCompleted, "Why are we here?"); if (mState == eSetVersionCompleted) { // Allow transaction creation/other version change transactions to proceed // before we fire events. Other version changes will be postd to the end // of the event loop, and will be behind whatever the page does in // its error/success event handlers. mDatabase->ExitSetVersionTransaction(); mState = eFiringEvents; } else { // Notify the request that we're done, but only if we didn't just finish // a SetVersionHelper. In the SetVersionHelper case, that helper tells // the request that it is done, and we avoid calling NotifyHandlerCompleted // twice. nsresult rv = mOpenDBRequest->NotifyHelperCompleted(this); if (NS_SUCCEEDED(mResultCode) && NS_FAILED(rv)) { mResultCode = rv; } } NS_ASSERTION(mState == eFiringEvents, "Why are we here?"); if (NS_FAILED(mResultCode)) { DispatchErrorEvent(); } else { DispatchSuccessEvent(); } IndexedDatabaseManager* manager = IndexedDatabaseManager::Get(); NS_ASSERTION(manager, "This should never be null!"); manager->AllowNextSynchronizedOp(mASCIIOrigin, mDatabaseId); ReleaseMainThreadObjects(); return NS_OK; } // If we're on the DB thread, do that NS_ASSERTION(mState == eDBWork, "Why are we here?"); mResultCode = DoDatabaseWork(); NS_ASSERTION(mState != eDBWork, "We should be doing something else now."); return NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL); }
void nsPicoService::Init() { MOZ_ASSERT(!NS_IsMainThread()); MOZ_ASSERT(!mInitialized); if (!sPicoApi.Init()) { NS_WARNING("Failed to initialize pico library"); return; } // Use environment variable, or default android/b2g path nsAutoCString langPath(PR_GetEnv("PICO_LANG_PATH")); if (langPath.IsEmpty()) { langPath.AssignLiteral(GONK_PICO_LANG_PATH); } nsCOMPtr<nsIFile> voicesDir; NS_NewNativeLocalFile(langPath, true, getter_AddRefs(voicesDir)); nsCOMPtr<nsISimpleEnumerator> dirIterator; nsresult rv = voicesDir->GetDirectoryEntries(getter_AddRefs(dirIterator)); if (NS_FAILED(rv)) { NS_WARNING(nsPrintfCString("Failed to get contents of directory: %s", langPath.get()).get()); return; } bool hasMoreElements = false; rv = dirIterator->HasMoreElements(&hasMoreElements); MOZ_ASSERT(NS_SUCCEEDED(rv)); MonitorAutoLock autoLock(mVoicesMonitor); while (hasMoreElements && NS_SUCCEEDED(rv)) { nsCOMPtr<nsISupports> supports; rv = dirIterator->GetNext(getter_AddRefs(supports)); MOZ_ASSERT(NS_SUCCEEDED(rv)); nsCOMPtr<nsIFile> voiceFile = do_QueryInterface(supports); MOZ_ASSERT(voiceFile); nsAutoCString leafName; voiceFile->GetNativeLeafName(leafName); nsAutoString lang; if (GetVoiceFileLanguage(leafName, lang)) { nsAutoString uri; uri.AssignLiteral("urn:moz-tts:pico:"); uri.Append(lang); bool found = false; PicoVoice* voice = mVoices.GetWeak(uri, &found); if (!found) { voice = new PicoVoice(lang); mVoices.Put(uri, voice); } // Each voice consists of two lingware files: A language resource file, // suffixed by _ta.bin, and a speaker resource file, suffixed by _sb.bin. // We currently assume that there is a pair of files for each language. if (StringEndsWith(leafName, NS_LITERAL_CSTRING("_ta.bin"))) { rv = voiceFile->GetPersistentDescriptor(voice->mTaFile); MOZ_ASSERT(NS_SUCCEEDED(rv)); } else if (StringEndsWith(leafName, NS_LITERAL_CSTRING("_sg.bin"))) { rv = voiceFile->GetPersistentDescriptor(voice->mSgFile); MOZ_ASSERT(NS_SUCCEEDED(rv)); } } rv = dirIterator->HasMoreElements(&hasMoreElements); } NS_DispatchToMainThread(NS_NewRunnableMethod(this, &nsPicoService::RegisterVoices)); }
void AudioContext::OnStateChanged(void* aPromise, AudioContextState aNewState) { MOZ_ASSERT(NS_IsMainThread()); // This can happen if close() was called right after creating the // AudioContext, before the context has switched to "running". if (mAudioContextState == AudioContextState::Closed && aNewState == AudioContextState::Running && !aPromise) { return; } // This can happen if this is called in reaction to a // MediaStreamGraph shutdown, and a AudioContext was being // suspended at the same time, for example if a page was being // closed. if (mAudioContextState == AudioContextState::Closed && aNewState == AudioContextState::Suspended) { return; } #ifndef WIN32 // Bug 1170547 #ifndef XP_MACOSX #ifdef DEBUG if (!((mAudioContextState == AudioContextState::Suspended && aNewState == AudioContextState::Running) || (mAudioContextState == AudioContextState::Running && aNewState == AudioContextState::Suspended) || (mAudioContextState == AudioContextState::Running && aNewState == AudioContextState::Closed) || (mAudioContextState == AudioContextState::Suspended && aNewState == AudioContextState::Closed) || (mAudioContextState == aNewState))) { fprintf(stderr, "Invalid transition: mAudioContextState: %d -> aNewState %d\n", static_cast<int>(mAudioContextState), static_cast<int>(aNewState)); MOZ_ASSERT(false); } #endif // DEBUG #endif // XP_MACOSX #endif // WIN32 MOZ_ASSERT( mIsOffline || aPromise || aNewState == AudioContextState::Running, "We should have a promise here if this is a real-time AudioContext." "Or this is the first time we switch to \"running\"."); if (aPromise) { Promise* promise = reinterpret_cast<Promise*>(aPromise); promise->MaybeResolveWithUndefined(); DebugOnly<bool> rv = mPromiseGripArray.RemoveElement(promise); MOZ_ASSERT(rv, "Promise wasn't in the grip array?"); } if (mAudioContextState != aNewState) { RefPtr<OnStateChangeTask> onStateChangeTask = new OnStateChangeTask(this); NS_DispatchToMainThread(onStateChangeTask); } mAudioContextState = aNewState; }
mBufferSize ? static_cast<short*>(mBuffer->Data()) : nullptr, mBufferSize / 2); } private: nsRefPtr<SharedBuffer> mBuffer; size_t mBufferSize; bool mFirstData; nsRefPtr<PicoCallbackRunnable> mCallback; }; nsCOMPtr<nsIRunnable> sendEvent = new PicoSynthDataRunnable(aBuffer, aBufferSize, mFirstData, this); NS_DispatchToMainThread(sendEvent); mFirstData = false; } // nsISpeechTaskCallback NS_IMETHODIMP PicoCallbackRunnable::OnPause() { return NS_OK; } NS_IMETHODIMP PicoCallbackRunnable::OnResume() { return NS_OK;
void RootDirectoryEntry::GetInternal(const nsAString& aPath, const FileSystemFlags& aFlag, const Optional<OwningNonNull<EntryCallback>>& aSuccessCallback, const Optional<OwningNonNull<ErrorCallback>>& aErrorCallback, GetInternalType aType) const { if (!aSuccessCallback.WasPassed() && !aErrorCallback.WasPassed()) { return; } if (aFlag.mCreate) { ErrorCallbackHelper::Call(GetParentObject(), aErrorCallback, NS_ERROR_DOM_SECURITY_ERR); return; } nsTArray<nsString> parts; if (!FileSystemUtils::IsValidRelativeDOMPath(aPath, parts)) { ErrorCallbackHelper::Call(GetParentObject(), aErrorCallback, NS_ERROR_DOM_NOT_FOUND_ERR); return; } MOZ_ASSERT(!parts.IsEmpty()); RefPtr<Entry> entry; for (uint32_t i = 0; i < mEntries.Length(); ++i) { ErrorResult rv; nsAutoString name; mEntries[i]->GetName(name, rv); if (NS_WARN_IF(rv.Failed())) { ErrorCallbackHelper::Call(GetParentObject(), aErrorCallback, rv.StealNSResult()); return; } if (name == parts[0]) { entry = mEntries[i]; break; } } // Not found. if (!entry) { ErrorCallbackHelper::Call(GetParentObject(), aErrorCallback, NS_ERROR_DOM_NOT_FOUND_ERR); return; } // No subdirectory in the path. if (parts.Length() == 1) { if ((entry->IsFile() && aType == eGetDirectory) || (entry->IsDirectory() && aType == eGetFile)) { ErrorCallbackHelper::Call(GetParentObject(), aErrorCallback, NS_ERROR_DOM_TYPE_MISMATCH_ERR); return; } if (aSuccessCallback.WasPassed()) { RefPtr<EntryCallbackRunnable> runnable = new EntryCallbackRunnable(&aSuccessCallback.Value(), entry); nsresult rv = NS_DispatchToMainThread(runnable); NS_WARN_IF(NS_FAILED(rv)); } return; } // Subdirectories, but this is a file. if (entry->IsFile()) { ErrorCallbackHelper::Call(GetParentObject(), aErrorCallback, NS_ERROR_DOM_NOT_FOUND_ERR); return; } // Let's recreate a path without the first directory. nsAutoString path; for (uint32_t i = 1, len = parts.Length(); i < len; ++i) { path.Append(parts[i]); if (i < len - 1) { path.AppendLiteral(FILESYSTEM_DOM_PATH_SEPARATOR_LITERAL); } } auto* directoryEntry = static_cast<DirectoryEntry*>(entry.get()); directoryEntry->GetInternal(path, aFlag, aSuccessCallback, aErrorCallback, aType); }
void DASHRepDecoder::LoadNextByteRange() { NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); NS_ASSERTION(mResource, "Error: resource is reported as null!"); // Return silently if shutting down. if (mShuttingDown) { LOG1("Shutting down! Ignoring LoadNextByteRange()."); return; } ReentrantMonitorAutoEnter mon(GetReentrantMonitor()); NS_ASSERTION(mMainDecoder, "Error: main decoder is null!"); NS_ASSERTION(mMainDecoder->IsDecoderAllowedToDownloadData(this), "Should not be called on non-active decoders!"); // Cannot have empty byte ranges. if (mByteRanges.IsEmpty()) { LOG1("Error getting list of subsegment byte ranges."); DecodeError(); return; } // Get byte range for subsegment. int32_t subsegmentIdx = mMainDecoder->GetSubsegmentIndex(this); NS_ASSERTION(0 <= subsegmentIdx, "Subsegment index should be >= 0 for active decoders"); if (subsegmentIdx >= 0 && (uint32_t)subsegmentIdx < mByteRanges.Length()) { mCurrentByteRange = mByteRanges[subsegmentIdx]; mSubsegmentIdx = subsegmentIdx; } else { mCurrentByteRange.Clear(); mSubsegmentIdx = -1; LOG("End of subsegments: index [%d] out of range.", subsegmentIdx); return; } // Request a seek for the first reader. Required so that the reader is // primed to start here, and will block subsequent subsegment seeks unless // the subsegment has been read. if (subsegmentIdx == 0) { ReentrantMonitorAutoEnter mon(GetReentrantMonitor()); mReader->RequestSeekToSubsegment(0); } // Query resource for cached ranges; only download if it's not there. if (IsSubsegmentCached(mSubsegmentIdx)) { LOG("Subsegment [%d] bytes [%lld] to [%lld] already cached. No need to " "download.", mSubsegmentIdx, mCurrentByteRange.mStart, mCurrentByteRange.mEnd); nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(this, &DASHRepDecoder::DoNotifyDownloadEnded); nsresult rv = NS_DispatchToMainThread(event); if (NS_FAILED(rv)) { LOG("Error notifying subsegment [%d] cached: rv[0x%x].", mSubsegmentIdx, rv); NetworkError(); } return; } // Open byte range corresponding to subsegment. nsresult rv = mResource->OpenByteRange(nullptr, mCurrentByteRange); if (NS_FAILED(rv)) { LOG("Error opening byte range [%lld - %lld]: subsegmentIdx [%d] rv [%x].", mCurrentByteRange.mStart, mCurrentByteRange.mEnd, mSubsegmentIdx, rv); NetworkError(); return; } }
/* * Start session (called in a thread) */ void MediaRecorder::BeginSessionThread(void *data) { nsresult rv; MediaRecorder *mr = static_cast<MediaRecorder*>(data); Properties *params = mr->params; /* Setup backends */ #ifdef RAINBOW_Mac mr->aState->backend = new AudioSourceMac(params->chan, params->rate); mr->vState->backend = new VideoSourceMac(params->width, params->height); #endif #ifdef RAINBOW_Win mr->aState->backend = new AudioSourceWin(params->chan, params->rate); mr->vState->backend = new VideoSourceWin(params->width, params->height); #endif #ifdef RAINBOW_Nix mr->aState->backend = new AudioSourceNix(params->chan, params->rate); mr->vState->backend = new VideoSourceNix(params->width, params->height); #endif /* Is the given canvas source or destination? */ if (params->canvas) { mr->vState->backend = new VideoSourceCanvas(params->width, params->height); } /* Update parameters. What we asked for were just hints, * may not end up the same */ params->fps_n = mr->vState->backend->GetFPSN(); params->fps_d = mr->vState->backend->GetFPSD(); params->rate = mr->aState->backend->GetRate(); params->chan = mr->aState->backend->GetChannels(); /* FIXME: device detection TBD */ if (params->audio && (mr->aState == nsnull)) { NS_DispatchToMainThread(new MediaCallback( mr->observer, "error", "audio requested but no devices found" )); return; } if (params->video && (mr->vState == nsnull)) { NS_DispatchToMainThread(new MediaCallback( mr->observer, "error", "video requested but no devices found" )); return; } /* Let's DO this. */ if (params->video) { rv = mr->vState->backend->Start(mr->canvas); if (NS_FAILED(rv)) { NS_DispatchToMainThread(new MediaCallback( mr->observer, "error", "internal: could not start video session" )); return; } } /* No preview for audio */ mr->m_session = PR_TRUE; NS_DispatchToMainThread(new MediaCallback( mr->observer, "session-began", "" )); return; }
/* * End recording (called in a thread) */ void MediaRecorder::EndRecordingThread(void *data) { nsresult rv; PRUint32 wr; MediaRecorder *mr = static_cast<MediaRecorder*>(data); if (mr->v_rec) { rv = mr->vState->backend->StopRecording(); if (NS_FAILED(rv)) { NS_DispatchToMainThread(new MediaCallback( mr->observer, "error", "could not stop video recording" )); return; } } if (mr->a_rec) { rv = mr->aState->backend->Stop(); if (NS_FAILED(rv)) { NS_DispatchToMainThread(new MediaCallback( mr->observer, "error", "could not stop audio recording" )); return; } } /* Wait for encoder to finish */ if (mr->v_rec) { mr->v_stp = PR_TRUE; mr->vState->vPipeOut->Close(); } if (mr->a_rec) { mr->a_stp = PR_TRUE; mr->aState->aPipeOut->Close(); } PR_JoinThread(mr->thread); if (mr->v_rec) { mr->vState->vPipeIn->Close(); th_encode_free(mr->vState->th); /* Video trailer */ if (ogg_stream_flush(&mr->vState->os, &mr->vState->og)) { rv = mr->WriteData( mr->vState->og.header, mr->vState->og.header_len, &wr ); rv = mr->WriteData( mr->vState->og.body, mr->vState->og.body_len, &wr ); } ogg_stream_clear(&mr->vState->os); mr->v_rec = PR_FALSE; } if (mr->a_rec) { mr->aState->aPipeIn->Close(); /* Audio trailer */ vorbis_analysis_wrote(&mr->aState->vd, 0); mr->WriteAudio(); vorbis_block_clear(&mr->aState->vb); vorbis_dsp_clear(&mr->aState->vd); vorbis_comment_clear(&mr->aState->vc); vorbis_info_clear(&mr->aState->vi); ogg_stream_clear(&mr->aState->os); mr->a_rec = PR_FALSE; } /* GG */ mr->pipeStream->Close(); NS_DispatchToMainThread(new MediaCallback( mr->observer, "record-ended", "" )); return; }
void MediaRecorder::BeginRecordingThread(void *data) { nsresult rv; MediaRecorder *mr = static_cast<MediaRecorder*>(data); /* Get ready for video! */ if (mr->params->video) { mr->SetupTheoraBOS(); rv = mr->MakePipe( getter_AddRefs(mr->vState->vPipeIn), getter_AddRefs(mr->vState->vPipeOut) ); if (NS_FAILED(rv)) { NS_DispatchToMainThread(new MediaCallback( mr->observer, "error", "internal: could not create video pipe" )); return; } } /* Get ready for audio! */ if (mr->params->audio) { mr->SetupVorbisBOS(); rv = mr->MakePipe( getter_AddRefs(mr->aState->aPipeIn), getter_AddRefs(mr->aState->aPipeOut) ); if (NS_FAILED(rv)) { NS_DispatchToMainThread(new MediaCallback( mr->observer, "error", "internal: could not create audio pipe" )); return; } } if (mr->params->video) { mr->v_rec = PR_TRUE; mr->v_stp = PR_FALSE; mr->SetupTheoraHeaders(); mr->vState->backend->StartRecording(mr->vState->vPipeOut); } if (mr->params->audio) { mr->SetupVorbisHeaders(); rv = mr->aState->backend->Start(mr->aState->aPipeOut); if (NS_FAILED(rv)) { /* FIXME: Stop and clean up video! */ NS_DispatchToMainThread(new MediaCallback( mr->observer, "error", "internal: could not start audio recording" )); return; } mr->a_rec = PR_TRUE; mr->a_stp = PR_FALSE; } /* Start off encoder after notifying observer */ NS_DispatchToMainThread(new MediaCallback( mr->observer, "record-began", "" )); mr->Encode(); }
NS_IMETHODIMP RenameFolderTask::Run() { int ret = EWS_FAIL; nsresult rv; if (EWS_FAIL == NotifyBegin(this)) { return NS_OK; } ews_session * session = NULL; nsCOMPtr<IMailEwsMsgIncomingServer> ewsServer(do_QueryInterface(m_pIncomingServer, &rv)); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<IMailEwsService> ewsService; rv = ewsServer->GetService(getter_AddRefs(ewsService)); NS_ENSURE_SUCCESS(rv, rv); nsresult rv1 = ewsService->GetNewSession(&session); if (NS_SUCCEEDED(rv) && NS_SUCCEEDED(rv1) && session) { nsCOMPtr<IMailEwsMsgFolder> curFolder(do_QueryInterface(m_Folder)); nsCString savedFolderId; rv = curFolder->GetFolderId(savedFolderId); if (NS_FAILED(rv)) { NotifyError(this, EWS_FAIL, "unable to get folder id"); return NS_OK; } nsCString change_key; rv = curFolder->GetChangeKey(change_key); if (NS_FAILED(rv)) { NotifyError(this, EWS_FAIL, "unable to get folder change key"); return NS_OK; } ews_folder * folder = (ews_folder *)malloc(sizeof(char) * sizeof(ews_folder)); memset(folder, 0, sizeof(ews_folder)); char * display_name = ToNewUTF8String(m_NewName); folder->display_name = strdup(display_name); folder->id = strdup(savedFolderId.get()); folder->change_key = strdup(change_key.get()); NS_Free(display_name); char * err_msg = NULL; ret = ews_update_folder(session, folder, &err_msg); if (ret != EWS_SUCCESS) { mailews_logger << "rename folder on server fail:" << ret << "," << err_msg << std::endl; NotifyError(this, ret, err_msg); } if (err_msg) free(err_msg); ews_free_folder(folder); } else { NotifyError(this, session ? EWS_FAIL : 401, NULL); } ewsService->ReleaseSession(session); nsCOMPtr<nsIRunnable> resultrunnable = new RenameFolderDoneTask(ret, m_Folder, m_NewName, m_MsgWindow, m_pEwsTaskCallbacks, this); NS_DispatchToMainThread(resultrunnable); return NS_OK; }
void FakeMediaStreamGraph::DispatchToMainThreadAfterStreamStateUpdate(already_AddRefed<nsIRunnable> aRunnable) { nsCOMPtr<nsIRunnable> task = aRunnable; NS_DispatchToMainThread(task); }
template<class Super> mozilla::ipc::IPCResult Parent<Super>::RecvGetPrincipalKey(const uint32_t& aRequestId, const ipc::PrincipalInfo& aPrincipalInfo, const bool& aPersist) { MOZ_ASSERT(NS_IsMainThread()); // First, get profile dir. MOZ_ASSERT(NS_IsMainThread()); nsCOMPtr<nsIFile> profileDir; nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(profileDir)); if (NS_WARN_IF(NS_FAILED(rv))) { return IPCResult(this, false); } // Then over to stream-transport thread to do the actual file io. // Stash a pledge to hold the answer and get an id for this request. RefPtr<Pledge<nsCString>> p = new Pledge<nsCString>(); uint32_t id = mOutstandingPledges.Append(*p); nsCOMPtr<nsIEventTarget> sts = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID); MOZ_ASSERT(sts); RefPtr<Parent<Super>> that(this); rv = sts->Dispatch(NewRunnableFrom([this, that, id, profileDir, aPrincipalInfo, aPersist]() -> nsresult { MOZ_ASSERT(!NS_IsMainThread()); mOriginKeyStore->mOriginKeys.SetProfileDir(profileDir); nsresult rv; nsAutoCString result; if (IsPincipalInfoPrivate(aPrincipalInfo)) { rv = mOriginKeyStore->mPrivateBrowsingOriginKeys.GetPrincipalKey(aPrincipalInfo, result); } else { rv = mOriginKeyStore->mOriginKeys.GetPrincipalKey(aPrincipalInfo, result, aPersist); } if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } // Pass result back to main thread. rv = NS_DispatchToMainThread(NewRunnableFrom([this, that, id, result]() -> nsresult { if (mDestroyed) { return NS_OK; } RefPtr<Pledge<nsCString>> p = mOutstandingPledges.Remove(id); if (!p) { return NS_ERROR_UNEXPECTED; } p->Resolve(result); return NS_OK; }), NS_DISPATCH_NORMAL); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } return NS_OK; }), NS_DISPATCH_NORMAL); if (NS_WARN_IF(NS_FAILED(rv))) { return IPCResult(this, false); } p->Then([this, that, aRequestId](const nsCString& aKey) mutable { if (mDestroyed) { return NS_OK; } Unused << this->SendGetPrincipalKeyResponse(aRequestId, aKey); return NS_OK; }); return IPC_OK(); }