| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2011 Google Inc. All rights reserved. | 2 * Copyright (C) 2017 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| 11 * copyright notice, this list of conditions and the following disclaimer | 11 * copyright notice, this list of conditions and the following disclaimer |
| 12 * in the documentation and/or other materials provided with the | 12 * in the documentation and/or other materials provided with the |
| (...skipping 11 matching lines...) Expand all Loading... |
| 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 */ | 29 */ |
| 30 | 30 |
| 31 #include "public/web/WebFrameSerializer.h" | 31 #include "public/web/WebFrameSerializer.h" |
| 32 | 32 |
| 33 #include "core/exported/WebViewBase.h" | 33 #include "core/exported/WebViewBase.h" |
| 34 #include "platform/mhtml/MHTMLArchive.h" | |
| 35 #include "platform/mhtml/MHTMLParser.h" | |
| 36 #include "platform/testing/HistogramTester.h" | |
| 37 #include "platform/testing/URLTestHelpers.h" | 34 #include "platform/testing/URLTestHelpers.h" |
| 38 #include "platform/testing/UnitTestHelpers.h" | 35 #include "platform/testing/UnitTestHelpers.h" |
| 39 #include "platform/weborigin/KURL.h" | 36 #include "platform/weborigin/KURL.h" |
| 40 #include "platform/wtf/text/StringBuilder.h" | 37 #include "platform/wtf/text/StringBuilder.h" |
| 41 #include "public/platform/Platform.h" | 38 #include "public/platform/Platform.h" |
| 42 #include "public/platform/WebCString.h" | 39 #include "public/platform/WebCString.h" |
| 43 #include "public/platform/WebCache.h" | |
| 44 #include "public/platform/WebString.h" | 40 #include "public/platform/WebString.h" |
| 45 #include "public/platform/WebURL.h" | 41 #include "public/platform/WebURL.h" |
| 46 #include "public/platform/WebURLLoaderMockFactory.h" | 42 #include "public/platform/WebURLLoaderMockFactory.h" |
| 47 #include "public/web/WebFrameSerializerClient.h" | 43 #include "public/web/WebFrameSerializerClient.h" |
| 48 #include "testing/gtest/include/gtest/gtest.h" | 44 #include "testing/gtest/include/gtest/gtest.h" |
| 49 #include "web/WebLocalFrameImpl.h" | 45 #include "web/WebLocalFrameImpl.h" |
| 50 #include "web/tests/FrameTestHelpers.h" | 46 #include "web/tests/FrameTestHelpers.h" |
| 51 | 47 |
| 52 namespace blink { | 48 namespace blink { |
| 53 | 49 |
| 54 namespace { | 50 namespace { |
| 51 |
| 55 class SimpleWebFrameSerializerClient final : public WebFrameSerializerClient { | 52 class SimpleWebFrameSerializerClient final : public WebFrameSerializerClient { |
| 56 public: | 53 public: |
| 57 String ToString() { return builder_.ToString(); } | 54 String ToString() { return builder_.ToString(); } |
| 58 | 55 |
| 59 private: | 56 private: |
| 60 void DidSerializeDataForFrame(const WebCString& data, | 57 void DidSerializeDataForFrame(const WebCString& data, |
| 61 FrameSerializationStatus) final { | 58 FrameSerializationStatus) final { |
| 62 builder_.Append(data.Data(), data.length()); | 59 builder_.Append(data.Data(), data.length()); |
| 63 } | 60 } |
| 64 | 61 |
| 65 StringBuilder builder_; | 62 StringBuilder builder_; |
| 66 }; | 63 }; |
| 67 | 64 |
| 68 class SimpleMHTMLPartsGenerationDelegate | |
| 69 : public WebFrameSerializer::MHTMLPartsGenerationDelegate { | |
| 70 public: | |
| 71 SimpleMHTMLPartsGenerationDelegate() : remove_popup_overlay_(false) {} | |
| 72 | |
| 73 void SetRemovePopupOverlay(bool remove_popup_overlay) { | |
| 74 remove_popup_overlay_ = remove_popup_overlay; | |
| 75 } | |
| 76 | |
| 77 private: | |
| 78 bool ShouldSkipResource(const WebURL&) final { return false; } | |
| 79 | |
| 80 WebString GetContentID(WebFrame*) final { return WebString("<cid>"); } | |
| 81 | |
| 82 WebFrameSerializerCacheControlPolicy CacheControlPolicy() final { | |
| 83 return WebFrameSerializerCacheControlPolicy::kNone; | |
| 84 } | |
| 85 | |
| 86 bool UseBinaryEncoding() final { return false; } | |
| 87 bool RemovePopupOverlay() final { return remove_popup_overlay_; } | |
| 88 | |
| 89 bool remove_popup_overlay_; | |
| 90 }; | |
| 91 | |
| 92 // Returns the count of match for substring |pattern| in string |str|. | |
| 93 int MatchSubstring(const String& str, const char* pattern, size_t size) { | |
| 94 int matches = 0; | |
| 95 size_t start = 0; | |
| 96 while (true) { | |
| 97 size_t pos = str.Find(pattern, start); | |
| 98 if (pos == WTF::kNotFound) | |
| 99 break; | |
| 100 matches++; | |
| 101 start = pos + size; | |
| 102 } | |
| 103 return matches; | |
| 104 } | |
| 105 | |
| 106 } // namespace | 65 } // namespace |
| 107 | 66 |
| 108 class WebFrameSerializerTest : public ::testing::Test { | 67 class WebFrameSerializerTest : public ::testing::Test { |
| 109 protected: | 68 protected: |
| 110 WebFrameSerializerTest() { helper_.Initialize(); } | 69 WebFrameSerializerTest() { helper_.Initialize(); } |
| 111 | 70 |
| 112 ~WebFrameSerializerTest() override { | 71 ~WebFrameSerializerTest() override { |
| 113 Platform::Current() | 72 Platform::Current() |
| 114 ->GetURLLoaderMockFactory() | 73 ->GetURLLoaderMockFactory() |
| 115 ->UnregisterAllURLsAndClearMemoryCache(); | 74 ->UnregisterAllURLsAndClearMemoryCache(); |
| 116 } | 75 } |
| 117 | 76 |
| 118 void RegisterMockedImageURLLoad(const String& url) { | 77 void RegisterMockedImageURLLoad(const String& url) { |
| 119 // Image resources need to be mocked, but irrelevant here what image they | 78 // Image resources need to be mocked, but irrelevant here what image they |
| 120 // map to. | 79 // map to. |
| 121 RegisterMockedFileURLLoad(URLTestHelpers::ToKURL(url.Utf8().data()), | 80 RegisterMockedFileURLLoad(URLTestHelpers::ToKURL(url.Utf8().data()), |
| 122 "frameserialization/awesome.png"); | 81 "frameserialization/awesome.png"); |
| 123 } | 82 } |
| 83 |
| 124 void RegisterMockedFileURLLoad(const KURL& url, | 84 void RegisterMockedFileURLLoad(const KURL& url, |
| 125 const String& file_path, | 85 const String& file_path, |
| 126 const String& mime_type = "image/png") { | 86 const String& mime_type = "image/png") { |
| 127 URLTestHelpers::RegisterMockedURLLoad( | 87 URLTestHelpers::RegisterMockedURLLoad( |
| 128 url, testing::WebTestDataPath(file_path.Utf8().data()), mime_type); | 88 url, testing::WebTestDataPath(file_path.Utf8().data()), mime_type); |
| 129 } | 89 } |
| 130 | 90 |
| 131 class SingleLinkRewritingDelegate | 91 class SingleLinkRewritingDelegate |
| 132 : public WebFrameSerializer::LinkRewritingDelegate { | 92 : public WebFrameSerializer::LinkRewritingDelegate { |
| 133 public: | 93 public: |
| (...skipping 23 matching lines...) Expand all Loading... |
| 157 String file_path("frameserialization/" + file_name); | 117 String file_path("frameserialization/" + file_name); |
| 158 RegisterMockedFileURLLoad(parsed_url, file_path, "text/html"); | 118 RegisterMockedFileURLLoad(parsed_url, file_path, "text/html"); |
| 159 FrameTestHelpers::LoadFrame(MainFrameImpl(), url.Utf8().data()); | 119 FrameTestHelpers::LoadFrame(MainFrameImpl(), url.Utf8().data()); |
| 160 SingleLinkRewritingDelegate delegate(parsed_url, WebString("local")); | 120 SingleLinkRewritingDelegate delegate(parsed_url, WebString("local")); |
| 161 SimpleWebFrameSerializerClient serializer_client; | 121 SimpleWebFrameSerializerClient serializer_client; |
| 162 WebFrameSerializer::Serialize(MainFrameImpl(), &serializer_client, | 122 WebFrameSerializer::Serialize(MainFrameImpl(), &serializer_client, |
| 163 &delegate); | 123 &delegate); |
| 164 return serializer_client.ToString(); | 124 return serializer_client.ToString(); |
| 165 } | 125 } |
| 166 | 126 |
| 167 WebViewBase* WebView() { return helper_.WebView(); } | |
| 168 | |
| 169 WebLocalFrameImpl* MainFrameImpl() { | 127 WebLocalFrameImpl* MainFrameImpl() { |
| 170 return helper_.WebView()->MainFrameImpl(); | 128 return helper_.WebView()->MainFrameImpl(); |
| 171 } | 129 } |
| 172 | 130 |
| 173 private: | 131 private: |
| 174 FrameTestHelpers::WebViewHelper helper_; | 132 FrameTestHelpers::WebViewHelper helper_; |
| 175 }; | 133 }; |
| 176 | 134 |
| 177 TEST_F(WebFrameSerializerTest, URLAttributeValues) { | 135 TEST_F(WebFrameSerializerTest, URLAttributeValues) { |
| 178 RegisterMockedImageURLLoad("javascript:\""); | 136 RegisterMockedImageURLLoad("javascript:\""); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 208 EXPECT_EQ(expected_html, actual_html); | 166 EXPECT_EQ(expected_html, actual_html); |
| 209 } | 167 } |
| 210 | 168 |
| 211 TEST_F(WebFrameSerializerTest, FromUrlWithMinusMinus) { | 169 TEST_F(WebFrameSerializerTest, FromUrlWithMinusMinus) { |
| 212 String actual_html = | 170 String actual_html = |
| 213 SerializeFile("http://www.test.com?--x--", "text_only_page.html"); | 171 SerializeFile("http://www.test.com?--x--", "text_only_page.html"); |
| 214 EXPECT_EQ("<!-- saved from url=(0030)http://www.test.com/?-%2Dx-%2D -->", | 172 EXPECT_EQ("<!-- saved from url=(0030)http://www.test.com/?-%2Dx-%2D -->", |
| 215 actual_html.Substring(1, 60)); | 173 actual_html.Substring(1, 60)); |
| 216 } | 174 } |
| 217 | 175 |
| 218 class WebFrameSerializerSanitizationTest : public WebFrameSerializerTest { | |
| 219 protected: | |
| 220 WebFrameSerializerSanitizationTest() {} | |
| 221 | |
| 222 ~WebFrameSerializerSanitizationTest() override {} | |
| 223 | |
| 224 String GenerateMHTMLFromHtml(const String& url, const String& file_name) { | |
| 225 return GenerateMHTML(url, file_name, "text/html", false); | |
| 226 } | |
| 227 | |
| 228 String GenerateMHTMLPartsFromPng(const String& url, const String& file_name) { | |
| 229 return GenerateMHTML(url, file_name, "image/png", true); | |
| 230 } | |
| 231 | |
| 232 String GenerateMHTML(const String& url, | |
| 233 const String& file_name, | |
| 234 const String& mime_type, | |
| 235 const bool only_body_parts) { | |
| 236 KURL parsed_url(kParsedURLString, url); | |
| 237 String file_path("frameserialization/" + file_name); | |
| 238 RegisterMockedFileURLLoad(parsed_url, file_path, mime_type); | |
| 239 FrameTestHelpers::LoadFrame(MainFrameImpl(), url.Utf8().data()); | |
| 240 // Boundaries are normally randomly generated but this one is predefined for | |
| 241 // simplicity and as good as any other. Plus it gets used in almost all the | |
| 242 // examples in the MHTML spec - RFC 2557. | |
| 243 const WebString boundary("boundary-example"); | |
| 244 StringBuilder mhtml; | |
| 245 if (!only_body_parts) { | |
| 246 WebThreadSafeData header_result = WebFrameSerializer::GenerateMHTMLHeader( | |
| 247 boundary, MainFrameImpl(), &mhtml_delegate_); | |
| 248 mhtml.Append(header_result.Data(), header_result.size()); | |
| 249 } | |
| 250 | |
| 251 WebThreadSafeData body_result = WebFrameSerializer::GenerateMHTMLParts( | |
| 252 boundary, MainFrameImpl(), &mhtml_delegate_); | |
| 253 mhtml.Append(body_result.Data(), body_result.size()); | |
| 254 | |
| 255 if (!only_body_parts) { | |
| 256 RefPtr<RawData> footer_data = RawData::Create(); | |
| 257 MHTMLArchive::GenerateMHTMLFooterForTesting(boundary, | |
| 258 *footer_data->MutableData()); | |
| 259 mhtml.Append(footer_data->data(), footer_data->length()); | |
| 260 } | |
| 261 | |
| 262 String mhtml_string = mhtml.ToString(); | |
| 263 if (!only_body_parts) { | |
| 264 // Validate the generated MHTML. | |
| 265 MHTMLParser parser(SharedBuffer::Create(mhtml_string.Characters8(), | |
| 266 size_t(mhtml_string.length()))); | |
| 267 EXPECT_FALSE(parser.ParseArchive().IsEmpty()) | |
| 268 << "Generated MHTML is not well formed"; | |
| 269 } | |
| 270 return mhtml_string; | |
| 271 } | |
| 272 | |
| 273 void SetRemovePopupOverlay(bool remove_popup_overlay) { | |
| 274 mhtml_delegate_.SetRemovePopupOverlay(remove_popup_overlay); | |
| 275 } | |
| 276 | |
| 277 protected: | |
| 278 HistogramTester histogram_tester_; | |
| 279 | |
| 280 private: | |
| 281 SimpleMHTMLPartsGenerationDelegate mhtml_delegate_; | |
| 282 }; | |
| 283 | |
| 284 TEST_F(WebFrameSerializerSanitizationTest, RemoveInlineScriptInAttributes) { | |
| 285 String mhtml = | |
| 286 GenerateMHTMLFromHtml("http://www.test.com", "script_in_attributes.html"); | |
| 287 | |
| 288 // These scripting attributes should be removed. | |
| 289 EXPECT_EQ(WTF::kNotFound, mhtml.Find("onload=")); | |
| 290 EXPECT_EQ(WTF::kNotFound, mhtml.Find("ONLOAD=")); | |
| 291 EXPECT_EQ(WTF::kNotFound, mhtml.Find("onclick=")); | |
| 292 EXPECT_EQ(WTF::kNotFound, mhtml.Find("href=")); | |
| 293 EXPECT_EQ(WTF::kNotFound, mhtml.Find("from=")); | |
| 294 EXPECT_EQ(WTF::kNotFound, mhtml.Find("to=")); | |
| 295 EXPECT_EQ(WTF::kNotFound, mhtml.Find("javascript:")); | |
| 296 | |
| 297 // These non-scripting attributes should remain intact. | |
| 298 EXPECT_NE(WTF::kNotFound, mhtml.Find("class=")); | |
| 299 EXPECT_NE(WTF::kNotFound, mhtml.Find("id=")); | |
| 300 | |
| 301 // srcdoc attribute of frame element should be replaced with src attribute. | |
| 302 EXPECT_EQ(WTF::kNotFound, mhtml.Find("srcdoc=")); | |
| 303 EXPECT_NE(WTF::kNotFound, mhtml.Find("src=")); | |
| 304 } | |
| 305 | |
| 306 TEST_F(WebFrameSerializerSanitizationTest, RemoveOtherAttributes) { | |
| 307 String mhtml = | |
| 308 GenerateMHTMLFromHtml("http://www.test.com", "remove_attributes.html"); | |
| 309 EXPECT_EQ(WTF::kNotFound, mhtml.Find("ping=")); | |
| 310 } | |
| 311 | |
| 312 TEST_F(WebFrameSerializerSanitizationTest, DisableFormElements) { | |
| 313 String mhtml = GenerateMHTMLFromHtml("http://www.test.com", "form.html"); | |
| 314 | |
| 315 const char kDisabledAttr[] = "disabled=3D\"\""; | |
| 316 int matches = | |
| 317 MatchSubstring(mhtml, kDisabledAttr, arraysize(kDisabledAttr) - 1); | |
| 318 EXPECT_EQ(21, matches); | |
| 319 } | |
| 320 | |
| 321 TEST_F(WebFrameSerializerSanitizationTest, RemoveHiddenElements) { | |
| 322 String mhtml = | |
| 323 GenerateMHTMLFromHtml("http://www.test.com", "hidden_elements.html"); | |
| 324 | |
| 325 // The element with hidden attribute should be removed. | |
| 326 EXPECT_EQ(WTF::kNotFound, mhtml.Find("<p id=3D\"hidden_id\"")); | |
| 327 | |
| 328 // The hidden form element should be removed. | |
| 329 EXPECT_EQ(WTF::kNotFound, mhtml.Find("<input type=3D\"hidden\"")); | |
| 330 | |
| 331 // All other hidden elements should not be removed. | |
| 332 EXPECT_NE(WTF::kNotFound, mhtml.Find("<html")); | |
| 333 EXPECT_NE(WTF::kNotFound, mhtml.Find("<head")); | |
| 334 EXPECT_NE(WTF::kNotFound, mhtml.Find("<style")); | |
| 335 EXPECT_NE(WTF::kNotFound, mhtml.Find("<title")); | |
| 336 EXPECT_NE(WTF::kNotFound, mhtml.Find("<h1")); | |
| 337 EXPECT_NE(WTF::kNotFound, mhtml.Find("<h2")); | |
| 338 EXPECT_NE(WTF::kNotFound, mhtml.Find("<datalist")); | |
| 339 EXPECT_NE(WTF::kNotFound, mhtml.Find("<option")); | |
| 340 // One for meta in head and another for meta in body. | |
| 341 EXPECT_EQ(2, MatchSubstring(mhtml, "<meta", 5)); | |
| 342 // One for style in head and another for style in body. | |
| 343 EXPECT_EQ(2, MatchSubstring(mhtml, "<style", 6)); | |
| 344 // One for link in head and another for link in body. | |
| 345 EXPECT_EQ(2, MatchSubstring(mhtml, "<link", 5)); | |
| 346 | |
| 347 // These visible elements should remain intact. | |
| 348 EXPECT_NE(WTF::kNotFound, mhtml.Find("<p id=3D\"visible_id\"")); | |
| 349 EXPECT_NE(WTF::kNotFound, mhtml.Find("<form")); | |
| 350 EXPECT_NE(WTF::kNotFound, mhtml.Find("<input type=3D\"text\"")); | |
| 351 EXPECT_NE(WTF::kNotFound, mhtml.Find("<div")); | |
| 352 } | |
| 353 | |
| 354 // Regression test for crbug.com/678893, where in some cases serializing an | |
| 355 // image document could cause code to pick an element from an empty container. | |
| 356 TEST_F(WebFrameSerializerSanitizationTest, FromBrokenImageDocument) { | |
| 357 // This test only cares that the result of the parts generation is empty so it | |
| 358 // is simpler to not generate only that instead of the full MHTML. | |
| 359 String mhtml = | |
| 360 GenerateMHTMLPartsFromPng("http://www.test.com", "broken-image.png"); | |
| 361 EXPECT_TRUE(mhtml.IsEmpty()); | |
| 362 } | |
| 363 | |
| 364 TEST_F(WebFrameSerializerSanitizationTest, ImageLoadedFromSrcsetForHiDPI) { | |
| 365 RegisterMockedFileURLLoad( | |
| 366 KURL(kParsedURLString, "http://www.test.com/1x.png"), | |
| 367 "frameserialization/1x.png"); | |
| 368 RegisterMockedFileURLLoad( | |
| 369 KURL(kParsedURLString, "http://www.test.com/2x.png"), | |
| 370 "frameserialization/2x.png"); | |
| 371 | |
| 372 // Set high DPR in order to load image from srcset, instead of src. | |
| 373 WebView()->SetDeviceScaleFactor(2.0f); | |
| 374 | |
| 375 String mhtml = | |
| 376 GenerateMHTMLFromHtml("http://www.test.com", "img_srcset.html"); | |
| 377 | |
| 378 // srcset attribute should be skipped. | |
| 379 EXPECT_EQ(WTF::kNotFound, mhtml.Find("srcset=")); | |
| 380 | |
| 381 // Width and height attributes should be set when none is present in <img>. | |
| 382 EXPECT_NE(WTF::kNotFound, | |
| 383 mhtml.Find("id=3D\"i1\" width=3D\"6\" height=3D\"6\">")); | |
| 384 | |
| 385 // Height attribute should not be set if width attribute is already present in | |
| 386 // <img> | |
| 387 EXPECT_NE(WTF::kNotFound, mhtml.Find("id=3D\"i2\" width=3D\"8\">")); | |
| 388 } | |
| 389 | |
| 390 TEST_F(WebFrameSerializerSanitizationTest, ImageLoadedFromSrcForNormalDPI) { | |
| 391 RegisterMockedFileURLLoad( | |
| 392 KURL(kParsedURLString, "http://www.test.com/1x.png"), | |
| 393 "frameserialization/1x.png"); | |
| 394 RegisterMockedFileURLLoad( | |
| 395 KURL(kParsedURLString, "http://www.test.com/2x.png"), | |
| 396 "frameserialization/2x.png"); | |
| 397 | |
| 398 String mhtml = | |
| 399 GenerateMHTMLFromHtml("http://www.test.com", "img_srcset.html"); | |
| 400 | |
| 401 // srcset attribute should be skipped. | |
| 402 EXPECT_EQ(WTF::kNotFound, mhtml.Find("srcset=")); | |
| 403 | |
| 404 // New width and height attributes should not be set. | |
| 405 EXPECT_NE(WTF::kNotFound, mhtml.Find("id=3D\"i1\">")); | |
| 406 EXPECT_NE(WTF::kNotFound, mhtml.Find("id=3D\"i2\" width=3D\"8\">")); | |
| 407 } | |
| 408 | |
| 409 TEST_F(WebFrameSerializerSanitizationTest, RemovePopupOverlayIfRequested) { | |
| 410 WebView()->Resize(WebSize(500, 500)); | |
| 411 SetRemovePopupOverlay(true); | |
| 412 String mhtml = GenerateMHTMLFromHtml("http://www.test.com", "popup.html"); | |
| 413 EXPECT_EQ(WTF::kNotFound, mhtml.Find("class=3D\"overlay")); | |
| 414 EXPECT_EQ(WTF::kNotFound, mhtml.Find("class=3D\"modal")); | |
| 415 histogram_tester_.ExpectUniqueSample( | |
| 416 "PageSerialization.MhtmlGeneration.PopupOverlaySkipped", true, 1); | |
| 417 } | |
| 418 | |
| 419 TEST_F(WebFrameSerializerSanitizationTest, PopupOverlayNotFound) { | |
| 420 WebView()->Resize(WebSize(500, 500)); | |
| 421 SetRemovePopupOverlay(true); | |
| 422 String mhtml = | |
| 423 GenerateMHTMLFromHtml("http://www.test.com", "text_only_page.html"); | |
| 424 histogram_tester_.ExpectUniqueSample( | |
| 425 "PageSerialization.MhtmlGeneration.PopupOverlaySkipped", false, 1); | |
| 426 } | |
| 427 | |
| 428 TEST_F(WebFrameSerializerSanitizationTest, KeepPopupOverlayIfNotRequested) { | |
| 429 WebView()->Resize(WebSize(500, 500)); | |
| 430 SetRemovePopupOverlay(false); | |
| 431 String mhtml = GenerateMHTMLFromHtml("http://www.test.com", "popup.html"); | |
| 432 EXPECT_NE(WTF::kNotFound, mhtml.Find("class=3D\"overlay")); | |
| 433 EXPECT_NE(WTF::kNotFound, mhtml.Find("class=3D\"modal")); | |
| 434 histogram_tester_.ExpectTotalCount( | |
| 435 "PageSerialization.MhtmlGeneration.PopupOverlaySkipped", 0); | |
| 436 } | |
| 437 | |
| 438 TEST_F(WebFrameSerializerSanitizationTest, RemoveElements) { | |
| 439 String mhtml = | |
| 440 GenerateMHTMLFromHtml("http://www.test.com", "remove_elements.html"); | |
| 441 | |
| 442 EXPECT_EQ(WTF::kNotFound, mhtml.Find("<script")); | |
| 443 EXPECT_EQ(WTF::kNotFound, mhtml.Find("<noscript")); | |
| 444 | |
| 445 // Only the meta element containing "Content-Security-Policy" is removed. | |
| 446 // Other meta elements should be preserved. | |
| 447 EXPECT_EQ(WTF::kNotFound, | |
| 448 mhtml.Find("<meta http-equiv=3D\"Content-Security-Policy")); | |
| 449 EXPECT_NE(WTF::kNotFound, mhtml.Find("<meta name=3D\"description")); | |
| 450 EXPECT_NE(WTF::kNotFound, mhtml.Find("<meta http-equiv=3D\"refresh")); | |
| 451 | |
| 452 // If an element is removed, its children should also be skipped. | |
| 453 EXPECT_EQ(WTF::kNotFound, mhtml.Find("<select")); | |
| 454 EXPECT_EQ(WTF::kNotFound, mhtml.Find("<option")); | |
| 455 } | |
| 456 | |
| 457 } // namespace blink | 176 } // namespace blink |
| OLD | NEW |