[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc

weinig at apple.com weinig at apple.com
Wed Dec 22 13:08:22 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit c741258daf0aceba09af4291294ee2eccb597910
Author: weinig at apple.com <weinig at apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Tue Sep 7 19:18:03 2010 +0000

    Add support for Undo/Redo
    <rdar://problem/7660519>
    https://bugs.webkit.org/show_bug.cgi?id=42781
    
    Reviewed by Darin Adler.
    
    Adds platform independent parts of Undo/Redo support and the mac
    platform support.
    
    To work around the common assumption made by platforms, that a redo
    item will be added synchronously while an undo is in progress, we
    ignore the calls from WebCore to add redo items, and instead add add
    them after telling WebCore to unapply the EditCommand. We similarly
    need to ignore undos, that take place during a redo, and force the
    addition ourselves.
    
    * Shared/CoreIPCSupport/WebPageMessageKinds.h:
    * Shared/CoreIPCSupport/WebPageProxyMessageKinds.h:
    Add new messages.
    
    * UIProcess/API/mac/PageClientImpl.h:
    * UIProcess/API/mac/PageClientImpl.mm:
    (-[WebEditCommandObjC initWithWebEditCommandProxy:WebKit::]):
    (-[WebEditCommandObjC WebKit::]):
    (-[WebEditorUndoTargetObjC undoEditing:]):
    (-[WebEditorUndoTargetObjC redoEditing:]):
    (WebKit::PageClientImpl::PageClientImpl):
    (WebKit::nameForEditAction):
    (WebKit::PageClientImpl::registerEditCommand):
    (WebKit::PageClientImpl::clearAllEditCommands):
    * UIProcess/API/qt/qwkpage.cpp:
    (QWKPagePrivate::registerEditCommand):
    (QWKPagePrivate::clearAllEditCommands):
    * UIProcess/API/qt/qwkpage_p.h:
    * UIProcess/PageClient.h:
    * UIProcess/win/WebView.cpp:
    (WebKit::WebView::registerEditCommand):
    (WebKit::WebView::clearAllEditCommands):
    * UIProcess/win/WebView.h:
    Add platform specific hooks for undo/redo.
    
    * UIProcess/WebEditCommandProxy.cpp: Added.
    (WebKit::WebEditCommandProxy::WebEditCommandProxy):
    (WebKit::WebEditCommandProxy::~WebEditCommandProxy):
    (WebKit::WebEditCommandProxy::unapply):
    (WebKit::WebEditCommandProxy::reapply):
    * UIProcess/WebEditCommandProxy.h: Added.
    (WebKit::WebEditCommandProxy::create):
    (WebKit::WebEditCommandProxy::commandID):
    (WebKit::WebEditCommandProxy::editAction):
    (WebKit::WebEditCommandProxy::invalidate):
    A proxy for the WebEditCommands in the WebProcess. These are owned
    by the platform back/forward list, with a weak reference back to the
    WebPageProxy (which holds a weakset of live WebEditCommandProxys).
    
    * UIProcess/WebPageProxy.cpp:
    (WebKit::WebPageProxy::close):
    (WebKit::WebPageProxy::didReceiveMessage):
    (WebKit::WebPageProxy::registerEditCommandForUndo):
    (WebKit::WebPageProxy::clearAllEditCommands):
    (WebKit::WebPageProxy::registerEditCommandForRedo):
    (WebKit::WebPageProxy::addEditCommand):
    (WebKit::WebPageProxy::removeEditCommand):
    (WebKit::WebPageProxy::processDidExit):
    * UIProcess/WebPageProxy.h:
    Forward messages.
    
    * WebProcess/WebCoreSupport/WebEditorClient.cpp:
    (WebKit::WebEditorClient::registerCommandForUndo):
    (WebKit::WebEditorClient::registerCommandForRedo):
    (WebKit::WebEditorClient::clearUndoRedoOperations):
    Send undo/redo registration and clearing to the UIProcess.
    
    * WebProcess/WebPage/WebEditCommand.cpp: Added.
    (WebKit::generateCommandID):
    (WebKit::WebEditCommand::WebEditCommand):
    * WebProcess/WebPage/WebEditCommand.h: Added.
    (WebKit::WebEditCommand::create):
    (WebKit::WebEditCommand::command):
    (WebKit::WebEditCommand::commandID):
    Wrapper for WebCore::EditCommand, with an added unique ID.
    
    * WebProcess/WebPage/WebPage.cpp:
    (WebKit::WebPage::WebPage):
    (WebKit::WebPage::webEditCommand):
    (WebKit::WebPage::addWebEditCommand):
    (WebKit::WebPage::removeWebEditCommand):
    (WebKit::WebPage::unapplyEditCommand):
    (WebKit::WebPage::reapplyEditCommand):
    (WebKit::WebPage::didRemoveEditCommand):
    (WebKit::WebPage::didReceiveMessage):
    * WebProcess/WebPage/WebPage.h:
    (WebKit::WebPage::isInRedo):
    Forward messages.
    
    * WebKit2.pro:
    * WebKit2.xcodeproj/project.pbxproj:
    * win/WebKit2.vcproj:
    Add new files.
    
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@66897 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/WebKit2/ChangeLog b/WebKit2/ChangeLog
index 2e30e8c..9ba56a7 100644
--- a/WebKit2/ChangeLog
+++ b/WebKit2/ChangeLog
@@ -1,3 +1,105 @@
+2010-09-07  Sam Weinig  <sam at webkit.org>
+
+        Reviewed by Darin Adler.
+
+        Add support for Undo/Redo
+        <rdar://problem/7660519>
+        https://bugs.webkit.org/show_bug.cgi?id=42781
+
+        Adds platform independent parts of Undo/Redo support and the mac
+        platform support.
+
+        To work around the common assumption made by platforms, that a redo
+        item will be added synchronously while an undo is in progress, we
+        ignore the calls from WebCore to add redo items, and instead add add
+        them after telling WebCore to unapply the EditCommand. We similarly
+        need to ignore undos, that take place during a redo, and force the
+        addition ourselves.
+
+        * Shared/CoreIPCSupport/WebPageMessageKinds.h:
+        * Shared/CoreIPCSupport/WebPageProxyMessageKinds.h:
+        Add new messages.
+
+        * UIProcess/API/mac/PageClientImpl.h:
+        * UIProcess/API/mac/PageClientImpl.mm:
+        (-[WebEditCommandObjC initWithWebEditCommandProxy:WebKit::]):
+        (-[WebEditCommandObjC WebKit::]):
+        (-[WebEditorUndoTargetObjC undoEditing:]):
+        (-[WebEditorUndoTargetObjC redoEditing:]):
+        (WebKit::PageClientImpl::PageClientImpl):
+        (WebKit::nameForEditAction):
+        (WebKit::PageClientImpl::registerEditCommand):
+        (WebKit::PageClientImpl::clearAllEditCommands):
+        * UIProcess/API/qt/qwkpage.cpp:
+        (QWKPagePrivate::registerEditCommand):
+        (QWKPagePrivate::clearAllEditCommands):
+        * UIProcess/API/qt/qwkpage_p.h:
+        * UIProcess/PageClient.h:
+        * UIProcess/win/WebView.cpp:
+        (WebKit::WebView::registerEditCommand):
+        (WebKit::WebView::clearAllEditCommands):
+        * UIProcess/win/WebView.h:
+        Add platform specific hooks for undo/redo.
+
+        * UIProcess/WebEditCommandProxy.cpp: Added.
+        (WebKit::WebEditCommandProxy::WebEditCommandProxy):
+        (WebKit::WebEditCommandProxy::~WebEditCommandProxy):
+        (WebKit::WebEditCommandProxy::unapply):
+        (WebKit::WebEditCommandProxy::reapply):
+        * UIProcess/WebEditCommandProxy.h: Added.
+        (WebKit::WebEditCommandProxy::create):
+        (WebKit::WebEditCommandProxy::commandID):
+        (WebKit::WebEditCommandProxy::editAction):
+        (WebKit::WebEditCommandProxy::invalidate):
+        A proxy for the WebEditCommands in the WebProcess. These are owned
+        by the platform back/forward list, with a weak reference back to the
+        WebPageProxy (which holds a weakset of live WebEditCommandProxys).
+
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::close):
+        (WebKit::WebPageProxy::didReceiveMessage):
+        (WebKit::WebPageProxy::registerEditCommandForUndo):
+        (WebKit::WebPageProxy::clearAllEditCommands):
+        (WebKit::WebPageProxy::registerEditCommandForRedo):
+        (WebKit::WebPageProxy::addEditCommand):
+        (WebKit::WebPageProxy::removeEditCommand):
+        (WebKit::WebPageProxy::processDidExit):
+        * UIProcess/WebPageProxy.h:
+        Forward messages.
+
+        * WebProcess/WebCoreSupport/WebEditorClient.cpp:
+        (WebKit::WebEditorClient::registerCommandForUndo):
+        (WebKit::WebEditorClient::registerCommandForRedo):
+        (WebKit::WebEditorClient::clearUndoRedoOperations):
+        Send undo/redo registration and clearing to the UIProcess.
+
+        * WebProcess/WebPage/WebEditCommand.cpp: Added.
+        (WebKit::generateCommandID):
+        (WebKit::WebEditCommand::WebEditCommand):
+        * WebProcess/WebPage/WebEditCommand.h: Added.
+        (WebKit::WebEditCommand::create):
+        (WebKit::WebEditCommand::command):
+        (WebKit::WebEditCommand::commandID):
+        Wrapper for WebCore::EditCommand, with an added unique ID.
+
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::WebPage):
+        (WebKit::WebPage::webEditCommand):
+        (WebKit::WebPage::addWebEditCommand):
+        (WebKit::WebPage::removeWebEditCommand):
+        (WebKit::WebPage::unapplyEditCommand):
+        (WebKit::WebPage::reapplyEditCommand):
+        (WebKit::WebPage::didRemoveEditCommand):
+        (WebKit::WebPage::didReceiveMessage):
+        * WebProcess/WebPage/WebPage.h:
+        (WebKit::WebPage::isInRedo):
+        Forward messages.
+
+        * WebKit2.pro:
+        * WebKit2.xcodeproj/project.pbxproj:
+        * win/WebKit2.vcproj:
+        Add new files.
+
 2010-09-07  Jessie Berlin  <jberlin at apple.com>
 
         Reviewed by Darin Adler.
