| Differences between
and this patch
- a/Source/WebCore/ChangeLog +32 lines
Lines 1-3 a/Source/WebCore/ChangeLog_sec1
1
2011-11-30  Shinya Kawanaka  <shinyak@google.com>
2
3
        Asynchronous SpellChecker should consider multiple requests.
4
        https://bugs.webkit.org/show_bug.cgi?id=72939
5
6
        Reviewed by NOBODY (OOPS!).
7
8
        Now SpellChecker saves a request when it is processing the previous spellcheck request.
9
        Currently only the latest request is saved.
10
11
        Test: editing/spelling/spellcheck-queue.html
12
13
        * editing/SpellChecker.cpp:
14
        (WebCore::SpellChecker::SpellCheckRequest::SpellCheckRequest):
15
          A structure to have spell check request.
16
        (WebCore::SpellChecker::SpellCheckRequest::sequence):
17
        (WebCore::SpellChecker::SpellCheckRequest::range):
18
        (WebCore::SpellChecker::SpellCheckRequest::text):
19
        (WebCore::SpellChecker::SpellCheckRequest::mask):
20
        (WebCore::SpellChecker::SpellChecker):
21
        (WebCore::SpellChecker::createRequest):
22
        (WebCore::SpellChecker::timerFiredToProcessQueuedRequest):
23
          When timer is fired, queued request is processed if any.
24
        (WebCore::SpellChecker::processQueuedRequest):
25
          Sets a timer.
26
        (WebCore::SpellChecker::isAsynchronousEnabled):
27
        (WebCore::SpellChecker::canCheckAsynchronously):
28
        (WebCore::SpellChecker::doRequestCheckingFor):
29
          When the spellchecker is processing another request, the latest request is queued.
30
        (WebCore::SpellChecker::didCheck):
31
        * editing/SpellChecker.h:
32
1
2011-11-30  Leo Yang  <leo.yang@torchmobile.com.cn>
33
2011-11-30  Leo Yang  <leo.yang@torchmobile.com.cn>
2
34
3
        [BlackBerry] Add 2 cpp files to the BlackBerry build system
35
        [BlackBerry] Add 2 cpp files to the BlackBerry build system
