Title: [105441] trunk
Revision
105441
Author
[email protected]
Date
2012-01-19 13:41:08 -0800 (Thu, 19 Jan 2012)

Log Message

Crash in CompositeEditCommand::ensureComposition
https://bugs.webkit.org/show_bug.cgi?id=76207

Reviewed by Chang Shu.

Source/WebCore: 

The crash was caused by TypingCommand not kept alive when new editing commands are executed
during adding more typings to the open last typing command since m_lastEditCommand is replaced
by the new command. Fixed the bug by keeping them alive a little longer with RefPtr.

Test: editing/execCommand/editing-command-while-executing-typing-command-crash.html

* editing/FrameSelection.cpp:
(WebCore::shouldStopBlinkingDueToTypingCommand):
(WebCore::FrameSelection::updateAppearance):
* editing/TypingCommand.cpp:
(WebCore::TypingCommand::deleteSelection):
(WebCore::TypingCommand::deleteKeyPressed):
(WebCore::TypingCommand::forwardDeleteKeyPressed):
(WebCore::TypingCommand::insertText):
(WebCore::TypingCommand::insertLineBreak):
(WebCore::TypingCommand::insertParagraphSeparatorInQuotedContent):
(WebCore::TypingCommand::insertParagraphSeparator):
(WebCore::TypingCommand::lastTypingCommandIfStillOpenForTyping):
(WebCore::TypingCommand::closeTyping):
* editing/TypingCommand.h:

LayoutTests: 

Add a regression test.

* editing/execCommand/editing-command-while-executing-typing-command-crash-expected.txt: Added.
* editing/execCommand/editing-command-while-executing-typing-command-crash.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (105440 => 105441)


--- trunk/LayoutTests/ChangeLog	2012-01-19 21:16:46 UTC (rev 105440)
+++ trunk/LayoutTests/ChangeLog	2012-01-19 21:41:08 UTC (rev 105441)
@@ -1,3 +1,15 @@
+2012-01-13  Ryosuke Niwa  <[email protected]>
+
+        Crash in CompositeEditCommand::ensureComposition
+        https://bugs.webkit.org/show_bug.cgi?id=76207
+
+        Reviewed by Chang Shu.
+
+        Add a regression test.
+
+        * editing/execCommand/editing-command-while-executing-typing-command-crash-expected.txt: Added.
+        * editing/execCommand/editing-command-while-executing-typing-command-crash.html: Added.
+
 2012-01-19  Eric Carlson  <[email protected]>
 
         https://bugs.webkit.org/show_bug.cgi?id=75192

Added: trunk/LayoutTests/editing/execCommand/editing-command-while-executing-typing-command-crash-expected.txt (0 => 105441)


--- trunk/LayoutTests/editing/execCommand/editing-command-while-executing-typing-command-crash-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/editing/execCommand/editing-command-while-executing-typing-command-crash-expected.txt	2012-01-19 21:41:08 UTC (rev 105441)
@@ -0,0 +1,2 @@
+This tests executing an editing command while executing a typing command.
+PASS

Added: trunk/LayoutTests/editing/execCommand/editing-command-while-executing-typing-command-crash.html (0 => 105441)


--- trunk/LayoutTests/editing/execCommand/editing-command-while-executing-typing-command-crash.html	                        (rev 0)
+++ trunk/LayoutTests/editing/execCommand/editing-command-while-executing-typing-command-crash.html	2012-01-19 21:41:08 UTC (rev 105441)
@@ -0,0 +1,18 @@
+<script>
+window._onload_ = function() {
+    if (window.layoutTestController)
+        layoutTestController.dumpAsText();
+
+    document.execCommand("selectall", false);
+    document.designMode="on";
+    document.execCommand("insertparagraph", false);
+    document.execCommand("InsertText", false);
+
+    document.firstChild.appendChild(document.createElement('body'));
+    document.body.innerText = "This tests executing an editing command while executing a typing command.\nPASS";
+};
+
+document.addEventListener("DOMNodeRemovedFromDocument",
+    function() { document.execCommand("JustifyNone", false); },true);
+
+</script>

Modified: trunk/Source/WebCore/ChangeLog (105440 => 105441)


