[SCM] WebKit Debian packaging branch, webkit-1.3, updated. upstream/1.3.7-4207-g178b198

satish at chromium.org satish at chromium.org
Sun Feb 20 22:58:15 UTC 2011


The following commit has been merged in the webkit-1.3 branch:
commit d12b0054b3df1e59dee3813622b89ee36e420181
Author: satish at chromium.org <satish at chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Fri Jan 14 20:39:09 2011 +0000

    2011-01-12  Satish Sampath  <satish at chromium.org>
    
            Reviewed by Dimitri Glazkov.
    
            Fix a crash when accessing speech input from script.
            https://bugs.webkit.org/show_bug.cgi?id=52325
    
            Added a layout test to check enabling/disabling speech input from script.
    
            * fast/speech/speech-input-scripting-expected.txt: Added.
            * fast/speech/speech-input-scripting.html: Added.
    2011-01-12  Satish Sampath  <satish at chromium.org>
    
            Reviewed by Dimitri Glazkov.
    
            Fix a crash when accessing speech input from script.
            https://bugs.webkit.org/show_bug.cgi?id=52325
    
            Test: fast/speech/speech-input-scripting.html
    
            * html/HTMLInputElement.cpp:
            (WebCore::HTMLInputElement::parseMappedAttribute): Recreate renderer when speech input is enabled/disabled.
            * rendering/RenderTextControlSingleLine.cpp: Remove unused code.
            * rendering/RenderTextControlSingleLine.h:
            * rendering/TextControlInnerElements.cpp: Take self references before firing events and check for renderer validity after.
            (WebCore::InputFieldSpeechButtonElement::defaultEventHandler):
            (WebCore::InputFieldSpeechButtonElement::setRecognitionResult):
            (WebCore::InputFieldSpeechButtonElement::detach):
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@75811 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 8b507c2..a1a2dc4 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,15 @@
+2011-01-12  Satish Sampath  <satish at chromium.org>
+
+        Reviewed by Dimitri Glazkov.
+
+        Fix a crash when accessing speech input from script.
+        https://bugs.webkit.org/show_bug.cgi?id=52325
+
+        Added a layout test to check enabling/disabling speech input from script.
+
+        * fast/speech/speech-input-scripting-expected.txt: Added.
+        * fast/speech/speech-input-scripting.html: Added.
+
 2011-01-14  Abhishek Arya  <inferno at chromium.org>
 
         Reviewed by David Hyatt.
diff --git a/LayoutTests/fast/speech/speech-input-scripting-expected.txt b/LayoutTests/fast/speech/speech-input-scripting-expected.txt
new file mode 100644
index 0000000..428d359
--- /dev/null
+++ b/LayoutTests/fast/speech/speech-input-scripting-expected.txt
@@ -0,0 +1,13 @@
+Tests for enabling and disabling speech input via script.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS document.getElementById("speechInput").value is "Pictures of the moon"
+PASS document.getElementById("speechInput").value is "Pictures of the moon"
+PASS document.getElementById("speechInput").value is "Pictures of the moon"
+PASS document.getElementById("speechInput").value is "Pictures of the moon"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+   
diff --git a/LayoutTests/fast/speech/speech-input-scripting.html b/LayoutTests/fast/speech/speech-input-scripting.html
new file mode 100644
index 0000000..dd887a1
--- /dev/null
+++ b/LayoutTests/fast/speech/speech-input-scripting.html
@@ -0,0 +1,79 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="stylesheet" href="../js/resources/js-test-style.css">
+<script src="../js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script type="text/javascript">
+description('Tests for enabling and disabling speech input via script.');
+
+var speechInputCreatedByScript = false;
+
+function onWebkitSpeechChange() {
+    shouldBeEqualToString('document.getElementById("speechInput").value', 'Pictures of the moon');
+
+    // Disable speech input now, just to verify this doesn't result in any crashes.
+    var input = document.getElementById('speechInput');
+    input.removeAttribute('x-webkit-speech');
+
+    // If the test has only been done with a type='text' field, repeat the same with a
+    // type='search' field since that takes a slightly different code path.
+    if (input.type != 'search') {
+        input.type = 'search';
+        testSetAttributeAndClick();
+        return;
+    }
+
+    // If the test has only been done with a statically declared element, now repeat the same
+    // with a dynamically created/inserted element.
+    if (!speechInputCreatedByScript) {
+        document.body.removeChild(input);
+        input = document.createElement('input');
+        input.id = 'speechInput';
+        document.body.appendChild(input);
+        speechInputCreatedByScript = true;
+        testSetAttributeAndClick();
+        return;
+    }
+
+    finishJSTest();
+}
+
+function testSetAttributeAndClick() {
+    // Enable speech input and test that clicking the speech button fills in mock speech-recognized text.
+    var input = document.getElementById('speechInput');
+    input.setAttribute('x-webkit-speech', '');
+    input.addEventListener('webkitspeechchange', onWebkitSpeechChange);
+
+    var x = input.offsetLeft + input.offsetWidth - 8;
+    var y = input.offsetTop + input.offsetHeight / 2;
+    eventSender.mouseMoveTo(x, y);
+    eventSender.mouseDown();
+    eventSender.mouseUp();
+}
+
+function run() {
+    if (!window.layoutTestController || !window.eventSender)
+        return;
+
+    layoutTestController.addMockSpeechInputResult('Pictures of the moon', 1.0, '');
+
+    // Try disabling speech with an input tag which has the attribute set in HTML and
+    // verify that doesn't result in any crashes.
+    document.getElementById('inputWithAttribute').removeAttribute('x-webkit-speech');
+
+    testSetAttributeAndClick();
+}
+
+window.onload = run;
+window.jsTestIsAsync = true;
+window.successfullyParsed = true;
+</script>
+<script src="../js/resources/js-test-post.js"></script>
+<input id='speechInput'>
+<input id='inputWithAttribute' x-webkit-speech>
+</body>
+</html>
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index dbe5b0a..440990e 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,21 @@
+2011-01-12  Satish Sampath  <satish at chromium.org>
+
+        Reviewed by Dimitri Glazkov.
+
+        Fix a crash when accessing speech input from script.
+        https://bugs.webkit.org/show_bug.cgi?id=52325
+
+        Test: fast/speech/speech-input-scripting.html
+
+        * html/HTMLInputElement.cpp:
+        (WebCore::HTMLInputElement::parseMappedAttribute): Recreate renderer when speech input is enabled/disabled.
+        * rendering/RenderTextControlSingleLine.cpp: Remove unused code.
+        * rendering/RenderTextControlSingleLine.h:
+        * rendering/TextControlInnerElements.cpp: Take self references before firing events and check for renderer validity after.
+        (WebCore::InputFieldSpeechButtonElement::defaultEventHandler):
+        (WebCore::InputFieldSpeechButtonElement::setRecognitionResult):
+        (WebCore::InputFieldSpeechButtonElement::detach):
+
 2011-01-14  Abhishek Arya  <inferno at chromium.org>
 
         Reviewed by David Hyatt.