- a/Source/WebCore/editing/SpellChecker.cpp -33 / +59 lines
Lines 45-53 a/Source/WebCore/editing/SpellChecker.cpp_sec1
45
45
46
namespace WebCore {
46
namespace WebCore {
47
47
48
class SpellChecker::SpellCheckRequest {
49
public:
50
    SpellCheckRequest(int sequence, PassRefPtr<Range> range, const String& text, TextCheckingTypeMask mask)
51
        : m_sequence(sequence)
52
        , m_range(range)
53
        , m_text(text)
54
        , m_mask(mask)
55
    {
56
    }
57
58
    int sequence() const { return m_sequence; }
59
    Range* range() const { return m_range.get(); }
60
    const String& text() const { return m_text; }
61
    TextCheckingTypeMask mask() const { return m_mask; }
62
63
private:
64
    int m_sequence;
65
    RefPtr<Range> m_range;
66
    String m_text;
67
    TextCheckingTypeMask m_mask;
68
};
69
48
SpellChecker::SpellChecker(Frame* frame)
70
SpellChecker::SpellChecker(Frame* frame)
49
    : m_frame(frame)
71
    : m_frame(frame)
50
    , m_requestSequence(0)
72
    , m_lastRequestedSequence(0)
73
    , m_timerToProcessQueuedRequest(this, &SpellChecker::timerFiredToProcessQueuedRequest)
51
{
74
{
52
}
75
}
53
76
Lines 63-107 TextCheckerClient* SpellChecker::client() const a/Source/WebCore/editing/SpellChecker.cpp_sec2
63
    return page->editorClient()->textChecker();
86
    return page->editorClient()->textChecker();
64
}
87
}
65
88
66
bool SpellChecker::initRequest(PassRefPtr<Range> range)
89
PassOwnPtr<SpellChecker::SpellCheckRequest> SpellChecker::createRequest(TextCheckingTypeMask mask, PassRefPtr<Range> range)
67
{
90
{
68
    ASSERT(canCheckAsynchronously(range.get()));
91
    ASSERT(canCheckAsynchronously(range.get()));
69
92
70
    String text = range->text();
93
    String text = range->text();
71
    if (!text.length())
94
    if (!text.length())
72
        return false;
95
        return PassOwnPtr<SpellCheckRequest>();
73
74
    m_requestRange = range;
75
    m_requestText = text;
76
    m_requestSequence++;
77
96
78
    return true;
97
    return adoptPtr(new SpellCheckRequest(++m_lastRequestedSequence, range, text, mask));
79
}
98
}
80
99
81
void SpellChecker::clearRequest()
100
void SpellChecker::timerFiredToProcessQueuedRequest(Timer<SpellChecker>*)
82
{
101
{
83
    m_requestRange.clear();
102
    if (!m_queuedRequest.get())
84
    m_requestText = String();
103
        return;
85
}
86
104
87
bool SpellChecker::isAsynchronousEnabled() const
105
    m_processingRequest = m_queuedRequest.release();
88
{
106
    client()->requestCheckingOfString(this, m_processingRequest->sequence(), m_processingRequest->mask(), m_processingRequest->text());
89
    return m_frame->settings() && m_frame->settings()->asynchronousSpellCheckingEnabled();
90
}
107
}
91
108
92
bool SpellChecker::canCheckAsynchronously(Range* range) const
109
void SpellChecker::processQueuedRequest()
93
{
110
{
94
    return client() && isCheckable(range) && isAsynchronousEnabled() && !isBusy();
111
    m_processingRequest.clear();
112
    if (!m_queuedRequest.get())
113
        return;
114
115
    m_timerToProcessQueuedRequest.startOneShot(0);
95
}
116
}
96
117
97
bool SpellChecker::isBusy() const
118
bool SpellChecker::isAsynchronousEnabled() const
98
{
119
{
99
    return m_requestRange.get();
120
    return m_frame->settings() && m_frame->settings()->asynchronousSpellCheckingEnabled();
100
}
121
}
101
122
102
bool SpellChecker::isValid(int sequence) const
123
bool SpellChecker::canCheckAsynchronously(Range* range) const
103
{
124
{
104
    return m_requestRange.get() && m_requestText.length() && m_requestSequence == sequence;
125
    return client() && isCheckable(range) && isAsynchronousEnabled();
105
}
126
}
106
127
107
bool SpellChecker::isCheckable(Range* range) const
128
bool SpellChecker::isCheckable(Range* range) const
Lines 121-129 void SpellChecker::doRequestCheckingFor(TextCheckingTypeMask mask, PassRefPtr<Ra a/Source/WebCore/editing/SpellChecker.cpp_sec3
121
{
142
{
122
    ASSERT(canCheckAsynchronously(range.get()));
143
    ASSERT(canCheckAsynchronously(range.get()));
123
144
124
    if (!initRequest(range))
145
    OwnPtr<SpellCheckRequest> request(createRequest(mask, range));
146
    if (!request)
125
        return;
147
        return;
126
    client()->requestCheckingOfString(this, m_requestSequence, mask, m_requestText);
148
149
    if (m_processingRequest) {
150
        m_queuedRequest = request.release();
151
        return;
152
    }
153
154
    client()->requestCheckingOfString(this, request->sequence(), request->mask(), request->text());
155
    m_processingRequest = request.release();
127
}
156
}
128
157
129
static bool forwardIterator(PositionIterator& iterator, int distance)
158
static bool forwardIterator(PositionIterator& iterator, int distance)
Lines 159-174 static DocumentMarker::MarkerType toMarkerType(TextCheckingType type) a/Source/WebCore/editing/SpellChecker.cpp_sec4
159
// Currenntly ignoring TextCheckingResult::details but should be handled. See Bug 56368.
188
// Currenntly ignoring TextCheckingResult::details but should be handled. See Bug 56368.
160
void SpellChecker::didCheck(int sequence, const Vector<TextCheckingResult>& results)
189
void SpellChecker::didCheck(int sequence, const Vector<TextCheckingResult>& results)
161
{
190
{
162
    if (!isValid(sequence))
191
    ASSERT(m_processingRequest);
163
        return;
164
192
165
    if (!isCheckable(m_requestRange.get())) {
193
    if (m_processingRequest->sequence() != sequence)
166
        clearRequest();
167
        return;
194
        return;
168
    }
169
195
170
    int startOffset = 0;
196
    int startOffset = 0;
171
    PositionIterator start = m_requestRange->startPosition();
197
    PositionIterator start = m_processingRequest->range()->startPosition();
172
    for (size_t i = 0; i < results.size(); ++i) {
198
    for (size_t i = 0; i < results.size(); ++i) {
173
        if (results[i].type != TextCheckingTypeSpelling && results[i].type != TextCheckingTypeGrammar)
199
        if (results[i].type != TextCheckingTypeSpelling && results[i].type != TextCheckingTypeGrammar)
174
            continue;
200
            continue;
Lines 186-202 void SpellChecker::didCheck(int sequence, const Vector<TextCheckingResult>& resu a/Source/WebCore/editing/SpellChecker.cpp_sec5
186
        // spellings in the background. To avoid adding markers to the words modified by users or
212
        // spellings in the background. To avoid adding markers to the words modified by users or
187
        // JavaScript applications, retrieve the words in the specified region and compare them with
213
        // JavaScript applications, retrieve the words in the specified region and compare them with
188
        // the original ones.
214
        // the original ones.
189
        RefPtr<Range> range = Range::create(m_requestRange->ownerDocument(), start, end);
215
        RefPtr<Range> range = Range::create(m_processingRequest->range()->ownerDocument(), start, end);
190
        // FIXME: Use textContent() compatible string conversion.
216
        // FIXME: Use textContent() compatible string conversion.
191
        String destination = range->text();
217
        String destination = range->text();
192
        String source = m_requestText.substring(results[i].location, results[i].length);
218
        String source = m_processingRequest->text().substring(results[i].location, results[i].length);
193
        if (destination == source)
219
        if (destination == source)
194
            m_requestRange->ownerDocument()->markers()->addMarker(range.get(), toMarkerType(results[i].type));
220
            m_processingRequest->range()->ownerDocument()->markers()->addMarker(range.get(), toMarkerType(results[i].type));
195
221
196
        startOffset = results[i].location;
222
        startOffset = results[i].location;
197
    }
223
    }
198
224
199
    clearRequest();
225
    processQueuedRequest();
200
}
226
}
201
227
202
228
- a/Source/WebCore/editing/SpellChecker.h -8 / +12 lines
Lines 28-33 a/Source/WebCore/editing/SpellChecker.h_sec1
28
28
29
#include "PlatformString.h"
29
#include "PlatformString.h"
30
#include "TextChecking.h"
30
#include "TextChecking.h"
31
#include "Timer.h"
31
#include <wtf/RefPtr.h>
32
#include <wtf/RefPtr.h>
32
#include <wtf/Noncopyable.h>
33
#include <wtf/Noncopyable.h>
33
#include <wtf/Vector.h>
34
#include <wtf/Vector.h>
Lines 47-70 public: a/Source/WebCore/editing/SpellChecker.h_sec2
47
    ~SpellChecker();
48
    ~SpellChecker();
48
49
49
    bool isAsynchronousEnabled() const;
50
    bool isAsynchronousEnabled() const;
50
    bool canCheckAsynchronously(Range*) const;
51
    bool isBusy() const;
52
    bool isValid(int sequence) const;
53
    bool isCheckable(Range*) const;
51
    bool isCheckable(Range*) const;
54
    void requestCheckingFor(TextCheckingTypeMask, PassRefPtr<Range>);
52
    void requestCheckingFor(TextCheckingTypeMask, PassRefPtr<Range>);
55
    void didCheck(int sequence, const Vector<TextCheckingResult>&);
53
    void didCheck(int sequence, const Vector<TextCheckingResult>&);
56
54
57
private:
55
private:
58
    bool initRequest(PassRefPtr<Range>);
56
    class SpellCheckRequest;
59
    void clearRequest();
57
58
    bool canCheckAsynchronously(Range*) const;
59
    PassOwnPtr<SpellCheckRequest> createRequest(TextCheckingTypeMask, PassRefPtr<Range>);
60
    void processQueuedRequest();
60
    void doRequestCheckingFor(TextCheckingTypeMask, PassRefPtr<Range>);
61
    void doRequestCheckingFor(TextCheckingTypeMask, PassRefPtr<Range>);
61
    TextCheckerClient* client() const;
62
    TextCheckerClient* client() const;
63
    void timerFiredToProcessQueuedRequest(Timer<SpellChecker>*);
62
64
63
    Frame* m_frame;
65
    Frame* m_frame;
66
    int m_lastRequestedSequence;
67
68
    Timer<SpellChecker> m_timerToProcessQueuedRequest;
64
69
65
    RefPtr<Range> m_requestRange;
70
    OwnPtr<SpellCheckRequest> m_processingRequest;
66
    String m_requestText;
71
    OwnPtr<SpellCheckRequest> m_queuedRequest;
67
    int m_requestSequence;
68
};
72
};
69
73
70
} // namespace WebCore
74
} // namespace WebCore
- a/LayoutTests/ChangeLog +14 lines
Lines 1-3 a/LayoutTests/ChangeLog_sec1
1
2011-11-30  Shinya Kawanaka  <shinyak@google.com>
2
3
        Asynchronous SpellChecker should consider multiple requests.
