Commit f544bbaa authored by Jian Li's avatar Jian Li Committed by Commit Bot

Switch to disabling form control elements in loaded MHTML

We used to disable all form control elements when saving a page as
MHTML since the form in the MHTML document cannot be worked on due
to form submission and script execution disabled. As suggested by
Jeffrey Yasskin, we switched to disable form control elements in
the loaded MHTML document.

Bug: 771786
Change-Id: I44b9c324192be052dd47db3d126a911ab5dd34e3
Reviewed-on: https://chromium-review.googlesource.com/701368
Commit-Queue: Jian Li <jianli@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#506839}
parent b0b6dfa9
...@@ -111,8 +111,6 @@ class MHTMLFrameSerializerDelegate final : public FrameSerializer::Delegate { ...@@ -111,8 +111,6 @@ class MHTMLFrameSerializerDelegate final : public FrameSerializer::Delegate {
bool ShouldIgnorePopupOverlayElement(const Element&); bool ShouldIgnorePopupOverlayElement(const Element&);
void GetCustomAttributesForImageElement(const HTMLImageElement&, void GetCustomAttributesForImageElement(const HTMLImageElement&,
Vector<Attribute>*); Vector<Attribute>*);
void GetCustomAttributesForFormControlElement(const Element&,
Vector<Attribute>*);
WebFrameSerializer::MHTMLPartsGenerationDelegate& web_delegate_; WebFrameSerializer::MHTMLPartsGenerationDelegate& web_delegate_;
HeapHashSet<WeakMember<const Element>>& shadow_template_elements_; HeapHashSet<WeakMember<const Element>>& shadow_template_elements_;
...@@ -304,8 +302,6 @@ Vector<Attribute> MHTMLFrameSerializerDelegate::GetCustomAttributes( ...@@ -304,8 +302,6 @@ Vector<Attribute> MHTMLFrameSerializerDelegate::GetCustomAttributes(
if (auto* image = ToHTMLImageElementOrNull(element)) { if (auto* image = ToHTMLImageElementOrNull(element)) {
GetCustomAttributesForImageElement(*image, &attributes); GetCustomAttributesForImageElement(*image, &attributes);
} else if (element.IsFormControlElement()) {
GetCustomAttributesForFormControlElement(element, &attributes);
} }
return attributes; return attributes;
...@@ -352,18 +348,6 @@ void MHTMLFrameSerializerDelegate::GetCustomAttributesForImageElement( ...@@ -352,18 +348,6 @@ void MHTMLFrameSerializerDelegate::GetCustomAttributesForImageElement(
attributes->push_back(height_attribute); attributes->push_back(height_attribute);
} }
void MHTMLFrameSerializerDelegate::GetCustomAttributesForFormControlElement(
const Element& element,
Vector<Attribute>* attributes) {
// Disable all form elements in MTHML to tell the user that the form cannot be
// worked on. MHTML is loaded in full sandboxing mode which disable the form
// submission and script execution.
if (element.FastHasAttribute(HTMLNames::disabledAttr))
return;
Attribute disabled_attribute(HTMLNames::disabledAttr, "");
attributes->push_back(disabled_attribute);
}
std::pair<Node*, Element*> MHTMLFrameSerializerDelegate::GetAuxiliaryDOMTree( std::pair<Node*, Element*> MHTMLFrameSerializerDelegate::GetAuxiliaryDOMTree(
const Element& element) const { const Element& element) const {
const ElementShadow* shadow = element.Shadow(); const ElementShadow* shadow = element.Shadow();
......
...@@ -230,15 +230,6 @@ TEST_F(WebFrameSerializerSanitizationTest, RemoveOtherAttributes) { ...@@ -230,15 +230,6 @@ TEST_F(WebFrameSerializerSanitizationTest, RemoveOtherAttributes) {
EXPECT_EQ(WTF::kNotFound, mhtml.Find("ping=")); EXPECT_EQ(WTF::kNotFound, mhtml.Find("ping="));
} }
TEST_F(WebFrameSerializerSanitizationTest, DisableFormElements) {
String mhtml = GenerateMHTMLFromHtml("http://www.test.com", "form.html");
const char kDisabledAttr[] = "disabled=3D\"\"";
int matches =
MatchSubstring(mhtml, kDisabledAttr, arraysize(kDisabledAttr) - 1);
EXPECT_EQ(21, matches);
}
TEST_F(WebFrameSerializerSanitizationTest, RemoveHiddenElements) { TEST_F(WebFrameSerializerSanitizationTest, RemoveHiddenElements) {
String mhtml = String mhtml =
GenerateMHTMLFromHtml("http://www.test.com", "hidden_elements.html"); GenerateMHTMLFromHtml("http://www.test.com", "hidden_elements.html");
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <map> #include <map>
#include "build/build_config.h" #include "build/build_config.h"
#include "core/dom/ClassCollection.h"
#include "core/dom/Document.h" #include "core/dom/Document.h"
#include "core/dom/Element.h" #include "core/dom/Element.h"
#include "core/dom/ElementShadow.h" #include "core/dom/ElementShadow.h"
...@@ -421,4 +422,25 @@ TEST_F(MHTMLTest, ShadowDom) { ...@@ -421,4 +422,25 @@ TEST_F(MHTMLTest, ShadowDom) {
.getElementById("s2")); .getElementById("s2"));
} }
TEST_F(MHTMLTest, FormControlElements) {
const char kURL[] = "http://www.example.com";
// Register the mocked frame and load it.
RegisterMockedURLLoad(kURL, "form.mht");
LoadURLInTopFrame(ToKURL(kURL));
ASSERT_TRUE(GetPage());
LocalFrame* frame = ToLocalFrame(GetPage()->MainFrame());
ASSERT_TRUE(frame);
Document* document = frame->GetDocument();
ASSERT_TRUE(document);
ClassCollection* 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());
}
} // namespace blink } // namespace blink
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include "core/page/Page.h" #include "core/page/Page.h"
#include "core/page/ValidationMessageClient.h" #include "core/page/ValidationMessageClient.h"
#include "platform/EventDispatchForbiddenScope.h" #include "platform/EventDispatchForbiddenScope.h"
#include "platform/loader/fetch/ResourceFetcher.h"
#include "platform/text/BidiTextRun.h" #include "platform/text/BidiTextRun.h"
#include "platform/wtf/Vector.h" #include "platform/wtf/Vector.h"
...@@ -338,6 +339,12 @@ bool HTMLFormControlElement::IsDisabledFormControl() const { ...@@ -338,6 +339,12 @@ bool HTMLFormControlElement::IsDisabledFormControl() const {
if (FastHasAttribute(disabledAttr)) if (FastHasAttribute(disabledAttr))
return true; return true;
// Since the MHTML is loaded in sandboxing mode with form submission and
// script execution disabled, we should gray out all form control elements
// to indicate that the form cannot be worked on.
if (GetDocument().Fetcher()->Archive())
return true;
if (ancestor_disabled_state_ == kAncestorDisabledStateUnknown) if (ancestor_disabled_state_ == kAncestorDisabledStateUnknown)
UpdateAncestorDisabledState(); UpdateAncestorDisabledState();
return ancestor_disabled_state_ == kAncestorDisabledStateDisabled; return ancestor_disabled_state_ == kAncestorDisabledStateDisabled;
......
<html>
<meta charset="utf8">
<body>
<form>
<input type="text" name="dname" value="" disabled>
<input type="text" name="name" value="">
<input type="password" name="pwd">
<input type="email" name="email">
<input type="file" name="attachment">
<input type="date" name="date">
<input type="time" name="time">
<input type="radio" name="radio" value="1">
<input type="checkbox" name="checkbox" value="here">
<input type="number" name="quantity" min="1" max="5">
<input type="color" name="favcolor">
<input type="range" name="points" min="0" max="10">
<textarea name="message" rows="2" cols="20"></textarea>
<select name="choices">
<option value="c1">c1</option>
</select>
<input list="items">
<datalist id="items" default="i1">
<option value="i1">i1</option>
</datalist>
<output name="sum" for=""></output>
<button type="button" disabled>Foo</button>
<button type="button">Validate</button>
<input type="button" value="Click">
<input type="reset">
<input type="submit" value="Submit">
</form>
</body>
</html>
From: <Saved by Blink>
Subject: Form
Date: Thu, 4 Oct 2017 21:18:18 -0000
MIME-Version: 1.0
Content-Type: multipart/related;
type="text/html";
boundary="----MultipartBoundary--e77OylKXx1PBMEF67x53AwnQLf4DUmwdt037X9MjPK----"
------MultipartBoundary--e77OylKXx1PBMEF67x53AwnQLf4DUmwdt037X9MjPK----
Content-Type: text/html
Content-ID: <frame-31894-fca076b5-329b-490d-a9ee-6974bf0c4bcd@mhtml.blink>
Content-Transfer-Encoding: quoted-printable
Content-Location: file:///usr/local/google/home/jianli/form.html
<html>
<head><meta http-equiv=3D"Content-Type" content=3D"text/html; charset=
=3DUTF-8">
</head>
<body>
<h1 id="h1">Form</h1>
<form id="fm">
<input class="fc" type=3D"text" name=3D"name" value=3D"">
<input class="fc" type=3D"password" name=3D"pwd">
<input class="fc" type=3D"button" value=3D"Click">
<input class="fc" type=3D"reset">
<input class="fc" type=3D"submit" value=3D"Submit">
</form>
</body>
</html>
------MultipartBoundary--e77OylKXx1PBMEF67x53AwnQLf4DUmwdt037X9MjPK------
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment