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.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@105441 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/editing/TypingCommand.cpp b/Source/WebCore/editing/TypingCommand.cpp
index 1ee0033..4101ecf 100644
--- a/Source/WebCore/editing/TypingCommand.cpp
+++ b/Source/WebCore/editing/TypingCommand.cpp
@@ -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();
}