--- trunk/Source/WebCore/ChangeLog	2012-01-19 21:16:46 UTC (rev 105440)
+++ trunk/Source/WebCore/ChangeLog	2012-01-19 21:41:08 UTC (rev 105441)
@@ -1,3 +1,31 @@
+2012-01-13  Ryosuke Niwa  <[email protected]>
+
+        Crash in CompositeEditCommand::ensureComposition
+        https://bugs.webkit.org/show_bug.cgi?id=76207
+
+        Reviewed by Chang Shu.
+
+        The crash was caused by TypingCommand not kept alive when new editing commands are executed
+        during adding more typings to the open last typing command since m_lastEditCommand is replaced
+        by the new command. Fixed the bug by keeping them alive a little longer with RefPtr.
+
+        Test: editing/execCommand/editing-command-while-executing-typing-command-crash.html
+
+        * editing/FrameSelection.cpp:
+        (WebCore::shouldStopBlinkingDueToTypingCommand):
+        (WebCore::FrameSelection::updateAppearance):
+        * editing/TypingCommand.cpp:
+        (WebCore::TypingCommand::deleteSelection):
+        (WebCore::TypingCommand::deleteKeyPressed):
+        (WebCore::TypingCommand::forwardDeleteKeyPressed):
+        (WebCore::TypingCommand::insertText):
+        (WebCore::TypingCommand::insertLineBreak):
+        (WebCore::TypingCommand::insertParagraphSeparatorInQuotedContent):
+        (WebCore::TypingCommand::insertParagraphSeparator):
+        (WebCore::TypingCommand::lastTypingCommandIfStillOpenForTyping):
+        (WebCore::TypingCommand::closeTyping):
+        * editing/TypingCommand.h:
+
 2012-01-19  Andreas Kling  <[email protected]>
 
         Unreviewed debug build fix.

Modified: trunk/Source/WebCore/editing/FrameSelection.cpp (105440 => 105441)


--- trunk/Source/WebCore/editing/FrameSelection.cpp	2012-01-19 21:16:46 UTC (rev 105440)
+++ trunk/Source/WebCore/editing/FrameSelection.cpp	2012-01-19 21:41:08 UTC (rev 105441)
@@ -1654,6 +1654,11 @@
     return m_focused && m_frame->page() && m_frame->page()->focusController()->isActive();
 }
 
