2010-10-28 MORITA Hajime <morrita@google.com>
authormorrita@google.com <morrita@google.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 13 Dec 2010 06:06:19 +0000 (06:06 +0000)
committermorrita@google.com <morrita@google.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 13 Dec 2010 06:06:19 +0000 (06:06 +0000)
        Reviewed by Ojan Vafai.

        spellcheck does not check pasted text
        https://bugs.webkit.org/show_bug.cgi?id=40092

        * editing/spelling/script-tests/spellcheck-paste.js: Added.
        * editing/spelling/spellcheck-paste.html: Added.
        * editing/spelling/spellcheck-paste-expected.txt: Added.
        * platform/chromium/test_expectations.txt:
        * platform/gtk/Skipped:
        * platform/mac-leopard/Skipped:
        * platform/mac-tiger/Skipped:
        * platform/mac-wk2/Skipped:
        * platform/qt/Skipped:
        * platform/win/Skipped:
2010-10-28  MORITA Hajime  <morrita@google.com>

        Reviewed by Ojan Vafai.

        spellcheck does not check pasted text
        https://bugs.webkit.org/show_bug.cgi?id=40092

        - Introduced SpellChecker class to encapsulate asynchronous spell
          checker state: sequence id, requesting text and target node.
          This is also the first step to decompose spell-check related
          code to a separate class.
        - Added EditorClient::isAsynchronousSpellCheckingEnabled()
          to use async spellcheck API on the platform.
          These APIs are touched by SpellChecker.
        - Used SpellChecker to check a pasted test. Text to check is
          collected from the subtree under the editingRoot.
        - Added Setting::m_asynchronousSpellCheckingEnabled to control
          async spell checking.

        Test: editing/spelling/spellcheck-paste.html

        * CMakeLists.txt:
        * GNUmakefile.am:
        * WebCore.exp.in:
        * WebCore.gypi:
        * WebCore.pro:
        * WebCore.vcproj/WebCore.vcproj:
        * WebCore.xcodeproj/project.pbxproj:
        * dom/DocumentMarkerController.cpp:
        (WebCore::DocumentMarkerController::showMarkers):
        (showDocumentMarkers):
        * dom/DocumentMarkerController.h:
        * dom/PositionIterator.cpp:
        (WebCore::PositionIterator::setOffsetInLeafNode):
        * dom/PositionIterator.h:
        * editing/Editor.cpp:
        (WebCore::Editor::replaceSelectionWithFragment):
        (WebCore::Editor::Editor):
        (WebCore::findFirstMarkable):
        (WebCore::Editor::selectionStartHasSpellingMarkerFor):
        * editing/Editor.h:
        (WebCore::Editor::spellChecker):
        * editing/SpellChecker.cpp: Added.
        (WebCore::SpellChecker::SpellChecker):
        (WebCore::SpellChecker::~SpellChecker):
        (WebCore::SpellChecker::initRequest):
        (WebCore::SpellChecker::clearRequest):
        (WebCore::SpellChecker::isAsynchronousEnabled):
        (WebCore::SpellChecker::canCheckAsynchronously):
        (WebCore::SpellChecker::isBusy):
        (WebCore::SpellChecker::isValid):
        (WebCore::SpellChecker::isCheckable):
        (WebCore::SpellChecker::requestCheckingFor):
        (WebCore::forwardIterator):
        (WebCore::SpellChecker::didCheck):
        * editing/SpellChecker.h: Added.
        (WebCore::SpellCheckingResult::SpellCheckingResult):
        (WebCore::SpellCheckingResult::type):
        (WebCore::SpellCheckingResult::location):
        (WebCore::SpellCheckingResult::length):
        * loader/EmptyClients.h:
        (WebCore::EmptyEditorClient::requestCheckingOfString):
        * page/EditorClient.h:
        * page/Settings.cpp:
        (WebCore::Settings::Settings):
        * page/Settings.h:
        (WebCore::Settings::setAsynchronousSpellCheckingEnabled):
        (WebCore::Settings::asynchronousSpellCheckingEnabled):
2010-10-28  MORITA Hajime  <morrita@google.com>

        Reviewed by Ojan Vafai.

        spellcheck does not check pasted text
        https://bugs.webkit.org/show_bug.cgi?id=40092

        Added a stub implememntation.

        * src/EditorClientImpl.h:
        (WebKit::EditorClientImpl::requestCheckingOfString):
2010-10-28  MORITA Hajime  <morrita@google.com>

        Reviewed by Ojan Vafai.

        spellcheck does not check pasted text
        https://bugs.webkit.org/show_bug.cgi?id=40092

        Added a stub implememntation.

        * WebCoreSupport/EditorClientEfl.h:
        (WebCore::EditorClientEfl::requestCheckingOfString):
2010-10-28  MORITA Hajime  <morrita@google.com>

        Reviewed by Ojan Vafai.

        spellcheck does not check pasted text
        https://bugs.webkit.org/show_bug.cgi?id=40092

        Added a stub implememntation.

        * WebCoreSupport/EditorClientGtk.h:
        (WebKit::EditorClient::requestCheckingOfString):
2010-10-28  MORITA Hajime  <morrita@google.com>

        Reviewed by Ojan Vafai.

        spellcheck does not check pasted text
        https://bugs.webkit.org/show_bug.cgi?id=40092

        Added a stub implememntation.

        * WebCoreSupport/EditorClientHaiku.h:
        (WebCore::EditorClientHaiku::requestCheckingOfString):
2010-10-28  MORITA Hajime  <morrita@google.com>

        Reviewed by Ojan Vafai.

        spellcheck does not check pasted text
        https://bugs.webkit.org/show_bug.cgi?id=40092

        Added asynchronous spell checking API to WebEditorClient using
        -[NSSpellChecker requestCheckingOfString].
        Note that WebEditorSpellCheckResponder is a small class to receive
        requested spell-checking result. Note that this feature is
        disabled at default.

        Also added [WebPreferences setAsynchronousSpellCheckingEnabled:] to
        enable the feature from LayoutTestController.

        * WebCoreSupport/WebEditorClient.h:
        * WebCoreSupport/WebEditorClient.mm:
        (-[WebEditorSpellCheckResponder initWithSender:WebCore::sequence:results:]):
        (-[WebEditorSpellCheckResponder perform]):
        (toCoreSpellingResult):
        (-[WebEditorSpellCheckResponder WTF::WebCore::]):
        (WebEditorClient::requestCheckingOfString):
        * WebView/WebPreferenceKeysPrivate.h:
        * WebView/WebPreferences.mm:
        (+[WebPreferences initialize]):
        (-[WebPreferences setAsynchronousSpellCheckingEnabled:]):
        (-[WebPreferences asynchronousSpellCheckingEnabled]):
        * WebView/WebPreferencesPrivate.h:
        * WebView/WebView.mm:
        (-[WebView _preferencesChangedNotification:]):
2010-10-28  MORITA Hajime  <morrita@google.com>

        Reviewed by Ojan Vafai.

        spellcheck does not check pasted text
        https://bugs.webkit.org/show_bug.cgi?id=40092

        Added a stub implememntation.

        * WebCoreSupport/EditorClientQt.h:
        (WebCore::EditorClientQt::requestCheckingOfString):
2010-10-28  MORITA Hajime  <morrita@google.com>

        Reviewed by Ojan Vafai.

        spellcheck does not check pasted text
        https://bugs.webkit.org/show_bug.cgi?id=40092

        Added a stub implememntation.

        * WebCoreSupport/WebEditorClient.h:
        (WebEditorClient::requestCheckingOfString):
2010-10-28  MORITA Hajime  <morrita@google.com>

        Reviewed by Ojan Vafai.

        spellcheck does not check pasted text
        https://bugs.webkit.org/show_bug.cgi?id=40092

        Added a stub implememntation.

        * WebCoreSupport/EditorClientWinCE.h:
        (WebKit::EditorClient::requestCheckingOfString):
2010-10-28  MORITA Hajime  <morrita@google.com>

        Reviewed by Ojan Vafai.

        spellcheck does not check pasted text
        https://bugs.webkit.org/show_bug.cgi?id=40092

        Added a stub implememntation.

        * WebKitSupport/EditorClientWx.h:
        (WebCore::EditorClientWx::requestCheckingOfString):
2010-10-28  MORITA Hajime  <morrita@google.com>

        Reviewed by Ojan Vafai.

        spellcheck does not check pasted text
        https://bugs.webkit.org/show_bug.cgi?id=40092

        Added a stub implememntation.

        * WebProcess/WebCoreSupport/WebEditorClient.cpp:
        (WebKit::WebEditorClient::requestCheckingOfString):
        * WebProcess/WebCoreSupport/WebEditorClient.h:
2010-10-28  MORITA Hajime  <morrita@google.com>

        Reviewed by Ojan Vafai.

        spellcheck does not check pasted text
        https://bugs.webkit.org/show_bug.cgi?id=40092

        Added LayoutTestController::setAsynchronousSpellCheckingEnabled()
        to control the setting.

        * DumpRenderTree/LayoutTestController.cpp:
        (setAsynchronousSpellCheckingEnabledCallback):
        (LayoutTestController::staticFunctions):
        * DumpRenderTree/LayoutTestController.h:
        * DumpRenderTree/chromium/LayoutTestController.h:
        * DumpRenderTree/chromium/LayoutTestController.cpp:
        (LayoutTestController::LayoutTestController):
        (LayoutTestController::setAsynchronousSpellCheckingEnabled):
        * DumpRenderTree/gtk/LayoutTestControllerGtk.cpp:
        (LayoutTestController::setAsynchronousSpellCheckingEnabled):
        * DumpRenderTree/mac/DumpRenderTree.mm:
        (resetDefaultsToConsistentValues):
        * DumpRenderTree/mac/LayoutTestControllerMac.mm:
        (LayoutTestController::setAsynchronousSpellCheckingEnabled):
        * DumpRenderTree/qt/LayoutTestControllerQt.h:
        * DumpRenderTree/qt/LayoutTestControllerQt.cpp:
        (LayoutTestController::setAsynchronousSpellCheckingEnabled):
        * DumpRenderTree/win/LayoutTestControllerWin.cpp:
        (LayoutTestController::setAsynchronousSpellCheckingEnabled):
        * DumpRenderTree/wx/LayoutTestControllerWx.cpp:
        (LayoutTestController::setAsynchronousSpellCheckingEnabled):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@73886 268f45cc-cd09-0410-ab3c-d52691b4dbfc

