e42c8150a32d94f7df093734680cb2ffd2f56263
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / web / tests / WebPageNewSerializerTest.cpp
1 /*
2  * Copyright (C) 2011 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 are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 #include "config.h"
31
32 #include "FrameTestHelpers.h"
33 #include "URLTestHelpers.h"
34 #include "WebFrame.h"
35 #include "WebPageSerializer.h"
36 #include "WebPageSerializerClient.h"
37 #include "WebScriptSource.h"
38 #include "WebSettings.h"
39 #include "WebView.h"
40 #include "core/dom/Document.h"
41 #include "public/platform/Platform.h"
42 #include "public/platform/WebString.h"
43 #include "public/platform/WebThread.h"
44 #include "public/platform/WebURL.h"
45 #include "public/platform/WebURLRequest.h"
46 #include "public/platform/WebURLResponse.h"
47 #include "public/platform/WebUnitTestSupport.h"
48 #include "public/web/WebDocument.h"
49 #include <gtest/gtest.h>
50
51 using namespace blink;
52 using WebCore::Document;
53 using blink::FrameTestHelpers::runPendingTasks;
54 using blink::URLTestHelpers::toKURL;
55 using blink::URLTestHelpers::registerMockedURLLoad;
56
57 namespace {
58
59 class LineReader {
60 public:
61     LineReader(const std::string& text) : m_text(text), m_index(0) { }
62     bool getNextLine(std::string* line)
63     {
64         line->clear();
65         if (m_index >= m_text.length())
66             return false;
67
68         size_t endOfLineIndex = m_text.find("\r\n", m_index);
69         if (endOfLineIndex == std::string::npos) {
70             *line = m_text.substr(m_index);
71             m_index = m_text.length();
72         } else {
73             *line = m_text.substr(m_index, endOfLineIndex - m_index);
74             m_index = endOfLineIndex + 2;
75         }
76         return true;
77     }
78
79 private:
80     std::string m_text;
81     size_t m_index;
82 };
83
84 class LengthCountingWebPageSerializerClient : public WebPageSerializerClient {
85 public:
86     LengthCountingWebPageSerializerClient(size_t* counter)
87         : m_counter(counter)
88     {
89     }
90
91     virtual void didSerializeDataForFrame(const WebURL& frameURL, const WebCString& data, PageSerializationStatus status) {
92         *m_counter += data.length();
93     }
94
95 private:
96     size_t* m_counter;
97 };
98
99 class WebPageNewSerializeTest : public testing::Test {
100 public:
101     WebPageNewSerializeTest()
102         : m_htmlMimeType(WebString::fromUTF8("text/html"))
103         , m_xhtmlMimeType(WebString::fromUTF8("application/xhtml+xml"))
104         , m_cssMimeType(WebString::fromUTF8("text/css"))
105         , m_pngMimeType(WebString::fromUTF8("image/png"))
106         , m_svgMimeType(WebString::fromUTF8("image/svg+xml"))
107     {
108     }
109
110 protected:
111     virtual void SetUp()
112     {
113         // We want the images to load and JavaScript to be on.
114         m_helper.initialize(true, 0, 0, &configureSettings);
115     }
116
117     virtual void TearDown()
118     {
119         Platform::current()->unitTestSupport()->unregisterAllMockedURLs();
120     }
121
122     WebURL setUpCSSTestPage()
123     {
124         WebURL topFrameURL = toKURL("http://www.test.com");
125         registerMockedURLLoad(topFrameURL, WebString::fromUTF8("css_test_page.html"), WebString::fromUTF8("pageserializer/"), htmlMimeType());
126         registerMockedURLLoad(toKURL("http://www.test.com/link_styles.css"), WebString::fromUTF8("link_styles.css"), WebString::fromUTF8("pageserializer/"), cssMimeType());
127         registerMockedURLLoad(toKURL("http://www.test.com/import_style_from_link.css"), WebString::fromUTF8("import_style_from_link.css"), WebString::fromUTF8("pageserializer/"), cssMimeType());
128         registerMockedURLLoad(toKURL("http://www.test.com/import_styles.css"), WebString::fromUTF8("import_styles.css"), WebString::fromUTF8("pageserializer/"), cssMimeType());
129         registerMockedURLLoad(toKURL("http://www.test.com/red_background.png"), WebString::fromUTF8("red_background.png"), WebString::fromUTF8("pageserializer/"), pngMimeType());
130         registerMockedURLLoad(toKURL("http://www.test.com/orange_background.png"), WebString::fromUTF8("orange_background.png"), WebString::fromUTF8("pageserializer/"), pngMimeType());
131         registerMockedURLLoad(toKURL("http://www.test.com/yellow_background.png"), WebString::fromUTF8("yellow_background.png"), WebString::fromUTF8("pageserializer/"), pngMimeType());
132         registerMockedURLLoad(toKURL("http://www.test.com/green_background.png"), WebString::fromUTF8("green_background.png"), WebString::fromUTF8("pageserializer/"), pngMimeType());
133         registerMockedURLLoad(toKURL("http://www.test.com/blue_background.png"), WebString::fromUTF8("blue_background.png"), WebString::fromUTF8("pageserializer/"), pngMimeType());
134         registerMockedURLLoad(toKURL("http://www.test.com/purple_background.png"), WebString::fromUTF8("purple_background.png"), WebString::fromUTF8("pageserializer/"), pngMimeType());
135         registerMockedURLLoad(toKURL("http://www.test.com/ul-dot.png"), WebString::fromUTF8("ul-dot.png"), WebString::fromUTF8("pageserializer/"), pngMimeType());
136         registerMockedURLLoad(toKURL("http://www.test.com/ol-dot.png"), WebString::fromUTF8("ol-dot.png"), WebString::fromUTF8("pageserializer/"), pngMimeType());
137         return topFrameURL;
138     }
139
140     void loadURLInTopFrame(const WebURL& url)
141     {
142         WebURLRequest urlRequest;
143         urlRequest.initialize();
144         urlRequest.setURL(url);
145         m_helper.webView()->mainFrame()->loadRequest(urlRequest);
146         // Make sure any pending request get served.
147         Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
148         // Some requests get delayed, run the timer.
149         runPendingTasks();
150         // Server the delayed resources.
151         Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
152     }
153
154     const WebString& htmlMimeType() const { return m_htmlMimeType; }
155     const WebString& xhtmlMimeType() const { return m_xhtmlMimeType; }
156     const WebString& cssMimeType() const { return m_cssMimeType; }
157     const WebString& pngMimeType() const { return m_pngMimeType; }
158     const WebString& svgMimeType() const { return m_svgMimeType; }
159
160     static bool resourceVectorContains(const WebVector<WebPageSerializer::Resource>& resources, const char* url, const char* mimeType)
161     {
162         WebURL webURL = WebURL(toKURL(url));
163         for (size_t i = 0; i < resources.size(); ++i) {
164             const WebPageSerializer::Resource& resource = resources[i];
165             if (resource.url == webURL && !resource.data.isEmpty() && !resource.mimeType.compare(WebCString(mimeType)))
166                 return true;
167         }
168         return false;
169     }
170
171     WebView* webView() const { return m_helper.webView(); }
172
173 private:
174     static void configureSettings(WebSettings* settings)
175     {
176         settings->setImagesEnabled(true);
177         settings->setLoadsImagesAutomatically(true);
178         settings->setJavaScriptEnabled(true);
179     }
180
181     FrameTestHelpers::WebViewHelper m_helper;
182     WebString m_htmlMimeType;
183     WebString m_xhtmlMimeType;
184     WebString m_cssMimeType;
185     WebString m_pngMimeType;
186     WebString m_svgMimeType;
187 };
188
189 // Tests that a page with resources and sub-frame is reported with all its resources.
190 TEST_F(WebPageNewSerializeTest, PageWithFrames)
191 {
192     // Register the mocked frames.
193     WebURL topFrameURL = toKURL("http://www.test.com");
194     registerMockedURLLoad(topFrameURL, WebString::fromUTF8("top_frame.html"), WebString::fromUTF8("pageserializer/"), htmlMimeType());
195     registerMockedURLLoad(toKURL("http://www.test.com/iframe.html"), WebString::fromUTF8("iframe.html"), WebString::fromUTF8("pageserializer/"), htmlMimeType());
196     registerMockedURLLoad(toKURL("http://www.test.com/iframe2.html"), WebString::fromUTF8("iframe2.html"), WebString::fromUTF8("pageserializer/"), htmlMimeType());
197     registerMockedURLLoad(toKURL("http://www.test.com/red_background.png"), WebString::fromUTF8("red_background.png"), WebString::fromUTF8("pageserializer/"), pngMimeType());
198     registerMockedURLLoad(toKURL("http://www.test.com/green_background.png"), WebString::fromUTF8("green_background.png"), WebString::fromUTF8("pageserializer/"), pngMimeType());
199     registerMockedURLLoad(toKURL("http://www.test.com/blue_background.png"), WebString::fromUTF8("blue_background.png"), WebString::fromUTF8("pageserializer/"), pngMimeType());
200
201     loadURLInTopFrame(topFrameURL);
202     // OBJECT/EMBED have some delay to start to load their content. The first
203     // serveAsynchronousMockedRequests call in loadURLInTopFrame() finishes
204     // before the start.
205     RefPtr<Document> document = static_cast<PassRefPtr<Document> >(webView()->mainFrame()->document());
206     document->updateLayoutIgnorePendingStylesheets(Document::RunPostLayoutTasksSynchronously);
207     Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
208
209     WebVector<WebPageSerializer::Resource> resources;
210     WebPageSerializer::serialize(webView(), &resources);
211     ASSERT_FALSE(resources.isEmpty());
212
213     // The first resource should be the main-frame.
214     const WebPageSerializer::Resource& resource = resources[0];
215     EXPECT_TRUE(resource.url == WebURL(toKURL("http://www.test.com")));
216     EXPECT_EQ(0, resource.mimeType.compare(WebCString("text/html")));
217     EXPECT_FALSE(resource.data.isEmpty());
218
219     EXPECT_EQ(6U, resources.size()); // There should be no duplicates.
220     EXPECT_TRUE(resourceVectorContains(resources, "http://www.test.com/red_background.png", "image/png"));
221     EXPECT_TRUE(resourceVectorContains(resources, "http://www.test.com/green_background.png", "image/png"));
222     EXPECT_TRUE(resourceVectorContains(resources, "http://www.test.com/blue_background.png", "image/png"));
223     EXPECT_TRUE(resourceVectorContains(resources, "http://www.test.com/iframe.html", "text/html"));
224     EXPECT_TRUE(resourceVectorContains(resources, "http://www.test.com/iframe2.html", "text/html"));
225 }
226
227 // Test that when serializing a page, all CSS resources are reported, including url()'s
228 // and imports and links. Note that we don't test the resources contents, we only make sure
229 // they are all reported with the right mime type and that they contain some data.
230 TEST_F(WebPageNewSerializeTest, FAILS_CSSResources)
231 {
232     // Register the mocked frame and load it.
233     WebURL topFrameURL = setUpCSSTestPage();
234     loadURLInTopFrame(topFrameURL);
235
236     WebVector<WebPageSerializer::Resource> resources;
237     WebPageSerializer::serialize(webView(), &resources);
238     ASSERT_FALSE(resources.isEmpty());
239
240     // The first resource should be the main-frame.
241     const WebPageSerializer::Resource& resource = resources[0];
242     EXPECT_TRUE(resource.url == WebURL(toKURL("http://www.test.com")));
243     EXPECT_EQ(0, resource.mimeType.compare(WebCString("text/html")));
244     EXPECT_FALSE(resource.data.isEmpty());
245
246     EXPECT_EQ(12U, resources.size()); // There should be no duplicates.
247     EXPECT_TRUE(resourceVectorContains(resources, "http://www.test.com/link_styles.css", "text/css"));
248     EXPECT_TRUE(resourceVectorContains(resources, "http://www.test.com/import_styles.css", "text/css"));
249     EXPECT_TRUE(resourceVectorContains(resources, "http://www.test.com/import_style_from_link.css", "text/css"));
250     EXPECT_TRUE(resourceVectorContains(resources, "http://www.test.com/red_background.png", "image/png"));
251     EXPECT_TRUE(resourceVectorContains(resources, "http://www.test.com/orange_background.png", "image/png"));
252     EXPECT_TRUE(resourceVectorContains(resources, "http://www.test.com/yellow_background.png", "image/png"));
253     EXPECT_TRUE(resourceVectorContains(resources, "http://www.test.com/green_background.png", "image/png"));
254     EXPECT_TRUE(resourceVectorContains(resources, "http://www.test.com/blue_background.png", "image/png"));
255     EXPECT_TRUE(resourceVectorContains(resources, "http://www.test.com/purple_background.png", "image/png"));
256     EXPECT_TRUE(resourceVectorContains(resources, "http://www.test.com/ul-dot.png", "image/png"));
257     EXPECT_TRUE(resourceVectorContains(resources, "http://www.test.com/ol-dot.png", "image/png"));
258 }
259
260 // Tests that when serializing a page with blank frames these are reported with their resources.
261 TEST_F(WebPageNewSerializeTest, BlankFrames)
262 {
263     // Register the mocked frame and load it.
264     WebURL topFrameURL = toKURL("http://www.test.com");
265     registerMockedURLLoad(topFrameURL, WebString::fromUTF8("blank_frames.html"), WebString::fromUTF8("pageserializer/"), htmlMimeType());
266     registerMockedURLLoad(toKURL("http://www.test.com/red_background.png"), WebString::fromUTF8("red_background.png"), WebString::fromUTF8("pageserializer/"), pngMimeType());
267     registerMockedURLLoad(toKURL("http://www.test.com/orange_background.png"), WebString::fromUTF8("orange_background.png"), WebString::fromUTF8("pageserializer/"), pngMimeType());
268     registerMockedURLLoad(toKURL("http://www.test.com/blue_background.png"), WebString::fromUTF8("blue_background.png"), WebString::fromUTF8("pageserializer/"), pngMimeType());
269
270     loadURLInTopFrame(topFrameURL);
271
272     WebVector<WebPageSerializer::Resource> resources;
273     WebPageSerializer::serialize(webView(), &resources);
274     ASSERT_FALSE(resources.isEmpty());
275
276     // The first resource should be the main-frame.
277     const WebPageSerializer::Resource& resource = resources[0];
278     EXPECT_TRUE(resource.url == WebURL(toKURL("http://www.test.com")));
279     EXPECT_EQ(0, resource.mimeType.compare(WebCString("text/html")));
280     EXPECT_FALSE(resource.data.isEmpty());
281
282     EXPECT_EQ(7U, resources.size()); // There should be no duplicates.
283     EXPECT_TRUE(resourceVectorContains(resources, "http://www.test.com/red_background.png", "image/png"));
284     EXPECT_TRUE(resourceVectorContains(resources, "http://www.test.com/orange_background.png", "image/png"));
285     EXPECT_TRUE(resourceVectorContains(resources, "http://www.test.com/blue_background.png", "image/png"));
286     // The blank frames should have got a magic URL.
287     EXPECT_TRUE(resourceVectorContains(resources, "wyciwyg://frame/0", "text/html"));
288     EXPECT_TRUE(resourceVectorContains(resources, "wyciwyg://frame/1", "text/html"));
289     EXPECT_TRUE(resourceVectorContains(resources, "wyciwyg://frame/2", "text/html"));
290 }
291
292 TEST_F(WebPageNewSerializeTest, SerializeXMLHasRightDeclaration)
293 {
294     WebURL topFrameURL = toKURL("http://www.test.com/simple.xhtml");
295     registerMockedURLLoad(topFrameURL, WebString::fromUTF8("simple.xhtml"), WebString::fromUTF8("pageserializer/"), xhtmlMimeType());
296
297     loadURLInTopFrame(topFrameURL);
298
299     WebVector<WebPageSerializer::Resource> resources;
300     WebPageSerializer::serialize(webView(), &resources);
301     ASSERT_FALSE(resources.isEmpty());
302
303     // We expect only one resource, the XML.
304     ASSERT_EQ(1U, resources.size());
305     std::string xml = std::string(resources[0].data.data());
306
307     // We should have one and only one instance of the XML declaration.
308     size_t pos = xml.find("<?xml version=");
309     ASSERT_TRUE(pos != std::string::npos);
310
311     pos = xml.find("<?xml version=", pos + 1);
312     ASSERT_TRUE(pos == std::string::npos);
313 }
314
315 TEST_F(WebPageNewSerializeTest, FAILS_TestMHTMLEncoding)
316 {
317     // Load a page with some CSS and some images.
318     WebURL topFrameURL = setUpCSSTestPage();
319     loadURLInTopFrame(topFrameURL);
320
321     WebCString mhtmlData = WebPageSerializer::serializeToMHTML(webView());
322     ASSERT_FALSE(mhtmlData.isEmpty());
323
324     // Read the MHTML data line per line and do some pseudo-parsing to make sure the right encoding is used for the different sections.
325     LineReader lineReader(std::string(mhtmlData.data()));
326     int sectionCheckedCount = 0;
327     const char* expectedEncoding = 0;
328     std::string line;
329     while (lineReader.getNextLine(&line)) {
330         if (!line.find("Content-Type:")) {
331             ASSERT_FALSE(expectedEncoding);
332             if (line.find("multipart/related;") != std::string::npos) {
333                 // Skip this one, it's part of the MHTML header.
334                 continue;
335             }
336             if (line.find("text/") != std::string::npos)
337                 expectedEncoding = "quoted-printable";
338             else if (line.find("image/") != std::string::npos)
339                 expectedEncoding = "base64";
340             else
341                 FAIL() << "Unexpected Content-Type: " << line;
342             continue;
343         }
344         if (!line.find("Content-Transfer-Encoding:")) {
345            ASSERT_TRUE(expectedEncoding);
346            EXPECT_TRUE(line.find(expectedEncoding) != std::string::npos);
347            expectedEncoding = 0;
348            sectionCheckedCount++;
349         }
350     }
351     EXPECT_EQ(12, sectionCheckedCount);
352 }
353
354 // Test that we don't regress https://bugs.webkit.org/show_bug.cgi?id=99105
355 TEST_F(WebPageNewSerializeTest, SVGImageDontCrash)
356 {
357     WebURL pageUrl = toKURL("http://www.test.com");
358     WebURL imageUrl = toKURL("http://www.test.com/green_rectangle.svg");
359
360     registerMockedURLLoad(pageUrl, WebString::fromUTF8("page_with_svg_image.html"), WebString::fromUTF8("pageserializer/"), htmlMimeType());
361     registerMockedURLLoad(imageUrl, WebString::fromUTF8("green_rectangle.svg"), WebString::fromUTF8("pageserializer/"), svgMimeType());
362
363     loadURLInTopFrame(pageUrl);
364
365     WebCString mhtml = WebPageSerializer::serializeToMHTML(webView());
366     // We expect some data to be generated.
367     EXPECT_GT(mhtml.length(), 50U);
368 }
369
370
371 TEST_F(WebPageNewSerializeTest, DontIncludeErrorImage)
372 {
373     WebURL pageUrl = toKURL("http://www.test.com");
374     WebURL imageUrl = toKURL("http://www.test.com/error_image.png");
375
376     registerMockedURLLoad(pageUrl, WebString::fromUTF8("page_with_img_error.html"), WebString::fromUTF8("pageserializer/"), htmlMimeType());
377     registerMockedURLLoad(imageUrl, WebString::fromUTF8("error_image.png"), WebString::fromUTF8("pageserializer/"), pngMimeType());
378
379     loadURLInTopFrame(pageUrl);
380
381     WebCString mhtmlData = WebPageSerializer::serializeToMHTML(webView());
382     ASSERT_FALSE(mhtmlData.isEmpty());
383
384     // Sniff the MHTML data to make sure image content is excluded.
385     LineReader lineReader(std::string(mhtmlData.data()));
386     std::string line;
387     while (lineReader.getNextLine(&line)) {
388         if (line.find("image/") != std::string::npos)
389             FAIL() << "Error Image was not excluded " << line;
390     }
391 }
392
393
394 TEST_F(WebPageNewSerializeTest, NamespaceElementsDontCrash)
395 {
396     WebURL pageUrl = toKURL("http://www.test.com");
397     registerMockedURLLoad(pageUrl, WebString::fromUTF8("namespace_element.html"), WebString::fromUTF8("pageserializer/"), htmlMimeType());
398
399     loadURLInTopFrame(pageUrl);
400
401     WebVector<WebURL> localLinks(static_cast<size_t>(1));
402     WebVector<WebString> localPaths(static_cast<size_t>(1));
403     localLinks[0] = pageUrl;
404     localPaths[0] = WebString("/");
405
406     size_t counter = 0;
407     LengthCountingWebPageSerializerClient client(&counter);
408
409     // We just want to make sure nothing crazy happens, namely that no
410     // assertions are hit. As a sanity check, we also make sure that some data
411     // was returned.
412     WebPageSerializer::serialize(webView()->mainFrame(), true, &client, localLinks, localPaths, WebString(""));
413
414     EXPECT_GT(counter, 0U);
415 }
416
417 }
418
419 TEST_F(WebPageNewSerializeTest, TestMHTMLEncodingWithDataURL)
420 {
421     // Load a page with some data urls.
422     WebURL topFrameURL = toKURL("http://www.test.com");
423     registerMockedURLLoad(topFrameURL, WebString::fromUTF8("page_with_data.html"), WebString::fromUTF8("pageserializer/"), htmlMimeType());
424     loadURLInTopFrame(topFrameURL);
425
426     WebCString mhtmlData = WebPageSerializer::serializeToMHTML(webView());
427     ASSERT_FALSE(mhtmlData.isEmpty());
428
429     // Read the MHTML data line and check that the string data:image is found
430     // exactly one time.
431     size_t nbDataURLs = 0;
432     LineReader lineReader(std::string(mhtmlData.data()));
433     std::string line;
434     while (lineReader.getNextLine(&line)) {
435         if (line.find("data:image") != std::string::npos)
436             nbDataURLs++;
437     }
438     EXPECT_EQ(1u, nbDataURLs);
439 }
440
441
442 TEST_F(WebPageNewSerializeTest, TestMHTMLEncodingWithMorphingDataURL)
443 {
444     // Load a page with some data urls.
445     WebURL topFrameURL = toKURL("http://www.test.com");
446     registerMockedURLLoad(topFrameURL, WebString::fromUTF8("page_with_morphing_data.html"), WebString::fromUTF8("pageserializer/"), htmlMimeType());
447     loadURLInTopFrame(topFrameURL);
448
449     WebCString mhtmlData = WebPageSerializer::serializeToMHTML(webView());
450     ASSERT_FALSE(mhtmlData.isEmpty());
451
452     // Read the MHTML data line and check that the string data:image is found
453     // exactly two times.
454     size_t nbDataURLs = 0;
455     LineReader lineReader(std::string(mhtmlData.data()));
456     std::string line;
457     while (lineReader.getNextLine(&line)) {
458         if (line.find("data:text") != std::string::npos)
459             nbDataURLs++;
460     }
461     EXPECT_EQ(2u, nbDataURLs);
462 }