Expand r209943 to suppress paste during provisional navigation as well
[WebKit-https.git] / Source / WebCore / editing / Editor.cpp
1 /*
2  * Copyright (C) 2006-2016 Apple Inc. All rights reserved.
3  * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE 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 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. 
25  */
26
27 #include "config.h"
28 #include "Editor.h"
29
30 #include "AXObjectCache.h"
31 #include "AlternativeTextController.h"
32 #include "ApplyStyleCommand.h"
33 #include "CSSComputedStyleDeclaration.h"
34 #include "CSSPropertyNames.h"
35 #include "CachedResourceLoader.h"
36 #include "ClipboardEvent.h"
37 #include "CompositionEvent.h"
38 #include "CreateLinkCommand.h"
39 #include "DataTransfer.h"
40 #include "DeleteSelectionCommand.h"
41 #include "DictationAlternative.h"
42 #include "DictationCommand.h"
43 #include "DocumentFragment.h"
44 #include "DocumentMarkerController.h"
45 #include "Editing.h"
46 #include "EditorClient.h"
47 #include "EventHandler.h"
48 #include "EventNames.h"
49 #include "FocusController.h"
50 #include "Frame.h"
51 #include "FrameLoader.h"
52 #include "FrameTree.h"
53 #include "FrameView.h"
54 #include "GraphicsContext.h"
55 #include "HTMLCollection.h"
56 #include "HTMLFormControlElement.h"
57 #include "HTMLFrameOwnerElement.h"
58 #include "HTMLImageElement.h"
59 #include "HTMLInputElement.h"
60 #include "HTMLNames.h"
61 #include "HTMLSpanElement.h"
62 #include "HitTestResult.h"
63 #include "IndentOutdentCommand.h"
64 #include "InputEvent.h"
65 #include "InsertListCommand.h"
66 #include "InsertTextCommand.h"
67 #include "KeyboardEvent.h"
68 #include "Logging.h"
69 #include "MainFrame.h"
70 #include "ModifySelectionListLevel.h"
71 #include "NodeList.h"
72 #include "NodeTraversal.h"
73 #include "Page.h"
74 #include "Pasteboard.h"
75 #include "Range.h"
76 #include "RemoveFormatCommand.h"
77 #include "RenderBlock.h"
78 #include "RenderTextControl.h"
79 #include "RenderedDocumentMarker.h"
80 #include "RenderedPosition.h"
81 #include "ReplaceRangeWithTextCommand.h"
82 #include "ReplaceSelectionCommand.h"
83 #include "Settings.h"
84 #include "ShadowRoot.h"
85 #include "SimplifyMarkupCommand.h"
86 #include "SpellChecker.h"
87 #include "SpellingCorrectionCommand.h"
88 #include "StaticPasteboard.h"
89 #include "StyleProperties.h"
90 #include "TelephoneNumberDetector.h"
91 #include "Text.h"
92 #include "TextCheckerClient.h"
93 #include "TextCheckingHelper.h"
94 #include "TextEvent.h"
95 #include "TextIterator.h"
96 #include "TypingCommand.h"
97 #include "UserTypingGestureIndicator.h"
98 #include "VisibleUnits.h"
99 #include "markup.h"
100 #include <pal/system/Sound.h>
101 #include <pal/text/KillRing.h>
102 #include <wtf/unicode/CharacterNames.h>
103
104 #if PLATFORM(MAC)
105 #include "ServicesOverlayController.h"
106 #endif
107
108 namespace WebCore {
109
110 static bool dispatchBeforeInputEvent(Element& element, const AtomicString& inputType, const String& data = { }, RefPtr<DataTransfer>&& dataTransfer = nullptr, const Vector<RefPtr<StaticRange>>& targetRanges = { }, bool cancelable = true)
111 {
112     if (!element.document().settings().inputEventsEnabled())
113         return true;
114
115     return element.dispatchEvent(InputEvent::create(eventNames().beforeinputEvent, inputType, true, cancelable, element.document().defaultView(), data, WTFMove(dataTransfer), targetRanges, 0));
116 }
117
118 static void dispatchInputEvent(Element& element, const AtomicString& inputType, const String& data = { }, RefPtr<DataTransfer>&& dataTransfer = nullptr, const Vector<RefPtr<StaticRange>>& targetRanges = { })
119 {
120     if (element.document().settings().inputEventsEnabled()) {
121         // FIXME: We should not be dispatching to the scoped queue here. Normally, input events are dispatched in CompositeEditCommand::apply after the end of the scope,
122         // but TypingCommands are special in that existing TypingCommands that are applied again fire input events *from within* the scope by calling typingAddedToOpenCommand.
123         // Instead, TypingCommands should always dispatch events synchronously after the end of the scoped queue in CompositeEditCommand::apply. To work around this for the
124         // time being, just revert back to calling dispatchScopedEvent.
125         element.dispatchScopedEvent(InputEvent::create(eventNames().inputEvent, inputType, true, false, element.document().defaultView(), data, WTFMove(dataTransfer), targetRanges, 0));
126     } else
127         element.dispatchInputEvent();
128 }
129
130 static String inputEventDataForEditingStyleAndAction(const StyleProperties* style, EditAction action)
131 {
132     if (!style)
133         return { };
134
135     switch (action) {
136     case EditActionSetColor:
137         return style->getPropertyValue(CSSPropertyColor);
138     case EditActionSetWritingDirection:
139         return style->getPropertyValue(CSSPropertyDirection);
140     default:
141         return { };
142     }
143 }
144
145 static String inputEventDataForEditingStyleAndAction(EditingStyle& style, EditAction action)
146 {
147     return inputEventDataForEditingStyleAndAction(style.style(), action);
148 }
149
150 class ClearTextCommand : public DeleteSelectionCommand {
151 public:
152     ClearTextCommand(Document& document);
153     static void CreateAndApply(const RefPtr<Frame> frame);
154     
155 private:
156     EditAction editingAction() const override;
157 };
158
159 ClearTextCommand::ClearTextCommand(Document& document)
160     : DeleteSelectionCommand(document, false, true, false, false, true)
161 {
162 }
163
164 EditAction ClearTextCommand::editingAction() const
165 {
166     return EditActionDelete;
167 }
168
169 void ClearTextCommand::CreateAndApply(const RefPtr<Frame> frame)
170 {
171     if (frame->selection().isNone())
172         return;
173
174     // Don't leave around stale composition state.
175     frame->editor().clear();
176     
177     const VisibleSelection oldSelection = frame->selection().selection();
178     frame->selection().selectAll();
179     auto clearCommand = adoptRef(*new ClearTextCommand(*frame->document()));
180     clearCommand->setStartingSelection(oldSelection);
181     clearCommand->apply();
182 }
183
184 using namespace HTMLNames;
185 using namespace WTF;
186 using namespace Unicode;
187
188 TemporarySelectionChange::TemporarySelectionChange(Frame& frame, std::optional<VisibleSelection> temporarySelection, TemporarySelectionOptions options)
189     : m_frame(frame)
190     , m_options(options)
191     , m_wasIgnoringSelectionChanges(frame.editor().ignoreSelectionChanges())
192 #if PLATFORM(IOS)
193     , m_appearanceUpdatesWereEnabled(frame.selection().isUpdateAppearanceEnabled())
194 #endif
195 {
196 #if PLATFORM(IOS)
197     if (options & TemporarySelectionOptionEnableAppearanceUpdates)
198         frame.selection().setUpdateAppearanceEnabled(true);
199 #endif
200
201     if (options & TemporarySelectionOptionIgnoreSelectionChanges)
202         frame.editor().setIgnoreSelectionChanges(true);
203
204     if (temporarySelection) {
205         m_selectionToRestore = frame.selection().selection();
206         frame.selection().setSelection(temporarySelection.value());
207     }
208 }
209
210 TemporarySelectionChange::~TemporarySelectionChange()
211 {
212     if (m_selectionToRestore)
213         m_frame->selection().setSelection(m_selectionToRestore.value());
214
215     if (m_options & TemporarySelectionOptionIgnoreSelectionChanges) {
216         auto revealSelection = m_options & TemporarySelectionOptionRevealSelection ? Editor::RevealSelection::Yes : Editor::RevealSelection::No;
217         m_frame->editor().setIgnoreSelectionChanges(m_wasIgnoringSelectionChanges, revealSelection);
218     }
219
220 #if PLATFORM(IOS)
221     if (m_options & TemporarySelectionOptionEnableAppearanceUpdates)
222         m_frame->selection().setUpdateAppearanceEnabled(m_appearanceUpdatesWereEnabled);
223 #endif
224 }
225
226 // When an event handler has moved the selection outside of a text control
227 // we should use the target control's selection for this editing operation.
228 VisibleSelection Editor::selectionForCommand(Event* event)
229 {
230     VisibleSelection selection = m_frame.selection().selection();
231     if (!event)
232         return selection;
233     // If the target is a text control, and the current selection is outside of its shadow tree,
234     // then use the saved selection for that text control.
235     HTMLTextFormControlElement* textFormControlOfSelectionStart = enclosingTextFormControl(selection.start());
236     HTMLTextFormControlElement* textFromControlOfTarget = is<HTMLTextFormControlElement>(*event->target()->toNode()) ? downcast<HTMLTextFormControlElement>(event->target()->toNode().get()) : nullptr;
237     if (textFromControlOfTarget && (selection.start().isNull() || textFromControlOfTarget != textFormControlOfSelectionStart)) {
238         if (RefPtr<Range> range = textFromControlOfTarget->selection())
239             return VisibleSelection(*range, DOWNSTREAM, selection.isDirectional());
240     }
241     return selection;
242 }
243
244 // Function considers Mac editing behavior a fallback when Page or Settings is not available.
245 EditingBehavior Editor::behavior() const
246 {
247     return EditingBehavior(m_frame.settings().editingBehaviorType());
248 }
249
250 EditorClient* Editor::client() const
251 {
252     if (Page* page = m_frame.page())
253         return &page->editorClient();
254     return nullptr;
255 }
256
257 TextCheckerClient* Editor::textChecker() const
258 {
259     if (EditorClient* owner = client())
260         return owner->textChecker();
261     return 0;
262 }
263
264 void Editor::handleKeyboardEvent(KeyboardEvent& event)
265 {
266     if (EditorClient* c = client())
267         c->handleKeyboardEvent(&event);
268 }
269
270 void Editor::handleInputMethodKeydown(KeyboardEvent& event)
271 {
272     if (EditorClient* c = client())
273         c->handleInputMethodKeydown(&event);
274 }
275
276 bool Editor::handleTextEvent(TextEvent& event)
277 {
278     LOG(Editing, "Editor %p handleTextEvent (data %s)", this, event.data().utf8().data());
279
280     // Default event handling for Drag and Drop will be handled by DragController
281     // so we leave the event for it.
282     if (event.isDrop())
283         return false;
284
285     if (event.isPaste()) {
286         if (event.pastingFragment()) {
287 #if PLATFORM(IOS)
288             if (client()->performsTwoStepPaste(event.pastingFragment()))
289                 return true;
290 #endif
291             replaceSelectionWithFragment(*event.pastingFragment(), false, event.shouldSmartReplace(), event.shouldMatchStyle(), EditActionPaste, event.mailBlockquoteHandling());
292         } else
293             replaceSelectionWithText(event.data(), false, event.shouldSmartReplace(), EditActionPaste);
294         return true;
295     }
296
297     String data = event.data();
298     if (data == "\n") {
299         if (event.isLineBreak())
300             return insertLineBreak();
301         return insertParagraphSeparator();
302     }
303
304     return insertTextWithoutSendingTextEvent(data, false, &event);
305 }
306
307 bool Editor::canEdit() const
308 {
309     return m_frame.selection().selection().rootEditableElement();
310 }
311
312 bool Editor::canEditRichly() const
313 {
314     return m_frame.selection().selection().isContentRichlyEditable();
315 }
316
317 enum class ClipboardEventKind {
318     Copy,
319     Cut,
320     Paste,
321     PasteAsPlainText,
322     BeforeCopy,
323     BeforeCut,
324     BeforePaste,
325 };
326
327 static AtomicString eventNameForClipboardEvent(ClipboardEventKind kind)
328 {
329     switch (kind) {
330     case ClipboardEventKind::Copy:
331         return eventNames().copyEvent;
332     case ClipboardEventKind::Cut:
333         return eventNames().cutEvent;
334     case ClipboardEventKind::Paste:
335     case ClipboardEventKind::PasteAsPlainText:
336         return eventNames().pasteEvent;
337     case ClipboardEventKind::BeforeCopy:
338         return eventNames().beforecopyEvent;
339     case ClipboardEventKind::BeforeCut:
340         return eventNames().beforecutEvent;
341     case ClipboardEventKind::BeforePaste:
342         return eventNames().beforepasteEvent;
343     }
344     ASSERT_NOT_REACHED();
345     return { };
346 }
347
348 static Ref<DataTransfer> createDataTransferForClipboardEvent(Document& document, ClipboardEventKind kind)
349 {
350     switch (kind) {
351     case ClipboardEventKind::Copy:
352     case ClipboardEventKind::Cut:
353         return DataTransfer::createForCopyAndPaste(document, DataTransfer::StoreMode::ReadWrite, std::make_unique<StaticPasteboard>());
354     case ClipboardEventKind::PasteAsPlainText:
355         if (Settings::customPasteboardDataEnabled()) {
356             auto plainTextType = ASCIILiteral("text/plain");
357             auto plainText = Pasteboard::createForCopyAndPaste()->readString(plainTextType);
358             auto pasteboard = std::make_unique<StaticPasteboard>();
359             pasteboard->writeString(plainTextType, plainText);
360             return DataTransfer::createForCopyAndPaste(document, DataTransfer::StoreMode::Readonly, WTFMove(pasteboard));
361         }
362         FALLTHROUGH;
363     case ClipboardEventKind::Paste:
364         return DataTransfer::createForCopyAndPaste(document, DataTransfer::StoreMode::Readonly, Pasteboard::createForCopyAndPaste());
365     case ClipboardEventKind::BeforeCopy:
366     case ClipboardEventKind::BeforeCut:
367     case ClipboardEventKind::BeforePaste:
368         return DataTransfer::createForCopyAndPaste(document, DataTransfer::StoreMode::Invalid, std::make_unique<StaticPasteboard>());
369     }
370     ASSERT_NOT_REACHED();
371     return DataTransfer::createForCopyAndPaste(document, DataTransfer::StoreMode::Invalid, std::make_unique<StaticPasteboard>());
372 }
373
374 // Returns whether caller should continue with "the default processing", which is the same as
375 // the event handler NOT setting the return value to false
376 // https://w3c.github.io/clipboard-apis/#fire-a-clipboard-event
377 static bool dispatchClipboardEvent(RefPtr<Element>&& target, ClipboardEventKind kind)
378 {
379     // FIXME: Move the target selection code here.
380     if (!target)
381         return true;
382
383     auto dataTransfer = createDataTransferForClipboardEvent(target->document(), kind);
384
385     ClipboardEvent::Init init;
386     init.bubbles = true;
387     init.cancelable = true;
388     init.clipboardData = dataTransfer.ptr();
389     auto event = ClipboardEvent::create(eventNameForClipboardEvent(kind), init, Event::IsTrusted::Yes);
390
391     target->dispatchEvent(event);
392     bool noDefaultProcessing = event->defaultPrevented();
393     if (noDefaultProcessing && (kind == ClipboardEventKind::Copy || kind == ClipboardEventKind::Cut)) {
394         auto pasteboard = Pasteboard::createForCopyAndPaste();
395         pasteboard->clear();
396         dataTransfer->commitToPasteboard(*pasteboard);
397     }
398
399     dataTransfer->makeInvalidForSecurity();
400
401     return !noDefaultProcessing;
402 }
403
404 // WinIE uses onbeforecut and onbeforepaste to enables the cut and paste menu items.  They
405 // also send onbeforecopy, apparently for symmetry, but it doesn't affect the menu items.
406 // We need to use onbeforecopy as a real menu enabler because we allow elements that are not
407 // normally selectable to implement copy/paste (like divs, or a document body).
408
409 bool Editor::canDHTMLCut()
410 {
411     if (m_frame.selection().selection().isInPasswordField())
412         return false;
413
414     return !dispatchClipboardEvent(findEventTargetFromSelection(), ClipboardEventKind::BeforeCut);
415 }
416
417 bool Editor::canDHTMLCopy()
418 {
419     if (m_frame.selection().selection().isInPasswordField())
420         return false;
421     return !dispatchClipboardEvent(findEventTargetFromSelection(), ClipboardEventKind::BeforeCopy);
422 }
423
424 bool Editor::canDHTMLPaste()
425 {
426     return !dispatchClipboardEvent(findEventTargetFromSelection(), ClipboardEventKind::BeforePaste);
427 }
428
429 bool Editor::canCut() const
430 {
431     return canCopy() && canDelete();
432 }
433
434 static HTMLImageElement* imageElementFromImageDocument(Document& document)
435 {
436     if (!document.isImageDocument())
437         return nullptr;
438     
439     HTMLElement* body = document.bodyOrFrameset();
440     if (!body)
441         return nullptr;
442     
443     Node* node = body->firstChild();
444     if (!is<HTMLImageElement>(node))
445         return nullptr;
446     return downcast<HTMLImageElement>(node);
447 }
448
449 bool Editor::canCopy() const
450 {
451     if (imageElementFromImageDocument(document()))
452         return true;
453     const VisibleSelection& selection = m_frame.selection().selection();
454     return selection.isRange() && !selection.isInPasswordField();
455 }
456
457 bool Editor::canPaste() const
458 {
459     if (m_frame.mainFrame().loader().shouldSuppressTextInputFromEditing())
460         return false;
461
462     return canEdit();
463 }
464
465 bool Editor::canDelete() const
466 {
467     const VisibleSelection& selection = m_frame.selection().selection();
468     return selection.isRange() && selection.rootEditableElement();
469 }
470
471 bool Editor::canDeleteRange(Range* range) const
472 {
473     Node& startContainer = range->startContainer();
474     Node& endContainer = range->endContainer();
475     
476     if (!startContainer.hasEditableStyle() || !endContainer.hasEditableStyle())
477         return false;
478
479     if (range->collapsed()) {
480         VisiblePosition start(range->startPosition(), DOWNSTREAM);
481         VisiblePosition previous = start.previous();
482         // FIXME: We sometimes allow deletions at the start of editable roots, like when the caret is in an empty list item.
483         if (previous.isNull() || previous.deepEquivalent().deprecatedNode()->rootEditableElement() != startContainer.rootEditableElement())
484             return false;
485     }
486     return true;
487 }
488
489 bool Editor::smartInsertDeleteEnabled()
490 {   
491     return client() && client()->smartInsertDeleteEnabled();
492 }
493     
494 bool Editor::canSmartCopyOrDelete()
495 {
496     return client() && client()->smartInsertDeleteEnabled() && m_frame.selection().granularity() == WordGranularity;
497 }
498
499 bool Editor::isSelectTrailingWhitespaceEnabled() const
500 {
501     return client() && client()->isSelectTrailingWhitespaceEnabled();
502 }
503
504 bool Editor::deleteWithDirection(SelectionDirection direction, TextGranularity granularity, bool shouldAddToKillRing, bool isTypingAction)
505 {
506     if (!canEdit())
507         return false;
508
509     if (m_frame.selection().isRange()) {
510         if (isTypingAction) {
511             TypingCommand::deleteKeyPressed(document(), canSmartCopyOrDelete() ? TypingCommand::SmartDelete : 0, granularity);
512             revealSelectionAfterEditingOperation();
513         } else {
514             if (shouldAddToKillRing)
515                 addRangeToKillRing(*selectedRange().get(), KillRingInsertionMode::AppendText);
516             deleteSelectionWithSmartDelete(canSmartCopyOrDelete());
517             // Implicitly calls revealSelectionAfterEditingOperation().
518         }
519     } else {
520         TypingCommand::Options options = 0;
521         if (canSmartCopyOrDelete())
522             options |= TypingCommand::SmartDelete;
523         if (shouldAddToKillRing)
524             options |= TypingCommand::AddsToKillRing;
525         switch (direction) {
526         case DirectionForward:
527         case DirectionRight:
528             TypingCommand::forwardDeleteKeyPressed(document(), options, granularity);
529             break;
530         case DirectionBackward:
531         case DirectionLeft:
532             TypingCommand::deleteKeyPressed(document(), options, granularity);
533             break;
534         }
535         revealSelectionAfterEditingOperation();
536     }
537
538     // FIXME: We should to move this down into deleteKeyPressed.
539     // clear the "start new kill ring sequence" setting, because it was set to true
540     // when the selection was updated by deleting the range
541     if (shouldAddToKillRing)
542         setStartNewKillRingSequence(false);
543
544     return true;
545 }
546
547 void Editor::deleteSelectionWithSmartDelete(bool smartDelete, EditAction editingAction)
548 {
549     if (m_frame.selection().isNone())
550         return;
551
552     DeleteSelectionCommand::create(document(), smartDelete, true, false, false, true, editingAction)->apply();
553 }
554
555 void Editor::clearText()
556 {
557     ClearTextCommand::CreateAndApply(&m_frame);
558 }
559
560 void Editor::pasteAsPlainText(const String& pastingText, bool smartReplace)
561 {
562     Element* target = findEventTargetFromSelection();
563     if (!target)
564         return;
565     target->dispatchEvent(TextEvent::createForPlainTextPaste(document().domWindow(), pastingText, smartReplace));
566 }
567
568 void Editor::pasteAsFragment(Ref<DocumentFragment>&& pastingFragment, bool smartReplace, bool matchStyle, MailBlockquoteHandling respectsMailBlockquote)
569 {
570     Element* target = findEventTargetFromSelection();
571     if (!target)
572         return;
573     target->dispatchEvent(TextEvent::createForFragmentPaste(document().domWindow(), WTFMove(pastingFragment), smartReplace, matchStyle, respectsMailBlockquote));
574 }
575
576 void Editor::pasteAsPlainTextBypassingDHTML()
577 {
578     pasteAsPlainTextWithPasteboard(*Pasteboard::createForCopyAndPaste());
579 }
580
581 void Editor::pasteAsPlainTextWithPasteboard(Pasteboard& pasteboard)
582 {
583     String text = readPlainTextFromPasteboard(pasteboard);
584     if (client() && client()->shouldInsertText(text, selectedRange().get(), EditorInsertAction::Pasted))
585         pasteAsPlainText(text, canSmartReplaceWithPasteboard(pasteboard));
586 }
587
588 String Editor::readPlainTextFromPasteboard(Pasteboard& pasteboard)
589 {
590     PasteboardPlainText text;
591     pasteboard.read(text);
592     return plainTextFromPasteboard(text);
593 }
594
595 #if !PLATFORM(MAC)
596
597 String Editor::plainTextFromPasteboard(const PasteboardPlainText& text)
598 {
599     return text.text;
600 }
601
602 #endif
603
604 bool Editor::canSmartReplaceWithPasteboard(Pasteboard& pasteboard)
605 {
606     return client() && client()->smartInsertDeleteEnabled() && pasteboard.canSmartReplace();
607 }
608
609 bool Editor::shouldInsertFragment(DocumentFragment& fragment, Range* replacingDOMRange, EditorInsertAction givenAction)
610 {
611     if (!client())
612         return false;
613     
614     auto* child = fragment.firstChild();
615     if (is<CharacterData>(child) && fragment.lastChild() == child)
616         return client()->shouldInsertText(downcast<CharacterData>(*child).data(), replacingDOMRange, givenAction);
617
618     return client()->shouldInsertNode(&fragment, replacingDOMRange, givenAction);
619 }
620
621 void Editor::replaceSelectionWithFragment(DocumentFragment& fragment, bool selectReplacement, bool smartReplace, bool matchStyle, EditAction editingAction, MailBlockquoteHandling mailBlockquoteHandling)
622 {
623     VisibleSelection selection = m_frame.selection().selection();
624     if (selection.isNone() || !selection.isContentEditable())
625         return;
626
627     AccessibilityReplacedText replacedText;
628     if (AXObjectCache::accessibilityEnabled() && editingAction == EditActionPaste)
629         replacedText = AccessibilityReplacedText(selection);
630
631     ReplaceSelectionCommand::CommandOptions options = ReplaceSelectionCommand::PreventNesting | ReplaceSelectionCommand::SanitizeFragment;
632     if (selectReplacement)
633         options |= ReplaceSelectionCommand::SelectReplacement;
634     if (smartReplace)
635         options |= ReplaceSelectionCommand::SmartReplace;
636     if (matchStyle)
637         options |= ReplaceSelectionCommand::MatchStyle;
638     if (mailBlockquoteHandling == MailBlockquoteHandling::IgnoreBlockquote)
639         options |= ReplaceSelectionCommand::IgnoreMailBlockquote;
640
641     auto command = ReplaceSelectionCommand::create(document(), &fragment, options, editingAction);
642     command->apply();
643     revealSelectionAfterEditingOperation();
644
645     selection = m_frame.selection().selection();
646     if (selection.isInPasswordField())
647         return;
648
649     if (AXObjectCache::accessibilityEnabled() && editingAction == EditActionPaste) {
650         String text = AccessibilityObject::stringForVisiblePositionRange(command->visibleSelectionForInsertedText());
651         replacedText.postTextStateChangeNotification(document().existingAXObjectCache(), AXTextEditTypePaste, text, m_frame.selection().selection());
652         command->composition()->setRangeDeletedByUnapply(replacedText.replacedRange());
653     }
654
655     if (!isContinuousSpellCheckingEnabled())
656         return;
657
658     Node* nodeToCheck = selection.rootEditableElement();
659     if (!nodeToCheck)
660         return;
661
662     auto rangeToCheck = Range::create(document(), firstPositionInNode(nodeToCheck), lastPositionInNode(nodeToCheck));
663     if (auto request = SpellCheckRequest::create(resolveTextCheckingTypeMask(*nodeToCheck, TextCheckingTypeSpelling | TextCheckingTypeGrammar), TextCheckingProcessBatch, rangeToCheck.copyRef(), rangeToCheck.copyRef()))
664         m_spellChecker->requestCheckingFor(request.releaseNonNull());
665 }
666
667 void Editor::replaceSelectionWithText(const String& text, bool selectReplacement, bool smartReplace, EditAction editingAction)
668 {
669     RefPtr<Range> range = selectedRange();
670     if (!range)
671         return;
672
673     replaceSelectionWithFragment(createFragmentFromText(*range, text), selectReplacement, smartReplace, true, editingAction);
674 }
675
676 RefPtr<Range> Editor::selectedRange()
677 {
678     return m_frame.selection().toNormalizedRange();
679 }
680
681 bool Editor::shouldDeleteRange(Range* range) const
682 {
683     if (!range || range->collapsed())
684         return false;
685     
686     if (!canDeleteRange(range))
687         return false;
688
689     return client() && client()->shouldDeleteRange(range);
690 }
691
692 bool Editor::tryDHTMLCopy()
693 {   
694     if (m_frame.selection().selection().isInPasswordField())
695         return false;
696
697     return !dispatchClipboardEvent(findEventTargetFromSelection(), ClipboardEventKind::Copy);
698 }
699
700 bool Editor::tryDHTMLCut()
701 {
702     if (m_frame.selection().selection().isInPasswordField())
703         return false;
704     
705     return !dispatchClipboardEvent(findEventTargetFromSelection(), ClipboardEventKind::Cut);
706 }
707
708 bool Editor::shouldInsertText(const String& text, Range* range, EditorInsertAction action) const
709 {
710     if (m_frame.mainFrame().loader().shouldSuppressTextInputFromEditing() && action == EditorInsertAction::Typed)
711         return false;
712
713     return client() && client()->shouldInsertText(text, range, action);
714 }
715
716 void Editor::respondToChangedContents(const VisibleSelection& endingSelection)
717 {
718     if (AXObjectCache::accessibilityEnabled()) {
719         Node* node = endingSelection.start().deprecatedNode();
720         if (AXObjectCache* cache = document().existingAXObjectCache())
721             cache->postNotification(node, AXObjectCache::AXValueChanged, TargetObservableParent);
722     }
723
724     updateMarkersForWordsAffectedByEditing(true);
725
726     if (client())
727         client()->respondToChangedContents();
728 }
729
730 bool Editor::hasBidiSelection() const
731 {
732     if (m_frame.selection().isNone())
733         return false;
734
735     Node* startNode;
736     if (m_frame.selection().isRange()) {
737         startNode = m_frame.selection().selection().start().downstream().deprecatedNode();
738         Node* endNode = m_frame.selection().selection().end().upstream().deprecatedNode();
739         if (enclosingBlock(startNode) != enclosingBlock(endNode))
740             return false;
741     } else
742         startNode = m_frame.selection().selection().visibleStart().deepEquivalent().deprecatedNode();
743
744     if (!startNode)
745         return false;
746
747     auto renderer = startNode->renderer();
748     while (renderer && !is<RenderBlockFlow>(*renderer))
749         renderer = renderer->parent();
750
751     if (!renderer)
752         return false;
753
754     if (!renderer->style().isLeftToRightDirection())
755         return true;
756
757     return downcast<RenderBlockFlow>(*renderer).containsNonZeroBidiLevel();
758 }
759
760 TriState Editor::selectionUnorderedListState() const
761 {
762     if (m_frame.selection().isCaret()) {
763         if (enclosingElementWithTag(m_frame.selection().selection().start(), ulTag))
764             return TrueTriState;
765     } else if (m_frame.selection().isRange()) {
766         auto* startNode = enclosingElementWithTag(m_frame.selection().selection().start(), ulTag);
767         auto* endNode = enclosingElementWithTag(m_frame.selection().selection().end(), ulTag);
768         if (startNode && endNode && startNode == endNode)
769             return TrueTriState;
770     }
771
772     return FalseTriState;
773 }
774
775 TriState Editor::selectionOrderedListState() const
776 {
777     if (m_frame.selection().isCaret()) {
778         if (enclosingElementWithTag(m_frame.selection().selection().start(), olTag))
779             return TrueTriState;
780     } else if (m_frame.selection().isRange()) {
781         auto* startNode = enclosingElementWithTag(m_frame.selection().selection().start(), olTag);
782         auto* endNode = enclosingElementWithTag(m_frame.selection().selection().end(), olTag);
783         if (startNode && endNode && startNode == endNode)
784             return TrueTriState;
785     }
786
787     return FalseTriState;
788 }
789
790 RefPtr<Node> Editor::insertOrderedList()
791 {
792     if (!canEditRichly())
793         return nullptr;
794         
795     RefPtr<Node> newList = InsertListCommand::insertList(document(), InsertListCommand::OrderedList);
796     revealSelectionAfterEditingOperation();
797     return newList;
798 }
799
800 RefPtr<Node> Editor::insertUnorderedList()
801 {
802     if (!canEditRichly())
803         return nullptr;
804         
805     RefPtr<Node> newList = InsertListCommand::insertList(document(), InsertListCommand::UnorderedList);
806     revealSelectionAfterEditingOperation();
807     return newList;
808 }
809
810 bool Editor::canIncreaseSelectionListLevel()
811 {
812     return canEditRichly() && IncreaseSelectionListLevelCommand::canIncreaseSelectionListLevel(&document());
813 }
814
815 bool Editor::canDecreaseSelectionListLevel()
816 {
817     return canEditRichly() && DecreaseSelectionListLevelCommand::canDecreaseSelectionListLevel(&document());
818 }
819
820 RefPtr<Node> Editor::increaseSelectionListLevel()
821 {
822     if (!canEditRichly() || m_frame.selection().isNone())
823         return nullptr;
824     
825     RefPtr<Node> newList = IncreaseSelectionListLevelCommand::increaseSelectionListLevel(&document());
826     revealSelectionAfterEditingOperation();
827     return newList;
828 }
829
830 RefPtr<Node> Editor::increaseSelectionListLevelOrdered()
831 {
832     if (!canEditRichly() || m_frame.selection().isNone())
833         return nullptr;
834     
835     RefPtr<Node> newList = IncreaseSelectionListLevelCommand::increaseSelectionListLevelOrdered(&document());
836     revealSelectionAfterEditingOperation();
837     return newList;
838 }
839
840 RefPtr<Node> Editor::increaseSelectionListLevelUnordered()
841 {
842     if (!canEditRichly() || m_frame.selection().isNone())
843         return nullptr;
844     
845     RefPtr<Node> newList = IncreaseSelectionListLevelCommand::increaseSelectionListLevelUnordered(&document());
846     revealSelectionAfterEditingOperation();
847     return newList;
848 }
849
850 void Editor::decreaseSelectionListLevel()
851 {
852     if (!canEditRichly() || m_frame.selection().isNone())
853         return;
854     
855     DecreaseSelectionListLevelCommand::decreaseSelectionListLevel(&document());
856     revealSelectionAfterEditingOperation();
857 }
858
859 void Editor::removeFormattingAndStyle()
860 {
861     RemoveFormatCommand::create(document())->apply();
862 }
863
864 void Editor::clearLastEditCommand() 
865 {
866     m_lastEditCommand = nullptr;
867 }
868
869 Element* Editor::findEventTargetFrom(const VisibleSelection& selection) const
870 {
871     Element* target = selection.start().element();
872     if (!target)
873         target = document().bodyOrFrameset();
874     if (!target)
875         return nullptr;
876
877     return target;
878 }
879
880 Element* Editor::findEventTargetFromSelection() const
881 {
882     return findEventTargetFrom(m_frame.selection().selection());
883 }
884
885 void Editor::applyStyle(StyleProperties* style, EditAction editingAction)
886 {
887     if (style)
888         applyStyle(EditingStyle::create(style), editingAction);
889 }
890
891 void Editor::applyStyle(RefPtr<EditingStyle>&& style, EditAction editingAction)
892 {
893     if (!style)
894         return;
895
896     auto selectionType = m_frame.selection().selection().selectionType();
897     if (selectionType == VisibleSelection::NoSelection)
898         return;
899
900     String inputTypeName = inputTypeNameForEditingAction(editingAction);
901     String inputEventData = inputEventDataForEditingStyleAndAction(*style, editingAction);
902     RefPtr<Element> element = m_frame.selection().selection().rootEditableElement();
903     if (element && !dispatchBeforeInputEvent(*element, inputTypeName, inputEventData))
904         return;
905
906     switch (selectionType) {
907     case VisibleSelection::CaretSelection:
908         computeAndSetTypingStyle(*style, editingAction);
909         break;
910     case VisibleSelection::RangeSelection:
911         ApplyStyleCommand::create(document(), style.get(), editingAction)->apply();
912         break;
913     default:
914         break;
915     }
916
917     client()->didApplyStyle();
918     if (element)
919         dispatchInputEvent(*element, inputTypeName, inputEventData);
920 }
921     
922 bool Editor::shouldApplyStyle(StyleProperties* style, Range* range)
923 {   
924     return client()->shouldApplyStyle(style, range);
925 }
926     
927 void Editor::applyParagraphStyle(StyleProperties* style, EditAction editingAction)
928 {
929     if (!style)
930         return;
931
932     auto selectionType = m_frame.selection().selection().selectionType();
933     if (selectionType == VisibleSelection::NoSelection)
934         return;
935
936     String inputTypeName = inputTypeNameForEditingAction(editingAction);
937     String inputEventData = inputEventDataForEditingStyleAndAction(style, editingAction);
938     RefPtr<Element> element = m_frame.selection().selection().rootEditableElement();
939     if (element && !dispatchBeforeInputEvent(*element, inputTypeName, inputEventData))
940         return;
941
942     ApplyStyleCommand::create(document(), EditingStyle::create(style).ptr(), editingAction, ApplyStyleCommand::ForceBlockProperties)->apply();
943     client()->didApplyStyle();
944     if (element)
945         dispatchInputEvent(*element, inputTypeName, inputEventData);
946 }
947
948 void Editor::applyStyleToSelection(StyleProperties* style, EditAction editingAction)
949 {
950     if (!style || style->isEmpty() || !canEditRichly())
951         return;
952
953     if (!client() || !client()->shouldApplyStyle(style, m_frame.selection().toNormalizedRange().get()))
954         return;
955     applyStyle(style, editingAction);
956 }
957
958 void Editor::applyStyleToSelection(Ref<EditingStyle>&& style, EditAction editingAction)
959 {
960     if (style->isEmpty() || !canEditRichly())
961         return;
962
963     // FIXME: This is wrong for text decorations since m_mutableStyle is empty.
964     if (!client() || !client()->shouldApplyStyle(style->styleWithResolvedTextDecorations().ptr(), m_frame.selection().toNormalizedRange().get()))
965         return;
966
967     applyStyle(WTFMove(style), editingAction);
968 }
969
970 void Editor::applyParagraphStyleToSelection(StyleProperties* style, EditAction editingAction)
971 {
972     if (!style || style->isEmpty() || !canEditRichly())
973         return;
974     
975     if (client() && client()->shouldApplyStyle(style, m_frame.selection().toNormalizedRange().get()))
976         applyParagraphStyle(style, editingAction);
977 }
978
979 bool Editor::selectionStartHasStyle(CSSPropertyID propertyID, const String& value) const
980 {
981     if (auto editingStyle = EditingStyle::styleAtSelectionStart(m_frame.selection().selection(), propertyID == CSSPropertyBackgroundColor))
982         return editingStyle->hasStyle(propertyID, value);
983     return false;
984 }
985
986 TriState Editor::selectionHasStyle(CSSPropertyID propertyID, const String& value) const
987 {
988     return EditingStyle::create(propertyID, value)->triStateOfStyle(m_frame.selection().selection());
989 }
990
991 String Editor::selectionStartCSSPropertyValue(CSSPropertyID propertyID)
992 {
993     RefPtr<EditingStyle> selectionStyle = EditingStyle::styleAtSelectionStart(m_frame.selection().selection(),
994         propertyID == CSSPropertyBackgroundColor);
995     if (!selectionStyle || !selectionStyle->style())
996         return String();
997
998     if (propertyID == CSSPropertyFontSize)
999         return String::number(selectionStyle->legacyFontSize(&document()));
1000     return selectionStyle->style()->getPropertyValue(propertyID);
1001 }
1002
1003 void Editor::indent()
1004 {
1005     IndentOutdentCommand::create(document(), IndentOutdentCommand::Indent)->apply();
1006 }
1007
1008 void Editor::outdent()
1009 {
1010     IndentOutdentCommand::create(document(), IndentOutdentCommand::Outdent)->apply();
1011 }
1012
1013 static void notifyTextFromControls(Element* startRoot, Element* endRoot)
1014 {
1015     HTMLTextFormControlElement* startingTextControl = enclosingTextFormControl(firstPositionInOrBeforeNode(startRoot));
1016     HTMLTextFormControlElement* endingTextControl = enclosingTextFormControl(firstPositionInOrBeforeNode(endRoot));
1017     if (startingTextControl)
1018         startingTextControl->didEditInnerTextValue();
1019     if (endingTextControl && startingTextControl != endingTextControl)
1020         endingTextControl->didEditInnerTextValue();
1021 }
1022
1023 static bool dispatchBeforeInputEvents(RefPtr<Element> startRoot, RefPtr<Element> endRoot, const AtomicString& inputTypeName, const String& data = { }, RefPtr<DataTransfer>&& dataTransfer = nullptr, const Vector<RefPtr<StaticRange>>& targetRanges = { }, bool cancelable = true)
1024 {
1025     bool continueWithDefaultBehavior = true;
1026     if (startRoot)
1027         continueWithDefaultBehavior &= dispatchBeforeInputEvent(*startRoot, inputTypeName, data, WTFMove(dataTransfer), targetRanges, cancelable);
1028     if (endRoot && endRoot != startRoot)
1029         continueWithDefaultBehavior &= dispatchBeforeInputEvent(*endRoot, inputTypeName, data, WTFMove(dataTransfer), targetRanges, cancelable);
1030     return continueWithDefaultBehavior;
1031 }
1032
1033 static void dispatchInputEvents(RefPtr<Element> startRoot, RefPtr<Element> endRoot, const AtomicString& inputTypeName, const String& data = { }, RefPtr<DataTransfer>&& dataTransfer = nullptr, const Vector<RefPtr<StaticRange>>& targetRanges = { })
1034 {
1035     if (startRoot)
1036         dispatchInputEvent(*startRoot, inputTypeName, data, WTFMove(dataTransfer), targetRanges);
1037     if (endRoot && endRoot != startRoot)
1038         dispatchInputEvent(*endRoot, inputTypeName, data, WTFMove(dataTransfer), targetRanges);
1039 }
1040
1041 bool Editor::willApplyEditing(CompositeEditCommand& command, Vector<RefPtr<StaticRange>>&& targetRanges) const
1042 {
1043     if (!command.shouldDispatchInputEvents())
1044         return true;
1045
1046     auto* composition = command.composition();
1047     if (!composition)
1048         return true;
1049
1050     return dispatchBeforeInputEvents(composition->startingRootEditableElement(), composition->endingRootEditableElement(), command.inputEventTypeName(), command.inputEventData(), command.inputEventDataTransfer(), targetRanges, command.isBeforeInputEventCancelable());
1051 }
1052
1053 void Editor::appliedEditing(CompositeEditCommand& command)
1054 {
1055     LOG(Editing, "Editor %p appliedEditing", this);
1056
1057     document().updateLayout();
1058
1059     ASSERT(command.composition());
1060     auto& composition = *command.composition();
1061     VisibleSelection newSelection(command.endingSelection());
1062
1063     notifyTextFromControls(composition.startingRootEditableElement(), composition.endingRootEditableElement());
1064
1065     if (command.isTopLevelCommand()) {
1066         // Don't clear the typing style with this selection change. We do those things elsewhere if necessary.
1067         FrameSelection::SetSelectionOptions options = command.isDictationCommand() ? FrameSelection::DictationTriggered : 0;
1068
1069         changeSelectionAfterCommand(newSelection, options);
1070     }
1071
1072     if (command.shouldDispatchInputEvents())
1073         dispatchInputEvents(composition.startingRootEditableElement(), composition.endingRootEditableElement(), command.inputEventTypeName(), command.inputEventData(), command.inputEventDataTransfer());
1074
1075     if (command.isTopLevelCommand()) {
1076         updateEditorUINowIfScheduled();
1077
1078         m_alternativeTextController->respondToAppliedEditing(&command);
1079
1080         if (!command.preservesTypingStyle())
1081             m_frame.selection().clearTypingStyle();
1082
1083         // Command will be equal to last edit command only in the case of typing
1084         if (m_lastEditCommand.get() == &command)
1085             ASSERT(command.isTypingCommand());
1086         else {
1087             // Only register a new undo command if the command passed in is
1088             // different from the last command
1089             m_lastEditCommand = &command;
1090             if (client())
1091                 client()->registerUndoStep(m_lastEditCommand->ensureComposition());
1092         }
1093         respondToChangedContents(newSelection);
1094     }
1095 }
1096
1097 bool Editor::willUnapplyEditing(const EditCommandComposition& composition) const
1098 {
1099     return dispatchBeforeInputEvents(composition.startingRootEditableElement(), composition.endingRootEditableElement(), "historyUndo");
1100 }
1101
1102 void Editor::unappliedEditing(EditCommandComposition& composition)
1103 {
1104     document().updateLayout();
1105
1106     notifyTextFromControls(composition.startingRootEditableElement(), composition.endingRootEditableElement());
1107
1108     VisibleSelection newSelection(composition.startingSelection());
1109     changeSelectionAfterCommand(newSelection, FrameSelection::defaultSetSelectionOptions());
1110     dispatchInputEvents(composition.startingRootEditableElement(), composition.endingRootEditableElement(), "historyUndo");
1111
1112     updateEditorUINowIfScheduled();
1113
1114     m_alternativeTextController->respondToUnappliedEditing(&composition);
1115
1116     m_lastEditCommand = nullptr;
1117     if (auto* client = this->client())
1118         client->registerRedoStep(composition);
1119     respondToChangedContents(newSelection);
1120 }
1121
1122 bool Editor::willReapplyEditing(const EditCommandComposition& composition) const
1123 {
1124     return dispatchBeforeInputEvents(composition.startingRootEditableElement(), composition.endingRootEditableElement(), "historyRedo");
1125 }
1126
1127 void Editor::reappliedEditing(EditCommandComposition& composition)
1128 {
1129     document().updateLayout();
1130
1131     notifyTextFromControls(composition.startingRootEditableElement(), composition.endingRootEditableElement());
1132
1133     VisibleSelection newSelection(composition.endingSelection());
1134     changeSelectionAfterCommand(newSelection, FrameSelection::defaultSetSelectionOptions());
1135     dispatchInputEvents(composition.startingRootEditableElement(), composition.endingRootEditableElement(), "historyRedo");
1136     
1137     updateEditorUINowIfScheduled();
1138
1139     m_lastEditCommand = nullptr;
1140     if (auto* client = this->client())
1141         client->registerUndoStep(composition);
1142     respondToChangedContents(newSelection);
1143 }
1144
1145 Editor::Editor(Frame& frame)
1146     : m_frame(frame)
1147     , m_killRing(std::make_unique<PAL::KillRing>())
1148     , m_spellChecker(std::make_unique<SpellChecker>(frame))
1149     , m_alternativeTextController(std::make_unique<AlternativeTextController>(frame))
1150     , m_editorUIUpdateTimer(*this, &Editor::editorUIUpdateTimerFired)
1151 #if ENABLE(TELEPHONE_NUMBER_DETECTION) && !PLATFORM(IOS)
1152     , m_telephoneNumberDetectionUpdateTimer(*this, &Editor::scanSelectionForTelephoneNumbers)
1153 #endif
1154 {
1155 }
1156
1157 Editor::~Editor()
1158 {
1159 }
1160
1161 void Editor::clear()
1162 {
1163     if (m_compositionNode) {
1164         m_compositionNode = nullptr;
1165         if (EditorClient* client = this->client())
1166             client->discardedComposition(&m_frame);
1167     }
1168     m_customCompositionUnderlines.clear();
1169     m_shouldStyleWithCSS = false;
1170     m_defaultParagraphSeparator = EditorParagraphSeparatorIsDiv;
1171 }
1172
1173 bool Editor::insertText(const String& text, Event* triggeringEvent, TextEventInputType inputType)
1174 {
1175     return m_frame.eventHandler().handleTextInputEvent(text, triggeringEvent, inputType);
1176 }
1177
1178 bool Editor::insertTextForConfirmedComposition(const String& text)
1179 {
1180     return m_frame.eventHandler().handleTextInputEvent(text, 0, TextEventInputComposition);
1181 }
1182
1183 bool Editor::insertDictatedText(const String& text, const Vector<DictationAlternative>& dictationAlternatives, Event* triggeringEvent)
1184 {
1185     return m_alternativeTextController->insertDictatedText(text, dictationAlternatives, triggeringEvent);
1186 }
1187
1188 bool Editor::insertTextWithoutSendingTextEvent(const String& text, bool selectInsertedText, TextEvent* triggeringEvent)
1189 {
1190     if (text.isEmpty())
1191         return false;
1192
1193     VisibleSelection selection = selectionForCommand(triggeringEvent);
1194     if (!selection.isContentEditable())
1195         return false;
1196     RefPtr<Range> range = selection.toNormalizedRange();
1197
1198     if (!shouldInsertText(text, range.get(), EditorInsertAction::Typed))
1199         return true;
1200
1201     updateMarkersForWordsAffectedByEditing(isSpaceOrNewline(text[0]));
1202
1203     bool shouldConsiderApplyingAutocorrection = false;
1204     if (text == " " || text == "\t")
1205         shouldConsiderApplyingAutocorrection = true;
1206
1207     if (text.length() == 1 && u_ispunct(text[0]) && !isAmbiguousBoundaryCharacter(text[0]))
1208         shouldConsiderApplyingAutocorrection = true;
1209
1210     bool autocorrectionWasApplied = shouldConsiderApplyingAutocorrection && m_alternativeTextController->applyAutocorrectionBeforeTypingIfAppropriate();
1211
1212     // Get the selection to use for the event that triggered this insertText.
1213     // If the event handler changed the selection, we may want to use a different selection
1214     // that is contained in the event target.
1215     selection = selectionForCommand(triggeringEvent);
1216     if (selection.isContentEditable()) {
1217         if (Node* selectionStart = selection.start().deprecatedNode()) {
1218             Ref<Document> document(selectionStart->document());
1219
1220             // Insert the text
1221             if (triggeringEvent && triggeringEvent->isDictation())
1222                 DictationCommand::insertText(document, text, triggeringEvent->dictationAlternatives(), selection);
1223             else {
1224                 TypingCommand::Options options = 0;
1225                 if (selectInsertedText)
1226                     options |= TypingCommand::SelectInsertedText;
1227                 if (autocorrectionWasApplied)
1228                     options |= TypingCommand::RetainAutocorrectionIndicator;
1229                 if (triggeringEvent && triggeringEvent->isAutocompletion())
1230                     options |= TypingCommand::IsAutocompletion;
1231                 TypingCommand::insertText(document, text, selection, options, triggeringEvent && triggeringEvent->isComposition() ? TypingCommand::TextCompositionFinal : TypingCommand::TextCompositionNone);
1232             }
1233
1234             // Reveal the current selection
1235             if (Frame* editedFrame = document->frame())
1236                 if (Page* page = editedFrame->page()) {
1237 #if PLATFORM(IOS)
1238                     SelectionRevealMode revealMode = SelectionRevealMode::RevealUpToMainFrame;
1239 #else
1240                     SelectionRevealMode revealMode = SelectionRevealMode::Reveal;
1241 #endif
1242                     page->focusController().focusedOrMainFrame().selection().revealSelection(revealMode, ScrollAlignment::alignCenterIfNeeded);
1243                 }
1244         }
1245     }
1246
1247     return true;
1248 }
1249
1250 bool Editor::insertLineBreak()
1251 {
1252     if (!canEdit())
1253         return false;
1254
1255     if (!shouldInsertText("\n", m_frame.selection().toNormalizedRange().get(), EditorInsertAction::Typed))
1256         return true;
1257
1258     VisiblePosition caret = m_frame.selection().selection().visibleStart();
1259     bool alignToEdge = isEndOfEditableOrNonEditableContent(caret);
1260     bool autocorrectionIsApplied = m_alternativeTextController->applyAutocorrectionBeforeTypingIfAppropriate();
1261     TypingCommand::insertLineBreak(document(), autocorrectionIsApplied ? TypingCommand::RetainAutocorrectionIndicator : 0);
1262     revealSelectionAfterEditingOperation(alignToEdge ? ScrollAlignment::alignToEdgeIfNeeded : ScrollAlignment::alignCenterIfNeeded);
1263
1264     return true;
1265 }
1266
1267 bool Editor::insertParagraphSeparator()
1268 {
1269     if (!canEdit())
1270         return false;
1271
1272     if (!canEditRichly())
1273         return insertLineBreak();
1274
1275     if (!shouldInsertText("\n", m_frame.selection().toNormalizedRange().get(), EditorInsertAction::Typed))
1276         return true;
1277
1278     VisiblePosition caret = m_frame.selection().selection().visibleStart();
1279     bool alignToEdge = isEndOfEditableOrNonEditableContent(caret);
1280     bool autocorrectionIsApplied = m_alternativeTextController->applyAutocorrectionBeforeTypingIfAppropriate();
1281     TypingCommand::insertParagraphSeparator(document(), autocorrectionIsApplied ? TypingCommand::RetainAutocorrectionIndicator : 0);
1282     revealSelectionAfterEditingOperation(alignToEdge ? ScrollAlignment::alignToEdgeIfNeeded : ScrollAlignment::alignCenterIfNeeded);
1283
1284     return true;
1285 }
1286
1287 bool Editor::insertParagraphSeparatorInQuotedContent()
1288 {
1289     // FIXME: Why is this missing calls to canEdit, canEditRichly, etc.?
1290     TypingCommand::insertParagraphSeparatorInQuotedContent(document());
1291     revealSelectionAfterEditingOperation();
1292     return true;
1293 }
1294
1295 void Editor::cut()
1296 {
1297     if (tryDHTMLCut())
1298         return; // DHTML did the whole operation
1299     if (!canCut()) {
1300         PAL::systemBeep();
1301         return;
1302     }
1303
1304     performCutOrCopy(CutAction);
1305 }
1306
1307 void Editor::copy()
1308 {
1309     if (tryDHTMLCopy())
1310         return; // DHTML did the whole operation
1311     if (!canCopy()) {
1312         PAL::systemBeep();
1313         return;
1314     }
1315
1316     performCutOrCopy(CopyAction);
1317 }
1318
1319 void Editor::postTextStateChangeNotificationForCut(const String& text, const VisibleSelection& selection)
1320 {
1321     if (!AXObjectCache::accessibilityEnabled())
1322         return;
1323     if (!text.length())
1324         return;
1325     AXObjectCache* cache = document().existingAXObjectCache();
1326     if (!cache)
1327         return;
1328     cache->postTextStateChangeNotification(selection.start().anchorNode(), AXTextEditTypeCut, text, selection.start());
1329 }
1330
1331 void Editor::performCutOrCopy(EditorActionSpecifier action)
1332 {
1333     RefPtr<Range> selection = selectedRange();
1334     willWriteSelectionToPasteboard(selection.get());
1335     if (action == CutAction) {
1336         if (!shouldDeleteRange(selection.get()))
1337             return;
1338
1339         updateMarkersForWordsAffectedByEditing(true);
1340     }
1341
1342     if (enclosingTextFormControl(m_frame.selection().selection().start()))
1343         Pasteboard::createForCopyAndPaste()->writePlainText(selectedTextForDataTransfer(), canSmartCopyOrDelete() ? Pasteboard::CanSmartReplace : Pasteboard::CannotSmartReplace);
1344     else {
1345         HTMLImageElement* imageElement = nullptr;
1346         if (action == CopyAction)
1347             imageElement = imageElementFromImageDocument(document());
1348
1349         if (imageElement) {
1350 #if !PLATFORM(WIN)
1351             writeImageToPasteboard(*Pasteboard::createForCopyAndPaste(), *imageElement, document().url(), document().title());
1352 #else
1353             // FIXME: Delete after <http://webkit.org/b/177618> lands.
1354             Pasteboard::createForCopyAndPaste()->writeImage(*imageElement, document().url(), document().title());
1355 #endif
1356         } else {
1357 #if !PLATFORM(WIN)
1358             writeSelectionToPasteboard(*Pasteboard::createForCopyAndPaste());
1359 #else
1360             // FIXME: Delete after <http://webkit.org/b/177618> lands.
1361             Pasteboard::createForCopyAndPaste()->writeSelection(*selection, canSmartCopyOrDelete(), m_frame, IncludeImageAltTextForDataTransfer);
1362 #endif
1363         }
1364     }
1365
1366     didWriteSelectionToPasteboard();
1367     if (action == CutAction) {
1368         String text;
1369         if (AXObjectCache::accessibilityEnabled())
1370             text = AccessibilityObject::stringForVisiblePositionRange(m_frame.selection().selection());
1371         deleteSelectionWithSmartDelete(canSmartCopyOrDelete(), EditActionCut);
1372         if (AXObjectCache::accessibilityEnabled())
1373             postTextStateChangeNotificationForCut(text, m_frame.selection().selection());
1374     }
1375 }
1376
1377 void Editor::paste()
1378 {
1379     paste(*Pasteboard::createForCopyAndPaste());
1380 }
1381
1382 void Editor::paste(Pasteboard& pasteboard)
1383 {
1384     if (!dispatchClipboardEvent(findEventTargetFromSelection(), ClipboardEventKind::Paste))
1385         return; // DHTML did the whole operation
1386     if (!canPaste())
1387         return;
1388     updateMarkersForWordsAffectedByEditing(false);
1389     ResourceCacheValidationSuppressor validationSuppressor(document().cachedResourceLoader());
1390     if (m_frame.selection().selection().isContentRichlyEditable())
1391         pasteWithPasteboard(&pasteboard, true);
1392     else
1393         pasteAsPlainTextWithPasteboard(pasteboard);
1394 }
1395
1396 void Editor::pasteAsPlainText()
1397 {
1398     if (!dispatchClipboardEvent(findEventTargetFromSelection(), ClipboardEventKind::PasteAsPlainText))
1399         return;
1400     if (!canPaste())
1401         return;
1402     updateMarkersForWordsAffectedByEditing(false);
1403     pasteAsPlainTextWithPasteboard(*Pasteboard::createForCopyAndPaste());
1404 }
1405
1406 void Editor::performDelete()
1407 {
1408     if (!canDelete()) {
1409         PAL::systemBeep();
1410         return;
1411     }
1412
1413     addRangeToKillRing(*selectedRange().get(), KillRingInsertionMode::AppendText);
1414     deleteSelectionWithSmartDelete(canSmartCopyOrDelete());
1415
1416     // clear the "start new kill ring sequence" setting, because it was set to true
1417     // when the selection was updated by deleting the range
1418     setStartNewKillRingSequence(false);
1419 }
1420
1421 void Editor::simplifyMarkup(Node* startNode, Node* endNode)
1422 {
1423     if (!startNode)
1424         return;
1425     if (endNode) {
1426         if (&startNode->document() != &endNode->document())
1427             return;
1428         // check if start node is before endNode
1429         Node* node = startNode;
1430         while (node && node != endNode)
1431             node = NodeTraversal::next(*node);
1432         if (!node)
1433             return;
1434     }
1435     
1436     SimplifyMarkupCommand::create(document(), startNode, endNode ? NodeTraversal::next(*endNode) : nullptr)->apply();
1437 }
1438
1439 void Editor::copyURL(const URL& url, const String& title)
1440 {
1441     copyURL(url, title, *Pasteboard::createForCopyAndPaste());
1442 }
1443
1444 void Editor::copyURL(const URL& url, const String& title, Pasteboard& pasteboard)
1445 {
1446     PasteboardURL pasteboardURL;
1447     pasteboardURL.url = url;
1448     pasteboardURL.title = title;
1449
1450 #if PLATFORM(MAC)
1451     pasteboardURL.userVisibleForm = userVisibleString(url);
1452 #endif
1453
1454     pasteboard.write(pasteboardURL);
1455 }
1456
1457 PasteboardWriterData::URL Editor::pasteboardWriterURL(const URL& url, const String& title)
1458 {
1459     PasteboardWriterData::URL result;
1460
1461     result.url = url;
1462     result.title = title;
1463 #if PLATFORM(MAC)
1464     result.userVisibleForm = userVisibleString(url);
1465 #endif
1466
1467     return result;
1468 }
1469
1470 #if !PLATFORM(IOS)
1471
1472 void Editor::copyImage(const HitTestResult& result)
1473 {
1474     Element* element = result.innerNonSharedElement();
1475     if (!element)
1476         return;
1477
1478     URL url = result.absoluteLinkURL();
1479     if (url.isEmpty())
1480         url = result.absoluteImageURL();
1481
1482 #if !PLATFORM(WIN)
1483     writeImageToPasteboard(*Pasteboard::createForCopyAndPaste(), *element, url, result.altDisplayString());
1484 #else
1485     // FIXME: Delete after <http://webkit.org/b/177618> lands.
1486     Pasteboard::createForCopyAndPaste()->writeImage(*element, url, result.altDisplayString());
1487 #endif
1488 }
1489
1490 #endif
1491
1492 bool Editor::isContinuousSpellCheckingEnabled() const
1493 {
1494     return client() && client()->isContinuousSpellCheckingEnabled();
1495 }
1496
1497 void Editor::toggleContinuousSpellChecking()
1498 {
1499     if (client())
1500         client()->toggleContinuousSpellChecking();
1501 }
1502
1503 bool Editor::isGrammarCheckingEnabled()
1504 {
1505     return client() && client()->isGrammarCheckingEnabled();
1506 }
1507
1508 void Editor::toggleGrammarChecking()
1509 {
1510     if (client())
1511         client()->toggleGrammarChecking();
1512 }
1513
1514 int Editor::spellCheckerDocumentTag()
1515 {
1516     return client() ? client()->spellCheckerDocumentTag() : 0;
1517 }
1518
1519 #if USE(APPKIT)
1520
1521 void Editor::uppercaseWord()
1522 {
1523     if (client())
1524         client()->uppercaseWord();
1525 }
1526
1527 void Editor::lowercaseWord()
1528 {
1529     if (client())
1530         client()->lowercaseWord();
1531 }
1532
1533 void Editor::capitalizeWord()
1534 {
1535     if (client())
1536         client()->capitalizeWord();
1537 }
1538     
1539 #endif
1540
1541 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
1542
1543 void Editor::showSubstitutionsPanel()
1544 {
1545     if (!client()) {
1546         LOG_ERROR("No NSSpellChecker");
1547         return;
1548     }
1549
1550     if (client()->substitutionsPanelIsShowing()) {
1551         client()->showSubstitutionsPanel(false);
1552         return;
1553     }
1554     client()->showSubstitutionsPanel(true);
1555 }
1556
1557 bool Editor::substitutionsPanelIsShowing()
1558 {
1559     if (!client())
1560         return false;
1561     return client()->substitutionsPanelIsShowing();
1562 }
1563
1564 void Editor::toggleSmartInsertDelete()
1565 {
1566     if (client())
1567         client()->toggleSmartInsertDelete();
1568 }
1569
1570 bool Editor::isAutomaticQuoteSubstitutionEnabled()
1571 {
1572     return client() && client()->isAutomaticQuoteSubstitutionEnabled();
1573 }
1574
1575 void Editor::toggleAutomaticQuoteSubstitution()
1576 {
1577     if (client())
1578         client()->toggleAutomaticQuoteSubstitution();
1579 }
1580
1581 bool Editor::isAutomaticLinkDetectionEnabled()
1582 {
1583     return client() && client()->isAutomaticLinkDetectionEnabled();
1584 }
1585
1586 void Editor::toggleAutomaticLinkDetection()
1587 {
1588     if (client())
1589         client()->toggleAutomaticLinkDetection();
1590 }
1591
1592 bool Editor::isAutomaticDashSubstitutionEnabled()
1593 {
1594     return client() && client()->isAutomaticDashSubstitutionEnabled();
1595 }
1596
1597 void Editor::toggleAutomaticDashSubstitution()
1598 {
1599     if (client())
1600         client()->toggleAutomaticDashSubstitution();
1601 }
1602
1603 bool Editor::isAutomaticTextReplacementEnabled()
1604 {
1605     return client() && client()->isAutomaticTextReplacementEnabled();
1606 }
1607
1608 void Editor::toggleAutomaticTextReplacement()
1609 {
1610     if (client())
1611         client()->toggleAutomaticTextReplacement();
1612 }
1613
1614 bool Editor::isAutomaticSpellingCorrectionEnabled()
1615 {
1616     return m_alternativeTextController->isAutomaticSpellingCorrectionEnabled();
1617 }
1618
1619 void Editor::toggleAutomaticSpellingCorrection()
1620 {
1621     if (client())
1622         client()->toggleAutomaticSpellingCorrection();
1623 }
1624
1625 #endif
1626
1627 bool Editor::shouldEndEditing(Range* range)
1628 {
1629     return client() && client()->shouldEndEditing(range);
1630 }
1631
1632 bool Editor::shouldBeginEditing(Range* range)
1633 {
1634     return client() && client()->shouldBeginEditing(range);
1635 }
1636
1637 void Editor::clearUndoRedoOperations()
1638 {
1639     if (client())
1640         client()->clearUndoRedoOperations();
1641 }
1642
1643 bool Editor::canUndo()
1644 {
1645     return client() && client()->canUndo();
1646 }
1647
1648 void Editor::undo()
1649 {
1650     if (client())
1651         client()->undo();
1652 }
1653
1654 bool Editor::canRedo()
1655 {
1656     return client() && client()->canRedo();
1657 }
1658
1659 void Editor::redo()
1660 {
1661     if (client())
1662         client()->redo();
1663 }
1664
1665 void Editor::didBeginEditing()
1666 {
1667     if (client())
1668         client()->didBeginEditing();
1669 }
1670
1671 void Editor::didEndEditing()
1672 {
1673     if (client())
1674         client()->didEndEditing();
1675 }
1676
1677 void Editor::willWriteSelectionToPasteboard(Range* range)
1678 {
1679     if (client())
1680         client()->willWriteSelectionToPasteboard(range);
1681 }
1682
1683 void Editor::didWriteSelectionToPasteboard()
1684 {
1685     if (client())
1686         client()->didWriteSelectionToPasteboard();
1687 }
1688
1689 void Editor::toggleBold()
1690 {
1691     command("ToggleBold").execute();
1692 }
1693
1694 void Editor::toggleUnderline()
1695 {
1696     command("ToggleUnderline").execute();
1697 }
1698
1699 void Editor::setBaseWritingDirection(WritingDirection direction)
1700 {
1701 #if PLATFORM(IOS)
1702     if (inSameParagraph(m_frame.selection().selection().visibleStart(), m_frame.selection().selection().visibleEnd()) && 
1703         baseWritingDirectionForSelectionStart() == direction)
1704         return;
1705 #endif
1706         
1707     Element* focusedElement = document().focusedElement();
1708     if (is<HTMLTextFormControlElement>(focusedElement)) {
1709         if (direction == NaturalWritingDirection)
1710             return;
1711
1712         auto& focusedFormElement = downcast<HTMLTextFormControlElement>(*focusedElement);
1713         auto directionValue = direction == LeftToRightWritingDirection ? "ltr" : "rtl";
1714         auto writingDirectionInputTypeName = inputTypeNameForEditingAction(EditActionSetWritingDirection);
1715         if (!dispatchBeforeInputEvent(focusedFormElement, writingDirectionInputTypeName, directionValue))
1716             return;
1717
1718         focusedFormElement.setAttributeWithoutSynchronization(dirAttr, directionValue);
1719         dispatchInputEvent(focusedFormElement, writingDirectionInputTypeName, directionValue);
1720         document().updateStyleIfNeeded();
1721         return;
1722     }
1723
1724     RefPtr<MutableStyleProperties> style = MutableStyleProperties::create();
1725     style->setProperty(CSSPropertyDirection, direction == LeftToRightWritingDirection ? "ltr" : direction == RightToLeftWritingDirection ? "rtl" : "inherit", false);
1726     applyParagraphStyleToSelection(style.get(), EditActionSetWritingDirection);
1727 }
1728
1729 WritingDirection Editor::baseWritingDirectionForSelectionStart() const
1730 {
1731     WritingDirection result = LeftToRightWritingDirection;
1732
1733     Position pos = m_frame.selection().selection().visibleStart().deepEquivalent();
1734     Node* node = pos.deprecatedNode();
1735     if (!node)
1736         return result;
1737
1738     auto renderer = node->renderer();
1739     if (!renderer)
1740         return result;
1741
1742     if (!renderer->isRenderBlockFlow()) {
1743         renderer = renderer->containingBlock();
1744         if (!renderer)
1745             return result;
1746     }
1747
1748     switch (renderer->style().direction()) {
1749     case LTR:
1750         return LeftToRightWritingDirection;
1751     case RTL:
1752         return RightToLeftWritingDirection;
1753     }
1754     
1755     return result;
1756 }
1757
1758 void Editor::selectComposition()
1759 {
1760     RefPtr<Range> range = compositionRange();
1761     if (!range)
1762         return;
1763     
1764     // The composition can start inside a composed character sequence, so we have to override checks.
1765     // See <http://bugs.webkit.org/show_bug.cgi?id=15781>
1766     VisibleSelection selection;
1767     selection.setWithoutValidation(range->startPosition(), range->endPosition());
1768     m_frame.selection().setSelection(selection, 0);
1769 }
1770
1771 void Editor::confirmComposition()
1772 {
1773     if (!m_compositionNode)
1774         return;
1775     setComposition(m_compositionNode->data().substring(m_compositionStart, m_compositionEnd - m_compositionStart), ConfirmComposition);
1776 }
1777
1778 void Editor::cancelComposition()
1779 {
1780     if (!m_compositionNode)
1781         return;
1782     setComposition(emptyString(), CancelComposition);
1783 }
1784
1785 bool Editor::cancelCompositionIfSelectionIsInvalid()
1786 {
1787     unsigned start;
1788     unsigned end;
1789     if (!hasComposition() || ignoreSelectionChanges() || getCompositionSelection(start, end))
1790         return false;
1791
1792     cancelComposition();
1793     return true;
1794 }
1795
1796 void Editor::confirmComposition(const String& text)
1797 {
1798     setComposition(text, ConfirmComposition);
1799 }
1800
1801 class SetCompositionScope {
1802 public:
1803     SetCompositionScope(Frame& frame)
1804         : m_frame(frame)
1805         , m_typingGestureIndicator(frame)
1806     {
1807         m_frame->editor().setIgnoreSelectionChanges(true);
1808     }
1809
1810     ~SetCompositionScope()
1811     {
1812         m_frame->editor().setIgnoreSelectionChanges(false);
1813         if (auto* editorClient = m_frame->editor().client())
1814             editorClient->didUpdateComposition();
1815     }
1816
1817     Ref<Frame> m_frame;
1818     UserTypingGestureIndicator m_typingGestureIndicator;
1819 };
1820
1821 void Editor::setComposition(const String& text, SetCompositionMode mode)
1822 {
1823     ASSERT(mode == ConfirmComposition || mode == CancelComposition);
1824     SetCompositionScope setCompositionScope(m_frame);
1825
1826     if (mode == CancelComposition)
1827         ASSERT(text == emptyString());
1828     else
1829         selectComposition();
1830
1831     m_compositionNode = nullptr;
1832     m_customCompositionUnderlines.clear();
1833
1834     if (m_frame.selection().isNone())
1835         return;
1836
1837     // Always delete the current composition before inserting the finalized composition text if we're confirming our composition.
1838     // Our default behavior (if the beforeinput event is not prevented) is to insert the finalized composition text back in.
1839     // We pass TypingCommand::TextCompositionPending here to indicate that we are deleting the pending composition.
1840     if (mode != CancelComposition)
1841         TypingCommand::deleteSelection(document(), 0, TypingCommand::TextCompositionPending);
1842
1843     insertTextForConfirmedComposition(text);
1844
1845     if (auto* target = document().focusedElement())
1846         target->dispatchEvent(CompositionEvent::create(eventNames().compositionendEvent, document().domWindow(), text));
1847
1848     if (mode == CancelComposition) {
1849         // An open typing command that disagrees about current selection would cause issues with typing later on.
1850         TypingCommand::closeTyping(&m_frame);
1851     }
1852 }
1853
1854 void Editor::setComposition(const String& text, const Vector<CompositionUnderline>& underlines, unsigned selectionStart, unsigned selectionEnd)
1855 {
1856     SetCompositionScope setCompositionScope(m_frame);
1857
1858     // Updates styles before setting selection for composition to prevent
1859     // inserting the previous composition text into text nodes oddly.
1860     // See https://bugs.webkit.org/show_bug.cgi?id=46868
1861     document().updateStyleIfNeeded();
1862
1863     selectComposition();
1864
1865     if (m_frame.selection().isNone())
1866         return;
1867
1868     String originalText = selectedText();
1869     bool isStartingToRecomposeExistingRange = !text.isEmpty() && selectionStart < selectionEnd && !hasComposition();
1870     if (isStartingToRecomposeExistingRange) {
1871         // We pass TypingCommand::TextCompositionFinal here to indicate that we are removing composition text that has been finalized.
1872         TypingCommand::deleteSelection(document(), 0, TypingCommand::TextCompositionFinal);
1873         const VisibleSelection& currentSelection = m_frame.selection().selection();
1874         if (currentSelection.isRange()) {
1875             // If deletion was prevented, then we need to collapse the selection to the end so that the original text will not be recomposed.
1876             m_frame.selection().setSelection({ currentSelection.end(), currentSelection.end() });
1877         }
1878     }
1879
1880 #if PLATFORM(IOS)
1881     client()->startDelayingAndCoalescingContentChangeNotifications();
1882 #endif
1883
1884     Element* target = document().focusedElement();
1885     if (target) {
1886         // Dispatch an appropriate composition event to the focused node.
1887         // We check the composition status and choose an appropriate composition event since this
1888         // function is used for three purposes:
1889         // 1. Starting a new composition.
1890         //    Send a compositionstart and a compositionupdate event when this function creates
1891         //    a new composition node, i.e.
1892         //    m_compositionNode == 0 && !text.isEmpty().
1893         //    Sending a compositionupdate event at this time ensures that at least one
1894         //    compositionupdate event is dispatched.
1895         // 2. Updating the existing composition node.
1896         //    Send a compositionupdate event when this function updates the existing composition
1897         //    node, i.e. m_compositionNode != 0 && !text.isEmpty().
1898         // 3. Canceling the ongoing composition.
1899         //    Send a compositionend event when function deletes the existing composition node, i.e.
1900         //    m_compositionNode != 0 && test.isEmpty().
1901         RefPtr<CompositionEvent> event;
1902         if (!m_compositionNode) {
1903             // We should send a compositionstart event only when the given text is not empty because this
1904             // function doesn't create a composition node when the text is empty.
1905             if (!text.isEmpty()) {
1906                 target->dispatchEvent(CompositionEvent::create(eventNames().compositionstartEvent, document().domWindow(), originalText));
1907                 event = CompositionEvent::create(eventNames().compositionupdateEvent, document().domWindow(), text);
1908             }
1909         } else if (!text.isEmpty())
1910             event = CompositionEvent::create(eventNames().compositionupdateEvent, document().domWindow(), text);
1911
1912         if (event)
1913             target->dispatchEvent(*event);
1914     }
1915
1916     // If text is empty, then delete the old composition here.  If text is non-empty, InsertTextCommand::input
1917     // will delete the old composition with an optimized replace operation.
1918     if (text.isEmpty()) {
1919         TypingCommand::deleteSelection(document(), TypingCommand::PreventSpellChecking, TypingCommand::TextCompositionPending);
1920         if (target)
1921             target->dispatchEvent(CompositionEvent::create(eventNames().compositionendEvent, document().domWindow(), text));
1922     }
1923
1924     m_compositionNode = nullptr;
1925     m_customCompositionUnderlines.clear();
1926
1927     if (!text.isEmpty()) {
1928         TypingCommand::insertText(document(), text, TypingCommand::SelectInsertedText | TypingCommand::PreventSpellChecking, TypingCommand::TextCompositionPending);
1929
1930         // Find out what node has the composition now.
1931         Position base = m_frame.selection().selection().base().downstream();
1932         Position extent = m_frame.selection().selection().extent();
1933         Node* baseNode = base.deprecatedNode();
1934         unsigned baseOffset = base.deprecatedEditingOffset();
1935         Node* extentNode = extent.deprecatedNode();
1936         unsigned extentOffset = extent.deprecatedEditingOffset();
1937
1938         if (is<Text>(baseNode) && baseNode == extentNode && baseOffset + text.length() == extentOffset) {
1939             m_compositionNode = downcast<Text>(baseNode);
1940             m_compositionStart = baseOffset;
1941             m_compositionEnd = extentOffset;
1942             m_customCompositionUnderlines = underlines;
1943             for (auto& underline : m_customCompositionUnderlines) {
1944                 underline.startOffset += baseOffset;
1945                 underline.endOffset += baseOffset;
1946             }
1947             if (baseNode->renderer())
1948                 baseNode->renderer()->repaint();
1949
1950             unsigned start = std::min(baseOffset + selectionStart, extentOffset);
1951             unsigned end = std::min(std::max(start, baseOffset + selectionEnd), extentOffset);
1952             RefPtr<Range> selectedRange = Range::create(baseNode->document(), baseNode, start, baseNode, end);
1953             m_frame.selection().setSelectedRange(selectedRange.get(), DOWNSTREAM, false);
1954         }
1955     }
1956
1957 #if PLATFORM(IOS)        
1958     client()->stopDelayingAndCoalescingContentChangeNotifications();
1959 #endif
1960 }
1961
1962 void Editor::ignoreSpelling()
1963 {
1964     if (!client())
1965         return;
1966         
1967     RefPtr<Range> selectedRange = m_frame.selection().toNormalizedRange();
1968     if (selectedRange)
1969         document().markers().removeMarkers(selectedRange.get(), DocumentMarker::Spelling);
1970
1971     String text = selectedText();
1972     ASSERT(text.length());
1973     textChecker()->ignoreWordInSpellDocument(text);
1974 }
1975
1976 void Editor::learnSpelling()
1977 {
1978     if (!client())
1979         return;
1980         
1981     // FIXME: On Mac OS X, when use "learn" button on "Spelling and Grammar" panel, we don't call this function. It should remove misspelling markers around the learned word, see <rdar://problem/5396072>.
1982
1983     RefPtr<Range> selectedRange = m_frame.selection().toNormalizedRange();
1984     if (selectedRange)
1985         document().markers().removeMarkers(selectedRange.get(), DocumentMarker::Spelling);
1986
1987     String text = selectedText();
1988     ASSERT(text.length());
1989     textChecker()->learnWord(text);
1990 }
1991
1992 #if !PLATFORM(IOS)
1993
1994 void Editor::advanceToNextMisspelling(bool startBeforeSelection)
1995 {
1996     Ref<Frame> protection(m_frame);
1997
1998     // The basic approach is to search in two phases - from the selection end to the end of the doc, and
1999     // then we wrap and search from the doc start to (approximately) where we started.
2000     
2001     // Start at the end of the selection, search to edge of document.  Starting at the selection end makes
2002     // repeated "check spelling" commands work.
2003     VisibleSelection selection(m_frame.selection().selection());
2004     Ref<Range> spellingSearchRange = rangeOfContents(document());
2005
2006     bool startedWithSelection = false;
2007     if (selection.start().deprecatedNode()) {
2008         startedWithSelection = true;
2009         if (startBeforeSelection) {
2010             VisiblePosition start(selection.visibleStart());
2011             // We match AppKit's rule: Start 1 character before the selection.
2012             VisiblePosition oneBeforeStart = start.previous();
2013             setStart(spellingSearchRange.ptr(), oneBeforeStart.isNotNull() ? oneBeforeStart : start);
2014         } else
2015             setStart(spellingSearchRange.ptr(), selection.visibleEnd());
2016     }
2017
2018     Position position = spellingSearchRange->startPosition();
2019     if (!isEditablePosition(position)) {
2020         // This shouldn't happen in very often because the Spelling menu items aren't enabled unless the
2021         // selection is editable.
2022         // This can happen in Mail for a mix of non-editable and editable content (like Stationary), 
2023         // when spell checking the whole document before sending the message.
2024         // In that case the document might not be editable, but there are editable pockets that need to be spell checked.
2025
2026         position = VisiblePosition(firstEditablePositionAfterPositionInRoot(position, document().documentElement())).deepEquivalent();
2027         if (position.isNull())
2028             return;
2029         
2030         Position rangeCompliantPosition = position.parentAnchoredEquivalent();
2031         if (rangeCompliantPosition.deprecatedNode())
2032             spellingSearchRange->setStart(*rangeCompliantPosition.deprecatedNode(), rangeCompliantPosition.deprecatedEditingOffset());
2033         startedWithSelection = false; // won't need to wrap
2034     }
2035     
2036     // topNode defines the whole range we want to operate on 
2037     auto* topNode = highestEditableRoot(position);
2038     // FIXME: lastOffsetForEditing() is wrong here if editingIgnoresContent(highestEditableRoot()) returns true (e.g. a <table>)
2039     if (topNode)
2040         spellingSearchRange->setEnd(*topNode, lastOffsetForEditing(*topNode));
2041
2042     // If spellingSearchRange starts in the middle of a word, advance to the next word so we start checking
2043     // at a word boundary. Going back by one char and then forward by a word does the trick.
2044     if (startedWithSelection) {
2045         VisiblePosition oneBeforeStart = startVisiblePosition(spellingSearchRange.ptr(), DOWNSTREAM).previous();
2046         if (oneBeforeStart.isNotNull())
2047             setStart(spellingSearchRange.ptr(), endOfWord(oneBeforeStart));
2048         // else we were already at the start of the editable node
2049     }
2050
2051     if (spellingSearchRange->collapsed())
2052         return; // nothing to search in
2053     
2054     // Get the spell checker if it is available
2055     if (!client())
2056         return;
2057         
2058     // We go to the end of our first range instead of the start of it, just to be sure
2059     // we don't get foiled by any word boundary problems at the start.  It means we might
2060     // do a tiny bit more searching.
2061     Node& searchEndNodeAfterWrap = spellingSearchRange->endContainer();
2062     int searchEndOffsetAfterWrap = spellingSearchRange->endOffset();
2063     
2064     int misspellingOffset = 0;
2065     GrammarDetail grammarDetail;
2066     int grammarPhraseOffset = 0;
2067     RefPtr<Range> grammarSearchRange;
2068     String badGrammarPhrase;
2069     String misspelledWord;
2070
2071     bool isSpelling = true;
2072     int foundOffset = 0;
2073     String foundItem;
2074     RefPtr<Range> firstMisspellingRange;
2075     if (unifiedTextCheckerEnabled()) {
2076         grammarSearchRange = spellingSearchRange->cloneRange();
2077         foundItem = TextCheckingHelper(*client(), spellingSearchRange).findFirstMisspellingOrBadGrammar(isGrammarCheckingEnabled(), isSpelling, foundOffset, grammarDetail);
2078         if (isSpelling) {
2079             misspelledWord = foundItem;
2080             misspellingOffset = foundOffset;
2081         } else {
2082             badGrammarPhrase = foundItem;
2083             grammarPhraseOffset = foundOffset;
2084         }
2085     } else {
2086         misspelledWord = TextCheckingHelper(*client(), spellingSearchRange).findFirstMisspelling(misspellingOffset, false, firstMisspellingRange);
2087
2088 #if USE(GRAMMAR_CHECKING)
2089         grammarSearchRange = spellingSearchRange->cloneRange();
2090         if (!misspelledWord.isEmpty()) {
2091             // Stop looking at start of next misspelled word
2092             CharacterIterator chars(*grammarSearchRange);
2093             chars.advance(misspellingOffset);
2094             grammarSearchRange->setEnd(chars.range()->startContainer(), chars.range()->startOffset());
2095         }
2096     
2097         if (isGrammarCheckingEnabled())
2098             badGrammarPhrase = TextCheckingHelper(*client(), *grammarSearchRange).findFirstBadGrammar(grammarDetail, grammarPhraseOffset, false);
2099 #endif
2100     }
2101     
2102     // If we found neither bad grammar nor a misspelled word, wrap and try again (but don't bother if we started at the beginning of the
2103     // block rather than at a selection).
2104     if (startedWithSelection && !misspelledWord && !badGrammarPhrase) {
2105         if (topNode)
2106             spellingSearchRange->setStart(*topNode, 0);
2107         // going until the end of the very first chunk we tested is far enough
2108         spellingSearchRange->setEnd(searchEndNodeAfterWrap, searchEndOffsetAfterWrap);
2109         
2110         if (unifiedTextCheckerEnabled()) {
2111             grammarSearchRange = spellingSearchRange->cloneRange();
2112             foundItem = TextCheckingHelper(*client(), spellingSearchRange).findFirstMisspellingOrBadGrammar(isGrammarCheckingEnabled(), isSpelling, foundOffset, grammarDetail);
2113             if (isSpelling) {
2114                 misspelledWord = foundItem;
2115                 misspellingOffset = foundOffset;
2116             } else {
2117                 badGrammarPhrase = foundItem;
2118                 grammarPhraseOffset = foundOffset;
2119             }
2120         } else {
2121             misspelledWord = TextCheckingHelper(*client(), spellingSearchRange).findFirstMisspelling(misspellingOffset, false, firstMisspellingRange);
2122
2123 #if USE(GRAMMAR_CHECKING)
2124             grammarSearchRange = spellingSearchRange->cloneRange();
2125             if (!misspelledWord.isEmpty()) {
2126                 // Stop looking at start of next misspelled word
2127                 CharacterIterator chars(*grammarSearchRange);
2128                 chars.advance(misspellingOffset);
2129                 grammarSearchRange->setEnd(chars.range()->startContainer(), chars.range()->startOffset());
2130             }
2131
2132             if (isGrammarCheckingEnabled())
2133                 badGrammarPhrase = TextCheckingHelper(*client(), *grammarSearchRange).findFirstBadGrammar(grammarDetail, grammarPhraseOffset, false);
2134 #endif
2135         }
2136     }
2137     
2138 #if !USE(GRAMMAR_CHECKING)
2139     ASSERT(badGrammarPhrase.isEmpty());
2140     UNUSED_PARAM(grammarPhraseOffset);
2141 #else
2142     if (!badGrammarPhrase.isEmpty()) {
2143         // We found bad grammar. Since we only searched for bad grammar up to the first misspelled word, the bad grammar
2144         // takes precedence and we ignore any potential misspelled word. Select the grammar detail, update the spelling
2145         // panel, and store a marker so we draw the green squiggle later.
2146         
2147         ASSERT(badGrammarPhrase.length() > 0);
2148         ASSERT(grammarDetail.location != -1 && grammarDetail.length > 0);
2149         
2150         // FIXME 4859190: This gets confused with doubled punctuation at the end of a paragraph
2151         RefPtr<Range> badGrammarRange = TextIterator::subrange(*grammarSearchRange, grammarPhraseOffset + grammarDetail.location, grammarDetail.length);
2152         m_frame.selection().setSelection(VisibleSelection(*badGrammarRange, SEL_DEFAULT_AFFINITY));
2153         m_frame.selection().revealSelection();
2154         
2155         client()->updateSpellingUIWithGrammarString(badGrammarPhrase, grammarDetail);
2156         document().markers().addMarker(badGrammarRange.get(), DocumentMarker::Grammar, grammarDetail.userDescription);
2157     } else
2158 #endif
2159     if (!misspelledWord.isEmpty()) {
2160         // We found a misspelling, but not any earlier bad grammar. Select the misspelling, update the spelling panel, and store
2161         // a marker so we draw the red squiggle later.
2162         
2163         auto misspellingRange = TextIterator::subrange(spellingSearchRange, misspellingOffset, misspelledWord.length());
2164         m_frame.selection().setSelection(VisibleSelection(misspellingRange, DOWNSTREAM));
2165         m_frame.selection().revealSelection();
2166         
2167         client()->updateSpellingUIWithMisspelledWord(misspelledWord);
2168         document().markers().addMarker(misspellingRange.ptr(), DocumentMarker::Spelling);
2169     }
2170 }
2171
2172 #endif // !PLATFORM(IOS)
2173
2174 String Editor::misspelledWordAtCaretOrRange(Node* clickedNode) const
2175 {
2176     if (!isContinuousSpellCheckingEnabled() || !clickedNode || !isSpellCheckingEnabledFor(clickedNode))
2177         return String();
2178
2179     VisibleSelection selection = m_frame.selection().selection();
2180     if (!selection.isContentEditable() || selection.isNone())
2181         return String();
2182
2183     VisibleSelection wordSelection(selection.base());
2184     wordSelection.expandUsingGranularity(WordGranularity);
2185     RefPtr<Range> wordRange = wordSelection.toNormalizedRange();
2186     if (!wordRange)
2187         return String();
2188
2189     // In compliance with GTK+ applications, additionally allow to provide suggestions when the current
2190     // selection exactly match the word selection.
2191     if (selection.isRange() && !areRangesEqual(wordRange.get(), selection.toNormalizedRange().get()))
2192         return String();
2193
2194     String word = wordRange->text();
2195     if (word.isEmpty() || !client())
2196         return String();
2197
2198     int wordLength = word.length();
2199     int misspellingLocation = -1;
2200     int misspellingLength = 0;
2201     textChecker()->checkSpellingOfString(word, &misspellingLocation, &misspellingLength);
2202
2203     return misspellingLength == wordLength ? word : String();
2204 }
2205
2206 String Editor::misspelledSelectionString() const
2207 {
2208     String selectedString = selectedText();
2209     int length = selectedString.length();
2210     if (!length || !client())
2211         return String();
2212
2213     int misspellingLocation = -1;
2214     int misspellingLength = 0;
2215     textChecker()->checkSpellingOfString(selectedString, &misspellingLocation, &misspellingLength);
2216     
2217     // The selection only counts as misspelled if the selected text is exactly one misspelled word
2218     if (misspellingLength != length)
2219         return String();
2220     
2221     // Update the spelling panel to be displaying this error (whether or not the spelling panel is on screen).
2222     // This is necessary to make a subsequent call to [NSSpellChecker ignoreWord:inSpellDocumentWithTag:] work
2223     // correctly; that call behaves differently based on whether the spelling panel is displaying a misspelling
2224     // or a grammar error.
2225     client()->updateSpellingUIWithMisspelledWord(selectedString);
2226     
2227     return selectedString;
2228 }
2229
2230 bool Editor::isSelectionUngrammatical()
2231 {
2232 #if USE(GRAMMAR_CHECKING)
2233     RefPtr<Range> range = m_frame.selection().toNormalizedRange();
2234     if (!range || !client())
2235         return false;
2236     return TextCheckingHelper(*client(), *range).isUngrammatical();
2237 #else
2238     return false;
2239 #endif
2240 }
2241
2242 Vector<String> Editor::guessesForMisspelledWord(const String& word) const
2243 {
2244     ASSERT(word.length());
2245
2246     Vector<String> guesses;
2247     if (client())
2248         textChecker()->getGuessesForWord(word, String(), m_frame.selection().selection(), guesses);
2249     return guesses;
2250 }
2251
2252 Vector<String> Editor::guessesForMisspelledOrUngrammatical(bool& misspelled, bool& ungrammatical)
2253 {
2254     if (unifiedTextCheckerEnabled()) {
2255         RefPtr<Range> range;
2256         VisibleSelection selection = m_frame.selection().selection();
2257         if (selection.isCaret() && behavior().shouldAllowSpellingSuggestionsWithoutSelection()) {
2258             VisibleSelection wordSelection = VisibleSelection(selection.base());
2259             wordSelection.expandUsingGranularity(WordGranularity);
2260             range = wordSelection.toNormalizedRange();
2261         } else
2262             range = selection.toNormalizedRange();
2263         if (!range || !client())
2264             return Vector<String>();
2265         return TextCheckingHelper(*client(), *range).guessesForMisspelledOrUngrammaticalRange(isGrammarCheckingEnabled(), misspelled, ungrammatical);
2266     }
2267
2268     String misspelledWord = behavior().shouldAllowSpellingSuggestionsWithoutSelection() ? misspelledWordAtCaretOrRange(document().focusedElement()) : misspelledSelectionString();
2269     misspelled = !misspelledWord.isEmpty();
2270     // Only unified text checker supports guesses for ungrammatical phrases.
2271     ungrammatical = false;
2272
2273     if (misspelled)
2274         return guessesForMisspelledWord(misspelledWord);
2275     return Vector<String>();
2276 }
2277
2278 void Editor::showSpellingGuessPanel()
2279 {
2280     if (!client()) {
2281         LOG_ERROR("No NSSpellChecker");
2282         return;
2283     }
2284
2285     if (client()->spellingUIIsShowing()) {
2286         client()->showSpellingUI(false);
2287         return;
2288     }
2289
2290 #if !PLATFORM(IOS)
2291     advanceToNextMisspelling(true);
2292 #endif
2293     client()->showSpellingUI(true);
2294 }
2295
2296 bool Editor::spellingPanelIsShowing()
2297 {
2298     if (!client())
2299         return false;
2300     return client()->spellingUIIsShowing();
2301 }
2302
2303 void Editor::clearMisspellingsAndBadGrammar(const VisibleSelection &movingSelection)
2304 {
2305     RefPtr<Range> selectedRange = movingSelection.toNormalizedRange();
2306     if (selectedRange) {
2307         document().markers().removeMarkers(selectedRange.get(), DocumentMarker::Spelling);
2308         document().markers().removeMarkers(selectedRange.get(), DocumentMarker::Grammar);
2309     }
2310 }
2311
2312 void Editor::markMisspellingsAndBadGrammar(const VisibleSelection &movingSelection)
2313 {
2314     markMisspellingsAndBadGrammar(movingSelection, isContinuousSpellCheckingEnabled() && isGrammarCheckingEnabled(), movingSelection);
2315 }
2316
2317 void Editor::markMisspellingsAfterTypingToWord(const VisiblePosition &wordStart, const VisibleSelection& selectionAfterTyping, bool doReplacement)
2318 {
2319     Ref<Frame> protection(m_frame);
2320
2321 #if PLATFORM(IOS)
2322     UNUSED_PARAM(selectionAfterTyping);
2323     UNUSED_PARAM(doReplacement);
2324     TextCheckingTypeMask textCheckingOptions = 0;
2325     if (isContinuousSpellCheckingEnabled())
2326         textCheckingOptions |= TextCheckingTypeSpelling;
2327     if (!(textCheckingOptions & TextCheckingTypeSpelling))
2328         return;
2329
2330     VisibleSelection adjacentWords = VisibleSelection(startOfWord(wordStart, LeftWordIfOnBoundary), endOfWord(wordStart, RightWordIfOnBoundary));
2331     markAllMisspellingsAndBadGrammarInRanges(textCheckingOptions, adjacentWords.toNormalizedRange().get(), adjacentWords.toNormalizedRange().get());
2332 #else
2333 #if !USE(AUTOMATIC_TEXT_REPLACEMENT)
2334     UNUSED_PARAM(doReplacement);
2335 #endif
2336
2337     if (unifiedTextCheckerEnabled()) {
2338         m_alternativeTextController->applyPendingCorrection(selectionAfterTyping);
2339
2340         TextCheckingTypeMask textCheckingOptions = 0;
2341
2342         if (isContinuousSpellCheckingEnabled())
2343             textCheckingOptions |= TextCheckingTypeSpelling;
2344
2345 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
2346         if (doReplacement
2347             && (isAutomaticQuoteSubstitutionEnabled()
2348                 || isAutomaticLinkDetectionEnabled()
2349                 || isAutomaticDashSubstitutionEnabled()
2350                 || isAutomaticTextReplacementEnabled()
2351                 || ((textCheckingOptions & TextCheckingTypeSpelling) && isAutomaticSpellingCorrectionEnabled())))
2352             textCheckingOptions |= TextCheckingTypeReplacement;
2353 #endif
2354         if (!(textCheckingOptions & (TextCheckingTypeSpelling | TextCheckingTypeReplacement)))
2355             return;
2356
2357         if (isGrammarCheckingEnabled())
2358             textCheckingOptions |= TextCheckingTypeGrammar;
2359
2360         VisibleSelection adjacentWords = VisibleSelection(startOfWord(wordStart, LeftWordIfOnBoundary), endOfWord(wordStart, RightWordIfOnBoundary));
2361         if (textCheckingOptions & TextCheckingTypeGrammar) {
2362             VisibleSelection selectedSentence = VisibleSelection(startOfSentence(wordStart), endOfSentence(wordStart));
2363             markAllMisspellingsAndBadGrammarInRanges(textCheckingOptions, adjacentWords.toNormalizedRange().get(), selectedSentence.toNormalizedRange().get());
2364         } else
2365             markAllMisspellingsAndBadGrammarInRanges(textCheckingOptions, adjacentWords.toNormalizedRange().get(), adjacentWords.toNormalizedRange().get());
2366         return;
2367     }
2368
2369     if (!isContinuousSpellCheckingEnabled())
2370         return;
2371
2372     // Check spelling of one word
2373     RefPtr<Range> misspellingRange;
2374     markMisspellings(VisibleSelection(startOfWord(wordStart, LeftWordIfOnBoundary), endOfWord(wordStart, RightWordIfOnBoundary)), misspellingRange);
2375
2376     // Autocorrect the misspelled word.
2377     if (!misspellingRange)
2378         return;
2379     
2380     // Get the misspelled word.
2381     const String misspelledWord = plainText(misspellingRange.get());
2382     String autocorrectedString = textChecker()->getAutoCorrectSuggestionForMisspelledWord(misspelledWord);
2383
2384     // If autocorrected word is non empty, replace the misspelled word by this word.
2385     if (!autocorrectedString.isEmpty()) {
2386         VisibleSelection newSelection(*misspellingRange, DOWNSTREAM);
2387         if (newSelection != m_frame.selection().selection()) {
2388             if (!m_frame.selection().shouldChangeSelection(newSelection))
2389                 return;
2390             m_frame.selection().setSelection(newSelection);
2391         }
2392
2393         if (!m_frame.editor().shouldInsertText(autocorrectedString, misspellingRange.get(), EditorInsertAction::Typed))
2394             return;
2395         m_frame.editor().replaceSelectionWithText(autocorrectedString, false, false, EditActionInsert);
2396
2397         // Reset the charet one character further.
2398         m_frame.selection().moveTo(m_frame.selection().selection().end());
2399         m_frame.selection().modify(FrameSelection::AlterationMove, DirectionForward, CharacterGranularity);
2400     }
2401
2402     if (!isGrammarCheckingEnabled())
2403         return;
2404     
2405     // Check grammar of entire sentence
2406     markBadGrammar(VisibleSelection(startOfSentence(wordStart), endOfSentence(wordStart)));
2407 #endif
2408 }
2409     
2410 void Editor::markMisspellingsOrBadGrammar(const VisibleSelection& selection, bool checkSpelling, RefPtr<Range>& firstMisspellingRange)
2411 {
2412 #if !PLATFORM(IOS)
2413     // This function is called with a selection already expanded to word boundaries.
2414     // Might be nice to assert that here.
2415     
2416     // This function is used only for as-you-type checking, so if that's off we do nothing. Note that
2417     // grammar checking can only be on if spell checking is also on.
2418     if (!isContinuousSpellCheckingEnabled())
2419         return;
2420     
2421     RefPtr<Range> searchRange(selection.toNormalizedRange());
2422     if (!searchRange)
2423         return;
2424     
2425     // If we're not in an editable node, bail.
2426     Node& editableNode = searchRange->startContainer();
2427     if (!editableNode.hasEditableStyle())
2428         return;
2429
2430     if (!isSpellCheckingEnabledFor(&editableNode))
2431         return;
2432
2433     // Get the spell checker if it is available
2434     if (!client())
2435         return;
2436     
2437     TextCheckingHelper checker(*client(), *searchRange);
2438     if (checkSpelling)
2439         checker.markAllMisspellings(firstMisspellingRange);
2440     else {
2441 #if USE(GRAMMAR_CHECKING)
2442         if (isGrammarCheckingEnabled())
2443             checker.markAllBadGrammar();
2444 #else
2445         ASSERT_NOT_REACHED();
2446 #endif
2447     }    
2448 #else
2449         UNUSED_PARAM(selection);
2450         UNUSED_PARAM(checkSpelling);
2451         UNUSED_PARAM(firstMisspellingRange);
2452 #endif // !PLATFORM(IOS)
2453 }
2454
2455 bool Editor::isSpellCheckingEnabledFor(Node* node) const
2456 {
2457     if (!node)
2458         return false;
2459     Element* element = is<Element>(*node) ? downcast<Element>(node) : node->parentElement();
2460     if (!element)
2461         return false;
2462     if (element->isInUserAgentShadowTree()) {
2463         if (HTMLTextFormControlElement* textControl = enclosingTextFormControl(firstPositionInOrBeforeNode(element)))
2464             return textControl->isSpellCheckingEnabled();
2465     }
2466     return element->isSpellCheckingEnabled();
2467 }
2468
2469 bool Editor::isSpellCheckingEnabledInFocusedNode() const
2470 {
2471     return isSpellCheckingEnabledFor(m_frame.selection().selection().start().deprecatedNode());
2472 }
2473
2474 void Editor::markMisspellings(const VisibleSelection& selection, RefPtr<Range>& firstMisspellingRange)
2475 {
2476     markMisspellingsOrBadGrammar(selection, true, firstMisspellingRange);
2477 }
2478     
2479 void Editor::markBadGrammar(const VisibleSelection& selection)
2480 {
2481 #if USE(GRAMMAR_CHECKING)
2482     RefPtr<Range> firstMisspellingRange;
2483     markMisspellingsOrBadGrammar(selection, false, firstMisspellingRange);
2484 #else
2485     ASSERT_NOT_REACHED();
2486 #endif
2487 }
2488
2489 void Editor::markAllMisspellingsAndBadGrammarInRanges(TextCheckingTypeMask textCheckingOptions, Range* spellingRange, Range* grammarRange)
2490 {
2491     ASSERT(unifiedTextCheckerEnabled());
2492
2493     // There shouldn't be pending autocorrection at this moment.
2494     ASSERT(!m_alternativeTextController->hasPendingCorrection());
2495
2496     bool shouldMarkGrammar = textCheckingOptions & TextCheckingTypeGrammar;
2497     bool shouldShowCorrectionPanel = textCheckingOptions & TextCheckingTypeShowCorrectionPanel;
2498
2499     // This function is called with selections already expanded to word boundaries.
2500     if (!client() || !spellingRange || (shouldMarkGrammar && !grammarRange))
2501         return;
2502
2503     // If we're not in an editable node, bail.
2504     Node& editableNode = spellingRange->startContainer();
2505     if (!editableNode.hasEditableStyle())
2506         return;
2507
2508     if (!isSpellCheckingEnabledFor(&editableNode))
2509         return;
2510
2511     Range& rangeToCheck = shouldMarkGrammar ? *grammarRange : *spellingRange;
2512     TextCheckingParagraph paragraphToCheck(rangeToCheck);
2513     if (paragraphToCheck.isEmpty())
2514         return;
2515     Ref<Range> paragraphRange = paragraphToCheck.paragraphRange();
2516
2517     bool asynchronous = m_frame.settings().asynchronousSpellCheckingEnabled() && !shouldShowCorrectionPanel;
2518
2519     // In asynchronous mode, we intentionally check paragraph-wide sentence.
2520     const auto resolvedOptions = resolveTextCheckingTypeMask(editableNode, textCheckingOptions);
2521     auto request = SpellCheckRequest::create(resolvedOptions, TextCheckingProcessIncremental, asynchronous ? paragraphRange.get() : rangeToCheck, paragraphRange.copyRef());
2522     if (!request)
2523         return;
2524
2525     if (asynchronous) {
2526         m_spellChecker->requestCheckingFor(request.releaseNonNull());
2527         return;
2528     }
2529
2530     Vector<TextCheckingResult> results;
2531     checkTextOfParagraph(*textChecker(), paragraphToCheck.text(), resolvedOptions, results, m_frame.selection().selection());
2532     markAndReplaceFor(request.releaseNonNull(), results);
2533 }
2534
2535 static bool isAutomaticTextReplacementType(TextCheckingType type)
2536 {
2537     switch (type) {
2538     case TextCheckingTypeNone:
2539     case TextCheckingTypeSpelling:
2540     case TextCheckingTypeGrammar:
2541         return false;
2542     case TextCheckingTypeLink:
2543     case TextCheckingTypeQuote:
2544     case TextCheckingTypeDash:
2545     case TextCheckingTypeReplacement:
2546     case TextCheckingTypeCorrection:
2547     case TextCheckingTypeShowCorrectionPanel:
2548         return true;
2549     }
2550     ASSERT_NOT_REACHED();
2551     return false;
2552 }
2553
2554 static void correctSpellcheckingPreservingTextCheckingParagraph(TextCheckingParagraph& paragraph, Range& rangeToReplace, const String& replacement, int resultLocation, int resultLength)
2555 {
2556     auto& scope = downcast<ContainerNode>(paragraph.paragraphRange().startContainer().rootNode());
2557
2558     size_t paragraphLocation;
2559     size_t paragraphLength;
2560     TextIterator::getLocationAndLengthFromRange(&scope, &paragraph.paragraphRange(), paragraphLocation, paragraphLength);
2561
2562     SpellingCorrectionCommand::create(rangeToReplace, replacement)->apply();
2563
2564     // TextCheckingParagraph may be orphaned after SpellingCorrectionCommand mutated DOM.
2565     // See <rdar://10305315>, http://webkit.org/b/89526.
2566
2567     RefPtr<Range> newParagraphRange = TextIterator::rangeFromLocationAndLength(&scope, paragraphLocation, paragraphLength + replacement.length() - resultLength);
2568
2569     paragraph = TextCheckingParagraph(TextIterator::subrange(*newParagraphRange, resultLocation, replacement.length()), newParagraphRange.get());
2570 }
2571
2572 void Editor::markAndReplaceFor(const SpellCheckRequest& request, const Vector<TextCheckingResult>& results)
2573 {
2574     Ref<Frame> protection(m_frame);
2575
2576     TextCheckingTypeMask textCheckingOptions = request.data().mask();
2577     TextCheckingParagraph paragraph(request.checkingRange(), &request.paragraphRange());
2578
2579     const bool shouldMarkSpelling = textCheckingOptions & TextCheckingTypeSpelling;
2580     const bool shouldMarkGrammar = textCheckingOptions & TextCheckingTypeGrammar;
2581     const bool shouldMarkLink = textCheckingOptions & TextCheckingTypeLink;
2582     const bool shouldPerformReplacement = textCheckingOptions & (TextCheckingTypeQuote | TextCheckingTypeDash | TextCheckingTypeReplacement);
2583     const bool shouldShowCorrectionPanel = textCheckingOptions & TextCheckingTypeShowCorrectionPanel;
2584     const bool shouldCheckForCorrection = shouldShowCorrectionPanel || (textCheckingOptions & TextCheckingTypeCorrection);
2585 #if !USE(AUTOCORRECTION_PANEL)
2586     ASSERT(!shouldShowCorrectionPanel);
2587 #endif
2588
2589     // Expand the range to encompass entire paragraphs, since text checking needs that much context.
2590     int selectionOffset = 0;
2591     bool useAmbiguousBoundaryOffset = false;
2592     bool selectionChanged = false;
2593     bool restoreSelectionAfterChange = false;
2594     bool adjustSelectionForParagraphBoundaries = false;
2595
2596     if (shouldPerformReplacement || shouldMarkSpelling || shouldCheckForCorrection) {
2597         if (m_frame.selection().selection().selectionType() == VisibleSelection::CaretSelection) {
2598             // Attempt to save the caret position so we can restore it later if needed
2599             Position caretPosition = m_frame.selection().selection().end();
2600             selectionOffset = paragraph.offsetTo(caretPosition).releaseReturnValue();
2601             restoreSelectionAfterChange = true;
2602             if (selectionOffset > 0 && (selectionOffset > paragraph.textLength() || paragraph.textCharAt(selectionOffset - 1) == newlineCharacter))
2603                 adjustSelectionForParagraphBoundaries = true;
2604             if (selectionOffset > 0 && selectionOffset <= paragraph.textLength() && isAmbiguousBoundaryCharacter(paragraph.textCharAt(selectionOffset - 1)))
2605                 useAmbiguousBoundaryOffset = true;
2606         }
2607     }
2608
2609     int offsetDueToReplacement = 0;
2610
2611     for (unsigned i = 0; i < results.size(); i++) {
2612         const int spellingRangeEndOffset = paragraph.checkingEnd() + offsetDueToReplacement;
2613         const TextCheckingType resultType = results[i].type;
2614         const int resultLocation = results[i].location + offsetDueToReplacement;
2615         const int resultLength = results[i].length;
2616         const int resultEndLocation = resultLocation + resultLength;
2617         const String& replacement = results[i].replacement;
2618         const bool resultEndsAtAmbiguousBoundary = useAmbiguousBoundaryOffset && selectionOffset - 1 <= resultEndLocation;
2619
2620         // Only mark misspelling if:
2621         // 1. Current text checking isn't done for autocorrection, in which case shouldMarkSpelling is false.
2622         // 2. Result falls within spellingRange.
2623         // 3. The word in question doesn't end at an ambiguous boundary. For instance, we would not mark
2624         //    "wouldn'" as misspelled right after apostrophe is typed.
2625         if (shouldMarkSpelling && !shouldShowCorrectionPanel && resultType == TextCheckingTypeSpelling
2626             && resultLocation >= paragraph.checkingStart() && resultEndLocation <= spellingRangeEndOffset && !resultEndsAtAmbiguousBoundary) {
2627             ASSERT(resultLength > 0 && resultLocation >= 0);
2628             auto misspellingRange = paragraph.subrange(resultLocation, resultLength);
2629             if (!m_alternativeTextController->isSpellingMarkerAllowed(misspellingRange))
2630                 continue;
2631             misspellingRange->startContainer().document().markers().addMarker(misspellingRange.ptr(), DocumentMarker::Spelling, replacement);
2632         } else if (shouldMarkGrammar && resultType == TextCheckingTypeGrammar && paragraph.checkingRangeCovers(resultLocation, resultLength)) {
2633             ASSERT(resultLength > 0 && resultLocation >= 0);
2634             for (auto& detail : results[i].details) {
2635                 ASSERT(detail.length > 0 && detail.location >= 0);
2636                 if (paragraph.checkingRangeCovers(resultLocation + detail.location, detail.length)) {
2637                     auto badGrammarRange = paragraph.subrange(resultLocation + detail.location, detail.length);
2638                     badGrammarRange->startContainer().document().markers().addMarker(badGrammarRange.ptr(), DocumentMarker::Grammar, detail.userDescription);
2639                 }
2640             }
2641         } else if (resultEndLocation <= spellingRangeEndOffset && resultEndLocation >= paragraph.checkingStart()
2642             && isAutomaticTextReplacementType(resultType)) {
2643             // In this case the result range just has to touch the spelling range, so we can handle replacing non-word text such as punctuation.
2644             ASSERT(resultLength > 0 && resultLocation >= 0);
2645
2646             if (shouldShowCorrectionPanel && (resultEndLocation < spellingRangeEndOffset
2647                 || !(resultType & (TextCheckingTypeReplacement | TextCheckingTypeCorrection))))
2648                 continue;
2649
2650             // Apply replacement if:
2651             // 1. The replacement length is non-zero.
2652             // 2. The result doesn't end at an ambiguous boundary.
2653             //    (FIXME: this is required until 6853027 is fixed and text checking can do this for us
2654             bool doReplacement = replacement.length() > 0 && !resultEndsAtAmbiguousBoundary;
2655             auto rangeToReplace = paragraph.subrange(resultLocation, resultLength);
2656
2657             // adding links should be done only immediately after they are typed
2658             if (resultType == TextCheckingTypeLink && selectionOffset != resultEndLocation + 1)
2659                 continue;
2660
2661             if (!(shouldPerformReplacement || shouldCheckForCorrection || shouldMarkLink) || !doReplacement)
2662                 continue;
2663
2664             String replacedString = plainText(rangeToReplace.ptr());
2665             const bool existingMarkersPermitReplacement = m_alternativeTextController->processMarkersOnTextToBeReplacedByResult(results[i], rangeToReplace, replacedString);
2666             if (!existingMarkersPermitReplacement)
2667                 continue;
2668
2669             if (shouldShowCorrectionPanel) {
2670                 if (resultEndLocation == spellingRangeEndOffset) {
2671                     // We only show the correction panel on the last word.
2672                     m_alternativeTextController->show(rangeToReplace, replacement);
2673                     break;
2674                 }
2675                 // If this function is called for showing correction panel, we ignore other correction or replacement.
2676                 continue;
2677             }
2678
2679             VisibleSelection selectionToReplace(rangeToReplace, DOWNSTREAM);
2680             if (selectionToReplace != m_frame.selection().selection()) {
2681                 if (!m_frame.selection().shouldChangeSelection(selectionToReplace))
2682                     continue;
2683             }
2684
2685             if (resultType == TextCheckingTypeLink) {
2686                 m_frame.selection().setSelection(selectionToReplace);
2687                 selectionChanged = true;
2688                 restoreSelectionAfterChange = false;
2689                 if (canEditRichly())
2690                     CreateLinkCommand::create(document(), replacement)->apply();
2691             } else if (canEdit() && shouldInsertText(replacement, rangeToReplace.ptr(), EditorInsertAction::Typed)) {
2692                 correctSpellcheckingPreservingTextCheckingParagraph(paragraph, rangeToReplace, replacement, resultLocation, resultLength);
2693
2694                 if (AXObjectCache* cache = document().existingAXObjectCache()) {
2695                     if (Element* root = m_frame.selection().selection().rootEditableElement())
2696                         cache->postNotification(root, AXObjectCache::AXAutocorrectionOccured);
2697                 }
2698
2699                 // Skip all other results for the replaced text.
2700                 while (i + 1 < results.size() && results[i + 1].location + offsetDueToReplacement <= resultLocation)
2701                     i++;
2702
2703                 selectionChanged = true;
2704                 offsetDueToReplacement += replacement.length() - resultLength;
2705                 if (resultLocation < selectionOffset)
2706                     selectionOffset += replacement.length() - resultLength;
2707
2708                 if (resultType == TextCheckingTypeCorrection) {
2709                     auto replacementRange = paragraph.subrange(resultLocation, replacement.length());
2710                     m_alternativeTextController->recordAutocorrectionResponse(AutocorrectionResponse::Accepted, replacedString, replacementRange.ptr());
2711
2712                     // Add a marker so that corrections can easily be undone and won't be re-corrected.
2713                     m_alternativeTextController->markCorrection(replacementRange, replacedString);
2714                 }
2715             }
2716         }
2717     }
2718
2719     if (selectionChanged) {
2720         TextCheckingParagraph extendedParagraph(WTFMove(paragraph));
2721         // Restore the caret position if we have made any replacements
2722         extendedParagraph.expandRangeToNextEnd();
2723         if (restoreSelectionAfterChange && selectionOffset >= 0 && selectionOffset <= extendedParagraph.rangeLength()) {
2724             auto selectionRange = extendedParagraph.subrange(0, selectionOffset);
2725             m_frame.selection().moveTo(selectionRange->endPosition(), DOWNSTREAM);
2726             if (adjustSelectionForParagraphBoundaries)
2727                 m_frame.selection().modify(FrameSelection::AlterationMove, DirectionForward, CharacterGranularity);
2728         } else {
2729             // If this fails for any reason, the fallback is to go one position beyond the last replacement
2730             m_frame.selection().moveTo(m_frame.selection().selection().end());
2731             m_frame.selection().modify(FrameSelection::AlterationMove, DirectionForward, CharacterGranularity);
2732         }
2733     }
2734 }
2735
2736 void Editor::changeBackToReplacedString(const String& replacedString)
2737 {
2738 #if !PLATFORM(IOS)
2739     ASSERT(unifiedTextCheckerEnabled());
2740
2741     if (replacedString.isEmpty())
2742         return;
2743
2744     RefPtr<Range> selection = selectedRange();
2745     if (!shouldInsertText(replacedString, selection.get(), EditorInsertAction::Pasted))
2746         return;
2747     
2748     m_alternativeTextController->recordAutocorrectionResponse(AutocorrectionResponse::Reverted, replacedString, selection.get());
2749     TextCheckingParagraph paragraph(*selection);
2750     replaceSelectionWithText(replacedString, false, false, EditActionInsert);
2751     auto changedRange = paragraph.subrange(paragraph.checkingStart(), replacedString.length());
2752     changedRange->startContainer().document().markers().addMarker(changedRange.ptr(), DocumentMarker::Replacement, String());
2753     m_alternativeTextController->markReversed(changedRange);
2754 #else
2755     ASSERT_NOT_REACHED();
2756     UNUSED_PARAM(replacedString);
2757 #endif // !PLATFORM(IOS)
2758 }
2759
2760
2761 void Editor::markMisspellingsAndBadGrammar(const VisibleSelection& spellingSelection, bool markGrammar, const VisibleSelection& grammarSelection)
2762 {
2763     if (unifiedTextCheckerEnabled()) {
2764         if (!isContinuousSpellCheckingEnabled())
2765             return;
2766
2767         // markMisspellingsAndBadGrammar() is triggered by selection change, in which case we check spelling and grammar, but don't autocorrect misspellings.
2768         TextCheckingTypeMask textCheckingOptions = TextCheckingTypeSpelling;
2769         if (markGrammar && isGrammarCheckingEnabled())
2770             textCheckingOptions |= TextCheckingTypeGrammar;
2771         markAllMisspellingsAndBadGrammarInRanges(textCheckingOptions, spellingSelection.toNormalizedRange().get(), grammarSelection.toNormalizedRange().get());
2772         return;
2773     }
2774
2775     RefPtr<Range> firstMisspellingRange;
2776     markMisspellings(spellingSelection, firstMisspellingRange);
2777     if (markGrammar)
2778         markBadGrammar(grammarSelection);
2779 }
2780
2781 void Editor::unappliedSpellCorrection(const VisibleSelection& selectionOfCorrected, const String& corrected, const String& correction)
2782 {
2783     m_alternativeTextController->respondToUnappliedSpellCorrection(selectionOfCorrected, corrected, correction);
2784 }
2785
2786 void Editor::updateMarkersForWordsAffectedByEditing(bool doNotRemoveIfSelectionAtWordBoundary)
2787 {
2788     if (!document().markers().hasMarkers())
2789         return;
2790
2791     if (!m_alternativeTextController->shouldRemoveMarkersUponEditing() && (!textChecker() || textChecker()->shouldEraseMarkersAfterChangeSelection(TextCheckingTypeSpelling)))
2792         return;
2793
2794     // We want to remove the markers from a word if an editing command will change the word. This can happen in one of
2795     // several scenarios:
2796     // 1. Insert in the middle of a word.
2797     // 2. Appending non whitespace at the beginning of word.
2798     // 3. Appending non whitespace at the end of word.
2799     // Note that, appending only whitespaces at the beginning or end of word won't change the word, so we don't need to
2800     // remove the markers on that word.
2801     // Of course, if current selection is a range, we potentially will edit two words that fall on the boundaries of
2802     // selection, and remove words between the selection boundaries.
2803     //
2804     VisiblePosition startOfSelection = m_frame.selection().selection().start();
2805     VisiblePosition endOfSelection = m_frame.selection().selection().end();
2806     if (startOfSelection.isNull())
2807         return;
2808     // First word is the word that ends after or on the start of selection.
2809     VisiblePosition startOfFirstWord = startOfWord(startOfSelection, LeftWordIfOnBoundary);
2810     VisiblePosition endOfFirstWord = endOfWord(startOfSelection, LeftWordIfOnBoundary);
2811     // Last word is the word that begins before or on the end of selection
2812     VisiblePosition startOfLastWord = startOfWord(endOfSelection, RightWordIfOnBoundary);
2813     VisiblePosition endOfLastWord = endOfWord(endOfSelection, RightWordIfOnBoundary);
2814
2815     if (startOfFirstWord.isNull()) {
2816         startOfFirstWord = startOfWord(startOfSelection, RightWordIfOnBoundary);
2817         endOfFirstWord = endOfWord(startOfSelection, RightWordIfOnBoundary);
2818     }
2819     
2820     if (endOfLastWord.isNull()) {
2821         startOfLastWord = startOfWord(endOfSelection, LeftWordIfOnBoundary);
2822         endOfLastWord = endOfWord(endOfSelection, LeftWordIfOnBoundary);
2823     }
2824
2825     // If doNotRemoveIfSelectionAtWordBoundary is true, and first word ends at the start of selection,
2826     // we choose next word as the first word.
2827     if (doNotRemoveIfSelectionAtWordBoundary && endOfFirstWord == startOfSelection) {
2828         startOfFirstWord = nextWordPosition(startOfFirstWord);
2829         endOfFirstWord = endOfWord(startOfFirstWord, RightWordIfOnBoundary);
2830         if (startOfFirstWord == endOfSelection)
2831             return;
2832     }
2833
2834     // If doNotRemoveIfSelectionAtWordBoundary is true, and last word begins at the end of selection,
2835     // we choose previous word as the last word.
2836     if (doNotRemoveIfSelectionAtWordBoundary && startOfLastWord == endOfSelection) {
2837         startOfLastWord = previousWordPosition(startOfLastWord);
2838         endOfLastWord = endOfWord(startOfLastWord, RightWordIfOnBoundary);
2839         if (endOfLastWord == startOfSelection)
2840             return;
2841     }
2842
2843     if (startOfFirstWord.isNull() || endOfFirstWord.isNull() || startOfLastWord.isNull() || endOfLastWord.isNull())
2844         return;
2845
2846     // Now we remove markers on everything between startOfFirstWord and endOfLastWord.
2847     // However, if an autocorrection change a single word to multiple words, we want to remove correction mark from all the
2848     // resulted words even we only edit one of them. For example, assuming autocorrection changes "avantgarde" to "avant
2849     // garde", we will have CorrectionIndicator marker on both words and on the whitespace between them. If we then edit garde,
2850     // we would like to remove the marker from word "avant" and whitespace as well. So we need to get the continous range of
2851     // of marker that contains the word in question, and remove marker on that whole range.
2852     auto wordRange = Range::create(document(), startOfFirstWord.deepEquivalent(), endOfLastWord.deepEquivalent());
2853
2854     Vector<RenderedDocumentMarker*> markers = document().markers().markersInRange(wordRange, DocumentMarker::DictationAlternatives);
2855     for (auto* marker : markers)
2856         m_alternativeTextController->removeDictationAlternativesForMarker(*marker);
2857
2858     OptionSet<DocumentMarker::MarkerType> markerTypesToRemove {
2859         DocumentMarker::CorrectionIndicator,
2860         DocumentMarker::DictationAlternatives,
2861         DocumentMarker::SpellCheckingExemption,
2862         DocumentMarker::Spelling,
2863 #if !PLATFORM(IOS)
2864         DocumentMarker::Grammar,
2865 #endif
2866     };
2867     document().markers().removeMarkers(wordRange.ptr(), markerTypesToRemove, DocumentMarkerController::RemovePartiallyOverlappingMarker);
2868     document().markers().clearDescriptionOnMarkersIntersectingRange(wordRange, DocumentMarker::Replacement);
2869 }
2870
2871 void Editor::deletedAutocorrectionAtPosition(const Position& position, const String& originalString)
2872 {
2873     m_alternativeTextController->deletedAutocorrectionAtPosition(position, originalString);
2874 }
2875
2876 RefPtr<Range> Editor::rangeForPoint(const IntPoint& windowPoint)
2877 {
2878     Document* document = m_frame.documentAtPoint(windowPoint);
2879     if (!document)
2880         return nullptr;
2881     
2882     Frame* frame = document->frame();
2883     ASSERT(frame);
2884     FrameView* frameView = frame->view();
2885     if (!frameView)
2886         return nullptr;
2887     IntPoint framePoint = frameView->windowToContents(windowPoint);
2888     VisibleSelection selection(frame->visiblePositionForPoint(framePoint));
2889
2890     return selection.toNormalizedRange();
2891 }
2892
2893 void Editor::revealSelectionAfterEditingOperation(const ScrollAlignment& alignment, RevealExtentOption revealExtentOption)
2894 {
2895     if (m_ignoreSelectionChanges)
2896         return;
2897
2898 #if PLATFORM(IOS)
2899     SelectionRevealMode revealMode = SelectionRevealMode::RevealUpToMainFrame;
2900 #else
2901     SelectionRevealMode revealMode = SelectionRevealMode::Reveal;
2902 #endif
2903
2904     m_frame.selection().revealSelection(revealMode, alignment, revealExtentOption);
2905 }
2906
2907 void Editor::setIgnoreSelectionChanges(bool ignore, RevealSelection shouldRevealExistingSelection)
2908 {
2909     if (m_ignoreSelectionChanges == ignore)
2910         return;
2911
2912     m_ignoreSelectionChanges = ignore;
2913 #if PLATFORM(IOS)
2914     // FIXME: Should suppress selection change notifications during a composition change <https://webkit.org/b/38830> 
2915     if (!ignore)
2916         respondToChangedSelection(m_frame.selection().selection(), 0);
2917 #endif
2918     if (!ignore && shouldRevealExistingSelection == RevealSelection::Yes)
2919         revealSelectionAfterEditingOperation(ScrollAlignment::alignToEdgeIfNeeded, RevealExtent);
2920 }
2921
2922 RefPtr<Range> Editor::compositionRange() const
2923 {
2924     if (!m_compositionNode)
2925         return nullptr;
2926     unsigned length = m_compositionNode->length();
2927     unsigned start = std::min(m_compositionStart, length);
2928     unsigned end = std::min(std::max(start, m_compositionEnd), length);
2929     if (start >= end)
2930         return nullptr;
2931     return Range::create(m_compositionNode->document(), m_compositionNode.get(), start, m_compositionNode.get(), end);
2932 }
2933
2934 bool Editor::getCompositionSelection(unsigned& selectionStart, unsigned& selectionEnd) const
2935 {
2936     if (!m_compositionNode)
2937         return false;
2938     const VisibleSelection& selection = m_frame.selection().selection();
2939     Position start = selection.start();
2940     if (start.deprecatedNode() != m_compositionNode)
2941         return false;
2942     Position end = selection.end();
2943     if (end.deprecatedNode() != m_compositionNode)
2944         return false;
2945
2946     if (static_cast<unsigned>(start.deprecatedEditingOffset()) < m_compositionStart)
2947         return false;
2948     if (static_cast<unsigned>(end.deprecatedEditingOffset()) > m_compositionEnd)
2949         return false;
2950
2951     selectionStart = start.deprecatedEditingOffset() - m_compositionStart;
2952     selectionEnd = start.deprecatedEditingOffset() - m_compositionEnd;
2953     return true;
2954 }
2955
2956 void Editor::transpose()
2957 {
2958     if (!canEdit())
2959         return;
2960
2961     VisibleSelection selection = m_frame.selection().selection();
2962     if (!selection.isCaret())
2963         return;
2964
2965     // Make a selection that goes back one character and forward two characters.
2966     VisiblePosition caret = selection.visibleStart();
2967     VisiblePosition next = isEndOfParagraph(caret) ? caret : caret.next();
2968     VisiblePosition previous = next.previous();
2969     if (next == previous)
2970         return;
2971     previous = previous.previous();
2972     if (!inSameParagraph(next, previous))
2973         return;
2974     RefPtr<Range> range = makeRange(previous, next);
2975     if (!range)
2976         return;
2977     VisibleSelection newSelection(*range, DOWNSTREAM);
2978
2979     // Transpose the two characters.
2980     String text = plainText(range.get());
2981     if (text.length() != 2)
2982         return;
2983     String transposed = text.right(1) + text.left(1);
2984
2985     // Select the two characters.
2986     if (newSelection != m_frame.selection().selection()) {
2987         if (!m_frame.selection().shouldChangeSelection(newSelection))
2988             return;
2989         m_frame.selection().setSelection(newSelection);
2990     }
2991
2992     // Insert the transposed characters.
2993     if (!shouldInsertText(transposed, range.get(), EditorInsertAction::Typed))
2994         return;
2995     replaceSelectionWithText(transposed, false, false, EditActionInsert);
2996 }
2997
2998 void Editor::addRangeToKillRing(const Range& range, KillRingInsertionMode mode)
2999 {
3000     addTextToKillRing(plainText(&range), mode);
3001 }
3002
3003 void Editor::addTextToKillRing(const String& text, KillRingInsertionMode mode)
3004 {
3005     if (m_shouldStartNewKillRingSequence)
3006         killRing().startNewSequence();
3007
3008     m_shouldStartNewKillRingSequence = false;
3009
3010     // If the kill was from a backwards motion, prepend to the kill ring.
3011     // This will ensure that alternating forward and backward kills will
3012     // build up the original string in the kill ring without permuting it.
3013     switch (mode) {
3014     case KillRingInsertionMode::PrependText:
3015         killRing().prepend(text);
3016         break;
3017     case KillRingInsertionMode::AppendText:
3018         killRing().append(text);
3019         break;
3020     }
3021 }
3022
3023 void Editor::startAlternativeTextUITimer()
3024 {
3025     m_alternativeTextController->startAlternativeTextUITimer(AlternativeTextTypeCorrection);
3026 }
3027
3028 void Editor::handleAlternativeTextUIResult(const String& correction)
3029 {
3030     m_alternativeTextController->handleAlternativeTextUIResult(correction);
3031 }
3032
3033
3034 void Editor::dismissCorrectionPanelAsIgnored()
3035 {
3036     m_alternativeTextController->dismiss(ReasonForDismissingAlternativeTextIgnored);
3037 }
3038
3039 void Editor::changeSelectionAfterCommand(const VisibleSelection& newSelection, FrameSelection::SetSelectionOptions options)
3040 {
3041     Ref<Frame> protection(m_frame);
3042
3043     // If the new selection is orphaned, then don't update the selection.
3044     if (newSelection.start().isOrphan() || newSelection.end().isOrphan())
3045         return;
3046
3047     // If there is no selection change, don't bother sending shouldChangeSelection, but still call setSelection,
3048     // because there is work that it must do in this situation.
3049     // The old selection can be invalid here and calling shouldChangeSelection can produce some strange calls.
3050     // See <rdar://problem/5729315> Some shouldChangeSelectedDOMRange contain Ranges for selections that are no longer valid
3051     bool selectionDidNotChangeDOMPosition = newSelection == m_frame.selection().selection();
3052     if (selectionDidNotChangeDOMPosition || m_frame.selection().shouldChangeSelection(newSelection))
3053         m_frame.selection().setSelection(newSelection, options);
3054
3055     // Some editing operations change the selection visually without affecting its position within the DOM.
3056     // For example when you press return in the following (the caret is marked by ^):
3057     // <div contentEditable="true"><div>^Hello</div></div>
3058     // WebCore inserts <div><br></div> *before* the current block, which correctly moves the paragraph down but which doesn't
3059     // change the caret's DOM position (["hello", 0]). In these situations the above FrameSelection::setSelection call
3060     // does not call EditorClient::respondToChangedSelection(), which, on the Mac, sends selection change notifications and
3061     // starts a new kill ring sequence, but we want to do these things (matches AppKit).
3062 #if PLATFORM(IOS)
3063     // FIXME: Should suppress selection change notifications during a composition change <https://webkit.org/b/38830>
3064     if (m_ignoreSelectionChanges)
3065         return;
3066 #endif
3067     if (selectionDidNotChangeDOMPosition && client())
3068         client()->respondToChangedSelection(&m_frame);
3069 }
3070
3071 String Editor::selectedText() const
3072 {
3073     return selectedText(TextIteratorDefaultBehavior);
3074 }
3075
3076 String Editor::selectedTextForDataTransfer() const
3077 {
3078     return selectedText(TextIteratorEmitsImageAltText);
3079 }
3080
3081 String Editor::selectedText(TextIteratorBehavior behavior) const
3082 {
3083     // We remove '\0' characters because they are not visibly rendered to the user.
3084     return plainText(m_frame.selection().toNormalizedRange().get(), behavior).replaceWithLiteral('\0', "");
3085 }
3086
3087 static inline void collapseCaretWidth(IntRect& rect)
3088 {
3089     // FIXME: Width adjustment doesn't work for rotated text.
3090     if (rect.width() == caretWidth)
3091         rect.setWidth(0);
3092     else if (rect.height() == caretWidth)
3093         rect.setHeight(0);
3094 }
3095
3096 IntRect Editor::firstRectForRange(Range* range) const
3097 {
3098     VisiblePosition startVisiblePosition(range->startPosition(), DOWNSTREAM);
3099
3100     if (range->collapsed()) {
3101         // FIXME: Getting caret rect and removing caret width is a very roundabout way to get collapsed range location.
3102         // In particular, width adjustment doesn't work for rotated text.
3103         IntRect startCaretRect = RenderedPosition(startVisiblePosition).absoluteRect();
3104         collapseCaretWidth(startCaretRect);
3105         return startCaretRect;
3106     }
3107
3108     VisiblePosition endVisiblePosition(range->endPosition(), UPSTREAM);
3109
3110     if (inSameLine(startVisiblePosition, endVisiblePosition))
3111         return enclosingIntRect(RenderObject::absoluteBoundingBoxRectForRange(range));
3112
3113     LayoutUnit extraWidthToEndOfLine = 0;
3114     IntRect startCaretRect = RenderedPosition(startVisiblePosition).absoluteRect(&extraWidthToEndOfLine);
3115     if (startCaretRect == IntRect())
3116         return IntRect();
3117
3118     // When start and end aren't on the same line, we want to go from start to the end of its line.
3119     bool textIsHorizontal = startCaretRect.width() == caretWidth;
3120     return textIsHorizontal ?
3121         IntRect(startCaretRect.x(),
3122             startCaretRect.y(),
3123             startCaretRect.width() + extraWidthToEndOfLine,
3124             startCaretRect.height()) :
3125         IntRect(startCaretRect.x(),
3126             startCaretRect.y(),
3127             startCaretRect.width(),
3128             startCaretRect.height() + extraWidthToEndOfLine);
3129 }
3130
3131 bool Editor::shouldChangeSelection(const VisibleSelection& oldSelection, const VisibleSelection& newSelection, EAffinity affinity, bool stillSelecting) const
3132 {
3133 #if PLATFORM(IOS)
3134     if (m_frame.selectionChangeCallbacksDisabled())
3135         return true;
3136 #endif
3137     return client() && client()->shouldChangeSelectedRange(oldSelection.toNormalizedRange().get(), newSelection.toNormalizedRange().get(), affinity, stillSelecting);
3138 }
3139
3140 void Editor::computeAndSetTypingStyle(EditingStyle& style, EditAction editingAction)
3141 {
3142     if (style.isEmpty()) {
3143         m_frame.selection().clearTypingStyle();
3144         return;
3145     }
3146
3147     // Calculate the current typing style.
3148     RefPtr<EditingStyle> typingStyle;
3149     if (auto existingTypingStyle = m_frame.selection().typingStyle())
3150         typingStyle = existingTypingStyle->copy();
3151     else
3152         typingStyle = EditingStyle::create();
3153     typingStyle->overrideTypingStyleAt(style, m_frame.selection().selection().visibleStart().deepEquivalent());
3154
3155     // Handle block styles, substracting these from the typing style.
3156     RefPtr<EditingStyle> blockStyle = typingStyle->extractAndRemoveBlockProperties();
3157     if (!blockStyle->isEmpty())
3158         ApplyStyleCommand::create(document(), blockStyle.get(), editingAction)->apply();
3159
3160     // Set the remaining style as the typing style.
3161     m_frame.selection().setTypingStyle(WTFMove(typingStyle));
3162 }
3163
3164 void Editor::computeAndSetTypingStyle(StyleProperties& properties, EditAction editingAction)
3165 {
3166     return computeAndSetTypingStyle(EditingStyle::create(&properties), editingAction);
3167 }
3168
3169 void Editor::textFieldDidBeginEditing(Element* e)
3170 {
3171     if (client())
3172         client()->textFieldDidBeginEditing(e);
3173 }
3174
3175 void Editor::textFieldDidEndEditing(Element* e)
3176 {
3177     dismissCorrectionPanelAsIgnored();
3178     if (client())
3179         client()->textFieldDidEndEditing(e);
3180 }
3181
3182 void Editor::textDidChangeInTextField(Element* e)
3183 {
3184     if (client())
3185         client()->textDidChangeInTextField(e);
3186 }
3187
3188 bool Editor::doTextFieldCommandFromEvent(Element* e, KeyboardEvent* ke)
3189 {
3190     if (client())
3191         return client()->doTextFieldCommandFromEvent(e, ke);
3192
3193     return false;
3194 }
3195
3196 void Editor::textWillBeDeletedInTextField(Element* input)
3197 {
3198     if (client())
3199         client()->textWillBeDeletedInTextField(input);
3200 }
3201
3202 void Editor::textDidChangeInTextArea(Element* e)
3203 {
3204     if (client())
3205         client()->textDidChangeInTextArea(e);
3206 }
3207
3208 void Editor::applyEditingStyleToBodyElement() const
3209 {
3210     auto collection = document().getElementsByTagName(HTMLNames::bodyTag.localName());
3211     unsigned length = collection->length();
3212     for (unsigned i = 0; i < length; ++i)
3213         applyEditingStyleToElement(collection->item(i));
3214 }
3215
3216 void Editor::applyEditingStyleToElement(Element* element) const
3217 {
3218     ASSERT(!element || is<StyledElement>(*element));
3219     if (!is<StyledElement>(element))
3220         return;
3221
3222     // Mutate using the CSSOM wrapper so we get the same event behavior as a script.
3223     auto& style = downcast<StyledElement>(*element).cssomStyle();
3224     style.setPropertyInternal(CSSPropertyWordWrap, "break-word", false);
3225     style.setPropertyInternal(CSSPropertyWebkitNbspMode, "space", false);
3226     style.setPropertyInternal(CSSPropertyLineBreak, "after-white-space", false);
3227 }
3228
3229 bool Editor::findString(const String& target, FindOptions options)
3230 {
3231     Ref<Frame> protection(m_frame);
3232
3233     VisibleSelection selection = m_frame.selection().selection();
3234
3235     RefPtr<Range> resultRange = rangeOfString(target, selection.firstRange().get(), options);
3236
3237     if (!resultRange)
3238         return false;
3239
3240     m_frame.selection().setSelection(VisibleSelection(*resultRange, DOWNSTREAM));
3241
3242     if (!(options & DoNotRevealSelection))
3243         m_frame.selection().revealSelection();
3244
3245     return true;
3246 }
3247
3248 RefPtr<Range> Editor::rangeOfString(const String& target, Range* referenceRange, FindOptions options)
3249 {
3250     if (target.isEmpty())
3251         return nullptr;
3252
3253     // Start from an edge of the reference range, if there's a reference range that's not in shadow content. Which edge
3254     // is used depends on whether we're searching forward or backward, and whether startInSelection is set.
3255     RefPtr<Range> searchRange(rangeOfContents(document()));
3256
3257     bool forward = !(options & Backwards);
3258     bool startInReferenceRange = referenceRange && (options & StartInSelection);
3259     if (referenceRange) {
3260         if (forward)
3261             searchRange->setStart(startInReferenceRange ? referenceRange->startPosition() : referenceRange->endPosition());
3262         else
3263             searchRange->setEnd(startInReferenceRange ? referenceRange->endPosition() : referenceRange->startPosition());
3264     }
3265
3266     RefPtr<ShadowRoot> shadowTreeRoot = referenceRange ? referenceRange->startContainer().containingShadowRoot() : nullptr;
3267     if (shadowTreeRoot) {
3268         if (forward)
3269             searchRange->setEnd(*shadowTreeRoot, shadowTreeRoot->countChildNodes());
3270         else
3271             searchRange->setStart(*shadowTreeRoot, 0);
3272     }
3273
3274     RefPtr<Range> resultRange = findPlainText(*searchRange, target, options);
3275     // If we started in the reference range and the found range exactly matches the reference range, find again.
3276     // Build a selection with the found range to remove collapsed whitespace.
3277     // Compare ranges instead of selection objects to ignore the way that the current selection was made.
3278     if (startInReferenceRange && areRangesEqual(VisibleSelection(*resultRange).toNormalizedRange().get(), referenceRange)) {
3279         searchRange = rangeOfContents(document());
3280         if (forward)
3281             searchRange->setStart(referenceRange->endPosition());
3282         else
3283             searchRange->setEnd(referenceRange->startPosition());
3284
3285         if (shadowTreeRoot) {
3286             if (forward)
3287                 searchRange->setEnd(*shadowTreeRoot, shadowTreeRoot->countChildNodes());
3288             else
3289                 searchRange->setStart(*shadowTreeRoot, 0);
3290         }
3291
3292         resultRange = findPlainText(*searchRange, target, options);
3293     }
3294
3295     // If nothing was found in the shadow tree, search in main content following the shadow tree.
3296     if (resultRange->collapsed() && shadowTreeRoot) {
3297         searchRange = rangeOfContents(document());
3298         if (shadowTreeRoot->shadowHost()) {
3299             if (forward)
3300                 searchRange->setStartAfter(*shadowTreeRoot->shadowHost());
3301             else
3302                 searchRange->setEndBefore(*shadowTreeRoot->shadowHost());
3303         }
3304
3305         resultRange = findPlainText(*searchRange, target, options);
3306     }
3307
3308     // If we didn't find anything and we're wrapping, search again in the entire document (this will
3309     // redundantly re-search the area already searched in some cases).
3310     if (resultRange->collapsed() && options & WrapAround) {
3311         searchRange = rangeOfContents(document());
3312         resultRange = findPlainText(*searchRange, target, options);
3313         // We used to return false here if we ended up with the same range that we started with
3314         // (e.g., the reference range was already the only instance of this text). But we decided that
3315         // this should be a success case instead, so we'll just fall through in that case.
3316     }
3317
3318     return resultRange->collapsed() ? nullptr : resultRange;
3319 }
3320
3321 static bool isFrameInRange(Frame& frame, Range& range)
3322 {
3323     for (auto* ownerElement = frame.ownerElement(); ownerElement; ownerElement = ownerElement->document().ownerElement()) {
3324         if (&ownerElement->document() == &range.ownerDocument()) {
3325             auto result = range.intersectsNode(*ownerElement);
3326             return !result.hasException() && result.releaseReturnValue();
3327         }
3328     }
3329     return false;
3330 }
3331
3332 unsigned Editor::countMatchesForText(const String& target, Range* range, FindOptions options, unsigned limit, bool markMatches, Vector<RefPtr<Range>>* matches)
3333 {
3334     if (target.isEmpty())
3335         return 0;
3336
3337     RefPtr<Range> searchRange;
3338     if (range) {
3339         if (&range->ownerDocument() == &document())
3340             searchRange = range;
3341         else if (!isFrameInRange(m_frame, *range))
3342             return 0;
3343     }
3344     if (!searchRange)
3345         searchRange = rangeOfContents(document());
3346
3347     Node& originalEndContainer = searchRange->endContainer();
3348     int originalEndOffset = searchRange->endOffset();
3349
3350     unsigned matchCount = 0;
3351     do {
3352         RefPtr<Range> resultRange(findPlainText(*searchRange, target, options & ~Backwards));
3353         if (resultRange->collapsed()) {
3354             if (!resultRange->startContainer().isInShadowTree())
3355                 break;
3356
3357             searchRange->setStartAfter(*resultRange->startContainer().shadowHost());
3358             searchRange->setEnd(originalEndContainer, originalEndOffset);
3359             continue;
3360         }
3361
3362         ++matchCount;
3363         if (matches)
3364             matches->append(resultRange);
3365         
3366         if (markMatches)
3367             document().markers().addMarker(resultRange.get(), DocumentMarker::TextMatch);
3368
3369         // Stop looking if we hit the specified limit. A limit of 0 means no limit.
3370         if (limit > 0 && matchCount >= limit)
3371             break;
3372
3373         // Set the new start for the search range to be the end of the previous
3374         // result range. There is no need to use a VisiblePosition here,
3375         // since findPlainText will use a TextIterator to go over the visible
3376         // text nodes. 
3377         searchRange->setStart(resultRange->endContainer(), resultRange->endOffset());
3378
3379         Node* shadowTreeRoot = searchRange->shadowRoot();
3380         if (searchRange->collapsed() && shadowTreeRoot)
3381             searchRange->setEnd(*shadowTreeRoot, shadowTreeRoot->countChildNodes());
3382     } while (true);
3383
3384     return matchCount;
3385 }
3386
3387 void Editor::setMarkedTextMatchesAreHighlighted(bool flag)
3388 {
3389     if (flag == m_areMarkedTextMatchesHighlighted)
3390         return;
3391
3392     m_areMarkedTextMatchesHighlighted = flag;
3393     document().markers().repaintMarkers(DocumentMarker::TextMatch);
3394 }
3395
3396 #if !PLATFORM(MAC)
3397 void Editor::selectionWillChange()
3398 {
3399 }
3400 #endif
3401
3402 void Editor::respondToChangedSelection(const VisibleSelection&, FrameSelection::SetSelectionOptions options)
3403 {
3404 #if PLATFORM(IOS)
3405     // FIXME: Should suppress selection change notifications during a composition change <https://webkit.org/b/38830> 
3406     if (m_ignoreSelectionChanges)
3407         return;
3408 #endif
3409
3410     if (client())
3411         client()->respondToChangedSelection(&m_frame);
3412
3413 #if ENABLE(TELEPHONE_NUMBER_DETECTION) && !PLATFORM(IOS)
3414     if (shouldDetectTelephoneNumbers())
3415         m_telephoneNumberDetectionUpdateTimer.startOneShot(0_s);
3416 #endif
3417
3418     setStartNewKillRingSequence(true);
3419
3420     if (m_editorUIUpdateTimer.isActive())
3421         return;
3422
3423     // Don't check spelling and grammar if the change of selection is triggered by spelling correction itself.
3424     m_editorUIUpdateTimerShouldCheckSpellingAndGrammar = options & FrameSelection::CloseTyping
3425         && !(options & FrameSelection::SpellCorrectionTriggered);
3426     m_editorUIUpdateTimerWasTriggeredByDictation = options & FrameSelection::DictationTriggered;
3427     m_editorUIUpdateTimer.startOneShot(0_s);
3428 }
3429
3430 #if ENABLE(TELEPHONE_NUMBER_DETECTION) && !PLATFORM(IOS)
3431
3432 bool Editor::shouldDetectTelephoneNumbers()
3433 {
3434     if (!m_frame.document())
3435         return false;
3436     return document().isTelephoneNumberParsingEnabled() && TelephoneNumberDetector::isSupported();
3437 }
3438
3439 void Editor::scanSelectionForTelephoneNumbers()
3440 {
3441     if (!shouldDetectTelephoneNumbers() || !client())
3442         return;
3443
3444     m_detectedTelephoneNumberRanges.clear();
3445
3446     Vector<RefPtr<Range>> markedRanges;
3447
3448     FrameSelection& frameSelection = m_frame.selection();
3449     if (!frameSelection.isRange()) {
3450         m_frame.mainFrame().servicesOverlayController().selectedTelephoneNumberRangesChanged();
3451         return;
3452     }
3453     RefPtr<Range> selectedRange = frameSelection.toNormalizedRange();
3454
3455     // Extend the range a few characters in each direction to detect incompletely selected phone numbers.
3456     static const int charactersToExtend = 15;
3457     const VisibleSelection& visibleSelection = frameSelection.selection();
3458     Position start = visibleSelection.start();
3459     Position end = visibleSelection.end();
3460     for (int i = 0; i < charactersToExtend; ++i) {
3461         start = start.previous(Character);
3462         end = end.next(Character);
3463     }
3464
3465     FrameSelection extendedSelection;
3466     extendedSelection.setStart(start);
3467     extendedSelection.setEnd(end);
3468     RefPtr<Range> extendedRange = extendedSelection.toNormalizedRange();
3469
3470     if (!extendedRange) {
3471         m_frame.mainFrame().servicesOverlayController().selectedTelephoneNumberRangesChanged();
3472         return;
3473     }
3474
3475     scanRangeForTelephoneNumbers(*extendedRange, extendedRange->text(), markedRanges);
3476
3477     // Only consider ranges with a detected telephone number if they overlap with the actual selection range.
3478     for (auto& range : markedRanges) {
3479         if (rangesOverlap(range.get(), selectedRange.get()))
3480             m_detectedTelephoneNumberRanges.append(range);
3481     }
3482
3483     m_frame.mainFrame().servicesOverlayController().selectedTelephoneNumberRangesChanged();
3484 }
3485
3486 void Editor::scanRangeForTelephoneNumbers(Range& range, const StringView& stringView, Vector<RefPtr<Range>>& markedRanges)
3487 {
3488     // Don't scan for phone numbers inside editable regions.
3489     Node& startNode = range.startContainer();
3490     if (startNode.hasEditableStyle())
3491         return;
3492
3493     // relativeStartPosition and relativeEndPosition are the endpoints of the phone number range,
3494     // relative to the scannerPosition
3495     unsigned length = stringView.length();
3496     unsigned scannerPosition = 0;
3497     int relativeStartPosition = 0;
3498     int relativeEndPosition = 0;
3499
3500     auto characters = stringView.upconvertedCharacters();
3501
3502     while (scannerPosition < length && TelephoneNumberDetector::find(&characters[scannerPosition], length - scannerPosition, &relativeStartPosition, &relativeEndPosition)) {
3503         // The convention in the Data Detectors framework is that the end position is the first character NOT in the phone number
3504         // (that is, the length of the range is relativeEndPosition - relativeStartPosition). So subtract 1 to get the same
3505         // convention as the old WebCore phone number parser (so that the rest of the code is still valid if we want to go back
3506         // to the old parser).
3507         --relativeEndPosition;
3508
3509         ASSERT(scannerPosition + relativeEndPosition < length);
3510
3511         unsigned subrangeOffset = scannerPosition + relativeStartPosition;
3512         unsigned subrangeLength = relativeEndPosition - relativeStartPosition + 1;
3513
3514         RefPtr<Range> subrange = TextIterator::subrange(range, subrangeOffset, subrangeLength);
3515
3516         markedRanges.append(subrange);
3517         range.ownerDocument().markers().addMarker(subrange.get(), DocumentMarker::TelephoneNumber);
3518
3519         scannerPosition += relativeEndPosition + 1;
3520     }
3521 }
3522
3523 #endif // ENABLE(TELEPHONE_NUMBER_DETECTION) && !PLATFORM(IOS)
3524
3525 void Editor::updateEditorUINowIfScheduled()
3526 {
3527     if (!m_editorUIUpdateTimer.isActive())
3528         return;
3529     m_editorUIUpdateTimer.stop();
3530     editorUIUpdateTimerFired();
3531 }
3532
3533 void Editor::editorUIUpdateTimerFired()
3534 {
3535     VisibleSelection oldSelection = m_oldSelectionForEditorUIUpdate;
3536
3537     m_alternativeTextController->stopPendingCorrection(oldSelection);
3538     
3539     bool isContinuousSpellCheckingEnabled = this->isContinuousSpellCheckingEnabled();
3540     bool isContinuousGrammarCheckingEnabled = isContinuousSpellCheckingEnabled && isGrammarCheckingEnabled();
3541     if (isContinuousSpellCheckingEnabled) {
3542         VisibleSelection newAdjacentWords;
3543         VisibleSelection newSelectedSentence;
3544         bool caretBrowsing = m_frame.settings().caretBrowsingEnabled();
3545         if (m_frame.selection().selection().isContentEditable() || caretBrowsing) {
3546             VisiblePosition newStart(m_frame.selection().selection().visibleStart());
3547 #if !PLATFORM(IOS)
3548             newAdjacentWords = VisibleSelection(startOfWord(newStart, LeftWordIfOnBoundary), endOfWord(newStart, RightWordIfOnBoundary));
3549 #else
3550             // If this bug gets fixed, this PLATFORM(IOS) code could be removed:
3551             // <rdar://problem/7259611> Word boundary code on&