예제 #1
0
void WithSingleChunkDecode(const ImageTestCase& aTestCase,
                           const Maybe<IntSize>& aOutputSize,
                           Func aResultChecker)
{
  nsCOMPtr<nsIInputStream> inputStream = LoadFile(aTestCase.mPath);
  ASSERT_TRUE(inputStream != nullptr);

  // Figure out how much data we have.
  uint64_t length;
  nsresult rv = inputStream->Available(&length);
  ASSERT_TRUE(NS_SUCCEEDED(rv));

  // Write the data into a SourceBuffer.
  NotNull<RefPtr<SourceBuffer>> sourceBuffer = WrapNotNull(new SourceBuffer());
  sourceBuffer->ExpectLength(length);
  rv = sourceBuffer->AppendFromInputStream(inputStream, length);
  ASSERT_TRUE(NS_SUCCEEDED(rv));
  sourceBuffer->Complete(NS_OK);

  // Create a decoder.
  DecoderType decoderType =
    DecoderFactory::GetDecoderType(aTestCase.mMimeType);
  RefPtr<Decoder> decoder =
    DecoderFactory::CreateAnonymousDecoder(decoderType, sourceBuffer, aOutputSize,
                                           DefaultSurfaceFlags());
  ASSERT_TRUE(decoder != nullptr);
  RefPtr<IDecodingTask> task = new AnonymousDecodingTask(WrapNotNull(decoder));

  // Run the full decoder synchronously.
  task->Run();

  // Call the lambda to verify the expected results.
  aResultChecker(decoder);
}
예제 #2
0
/* static */ void
IDecodingTask::NotifyProgress(NotNull<RasterImage*> aImage,
                              NotNull<Decoder*> aDecoder)
{
  MOZ_ASSERT(aDecoder->HasProgress() && !aDecoder->IsMetadataDecode());

  // Capture the decoder's state. If we need to notify asynchronously, it's
  // important that we don't wait until the lambda actually runs to capture the
  // state that we're going to notify. That would both introduce data races on
  // the decoder's state and cause inconsistencies between the NotifyProgress()
  // calls we make off-main-thread and the notifications that RasterImage
  // actually receives, which would cause bugs.
  Progress progress = aDecoder->TakeProgress();
  IntRect invalidRect = aDecoder->TakeInvalidRect();
  Maybe<uint32_t> frameCount = aDecoder->TakeCompleteFrameCount();
  SurfaceFlags surfaceFlags = aDecoder->GetSurfaceFlags();

  // Synchronously notify if we can.
  if (NS_IsMainThread() &&
      !(aDecoder->GetDecoderFlags() & DecoderFlags::ASYNC_NOTIFY)) {
    aImage->NotifyProgress(progress, invalidRect,
                           frameCount, surfaceFlags);
    return;
  }

  // We're forced to notify asynchronously.
  NotNull<RefPtr<RasterImage>> image = aImage;
  NS_DispatchToMainThread(NS_NewRunnableFunction([=]() -> void {
    image->NotifyProgress(progress, invalidRect,
                          frameCount, surfaceFlags);
  }));
}
예제 #3
0
static void
NotifyProgress(NotNull<Decoder*> aDecoder)
{
  MOZ_ASSERT(aDecoder->HasProgress() && !aDecoder->IsMetadataDecode());

  Progress progress = aDecoder->TakeProgress();
  IntRect invalidRect = aDecoder->TakeInvalidRect();
  Maybe<uint32_t> frameCount = aDecoder->TakeCompleteFrameCount();
  SurfaceFlags surfaceFlags = aDecoder->GetSurfaceFlags();

  // Synchronously notify if we can.
  if (NS_IsMainThread() &&
      !(aDecoder->GetDecoderFlags() & DecoderFlags::ASYNC_NOTIFY)) {
    aDecoder->GetImage()->NotifyProgress(progress, invalidRect,
                                         frameCount, surfaceFlags);
    return;
  }

  // We're forced to notify asynchronously.
  NotNull<RefPtr<Decoder>> decoder = aDecoder;
  NS_DispatchToMainThread(NS_NewRunnableFunction([=]() -> void {
    decoder->GetImage()->NotifyProgress(progress, invalidRect,
                                        frameCount, surfaceFlags);
  }));
}
예제 #4
0
IPCResult
IPCResult::Fail(NotNull<IProtocol*> actor, const char* where, const char* why)
{
  // Calls top-level protocol to handle the error.
  nsPrintfCString errorMsg("%s::%s %s\n", actor->ProtocolName(), where, why);
  actor->GetIPCChannel()->Listener()->ProcessingError(
    HasResultCodes::MsgProcessingError, errorMsg.get());
  return IPCResult(false);
}
예제 #5
0
void
MsaaIdGenerator::ReleaseID(NotNull<AccessibleWrap*> aAccWrap)
{
  if (!ReleaseID(aAccWrap->GetExistingID())) {
    // This may happen if chrome holds a proxy whose ID was originally generated
    // by a content process. Since ReleaseID only has meaning in the process
    // that originally generated that ID, we ignore ReleaseID calls for any ID
    // that did not come from the current process.
    MOZ_ASSERT(aAccWrap->IsProxy());
  }
}
DecodedSurfaceProvider::DecodedSurfaceProvider(NotNull<RasterImage*> aImage,
                                               const SurfaceKey& aSurfaceKey,
                                               NotNull<Decoder*> aDecoder)
  : ISurfaceProvider(ImageKey(aImage.get()), aSurfaceKey,
                     AvailabilityState::StartAsPlaceholder())
  , mImage(aImage.get())
  , mMutex("mozilla::image::DecodedSurfaceProvider")
  , mDecoder(aDecoder.get())
{
  MOZ_ASSERT(!mDecoder->IsMetadataDecode(),
             "Use MetadataDecodingTask for metadata decodes");
  MOZ_ASSERT(mDecoder->IsFirstFrameDecode(),
             "Use AnimationSurfaceProvider for animation decodes");
}
예제 #7
0
/* static */ already_AddRefed<Decoder>
DecoderFactory::CreateDecoderForICOResource(DecoderType aType,
                                            SourceBufferIterator&& aIterator,
                                            NotNull<nsICODecoder*> aICODecoder,
                                            bool aIsMetadataDecode,
                                            const Maybe<IntSize>& aExpectedSize,
                                            const Maybe<uint32_t>& aDataOffset
                                              /* = Nothing() */)
{
  // Create the decoder.
  RefPtr<Decoder> decoder;
  switch (aType) {
    case DecoderType::BMP:
      MOZ_ASSERT(aDataOffset);
      decoder = new nsBMPDecoder(aICODecoder->GetImageMaybeNull(), *aDataOffset);
      break;

    case DecoderType::PNG:
      MOZ_ASSERT(!aDataOffset);
      decoder = new nsPNGDecoder(aICODecoder->GetImageMaybeNull());
      break;

    default:
      MOZ_ASSERT_UNREACHABLE("Invalid ICO resource decoder type");
      return nullptr;
  }

  MOZ_ASSERT(decoder);

  // Initialize the decoder, copying settings from @aICODecoder.
  decoder->SetMetadataDecode(aIsMetadataDecode);
  decoder->SetIterator(Forward<SourceBufferIterator>(aIterator));
  if (!aIsMetadataDecode) {
    decoder->SetOutputSize(aICODecoder->OutputSize());
  }
  if (aExpectedSize) {
    decoder->SetExpectedSize(*aExpectedSize);
  }
  decoder->SetDecoderFlags(aICODecoder->GetDecoderFlags());
  decoder->SetSurfaceFlags(aICODecoder->GetSurfaceFlags());
  decoder->SetFinalizeFrames(false);

  if (NS_FAILED(decoder->Init())) {
    return nullptr;
  }

  return decoder.forget();
}
예제 #8
0
/* static */ already_AddRefed<IDecodingTask>
DecoderFactory::CreateAnimationDecoder(DecoderType aType,
                                       NotNull<RasterImage*> aImage,
                                       NotNull<SourceBuffer*> aSourceBuffer,
                                       DecoderFlags aDecoderFlags,
                                       SurfaceFlags aSurfaceFlags)
{
  if (aType == DecoderType::UNKNOWN) {
    return nullptr;
  }

  MOZ_ASSERT(aType == DecoderType::GIF || aType == DecoderType::PNG,
             "Calling CreateAnimationDecoder for non-animating DecoderType");

  RefPtr<Decoder> decoder =
    GetDecoder(aType, aImage, /* aIsRedecode = */ true);
  MOZ_ASSERT(decoder, "Should have a decoder now");

  // Initialize the decoder.
  decoder->SetMetadataDecode(false);
  decoder->SetIterator(aSourceBuffer->Iterator());
  decoder->SetDecoderFlags(aDecoderFlags | DecoderFlags::IS_REDECODE);
  decoder->SetSurfaceFlags(aSurfaceFlags);

  decoder->Init();
  if (NS_FAILED(decoder->GetDecoderError())) {
    return nullptr;
  }

  RefPtr<IDecodingTask> task = new DecodingTask(WrapNotNull(decoder));
  return task.forget();
}
예제 #9
0
/* static */ already_AddRefed<IDecodingTask>
DecoderFactory::CreateMetadataDecoder(DecoderType aType,
                                      NotNull<RasterImage*> aImage,
                                      NotNull<SourceBuffer*> aSourceBuffer,
                                      int aSampleSize)
{
  if (aType == DecoderType::UNKNOWN) {
    return nullptr;
  }

  RefPtr<Decoder> decoder =
    GetDecoder(aType, aImage, /* aIsRedecode = */ false);
  MOZ_ASSERT(decoder, "Should have a decoder now");

  // Initialize the decoder.
  decoder->SetMetadataDecode(true);
  decoder->SetIterator(aSourceBuffer->Iterator());
  decoder->SetSampleSize(aSampleSize);

  decoder->Init();
  if (NS_FAILED(decoder->GetDecoderError())) {
    return nullptr;
  }

  RefPtr<IDecodingTask> task = new MetadataDecodingTask(WrapNotNull(decoder));
  return task.forget();
}
예제 #10
0
static void
NotifyDecodeComplete(NotNull<Decoder*> aDecoder)
{
  // Synchronously notify if we can.
  if (NS_IsMainThread() &&
      !(aDecoder->GetDecoderFlags() & DecoderFlags::ASYNC_NOTIFY)) {
    aDecoder->GetImage()->FinalizeDecoder(aDecoder);
    return;
  }

  // We're forced to notify asynchronously.
  NotNull<RefPtr<Decoder>> decoder = aDecoder;
  NS_DispatchToMainThread(NS_NewRunnableFunction([=]() -> void {
    decoder->GetImage()->FinalizeDecoder(decoder.get());
  }));
}
예제 #11
0
IAccessibleHolder
CreateHolderFromAccessible(NotNull<Accessible*> aAccToWrap)
{
  MOZ_ASSERT(NS_IsMainThread());

  STAUniquePtr<IAccessible> iaToProxy;
  aAccToWrap->GetNativeInterface(mscom::getter_AddRefs(iaToProxy));
  MOZ_DIAGNOSTIC_ASSERT(iaToProxy);
  if (!iaToProxy) {
    return nullptr;
  }

  static const bool useHandler =
    Preferences::GetBool("accessibility.handler.enabled", false) &&
    IsHandlerRegistered();

  RefPtr<HandlerProvider> payload;
  if (useHandler) {
    payload = new HandlerProvider(IID_IAccessible,
                                  mscom::ToInterceptorTargetPtr(iaToProxy));
  }

  ProxyUniquePtr<IAccessible> intercepted;
  HRESULT hr = MainThreadHandoff::WrapInterface(Move(iaToProxy), payload,
                                                (IAccessible**) mscom::getter_AddRefs(intercepted));
  MOZ_ASSERT(SUCCEEDED(hr));
  if (FAILED(hr)) {
    return nullptr;
  }

  return IAccessibleHolder(Move(intercepted));
}
예제 #12
0
void
MsaaIdGenerator::ReleaseID(NotNull<sdnAccessible*> aSdnAcc)
{
  Maybe<uint32_t> id = aSdnAcc->ReleaseUniqueID();
  if (id.isSome()) {
    DebugOnly<bool> released = ReleaseID(id.value());
    MOZ_ASSERT(released);
  }
}
예제 #13
0
static void
CheckDecoderMultiChunk(const ImageTestCase& aTestCase)
{
  nsCOMPtr<nsIInputStream> inputStream = LoadFile(aTestCase.mPath);
  ASSERT_TRUE(inputStream != nullptr);

  // Figure out how much data we have.
  uint64_t length;
  nsresult rv = inputStream->Available(&length);
  ASSERT_TRUE(NS_SUCCEEDED(rv));

  // Create a SourceBuffer and a decoder.
  NotNull<RefPtr<SourceBuffer>> sourceBuffer = WrapNotNull(new SourceBuffer());
  sourceBuffer->ExpectLength(length);
  DecoderType decoderType =
    DecoderFactory::GetDecoderType(aTestCase.mMimeType);
  RefPtr<Decoder> decoder =
    DecoderFactory::CreateAnonymousDecoder(decoderType, sourceBuffer, Nothing(),
                                           DefaultSurfaceFlags());
  ASSERT_TRUE(decoder != nullptr);
  RefPtr<IDecodingTask> task = new AnonymousDecodingTask(WrapNotNull(decoder));

  for (uint64_t read = 0; read < length ; ++read) {
    uint64_t available = 0;
    rv = inputStream->Available(&available);
    ASSERT_TRUE(available > 0);
    ASSERT_TRUE(NS_SUCCEEDED(rv));

    rv = sourceBuffer->AppendFromInputStream(inputStream, 1);
    ASSERT_TRUE(NS_SUCCEEDED(rv));

    task->Run();
  }

  sourceBuffer->Complete(NS_OK);
  task->Run();
  
  CheckDecoderResults(aTestCase, decoder);
}
예제 #14
0
/* static */ already_AddRefed<IDecodingTask>
DecoderFactory::CreateDecoder(DecoderType aType,
                              NotNull<RasterImage*> aImage,
                              NotNull<SourceBuffer*> aSourceBuffer,
                              const IntSize& aIntrinsicSize,
                              const IntSize& aOutputSize,
                              DecoderFlags aDecoderFlags,
                              SurfaceFlags aSurfaceFlags)
{
  if (aType == DecoderType::UNKNOWN) {
    return nullptr;
  }

  // Create an anonymous decoder. Interaction with the SurfaceCache and the
  // owning RasterImage will be mediated by DecodedSurfaceProvider.
  RefPtr<Decoder> decoder =
    GetDecoder(aType, nullptr, bool(aDecoderFlags & DecoderFlags::IS_REDECODE));
  MOZ_ASSERT(decoder, "Should have a decoder now");

  // Initialize the decoder.
  decoder->SetMetadataDecode(false);
  decoder->SetIterator(aSourceBuffer->Iterator());
  decoder->SetOutputSize(aOutputSize);
  decoder->SetDecoderFlags(aDecoderFlags | DecoderFlags::FIRST_FRAME_ONLY);
  decoder->SetSurfaceFlags(aSurfaceFlags);

  if (NS_FAILED(decoder->Init())) {
    return nullptr;
  }

  // Create a DecodedSurfaceProvider which will manage the decoding process and
  // make this decoder's output available in the surface cache.
  SurfaceKey surfaceKey =
    RasterSurfaceKey(aOutputSize, aSurfaceFlags, PlaybackType::eStatic);
  auto provider = MakeNotNull<RefPtr<DecodedSurfaceProvider>>(
    aImage, surfaceKey, WrapNotNull(decoder));
  if (aDecoderFlags & DecoderFlags::CANNOT_SUBSTITUTE) {
    provider->Availability().SetCannotSubstitute();
  }

  // Attempt to insert the surface provider into the surface cache right away so
  // we won't trigger any more decoders with the same parameters.
  if (SurfaceCache::Insert(provider) != InsertOutcome::SUCCESS) {
    return nullptr;
  }

  // Return the surface provider in its IDecodingTask guise.
  RefPtr<IDecodingTask> task = provider.get();
  return task.forget();
}
예제 #15
0
/* static */ already_AddRefed<IDecodingTask>
DecoderFactory::CreateAnimationDecoder(DecoderType aType,
                                       NotNull<RasterImage*> aImage,
                                       NotNull<SourceBuffer*> aSourceBuffer,
                                       const IntSize& aIntrinsicSize,
                                       DecoderFlags aDecoderFlags,
                                       SurfaceFlags aSurfaceFlags)
{
  if (aType == DecoderType::UNKNOWN) {
    return nullptr;
  }

  MOZ_ASSERT(aType == DecoderType::GIF || aType == DecoderType::PNG,
             "Calling CreateAnimationDecoder for non-animating DecoderType");

  // Create an anonymous decoder. Interaction with the SurfaceCache and the
  // owning RasterImage will be mediated by AnimationSurfaceProvider.
  RefPtr<Decoder> decoder = GetDecoder(aType, nullptr, /* aIsRedecode = */ true);
  MOZ_ASSERT(decoder, "Should have a decoder now");

  // Initialize the decoder.
  decoder->SetMetadataDecode(false);
  decoder->SetIterator(aSourceBuffer->Iterator());
  decoder->SetDecoderFlags(aDecoderFlags | DecoderFlags::IS_REDECODE);
  decoder->SetSurfaceFlags(aSurfaceFlags);

  if (NS_FAILED(decoder->Init())) {
    return nullptr;
  }

  // Create an AnimationSurfaceProvider which will manage the decoding process
  // and make this decoder's output available in the surface cache.
  SurfaceKey surfaceKey =
    RasterSurfaceKey(aIntrinsicSize, aSurfaceFlags, PlaybackType::eAnimated);
  auto provider = MakeNotNull<RefPtr<AnimationSurfaceProvider>>(
    aImage, surfaceKey, WrapNotNull(decoder));

  // Attempt to insert the surface provider into the surface cache right away so
  // we won't trigger any more decoders with the same parameters.
  if (SurfaceCache::Insert(provider) != InsertOutcome::SUCCESS) {
    return nullptr;
  }

  // Return the surface provider in its IDecodingTask guise.
  RefPtr<IDecodingTask> task = provider.get();
  return task.forget();
}
예제 #16
0
/* static */ already_AddRefed<Decoder>
DecoderFactory::CreateAnonymousDecoder(DecoderType aType,
                                       NotNull<SourceBuffer*> aSourceBuffer,
                                       const Maybe<IntSize>& aTargetSize,
                                       SurfaceFlags aSurfaceFlags)
{
  if (aType == DecoderType::UNKNOWN) {
    return nullptr;
  }

  RefPtr<Decoder> decoder =
    GetDecoder(aType, /* aImage = */ nullptr, /* aIsRedecode = */ false);
  MOZ_ASSERT(decoder, "Should have a decoder now");

  // Initialize the decoder.
  decoder->SetMetadataDecode(false);
  decoder->SetIterator(aSourceBuffer->Iterator());

  // Anonymous decoders are always transient; we don't want to optimize surfaces
  // or do any other expensive work that might be wasted.
  DecoderFlags decoderFlags = DecoderFlags::IMAGE_IS_TRANSIENT;

  // Without an image, the decoder can't store anything in the SurfaceCache, so
  // callers will only be able to retrieve the most recent frame via
  // Decoder::GetCurrentFrame(). That means that anonymous decoders should
  // always be first-frame-only decoders, because nobody ever wants the *last*
  // frame.
  decoderFlags |= DecoderFlags::FIRST_FRAME_ONLY;

  decoder->SetDecoderFlags(decoderFlags);
  decoder->SetSurfaceFlags(aSurfaceFlags);

  // Set a target size for downscale-during-decode if applicable.
  if (aTargetSize) {
    DebugOnly<nsresult> rv = decoder->SetTargetSize(*aTargetSize);
    MOZ_ASSERT(NS_SUCCEEDED(rv), "Bad downscale-during-decode target size?");
  }

  decoder->Init();
  if (NS_FAILED(decoder->GetDecoderError())) {
    return nullptr;
  }

  return decoder.forget();
}
예제 #17
0
/* static */ already_AddRefed<IDecodingTask>
DecoderFactory::CreateDecoder(DecoderType aType,
                              NotNull<RasterImage*> aImage,
                              NotNull<SourceBuffer*> aSourceBuffer,
                              const Maybe<IntSize>& aTargetSize,
                              DecoderFlags aDecoderFlags,
                              SurfaceFlags aSurfaceFlags,
                              int aSampleSize)
{
  if (aType == DecoderType::UNKNOWN) {
    return nullptr;
  }

  RefPtr<Decoder> decoder =
    GetDecoder(aType, aImage, bool(aDecoderFlags & DecoderFlags::IS_REDECODE));
  MOZ_ASSERT(decoder, "Should have a decoder now");

  // Initialize the decoder.
  decoder->SetMetadataDecode(false);
  decoder->SetIterator(aSourceBuffer->Iterator());
  decoder->SetDecoderFlags(aDecoderFlags | DecoderFlags::FIRST_FRAME_ONLY);
  decoder->SetSurfaceFlags(aSurfaceFlags);
  decoder->SetSampleSize(aSampleSize);

  // Set a target size for downscale-during-decode if applicable.
  if (aTargetSize) {
    DebugOnly<nsresult> rv = decoder->SetTargetSize(*aTargetSize);
    MOZ_ASSERT(NS_SUCCEEDED(rv), "Bad downscale-during-decode target size?");
  }

  decoder->Init();
  if (NS_FAILED(decoder->GetDecoderError())) {
    return nullptr;
  }

  RefPtr<IDecodingTask> task = new DecodingTask(WrapNotNull(decoder));
  return task.forget();
}
예제 #18
0
/* static */ already_AddRefed<Decoder>
DecoderFactory::CreateAnonymousMetadataDecoder(DecoderType aType,
                                               NotNull<SourceBuffer*> aSourceBuffer)
{
  if (aType == DecoderType::UNKNOWN) {
    return nullptr;
  }

  RefPtr<Decoder> decoder =
    GetDecoder(aType, /* aImage = */ nullptr, /* aIsRedecode = */ false);
  MOZ_ASSERT(decoder, "Should have a decoder now");

  // Initialize the decoder.
  decoder->SetMetadataDecode(true);
  decoder->SetIterator(aSourceBuffer->Iterator());
  decoder->SetDecoderFlags(DecoderFlags::FIRST_FRAME_ONLY);

  if (NS_FAILED(decoder->Init())) {
    return nullptr;
  }

  return decoder.forget();
}
예제 #19
0
void
nsThreadManager::Shutdown()
{
  MOZ_ASSERT(NS_IsMainThread(), "shutdown not called from main thread");

  // Prevent further access to the thread manager (no more new threads!)
  //
  // What happens if shutdown happens before NewThread completes?
  // We Shutdown() the new thread, and return error if we've started Shutdown
  // between when NewThread started, and when the thread finished initializing
  // and registering with ThreadManager.
  //
  mInitialized = false;

  // Empty the main thread event queue before we begin shutting down threads.
  NS_ProcessPendingEvents(mMainThread);

  // We gather the threads from the hashtable into a list, so that we avoid
  // holding the hashtable lock while calling nsIThread::Shutdown.
  nsThreadArray threads;
  {
    OffTheBooksMutexAutoLock lock(mLock);
    for (auto iter = mThreadsByPRThread.Iter(); !iter.Done(); iter.Next()) {
      RefPtr<nsThread>& thread = iter.Data();
      threads.AppendElement(WrapNotNull(thread));
      iter.Remove();
    }
  }

  // It's tempting to walk the list of threads here and tell them each to stop
  // accepting new events, but that could lead to badness if one of those
  // threads is stuck waiting for a response from another thread.  To do it
  // right, we'd need some way to interrupt the threads.
  //
  // Instead, we process events on the current thread while waiting for threads
  // to shutdown.  This means that we have to preserve a mostly functioning
  // world until such time as the threads exit.

  // Shutdown all threads that require it (join with threads that we created).
  for (uint32_t i = 0; i < threads.Length(); ++i) {
    NotNull<nsThread*> thread = threads[i];
    if (thread->ShutdownRequired()) {
      thread->Shutdown();
    }
  }

  // NB: It's possible that there are events in the queue that want to *start*
  // an asynchronous shutdown. But we have already shutdown the threads above,
  // so there's no need to worry about them. We only have to wait for all
  // in-flight asynchronous thread shutdowns to complete.
  mMainThread->WaitForAllAsynchronousShutdowns();

  // In case there are any more events somehow...
  NS_ProcessPendingEvents(mMainThread);

  // There are no more background threads at this point.

  // Clear the table of threads.
  {
    OffTheBooksMutexAutoLock lock(mLock);
    mThreadsByPRThread.Clear();
  }

  // Normally thread shutdown clears the observer for the thread, but since the
  // main thread is special we do it manually here after we're sure all events
  // have been processed.
  mMainThread->SetObserver(nullptr);
  mMainThread->ClearObservers();

  // Release main thread object.
  mMainThread = nullptr;

  // Remove the TLS entry for the main thread.
  PR_SetThreadPrivate(mCurThreadIndex, nullptr);
}
예제 #20
0
/* static */ void
IDecodingTask::NotifyProgress(NotNull<Decoder*> aDecoder)
{
  MOZ_ASSERT(aDecoder->HasProgress() && !aDecoder->IsMetadataDecode());

  // Synchronously notify if we can.
  if (NS_IsMainThread() &&
      !(aDecoder->GetDecoderFlags() & DecoderFlags::ASYNC_NOTIFY)) {
    aDecoder->GetImage()->NotifyProgress(aDecoder->TakeProgress(),
                                         aDecoder->TakeInvalidRect(),
                                         aDecoder->GetSurfaceFlags());
    return;
  }

  // We're forced to notify asynchronously.
  NotNull<RefPtr<Decoder>> decoder = aDecoder;
  NS_DispatchToMainThread(NS_NewRunnableFunction([=]() -> void {
    decoder->GetImage()->NotifyProgress(decoder->TakeProgress(),
                                        decoder->TakeInvalidRect(),
                                        decoder->GetSurfaceFlags());
  }));
}
예제 #21
0
/* static */ void
IDecodingTask::NotifyDecodeComplete(NotNull<RasterImage*> aImage,
                                    NotNull<Decoder*> aDecoder)
{
  MOZ_ASSERT(aDecoder->HasError() || !aDecoder->InFrame(),
             "Decode complete in the middle of a frame?");

  // Capture the decoder's state.
  DecoderFinalStatus finalStatus = aDecoder->FinalStatus();
  ImageMetadata metadata = aDecoder->GetImageMetadata();
  DecoderTelemetry telemetry = aDecoder->Telemetry();
  Progress progress = aDecoder->TakeProgress();
  IntRect invalidRect = aDecoder->TakeInvalidRect();
  Maybe<uint32_t> frameCount = aDecoder->TakeCompleteFrameCount();
  SurfaceFlags surfaceFlags = aDecoder->GetSurfaceFlags();

  // Synchronously notify if we can.
  if (NS_IsMainThread() &&
      !(aDecoder->GetDecoderFlags() & DecoderFlags::ASYNC_NOTIFY)) {
    aImage->NotifyDecodeComplete(finalStatus, metadata, telemetry, progress,
                                 invalidRect, frameCount, surfaceFlags);
    return;
  }

  // We're forced to notify asynchronously.
  NotNull<RefPtr<RasterImage>> image = aImage;
  NS_DispatchToMainThread(NS_NewRunnableFunction([=]() -> void {
    image->NotifyDecodeComplete(finalStatus, metadata, telemetry, progress,
                                invalidRect, frameCount, surfaceFlags);
  }));
}
예제 #22
0
void
TestNotNullWithMyPtr()
{
  int i4 = 4;
  int i5 = 5;

  MyPtr<int> my4 = &i4;
  MyPtr<int> my5 = &i5;

  NotNull<int*> nni4 = WrapNotNull(&i4);
  NotNull<int*> nni5 = WrapNotNull(&i5);
  NotNull<MyPtr<int>> nnmy4 = WrapNotNull(my4);

  //WrapNotNull(nullptr);                       // no wrapping from nullptr
  //WrapNotNull(0);                             // no wrapping from zero

  // NotNull<int*> construction combinations
  //NotNull<int*> nni4a;                        // no default
  //NotNull<int*> nni4a(nullptr);               // no nullptr
  //NotNull<int*> nni4a(0);                     // no zero
  //NotNull<int*> nni4a(&i4);                   // no int*
  //NotNull<int*> nni4a(my4);                   // no MyPtr<int>
  NotNull<int*> nni4b(WrapNotNull(&i4));        // WrapNotNull(int*)
  NotNull<int*> nni4c(WrapNotNull(my4));        // WrapNotNull(MyPtr<int>)
  NotNull<int*> nni4d(nni4);                    // NotNull<int*>
  NotNull<int*> nni4e(nnmy4);                   // NotNull<MyPtr<int>>
  CHECK(*nni4b == 4);
  CHECK(*nni4c == 4);
  CHECK(*nni4d == 4);
  CHECK(*nni4e == 4);

  // NotNull<MyPtr<int>> construction combinations
  //NotNull<MyPtr<int>> nnmy4a;                 // no default
  //NotNull<MyPtr<int>> nnmy4a(nullptr);        // no nullptr
  //NotNull<MyPtr<int>> nnmy4a(0);              // no zero
  //NotNull<MyPtr<int>> nnmy4a(&i4);            // no int*
  //NotNull<MyPtr<int>> nnmy4a(my4);            // no MyPtr<int>
  NotNull<MyPtr<int>> nnmy4b(WrapNotNull(&i4)); // WrapNotNull(int*)
  NotNull<MyPtr<int>> nnmy4c(WrapNotNull(my4)); // WrapNotNull(MyPtr<int>)
  NotNull<MyPtr<int>> nnmy4d(nni4);             // NotNull<int*>
  NotNull<MyPtr<int>> nnmy4e(nnmy4);            // NotNull<MyPtr<int>>
  CHECK(*nnmy4b == 4);
  CHECK(*nnmy4c == 4);
  CHECK(*nnmy4d == 4);
  CHECK(*nnmy4e == 4);

  // NotNull<int*> assignment combinations
  //nni4b = nullptr;                            // no nullptr
  //nni4b = 0;                                  // no zero
  //nni4a = &i4;                                // no int*
  //nni4a = my4;                                // no MyPtr<int>
  nni4b = WrapNotNull(&i4);                     // WrapNotNull(int*)
  nni4c = WrapNotNull(my4);                     // WrapNotNull(MyPtr<int>)
  nni4d = nni4;                                 // NotNull<int*>
  nni4e = nnmy4;                                // NotNull<MyPtr<int>>
  CHECK(*nni4b == 4);
  CHECK(*nni4c == 4);
  CHECK(*nni4d == 4);
  CHECK(*nni4e == 4);

  // NotNull<MyPtr<int>> assignment combinations
  //nnmy4a = nullptr;                           // no nullptr
  //nnmy4a = 0;                                 // no zero
  //nnmy4a = &i4;                               // no int*
  //nnmy4a = my4;                               // no MyPtr<int>
  nnmy4b = WrapNotNull(&i4);                    // WrapNotNull(int*)
  nnmy4c = WrapNotNull(my4);                    // WrapNotNull(MyPtr<int>)
  nnmy4d = nni4;                                // NotNull<int*>
  nnmy4e = nnmy4;                               // NotNull<MyPtr<int>>
  CHECK(*nnmy4b == 4);
  CHECK(*nnmy4c == 4);
  CHECK(*nnmy4d == 4);
  CHECK(*nnmy4e == 4);

  NotNull<MyPtr<int>> nnmy5 = WrapNotNull(&i5);
  CHECK(*nnmy5 == 5);
  CHECK(nnmy5 == &i5);       // NotNull<MyPtr<int>> == int*
  CHECK(nnmy5 == my5);       // NotNull<MyPtr<int>> == MyPtr<int>
  CHECK(nnmy5 == nni5);      // NotNull<MyPtr<int>> == NotNull<int*>
  CHECK(nnmy5 == nnmy5);     // NotNull<MyPtr<int>> == NotNull<MyPtr<int>>
  CHECK(&i5   == nnmy5);     // int*                == NotNull<MyPtr<int>>
  CHECK(my5   == nnmy5);     // MyPtr<int>          == NotNull<MyPtr<int>>
  CHECK(nni5  == nnmy5);     // NotNull<int*>       == NotNull<MyPtr<int>>
  CHECK(nnmy5 == nnmy5);     // NotNull<MyPtr<int>> == NotNull<MyPtr<int>>
  //CHECK(nni5 == nullptr);  // no comparisons with nullptr
  //CHECK(nullptr == nni5);  // no comparisons with nullptr
  //CHECK(nni5 == 0);        // no comparisons with zero
  //CHECK(0 == nni5);        // no comparisons with zero

  CHECK(*nnmy5 == 5);
  CHECK(nnmy5 != &i4);       // NotNull<MyPtr<int>> != int*
  CHECK(nnmy5 != my4);       // NotNull<MyPtr<int>> != MyPtr<int>
  CHECK(nnmy5 != nni4);      // NotNull<MyPtr<int>> != NotNull<int*>
  CHECK(nnmy5 != nnmy4);     // NotNull<MyPtr<int>> != NotNull<MyPtr<int>>
  CHECK(&i4   != nnmy5);     // int*                != NotNull<MyPtr<int>>
  CHECK(my4   != nnmy5);     // MyPtr<int>          != NotNull<MyPtr<int>>
  CHECK(nni4  != nnmy5);     // NotNull<int*>       != NotNull<MyPtr<int>>
  CHECK(nnmy4 != nnmy5);     // NotNull<MyPtr<int>> != NotNull<MyPtr<int>>
  //CHECK(nni4 != nullptr);  // no comparisons with nullptr
  //CHECK(nullptr != nni4);  // no comparisons with nullptr
  //CHECK(nni4 != 0);        // no comparisons with zero
  //CHECK(0 != nni4);        // no comparisons with zero

  // int* parameter
  f_i(&i4);             // identity int*                        --> int*
  f_i(my4);             // implicit MyPtr<int>                  --> int*
  f_i(my4.get());       // explicit MyPtr<int>                  --> int*
  f_i(nni4);            // implicit NotNull<int*>               --> int*
  f_i(nni4.get());      // explicit NotNull<int*>               --> int*
  //f_i(nnmy4);         // no implicit NotNull<MyPtr<int>>      --> int*
  f_i(nnmy4.get());     // explicit NotNull<MyPtr<int>>         --> int*
  f_i(nnmy4.get().get());// doubly-explicit NotNull<MyPtr<int>> --> int*

  // MyPtr<int> parameter
  f_my(&i4);            // implicit int*                         --> MyPtr<int>
  f_my(my4);            // identity MyPtr<int>                   --> MyPtr<int>
  f_my(my4.get());      // explicit MyPtr<int>                   --> MyPtr<int>
  //f_my(nni4);         // no implicit NotNull<int*>             --> MyPtr<int>
  f_my(nni4.get());     // explicit NotNull<int*>                --> MyPtr<int>
  f_my(nnmy4);          // implicit NotNull<MyPtr<int>>          --> MyPtr<int>
  f_my(nnmy4.get());    // explicit NotNull<MyPtr<int>>          --> MyPtr<int>
  f_my(nnmy4.get().get());// doubly-explicit NotNull<MyPtr<int>> --> MyPtr<int>

  // NotNull<int*> parameter
  f_nni(nni4);          // identity NotNull<int*>       --> NotNull<int*>
  f_nni(nnmy4);         // implicit NotNull<MyPtr<int>> --> NotNull<int*>

  // NotNull<MyPtr<int>> parameter
  f_nnmy(nni4);         // implicit NotNull<int*>       --> NotNull<MyPtr<int>>
  f_nnmy(nnmy4);        // identity NotNull<MyPtr<int>> --> NotNull<MyPtr<int>>

  //CHECK(nni4);        // disallow boolean conversion / unary expression usage
  //CHECK(nnmy4);       // ditto

  // '->' dereferencing.
  Blah blah;
  MyPtr<Blah> myblah = &blah;
  NotNull<Blah*> nnblah = WrapNotNull(&blah);
  NotNull<MyPtr<Blah>> nnmyblah = WrapNotNull(myblah);
  (&blah)->blah();          // int*
  myblah->blah();           // MyPtr<int>
  nnblah->blah();           // NotNull<int*>
  nnmyblah->blah();         // NotNull<MyPtr<int>>

  (&blah)->mX = 1;
  CHECK((&blah)->mX == 1);
  myblah->mX = 2;
  CHECK(myblah->mX == 2);
  nnblah->mX = 3;
  CHECK(nnblah->mX == 3);
  nnmyblah->mX = 4;
  CHECK(nnmyblah->mX == 4);

  // '*' dereferencing (lvalues and rvalues)
  *(&i4) = 7;               // int*
  CHECK(*(&i4) == 7);
  *my4 = 6;                 // MyPtr<int>
  CHECK(*my4 == 6);
  *nni4 = 5;                // NotNull<int*>
  CHECK(*nni4 == 5);
  *nnmy4 = 4;               // NotNull<MyPtr<int>>
  CHECK(*nnmy4 == 4);

  // Non-null arrays.
  static const int N = 20;
  int a[N];
  NotNull<int*> nna = WrapNotNull(a);
  for (int i = 0; i < N; i++) {
    nna[i] = i;
  }
  for (int i = 0; i < N; i++) {
    nna[i] *= 2;
  }
  for (int i = 0; i < N; i++) {
    CHECK(nna[i] == i * 2);
  }
}
예제 #23
0
nsresult
nsNSSCertificateDB::handleCACertDownload(NotNull<nsIArray*> x509Certs,
                                         nsIInterfaceRequestor *ctx,
                                         const nsNSSShutDownPreventionLock &proofOfLock)
{
  // First thing we have to do is figure out which certificate we're 
  // gonna present to the user.  The CA may have sent down a list of 
  // certs which may or may not be a chained list of certs.  Until
  // the day we can design some solid UI for the general case, we'll
  // code to the > 90% case.  That case is where a CA sends down a
  // list that is a hierarchy whose root is either the first or 
  // the last cert.  What we're gonna do is compare the first 
  // 2 entries, if the second was signed by the first, we assume
  // the root cert is the first cert and display it.  Otherwise,
  // we compare the last 2 entries, if the second to last cert was
  // signed by the last cert, then we assume the last cert is the
  // root and display it.

  uint32_t numCerts;

  x509Certs->GetLength(&numCerts);
  NS_ASSERTION(numCerts > 0, "Didn't get any certs to import.");
  if (numCerts == 0)
    return NS_OK; // Nothing to import, so nothing to do.

  nsCOMPtr<nsIX509Cert> certToShow;
  uint32_t selCertIndex;
  if (numCerts == 1) {
    // There's only one cert, so let's show it.
    selCertIndex = 0;
    certToShow = do_QueryElementAt(x509Certs, selCertIndex);
  } else {
    nsCOMPtr<nsIX509Cert> cert0;    // first cert
    nsCOMPtr<nsIX509Cert> cert1;    // second cert
    nsCOMPtr<nsIX509Cert> certn_2;  // second to last cert
    nsCOMPtr<nsIX509Cert> certn_1;  // last cert

    cert0 = do_QueryElementAt(x509Certs, 0);
    cert1 = do_QueryElementAt(x509Certs, 1);
    certn_2 = do_QueryElementAt(x509Certs, numCerts-2);
    certn_1 = do_QueryElementAt(x509Certs, numCerts-1);

    nsXPIDLString cert0SubjectName;
    nsXPIDLString cert1IssuerName;
    nsXPIDLString certn_2IssuerName;
    nsXPIDLString certn_1SubjectName;

    cert0->GetSubjectName(cert0SubjectName);
    cert1->GetIssuerName(cert1IssuerName);
    certn_2->GetIssuerName(certn_2IssuerName);
    certn_1->GetSubjectName(certn_1SubjectName);

    if (cert1IssuerName.Equals(cert0SubjectName)) {
      // In this case, the first cert in the list signed the second,
      // so the first cert is the root.  Let's display it. 
      selCertIndex = 0;
      certToShow = cert0;
    } else 
    if (certn_2IssuerName.Equals(certn_1SubjectName)) { 
      // In this case the last cert has signed the second to last cert.
      // The last cert is the root, so let's display it.
      selCertIndex = numCerts-1;
      certToShow = certn_1;
    } else {
      // It's not a chain, so let's just show the first one in the 
      // downloaded list.
      selCertIndex = 0;
      certToShow = cert0;
    }
  }

  if (!certToShow)
    return NS_ERROR_FAILURE;

  nsCOMPtr<nsICertificateDialogs> dialogs;
  nsresult rv = ::getNSSDialogs(getter_AddRefs(dialogs), 
                                NS_GET_IID(nsICertificateDialogs),
                                NS_CERTIFICATEDIALOGS_CONTRACTID);
  if (NS_FAILED(rv)) {
    return rv;
  }

  UniqueCERTCertificate tmpCert(certToShow->GetCert());
  if (!tmpCert) {
    return NS_ERROR_FAILURE;
  }

  if (!CERT_IsCACert(tmpCert.get(), nullptr)) {
    DisplayCertificateAlert(ctx, "NotACACert", certToShow, proofOfLock);
    return NS_ERROR_FAILURE;
  }

  if (tmpCert->isperm) {
    DisplayCertificateAlert(ctx, "CaCertExists", certToShow, proofOfLock);
    return NS_ERROR_FAILURE;
  }

  uint32_t trustBits;
  bool allows;
  rv = dialogs->ConfirmDownloadCACert(ctx, certToShow, &trustBits, &allows);
  if (NS_FAILED(rv))
    return rv;

  if (!allows)
    return NS_ERROR_NOT_AVAILABLE;

  MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("trust is %d\n", trustBits));
  UniquePORTString nickname(CERT_MakeCANickname(tmpCert.get()));

  MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("Created nick \"%s\"\n", nickname.get()));

  nsNSSCertTrust trust;
  trust.SetValidCA();
  trust.AddCATrust(!!(trustBits & nsIX509CertDB::TRUSTED_SSL),
                   !!(trustBits & nsIX509CertDB::TRUSTED_EMAIL),
                   !!(trustBits & nsIX509CertDB::TRUSTED_OBJSIGN));

  if (CERT_AddTempCertToPerm(tmpCert.get(), nickname.get(),
                             trust.GetTrust()) != SECSuccess) {
    return NS_ERROR_FAILURE;
  }

  // Import additional delivered certificates that can be verified.

  // build a CertList for filtering
  UniqueCERTCertList certList(CERT_NewCertList());
  if (!certList) {
    return NS_ERROR_FAILURE;
  }

  // get all remaining certs into temp store

  for (uint32_t i=0; i<numCerts; i++) {
    if (i == selCertIndex) {
      // we already processed that one
      continue;
    }

    nsCOMPtr<nsIX509Cert> remainingCert = do_QueryElementAt(x509Certs, i);
    if (!remainingCert) {
      continue;
    }

    UniqueCERTCertificate tmpCert2(remainingCert->GetCert());
    if (!tmpCert2) {
      continue;  // Let's try to import the rest of 'em
    }

    if (CERT_AddCertToListTail(certList.get(), tmpCert2.get()) != SECSuccess) {
      continue;
    }

    Unused << tmpCert2.release();
  }

  return ImportValidCACertsInList(certList, ctx, proofOfLock);
}
예제 #24
0
void
VectorImage::CreateSurfaceAndShow(const SVGDrawingParameters& aParams)
{
  mSVGDocumentWrapper->UpdateViewportBounds(aParams.viewportSize);
  mSVGDocumentWrapper->FlushImageTransformInvalidation();

  RefPtr<gfxDrawingCallback> cb =
    new SVGDrawingCallback(mSVGDocumentWrapper,
                           IntRect(IntPoint(0, 0), aParams.viewportSize),
                           aParams.size,
                           aParams.flags);

  RefPtr<gfxDrawable> svgDrawable =
    new gfxCallbackDrawable(cb, aParams.size);

  bool bypassCache = bool(aParams.flags & FLAG_BYPASS_SURFACE_CACHE) ||
                     // Refuse to cache animated images:
                     // XXX(seth): We may remove this restriction in bug 922893.
                     mHaveAnimations ||
                     // The image is too big to fit in the cache:
                     !SurfaceCache::CanHold(aParams.size);
  if (bypassCache) {
    return Show(svgDrawable, aParams);
  }

  // We're about to rerasterize, which may mean that some of the previous
  // surfaces we've rasterized aren't useful anymore. We can allow them to
  // expire from the cache by unlocking them here, and then sending out an
  // invalidation. If this image is locked, any surfaces that are still useful
  // will become locked again when Draw touches them, and the remainder will
  // eventually expire.
  SurfaceCache::UnlockEntries(ImageKey(this));

  // Try to create an imgFrame, initializing the surface it contains by drawing
  // our gfxDrawable into it. (We use FILTER_NEAREST since we never scale here.)
  NotNull<RefPtr<imgFrame>> frame = WrapNotNull(new imgFrame);
  nsresult rv =
    frame->InitWithDrawable(svgDrawable, aParams.size,
                            SurfaceFormat::B8G8R8A8,
                            SamplingFilter::POINT, aParams.flags);

  // If we couldn't create the frame, it was probably because it would end
  // up way too big. Generally it also wouldn't fit in the cache, but the prefs
  // could be set such that the cache isn't the limiting factor.
  if (NS_FAILED(rv)) {
    return Show(svgDrawable, aParams);
  }

  // Take a strong reference to the frame's surface and make sure it hasn't
  // already been purged by the operating system.
  RefPtr<SourceSurface> surface = frame->GetSourceSurface();
  if (!surface) {
    return Show(svgDrawable, aParams);
  }

  // Attempt to cache the frame.
  SurfaceKey surfaceKey = VectorSurfaceKey(aParams.size, aParams.svgContext);
  NotNull<RefPtr<ISurfaceProvider>> provider =
    WrapNotNull(new SimpleSurfaceProvider(ImageKey(this), surfaceKey, frame));
  SurfaceCache::Insert(provider);

  // Draw.
  RefPtr<gfxDrawable> drawable =
    new gfxSurfaceDrawable(surface, aParams.size);
  Show(drawable, aParams);

  // Send out an invalidation so that surfaces that are still in use get
  // re-locked. See the discussion of the UnlockSurfaces call above.
  mProgressTracker->SyncNotifyProgress(FLAG_FRAME_COMPLETE,
                                       GetMaxSizedIntRect());
}