Changeset 140170 in webkit


Ignore:
Timestamp:
Jan 18, 2013 10:00:48 AM (11 years ago)
Author:
nghanavatian@rim.com
Message:

[BlackBerry] Set spellchecking calculations on a timer to free up the WebKit thread
https://bugs.webkit.org/show_bug.cgi?id=107284

Reviewed by Rob Buis.

PR282351
Firing off spellcheck requests is tieing up the WebKit thread for an
extended period of time. In testing with large blocks of text, this
can be in the matter of 5-10 seconds. Though we are using asynchronous
spellchecking, the process in which we break down blocks of text based
on input_service limitations is the issue.
Using a timer here which fires with an arbitrary timeout to allow for
focus and interaction to maintain at a reasonable level.
Further, pulling this code out of InputHandler and into its own class.

Internally reviewed by Mike Fenton and Gen Mak.

  • WebKitSupport/InputHandler.cpp:

(BlackBerry::WebKit::InputHandler::InputHandler):
(BlackBerry::WebKit::InputHandler::~InputHandler):
(BlackBerry::WebKit::InputHandler::callRequestCheckingFor):
(WebKit):
(BlackBerry::WebKit::InputHandler::requestCheckingOfString):
(BlackBerry::WebKit::InputHandler::spellCheckingRequestProcessed):
(BlackBerry::WebKit::InputHandler::shouldRequestSpellCheckingOptionsForPoint):
(BlackBerry::WebKit::InputHandler::setElementUnfocused):
(BlackBerry::WebKit::InputHandler::setElementFocused):

  • WebKitSupport/InputHandler.h:

(WebCore):
(WebKit):
(InputHandler):

  • WebKitSupport/SpellingHandler.cpp: Added.

(WebKit):
(BlackBerry::WebKit::SpellingHandler::SpellingHandler):
(BlackBerry::WebKit::SpellingHandler::~SpellingHandler):
(BlackBerry::WebKit::SpellingHandler::spellCheckTextBlock):
(BlackBerry::WebKit::SpellingHandler::createSpellCheckRequest):
(BlackBerry::WebKit::SpellingHandler::parseBlockForSpellChecking):
(BlackBerry::WebKit::SpellingHandler::getRangeForSpellCheckWithFineGranularity):

  • WebKitSupport/SpellingHandler.h: Added.

(WebCore):
(WebKit):
(SpellingHandler):
(BlackBerry::WebKit::SpellingHandler::isSpellCheckActive):
(BlackBerry::WebKit::SpellingHandler::setSpellCheckActive):

