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