<https://webkit.org/b/119930> input[type=range]: Fix a crash by changing input type...
authorrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 20 Aug 2013 00:02:56 +0000 (00:02 +0000)
committerrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 20 Aug 2013 00:02:56 +0000 (00:02 +0000)
Reviewed by Kent Tamura.

Source/WebCore:

Merge https://chromium.googlesource.com/chromium/blink/+/99afc9b55ce176b4f5fe053070e19dbebc1891a5

In SliderThumbElement::setPositionFromPoint, renderer() can be NULL after HTMLInputElement::setValueFromRenderer,
which dispatches 'input' event. Also, make a local vairable 'input' a RefPtr just in case.

Also add null-poinetr checks for the host element as SliderThumbElement only weakly holds onto the host element.

Test: fast/forms/range/range-type-change-oninput.html

* html/shadow/SliderThumbElement.cpp:
(WebCore::SliderThumbElement::isDisabledFormControl):
(WebCore::SliderThumbElement::matchesReadOnlyPseudoClass):
(WebCore::SliderThumbElement::matchesReadWritePseudoClass):
(WebCore::SliderThumbElement::setPositionFromPoint):
(WebCore::SliderThumbElement::hostInput):

LayoutTests:

Add a regresion test from https://chromium.googlesource.com/chromium/blink/+/99afc9b55ce176b4f5fe053070e19dbebc1891a5

* fast/forms/range/range-type-change-oninput-expected.txt: Added.
* fast/forms/range/range-type-change-oninput.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@154308 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/fast/forms/range/range-type-change-oninput-expected.txt [new file with mode: 0644]
LayoutTests/fast/forms/range/range-type-change-oninput.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/html/shadow/SliderThumbElement.cpp

index a72100f20dfd03a4e358ad796332ca669393aebb..b6949489c4a4a6176f6de8c41626bcd87d45047a 100644 (file)
@@ -1,3 +1,14 @@
+2013-08-19  Ryosuke Niwa  <rniwa@webkit.org>
+
+        <https://webkit.org/b/119930> input[type=range]: Fix a crash by changing input type in 'input' event handler
+
+        Reviewed by Kent Tamura.
+
+        Add a regresion test from https://chromium.googlesource.com/chromium/blink/+/99afc9b55ce176b4f5fe053070e19dbebc1891a5
+
+        * fast/forms/range/range-type-change-oninput-expected.txt: Added.
+        * fast/forms/range/range-type-change-oninput.html: Added.
+
 2013-08-19  Alexey Proskuryakov  <ap@apple.com>
 
         https://bugs.webkit.org/show_bug.cgi?id=120028
diff --git a/LayoutTests/fast/forms/range/range-type-change-oninput-expected.txt b/LayoutTests/fast/forms/range/range-type-change-oninput-expected.txt
new file mode 100644 (file)
index 0000000..93ab568
--- /dev/null
@@ -0,0 +1,5 @@
+PASS if not crashed.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/forms/range/range-type-change-oninput.html b/LayoutTests/fast/forms/range/range-type-change-oninput.html
new file mode 100644 (file)
index 0000000..590b36f
--- /dev/null
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src="../../js/resources/js-test-pre.js"></script>
+<script src="../resources/common.js"></script>
+<input type="range" value="0" oninput="this.type = 'text';">
+<script>
+if (!window.eventSender) {
+    debug('Manual test instruction: Click on the slider.');
+} else {
+    clickElement(document.querySelector('input'));
+    testPassed('if not crashed.');
+}
+</script>
+<script src="../../js/resources/js-test-post.js"></script>
+</body>
+</html>
index b1050fad3dba1f95a45fd49e4abe0cc6a7e2a318..b5b8f0f0a44425a601bc4511544c13cc0bf3378e 100644 (file)
@@ -1,3 +1,25 @@
+2013-08-19  Ryosuke Niwa  <rniwa@webkit.org>
+
+        <https://webkit.org/b/119930> input[type=range]: Fix a crash by changing input type in 'input' event handler
+
+        Reviewed by Kent Tamura.
+
+        Merge https://chromium.googlesource.com/chromium/blink/+/99afc9b55ce176b4f5fe053070e19dbebc1891a5
+
+        In SliderThumbElement::setPositionFromPoint, renderer() can be NULL after HTMLInputElement::setValueFromRenderer,
+        which dispatches 'input' event. Also, make a local vairable 'input' a RefPtr just in case.
+
+        Also add null-poinetr checks for the host element as SliderThumbElement only weakly holds onto the host element.
+
+        Test: fast/forms/range/range-type-change-oninput.html
+
+        * html/shadow/SliderThumbElement.cpp:
+        (WebCore::SliderThumbElement::isDisabledFormControl):
+        (WebCore::SliderThumbElement::matchesReadOnlyPseudoClass):
+        (WebCore::SliderThumbElement::matchesReadWritePseudoClass):
+        (WebCore::SliderThumbElement::setPositionFromPoint):
+        (WebCore::SliderThumbElement::hostInput):
+
 2013-08-19  Alexey Proskuryakov  <ap@apple.com>
 
         https://bugs.webkit.org/show_bug.cgi?id=120028
