Manually propagate sandbox flags to documents transformed by XSLT

Normally, this would Just Work but the combination of MHTML and XSLT
ends up resulting in a weird interaction. MHTML enforces sandbox flags
on a per-document basis, rather than forcing them on the frame: this
makes sense, since the sandbox flags enforced by a MHTML document should
not apply on subsequent pages. However, XSLT installs a new document to
hold the transformed content. When installing a new Document, the
effective sandbox flags from the FrameLoader are applied--but MHTML only
applied them to the Document, so FrameLoader doesn't know about them.
This fix is to manually propagate the flags for XSLT...

Bug: 762930
Change-Id: I29efb0713195febb1ff4e8af7fd27ba1230abab4
Reviewed-on: https://chromium-review.googlesource.com/656397
Reviewed-by: Kouhei Ueno <kouhei@chromium.org>
Commit-Queue: Daniel Cheng <dcheng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#500510}
diff --git a/third_party/WebKit/Source/core/frame/MHTMLTest.cpp b/third_party/WebKit/Source/core/frame/MHTMLTest.cpp
index 5cdb8de..c3c5613 100644
--- a/third_party/WebKit/Source/core/frame/MHTMLTest.cpp
+++ b/third_party/WebKit/Source/core/frame/MHTMLTest.cpp
@@ -343,6 +343,30 @@
   EXPECT_FALSE(document->getElementById("mySpan"));
 }
 
+TEST_F(MHTMLTest, EnforceSandboxFlagsInXSLT) {
+  const char kURL[] = "http://www.example.com";
+
+  // Register the mocked frame and load it.
+  RegisterMockedURLLoad(kURL, "xslt.mht");
+  LoadURLInTopFrame(ToKURL(kURL));
+  ASSERT_TRUE(GetPage());
+  LocalFrame* frame = ToLocalFrame(GetPage()->MainFrame());
+  ASSERT_TRUE(frame);
+  Document* document = frame->GetDocument();
+  ASSERT_TRUE(document);
+
+  // Full sandboxing with the exception to new top-level windows should be
+  // turned on.
+  EXPECT_EQ(kSandboxAll & ~(kSandboxPopups |
+                            kSandboxPropagatesToAuxiliaryBrowsingContexts),
+            document->GetSandboxFlags());
+
+  // MHTML document should be loaded into unique origin.
+  EXPECT_TRUE(document->GetSecurityOrigin()->IsUnique());
+  // Script execution should be disabled.
+  EXPECT_FALSE(document->CanExecuteScripts(kNotAboutToExecuteScript));
+}
+
 TEST_F(MHTMLTest, ShadowDom) {
   const char kURL[] = "http://www.example.com";
 
diff --git a/third_party/WebKit/Source/core/testing/data/mhtml/xslt.mht b/third_party/WebKit/Source/core/testing/data/mhtml/xslt.mht
new file mode 100644
index 0000000..4392167
--- /dev/null
+++ b/third_party/WebKit/Source/core/testing/data/mhtml/xslt.mht
@@ -0,0 +1,25 @@
+MIME-Version: 1.0
+Content-Type: multipart/related;
+	type="text/html";
+	boundary="----MultipartBoundary--"
+
+------MultipartBoundary--
+Content-Type: text/xml
+
+<?xml version="1.0" encoding="UTF-8"?>
+<?xml-stylesheet type="text/xml" href="#stylesheet"?>
+<!DOCTYPE catalog [
+<!ATTLIST xsl:stylesheet
+  id    ID  #REQUIRED>
+]>
+<root>
+<xsl:stylesheet id="stylesheet" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:template match="/">
+<html>
+<body>
+</body>
+</html>
+</xsl:template>
+</xsl:stylesheet>
+</root>
+------MultipartBoundary----
diff --git a/third_party/WebKit/Source/core/xml/XSLTProcessor.cpp b/third_party/WebKit/Source/core/xml/XSLTProcessor.cpp
index b445f074..5e434379 100644
--- a/third_party/WebKit/Source/core/xml/XSLTProcessor.cpp
+++ b/third_party/WebKit/Source/core/xml/XSLTProcessor.cpp
@@ -95,6 +95,7 @@
       DocumentXSLT::From(*result).SetTransformSourceDocument(old_document);
       result->UpdateSecurityOrigin(old_document->GetSecurityOrigin());
       result->SetCookieURL(old_document->CookieURL());
+      result->EnforceSandboxFlags(old_document->GetSandboxFlags());
 
       ContentSecurityPolicy* csp = ContentSecurityPolicy::Create();
       csp->CopyStateFrom(old_document->GetContentSecurityPolicy());