+inline static bool shouldStopBlinkingDueToTypingCommand(Frame* frame)
+{
+    return frame->editor()->lastEditCommand() && frame->editor()->lastEditCommand()->shouldStopCaretBlinking();
+}
+
 void FrameSelection::updateAppearance()
 {
 #if ENABLE(TEXT_CARET)
@@ -1661,13 +1666,10 @@
 
     bool caretBrowsing = m_frame->settings() && m_frame->settings()->caretBrowsingEnabled();
     bool shouldBlink = caretIsVisible() && isCaret() && (isContentEditable() || caretBrowsing);
-    
-    CompositeEditCommand* lastEditCommand = m_frame ? m_frame->editor()->lastEditCommand() : 0;
-    bool shouldStopBlinkingDueToTypingCommand = lastEditCommand && lastEditCommand->shouldStopCaretBlinking();
 
     // If the caret moved, stop the blink timer so we can restart with a
     // black caret in the new location.
-    if (caretRectChanged || !shouldBlink || shouldStopBlinkingDueToTypingCommand)
+    if (caretRectChanged || !shouldBlink || shouldStopBlinkingDueToTypingCommand(m_frame))
         m_caretBlinkTimer.stop();
 
     // Start blinking with a black caret. Be sure not to restart if we're

Modified: trunk/Source/WebCore/editing/TypingCommand.cpp (105440 => 105441)


--- trunk/Source/WebCore/editing/TypingCommand.cpp	2012-01-19 21:16:46 UTC (rev 105440)
+++ trunk/Source/WebCore/editing/TypingCommand.cpp	2012-01-19 21:41:08 UTC (rev 105441)
@@ -87,7 +87,7 @@
     if (!frame->selection()->isRange())
         return;
 
-    if (TypingCommand* lastTypingCommand = lastTypingCommandIfStillOpenForTyping(frame)) {
+    if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(frame)) {
         lastTypingCommand->setShouldPreventSpellChecking(options & PreventSpellChecking);
         lastTypingCommand->deleteSelection(options & SmartDelete);
         return;
@@ -100,8 +100,8 @@
 {
     ASSERT(document);
     if (granularity == CharacterGranularity) {
-        if (TypingCommand* lastTypingCommand = lastTypingCommandIfStillOpenForTyping(document->frame())) {
-            updateSelectionIfDifferentFromCurrentSelection(lastTypingCommand, document->frame());
+        if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(document->frame())) {
+            updateSelectionIfDifferentFromCurrentSelection(lastTypingCommand.get(), document->frame());
             lastTypingCommand->setShouldPreventSpellChecking(options & PreventSpellChecking);
             lastTypingCommand->deleteKeyPressed(granularity, options & KillRing);
             return;
@@ -117,8 +117,8 @@
     ASSERT(document);
     Frame* frame = document->frame();
     if (granularity == CharacterGranularity) {
-        if (TypingCommand* lastTypingCommand = lastTypingCommandIfStillOpenForTyping(frame)) {
-            updateSelectionIfDifferentFromCurrentSelection(lastTypingCommand, frame);
+        if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(frame)) {
+            updateSelectionIfDifferentFromCurrentSelection(lastTypingCommand.get(), frame);
             lastTypingCommand->setShouldPreventSpellChecking(options & PreventSpellChecking);
             lastTypingCommand->forwardDeleteKeyPressed(granularity, options & KillRing);
             return;
@@ -176,7 +176,7 @@
     // Set the starting and ending selection appropriately if we are using a selection
     // that is different from the current selection.  In the future, we should change EditCommand
     // to deal with custom selections in a general way that can be used by all of the commands.
-    if (TypingCommand* lastTypingCommand = lastTypingCommandIfStillOpenForTyping(frame.get())) {
+    if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(frame.get())) {
         if (lastTypingCommand->endingSelection() != selectionForInsertion) {
             lastTypingCommand->setStartingSelection(selectionForInsertion);
             lastTypingCommand->setEndingSelection(selectionForInsertion);
@@ -204,7 +204,7 @@
 void TypingCommand::insertLineBreak(Document *document, Options options)
 {
     ASSERT(document);
-    if (TypingCommand* lastTypingCommand = lastTypingCommandIfStillOpenForTyping(document->frame())) {
+    if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(document->frame())) {
         lastTypingCommand->setShouldRetainAutocorrectionIndicator(options & RetainAutocorrectionIndicator);
         lastTypingCommand->insertLineBreak();
         return;
@@ -216,7 +216,7 @@
 void TypingCommand::insertParagraphSeparatorInQuotedContent(Document *document)
 {
     ASSERT(document);
-    if (TypingCommand* lastTypingCommand = lastTypingCommandIfStillOpenForTyping(document->frame())) {
+    if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(document->frame())) {
         lastTypingCommand->insertParagraphSeparatorInQuotedContent();
         return;
     }
@@ -227,7 +227,7 @@
 void TypingCommand::insertParagraphSeparator(Document *document, Options options)
 {
     ASSERT(document);
-    if (TypingCommand* lastTypingCommand = lastTypingCommandIfStillOpenForTyping(document->frame())) {
+    if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(document->frame())) {
         lastTypingCommand->setShouldRetainAutocorrectionIndicator(options & RetainAutocorrectionIndicator);
         lastTypingCommand->insertParagraphSeparator();
         return;
@@ -236,20 +236,20 @@
     applyCommand(TypingCommand::create(document, InsertParagraphSeparator, "", options));
 }
 
-TypingCommand* TypingCommand::lastTypingCommandIfStillOpenForTyping(Frame* frame)
+PassRefPtr<TypingCommand> TypingCommand::lastTypingCommandIfStillOpenForTyping(Frame* frame)
 {
     ASSERT(frame);
 
-    CompositeEditCommand* lastEditCommand = frame->editor()->lastEditCommand();
-    if (!lastEditCommand || !lastEditCommand->isTypingCommand() || !static_cast<TypingCommand*>(lastEditCommand)->isOpenForMoreTyping())
+    RefPtr<CompositeEditCommand> lastEditCommand = frame->editor()->lastEditCommand();
+    if (!lastEditCommand || !lastEditCommand->isTypingCommand() || !static_cast<TypingCommand*>(lastEditCommand.get())->isOpenForMoreTyping())
         return 0;
 
-    return static_cast<TypingCommand*>(lastEditCommand);
+    return static_cast<TypingCommand*>(lastEditCommand.get());
 }
 
 void TypingCommand::closeTyping(Frame* frame)
 {
-    if (TypingCommand* lastTypingCommand = lastTypingCommandIfStillOpenForTyping(frame))
+    if (RefPtr<TypingCommand> lastTypingCommand = lastTypingCommandIfStillOpenForTyping(frame))
         lastTypingCommand->closeTyping();
 }
 

Modified: trunk/Source/WebCore/editing/TypingCommand.h (105440 => 105441)


--- trunk/Source/WebCore/editing/TypingCommand.h	2012-01-19 21:16:46 UTC (rev 105440)
+++ trunk/Source/WebCore/editing/TypingCommand.h	2012-01-19 21:41:08 UTC (rev 105441)
@@ -95,7 +95,7 @@
     bool isOpenForMoreTyping() const { return m_openForMoreTyping; }
     void closeTyping() { m_openForMoreTyping = false; }
 
-    static TypingCommand* lastTypingCommandIfStillOpenForTyping(Frame*);
+    static PassRefPtr<TypingCommand> lastTypingCommandIfStillOpenForTyping(Frame*);
 
     virtual void doApply();
     virtual EditAction editingAction() const;
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to