Do not notify editor state during executing command
[framework/web/webkit-efl.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 "EditorState.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/FocusController.h>
39 #include <WebCore/Frame.h>
40 #include <WebCore/FrameView.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/UndoStep.h>
49 #include <WebCore/UserTypingGestureIndicator.h>
50
51 using namespace WebCore;
52 using namespace HTMLNames;
53
54 namespace WebKit {
55
56 void WebEditorClient::pageDestroyed()
57 {
58     delete this;
59 }
60
61 bool WebEditorClient::shouldDeleteRange(Range* range)
62 {
63     bool result = m_page->injectedBundleEditorClient().shouldDeleteRange(m_page, range);
64     notImplemented();
65     return result;
66 }
67
68 #if OS(TIZEN) // https://bugs.webkit.org/show_bug.cgi?id=86615
69 bool WebEditorClient::shouldShowDeleteInterface(HTMLElement* element)
70 {
71     return element->getAttribute(HTMLNames::classAttr) == "needsDeletionUI";
72 }
73 #else
74 bool WebEditorClient::shouldShowDeleteInterface(HTMLElement*)
75 {
76     notImplemented();
77     return false;
78 }
79 #endif
80
81 bool WebEditorClient::smartInsertDeleteEnabled()
82 {
83     // FIXME: Why isn't this Mac specific like toggleSmartInsertDeleteEnabled?
84 #if PLATFORM(MAC)
85     return m_page->isSmartInsertDeleteEnabled();
86 #else
87     return true;
88 #endif
89 }
90  
91 bool WebEditorClient::isSelectTrailingWhitespaceEnabled()
92 {
93     notImplemented();
94     return false;
95 }
96
97 bool WebEditorClient::isContinuousSpellCheckingEnabled()
98 {
99     return WebProcess::shared().textCheckerState().isContinuousSpellCheckingEnabled;
100 }
101
102 void WebEditorClient::toggleContinuousSpellChecking()
103 {
104     notImplemented();
105 }
106
107 bool WebEditorClient::isGrammarCheckingEnabled()
108 {
109     return WebProcess::shared().textCheckerState().isGrammarCheckingEnabled;
110 }
111
112 void WebEditorClient::toggleGrammarChecking()
113 {
114     notImplemented();
115 }
116
117 int WebEditorClient::spellCheckerDocumentTag()
118 {
119     notImplemented();
120     return false;
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(StylePropertySet* style, Range* range)
159 {
160     bool result = m_page->injectedBundleEditorClient().shouldApplyStyle(m_page, style->ensureCSSStyleDeclaration(), 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(Frame* frame)
187 {
188 #if ENABLE(TIZEN_ISF_PORT)
189     if (m_lockCountOfRespondToChangedSelection)
190         return;
191 #endif
192
193     DEFINE_STATIC_LOCAL(String, WebViewDidChangeSelectionNotification, ("WebViewDidChangeSelectionNotification"));
194     m_page->injectedBundleEditorClient().didChangeSelection(m_page, WebViewDidChangeSelectionNotification.impl());
195     if (!frame)
196         return;
197
198     EditorState state = m_page->editorState();
199
200 #if ENABLE(TIZEN_ISF_PORT) || ENABLE(TIZEN_WEBKIT2_TEXT_SELECTION)
201     const EditorState& currentState = m_page->currentEditorState();
202     if (currentState.hasComposition && currentState.inputMethodContextID != state.inputMethodContextID)
203         didCancelComposition(reinterpret_cast<Node*>(currentState.inputMethodContextID));
204
205     m_page->setEditorState(state);
206 #endif
207
208     m_page->send(Messages::WebPageProxy::EditorStateChanged(state));
209
210 #if PLATFORM(WIN)
211     // FIXME: This should also go into the selection state.
212     if (!frame->editor()->hasComposition() || frame->editor()->ignoreCompositionSelectionChange())
213         return;
214
215     unsigned start;
216     unsigned end;
217     m_page->send(Messages::WebPageProxy::DidChangeCompositionSelection(frame->editor()->getCompositionSelection(start, end)));
218 #elif PLATFORM(GTK)
219     setSelectionPrimaryClipboardIfNeeded(frame);
220 #endif
221 }
222
223 void WebEditorClient::didEndEditing()
224 {
225     DEFINE_STATIC_LOCAL(String, WebViewDidEndEditingNotification, ("WebViewDidEndEditingNotification"));
226     m_page->injectedBundleEditorClient().didEndEditing(m_page, WebViewDidEndEditingNotification.impl());
227     notImplemented();
228 }
229
230 void WebEditorClient::didWriteSelectionToPasteboard()
231 {
232     notImplemented();
233 }
234
235 void WebEditorClient::didSetSelectionTypesForPasteboard()
236 {
237     notImplemented();
238 }
239
240 void WebEditorClient::registerUndoStep(PassRefPtr<UndoStep> step)
241 {
242     // FIXME: Add assertion that the command being reapplied is the same command that is
243     // being passed to us.
244     if (m_page->isInRedo())
245         return;
246
247     RefPtr<WebUndoStep> webStep = WebUndoStep::create(step);
248     m_page->addWebUndoStep(webStep->stepID(), webStep.get());
249     uint32_t editAction = static_cast<uint32_t>(webStep->step()->editingAction());
250
251     m_page->send(Messages::WebPageProxy::RegisterEditCommandForUndo(webStep->stepID(), editAction));
252 }
253
254 void WebEditorClient::registerRedoStep(PassRefPtr<UndoStep>)
255 {
256 }
257
258 void WebEditorClient::clearUndoRedoOperations()
259 {
260     m_page->send(Messages::WebPageProxy::ClearAllEditCommands());
261 }
262
263 bool WebEditorClient::canCopyCut(Frame*, bool defaultValue) const
264 {
265     return defaultValue;
266 }
267
268 bool WebEditorClient::canPaste(Frame*, bool defaultValue) const
269 {
270     return defaultValue;
271 }
272
273 bool WebEditorClient::canUndo() const
274 {
275     bool result = false;
276     m_page->sendSync(Messages::WebPageProxy::CanUndoRedo(static_cast<uint32_t>(WebPageProxy::Undo)), Messages::WebPageProxy::CanUndoRedo::Reply(result));
277     return result;
278 }
279
280 bool WebEditorClient::canRedo() const
281 {
282     bool result = false;
283     m_page->sendSync(Messages::WebPageProxy::CanUndoRedo(static_cast<uint32_t>(WebPageProxy::Redo)), Messages::WebPageProxy::CanUndoRedo::Reply(result));
284     return result;
285 }
286
287 void WebEditorClient::undo()
288 {
289     bool result = false;
290     m_page->sendSync(Messages::WebPageProxy::ExecuteUndoRedo(static_cast<uint32_t>(WebPageProxy::Undo)), Messages::WebPageProxy::ExecuteUndoRedo::Reply(result));
291 }
292
293 void WebEditorClient::redo()
294 {
295     bool result = false;
296     m_page->sendSync(Messages::WebPageProxy::ExecuteUndoRedo(static_cast<uint32_t>(WebPageProxy::Redo)), Messages::WebPageProxy::ExecuteUndoRedo::Reply(result));
297 }
298
299 #if !PLATFORM(GTK) && !PLATFORM(MAC) && !PLATFORM(EFL)
300 void WebEditorClient::handleKeyboardEvent(KeyboardEvent* event)
301 {
302     if (m_page->handleEditingKeyboardEvent(event))
303         event->setDefaultHandled();
304 }
305
306 void WebEditorClient::handleInputMethodKeydown(KeyboardEvent*)
307 {
308     notImplemented();
309 }
310 #endif
311
312 void WebEditorClient::textFieldDidBeginEditing(Element* element)
313 {
314     if (!element->hasTagName(inputTag))
315         return;
316
317     WebFrame* webFrame =  static_cast<WebFrameLoaderClient*>(element->document()->frame()->loader()->client())->webFrame();
318     m_page->injectedBundleFormClient().textFieldDidBeginEditing(m_page, static_cast<HTMLInputElement*>(element), webFrame);
319 }
320
321 void WebEditorClient::textFieldDidEndEditing(Element* element)
322 {
323     if (!element->hasTagName(inputTag))
324         return;
325
326     WebFrame* webFrame =  static_cast<WebFrameLoaderClient*>(element->document()->frame()->loader()->client())->webFrame();
327     m_page->injectedBundleFormClient().textFieldDidEndEditing(m_page, static_cast<HTMLInputElement*>(element), webFrame);
328 }
329
330 void WebEditorClient::textDidChangeInTextField(Element* element)
331 {
332     if (!element->hasTagName(inputTag))
333         return;
334
335 #if ENABLE(TIZEN_WEBKIT2_FORM_DATABASE)
336     HTMLInputElement* inputElement = static_cast<HTMLInputElement*>(element);
337     if (inputElement->shouldAutocomplete() && !(inputElement->isPasswordField()))
338         m_page->send(Messages::WebPageProxy::TextChangeInTextField(inputElement->name(), inputElement->value()));
339 #endif
340
341     if (!UserTypingGestureIndicator::processingUserTypingGesture() || UserTypingGestureIndicator::focusedElementAtGestureStart() != element)
342         return;
343
344     WebFrame* webFrame =  static_cast<WebFrameLoaderClient*>(element->document()->frame()->loader()->client())->webFrame();
345     m_page->injectedBundleFormClient().textDidChangeInTextField(m_page, static_cast<HTMLInputElement*>(element), webFrame);
346 }
347
348 void WebEditorClient::textDidChangeInTextArea(Element* element)
349 {
350     if (!element->hasTagName(textareaTag))
351         return;
352
353     WebFrame* webFrame =  static_cast<WebFrameLoaderClient*>(element->document()->frame()->loader()->client())->webFrame();
354     m_page->injectedBundleFormClient().textDidChangeInTextArea(m_page, static_cast<HTMLTextAreaElement*>(element), webFrame);
355 }
356
357 static bool getActionTypeForKeyEvent(KeyboardEvent* event, WKInputFieldActionType& type)
358 {
359     String key = event->keyIdentifier();
360     if (key == "Up")
361         type = WKInputFieldActionTypeMoveUp;
362     else if (key == "Down")
363         type = WKInputFieldActionTypeMoveDown;
364     else if (key == "U+001B")
365         type = WKInputFieldActionTypeCancel;
366     else if (key == "U+0009") {
367         if (event->shiftKey())
368             type = WKInputFieldActionTypeInsertBacktab;
369         else
370             type = WKInputFieldActionTypeInsertTab;
371     } else if (key == "Enter")
372         type = WKInputFieldActionTypeInsertNewline;
373     else
374         return false;
375
376     return true;
377 }
378
379 bool WebEditorClient::doTextFieldCommandFromEvent(Element* element, KeyboardEvent* event)
380 {
381     if (!element->hasTagName(inputTag))
382         return false;
383
384     WKInputFieldActionType actionType = static_cast<WKInputFieldActionType>(0);
385     if (!getActionTypeForKeyEvent(event, actionType))
386         return false;
387
388     WebFrame* webFrame =  static_cast<WebFrameLoaderClient*>(element->document()->frame()->loader()->client())->webFrame();
389     return m_page->injectedBundleFormClient().shouldPerformActionInTextField(m_page, static_cast<HTMLInputElement*>(element), actionType, webFrame);
390 }
391
392 void WebEditorClient::textWillBeDeletedInTextField(Element* element)
393 {
394     if (!element->hasTagName(inputTag))
395         return;
396
397     WebFrame* webFrame =  static_cast<WebFrameLoaderClient*>(element->document()->frame()->loader()->client())->webFrame();
398     m_page->injectedBundleFormClient().shouldPerformActionInTextField(m_page, static_cast<HTMLInputElement*>(element), WKInputFieldActionTypeInsertDelete, webFrame);
399 }
400
401 bool WebEditorClient::shouldEraseMarkersAfterChangeSelection(WebCore::TextCheckingType type) const
402 {
403     // This prevents erasing spelling markers on OS X Lion or later to match AppKit on these Mac OS X versions.
404 #if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
405     return type != TextCheckingTypeSpelling;
406 #else
407     return true;
408 #endif
409 }
410
411 void WebEditorClient::ignoreWordInSpellDocument(const String& word)
412 {
413     m_page->send(Messages::WebPageProxy::IgnoreWord(word));
414 }
415
416 void WebEditorClient::learnWord(const String& word)
417 {
418     m_page->send(Messages::WebPageProxy::LearnWord(word));
419 }
420
421 void WebEditorClient::checkSpellingOfString(const UChar* text, int length, int* misspellingLocation, int* misspellingLength)
422 {
423     int32_t resultLocation = -1;
424     int32_t resultLength = 0;
425     // FIXME: It would be nice if we wouldn't have to copy the text here.
426     m_page->sendSync(Messages::WebPageProxy::CheckSpellingOfString(String(text, length)),
427         Messages::WebPageProxy::CheckSpellingOfString::Reply(resultLocation, resultLength));
428     *misspellingLocation = resultLocation;
429     *misspellingLength = resultLength;
430 }
431
432 String WebEditorClient::getAutoCorrectSuggestionForMisspelledWord(const String&)
433 {
434     notImplemented();
435     return String();
436 }
437
438 void WebEditorClient::checkGrammarOfString(const UChar* text, int length, Vector<WebCore::GrammarDetail>& grammarDetails, int* badGrammarLocation, int* badGrammarLength)
439 {
440     int32_t resultLocation = -1;
441     int32_t resultLength = 0;
442     // FIXME: It would be nice if we wouldn't have to copy the text here.
443     m_page->sendSync(Messages::WebPageProxy::CheckGrammarOfString(String(text, length)),
444         Messages::WebPageProxy::CheckGrammarOfString::Reply(grammarDetails, resultLocation, resultLength));
445     *badGrammarLocation = resultLocation;
446     *badGrammarLength = resultLength;
447 }
448
449 void WebEditorClient::updateSpellingUIWithGrammarString(const String& badGrammarPhrase, const GrammarDetail& grammarDetail)
450 {
451     m_page->send(Messages::WebPageProxy::UpdateSpellingUIWithGrammarString(badGrammarPhrase, grammarDetail));
452 }
453
454 void WebEditorClient::updateSpellingUIWithMisspelledWord(const String& misspelledWord)
455 {
456     m_page->send(Messages::WebPageProxy::UpdateSpellingUIWithMisspelledWord(misspelledWord));
457 }
458
459 void WebEditorClient::showSpellingUI(bool)
460 {
461     notImplemented();
462 }
463
464 bool WebEditorClient::spellingUIIsShowing()
465 {
466     bool isShowing = false;
467     m_page->sendSync(Messages::WebPageProxy::SpellingUIIsShowing(), Messages::WebPageProxy::SpellingUIIsShowing::Reply(isShowing));
468     return isShowing;
469 }
470
471 void WebEditorClient::getGuessesForWord(const String& word, const String& context, Vector<String>& guesses)
472 {
473     m_page->sendSync(Messages::WebPageProxy::GetGuessesForWord(word, context), Messages::WebPageProxy::GetGuessesForWord::Reply(guesses));
474 }
475
476 void WebEditorClient::willSetInputMethodState()
477 {
478     notImplemented();
479 }
480
481 void WebEditorClient::setInputMethodState(bool active)
482 {
483     notImplemented();
484 }
485
486 void WebEditorClient::requestCheckingOfString(WTF::PassRefPtr<WebCore::TextCheckingRequest>)
487 {
488     notImplemented();
489 }
490
491 } // namespace WebKit