Backed out changeset e39309b6fe7f (bug 1315554)
authorSebastian Hengst <archaeopteryx@coole-files.de>
Sat, 22 Jul 2017 11:04:02 +0200
changeset 419100 aee78154a945c91d826a856d7ad1dfd3553d9eeb
parent 419099 e2e062406f6320a608921b0eaa0ffc95dbd9b108
child 419101 2df50fe08bc681d471b8f351b8de8337d41adb4e
push id7566
push usermtabara@mozilla.com
push dateWed, 02 Aug 2017 08:25:16 +0000
treeherdermozilla-beta@86913f512c3c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1315554
milestone56.0a1
backs oute39309b6fe7f29b2ecfb16bf3c17c710b74d11f4
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out changeset e39309b6fe7f (bug 1315554)
image/DecoderFactory.cpp
image/DecoderFactory.h
image/decoders/nsICODecoder.cpp
image/decoders/nsICODecoder.h
--- a/image/DecoderFactory.cpp
+++ b/image/DecoderFactory.cpp
@@ -229,17 +229,17 @@ DecoderFactory::CreateMetadataDecoder(De
   }
 
   RefPtr<IDecodingTask> task = new MetadataDecodingTask(WrapNotNull(decoder));
   return task.forget();
 }
 
 /* static */ already_AddRefed<Decoder>
 DecoderFactory::CreateDecoderForICOResource(DecoderType aType,
-                                            SourceBufferIterator&& aIterator,
+                                            NotNull<SourceBuffer*> aSourceBuffer,
                                             NotNull<nsICODecoder*> aICODecoder,
                                             const Maybe<IntSize>& aExpectedSize,
                                             const Maybe<uint32_t>& aDataOffset
                                               /* = Nothing() */)
 {
   // Create the decoder.
   RefPtr<Decoder> decoder;
   switch (aType) {
@@ -258,17 +258,17 @@ DecoderFactory::CreateDecoderForICOResou
       return nullptr;
   }
 
   MOZ_ASSERT(decoder);
 
   // Initialize the decoder, copying settings from @aICODecoder.
   MOZ_ASSERT(!aICODecoder->IsMetadataDecode());
   decoder->SetMetadataDecode(aICODecoder->IsMetadataDecode());
-  decoder->SetIterator(Forward<SourceBufferIterator>(aIterator));
+  decoder->SetIterator(aSourceBuffer->Iterator());
   decoder->SetOutputSize(aICODecoder->OutputSize());
   if (aExpectedSize) {
     decoder->SetExpectedSize(*aExpectedSize);
   }
   decoder->SetDecoderFlags(aICODecoder->GetDecoderFlags());
   decoder->SetSurfaceFlags(aICODecoder->GetSurfaceFlags());
   decoder->SetFinalizeFrames(false);
 
--- a/image/DecoderFactory.h
+++ b/image/DecoderFactory.h
@@ -18,17 +18,16 @@
 namespace mozilla {
 namespace image {
 
 class Decoder;
 class IDecodingTask;
 class nsICODecoder;
 class RasterImage;
 class SourceBuffer;
-class SourceBufferIterator;
 
 /**
  * The type of decoder; this is usually determined from a MIME type using
  * DecoderFactory::GetDecoderType().
  */
 enum class DecoderType
 {
   PNG,
@@ -115,31 +114,31 @@ public:
                         NotNull<SourceBuffer*> aSourceBuffer);
 
   /**
    * Creates and initializes a decoder for an ICO resource, which may be either
    * a BMP or PNG image.
    *
    * @param aType Which type of decoder to create. This must be either BMP or
    *              PNG.
-   * @param aIterator The SourceBufferIterator which the decoder will read its
-   *                  data from.
+   * @param aSourceBuffer The SourceBuffer which the decoder will read its data
+   *                      from.
    * @param aICODecoder The ICO decoder which is controlling this resource
    *                    decoder. @aICODecoder's settings will be copied to the
    *                    resource decoder, so the two decoders will have the
    *                    same decoder flags, surface flags, target size, and
    *                    other parameters.
    * @param aExpectedSize The expected size of the resource from the ICO header.
    * @param aDataOffset If @aType is BMP, specifies the offset at which data
    *                    begins in the BMP resource. Must be Some() if and only
    *                    if @aType is BMP.
    */
   static already_AddRefed<Decoder>
   CreateDecoderForICOResource(DecoderType aType,
-                              SourceBufferIterator&& aIterator,
+                              NotNull<SourceBuffer*> aSourceBuffer,
                               NotNull<nsICODecoder*> aICODecoder,
                               const Maybe<gfx::IntSize>& aExpectedSize,
                               const Maybe<uint32_t>& aDataOffset = Nothing());
 
   /**
    * Creates and initializes an anonymous decoder (one which isn't associated
    * with an Image object). Only the first frame of the image will be decoded.
    *
--- a/image/decoders/nsICODecoder.cpp
+++ b/image/decoders/nsICODecoder.cpp
@@ -86,18 +86,24 @@ nsICODecoder::FinishWithErrorInternal()
 
 nsresult
 nsICODecoder::GetFinalStateFromContainedDecoder()
 {
   if (!mContainedDecoder) {
     return NS_OK;
   }
 
+  MOZ_ASSERT(mContainedSourceBuffer,
+             "Should have a SourceBuffer if we have a decoder");
+
   // Let the contained decoder finish up if necessary.
-  FlushContainedDecoder();
+  if (!mContainedSourceBuffer->IsComplete()) {
+    mContainedSourceBuffer->Complete(NS_OK);
+    mContainedDecoder->Decode();
+  }
 
   // Make our state the same as the state of the contained decoder.
   mDecodeDone = mContainedDecoder->GetDecodeDone();
   mProgress |= mContainedDecoder->TakeProgress();
   mInvalidRect.UnionRect(mInvalidRect, mContainedDecoder->TakeInvalidRect());
   mCurrentFrame = mContainedDecoder->GetCurrentFrameRef();
 
   // Propagate errors.
@@ -244,35 +250,37 @@ nsICODecoder::ReadDirEntry(const char* a
   }
 
   return Transition::To(ICOState::DIR_ENTRY, ICODIRENTRYSIZE);
 }
 
 LexerTransition<ICOState>
 nsICODecoder::SniffResource(const char* aData)
 {
-  // Prepare a new iterator for the contained decoder to advance as it wills.
-  // Cloning at the point ensures it will begin at the resource offset.
-  mContainedIterator.emplace(mLexer.Clone(*mIterator, mDirEntry.mBytesInRes));
-
   // We use the first PNGSIGNATURESIZE bytes to determine whether this resource
   // is a PNG or a BMP.
   bool isPNG = !memcmp(aData, nsPNGDecoder::pngSignatureBytes,
                        PNGSIGNATURESIZE);
   if (isPNG) {
-    if (mDirEntry.mBytesInRes <= PNGSIGNATURESIZE) {
+    // Create a PNG decoder which will do the rest of the work for us.
+    mContainedSourceBuffer = new SourceBuffer();
+    mContainedSourceBuffer->ExpectLength(mDirEntry.mBytesInRes);
+    mContainedDecoder =
+      DecoderFactory::CreateDecoderForICOResource(DecoderType::PNG,
+                                                  WrapNotNull(mContainedSourceBuffer),
+                                                  WrapNotNull(this),
+                                                  Some(GetRealSize()));
+
+    if (!WriteToContainedDecoder(aData, PNGSIGNATURESIZE)) {
       return Transition::TerminateFailure();
     }
 
-    // Create a PNG decoder which will do the rest of the work for us.
-    mContainedDecoder =
-      DecoderFactory::CreateDecoderForICOResource(DecoderType::PNG,
-                                                  Move(*mContainedIterator),
-                                                  WrapNotNull(this),
-                                                  Some(GetRealSize()));
+    if (mDirEntry.mBytesInRes <= PNGSIGNATURESIZE) {
+      return Transition::TerminateFailure();
+    }
 
     // Read in the rest of the PNG unbuffered.
     size_t toRead = mDirEntry.mBytesInRes - PNGSIGNATURESIZE;
     return Transition::ToUnbuffered(ICOState::FINISHED_RESOURCE,
                                     ICOState::READ_RESOURCE,
                                     toRead);
   } else {
     // Make sure we have a sane size for the bitmap information header.
@@ -286,19 +294,19 @@ nsICODecoder::SniffResource(const char* 
 
     // Read in the rest of the bitmap information header.
     return Transition::To(ICOState::READ_BIH,
                           BITMAPINFOSIZE - PNGSIGNATURESIZE);
   }
 }
 
 LexerTransition<ICOState>
-nsICODecoder::ReadResource()
+nsICODecoder::ReadResource(const char* aData, uint32_t aLen)
 {
-  if (!FlushContainedDecoder()) {
+  if (!WriteToContainedDecoder(aData, aLen)) {
     return Transition::TerminateFailure();
   }
 
   return Transition::ContinueUnbuffered(ICOState::READ_RESOURCE);
 }
 
 LexerTransition<ICOState>
 nsICODecoder::ReadBIH(const char* aData)
@@ -321,28 +329,29 @@ nsICODecoder::ReadBIH(const char* aData)
     if (numColors == (uint16_t)-1) {
       return Transition::TerminateFailure();
     }
     dataOffset += 4 * numColors;
   }
 
   // Create a BMP decoder which will do most of the work for us; the exception
   // is the AND mask, which isn't present in standalone BMPs.
+  mContainedSourceBuffer = new SourceBuffer();
+  mContainedSourceBuffer->ExpectLength(mDirEntry.mBytesInRes);
   mContainedDecoder =
     DecoderFactory::CreateDecoderForICOResource(DecoderType::BMP,
-                                                Move(*mContainedIterator),
+                                                WrapNotNull(mContainedSourceBuffer),
                                                 WrapNotNull(this),
                                                 Some(GetRealSize()),
                                                 Some(dataOffset));
-
   RefPtr<nsBMPDecoder> bmpDecoder =
     static_cast<nsBMPDecoder*>(mContainedDecoder.get());
 
-  // Ensure the decoder has parsed at least the BMP's bitmap info header.
-  if (!FlushContainedDecoder()) {
+  // Write out the BMP's bitmap info header.
+  if (!WriteToContainedDecoder(mBIHraw, sizeof(mBIHraw))) {
     return Transition::TerminateFailure();
   }
 
   // Check to make sure we have valid color settings.
   uint16_t numColors = GetNumColors();
   if (numColors == uint16_t(-1)) {
     return Transition::TerminateFailure();
   }
@@ -358,24 +367,16 @@ nsICODecoder::ReadBIH(const char* aData)
   return Transition::ToUnbuffered(afterBMPState,
                                   ICOState::READ_RESOURCE,
                                   bmpDataLength);
 }
 
 LexerTransition<ICOState>
 nsICODecoder::PrepareForMask()
 {
-  // We have received all of the data required by the BMP decoder so flushing
-  // here guarantees the decode has finished.
-  if (!FlushContainedDecoder()) {
-    return Transition::TerminateFailure();
-  }
-
-  MOZ_ASSERT(mContainedDecoder->GetDecodeDone());
-
   RefPtr<nsBMPDecoder> bmpDecoder =
     static_cast<nsBMPDecoder*>(mContainedDecoder.get());
 
   uint16_t numColors = GetNumColors();
   MOZ_ASSERT(numColors != uint16_t(-1));
 
   // Determine the length of the AND mask.
   uint32_t bmpLengthWithHeader =
@@ -511,24 +512,16 @@ nsICODecoder::FinishMask()
   }
 
   return Transition::To(ICOState::FINISHED_RESOURCE, 0);
 }
 
 LexerTransition<ICOState>
 nsICODecoder::FinishResource()
 {
-  // We have received all of the data required by the PNG/BMP decoder so
-  // flushing here guarantees the decode has finished.
-  if (!FlushContainedDecoder()) {
-    return Transition::TerminateFailure();
-  }
-
-  MOZ_ASSERT(mContainedDecoder->GetDecodeDone());
-
   // Make sure the actual size of the resource matches the size in the directory
   // entry. If not, we consider the image corrupt.
   if (mContainedDecoder->HasSize() &&
       mContainedDecoder->Size() != GetRealSize()) {
     return Transition::TerminateFailure();
   }
 
   // Raymond Chen says that 32bpp only are valid PNG ICOs
@@ -561,17 +554,17 @@ nsICODecoder::DoDecode(SourceBufferItera
         return ReadDirEntry(aData);
       case ICOState::SKIP_TO_RESOURCE:
         return Transition::ContinueUnbuffered(ICOState::SKIP_TO_RESOURCE);
       case ICOState::FOUND_RESOURCE:
         return Transition::To(ICOState::SNIFF_RESOURCE, PNGSIGNATURESIZE);
       case ICOState::SNIFF_RESOURCE:
         return SniffResource(aData);
       case ICOState::READ_RESOURCE:
-        return ReadResource();
+        return ReadResource(aData, aLength);
       case ICOState::READ_BIH:
         return ReadBIH(aData);
       case ICOState::PREPARE_FOR_MASK:
         return PrepareForMask();
       case ICOState::READ_MASK_ROW:
         return ReadMaskRow(aData);
       case ICOState::FINISH_MASK:
         return FinishMask();
@@ -581,26 +574,31 @@ nsICODecoder::DoDecode(SourceBufferItera
         return FinishResource();
       default:
         MOZ_CRASH("Unknown ICOState");
     }
   });
 }
 
 bool
-nsICODecoder::FlushContainedDecoder()
+nsICODecoder::WriteToContainedDecoder(const char* aBuffer, uint32_t aCount)
 {
   MOZ_ASSERT(mContainedDecoder);
+  MOZ_ASSERT(mContainedSourceBuffer);
+
+  // Append the provided data to the SourceBuffer that the contained decoder is
+  // reading from.
+  mContainedSourceBuffer->Append(aBuffer, aCount);
 
   bool succeeded = true;
 
-  // If we run out of data, the ICO decoder will get resumed when there's more
-  // data available, as usual, so we don't need the contained decoder to get
-  // resumed too. To avoid that, we provide an IResumable which just does
-  // nothing. All the caller needs to do is flush when there is new data.
+  // Write to the contained decoder. If we run out of data, the ICO decoder will
+  // get resumed when there's more data available, as usual, so we don't need
+  // the contained decoder to get resumed too. To avoid that, we provide an
+  // IResumable which just does nothing.
   LexerResult result = mContainedDecoder->Decode();
   if (result == LexerResult(TerminalState::FAILURE)) {
     succeeded = false;
   }
 
   MOZ_ASSERT(result != LexerResult(Yield::OUTPUT_AVAILABLE),
              "Unexpected yield");
 
--- a/image/decoders/nsICODecoder.h
+++ b/image/decoders/nsICODecoder.h
@@ -74,39 +74,39 @@ public:
   nsresult FinishWithErrorInternal() override;
 
 private:
   friend class DecoderFactory;
 
   // Decoders should only be instantiated via DecoderFactory.
   explicit nsICODecoder(RasterImage* aImage);
 
-  // Flushes the contained decoder to read all available data and sets the
-  // appropriate errors. Returns true if there are no errors.
-  bool FlushContainedDecoder();
+  // Writes to the contained decoder and sets the appropriate errors
+  // Returns true if there are no errors.
+  bool WriteToContainedDecoder(const char* aBuffer, uint32_t aCount);
 
   // Gets decoder state from the contained decoder so it's visible externally.
   nsresult GetFinalStateFromContainedDecoder();
 
   // Obtains the number of colors from the BPP, mBPP must be filled in
   uint16_t GetNumColors();
 
   LexerTransition<ICOState> ReadHeader(const char* aData);
   LexerTransition<ICOState> ReadDirEntry(const char* aData);
   LexerTransition<ICOState> SniffResource(const char* aData);
-  LexerTransition<ICOState> ReadResource();
+  LexerTransition<ICOState> ReadResource(const char* aData, uint32_t aLen);
   LexerTransition<ICOState> ReadBIH(const char* aData);
   LexerTransition<ICOState> PrepareForMask();
   LexerTransition<ICOState> ReadMaskRow(const char* aData);
   LexerTransition<ICOState> FinishMask();
   LexerTransition<ICOState> FinishResource();
 
   StreamingLexer<ICOState, 32> mLexer; // The lexer.
   RefPtr<Decoder> mContainedDecoder; // Either a BMP or PNG decoder.
-  Maybe<SourceBufferIterator> mContainedIterator; // Iterator for the subdecoder.
+  RefPtr<SourceBuffer> mContainedSourceBuffer;  // SourceBuffer for mContainedDecoder.
   UniquePtr<uint8_t[]> mMaskBuffer;    // A temporary buffer for the alpha mask.
   char mBIHraw[bmp::InfoHeaderLength::WIN_ICO]; // The bitmap information header.
   IconDirEntry mDirEntry;              // The dir entry for the selected resource.
   gfx::IntSize mBiggestResourceSize;   // Used to select the intrinsic size.
   gfx::IntSize mBiggestResourceHotSpot; // Used to select the intrinsic size.
   uint16_t mBiggestResourceColorDepth; // Used to select the intrinsic size.
   int32_t mBestResourceDelta;          // Used to select the best resource.
   uint16_t mBestResourceColorDepth;    // Used to select the best resource.