69 files changed:
LayoutTests/ChangeLog
LayoutTests/editing/spelling/script-tests/spellcheck-paste.js [new file with mode: 0644]
LayoutTests/editing/spelling/spellcheck-paste-expected.txt [new file with mode: 0644]
LayoutTests/editing/spelling/spellcheck-paste.html [new file with mode: 0644]
LayoutTests/platform/chromium/test_expectations.txt
LayoutTests/platform/gtk/Skipped
LayoutTests/platform/mac-leopard/Skipped
LayoutTests/platform/mac-tiger/Skipped
LayoutTests/platform/mac-wk2/Skipped
LayoutTests/platform/qt/Skipped
LayoutTests/platform/win/Skipped
WebCore/CMakeLists.txt
WebCore/ChangeLog
WebCore/GNUmakefile.am
WebCore/WebCore.exp.in
WebCore/WebCore.gypi
WebCore/WebCore.pro
WebCore/WebCore.vcproj/WebCore.vcproj
WebCore/WebCore.xcodeproj/project.pbxproj
WebCore/dom/DocumentMarkerController.cpp
WebCore/dom/DocumentMarkerController.h
WebCore/dom/PositionIterator.cpp
WebCore/dom/PositionIterator.h
WebCore/editing/Editor.cpp
WebCore/editing/Editor.h
WebCore/editing/SpellChecker.cpp [new file with mode: 0644]
WebCore/editing/SpellChecker.h [new file with mode: 0644]
WebCore/loader/EmptyClients.h
WebCore/page/EditorClient.h
WebCore/page/Settings.cpp
WebCore/page/Settings.h
WebKit/chromium/ChangeLog
WebKit/chromium/src/EditorClientImpl.h
WebKit/efl/ChangeLog
WebKit/efl/WebCoreSupport/EditorClientEfl.h
WebKit/gtk/ChangeLog
WebKit/gtk/WebCoreSupport/EditorClientGtk.h
WebKit/haiku/ChangeLog
WebKit/haiku/WebCoreSupport/EditorClientHaiku.h
WebKit/mac/ChangeLog
WebKit/mac/WebCoreSupport/WebEditorClient.h
WebKit/mac/WebCoreSupport/WebEditorClient.mm
WebKit/mac/WebView/WebPreferenceKeysPrivate.h
WebKit/mac/WebView/WebPreferences.mm
WebKit/mac/WebView/WebPreferencesPrivate.h
WebKit/mac/WebView/WebView.mm
WebKit/qt/ChangeLog
WebKit/qt/WebCoreSupport/EditorClientQt.h
WebKit/win/ChangeLog
WebKit/win/WebCoreSupport/WebEditorClient.h
WebKit/wince/ChangeLog
WebKit/wince/WebCoreSupport/EditorClientWinCE.h
WebKit/wx/ChangeLog
WebKit/wx/WebKitSupport/EditorClientWx.h
WebKit2/ChangeLog
WebKit2/WebProcess/WebCoreSupport/WebEditorClient.cpp
WebKit2/WebProcess/WebCoreSupport/WebEditorClient.h
WebKitTools/ChangeLog
WebKitTools/DumpRenderTree/LayoutTestController.cpp
WebKitTools/DumpRenderTree/LayoutTestController.h
WebKitTools/DumpRenderTree/chromium/LayoutTestController.cpp
WebKitTools/DumpRenderTree/chromium/LayoutTestController.h
WebKitTools/DumpRenderTree/gtk/LayoutTestControllerGtk.cpp
WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm
WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm
WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.cpp
WebKitTools/DumpRenderTree/qt/LayoutTestControllerQt.h
WebKitTools/DumpRenderTree/win/LayoutTestControllerWin.cpp
WebKitTools/DumpRenderTree/wx/LayoutTestControllerWx.cpp

index 1124bf0ee057969681f349d5b78d48a83be18bfb..b098c84e7ce75eb02c8192ef80a50e1a41e5fbab 100644 (file)
@@ -1,3 +1,21 @@
+2010-10-28  MORITA Hajime  <morrita@google.com>
+
+        Reviewed by Ojan Vafai.
+
+        spellcheck does not check pasted text
+        https://bugs.webkit.org/show_bug.cgi?id=40092
+
+        * editing/spelling/script-tests/spellcheck-paste.js: Added.
+        * editing/spelling/spellcheck-paste.html: Added.
+        * editing/spelling/spellcheck-paste-expected.txt: Added.
+        * platform/chromium/test_expectations.txt:
+        * platform/gtk/Skipped:
+        * platform/mac-leopard/Skipped:
+        * platform/mac-tiger/Skipped:
+        * platform/mac-wk2/Skipped:
+        * platform/qt/Skipped:
+        * platform/win/Skipped:
+
 2010-12-12  Sam Weinig  <sam@webkit.org>
 
         Update WebKit2 skipped list.
diff --git a/LayoutTests/editing/spelling/script-tests/spellcheck-paste.js b/LayoutTests/editing/spelling/script-tests/spellcheck-paste.js
new file mode 100644 (file)
index 0000000..013d2b0
--- /dev/null
@@ -0,0 +1,98 @@
+
+description('For Bug 40092: Spell checking for pasted text.');
+
+layoutTestController.waitUntilDone();
+
+var testRoot = document.createElement("div");
+document.body.insertBefore(testRoot, document.body.firstChild);
+
+var testTextArea = document.createElement("textarea");
+testRoot.appendChild(testTextArea);
+
+var testInput = document.createElement("input");
+testInput.setAttribute("type", "text");
+testRoot.appendChild(testInput);
+
+var testEditable = document.createElement("div");
+testEditable.setAttribute("contentEditable", "true");
+testRoot.appendChild(testEditable);
+
+var testSourcePlain = document.createElement("div");
+testSourcePlain.innerHTML = "foo bar";
+testRoot.appendChild(testSourcePlain);
+
+var testSourceDecorated = document.createElement("div");
+testSourceDecorated.innerHTML = "fo<b>o ba</b>r";
+testRoot.appendChild(testSourceDecorated);
+
+var sel = window.getSelection();
+
+var tests = [];
+
+function done()
+{
+    var next = tests.shift();
+    if (next)
+        return window.setTimeout(next, 0);
+    testRoot.style.display = "none";
+    layoutTestController.notifyDone();
+}
+
+function verifyMarker(node, expectedMarked)
+{
+    if (node instanceof HTMLInputElement || node instanceof HTMLTextAreaElement) {
+        node.focus();
+    } else {
+        sel.selectAllChildren(node);
+    }
+    return layoutTestController.hasSpellingMarker(expectedMarked[0], expectedMarked[1]);
+}
+
+function pasteAndVerify(source, dest, expectedMarked)
+{
+    sel.selectAllChildren(source);
+    document.execCommand("Copy");
+    if (dest instanceof HTMLInputElement || dest instanceof HTMLTextAreaElement) {
+        dest.value = "";
+        dest.focus();
+    } else {
+        dest.innerHTML = "";
+        sel.selectAllChildren(dest);
+    }
+    document.execCommand("Paste");
+
+    var nretry = 10;
+    var nsleep = 1;
+    function trial() { 
+        var verified = verifyMarker(dest, expectedMarked);
+        if (verified) {
+            testPassed(dest.tagName + " has a marker on '" + source.innerHTML + "'");
+            done();
+            return;
+        }
+
+        nretry--;
+        if (0 == nretry) {
+            testFailed(dest.tagName + " should have a marker on for '" + source.innerHTML + "'");
+            done();
+            return;
+        }
+        
+        nsleep *= 2;
+        window.setTimeout(trial, nsleep);
+    };
+    trial();
+};
+
+if (window.layoutTestController)
+    layoutTestController.setAsynchronousSpellCheckingEnabled(true);
+
+tests.push(function() { pasteAndVerify(testSourcePlain, testInput, [0, 3]); });
+tests.push(function() { pasteAndVerify(testSourceDecorated, testInput, [0, 3]); });
+tests.push(function() { pasteAndVerify(testSourcePlain, testTextArea, [0, 3]); });
+tests.push(function() { pasteAndVerify(testSourceDecorated, testTextArea, [0, 3]); });
+tests.push(function() { pasteAndVerify(testSourcePlain, testEditable, [0, 3]); });
+tests.push(function() { pasteAndVerify(testSourceDecorated, testEditable, [0, 2]); }); // To check "fo" part of foo.
+done();
+
+var successfullyParsed = true;
diff --git a/LayoutTests/editing/spelling/spellcheck-paste-expected.txt b/LayoutTests/editing/spelling/spellcheck-paste-expected.txt
new file mode 100644 (file)
index 0000000..ee3a873
--- /dev/null
@@ -0,0 +1,15 @@
+For Bug 40092: Spell checking for pasted text.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+PASS INPUT has a marker on 'foo bar'
+PASS INPUT has a marker on 'fo<b>o ba</b>r'
+PASS TEXTAREA has a marker on 'foo bar'
+PASS TEXTAREA has a marker on 'fo<b>o ba</b>r'
+PASS DIV has a marker on 'foo bar'
+PASS DIV has a marker on 'fo<b>o ba</b>r'
+
diff --git a/LayoutTests/editing/spelling/spellcheck-paste.html b/LayoutTests/editing/spelling/spellcheck-paste.html
new file mode 100644 (file)
index 0000000..2baba0c
--- /dev/null
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="stylesheet" href="../../fast/js/resources/js-test-style.css">
+<script src="../../fast/js/resources/js-test-pre.js"></script>
+<script src="resources/js-test-selection-shared.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script src="script-tests/spellcheck-paste.js"></script>
+<script src="../../fast/js/resources/js-test-post.js"></script>
+</body>
+</html>
index e66cd772617375811dbfaab3aebbbc41aff59f83..c2fc69381d4c91587eb27fa85103205055b1a71e 100644 (file)
@@ -2485,6 +2485,9 @@ BUGWK41311 WIN LINUX : fast/borders/borderRadiusDouble07.html = IMAGE
 BUGWK41311 WIN LINUX : fast/borders/borderRadiusDouble08.html = IMAGE
 BUGWK41311 WIN LINUX : fast/borders/borderRadiusDouble09.html = IMAGE
 
+// Need to implement EditorClient::requestCheckingOfString()
+BUGWK41423 : editing/spelling/spellcheck-paste.html = TIMEOUT
+
 // Flaky tests.
 BUG44345 LINUX : svg/zoom/text/zoom-hixie-mixed-009.xml = IMAGE PASS
 BUG44346 LINUX : svg/zoom/page/zoom-hixie-mixed-009.xml = IMAGE PASS
index 1acdccd5d63dd23c620e68d2850fb923d7369ccd..2b45241721032ceef24d14be6f10a12c1e7d6969 100644 (file)
@@ -964,6 +964,14 @@ editing/selection/unrendered-004.html
 editing/selection/unrendered-005.html
 editing/selection/unrendered-space.html
 editing/selection/word-granularity.html
+editing/spelling/inline_spelling_markers.html
+editing/spelling/spellcheck-attribute.html
+editing/spelling/spelling-hasspellingmarker.html
+editing/spelling/spelling-backspace-between-lines.html
+editing/spelling/spelling-linebreak.html
+editing/spelling/spelling-attribute-change.html
+editing/spelling/spelling-attribute-at-child.html
+editing/spelling/spellcheck-paste.html
 editing/style/5065910.html
 editing/style/apple-style-editable-mix.html
 editing/style/block-style-001.html
index c466413554657126183c4fcab22ff6a1709d9946..3c14cab361191c7afd8ddafe2fc6673637e97242 100644 (file)
@@ -88,6 +88,9 @@ fast/text/hyphenate-locale.html
 # See https://bugs.webkit.org/show_bug.cgi?id=35271
 http/tests/media/video-seekable-stall.html
 