Location:
trunk/Source/WebKit
Files:
2 added
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/PlatformBlackBerry.cmake

    r136790 r140170  
    137137    blackberry/WebKitSupport/SelectionHandler.cpp
    138138    blackberry/WebKitSupport/SelectionOverlay.cpp
     139    blackberry/WebKitSupport/SpellingHandler.cpp
    139140    blackberry/WebKitSupport/SurfacePool.cpp
    140141    blackberry/WebKitSupport/TouchEventHandler.cpp
  • trunk/Source/WebKit/blackberry/ChangeLog

    r140161 r140170  
     12013-01-18  Nima Ghanavatian  <nghanavatian@rim.com>
     2
     3        [BlackBerry] Set spellchecking calculations on a timer to free up the WebKit thread
     4        https://bugs.webkit.org/show_bug.cgi?id=107284
     5
     6        Reviewed by Rob Buis.
     7
     8        PR282351
     9        Firing off spellcheck requests is tieing up the WebKit thread for an
     10        extended period of time. In testing with large blocks of text, this
     11        can be in the matter of 5-10 seconds. Though we are using asynchronous
     12        spellchecking, the process in which we break down blocks of text based
     13        on input_service limitations is the issue.
     14        Using a timer here which fires with an arbitrary timeout to allow for
     15        focus and interaction to maintain at a reasonable level.
     16        Further, pulling this code out of InputHandler and into its own class.
     17
     18        Internally reviewed by Mike Fenton and Gen Mak.
     19
     20        * WebKitSupport/InputHandler.cpp:
     21        (BlackBerry::WebKit::InputHandler::InputHandler):
     22        (BlackBerry::WebKit::InputHandler::~InputHandler):
     23        (BlackBerry::WebKit::InputHandler::callRequestCheckingFor):
     24        (WebKit):
     25        (BlackBerry::WebKit::InputHandler::requestCheckingOfString):
     26        (BlackBerry::WebKit::InputHandler::spellCheckingRequestProcessed):
     27        (BlackBerry::WebKit::InputHandler::shouldRequestSpellCheckingOptionsForPoint):
     28        (BlackBerry::WebKit::InputHandler::setElementUnfocused):
     29        (BlackBerry::WebKit::InputHandler::setElementFocused):
     30        * WebKitSupport/InputHandler.h:
     31        (WebCore):
     32        (WebKit):
     33        (InputHandler):
     34        * WebKitSupport/SpellingHandler.cpp: Added.
     35        (WebKit):
     36        (BlackBerry::WebKit::SpellingHandler::SpellingHandler):
     37        (BlackBerry::WebKit::SpellingHandler::~SpellingHandler):
     38        (BlackBerry::WebKit::SpellingHandler::spellCheckTextBlock):
     39        (BlackBerry::WebKit::SpellingHandler::createSpellCheckRequest):
     40        (BlackBerry::WebKit::SpellingHandler::parseBlockForSpellChecking):
     41        (BlackBerry::WebKit::SpellingHandler::getRangeForSpellCheckWithFineGranularity):
     42        * WebKitSupport/SpellingHandler.h: Added.
     43        (WebCore):
     44        (WebKit):
     45        (SpellingHandler):
     46        (BlackBerry::WebKit::SpellingHandler::isSpellCheckActive):
     47        (BlackBerry::WebKit::SpellingHandler::setSpellCheckActive):
     48
    1492013-01-18  Nima Ghanavatian  <nghanavatian@rim.com>
    250
  • trunk/Source/WebKit/blackberry/WebKitSupport/InputHandler.cpp

    r140161 r140170  
    3030#include "DocumentLoader.h"
    3131#include "DocumentMarkerController.h"
     32#include "EditorClientBlackBerry.h"
    3233#include "FocusController.h"
    3334#include "Frame.h"
     
    5657#include "SelectionHandler.h"
    5758#include "SpellChecker.h"
     59#include "SpellingHandler.h"
    5860#include "TextCheckerClient.h"
    5961#include "TextIterator.h"
     
    144146    , m_expectedKeyUpChar(0)
    145147    , m_didSpellCheckWord(false)
     148    , m_spellingHandler(new SpellingHandler(this))
    146149{
    147150}
     
    149152InputHandler::~InputHandler()
    150153{
     154    delete m_spellingHandler;
    151155}
    152156
     
    577581}
    578582
     583void InputHandler::callRequestCheckingFor(PassRefPtr<WebCore::SpellCheckRequest> spellCheckRequest)
     584{
     585    if (SpellChecker* spellChecker = getSpellChecker())
     586        spellChecker->requestCheckingFor(spellCheckRequest);
     587}
     588
    579589void InputHandler::requestCheckingOfString(PassRefPtr<WebCore::TextCheckingRequest> textCheckingRequest)
    580590{
     
    604614            VisiblePosition caretPosition = m_currentFocusElement->document()->frame()->selection()->start();
    605615            VisibleSelection visibleSelection = VisibleSelection(previousLinePosition(caretPosition, caretPosition.lineDirectionPointForBlockDirectionNavigation()), caretPosition);
    606             spellCheckBlock(visibleSelection, TextCheckingProcessIncremental);
     616            m_spellingHandler->spellCheckTextBlock(visibleSelection, TextCheckingProcessIncremental);
    607617        }
    608618        return;
     
    656666        transactionId == m_processingTransactionId ? "" : "We are out of sync with input service.");
    657667
    658     if (!spannableString || !isActiveTextEdit() || !DOMSupport::elementHasContinuousSpellCheckingEnabled(m_currentFocusElement)) {
     668    if (!spannableString || !isActiveTextEdit() || !DOMSupport::elementHasContinuousSpellCheckingEnabled(m_currentFocusElement) || !m_processingTransactionId) {
    659669        SpellingLog(Platform::LogLevelWarn, "InputHandler::spellCheckingRequestProcessed Cancelling request with transactionId %d.", transactionId);
    660670        m_request->didCancel();
     
    752762    SpellingLog(Platform::LogLevelInfo,
    753763        "InputHandler::shouldRequestSpellCheckingOptionsForPoint Found spelling marker at point %s\nMarker start %d end %d",
    754         point.toString().c_str(),
     764        documentContentPosition.toString().c_str(),
    755765        spellCheckingOptionRequest.startTextPosition,
    756766        spellCheckingOptionRequest.endTextPosition);
     
    856866    }
    857867
     868    m_spellingHandler->setSpellCheckActive(false);
     869    m_processingTransactionId = 0;
     870
    858871    // Clear the node details.
    859872    m_currentFocusElement = 0;
     
    946959
    947960    // Check if the field should be spellchecked.
    948     if (!shouldSpellCheckElement(element))
     961    if (!shouldSpellCheckElement(element) || !isActiveTextEdit())
    949962        return;
    950963
    951964    // Spellcheck the field in its entirety.
    952965    VisibleSelection focusedBlock = DOMSupport::visibleSelectionForInputElement(element);
    953     spellCheckBlock(focusedBlock, TextCheckingProcessBatch);
     966    m_spellingHandler->spellCheckTextBlock(focusedBlock, TextCheckingProcessBatch);
    954967
    955968#ifdef ENABLE_SPELLING_LOG
     
    982995        requestSpellingCheckingOptions(spellCheckingOptionRequest, screenOffset, shouldMoveDialog);
    983996    }
    984 }
    985 
    986 void InputHandler::spellCheckBlock(VisibleSelection& visibleSelection, TextCheckingProcessType textCheckingProcessType)
    987 {
    988     if (!isActiveTextEdit())
    989         return;
    990 
    991     RefPtr<Range> rangeForSpellChecking = visibleSelection.toNormalizedRange();
    992     if (!rangeForSpellChecking || !rangeForSpellChecking->text() || !rangeForSpellChecking->text().length())
    993         return;
    994 
    995     SpellChecker* spellChecker = getSpellChecker();
    996     if (!spellChecker) {
    997         SpellingLog(Platform::LogLevelInfo, "InputHandler::spellCheckBlock Failed to spellcheck the current focused element.");
    998         return;
    999     }
    1000 
    1001     // If we have a batch request, try to send off the entire block.
    1002     if (textCheckingProcessType == TextCheckingProcessBatch) {
    1003         // If total block text is under the limited amount, send the entire chunk.
    1004         if (rangeForSpellChecking->text().length() < MaxSpellCheckingStringLength) {
    1005             spellChecker->requestCheckingFor(SpellCheckRequest::create(TextCheckingTypeSpelling, TextCheckingProcessBatch, rangeForSpellChecking, rangeForSpellChecking));
    1006             return;
    1007         }
    1008     }
    1009 
    1010     // Since we couldn't check the entire block at once, set up starting and ending markers to fire incrementally.
    1011     VisiblePosition startPos = visibleSelection.visibleStart();
    1012     VisiblePosition startOfCurrentLine = startOfLine(startPos);
    1013     VisiblePosition endOfCurrentLine = endOfLine(startOfCurrentLine);
    1014 
    1015     while (!isEndOfBlock(startOfCurrentLine)) {
    1016         // Create a selection with the start and end points of the line, and convert to Range to create a SpellCheckRequest.
    1017         rangeForSpellChecking = VisibleSelection(startOfCurrentLine, endOfCurrentLine).toNormalizedRange();
    1018 
    1019         if (rangeForSpellChecking->text().length() < MaxSpellCheckingStringLength) {
    1020             startOfCurrentLine = nextLinePosition(startOfCurrentLine, startOfCurrentLine.lineDirectionPointForBlockDirectionNavigation());
    1021             endOfCurrentLine = endOfLine(startOfCurrentLine);
    1022         } else {
    1023             // Iterate through words from the start of the line to the end.
    1024             rangeForSpellChecking = getRangeForSpellCheckWithFineGranularity(startOfCurrentLine, endOfCurrentLine);
    1025             if (!rangeForSpellChecking) {
    1026                 SpellingLog(Platform::LogLevelWarn, "InputHandler::spellCheckBlock Failed to set text range for spellchecking");
    1027                 return;
    1028             }
    1029             startOfCurrentLine = VisiblePosition(rangeForSpellChecking->endPosition());
    1030             endOfCurrentLine = endOfLine(startOfCurrentLine);
    1031             rangeForSpellChecking = DOMSupport::trimWhitespaceFromRange(VisiblePosition(rangeForSpellChecking->startPosition()), VisiblePosition(rangeForSpellChecking->endPosition()));
    1032         }
    1033 
    1034         SpellingLog(Platform::LogLevelInfo,
    1035             "InputHandler::spellCheckBlock Substring text is '%s', of size %d",
    1036             rangeForSpellChecking->text().latin1().data(),
    1037             rangeForSpellChecking->text().length());
    1038 
    1039         // Call spellcheck with substring.
    1040         spellChecker->requestCheckingFor(SpellCheckRequest::create(TextCheckingTypeSpelling, TextCheckingProcessBatch, rangeForSpellChecking, rangeForSpellChecking));
    1041     }
    1042 }
    1043 
    1044 PassRefPtr<Range> InputHandler::getRangeForSpellCheckWithFineGranularity(VisiblePosition startPosition, VisiblePosition endPosition)
    1045 {
    1046     VisiblePosition endOfCurrentWord = endOfWord(startPosition);
    1047 
    1048     // Keep iterating until one of our cases is hit, or we've incremented the starting position right to the end.
    1049     while (startPosition != endPosition) {
    1050         // Check the text length within this range.
    1051         if (VisibleSelection(startPosition, endOfCurrentWord).toNormalizedRange()->text().length() >= MaxSpellCheckingStringLength) {
    1052             // If this is not the first word, return a Range with end boundary set to the previous word.
    1053             if (startOfWord(endOfCurrentWord, LeftWordIfOnBoundary) != startPosition && !DOMSupport::isEmptyRangeOrAllSpaces(startPosition, endOfCurrentWord))
    1054                 return VisibleSelection(startPosition, endOfWord(previousWordPosition(endOfCurrentWord), LeftWordIfOnBoundary)).toNormalizedRange();
    1055 
    1056             // Our first word has gone over the character limit. Increment the starting position past an uncheckable word.
    1057             startPosition = endOfCurrentWord;
    1058             endOfCurrentWord = endOfWord(nextWordPosition(endOfCurrentWord));
    1059         } else if (endOfCurrentWord == endPosition) {
    1060             // Return the last segment if the end of our word lies at the end of the range.
    1061             return VisibleSelection(startPosition, endPosition).toNormalizedRange();
    1062         } else {
    1063             // Increment the current word.
    1064             endOfCurrentWord = endOfWord(nextWordPosition(endOfCurrentWord));
    1065         }
    1066     }
    1067     return 0;
    1068997}
    1069998
  • trunk/Source/WebKit/blackberry/WebKitSupport/InputHandler.h

    r139787 r140170  
    4646class Range;
    4747class SpellChecker;
     48class SpellCheckRequest;
    4849class TextCheckingRequest;
    4950class VisiblePosition;
     
    6061namespace WebKit {
    6162
     63class SpellingHandler;
    6264class WebPagePrivate;
    6365
     
    139141    int32_t commitText(spannable_string_t*, int32_t relativeCursorPosition);
    140142
    141     void requestCheckingOfString(WTF::PassRefPtr<WebCore::TextCheckingRequest>);
     143    void requestCheckingOfString(PassRefPtr<WebCore::TextCheckingRequest>);
    142144    void spellCheckingRequestProcessed(int32_t transactionId, spannable_string_t*);
    143145    void spellCheckingRequestCancelled(int32_t transactionId);
     
    147149    void clearDidSpellCheckState() { m_didSpellCheckWord = false; }
    148150    void redrawSpellCheckDialogIfRequired(const bool shouldMoveDialog = true);
     151
     152    void callRequestCheckingFor(PassRefPtr<WebCore::SpellCheckRequest>);
    149153
    150154private:
     
    203207    void learnText();
    204208    void sendLearnTextDetails(const WTF::String&);
    205     void spellCheckBlock(WebCore::VisibleSelection&, WebCore::TextCheckingProcessType);
    206     PassRefPtr<WebCore::Range> getRangeForSpellCheckWithFineGranularity(WebCore::VisiblePosition startPosition, WebCore::VisiblePosition endPosition);
    207209    WebCore::SpellChecker* getSpellChecker();
    208210    bool shouldSpellCheckElement(const WebCore::Element*) const;
     
    237239    WebCore::IntSize m_screenOffset;
    238240    bool m_didSpellCheckWord;
     241    SpellingHandler* m_spellingHandler;
     242
    239243};
    240244
Note: See TracChangeset for help on using the changeset viewer.