Remove NavigatorBase::serviceWorkerIfExists
[WebKit-https.git] / Source / WebKit / UIProcess / ios / TextCheckerIOS.mm
1 /*
2  * Copyright (C) 2012 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "config.h"
27 #import "TextChecker.h"
28
29 #if PLATFORM(IOS_FAMILY)
30
31 #import "TextCheckerState.h"
32 #import "UIKitSPI.h"
33 #import <WebCore/NotImplemented.h>
34 #import <wtf/HashMap.h>
35 #import <wtf/NeverDestroyed.h>
36 #import <wtf/RetainPtr.h>
37 #import <wtf/text/StringView.h>
38
39 namespace WebKit {
40 using namespace WebCore;
41
42 static TextCheckerState& mutableState()
43 {
44     static NeverDestroyed<TextCheckerState> state = makeNeverDestroyed([] {
45         TextCheckerState initialState;
46         initialState.isContinuousSpellCheckingEnabled = TextChecker::isContinuousSpellCheckingAllowed();
47         initialState.isGrammarCheckingEnabled = false;
48         return initialState;
49     }());
50     return state;
51 }
52
53 const TextCheckerState& TextChecker::state()
54 {
55     return mutableState();
56 }
57
58 bool TextChecker::isContinuousSpellCheckingAllowed()
59 {
60 #if USE(UNIFIED_TEXT_CHECKING)
61     return true;
62 #else
63     return false;
64 #endif
65 }
66
67 void TextChecker::setContinuousSpellCheckingEnabled(bool enabled)
68 {
69     mutableState().isContinuousSpellCheckingEnabled = enabled;
70 }
71
72 void TextChecker::setGrammarCheckingEnabled(bool)
73 {
74     notImplemented();
75 }
76
77 void TextChecker::setAutomaticSpellingCorrectionEnabled(bool)
78 {
79     notImplemented();
80 }
81
82 void TextChecker::setAutomaticQuoteSubstitutionEnabled(bool)
83 {
84     notImplemented();
85 }
86
87 void TextChecker::setAutomaticDashSubstitutionEnabled(bool)
88 {
89     notImplemented();
90 }
91
92 void TextChecker::setAutomaticLinkDetectionEnabled(bool)
93 {
94     notImplemented();
95 }
96
97 void TextChecker::setAutomaticTextReplacementEnabled(bool)
98 {
99     notImplemented();
100 }
101     
102 static bool testingModeEnabled = false;
103     
104 void TextChecker::setTestingMode(bool enabled)
105 {
106     testingModeEnabled = enabled;
107 }
108     
109 bool TextChecker::isTestingMode()
110 {
111     return testingModeEnabled;
112 }
113
114 bool TextChecker::isSmartInsertDeleteEnabled()
115 {
116     return [[UIKeyboardImpl sharedInstance] smartInsertDeleteIsEnabled];
117 }
118
119 void TextChecker::setSmartInsertDeleteEnabled(bool)
120 {
121     notImplemented();
122 }
123
124 bool TextChecker::substitutionsPanelIsShowing()
125 {
126     notImplemented();
127     return false;
128 }
129
130 void TextChecker::toggleSubstitutionsPanelIsShowing()
131 {
132     notImplemented();
133 }
134
135 void TextChecker::continuousSpellCheckingEnabledStateChanged(bool enabled)
136 {
137     mutableState().isContinuousSpellCheckingEnabled = enabled;
138 }
139
140 void TextChecker::grammarCheckingEnabledStateChanged(bool)
141 {
142     notImplemented();
143 }
144
145 #if USE(UNIFIED_TEXT_CHECKING)
146
147 static HashMap<SpellDocumentTag, RetainPtr<UITextChecker>>& spellDocumentTagMap()
148 {
149     static NeverDestroyed<HashMap<SpellDocumentTag, RetainPtr<UITextChecker>>> tagMap;
150     return tagMap;
151 }
152
153 #endif
154
155 SpellDocumentTag TextChecker::uniqueSpellDocumentTag(WebPageProxy*)
156 {
157 #if USE(UNIFIED_TEXT_CHECKING)
158     static SpellDocumentTag nextSpellDocumentTag;
159     return ++nextSpellDocumentTag;
160 #else
161     return { };
162 #endif
163 }
164
165 void TextChecker::closeSpellDocumentWithTag(SpellDocumentTag spellDocumentTag)
166 {
167 #if USE(UNIFIED_TEXT_CHECKING)
168     spellDocumentTagMap().remove(spellDocumentTag);
169 #else
170     UNUSED_PARAM(spellDocumentTag);
171 #endif
172 }
173
174 #if USE(UNIFIED_TEXT_CHECKING)
175
176 static RetainPtr<UITextChecker> textCheckerFor(SpellDocumentTag spellDocumentTag)
177 {
178     auto addResult = spellDocumentTagMap().add(spellDocumentTag, nullptr);
179     if (addResult.isNewEntry)
180         addResult.iterator->value = adoptNS([[UITextChecker alloc] _initWithAsynchronousLoading:YES]);
181     return addResult.iterator->value;
182 }
183
184 Vector<TextCheckingResult> TextChecker::checkTextOfParagraph(SpellDocumentTag spellDocumentTag, StringView text, int32_t /* insertionPoint */, OptionSet<TextCheckingType> checkingTypes, bool /* initialCapitalizationEnabled */)
185 {
186     Vector<TextCheckingResult> results;
187     if (!checkingTypes.contains(TextCheckingType::Spelling))
188         return results;
189
190     auto textChecker = textCheckerFor(spellDocumentTag);
191     if (![textChecker _doneLoading])
192         return results;
193
194     NSArray<NSString *> *keyboardLanguages = @[ ];
195     auto *currentInputMode = [UIKeyboardInputModeController sharedInputModeController].currentInputMode;
196     if (currentInputMode.multilingualLanguages.count)
197         keyboardLanguages = currentInputMode.multilingualLanguages;
198     else if (currentInputMode.primaryLanguage)
199         keyboardLanguages = @[ currentInputMode.languageWithRegion ];
200
201     auto stringToCheck = text.createNSStringWithoutCopying();
202     auto range = NSMakeRange(0, [stringToCheck length]);
203     NSUInteger offsetSoFar = 0;
204     do {
205         auto misspelledRange = [textChecker rangeOfMisspelledWordInString:stringToCheck.get() range:range startingAt:offsetSoFar wrap:NO languages:keyboardLanguages];
206         if (misspelledRange.location == NSNotFound)
207             break;
208
209         TextCheckingResult result;
210         result.type = TextCheckingType::Spelling;
211         result.location = misspelledRange.location;
212         result.length = misspelledRange.length;
213         results.append(WTFMove(result));
214
215         offsetSoFar = misspelledRange.location + misspelledRange.length;
216     } while (offsetSoFar < [stringToCheck length]);
217     return results;
218 }
219
220 #endif
221
222 void TextChecker::checkSpellingOfString(SpellDocumentTag, StringView, int32_t&, int32_t&)
223 {
224     // iOS uses checkTextOfParagraph() instead.
225     notImplemented();
226 }
227
228 void TextChecker::checkGrammarOfString(SpellDocumentTag, StringView, Vector<WebCore::GrammarDetail>&, int32_t&, int32_t&)
229 {
230     // iOS uses checkTextOfParagraph() instead.
231     notImplemented();
232 }
233
234 bool TextChecker::spellingUIIsShowing()
235 {
236     notImplemented();
237     return false;
238 }
239
240 void TextChecker::toggleSpellingUIIsShowing()
241 {
242     notImplemented();
243 }
244
245 void TextChecker::updateSpellingUIWithMisspelledWord(SpellDocumentTag, const String&)
246 {
247     notImplemented();
248 }
249
250 void TextChecker::updateSpellingUIWithGrammarString(SpellDocumentTag, const String&, const GrammarDetail&)
251 {
252     notImplemented();
253 }
254
255 void TextChecker::getGuessesForWord(SpellDocumentTag, const String&, const String&, int32_t, Vector<String>&, bool)
256 {
257     notImplemented();
258 }
259
260 void TextChecker::learnWord(SpellDocumentTag, const String&)
261 {
262     notImplemented();
263 }
264
265 void TextChecker::ignoreWord(SpellDocumentTag, const String&)
266 {
267     notImplemented();
268 }
269
270 void TextChecker::requestCheckingOfString(Ref<TextCheckerCompletion>&&, int32_t)
271 {
272     notImplemented();
273 }
274
275 } // namespace WebKit
276
277 #endif // PLATFORM(IOS_FAMILY)