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