| /* |
| * Copyright (C) 2014 Google Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: |
| * |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above |
| * copyright notice, this list of conditions and the following disclaimer |
| * in the documentation and/or other materials provided with the |
| * distribution. |
| * * Neither the name of Google Inc. nor the names of its |
| * contributors may be used to endorse or promote products derived from |
| * this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include "base/callback_helpers.h" |
| #include "build/build_config.h" |
| #include "services/network/public/cpp/web_sandbox_flags.h" |
| #include "services/network/public/mojom/web_sandbox_flags.mojom-blink.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "third_party/blink/public/platform/web_string.h" |
| #include "third_party/blink/public/platform/web_url.h" |
| #include "third_party/blink/public/web/web_view.h" |
| #include "third_party/blink/renderer/core/dom/class_collection.h" |
| #include "third_party/blink/renderer/core/dom/document.h" |
| #include "third_party/blink/renderer/core/dom/element.h" |
| #include "third_party/blink/renderer/core/dom/shadow_root.h" |
| #include "third_party/blink/renderer/core/frame/frame_test_helpers.h" |
| #include "third_party/blink/renderer/core/frame/local_dom_window.h" |
| #include "third_party/blink/renderer/core/frame/local_frame.h" |
| #include "third_party/blink/renderer/core/frame/location.h" |
| #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h" |
| #include "third_party/blink/renderer/core/page/page.h" |
| #include "third_party/blink/renderer/platform/loader/static_data_navigation_body_loader.h" |
| #include "third_party/blink/renderer/platform/testing/testing_platform_support.h" |
| #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h" |
| #include "third_party/blink/renderer/platform/testing/url_test_helpers.h" |
| #include "third_party/blink/renderer/platform/weborigin/kurl.h" |
| #include "third_party/blink/renderer/platform/weborigin/scheme_registry.h" |
| |
| using blink::url_test_helpers::ToKURL; |
| |
| namespace blink { |
| namespace test { |
| |
| class MHTMLLoadingTest : public testing::Test { |
| public: |
| MHTMLLoadingTest() = default; |
| |
| protected: |
| void SetUp() override { helper_.Initialize(); } |
| |
| void LoadURLInTopFrame(const WebURL& url, const std::string& file_name) { |
| scoped_refptr<SharedBuffer> buffer = test::ReadFromFile( |
| test::CoreTestDataPath(WebString::FromUTF8("mhtml/" + file_name))); |
| WebLocalFrameImpl* frame = helper_.GetWebView()->MainFrameImpl(); |
| auto params = std::make_unique<WebNavigationParams>(); |
| params->url = url; |
| params->response = WebURLResponse(url); |
| params->response.SetMimeType("multipart/related"); |
| params->response.SetHttpStatusCode(200); |
| params->response.SetExpectedContentLength(buffer->size()); |
| auto body_loader = std::make_unique<StaticDataNavigationBodyLoader>(); |
| body_loader->Write(*buffer); |
| body_loader->Finish(); |
| params->body_loader = std::move(body_loader); |
| frame->CommitNavigation(std::move(params), nullptr /* extra_data */); |
| frame_test_helpers::PumpPendingRequestsForFrameToLoad(frame); |
| } |
| |
| Page* GetPage() const { return helper_.GetWebView()->GetPage(); } |
| |
| private: |
| ScopedTestingPlatformSupport<TestingPlatformSupport> platform_; |
| frame_test_helpers::WebViewHelper helper_; |
| }; |
| |
| // Checks that the domain is set to the actual MHTML file, not the URL it was |
| // generated from. |
| TEST_F(MHTMLLoadingTest, CheckDomain) { |
| const char kFileURL[] = "file:///simple_test.mht"; |
| |
| LoadURLInTopFrame(ToKURL(kFileURL), "simple_test.mht"); |
| ASSERT_TRUE(GetPage()); |
| LocalFrame* frame = To<LocalFrame>(GetPage()->MainFrame()); |
| ASSERT_TRUE(frame); |
| |
| EXPECT_EQ(kFileURL, frame->DomWindow()->location()->toString()); |
| |
| const SecurityOrigin* origin = frame->DomWindow()->GetSecurityOrigin(); |
| EXPECT_NE("localhost", origin->Domain().Ascii()); |
| } |
| |
| // Checks that full sandboxing protection has been turned on. |
| TEST_F(MHTMLLoadingTest, EnforceSandboxFlags) { |
| const char kURL[] = "http://www.example.com"; |
| |
| LoadURLInTopFrame(ToKURL(kURL), "page_with_javascript.mht"); |
| ASSERT_TRUE(GetPage()); |
| LocalFrame* frame = To<LocalFrame>(GetPage()->MainFrame()); |
| ASSERT_TRUE(frame); |
| LocalDOMWindow* window = frame->DomWindow(); |
| ASSERT_TRUE(window); |
| |
| // Full sandboxing with the exception to new top-level windows should be |
| // turned on. |
| EXPECT_EQ(network::mojom::blink::WebSandboxFlags::kAll & |
| ~(network::mojom::blink::WebSandboxFlags::kPopups | |
| network::mojom::blink::WebSandboxFlags:: |
| kPropagatesToAuxiliaryBrowsingContexts), |
| window->GetSandboxFlags()); |
| |
| // MHTML document should be loaded into unique origin. |
| EXPECT_TRUE(window->GetSecurityOrigin()->IsOpaque()); |
| // Script execution should be disabled. |
| EXPECT_FALSE(window->CanExecuteScripts(kNotAboutToExecuteScript)); |
| |
| // The element to be created by the script is not there. |
| EXPECT_FALSE(window->document()->getElementById("mySpan")); |
| |
| // Make sure the subframe is also sandboxed. |
| LocalFrame* child_frame = |
| To<LocalFrame>(GetPage()->MainFrame()->Tree().FirstChild()); |
| ASSERT_TRUE(child_frame); |
| LocalDOMWindow* child_window = child_frame->DomWindow(); |
| ASSERT_TRUE(child_window); |
| |
| EXPECT_EQ(network::mojom::blink::WebSandboxFlags::kAll & |
| ~(network::mojom::blink::WebSandboxFlags::kPopups | |
| network::mojom::blink::WebSandboxFlags:: |
| kPropagatesToAuxiliaryBrowsingContexts), |
| child_window->GetSandboxFlags()); |
| |
| // MHTML document should be loaded into unique origin. |
| EXPECT_TRUE(child_window->GetSecurityOrigin()->IsOpaque()); |
| // Script execution should be disabled. |
| EXPECT_FALSE(child_window->CanExecuteScripts(kNotAboutToExecuteScript)); |
| |
| // The element to be created by the script is not there. |
| EXPECT_FALSE(child_window->document()->getElementById("mySpan")); |
| } |
| |
| TEST_F(MHTMLLoadingTest, EnforceSandboxFlagsInXSLT) { |
| const char kURL[] = "http://www.example.com"; |
| |
| LoadURLInTopFrame(ToKURL(kURL), "xslt.mht"); |
| ASSERT_TRUE(GetPage()); |
| LocalFrame* frame = To<LocalFrame>(GetPage()->MainFrame()); |
| ASSERT_TRUE(frame); |
| LocalDOMWindow* window = frame->DomWindow(); |
| ASSERT_TRUE(window); |
| |
| // Full sandboxing with the exception to new top-level windows should be |
| // turned on. |
| EXPECT_EQ(network::mojom::blink::WebSandboxFlags::kAll & |
| ~(network::mojom::blink::WebSandboxFlags::kPopups | |
| network::mojom::blink::WebSandboxFlags:: |
| kPropagatesToAuxiliaryBrowsingContexts), |
| window->GetSandboxFlags()); |
| |
| // MHTML document should be loaded into unique origin. |
| EXPECT_TRUE(window->GetSecurityOrigin()->IsOpaque()); |
| // Script execution should be disabled. |
| EXPECT_FALSE(window->CanExecuteScripts(kNotAboutToExecuteScript)); |
| } |
| |
| TEST_F(MHTMLLoadingTest, ShadowDom) { |
| const char kURL[] = "http://www.example.com"; |
| |
| LoadURLInTopFrame(ToKURL(kURL), "shadow.mht"); |
| ASSERT_TRUE(GetPage()); |
| LocalFrame* frame = To<LocalFrame>(GetPage()->MainFrame()); |
| ASSERT_TRUE(frame); |
| Document* document = frame->GetDocument(); |
| ASSERT_TRUE(document); |
| |
| EXPECT_TRUE(IsShadowHost(document->getElementById("h2"))); |
| // The nested shadow DOM tree is created. |
| EXPECT_TRUE(IsShadowHost( |
| document->getElementById("h2")->GetShadowRoot()->getElementById("h3"))); |
| |
| EXPECT_TRUE(IsShadowHost(document->getElementById("h4"))); |
| // The static element in the shadow dom template is found. |
| EXPECT_TRUE( |
| document->getElementById("h4")->GetShadowRoot()->getElementById("s1")); |
| // The element to be created by the script in the shadow dom template is |
| // not found because the script is blocked. |
| EXPECT_FALSE( |
| document->getElementById("h4")->GetShadowRoot()->getElementById("s2")); |
| } |
| |
| TEST_F(MHTMLLoadingTest, FormControlElements) { |
| const char kURL[] = "http://www.example.com"; |
| |
| LoadURLInTopFrame(ToKURL(kURL), "form.mht"); |
| ASSERT_TRUE(GetPage()); |
| LocalFrame* frame = To<LocalFrame>(GetPage()->MainFrame()); |
| ASSERT_TRUE(frame); |
| Document* document = frame->GetDocument(); |
| ASSERT_TRUE(document); |
| |
| HTMLCollection* formControlElements = document->getElementsByClassName("fc"); |
| ASSERT_TRUE(formControlElements); |
| for (Element* element : *formControlElements) |
| EXPECT_TRUE(element->IsDisabledFormControl()); |
| |
| EXPECT_FALSE(document->getElementById("h1")->IsDisabledFormControl()); |
| EXPECT_FALSE(document->getElementById("fm")->IsDisabledFormControl()); |
| } |
| |
| TEST_F(MHTMLLoadingTest, LoadMHTMLContainingSoftLineBreaks) { |
| const char kURL[] = "http://www.example.com"; |
| |
| LoadURLInTopFrame(ToKURL(kURL), "soft_line_break.mht"); |
| ASSERT_TRUE(GetPage()); |
| LocalFrame* frame = To<LocalFrame>(GetPage()->MainFrame()); |
| ASSERT_TRUE(frame); |
| // We should not have problem to concatenate header lines separated by soft |
| // line breaks. |
| Document* document = frame->GetDocument(); |
| ASSERT_TRUE(document); |
| |
| // We should not have problem to concatenate body lines separated by soft |
| // line breaks. |
| EXPECT_TRUE(document->getElementById( |
| "AVeryLongID012345678901234567890123456789012345678901234567890End")); |
| } |
| |
| } // namespace test |
| } // namespace blink |