+# Available 10.6 or later
+editing/spelling/spellcheck-paste.html
+
 # Disable tests which started failing after r66961
 # Failures look like an underlying platform issue
 # https://bugs.webkit.org/show_bug.cgi?id=45546
index a2bad9fec18c0239621e52cc641981b0a5055ba9..24f3250f5a1fd65709c1d10600c2b0466f51e29b 100644 (file)
@@ -209,6 +209,9 @@ fast/harness/show-modal-dialog.html
 # Loading fails on Tiger with error -1012 after asking NSURLConnection to continue without credentials.
 http/tests/misc/401-alternative-content.php
 
+# Available only 10.6 or later
+editing/spelling/spellcheck-paste.html
+
 # Disable spelling tests for autocorrection panel
 platform/mac/editing/spelling/autocorrection-contraction.html
 platform/mac/editing/spelling/autocorrection-delete.html
index 3190c11b6b4608b42b21fc0f1e31b804baae0361..81b9e7179585621bc8eea768deebdc28ad70aa9c 100644 (file)
@@ -173,6 +173,7 @@ editing/selection/triple-click-in-pre.html
 editing/selection/user-drag-element-and-user-select-none.html
 editing/selection/word-granularity.html
 editing/spelling/context-menu-suggestions.html
+editing/spelling/spellcheck-paste.html
 editing/undo/undo-deleteWord.html
 editing/undo/undo-smart-delete-reversed-selection.html
 editing/undo/undo-smart-delete-word.html
index 04bec9e0e9395a4e99845abe585336514e159d49..c3d8f388ab1b9c15485448be2af27951c96f713c 100644 (file)
@@ -2090,6 +2090,9 @@ editing/spelling/spelling-backspace-between-lines.html
 editing/spelling/spelling-attribute-change.html
 editing/spelling/spelling-attribute-at-child.html
 
+# EditorClient::requestCheckingOfString() is not implemented
+editing/spelling/spellcheck-paste.html
+
 # ============================================================================= #
 # failing editing/style tests
 # ============================================================================= #
index f7065637207ad0853210e97eef699071ab28c214..9c0403aa8177a40211afa2d5032d9b4bf3143aec 100644 (file)
@@ -945,6 +945,9 @@ editing/spelling/spelling-backspace-between-lines.html
 editing/spelling/spelling-contenteditable.html
 editing/spelling/spelling-textarea.html
 
+# EditorClient::requestCheckingOfString() is not implemented
+editing/spelling/spellcheck-paste.html
+
 # IndexedDB is not yet enabled.
 storage/indexeddb
 
index 419888e72ffe5c3b6d28b1ce0f37d8d3bc0471dd..2b0ee30f31c8cd0a1703ea7ec1937aff881a30b0 100644 (file)
@@ -951,6 +951,7 @@ SET(WebCore_SOURCES
     editing/SelectionController.cpp
     editing/SetNodeAttributeCommand.cpp
     editing/SmartReplace.cpp
+    editing/SpellChecker.cpp
     editing/SplitElementCommand.cpp
     editing/SplitTextNodeCommand.cpp
     editing/SplitTextNodeContainingElementCommand.cpp
index 1d6af42b596405a392bba31af1198ae07d9d127e..b90da4fcc0197612b8e2072306a0974ad8871c38 100644 (file)
@@ -1,3 +1,72 @@
+2010-10-28  MORITA Hajime  <morrita@google.com>
+
+        Reviewed by Ojan Vafai.
+
+        spellcheck does not check pasted text
+        https://bugs.webkit.org/show_bug.cgi?id=40092
+
+        - Introduced SpellChecker class to encapsulate asynchronous spell
+          checker state: sequence id, requesting text and target node.
+          This is also the first step to decompose spell-check related
+          code to a separate class.
+        - Added EditorClient::isAsynchronousSpellCheckingEnabled() 
+          to use async spellcheck API on the platform.
+          These APIs are touched by SpellChecker.
+        - Used SpellChecker to check a pasted test. Text to check is
+          collected from the subtree under the editingRoot.
+        - Added Setting::m_asynchronousSpellCheckingEnabled to control
+          async spell checking.
+
+        Test: editing/spelling/spellcheck-paste.html
+
+        * CMakeLists.txt:
+        * GNUmakefile.am:
+        * WebCore.exp.in:
+        * WebCore.gypi:
+        * WebCore.pro:
+        * WebCore.vcproj/WebCore.vcproj:
+        * WebCore.xcodeproj/project.pbxproj:
+        * dom/DocumentMarkerController.cpp:
+        (WebCore::DocumentMarkerController::showMarkers):
+        (showDocumentMarkers):
+        * dom/DocumentMarkerController.h:
+        * dom/PositionIterator.cpp:
+        (WebCore::PositionIterator::setOffsetInLeafNode):
+        * dom/PositionIterator.h:
+        * editing/Editor.cpp:
+        (WebCore::Editor::replaceSelectionWithFragment):
+        (WebCore::Editor::Editor):
+        (WebCore::findFirstMarkable):
+        (WebCore::Editor::selectionStartHasSpellingMarkerFor):
+        * editing/Editor.h:
+        (WebCore::Editor::spellChecker):
+        * editing/SpellChecker.cpp: Added.
+        (WebCore::SpellChecker::SpellChecker):
+        (WebCore::SpellChecker::~SpellChecker):
+        (WebCore::SpellChecker::initRequest):
+        (WebCore::SpellChecker::clearRequest):
+        (WebCore::SpellChecker::isAsynchronousEnabled):
+        (WebCore::SpellChecker::canCheckAsynchronously):
+        (WebCore::SpellChecker::isBusy):
+        (WebCore::SpellChecker::isValid):
+        (WebCore::SpellChecker::isCheckable):
+        (WebCore::SpellChecker::requestCheckingFor):
+        (WebCore::forwardIterator):
+        (WebCore::SpellChecker::didCheck):
+        * editing/SpellChecker.h: Added.
+        (WebCore::SpellCheckingResult::SpellCheckingResult):
+        (WebCore::SpellCheckingResult::type):
+        (WebCore::SpellCheckingResult::location):
+        (WebCore::SpellCheckingResult::length):
+        * loader/EmptyClients.h:
+        (WebCore::EmptyEditorClient::requestCheckingOfString):
+        * page/EditorClient.h:
+        * page/Settings.cpp:
+        (WebCore::Settings::Settings):
+        * page/Settings.h:
+        (WebCore::Settings::setAsynchronousSpellCheckingEnabled):
+        (WebCore::Settings::asynchronousSpellCheckingEnabled):
+
 2010-12-09  Antonio Gomes  <agomes@rim.com>
 
         Reviewed by Daniel Bates.
index cc121c93a2fe2aa7cba3d142d032bc7df41ec524..4d95df7c949bf59df284ca28f62e89bc2bf0d6d0 100644 (file)
@@ -1423,6 +1423,8 @@ webcore_sources += \
        WebCore/editing/SmartReplace.cpp \
        WebCore/editing/SmartReplace.h \
        WebCore/editing/SmartReplaceICU.cpp \
+       WebCore/editing/SpellChecker.cpp \
+       WebCore/editing/SpellChecker.h \
        WebCore/editing/SplitElementCommand.cpp \
        WebCore/editing/SplitElementCommand.h \
        WebCore/editing/SplitTextNodeCommand.cpp \
index 45632d2a54d9bd285a3cd6dabeb90d7785c79f88..bb0d8925ba7ca4b3db68a32cba937dd8763bfe64 100644 (file)
@@ -518,6 +518,7 @@ __ZN7WebCore23ReplaceSelectionCommandC1EPNS_8DocumentEN3WTF10PassRefPtrINS_16Doc
 __ZN7WebCore23createFragmentFromNodesEPNS_8DocumentERKN3WTF6VectorIPNS_4NodeELm0EEE
 __ZN7WebCore23overrideDefaultLanguageERKN3WTF6StringE
 __ZN7WebCore24BinaryPropertyListWriter17writePropertyListEv
+__ZN7WebCore24DocumentMarkerController14markersForNodeEPNS_4NodeE
 __ZN7WebCore24DocumentMarkerController13removeMarkersENS_14DocumentMarker10MarkerTypeE
 __ZN7WebCore24DocumentMarkerController14markersForNodeEPNS_4NodeE
 __ZN7WebCore24DocumentMarkerController23renderedRectsForMarkersENS_14DocumentMarker10MarkerTypeE
@@ -922,6 +923,7 @@ __ZN7WebCore9makeRangeERKNS_15VisiblePositionES2_
 __ZN7WebCore9pageCacheEv
 __ZN7WebCore9plainTextEPKNS_5RangeENS_20TextIteratorBehaviorE
 __ZN7WebCore9toElementEN3JSC7JSValueE
+__ZN7WebCore12SpellChecker8didCheckEiRKN3WTF6VectorINS_19SpellCheckingResultELm0EEE
 __ZNK3JSC8Bindings10RootObject12globalObjectEv
 __ZNK3WTF6String14createCFStringEv
 __ZNK7WebCore10Credential11persistenceEv
index 0f7c7dbb4540b9fe3b9fbf52b8d226e8edfd7f1d..ba9d627f975a04dc3598717a11a5690fd0c042e5 100644 (file)
             'editing/SmartReplace.h',
             'editing/SmartReplaceCF.cpp',
             'editing/SmartReplaceICU.cpp',
+            'editing/SpellChecker.cpp',
+            'editing/SpellChecker.h',
             'editing/SplitElementCommand.cpp',
             'editing/SplitElementCommand.h',
             'editing/SplitTextNodeCommand.cpp',
index 7e979040f0f78b1e102749f3efa2c1e3e6af6f6a..01bea1e5543bf5a58c0e8aa9b0cfd835c0420470 100644 (file)
@@ -831,6 +831,7 @@ SOURCES += \
     editing/SelectionController.cpp \
     editing/SetNodeAttributeCommand.cpp \
     editing/SmartReplaceICU.cpp \
+    editing/SpellChecker.cpp \
     editing/SplitElementCommand.cpp \
     editing/SplitTextNodeCommand.cpp \
     editing/SplitTextNodeContainingElementCommand.cpp \
index 348242d46dff71fdb030bc86f19c036aa7f96ccd..a1bdc33bd855f0d8d36ab34b957fd26148be1db2 100755 (executable)
@@ -1,3 +1,4 @@
+<<<<<<< HEAD
 <?xml version="1.0" encoding="Windows-1252"?>
 <VisualStudioProject
        ProjectType="Visual C++"
                                        />
                                </FileConfiguration>
                        </File>
+                       <File
+                               RelativePath="..\editing\SpellChecker.cpp"
+                               >
+                               <FileConfiguration
+                                       Name="Debug|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                               <FileConfiguration
+                                       Name="Release|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                               <FileConfiguration
+                                       Name="Debug_Cairo_CFLite|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                               <FileConfiguration
+                                       Name="Release_Cairo_CFLite|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                               <FileConfiguration
+                                       Name="Debug_All|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                               <FileConfiguration
+                                       Name="Release_LTCG|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                       </File>
+                       <File
+                               RelativePath="..\editing\SpellChecker.h"
+                               >
+                       </File>
                        <File
                                RelativePath="..\editing\SplitElementCommand.cpp"
                                >
index b4d6aa0e073e9f90f5aa27f5e5b1487af4e10c7d..e6d0cd0b431d2f4d265d9a995cf32b733b8dacbe 100644 (file)
                A77979280D6B9E64003851B9 /* JSImageData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A77979240D6B9E64003851B9 /* JSImageData.cpp */; };
                A77979290D6B9E64003851B9 /* JSImageData.h in Headers */ = {isa = PBXBuildFile; fileRef = A77979250D6B9E64003851B9 /* JSImageData.h */; };
                A784941B0B5FE507001E237A /* Clipboard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A784941A0B5FE507001E237A /* Clipboard.cpp */; };
