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