// NOTE: this will not find a new entry until it has been written to disk! // Consumer should take ownership of the resulting buffer. nsresult StartupCache::GetBuffer(const char* id, UniquePtr<char[]>* outbuf, uint32_t* length) { PROFILER_LABEL_FUNC(js::ProfileEntry::Category::OTHER); NS_ASSERTION(NS_IsMainThread(), "Startup cache only available on main thread"); WaitOnWriteThread(); if (!mStartupWriteInitiated) { CacheEntry* entry; nsDependentCString idStr(id); mTable.Get(idStr, &entry); if (entry) { *outbuf = MakeUnique<char[]>(entry->size); memcpy(outbuf->get(), entry->data.get(), entry->size); *length = entry->size; return NS_OK; } } nsresult rv = GetBufferFromZipArchive(mArchive, true, id, outbuf, length); if (NS_SUCCEEDED(rv)) return rv; RefPtr<nsZipArchive> omnijar = mozilla::Omnijar::GetReader(mozilla::Omnijar::APP); // no need to checksum omnijarred entries rv = GetBufferFromZipArchive(omnijar, false, id, outbuf, length); if (NS_SUCCEEDED(rv)) return rv; omnijar = mozilla::Omnijar::GetReader(mozilla::Omnijar::GRE); // no need to checksum omnijarred entries return GetBufferFromZipArchive(omnijar, false, id, outbuf, length); }
void StorageDBThread::SyncPreload(StorageCacheBridge* aCache, bool aForceSync) { PROFILER_LABEL_FUNC(js::ProfileEntry::Category::STORAGE); if (!aForceSync && aCache->LoadedCount()) { // Preload already started for this cache, just wait for it to finish. // LoadWait will exit after LoadDone on the cache has been called. SetHigherPriority(); aCache->LoadWait(); SetDefaultPriority(); return; } // Bypass sync load when an update is pending in the queue to write, we would // get incosistent data in the cache. Also don't allow sync main-thread // preload when DB open and init is still pending on the background thread. if (mDBReady && mWALModeEnabled) { bool pendingTasks; { MonitorAutoLock monitor(mThreadObserver->GetMonitor()); pendingTasks = mPendingTasks.IsOriginUpdatePending(aCache->OriginSuffix(), aCache->OriginNoSuffix()) || mPendingTasks.IsOriginClearPending(aCache->OriginSuffix(), aCache->OriginNoSuffix()); } if (!pendingTasks) { // WAL is enabled, thus do the load synchronously on the main thread. DBOperation preload(DBOperation::opPreload, aCache); preload.PerformAndFinalize(this); return; } } // Need to go asynchronously since WAL is not allowed or scheduled updates // need to be flushed first. // Schedule preload for this cache as the first operation. nsresult rv = InsertDBOp(new DBOperation(DBOperation::opPreloadUrgent, aCache)); // LoadWait exits after LoadDone of the cache has been called. if (NS_SUCCEEDED(rv)) { aCache->LoadWait(); } }
bool SapiService::Init() { PROFILER_LABEL_FUNC(js::ProfileEntry::Category::OTHER); MOZ_ASSERT(!mInitialized); if (Preferences::GetBool("media.webspeech.synth.test") || !Preferences::GetBool("media.webspeech.synth.enabled")) { // When enabled, we shouldn't add OS backend (Bug 1160844) return false; } if (FAILED(CoCreateInstance(CLSID_SpVoice, nullptr, CLSCTX_ALL, IID_ISpVoice, getter_AddRefs(mSapiClient)))) { return false; } // Set interest for all the events we are interested in ULONGLONG eventMask = SPFEI(SPEI_START_INPUT_STREAM) | SPFEI(SPEI_TTS_BOOKMARK) | SPFEI(SPEI_WORD_BOUNDARY) | SPFEI(SPEI_SENTENCE_BOUNDARY) | SPFEI(SPEI_END_INPUT_STREAM); if (FAILED(mSapiClient->SetInterest(eventMask, eventMask))) { return false; } // Get all the voices from sapi and register in the SynthVoiceRegistry if (!RegisterVoices()) { return false; } // Set the callback function for receiving the events mSapiClient->SetNotifyCallbackFunction( (SPNOTIFYCALLBACK*) SapiService::SpeechEventCallback, (WPARAM) this, 0); mInitialized = true; return true; }
bool AddonWrapper<Base>::get(JSContext* cx, JS::Handle<JSObject*> wrapper, JS::Handle<Value> receiver, JS::Handle<jsid> id, JS::MutableHandle<JS::Value> vp) const { PROFILER_LABEL_FUNC(js::ProfileEntry::Category::OTHER); Rooted<JSPropertyDescriptor> desc(cx); if (!InterposeProperty(cx, wrapper, nullptr, id, &desc)) return false; if (!desc.object()) return Base::get(cx, wrapper, receiver, id, vp); if (desc.getter()) { return Call(cx, receiver, desc.getterObject(), HandleValueArray::empty(), vp); } else { vp.set(desc.value()); return true; } }
RefreshResult FrameAnimator::AdvanceFrame(AnimationState& aState, TimeStamp aTime) { NS_ASSERTION(aTime <= TimeStamp::Now(), "Given time appears to be in the future"); PROFILER_LABEL_FUNC(js::ProfileEntry::Category::GRAPHICS); RefreshResult ret; // Determine what the next frame is, taking into account looping. uint32_t currentFrameIndex = aState.mCurrentAnimationFrameIndex; uint32_t nextFrameIndex = currentFrameIndex + 1; // Check if we're at the end of the loop. (FrameCount() returns Nothing() if // we don't know the total count yet.) if (aState.FrameCount() == Some(nextFrameIndex)) { // If we are not looping forever, initialize the loop counter if (aState.mLoopRemainingCount < 0 && aState.LoopCount() >= 0) { aState.mLoopRemainingCount = aState.LoopCount(); } // If animation mode is "loop once", or we're at end of loop counter, // it's time to stop animating. if (aState.mAnimationMode == imgIContainer::kLoopOnceAnimMode || aState.mLoopRemainingCount == 0) { ret.mAnimationFinished = true; } nextFrameIndex = 0; if (aState.mLoopRemainingCount > 0) { aState.mLoopRemainingCount--; } // If we're done, exit early. if (ret.mAnimationFinished) { return ret; } } if (nextFrameIndex >= aState.KnownFrameCount()) { // We've already advanced to the last decoded frame, nothing more we can do. // We're blocked by network/decoding from displaying the animation at the // rate specified, so that means the frame we are displaying (the latest // available) is the frame we want to be displaying at this time. So we // update the current animation time. If we didn't update the current // animation time then it could lag behind, which would indicate that we are // behind in the animation and should try to catch up. When we are done // decoding (and thus can loop around back to the start of the animation) we // would then jump to a random point in the animation to try to catch up. // But we were never behind in the animation. aState.mCurrentAnimationFrameTime = aTime; return ret; } // There can be frames in the surface cache with index >= KnownFrameCount() // which GetRawFrame() can access because an async decoder has decoded them, // but which AnimationState doesn't know about yet because we haven't received // the appropriate notification on the main thread. Make sure we stay in sync // with AnimationState. MOZ_ASSERT(nextFrameIndex < aState.KnownFrameCount()); RawAccessFrameRef nextFrame = GetRawFrame(nextFrameIndex); // We should always check to see if we have the next frame even if we have // previously finished decoding. If we needed to redecode (e.g. due to a draw // failure) we would have discarded all the old frames and may not yet have // the new ones. if (!nextFrame || !nextFrame->IsFinished()) { // Uh oh, the frame we want to show is currently being decoded (partial) // Wait until the next refresh driver tick and try again return ret; } if (GetTimeoutForFrame(nextFrameIndex) == FrameTimeout::Forever()) { ret.mAnimationFinished = true; } if (nextFrameIndex == 0) { ret.mDirtyRect = aState.FirstFrameRefreshArea(); } else { MOZ_ASSERT(nextFrameIndex == currentFrameIndex + 1); // Change frame if (!DoBlend(&ret.mDirtyRect, currentFrameIndex, nextFrameIndex)) { // something went wrong, move on to next NS_WARNING("FrameAnimator::AdvanceFrame(): Compositing of frame failed"); nextFrame->SetCompositingFailed(true); aState.mCurrentAnimationFrameTime = GetCurrentImgFrameEndTime(aState); aState.mCurrentAnimationFrameIndex = nextFrameIndex; return ret; } nextFrame->SetCompositingFailed(false); } aState.mCurrentAnimationFrameTime = GetCurrentImgFrameEndTime(aState); // If we can get closer to the current time by a multiple of the image's loop // time, we should. We can only do this if we're done decoding; otherwise, we // don't know the full loop length, and LoopLength() will have to return // FrameTimeout::Forever(). FrameTimeout loopTime = aState.LoopLength(); if (loopTime != FrameTimeout::Forever()) { TimeDuration delay = aTime - aState.mCurrentAnimationFrameTime; if (delay.ToMilliseconds() > loopTime.AsMilliseconds()) { // Explicitly use integer division to get the floor of the number of // loops. uint64_t loops = static_cast<uint64_t>(delay.ToMilliseconds()) / loopTime.AsMilliseconds(); aState.mCurrentAnimationFrameTime += TimeDuration::FromMilliseconds(loops * loopTime.AsMilliseconds()); } } // Set currentAnimationFrameIndex at the last possible moment aState.mCurrentAnimationFrameIndex = nextFrameIndex; // If we're here, we successfully advanced the frame. ret.mFrameAdvanced = true; return ret; }
FrameAnimator::RefreshResult FrameAnimator::AdvanceFrame(TimeStamp aTime) { NS_ASSERTION(aTime <= TimeStamp::Now(), "Given time appears to be in the future"); PROFILER_LABEL_FUNC(js::ProfileEntry::Category::GRAPHICS); RefreshResult ret; // Determine what the next frame is, taking into account looping. uint32_t currentFrameIndex = mCurrentAnimationFrameIndex; uint32_t nextFrameIndex = currentFrameIndex + 1; if (mImage->GetNumFrames() == nextFrameIndex) { // We can only accurately determine if we are at the end of the loop if we are // done decoding, otherwise we don't know how many frames there will be. if (!mDoneDecoding) { // We've already advanced to the last decoded frame, nothing more we can do. // We're blocked by network/decoding from displaying the animation at the // rate specified, so that means the frame we are displaying (the latest // available) is the frame we want to be displaying at this time. So we // update the current animation time. If we didn't update the current // animation time then it could lag behind, which would indicate that we // are behind in the animation and should try to catch up. When we are // done decoding (and thus can loop around back to the start of the // animation) we would then jump to a random point in the animation to // try to catch up. But we were never behind in the animation. mCurrentAnimationFrameTime = aTime; return ret; } // End of an animation loop... // If we are not looping forever, initialize the loop counter if (mLoopRemainingCount < 0 && LoopCount() >= 0) { mLoopRemainingCount = LoopCount(); } // If animation mode is "loop once", or we're at end of loop counter, // it's time to stop animating. if (mAnimationMode == imgIContainer::kLoopOnceAnimMode || mLoopRemainingCount == 0) { ret.animationFinished = true; } nextFrameIndex = 0; if (mLoopRemainingCount > 0) { mLoopRemainingCount--; } // If we're done, exit early. if (ret.animationFinished) { return ret; } } // There can be frames in the surface cache with index >= mImage->GetNumFrames() // that GetRawFrame can access because the decoding thread has decoded them, but // RasterImage hasn't acknowledged those frames yet. We don't want to go past // what RasterImage knows about so that we stay in sync with RasterImage. The code // above should obey this, the MOZ_ASSERT records this invariant. MOZ_ASSERT(nextFrameIndex < mImage->GetNumFrames()); RawAccessFrameRef nextFrame = GetRawFrame(nextFrameIndex); // If we're done decoding, we know we've got everything we're going to get. // If we aren't, we only display fully-downloaded frames; everything else // gets delayed. bool canDisplay = mDoneDecoding || (nextFrame && nextFrame->IsFinished()); if (!canDisplay) { // Uh oh, the frame we want to show is currently being decoded (partial) // Wait until the next refresh driver tick and try again return ret; } // Bad data if (GetTimeoutForFrame(nextFrameIndex) < 0) { ret.animationFinished = true; ret.error = true; } if (nextFrameIndex == 0) { ret.dirtyRect = mFirstFrameRefreshArea; } else { MOZ_ASSERT(nextFrameIndex == currentFrameIndex + 1); // Change frame if (!DoBlend(&ret.dirtyRect, currentFrameIndex, nextFrameIndex)) { // something went wrong, move on to next NS_WARNING("FrameAnimator::AdvanceFrame(): Compositing of frame failed"); nextFrame->SetCompositingFailed(true); mCurrentAnimationFrameTime = GetCurrentImgFrameEndTime(); mCurrentAnimationFrameIndex = nextFrameIndex; ret.error = true; return ret; } nextFrame->SetCompositingFailed(false); } mCurrentAnimationFrameTime = GetCurrentImgFrameEndTime(); // If we can get closer to the current time by a multiple of the image's loop // time, we should. We need to be done decoding in order to know the full loop // time though! int32_t loopTime = GetSingleLoopTime(); if (loopTime > 0) { // We shouldn't be advancing by a whole loop unless we are decoded and know // what a full loop actually is. GetSingleLoopTime should return -1 so this // never happens. MOZ_ASSERT(mDoneDecoding); TimeDuration delay = aTime - mCurrentAnimationFrameTime; if (delay.ToMilliseconds() > loopTime) { // Explicitly use integer division to get the floor of the number of // loops. uint64_t loops = static_cast<uint64_t>(delay.ToMilliseconds()) / loopTime; mCurrentAnimationFrameTime += TimeDuration::FromMilliseconds(loops * loopTime); } } // Set currentAnimationFrameIndex at the last possible moment mCurrentAnimationFrameIndex = nextFrameIndex; // If we're here, we successfully advanced the frame. ret.frameAdvanced = true; return ret; }