+               A78FE13B12366B1000ACE8D0 /* SpellChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A78FE13912366B1000ACE8D0 /* SpellChecker.cpp */; };
+               A78FE13C12366B1000ACE8D0 /* SpellChecker.h in Headers */ = {isa = PBXBuildFile; fileRef = A78FE13A12366B1000ACE8D0 /* SpellChecker.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A795463E0B5C4C80007B438F /* DragDataMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = A795463D0B5C4C80007B438F /* DragDataMac.mm */; };
                A79546430B5C4CB4007B438F /* DragData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A79546420B5C4CB4007B438F /* DragData.cpp */; };
                A7AA66D611C5ED6A001D8C8C /* RenderIndicator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7AA66D411C5ED6A001D8C8C /* RenderIndicator.cpp */; };
                A77979240D6B9E64003851B9 /* JSImageData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSImageData.cpp; sourceTree = "<group>"; };
                A77979250D6B9E64003851B9 /* JSImageData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSImageData.h; sourceTree = "<group>"; };
                A784941A0B5FE507001E237A /* Clipboard.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Clipboard.cpp; sourceTree = "<group>"; };
+               A78FE13912366B1000ACE8D0 /* SpellChecker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SpellChecker.cpp; sourceTree = "<group>"; };
+               A78FE13A12366B1000ACE8D0 /* SpellChecker.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; path = SpellChecker.h; sourceTree = "<group>"; };
                A795463D0B5C4C80007B438F /* DragDataMac.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; path = DragDataMac.mm; sourceTree = "<group>"; };
                A79546420B5C4CB4007B438F /* DragData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DragData.cpp; sourceTree = "<group>"; };
                A7AA66D411C5ED6A001D8C8C /* RenderIndicator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderIndicator.cpp; sourceTree = "<group>"; };
                                4B6FA6F30C39E48C00087011 /* SmartReplace.cpp */,
                                4B6FA6F20C39E48C00087011 /* SmartReplace.h */,
                                4B6FA6F60C39E4A100087011 /* SmartReplaceCF.cpp */,
+                               A78FE13912366B1000ACE8D0 /* SpellChecker.cpp */,
+                               A78FE13A12366B1000ACE8D0 /* SpellChecker.h */,
                                93309DC2099E64910056E581 /* SplitElementCommand.cpp */,
                                93309DC3099E64910056E581 /* SplitElementCommand.h */,
                                93309DC4099E64910056E581 /* SplitTextNodeCommand.cpp */,
                                75415AFD12958D5E003AD669 /* SpeechInputEvent.h in Headers */,
                                7578F92011E4E32800D933C5 /* SpeechInputListener.h in Headers */,
                                75415B0012958D5E003AD669 /* SpeechInputResultList.h in Headers */,
+                               A78FE13C12366B1000ACE8D0 /* SpellChecker.h in Headers */,
                                93309E12099E64920056E581 /* SplitElementCommand.h in Headers */,
                                93309E14099E64920056E581 /* SplitTextNodeCommand.h in Headers */,
                                93309E16099E64920056E581 /* SplitTextNodeContainingElementCommand.h in Headers */,
                                75415C28129A9920003AD669 /* SpeechInputEvent.cpp in Sources */,
                                758978EC127090D60076D5A9 /* SpeechInputResult.cpp in Sources */,
                                75415C29129A9920003AD669 /* SpeechInputResultList.cpp in Sources */,
+                               A78FE13B12366B1000ACE8D0 /* SpellChecker.cpp in Sources */,
                                93309E11099E64920056E581 /* SplitElementCommand.cpp in Sources */,
                                93309E13099E64920056E581 /* SplitTextNodeCommand.cpp in Sources */,
                                93309E15099E64920056E581 /* SplitTextNodeContainingElementCommand.cpp in Sources */,
index 3b7abccc117c2a3137b359df489e67b8e919d465..5f8863102e1853daed22a083dd35c9a1bf9b8776 100644 (file)
@@ -567,4 +567,31 @@ bool DocumentMarkerController::hasMarkers(Range* range, DocumentMarker::MarkerTy
     return false;
 }
 
+#ifndef NDEBUG
+void DocumentMarkerController::showMarkers() const
+{
+    fprintf(stderr, "%d nodes have markers:\n", m_markers.size());
+    MarkerMap::const_iterator end = m_markers.end();
+    for (MarkerMap::const_iterator nodeIterator = m_markers.begin(); nodeIterator != end; ++nodeIterator) {
+        Node* node = nodeIterator->first.get();
+        fprintf(stderr, "%p", node);
+        MarkerMapVectorPair* vectorPair = nodeIterator->second;
+        Vector<DocumentMarker>& markers = vectorPair->first;
+        unsigned markerCount = markers.size();
+        for (unsigned markerIndex = 0; markerIndex < markerCount; ++markerIndex)
+            fprintf(stderr, " %d:[%d:%d](%d)", markers[markerIndex].type, markers[markerIndex].startOffset, markers[markerIndex].endOffset, markers[markerIndex].activeMatch);
+        fprintf(stderr, "\n");
+    }
+}
+#endif
+
 } // namespace WebCore
+
+
+#ifndef NDEBUG
+void showDocumentMarkers(const WebCore::DocumentMarkerController* controller)
+{
+    if (controller)
+        controller->showMarkers();
+}
+#endif
index 96fb7f3cd3237154fa14efff3f9076d0241acb1b..83177fcf8806d7b6ea8a0517184a00ccc073d81d 100644 (file)
@@ -62,6 +62,10 @@ public:
     Vector<DocumentMarker> markersForNode(Node*);
     Vector<IntRect> renderedRectsForMarkers(DocumentMarker::MarkerType = DocumentMarker::AllMarkers);
 
+#ifndef NDEBUG
+    void showMarkers() const;
+#endif
+
 private:
     typedef std::pair<Vector<DocumentMarker>, Vector<IntRect> > MarkerMapVectorPair;
     typedef HashMap<RefPtr<Node>, MarkerMapVectorPair*> MarkerMap;
@@ -71,4 +75,8 @@ private:
 
 } // namespace WebCore
 
+#ifndef NDEBUG
+void showDocumentMarkers(const WebCore::DocumentMarkerController*);
+#endif
+
 #endif // DocumentMarkerController_h
index 767e7059c9d08118574e64ce0f96e47c3584c43d..5de9d9d0621393289d8c11b99691530b529c3ea1 100644 (file)
@@ -98,6 +98,13 @@ void PositionIterator::decrement()
     }
 }
 