4
        https://bugs.webkit.org/show_bug.cgi?id=72939
5
6
        Reviewed by NOBODY (OOPS!).
7
8
        Tests for multiple spellcheck requests.
9
10
        * editing/spelling/spellcheck-queue-expected.txt: Added.
11
        * editing/spelling/spellcheck-queue.html: Added.
12
        * platform/gtk/Skipped:
13
        * platform/qt/Skipped:
14
1
2011-11-30  Vincent Scheib  <scheib@chromium.org>
15
2011-11-30  Vincent Scheib  <scheib@chromium.org>
2
16
3
        Rebasing many SVG text & pixel tests due to r101517 Add new renderer for SVGRectElement. Differences are primarily 1 pixel bounds differences
17
        Rebasing many SVG text & pixel tests due to r101517 Add new renderer for SVGRectElement. Differences are primarily 1 pixel bounds differences
- a/LayoutTests/editing/spelling/spellcheck-queue-expected.txt +11 lines
Line 0 a/LayoutTests/editing/spelling/spellcheck-queue-expected.txt_sec1
1
For Bug 72939: Asynchronous SpellChecker should consider multiple requests.
2
3
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
4
5
6
PASS successfullyParsed is true
7
8
TEST COMPLETE
9
PASS INPUT has a marker on 'foo bar'
10
PASS INPUT has a marker on 'foo bar'
11
- a/LayoutTests/editing/spelling/spellcheck-queue.html +121 lines
Line 0 a/LayoutTests/editing/spelling/spellcheck-queue.html_sec1
1
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
2
<html>
3
<head>
4
<script src="../../fast/js/resources/js-test-pre.js"></script>
5
<script src="resources/js-test-selection-shared.js"></script>
6
</head>
7
<body>
8
<p id="description"></p>
9
<div id="console"></div>
10
<script>
11
description('For Bug 72939: Asynchronous SpellChecker should consider multiple requests.');
12
13
if (window.layoutTestController) {
14
    layoutTestController.waitUntilDone();
15
    layoutTestController.setAsynchronousSpellCheckingEnabled(true);
16
}
17
18
var testRoot = document.createElement("div");
19
document.body.insertBefore(testRoot, document.body.firstChild);
20
21
22
var source = document.createElement("div");
23
source.innerHTML = "foo bar";
24
testRoot.appendChild(source);
25
26
var testInput1 = document.createElement("input");
27
testInput1.setAttribute("type", "text");
28
testRoot.appendChild(testInput1);
29
var testInput2 = document.createElement("input");
30
testInput2.setAttribute("type", "text");
31
testRoot.appendChild(testInput2);
32
var testInput3 = document.createElement("input");
33
testInput3.setAttribute("type", "text");
34
testRoot.appendChild(testInput3);
35
36
var sel = window.getSelection();
37
38
// At least, testInput1 and testInput3 should have markers.
39
var tests = [
40
    function() { verify(source, testInput1, [[0, 3]]); },
41
    function() { verify(source, testInput3, [[0, 3]]); }
42
];
43
44
function verifyIfAny()
45
{
46
    var next = tests.shift();
47
    if (next) {
48
        next();
49
        return;
50
    }
51
52
    testRoot.style.display = "none";
53
    if (window.layoutTestController) {
54
        layoutTestController.setAsynchronousSpellCheckingEnabled(false);
55
        layoutTestController.notifyDone();
56
    }
57
}
58
59
function verifyMarker(node, expectedMarked)
60
{
61
    node.focus();
62
63
    if (!window.layoutTestController)
64
        return;
65
66
    var ok = true;
67
    for (var i = 0; ok && i < expectedMarked.length; ++i)
68
        ok = ok && layoutTestController.hasSpellingMarker(expectedMarked[i][0], expectedMarked[i][1]);
69
    return ok;
70
}
71
72
function copyAndPaste(source, dest)
73
{
74
    sel.selectAllChildren(source);
75
    document.execCommand("Copy");
76
    if (dest instanceof HTMLInputElement || dest instanceof HTMLTextAreaElement) {
77
        dest.value = "";
78
        dest.focus();
79
    } else {
80
        dest.innerHTML = "";
81
        sel.selectAllChildren(dest);
82
    }
83
    document.execCommand("Paste");
84
}
85
86
function verify(source, dest, expectedMarked)
87
{
88
    var nretry = 10;
89
    var nsleep = 1;
90
    function trial() {
91
        var verified = verifyMarker(dest, expectedMarked);
92
        if (verified) {
93
            testPassed(dest.tagName + " has a marker on '" + source.innerHTML + "'");
94
            verifyIfAny();
95
            return;
96
        }
97
98
        nretry--;
99
        if (0 == nretry) {
100
            testFailed(dest.tagName + " should have a marker on for '" + source.innerHTML + "'");
101
            verifyIfAny();
102
            return;
103
        }
104
105
        nsleep *= 2;
106
        window.setTimeout(trial, nsleep);
107
    };
108
    trial();
109
}
110
111
var destinations = [testInput1, testInput2, testInput3];
112
for (var i = 0; i < destinations.length; ++i)
113
    copyAndPaste(source, destinations[i]);
