thestig | c5eeb9f36 | 2015-04-22 18:42:32 | [diff] [blame] | 1 | // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "chrome/browser/image_decoder.h" |
| 6 | |
avi | 6846aef | 2015-12-26 01:09:38 | [diff] [blame] | 7 | #include "base/macros.h" |
| 8 | #include "build/build_config.h" |
thestig | 3d8ebe3a | 2015-05-08 03:25:32 | [diff] [blame] | 9 | #include "chrome/grit/generated_resources.h" |
thestig | c5eeb9f36 | 2015-04-22 18:42:32 | [diff] [blame] | 10 | #include "chrome/test/base/in_process_browser_test.h" |
amistry | d59fe6b | 2015-04-30 23:50:30 | [diff] [blame] | 11 | #include "content/public/browser/browser_child_process_observer.h" |
thestig | c5eeb9f36 | 2015-04-22 18:42:32 | [diff] [blame] | 12 | #include "content/public/browser/browser_thread.h" |
amistry | d59fe6b | 2015-04-30 23:50:30 | [diff] [blame] | 13 | #include "content/public/browser/child_process_data.h" |
thestig | c5eeb9f36 | 2015-04-22 18:42:32 | [diff] [blame] | 14 | #include "content/public/test/test_utils.h" |
thestig | 3d8ebe3a | 2015-05-08 03:25:32 | [diff] [blame] | 15 | #include "ui/base/l10n/l10n_util.h" |
thestig | c5eeb9f36 | 2015-04-22 18:42:32 | [diff] [blame] | 16 | |
| 17 | using content::BrowserThread; |
| 18 | |
| 19 | namespace { |
| 20 | |
nya | 601d970 | 2016-07-26 18:39:21 | [diff] [blame] | 21 | std::vector<uint8_t> GetValidPngData() { |
thestig | 3d8ebe3a | 2015-05-08 03:25:32 | [diff] [blame] | 22 | // 1x1 PNG. Does not get much smaller than this. |
| 23 | static const char kPngData[] = |
| 24 | "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52" |
| 25 | "\x00\x00\x00\x01\x00\x00\x00\x01\x08\x02\x00\x00\x00\x90\x77\x53" |
| 26 | "\xde\x00\x00\x00\x0c\x49\x44\x41\x54\x08\xd7\x63\xf8\xff\xff\x3f" |
| 27 | "\x00\x05\xfe\x02\xfe\xdc\xcc\x59\xe7\x00\x00\x00\x00\x49\x45\x4e" |
| 28 | "\x44\xae\x42\x60\x82"; |
| 29 | // Need to specify the buffer size because it contains NULs. |
nya | 601d970 | 2016-07-26 18:39:21 | [diff] [blame] | 30 | return std::vector<uint8_t>(kPngData, kPngData + sizeof(kPngData) - 1); |
thestig | 3d8ebe3a | 2015-05-08 03:25:32 | [diff] [blame] | 31 | } |
| 32 | |
satorux | f7e76f0 | 2016-03-09 06:30:45 | [diff] [blame] | 33 | #if defined(OS_CHROMEOS) |
| 34 | |
nya | 601d970 | 2016-07-26 18:39:21 | [diff] [blame] | 35 | std::vector<uint8_t> GetValidJpgData() { |
satorux | f7e76f0 | 2016-03-09 06:30:45 | [diff] [blame] | 36 | // 1x1 JPG created from the 1x1 PNG above. |
| 37 | static const char kJpgData[] = |
| 38 | "\xFF\xD8\xFF\xE0\x00\x10\x4A\x46\x49\x46\x00\x01\x01\x01\x00\x48" |
| 39 | "\x00\x48\x00\x00\xFF\xDB\x00\x43\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF" |
| 40 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" |
| 41 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" |
| 42 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" |
| 43 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xDB\x00\x43\x01\xFF\xFF" |
| 44 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" |
| 45 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" |
| 46 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" |
| 47 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xC0" |
| 48 | "\x00\x11\x08\x00\x01\x00\x01\x03\x01\x22\x00\x02\x11\x01\x03\x11" |
| 49 | "\x01\xFF\xC4\x00\x15\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00" |
| 50 | "\x00\x00\x00\x00\x00\x00\x00\x03\xFF\xC4\x00\x14\x10\x01\x00\x00" |
| 51 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xC4" |
| 52 | "\x00\x14\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" |
| 53 | "\x00\x00\x00\x00\xFF\xC4\x00\x14\x11\x01\x00\x00\x00\x00\x00\x00" |
| 54 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xDA\x00\x0C\x03\x01" |
| 55 | "\x00\x02\x11\x03\x11\x00\x3F\x00\xA0\x00\xFF\xD9"; |
| 56 | // Need to specify the buffer size because it contains NULs. |
nya | 601d970 | 2016-07-26 18:39:21 | [diff] [blame] | 57 | return std::vector<uint8_t>(kJpgData, kJpgData + sizeof(kJpgData) - 1); |
satorux | f7e76f0 | 2016-03-09 06:30:45 | [diff] [blame] | 58 | } |
| 59 | |
| 60 | #endif // defined(OS_CHROMEOS) |
| 61 | |
thestig | c5eeb9f36 | 2015-04-22 18:42:32 | [diff] [blame] | 62 | class TestImageRequest : public ImageDecoder::ImageRequest { |
| 63 | public: |
| 64 | explicit TestImageRequest(const base::Closure& quit_closure) |
thestig | 3d8ebe3a | 2015-05-08 03:25:32 | [diff] [blame] | 65 | : decode_succeeded_(false), |
| 66 | quit_closure_(quit_closure), |
thestig | c5eeb9f36 | 2015-04-22 18:42:32 | [diff] [blame] | 67 | quit_called_(false) { |
| 68 | } |
| 69 | |
| 70 | ~TestImageRequest() override { |
| 71 | if (!quit_called_) { |
| 72 | quit_closure_.Run(); |
| 73 | } |
| 74 | } |
| 75 | |
thestig | 3d8ebe3a | 2015-05-08 03:25:32 | [diff] [blame] | 76 | bool decode_succeeded() const { return decode_succeeded_; } |
| 77 | |
thestig | c5eeb9f36 | 2015-04-22 18:42:32 | [diff] [blame] | 78 | private: |
| 79 | void OnImageDecoded(const SkBitmap& decoded_image) override { |
thestig | 3d8ebe3a | 2015-05-08 03:25:32 | [diff] [blame] | 80 | decode_succeeded_ = true; |
thestig | c5eeb9f36 | 2015-04-22 18:42:32 | [diff] [blame] | 81 | Quit(); |
| 82 | } |
| 83 | |
| 84 | void OnDecodeImageFailed() override { |
| 85 | Quit(); |
| 86 | } |
| 87 | |
| 88 | void Quit() { |
| 89 | EXPECT_FALSE(quit_called_); |
| 90 | quit_called_ = true; |
| 91 | quit_closure_.Run(); |
| 92 | } |
| 93 | |
thestig | 3d8ebe3a | 2015-05-08 03:25:32 | [diff] [blame] | 94 | bool decode_succeeded_; |
| 95 | |
thestig | c5eeb9f36 | 2015-04-22 18:42:32 | [diff] [blame] | 96 | base::Closure quit_closure_; |
| 97 | bool quit_called_; |
| 98 | |
| 99 | DISALLOW_COPY_AND_ASSIGN(TestImageRequest); |
| 100 | }; |
| 101 | |
| 102 | } // namespace |
| 103 | |
| 104 | class ImageDecoderBrowserTest : public InProcessBrowserTest { |
| 105 | }; |
| 106 | |
| 107 | IN_PROC_BROWSER_TEST_F(ImageDecoderBrowserTest, Basic) { |
| 108 | scoped_refptr<content::MessageLoopRunner> runner = |
| 109 | new content::MessageLoopRunner; |
| 110 | TestImageRequest test_request(runner->QuitClosure()); |
nya | 601d970 | 2016-07-26 18:39:21 | [diff] [blame] | 111 | ImageDecoder::Start(&test_request, std::vector<uint8_t>()); |
thestig | c5eeb9f36 | 2015-04-22 18:42:32 | [diff] [blame] | 112 | runner->Run(); |
thestig | 3d8ebe3a | 2015-05-08 03:25:32 | [diff] [blame] | 113 | EXPECT_FALSE(test_request.decode_succeeded()); |
| 114 | } |
| 115 | |
satorux | f7e76f0 | 2016-03-09 06:30:45 | [diff] [blame] | 116 | #if defined(OS_CHROMEOS) |
| 117 | |
nya | 601d970 | 2016-07-26 18:39:21 | [diff] [blame] | 118 | IN_PROC_BROWSER_TEST_F(ImageDecoderBrowserTest, BasicDecodeWithOptionsString) { |
| 119 | scoped_refptr<content::MessageLoopRunner> runner = |
| 120 | new content::MessageLoopRunner; |
| 121 | TestImageRequest test_request(runner->QuitClosure()); |
| 122 | const std::vector<uint8_t> data = GetValidPngData(); |
| 123 | ImageDecoder::StartWithOptions(&test_request, |
| 124 | std::string(data.begin(), data.end()), |
| 125 | ImageDecoder::ROBUST_PNG_CODEC, |
tschumann | 30ee108 | 2017-03-02 19:37:53 | [diff] [blame] | 126 | /*shrink_to_fit=*/false); |
nya | 601d970 | 2016-07-26 18:39:21 | [diff] [blame] | 127 | runner->Run(); |
| 128 | EXPECT_TRUE(test_request.decode_succeeded()); |
| 129 | } |
| 130 | |
satorux | f7e76f0 | 2016-03-09 06:30:45 | [diff] [blame] | 131 | IN_PROC_BROWSER_TEST_F(ImageDecoderBrowserTest, RobustJpegCodecWithJpegData) { |
| 132 | scoped_refptr<content::MessageLoopRunner> runner = |
| 133 | new content::MessageLoopRunner; |
| 134 | TestImageRequest test_request(runner->QuitClosure()); |
tschumann | 30ee108 | 2017-03-02 19:37:53 | [diff] [blame] | 135 | ImageDecoder::StartWithOptions( |
| 136 | &test_request, GetValidJpgData(), ImageDecoder::ROBUST_JPEG_CODEC, |
| 137 | /*shrink_to_fit=*/false, /*desired_image_frame_size=*/gfx::Size()); |
satorux | f7e76f0 | 2016-03-09 06:30:45 | [diff] [blame] | 138 | runner->Run(); |
| 139 | EXPECT_TRUE(test_request.decode_succeeded()); |
| 140 | } |
| 141 | |
| 142 | IN_PROC_BROWSER_TEST_F(ImageDecoderBrowserTest, RobustJpegCodecWithPngData) { |
| 143 | scoped_refptr<content::MessageLoopRunner> runner = |
| 144 | new content::MessageLoopRunner; |
| 145 | TestImageRequest test_request(runner->QuitClosure()); |
tschumann | 30ee108 | 2017-03-02 19:37:53 | [diff] [blame] | 146 | ImageDecoder::StartWithOptions( |
| 147 | &test_request, GetValidPngData(), ImageDecoder::ROBUST_JPEG_CODEC, |
| 148 | /*shrink_to_fit=*/false, /*desired_image_frame_size=*/gfx::Size()); |
satorux | f7e76f0 | 2016-03-09 06:30:45 | [diff] [blame] | 149 | runner->Run(); |
| 150 | // Should fail with PNG data because only JPEG data is allowed. |
| 151 | EXPECT_FALSE(test_request.decode_succeeded()); |
| 152 | } |
| 153 | |
| 154 | IN_PROC_BROWSER_TEST_F(ImageDecoderBrowserTest, RobustPngCodecWithPngData) { |
| 155 | scoped_refptr<content::MessageLoopRunner> runner = |
| 156 | new content::MessageLoopRunner; |
| 157 | TestImageRequest test_request(runner->QuitClosure()); |
tschumann | 30ee108 | 2017-03-02 19:37:53 | [diff] [blame] | 158 | ImageDecoder::StartWithOptions( |
| 159 | &test_request, GetValidPngData(), ImageDecoder::ROBUST_PNG_CODEC, |
| 160 | /*shrink_to_fit=*/false, /*desired_image_frame_size=*/gfx::Size()); |
satorux | f7e76f0 | 2016-03-09 06:30:45 | [diff] [blame] | 161 | runner->Run(); |
| 162 | EXPECT_TRUE(test_request.decode_succeeded()); |
| 163 | } |
| 164 | |
| 165 | IN_PROC_BROWSER_TEST_F(ImageDecoderBrowserTest, RobustPngCodecWithJpegData) { |
| 166 | scoped_refptr<content::MessageLoopRunner> runner = |
| 167 | new content::MessageLoopRunner; |
| 168 | TestImageRequest test_request(runner->QuitClosure()); |
tschumann | 30ee108 | 2017-03-02 19:37:53 | [diff] [blame] | 169 | ImageDecoder::StartWithOptions( |
| 170 | &test_request, GetValidJpgData(), ImageDecoder::ROBUST_PNG_CODEC, |
| 171 | /*shrink_to_fit=*/false, /*desired_image_frame_size=*/gfx::Size()); |
satorux | f7e76f0 | 2016-03-09 06:30:45 | [diff] [blame] | 172 | runner->Run(); |
| 173 | // Should fail with JPEG data because only PNG data is allowed. |
| 174 | EXPECT_FALSE(test_request.decode_succeeded()); |
| 175 | } |
| 176 | |
| 177 | #endif // defined(OS_CHROMEOS) |
| 178 | |
thestig | 3d8ebe3a | 2015-05-08 03:25:32 | [diff] [blame] | 179 | IN_PROC_BROWSER_TEST_F(ImageDecoderBrowserTest, BasicDecode) { |
| 180 | scoped_refptr<content::MessageLoopRunner> runner = |
| 181 | new content::MessageLoopRunner; |
| 182 | TestImageRequest test_request(runner->QuitClosure()); |
nya | 601d970 | 2016-07-26 18:39:21 | [diff] [blame] | 183 | ImageDecoder::Start(&test_request, GetValidPngData()); |
| 184 | runner->Run(); |
| 185 | EXPECT_TRUE(test_request.decode_succeeded()); |
| 186 | } |
| 187 | |
| 188 | IN_PROC_BROWSER_TEST_F(ImageDecoderBrowserTest, BasicDecodeString) { |
| 189 | scoped_refptr<content::MessageLoopRunner> runner = |
| 190 | new content::MessageLoopRunner; |
| 191 | TestImageRequest test_request(runner->QuitClosure()); |
| 192 | const std::vector<uint8_t> data = GetValidPngData(); |
| 193 | ImageDecoder::Start(&test_request, std::string(data.begin(), data.end())); |
thestig | 3d8ebe3a | 2015-05-08 03:25:32 | [diff] [blame] | 194 | runner->Run(); |
| 195 | EXPECT_TRUE(test_request.decode_succeeded()); |
thestig | c5eeb9f36 | 2015-04-22 18:42:32 | [diff] [blame] | 196 | } |
| 197 | |
| 198 | IN_PROC_BROWSER_TEST_F(ImageDecoderBrowserTest, StartAndDestroy) { |
| 199 | scoped_refptr<content::MessageLoopRunner> runner = |
| 200 | new content::MessageLoopRunner; |
dcheng | 4af4858 | 2016-04-19 00:29:35 | [diff] [blame] | 201 | std::unique_ptr<TestImageRequest> test_request( |
thestig | c5eeb9f36 | 2015-04-22 18:42:32 | [diff] [blame] | 202 | new TestImageRequest(runner->QuitClosure())); |
nya | 601d970 | 2016-07-26 18:39:21 | [diff] [blame] | 203 | ImageDecoder::Start(test_request.get(), std::vector<uint8_t>()); |
thestig | c5eeb9f36 | 2015-04-22 18:42:32 | [diff] [blame] | 204 | test_request.reset(); |
| 205 | runner->Run(); |
| 206 | } |