+void PositionIterator::setOffsetInLeafNode(int offset)
+{
+    ASSERT(!m_anchorNode->hasChildNodes());
+    ASSERT(0 <= offset && offset <= lastOffsetForEditing(m_anchorNode));
+    m_offsetInAnchor = offset;
+}
+
 bool PositionIterator::atStart() const
 {
     if (!m_anchorNode)
index 7af8977591d16c297931890ebd1ae069c2d47f36..08329bb15cd3e5210046293588ab7aabd30fe4f6 100644 (file)
@@ -56,6 +56,7 @@ public:
 
     Node* node() const { return m_anchorNode; }
     int offsetInLeafNode() const { return m_offsetInAnchor; }
+    void setOffsetInLeafNode(int offset);
 
     bool atStart() const;
     bool atEnd() const;
index 2b22651b52524b4e281db3a513ceec555d5ed56e..5b61f1cf2b1fa22a2e2d8c76aed5c69857a54aff 100644 (file)
 #include "RemoveFormatCommand.h"
 #include "RenderBlock.h"
 #include "RenderPart.h"
+#include "RenderTextControl.h"
 #include "ReplaceSelectionCommand.h"
 #include "Settings.h"
 #include "Sound.h"
+#include "SpellChecker.h"
 #include "Text.h"
 #include "TextEvent.h"
 #include "TextIterator.h"
@@ -423,6 +425,10 @@ void Editor::replaceSelectionWithFragment(PassRefPtr<DocumentFragment> fragment,
     
     applyCommand(ReplaceSelectionCommand::create(m_frame->document(), fragment, selectReplacement, smartReplace, matchStyle));
     revealSelectionAfterEditingOperation();
+
+    Node* nodeToCheck = m_frame->selection()->rootEditableElement();
+    if (m_spellChecker->canCheckAsynchronously(nodeToCheck))
+        m_spellChecker->requestCheckingFor(nodeToCheck);
 }
 
 void Editor::replaceSelectionWithText(const String& text, bool selectReplacement, bool smartReplace)
@@ -1140,6 +1146,7 @@ Editor::Editor(Frame* frame)
     // This is off by default, since most editors want this behavior (this matches IE but not FF).
     , m_shouldStyleWithCSS(false)
     , m_killRing(adoptPtr(new KillRing))
+    , m_spellChecker(new SpellChecker(frame, frame->page() ? frame->page()->editorClient() : 0))
     , m_correctionPanelTimer(this, &Editor::correctionPanelTimerFired)
     , m_areMarkedTextMatchesHighlighted(false)
 {
@@ -3476,12 +3483,29 @@ void Editor::respondToChangedSelection(const VisibleSelection& oldSelection, boo
     respondToChangedSelection(oldSelection);
 }
 
+static Node* findFirstMarkable(Node* node)
+{
+    while (node) {
+        if (!node->renderer())
+            return 0;
+        if (node->renderer()->isText())
+            return node;
+        if (node->renderer()->isTextControl())
+            node = toRenderTextControl(node->renderer())->visiblePositionForIndex(1).deepEquivalent().node();
+        else if (node->firstChild())
+            node = node->firstChild();
+        else
+            node = node->nextSibling();
+    }
+
+    return 0;
+}
+
 bool Editor::selectionStartHasSpellingMarkerFor(int from, int length) const
 {
-    Node* node = m_frame->selection()->start().node();
-    if (!node || !node->renderer())
+    Node* node = findFirstMarkable(m_frame->selection()->start().node());
+    if (!node)
         return false;
-    ASSERT(node->renderer()->isText());
 
     unsigned int startOffset = static_cast<unsigned int>(from);
     unsigned int endOffset = static_cast<unsigned int>(from + length);
index 0e4f2ba2a9ea6b22bdb822d8a8c094ade9a970d0..581a2796d28a427dcfdb494c69739149d3b67009 100644 (file)
@@ -55,6 +55,7 @@ class HitTestResult;
 class KillRing;
 class Pasteboard;
 class SimpleFontData;
+class SpellChecker;
 class Text;
 class TextEvent;
 
@@ -300,6 +301,7 @@ public:
     VisibleSelection selectionForCommand(Event*);
 
     KillRing* killRing() const { return m_killRing.get(); }
+    SpellChecker* spellChecker() const { return m_spellChecker.get(); }
 
     EditingBehavior behavior() const;
 
@@ -385,6 +387,7 @@ private:
     bool m_shouldStyleWithCSS;
     OwnPtr<KillRing> m_killRing;
     CorrectionPanelInfo m_correctionPanelInfo;
+    OwnPtr<SpellChecker> m_spellChecker;
     Timer<Editor> m_correctionPanelTimer;
     bool m_correctionPanelIsDismissedByEditor;
     VisibleSelection m_mark;
diff --git a/WebCore/editing/SpellChecker.cpp b/WebCore/editing/SpellChecker.cpp
new file mode 100644 (file)
index 0000000..1807474
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2010 Google 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 COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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 "SpellChecker.h"
+
+#include "Document.h"
+#include "DocumentMarkerController.h"
+#include "EditorClient.h"
+#include "Frame.h"
+#include "HTMLInputElement.h"
+#include "HTMLTextAreaElement.h"
+#include "Node.h"
+#include "PositionIterator.h"
+#include "Range.h"
+#include "RenderObject.h"
+#include "Settings.h"
+#include "TextIterator.h"
+#include "htmlediting.h"
+
+namespace WebCore {
+
+SpellChecker::SpellChecker(Frame* frame, EditorClient* client)
+    : m_frame(frame)
+    , m_client(client)
+    , m_requestSequence(0)
+{
+}
+
+SpellChecker::~SpellChecker()
+{
+}
+
+bool SpellChecker::initRequest(Node* node)
+{
+    ASSERT(canCheckAsynchronously(node));
+
+    String text = node->textContent();
+    if (!text.length())
+        return false;
+
+    m_requestNode = node;
+    m_requestText = text;
+    m_requestSequence++;
+
+    return true;
+}
+
+void SpellChecker::clearRequest()
+{
+    m_requestNode.clear();
+    m_requestText = String();
+}
+
+bool SpellChecker::isAsynchronousEnabled() const
+{
+    return m_frame->settings() && m_frame->settings()->asynchronousSpellCheckingEnabled();
+}
+
+bool SpellChecker::canCheckAsynchronously(Node* node) const
+{
+    return isCheckable(node) && isAsynchronousEnabled() && !isBusy();
+}
+
+bool SpellChecker::isBusy() const
+{
+    return m_requestNode.get();
+}
+
+bool SpellChecker::isValid(int sequence) const
+{
+    return m_requestNode.get() && m_requestText.length() && m_requestSequence == sequence;
+}
+
+bool SpellChecker::isCheckable(Node* node) const
+{
+    return node && node->renderer();
+}
+
+void SpellChecker::requestCheckingFor(Node* node)
+{
+    ASSERT(canCheckAsynchronously(node));
+
+    if (!initRequest(node))
+        return;
+    m_client->requestCheckingOfString(this, m_requestSequence, m_requestText);
+}
+
+static bool forwardIterator(PositionIterator& iterator, int distance)
+{
+    int remaining = distance;
+    while (!iterator.atEnd()) {
+        if (iterator.node()->isCharacterDataNode()) {
+            int length = lastOffsetForEditing(iterator.node());
+            int last = length - iterator.offsetInLeafNode();
+            if (remaining < last) {
+                iterator.setOffsetInLeafNode(iterator.offsetInLeafNode() + remaining);
+                return true;
+            }
+
+            remaining -= last;
+            iterator.setOffsetInLeafNode(iterator.offsetInLeafNode() + last);
+        }
+
+        iterator.increment();
+    }
+
+    return false;    
+}
+
+void SpellChecker::didCheck(int sequence, const Vector<SpellCheckingResult>& results)
+{
+    if (!isValid(sequence))
+        return;
+
+    if (!m_requestNode->renderer()) {
+        clearRequest();
+        return;
+    }
+
+    int startOffset = 0;
+    PositionIterator start = Position(m_requestNode, 0);
+    for (size_t i = 0; i < results.size(); ++i) {
+        if (results[i].type() != DocumentMarker::Spelling && results[i].type() != DocumentMarker::Grammar)
+            continue;
+
+        // To avoid moving the position backward, we assume the given results are sorted with
+        // startOffset as the ones returned by [NSSpellChecker requestCheckingOfString:].
+        ASSERT(startOffset <= results[i].location());
+        if (!forwardIterator(start, results[i].location() - startOffset))
+            break;
+        PositionIterator end = start;
+        if (!forwardIterator(end, results[i].length()))
+            break;
+
+        // Users or JavaScript applications may change text while a spell-checker checks its
+        // spellings in the background. To avoid adding markers to the words modified by users or
+        // JavaScript applications, retrieve the words in the specified region and compare them with
+        // the original ones.
+        RefPtr<Range> range = Range::create(m_requestNode->document(), start, end);
+        // FIXME: Use textContent() compatible string conversion.
+        String destination = range->text();
+        String source = m_requestText.substring(results[i].location(), results[i].length());
+        if (destination == source)
+            m_requestNode->document()->markers()->addMarker(range.get(), results[i].type());
+
+        startOffset = results[i].location();
+    }
+
+    clearRequest();
+}
+
+
+} // namespace WebCore
diff --git a/WebCore/editing/SpellChecker.h b/WebCore/editing/SpellChecker.h
new file mode 100644 (file)
index 0000000..6922f0e
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2010 Google 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 COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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 SpellChecker_h
+#define SpellChecker_h
+
+#include "Document.h"
+#include <wtf/Noncopyable.h>
+
+namespace WebCore {
+
+class EditorClient;
+class Frame;
+
+class SpellCheckingResult {
+public:
+    explicit SpellCheckingResult(DocumentMarker::MarkerType type = DocumentMarker::Spelling, int location = 0, int length = 0)
+        : m_type(type)
+        , m_location(location)
+        , m_length(length)
+    {
+    }
+
+    DocumentMarker::MarkerType type() const { return m_type; } 
+    int location() const { return m_location; }
+    int length() const { return m_length; }
+
+private:
+    DocumentMarker::MarkerType m_type;
+    int m_location;
+    int m_length;
+};
+
+class SpellChecker : public Noncopyable {
+public:
+    explicit SpellChecker(Frame*, EditorClient*);
+    ~SpellChecker();
+
+    bool isAsynchronousEnabled() const;
+    bool canCheckAsynchronously(Node*) const;
+    bool isBusy() const;
+    bool isValid(int sequence) const;
+    bool isCheckable(Node*) const;
+    void requestCheckingFor(Node*);
+    void didCheck(int sequence, const Vector<SpellCheckingResult>&);
+
+private:
+    bool initRequest(Node*);
+    void clearRequest();
+
+    Frame* m_frame;
+    EditorClient* m_client;
+
+    RefPtr<Node> m_requestNode;
+    String m_requestText;
+    int m_requestSequence;
+};
+
+} // namespace WebCore
+
+#endif // SpellChecker_h
index d3884f564075d2b6c6a417db5eb9420e6e4b5153..b0f18fab0a36cf0491fcf4f18bb2e8e6f3a8db49 100644 (file)
@@ -491,8 +491,7 @@ public:
     virtual void getGuessesForWord(const String&, const String&, Vector<String>&) { }
     virtual void willSetInputMethodState() { }
     virtual void setInputMethodState(bool) { }
-
-
+    virtual void requestCheckingOfString(SpellChecker*, int, const String&) { }
 };
 
 #if ENABLE(CONTEXT_MENUS)
index 64d19a4dba2990cafc661bab9d9a45620ceb1b90..1ec0c7ef331cf29e51e622d1586a0a80de1f37c1 100644 (file)
@@ -66,6 +66,7 @@ class HTMLElement;
 class KeyboardEvent;
 class Node;
 class Range;
+class SpellChecker;
 class VisibleSelection;
 class VisiblePosition;
 
@@ -203,6 +204,7 @@ public:
     virtual void getGuessesForWord(const String& word, const String& context, Vector<String>& guesses) = 0;
     virtual void willSetInputMethodState() = 0;
     virtual void setInputMethodState(bool enabled) = 0;
+    virtual void requestCheckingOfString(SpellChecker*, int, const String&) = 0;
 };
 
 }
index 7dc103b673dc49279f7c4eefe74d4d15022b551e..fc182249be6c4abfddf979ca56b8eeb5545d62ac 100644 (file)
@@ -164,6 +164,7 @@ Settings::Settings(Page* page)
 #if ENABLE(FULLSCREEN_API)
     , m_fullScreenAPIEnabled(false)
 #endif
+    , m_asynchronousSpellCheckingEnabled(false)
     , m_memoryInfoEnabled(false)
     , m_interactiveFormValidation(false)
     , m_usePreHTML5ParserQuirks(false)
