2 * Copyright (C) 2006, 2007 Apple, Inc. All rights reserved.
3 * Copyright (C) 2012 Google, Inc. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include "web/SpellCheckerClientImpl.h"
30 #include "core/dom/Element.h"
31 #include "core/editing/Editor.h"
32 #include "core/editing/markers/DocumentMarkerController.h"
33 #include "core/editing/spellcheck/SpellChecker.h"
34 #include "core/frame/LocalFrame.h"
35 #include "core/frame/Settings.h"
36 #include "core/page/Page.h"
37 #include "public/web/WebSpellCheckClient.h"
38 #include "public/web/WebTextCheckingResult.h"
39 #include "web/WebTextCheckingCompletionImpl.h"
40 #include "web/WebViewImpl.h"
44 SpellCheckerClientImpl::SpellCheckerClientImpl(WebViewImpl
* webview
)
46 , m_spellCheckThisFieldStatus(SpellCheckAutomatic
)
50 SpellCheckerClientImpl::~SpellCheckerClientImpl()
54 bool SpellCheckerClientImpl::shouldSpellcheckByDefault()
56 // Spellcheck should be enabled for all editable areas (such as textareas,
57 // contentEditable regions, designMode docs and inputs).
58 if (!m_webView
->focusedCoreFrame()->isLocalFrame())
60 const LocalFrame
* frame
= toLocalFrame(m_webView
->focusedCoreFrame());
63 if (frame
->spellChecker().isSpellCheckingEnabledInFocusedNode())
65 const Document
* document
= frame
->document();
68 const Element
* element
= document
->focusedElement();
69 // If |element| is null, we default to allowing spellchecking. This is done
70 // in order to mitigate the issue when the user clicks outside the textbox,
71 // as a result of which |element| becomes null, resulting in all the spell
72 // check markers being deleted. Also, the LocalFrame will decide not to do
73 // spellchecking if the user can't edit - so returning true here will not
74 // cause any problems to the LocalFrame's behavior.
77 const LayoutObject
* layoutObject
= element
->layoutObject();
84 bool SpellCheckerClientImpl::isContinuousSpellCheckingEnabled()
86 if (m_spellCheckThisFieldStatus
== SpellCheckForcedOff
)
88 if (m_spellCheckThisFieldStatus
== SpellCheckForcedOn
)
90 return shouldSpellcheckByDefault();
93 void SpellCheckerClientImpl::toggleContinuousSpellChecking()
95 if (isContinuousSpellCheckingEnabled()) {
96 m_spellCheckThisFieldStatus
= SpellCheckForcedOff
;
97 if (Page
* page
= m_webView
->page()) {
98 for (Frame
* frame
= page
->mainFrame(); frame
; frame
= frame
->tree().traverseNext()) {
99 if (!frame
->isLocalFrame())
101 toLocalFrame(frame
)->document()->markers().removeMarkers(DocumentMarker::MisspellingMarkers());
105 m_spellCheckThisFieldStatus
= SpellCheckForcedOn
;
106 if (m_webView
->focusedCoreFrame()->isLocalFrame()) {
107 if (LocalFrame
* frame
= toLocalFrame(m_webView
->focusedCoreFrame())) {
108 VisibleSelection frameSelection
= frame
->selection().selection();
109 // If a selection is in an editable element spell check its content.
110 if (Element
* rootEditableElement
= frameSelection
.rootEditableElement()) {
111 frame
->spellChecker().didBeginEditing(rootEditableElement
);
118 bool SpellCheckerClientImpl::isGrammarCheckingEnabled()
120 const LocalFrame
* frame
= toLocalFrame(m_webView
->focusedCoreFrame());
121 return frame
&& frame
->settings() && (frame
->settings()->asynchronousSpellCheckingEnabled() || frame
->settings()->unifiedTextCheckerEnabled());
124 bool SpellCheckerClientImpl::shouldEraseMarkersAfterChangeSelection(TextCheckingType type
) const
126 const Frame
* frame
= m_webView
->focusedCoreFrame();
127 return !frame
|| !frame
->settings() || (!frame
->settings()->asynchronousSpellCheckingEnabled() && !frame
->settings()->unifiedTextCheckerEnabled());
130 void SpellCheckerClientImpl::checkSpellingOfString(const String
& text
, int* misspellingLocation
, int* misspellingLength
)
132 // SpellCheckWord will write (0, 0) into the output vars, which is what our
133 // caller expects if the word is spelled correctly.
134 int spellLocation
= -1;
137 // Check to see if the provided text is spelled correctly.
138 if (m_webView
->spellCheckClient()) {
139 m_webView
->spellCheckClient()->spellCheck(text
, spellLocation
, spellLength
, 0);
145 // Note: the Mac code checks if the pointers are null before writing to them,
147 if (misspellingLocation
)
148 *misspellingLocation
= spellLocation
;
149 if (misspellingLength
)
150 *misspellingLength
= spellLength
;
153 void SpellCheckerClientImpl::requestCheckingOfString(PassRefPtrWillBeRawPtr
<TextCheckingRequest
> request
)
155 if (m_webView
->spellCheckClient()) {
156 const String
& text
= request
->data().text();
157 const Vector
<uint32_t>& markers
= request
->data().markers();
158 const Vector
<unsigned>& markerOffsets
= request
->data().offsets();
159 m_webView
->spellCheckClient()->requestCheckingOfText(text
, markers
, markerOffsets
, new WebTextCheckingCompletionImpl(request
));
163 String
SpellCheckerClientImpl::getAutoCorrectSuggestionForMisspelledWord(const String
& misspelledWord
)
165 if (!(isContinuousSpellCheckingEnabled() && m_webView
->client()))
168 // Do not autocorrect words with capital letters in it except the
169 // first letter. This will remove cases changing "IMB" to "IBM".
170 for (size_t i
= 1; i
< misspelledWord
.length(); i
++) {
171 if (u_isupper(static_cast<UChar32
>(misspelledWord
[i
])))
175 if (m_webView
->spellCheckClient())
176 return m_webView
->spellCheckClient()->autoCorrectWord(WebString(misspelledWord
));
180 void SpellCheckerClientImpl::checkGrammarOfString(const String
& text
, WTF::Vector
<GrammarDetail
>& details
, int* badGrammarLocation
, int* badGrammarLength
)
182 if (badGrammarLocation
)
183 *badGrammarLocation
= -1;
184 if (badGrammarLength
)
185 *badGrammarLength
= 0;
187 if (!m_webView
->spellCheckClient())
189 WebVector
<WebTextCheckingResult
> webResults
;
190 m_webView
->spellCheckClient()->checkTextOfParagraph(text
, WebTextCheckingTypeGrammar
, &webResults
);
191 if (!webResults
.size())
194 // Convert a list of WebTextCheckingResults to a list of GrammarDetails. If
195 // the converted vector of GrammarDetails has grammar errors, we set
196 // badGrammarLocation and badGrammarLength to tell WebKit that the input
197 // text has grammar errors.
198 for (size_t i
= 0; i
< webResults
.size(); ++i
) {
199 if (webResults
[i
].decoration
== WebTextDecorationTypeGrammar
) {
200 GrammarDetail detail
;
201 detail
.location
= webResults
[i
].location
;
202 detail
.length
= webResults
[i
].length
;
203 detail
.userDescription
= webResults
[i
].replacement
;
204 details
.append(detail
);
209 if (badGrammarLocation
)
210 *badGrammarLocation
= 0;
211 if (badGrammarLength
)
212 *badGrammarLength
= text
.length();
215 void SpellCheckerClientImpl::updateSpellingUIWithMisspelledWord(const String
& misspelledWord
)
217 if (m_webView
->spellCheckClient())
218 m_webView
->spellCheckClient()->updateSpellingUIWithMisspelledWord(WebString(misspelledWord
));
221 void SpellCheckerClientImpl::showSpellingUI(bool show
)
223 if (m_webView
->spellCheckClient())
224 m_webView
->spellCheckClient()->showSpellingUI(show
);
227 bool SpellCheckerClientImpl::spellingUIIsShowing()
229 if (m_webView
->spellCheckClient())
230 return m_webView
->spellCheckClient()->isShowingSpellingUI();