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