index 04b126a28988decc578592cd937e05f46c07b363..f4630de4a942d1f53612232f6d3066a9a2714f6c 100644 (file)
@@ -331,6 +331,9 @@ namespace WebCore {
         bool fullScreenEnabled() const  { return m_fullScreenAPIEnabled; }
 #endif
 
+        void setAsynchronousSpellCheckingEnabled(bool flag) { m_asynchronousSpellCheckingEnabled = flag; }
+        bool asynchronousSpellCheckingEnabled() const  { return m_asynchronousSpellCheckingEnabled; }
+
         void setMemoryInfoEnabled(bool flag) { m_memoryInfoEnabled = flag; }
         bool memoryInfoEnabled() const { return m_memoryInfoEnabled; }
 
@@ -438,6 +441,7 @@ namespace WebCore {
 #if ENABLE(FULLSCREEN_API)
         bool m_fullScreenAPIEnabled : 1;
 #endif
+        bool m_asynchronousSpellCheckingEnabled: 1;
         bool m_memoryInfoEnabled: 1;
         bool m_interactiveFormValidation: 1;
         bool m_usePreHTML5ParserQuirks: 1;
index 5ffbfbbf7beaf82dcf1cf72633da27e313de6c1c..27e695e4c453878176928de92eaa3a7755784295 100644 (file)
@@ -1,3 +1,15 @@
+2010-10-28  MORITA Hajime  <morrita@google.com>
+
+        Reviewed by Ojan Vafai.
+
+        spellcheck does not check pasted text
+        https://bugs.webkit.org/show_bug.cgi?id=40092
+
+        Added a stub implememntation.
+
+        * src/EditorClientImpl.h:
+        (WebKit::EditorClientImpl::requestCheckingOfString):
+
 2010-12-10  Chris Fleizach  <cfleizach@apple.com>
 
         Reviewed by Darin Adler.
index a1943993ac7af58723df9a94be33e5155dbb99ed..9dbd6afb371d6412a0af20e8db7b8518c7887e0e 100644 (file)
@@ -111,6 +111,7 @@ public:
                                    WTF::Vector<WTF::String>& guesses);
     virtual void willSetInputMethodState();
     virtual void setInputMethodState(bool enabled);
+    virtual void requestCheckingOfString(WebCore::SpellChecker*, int, const WTF::String&) {}
 
     // Shows the form autofill popup for |node| if it is an HTMLInputElement and
     // it is empty.  This is called when you press the up or down arrow in a
index 827cfbcfb5f314a7a30ca77f275bb9f0a6ff7334..91c9327199489067ad18a5e76d2fbe34ba39a5fa 100644 (file)
@@ -1,3 +1,15 @@
+2010-10-28  MORITA Hajime  <morrita@google.com>
+
+        Reviewed by Ojan Vafai.
+
+        spellcheck does not check pasted text
+        https://bugs.webkit.org/show_bug.cgi?id=40092
+
+        Added a stub implememntation.
+        
+        * WebCoreSupport/EditorClientEfl.h:
+        (WebCore::EditorClientEfl::requestCheckingOfString):
+
 2010-12-09  Alex Bredariol Grilo  <abgrilo@profusion.mobi>
 
         Reviewed by Antonio Gomes.
index b108ab66707494e4c384b65f04a21c3440589274..e25b1e6f0f244f8b22d6c2032bd793f7fedc43c6 100644 (file)
@@ -113,6 +113,7 @@ public:
     virtual void getGuessesForWord(const String& word, const String& context, WTF::Vector<String>& guesses);
     virtual void willSetInputMethodState();
     virtual void setInputMethodState(bool enabled);
+    virtual void requestCheckingOfString(WebCore::SpellChecker*, int, const WTF::String&) {}
 
 private:
     Evas_Object *m_view;
index d996b3e59283bd72b86c9bdd9b104bdffb90ec2f..67ccc9f0ff7d02ac8a6b4c7a11b0e0b2e2987d31 100644 (file)
@@ -1,3 +1,15 @@
+2010-10-28  MORITA Hajime  <morrita@google.com>
+
+        Reviewed by Ojan Vafai.
+
+        spellcheck does not check pasted text
+        https://bugs.webkit.org/show_bug.cgi?id=40092
+
+        Added a stub implememntation.
+
+        * WebCoreSupport/EditorClientGtk.h:
+        (WebKit::EditorClient::requestCheckingOfString):
+
 2010-12-12  Xan Lopez  <xlopez@igalia.com>
 
         Rubber-stamped by Martin Robinson.
index 22543c61784f73e2ce87074dec08715baa055e66..f2db1d997e2cf760a213fc5dc97f32a07ba3a112 100644 (file)
@@ -132,6 +132,7 @@ namespace WebKit {
         virtual void getGuessesForWord(const WTF::String& word, const WTF::String& context, WTF::Vector<WTF::String>& guesses);
         virtual void willSetInputMethodState();
         virtual void setInputMethodState(bool enabled);
+        virtual void requestCheckingOfString(WebCore::SpellChecker*, int, const WTF::String&) {}
 
     private:
         WebKitWebView* m_webView;
index 65a83f9b7e9d88408bc34ea4fdd6340baa5ce5f7..0c689bc80c14f9935180a27e3d41ae0f1ed85671 100644 (file)
@@ -1,3 +1,15 @@
+2010-10-28  MORITA Hajime  <morrita@google.com>
+
+        Reviewed by Ojan Vafai.
+
+        spellcheck does not check pasted text
+        https://bugs.webkit.org/show_bug.cgi?id=40092
+
+        Added a stub implememntation.
+
+        * WebCoreSupport/EditorClientHaiku.h:
+        (WebCore::EditorClientHaiku::requestCheckingOfString):
+
 2010-12-01  Jia Pu  <jpu@apple.com>
 
         Reviewed by Darin Adler.
index cfde51c1b26678772fdbdafd5380042b8b27410b..ca270e95cb427a3ed7a066f3ee30139349e0468c 100644 (file)
@@ -110,6 +110,7 @@ namespace WebCore {
         virtual void getGuessesForWord(const String& word, const String& context, Vector<String>& guesses);
         virtual void willSetInputMethodState();
         virtual void setInputMethodState(bool enabled);
+        virtual void requestCheckingOfString(SpellChecker*, int, const String&) {}
 
         bool isEditing() const;
 
index 5f936a41f751577471a91b832e906721276536a1..0da82a617a360200b8b921779476f201ef6f5a8d 100644 (file)
@@ -1,3 +1,35 @@
+2010-10-28  MORITA Hajime  <morrita@google.com>
+
+        Reviewed by Ojan Vafai.
+
+        spellcheck does not check pasted text
+        https://bugs.webkit.org/show_bug.cgi?id=40092
+
+        Added asynchronous spell checking API to WebEditorClient using
+        -[NSSpellChecker requestCheckingOfString].
+        Note that WebEditorSpellCheckResponder is a small class to receive
+        requested spell-checking result. Note that this feature is
+        disabled at default.
+        
+        Also added [WebPreferences setAsynchronousSpellCheckingEnabled:] to 
+        enable the feature from LayoutTestController.
+
+        * WebCoreSupport/WebEditorClient.h:
+        * WebCoreSupport/WebEditorClient.mm:
+        (-[WebEditorSpellCheckResponder initWithSender:WebCore::sequence:results:]):
+        (-[WebEditorSpellCheckResponder perform]):
+        (toCoreSpellingResult):
+        (-[WebEditorSpellCheckResponder WTF::WebCore::]):
+        (WebEditorClient::requestCheckingOfString):
+        * WebView/WebPreferenceKeysPrivate.h:
+        * WebView/WebPreferences.mm:
+        (+[WebPreferences initialize]):
+        (-[WebPreferences setAsynchronousSpellCheckingEnabled:]):
+        (-[WebPreferences asynchronousSpellCheckingEnabled]):
+        * WebView/WebPreferencesPrivate.h:
+        * WebView/WebView.mm:
+        (-[WebView _preferencesChangedNotification:]):
+
 2010-12-09  Anders Carlsson  <andersca@apple.com>
 
         Fix a bug uncovered by clang++.
         (-[WebView setEditable:]):
         Changed call sites to use editor().
 
+2010-09-08  MORITA Hajime  <morrita@google.com>
+
+        Reviewed by Ojan Vafai.
+
+        spellcheck does not check pasted text
+        https://bugs.webkit.org/show_bug.cgi?id=40092
+
+        Implemented async spell-check APIs on WebEditorClient.
+        The implementations are using [NSSpellChecker requestCheckingOfString]
+        which is available only on Mac OS 10.6 or later.
+        
+        Note that [NSSpellChecker requestCheckingOfString] could invoke
+        the callback block on on of their worker thread, so we need to
+        return the result to the main thread where WebCore is running.
+        For that purpose, we made WebEditorSpellCheckResponder class.
+        
+        Test: editing/spelling/spellcheck-pasted-text-001.html
+        
+        * WebCoreSupport/WebEditorClient.h:
+        * WebCoreSupport/WebEditorClient.mm:
+        (WebEditorClient::isAsynchronousSpellCheckingEnabled): Added.
+        (-[WebEditorSpellCheckResponder initWithSender:WebCore::sequence:results:]): Added.
+        (-[WebEditorSpellCheckResponder perform]): Added.
+        (WebEditorClient::requestCheckingOfString): Added.
+        * WebView/WebFramePrivate.h:
+
 2010-09-08  MORITA Hajime  <morrita@google.com>
 
         Reviewed by Tony Chang.
index 8b6e3f94f053488348732a977cf47ff6450a3175..8a54ca9a521674991385b4d26c1937438ae3900f 100644 (file)
@@ -132,6 +132,7 @@ public:
     virtual void getGuessesForWord(const WTF::String& word, const WTF::String& context, WTF::Vector<WTF::String>& guesses);
     virtual void willSetInputMethodState();
     virtual void setInputMethodState(bool enabled);
+    virtual void requestCheckingOfString(WebCore::SpellChecker*, int, const WTF::String&);
 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
     virtual void showCorrectionPanel(WebCore::CorrectionPanelInfo::PanelType, const WebCore::FloatRect& boundingBoxOfReplacedString, const WTF::String& replacedString, const WTF::String& replacementString, const WTF::Vector<WTF::String>& alternativeReplacementStrings, WebCore::Editor*);
     virtual void dismissCorrectionPanel(WebCore::ReasonForDismissingCorrectionPanel);
index 455aa9ad1d1d8f233a17fe86cf7eabb2de398909..d3b38de23668c58cfff75b800a97c4abc05dfea4 100644 (file)
@@ -63,6 +63,7 @@
 #import <WebCore/LegacyWebArchive.h>
 #import <WebCore/PlatformKeyboardEvent.h>
 #import <WebCore/PlatformString.h>
+#import <WebCore/SpellChecker.h>
 #import <WebCore/UserTypingGestureIndicator.h>
 #import <WebCore/WebCoreObjCExtras.h>
 #import <runtime/InitializeThreading.h>
@@ -990,3 +991,73 @@ void WebEditorClient::willSetInputMethodState()
 void WebEditorClient::setInputMethodState(bool)
 {
 }
+
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+@interface WebEditorSpellCheckResponder : NSObject
+{
+    WebCore::SpellChecker* _sender;
+    int _sequence;
+    RetainPtr<NSArray> _results;
+}
+- (id)initWithSender:(WebCore::SpellChecker*)sender sequence:(int)sequence results:(NSArray*)results;
+- (void)perform;
+- (WTF::Vector<WebCore::SpellCheckingResult>) _coreResults;
+@end
+
+@implementation WebEditorSpellCheckResponder
+- (id)initWithSender:(WebCore::SpellChecker*)sender sequence:(int)sequence results:(NSArray*)results
+{
+    self = [super init];
+    if (!self)
+        return nil;
+    _sender = sender;
+    _sequence = sequence;
+    _results = results;
+    return self;
+}
+
+- (void)perform
+{
+    _sender->didCheck(_sequence, [self _coreResults]);
+}
+
+static SpellCheckingResult toCoreSpellingResult(NSTextCheckingResult* result)
+{
+    NSTextCheckingType type = [result resultType];
+    NSRange range = [result range];
+    DocumentMarker::MarkerType coreType;
+    if (type & NSTextCheckingTypeSpelling)
+        coreType = DocumentMarker::Spelling;
+    else if (type & NSTextCheckingTypeGrammar)
+        coreType = DocumentMarker::Grammar;
+    else
+        coreType = DocumentMarker::AllMarkers;
+
+    return SpellCheckingResult(coreType, range.location, range.length);
+}
+
+- (WTF::Vector<WebCore::SpellCheckingResult>)_coreResults
+{
+    WTF::Vector<WebCore::SpellCheckingResult> coreResults;
+    coreResults.reserveCapacity([_results.get() count]);
+    for (NSTextCheckingResult* result in _results.get())
+        coreResults.append(toCoreSpellingResult(result));
+    return coreResults;
+}
+
+@end
+#endif
+
+void WebEditorClient::requestCheckingOfString(WebCore::SpellChecker* sender, int sequence, const String& text)
+{
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+    NSRange range = NSMakeRange(0, text.length());
+    NSRunLoop* currentLoop = [NSRunLoop currentRunLoop];
+    [[NSSpellChecker sharedSpellChecker] requestCheckingOfString:text range:range types:NSTextCheckingAllSystemTypes options:0 inSpellDocumentWithTag:0 
+                                         completionHandler:^(NSInteger, NSArray* results, NSOrthography*, NSInteger) {
+            [currentLoop performSelector:@selector(perform) 
+                                  target:[[[WebEditorSpellCheckResponder alloc] initWithSender:sender sequence:sequence results:results] autorelease]
+                                argument:nil order:0 modes:[NSArray arrayWithObject:NSDefaultRunLoopMode]];
+        }];
+#endif
+}
index 5c6b5301036db3a4d525389dcda5b53618c46958..93f83fc515aa9672ef33ef0633da13e53452da57 100644 (file)
@@ -99,6 +99,7 @@
 #define WebKitPaginateDuringLayoutEnabledPreferenceKey @"WebKitPaginateDuringLayoutEnabled"
 #define WebKitDNSPrefetchingEnabledPreferenceKey @"WebKitDNSPrefetchingEnabled"
 #define WebKitFullScreenEnabledPreferenceKey @"WebKitFullScreenEnabled"
+#define WebKitAsynchronousSpellCheckingEnabledPreferenceKey @"WebKitAsynchronousSpellCheckingEnabled"
 #define WebKitMemoryInfoEnabledPreferenceKey @"WebKitMemoryInfoEnabled"
 #define WebKitHyperlinkAuditingEnabledPreferenceKey @"WebKitHyperlinkAuditingEnabled"
 
index e0844254b931b3aec53b9cddcf748e41bd4e5201..3817d4ac26aeb9e1def1bc7468dfed617ea3b640 100644 (file)
@@ -367,6 +367,7 @@ static WebCacheModel cacheModelForMainBundle(void)
         [NSNumber numberWithBool:NO],   WebKitSpatialNavigationEnabledPreferenceKey,
         [NSNumber numberWithBool:YES],  WebKitDNSPrefetchingEnabledPreferenceKey,
         [NSNumber numberWithBool:NO],   WebKitFullScreenEnabledPreferenceKey,
+        [NSNumber numberWithBool:NO],   WebKitAsynchronousSpellCheckingEnabledPreferenceKey,
         [NSNumber numberWithBool:NO],   WebKitMemoryInfoEnabledPreferenceKey,
         [NSNumber numberWithBool:YES],  WebKitHyperlinkAuditingEnabledPreferenceKey,
         [NSNumber numberWithBool:NO],   WebKitUsePreHTML5ParserQuirksKey,
@@ -1393,6 +1394,16 @@ static NSString *classIBCreatorID = nil;
     return [self _boolValueForKey:WebKitFullScreenEnabledPreferenceKey];
 }
 
+- (void)setAsynchronousSpellCheckingEnabled:(BOOL)flag
+{
+    [self _setBoolValue:flag forKey:WebKitAsynchronousSpellCheckingEnabledPreferenceKey];
+}
+
+- (BOOL)asynchronousSpellCheckingEnabled
+{
+    return [self _boolValueForKey:WebKitAsynchronousSpellCheckingEnabledPreferenceKey];
+}
+
 + (void)setWebKitLinkTimeVersion:(int)version
 {
     setWebKitLinkTimeVersion(version);
index 2ee07d7e59d01110d2d53640eefa6c4e33344d0f..89b6288beba384a1345b023439c2406803c50d6d 100644 (file)
@@ -221,6 +221,9 @@ extern NSString *WebPreferencesRemovedNotification;
 - (void)setFullScreenEnabled:(BOOL)flag;
 - (BOOL)fullScreenEnabled;
 
+- (void)setAsynchronousSpellCheckingEnabled:(BOOL)flag;
+- (BOOL)asynchronousSpellCheckingEnabled;
+
 - (void)setUsePreHTML5ParserQuirks:(BOOL)flag;
 - (BOOL)usePreHTML5ParserQuirks;
 
index 527b5636c8ca00df740f9b86a899e759b17645d0..ee62f6177efa27ae622e1f8da93a9500a7208c12 100644 (file)
@@ -1504,6 +1504,10 @@ static bool fastDocumentTeardownEnabled()
     settings->setPaginateDuringLayoutEnabled([preferences paginateDuringLayoutEnabled]);
 #if ENABLE(FULLSCREEN_API)
     settings->setFullScreenEnabled([preferences fullScreenEnabled]);
+#endif
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+    // Asynchronous spell checking API is available for 10.6 or later.
+    settings->setAsynchronousSpellCheckingEnabled([preferences asynchronousSpellCheckingEnabled]);
 #endif
     settings->setMemoryInfoEnabled([preferences memoryInfoEnabled]);
     settings->setHyperlinkAuditingEnabled([preferences hyperlinkAuditingEnabled]);
index fef2d75d20cde5dedfae75e7d2543c54e0078792..ed8201fd07dd457b7542addcbd883eb6c824a910 100644 (file)
@@ -1,3 +1,15 @@
+2010-10-28  MORITA Hajime  <morrita@google.com>
+
+        Reviewed by Ojan Vafai.
+
+        spellcheck does not check pasted text
+        https://bugs.webkit.org/show_bug.cgi?id=40092
+
+        Added a stub implememntation.
+
+        * WebCoreSupport/EditorClientQt.h:
+        (WebCore::EditorClientQt::requestCheckingOfString):
+
 2010-12-11  Yi Shen  <yi.4.shen@nokia.com>
 
         Reviewed by Kenneth Rohde Christiansen.
index defa8bb997613e8cd415d4590cb38ba680fa7b1e..1e410e6d7ed34b398ff2e00b62e4deb9178f44cf 100644 (file)
@@ -107,6 +107,7 @@ public:
     virtual void getGuessesForWord(const String& word, const String& context, Vector<String>& guesses);
     virtual void willSetInputMethodState();
     virtual void setInputMethodState(bool enabled);
+    virtual void requestCheckingOfString(SpellChecker*, int, const String&) {}
 
     bool isEditing() const;
 
index c2a111edc4f1a8a1ba554e3d4a71d42209ad76b1..d4ceb67b2680d32943977ce72388b91672aa12fb 100644 (file)
@@ -1,3 +1,15 @@
+2010-10-28  MORITA Hajime  <morrita@google.com>
+
+        Reviewed by Ojan Vafai.
+
+        spellcheck does not check pasted text
+        https://bugs.webkit.org/show_bug.cgi?id=40092
+
+        Added a stub implememntation.
+
+        * WebCoreSupport/WebEditorClient.h:
+        (WebEditorClient::requestCheckingOfString):
+
 2010-12-10  Chris Fleizach  <cfleizach@apple.com>
 
         Reviewed by Darin Adler.
index f0b78ba2d5eedf74a02a3d75e3f70726048b03a9..358a3656a6df604b122a09d0d0ea105eafa48913 100644 (file)
@@ -111,6 +111,7 @@ public:
 
     virtual void willSetInputMethodState();
     virtual void setInputMethodState(bool);
+    virtual void requestCheckingOfString(WebCore::SpellChecker*, int, const WTF::String&) {}
 
 private:
     WebView* m_webView;
index 31f55432a34ad1728bacc42d9300361ce56ba931..741e527f1763c3d0b454769e62f00a61f17ee251 100644 (file)
@@ -1,3 +1,15 @@
+2010-10-28  MORITA Hajime  <morrita@google.com>
+
+        Reviewed by Ojan Vafai.
+
+        spellcheck does not check pasted text
+        https://bugs.webkit.org/show_bug.cgi?id=40092
+
+        Added a stub implememntation.
+
+        * WebCoreSupport/EditorClientWinCE.h:
+        (WebKit::EditorClient::requestCheckingOfString):
+
 2010-12-07  Martin Robinson  <mrobinson@igalia.com>
 
         Unreviewed, rolling out r73392.
index fd3dd10c46a1aae7a423a96510488c0bd5e1ee57..8db8c168462f8ddb3c00ac7dc4c1e76dcd49bfad 100644 (file)
@@ -100,6 +100,7 @@ public:
     virtual void getGuessesForWord(const WTF::String& word, const WTF::String& context, WTF::Vector<WTF::String>& guesses);
     virtual void willSetInputMethodState();
     virtual void setInputMethodState(bool);
+    virtual void requestCheckingOfString(WebCore::SpellChecker*, int, const WTF::String&) {}
 
 private:
     WebView* m_webView;
index ae7f240ce21a9aab112def11869807248b5c4622..975468a81d14239d18c0ff8bcc4e972030e4aa0f 100644 (file)
@@ -1,3 +1,15 @@
+2010-10-28  MORITA Hajime  <morrita@google.com>
+
+        Reviewed by Ojan Vafai.
+
+        spellcheck does not check pasted text
+        https://bugs.webkit.org/show_bug.cgi?id=40092
+
+        Added a stub implememntation.
+
+        * WebKitSupport/EditorClientWx.h:
+        (WebCore::EditorClientWx::requestCheckingOfString):
+
 2010-12-07  Martin Robinson  <mrobinson@igalia.com>
 
         Unreviewed, rolling out r73392.
index 35a95abc8a94a0f688336e1d8966c7cb53df952e..7dbee31a5f944a48ddcd31dd5b8a8e02a52e6bf0 100644 (file)
@@ -112,6 +112,7 @@ public:
 
     virtual void willSetInputMethodState();
     virtual void setInputMethodState(bool enabled);
+    virtual void requestCheckingOfString(WebCore::SpellChecker*, int, const WTF::String&) {}
 
 private:
     Page* m_page;
index 2370c8cdb170130e12dc95049517760586a676e9..758a7fe8dd5d8ba2357f2e1ff6d2f4234b8adaa6 100644 (file)
@@ -1,3 +1,16 @@
+2010-10-28  MORITA Hajime  <morrita@google.com>
+
+        Reviewed by Ojan Vafai.
+
+        spellcheck does not check pasted text
+        https://bugs.webkit.org/show_bug.cgi?id=40092
+
+        Added a stub implememntation.
+
+        * WebProcess/WebCoreSupport/WebEditorClient.cpp:
+        (WebKit::WebEditorClient::requestCheckingOfString):
+        * WebProcess/WebCoreSupport/WebEditorClient.h:
+
 2010-12-12  Brian Weinstein  <bweinstein@apple.com>
 
         Reviewed by Tim Hatcher.
index 9fa9b00cac714c607e6a4801f22809eb8f933b00..563e2481b679d4034247491b06542147363febd5 100644 (file)
@@ -410,4 +410,9 @@ void WebEditorClient::setInputMethodState(bool)
     notImplemented();
 }
 
+void WebEditorClient::requestCheckingOfString(WebCore::SpellChecker*, int, const WTF::String&)
+{
+    notImplemented();
+}
+
 } // namespace WebKit
index ccdaf43032defced1ca9b09d528d187b9bca5b33..1e340dda941fe8d9c0bbe98cfa36db024ca667b1 100644 (file)
@@ -133,6 +133,7 @@ private:
     virtual void getGuessesForWord(const String& word, const String& context, Vector<String>& guesses);
     virtual void willSetInputMethodState();
     virtual void setInputMethodState(bool enabled);
+    virtual void requestCheckingOfString(WebCore::SpellChecker*, int, const WTF::String&);
 #if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
     virtual void showCorrectionPanel(WebCore::CorrectionPanelInfo::PanelType, const WebCore::FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings, WebCore::Editor*);
     virtual void dismissCorrectionPanel(WebCore::ReasonForDismissingCorrectionPanel);
index 20df9bea3c3a21ee065ae267b6db8c156a9f06c2..62f30ae34e611b6efa7cd52ec3a326a18b486677 100644 (file)
@@ -1,3 +1,35 @@
+2010-10-28  MORITA Hajime  <morrita@google.com>
+
+        Reviewed by Ojan Vafai.
+
+        spellcheck does not check pasted text
+        https://bugs.webkit.org/show_bug.cgi?id=40092
+
+        Added LayoutTestController::setAsynchronousSpellCheckingEnabled()
+        to control the setting.
+
+        * DumpRenderTree/LayoutTestController.cpp:
+        (setAsynchronousSpellCheckingEnabledCallback):
+        (LayoutTestController::staticFunctions):
+        * DumpRenderTree/LayoutTestController.h:
+        * DumpRenderTree/chromium/LayoutTestController.h:
+        * DumpRenderTree/chromium/LayoutTestController.cpp:
+        (LayoutTestController::LayoutTestController):
+        (LayoutTestController::setAsynchronousSpellCheckingEnabled):
+        * DumpRenderTree/gtk/LayoutTestControllerGtk.cpp:
+        (LayoutTestController::setAsynchronousSpellCheckingEnabled):
+        * DumpRenderTree/mac/DumpRenderTree.mm:
+        (resetDefaultsToConsistentValues):
+        * DumpRenderTree/mac/LayoutTestControllerMac.mm:
+        (LayoutTestController::setAsynchronousSpellCheckingEnabled):
+        * DumpRenderTree/qt/LayoutTestControllerQt.h:
+        * DumpRenderTree/qt/LayoutTestControllerQt.cpp:
+        (LayoutTestController::setAsynchronousSpellCheckingEnabled):
+        * DumpRenderTree/win/LayoutTestControllerWin.cpp:
+        (LayoutTestController::setAsynchronousSpellCheckingEnabled):
+        * DumpRenderTree/wx/LayoutTestControllerWx.cpp:
+        (LayoutTestController::setAsynchronousSpellCheckingEnabled):
+
 2010-12-12  Sam Weinig  <sam@webkit.org>
 
         Reviewed by Anders Carlsson.
index 5bbd3f6e8f49c48b8d9159a393a02abc9d750778..2270160601666e8cc8b08ac6fd31ea30f2a0d1da 100644 (file)
@@ -1518,6 +1518,16 @@ static JSValueRef setStopProvisionalFrameLoadsCallback(JSContextRef context, JSO
     return JSValueMakeUndefined(context);
 }
 
+static JSValueRef setAsynchronousSpellCheckingEnabledCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+    if (argumentCount < 1)
+        return JSValueMakeUndefined(context);
+
+    LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
+    controller->setAsynchronousSpellCheckingEnabled(JSValueToBoolean(context, arguments[0]));
+    return JSValueMakeUndefined(context);
+}
+
 static JSValueRef showWebInspectorCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
 {
     LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
@@ -2035,6 +2045,7 @@ JSStaticFunction* LayoutTestController::staticFunctions()
         { "setWindowIsKey", setWindowIsKeyCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
         { "setJavaScriptCanAccessClipboard", setJavaScriptCanAccessClipboardCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
         { "setXSSAuditorEnabled", setXSSAuditorEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+        { "setAsynchronousSpellCheckingEnabled", setAsynchronousSpellCheckingEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
         { "showWebInspector", showWebInspectorCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
         { "testOnscreen", testOnscreenCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
         { "testRepaint", testRepaintCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
index e39c9391ca957810e527923c1b6a57eb6d8d6cce..21d6add2ad6f6476f7bab120b70908c606788ee6 100644 (file)
@@ -271,6 +271,7 @@ public:
     bool geolocationPermission() const { return m_geolocationPermission; }
 
     void setDeveloperExtrasEnabled(bool);
+    void setAsynchronousSpellCheckingEnabled(bool);
     void showWebInspector();
     void closeWebInspector();
     void setTimelineProfilingEnabled(bool enabled);
index d252c63b4506d31dbb15c7d95dbec9248b7e16d3..e3af738313ffa99bcd1be06c131e5bf24dd30f91 100644 (file)
@@ -170,6 +170,7 @@ LayoutTestController::LayoutTestController(TestShell* shell)
     bindMethod("setWillSendRequestReturnsNullOnRedirect", &LayoutTestController::setWillSendRequestReturnsNullOnRedirect);
     bindMethod("setWindowIsKey", &LayoutTestController::setWindowIsKey);
     bindMethod("setXSSAuditorEnabled", &LayoutTestController::setXSSAuditorEnabled);
+    bindMethod("setAsynchronousSpellCheckingEnabled", &LayoutTestController::setAsynchronousSpellCheckingEnabled);
     bindMethod("showWebInspector", &LayoutTestController::showWebInspector);
     bindMethod("simulateDesktopNotificationClick", &LayoutTestController::simulateDesktopNotificationClick);
     bindMethod("suspendAnimations", &LayoutTestController::suspendAnimations);
@@ -623,6 +624,11 @@ void LayoutTestController::setAlwaysAcceptCookies(const CppArgumentList& argumen
     result->setNull();
 }
 
+void LayoutTestController::setAsynchronousSpellCheckingEnabled(const CppArgumentList&, CppVariant*)
+{
+    // FIXME: Implement this.
+}
+
 void LayoutTestController::showWebInspector(const CppArgumentList&, CppVariant* result)
 {
     m_shell->showDevTools();
index 03affa3954e4654a8b325701420297b87059e7c1..13d14475856f0978d2204fb82b3057bb6de526a3 100644 (file)
@@ -152,6 +152,9 @@ public:
     // Changes the cookie policy from the default to allow all cookies.
     void setAlwaysAcceptCookies(const CppArgumentList&, CppVariant*);
 
+    // Changes asynchronous spellchecking flag on the settings.
+    void setAsynchronousSpellCheckingEnabled(const CppArgumentList&, CppVariant*);
+
     // Shows DevTools window.
     void showWebInspector(const CppArgumentList&, CppVariant*);
     void closeWebInspector(const CppArgumentList&, CppVariant*);
index 7380d7590464ee59db0467dbe6cfe4aa2ee4da18..33a3727fd7101c8213fff43b18c88862b8cee072 100644 (file)
@@ -732,6 +732,11 @@ void LayoutTestController::setDeveloperExtrasEnabled(bool enabled)
     g_object_set(webSettings, "enable-developer-extras", enabled, NULL);
 }
 
+void LayoutTestController::setAsynchronousSpellCheckingEnabled(bool)
+{
+    // FIXME: Implement this.
+}
+
 void LayoutTestController::showWebInspector()
 {
     WebKitWebView* webView = webkit_web_frame_get_web_view(mainFrame);
index c08aee5f1f00907dc027f6fc2b67f9e36fd127f7..5cf60ef2281233a266f5cf35e11a9bdd4f2373ed 100644 (file)
@@ -461,6 +461,7 @@ static void resetDefaultsToConsistentValues()
     [preferences setAcceleratedCompositingEnabled:YES];
     [preferences setWebGLEnabled:NO];
     [preferences setUsePreHTML5ParserQuirks:NO];
+    [preferences setAsynchronousSpellCheckingEnabled:NO];
 
     [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain];
 
index 5df941d3ef1fb3c6b722c146267fbbe36091a933..b0be44fa6eb4a50b6f8ddb843a3533a7937b5298 100644 (file)
@@ -746,6 +746,11 @@ void LayoutTestController::setDeveloperExtrasEnabled(bool enabled)
     [[[mainFrame webView] preferences] setDeveloperExtrasEnabled:enabled];
 }
 
+void LayoutTestController::setAsynchronousSpellCheckingEnabled(bool enabled)
+{
+    [[[mainFrame webView] preferences] setAsynchronousSpellCheckingEnabled:enabled];
+}
+
 void LayoutTestController::showWebInspector()
 {
     [[[mainFrame webView] inspector] show:nil];
index 2d00c3e57edd36e08b4b81341673dc80a89e9681..b8cc9be6571a1a5584c497b9644fd7aaeadf7db9 100644 (file)
@@ -384,6 +384,11 @@ void LayoutTestController::setDeveloperExtrasEnabled(bool enabled)
     m_drt->webPage()->settings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, enabled);
 }
 
+void LayoutTestController::setAsynchronousSpellCheckingEnabled(bool)
+{
+    // FIXME: Implement this.
+}
+
 void LayoutTestController::showWebInspector()
 {
     m_drt->webPage()->settings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true);
index 5fddef16f5fe5c133806292951eeb0b4580e0f1f..0048a7efc6632317c879121d01094d571181f9d1 100644 (file)
@@ -140,6 +140,7 @@ public slots:
     QString decodeHostName(const QString& host);
     void dumpSelectionRect() const {}
     void setDeveloperExtrasEnabled(bool);
+    void setAsynchronousSpellCheckingEnabled(bool);
     void showWebInspector();
     void closeWebInspector();
     void evaluateInWebInspector(long callId, const QString& script);
index edb0517df391b3d7de2b4a602fa84fadc75ad9e3..2c4a52dea77cb72bdfedab0fbffa0b3189aa79d7 100644 (file)
@@ -1174,6 +1174,11 @@ void LayoutTestController::setDeveloperExtrasEnabled(bool enabled)
     prefsPrivate->setDeveloperExtrasEnabled(enabled);
 }
 
+void LayoutTestController::setAsynchronousSpellCheckingEnabled(bool)
+{
+    // FIXME: Implement this.
+}
+
 void LayoutTestController::showWebInspector()
 {
     COMPtr<IWebView> webView;
index 714a4c43ca9c48367dd7648c9e433ca867c01564..32b5f7e2e5848b553f958f5dc861d702c199ad22 100644 (file)
@@ -534,6 +534,11 @@ JSRetainPtr<JSStringRef> LayoutTestController::pageSizeAndMarginsInPixels(int pa
     return 0;
 }
 
+void LayoutTestController::setAsynchronousSpellCheckingEnabled(bool)
+{
+    // FIXME: Implement this.
+}
+
 bool LayoutTestController::findString(JSContextRef context, JSStringRef target, JSObjectRef optionsArray)
 {
     // FIXME: Implement