diff --git a/Source/WebCore/html/HTMLInputElement.cpp b/Source/WebCore/html/HTMLInputElement.cpp
index 7d2a3c5..a1e7d8b 100644
--- a/Source/WebCore/html/HTMLInputElement.cpp
+++ b/Source/WebCore/html/HTMLInputElement.cpp
@@ -631,9 +631,14 @@ void HTMLInputElement::parseMappedAttribute(Attribute* attr)
 #endif
 #if ENABLE(INPUT_SPEECH)
     else if (attr->name() == webkitspeechAttr) {
-      if (renderer())
-          toRenderTextControlSingleLine(renderer())->speechAttributeChanged();
-      setNeedsStyleRecalc();
+        if (renderer()) {
+            // This renderer and its children have quite different layouts and styles depending on
+            // whether the speech button is visible or not. So we reset the whole thing and recreate
+            // to get the right styles and layout.
+            detach();
+            attach();
+        }
+        setNeedsStyleRecalc();
     } else if (attr->name() == onwebkitspeechchangeAttr)
         setAttributeEventListener(eventNames().webkitspeechchangeEvent, createAttributeEventListener(this, attr));
 #endif
diff --git a/Source/WebCore/platform/mock/SpeechInputClientMock.cpp b/Source/WebCore/platform/mock/SpeechInputClientMock.cpp
index 16f2825..16a7c76 100644
--- a/Source/WebCore/platform/mock/SpeechInputClientMock.cpp
+++ b/Source/WebCore/platform/mock/SpeechInputClientMock.cpp
@@ -72,8 +72,8 @@ void SpeechInputClientMock::stopRecording(int requestId)
 
 void SpeechInputClientMock::cancelRecognition(int requestId)
 {
-    ASSERT(requestId == m_requestId);
     if (m_timer.isActive()) {
+        ASSERT(requestId == m_requestId);
         m_timer.stop();
         m_recording = false;
         m_listener->didCompleteRecognition(m_requestId);
@@ -107,15 +107,20 @@ void SpeechInputClientMock::timerFired(WebCore::Timer<SpeechInputClientMock>*)
     } else {
         bool noResultsFound = false;
 
+        // We take a copy of the requestId here so that if scripts destroyed the input element
+        // inside one of the callbacks below, we'll still know what this session's requestId was.
+        int requestId = m_requestId;
+        m_requestId = 0;
+
         // Empty language case must be handled separately to avoid problems with HashMap and empty keys.
         if (m_language.isEmpty()) {
             if (!m_resultsForEmptyLanguage.isEmpty())
-                m_listener->setRecognitionResult(m_requestId, m_resultsForEmptyLanguage);
+                m_listener->setRecognitionResult(requestId, m_resultsForEmptyLanguage);
             else
                 noResultsFound = true;
         } else {
             if (m_recognitionResults.contains(m_language))
-                m_listener->setRecognitionResult(m_requestId, m_recognitionResults.get(m_language));
+                m_listener->setRecognitionResult(requestId, m_recognitionResults.get(m_language));
             else
                 noResultsFound = true;
         }
@@ -128,11 +133,10 @@ void SpeechInputClientMock::timerFired(WebCore::Timer<SpeechInputClientMock>*)
             error.append("'");
             SpeechInputResultArray results;
             results.append(SpeechInputResult::create(error, 1.0));
-            m_listener->setRecognitionResult(m_requestId, results);
+            m_listener->setRecognitionResult(requestId, results);
         }
 
-        m_listener->didCompleteRecognition(m_requestId);
-        m_requestId = 0;
+        m_listener->didCompleteRecognition(requestId);
     }
 }
 
