WebKit2: Implement TextChecker on Windows
[WebKit-https.git] / Source / WebKit2 / WebProcess / WebCoreSupport / WebEditorClient.cpp
1 /*
2  * Copyright (C) 2010 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 #include "config.h"
27 #include "WebEditorClient.h"
28
29 #include "SelectionState.h"
30 #include "WebCoreArgumentCoders.h"
31 #include "WebFrameLoaderClient.h"
32 #include "WebPage.h"
33 #include "WebPageProxy.h"
34 #include "WebPageProxyMessages.h"
35 #include "WebProcess.h"
36 #include <WebCore/ArchiveResource.h>
37 #include <WebCore/DocumentFragment.h>
38 #include <WebCore/EditCommand.h>
39 #include <WebCore/FocusController.h>
40 #include <WebCore/Frame.h>
41 #include <WebCore/HTMLInputElement.h>
42 #include <WebCore/HTMLNames.h>
43 #include <WebCore/HTMLTextAreaElement.h>
44 #include <WebCore/KeyboardEvent.h>
45 #include <WebCore/NotImplemented.h>
46 #include <WebCore/Page.h>
47 #include <WebCore/TextIterator.h>
48 #include <WebCore/UserTypingGestureIndicator.h>
49
50 using namespace WebCore;
51 using namespace HTMLNames;
52
53 namespace WebKit {
54
55 void WebEditorClient::pageDestroyed()
56 {
57     delete this;
58 }
59
60 bool WebEditorClient::shouldDeleteRange(Range* range)
61 {
62     bool result = m_page->injectedBundleEditorClient().shouldDeleteRange(m_page, range);
63     notImplemented();
64     return result;
65 }
66
67 bool WebEditorClient::shouldShowDeleteInterface(HTMLElement*)
68 {
69     notImplemented();
70     return false;
71 }
72
73 bool WebEditorClient::smartInsertDeleteEnabled()
74 {
75     // FIXME: Why isn't this Mac specific like toggleSmartInsertDeleteEnabled?
76 #if PLATFORM(MAC)
77     return m_page->isSmartInsertDeleteEnabled();
78 #else
79     return true;
80 #endif
81 }
82  
83 bool WebEditorClient::isSelectTrailingWhitespaceEnabled()
84 {
85     notImplemented();
86     return false;
87 }
88
89 bool WebEditorClient::isContinuousSpellCheckingEnabled()
90 {
91     return WebProcess::shared().textCheckerState().isContinuousSpellCheckingEnabled;
92 }
93
94 void WebEditorClient::toggleContinuousSpellChecking()
95 {
96     notImplemented();
97 }
98
99 bool WebEditorClient::isGrammarCheckingEnabled()
100 {
101     return WebProcess::shared().textCheckerState().isGrammarCheckingEnabled;
102 }
103
104 void WebEditorClient::toggleGrammarChecking()
105 {
106     notImplemented();
107 }
108
109 int WebEditorClient::spellCheckerDocumentTag()
110 {
111     notImplemented();
112     return false;
113 }
114
115     
116 bool WebEditorClient::isEditable()
117 {
118     notImplemented();
119     return false;
120 }
121
122
123 bool WebEditorClient::shouldBeginEditing(Range* range)
124 {
125     bool result = m_page->injectedBundleEditorClient().shouldBeginEditing(m_page, range);
126     notImplemented();
127     return result;
128 }
129
130 bool WebEditorClient::shouldEndEditing(Range* range)
131 {
132     bool result = m_page->injectedBundleEditorClient().shouldEndEditing(m_page, range);
133     notImplemented();
134     return result;
135 }
136
137 bool WebEditorClient::shouldInsertNode(Node* node, Range* rangeToReplace, EditorInsertAction action)
138 {
139     bool result = m_page->injectedBundleEditorClient().shouldInsertNode(m_page, node, rangeToReplace, action);
140     notImplemented();
141     return result;
142 }
143
144 bool WebEditorClient::shouldInsertText(const String& text, Range* rangeToReplace, EditorInsertAction action)
145 {
146     bool result = m_page->injectedBundleEditorClient().shouldInsertText(m_page, text.impl(), rangeToReplace, action);
147     notImplemented();
148     return result;
149 }
150
151 bool WebEditorClient::shouldChangeSelectedRange(Range* fromRange, Range* toRange, EAffinity affinity, bool stillSelecting)
152 {
153     bool result = m_page->injectedBundleEditorClient().shouldChangeSelectedRange(m_page, fromRange, toRange, affinity, stillSelecting);
154     notImplemented();
155     return result;
156 }
157     
158 bool WebEditorClient::shouldApplyStyle(CSSStyleDeclaration* style, Range* range)
159 {
160     bool result = m_page->injectedBundleEditorClient().shouldApplyStyle(m_page, style, range);
161     notImplemented();
162     return result;
163 }
164
165 bool WebEditorClient::shouldMoveRangeAfterDelete(Range*, Range*)
166 {
167     notImplemented();
168     return true;
169 }
170
171 void WebEditorClient::didBeginEditing()
172 {
173     // FIXME: What good is a notification name, if it's always the same?
174     DEFINE_STATIC_LOCAL(String, WebViewDidBeginEditingNotification, ("WebViewDidBeginEditingNotification"));
175     m_page->injectedBundleEditorClient().didBeginEditing(m_page, WebViewDidBeginEditingNotification.impl());
176     notImplemented();
177 }
178
179 void WebEditorClient::respondToChangedContents()
180 {
181     DEFINE_STATIC_LOCAL(String, WebViewDidChangeNotification, ("WebViewDidChangeNotification"));
182     m_page->injectedBundleEditorClient().didChange(m_page, WebViewDidChangeNotification.impl());
183     notImplemented();
184 }
185
186 void WebEditorClient::respondToChangedSelection()
187 {
188     DEFINE_STATIC_LOCAL(String, WebViewDidChangeSelectionNotification, ("WebViewDidChangeSelectionNotification"));
189     m_page->injectedBundleEditorClient().didChangeSelection(m_page, WebViewDidChangeSelectionNotification.impl());
190     Frame* frame = m_page->corePage()->focusController()->focusedFrame();
191     if (!frame)
192         return;
193
194     SelectionState selectionState;
195     selectionState.isNone = frame->selection()->isNone();
196     selectionState.isContentEditable = frame->selection()->isContentEditable();
197     selectionState.isContentRichlyEditable = frame->selection()->isContentRichlyEditable();
198     selectionState.isInPasswordField = frame->selection()->isInPasswordField();
199     selectionState.hasComposition = frame->editor()->hasComposition();
200
201     RefPtr<Range> range = frame->selection()->toNormalizedRange();
202     if (range) {
203         size_t location;
204         size_t length;
205         if (!TextIterator::locationAndLengthFromRange(range.get(), location, length))
206             return;
207         selectionState.selectedRangeStart = static_cast<uint64_t>(location);
208         selectionState.selectedRangeLength = static_cast<uint64_t>(length);
209     }
210
211     m_page->send(Messages::WebPageProxy::SelectionStateChanged(selectionState));
212
213 #if PLATFORM(WIN)
214     // FIXME: This should also go into the selection state.
215     if (!frame->editor()->hasComposition() || frame->editor()->ignoreCompositionSelectionChange())
216         return;
217
218     unsigned start;
219     unsigned end;
220     m_page->send(Messages::WebPageProxy::DidChangeCompositionSelection(frame->editor()->getCompositionSelection(start, end)));
221 #endif
222 }
223     
224 void WebEditorClient::didEndEditing()
225 {
226     DEFINE_STATIC_LOCAL(String, WebViewDidEndEditingNotification, ("WebViewDidEndEditingNotification"));
227     m_page->injectedBundleEditorClient().didEndEditing(m_page, WebViewDidEndEditingNotification.impl());
228     notImplemented();
229 }
230
231 void WebEditorClient::didWriteSelectionToPasteboard()
232 {
233     notImplemented();
234 }
235
236 void WebEditorClient::didSetSelectionTypesForPasteboard()
237 {
238     notImplemented();
239 }
240
241 void WebEditorClient::registerCommandForUndo(PassRefPtr<EditCommand> command)
242 {
243     // FIXME: Add assertion that the command being reapplied is the same command that is
244     // being passed to us.
245     if (m_page->isInRedo())
246         return;
247
248     RefPtr<WebEditCommand> webCommand = WebEditCommand::create(command);
249     m_page->addWebEditCommand(webCommand->commandID(), webCommand.get());
250     uint32_t editAction = static_cast<uint32_t>(webCommand->command()->editingAction());
251
252     m_page->send(Messages::WebPageProxy::RegisterEditCommandForUndo(webCommand->commandID(), editAction));
253 }
254
255 void WebEditorClient::registerCommandForRedo(PassRefPtr<EditCommand>)
256 {
257 }
258
259 void WebEditorClient::clearUndoRedoOperations()
260 {
261     m_page->send(Messages::WebPageProxy::ClearAllEditCommands());
262 }
263
264 bool WebEditorClient::canCopyCut(bool defaultValue) const
265 {
266     return defaultValue;
267 }
268
269 bool WebEditorClient::canPaste(bool defaultValue) const
270 {
271     return defaultValue;
272 }
273
274 bool WebEditorClient::canUndo() const
275 {
276     bool result = false;
277     m_page->sendSync(Messages::WebPageProxy::CanUndoRedo(static_cast<uint32_t>(WebPageProxy::Undo)), Messages::WebPageProxy::CanUndoRedo::Reply(result));
278     return result;
279 }
280
281 bool WebEditorClient::canRedo() const
282 {
283     bool result = false;
284     m_page->sendSync(Messages::WebPageProxy::CanUndoRedo(static_cast<uint32_t>(WebPageProxy::Redo)), Messages::WebPageProxy::CanUndoRedo::Reply(result));
285     return result;
286 }
287
288 void WebEditorClient::undo()
289 {
290     bool result = false;
291     m_page->sendSync(Messages::WebPageProxy::ExecuteUndoRedo(static_cast<uint32_t>(WebPageProxy::Undo)), Messages::WebPageProxy::ExecuteUndoRedo::Reply(result));
292 }
293
294 void WebEditorClient::redo()
295 {
296     bool result = false;
297     m_page->sendSync(Messages::WebPageProxy::ExecuteUndoRedo(static_cast<uint32_t>(WebPageProxy::Redo)), Messages::WebPageProxy::ExecuteUndoRedo::Reply(result));
298 }
299
300 #if !PLATFORM(GTK) && !PLATFORM(MAC)
301 void WebEditorClient::handleKeyboardEvent(KeyboardEvent* event)
302 {
303     if (m_page->handleEditingKeyboardEvent(event))
304         event->setDefaultHandled();
305 }
306
307 void WebEditorClient::handleInputMethodKeydown(KeyboardEvent*)
308 {
309     notImplemented();
310 }
311 #endif
312
313 void WebEditorClient::textFieldDidBeginEditing(Element* element)
314 {
315     if (!element->hasTagName(inputTag))
316         return;
317
318     WebFrame* webFrame =  static_cast<WebFrameLoaderClient*>(element->document()->frame()->loader()->client())->webFrame();
319     m_page->injectedBundleFormClient().textFieldDidBeginEditing(m_page, static_cast<HTMLInputElement*>(element), webFrame);
320 }
321
322 void WebEditorClient::textFieldDidEndEditing(Element* element)
323 {
324     if (!element->hasTagName(inputTag))
325         return;
326
327     WebFrame* webFrame =  static_cast<WebFrameLoaderClient*>(element->document()->frame()->loader()->client())->webFrame();
328     m_page->injectedBundleFormClient().textFieldDidEndEditing(m_page, static_cast<HTMLInputElement*>(element), webFrame);
329 }
330
331 void WebEditorClient::textDidChangeInTextField(Element* element)
332 {
333     if (!element->hasTagName(inputTag))
334         return;
335
336     if (!UserTypingGestureIndicator::processingUserTypingGesture() || UserTypingGestureIndicator::focusedElementAtGestureStart() != element)
337         return;
338
339     WebFrame* webFrame =  static_cast<WebFrameLoaderClient*>(element->document()->frame()->loader()->client())->webFrame();
340     m_page->injectedBundleFormClient().textDidChangeInTextField(m_page, static_cast<HTMLInputElement*>(element), webFrame);
341 }
342
343 void WebEditorClient::textDidChangeInTextArea(Element* element)
344 {
345     if (!element->hasTagName(textareaTag))
346         return;
347
348     WebFrame* webFrame =  static_cast<WebFrameLoaderClient*>(element->document()->frame()->loader()->client())->webFrame();
349     m_page->injectedBundleFormClient().textDidChangeInTextArea(m_page, static_cast<HTMLTextAreaElement*>(element), webFrame);
350 }
351
352 static bool getActionTypeForKeyEvent(KeyboardEvent* event, WKInputFieldActionType& type)
353 {
354     String key = event->keyIdentifier();
355     if (key == "Up")
356         type = WKInputFieldActionTypeMoveUp;
357     else if (key == "Down")
358         type = WKInputFieldActionTypeMoveDown;
359     else if (key == "U+001B")
360         type = WKInputFieldActionTypeCancel;
361     else if (key == "U+0009") {
362         if (event->shiftKey())
363             type = WKInputFieldActionTypeInsertBacktab;
364         else
365             type = WKInputFieldActionTypeInsertTab;
366     } else if (key == "Enter")
367         type = WKInputFieldActionTypeInsertNewline;
368     else
369         return false;
370
371     return true;
372 }
373
374 bool WebEditorClient::doTextFieldCommandFromEvent(Element* element, KeyboardEvent* event)
375 {
376     if (!element->hasTagName(inputTag))
377         return false;
378
379     WKInputFieldActionType actionType = static_cast<WKInputFieldActionType>(0);
380     if (!getActionTypeForKeyEvent(event, actionType))
381         return false;
382
383     WebFrame* webFrame =  static_cast<WebFrameLoaderClient*>(element->document()->frame()->loader()->client())->webFrame();
384     return m_page->injectedBundleFormClient().shouldPerformActionInTextField(m_page, static_cast<HTMLInputElement*>(element), actionType, webFrame);
385 }
386
387 void WebEditorClient::textWillBeDeletedInTextField(Element* element)
388 {
389     if (!element->hasTagName(inputTag))
390         return;
391
392     WebFrame* webFrame =  static_cast<WebFrameLoaderClient*>(element->document()->frame()->loader()->client())->webFrame();
393     m_page->injectedBundleFormClient().shouldPerformActionInTextField(m_page, static_cast<HTMLInputElement*>(element), WKInputFieldActionTypeInsertDelete, webFrame);
394 }
395
396 void WebEditorClient::ignoreWordInSpellDocument(const String& word)
397 {
398     m_page->send(Messages::WebPageProxy::IgnoreWord(word));
399 }
400
401 void WebEditorClient::learnWord(const String& word)
402 {
403     m_page->send(Messages::WebPageProxy::LearnWord(word));
404 }
405
406 void WebEditorClient::checkSpellingOfString(const UChar* text, int length, int* misspellingLocation, int* misspellingLength)
407 {
408     int32_t resultLocation = -1;
409     int32_t resultLength = 0;
410     // FIXME: It would be nice if we wouldn't have to copy the text here.
411     m_page->sendSync(Messages::WebPageProxy::CheckSpellingOfString(String(text, length)),
412         Messages::WebPageProxy::CheckSpellingOfString::Reply(resultLocation, resultLength));
413     *misspellingLocation = resultLocation;
414     *misspellingLength = resultLength;
415 }
416
417 String WebEditorClient::getAutoCorrectSuggestionForMisspelledWord(const String&)
418 {
419     notImplemented();
420     return String();
421 }
422
423 void WebEditorClient::checkGrammarOfString(const UChar* text, int length, Vector<WebCore::GrammarDetail>& grammarDetails, int* badGrammarLocation, int* badGrammarLength)
424 {
425     int32_t resultLocation = -1;
426     int32_t resultLength = 0;
427     // FIXME: It would be nice if we wouldn't have to copy the text here.
428     m_page->sendSync(Messages::WebPageProxy::CheckGrammarOfString(String(text, length)),
429         Messages::WebPageProxy::CheckGrammarOfString::Reply(grammarDetails, resultLocation, resultLength));
430     *badGrammarLocation = resultLocation;
431     *badGrammarLength = resultLength;
432 }
433
434 void WebEditorClient::updateSpellingUIWithGrammarString(const String& badGrammarPhrase, const GrammarDetail& grammarDetail)
435 {
436     m_page->send(Messages::WebPageProxy::UpdateSpellingUIWithGrammarString(badGrammarPhrase, grammarDetail));
437 }
438
439 void WebEditorClient::updateSpellingUIWithMisspelledWord(const String& misspelledWord)
440 {
441     m_page->send(Messages::WebPageProxy::UpdateSpellingUIWithMisspelledWord(misspelledWord));
442 }
443
444 void WebEditorClient::showSpellingUI(bool)
445 {
446     notImplemented();
447 }
448
449 bool WebEditorClient::spellingUIIsShowing()
450 {
451     bool isShowing = false;
452     m_page->sendSync(Messages::WebPageProxy::SpellingUIIsShowing(), Messages::WebPageProxy::SpellingUIIsShowing::Reply(isShowing));
453     return isShowing;
454 }
455
456 void WebEditorClient::getGuessesForWord(const String& word, const String& context, Vector<String>& guesses)
457 {
458     m_page->sendSync(Messages::WebPageProxy::GetGuessesForWord(word, context), Messages::WebPageProxy::GetGuessesForWord::Reply(guesses));
459 }
460
461 void WebEditorClient::willSetInputMethodState()
462 {
463     notImplemented();
464 }
465
466 void WebEditorClient::setInputMethodState(bool)
467 {
468     notImplemented();
469 }
470
471 void WebEditorClient::requestCheckingOfString(WebCore::SpellChecker*, int, WebCore::TextCheckingTypeMask, const WTF::String&)
472 {
473     notImplemented();
474 }
475
476 } // namespace WebKit