index b68929ad18bea244dd37cb9830bfaded3252e311..2d0a7e18191f49da7c9fc241732498601df9c713 100644 (file)
@@ -229,17 +229,20 @@ RenderObject* SliderThumbElement::createRenderer(RenderArena* arena, RenderStyle
 
 bool SliderThumbElement::isDisabledFormControl() const
 {
-    return hostInput()->isDisabledFormControl();
+    HTMLInputElement* input = hostInput();
+    return !input || input->isDisabledFormControl();
 }
 
 bool SliderThumbElement::matchesReadOnlyPseudoClass() const
 {
-    return hostInput()->matchesReadOnlyPseudoClass();
+    HTMLInputElement* input = hostInput();
+    return input && input->matchesReadOnlyPseudoClass();
 }
 
 bool SliderThumbElement::matchesReadWritePseudoClass() const
 {
-    return hostInput()->matchesReadWritePseudoClass();
+    HTMLInputElement* input = hostInput();
+    return input && input->matchesReadWritePseudoClass();
 }
 
 Element* SliderThumbElement::focusDelegate()
@@ -255,15 +258,15 @@ void SliderThumbElement::dragFrom(const LayoutPoint& point)
 
 void SliderThumbElement::setPositionFromPoint(const LayoutPoint& point)
 {
-    HTMLInputElement* input = hostInput();
-    HTMLElement* trackElement = sliderTrackElementOf(input);
+    RefPtr<HTMLInputElement> input(hostInput());
+    HTMLElement* trackElement = sliderTrackElementOf(input.get());
 
     if (!input->renderer() || !renderBox() || !trackElement->renderBox())
         return;
 
     input->setTextAsOfLastFormControlChangeEvent(input->value());
     LayoutPoint offset = roundedLayoutPoint(input->renderer()->absoluteToLocal(point, UseTransforms));
-    bool isVertical = hasVerticalAppearance(input);
+    bool isVertical = hasVerticalAppearance(input.get());
     bool isLeftToRightDirection = renderBox()->style()->isLeftToRightDirection();
     LayoutUnit trackSize;
     LayoutUnit position;
@@ -312,7 +315,8 @@ void SliderThumbElement::setPositionFromPoint(const LayoutPoint& point)
 
     // FIXME: This is no longer being set from renderer. Consider updating the method name.
     input->setValueFromRenderer(valueString);
-    renderer()->setNeedsLayout(true);
+    if (renderer())
+        renderer()->setNeedsLayout(true);
     input->dispatchFormControlChangeEvent();
 }
 
@@ -404,7 +408,8 @@ HTMLInputElement* SliderThumbElement::hostInput() const
 {
     // Only HTMLInputElement creates SliderThumbElement instances as its shadow nodes.
     // So, shadowHost() must be an HTMLInputElement.
-    return shadowHost()->toInputElement();
+    Element* host = shadowHost();
+    return host ? host->toInputElement() : 0;
 }
 
 static const AtomicString& sliderThumbShadowPseudoId()