diff --git a/Source/WebCore/rendering/RenderTextControlSingleLine.cpp b/Source/WebCore/rendering/RenderTextControlSingleLine.cpp
index c815be1..c850321 100644
--- a/Source/WebCore/rendering/RenderTextControlSingleLine.cpp
+++ b/Source/WebCore/rendering/RenderTextControlSingleLine.cpp
@@ -667,21 +667,6 @@ void RenderTextControlSingleLine::createSubtreeIfNeeded()
     }
 }
 
-#if ENABLE(INPUT_SPEECH)
-void RenderTextControlSingleLine::speechAttributeChanged()
-{
-    // The inner text element of this renderer has different styles depending on whether the
-    // speech button is visible or not. So when the speech attribute changes, we reset the
-    // whole thing and recreate to get the right styles and layout.
-    if (m_speechButton)
-        m_speechButton->detach();
-    setChildrenInline(true);
-    RenderStyle* parentStyle = m_innerBlock ? m_innerBlock->renderer()->style() : style();
-    setStyle(createInnerTextStyle(parentStyle));
-    updateFromElement();
-}
-#endif
-
 void RenderTextControlSingleLine::updateFromElement()
 {
     createSubtreeIfNeeded();
diff --git a/Source/WebCore/rendering/RenderTextControlSingleLine.h b/Source/WebCore/rendering/RenderTextControlSingleLine.h
index 51509c0..16ce1e4 100644
--- a/Source/WebCore/rendering/RenderTextControlSingleLine.h
+++ b/Source/WebCore/rendering/RenderTextControlSingleLine.h
@@ -59,10 +59,6 @@ public:
     // Decoration width outside of the text field.
     int decorationWidthRight() const;
 
-#if ENABLE(INPUT_SPEECH)
-    void speechAttributeChanged();
-#endif
-
 private:
     int preferredDecorationWidthRight() const;
     virtual bool hasControlClip() const;
diff --git a/Source/WebCore/rendering/TextControlInnerElements.cpp b/Source/WebCore/rendering/TextControlInnerElements.cpp
index d6fc7aa..5b8712d 100644
--- a/Source/WebCore/rendering/TextControlInnerElements.cpp
+++ b/Source/WebCore/rendering/TextControlInnerElements.cpp
@@ -383,7 +383,7 @@ inline InputFieldSpeechButtonElement::InputFieldSpeechButtonElement(HTMLElement*
 InputFieldSpeechButtonElement::~InputFieldSpeechButtonElement()
 {
     SpeechInput* speech = speechInput();
-    if (speech)  { // Could be null when page is unloading.
+    if (speech && m_listenerId)  { // Could be null when page is unloading.
         if (m_state != Idle)
             speech->cancelRecognition(m_listenerId);
         speech->unregisterListener(m_listenerId);
@@ -416,6 +416,7 @@ void InputFieldSpeechButtonElement::defaultEventHandler(Event* event)
         // remove the input element from DOM. To make sure it remains valid until we finish our work
         // here, we take a temporary reference.
         RefPtr<HTMLInputElement> holdRef(input);
+        RefPtr<InputFieldSpeechButtonElement> holdRefButton(this);
         input->focus();
         input->select();
         event->setDefaultHandled();
@@ -482,9 +483,14 @@ void InputFieldSpeechButtonElement::setRecognitionResult(int, const SpeechInputR
     // remove the input element from DOM. To make sure it remains valid until we finish our work
     // here, we take a temporary reference.
     RefPtr<HTMLInputElement> holdRef(input);
+    RefPtr<InputFieldSpeechButtonElement> holdRefButton(this);
     input->setValue(results.isEmpty() ? "" : results[0]->utterance());
     input->dispatchEvent(SpeechInputEvent::create(eventNames().webkitspeechchangeEvent, results));
-    renderer()->repaint();
+
+    // Check before accessing the renderer as the above event could have potentially turned off
+    // speech in the input element, hence removing this button and renderer from the hierarchy.
+    if (renderer())
+        renderer()->repaint();
 }
 
 void InputFieldSpeechButtonElement::detach()
@@ -494,8 +500,12 @@ void InputFieldSpeechButtonElement::detach()
             frame->eventHandler()->setCapturingMouseEventsNode(0);
     }
 
-    if (m_state != Idle)
-      speechInput()->cancelRecognition(m_listenerId);
+    if (m_listenerId) {
+        if (m_state != Idle)
+            speechInput()->cancelRecognition(m_listenerId);
+        speechInput()->unregisterListener(m_listenerId);
+        m_listenerId = 0;
+    }
 
     TextControlInnerElement::detach();
 }

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list