| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2010 Google Inc. All rights reserved. | 2 * Copyright (C) 2010 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
| 8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
| 10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
| (...skipping 18 matching lines...) Expand all Loading... |
| 29 #include "core/dom/Node.h" | 29 #include "core/dom/Node.h" |
| 30 #include "core/editing/markers/DocumentMarkerController.h" | 30 #include "core/editing/markers/DocumentMarkerController.h" |
| 31 #include "core/editing/spellcheck/SpellChecker.h" | 31 #include "core/editing/spellcheck/SpellChecker.h" |
| 32 #include "core/frame/LocalFrame.h" | 32 #include "core/frame/LocalFrame.h" |
| 33 #include "core/frame/Settings.h" | 33 #include "core/frame/Settings.h" |
| 34 #include "platform/text/TextCheckerClient.h" | 34 #include "platform/text/TextCheckerClient.h" |
| 35 | 35 |
| 36 namespace blink { | 36 namespace blink { |
| 37 | 37 |
| 38 SpellCheckRequest::SpellCheckRequest( | 38 SpellCheckRequest::SpellCheckRequest( |
| 39 PassRefPtrWillBeRawPtr<Range> checkingRange, | 39 RawPtr<Range> checkingRange, |
| 40 PassRefPtrWillBeRawPtr<Range> paragraphRange, | 40 RawPtr<Range> paragraphRange, |
| 41 const String& text, | 41 const String& text, |
| 42 TextCheckingTypeMask mask, | 42 TextCheckingTypeMask mask, |
| 43 TextCheckingProcessType processType, | 43 TextCheckingProcessType processType, |
| 44 const Vector<uint32_t>& documentMarkersInRange, | 44 const Vector<uint32_t>& documentMarkersInRange, |
| 45 const Vector<unsigned>& documentMarkerOffsets, | 45 const Vector<unsigned>& documentMarkerOffsets, |
| 46 int requestNumber) | 46 int requestNumber) |
| 47 : m_requester(nullptr) | 47 : m_requester(nullptr) |
| 48 , m_checkingRange(checkingRange) | 48 , m_checkingRange(checkingRange) |
| 49 , m_paragraphRange(paragraphRange) | 49 , m_paragraphRange(paragraphRange) |
| 50 , m_rootEditableElement(m_checkingRange->startContainer()->rootEditableEleme
nt()) | 50 , m_rootEditableElement(m_checkingRange->startContainer()->rootEditableEleme
nt()) |
| (...skipping 22 matching lines...) Expand all Loading... |
| 73 | 73 |
| 74 void SpellCheckRequest::dispose() | 74 void SpellCheckRequest::dispose() |
| 75 { | 75 { |
| 76 if (m_checkingRange) | 76 if (m_checkingRange) |
| 77 m_checkingRange->dispose(); | 77 m_checkingRange->dispose(); |
| 78 if (m_paragraphRange && m_paragraphRange != m_checkingRange) | 78 if (m_paragraphRange && m_paragraphRange != m_checkingRange) |
| 79 m_paragraphRange->dispose(); | 79 m_paragraphRange->dispose(); |
| 80 } | 80 } |
| 81 | 81 |
| 82 // static | 82 // static |
| 83 PassRefPtrWillBeRawPtr<SpellCheckRequest> SpellCheckRequest::create(TextChecking
TypeMask textCheckingOptions, TextCheckingProcessType processType, const Ephemer
alRange& checkingRange, const EphemeralRange& paragraphRange, int requestNumber) | 83 RawPtr<SpellCheckRequest> SpellCheckRequest::create(TextCheckingTypeMask textChe
ckingOptions, TextCheckingProcessType processType, const EphemeralRange& checkin
gRange, const EphemeralRange& paragraphRange, int requestNumber) |
| 84 { | 84 { |
| 85 if (checkingRange.isNull()) | 85 if (checkingRange.isNull()) |
| 86 return nullptr; | 86 return nullptr; |
| 87 if (!checkingRange.startPosition().computeContainerNode()->rootEditableEleme
nt()) | 87 if (!checkingRange.startPosition().computeContainerNode()->rootEditableEleme
nt()) |
| 88 return nullptr; | 88 return nullptr; |
| 89 | 89 |
| 90 String text = plainText(checkingRange, TextIteratorEmitsObjectReplacementCha
racter); | 90 String text = plainText(checkingRange, TextIteratorEmitsObjectReplacementCha
racter); |
| 91 if (text.isEmpty()) | 91 if (text.isEmpty()) |
| 92 return nullptr; | 92 return nullptr; |
| 93 | 93 |
| 94 RefPtrWillBeRawPtr<Range> checkingRangeObject = createRange(checkingRange); | 94 RawPtr<Range> checkingRangeObject = createRange(checkingRange); |
| 95 RefPtrWillBeRawPtr<Range> paragraphRangeObject = nullptr; | 95 RawPtr<Range> paragraphRangeObject = nullptr; |
| 96 // Share identical Range objects. | 96 // Share identical Range objects. |
| 97 if (checkingRange == paragraphRange) | 97 if (checkingRange == paragraphRange) |
| 98 paragraphRangeObject = checkingRangeObject; | 98 paragraphRangeObject = checkingRangeObject; |
| 99 else | 99 else |
| 100 paragraphRangeObject = createRange(paragraphRange); | 100 paragraphRangeObject = createRange(paragraphRange); |
| 101 | 101 |
| 102 const DocumentMarkerVector& markers = checkingRangeObject->ownerDocument().m
arkers().markersInRange(checkingRange, DocumentMarker::SpellCheckClientMarkers()
); | 102 const DocumentMarkerVector& markers = checkingRangeObject->ownerDocument().m
arkers().markersInRange(checkingRange, DocumentMarker::SpellCheckClientMarkers()
); |
| 103 Vector<uint32_t> hashes(markers.size()); | 103 Vector<uint32_t> hashes(markers.size()); |
| 104 Vector<unsigned> offsets(markers.size()); | 104 Vector<unsigned> offsets(markers.size()); |
| 105 for (size_t i = 0; i < markers.size(); ++i) { | 105 for (size_t i = 0; i < markers.size(); ++i) { |
| 106 hashes[i] = markers[i]->hash(); | 106 hashes[i] = markers[i]->hash(); |
| 107 offsets[i] = markers[i]->startOffset(); | 107 offsets[i] = markers[i]->startOffset(); |
| 108 } | 108 } |
| 109 | 109 |
| 110 return adoptRefWillBeNoop(new SpellCheckRequest(checkingRangeObject, paragra
phRangeObject, text, textCheckingOptions, processType, hashes, offsets, requestN
umber)); | 110 return new SpellCheckRequest(checkingRangeObject, paragraphRangeObject, text
, textCheckingOptions, processType, hashes, offsets, requestNumber); |
| 111 } | 111 } |
| 112 | 112 |
| 113 const TextCheckingRequestData& SpellCheckRequest::data() const | 113 const TextCheckingRequestData& SpellCheckRequest::data() const |
| 114 { | 114 { |
| 115 return m_requestData; | 115 return m_requestData; |
| 116 } | 116 } |
| 117 | 117 |
| 118 bool SpellCheckRequest::isValid() const | 118 bool SpellCheckRequest::isValid() const |
| 119 { | 119 { |
| 120 return m_checkingRange->inDocument() && m_paragraphRange->inDocument() && m_
rootEditableElement->inDocument(); | 120 return m_checkingRange->inDocument() && m_paragraphRange->inDocument() && m_
rootEditableElement->inDocument(); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 193 bool SpellCheckRequester::isCheckable(Range* range) const | 193 bool SpellCheckRequester::isCheckable(Range* range) const |
| 194 { | 194 { |
| 195 if (!range || !range->firstNode() || !range->firstNode()->layoutObject()) | 195 if (!range || !range->firstNode() || !range->firstNode()->layoutObject()) |
| 196 return false; | 196 return false; |
| 197 const Node* node = range->startContainer(); | 197 const Node* node = range->startContainer(); |
| 198 if (node && node->isElementNode() && !toElement(node)->isSpellCheckingEnable
d()) | 198 if (node && node->isElementNode() && !toElement(node)->isSpellCheckingEnable
d()) |
| 199 return false; | 199 return false; |
| 200 return true; | 200 return true; |
| 201 } | 201 } |
| 202 | 202 |
| 203 void SpellCheckRequester::requestCheckingFor(PassRefPtrWillBeRawPtr<SpellCheckRe
quest> request) | 203 void SpellCheckRequester::requestCheckingFor(RawPtr<SpellCheckRequest> request) |
| 204 { | 204 { |
| 205 if (!request || !canCheckAsynchronously(request->paragraphRange().get())) | 205 if (!request || !canCheckAsynchronously(request->paragraphRange().get())) |
| 206 return; | 206 return; |
| 207 | 207 |
| 208 ASSERT(request->data().sequence() == unrequestedTextCheckingSequence); | 208 ASSERT(request->data().sequence() == unrequestedTextCheckingSequence); |
| 209 int sequence = ++m_lastRequestSequence; | 209 int sequence = ++m_lastRequestSequence; |
| 210 if (sequence == unrequestedTextCheckingSequence) | 210 if (sequence == unrequestedTextCheckingSequence) |
| 211 sequence = ++m_lastRequestSequence; | 211 sequence = ++m_lastRequestSequence; |
| 212 | 212 |
| 213 request->setCheckerAndSequence(this, sequence); | 213 request->setCheckerAndSequence(this, sequence); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 232 // Empty the queue of pending requests to prevent it being a leak source. | 232 // Empty the queue of pending requests to prevent it being a leak source. |
| 233 // Pending spell checker requests are cancellable requests not representing | 233 // Pending spell checker requests are cancellable requests not representing |
| 234 // leaks, just async work items waiting to be processed. | 234 // leaks, just async work items waiting to be processed. |
| 235 // | 235 // |
| 236 // Rather than somehow wait for this async queue to drain before running | 236 // Rather than somehow wait for this async queue to drain before running |
| 237 // the leak detector, they're all cancelled to prevent flaky leaks being | 237 // the leak detector, they're all cancelled to prevent flaky leaks being |
| 238 // reported. | 238 // reported. |
| 239 m_requestQueue.clear(); | 239 m_requestQueue.clear(); |
| 240 } | 240 } |
| 241 | 241 |
| 242 void SpellCheckRequester::invokeRequest(PassRefPtrWillBeRawPtr<SpellCheckRequest
> request) | 242 void SpellCheckRequester::invokeRequest(RawPtr<SpellCheckRequest> request) |
| 243 { | 243 { |
| 244 ASSERT(!m_processingRequest); | 244 ASSERT(!m_processingRequest); |
| 245 m_processingRequest = request; | 245 m_processingRequest = request; |
| 246 client().requestCheckingOfString(m_processingRequest); | 246 client().requestCheckingOfString(m_processingRequest); |
| 247 } | 247 } |
| 248 | 248 |
| 249 void SpellCheckRequester::clearProcessingRequest() | 249 void SpellCheckRequester::clearProcessingRequest() |
| 250 { | 250 { |
| 251 if (!m_processingRequest) | 251 if (!m_processingRequest) |
| 252 return; | 252 return; |
| 253 | 253 |
| 254 m_processingRequest->dispose(); | 254 m_processingRequest->dispose(); |
| 255 m_processingRequest.clear(); | 255 m_processingRequest.clear(); |
| 256 } | 256 } |
| 257 | 257 |
| 258 void SpellCheckRequester::enqueueRequest(PassRefPtrWillBeRawPtr<SpellCheckReques
t> request) | 258 void SpellCheckRequester::enqueueRequest(RawPtr<SpellCheckRequest> request) |
| 259 { | 259 { |
| 260 ASSERT(request); | 260 ASSERT(request); |
| 261 bool continuation = false; | 261 bool continuation = false; |
| 262 if (!m_requestQueue.isEmpty()) { | 262 if (!m_requestQueue.isEmpty()) { |
| 263 RefPtrWillBeRawPtr<SpellCheckRequest> lastRequest = m_requestQueue.last(
); | 263 RawPtr<SpellCheckRequest> lastRequest = m_requestQueue.last(); |
| 264 // It's a continuation if the number of the last request got incremented
in the new one and | 264 // It's a continuation if the number of the last request got incremented
in the new one and |
| 265 // both apply to the same editable. | 265 // both apply to the same editable. |
| 266 continuation = request->rootEditableElement() == lastRequest->rootEditab
leElement() | 266 continuation = request->rootEditableElement() == lastRequest->rootEditab
leElement() |
| 267 && request->requestNumber() == lastRequest->requestNumber() + 1; | 267 && request->requestNumber() == lastRequest->requestNumber() + 1; |
| 268 } | 268 } |
| 269 | 269 |
| 270 // Spellcheck requests for chunks of text in the same element should not ove
rwrite each other. | 270 // Spellcheck requests for chunks of text in the same element should not ove
rwrite each other. |
| 271 if (!continuation) { | 271 if (!continuation) { |
| 272 for (auto& requestQueue : m_requestQueue) { | 272 for (auto& requestQueue : m_requestQueue) { |
| 273 if (request->rootEditableElement() != requestQueue->rootEditableElem
ent()) | 273 if (request->rootEditableElement() != requestQueue->rootEditableElem
ent()) |
| (...skipping 29 matching lines...) Expand all Loading... |
| 303 void SpellCheckRequester::didCheckSucceed(int sequence, const Vector<TextCheckin
gResult>& results) | 303 void SpellCheckRequester::didCheckSucceed(int sequence, const Vector<TextCheckin
gResult>& results) |
| 304 { | 304 { |
| 305 TextCheckingRequestData requestData = m_processingRequest->data(); | 305 TextCheckingRequestData requestData = m_processingRequest->data(); |
| 306 if (requestData.sequence() == sequence) { | 306 if (requestData.sequence() == sequence) { |
| 307 DocumentMarker::MarkerTypes markers = DocumentMarker::SpellCheckClientMa
rkers(); | 307 DocumentMarker::MarkerTypes markers = DocumentMarker::SpellCheckClientMa
rkers(); |
| 308 if (!requestData.maskContains(TextCheckingTypeSpelling)) | 308 if (!requestData.maskContains(TextCheckingTypeSpelling)) |
| 309 markers.remove(DocumentMarker::Spelling); | 309 markers.remove(DocumentMarker::Spelling); |
| 310 if (!requestData.maskContains(TextCheckingTypeGrammar)) | 310 if (!requestData.maskContains(TextCheckingTypeGrammar)) |
| 311 markers.remove(DocumentMarker::Grammar); | 311 markers.remove(DocumentMarker::Grammar); |
| 312 if (m_processingRequest->isValid()) { | 312 if (m_processingRequest->isValid()) { |
| 313 RefPtrWillBeRawPtr<Range> checkingRange = m_processingRequest->check
ingRange(); | 313 RawPtr<Range> checkingRange = m_processingRequest->checkingRange(); |
| 314 frame().document()->markers().removeMarkers(EphemeralRange(checkingR
ange.get()), markers); | 314 frame().document()->markers().removeMarkers(EphemeralRange(checkingR
ange.get()), markers); |
| 315 } | 315 } |
| 316 } | 316 } |
| 317 didCheck(sequence, results); | 317 didCheck(sequence, results); |
| 318 } | 318 } |
| 319 | 319 |
| 320 void SpellCheckRequester::didCheckCancel(int sequence) | 320 void SpellCheckRequester::didCheckCancel(int sequence) |
| 321 { | 321 { |
| 322 Vector<TextCheckingResult> results; | 322 Vector<TextCheckingResult> results; |
| 323 didCheck(sequence, results); | 323 didCheck(sequence, results); |
| 324 } | 324 } |
| 325 | 325 |
| 326 DEFINE_TRACE(SpellCheckRequester) | 326 DEFINE_TRACE(SpellCheckRequester) |
| 327 { | 327 { |
| 328 visitor->trace(m_frame); | 328 visitor->trace(m_frame); |
| 329 visitor->trace(m_processingRequest); | 329 visitor->trace(m_processingRequest); |
| 330 visitor->trace(m_requestQueue); | 330 visitor->trace(m_requestQueue); |
| 331 } | 331 } |
| 332 | 332 |
| 333 } // namespace blink | 333 } // namespace blink |
| OLD | NEW |