1 /*
2  * Copyright (C) 2012 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include "third_party/blink/renderer/platform/graphics/deferred_image_decoder.h"
27 
28 #include <memory>
29 #include "base/location.h"
30 #include "base/memory/scoped_refptr.h"
31 #include "build/build_config.h"
32 #include "testing/gtest/include/gtest/gtest.h"
33 #include "third_party/blink/public/platform/platform.h"
34 #include "third_party/blink/renderer/platform/graphics/image_decoding_store.h"
35 #include "third_party/blink/renderer/platform/graphics/image_frame_generator.h"
36 #include "third_party/blink/renderer/platform/graphics/paint/paint_canvas.h"
37 #include "third_party/blink/renderer/platform/graphics/paint/paint_image.h"
38 #include "third_party/blink/renderer/platform/graphics/paint/paint_record.h"
39 #include "third_party/blink/renderer/platform/graphics/paint/paint_recorder.h"
40 #include "third_party/blink/renderer/platform/graphics/test/mock_image_decoder.h"
41 #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
42 #include "third_party/blink/renderer/platform/scheduler/public/thread.h"
43 #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
44 #include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
45 #include "third_party/skia/include/core/SkImage.h"
46 #include "third_party/skia/include/core/SkPixmap.h"
47 #include "third_party/skia/include/core/SkSurface.h"
48 
49 namespace blink {
50 
51 namespace {
52 
53 // Raw data for a PNG file with 1x1 white pixels.
54 const unsigned char kWhitePNG[] = {
55     0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
56     0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
57     0x08, 0x02, 0x00, 0x00, 0x00, 0x90, 0x77, 0x53, 0xde, 0x00, 0x00, 0x00,
58     0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00,
59     0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00,
60     0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x0c, 0x49,
61     0x44, 0x41, 0x54, 0x08, 0xd7, 0x63, 0xf8, 0xff, 0xff, 0x3f, 0x00, 0x05,
62     0xfe, 0x02, 0xfe, 0xdc, 0xcc, 0x59, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x49,
63     0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82,
64 };
65 
66 // Raw data for a GIF file with 1x1 white pixels. Modified from animatedGIF.
67 const unsigned char kWhiteGIF[] = {
68     0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x01, 0x00, 0x01, 0x00, 0xf0, 0x00,
69     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x21, 0xff, 0x0b, 0x4e, 0x45,
70     0x54, 0x53, 0x43, 0x41, 0x50, 0x45, 0x32, 0x2e, 0x30, 0x03, 0x01, 0x00,
71     0x00, 0x00, 0x21, 0xff, 0x0b, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x4d, 0x61,
72     0x67, 0x69, 0x63, 0x6b, 0x0d, 0x67, 0x61, 0x6d, 0x6d, 0x61, 0x3d, 0x30,
73     0x2e, 0x34, 0x35, 0x34, 0x35, 0x35, 0x00, 0x21, 0xff, 0x0b, 0x49, 0x6d,
74     0x61, 0x67, 0x65, 0x4d, 0x61, 0x67, 0x69, 0x63, 0x6b, 0x0d, 0x67, 0x61,
75     0x6d, 0x6d, 0x61, 0x3d, 0x30, 0x2e, 0x34, 0x35, 0x34, 0x35, 0x35, 0x00,
76     0x21, 0xf9, 0x04, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2c, 0x00, 0x00, 0x00,
77     0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x02, 0x02, 0x4c, 0x01, 0x00, 0x3b};
78 
79 }  // namespace
80 
81 class DeferredImageDecoderTest : public testing::Test,
82                                  public MockImageDecoderClient {
83  public:
SetUp()84   void SetUp() override {
85     paint_image_id_ = PaintImage::GetNextId();
86     ImageDecodingStore::Instance().SetCacheLimitInBytes(1024 * 1024);
87     data_ = SharedBuffer::Create(kWhitePNG, sizeof(kWhitePNG));
88     frame_count_ = 1;
89     auto decoder = std::make_unique<MockImageDecoder>(this);
90     actual_decoder_ = decoder.get();
91     actual_decoder_->SetSize(1, 1);
92     lazy_decoder_ = DeferredImageDecoder::CreateForTesting(std::move(decoder));
93     bitmap_.allocPixels(SkImageInfo::MakeN32Premul(100, 100));
94     canvas_ = std::make_unique<cc::SkiaPaintCanvas>(bitmap_);
95     decode_request_count_ = 0;
96     repetition_count_ = kAnimationNone;
97     status_ = ImageFrame::kFrameComplete;
98     frame_duration_ = base::TimeDelta();
99     decoded_size_ = actual_decoder_->Size();
100   }
101 
TearDown()102   void TearDown() override { ImageDecodingStore::Instance().Clear(); }
103 
DecoderBeingDestroyed()104   void DecoderBeingDestroyed() override { actual_decoder_ = nullptr; }
105 
DecodeRequested()106   void DecodeRequested() override { ++decode_request_count_; }
107 
FrameCount()108   size_t FrameCount() override { return frame_count_; }
109 
RepetitionCount() const110   int RepetitionCount() const override { return repetition_count_; }
111 
GetStatus(size_t index)112   ImageFrame::Status GetStatus(size_t index) override { return status_; }
113 
FrameDuration() const114   base::TimeDelta FrameDuration() const override { return frame_duration_; }
115 
DecodedSize() const116   IntSize DecodedSize() const override { return decoded_size_; }
117 
CreatePaintImage(PaintImage::CompletionState state=PaintImage::CompletionState::DONE)118   PaintImage CreatePaintImage(
119       PaintImage::CompletionState state = PaintImage::CompletionState::DONE) {
120     return CreatePaintImage(lazy_decoder_.get(), state);
121   }
122 
CreatePaintImage(DeferredImageDecoder * decoder,PaintImage::CompletionState state=PaintImage::CompletionState::DONE)123   PaintImage CreatePaintImage(
124       DeferredImageDecoder* decoder,
125       PaintImage::CompletionState state = PaintImage::CompletionState::DONE) {
126     PaintImage::AnimationType type = FrameCount() > 1
127                                          ? PaintImage::AnimationType::ANIMATED
128                                          : PaintImage::AnimationType::STATIC;
129 
130     return PaintImageBuilder::WithDefault()
131         .set_id(paint_image_id_)
132         .set_animation_type(type)
133         .set_completion_state(state)
134         .set_paint_image_generator(decoder->CreateGenerator())
135         .TakePaintImage();
136   }
137 
138  protected:
UseMockImageDecoderFactory()139   void UseMockImageDecoderFactory() {
140     lazy_decoder_->FrameGenerator()->SetImageDecoderFactory(
141         MockImageDecoderFactory::Create(this, decoded_size_));
142   }
143 
144   // Don't own this but saves the pointer to query states.
145   PaintImage::Id paint_image_id_;
146   MockImageDecoder* actual_decoder_;
147   std::unique_ptr<DeferredImageDecoder> lazy_decoder_;
148   SkBitmap bitmap_;
149   std::unique_ptr<cc::PaintCanvas> canvas_;
150   int decode_request_count_;
151   scoped_refptr<SharedBuffer> data_;
152   size_t frame_count_;
153   int repetition_count_;
154   ImageFrame::Status status_;
155   base::TimeDelta frame_duration_;
156   IntSize decoded_size_;
157 };
158 
TEST_F(DeferredImageDecoderTest,drawIntoPaintRecord)159 TEST_F(DeferredImageDecoderTest, drawIntoPaintRecord) {
160   lazy_decoder_->SetData(data_, true /* all_data_received */);
161   PaintImage image = CreatePaintImage();
162   ASSERT_TRUE(image);
163   EXPECT_EQ(1, image.width());
164   EXPECT_EQ(1, image.height());
165 
166   PaintRecorder recorder;
167   cc::PaintCanvas* temp_canvas = recorder.beginRecording(100, 100);
168   temp_canvas->drawImage(image, 0, 0);
169   sk_sp<PaintRecord> record = recorder.finishRecordingAsPicture();
170   EXPECT_EQ(0, decode_request_count_);
171 
172   canvas_->drawPicture(record);
173   EXPECT_EQ(0, decode_request_count_);
174   EXPECT_EQ(SkColorSetARGB(255, 255, 255, 255), bitmap_.getColor(0, 0));
175 }
176 
TEST_F(DeferredImageDecoderTest,drawIntoPaintRecordProgressive)177 TEST_F(DeferredImageDecoderTest, drawIntoPaintRecordProgressive) {
178   scoped_refptr<SharedBuffer> partial_data =
179       SharedBuffer::Create(data_->Data(), data_->size() - 10);
180 
181   // Received only half the file.
182   lazy_decoder_->SetData(partial_data, false /* all_data_received */);
183   PaintRecorder recorder;
184   cc::PaintCanvas* temp_canvas = recorder.beginRecording(100, 100);
185   PaintImage image =
186       CreatePaintImage(PaintImage::CompletionState::PARTIALLY_DONE);
187   ASSERT_TRUE(image);
188   temp_canvas->drawImage(image, 0, 0);
189   canvas_->drawPicture(recorder.finishRecordingAsPicture());
190 
191   // Fully received the file and draw the PaintRecord again.
192   lazy_decoder_->SetData(data_, true /* all_data_received */);
193   image = CreatePaintImage();
194   ASSERT_TRUE(image);
195   temp_canvas = recorder.beginRecording(100, 100);
196   temp_canvas->drawImage(image, 0, 0);
197   canvas_->drawPicture(recorder.finishRecordingAsPicture());
198   EXPECT_EQ(SkColorSetARGB(255, 255, 255, 255), bitmap_.getColor(0, 0));
199 }
200 
TEST_F(DeferredImageDecoderTest,allDataReceivedPriorToDecodeNonIncrementally)201 TEST_F(DeferredImageDecoderTest, allDataReceivedPriorToDecodeNonIncrementally) {
202   // The image is received completely at once.
203   lazy_decoder_->SetData(data_, true /* all_data_received */);
204   PaintImage image = CreatePaintImage();
205   ASSERT_TRUE(image);
206   ASSERT_TRUE(image.GetImageHeaderMetadata());
207   EXPECT_TRUE(
208       image.GetImageHeaderMetadata()->all_data_received_prior_to_decode);
209 }
210 
TEST_F(DeferredImageDecoderTest,allDataReceivedPriorToDecodeIncrementally)211 TEST_F(DeferredImageDecoderTest, allDataReceivedPriorToDecodeIncrementally) {
212   // The image is received in two parts, but a PaintImageGenerator is created
213   // only after all the data is received.
214   scoped_refptr<SharedBuffer> partial_data =
215       SharedBuffer::Create(data_->Data(), data_->size() - 10);
216   lazy_decoder_->SetData(partial_data, false /* all_data_received */);
217   lazy_decoder_->SetData(data_, true /* all_data_received */);
218   PaintImage image = CreatePaintImage();
219   ASSERT_TRUE(image);
220   ASSERT_TRUE(image.GetImageHeaderMetadata());
221   EXPECT_TRUE(
222       image.GetImageHeaderMetadata()->all_data_received_prior_to_decode);
223 }
224 
TEST_F(DeferredImageDecoderTest,notAllDataReceivedPriorToDecode)225 TEST_F(DeferredImageDecoderTest, notAllDataReceivedPriorToDecode) {
226   // The image is received in two parts, and a PaintImageGenerator is created
227   // for each one. In real usage, it's likely that the software image decoder
228   // will start working with partial data.
229   scoped_refptr<SharedBuffer> partial_data =
230       SharedBuffer::Create(data_->Data(), data_->size() - 10);
231   lazy_decoder_->SetData(partial_data, false /* all_data_received */);
232   PaintImage image =
233       CreatePaintImage(PaintImage::CompletionState::PARTIALLY_DONE);
234   ASSERT_TRUE(image);
235   ASSERT_TRUE(image.GetImageHeaderMetadata());
236   EXPECT_FALSE(
237       image.GetImageHeaderMetadata()->all_data_received_prior_to_decode);
238 
239   lazy_decoder_->SetData(data_, true /* all_data_received */);
240   image = CreatePaintImage();
241   ASSERT_TRUE(image);
242   ASSERT_TRUE(image.GetImageHeaderMetadata());
243   EXPECT_FALSE(
244       image.GetImageHeaderMetadata()->all_data_received_prior_to_decode);
245 }
246 
RasterizeMain(cc::PaintCanvas * canvas,sk_sp<PaintRecord> record)247 static void RasterizeMain(cc::PaintCanvas* canvas, sk_sp<PaintRecord> record) {
248   canvas->drawPicture(record);
249 }
250 
251 // Flaky on Mac. crbug.com/792540.
252 #if defined(OS_MACOSX)
253 #define MAYBE_decodeOnOtherThread DISABLED_decodeOnOtherThread
254 #else
255 #define MAYBE_decodeOnOtherThread decodeOnOtherThread
256 #endif
TEST_F(DeferredImageDecoderTest,MAYBE_decodeOnOtherThread)257 TEST_F(DeferredImageDecoderTest, MAYBE_decodeOnOtherThread) {
258   lazy_decoder_->SetData(data_, true /* all_data_received */);
259   PaintImage image = CreatePaintImage();
260   ASSERT_TRUE(image);
261   EXPECT_EQ(1, image.width());
262   EXPECT_EQ(1, image.height());
263 
264   PaintRecorder recorder;
265   cc::PaintCanvas* temp_canvas = recorder.beginRecording(100, 100);
266   temp_canvas->drawImage(image, 0, 0);
267   sk_sp<PaintRecord> record = recorder.finishRecordingAsPicture();
268   EXPECT_EQ(0, decode_request_count_);
269 
270   // Create a thread to rasterize PaintRecord.
271   std::unique_ptr<Thread> thread = Platform::Current()->CreateThread(
272       ThreadCreationParams(ThreadType::kTestThread)
273           .SetThreadNameForTest("RasterThread"));
274   PostCrossThreadTask(
275       *thread->GetTaskRunner(), FROM_HERE,
276       CrossThreadBindOnce(&RasterizeMain, CrossThreadUnretained(canvas_.get()),
277                           record));
278   thread.reset();
279   EXPECT_EQ(0, decode_request_count_);
280   EXPECT_EQ(SkColorSetARGB(255, 255, 255, 255), bitmap_.getColor(0, 0));
281 }
282 
TEST_F(DeferredImageDecoderTest,singleFrameImageLoading)283 TEST_F(DeferredImageDecoderTest, singleFrameImageLoading) {
284   status_ = ImageFrame::kFramePartial;
285   lazy_decoder_->SetData(data_, false /* all_data_received */);
286   EXPECT_FALSE(lazy_decoder_->FrameIsReceivedAtIndex(0));
287   PaintImage image = CreatePaintImage();
288   ASSERT_TRUE(image);
289   EXPECT_FALSE(lazy_decoder_->FrameIsReceivedAtIndex(0));
290   EXPECT_TRUE(actual_decoder_);
291 
292   status_ = ImageFrame::kFrameComplete;
293   data_->Append(" ", 1u);
294   lazy_decoder_->SetData(data_, true /* all_data_received */);
295   EXPECT_FALSE(actual_decoder_);
296   EXPECT_TRUE(lazy_decoder_->FrameIsReceivedAtIndex(0));
297 
298   image = CreatePaintImage();
299   ASSERT_TRUE(image);
300   EXPECT_FALSE(decode_request_count_);
301 }
302 
TEST_F(DeferredImageDecoderTest,multiFrameImageLoading)303 TEST_F(DeferredImageDecoderTest, multiFrameImageLoading) {
304   repetition_count_ = 10;
305   frame_count_ = 1;
306   frame_duration_ = base::TimeDelta::FromMilliseconds(10);
307   status_ = ImageFrame::kFramePartial;
308   lazy_decoder_->SetData(data_, false /* all_data_received */);
309 
310   PaintImage image = CreatePaintImage();
311   ASSERT_TRUE(image);
312   EXPECT_FALSE(lazy_decoder_->FrameIsReceivedAtIndex(0));
313   // Anything <= 10ms is clamped to 100ms. See the implementaiton for details.
314   EXPECT_EQ(base::TimeDelta::FromMilliseconds(100),
315             lazy_decoder_->FrameDurationAtIndex(0));
316 
317   frame_count_ = 2;
318   frame_duration_ = base::TimeDelta::FromMilliseconds(20);
319   status_ = ImageFrame::kFrameComplete;
320   data_->Append(" ", 1u);
321   lazy_decoder_->SetData(data_, false /* all_data_received */);
322 
323   image = CreatePaintImage();
324   ASSERT_TRUE(image);
325   EXPECT_TRUE(lazy_decoder_->FrameIsReceivedAtIndex(0));
326   EXPECT_TRUE(lazy_decoder_->FrameIsReceivedAtIndex(1));
327   EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
328             lazy_decoder_->FrameDurationAtIndex(1));
329   EXPECT_TRUE(actual_decoder_);
330 
331   frame_count_ = 3;
332   frame_duration_ = base::TimeDelta::FromMilliseconds(30);
333   status_ = ImageFrame::kFrameComplete;
334   lazy_decoder_->SetData(data_, true /* all_data_received */);
335   EXPECT_FALSE(actual_decoder_);
336   EXPECT_TRUE(lazy_decoder_->FrameIsReceivedAtIndex(0));
337   EXPECT_TRUE(lazy_decoder_->FrameIsReceivedAtIndex(1));
338   EXPECT_TRUE(lazy_decoder_->FrameIsReceivedAtIndex(2));
339   EXPECT_EQ(base::TimeDelta::FromMilliseconds(100),
340             lazy_decoder_->FrameDurationAtIndex(0));
341   EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
342             lazy_decoder_->FrameDurationAtIndex(1));
343   EXPECT_EQ(base::TimeDelta::FromMilliseconds(30),
344             lazy_decoder_->FrameDurationAtIndex(2));
345   EXPECT_EQ(10, lazy_decoder_->RepetitionCount());
346 }
347 
TEST_F(DeferredImageDecoderTest,decodedSize)348 TEST_F(DeferredImageDecoderTest, decodedSize) {
349   decoded_size_ = IntSize(22, 33);
350   lazy_decoder_->SetData(data_, true /* all_data_received */);
351   PaintImage image = CreatePaintImage();
352   ASSERT_TRUE(image);
353   EXPECT_EQ(decoded_size_.Width(), image.width());
354   EXPECT_EQ(decoded_size_.Height(), image.height());
355 
356   UseMockImageDecoderFactory();
357 
358   // The following code should not fail any assert.
359   PaintRecorder recorder;
360   cc::PaintCanvas* temp_canvas = recorder.beginRecording(100, 100);
361   temp_canvas->drawImage(image, 0, 0);
362   sk_sp<PaintRecord> record = recorder.finishRecordingAsPicture();
363   EXPECT_EQ(0, decode_request_count_);
364   canvas_->drawPicture(record);
365   EXPECT_EQ(1, decode_request_count_);
366 }
367 
TEST_F(DeferredImageDecoderTest,smallerFrameCount)368 TEST_F(DeferredImageDecoderTest, smallerFrameCount) {
369   frame_count_ = 1;
370   lazy_decoder_->SetData(data_, false /* all_data_received */);
371   EXPECT_EQ(frame_count_, lazy_decoder_->FrameCount());
372   frame_count_ = 2;
373   lazy_decoder_->SetData(data_, false /* all_data_received */);
374   EXPECT_EQ(frame_count_, lazy_decoder_->FrameCount());
375   frame_count_ = 0;
376   lazy_decoder_->SetData(data_, true /* all_data_received */);
377   EXPECT_EQ(frame_count_, lazy_decoder_->FrameCount());
378 }
379 
TEST_F(DeferredImageDecoderTest,frameOpacity)380 TEST_F(DeferredImageDecoderTest, frameOpacity) {
381   for (bool test_gif : {false, true}) {
382     if (test_gif)
383       data_ = SharedBuffer::Create(kWhiteGIF, sizeof(kWhiteGIF));
384 
385     std::unique_ptr<DeferredImageDecoder> decoder =
386         DeferredImageDecoder::Create(data_, true,
387                                      ImageDecoder::kAlphaPremultiplied,
388                                      ColorBehavior::TransformToSRGB());
389 
390     SkImageInfo pix_info = SkImageInfo::MakeN32Premul(1, 1);
391 
392     size_t row_bytes = pix_info.minRowBytes();
393     size_t size = pix_info.computeByteSize(row_bytes);
394 
395     Vector<char> storage(size);
396     SkPixmap pixmap(pix_info, storage.data(), row_bytes);
397 
398     // Before decoding, the frame is not known to be opaque.
399     sk_sp<SkImage> frame = CreatePaintImage(decoder.get()).GetSkImage();
400     ASSERT_TRUE(frame);
401     EXPECT_FALSE(frame->isOpaque());
402     EXPECT_TRUE(decoder->FrameHasAlphaAtIndex(0));
403 
404     // Force a lazy decode by reading pixels.
405     EXPECT_TRUE(frame->readPixels(pixmap, 0, 0));
406 
407     // After decoding, the frame is known to be opaque.
408     EXPECT_FALSE(decoder->FrameHasAlphaAtIndex(0));
409     frame = CreatePaintImage(decoder.get()).GetSkImage();
410     ASSERT_TRUE(frame);
411     EXPECT_TRUE(frame->isOpaque());
412 
413     // Re-generating the opaque-marked frame should not fail.
414     EXPECT_TRUE(frame->readPixels(pixmap, 0, 0));
415   }
416 }
417 
TEST_F(DeferredImageDecoderTest,data)418 TEST_F(DeferredImageDecoderTest, data) {
419   scoped_refptr<SharedBuffer> original_buffer =
420       SharedBuffer::Create(data_->Data(), data_->size());
421   EXPECT_EQ(original_buffer->size(), data_->size());
422   lazy_decoder_->SetData(original_buffer, false /* all_data_received */);
423   scoped_refptr<SharedBuffer> new_buffer = lazy_decoder_->Data();
424   EXPECT_EQ(original_buffer->size(), new_buffer->size());
425   const Vector<char> original_data = original_buffer->CopyAs<Vector<char>>();
426   const Vector<char> new_data = new_buffer->CopyAs<Vector<char>>();
427   EXPECT_EQ(0, std::memcmp(original_data.data(), new_data.data(),
428                            new_buffer->size()));
429 }
430 
431 class MultiFrameDeferredImageDecoderTest : public DeferredImageDecoderTest {
432  public:
GetStatus(size_t index)433   ImageFrame::Status GetStatus(size_t index) override {
434     return index > last_complete_frame_ ? ImageFrame::Status::kFramePartial
435                                         : ImageFrame::Status::kFrameComplete;
436   }
437 
438   size_t last_complete_frame_ = 0u;
439 };
440 
TEST_F(MultiFrameDeferredImageDecoderTest,PaintImage)441 TEST_F(MultiFrameDeferredImageDecoderTest, PaintImage) {
442   frame_count_ = 2;
443   frame_duration_ = base::TimeDelta::FromMilliseconds(20);
444   last_complete_frame_ = 0u;
445   lazy_decoder_->SetData(data_, false /* all_data_received */);
446 
447   // Only the first frame is complete.
448   PaintImage image = CreatePaintImage();
449   ASSERT_TRUE(image);
450   EXPECT_EQ(image.GetFrameMetadata().size(), 2u);
451   EXPECT_TRUE(image.GetFrameMetadata()[0].complete);
452   EXPECT_FALSE(image.GetFrameMetadata()[1].complete);
453   EXPECT_EQ(image.GetFrameMetadata()[0].duration, frame_duration_);
454   EXPECT_EQ(image.GetFrameMetadata()[1].duration, frame_duration_);
455 
456   auto frame0_key = image.GetKeyForFrame(0);
457   auto frame1_key = image.GetKeyForFrame(1);
458   EXPECT_NE(frame0_key, frame1_key);
459 
460   // Send some more data but the frame status remains the same.
461   last_complete_frame_ = 0u;
462   lazy_decoder_->SetData(data_, false /* all_data_received */);
463   PaintImage updated_image = CreatePaintImage();
464   ASSERT_TRUE(updated_image);
465   EXPECT_EQ(updated_image.GetFrameMetadata().size(), 2u);
466   EXPECT_TRUE(updated_image.GetFrameMetadata()[0].complete);
467   EXPECT_FALSE(updated_image.GetFrameMetadata()[1].complete);
468 
469   // Since the first frame was complete, the key remains constant. While the
470   // second frame generates a new key after it is updated.
471   auto updated_frame0_key = updated_image.GetKeyForFrame(0);
472   auto updated_frame1_key = updated_image.GetKeyForFrame(1);
473   EXPECT_NE(updated_frame0_key, updated_frame1_key);
474   EXPECT_EQ(updated_frame0_key, frame0_key);
475   EXPECT_NE(updated_frame1_key, frame1_key);
476 
477   // Mark all frames complete.
478   last_complete_frame_ = 1u;
479   lazy_decoder_->SetData(data_, true /* all_data_received */);
480   PaintImage complete_image = CreatePaintImage();
481   ASSERT_TRUE(complete_image);
482   EXPECT_EQ(complete_image.GetFrameMetadata().size(), 2u);
483   EXPECT_TRUE(complete_image.GetFrameMetadata()[0].complete);
484   EXPECT_TRUE(complete_image.GetFrameMetadata()[1].complete);
485 
486   auto complete_frame0_key = complete_image.GetKeyForFrame(0);
487   auto complete_frame1_key = complete_image.GetKeyForFrame(1);
488   EXPECT_NE(complete_frame0_key, complete_frame1_key);
489   EXPECT_EQ(updated_frame0_key, complete_frame0_key);
490   EXPECT_NE(updated_frame1_key, complete_frame1_key);
491 }
492 
TEST_F(MultiFrameDeferredImageDecoderTest,FrameDurationOverride)493 TEST_F(MultiFrameDeferredImageDecoderTest, FrameDurationOverride) {
494   frame_count_ = 2;
495   frame_duration_ = base::TimeDelta::FromMilliseconds(5);
496   last_complete_frame_ = 1u;
497   lazy_decoder_->SetData(data_, true /* all_data_received */);
498 
499   // If the frame duration is below a threshold, we override it to a constant
500   // value of 100 ms.
501   PaintImage image = CreatePaintImage();
502   EXPECT_EQ(image.GetFrameMetadata()[0].duration,
503             base::TimeDelta::FromMilliseconds(100));
504   EXPECT_EQ(image.GetFrameMetadata()[1].duration,
505             base::TimeDelta::FromMilliseconds(100));
506 }
507 
508 }  // namespace blink
509