diff --git a/WebKit2/Shared/CoreIPCSupport/WebPageMessageKinds.h b/WebKit2/Shared/CoreIPCSupport/WebPageMessageKinds.h
index b92cc75..1fa7204 100644
--- a/WebKit2/Shared/CoreIPCSupport/WebPageMessageKinds.h
+++ b/WebKit2/Shared/CoreIPCSupport/WebPageMessageKinds.h
@@ -35,6 +35,7 @@ namespace WebPageMessage {
 enum Kind {
     Close,
     DidReceivePolicyDecision,
+    DidRemoveEditCommand,
     GetRenderTreeExternalRepresentation,
     GoBack,
     GoForward,
@@ -44,6 +45,7 @@ enum Kind {
     LoadURLRequest,
     MouseEvent,
     PreferencesDidChange,
+    ReapplyEditCommand,
     Reload,
     RunJavaScriptInMainFrame,
     SetActive,
@@ -52,6 +54,7 @@ enum Kind {
     SetIsInWindow,
     StopLoading,
     TryClose,
+    UnapplyEditCommand,
     WheelEvent
 #if ENABLE(TOUCH_EVENTS)
     , TouchEvent
diff --git a/WebKit2/Shared/CoreIPCSupport/WebPageProxyMessageKinds.h b/WebKit2/Shared/CoreIPCSupport/WebPageProxyMessageKinds.h
index 2a1f1f3..9b0858b 100644
--- a/WebKit2/Shared/CoreIPCSupport/WebPageProxyMessageKinds.h
+++ b/WebKit2/Shared/CoreIPCSupport/WebPageProxyMessageKinds.h
@@ -67,7 +67,7 @@ enum Kind {
     SetToolTip,
     TakeFocus,
     WillSubmitForm,
-    
+
     BackForwardAddItem,
     BackForwardGoToItem,
     BackForwardBackItem,
@@ -77,6 +77,9 @@ enum Kind {
     BackForwardBackListCount,
     BackForwardForwardListCount,
 
+    RegisterEditCommandForUndo,
+    ClearAllEditCommands,
+
 #if USE(ACCELERATED_COMPOSITING)
     DidChangeAcceleratedCompositing,
 #endif
diff --git a/WebKit2/UIProcess/API/mac/PageClientImpl.h b/WebKit2/UIProcess/API/mac/PageClientImpl.h
index 1ff36bb..d4123c5 100644
--- a/WebKit2/UIProcess/API/mac/PageClientImpl.h
+++ b/WebKit2/UIProcess/API/mac/PageClientImpl.h
@@ -27,8 +27,10 @@
 #define PageClientImpl_h
 
 #include "PageClient.h"
+#include <wtf/RetainPtr.h>
 
 @class WKView;
+ at class WebEditorUndoTargetObjC;
 
 namespace WebKit {
 
@@ -50,12 +52,16 @@ private:
     virtual void toolTipChanged(const WTF::String& oldToolTip, const WTF::String& newToolTip);
     virtual void setCursor(const WebCore::Cursor&);
 
+    void registerEditCommand(PassRefPtr<WebEditCommandProxy>, UndoOrRedo);
+    void clearAllEditCommands();
+
 #if USE(ACCELERATED_COMPOSITING)
     void pageDidEnterAcceleratedCompositing();
     void pageDidLeaveAcceleratedCompositing();
 #endif
 
     WKView* m_wkView;
+    RetainPtr<WebEditorUndoTargetObjC> m_undoTarget;
 };
 
 } // namespace WebKit
diff --git a/WebKit2/UIProcess/API/mac/PageClientImpl.mm b/WebKit2/UIProcess/API/mac/PageClientImpl.mm
index b612e4b..0e2aa51 100644
--- a/WebKit2/UIProcess/API/mac/PageClientImpl.mm
+++ b/WebKit2/UIProcess/API/mac/PageClientImpl.mm
@@ -28,6 +28,7 @@
 #import "WKAPICast.h"
 #import "WKStringCF.h"
 #import "WKViewInternal.h"
+#import "WebEditCommandProxy.h"
 #import <WebCore/Cursor.h>
 #import <WebCore/FoundationExtras.h>
 #import <wtf/PassOwnPtr.h>
@@ -35,6 +36,59 @@
 
 using namespace WebCore;
 
+ at interface WebEditCommandObjC : NSObject
+{
+    RefPtr<WebKit::WebEditCommandProxy> m_command;   
+}
+
+- (id)initWithWebEditCommandProxy:(PassRefPtr<WebKit::WebEditCommandProxy>)command;
+- (WebKit::WebEditCommandProxy*)command;
+
+ at end
+
+ at implementation WebEditCommandObjC
+
+- (id)initWithWebEditCommandProxy:(PassRefPtr<WebKit::WebEditCommandProxy>)command
+{
+    self = [super init];
+    if (!self)
+        return nil;
+
+    m_command = command;
+    return self;
+}
+
+- (WebKit::WebEditCommandProxy*)command
+{
+    return m_command.get();
+}
+
+ at end
+
+ at interface WebEditorUndoTargetObjC : NSObject
+
+- (void)undoEditing:(id)arg;
+- (void)redoEditing:(id)arg;
+
+ at end
+
+ at implementation WebEditorUndoTargetObjC
+
+- (void)undoEditing:(id)sender
+{
+    ASSERT([sender isKindOfClass:[WebEditCommandObjC class]]);
+    [sender command]->unapply();
+}
+
+- (void)redoEditing:(id)sender
+{
+    ASSERT([sender isKindOfClass:[WebEditCommandObjC class]]);
+    [sender command]->reapply();
+}
+
+ at end
+
+
 namespace WebKit {
 
 NSString* nsStringFromWebCoreString(const WTF::String& string)
@@ -49,6 +103,7 @@ PassOwnPtr<PageClientImpl> PageClientImpl::create(WKView* wkView)
 
 PageClientImpl::PageClientImpl(WKView* wkView)
     : m_wkView(wkView)
+    , m_undoTarget(AdoptNS, [[WebEditorUndoTargetObjC alloc] init])
 {
 }
 
@@ -81,6 +136,71 @@ void PageClientImpl::setCursor(const WebCore::Cursor& cursor)
     [m_wkView _setCursor:cursor.platformCursor()];
 }
 
+static NSString* nameForEditAction(EditAction editAction)
+{
+    // FIXME: Use localized strings.
+    // FIXME: Move this to a platform independent location.
+
+    switch (editAction) {
+    case EditActionUnspecified: return nil;
+    case EditActionSetColor: return @"Set Color";
+    case EditActionSetBackgroundColor: return @"Set Background Color";
+    case EditActionTurnOffKerning: return @"Turn Off Kerning";
+    case EditActionTightenKerning: return @"Tighten Kerning";
+    case EditActionLoosenKerning: return @"Loosen Kerning";
+    case EditActionUseStandardKerning: return @"Use Standard Kerning";
+    case EditActionTurnOffLigatures: return @"Turn Off Ligatures";
+    case EditActionUseStandardLigatures: return @"Use Standard Ligatures";
+    case EditActionUseAllLigatures: return @"Use All Ligatures";
+    case EditActionRaiseBaseline: return @"Raise Baseline";
+    case EditActionLowerBaseline: return @"Lower Baseline";
+    case EditActionSetTraditionalCharacterShape: return @"Set Traditional Character Shape";
+    case EditActionSetFont: return @"Set Font";
+    case EditActionChangeAttributes: return @"Change Attributes";
+    case EditActionAlignLeft: return @"Align Left";
+    case EditActionAlignRight: return @"Align Right";
+    case EditActionCenter: return @"Center";
+    case EditActionJustify: return @"Justify";
+    case EditActionSetWritingDirection: return @"Set Writing Direction";
+    case EditActionSubscript: return @"Subscript";
+    case EditActionSuperscript: return @"Superscript";
+    case EditActionUnderline: return @"Underline";
+    case EditActionOutline: return @"Outline";
+    case EditActionUnscript: return @"Unscript";
+    case EditActionDrag: return @"Drag";
+    case EditActionCut: return @"Cut";
+    case EditActionPaste: return @"Paste";
+    case EditActionPasteFont: return @"Paste Font";
+    case EditActionPasteRuler: return @"Paste Ruler";
+    case EditActionTyping: return @"Typing";
+    case EditActionCreateLink: return @"Create Link";
+    case EditActionUnlink: return @"Unlink";
+    case EditActionInsertList: return @"Insert List";
+    case EditActionFormatBlock: return @"Formatting";
+    case EditActionIndent: return @"Indent";
+    case EditActionOutdent: return @"Outdent";
+    }
+    return nil;
+}
+
+void PageClientImpl::registerEditCommand(PassRefPtr<WebEditCommandProxy> prpCommand, UndoOrRedo undoOrRedo)
+{
+    RefPtr<WebEditCommandProxy> command = prpCommand;
+
+    RetainPtr<WebEditCommandObjC> commandObjC(AdoptNS, [[WebEditCommandObjC alloc] initWithWebEditCommandProxy:command]);
+    NSString *actionName = nameForEditAction(command->editAction());
+
+    NSUndoManager *undoManager = [m_wkView undoManager];
+    [undoManager registerUndoWithTarget:m_undoTarget.get() selector:((undoOrRedo == Undo) ? @selector(undoEditing:) : @selector(redoEditing:)) object:commandObjC.get()];
+    if (actionName)
+        [undoManager setActionName:actionName];
+}
+
+void PageClientImpl::clearAllEditCommands()
+{
+    [[m_wkView undoManager] removeAllActionsWithTarget:m_undoTarget.get()];
+}
+
 #if USE(ACCELERATED_COMPOSITING)
 void PageClientImpl::pageDidEnterAcceleratedCompositing()
 {
diff --git a/WebKit2/UIProcess/API/qt/qwkpage.cpp b/WebKit2/UIProcess/API/qt/qwkpage.cpp
index 54a3f44..7d7dabe 100644
--- a/WebKit2/UIProcess/API/qt/qwkpage.cpp
+++ b/WebKit2/UIProcess/API/qt/qwkpage.cpp
@@ -72,6 +72,14 @@ void QWKPagePrivate::toolTipChanged(const String&, const String& newTooltip)
     emit q->statusBarMessage(QString(newTooltip));
 }
 
+void QWKPagePrivate::registerEditCommand(PassRefPtr<WebEditCommandProxy>, UndoOrRedo)
+{
+}
+
+void QWKPagePrivate::clearAllEditCommands()
+{
+}
+
 void QWKPagePrivate::paint(QPainter* painter, QRect area)
 {
     painter->save();
diff --git a/WebKit2/UIProcess/API/qt/qwkpage_p.h b/WebKit2/UIProcess/API/qt/qwkpage_p.h
index 01ed102..437348c 100644
--- a/WebKit2/UIProcess/API/qt/qwkpage_p.h
+++ b/WebKit2/UIProcess/API/qt/qwkpage_p.h
@@ -51,6 +51,8 @@ public:
     virtual void setCursor(const WebCore::Cursor&);
     virtual void takeFocus(bool direction) { }
     virtual void toolTipChanged(const WTF::String&, const WTF::String&);
+    virtual void registerEditCommand(PassRefPtr<WebKit::WebEditCommandProxy>, UndoOrRedo);
+    virtual void clearAllEditCommands();
 
     void paint(QPainter* painter, QRect);
 
diff --git a/WebKit2/UIProcess/PageClient.h b/WebKit2/UIProcess/PageClient.h
index a583da1..1b04b9d 100644
--- a/WebKit2/UIProcess/PageClient.h
+++ b/WebKit2/UIProcess/PageClient.h
@@ -34,6 +34,8 @@ namespace WebCore {
 
 namespace WebKit {
 
+class WebEditCommandProxy;
+
 class PageClient {
 public:
     virtual ~PageClient() { }
@@ -46,6 +48,10 @@ public:
 
     virtual void setCursor(const WebCore::Cursor&) = 0;
 
+    enum UndoOrRedo { Undo, Redo };
+    virtual void registerEditCommand(PassRefPtr<WebEditCommandProxy>, UndoOrRedo) = 0;
+    virtual void clearAllEditCommands() = 0;
+
 #if USE(ACCELERATED_COMPOSITING)
     virtual void pageDidEnterAcceleratedCompositing() = 0;
     virtual void pageDidLeaveAcceleratedCompositing() = 0;
diff --git a/WebKit2/UIProcess/WebEditCommandProxy.cpp b/WebKit2/UIProcess/WebEditCommandProxy.cpp
new file mode 100644
index 0000000..6395685
--- /dev/null
+++ b/WebKit2/UIProcess/WebEditCommandProxy.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2010 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 "WebEditCommandProxy.h"
+
+#include "WebPageMessageKinds.h"
+#include "WebPageProxy.h"
+#include "WebProcessProxy.h"
+
+using namespace WebCore;
+
+namespace WebKit {
+
+WebEditCommandProxy::WebEditCommandProxy(uint64_t commandID, WebCore::EditAction editAction, WebPageProxy* page)
+    : m_commandID(commandID)
+    , m_editAction(editAction)
+    , m_page(page)
+{
+    m_page->addEditCommand(this);
+}
+
+WebEditCommandProxy::~WebEditCommandProxy()
+{
+    if (m_page)
+        m_page->removeEditCommand(this);
+}
+
+void WebEditCommandProxy::unapply()
+{
+    if (!m_page || !m_page->isValid())
+        return;
+
+    m_page->process()->connection()->send(WebPageMessage::UnapplyEditCommand, m_page->pageID(), CoreIPC::In(m_commandID));
+    m_page->registerEditCommandForRedo(this);
+}
+
+void WebEditCommandProxy::reapply()
+{
+    if (!m_page || !m_page->isValid())
+        return;
+
+    m_page->process()->connection()->send(WebPageMessage::ReapplyEditCommand, m_page->pageID(), CoreIPC::In(m_commandID));
+    m_page->registerEditCommandForUndo(this);
+}
+
+} // namespace WebKit
diff --git a/WebKit2/UIProcess/WebEditCommandProxy.h b/WebKit2/UIProcess/WebEditCommandProxy.h
new file mode 100644
index 0000000..9524d55
--- /dev/null
+++ b/WebKit2/UIProcess/WebEditCommandProxy.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef WebEditCommandProxy_h
+#define WebEditCommandProxy_h
+
+#include <WebCore/EditAction.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+
+namespace WebKit {
+
+class WebPageProxy;
+
+class WebEditCommandProxy : public RefCounted<WebEditCommandProxy> {
+public:
+    static PassRefPtr<WebEditCommandProxy> create(uint64_t commandID, WebCore::EditAction editAction, WebPageProxy* page)
+    {
+        return adoptRef(new WebEditCommandProxy(commandID, editAction, page));
+    }
+
+    uint64_t commandID() const { return m_commandID; }
+    WebCore::EditAction editAction() const { return m_editAction; }
+
+    void invalidate() { m_page = 0; }
+
+    void unapply();
+    void reapply();
+
+private:
+    friend class RefCounted<WebEditCommandProxy>;
+
+    WebEditCommandProxy(uint64_t commandID, WebCore::EditAction, WebPageProxy*);
+    ~WebEditCommandProxy();
+
+    uint64_t m_commandID;
+    WebCore::EditAction m_editAction;
+    WebPageProxy* m_page;
+};
+
+} // namespace WebKit
+
+#endif // WebEditCommandProxy_h
diff --git a/WebKit2/UIProcess/WebPageProxy.cpp b/WebKit2/UIProcess/WebPageProxy.cpp
index 5995f05..b712dc3 100644
--- a/WebKit2/UIProcess/WebPageProxy.cpp
+++ b/WebKit2/UIProcess/WebPageProxy.cpp
@@ -34,6 +34,7 @@
 #include "WebContextUserMessageCoders.h"
 #include "WebCoreArgumentCoders.h"
 #include "WebData.h"
+#include "WebEditCommandProxy.h"
 #include "WebEvent.h"
 #include "WebFormSubmissionListenerProxy.h"
 #include "WebFramePolicyListenerProxy.h"
@@ -187,6 +188,12 @@ void WebPageProxy::close()
         renderTreeExternalRepresentationCallbacks[i]->invalidate();
     m_renderTreeExternalRepresentationCallbacks.clear();
 
+    Vector<WebEditCommandProxy*> editCommandVector;
+    copyToVector(m_editCommandSet, editCommandVector);
+    m_editCommandSet.clear();
+    for (size_t i = 0, size = editCommandVector.size(); i < size; ++i)
+        editCommandVector[i]->invalidate();
+
     m_estimatedProgress = 0.0;
     
     m_loaderClient.initialize(0);
@@ -648,6 +655,18 @@ void WebPageProxy::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::M
             contentsSizeChanged(process()->webFrame(frameID), size);
             break;
         }
+        case WebPageProxyMessage::RegisterEditCommandForUndo: {
+            uint64_t commandID;
+            uint32_t editAction;
+            if (!arguments->decode(CoreIPC::Out(commandID, editAction)))
+                return;
+                
+            registerEditCommandForUndo(commandID, static_cast<EditAction>(editAction));
+            break;
+        }
+        case WebPageProxyMessage::ClearAllEditCommands:
+            clearAllEditCommands();
+            break;
         default:
             ASSERT_NOT_REACHED();
             break;
@@ -937,6 +956,42 @@ void WebPageProxy::goToItemInBackForwardList(WebBackForwardListItem* item)
     m_backForwardList->goToItem(item);
 }
 
+// Undo management
+
+void WebPageProxy::registerEditCommandForUndo(uint64_t commandID, EditAction editAction)
+{
+    registerEditCommandForUndo(WebEditCommandProxy::create(commandID, editAction, this));
+}
+
+void WebPageProxy::clearAllEditCommands()
+{
+    m_pageClient->clearAllEditCommands();
+}
+
+void WebPageProxy::registerEditCommandForUndo(PassRefPtr<WebEditCommandProxy> commandProxy)
+{
+    m_pageClient->registerEditCommand(commandProxy, PageClient::Undo);
+}
+
+void WebPageProxy::registerEditCommandForRedo(PassRefPtr<WebEditCommandProxy> commandProxy)
+{
+    m_pageClient->registerEditCommand(commandProxy, PageClient::Redo);
+}
+
+void WebPageProxy::addEditCommand(WebEditCommandProxy* command)
+{
+    m_editCommandSet.add(command);
+}
+
+void WebPageProxy::removeEditCommand(WebEditCommandProxy* command)
+{
+    m_editCommandSet.remove(command);
+
+    if (!isValid())
+        return;
+    process()->send(WebPageMessage::DidRemoveEditCommand, m_pageID, command->commandID());
+}
+
 // Other
 
 void WebPageProxy::takeFocus(bool direction)
@@ -1042,6 +1097,13 @@ void WebPageProxy::processDidExit()
         renderTreeExternalRepresentationCallbacks[i]->invalidate();
     m_renderTreeExternalRepresentationCallbacks.clear();
 
+    Vector<WebEditCommandProxy*> editCommandVector;
+    copyToVector(m_editCommandSet, editCommandVector);
+    m_editCommandSet.clear();
+    for (size_t i = 0, size = editCommandVector.size(); i < size; ++i)
+        editCommandVector[i]->invalidate();
+    m_pageClient->clearAllEditCommands();
+
     m_estimatedProgress = 0.0;
 
     m_pageClient->processDidExit();
diff --git a/WebKit2/UIProcess/WebPageProxy.h b/WebKit2/UIProcess/WebPageProxy.h
index baf2d75..c66ef87 100644
--- a/WebKit2/UIProcess/WebPageProxy.h
+++ b/WebKit2/UIProcess/WebPageProxy.h
@@ -37,8 +37,10 @@
 #include "WebLoaderClient.h"
 #include "WebPolicyClient.h"
 #include "WebUIClient.h"
+#include <WebCore/EditAction.h>
 #include <WebCore/FrameLoaderTypes.h>
 #include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
 #include <wtf/OwnPtr.h>
 #include <wtf/PassOwnPtr.h>
 #include <wtf/PassRefPtr.h>
@@ -65,6 +67,7 @@ class PageClient;
 class WebBackForwardList;
 class WebBackForwardListItem;
 class WebData;
+class WebEditCommandProxy;
 class WebKeyboardEvent;
 class WebMouseEvent;
 class WebPageNamespace;
@@ -162,6 +165,11 @@ public:
     void didLeaveAcceleratedCompositing();
 #endif
 
+    void addEditCommand(WebEditCommandProxy*);
+    void removeEditCommand(WebEditCommandProxy*);
+    void registerEditCommandForUndo(PassRefPtr<WebEditCommandProxy>);
+    void registerEditCommandForRedo(PassRefPtr<WebEditCommandProxy>);
+
     WebProcessProxy* process() const;
     WebPageNamespace* pageNamespace() const { return m_pageNamespace.get(); }
 
@@ -210,9 +218,14 @@ private:
     WTF::String runJavaScriptPrompt(WebFrameProxy* frame, const WTF::String&, const WTF::String&);
     void contentsSizeChanged(WebFrameProxy*, const WebCore::IntSize&);
 
+    // Back/Forward list management
     void addItemToBackForwardList(WebBackForwardListItem*);
     void goToItemInBackForwardList(WebBackForwardListItem*);
 
+    // Undo management
+    void registerEditCommandForUndo(uint64_t commandID, WebCore::EditAction);
+    void clearAllEditCommands();
+
     void takeFocus(bool direction);
     void setToolTip(const WTF::String&);
     void setCursor(const WebCore::Cursor&);
@@ -239,6 +252,8 @@ private:
     HashMap<uint64_t, RefPtr<ScriptReturnValueCallback> > m_scriptReturnValueCallbacks;
     HashMap<uint64_t, RefPtr<RenderTreeExternalRepresentationCallback> > m_renderTreeExternalRepresentationCallbacks;
 
+    HashSet<WebEditCommandProxy*> m_editCommandSet;
+
     double m_estimatedProgress;
 
     // Whether the web page is contained in a top-level window.
diff --git a/WebKit2/UIProcess/win/WebView.cpp b/WebKit2/UIProcess/win/WebView.cpp
index 4678c82..11fbdbc 100644
--- a/WebKit2/UIProcess/win/WebView.cpp
+++ b/WebKit2/UIProcess/win/WebView.cpp
@@ -569,6 +569,14 @@ void WebView::setCursor(const WebCore::Cursor& cursor)
     ::SetCursor(platformCursor);
 }
 
+void WebView::registerEditCommand(PassRefPtr<WebEditCommandProxy>, UndoOrRedo)
+{
+}
+
+void WebView::clearAllEditCommands()
+{
+}
+
 #if USE(ACCELERATED_COMPOSITING)
 void WebView::pageDidEnterAcceleratedCompositing()
 {
diff --git a/WebKit2/UIProcess/win/WebView.h b/WebKit2/UIProcess/win/WebView.h
index 2d536aa..6815c91 100644
--- a/WebKit2/UIProcess/win/WebView.h
+++ b/WebKit2/UIProcess/win/WebView.h
@@ -95,6 +95,9 @@ private:
     virtual void takeFocus(bool direction);
     virtual void toolTipChanged(const WTF::String&, const WTF::String&);
     virtual void setCursor(const WebCore::Cursor&);
+    virtual void registerEditCommand(PassRefPtr<WebEditCommandProxy>, UndoOrRedo);
+    virtual void clearAllEditCommands();
+
 #if USE(ACCELERATED_COMPOSITING)
     virtual void pageDidEnterAcceleratedCompositing();
     virtual void pageDidLeaveAcceleratedCompositing();
diff --git a/WebKit2/WebKit2.pro b/WebKit2/WebKit2.pro
index 0f35979..ecca6ac 100644
--- a/WebKit2/WebKit2.pro
+++ b/WebKit2/WebKit2.pro
@@ -207,6 +207,7 @@ HEADERS += \
     UIProcess/WebContext.h \
     UIProcess/WebContextInjectedBundleClient.h \
     UIProcess/WebContextUserMessageCoders.h \
+    UIProcess/WebEditCommandProxy.h \
     UIProcess/WebFormClient.h \
     UIProcess/WebFormSubmissionListenerProxy.h \
     UIProcess/WebFrameListenerProxy.h \
@@ -254,6 +255,7 @@ HEADERS += \
     WebProcess/WebCoreSupport/qt/WebFrameNetworkingContext.h \
     WebProcess/WebPage/ChunkedUpdateDrawingArea.h \
     WebProcess/WebPage/DrawingArea.h \
+    WebProcess/WebPage/WebEditCommand.h \
     WebProcess/WebPage/WebFrame.h \
     WebProcess/WebPage/WebPage.h \
     WebProcess/WebProcess.h \
@@ -315,6 +317,7 @@ SOURCES += \
     UIProcess/WebBackForwardListItem.cpp \
     UIProcess/WebContext.cpp \
     UIProcess/WebContextInjectedBundleClient.cpp \
+    UIProcess/WebEditCommandProxy.cpp \
     UIProcess/WebFormClient.cpp \
     UIProcess/WebFormSubmissionListenerProxy.cpp \
     UIProcess/WebFrameListenerProxy.cpp \
@@ -363,6 +366,7 @@ SOURCES += \
     WebProcess/WebCoreSupport/qt/WebFrameNetworkingContext.cpp \
     WebProcess/WebPage/ChunkedUpdateDrawingArea.cpp \
     WebProcess/WebPage/DrawingArea.cpp \
+    WebProcess/WebPage/WebEditCommand.cpp \
     WebProcess/WebPage/WebFrame.cpp \
     WebProcess/WebPage/WebPage.cpp \
     WebProcess/WebPage/WebBackForwardListProxy.cpp \
diff --git a/WebKit2/WebKit2.xcodeproj/project.pbxproj b/WebKit2/WebKit2.xcodeproj/project.pbxproj
index c782296..221ab33 100644
--- a/WebKit2/WebKit2.xcodeproj/project.pbxproj
+++ b/WebKit2/WebKit2.xcodeproj/project.pbxproj
@@ -241,6 +241,10 @@
 		BC9E95D411449B0300870E71 /* UpdateChunk.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC9E95D211449B0300870E71 /* UpdateChunk.cpp */; };
 		BC9E969A11457EDE00870E71 /* DrawingAreaProxyMessageKinds.h in Headers */ = {isa = PBXBuildFile; fileRef = BC9E969911457EDE00870E71 /* DrawingAreaProxyMessageKinds.h */; };
 		BC9E969C11457F3F00870E71 /* DrawingAreaMessageKinds.h in Headers */ = {isa = PBXBuildFile; fileRef = BC9E969B11457F3F00870E71 /* DrawingAreaMessageKinds.h */; };
+		BCA0EF7F12331E78007D3CFB /* WebEditCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA0EF7D12331E78007D3CFB /* WebEditCommand.h */; };
+		BCA0EF8012331E78007D3CFB /* WebEditCommand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCA0EF7E12331E78007D3CFB /* WebEditCommand.cpp */; };
+		BCA0EF9F12332642007D3CFB /* WebEditCommandProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA0EF9D12332642007D3CFB /* WebEditCommandProxy.h */; };
+		BCA0EFA012332642007D3CFB /* WebEditCommandProxy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCA0EF9E12332642007D3CFB /* WebEditCommandProxy.cpp */; };
 		BCA8C6A811E3BA5F00812FB7 /* InjectedBundlePageLoaderClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCA8C6A611E3BA5F00812FB7 /* InjectedBundlePageLoaderClient.cpp */; };
 		BCA8C6A911E3BA5F00812FB7 /* InjectedBundlePageLoaderClient.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA8C6A711E3BA5F00812FB7 /* InjectedBundlePageLoaderClient.h */; };
 		BCA8C6AF11E3C08700812FB7 /* InjectedBundlePageUIClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCA8C6AD11E3C08700812FB7 /* InjectedBundlePageUIClient.cpp */; };