114
verifyIfAny();
115
116
var successfullyParsed = true;
117
118
</script>
119
<script src="../../fast/js/resources/js-test-post.js"></script>
120
</body>
121
</html>
- a/LayoutTests/platform/gtk/Skipped +1 lines
Lines 1216-1221 media/event-attributes.html a/LayoutTests/platform/gtk/Skipped_sec1
1216
# https://bugs.webkit.org/show_bug.cgi?id=50740
1216
# https://bugs.webkit.org/show_bug.cgi?id=50740
1217
editing/spelling/spelling-backspace-between-lines.html
1217
editing/spelling/spelling-backspace-between-lines.html
1218
editing/spelling/spellcheck-paste.html
1218
editing/spelling/spellcheck-paste.html
1219
editing/spelling/spellcheck-queue.html
1219
1220
1220
# For https://bugs.webkit.org/show_bug.cgi?id=50758
1221
# For https://bugs.webkit.org/show_bug.cgi?id=50758
1221
# These require DRT setSerializeHTTPLoads implementation to be reliable.
1222
# These require DRT setSerializeHTTPLoads implementation to be reliable.
- a/LayoutTests/platform/qt/Skipped +1 lines
Lines 1001-1006 editing/spelling/spelling-attribute-at-child.html a/LayoutTests/platform/qt/Skipped_sec1
1001
1001
1002
# EditorClient::requestCheckingOfString() is not implemented
1002
# EditorClient::requestCheckingOfString() is not implemented
1003
editing/spelling/spellcheck-paste.html
1003
editing/spelling/spellcheck-paste.html
1004
editing/spelling/spellcheck-queue.html
1004
1005
1005
# [Qt][GTK] editing/spelling/spellcheck-async.html fails
1006
# [Qt][GTK] editing/spelling/spellcheck-async.html fails
1006
# https://bugs.webkit.org/show_bug.cgi?id=73003
1007
# https://bugs.webkit.org/show_bug.cgi?id=73003

Return to Bug 72939