WebKit Bugzilla
Attachment 358427 Details for
Bug 193111
: [Cocoa] Allow the page to add to the platform undo stack via UndoManager.addItem()
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
WIP (with tests)
bug-193111-20190104204522.patch (text/plain), 62.94 KB, created by
Wenson Hsieh
on 2019-01-04 20:45:23 PST
(
hide
)
Description:
WIP (with tests)
Filename:
MIME Type:
Creator:
Wenson Hsieh
Created:
2019-01-04 20:45:23 PST
Size:
62.94 KB
patch
obsolete
>Subversion Revision: 239627 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 2477a378bc95289e4fa3264ec73312e58d680b28..d719aca747dff854538c79ddc16a3697a0ea5aac 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,46 @@ >+2019-01-04 Wenson Hsieh <wenson_hsieh@apple.com> >+ >+ [Cocoa] Allow the page to add to the platform undo stack via UndoManager.addItem() >+ https://bugs.webkit.org/show_bug.cgi?id=193111 >+ <rdar://problem/44807048> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Tests: editing/undo/UndoManager/undo-manager-add-item.html >+ editing/undo/UndoManager/undo-manager-prevent-undo-redo.html >+ editing/undo/UndoManager/undo-manager-set-item-label.html >+ >+ * Sources.txt: >+ * WebCore.xcodeproj/project.pbxproj: >+ * editing/CompositeEditCommand.h: >+ * editing/CustomUndoStep.cpp: Added. >+ (WebCore::CustomUndoStep::CustomUndoStep): >+ (WebCore::CustomUndoStep::unapply): >+ (WebCore::CustomUndoStep::reapply): >+ (WebCore::CustomUndoStep::customUndoLabel const): >+ * editing/CustomUndoStep.h: Copied from Source/WebCore/page/UndoManager.cpp. >+ * editing/EditAction.cpp: >+ (WebCore::nameForUndoRedo): >+ * editing/EditAction.h: >+ * editing/EditingStyle.cpp: >+ * editing/Editor.cpp: >+ (WebCore::Editor::willUnapplyEditing const): >+ (WebCore::Editor::willReapplyEditing const): >+ (WebCore::Editor::unappliedEditing): >+ (WebCore::Editor::reappliedEditing): >+ (WebCore::Editor::registerCustomUndoStep): >+ * editing/Editor.h: >+ * editing/InsertEditableImageCommand.cpp: >+ (WebCore::InsertEditableImageCommand::doApply): >+ * editing/UndoStep.h: >+ * loader/EmptyClients.cpp: >+ (WebCore::EmptyEditorClient::registerUndoStep): >+ (WebCore::EmptyEditorClient::registerRedoStep): >+ * page/EditorClient.h: >+ * page/UndoItem.h: >+ * page/UndoManager.cpp: >+ (WebCore::UndoManager::addItem): >+ > 2019-01-03 Wenson Hsieh <wenson_hsieh@apple.com> > > Introduce IDL files for runtime-enabled UndoManager and UndoItem JavaScript API >diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog >index a4ee73742e05a78973944c44bfa20a185b2700de..2ec2a7ca3b52afa15addb099ff0859fe296f7547 100644 >--- a/Source/WebKit/ChangeLog >+++ b/Source/WebKit/ChangeLog >@@ -1,3 +1,29 @@ >+2019-01-04 Wenson Hsieh <wenson_hsieh@apple.com> >+ >+ [Cocoa] Allow the page to add to the platform undo stack via UndoManager.addItem() >+ https://bugs.webkit.org/show_bug.cgi?id=193111 >+ <rdar://problem/44807048> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * UIProcess/Cocoa/WebViewImpl.mm: >+ (WebKit::WebViewImpl::registerEditCommand): >+ * UIProcess/WebEditCommandProxy.cpp: >+ (WebKit::WebEditCommandProxy::WebEditCommandProxy): >+ (WebKit::WebEditCommandProxy::nameForUndoRedo const): >+ * UIProcess/WebEditCommandProxy.h: >+ (WebKit::WebEditCommandProxy::create): >+ * UIProcess/WebPageProxy.cpp: >+ (WebKit::WebPageProxy::registerEditCommandForUndo): >+ * UIProcess/WebPageProxy.h: >+ * UIProcess/WebPageProxy.messages.in: >+ * UIProcess/ios/PageClientImplIOS.mm: >+ (WebKit::PageClientImpl::registerEditCommand): >+ * WebProcess/WebCoreSupport/WebEditorClient.cpp: >+ (WebKit::WebEditorClient::registerUndoStep): >+ (WebKit::WebEditorClient::registerRedoStep): >+ * WebProcess/WebCoreSupport/WebEditorClient.h: >+ > 2019-01-03 Wenson Hsieh <wenson_hsieh@apple.com> > > Introduce IDL files for runtime-enabled UndoManager and UndoItem JavaScript API >diff --git a/Source/WebKitLegacy/mac/ChangeLog b/Source/WebKitLegacy/mac/ChangeLog >index e6c9f0ac51dd61a8b36776dc1c198ea5731dee6e..8cb2c4417fe9260e89c843f5f824cc72bc509bed 100644 >--- a/Source/WebKitLegacy/mac/ChangeLog >+++ b/Source/WebKitLegacy/mac/ChangeLog >@@ -1,3 +1,19 @@ >+2019-01-04 Wenson Hsieh <wenson_hsieh@apple.com> >+ >+ [Cocoa] Allow the page to add to the platform undo stack via UndoManager.addItem() >+ https://bugs.webkit.org/show_bug.cgi?id=193111 >+ <rdar://problem/44807048> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * WebCoreSupport/WebEditorClient.h: >+ * WebCoreSupport/WebEditorClient.mm: >+ (-[WebUndoStep initWithUndoStep:]): >+ (+[WebUndoStep stepWithUndoStep:]): >+ (WebEditorClient::registerUndoOrRedoStep): >+ (WebEditorClient::registerUndoStep): >+ (WebEditorClient::registerRedoStep): >+ > 2019-01-04 Wenson Hsieh <wenson_hsieh@apple.com> > > [Cocoa] Merge WebEditCommandProxy::nameForEditAction and undoNameForEditAction into a single function >diff --git a/Source/WebCore/Sources.txt b/Source/WebCore/Sources.txt >index cffd5d583016d92670c28500ffc2d863451c6681..56789f37493455196a5701fcbf93812f2e447799 100644 >--- a/Source/WebCore/Sources.txt >+++ b/Source/WebCore/Sources.txt >@@ -909,6 +909,7 @@ editing/BreakBlockquoteCommand.cpp > editing/ChangeListTypeCommand.cpp > editing/CompositeEditCommand.cpp > editing/CreateLinkCommand.cpp >+editing/CustomUndoStep.cpp > editing/DeleteFromTextNodeCommand.cpp > editing/DeleteSelectionCommand.cpp > editing/DictationAlternative.cpp >diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >index dbca0a07add4e1540a0ce9584f37bd58db1e8686..10265a409c666756d4a5ae0641707abd0a7f527b 100644 >--- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj >+++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >@@ -14921,6 +14921,8 @@ > F45C231B1995B73B00A6E2E3 /* AxisScrollSnapOffsets.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AxisScrollSnapOffsets.cpp; sourceTree = "<group>"; }; > F45C231C1995B73B00A6E2E3 /* AxisScrollSnapOffsets.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AxisScrollSnapOffsets.h; sourceTree = "<group>"; }; > F46729251E0DE5AB00ACC3D8 /* ScrollSnapOffsetsInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScrollSnapOffsetsInfo.h; sourceTree = "<group>"; }; >+ F46802D521D983720007DB24 /* CustomUndoStep.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CustomUndoStep.h; sourceTree = "<group>"; }; >+ F46802D621D983720007DB24 /* CustomUndoStep.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CustomUndoStep.cpp; sourceTree = "<group>"; }; > F478755219983AFF0024A287 /* ScrollSnapAnimatorState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScrollSnapAnimatorState.h; sourceTree = "<group>"; }; > F478755319983AFF0024A287 /* ScrollSnapAnimatorState.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ScrollSnapAnimatorState.mm; sourceTree = "<group>"; }; > F47A09CF20A939F600240FAE /* DisabledAdaptations.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DisabledAdaptations.h; sourceTree = "<group>"; }; >@@ -20784,6 +20786,8 @@ > 2DD5A7261EBEE47D009BA597 /* CompositionUnderline.h */, > D0B0556709C6700100307E43 /* CreateLinkCommand.cpp */, > D0B0556609C6700100307E43 /* CreateLinkCommand.h */, >+ F46802D521D983720007DB24 /* CustomUndoStep.h */, >+ F46802D621D983720007DB24 /* CustomUndoStep.cpp */, > 93309D8F099E64910056E581 /* DeleteFromTextNodeCommand.cpp */, > 93309D90099E64910056E581 /* DeleteFromTextNodeCommand.h */, > 93309D91099E64910056E581 /* DeleteSelectionCommand.cpp */, >diff --git a/Source/WebCore/editing/CompositeEditCommand.h b/Source/WebCore/editing/CompositeEditCommand.h >index 2da520fdc4649292dc7bfca20b7d11b118c5da1c..b2fa5d019a463fc6b250a484a2b43967fe2d61f2 100644 >--- a/Source/WebCore/editing/CompositeEditCommand.h >+++ b/Source/WebCore/editing/CompositeEditCommand.h >@@ -88,6 +88,8 @@ public: > private: > EditCommandComposition(Document&, const VisibleSelection& startingSelection, const VisibleSelection& endingSelection, EditAction); > >+ const String& customUndoLabel() const final { return emptyString(); } >+ > RefPtr<Document> m_document; > VisibleSelection m_startingSelection; > VisibleSelection m_endingSelection; >diff --git a/Source/WebCore/editing/CustomUndoStep.cpp b/Source/WebCore/editing/CustomUndoStep.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..b81a34d2b87c41525c24741ba160d090b2e1726c >--- /dev/null >+++ b/Source/WebCore/editing/CustomUndoStep.cpp >@@ -0,0 +1,96 @@ >+/* >+ * Copyright (C) 2019 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' >+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS >+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >+ * THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#include "config.h" >+#include "CustomUndoStep.h" >+ >+#include "Document.h" >+#include "Editor.h" >+#include "Frame.h" >+#include "UndoItem.h" >+#include "UndoManager.h" >+#include "VoidCallback.h" >+ >+namespace WebCore { >+ >+CustomUndoStep::CustomUndoStep(Ref<Document>&& document, Ref<UndoItem>&& undoItem) >+ : m_document(WTFMove(document)) >+ , m_undoItem(WTFMove(undoItem)) >+{ >+} >+ >+void CustomUndoStep::unapply() >+{ >+ Ref<CustomUndoStep> protectedThis(*this); >+ document().updateLayoutIgnorePendingStylesheets(); >+ >+ auto protectedFrame = makeRefPtr(document().frame()); >+ if (!protectedFrame) >+ return; >+ >+ // FIXME: It's currently unclear how beforeinput and input events should be dispatched when unapplying or reapplying custom >+ // edit commands. Should the page be allowed to specify a target in the DOM for undo and redo? For the time being, dispatch >+ // them on the document's active element. >+ auto activeElement = makeRefPtr(document().activeElement()); >+ if (!activeElement) >+ return; >+ >+ if (!protectedFrame->editor().willUnapplyEditing(*this, *activeElement)) >+ return; >+ >+ if (auto handler = item().undoHandler()) >+ handler->handleEvent(); >+ >+ protectedFrame->editor().unappliedEditing(*this, *activeElement); >+} >+ >+void CustomUndoStep::reapply() >+{ >+ Ref<CustomUndoStep> protectedThis(*this); >+ document().updateLayoutIgnorePendingStylesheets(); >+ >+ auto protectedFrame = makeRefPtr(document().frame()); >+ if (!protectedFrame) >+ return; >+ >+ auto activeElement = makeRefPtr(document().activeElement()); >+ if (!activeElement) >+ return; >+ >+ if (!protectedFrame->editor().willReapplyEditing(*this, *activeElement)) >+ return; >+ >+ if (auto handler = item().redoHandler()) >+ handler->handleEvent(); >+ >+ protectedFrame->editor().reappliedEditing(*this, *activeElement); >+} >+ >+const String& CustomUndoStep::customUndoLabel() const >+{ >+ return item().label(); >+} >+ >+} // namespace WebCore >diff --git a/Source/WebCore/editing/CustomUndoStep.h b/Source/WebCore/editing/CustomUndoStep.h >new file mode 100644 >index 0000000000000000000000000000000000000000..c8508e33d756e0fb55f3c898655fbc4008486311 >--- /dev/null >+++ b/Source/WebCore/editing/CustomUndoStep.h >@@ -0,0 +1,58 @@ >+/* >+ * Copyright (C) 2019 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' >+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS >+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >+ * THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#pragma once >+ >+#include "UndoStep.h" >+#include <wtf/Ref.h> >+ >+namespace WebCore { >+ >+class Document; >+class UndoItem; >+ >+class CustomUndoStep final : public UndoStep { >+public: >+ static Ref<CustomUndoStep> create(Ref<Document>&& document, Ref<UndoItem>&& item) >+ { >+ return adoptRef(*new CustomUndoStep(WTFMove(document), WTFMove(item))); >+ } >+ >+ Document& document() const { return m_document.get(); } >+ UndoItem& item() const { return m_undoItem.get(); } >+ >+private: >+ CustomUndoStep(Ref<Document>&&, Ref<UndoItem>&&); >+ >+ void unapply() final; >+ void reapply() final; >+ EditAction editingAction() const final { return EditAction::CustomEditCommand; } >+ const String& customUndoLabel() const final; >+ >+ Ref<Document> m_document; >+ Ref<UndoItem> m_undoItem; >+}; >+ >+} // namespace WebCore >diff --git a/Source/WebCore/editing/EditAction.cpp b/Source/WebCore/editing/EditAction.cpp >index 4125e35078f25a6edcf8e1d6899475474e962e3a..ec1fc5ff410b2d0752db14fdb15d193054f692b5 100644 >--- a/Source/WebCore/editing/EditAction.cpp >+++ b/Source/WebCore/editing/EditAction.cpp >@@ -37,6 +37,7 @@ String nameForUndoRedo(EditAction editAction) > case EditAction::Insert: > case EditAction::InsertReplacement: > case EditAction::InsertFromDrop: >+ case EditAction::CustomEditCommand: > return { }; > case EditAction::SetColor: > return WEB_UI_STRING_KEY("Set Color", "Set Color (Undo action name)", "Undo action name"); >diff --git a/Source/WebCore/editing/EditAction.h b/Source/WebCore/editing/EditAction.h >index b6c45daf846a649e02e2945c12c8bcfead60b76d..76ecd55fb0d9bc6096f014fb4dcc1b492bf35598 100644 >--- a/Source/WebCore/editing/EditAction.h >+++ b/Source/WebCore/editing/EditAction.h >@@ -92,7 +92,8 @@ enum class EditAction : uint8_t { > ConvertToUnorderedList, > Indent, > Outdent, >- InsertEditableImage >+ InsertEditableImage, >+ CustomEditCommand > }; > > WEBCORE_EXPORT WTF::String nameForUndoRedo(EditAction); >diff --git a/Source/WebCore/editing/EditingStyle.cpp b/Source/WebCore/editing/EditingStyle.cpp >index b38c1509ee979be9e40fe3bad290d4742660006c..6bbf014304b48c7751ec98ccb262b8a9a3070c01 100644 >--- a/Source/WebCore/editing/EditingStyle.cpp >+++ b/Source/WebCore/editing/EditingStyle.cpp >@@ -45,6 +45,7 @@ > #include "Node.h" > #include "NodeTraversal.h" > #include "QualifiedName.h" >+#include "RenderElement.h" > #include "RenderStyle.h" > #include "StyleFontSizeFunctions.h" > #include "StyleProperties.h" >diff --git a/Source/WebCore/editing/Editor.cpp b/Source/WebCore/editing/Editor.cpp >index 5854aeb55a0f24d85855eed1260e3e3d94eaf0a3..1bfea9cd99677be072ba8c3c98da8fe0648ee982 100644 >--- a/Source/WebCore/editing/Editor.cpp >+++ b/Source/WebCore/editing/Editor.cpp >@@ -39,6 +39,7 @@ > #include "ClipboardEvent.h" > #include "CompositionEvent.h" > #include "CreateLinkCommand.h" >+#include "CustomUndoStep.h" > #include "DataTransfer.h" > #include "DeleteSelectionCommand.h" > #include "DictationAlternative.h" >@@ -1150,6 +1151,46 @@ void Editor::unappliedEditing(EditCommandComposition& composition) > respondToChangedContents(newSelection); > } > >+bool Editor::willUnapplyEditing(const CustomUndoStep& undoStep, Element& target) const >+{ >+ if (&document() != &undoStep.document()) { >+ ASSERT_NOT_REACHED(); >+ return false; >+ } >+ >+ return dispatchBeforeInputEvents(&target, nullptr, "historyUndo"); >+} >+ >+bool Editor::willReapplyEditing(const CustomUndoStep& undoStep, Element& target) const >+{ >+ if (&document() != &undoStep.document()) { >+ ASSERT_NOT_REACHED(); >+ return false; >+ } >+ >+ return dispatchBeforeInputEvents(&target, nullptr, "historyRedo"); >+} >+ >+void Editor::unappliedEditing(CustomUndoStep& undoStep, Element& target) >+{ >+ if (&document() != &undoStep.document()) { >+ ASSERT_NOT_REACHED(); >+ return; >+ } >+ >+ dispatchInputEvents(&target, nullptr, "historyUndo"); >+} >+ >+void Editor::reappliedEditing(CustomUndoStep& undoStep, Element& target) >+{ >+ if (&document() != &undoStep.document()) { >+ ASSERT_NOT_REACHED(); >+ return; >+ } >+ >+ dispatchInputEvents(&target, nullptr, "historyRedo"); >+} >+ > bool Editor::willReapplyEditing(const EditCommandComposition& composition) const > { > return dispatchBeforeInputEvents(composition.startingRootEditableElement(), composition.endingRootEditableElement(), "historyRedo"); >@@ -1740,6 +1781,13 @@ void Editor::redo() > client()->redo(); > } > >+void Editor::registerCustomUndoStep(Ref<CustomUndoStep>&& undoStep) >+{ >+ ASSERT(RuntimeEnabledFeatures::sharedFeatures().undoManagerAPIEnabled()); >+ if (auto* client = this->client()) >+ client->registerUndoStep(WTFMove(undoStep)); >+} >+ > void Editor::didBeginEditing() > { > if (client()) >diff --git a/Source/WebCore/editing/Editor.h b/Source/WebCore/editing/Editor.h >index 05cc1b82aeac140b40930df6f37ea54955c63f46..fd3ee5649dde44cc784b1be360fa995a3b5fec85 100644 >--- a/Source/WebCore/editing/Editor.h >+++ b/Source/WebCore/editing/Editor.h >@@ -58,6 +58,7 @@ class AlternativeTextController; > class ArchiveResource; > class DataTransfer; > class CompositeEditCommand; >+class CustomUndoStep; > class DeleteButtonController; > class EditCommand; > class EditCommandComposition; >@@ -236,10 +237,14 @@ public: > bool willApplyEditing(CompositeEditCommand&, Vector<RefPtr<StaticRange>>&&) const; > bool willUnapplyEditing(const EditCommandComposition&) const; > bool willReapplyEditing(const EditCommandComposition&) const; >+ bool willUnapplyEditing(const CustomUndoStep&, Element& target) const; >+ bool willReapplyEditing(const CustomUndoStep&, Element& target) const; > > void appliedEditing(CompositeEditCommand&); > void unappliedEditing(EditCommandComposition&); > void reappliedEditing(EditCommandComposition&); >+ void unappliedEditing(CustomUndoStep&, Element& target); >+ void reappliedEditing(CustomUndoStep&, Element& target); > void unappliedSpellCorrection(const VisibleSelection& selectionOfCorrected, const String& corrected, const String& correction); > > // This is off by default, since most editors want this behavior (originally matched IE but not Firefox). >@@ -324,6 +329,8 @@ public: > bool canRedo() const; > void redo(); > >+ void registerCustomUndoStep(Ref<CustomUndoStep>&&); >+ > void didBeginEditing(); > void didEndEditing(); > void willWriteSelectionToPasteboard(Range*); >diff --git a/Source/WebCore/editing/InsertEditableImageCommand.cpp b/Source/WebCore/editing/InsertEditableImageCommand.cpp >index 55d1184c7807c7e09a4c5f66e56792ec18a36a26..d9afa56e6cccaf092bb3da52286fade192b69bf0 100644 >--- a/Source/WebCore/editing/InsertEditableImageCommand.cpp >+++ b/Source/WebCore/editing/InsertEditableImageCommand.cpp >@@ -49,10 +49,10 @@ void InsertEditableImageCommand::doApply() > return; > > m_imageElement = HTMLImageElement::create(document()); >- m_imageElement->setAttributeWithoutSynchronization(x_apple_editable_imageAttr, emptyAtom()); >- m_imageElement->setAttributeWithoutSynchronization(widthAttr, AtomicString("100%", AtomicString::ConstructFromLiteral)); >- m_imageElement->setAttributeWithoutSynchronization(heightAttr, AtomicString("300px", AtomicString::ConstructFromLiteral)); >- m_imageElement->setAttributeWithoutSynchronization(styleAttr, AtomicString("display: block", AtomicString::ConstructFromLiteral)); >+ m_imageElement->setAttributeWithoutSynchronization(HTMLNames::x_apple_editable_imageAttr, emptyAtom()); >+ m_imageElement->setAttributeWithoutSynchronization(HTMLNames::widthAttr, AtomicString("100%", AtomicString::ConstructFromLiteral)); >+ m_imageElement->setAttributeWithoutSynchronization(HTMLNames::heightAttr, AtomicString("300px", AtomicString::ConstructFromLiteral)); >+ m_imageElement->setAttributeWithoutSynchronization(HTMLNames::styleAttr, AtomicString("display: block", AtomicString::ConstructFromLiteral)); > > insertNodeAt(*m_imageElement, endingSelection().start()); > setEndingSelection(visiblePositionAfterNode(*m_imageElement)); >diff --git a/Source/WebCore/editing/UndoStep.h b/Source/WebCore/editing/UndoStep.h >index 00c1700107b2cc79cc132679d898d705ba787e78..3490fff898ba6358bb37a58acc26c34497b52411 100644 >--- a/Source/WebCore/editing/UndoStep.h >+++ b/Source/WebCore/editing/UndoStep.h >@@ -32,6 +32,7 @@ > > #include "EditAction.h" > #include <wtf/RefCounted.h> >+#include <wtf/text/WTFString.h> > > namespace WebCore { > >@@ -42,6 +43,7 @@ public: > virtual void unapply() = 0; > virtual void reapply() = 0; > virtual EditAction editingAction() const = 0; >+ virtual const String& customUndoLabel() const = 0; > }; > > } // namespace WebCore >diff --git a/Source/WebCore/loader/EmptyClients.cpp b/Source/WebCore/loader/EmptyClients.cpp >index 492524b23eed81fedf68ed65b7ae8887b55ac364..1f7295108011078651f9be1ee435de97653ff9f7 100644 >--- a/Source/WebCore/loader/EmptyClients.cpp >+++ b/Source/WebCore/loader/EmptyClients.cpp >@@ -185,8 +185,8 @@ private: > void requestCandidatesForSelection(const VisibleSelection&) final { } > void handleAcceptedCandidateWithSoftSpaces(TextCheckingResult) final { } > >- void registerUndoStep(UndoStep&) final; >- void registerRedoStep(UndoStep&) final; >+ void registerUndoStep(Ref<UndoStep>&&) final; >+ void registerRedoStep(Ref<UndoStep>&&) final; > void clearUndoRedoOperations() final { } > > bool canCopyCut(Frame*, bool defaultValue) const final { return defaultValue; } >@@ -506,11 +506,11 @@ void EmptyEditorClient::EmptyTextCheckerClient::requestCheckingOfString(TextChec > { > } > >-void EmptyEditorClient::registerUndoStep(UndoStep&) >+void EmptyEditorClient::registerUndoStep(Ref<UndoStep>&&) > { > } > >-void EmptyEditorClient::registerRedoStep(UndoStep&) >+void EmptyEditorClient::registerRedoStep(Ref<UndoStep>&&) > { > } > >diff --git a/Source/WebCore/page/EditorClient.h b/Source/WebCore/page/EditorClient.h >index 37bf1823a98c2d9e52f3d02cbf5bcffaee358c44..abbf5829c17dcae97d04b2ccfb4e0dd3344d42ac 100644 >--- a/Source/WebCore/page/EditorClient.h >+++ b/Source/WebCore/page/EditorClient.h >@@ -104,8 +104,8 @@ public: > virtual void canceledComposition() = 0; > virtual void didUpdateComposition() = 0; > >- virtual void registerUndoStep(UndoStep&) = 0; >- virtual void registerRedoStep(UndoStep&) = 0; >+ virtual void registerUndoStep(Ref<UndoStep>&&) = 0; >+ virtual void registerRedoStep(Ref<UndoStep>&&) = 0; > virtual void clearUndoRedoOperations() = 0; > > virtual bool canCopyCut(Frame*, bool defaultValue) const = 0; >diff --git a/Source/WebCore/page/UndoItem.h b/Source/WebCore/page/UndoItem.h >index 2a6e2516a1a8d75e10f67f62e53e84e35ea7c6fc..94a84e37cb337298369795bec7a8839192f2cecd 100644 >--- a/Source/WebCore/page/UndoItem.h >+++ b/Source/WebCore/page/UndoItem.h >@@ -28,6 +28,7 @@ > #include "VoidCallback.h" > #include <wtf/Function.h> > #include <wtf/RefCounted.h> >+#include <wtf/WeakPtr.h> > #include <wtf/text/WTFString.h> > > namespace WebCore { >diff --git a/Source/WebCore/page/UndoManager.cpp b/Source/WebCore/page/UndoManager.cpp >index ac86600bafd800ee02a2235dd2bf8ed9fa99e555..f4dd502763cd860559148b4d84e8676b00ffc9c6 100644 >--- a/Source/WebCore/page/UndoManager.cpp >+++ b/Source/WebCore/page/UndoManager.cpp >@@ -26,14 +26,17 @@ > #include "config.h" > #include "UndoManager.h" > >+#include "CustomUndoStep.h" > #include "Document.h" >-#include "UndoItem.h" >+#include "Editor.h" >+#include "Frame.h" > > namespace WebCore { > > void UndoManager::addItem(Ref<UndoItem>&& item) > { >- UNUSED_PARAM(item); >+ if (auto frame = makeRefPtr(m_document.frame())) >+ frame->editor().registerCustomUndoStep(CustomUndoStep::create(m_document, WTFMove(item))); > } > > void UndoManager::undo() >diff --git a/Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm b/Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm >index 771972b1ac81e9665b7ce4a6a8c3d60dc356b957..0b73ef29d5a1d45acd604f1458e47bc5f9f9d03e 100644 >--- a/Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm >+++ b/Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm >@@ -2677,7 +2677,7 @@ void WebViewImpl::executeEditCommandForSelector(SEL selector, const String& argu > > void WebViewImpl::registerEditCommand(Ref<WebEditCommandProxy>&& command, UndoOrRedo undoOrRedo) > { >- auto actionName = WebCore::nameForUndoRedo(command->editAction()); >+ auto actionName = command->nameForUndoRedo(); > auto commandObjC = adoptNS([[WKEditCommand alloc] initWithWebEditCommandProxy:WTFMove(command)]); > > NSUndoManager *undoManager = [m_view undoManager]; >diff --git a/Source/WebKit/UIProcess/WebEditCommandProxy.cpp b/Source/WebKit/UIProcess/WebEditCommandProxy.cpp >index 9f83e3c19d86c9f2353a7e957610a1ea5d8584b2..93ebcbd7a305754fc68e574aaa64a2e7ff7aa354 100644 >--- a/Source/WebKit/UIProcess/WebEditCommandProxy.cpp >+++ b/Source/WebKit/UIProcess/WebEditCommandProxy.cpp >@@ -36,9 +36,10 @@ > namespace WebKit { > using namespace WebCore; > >-WebEditCommandProxy::WebEditCommandProxy(WebUndoStepID commandID, WebCore::EditAction editAction, WebPageProxy* page) >+WebEditCommandProxy::WebEditCommandProxy(WebUndoStepID commandID, WebCore::EditAction editAction, const String& customUndoLabel, WebPageProxy* page) > : m_commandID(commandID) > , m_editAction(editAction) >+ , m_customUndoLabel(customUndoLabel) > , m_page(page) > { > m_page->addEditCommand(*this); >@@ -68,4 +69,9 @@ void WebEditCommandProxy::reapply() > m_page->registerEditCommand(*this, UndoOrRedo::Undo); > } > >+String WebEditCommandProxy::nameForUndoRedo() const >+{ >+ return m_customUndoLabel.isEmpty() ? WebCore::nameForUndoRedo(m_editAction) : m_customUndoLabel; >+} >+ > } // namespace WebKit >diff --git a/Source/WebKit/UIProcess/WebEditCommandProxy.h b/Source/WebKit/UIProcess/WebEditCommandProxy.h >index 716cb58f403dd823196f8642f75f4df3d71aa8ca..2e9c24f63ebb197faa22e0299ed186435c81f358 100644 >--- a/Source/WebKit/UIProcess/WebEditCommandProxy.h >+++ b/Source/WebKit/UIProcess/WebEditCommandProxy.h >@@ -31,6 +31,7 @@ > #include <wtf/Forward.h> > #include <wtf/RefCounted.h> > #include <wtf/RefPtr.h> >+#include <wtf/text/WTFString.h> > > namespace WebKit { > >@@ -38,14 +39,15 @@ class WebPageProxy; > > class WebEditCommandProxy : public API::ObjectImpl<API::Object::Type::EditCommandProxy> { > public: >- static Ref<WebEditCommandProxy> create(WebUndoStepID commandID, WebCore::EditAction editAction, WebPageProxy* page) >+ static Ref<WebEditCommandProxy> create(WebUndoStepID commandID, WebCore::EditAction editAction, const String& customUndoLabel, WebPageProxy* page) > { >- return adoptRef(*new WebEditCommandProxy(commandID, editAction, page)); >+ return adoptRef(*new WebEditCommandProxy(commandID, editAction, customUndoLabel, page)); > } > ~WebEditCommandProxy(); > > WebUndoStepID commandID() const { return m_commandID; } > WebCore::EditAction editAction() const { return m_editAction; } >+ String nameForUndoRedo() const; > > void invalidate() { m_page = 0; } > >@@ -53,10 +55,11 @@ public: > void reapply(); > > private: >- WebEditCommandProxy(WebUndoStepID commandID, WebCore::EditAction, WebPageProxy*); >+ WebEditCommandProxy(WebUndoStepID commandID, WebCore::EditAction, const String& customUndoLabel, WebPageProxy*); > > WebUndoStepID m_commandID; > WebCore::EditAction m_editAction; >+ String m_customUndoLabel; > WebPageProxy* m_page; > }; > >diff --git a/Source/WebKit/UIProcess/WebPageProxy.cpp b/Source/WebKit/UIProcess/WebPageProxy.cpp >index e73c27695e838bdea6f92a9c6db2ba8fd3a1669a..dc55d80e143fd0bce0933f6276f9d131bd5c0725 100644 >--- a/Source/WebKit/UIProcess/WebPageProxy.cpp >+++ b/Source/WebKit/UIProcess/WebPageProxy.cpp >@@ -5340,9 +5340,9 @@ void WebPageProxy::compositionWasCanceled() > > // Undo management > >-void WebPageProxy::registerEditCommandForUndo(WebUndoStepID commandID, uint32_t editAction) >+void WebPageProxy::registerEditCommandForUndo(WebUndoStepID commandID, uint32_t editAction, const String& customUndoLabel) > { >- registerEditCommand(WebEditCommandProxy::create(commandID, static_cast<EditAction>(editAction), this), UndoOrRedo::Undo); >+ registerEditCommand(WebEditCommandProxy::create(commandID, static_cast<EditAction>(editAction), customUndoLabel, this), UndoOrRedo::Undo); > } > > void WebPageProxy::registerInsertionUndoGrouping() >diff --git a/Source/WebKit/UIProcess/WebPageProxy.h b/Source/WebKit/UIProcess/WebPageProxy.h >index 9d621cff9d0c0b470377aebd02cde7a80a756c06..e4f9fc3faf8e991493b1b3de96865096d1f1231e 100644 >--- a/Source/WebKit/UIProcess/WebPageProxy.h >+++ b/Source/WebKit/UIProcess/WebPageProxy.h >@@ -1615,7 +1615,7 @@ private: > void backForwardClear(); > > // Undo management >- void registerEditCommandForUndo(WebUndoStepID commandID, uint32_t editAction); >+ void registerEditCommandForUndo(WebUndoStepID commandID, uint32_t editAction, const String& customUndoLabel); > void registerInsertionUndoGrouping(); > void clearAllEditCommands(); > void canUndoRedo(UndoOrRedo, bool& result); >diff --git a/Source/WebKit/UIProcess/WebPageProxy.messages.in b/Source/WebKit/UIProcess/WebPageProxy.messages.in >index cf40fdcb0e5d1ed0e176db296c230313ecbdc9b7..845f90780c76be57c8ab8e7aa5b40416081e823e 100644 >--- a/Source/WebKit/UIProcess/WebPageProxy.messages.in >+++ b/Source/WebKit/UIProcess/WebPageProxy.messages.in >@@ -233,7 +233,7 @@ messages -> WebPageProxy { > WillGoToBackForwardListItem(struct WebCore::BackForwardItemIdentifier itemID, bool inPageCache) > > # Undo/Redo messages >- RegisterEditCommandForUndo(uint64_t commandID, uint32_t editAction) >+ RegisterEditCommandForUndo(uint64_t commandID, uint32_t editAction, String customUndoLabel) > ClearAllEditCommands() > RegisterInsertionUndoGrouping() > CanUndoRedo(enum:bool WebKit::UndoOrRedo undoOrRedo) -> (bool result) LegacySync >diff --git a/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm b/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm >index 5bbc8329e9885d94a8c6c4dd29959c2892065977..d005986997870b48260fe4dc3b85b9cd78fa6956 100644 >--- a/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm >+++ b/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm >@@ -265,7 +265,7 @@ void PageClientImpl::didChangeViewportProperties(const ViewportAttributes&) > > void PageClientImpl::registerEditCommand(Ref<WebEditCommandProxy>&& command, UndoOrRedo undoOrRedo) > { >- auto actionName = WebCore::nameForUndoRedo(command->editAction()); >+ auto actionName = command->nameForUndoRedo(); > auto commandObjC = adoptNS([[WKEditCommand alloc] initWithWebEditCommandProxy:WTFMove(command)]); > > NSUndoManager *undoManager = [m_contentView undoManager]; >diff --git a/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.cpp b/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.cpp >index 0094e356d514b877db1f30b6a68ed2d73c9f1357..8b9fab509a9954b015265b4c5b6b0d921c29c763 100644 >--- a/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.cpp >+++ b/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.cpp >@@ -302,22 +302,23 @@ String WebEditorClient::replacementURLForResource(Ref<WebCore::SharedBuffer>&& r > return m_page->injectedBundleEditorClient().replacementURLForResource(*m_page, WTFMove(resourceData), mimeType); > } > >-void WebEditorClient::registerUndoStep(UndoStep& step) >+void WebEditorClient::registerUndoStep(Ref<UndoStep>&& step) > { > // FIXME: Add assertion that the command being reapplied is the same command that is > // being passed to us. > if (m_page->isInRedo()) > return; > >- auto webStep = WebUndoStep::create(step); >+ auto editAction = static_cast<uint32_t>(step->editingAction()); >+ auto customName = step->customUndoLabel(); >+ auto webStep = WebUndoStep::create(WTFMove(step)); > auto stepID = webStep->stepID(); >- auto editAction = static_cast<uint32_t>(webStep->step().editingAction()); > > m_page->addWebUndoStep(stepID, WTFMove(webStep)); >- m_page->send(Messages::WebPageProxy::RegisterEditCommandForUndo(stepID, editAction), m_page->pageID(), IPC::SendOption::DispatchMessageEvenWhenWaitingForSyncReply); >+ m_page->send(Messages::WebPageProxy::RegisterEditCommandForUndo(stepID, editAction, customName), m_page->pageID(), IPC::SendOption::DispatchMessageEvenWhenWaitingForSyncReply); > } > >-void WebEditorClient::registerRedoStep(UndoStep&) >+void WebEditorClient::registerRedoStep(Ref<UndoStep>&&) > { > } > >diff --git a/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.h b/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.h >index 4720b71175412a59a229bc47106dab2da3c8756e..f41b086321c1f42825c5ad9ae2d96a9e2d705b6f 100644 >--- a/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.h >+++ b/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.h >@@ -85,8 +85,8 @@ private: > void getClientPasteboardDataForRange(WebCore::Range*, Vector<String>& pasteboardTypes, Vector<RefPtr<WebCore::SharedBuffer>>& pasteboardData) final; > String replacementURLForResource(Ref<WebCore::SharedBuffer>&& resourceData, const String& mimeType) final; > >- void registerUndoStep(WebCore::UndoStep&) final; >- void registerRedoStep(WebCore::UndoStep&) final; >+ void registerUndoStep(Ref<WebCore::UndoStep>&&) final; >+ void registerRedoStep(Ref<WebCore::UndoStep>&&) final; > void clearUndoRedoOperations() final; > > bool canCopyCut(WebCore::Frame*, bool defaultValue) const final; >diff --git a/Source/WebKitLegacy/mac/WebCoreSupport/WebEditorClient.h b/Source/WebKitLegacy/mac/WebCoreSupport/WebEditorClient.h >index f0f968b7e2b66c891dc14b6c1faaf0b8bbe1d19e..af35db25acbbd4af32827fc2da9ce1287e05b802 100644 >--- a/Source/WebKitLegacy/mac/WebCoreSupport/WebEditorClient.h >+++ b/Source/WebKitLegacy/mac/WebCoreSupport/WebEditorClient.h >@@ -114,8 +114,8 @@ private: > void canceledComposition() final; > void didUpdateComposition() final { } > >- void registerUndoStep(WebCore::UndoStep&) final; >- void registerRedoStep(WebCore::UndoStep&) final; >+ void registerUndoStep(Ref<WebCore::UndoStep>&&) final; >+ void registerRedoStep(Ref<WebCore::UndoStep>&&) final; > void clearUndoRedoOperations() final; > > bool canCopyCut(WebCore::Frame*, bool defaultValue) const final; >@@ -172,7 +172,7 @@ private: > void handleAcceptedCandidateWithSoftSpaces(WebCore::TextCheckingResult) final; > #endif > >- void registerUndoOrRedoStep(WebCore::UndoStep&, bool isRedo); >+ void registerUndoOrRedoStep(Ref<WebCore::UndoStep>&&, bool isRedo); > > WebView *m_webView; > RetainPtr<WebEditorUndoTarget> m_undoTarget; >diff --git a/Source/WebKitLegacy/mac/WebCoreSupport/WebEditorClient.mm b/Source/WebKitLegacy/mac/WebCoreSupport/WebEditorClient.mm >index 69b767ae7d74de1e6d27d9b169226fcedcb4c719..913db6d0dfdedfd3b191dcb8e914d343013c9b5d 100644 >--- a/Source/WebKitLegacy/mac/WebCoreSupport/WebEditorClient.mm >+++ b/Source/WebKitLegacy/mac/WebCoreSupport/WebEditorClient.mm >@@ -125,7 +125,7 @@ @interface WebUndoStep : NSObject > RefPtr<UndoStep> m_step; > } > >-+ (WebUndoStep *)stepWithUndoStep:(UndoStep&)step; >++ (WebUndoStep *)stepWithUndoStep:(Ref<UndoStep>&&)step; > - (UndoStep&)step; > > @end >@@ -141,12 +141,12 @@ + (void)initialize > #endif > } > >-- (id)initWithUndoStep:(UndoStep&)step >+- (id)initWithUndoStep:(Ref<UndoStep>&&)step > { > self = [super init]; > if (!self) > return nil; >- m_step = &step; >+ m_step = WTFMove(step); > return self; > } > >@@ -158,9 +158,9 @@ - (void)dealloc > [super dealloc]; > } > >-+ (WebUndoStep *)stepWithUndoStep:(UndoStep&)step >++ (WebUndoStep *)stepWithUndoStep:(Ref<UndoStep>&&)step > { >- return [[[WebUndoStep alloc] initWithUndoStep:step] autorelease]; >+ return [[[WebUndoStep alloc] initWithUndoStep:WTFMove(step)] autorelease]; > } > > - (UndoStep&)step >@@ -589,7 +589,7 @@ bool WebEditorClient::shouldInsertNode(Node *node, Range* replacingRange, Editor > return [[m_webView _editingDelegateForwarder] webView:m_webView shouldInsertNode:kit(node) replacingDOMRange:kit(replacingRange) givenAction:(WebViewInsertAction)givenAction]; > } > >-void WebEditorClient::registerUndoOrRedoStep(UndoStep& step, bool isRedo) >+void WebEditorClient::registerUndoOrRedoStep(Ref<UndoStep>&& step, bool isRedo) > { > NSUndoManager *undoManager = [m_webView undoManager]; > >@@ -601,10 +601,9 @@ void WebEditorClient::registerUndoOrRedoStep(UndoStep& step, bool isRedo) > return; > #endif > >- NSString *actionName = WebCore::nameForUndoRedo(step.editingAction()); >- WebUndoStep *webEntry = [WebUndoStep stepWithUndoStep:step]; >- [undoManager registerUndoWithTarget:m_undoTarget.get() selector:(isRedo ? @selector(redoEditing:) : @selector(undoEditing:)) object:webEntry]; >- if (actionName) >+ String actionName = step->customUndoLabel().isEmpty() ? WebCore::nameForUndoRedo(step->editingAction()) : step->customUndoLabel(); >+ [undoManager registerUndoWithTarget:m_undoTarget.get() selector:(isRedo ? @selector(redoEditing:) : @selector(undoEditing:)) object:[WebUndoStep stepWithUndoStep:WTFMove(step)]]; >+ if (!actionName.isEmpty()) > [undoManager setActionName:actionName]; > m_haveUndoRedoOperations = YES; > } >@@ -629,14 +628,14 @@ void WebEditorClient::updateEditorStateAfterLayoutIfEditabilityChanged() > [m_webView updateTouchBar]; > } > >-void WebEditorClient::registerUndoStep(UndoStep& cmd) >+void WebEditorClient::registerUndoStep(Ref<UndoStep>&& command) > { >- registerUndoOrRedoStep(cmd, false); >+ registerUndoOrRedoStep(WTFMove(command), false); > } > >-void WebEditorClient::registerRedoStep(UndoStep& cmd) >+void WebEditorClient::registerRedoStep(Ref<UndoStep>&& command) > { >- registerUndoOrRedoStep(cmd, true); >+ registerUndoOrRedoStep(WTFMove(command), true); > } > > void WebEditorClient::clearUndoRedoOperations() >diff --git a/Tools/ChangeLog b/Tools/ChangeLog >index eb3fffc32e47688d8e35d6882fc3261d04314bbc..a0bd0efede1fb1506421ca6941225995edbfff35 100644 >--- a/Tools/ChangeLog >+++ b/Tools/ChangeLog >@@ -1,3 +1,32 @@ >+2019-01-04 Wenson Hsieh <wenson_hsieh@apple.com> >+ >+ [Cocoa] Allow the page to add to the platform undo stack via UndoManager.addItem() >+ https://bugs.webkit.org/show_bug.cgi?id=193111 >+ <rdar://problem/44807048> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * DumpRenderTree/ios/UIScriptControllerIOS.mm: >+ (WTR::UIScriptController::undoActionName const): >+ (WTR::UIScriptController::redoActionName const): >+ (WTR::UIScriptController::platformUndoManager const): >+ * DumpRenderTree/mac/UIScriptControllerMac.mm: >+ (WTR::UIScriptController::undoActionName const): >+ (WTR::UIScriptController::redoActionName const): >+ (WTR::UIScriptController::platformUndoManager const): >+ * TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl: >+ * TestRunnerShared/UIScriptContext/UIScriptController.cpp: >+ (WTR::UIScriptController::undoActionName const): >+ (WTR::UIScriptController::redoActionName const): >+ * TestRunnerShared/UIScriptContext/UIScriptController.h: >+ * WebKitTestRunner/UIScriptControllerCocoa.mm: >+ (WTR::UIScriptController::undoActionName const): >+ (WTR::UIScriptController::redoActionName const): >+ * WebKitTestRunner/ios/UIScriptControllerIOS.mm: >+ (WTR::UIScriptController::platformUndoManager const): >+ * WebKitTestRunner/mac/UIScriptControllerMac.mm: >+ (WTR::UIScriptController::platformUndoManager const): >+ > 2019-01-03 Wenson Hsieh <wenson_hsieh@apple.com> > > Introduce IDL files for runtime-enabled UndoManager and UndoItem JavaScript API >diff --git a/Tools/DumpRenderTree/ios/UIScriptControllerIOS.mm b/Tools/DumpRenderTree/ios/UIScriptControllerIOS.mm >index 398034a4c20e39acaef269ce94589484824c2b96..8a04e8af3bc8b57ae536095e21a99a174321f428 100644 >--- a/Tools/DumpRenderTree/ios/UIScriptControllerIOS.mm >+++ b/Tools/DumpRenderTree/ios/UIScriptControllerIOS.mm >@@ -440,6 +440,21 @@ void UIScriptController::setKeyboardInputModeIdentifier(JSStringRef) > { > } > >+JSRetainPtr<JSStringRef> UIScriptController::undoActionName() const >+{ >+ return nullptr; >+} >+ >+JSRetainPtr<JSStringRef> UIScriptController::redoActionName() const >+{ >+ return nullptr; >+} >+ >+NSUndoManager *UIScriptController::platformUndoManager() const >+{ >+ return nil; >+} >+ > } > > #endif // PLATFORM(IOS_FAMILY) >diff --git a/Tools/DumpRenderTree/mac/UIScriptControllerMac.mm b/Tools/DumpRenderTree/mac/UIScriptControllerMac.mm >index c445145f33bef0cc1949e3d5aae0f533bee142d7..b806846137aa21f9c6fe63ea35bafbfc213329af 100644 >--- a/Tools/DumpRenderTree/mac/UIScriptControllerMac.mm >+++ b/Tools/DumpRenderTree/mac/UIScriptControllerMac.mm >@@ -215,6 +215,21 @@ void UIScriptController::toggleCapsLock(JSValueRef callback) > doAsyncTask(callback); > } > >+JSRetainPtr<JSStringRef> UIScriptController::undoActionName() const >+{ >+ return nullptr; >+} >+ >+JSRetainPtr<JSStringRef> UIScriptController::redoActionName() const >+{ >+ return nullptr; >+} >+ >+NSUndoManager *UIScriptController::platformUndoManager() const >+{ >+ return nil; >+} >+ > } > > #endif // PLATFORM(MAC) >diff --git a/Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl b/Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl >index 7d204e85726a86d3fa8ec2c38b9778c13b706623..f787e4c72789c54b6e1d4cbcbc58194b2c43a627 100644 >--- a/Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl >+++ b/Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl >@@ -287,8 +287,11 @@ interface UIScriptController { > void makeWindowContentViewFirstResponder(); > readonly attribute boolean isWindowContentViewFirstResponder; > >+ object attachmentInfo(DOMString attachmentIdentifier); >+ >+ // Editing > void drawSquareInEditableImage(); > readonly attribute long numberOfStrokesInEditableImage; >- >- object attachmentInfo(DOMString attachmentIdentifier); >+ readonly attribute DOMString undoActionName; >+ readonly attribute DOMString redoActionName; > }; >diff --git a/Tools/TestRunnerShared/UIScriptContext/UIScriptController.cpp b/Tools/TestRunnerShared/UIScriptContext/UIScriptController.cpp >index c9587c42e9f03efa8994d54d39019e7678ec6b78..b3167d39a0b7ecc0cbee1792772e523d909615ea 100644 >--- a/Tools/TestRunnerShared/UIScriptContext/UIScriptController.cpp >+++ b/Tools/TestRunnerShared/UIScriptContext/UIScriptController.cpp >@@ -245,6 +245,16 @@ void UIScriptController::toggleCapsLock(JSValueRef) > { > } > >+JSRetainPtr<JSStringRef> UIScriptController::undoActionName() const >+{ >+ return nullptr; >+} >+ >+JSRetainPtr<JSStringRef> UIScriptController::redoActionName() const >+{ >+ return nullptr; >+} >+ > #endif // !PLATFORM(COCOA) > > void UIScriptController::playBackEventStream(JSStringRef stream, JSValueRef callback) >@@ -559,6 +569,16 @@ void UIScriptController::overridePreference(JSStringRef, JSStringRef) > { > } > >+JSRetainPtr<JSStringRef> UIScriptController::undoActionName() const >+{ >+ return nullptr; >+} >+ >+JSRetainPtr<JSStringRef> UIScriptController::redoActionName() const >+{ >+ return nullptr; >+} >+ > #endif // !PLATFORM(COCOA) > > #if !PLATFORM(MAC) >diff --git a/Tools/TestRunnerShared/UIScriptContext/UIScriptController.h b/Tools/TestRunnerShared/UIScriptContext/UIScriptController.h >index a6482c9e7940a9e5745fb026406408d0b4e3458e..0d3db5e4b17cba7282f56918746c074edae08cc3 100644 >--- a/Tools/TestRunnerShared/UIScriptContext/UIScriptController.h >+++ b/Tools/TestRunnerShared/UIScriptContext/UIScriptController.h >@@ -31,6 +31,8 @@ > #include <wtf/Optional.h> > #include <wtf/Ref.h> > >+OBJC_CLASS NSUndoManager; >+ > namespace WebCore { > class FloatRect; > } >@@ -203,6 +205,9 @@ public: > void drawSquareInEditableImage(); > long numberOfStrokesInEditableImage(); > >+ JSRetainPtr<JSStringRef> undoActionName() const; >+ JSRetainPtr<JSStringRef> redoActionName() const; >+ > JSObjectRef attachmentInfo(JSStringRef attachmentIdentifier); > > private: >@@ -222,6 +227,10 @@ private: > void platformClearAllCallbacks(); > void platformPlayBackEventStream(JSStringRef, JSValueRef); > >+#if PLATFORM(COCOA) >+ NSUndoManager *platformUndoManager() const; >+#endif >+ > JSClassRef wrapperClass() final; > > JSObjectRef objectFromRect(const WebCore::FloatRect&) const; >diff --git a/Tools/WebKitTestRunner/UIScriptControllerCocoa.mm b/Tools/WebKitTestRunner/UIScriptControllerCocoa.mm >index a7b98e404b83102294937f646f64ecf8925712f6..73a6c98ae6fecf1a375bdace9ac8bdb03efb364f 100644 >--- a/Tools/WebKitTestRunner/UIScriptControllerCocoa.mm >+++ b/Tools/WebKitTestRunner/UIScriptControllerCocoa.mm >@@ -192,5 +192,15 @@ JSObjectRef UIScriptController::calendarType() const > return nullptr; > #endif > } >- >+ >+JSRetainPtr<JSStringRef> UIScriptController::undoActionName() const >+{ >+ return JSStringCreateWithCFString((__bridge CFStringRef)platformUndoManager().undoActionName); >+} >+ >+JSRetainPtr<JSStringRef> UIScriptController::redoActionName() const >+{ >+ return JSStringCreateWithCFString((__bridge CFStringRef)platformUndoManager().redoActionName); >+} >+ > } // namespace WTR >diff --git a/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm b/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm >index 9e20477b1e868267f49c4a0092b0ad58c3d49186..478f885e5b9805142e9a86a94c7aae3134cf1776 100644 >--- a/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm >+++ b/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm >@@ -959,6 +959,11 @@ JSObjectRef UIScriptController::attachmentInfo(JSStringRef jsAttachmentIdentifie > return JSValueToObject(m_context->jsContext(), [JSValue valueWithObject:attachmentInfoDictionary inContext:[JSContext contextWithJSGlobalContextRef:m_context->jsContext()]].JSValueRef, nullptr); > } > >+NSUndoManager *UIScriptController::platformUndoManager() const >+{ >+ return [(UIView *)[TestController::singleton().mainWebView()->platformView() valueForKeyPath:@"_currentContentView"] undoManager]; >+} >+ > } > > #endif // PLATFORM(IOS_FAMILY) >diff --git a/Tools/WebKitTestRunner/mac/UIScriptControllerMac.mm b/Tools/WebKitTestRunner/mac/UIScriptControllerMac.mm >index 218881152a895cddb6a7f40716f1900a5d77ac3b..757fa06bd78f1833f13b38cbc9b030f93419763f 100644 >--- a/Tools/WebKitTestRunner/mac/UIScriptControllerMac.mm >+++ b/Tools/WebKitTestRunner/mac/UIScriptControllerMac.mm >@@ -209,4 +209,9 @@ void UIScriptController::toggleCapsLock(JSValueRef callback) > doAsyncTask(callback); > } > >+NSUndoManager *UIScriptController::platformUndoManager() const >+{ >+ return TestController::singleton().mainWebView()->platformView().undoManager; >+} >+ > } // namespace WTR >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index c6eca1ac902e61420b7a3bfd19cb872ce39341f6..1c187b5e5f710bb85f8453c609221fbdd067a43b 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,21 @@ >+2019-01-04 Wenson Hsieh <wenson_hsieh@apple.com> >+ >+ [Cocoa] Allow the page to add to the platform undo stack via UndoManager.addItem() >+ https://bugs.webkit.org/show_bug.cgi?id=193111 >+ <rdar://problem/44807048> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * editing/undo/UndoManager/undo-manager-add-item-expected.txt: Added. >+ * editing/undo/UndoManager/undo-manager-add-item.html: Added. >+ * editing/undo/UndoManager/undo-manager-prevent-undo-redo-expected.txt: Added. >+ * editing/undo/UndoManager/undo-manager-prevent-undo-redo.html: Added. >+ * editing/undo/UndoManager/undo-manager-set-item-label-expected.txt: Added. >+ * editing/undo/UndoManager/undo-manager-set-item-label.html: Added. >+ * resources/ui-helper.js: >+ (window.UIHelper.undoAndRedoActionNames): >+ (window.UIHelper): >+ > 2019-01-03 Wenson Hsieh <wenson_hsieh@apple.com> > > Introduce IDL files for runtime-enabled UndoManager and UndoItem JavaScript API >diff --git a/LayoutTests/editing/undo/UndoManager/undo-manager-add-item-expected.txt b/LayoutTests/editing/undo/UndoManager/undo-manager-add-item-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..956da89916c7bf440816a551efeacd7340d8136d >--- /dev/null >+++ b/LayoutTests/editing/undo/UndoManager/undo-manager-add-item-expected.txt >@@ -0,0 +1,32 @@ >+This test verifies that UndoManager.addItem() can be used to add undo items to the platform undo stack. >+ >+ >+After adding an undo item (mainframe): >+PASS undoName is "mainframe" >+PASS redoName is "" >+After performing undo (mainframe): >+** UNDO ** >+PASS undoName is "" >+PASS redoName is "mainframe" >+After performing redo (mainframe): >+** REDO ** >+PASS undoName is "mainframe" >+PASS redoName is "" >+After adding an undo item (subframe): >+PASS undoName is "subframe" >+PASS redoName is "" >+After performing undo (subframe): >+PASS undoName is "mainframe" >+PASS redoName is "subframe" >+After performing redo (subframe): >+PASS undoName is "subframe" >+PASS redoName is "" >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >+ >+-------- >+Frame: '<!--frame1-->' >+-------- >+UNDO, REDO >diff --git a/LayoutTests/editing/undo/UndoManager/undo-manager-add-item.html b/LayoutTests/editing/undo/UndoManager/undo-manager-add-item.html >new file mode 100644 >index 0000000000000000000000000000000000000000..b923615a09cf100a7c7bf3135c33b2c50b30f017 >--- /dev/null >+++ b/LayoutTests/editing/undo/UndoManager/undo-manager-add-item.html >@@ -0,0 +1,91 @@ >+<!DOCTYPE html> <!-- webkit-test-runner [ enableUndoManagerAPI=true ] --> >+<html> >+ <head> >+ <script src="../../../resources/js-test.js"></script> >+ <script src="../../../resources/ui-helper.js"></script> >+ <script> >+ function addUndoItem() >+ { >+ const item = new UndoItem("mainframe"); >+ item.undo = () => debug("** UNDO **"); >+ item.redo = () => debug("** REDO **"); >+ document.undoManager.addItem(item); >+ } >+ </script> >+ </head> >+ <body> >+ <p>This test verifies that <code>UndoManager.addItem()</code> can be used to add undo items to the platform undo stack.</p> >+ <iframe id="frame" srcdoc=" >+ <body> >+ <pre id='output'></pre> >+ </body> >+ <script> >+ function appendOutput(string) >+ { >+ if (output.textContent.length) >+ output.textContent += ', '; >+ output.textContent += string; >+ } >+ >+ function addUndoItem() >+ { >+ const item = new UndoItem('subframe'); >+ item.undo = () => appendOutput('UNDO'); >+ item.redo = () => appendOutput('REDO'); >+ document.undoManager.addItem(item); >+ } >+ </script> >+ "></iframe> >+ <pre id='console'></pre> >+ </body> >+ <script> >+ jsTestIsAsync = true; >+ undoName = null; >+ redoName = null; >+ >+ if (window.testRunner) >+ testRunner.dumpChildFramesAsText(); >+ >+ addEventListener("load", async () => { >+ debug("After adding an undo item (mainframe):"); >+ addUndoItem(); >+ [undoName, redoName] = await UIHelper.undoAndRedoActionNames(); >+ shouldBeEqualToString("undoName", "mainframe"); >+ shouldBeEqualToString("redoName", ""); >+ >+ debug("After performing undo (mainframe):"); >+ document.undoManager.undo(); >+ [undoName, redoName] = await UIHelper.undoAndRedoActionNames(); >+ shouldBeEqualToString("undoName", ""); >+ shouldBeEqualToString("redoName", "mainframe"); >+ >+ debug("After performing redo (mainframe):"); >+ document.undoManager.redo(); >+ [undoName, redoName] = await UIHelper.undoAndRedoActionNames(); >+ shouldBeEqualToString("undoName", "mainframe"); >+ shouldBeEqualToString("redoName", ""); >+ >+ const frameWindow = frame.contentWindow; >+ >+ debug("After adding an undo item (subframe):"); >+ frameWindow.addUndoItem(); >+ [undoName, redoName] = await UIHelper.undoAndRedoActionNames(); >+ shouldBeEqualToString("undoName", "subframe"); >+ shouldBeEqualToString("redoName", ""); >+ >+ debug("After performing undo (subframe):"); >+ frameWindow.document.undoManager.undo(); >+ [undoName, redoName] = await UIHelper.undoAndRedoActionNames(); >+ shouldBeEqualToString("undoName", "mainframe"); >+ shouldBeEqualToString("redoName", "subframe"); >+ >+ debug("After performing redo (subframe):"); >+ frameWindow.document.undoManager.redo(); >+ [undoName, redoName] = await UIHelper.undoAndRedoActionNames(); >+ shouldBeEqualToString("undoName", "subframe"); >+ shouldBeEqualToString("redoName", ""); >+ >+ finishJSTest(); >+ }); >+ </script> >+</html> >diff --git a/LayoutTests/editing/undo/UndoManager/undo-manager-prevent-undo-redo-expected.txt b/LayoutTests/editing/undo/UndoManager/undo-manager-prevent-undo-redo-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..1882dc2cd253c5e2413aede4655e53aa9573d409 >--- /dev/null >+++ b/LayoutTests/editing/undo/UndoManager/undo-manager-prevent-undo-redo-expected.txt >@@ -0,0 +1,21 @@ >+Verifies that custom undo items added via UndoManager API emit input events, and may be prevented. >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+<DIV id="editor"> beforeinput:historyUndo >+<DIV id="editor"> input:historyUndo >+PASS editor.textContent is "before" >+ >+<DIV id="editor"> beforeinput:historyRedo >+<DIV id="editor"> input:historyRedo >+PASS editor.textContent is "after" >+ >+<DIV id="editor"> beforeinput:historyUndo >+PASS editor.textContent is "before (prevented)" >+ >+<DIV id="editor"> beforeinput:historyRedo >+PASS editor.textContent is "after (prevented)" >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >diff --git a/LayoutTests/editing/undo/UndoManager/undo-manager-prevent-undo-redo.html b/LayoutTests/editing/undo/UndoManager/undo-manager-prevent-undo-redo.html >new file mode 100644 >index 0000000000000000000000000000000000000000..cb277e1f7761da8205aca54ac43496b996d15553 >--- /dev/null >+++ b/LayoutTests/editing/undo/UndoManager/undo-manager-prevent-undo-redo.html >@@ -0,0 +1,57 @@ >+<!DOCTYPE html> <!-- webkit-test-runner [ enableUndoManagerAPI=true ] --> >+<html> >+ <head> >+ <script src="../../../resources/js-test.js"></script> >+ </head> >+ <body> >+ <div id="editor" contenteditable>before</div> >+ <pre id="description"></pre> >+ <pre id="console"></pre> >+ </body> >+ <script> >+ function log(event) { >+ debug(`<${event.target.tagName} id="${event.target.id}"> ${event.type}:${event.inputType}`); >+ } >+ >+ shouldPreventDefault = false; >+ >+ editor = document.getElementById("editor"); >+ editor.addEventListener("input", log); >+ editor.addEventListener("beforeinput", event => { >+ if (shouldPreventDefault) { >+ if (event.inputType === "historyUndo") >+ editor.textContent = "before (prevented)"; >+ else >+ editor.textContent = "after (prevented)"; >+ event.preventDefault(); >+ } >+ log(event); >+ }); >+ >+ editor.focus(); >+ editor.textContent = "after"; >+ >+ description("Verifies that custom undo items added via UndoManager API emit input events, and may be prevented."); >+ const item = new UndoItem("custom action"); >+ item.undo = () => editor.textContent = "before"; >+ item.redo = () => editor.textContent = "after"; >+ document.undoManager.addItem(item); >+ testRunner.execCommand("undo"); >+ shouldBeEqualToString("editor.textContent", "before"); >+ debug(""); >+ >+ testRunner.execCommand("redo"); >+ shouldBeEqualToString("editor.textContent", "after"); >+ debug(""); >+ >+ shouldPreventDefault = true; >+ >+ testRunner.execCommand("undo"); >+ shouldBeEqualToString("editor.textContent", "before (prevented)"); >+ debug(""); >+ >+ testRunner.execCommand("redo"); >+ shouldBeEqualToString("editor.textContent", "after (prevented)"); >+ editor.remove(); >+ </script> >+</html> >diff --git a/LayoutTests/editing/undo/UndoManager/undo-manager-set-item-label-expected.txt b/LayoutTests/editing/undo/UndoManager/undo-manager-set-item-label-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..d6d75c163a74464f687931bf0aa2cc8cbdd3ce30 >--- /dev/null >+++ b/LayoutTests/editing/undo/UndoManager/undo-manager-set-item-label-expected.txt >@@ -0,0 +1,36 @@ >+ >+Verifies that setting the label attribute of UndoItem affects the undo and redo action names in the platform undo manager. >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+After typing: >+PASS undoName is "Typing" >+PASS redoName is "" >+After adding the first UndoItem: >+PASS undoName is "First ð¥" >+PASS redoName is "" >+After adding the second UndoItem: >+PASS undoName is "Second ð¥" >+PASS redoName is "" >+After undoing: >+PASS undoName is "First ð¥" >+PASS redoName is "Second ð¥" >+After undoing again: >+PASS undoName is "Typing" >+PASS redoName is "First ð¥" >+After redoing: >+PASS undoName is "First ð¥" >+PASS redoName is "Second ð¥" >+After redoing again: >+PASS undoName is "Second ð¥" >+PASS redoName is "" >+After undoing and then pasting: >+PASS undoName is "Paste" >+PASS redoName is "" >+After undoing the paste command: >+PASS undoName is "First ð¥" >+PASS redoName is "Paste" >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >diff --git a/LayoutTests/editing/undo/UndoManager/undo-manager-set-item-label.html b/LayoutTests/editing/undo/UndoManager/undo-manager-set-item-label.html >new file mode 100644 >index 0000000000000000000000000000000000000000..b528ff6ed52afea172967d101c7f371ffd651f3c >--- /dev/null >+++ b/LayoutTests/editing/undo/UndoManager/undo-manager-set-item-label.html >@@ -0,0 +1,89 @@ >+<!DOCTYPE html> <!-- webkit-test-runner [ enableUndoManagerAPI=true ] --> >+<html> >+ <meta charset="utf8"> >+ <head> >+ <script src="../../../resources/js-test.js"></script> >+ <script src="../../../resources/ui-helper.js"></script> >+ <script src="../../editing.js"></script> >+ <script> >+ jsTestIsAsync = true; >+ undoName = null; >+ redoName = null; >+ >+ async function runTest() { >+ description("Verifies that setting the label attribute of UndoItem affects the undo and redo action names " >+ + "in the platform undo manager."); >+ >+ field.focus(); >+ >+ debug("After typing:"); >+ document.execCommand("InsertText", true, "hello"); >+ [undoName, redoName] = await UIHelper.undoAndRedoActionNames(); >+ shouldBeEqualToString("undoName", "Typing"); >+ shouldBeEqualToString("redoName", ""); >+ >+ debug("After adding the first UndoItem:"); >+ const firstItem = new UndoItem(""); >+ firstItem.label = "First ð¥"; >+ document.undoManager.addItem(firstItem); >+ [undoName, redoName] = await UIHelper.undoAndRedoActionNames(); >+ shouldBeEqualToString("undoName", firstItem.label); >+ shouldBeEqualToString("redoName", ""); >+ >+ debug("After adding the second UndoItem:"); >+ const secondItem = new UndoItem(""); >+ secondItem.label = "Second ð¥"; >+ document.undoManager.addItem(secondItem); >+ [undoName, redoName] = await UIHelper.undoAndRedoActionNames(); >+ shouldBeEqualToString("undoName", secondItem.label); >+ shouldBeEqualToString("redoName", ""); >+ >+ debug("After undoing:"); >+ document.undoManager.undo(); >+ [undoName, redoName] = await UIHelper.undoAndRedoActionNames(); >+ shouldBeEqualToString("undoName", firstItem.label); >+ shouldBeEqualToString("redoName", secondItem.label); >+ >+ debug("After undoing again:"); >+ document.undoManager.undo(); >+ [undoName, redoName] = await UIHelper.undoAndRedoActionNames(); >+ shouldBeEqualToString("undoName", "Typing"); >+ shouldBeEqualToString("redoName", firstItem.label); >+ >+ debug("After redoing:"); >+ document.undoManager.redo(); >+ [undoName, redoName] = await UIHelper.undoAndRedoActionNames(); >+ shouldBeEqualToString("undoName", firstItem.label); >+ shouldBeEqualToString("redoName", secondItem.label); >+ >+ debug("After redoing again:"); >+ document.undoManager.redo(); >+ [undoName, redoName] = await UIHelper.undoAndRedoActionNames(); >+ shouldBeEqualToString("undoName", secondItem.label); >+ shouldBeEqualToString("redoName", ""); >+ >+ debug("After undoing and then pasting:"); >+ document.undoManager.undo(); >+ selectAllCommand(); >+ copyCommand(); >+ pasteCommand(); >+ [undoName, redoName] = await UIHelper.undoAndRedoActionNames(); >+ shouldBeEqualToString("undoName", "Paste"); >+ shouldBeEqualToString("redoName", ""); >+ >+ debug("After undoing the paste command:"); >+ document.undoManager.undo(); >+ [undoName, redoName] = await UIHelper.undoAndRedoActionNames(); >+ shouldBeEqualToString("undoName", firstItem.label); >+ shouldBeEqualToString("redoName", "Paste"); >+ >+ finishJSTest(); >+ } >+ </script> >+ </head> >+ <body onload="runTest()"> >+ <input id="field"></input> >+ <pre id="description"></pre> >+ <pre id="console"></pre> >+ </body> >+</html> >diff --git a/LayoutTests/resources/ui-helper.js b/LayoutTests/resources/ui-helper.js >index 2f569aacc55c45c7025ce216a70345729224bc6e..8c85b6b342dd6d2d21406544a3863daa5f8738f7 100644 >--- a/LayoutTests/resources/ui-helper.js >+++ b/LayoutTests/resources/ui-helper.js >@@ -504,4 +504,13 @@ window.UIHelper = class UIHelper { > const escapedIdentifier = identifier.replace(/`/g, "\\`"); > return new Promise(resolve => testRunner.runUIScript(`uiController.setKeyboardInputModeIdentifier(\`${escapedIdentifier}\`)`, resolve)); > } >+ >+ static undoAndRedoActionNames() >+ { >+ if (!this.isWebKit2()) >+ return Promise.resolve(); >+ >+ const script = "JSON.stringify([uiController.undoActionName, uiController.redoActionName])"; >+ return new Promise(resolve => testRunner.runUIScript(script, result => resolve(JSON.parse(result)))); >+ } > }
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 193111
:
358427
|
359498
|
359590
|
359591
|
359592
|
359593
|
359594
|
359631
|
359632
|
359819
|
359832
|
359834