@@ -611,6 +615,10 @@
 		BC9E95D211449B0300870E71 /* UpdateChunk.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UpdateChunk.cpp; sourceTree = "<group>"; };
 		BC9E969911457EDE00870E71 /* DrawingAreaProxyMessageKinds.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DrawingAreaProxyMessageKinds.h; sourceTree = "<group>"; };
 		BC9E969B11457F3F00870E71 /* DrawingAreaMessageKinds.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DrawingAreaMessageKinds.h; sourceTree = "<group>"; };
+		BCA0EF7D12331E78007D3CFB /* WebEditCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebEditCommand.h; sourceTree = "<group>"; };
+		BCA0EF7E12331E78007D3CFB /* WebEditCommand.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebEditCommand.cpp; sourceTree = "<group>"; };
+		BCA0EF9D12332642007D3CFB /* WebEditCommandProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebEditCommandProxy.h; sourceTree = "<group>"; };
+		BCA0EF9E12332642007D3CFB /* WebEditCommandProxy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebEditCommandProxy.cpp; sourceTree = "<group>"; };
 		BCA8C6A611E3BA5F00812FB7 /* InjectedBundlePageLoaderClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InjectedBundlePageLoaderClient.cpp; sourceTree = "<group>"; };
 		BCA8C6A711E3BA5F00812FB7 /* InjectedBundlePageLoaderClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InjectedBundlePageLoaderClient.h; sourceTree = "<group>"; };
 		BCA8C6AD11E3C08700812FB7 /* InjectedBundlePageUIClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InjectedBundlePageUIClient.cpp; sourceTree = "<group>"; };
@@ -1044,6 +1052,8 @@
 				0F5265B211DD37680006D33C /* LayerBackedDrawingArea.h */,
 				BC72B9F811E6476B001EB4EA /* WebBackForwardListProxy.cpp */,
 				BC72B9F911E6476B001EB4EA /* WebBackForwardListProxy.h */,
+				BCA0EF7E12331E78007D3CFB /* WebEditCommand.cpp */,
+				BCA0EF7D12331E78007D3CFB /* WebEditCommand.h */,
 				BC111ADC112F5B9300337BAB /* WebFrame.cpp */,
 				BC032D8910F437A00058C15A /* WebFrame.h */,
 				BC963D6A113DD19200574BE2 /* WebPage.cpp */,
@@ -1081,6 +1091,8 @@
 				BCDE059A11CDA8AE00E41AF1 /* WebContextInjectedBundleClient.cpp */,
 				BCDE059911CDA8AE00E41AF1 /* WebContextInjectedBundleClient.h */,
 				BCB0B0DB12305A2500B1341E /* WebContextUserMessageCoders.h */,
+				BCA0EF9E12332642007D3CFB /* WebEditCommandProxy.cpp */,
+				BCA0EF9D12332642007D3CFB /* WebEditCommandProxy.h */,
 				BCE4694F1214E6CB000B98EB /* WebFormClient.cpp */,
 				BCE469501214E6CB000B98EB /* WebFormClient.h */,
 				BCE469511214E6CB000B98EB /* WebFormSubmissionListenerProxy.cpp */,
@@ -1596,6 +1608,8 @@
 				BCB0B0DC12305A2500B1341E /* WebContextUserMessageCoders.h in Headers */,
 				BCB0B0DE12305A8C00B1341E /* InjectedBundleUserMessageCoders.h in Headers */,
 				BCB0B0E012305AB100B1341E /* UserMessageCoders.h in Headers */,
+				BCA0EF7F12331E78007D3CFB /* WebEditCommand.h in Headers */,
+				BCA0EF9F12332642007D3CFB /* WebEditCommandProxy.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -1832,6 +1846,8 @@
 				BCB0AD33122F285800B1341E /* MutableArray.cpp in Sources */,
 				BCB0AEEA122F53E300B1341E /* MutableDictionary.cpp in Sources */,
 				BCB0AF3612301DFB00B1341E /* WKMutableDictionary.cpp in Sources */,
+				BCA0EF8012331E78007D3CFB /* WebEditCommand.cpp in Sources */,
+				BCA0EFA012332642007D3CFB /* WebEditCommandProxy.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
diff --git a/WebKit2/WebProcess/WebCoreSupport/WebEditorClient.cpp b/WebKit2/WebProcess/WebCoreSupport/WebEditorClient.cpp
index b96eff7..357c66f 100644
--- a/WebKit2/WebProcess/WebCoreSupport/WebEditorClient.cpp
+++ b/WebKit2/WebProcess/WebCoreSupport/WebEditorClient.cpp
@@ -30,6 +30,8 @@
 
 #include "WebFrameLoaderClient.h"
 #include "WebPage.h"
+#include "WebPageProxyMessageKinds.h"
+#include "WebProcess.h"
 #include <WebCore/EditCommand.h>
 #include <WebCore/Frame.h>
 #include <WebCore/HTMLInputElement.h>
@@ -196,19 +198,28 @@ void WebEditorClient::didSetSelectionTypesForPasteboard()
     notImplemented();
 }
 
-void WebEditorClient::registerCommandForUndo(PassRefPtr<EditCommand>)
+void WebEditorClient::registerCommandForUndo(PassRefPtr<EditCommand> command)
 {
-    notImplemented();
+    // FIXME: Add assertion that the command being reapplied is the same command that is
+    // being passed to us.
+    if (m_page->isInRedo())
+        return;
+
+    RefPtr<WebEditCommand> webCommand = WebEditCommand::create(command);
+    m_page->addWebEditCommand(webCommand->commandID(), webCommand.get());
+    uint32_t editAction = static_cast<uint32_t>(webCommand->command()->editingAction());
+
+    WebProcess::shared().connection()->send(WebPageProxyMessage::RegisterEditCommandForUndo, m_page->pageID(),
+                                            CoreIPC::In(webCommand->commandID(), editAction));
 }
 
 void WebEditorClient::registerCommandForRedo(PassRefPtr<EditCommand>)
 {
-    notImplemented();
 }
 
 void WebEditorClient::clearUndoRedoOperations()
 {
-    notImplemented();
+    WebProcess::shared().connection()->send(WebPageProxyMessage::ClearAllEditCommands, m_page->pageID(), CoreIPC::In());
 }
 
 bool WebEditorClient::canUndo() const
diff --git a/WebKit2/WebProcess/WebPage/WebEditCommand.cpp b/WebKit2/WebProcess/WebPage/WebEditCommand.cpp
new file mode 100644
index 0000000..198cb6d
--- /dev/null
+++ b/WebKit2/WebProcess/WebPage/WebEditCommand.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2010 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 "WebEditCommand.h"
+
+namespace WebKit {
+
+static uint64_t generateCommandID()
+{
+    static uint64_t uniqueCommandID = 1;
+    return uniqueCommandID++;
+}
+
+PassRefPtr<WebEditCommand> WebEditCommand::create(PassRefPtr<WebCore::EditCommand> command)
+{
+    return adoptRef(new WebEditCommand(command, generateCommandID()));
+}
+
+} // namespace WebKit
diff --git a/WebKit2/WebProcess/WebPage/WebEditCommand.h b/WebKit2/WebProcess/WebPage/WebEditCommand.h
new file mode 100644
index 0000000..b6844a2
--- /dev/null
+++ b/WebKit2/WebProcess/WebPage/WebEditCommand.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef WebEditCommand_h
+#define WebEditCommand_h
+
+#include <WebCore/EditCommand.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace WebKit {
+
+class WebEditCommand : public RefCounted<WebEditCommand> {
+public:
+    static PassRefPtr<WebEditCommand> create(PassRefPtr<WebCore::EditCommand>);
+
+    WebCore::EditCommand* command() const { return m_command.get(); }
+    uint64_t commandID() const { return m_commandID; }
+
+private:
+    WebEditCommand(PassRefPtr<WebCore::EditCommand> command, uint64_t commandID)
+        : m_command(command)
+        , m_commandID(commandID)
+    {
+    }
+
+    RefPtr<WebCore::EditCommand> m_command;
+    uint64_t m_commandID;
+};
+
+} // namespace WebKit
+
+#endif // WebEditCommand_h
diff --git a/WebKit2/WebProcess/WebPage/WebPage.cpp b/WebKit2/WebProcess/WebPage/WebPage.cpp
index dbd54d0..53834e9 100644
--- a/WebKit2/WebProcess/WebPage/WebPage.cpp
+++ b/WebKit2/WebProcess/WebPage/WebPage.cpp
@@ -85,6 +85,7 @@ PassRefPtr<WebPage> WebPage::create(uint64_t pageID, const IntSize& viewSize, co
 WebPage::WebPage(uint64_t pageID, const IntSize& viewSize, const WebPreferencesStore& store, const DrawingAreaBase::DrawingAreaInfo& drawingAreaInfo)
     : m_viewSize(viewSize)
     , m_drawingArea(DrawingArea::create(drawingAreaInfo.type, drawingAreaInfo.id, this))
+    , m_isInRedo(false)
     , m_pageID(pageID)
 {
     ASSERT(m_pageID);
@@ -533,6 +534,46 @@ bool WebPage::handleEditingKeyboardEvent(KeyboardEvent* evt)
     return frame->editor()->insertText(evt->keyEvent()->text(), evt);
 }
 
+WebEditCommand* WebPage::webEditCommand(uint64_t commandID)
+{
+    return m_editCommandMap.get(commandID).get();
+}
+
+void WebPage::addWebEditCommand(uint64_t commandID, WebEditCommand* command)
+{
+    m_editCommandMap.set(commandID, command);
+}
+
+void WebPage::removeWebEditCommand(uint64_t commandID)
+{
+    m_editCommandMap.remove(commandID);
+}
+
+void WebPage::unapplyEditCommand(uint64_t commandID)
+{
+    WebEditCommand* command = webEditCommand(commandID);
+    if (!command)
+        return;
+
+    command->command()->unapply();
+}
+
+void WebPage::reapplyEditCommand(uint64_t commandID)
+{
+    WebEditCommand* command = webEditCommand(commandID);
+    if (!command)
+        return;
+
+    m_isInRedo = true;
+    command->command()->reapply();
+    m_isInRedo = false;
+}
+
+void WebPage::didRemoveEditCommand(uint64_t commandID)
+{
+    removeWebEditCommand(commandID);
+}
+
 void WebPage::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments)
 {
     if (messageID.is<CoreIPC::MessageClassDrawingArea>()) {
@@ -692,6 +733,27 @@ void WebPage::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::Messag
             setCustomUserAgent(customUserAgent);
             return;
         }
+        case WebPageMessage::UnapplyEditCommand: {
+            uint64_t commandID;
+            if (!arguments->decode(CoreIPC::Out(commandID)))
+                return;
+            unapplyEditCommand(commandID);
+            return;
+        }
+        case WebPageMessage::ReapplyEditCommand: {
+            uint64_t commandID;
+            if (!arguments->decode(CoreIPC::Out(commandID)))
+                return;
+            reapplyEditCommand(commandID);
+            return;
+        }
+        case WebPageMessage::DidRemoveEditCommand: {
+            uint64_t commandID;
+            if (!arguments->decode(CoreIPC::Out(commandID)))
+                return;
+            didRemoveEditCommand(commandID);
+            return;
+        }
     }
 
     ASSERT_NOT_REACHED();
diff --git a/WebKit2/WebProcess/WebPage/WebPage.h b/WebKit2/WebProcess/WebPage/WebPage.h
index 0de7e53..460fd7e 100644
--- a/WebKit2/WebProcess/WebPage/WebPage.h
+++ b/WebKit2/WebProcess/WebPage/WebPage.h
@@ -32,6 +32,7 @@
 #include "InjectedBundlePageFormClient.h"
 #include "InjectedBundlePageLoaderClient.h"
 #include "InjectedBundlePageUIClient.h"
+#include "WebEditCommand.h"
 #include <WebCore/FrameLoaderTypes.h>
 #include <WebCore/IntRect.h>
 #include <WebCore/ZoomMode.h>
@@ -98,6 +99,11 @@ public:
     void show();
     String userAgent() const;
 
+    WebEditCommand* webEditCommand(uint64_t);
+    void addWebEditCommand(uint64_t, WebEditCommand*);
+    void removeWebEditCommand(uint64_t);
+    bool isInRedo() const { return m_isInRedo; }
+
     // -- Called from WebProcess.
     void didReceiveMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*);
 
@@ -167,6 +173,10 @@ private:
     void didReceivePolicyDecision(WebFrame*, uint64_t listenerID, WebCore::PolicyAction policyAction);
     void setCustomUserAgent(const WTF::String&);
 
+    void unapplyEditCommand(uint64_t commandID);
+    void reapplyEditCommand(uint64_t commandID);
+    void didRemoveEditCommand(uint64_t commandID);
+
     OwnPtr<WebCore::Page> m_page;
     RefPtr<WebFrame> m_mainFrame;
 
@@ -175,6 +185,9 @@ private:
     WebCore::IntSize m_viewSize;
     RefPtr<DrawingArea> m_drawingArea;
 
+    bool m_isInRedo;
+    HashMap<uint64_t, RefPtr<WebEditCommand> > m_editCommandMap;
+
     InjectedBundlePageEditorClient m_editorClient;
     InjectedBundlePageFormClient m_formClient;
     InjectedBundlePageLoaderClient m_loaderClient;
diff --git a/WebKit2/win/WebKit2.vcproj b/WebKit2/win/WebKit2.vcproj
index 7d28104..c745901 100755
--- a/WebKit2/win/WebKit2.vcproj
+++ b/WebKit2/win/WebKit2.vcproj
@@ -681,32 +681,32 @@
 				</File>
 				<File
 					RelativePath="..\WebProcess\WebCoreSupport\WebSearchPopupMenu.h"
-					>
-				</File>
-				<Filter
-					Name="win"
-					>
-					<File
-						RelativePath="..\WebProcess\WebCoreSupport\win\WebErrorsWin.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\WebProcess\WebCoreSupport\win\WebFrameNetworkingContext.cpp"
-						>
-					</File>
-					<File
-						RelativePath="..\WebProcess\WebCoreSupport\win\WebFrameNetworkingContext.h"
-						>
-					</File>
-				</Filter>
-			</Filter>
-			<Filter
-				Name="WebPage"
-				>
-				<File
-					RelativePath="..\WebProcess\WebPage\ChunkedUpdateDrawingArea.cpp"
-					>
-				</File>
+					>
+				</File>
+				<Filter
+					Name="win"
+					>
+					<File
+						RelativePath="..\WebProcess\WebCoreSupport\win\WebErrorsWin.cpp"
+						>
+					</File>
+					<File
+						RelativePath="..\WebProcess\WebCoreSupport\win\WebFrameNetworkingContext.cpp"
+						>
+					</File>
+					<File
+						RelativePath="..\WebProcess\WebCoreSupport\win\WebFrameNetworkingContext.h"
+						>
+					</File>
+				</Filter>
+			</Filter>
+			<Filter
+				Name="WebPage"
+				>
+				<File
+					RelativePath="..\WebProcess\WebPage\ChunkedUpdateDrawingArea.cpp"
+					>
+				</File>
 				<File
 					RelativePath="..\WebProcess\WebPage\ChunkedUpdateDrawingArea.h"
 					>
@@ -728,6 +728,14 @@
 					>
 				</File>
 				<File
+					RelativePath="..\WebProcess\WebPage\WebEditCommand.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\WebProcess\WebPage\WebEditCommand.h"
+					>
+				</File>
+				<File
 					RelativePath="..\WebProcess\WebPage\WebFrame.cpp"
 					>
 				</File>
@@ -1121,11 +1129,11 @@
 				>
 			</File>
 			<File
-				RelativePath="..\UIProcess\WebData.h"
+				RelativePath="..\UIProcess\WebEditCommandProxy.cpp"
 				>
 			</File>
 			<File
-				RelativePath="..\UIProcess\WebError.h"
+				RelativePath="..\UIProcess\WebEditCommandProxy.h"
 				>
 			</File>
 			<File

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list