diff options
Diffstat (limited to 'chromium/third_party/blink/renderer/core/editing')
184 files changed, 2482 insertions, 1747 deletions
diff --git a/chromium/third_party/blink/renderer/core/editing/caret_display_item_client_test.cc b/chromium/third_party/blink/renderer/core/editing/caret_display_item_client_test.cc index cbafb7631ff..a89d234d80d 100644 --- a/chromium/third_party/blink/renderer/core/editing/caret_display_item_client_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/caret_display_item_client_test.cc @@ -64,10 +64,12 @@ class CaretDisplayItemClientTest : public PaintAndRasterInvalidationTest { void UpdateAllLifecyclePhasesForCaretTest() { // Partial lifecycle updates should not affect caret paint invalidation. - GetDocument().View()->UpdateLifecycleToLayoutClean(); + GetDocument().View()->UpdateLifecycleToLayoutClean( + DocumentUpdateReason::kTest); UpdateAllLifecyclePhasesForTest(); // Partial lifecycle updates should not affect caret paint invalidation. - GetDocument().View()->UpdateLifecycleToLayoutClean(); + GetDocument().View()->UpdateLifecycleToLayoutClean( + DocumentUpdateReason::kTest); } }; @@ -86,7 +88,8 @@ TEST_P(CaretDisplayItemClientTest, CaretPaintInvalidation) { GetDocument().View()->SetTracksRasterInvalidations(true); GetDocument().body()->focus(); - GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint(); + GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint( + DocumentUpdateReason::kTest); EXPECT_FALSE(GetCaretDisplayItemClient().IsValid()); UpdateAllLifecyclePhasesForCaretTest(); @@ -110,7 +113,8 @@ TEST_P(CaretDisplayItemClientTest, CaretPaintInvalidation) { SelectionInDOMTree::Builder().Collapse(Position(text, 5)).Build()); EXPECT_TRUE(GetCaretDisplayItemClient().IsValid()); - GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint(); + GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint( + DocumentUpdateReason::kTest); EXPECT_FALSE(GetCaretDisplayItemClient().IsValid()); UpdateAllLifecyclePhasesForCaretTest(); @@ -138,7 +142,8 @@ TEST_P(CaretDisplayItemClientTest, CaretPaintInvalidation) { Selection().SetSelectionAndEndTyping(SelectionInDOMTree()); EXPECT_TRUE(GetCaretDisplayItemClient().IsValid()); - GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint(); + GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint( + DocumentUpdateReason::kTest); EXPECT_FALSE(GetCaretDisplayItemClient().IsValid()); UpdateAllLifecyclePhasesForCaretTest(); @@ -167,7 +172,8 @@ TEST_P(CaretDisplayItemClientTest, CaretMovesBetweenBlocks) { // Focus the body. GetDocument().body()->focus(); - GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint(); + GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint( + DocumentUpdateReason::kTest); EXPECT_FALSE(GetCaretDisplayItemClient().IsValid()); UpdateAllLifecyclePhasesForCaretTest(); @@ -188,7 +194,8 @@ TEST_P(CaretDisplayItemClientTest, CaretMovesBetweenBlocks) { .Build()); EXPECT_TRUE(GetCaretDisplayItemClient().IsValid()); - GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint(); + GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint( + DocumentUpdateReason::kTest); EXPECT_FALSE(GetCaretDisplayItemClient().IsValid()); UpdateAllLifecyclePhasesForCaretTest(); @@ -219,7 +226,8 @@ TEST_P(CaretDisplayItemClientTest, CaretMovesBetweenBlocks) { .Build()); EXPECT_TRUE(GetCaretDisplayItemClient().IsValid()); - GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint(); + GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint( + DocumentUpdateReason::kTest); EXPECT_FALSE(GetCaretDisplayItemClient().IsValid()); UpdateAllLifecyclePhasesForCaretTest(); @@ -256,7 +264,8 @@ TEST_P(CaretDisplayItemClientTest, UpdatePreviousLayoutBlock) { SelectionInDOMTree::Builder() .Collapse(Position(block_element2, 0)) .Build()); - GetDocument().View()->UpdateLifecycleToLayoutClean(); + GetDocument().View()->UpdateLifecycleToLayoutClean( + DocumentUpdateReason::kTest); EXPECT_TRUE(block2->ShouldPaintCursorCaret()); EXPECT_EQ(block2, CaretLayoutBlock()); EXPECT_FALSE(block1->ShouldPaintCursorCaret()); @@ -267,7 +276,8 @@ TEST_P(CaretDisplayItemClientTest, UpdatePreviousLayoutBlock) { SelectionInDOMTree::Builder() .Collapse(Position(block_element1, 0)) .Build()); - GetDocument().View()->UpdateLifecycleToLayoutClean(); + GetDocument().View()->UpdateLifecycleToLayoutClean( + DocumentUpdateReason::kTest); EXPECT_TRUE(block1->ShouldPaintCursorCaret()); EXPECT_EQ(block1, CaretLayoutBlock()); EXPECT_FALSE(block2->ShouldPaintCursorCaret()); @@ -279,7 +289,8 @@ TEST_P(CaretDisplayItemClientTest, UpdatePreviousLayoutBlock) { SelectionInDOMTree::Builder() .Collapse(Position(block_element2, 0)) .Build()); - GetDocument().View()->UpdateLifecycleToLayoutClean(); + GetDocument().View()->UpdateLifecycleToLayoutClean( + DocumentUpdateReason::kTest); EXPECT_TRUE(block2->ShouldPaintCursorCaret()); EXPECT_EQ(block2, CaretLayoutBlock()); EXPECT_FALSE(block1->ShouldPaintCursorCaret()); @@ -298,7 +309,8 @@ TEST_P(CaretDisplayItemClientTest, UpdatePreviousLayoutBlock) { UpdateAllLifecyclePhasesForCaretTest(); // Remove selection. Selection().SetSelectionAndEndTyping(SelectionInDOMTree()); - GetDocument().View()->UpdateLifecycleToLayoutClean(); + GetDocument().View()->UpdateLifecycleToLayoutClean( + DocumentUpdateReason::kTest); EXPECT_EQ(block1, PreviousCaretLayoutBlock()); } @@ -326,7 +338,8 @@ TEST_P(CaretDisplayItemClientTest, CaretHideMoveAndShow) { Selection().SetCaretVisible(true); EXPECT_TRUE(GetCaretDisplayItemClient().IsValid()); - GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint(); + GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint( + DocumentUpdateReason::kTest); EXPECT_FALSE(GetCaretDisplayItemClient().IsValid()); UpdateAllLifecyclePhasesForCaretTest(); diff --git a/chromium/third_party/blink/renderer/core/editing/commands/apply_block_element_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/apply_block_element_command.cc index 9f4a15e0eda..81a99ce7a41 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/apply_block_element_command.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/apply_block_element_command.cc @@ -107,7 +107,7 @@ void ApplyBlockElementCommand::DoApply(EditingState* editing_state) { if (editing_state->IsAborted()) return; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); DCHECK_EQ(start_scope, end_scope); DCHECK_GE(start_index, 0); @@ -211,7 +211,7 @@ void ApplyBlockElementCommand::FormatSelection( !end_of_next_paragraph.IsConnected()) return; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); end_of_current_paragraph = CreateVisiblePosition(end_of_next_paragraph); } } @@ -372,7 +372,7 @@ ApplyBlockElementCommand::EndOfNextParagrahSplittingTextNodesIfNeeded( // pointing at this same text node, endOfNextParagraph will be shifted by one // paragraph. Avoid this by splitting "\n" SplitTextNode(end_of_next_paragraph_text, 1); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); Text* const previous_text = DynamicTo<Text>(end_of_next_paragraph_text->previousSibling()); if (end_of_next_paragraph_text == start.ComputeContainerNode() && diff --git a/chromium/third_party/blink/renderer/core/editing/commands/apply_block_element_command_test.cc b/chromium/third_party/blink/renderer/core/editing/commands/apply_block_element_command_test.cc index 0630b0654e5..0e5736dcc45 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/apply_block_element_command_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/apply_block_element_command_test.cc @@ -36,7 +36,7 @@ TEST_F(ApplyBlockElementCommandTest, selectionCrossingOverBody) { GetDocument().body()->setContentEditable("false", ASSERT_NO_EXCEPTION); GetDocument().setDesignMode("on"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Selection().SetSelection( SelectionInDOMTree::Builder() .SetBaseAndExtent( @@ -52,7 +52,7 @@ TEST_F(ApplyBlockElementCommandTest, selectionCrossingOverBody) { EXPECT_EQ( "<body contenteditable=\"false\">\n" "<pre><var id=\"va\" class=\"CLASS13\">\nC\n</var></pre><input></body>", - GetDocument().documentElement()->InnerHTMLAsString()); + GetDocument().documentElement()->innerHTML()); } // This is a regression test for https://crbug.com/660801 @@ -77,7 +77,7 @@ TEST_F(ApplyBlockElementCommandTest, visibilityChangeDuringCommand) { EXPECT_EQ( "<head><style>li:first-child { visibility:visible; }</style></head>" "<body><ul style=\"visibility:hidden\"><ul></ul><li>xyz</li></ul></body>", - GetDocument().documentElement()->InnerHTMLAsString()); + GetDocument().documentElement()->innerHTML()); } // This is a regression test for https://crbug.com/712510 @@ -109,7 +109,7 @@ TEST_F(ApplyBlockElementCommandTest, IndentHeadingIntoBlockquote) { "<h6><button></button></h6><br>" "<object></object>" "</div>", - GetDocument().body()->InnerHTMLAsString()); + GetDocument().body()->innerHTML()); } // This is a regression test for https://crbug.com/806525 diff --git a/chromium/third_party/blink/renderer/core/editing/commands/apply_style_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/apply_style_command.cc index 8367b7803a7..cd6d78a27bc 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/apply_style_command.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/apply_style_command.cc @@ -180,7 +180,7 @@ void ApplyStyleCommand::UpdateStartEnd(const EphemeralRange& range) { if (!use_ending_selection_ && (range.StartPosition() != start_ || range.EndPosition() != end_)) use_ending_selection_ = true; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); const bool was_base_first = StartingSelection().IsBaseFirst() || !SelectionIsDirectional(); SelectionInDOMTree::Builder builder; @@ -216,7 +216,8 @@ void ApplyStyleCommand::DoApply(EditingState* editing_state) { switch (property_level_) { case kPropertyDefault: { // Apply the block-centric properties of the style. - EditingStyle* block_style = style_->ExtractAndRemoveBlockProperties(); + EditingStyle* block_style = style_->ExtractAndRemoveBlockProperties( + GetDocument().ToExecutionContext()); if (!block_style->IsEmpty()) { ApplyBlockStyle(block_style, editing_state); if (editing_state->IsAborted()) @@ -250,7 +251,7 @@ void ApplyStyleCommand::ApplyBlockStyle(EditingStyle* style, // update document layout once before removing styles // so that we avoid the expense of updating before each and every call // to check a computed style - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); // get positions we want to use for applying style Position start = StartPosition(); @@ -312,7 +313,7 @@ void ApplyStyleCommand::ApplyBlockStyle(EditingStyle* style, if (new_block) { block = new_block; if (paragraph_start.IsOrphan()) { - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); paragraph_start = CreateVisiblePosition( Position::FirstPositionInNode(*new_block)); } @@ -330,7 +331,7 @@ void ApplyStyleCommand::ApplyBlockStyle(EditingStyle* style, } } - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); // Make the VisiblePositions valid again after style changes. // TODO(editing-dev): We shouldn't store VisiblePositions and inspect @@ -355,7 +356,7 @@ void ApplyStyleCommand::ApplyBlockStyle(EditingStyle* style, // Update style and layout again, since added or removed styles could have // affected the layout. We need clean layout in order to compute // plain-text ranges below. - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); EphemeralRange start_ephemeral_range = PlainTextRange(start_index) @@ -698,7 +699,7 @@ void ApplyStyleCommand::ApplyInlineStyle(EditingStyle* style, // update document layout once before removing styles // so that we avoid the expense of updating before each and every call // to check a computed style - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); // adjust to the positions we want to use for applying style Position start = StartPosition(); @@ -830,7 +831,7 @@ void ApplyStyleCommand::ApplyInlineStyle(EditingStyle* style, // update document layout once before running the rest of the function // so that we avoid the expense of updating before each and every call // to check a computed style - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); EditingStyle* style_to_apply = style; if (has_text_direction) { @@ -868,7 +869,7 @@ void ApplyStyleCommand::ApplyInlineStyle(EditingStyle* style, } } - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); FixRangeAndApplyInlineStyle(style_to_apply, start, end, editing_state); if (editing_state->IsAborted()) return; @@ -985,7 +986,7 @@ void ApplyStyleCommand::ApplyInlineStyleToNodeRange( if (remove_only_) return; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); HeapVector<InlineRunToApplyStyle> runs; Node* node = start_node; @@ -1060,7 +1061,7 @@ void ApplyStyleCommand::ApplyInlineStyleToNodeRange( } } - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); for (auto& run : runs) { if (run.position_for_style_computation.IsNotNull()) @@ -1442,7 +1443,7 @@ void ApplyStyleCommand::RemoveInlineStyle(EditingStyle* style, // TODO(editing-dev): Use of UpdateStyleAndLayout // needs to be audited. See http://crbug.com/590369 for more details. - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); Position push_down_start = MostForwardCaretPosition(start); // If the pushDownStart is at the end of a text node, then this node is not @@ -1460,7 +1461,7 @@ void ApplyStyleCommand::RemoveInlineStyle(EditingStyle* style, // TODO(editing-dev): Use of UpdateStyleAndLayout // needs to be audited. See http://crbug.com/590369 for more details. - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); Position push_down_end = MostBackwardCaretPosition(end); // If pushDownEnd is at the start of a text node, then this node is not fully @@ -1563,7 +1564,7 @@ bool ApplyStyleCommand::ElementFullySelected(const HTMLElement& element, const Position& end) const { // The tree may have changed and Position::upstream() relies on an up-to-date // layout. - element.GetDocument().UpdateStyleAndLayout(); + element.GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); return ComparePositions(FirstPositionInOrBeforeNode(element), start) >= 0 && ComparePositions( diff --git a/chromium/third_party/blink/renderer/core/editing/commands/apply_style_command_test.cc b/chromium/third_party/blink/renderer/core/editing/commands/apply_style_command_test.cc index 8cc843910dd..7732a825793 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/apply_style_command_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/apply_style_command_test.cc @@ -67,9 +67,9 @@ TEST_F(ApplyStyleCommandTest, JustifyRightDetachesDestination) { "<button></button>" "</ruby"); Element* body = GetDocument().body(); - // The bug does't reproduce with a contenteditable <div> as container. + // The bug doesn't reproduce with a contenteditable <div> as container. body->setAttribute(html_names::kContenteditableAttr, "true"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Selection().SelectAll(); auto* style = diff --git a/chromium/third_party/blink/renderer/core/editing/commands/break_blockquote_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/break_blockquote_command.cc index 849508fd7b0..1675649b6d8 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/break_blockquote_command.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/break_blockquote_command.cc @@ -151,7 +151,7 @@ void BreakBlockquoteCommand::DoApply(EditingState* editing_state) { if (editing_state->IsAborted()) return; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); // If we're inserting the break at the end of the quoted content, we don't // need to break the quote. diff --git a/chromium/third_party/blink/renderer/core/editing/commands/clipboard_commands.cc b/chromium/third_party/blink/renderer/core/editing/commands/clipboard_commands.cc index c5e7c916b89..e697b04265a 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/clipboard_commands.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/clipboard_commands.cc @@ -82,7 +82,7 @@ bool ClipboardCommands::CanWriteClipboard(LocalFrame& frame, bool ClipboardCommands::CanSmartReplaceInClipboard(LocalFrame& frame) { return frame.GetEditor().SmartInsertDeleteEnabled() && - SystemClipboard::GetInstance().CanSmartReplace(); + frame.GetSystemClipboard()->CanSmartReplace(); } Element* ClipboardCommands::FindEventTargetForClipboardEvent( @@ -110,19 +110,19 @@ bool ClipboardCommands::DispatchClipboardEvent(LocalFrame& frame, if (!target) return true; - DataTransfer* const data_transfer = - DataTransfer::Create(DataTransfer::kCopyAndPaste, policy, - policy == DataTransferAccessPolicy::kWritable - ? DataObject::Create() - : DataObject::CreateFromClipboard(paste_mode)); + SystemClipboard* system_clipboard = frame.GetSystemClipboard(); + DataTransfer* const data_transfer = DataTransfer::Create( + DataTransfer::kCopyAndPaste, policy, + policy == DataTransferAccessPolicy::kWritable + ? DataObject::Create() + : DataObject::CreateFromClipboard(system_clipboard, paste_mode)); Event* const evt = ClipboardEvent::Create(event_type, data_transfer); target->DispatchEvent(*evt); const bool no_default_processing = evt->defaultPrevented(); if (no_default_processing && policy == DataTransferAccessPolicy::kWritable) { - SystemClipboard::GetInstance().WriteDataObject( - data_transfer->GetDataObject()); - SystemClipboard::GetInstance().CommitWrite(); + frame.GetSystemClipboard()->WriteDataObject(data_transfer->GetDataObject()); + frame.GetSystemClipboard()->CommitWrite(); } // Invalidate clipboard here for security. @@ -135,7 +135,7 @@ bool ClipboardCommands::DispatchCopyOrCutEvent(LocalFrame& frame, const AtomicString& event_type) { // TODO(editing-dev): The use of UpdateStyleAndLayout // needs to be audited. See http://crbug.com/590369 for more details. - frame.GetDocument()->UpdateStyleAndLayout(); + frame.GetDocument()->UpdateStyleAndLayout(DocumentUpdateReason::kEditing); if (IsInPasswordField( frame.Selection().ComputeVisibleSelectionInDOMTree().Start())) return true; @@ -204,9 +204,9 @@ void ClipboardCommands::WriteSelectionToClipboard(LocalFrame& frame) { const KURL& url = frame.GetDocument()->Url(); const String html = frame.Selection().SelectedHTMLForClipboard(); const String plain_text = frame.SelectedTextForClipboard(); - SystemClipboard::GetInstance().WriteHTML(html, url, plain_text, - GetSmartReplaceOption(frame)); - SystemClipboard::GetInstance().CommitWrite(); + frame.GetSystemClipboard()->WriteHTML(html, url, plain_text, + GetSmartReplaceOption(frame)); + frame.GetSystemClipboard()->CommitWrite(); } bool ClipboardCommands::PasteSupported(LocalFrame* frame) { @@ -235,12 +235,20 @@ bool ClipboardCommands::ExecuteCopy(LocalFrame& frame, // needs to be audited. See http://crbug.com/590369 for more details. // A 'copy' event handler might have dirtied the layout so we need to update // before we obtain the selection. - document->UpdateStyleAndLayout(); + document->UpdateStyleAndLayout(DocumentUpdateReason::kEditing); if (HTMLImageElement* image_element = ImageElementFromImageDocument(document)) { - WriteImageNodeToClipboard(*image_element, document->title()); - return true; + // In an image document, normally there isn't anything to select, and we + // only want to copy the image itself. + if (frame.Selection().ComputeVisibleSelectionInDOMTree().IsNone()) { + WriteImageNodeToClipboard(*frame.GetSystemClipboard(), *image_element, + document->title()); + return true; + } + + // Scripts may insert other contents into an image document. Falls through + // when they are selected. } // Since copy is a read-only operation it succeeds anytime a selection @@ -252,9 +260,9 @@ bool ClipboardCommands::ExecuteCopy(LocalFrame& frame, if (EnclosingTextControl( frame.Selection().ComputeVisibleSelectionInDOMTree().Start())) { - SystemClipboard::GetInstance().WritePlainText( - frame.SelectedTextForClipboard(), GetSmartReplaceOption(frame)); - SystemClipboard::GetInstance().CommitWrite(); + frame.GetSystemClipboard()->WritePlainText(frame.SelectedTextForClipboard(), + GetSmartReplaceOption(frame)); + frame.GetSystemClipboard()->CommitWrite(); return true; } WriteSelectionToClipboard(frame); @@ -292,7 +300,7 @@ bool ClipboardCommands::ExecuteCut(LocalFrame& frame, // needs to be audited. See http://crbug.com/590369 for more details. // A 'cut' event handler might have dirtied the layout so we need to update // before we obtain the selection. - frame.GetDocument()->UpdateStyleAndLayout(); + frame.GetDocument()->UpdateStyleAndLayout(DocumentUpdateReason::kEditing); if (source == EditorCommandSource::kMenuOrKeyBinding && !frame.Selection().SelectionHasFocus()) @@ -303,9 +311,9 @@ bool ClipboardCommands::ExecuteCut(LocalFrame& frame, if (EnclosingTextControl( frame.Selection().ComputeVisibleSelectionInDOMTree().Start())) { const String plain_text = frame.SelectedTextForClipboard(); - SystemClipboard::GetInstance().WritePlainText(plain_text, - GetSmartReplaceOption(frame)); - SystemClipboard::GetInstance().CommitWrite(); + frame.GetSystemClipboard()->WritePlainText(plain_text, + GetSmartReplaceOption(frame)); + frame.GetSystemClipboard()->CommitWrite(); } else { WriteSelectionToClipboard(frame); } @@ -346,26 +354,35 @@ void ClipboardCommands::PasteAsPlainTextFromClipboard( if (!target) return; target->DispatchEvent(*TextEvent::CreateForPlainTextPaste( - frame.DomWindow(), SystemClipboard::GetInstance().ReadPlainText(), + frame.DomWindow(), frame.GetSystemClipboard()->ReadPlainText(), CanSmartReplaceInClipboard(frame))); } ClipboardCommands::FragmentAndPlainText ClipboardCommands::GetFragmentFromClipboard(LocalFrame& frame) { DocumentFragment* fragment = nullptr; - if (SystemClipboard::GetInstance().IsHTMLAvailable()) { + if (frame.GetSystemClipboard()->IsHTMLAvailable()) { unsigned fragment_start = 0; unsigned fragment_end = 0; KURL url; - const String markup = SystemClipboard::GetInstance().ReadHTML( - url, fragment_start, fragment_end); + const String markup = + frame.GetSystemClipboard()->ReadHTML(url, fragment_start, fragment_end); fragment = CreateSanitizedFragmentFromMarkupWithContext( *frame.GetDocument(), markup, fragment_start, fragment_end, url); } if (fragment) return std::make_pair(fragment, false); - const String text = SystemClipboard::GetInstance().ReadPlainText(); + if (const String markup = frame.GetSystemClipboard()->ReadImageAsImageMarkup( + mojom::blink::ClipboardBuffer::kStandard)) { + fragment = CreateFragmentFromMarkup(*frame.GetDocument(), markup, + /* base_url */ "", + kDisallowScriptingAndPluginContent); + DCHECK(fragment); + return std::make_pair(fragment, false); + } + + const String text = frame.GetSystemClipboard()->ReadPlainText(); if (text.IsEmpty()) return std::make_pair(fragment, false); @@ -373,7 +390,7 @@ ClipboardCommands::GetFragmentFromClipboard(LocalFrame& frame) { // needs to be audited. See http://crbug.com/590369 for more details. // |SelectedRange| requires clean layout for visible selection // normalization. - frame.GetDocument()->UpdateStyleAndLayout(); + frame.GetDocument()->UpdateStyleAndLayout(DocumentUpdateReason::kEditing); fragment = CreateFragmentFromText(frame.GetEditor().SelectedRange(), text); return std::make_pair(fragment, true); } @@ -402,7 +419,7 @@ void ClipboardCommands::Paste(LocalFrame& frame, EditorCommandSource source) { // needs to be audited. See http://crbug.com/590369 for more details. // A 'paste' event handler might have dirtied the layout so we need to update // before we obtain the selection. - frame.GetDocument()->UpdateStyleAndLayout(); + frame.GetDocument()->UpdateStyleAndLayout(DocumentUpdateReason::kEditing); if (source == EditorCommandSource::kMenuOrKeyBinding && !frame.Selection().SelectionHasFocus()) @@ -418,7 +435,8 @@ void ClipboardCommands::Paste(LocalFrame& frame, EditorCommandSource source) { if (source == EditorCommandSource::kMenuOrKeyBinding) { DataTransfer* data_transfer = DataTransfer::Create( DataTransfer::kCopyAndPaste, DataTransferAccessPolicy::kReadable, - DataObject::CreateFromClipboard(paste_mode)); + DataObject::CreateFromClipboard(frame.GetSystemClipboard(), + paste_mode)); if (DispatchBeforeInputDataTransfer( FindEventTargetForClipboardEvent(frame, source), @@ -453,11 +471,10 @@ bool ClipboardCommands::ExecutePasteGlobalSelection(LocalFrame& frame, return false; DCHECK_EQ(source, EditorCommandSource::kMenuOrKeyBinding); - const bool old_selection_mode = - SystemClipboard::GetInstance().IsSelectionMode(); - SystemClipboard::GetInstance().SetSelectionMode(true); + const bool old_selection_mode = frame.GetSystemClipboard()->IsSelectionMode(); + frame.GetSystemClipboard()->SetSelectionMode(true); Paste(frame, source); - SystemClipboard::GetInstance().SetSelectionMode(old_selection_mode); + frame.GetSystemClipboard()->SetSelectionMode(old_selection_mode); return true; } @@ -474,7 +491,7 @@ bool ClipboardCommands::ExecutePasteAndMatchStyle(LocalFrame& frame, // needs to be audited. See http://crbug.com/590369 for more details. // A 'paste' event handler might have dirtied the layout so we need to update // before we obtain the selection. - frame.GetDocument()->UpdateStyleAndLayout(); + frame.GetDocument()->UpdateStyleAndLayout(DocumentUpdateReason::kEditing); if (source == EditorCommandSource::kMenuOrKeyBinding && !frame.Selection().SelectionHasFocus()) diff --git a/chromium/third_party/blink/renderer/core/editing/commands/composite_edit_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/composite_edit_command.cc index a826be457eb..a665fe43804 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/composite_edit_command.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/composite_edit_command.cc @@ -104,7 +104,7 @@ VisibleSelection CompositeEditCommand::EndingVisibleSelection() const { // TODO(editing-dev): The use of // |Document::UpdateStyleAndLayout()| // needs to be audited. See http://crbug.com/590369 for more details. - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); return CreateVisibleSelection(ending_selection_); } @@ -144,7 +144,7 @@ bool CompositeEditCommand::Apply() { // operations, like RemoveNodeCommand, don't require a layout because the high // level operations that use them perform one if one is necessary (like for // the creation of VisiblePositions). - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); LocalFrame* frame = GetDocument().GetFrame(); DCHECK(frame); @@ -289,7 +289,7 @@ void CompositeEditCommand::InsertNodeBefore( ABORT_EDITING_COMMAND_IF(!ref_child->parentNode()); // TODO(editing-dev): Use of UpdateStyleAndLayout // needs to be audited. See http://crbug.com/590369 for more details. - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); ABORT_EDITING_COMMAND_IF(!HasEditableStyle(*ref_child->parentNode()) && ref_child->parentNode()->InActiveDocument()); ApplyCommandToComposite( @@ -319,7 +319,7 @@ void CompositeEditCommand::InsertNodeAfter(Node* insert_child, void CompositeEditCommand::InsertNodeAt(Node* insert_child, const Position& editing_position, EditingState* editing_state) { - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); ABORT_EDITING_COMMAND_IF(!IsEditablePosition(editing_position)); // For editing positions like [table, 0], insert before the table, // likewise for replaced elements, brs, etc. @@ -615,7 +615,7 @@ Position CompositeEditCommand::PositionOutsideTabSpan(const Position& pos) { // TODO(editing-dev): Hoist this UpdateStyleAndLayout // to the callers. See crbug.com/590369 for details. - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); if (pos.OffsetInContainerNode() <= CaretMinOffset(pos.ComputeContainerNode())) return Position::InParentBeforeNode(*tab_span); @@ -681,7 +681,7 @@ void CompositeEditCommand::SetNodeAttribute(Element* element, bool CompositeEditCommand::CanRebalance(const Position& position) const { // TODO(editing-dev): Use of UpdateStyleAndLayout() // needs to be audited. See http://crbug.com/590369 for more details. - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); auto* text_node = DynamicTo<Text>(position.ComputeContainerNode()); if (!position.IsOffsetInAnchor() || !text_node || @@ -740,7 +740,7 @@ void CompositeEditCommand::RebalanceWhitespaceOnTextSubstring(Text* text_node, if (!length) return; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); VisiblePosition visible_upstream_pos = CreateVisiblePosition(Position(text_node, upstream)); VisiblePosition visible_downstream_pos = @@ -788,14 +788,14 @@ void CompositeEditCommand::PrepareWhitespaceAtPositionForSplit( Position upstream_pos = MostBackwardCaretPosition(position); DeleteInsignificantText(upstream_pos, MostForwardCaretPosition(position)); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); position = MostForwardCaretPosition(upstream_pos); VisiblePosition visible_pos = CreateVisiblePosition(position); VisiblePosition previous_visible_pos = PreviousPositionOf(visible_pos); ReplaceCollapsibleWhitespaceWithNonBreakingSpaceIfNeeded( previous_visible_pos); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); ReplaceCollapsibleWhitespaceWithNonBreakingSpaceIfNeeded( CreateVisiblePosition(position)); } @@ -829,7 +829,7 @@ void CompositeEditCommand::DeleteInsignificantText(Text* text_node, if (!text_node || start >= end) return; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); LayoutText* text_layout_object = text_node->GetLayoutObject(); if (!text_layout_object) @@ -951,7 +951,7 @@ HTMLBRElement* CompositeEditCommand::AppendBlockPlaceholder( if (!container) return nullptr; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); // Should assert isLayoutBlockFlow || isInlineFlow when deletion improves. See // 4244964. @@ -987,7 +987,7 @@ HTMLBRElement* CompositeEditCommand::AddBlockPlaceholderIfNeeded( if (!container) return nullptr; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); auto* block = DynamicTo<LayoutBlockFlow>(container->GetLayoutObject()); if (!block) @@ -1102,7 +1102,7 @@ HTMLElement* CompositeEditCommand::MoveParagraphContentsToNewBlockIfNecessary( // Inserting default paragraph element can change visible position. We // should update visible positions before use them. - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); const VisiblePosition& destination = VisiblePosition::FirstPositionInNode(*new_block); if (destination.IsNull()) { @@ -1258,7 +1258,7 @@ void CompositeEditCommand::CleanupAfterDeletion(EditingState* editing_state) { void CompositeEditCommand::CleanupAfterDeletion(EditingState* editing_state, VisiblePosition destination) { - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); VisiblePosition caret_after_delete = EndingVisibleSelection().VisibleStart(); Node* destination_node = destination.DeepEquivalent().AnchorNode(); @@ -1360,7 +1360,7 @@ void CompositeEditCommand::MoveParagraphWithClones( if (editing_state->IsAborted()) return; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); // Add a br if pruning an empty block level element caused a collapse. For // example: @@ -1518,7 +1518,8 @@ void CompositeEditCommand::MoveParagraphs( start_of_paragraph_to_move.DeepEquivalent()); style_in_empty_paragraph->MergeTypingStyle(&GetDocument()); // The moved paragraph should assume the block style of the destination. - style_in_empty_paragraph->RemoveBlockProperties(); + style_in_empty_paragraph->RemoveBlockProperties( + GetDocument().ToExecutionContext()); } // FIXME (5098931): We should add a new insert action @@ -1541,7 +1542,7 @@ void CompositeEditCommand::MoveParagraphs( return; DCHECK(destination.DeepEquivalent().IsConnected()) << destination; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); // Add a br if pruning an empty block level element caused a collapse. For // example: @@ -1569,7 +1570,7 @@ void CompositeEditCommand::MoveParagraphs( } // TextIterator::rangeLength requires clean layout. - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); destination_index = TextIterator::RangeLength( Position::FirstPositionInNode(*GetDocument().documentElement()), @@ -1599,7 +1600,7 @@ void CompositeEditCommand::MoveParagraphs( return; ABORT_EDITING_COMMAND_IF(!EndingSelection().IsValidFor(GetDocument())); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); // If the selection is in an empty paragraph, restore styles from the old // empty paragraph to the new empty paragraph. @@ -1620,7 +1621,7 @@ void CompositeEditCommand::MoveParagraphs( return; // We need clean layout in order to compute plain-text ranges below. - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); // Fragment creation (using createMarkup) incorrectly uses regular spaces // instead of nbsps for some spaces that were rendered (11475), which causes @@ -1770,7 +1771,7 @@ bool CompositeEditCommand::BreakOutOfEmptyMailBlockquotedParagraph( if (!EndingSelection().IsCaret()) return false; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); VisiblePosition caret = EndingVisibleSelection().VisibleStart(); auto* highest_blockquote = To<HTMLQuoteElement>(HighestEnclosingNodeOfType( @@ -1796,7 +1797,7 @@ bool CompositeEditCommand::BreakOutOfEmptyMailBlockquotedParagraph( if (editing_state->IsAborted()) return false; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); VisiblePosition at_br = VisiblePosition::BeforeNode(*br); // If the br we inserted collapsed, for example: @@ -1807,7 +1808,7 @@ bool CompositeEditCommand::BreakOutOfEmptyMailBlockquotedParagraph( editing_state); if (editing_state->IsAborted()) return false; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); } SetEndingSelection(SelectionForUndoStep::From( SelectionInDOMTree::Builder() @@ -1855,7 +1856,7 @@ Position CompositeEditCommand::PositionAvoidingSpecialElementBoundary( if (original.IsNull()) return original; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); VisiblePosition visible_pos = CreateVisiblePosition(original); Element* enclosing_anchor = EnclosingAnchorElement(original); Position result = original; @@ -1885,7 +1886,7 @@ Position CompositeEditCommand::PositionAvoidingSpecialElementBoundary( return original; } - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); // Don't insert outside an anchor if doing so would skip over a line // break. It would probably be safe to move the line break so that we @@ -1947,7 +1948,7 @@ Node* CompositeEditCommand::SplitTreeToNode(Node* start, if (!parent_element) break; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); // Do not split a node when doing so introduces an empty node. VisiblePosition position_in_parent = diff --git a/chromium/third_party/blink/renderer/core/editing/commands/composite_edit_command_test.cc b/chromium/third_party/blink/renderer/core/editing/commands/composite_edit_command_test.cc index 3cf0ee68df3..760a475e3ae 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/composite_edit_command_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/composite_edit_command_test.cc @@ -77,7 +77,7 @@ TEST_F(CompositeEditCommandTest, insertNodeBefore) { EditingState editing_state; sample.InsertNodeBefore(insert_child, ref_child, &editing_state); EXPECT_FALSE(editing_state.IsAborted()); - EXPECT_EQ("foo<b></b>", div->InnerHTMLAsString()); + EXPECT_EQ("foo<b></b>", div->innerHTML()); } TEST_F(CompositeEditCommandTest, insertNodeBeforeInUneditable) { @@ -102,7 +102,7 @@ TEST_F(CompositeEditCommandTest, insertNodeBeforeDisconnectedNode) { EditingState editing_state; sample.InsertNodeBefore(insert_child, ref_child, &editing_state); EXPECT_FALSE(editing_state.IsAborted()); - EXPECT_EQ("<b></b>", div->InnerHTMLAsString()) + EXPECT_EQ("<b></b>", div->innerHTML()) << "InsertNodeBeforeCommand does nothing for disconnected node"; } @@ -117,7 +117,7 @@ TEST_F(CompositeEditCommandTest, insertNodeBeforeWithDirtyLayoutTree) { EditingState editing_state; sample.InsertNodeBefore(insert_child, ref_child, &editing_state); EXPECT_FALSE(editing_state.IsAborted()); - EXPECT_EQ("foo<b></b>", div->InnerHTMLAsString()); + EXPECT_EQ("foo<b></b>", div->innerHTML()); } TEST_F(CompositeEditCommandTest, @@ -129,7 +129,7 @@ TEST_F(CompositeEditCommandTest, Element* body = GetDocument().body(); Node* text = body->lastChild(); body->setAttribute(html_names::kContenteditableAttr, "true"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); EditingState editing_state; sample.MoveParagraphContentsToNewBlockIfNecessary(Position(text, 0), @@ -139,7 +139,7 @@ TEST_F(CompositeEditCommandTest, "<div><br></div>" "<style>div{-webkit-user-modify:read-only;user-select:none;}</style>" "foo", - body->InnerHTMLAsString()); + body->innerHTML()); } TEST_F(CompositeEditCommandTest, InsertNodeOnDisconnectedParent) { diff --git a/chromium/third_party/blink/renderer/core/editing/commands/delete_selection_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/delete_selection_command.cc index 9425c9c546e..44c3eff34e5 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/delete_selection_command.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/delete_selection_command.cc @@ -25,6 +25,7 @@ #include "third_party/blink/renderer/core/editing/commands/delete_selection_command.h" +#include "build/build_config.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/element.h" #include "third_party/blink/renderer/core/dom/node_traversal.h" @@ -61,7 +62,7 @@ static bool IsTableRowEmpty(Node* row) { if (!IsA<HTMLTableRowElement>(row)) return false; - row->GetDocument().UpdateStyleAndLayout(); + row->GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); for (Node* child = row->firstChild(); child; child = child->nextSibling()) { if (IsTableCell(child) && !IsTableCellEmpty(child)) return false; @@ -89,10 +90,10 @@ DeleteSelectionCommand::DeleteSelectionCommand( reference_move_position_(reference_move_position) {} DeleteSelectionCommand::DeleteSelectionCommand( - const VisibleSelection& selection, + const SelectionForUndoStep& selection, const DeleteSelectionOptions& options, InputEvent::InputType input_type) - : CompositeEditCommand(*selection.Start().GetDocument()), + : CompositeEditCommand(*selection.Base().GetDocument()), options_(options), has_selection_to_delete_(true), merge_blocks_after_delete_(options.IsMergeBlocksAfterDelete()), @@ -137,9 +138,10 @@ void DeleteSelectionCommand::InitializeStartEnd(Position& start, break; if (CreateVisiblePosition(start).DeepEquivalent() != - selection_to_delete_.VisibleStart().DeepEquivalent() || + CreateVisiblePosition(selection_to_delete_.Start()) + .DeepEquivalent() || CreateVisiblePosition(end).DeepEquivalent() != - selection_to_delete_.VisibleEnd().DeepEquivalent()) + CreateVisiblePosition(selection_to_delete_.End()).DeepEquivalent()) break; // If we're going to expand to include the startSpecialContainer, it must be @@ -224,6 +226,15 @@ static Position TrailingWhitespacePosition(const Position& position, return Position(); } +// Workaround: GCC fails to resolve overloaded template functions, passed as +// parameters of EnclosingNodeType. But it works wrapping that in a utility +// function. +#if defined(COMPILER_GCC) +static bool IsHTMLTableRowElement(const blink::Node* node) { + return IsA<HTMLTableRowElement>(node); +} +#endif + void DeleteSelectionCommand::InitializePositionData( EditingState* editing_state) { DCHECK(!GetDocument().NeedsLayoutTreeUpdate()); @@ -252,10 +263,18 @@ void DeleteSelectionCommand::InitializePositionData( start_root_ = RootEditableElementOf(start); end_root_ = RootEditableElementOf(end); +#if defined(COMPILER_GCC) + // Workaround. See declaration of IsHTMLTableRowElement + start_table_row_ = To<HTMLTableRowElement>( + EnclosingNodeOfType(start, &IsHTMLTableRowElement)); + end_table_row_ = + To<HTMLTableRowElement>(EnclosingNodeOfType(end, &IsHTMLTableRowElement)); +#else start_table_row_ = To<HTMLTableRowElement>( EnclosingNodeOfType(start, &IsA<HTMLTableRowElement>)); end_table_row_ = To<HTMLTableRowElement>( EnclosingNodeOfType(end, &IsA<HTMLTableRowElement>)); +#endif // Don't move content out of a table cell. // If the cell is non-editable, enclosingNodeOfType won't return it by @@ -442,7 +461,7 @@ bool DeleteSelectionCommand::HandleSpecialCaseBRDelete( // We detect the case where the start is an empty line consisting of BR not // wrapped in a block element. if (upstream_start_is_br && downstream_start_is_br) { - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); if (!(IsStartOfBlock( VisiblePosition::BeforeNode(*node_after_upstream_start)) && IsEndOfBlock( @@ -497,7 +516,7 @@ void DeleteSelectionCommand::RemoveNode( return; // Make sure empty cell has some height, if a placeholder can be inserted. - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); LayoutObject* r = node->GetLayoutObject(); if (r && r->IsTableCell() && ToLayoutBox(r)->ContentHeight() <= 0) { Position first_editable_position = FirstEditablePositionInNode(node); @@ -507,7 +526,7 @@ void DeleteSelectionCommand::RemoveNode( return; } - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); if (node == start_block_) { VisiblePosition previous = PreviousPositionOf( VisiblePosition::FirstPositionInNode(*start_block_.Get())); @@ -561,7 +580,8 @@ void DeleteSelectionCommand::DeleteTextFromNode(Text* node, void DeleteSelectionCommand:: MakeStylingElementsDirectChildrenOfEditableRootToPreventStyleLoss( EditingState* editing_state) { - Range* range = CreateRange(selection_to_delete_.ToNormalizedEphemeralRange()); + Range* range = CreateRange(CreateVisibleSelection(selection_to_delete_) + .ToNormalizedEphemeralRange()); Node* node = range->FirstNode(); while (node && node != range->PastLastNode()) { Node* next_node = NodeTraversal::Next(*node); @@ -605,12 +625,13 @@ void DeleteSelectionCommand::HandleGeneralDelete(EditingState* editing_state) { return; } - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); auto* text = DynamicTo<Text>(start_node); if (start_offset >= CaretMaxOffset(start_node) && text) { - if (text->length() > (unsigned)CaretMaxOffset(start_node)) + if (text->length() > static_cast<unsigned>(CaretMaxOffset(start_node))) { DeleteTextFromNode(text, CaretMaxOffset(start_node), text->length() - CaretMaxOffset(start_node)); + } } if (start_offset >= EditingStrategy::LastOffsetForEditing(start_node)) { @@ -638,7 +659,7 @@ void DeleteSelectionCommand::HandleGeneralDelete(EditingState* editing_state) { ending_position_ = upstream_start_; } // We should update layout to associate |start_node| to layout object. - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); } // The selection to delete is all in one node. @@ -686,7 +707,7 @@ void DeleteSelectionCommand::HandleGeneralDelete(EditingState* editing_state) { return; node = next_node; } else { - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); Node& n = NodeTraversal::LastWithinOrSelf(*node); if (downstream_end_.AnchorNode() == n && downstream_end_.ComputeEditingOffset() >= CaretMaxOffset(&n)) { @@ -702,7 +723,7 @@ void DeleteSelectionCommand::HandleGeneralDelete(EditingState* editing_state) { // TODO(editing-dev): Hoist UpdateStyleAndLayout // to caller. See http://crbug.com/590369 for more details. - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); if (downstream_end_.AnchorNode() != start_node && !upstream_start_.AnchorNode()->IsDescendantOf( @@ -752,7 +773,7 @@ void DeleteSelectionCommand::HandleGeneralDelete(EditingState* editing_state) { } void DeleteSelectionCommand::FixupWhitespace() { - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); if (leading_whitespace_.IsNotNull() && !IsRenderedCharacter(leading_whitespace_)) { if (auto* text_node = DynamicTo<Text>(leading_whitespace_.AnchorNode())) { @@ -812,7 +833,7 @@ void DeleteSelectionCommand::MergeParagraphs(EditingState* editing_state) { if (upstream_start_ == downstream_end_) return; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); VisiblePosition start_of_paragraph_to_move = CreateVisiblePosition(downstream_end_); @@ -846,7 +867,7 @@ void DeleteSelectionCommand::MergeParagraphs(EditingState* editing_state) { upstream_start_, editing_state); if (editing_state->IsAborted()) return; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); merge_destination = CreateVisiblePosition(upstream_start_); start_of_paragraph_to_move = CreateVisiblePosition(relocatable_start.GetPosition()); @@ -973,7 +994,8 @@ void DeleteSelectionCommand::RemovePreviouslySelectedEmptyTableRows( if (IsTableRowEmpty(end_table_row_.Get())) { // Don't remove end_table_row_ if it's where we're putting the ending // selection. - if (!ending_position_.AnchorNode()->IsDescendantOf( + if (ending_position_.IsNull() || + !ending_position_.AnchorNode()->IsDescendantOf( end_table_row_.Get())) { // FIXME: We probably shouldn't remove end_table_row_ unless it's // fully selected, even if it is empty. We'll need to start @@ -1020,7 +1042,7 @@ void DeleteSelectionCommand::CalculateTypingStyleAfterDelete() { } void DeleteSelectionCommand::ClearTransientState() { - selection_to_delete_ = VisibleSelection(); + selection_to_delete_ = SelectionForUndoStep(); upstream_start_ = Position(); downstream_start_ = Position(); upstream_end_ = Position(); @@ -1059,12 +1081,14 @@ void DeleteSelectionCommand::RemoveRedundantBlocks( void DeleteSelectionCommand::DoApply(EditingState* editing_state) { // If selection has not been set to a custom selection when the command was // created, use the current ending selection. - if (!has_selection_to_delete_) - selection_to_delete_ = EndingVisibleSelection(); + if (!has_selection_to_delete_) { + selection_to_delete_ = + SelectionForUndoStep::From(EndingVisibleSelection().AsSelection()); + } if (!selection_to_delete_.IsValidFor(GetDocument()) || !selection_to_delete_.IsRange() || - !selection_to_delete_.IsContentEditable()) { + !IsEditablePosition(selection_to_delete_.Base())) { // editing/execCommand/delete-non-editable-range-crash.html reaches here. return; } @@ -1074,7 +1098,7 @@ void DeleteSelectionCommand::DoApply(EditingState* editing_state) { // save this to later make the selection with TextAffinity affinity = selection_to_delete_.Affinity(); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); Position downstream_end = MostForwardCaretPosition(selection_to_delete_.End()); @@ -1084,20 +1108,26 @@ void DeleteSelectionCommand::DoApply(EditingState* editing_state) { (downstream_end.ComputeContainerNode()->IsTextNode() && downstream_end.ComputeContainerNode()->parentNode() == RootEditableElement(*downstream_end.ComputeContainerNode())); + VisiblePosition visible_start = CreateVisiblePosition( + selection_to_delete_.Start(), + selection_to_delete_.IsRange() ? TextAffinity::kDownstream : affinity); + VisiblePosition visible_end = CreateVisiblePosition( + selection_to_delete_.End(), + selection_to_delete_.IsRange() ? TextAffinity::kUpstream : affinity); + bool line_break_at_end_of_selection_to_delete = - LineBreakExistsAtVisiblePosition(selection_to_delete_.VisibleEnd()); - need_placeholder_ = !root_will_stay_open_without_placeholder && - IsStartOfParagraph(selection_to_delete_.VisibleStart(), - kCanCrossEditingBoundary) && - IsEndOfParagraph(selection_to_delete_.VisibleEnd(), - kCanCrossEditingBoundary) && - !line_break_at_end_of_selection_to_delete; + LineBreakExistsAtVisiblePosition(visible_end); + + need_placeholder_ = + !root_will_stay_open_without_placeholder && + IsStartOfParagraph(visible_start, kCanCrossEditingBoundary) && + IsEndOfParagraph(visible_end, kCanCrossEditingBoundary) && + !line_break_at_end_of_selection_to_delete; if (need_placeholder_) { // Don't need a placeholder when deleting a selection that starts just // before a table and ends inside it (we do need placeholders to hold // open empty cells, but that's handled elsewhere). - if (Element* table = - TableElementJustAfter(selection_to_delete_.VisibleStart())) { + if (Element* table = TableElementJustAfter(visible_start)) { if (selection_to_delete_.End().AnchorNode()->IsDescendantOf(table)) need_placeholder_ = false; } @@ -1124,7 +1154,7 @@ void DeleteSelectionCommand::DoApply(EditingState* editing_state) { return; if (br_result) { CalculateTypingStyleAfterDelete(); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); SelectionInDOMTree::Builder builder; builder.SetAffinity(affinity); if (ending_position_.IsNotNull()) @@ -1138,7 +1168,7 @@ void DeleteSelectionCommand::DoApply(EditingState* editing_state) { return; } - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); HandleGeneralDelete(editing_state); if (editing_state->IsAborted()) @@ -1155,7 +1185,7 @@ void DeleteSelectionCommand::DoApply(EditingState* editing_state) { return; if (!need_placeholder_ && root_will_stay_open_without_placeholder) { - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); VisiblePosition visual_ending = CreateVisiblePosition(ending_position_); bool has_placeholder = LineBreakExistsAtVisiblePosition(visual_ending) && @@ -1187,7 +1217,7 @@ void DeleteSelectionCommand::DoApply(EditingState* editing_state) { CalculateTypingStyleAfterDelete(); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); SelectionInDOMTree::Builder builder; builder.SetAffinity(affinity); diff --git a/chromium/third_party/blink/renderer/core/editing/commands/delete_selection_command.h b/chromium/third_party/blink/renderer/core/editing/commands/delete_selection_command.h index f9f3d3da710..66e8a82259d 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/delete_selection_command.h +++ b/chromium/third_party/blink/renderer/core/editing/commands/delete_selection_command.h @@ -43,7 +43,7 @@ class CORE_EXPORT DeleteSelectionCommand final : public CompositeEditCommand { InputEvent::InputType input_type = InputEvent::InputType::kNone, const Position& reference_move_position = Position()); DeleteSelectionCommand( - const VisibleSelection&, + const SelectionForUndoStep&, const DeleteSelectionOptions&, InputEvent::InputType input_type = InputEvent::InputType::kNone); @@ -85,7 +85,7 @@ class CORE_EXPORT DeleteSelectionCommand final : public CompositeEditCommand { // This data is transient and should be cleared at the end of the doApply // function. - VisibleSelection selection_to_delete_; + SelectionForUndoStep selection_to_delete_; Position upstream_start_; Position downstream_start_; Position upstream_end_; diff --git a/chromium/third_party/blink/renderer/core/editing/commands/delete_selection_command_test.cc b/chromium/third_party/blink/renderer/core/editing/commands/delete_selection_command_test.cc index 2ee3a40be4f..d5ad9c4c4d1 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/delete_selection_command_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/delete_selection_command_test.cc @@ -56,7 +56,7 @@ TEST_F(DeleteSelectionCommandTest, deleteListFromTable) { EXPECT_TRUE(command->Apply()) << "the delete command should have succeeded"; EXPECT_EQ("<div contenteditable=\"true\"><br></div>", - GetDocument().body()->InnerHTMLAsString()); + GetDocument().body()->innerHTML()); EXPECT_TRUE(frame->Selection().GetSelectionInDOMTree().IsCaret()); EXPECT_EQ(Position(div, 0), frame->Selection() .ComputeVisibleSelectionInDOMTree() diff --git a/chromium/third_party/blink/renderer/core/editing/commands/document_exec_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/document_exec_command.cc index bce2db4038c..0a859b99353 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/document_exec_command.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/document_exec_command.cc @@ -39,6 +39,7 @@ #include "third_party/blink/renderer/core/frame/web_feature.h" #include "third_party/blink/renderer/core/html/forms/text_control_element.h" #include "third_party/blink/renderer/core/inspector/console_message.h" +#include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/instrumentation/histogram.h" #include "third_party/blink/renderer/platform/instrumentation/use_counter.h" #include "third_party/blink/renderer/platform/wtf/std_lib_extras.h" @@ -81,9 +82,9 @@ bool Document::execCommand(const String& command_name, String message = "We don't execute document.execCommand() this time, because it is " "called recursively."; - AddConsoleMessage( - ConsoleMessage::Create(mojom::ConsoleMessageSource::kJavaScript, - mojom::ConsoleMessageLevel::kWarning, message)); + AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>( + mojom::ConsoleMessageSource::kJavaScript, + mojom::ConsoleMessageLevel::kWarning, message)); return false; } base::AutoReset<bool> execute_scope(&is_running_exec_command_, true); diff --git a/chromium/third_party/blink/renderer/core/editing/commands/editing_command_test.cc b/chromium/third_party/blink/renderer/core/editing/commands/editing_command_test.cc index 2016f475780..c2c2f90021c 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/editing_command_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/editing_command_test.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "base/stl_util.h" +#include "third_party/blink/public/mojom/input/focus_type.mojom-blink.h" #include "third_party/blink/renderer/core/editing/commands/editing_command_type.h" #include "third_party/blink/renderer/core/editing/commands/editor_command.h" #include "third_party/blink/renderer/core/editing/commands/editor_command_names.h" @@ -61,7 +62,7 @@ TEST_F(EditingCommandTest, CreateCommandFromStringCaseFolding) { Editor& dummy_editor = GetDocument().GetFrame()->GetEditor(); for (const auto& entry : kCommandNameEntries) { const EditorCommand lower_name_command = - dummy_editor.CreateCommand(String(entry.name).DeprecatedLower()); + dummy_editor.CreateCommand(String(entry.name).LowerASCII()); EXPECT_EQ(static_cast<int>(entry.type), lower_name_command.IdForHistogram()) << entry.name; const EditorCommand upper_name_command = @@ -91,8 +92,8 @@ TEST_F(EditingCommandTest, EnabledVisibleSelection) { SetSelectionOptions()); Element* div = GetDocument().QuerySelector("div"); GetDocument().SetFocusedElement( - div, - FocusParams(SelectionBehaviorOnFocus::kNone, kWebFocusTypeNone, nullptr)); + div, FocusParams(SelectionBehaviorOnFocus::kNone, + mojom::blink::FocusType::kNone, nullptr)); EXPECT_TRUE(command.IsEnabled()); div->removeAttribute("contenteditable"); EXPECT_FALSE(command.IsEnabled()); @@ -108,8 +109,8 @@ TEST_F(EditingCommandTest, EnabledVisibleSelectionAndMark) { SetSelectionOptions()); Element* div = GetDocument().QuerySelector("div"); GetDocument().SetFocusedElement( - div, - FocusParams(SelectionBehaviorOnFocus::kNone, kWebFocusTypeNone, nullptr)); + div, FocusParams(SelectionBehaviorOnFocus::kNone, + mojom::blink::FocusType::kNone, nullptr)); EXPECT_FALSE(command.IsEnabled()); editor.SetMark(); EXPECT_TRUE(command.IsEnabled()); @@ -135,8 +136,8 @@ TEST_F(EditingCommandTest, EnabledInEditableTextOrCaretBrowsing) { SetSelectionOptions()); Element* div = GetDocument().QuerySelector("div"); GetDocument().SetFocusedElement( - div, - FocusParams(SelectionBehaviorOnFocus::kNone, kWebFocusTypeNone, nullptr)); + div, FocusParams(SelectionBehaviorOnFocus::kNone, + mojom::blink::FocusType::kNone, nullptr)); EXPECT_TRUE(command.IsEnabled()); div->removeAttribute("contenteditable"); EXPECT_FALSE(command.IsEnabled()); diff --git a/chromium/third_party/blink/renderer/core/editing/commands/editing_commands_utilities.cc b/chromium/third_party/blink/renderer/core/editing/commands/editing_commands_utilities.cc index db361a8fa3d..e73728712a4 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/editing_commands_utilities.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/editing_commands_utilities.cc @@ -534,7 +534,7 @@ void TidyUpHTMLStructure(Document& document) { // documentElement as rootEditableElement is problematic. So we move // non-<html> root elements under <body>, and the <body> works as // rootEditableElement. - document.AddConsoleMessage(ConsoleMessage::Create( + document.AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>( mojom::ConsoleMessageSource::kJavaScript, mojom::ConsoleMessageLevel::kWarning, "document.execCommand() doesn't work with an invalid HTML structure. It " diff --git a/chromium/third_party/blink/renderer/core/editing/commands/editing_state.cc b/chromium/third_party/blink/renderer/core/editing/commands/editing_state.cc index 8c20b9f5a12..3b3d854c2af 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/editing_state.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/editing_state.cc @@ -8,8 +8,6 @@ namespace blink { EditingState::EditingState() = default; -EditingState::~EditingState() = default; - void EditingState::Abort() { DCHECK(!is_aborted_); is_aborted_ = true; diff --git a/chromium/third_party/blink/renderer/core/editing/commands/editing_state.h b/chromium/third_party/blink/renderer/core/editing/commands/editing_state.h index f5b63acbfe8..2ae504fc33d 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/editing_state.h +++ b/chromium/third_party/blink/renderer/core/editing/commands/editing_state.h @@ -27,7 +27,6 @@ class CORE_EXPORT EditingState final { public: EditingState(); - ~EditingState(); void Abort(); bool IsAborted() const { return is_aborted_; } diff --git a/chromium/third_party/blink/renderer/core/editing/commands/editor_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/editor_command.cc index 27d77a2af4b..96645898d7f 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/editor_command.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/editor_command.cc @@ -195,7 +195,7 @@ StaticRangeVector* RangesFromCurrentSelectionOrExtendCaret( const LocalFrame& frame, SelectionModifyDirection direction, TextGranularity granularity) { - frame.GetDocument()->UpdateStyleAndLayout(); + frame.GetDocument()->UpdateStyleAndLayout(DocumentUpdateReason::kEditing); SelectionModifier selection_modifier( frame, frame.Selection().GetSelectionInDOMTree()); selection_modifier.SetSelectionIsDirectional( @@ -361,12 +361,12 @@ static bool ExecuteDefaultParagraphSeparator(LocalFrame& frame, Event*, EditorCommandSource, const String& value) { - if (DeprecatedEqualIgnoringCase(value, "div")) { + if (EqualIgnoringASCIICase(value, "div")) { frame.GetEditor().SetDefaultParagraphSeparator( EditorParagraphSeparator::kIsDiv); return true; } - if (DeprecatedEqualIgnoringCase(value, "p")) { + if (EqualIgnoringASCIICase(value, "p")) { frame.GetEditor().SetDefaultParagraphSeparator( EditorParagraphSeparator::kIsP); } @@ -380,7 +380,7 @@ static void PerformDelete(LocalFrame& frame) { // TODO(editing-dev): The use of UpdateStyleAndLayout // needs to be audited. See http://crbug.com/590369 for more details. // |SelectedRange| requires clean layout for visible selection normalization. - frame.GetDocument()->UpdateStyleAndLayout(); + frame.GetDocument()->UpdateStyleAndLayout(DocumentUpdateReason::kEditing); frame.GetEditor().AddToKillRing(frame.GetEditor().SelectedRange()); // TODO(editing-dev): |Editor::performDelete()| has no direction. @@ -571,7 +571,7 @@ static bool ExecuteDeleteToMark(LocalFrame& frame, // TODO(editing-dev): The use of UpdateStyleAndLayout // needs to be audited. See http://crbug.com/590369 for more details. - frame.GetDocument()->UpdateStyleAndLayout(); + frame.GetDocument()->UpdateStyleAndLayout(DocumentUpdateReason::kEditing); frame.GetEditor().SetMark(); return true; } @@ -754,7 +754,8 @@ static bool ExecuteScrollPageBackward(LocalFrame& frame, EditorCommandSource, const String&) { return frame.GetEventHandler().BubblingScroll( - kScrollBlockDirectionBackward, ScrollGranularity::kScrollByPage); + mojom::blink::ScrollDirection::kScrollBlockDirectionBackward, + ScrollGranularity::kScrollByPage); } static bool ExecuteScrollPageForward(LocalFrame& frame, @@ -762,7 +763,8 @@ static bool ExecuteScrollPageForward(LocalFrame& frame, EditorCommandSource, const String&) { return frame.GetEventHandler().BubblingScroll( - kScrollBlockDirectionForward, ScrollGranularity::kScrollByPage); + mojom::blink::ScrollDirection::kScrollBlockDirectionForward, + ScrollGranularity::kScrollByPage); } static bool ExecuteScrollLineUp(LocalFrame& frame, @@ -770,7 +772,8 @@ static bool ExecuteScrollLineUp(LocalFrame& frame, EditorCommandSource, const String&) { return frame.GetEventHandler().BubblingScroll( - kScrollUpIgnoringWritingMode, ScrollGranularity::kScrollByLine); + mojom::blink::ScrollDirection::kScrollUpIgnoringWritingMode, + ScrollGranularity::kScrollByLine); } static bool ExecuteScrollLineDown(LocalFrame& frame, @@ -778,7 +781,8 @@ static bool ExecuteScrollLineDown(LocalFrame& frame, EditorCommandSource, const String&) { return frame.GetEventHandler().BubblingScroll( - kScrollDownIgnoringWritingMode, ScrollGranularity::kScrollByLine); + mojom::blink::ScrollDirection::kScrollDownIgnoringWritingMode, + ScrollGranularity::kScrollByLine); } static bool ExecuteScrollToBeginningOfDocument(LocalFrame& frame, @@ -786,7 +790,8 @@ static bool ExecuteScrollToBeginningOfDocument(LocalFrame& frame, EditorCommandSource, const String&) { return frame.GetEventHandler().BubblingScroll( - kScrollBlockDirectionBackward, ScrollGranularity::kScrollByDocument); + mojom::blink::ScrollDirection::kScrollBlockDirectionBackward, + ScrollGranularity::kScrollByDocument); } static bool ExecuteScrollToEndOfDocument(LocalFrame& frame, @@ -794,7 +799,8 @@ static bool ExecuteScrollToEndOfDocument(LocalFrame& frame, EditorCommandSource, const String&) { return frame.GetEventHandler().BubblingScroll( - kScrollBlockDirectionForward, ScrollGranularity::kScrollByDocument); + mojom::blink::ScrollDirection::kScrollBlockDirectionForward, + ScrollGranularity::kScrollByDocument); } static bool ExecuteSelectAll(LocalFrame& frame, @@ -893,7 +899,7 @@ static bool ExecuteTranspose(LocalFrame& frame, // TODO(editing-dev): The use of UpdateStyleAndLayout // needs to be audited. See http://crbug.com/590369 for more details. - document->UpdateStyleAndLayout(); + document->UpdateStyleAndLayout(DocumentUpdateReason::kEditing); const EphemeralRange& range = ComputeRangeForTranspose(frame); if (range.IsNull()) @@ -919,7 +925,7 @@ static bool ExecuteTranspose(LocalFrame& frame, // TODO(editing-dev): The use of UpdateStyleAndLayout // needs to be audited. See http://crbug.com/590369 for more details. - document->UpdateStyleAndLayout(); + document->UpdateStyleAndLayout(DocumentUpdateReason::kEditing); // 'beforeinput' event handler may change selection, we need to re-calculate // range. @@ -987,7 +993,7 @@ static bool ExecuteYank(LocalFrame& frame, // TODO(editing-dev): The use of UpdateStyleAndLayout // needs to be audited. see http://crbug.com/590369 for more details. - frame.GetDocument()->UpdateStyleAndLayout(); + frame.GetDocument()->UpdateStyleAndLayout(DocumentUpdateReason::kEditing); frame.GetEditor().InsertTextWithoutSendingTextEvent( yank_string, false, nullptr, InputEvent::InputType::kInsertFromYank); @@ -1012,7 +1018,7 @@ static bool ExecuteYankAndSelect(LocalFrame& frame, // TODO(editing-dev): The use of UpdateStyleAndLayout // needs to be audited. see http://crbug.com/590369 for more details. - frame.GetDocument()->UpdateStyleAndLayout(); + frame.GetDocument()->UpdateStyleAndLayout(DocumentUpdateReason::kEditing); frame.GetEditor().InsertTextWithoutSendingTextEvent( frame.GetEditor().GetKillRing().Yank(), true, nullptr, @@ -1040,7 +1046,7 @@ static bool Enabled(LocalFrame&, Event*, EditorCommandSource) { static bool EnabledVisibleSelection(LocalFrame& frame, Event* event, EditorCommandSource source) { - frame.GetDocument()->UpdateStyleAndLayout(); + frame.GetDocument()->UpdateStyleAndLayout(DocumentUpdateReason::kEditing); if (source == EditorCommandSource::kMenuOrKeyBinding && !frame.Selection().SelectionHasFocus()) @@ -1058,7 +1064,7 @@ static bool EnabledVisibleSelection(LocalFrame& frame, static bool EnabledVisibleSelectionAndMark(LocalFrame& frame, Event* event, EditorCommandSource source) { - frame.GetDocument()->UpdateStyleAndLayout(); + frame.GetDocument()->UpdateStyleAndLayout(DocumentUpdateReason::kEditing); if (source == EditorCommandSource::kMenuOrKeyBinding && !frame.Selection().SelectionHasFocus()) @@ -1075,7 +1081,7 @@ static bool EnabledVisibleSelectionAndMark(LocalFrame& frame, static bool EnableCaretInEditableText(LocalFrame& frame, Event* event, EditorCommandSource source) { - frame.GetDocument()->UpdateStyleAndLayout(); + frame.GetDocument()->UpdateStyleAndLayout(DocumentUpdateReason::kEditing); if (source == EditorCommandSource::kMenuOrKeyBinding && !frame.Selection().SelectionHasFocus()) @@ -1088,7 +1094,7 @@ static bool EnableCaretInEditableText(LocalFrame& frame, static bool EnabledInEditableText(LocalFrame& frame, Event* event, EditorCommandSource source) { - frame.GetDocument()->UpdateStyleAndLayout(); + frame.GetDocument()->UpdateStyleAndLayout(DocumentUpdateReason::kEditing); if (source == EditorCommandSource::kMenuOrKeyBinding && !frame.Selection().SelectionHasFocus()) return false; @@ -1124,7 +1130,7 @@ static bool EnabledDelete(LocalFrame& frame, static bool EnabledInRichlyEditableText(LocalFrame& frame, Event*, EditorCommandSource source) { - frame.GetDocument()->UpdateStyleAndLayout(); + frame.GetDocument()->UpdateStyleAndLayout(DocumentUpdateReason::kEditing); if (source == EditorCommandSource::kMenuOrKeyBinding && !frame.Selection().SelectionHasFocus()) return false; @@ -1137,7 +1143,7 @@ static bool EnabledInRichlyEditableText(LocalFrame& frame, static bool EnabledRangeInEditableText(LocalFrame& frame, Event*, EditorCommandSource source) { - frame.GetDocument()->UpdateStyleAndLayout(); + frame.GetDocument()->UpdateStyleAndLayout(DocumentUpdateReason::kEditing); if (source == EditorCommandSource::kMenuOrKeyBinding && !frame.Selection().SelectionHasFocus()) return false; @@ -1152,7 +1158,7 @@ static bool EnabledRangeInEditableText(LocalFrame& frame, static bool EnabledRangeInRichlyEditableText(LocalFrame& frame, Event*, EditorCommandSource source) { - frame.GetDocument()->UpdateStyleAndLayout(); + frame.GetDocument()->UpdateStyleAndLayout(DocumentUpdateReason::kEditing); if (source == EditorCommandSource::kMenuOrKeyBinding && !frame.Selection().SelectionHasFocus()) return false; @@ -1172,7 +1178,7 @@ static bool EnabledUndo(LocalFrame& frame, Event*, EditorCommandSource) { static bool EnabledUnselect(LocalFrame& frame, Event* event, EditorCommandSource) { - frame.GetDocument()->UpdateStyleAndLayout(); + frame.GetDocument()->UpdateStyleAndLayout(DocumentUpdateReason::kEditing); // The term "visible" here includes a caret in editable text or a range in any // text. @@ -1187,7 +1193,7 @@ static bool EnabledSelectAll(LocalFrame& frame, EditorCommandSource source) { // TODO(editing-dev): The use of UpdateStyleAndLayout // needs to be audited. See http://crbug.com/590369 for more details. - frame.GetDocument()->UpdateStyleAndLayout(); + frame.GetDocument()->UpdateStyleAndLayout(DocumentUpdateReason::kEditing); const VisibleSelection& selection = frame.Selection().ComputeVisibleSelectionInDOMTree(); if (selection.IsNone()) @@ -1853,7 +1859,8 @@ bool Editor::ExecuteCommand(const String& command_name) { if (command_name == "AdvanceToNextMisspelling") { // TODO(editing-dev): Use of UpdateStyleAndLayout // needs to be audited. see http://crbug.com/590369 for more details. - GetFrame().GetDocument()->UpdateStyleAndLayout(); + GetFrame().GetDocument()->UpdateStyleAndLayout( + DocumentUpdateReason::kEditing); // We need to pass false here or else the currently selected word will never // be skipped. @@ -1864,7 +1871,8 @@ bool Editor::ExecuteCommand(const String& command_name) { // TODO(editing-dev): Use of UpdateStyleAndLayout // needs to be audited. // see http://crbug.com/590369 for more details. - GetFrame().GetDocument()->UpdateStyleAndLayout(); + GetFrame().GetDocument()->UpdateStyleAndLayout( + DocumentUpdateReason::kEditing); GetSpellChecker().ShowSpellingGuessPanel(); return true; @@ -1878,18 +1886,21 @@ bool Editor::ExecuteCommand(const String& command_name, const String& value) { DCHECK(GetFrame().GetDocument()->IsActive()); if (!CanEdit() && command_name == "moveToBeginningOfDocument") { return GetFrame().GetEventHandler().BubblingScroll( - kScrollUpIgnoringWritingMode, ScrollGranularity::kScrollByDocument); + mojom::blink::ScrollDirection::kScrollUpIgnoringWritingMode, + ScrollGranularity::kScrollByDocument); } if (!CanEdit() && command_name == "moveToEndOfDocument") { return GetFrame().GetEventHandler().BubblingScroll( - kScrollDownIgnoringWritingMode, ScrollGranularity::kScrollByDocument); + mojom::blink::ScrollDirection::kScrollDownIgnoringWritingMode, + ScrollGranularity::kScrollByDocument); } if (command_name == "ToggleSpellPanel") { // TODO(editing-dev): Use of UpdateStyleAndLayout // needs to be audited. see http://crbug.com/590369 for more details. - GetFrame().GetDocument()->UpdateStyleAndLayout(); + GetFrame().GetDocument()->UpdateStyleAndLayout( + DocumentUpdateReason::kEditing); GetSpellChecker().ShowSpellingGuessPanel(); return true; @@ -1903,7 +1914,9 @@ bool Editor::IsCommandEnabled(const String& command_name) const { } EditorCommand::EditorCommand() - : command_(nullptr), source_(EditorCommandSource::kMenuOrKeyBinding) {} + : command_(nullptr), + source_(EditorCommandSource::kMenuOrKeyBinding), + frame_(nullptr) {} EditorCommand::EditorCommand(const EditorInternalCommand* command, EditorCommandSource source, @@ -1940,7 +1953,8 @@ bool EditorCommand::Execute(const String& parameter, } } - GetFrame().GetDocument()->UpdateStyleAndLayout(); + GetFrame().GetDocument()->UpdateStyleAndLayout( + DocumentUpdateReason::kEditing); DEFINE_STATIC_LOCAL(SparseHistogram, command_histogram, ("WebCore.Editing.Commands")); command_histogram.Sample(static_cast<int>(command_->command_type)); @@ -1964,7 +1978,7 @@ bool EditorCommand::IsSupported() const { case EditorCommandSource::kMenuOrKeyBinding: return true; case EditorCommandSource::kDOM: - return command_->is_supported_from_dom(frame_.Get()); + return command_->is_supported_from_dom(frame_); } NOTREACHED(); return false; diff --git a/chromium/third_party/blink/renderer/core/editing/commands/editor_command.h b/chromium/third_party/blink/renderer/core/editing/commands/editor_command.h index 0cee2e65931..41e3e935b73 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/editor_command.h +++ b/chromium/third_party/blink/renderer/core/editing/commands/editor_command.h @@ -76,7 +76,7 @@ class CORE_EXPORT EditorCommand { const EditorInternalCommand* command_; const EditorCommandSource source_; - const Member<LocalFrame> frame_; + LocalFrame* const frame_; }; } // namespace blink diff --git a/chromium/third_party/blink/renderer/core/editing/commands/format_block_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/format_block_command.cc index fe177074549..5cecaf62ad7 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/format_block_command.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/format_block_command.cc @@ -89,7 +89,7 @@ void FormatBlockCommand::FormatRange(const Position& start, Node* node_after_insertion_position = outer_block; const EphemeralRange range(start, end_of_selection); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); if (IsElementForFormatBlock(ref_element->TagQName()) && CreateVisiblePosition(start).DeepEquivalent() == StartOfBlock(CreateVisiblePosition(start)).DeepEquivalent() && @@ -112,7 +112,7 @@ void FormatBlockCommand::FormatRange(const Position& start, editing_state); if (editing_state->IsAborted()) return; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); } Position last_paragraph_in_block_node = @@ -146,7 +146,7 @@ void FormatBlockCommand::FormatRange(const Position& start, ->getAttribute(html_names::kStyleAttr)); } - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); if (was_end_of_paragraph && !IsEndOfParagraph(CreateVisiblePosition(last_paragraph_in_block_node)) && diff --git a/chromium/third_party/blink/renderer/core/editing/commands/indent_outdent_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/indent_outdent_command.cc index d251d94704d..177107431ac 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/indent_outdent_command.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/indent_outdent_command.cc @@ -98,7 +98,7 @@ bool IndentOutdentCommand::TryIndentingAsListItem(const Position& start, if (editing_state->IsAborted()) return false; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); // We should clone all the children of the list item for indenting purposes. // However, in case the current selection does not encompass all its children, @@ -134,7 +134,7 @@ bool IndentOutdentCommand::TryIndentingAsListItem(const Position& start, return false; } - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); DCHECK(new_list); if (previous_list && CanMergeLists(*previous_list, *new_list)) { MergeIdenticalElements(previous_list, new_list, editing_state); @@ -142,7 +142,7 @@ bool IndentOutdentCommand::TryIndentingAsListItem(const Position& start, return false; } - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); if (next_list && CanMergeLists(*new_list, *next_list)) { MergeIdenticalElements(new_list, next_list, editing_state); if (editing_state->IsAborted()) @@ -173,7 +173,7 @@ void IndentOutdentCommand::IndentIntoBlockquote(const Position& start, ? start.ComputeContainerNode() : SplitTreeToNode(start.ComputeContainerNode(), element_to_split_to); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); VisiblePosition start_of_contents = CreateVisiblePosition(start); if (!target_blockquote) { // Create a new blockquote and insert it as a child of the root editable @@ -191,7 +191,7 @@ void IndentOutdentCommand::IndentIntoBlockquote(const Position& start, InsertNodeBefore(target_blockquote, outer_block, editing_state); if (editing_state->IsAborted()) return; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); start_of_contents = VisiblePosition::InParentAfterNode(*target_blockquote); } @@ -268,7 +268,7 @@ void IndentOutdentCommand::OutdentParagraph(EditingState* editing_state) { } } - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); visible_start_of_paragraph = CreateVisiblePosition(visible_start_of_paragraph.DeepEquivalent()); if (visible_start_of_paragraph.IsNotNull() && @@ -279,7 +279,7 @@ void IndentOutdentCommand::OutdentParagraph(EditingState* editing_state) { return; } - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); visible_end_of_paragraph = CreateVisiblePosition(visible_end_of_paragraph.DeepEquivalent()); if (visible_end_of_paragraph.IsNotNull() && @@ -324,7 +324,7 @@ void IndentOutdentCommand::OutdentParagraph(EditingState* editing_state) { : visible_start_of_paragraph.DeepEquivalent().AnchorNode()); } - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); // Re-canonicalize visible{Start,End}OfParagraph, make them valid again // after DOM change. @@ -351,7 +351,7 @@ void IndentOutdentCommand::OutdentParagraph(EditingState* editing_state) { if (editing_state->IsAborted()) return; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); start_of_paragraph_to_move = CreateVisiblePosition( start_of_paragraph_to_move.ToPositionWithAffinity()); end_of_paragraph_to_move = @@ -407,7 +407,7 @@ void IndentOutdentCommand::OutdentRegion( if (end_after_selection.IsNotNull() && !end_after_selection.IsConnected()) break; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); if (end_of_next_paragraph.IsNotNull() && !end_of_next_paragraph.IsConnected()) { end_of_current_paragraph = diff --git a/chromium/third_party/blink/renderer/core/editing/commands/insert_incremental_text_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/insert_incremental_text_command.cc index 9df720b50ed..be0e603a835 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/insert_incremental_text_command.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/insert_incremental_text_command.cc @@ -118,14 +118,6 @@ SelectionInDOMTree ComputeSelectionForInsertion( } // anonymous namespace -InsertIncrementalTextCommand* InsertIncrementalTextCommand::Create( - Document& document, - const String& text, - RebalanceType rebalance_type) { - return MakeGarbageCollected<InsertIncrementalTextCommand>(document, text, - rebalance_type); -} - InsertIncrementalTextCommand::InsertIncrementalTextCommand( Document& document, const String& text, diff --git a/chromium/third_party/blink/renderer/core/editing/commands/insert_incremental_text_command.h b/chromium/third_party/blink/renderer/core/editing/commands/insert_incremental_text_command.h index 165a04a8be1..324767a1a4d 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/insert_incremental_text_command.h +++ b/chromium/third_party/blink/renderer/core/editing/commands/insert_incremental_text_command.h @@ -12,15 +12,11 @@ namespace blink { class CORE_EXPORT InsertIncrementalTextCommand final : public InsertTextCommand { public: - static InsertIncrementalTextCommand* Create( + InsertIncrementalTextCommand( Document&, - const String&, + const String& text, RebalanceType = kRebalanceLeadingAndTrailingWhitespaces); - InsertIncrementalTextCommand(Document&, - const String& text, - RebalanceType); - private: void DoApply(EditingState*) override; }; diff --git a/chromium/third_party/blink/renderer/core/editing/commands/insert_incremental_text_command_test.cc b/chromium/third_party/blink/renderer/core/editing/commands/insert_incremental_text_command_test.cc index b36ae21d721..881c52bec7f 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/insert_incremental_text_command_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/insert_incremental_text_command_test.cc @@ -7,6 +7,7 @@ #include "third_party/blink/renderer/core/editing/frame_selection.h" #include "third_party/blink/renderer/core/editing/selection_template.h" #include "third_party/blink/renderer/core/editing/testing/editing_test_base.h" +#include "third_party/blink/renderer/platform/heap/heap.h" namespace blink { @@ -23,7 +24,8 @@ TEST_F(InsertIncrementalTextCommandTest, SurrogatePairsReplace) { .Build(), SetSelectionOptions()); CompositeEditCommand* const command = - InsertIncrementalTextCommand::Create(GetDocument(), new_text); + MakeGarbageCollected<InsertIncrementalTextCommand>(GetDocument(), + new_text); command->Apply(); EXPECT_EQ(String(Vector<UChar>{'b', 0xD83D, 0xDE38}), @@ -41,7 +43,8 @@ TEST_F(InsertIncrementalTextCommandTest, SurrogatePairsNoReplace) { .Build(), SetSelectionOptions()); CompositeEditCommand* const command = - InsertIncrementalTextCommand::Create(GetDocument(), new_text); + MakeGarbageCollected<InsertIncrementalTextCommand>(GetDocument(), + new_text); command->Apply(); EXPECT_EQ(String(Vector<UChar>{'b', 0xD83D, 0xDE3A}), @@ -61,7 +64,8 @@ TEST_F(InsertIncrementalTextCommandTest, SurrogatePairsTwo) { .Build(), SetSelectionOptions()); CompositeEditCommand* const command = - InsertIncrementalTextCommand::Create(GetDocument(), new_text); + MakeGarbageCollected<InsertIncrementalTextCommand>(GetDocument(), + new_text); command->Apply(); EXPECT_EQ(String(Vector<UChar>{'b', 0xD83D, 0xDE38}), diff --git a/chromium/third_party/blink/renderer/core/editing/commands/insert_into_text_node_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/insert_into_text_node_command.cc index 4969f958e52..89293666dba 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/insert_into_text_node_command.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/insert_into_text_node_command.cc @@ -50,8 +50,9 @@ void InsertIntoTextNodeCommand::DoApply(EditingState*) { bool password_echo_enabled = GetDocument().GetSettings() && GetDocument().GetSettings()->GetPasswordEchoEnabled(); - if (password_echo_enabled) - GetDocument().UpdateStyleAndLayout(); + if (password_echo_enabled) { + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); + } if (!HasEditableStyle(*node_)) return; diff --git a/chromium/third_party/blink/renderer/core/editing/commands/insert_line_break_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/insert_line_break_command.cc index 40f823a5cf1..fe3f95f7da5 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/insert_line_break_command.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/insert_line_break_command.cc @@ -68,7 +68,7 @@ void InsertLineBreakCommand::DoApply(EditingState* editing_state) { if (!DeleteSelection(editing_state, DeleteSelectionOptions::NormalDelete())) return; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); VisibleSelection selection = EndingVisibleSelection(); if (selection.IsNone() || selection.Start().IsOrphan() || @@ -98,7 +98,7 @@ void InsertLineBreakCommand::DoApply(EditingState* editing_state) { else node_to_insert = GetDocument().createTextNode("\n"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); // FIXME: Need to merge text nodes when inserting just after or before text. @@ -137,7 +137,7 @@ void InsertLineBreakCommand::DoApply(EditingState* editing_state) { InsertNodeAt(node_to_insert, pos, editing_state); if (editing_state->IsAborted()) return; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); // Insert an extra br or '\n' if the just inserted one collapsed. if (!IsStartOfParagraph(VisiblePosition::BeforeNode(*node_to_insert))) { @@ -172,7 +172,7 @@ void InsertLineBreakCommand::DoApply(EditingState* editing_state) { Position ending_position = Position::FirstPositionInNode(*text_node); // Handle whitespace that occurs after the split - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); if (!IsRenderedCharacter(ending_position)) { Position position_before_text_node( Position::InParentBeforeNode(*text_node)); diff --git a/chromium/third_party/blink/renderer/core/editing/commands/insert_list_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/insert_list_command.cc index 45eabd837e1..e569395f451 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/insert_list_command.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/insert_list_command.cc @@ -75,7 +75,7 @@ HTMLElement* InsertListCommand::MergeWithNeighboringLists( DCHECK(passed_list); HTMLElement* list = passed_list; Element* previous_list = ElementTraversal::PreviousSibling(*list); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); if (previous_list && CanMergeLists(*previous_list, *list)) { MergeIdenticalElements(previous_list, list, editing_state); if (editing_state->IsAborted()) @@ -90,7 +90,7 @@ HTMLElement* InsertListCommand::MergeWithNeighboringLists( if (!next_list) return list; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); if (CanMergeLists(*list, *next_list)) { MergeIdenticalElements(list, next_list, editing_state); if (editing_state->IsAborted()) @@ -244,7 +244,7 @@ void InsertListCommand::DoApply(EditingState* editing_state) { if (!single_paragraph_result) break; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); // Make |visibleEndOfSelection| valid again. if (!end_of_selection.IsConnected() || @@ -280,7 +280,7 @@ void InsertListCommand::DoApply(EditingState* editing_state) { if (editing_state->IsAborted()) return; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); // Fetch the end of the selection, for the reason mentioned above. if (!end_of_selection.IsConnected()) { @@ -358,7 +358,7 @@ bool InsertListCommand::DoApplyForSingleParagraph( list_element = MergeWithNeighboringLists(list_element, editing_state); if (editing_state->IsAborted()) return false; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); } DCHECK(HasEditableStyle(*list_element)); DCHECK(HasEditableStyle(*list_element->parentNode())); @@ -393,7 +393,7 @@ bool InsertListCommand::DoApplyForSingleParagraph( if (editing_state->IsAborted()) return false; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); Node* first_child_in_list = EnclosingListChild(VisiblePosition::FirstPositionInNode(*list_element) .DeepEquivalent() @@ -449,7 +449,7 @@ bool InsertListCommand::DoApplyForSingleParagraph( list_child_node, editing_state); if (editing_state->IsAborted()) return false; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); } if (!list_child_node || switch_list_type || force_create_list) { @@ -538,7 +538,7 @@ void InsertListCommand::UnlistifyParagraph( if (editing_state->IsAborted()) return; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); // Make |start| and |end| valid again. start = CreateVisiblePosition(start_position); @@ -604,7 +604,7 @@ void InsertListCommand::ListifyParagraph(const VisiblePosition& original_start, if (editing_state->IsAborted()) return; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); if (previous_list && next_list && CanMergeLists(*previous_list, *next_list)) MergeIdenticalElements(previous_list, next_list, editing_state); @@ -626,7 +626,7 @@ void InsertListCommand::ListifyParagraph(const VisiblePosition& original_start, start_pos = Position::BeforeNode(*placeholder); } - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); // Insert the list at a position visually equivalent to start of the // paragraph that is being moved into the list. @@ -669,7 +669,7 @@ void InsertListCommand::ListifyParagraph(const VisiblePosition& original_start, MoveParagraphOverPositionIntoEmptyListItem( original_start, list_item_element, editing_state); } else { - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); MoveParagraphOverPositionIntoEmptyListItem( CreateVisiblePosition(start_pos), list_item_element, editing_state); } @@ -692,7 +692,7 @@ void InsertListCommand::MoveParagraphOverPositionIntoEmptyListItem( return; // Inserting list element and list item list may change start of pargraph // to move. We calculate start of paragraph again. - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); const VisiblePosition& valid_pos = CreateVisiblePosition(pos.ToPositionWithAffinity()); const VisiblePosition& start = diff --git a/chromium/third_party/blink/renderer/core/editing/commands/insert_list_command_test.cc b/chromium/third_party/blink/renderer/core/editing/commands/insert_list_command_test.cc index 727520dfd17..97a9ca423b2 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/insert_list_command_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/insert_list_command_test.cc @@ -48,8 +48,7 @@ TEST_F(InsertListCommandTest, ShouldCleanlyRemoveSpuriousTextNode) { // This should not DCHECK. EXPECT_TRUE(command->Apply()) << "The insert ordered list command should have succeeded"; - EXPECT_EQ("<ol><li>\nd\n</li></ol>", - GetDocument().body()->InnerHTMLAsString()); + EXPECT_EQ("<ol><li>\nd\n</li></ol>", GetDocument().body()->innerHTML()); } // Refer https://crbug.com/794356 diff --git a/chromium/third_party/blink/renderer/core/editing/commands/insert_paragraph_separator_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/insert_paragraph_separator_command.cc index d6b3421d0d2..8e5acdce6ee 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/insert_paragraph_separator_command.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/insert_paragraph_separator_command.cc @@ -193,7 +193,7 @@ void InsertParagraphSeparatorCommand::DoApply(EditingState* editing_state) { // Delete the current selection. if (EndingSelection().IsRange()) { - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); CalculateStyleBeforeInsertion(insertion_position); if (!DeleteSelection(editing_state, DeleteSelectionOptions::NormalDelete())) return; @@ -203,7 +203,7 @@ void InsertParagraphSeparatorCommand::DoApply(EditingState* editing_state) { affinity = visble_selection_after_delete.Affinity(); } - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); // FIXME: The parentAnchoredEquivalent conversion needs to be moved into // enclosingBlock. @@ -252,7 +252,7 @@ void InsertParagraphSeparatorCommand::DoApply(EditingState* editing_state) { To<HTMLElement>(EnclosingAnchorElement(original_insertion_position)); } - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); CalculateStyleBeforeInsertion(insertion_position); //--------------------------------------------------------------------- @@ -387,7 +387,7 @@ void InsertParagraphSeparatorCommand::DoApply(EditingState* editing_state) { ref_node = insertion_position.AnchorNode(); } - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); // find ending selection position easily before inserting the paragraph insertion_position = MostForwardCaretPosition(insertion_position); @@ -436,7 +436,7 @@ void InsertParagraphSeparatorCommand::DoApply(EditingState* editing_state) { InsertNodeAt(br, insertion_position, editing_state); if (editing_state->IsAborted()) return; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); insertion_position = Position::InParentAfterNode(*br); visible_pos = CreateVisiblePosition(insertion_position); @@ -493,7 +493,7 @@ void InsertParagraphSeparatorCommand::DoApply(EditingState* editing_state) { ReplaceTextInNode(text_node, leading_whitespace.ComputeOffsetInContainerNode(), 1, NonBreakingSpaceString()); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); } } @@ -506,7 +506,7 @@ void InsertParagraphSeparatorCommand::DoApply(EditingState* editing_state) { bool at_end = static_cast<unsigned>(text_offset) >= text_node->length(); if (text_offset > 0 && !at_end) { SplitTextNode(text_node, text_offset); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); position_after_split = Position::FirstPositionInNode(*text_node); insertion_position = @@ -534,7 +534,7 @@ void InsertParagraphSeparatorCommand::DoApply(EditingState* editing_state) { if (editing_state->IsAborted()) return; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); visible_pos = CreateVisiblePosition(insertion_position); // If the paragraph separator was inserted at the end of a paragraph, an empty @@ -547,7 +547,7 @@ void InsertParagraphSeparatorCommand::DoApply(EditingState* editing_state) { block_to_insert, editing_state); if (editing_state->IsAborted()) return; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); } // Move the start node and the siblings of the start node. @@ -565,7 +565,7 @@ void InsertParagraphSeparatorCommand::DoApply(EditingState* editing_state) { if (split_to) SplitTreeToNode(split_to, start_block); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); for (n = start_block->firstChild(); n; n = n->nextSibling()) { VisiblePosition before_node_position = VisiblePosition::BeforeNode(*n); @@ -584,7 +584,7 @@ void InsertParagraphSeparatorCommand::DoApply(EditingState* editing_state) { // Handle whitespace that occurs after the split if (position_after_split.IsNotNull()) { - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); if (!IsRenderedCharacter(position_after_split)) { // Clear out all whitespace and insert one non-breaking space DCHECK(!position_after_split.ComputeContainerNode()->GetLayoutObject() || diff --git a/chromium/third_party/blink/renderer/core/editing/commands/insert_paragraph_separator_command_test.cc b/chromium/third_party/blink/renderer/core/editing/commands/insert_paragraph_separator_command_test.cc index f93883a02cd..c4f9bc8e5c7 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/insert_paragraph_separator_command_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/insert_paragraph_separator_command_test.cc @@ -69,7 +69,7 @@ TEST_F(InsertParagraphSeparatorCommandTest, CrashWithCaptionBeforeBody) { // Insert <caption> between head and body Element* caption = GetDocument().CreateElementForBinding("caption"); - caption->SetInnerHTMLFromString("AxBxC"); + caption->setInnerHTML("AxBxC"); GetDocument().documentElement()->insertBefore(caption, GetDocument().body()); Selection().SetSelection( diff --git a/chromium/third_party/blink/renderer/core/editing/commands/insert_text_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/insert_text_command.cc index b7bd0eaa042..d59c6167bf5 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/insert_text_command.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/insert_text_command.cc @@ -157,7 +157,7 @@ void InsertTextCommand::DoApply(EditingState* editing_state) { if (EndingSelection().IsRange()) { if (PerformTrivialReplace(text_)) return; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); bool end_of_selection_was_at_start_of_block = IsStartOfBlock(EndingVisibleSelection().VisibleEnd()); if (!DeleteSelection(editing_state, DeleteSelectionOptions::Builder() @@ -174,14 +174,14 @@ void InsertTextCommand::DoApply(EditingState* editing_state) { if (end_of_selection_was_at_start_of_block) { if (EditingStyle* typing_style = GetDocument().GetFrame()->GetEditor().TypingStyle()) - typing_style->RemoveBlockProperties(); + typing_style->RemoveBlockProperties(GetDocument().ToExecutionContext()); } } else if (GetDocument().GetFrame()->GetEditor().IsOverwriteModeEnabled()) { if (PerformOverwrite(text_)) return; } - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); // Reached by InsertTextCommandTest.NoVisibleSelectionAfterDeletingSelection ABORT_EDITING_COMMAND_IF(EndingVisibleSelection().IsNone()); @@ -222,7 +222,7 @@ void InsertTextCommand::DoApply(EditingState* editing_state) { // TODO(editing-dev): Use of UpdateStyleAndLayout() // needs to be audited. See http://crbug.com/590369 for more details. - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); if (!start_position.IsConnected()) start_position = position_before_start_node; @@ -302,7 +302,7 @@ void InsertTextCommand::DoApply(EditingState* editing_state) { Position InsertTextCommand::InsertTab(const Position& pos, EditingState* editing_state) { - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); Position insert_pos = CreateVisiblePosition(pos).DeepEquivalent(); if (insert_pos.IsNull()) diff --git a/chromium/third_party/blink/renderer/core/editing/commands/insert_text_command_test.cc b/chromium/third_party/blink/renderer/core/editing/commands/insert_text_command_test.cc index 72d7153b370..14d4cfff12e 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/insert_text_command_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/insert_text_command_test.cc @@ -29,7 +29,7 @@ TEST_F(InsertTextCommandTest, WithTypingStyle) { EXPECT_EQ( "<div contenteditable=\"true\"><option id=\"sample\">x</option></div>", - GetDocument().body()->InnerHTMLAsString()) + GetDocument().body()->innerHTML()) << "Content of OPTION is distributed into shadow node as text" "without applying typing style."; } @@ -282,7 +282,7 @@ TEST_F(InsertTextCommandTest, AnchorElementWithBlockCrash) { Element* iElement = GetDocument().CreateRawElement(html_names::kITag); nested_anchor->setAttribute("href", "www"); - iElement->SetInnerHTMLFromString("home"); + iElement->setInnerHTML("home"); anchor->AppendChild(nested_anchor); nested_anchor->AppendChild(iElement); diff --git a/chromium/third_party/blink/renderer/core/editing/commands/move_commands.cc b/chromium/third_party/blink/renderer/core/editing/commands/move_commands.cc index f11ec20005c..83f4c4ef317 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/move_commands.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/move_commands.cc @@ -31,6 +31,7 @@ #include "third_party/blink/renderer/core/editing/commands/move_commands.h" +#include "third_party/blink/public/mojom/input/focus_type.mojom-blink.h" #include "third_party/blink/renderer/core/dom/node_computed_style.h" #include "third_party/blink/renderer/core/editing/editing_behavior.h" #include "third_party/blink/renderer/core/editing/editing_utilities.h" @@ -143,8 +144,8 @@ void MoveCommands::UpdateFocusForCaretBrowsing(LocalFrame& frame) { Element* new_focused_element = nullptr; while (node) { - if (node->IsElementNode() && ToElement(node)->IsFocusable()) { - new_focused_element = ToElement(node); + if (node->IsElementNode() && To<Element>(node)->IsFocusable()) { + new_focused_element = To<Element>(node); break; } node = node->ParentOrShadowHostNode(); @@ -155,7 +156,8 @@ void MoveCommands::UpdateFocusForCaretBrowsing(LocalFrame& frame) { frame.GetDocument()->SetFocusedElement( new_focused_element, - FocusParams(SelectionBehaviorOnFocus::kNone, kWebFocusTypeNone, nullptr)); + FocusParams(SelectionBehaviorOnFocus::kNone, + mojom::blink::FocusType::kNone, nullptr)); } void MoveCommands::UpdateSelectionForCaretBrowsing(LocalFrame& frame) { diff --git a/chromium/third_party/blink/renderer/core/editing/commands/move_commands_test.cc b/chromium/third_party/blink/renderer/core/editing/commands/move_commands_test.cc index 7de107b8210..f3e7cffdbd2 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/move_commands_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/move_commands_test.cc @@ -5,6 +5,7 @@ #include <string> #include "build/build_config.h" +#include "third_party/blink/public/mojom/input/focus_type.mojom-blink.h" #include "third_party/blink/renderer/core/dom/element.h" #include "third_party/blink/renderer/core/editing/commands/move_commands.h" #include "third_party/blink/renderer/core/editing/editor.h" @@ -27,8 +28,8 @@ class MoveCommandsTest : public EditingTestBase { SetSelectionOptions()); GetDocument().SetFocusedElement( GetDocument().QuerySelector(initial_focus_element), - FocusParams(SelectionBehaviorOnFocus::kNone, kWebFocusTypeNone, - nullptr)); + FocusParams(SelectionBehaviorOnFocus::kNone, + mojom::blink::FocusType::kNone, nullptr)); GetDocument().GetFrame()->GetSettings()->SetCaretBrowsingEnabled(true); execute(*GetDocument().GetFrame(), nullptr, EditorCommandSource::kMenuOrKeyBinding, String()); @@ -316,7 +317,8 @@ TEST_F(MoveCommandsTest, CaretBrowsingSelectionUpdate) { SetSelectionOptions()); GetDocument().SetFocusedElement( GetDocument().QuerySelector("a"), - FocusParams(SelectionBehaviorOnFocus::kNone, kWebFocusTypeNone, nullptr)); + FocusParams(SelectionBehaviorOnFocus::kNone, + mojom::blink::FocusType::kNone, nullptr)); GetDocument().GetFrame()->GetSettings()->SetCaretBrowsingEnabled(true); MoveCommands::ExecuteMoveRight(*GetDocument().GetFrame(), nullptr, EditorCommandSource::kMenuOrKeyBinding, diff --git a/chromium/third_party/blink/renderer/core/editing/commands/replace_selection_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/replace_selection_command.cc index 708ee997b89..f2ad9e8cd10 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/replace_selection_command.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/replace_selection_command.cc @@ -105,8 +105,8 @@ class ReplacementFragment final { void InsertNodeBefore(Node*, Node* ref_node); - Member<Document> document_; - Member<DocumentFragment> fragment_; + Document* document_; + DocumentFragment* fragment_; bool has_interchange_newline_at_start_; bool has_interchange_newline_at_end_; @@ -175,7 +175,7 @@ ReplacementFragment::ReplacementFragment(Document* document, if (!editable_root) return; - document_->UpdateStyleAndLayout(); + document_->UpdateStyleAndLayout(DocumentUpdateReason::kEditing); Element* shadow_ancestor_element; if (editable_root->IsInShadowTree()) @@ -191,7 +191,7 @@ ReplacementFragment::ReplacementFragment(Document* document, !(shadow_ancestor_element && shadow_ancestor_element->GetLayoutObject() && shadow_ancestor_element->GetLayoutObject()->IsTextControl()) && HasRichlyEditableStyle(*editable_root)) { - RemoveInterchangeNodes(fragment_.Get()); + RemoveInterchangeNodes(fragment_); return; } @@ -208,7 +208,7 @@ ReplacementFragment::ReplacementFragment(Document* document, // We don't need TestRendering for plain-text editing + plain-text // insertion. if (is_plain_text) { - RemoveInterchangeNodes(fragment_.Get()); + RemoveInterchangeNodes(fragment_); String original_text = fragment_->textContent(); auto* event = MakeGarbageCollected<BeforeTextInsertedEvent>(original_text); @@ -216,7 +216,7 @@ ReplacementFragment::ReplacementFragment(Document* document, if (original_text != event->GetText()) { fragment_ = CreateFragmentFromText( selection.ToNormalizedEphemeralRange(), event->GetText()); - RemoveInterchangeNodes(fragment_.Get()); + RemoveInterchangeNodes(fragment_); } return; } @@ -224,7 +224,7 @@ ReplacementFragment::ReplacementFragment(Document* document, HTMLElement* holder = InsertFragmentForTestRendering(editable_root); if (!holder) { - RemoveInterchangeNodes(fragment_.Get()); + RemoveInterchangeNodes(fragment_); return; } @@ -250,7 +250,7 @@ ReplacementFragment::ReplacementFragment(Document* document, // TODO(editing-dev): Use of UpdateStyleAndLayout // needs to be audited. See http://crbug.com/590369 for more details. - document->UpdateStyleAndLayout(); + document->UpdateStyleAndLayout(DocumentUpdateReason::kEditing); fragment_ = CreateFragmentFromText(selection.ToNormalizedEphemeralRange(), evt->GetText()); @@ -314,13 +314,13 @@ HTMLElement* ReplacementFragment::InsertFragmentForTestRendering( Element* root_editable_element) { TRACE_EVENT0("blink", "ReplacementFragment::insertFragmentForTestRendering"); DCHECK(document_); - HTMLElement* holder = CreateDefaultParagraphElement(*document_.Get()); + HTMLElement* holder = CreateDefaultParagraphElement(*document_); holder->AppendChild(fragment_); root_editable_element->AppendChild(holder); // TODO(editing-dev): Hoist this call to the call sites. - document_->UpdateStyleAndLayout(); + document_->UpdateStyleAndLayout(DocumentUpdateReason::kEditing); return holder; } @@ -391,24 +391,24 @@ inline void ReplaceSelectionCommand::InsertedNodes::RespondToNodeInsertion( inline void ReplaceSelectionCommand::InsertedNodes::WillRemoveNodePreservingChildren( Node& node) { - if (first_node_inserted_.Get() == node) + if (first_node_inserted_ == node) first_node_inserted_ = NodeTraversal::Next(node); - if (last_node_inserted_.Get() == node) + if (last_node_inserted_ == node) last_node_inserted_ = node.lastChild() ? node.lastChild() : NodeTraversal::NextSkippingChildren(node); - if (ref_node_.Get() == node) + if (ref_node_ == node) ref_node_ = NodeTraversal::Next(node); } inline void ReplaceSelectionCommand::InsertedNodes::WillRemoveNode(Node& node) { - if (first_node_inserted_.Get() == node && last_node_inserted_.Get() == node) { + if (first_node_inserted_ == node && last_node_inserted_ == node) { first_node_inserted_ = nullptr; last_node_inserted_ = nullptr; - } else if (first_node_inserted_.Get() == node) { + } else if (first_node_inserted_ == node) { first_node_inserted_ = NodeTraversal::NextSkippingChildren(*first_node_inserted_); - } else if (last_node_inserted_.Get() == node) { + } else if (last_node_inserted_ == node) { last_node_inserted_ = NodeTraversal::PreviousSkippingChildren(*last_node_inserted_); } @@ -419,11 +419,11 @@ inline void ReplaceSelectionCommand::InsertedNodes::WillRemoveNode(Node& node) { inline void ReplaceSelectionCommand::InsertedNodes::DidReplaceNode( Node& node, Node& new_node) { - if (first_node_inserted_.Get() == node) + if (first_node_inserted_ == node) first_node_inserted_ = &new_node; - if (last_node_inserted_.Get() == node) + if (last_node_inserted_ == node) last_node_inserted_ = &new_node; - if (ref_node_.Get() == node) + if (ref_node_ == node) ref_node_ = &new_node; } @@ -610,7 +610,7 @@ void ReplaceSelectionCommand::RemoveRedundantStylesAndKeepStyleSpanInline( // TODO(editing-dev): There is currently no way to update style without // updating layout. We might want to have updateLifcycleToStyleClean() // similar to FrameView::updateLifecylceToLayoutClean() in Document. - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); if (blockquote_element) new_inline_style->RemoveStyleFromRulesAndContext( @@ -635,7 +635,7 @@ void ReplaceSelectionCommand::RemoveRedundantStylesAndKeepStyleSpanInline( AtomicString(new_inline_style->Style()->AsText())); } - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); // FIXME: Tolerate differences in id, class, and style attributes. if (element->parentNode() && IsNonTableCellHTMLBlockElement(element) && @@ -765,7 +765,7 @@ void ReplaceSelectionCommand::MoveElementOutOfAncestor( if (!HasEditableStyle(*ancestor->parentNode())) return; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); VisiblePosition position_at_end_of_node = CreateVisiblePosition(LastPositionInOrAfterNode(*element)); VisiblePosition last_position_in_paragraph = @@ -801,7 +801,7 @@ static inline bool NodeHasVisibleLayoutText(Text& text) { void ReplaceSelectionCommand::RemoveUnrenderedTextNodesAtEnds( InsertedNodes& inserted_nodes) { - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); auto* last_leaf_inserted = DynamicTo<Text>(inserted_nodes.LastLeafInserted()); if (last_leaf_inserted && !NodeHasVisibleLayoutText(*last_leaf_inserted) && @@ -829,7 +829,7 @@ void ReplaceSelectionCommand::RemoveUnrenderedTextNodesAtEnds( VisiblePosition ReplaceSelectionCommand::PositionAtEndOfInsertedContent() const { // TODO(editing-dev): Hoist the call and change it into a DCHECK. - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); // TODO(yosin): We should set |end_of_inserted_content_| not in SELECT // element, since contents of SELECT elements, e.g. OPTION, OPTGROUP, are // not editable, or SELECT element is an atomic on editing. @@ -846,7 +846,7 @@ VisiblePosition ReplaceSelectionCommand::PositionAtEndOfInsertedContent() VisiblePosition ReplaceSelectionCommand::PositionAtStartOfInsertedContent() const { // TODO(editing-dev): Hoist the call and change it into a DCHECK. - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); if (start_of_inserted_content_.IsOrphan()) return VisiblePosition(); return CreateVisiblePosition(start_of_inserted_content_); @@ -981,7 +981,7 @@ void ReplaceSelectionCommand::MergeEndIfNeeded(EditingState* editing_state) { // TODO(editing-dev): Use of UpdateStyleAndLayout() // needs to be audited. See http://crbug.com/590369 for more details. - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); destination = VisiblePosition::BeforeNode(*placeholder); start_of_paragraph_to_move = CreateVisiblePosition( @@ -994,7 +994,7 @@ void ReplaceSelectionCommand::MergeEndIfNeeded(EditingState* editing_state) { if (editing_state->IsAborted()) return; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); // Merging forward will remove end_of_inserted_content from the document. if (merge_forward) { @@ -1118,7 +1118,7 @@ void ReplaceSelectionCommand::InsertParagraphSeparatorIfNeeds( .Build())) return; if (fragment.HasInterchangeNewlineAtStart()) { - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); VisiblePosition start_after_delete = EndingVisibleSelection().VisibleStart(); if (IsEndOfParagraph(start_after_delete) && @@ -1149,7 +1149,7 @@ void ReplaceSelectionCommand::InsertParagraphSeparatorIfNeeds( InsertParagraphSeparator(editing_state); if (editing_state->IsAborted()) return; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); } } // We split the current paragraph in two to avoid nesting the blocks from @@ -1174,7 +1174,7 @@ void ReplaceSelectionCommand::InsertParagraphSeparatorIfNeeds( InsertParagraphSeparator(editing_state); if (editing_state->IsAborted()) return; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); SetEndingSelection(SelectionForUndoStep::From( SelectionInDOMTree::Builder() .Collapse( @@ -1205,7 +1205,7 @@ void ReplaceSelectionCommand::DoApply(EditingState* editing_state) { if (trivial_replace_result) return; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); SetUpStyle(selection); Element* const current_root = selection.RootEditableElement(); @@ -1250,7 +1250,7 @@ void ReplaceSelectionCommand::DoApply(EditingState* editing_state) { // <div>foo</div> into hello^ world. PrepareWhitespaceAtPositionForSplit(insertion_pos); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); // If the downstream node has been removed there's no point in continuing. if (!MostForwardCaretPosition(insertion_pos).AnchorNode()) @@ -1305,7 +1305,7 @@ void ReplaceSelectionCommand::DoApply(EditingState* editing_state) { RemoveHeadContents(fragment); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); // We don't want the destination to end up inside nodes that weren't selected. // To avoid that, we move the position forward without changing the visible @@ -1421,7 +1421,7 @@ void ReplaceSelectionCommand::DoApply(EditingState* editing_state) { ABORT_EDITING_COMMAND_IF(!inserted_nodes.RefNode()); } - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); // Mutation events (bug 20161) may have already removed the inserted content if (!inserted_nodes.FirstNodeInserted() || @@ -1454,7 +1454,7 @@ void ReplaceSelectionCommand::DoApply(EditingState* editing_state) { return; } - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); if (end_br && (plain_text_fragment || (ShouldRemoveEndBR(end_br, original_vis_pos_before_end_br) && @@ -1570,7 +1570,7 @@ void ReplaceSelectionCommand::DoApply(EditingState* editing_state) { return; } - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); // Making the two VisiblePositions valid again. start_of_paragraph_to_move = @@ -1586,7 +1586,7 @@ void ReplaceSelectionCommand::DoApply(EditingState* editing_state) { if (editing_state->IsAborted()) return; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); const VisibleSelection& visible_selection_of_insterted_content = EndingVisibleSelection(); start_of_inserted_content_ = MostForwardCaretPosition( @@ -1654,7 +1654,7 @@ void ReplaceSelectionCommand::DoApply(EditingState* editing_state) { return; } - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); // Select up to the paragraph separator that was added. last_position_to_select = @@ -1772,7 +1772,7 @@ void ReplaceSelectionCommand::AddSpacesForSmartReplace( } } - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); VisiblePosition start_of_inserted_content = PositionAtStartOfInsertedContent(); @@ -1983,7 +1983,7 @@ Node* ReplaceSelectionCommand::InsertAsListItems(HTMLElement* list_element, IsHTMLListElement(list_element->firstChild())) list_element = To<HTMLElement>(list_element->firstChild()); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); bool is_start = IsStartOfParagraph(CreateVisiblePosition(insert_pos)); bool is_end = IsEndOfParagraph(CreateVisiblePosition(insert_pos)); bool is_middle = !is_start && !is_end; @@ -2060,7 +2060,7 @@ bool ReplaceSelectionCommand::PerformTrivialReplace( // TODO(editing-dev): Use of UpdateStyleAndLayout // needs to be audited. See http://crbug.com/590369 for more details. - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); Node* node_after_insertion_pos = MostForwardCaretPosition(EndingSelection().End()).AnchorNode(); @@ -2073,7 +2073,7 @@ bool ReplaceSelectionCommand::PerformTrivialReplace( if (end.IsNull()) return false; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); if (node_after_insertion_pos && node_after_insertion_pos->parentNode() && IsA<HTMLBRElement>(*node_after_insertion_pos) && diff --git a/chromium/third_party/blink/renderer/core/editing/commands/replace_selection_command.h b/chromium/third_party/blink/renderer/core/editing/commands/replace_selection_command.h index a0b3bd914e9..3913dccb1ce 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/replace_selection_command.h +++ b/chromium/third_party/blink/renderer/core/editing/commands/replace_selection_command.h @@ -71,7 +71,7 @@ class CORE_EXPORT ReplaceSelectionCommand final : public CompositeEditCommand { void WillRemoveNode(Node&); void DidReplaceNode(Node&, Node& new_node); - Node* FirstNodeInserted() const { return first_node_inserted_.Get(); } + Node* FirstNodeInserted() const { return first_node_inserted_; } Node* LastLeafInserted() const { return last_node_inserted_ ? &NodeTraversal::LastWithinOrSelf(*last_node_inserted_) @@ -83,13 +83,13 @@ class CORE_EXPORT ReplaceSelectionCommand final : public CompositeEditCommand { NodeTraversal::LastWithinOrSelf(*last_node_inserted_)) : nullptr; } - Node* RefNode() const { return ref_node_.Get(); } + Node* RefNode() const { return ref_node_; } void SetRefNode(Node* node) { ref_node_ = node; } private: - Member<Node> first_node_inserted_; - Member<Node> last_node_inserted_; - Member<Node> ref_node_; + Node* first_node_inserted_ = nullptr; + Node* last_node_inserted_ = nullptr; + Node* ref_node_ = nullptr; }; Node* InsertAsListItems(HTMLElement* list_element, diff --git a/chromium/third_party/blink/renderer/core/editing/commands/replace_selection_command_test.cc b/chromium/third_party/blink/renderer/core/editing/commands/replace_selection_command_test.cc index 0f6244a43e3..aaf00dd0f92 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/replace_selection_command_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/replace_selection_command_test.cc @@ -53,8 +53,7 @@ TEST_F(ReplaceSelectionCommandTest, pastingEmptySpan) { GetDocument(), fragment, options); EXPECT_TRUE(command->Apply()) << "the replace command should have succeeded"; - EXPECT_EQ("foo", GetDocument().body()->InnerHTMLAsString()) - << "no DOM tree mutation"; + EXPECT_EQ("foo", GetDocument().body()->innerHTML()) << "no DOM tree mutation"; } // This is a regression test for https://crbug.com/668808 @@ -79,7 +78,7 @@ TEST_F(ReplaceSelectionCommandTest, pasteSpanInText) { GetDocument(), fragment, options); EXPECT_TRUE(command->Apply()) << "the replace command should have succeeded"; - EXPECT_EQ("<b>t</b>bar<b>ext</b>", GetDocument().body()->InnerHTMLAsString()) + EXPECT_EQ("<b>t</b>bar<b>ext</b>", GetDocument().body()->innerHTML()) << "'bar' should have been inserted"; } diff --git a/chromium/third_party/blink/renderer/core/editing/commands/split_text_node_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/split_text_node_command.cc index 2a5c7e1ee35..2d8c4ccc459 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/split_text_node_command.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/split_text_node_command.cc @@ -72,7 +72,7 @@ void SplitTextNodeCommand::DoUnapply() { String prefix_text = text1_->data(); text2_->insertData(0, prefix_text, ASSERT_NO_EXCEPTION); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); GetDocument().Markers().MoveMarkers(*text1_, prefix_text.length(), *text2_); text1_->remove(ASSERT_NO_EXCEPTION); @@ -98,7 +98,7 @@ void SplitTextNodeCommand::InsertText1AndTrimText2() { if (exception_state.HadException()) return; text2_->deleteData(0, offset_, exception_state); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); } void SplitTextNodeCommand::Trace(Visitor* visitor) { diff --git a/chromium/third_party/blink/renderer/core/editing/commands/style_commands.cc b/chromium/third_party/blink/renderer/core/editing/commands/style_commands.cc index 00eef3d1f00..7d1900ad7a3 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/style_commands.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/style_commands.cc @@ -216,8 +216,9 @@ bool StyleCommands::SelectionStartHasStyle(LocalFrame& frame, frame.Selection().ComputeVisibleSelectionInDOMTreeDeprecated(), property_id == CSSPropertyID::kBackgroundColor, style_to_check->Style()); - return style_to_check->TriStateOfStyle(style_at_start, secure_context_mode) != - EditingTriState::kFalse; + return style_to_check->TriStateOfStyle( + frame.GetDocument()->ToExecutionContext(), style_at_start, + secure_context_mode) != EditingTriState::kFalse; } bool StyleCommands::ExecuteToggleStyle(LocalFrame& frame, @@ -351,7 +352,7 @@ bool StyleCommands::ExecuteStyleWithCSS(LocalFrame& frame, EditorCommandSource, const String& value) { frame.GetEditor().SetShouldStyleWithCSS( - !DeprecatedEqualIgnoringCase(value, "false")); + !EqualIgnoringASCIICase(value, "false")); return true; } @@ -360,7 +361,7 @@ bool StyleCommands::ExecuteUseCSS(LocalFrame& frame, EditorCommandSource, const String& value) { frame.GetEditor().SetShouldStyleWithCSS( - DeprecatedEqualIgnoringCase(value, "false")); + EqualIgnoringASCIICase(value, "false")); return true; } @@ -368,7 +369,7 @@ bool StyleCommands::ExecuteUseCSS(LocalFrame& frame, EditingTriState StyleCommands::StateStyle(LocalFrame& frame, CSSPropertyID property_id, const char* desired_value) { - frame.GetDocument()->UpdateStyleAndLayout(); + frame.GetDocument()->UpdateStyleAndLayout(DocumentUpdateReason::kEditing); if (frame.GetEditor().Behavior().ShouldToggleStyleBasedOnStartOfSelection()) { return SelectionStartHasStyle(frame, property_id, desired_value) ? EditingTriState::kTrue @@ -528,7 +529,7 @@ WritingDirection StyleCommands::TextDirectionForSelection( EditingTriState StyleCommands::StateTextWritingDirection( LocalFrame& frame, WritingDirection direction) { - frame.GetDocument()->UpdateStyleAndLayout(); + frame.GetDocument()->UpdateStyleAndLayout(DocumentUpdateReason::kEditing); bool has_nested_or_multiple_embeddings; WritingDirection selection_direction = TextDirectionForSelection( @@ -582,7 +583,7 @@ String StyleCommands::SelectionStartCSSPropertyValue( } String StyleCommands::ValueStyle(LocalFrame& frame, CSSPropertyID property_id) { - frame.GetDocument()->UpdateStyleAndLayout(); + frame.GetDocument()->UpdateStyleAndLayout(DocumentUpdateReason::kEditing); // TODO(editing-dev): Rather than retrieving the style at the start of the // current selection, we should retrieve the style present throughout the diff --git a/chromium/third_party/blink/renderer/core/editing/commands/typing_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/typing_command.cc index 99626cccad0..f32727d51fd 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/typing_command.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/typing_command.cc @@ -205,8 +205,9 @@ void TypingCommand::DeleteSelection(Document& document, Options options) { ->Apply(); } -void TypingCommand::DeleteSelectionIfRange(const VisibleSelection& selection, - EditingState* editing_state) { +void TypingCommand::DeleteSelectionIfRange( + const SelectionForUndoStep& selection, + EditingState* editing_state) { if (!selection.IsRange()) return; // Although the 'selection' to delete is indeed a Range, it may have been @@ -316,7 +317,7 @@ void TypingCommand::AdjustSelectionAfterIncrementalInsertion( // TODO(editing-dev): The use of UpdateStyleAndLayout // needs to be audited. see http://crbug.com/590369 for more details. - frame->GetDocument()->UpdateStyleAndLayout(); + frame->GetDocument()->UpdateStyleAndLayout(DocumentUpdateReason::kEditing); Element* element = frame->Selection() .ComputeVisibleSelectionInDOMTreeDeprecated() @@ -383,7 +384,7 @@ void TypingCommand::InsertText( // TODO(editing-dev): The use of UpdateStyleAndLayout // needs to be audited. see http://crbug.com/590369 for more details. - document.UpdateStyleAndLayout(); + document.UpdateStyleAndLayout(DocumentUpdateReason::kEditing); const PlainTextRange selection_offsets = GetSelectionOffsets(selection_for_insertion.AsSelection()); @@ -663,7 +664,7 @@ void TypingCommand::InsertTextRunWithoutNewlines(const String& text, EditingState* editing_state) { CompositeEditCommand* command; if (IsIncrementalInsertion()) { - command = InsertIncrementalTextCommand::Create( + command = MakeGarbageCollected<InsertIncrementalTextCommand>( GetDocument(), text, composition_type_ == kTextCompositionNone ? InsertIncrementalTextCommand:: @@ -785,8 +786,8 @@ void TypingCommand::DeleteKeyPressed(TextGranularity granularity, return; if (EndingSelection().IsRange()) { - DeleteKeyPressedInternal(EndingVisibleSelection(), EndingSelection(), - kill_ring, editing_state); + DeleteKeyPressedInternal(EndingSelection(), EndingSelection(), kill_ring, + editing_state); return; } @@ -806,7 +807,7 @@ void TypingCommand::DeleteKeyPressed(TextGranularity granularity, TypingAddedToOpenCommand(kDeleteKey); smart_delete_ = false; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); SelectionModifier selection_modifier(*frame, EndingSelection().AsSelection()); selection_modifier.SetSelectionIsDirectional(SelectionIsDirectional()); @@ -894,7 +895,7 @@ void TypingCommand::DeleteKeyPressed(TextGranularity granularity, if (!StartingSelection().IsRange() || selection_to_delete.Base() != StartingSelection().Start()) { DeleteKeyPressedInternal( - selection_to_delete, + SelectionForUndoStep::From(selection_to_delete.AsSelection()), SelectionForUndoStep::From(selection_to_delete.AsSelection()), kill_ring, editing_state); return; @@ -908,12 +909,13 @@ void TypingCommand::DeleteKeyPressed(TextGranularity granularity, CreateVisiblePosition(selection_to_delete.Extent()) .DeepEquivalent()) .Build(); - DeleteKeyPressedInternal(selection_to_delete, selection_after_undo, kill_ring, - editing_state); + DeleteKeyPressedInternal( + SelectionForUndoStep::From(selection_to_delete.AsSelection()), + selection_after_undo, kill_ring, editing_state); } void TypingCommand::DeleteKeyPressedInternal( - const VisibleSelection& selection_to_delete, + const SelectionForUndoStep& selection_to_delete, const SelectionForUndoStep& selection_after_undo, bool kill_ring, EditingState* editing_state) { @@ -927,9 +929,10 @@ void TypingCommand::DeleteKeyPressedInternal( LocalFrame* frame = GetDocument().GetFrame(); DCHECK(frame); - if (kill_ring) - frame->GetEditor().AddToKillRing( - selection_to_delete.ToNormalizedEphemeralRange()); + if (kill_ring) { + frame->GetEditor().AddToKillRing(CreateVisibleSelection(selection_to_delete) + .ToNormalizedEphemeralRange()); + } // On Mac, make undo select everything that has been deleted, unless an undo // will undo more than just this deletion. // FIXME: This behaves like TextEdit except for the case where you open with @@ -969,7 +972,7 @@ void TypingCommand::ForwardDeleteKeyPressed(TextGranularity granularity, return; if (EndingSelection().IsRange()) { - ForwardDeleteKeyPressedInternal(EndingVisibleSelection(), EndingSelection(), + ForwardDeleteKeyPressedInternal(EndingSelection(), EndingSelection(), kill_ring, editing_state); return; } @@ -980,7 +983,7 @@ void TypingCommand::ForwardDeleteKeyPressed(TextGranularity granularity, } smart_delete_ = false; - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); // Handle delete at beginning-of-block case. // Do nothing in the case that the caret is at the start of a @@ -1041,7 +1044,7 @@ void TypingCommand::ForwardDeleteKeyPressed(TextGranularity granularity, MostBackwardCaretPosition(selection_to_delete.Base()) != StartingSelection().Start()) { ForwardDeleteKeyPressedInternal( - selection_to_delete, + SelectionForUndoStep::From(selection_to_delete.AsSelection()), SelectionForUndoStep::From(selection_to_delete.AsSelection()), kill_ring, editing_state); return; @@ -1054,12 +1057,13 @@ void TypingCommand::ForwardDeleteKeyPressed(TextGranularity granularity, ComputeExtentForForwardDeleteUndo(selection_to_delete, StartingSelection().End())) .Build(); - ForwardDeleteKeyPressedInternal(selection_to_delete, selection_after_undo, - kill_ring, editing_state); + ForwardDeleteKeyPressedInternal( + SelectionForUndoStep::From(selection_to_delete.AsSelection()), + selection_after_undo, kill_ring, editing_state); } void TypingCommand::ForwardDeleteKeyPressedInternal( - const VisibleSelection& selection_to_delete, + const SelectionForUndoStep& selection_to_delete, const SelectionForUndoStep& selection_after_undo, bool kill_ring, EditingState* editing_state) { @@ -1073,9 +1077,10 @@ void TypingCommand::ForwardDeleteKeyPressedInternal( LocalFrame* frame = GetDocument().GetFrame(); DCHECK(frame); - if (kill_ring) - frame->GetEditor().AddToKillRing( - selection_to_delete.ToNormalizedEphemeralRange()); + if (kill_ring) { + frame->GetEditor().AddToKillRing(CreateVisibleSelection(selection_to_delete) + .ToNormalizedEphemeralRange()); + } // Make undo select what was deleted on Mac alone if (frame->GetEditor().Behavior().ShouldUndoOfDeleteSelectText()) SetStartingSelection(selection_after_undo); diff --git a/chromium/third_party/blink/renderer/core/editing/commands/typing_command.h b/chromium/third_party/blink/renderer/core/editing/commands/typing_command.h index 28a13a44582..cfec38f07c5 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/typing_command.h +++ b/chromium/third_party/blink/renderer/core/editing/commands/typing_command.h @@ -145,15 +145,15 @@ class CORE_EXPORT TypingCommand final : public CompositeEditCommand { bool IsIncrementalInsertion() const { return is_incremental_insertion_; } void DeleteKeyPressedInternal( - const VisibleSelection& selection_to_delete, + const SelectionForUndoStep& selection_to_delete, const SelectionForUndoStep& selection_after_undo, bool kill_ring, EditingState*); - void DeleteSelectionIfRange(const VisibleSelection&, EditingState*); + void DeleteSelectionIfRange(const SelectionForUndoStep&, EditingState*); void ForwardDeleteKeyPressedInternal( - const VisibleSelection& selection_to_delete, + const SelectionForUndoStep& selection_to_delete, const SelectionForUndoStep& selection_after_undo, bool kill_ring, EditingState*); diff --git a/chromium/third_party/blink/renderer/core/editing/commands/undo_step.cc b/chromium/third_party/blink/renderer/core/editing/commands/undo_step.cc index 8d11cf65807..e1a71e04ee7 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/undo_step.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/undo_step.cc @@ -44,7 +44,7 @@ void UndoStep::Unapply() { // operations, like RemoveNodeCommand, don't require a layout because the high // level operations that use them perform one if one is necessary (like for // the creation of VisiblePositions). - document_->UpdateStyleAndLayout(); + document_->UpdateStyleAndLayout(DocumentUpdateReason::kEditing); { wtf_size_t size = commands_.size(); @@ -86,7 +86,7 @@ void UndoStep::Reapply() { // operations, like RemoveNodeCommand, don't require a layout because the high // level operations that use them perform one if one is necessary (like for // the creation of VisiblePositions). - document_->UpdateStyleAndLayout(); + document_->UpdateStyleAndLayout(DocumentUpdateReason::kEditing); { for (const auto& command : commands_) diff --git a/chromium/third_party/blink/renderer/core/editing/compute_layer_selection.cc b/chromium/third_party/blink/renderer/core/editing/compute_layer_selection.cc index 17a681396fd..2526b31ad76 100644 --- a/chromium/third_party/blink/renderer/core/editing/compute_layer_selection.cc +++ b/chromium/third_party/blink/renderer/core/editing/compute_layer_selection.cc @@ -245,6 +245,11 @@ EndPositionInGraphicsLayerBacking(const SelectionInDOMTree& selection) { cc::LayerSelection ComputeLayerSelection( const FrameSelection& frame_selection) { + // TODO(https://crbug.com/1065049) - Implement layer selection for + // CompositeAfterPaint + if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) + return {}; + if (!frame_selection.IsHandleVisible() || frame_selection.IsHidden()) return {}; diff --git a/chromium/third_party/blink/renderer/core/editing/compute_layer_selection_test.cc b/chromium/third_party/blink/renderer/core/editing/compute_layer_selection_test.cc index f0062e79597..30ff7dd81d1 100644 --- a/chromium/third_party/blink/renderer/core/editing/compute_layer_selection_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/compute_layer_selection_test.cc @@ -121,7 +121,8 @@ TEST_F(ComputeLayerSelectionTest, PositionInScrollableRoot) { To<HTMLInputElement>(GetDocument().getElementById("target"))); ScrollableArea* root_scroller = GetDocument().View()->GetScrollableArea(); - root_scroller->SetScrollOffset(ScrollOffset(800, 500), kProgrammaticScroll); + root_scroller->SetScrollOffset(ScrollOffset(800, 500), + mojom::blink::ScrollType::kProgrammatic); ASSERT_EQ(ScrollOffset(800, 500), root_scroller->GetScrollOffset()); UpdateAllLifecyclePhasesForTest(); @@ -185,7 +186,8 @@ TEST_F(ComputeLayerSelectionTest, PositionInScroller) { Element* e = GetDocument().getElementById("scroller"); PaintLayerScrollableArea* scroller = ToLayoutBox(e->GetLayoutObject())->GetScrollableArea(); - scroller->SetScrollOffset(ScrollOffset(900, 800), kProgrammaticScroll); + scroller->SetScrollOffset(ScrollOffset(900, 800), + mojom::blink::ScrollType::kProgrammatic); ASSERT_EQ(ScrollOffset(900, 800), scroller->GetScrollOffset()); UpdateAllLifecyclePhasesForTest(); diff --git a/chromium/third_party/blink/renderer/core/editing/dom_selection.cc b/chromium/third_party/blink/renderer/core/editing/dom_selection.cc index 862ff5be65b..5c6960cbb03 100644 --- a/chromium/third_party/blink/renderer/core/editing/dom_selection.cc +++ b/chromium/third_party/blink/renderer/core/editing/dom_selection.cc @@ -46,6 +46,7 @@ #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/inspector/console_message.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" +#include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/instrumentation/use_counter.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" @@ -66,7 +67,7 @@ static Node* SelectionShadowAncestor(LocalFrame* frame) { } DOMSelection::DOMSelection(const TreeScope* tree_scope) - : ContextClient(tree_scope->RootNode().GetDocument().GetFrame()), + : ExecutionContextClient(tree_scope->RootNode().GetDocument().GetFrame()), tree_scope_(tree_scope) {} void DOMSelection::ClearTreeScope() { @@ -411,50 +412,51 @@ void DOMSelection::modify(const String& alter_string, return; SelectionModifyAlteration alter; - if (DeprecatedEqualIgnoringCase(alter_string, "extend")) + if (EqualIgnoringASCIICase(alter_string, "extend")) alter = SelectionModifyAlteration::kExtend; - else if (DeprecatedEqualIgnoringCase(alter_string, "move")) + else if (EqualIgnoringASCIICase(alter_string, "move")) alter = SelectionModifyAlteration::kMove; else return; SelectionModifyDirection direction; - if (DeprecatedEqualIgnoringCase(direction_string, "forward")) + if (EqualIgnoringASCIICase(direction_string, "forward")) direction = SelectionModifyDirection::kForward; - else if (DeprecatedEqualIgnoringCase(direction_string, "backward")) + else if (EqualIgnoringASCIICase(direction_string, "backward")) direction = SelectionModifyDirection::kBackward; - else if (DeprecatedEqualIgnoringCase(direction_string, "left")) + else if (EqualIgnoringASCIICase(direction_string, "left")) direction = SelectionModifyDirection::kLeft; - else if (DeprecatedEqualIgnoringCase(direction_string, "right")) + else if (EqualIgnoringASCIICase(direction_string, "right")) direction = SelectionModifyDirection::kRight; else return; TextGranularity granularity; - if (DeprecatedEqualIgnoringCase(granularity_string, "character")) + if (EqualIgnoringASCIICase(granularity_string, "character")) granularity = TextGranularity::kCharacter; - else if (DeprecatedEqualIgnoringCase(granularity_string, "word")) + else if (EqualIgnoringASCIICase(granularity_string, "word")) granularity = TextGranularity::kWord; - else if (DeprecatedEqualIgnoringCase(granularity_string, "sentence")) + else if (EqualIgnoringASCIICase(granularity_string, "sentence")) granularity = TextGranularity::kSentence; - else if (DeprecatedEqualIgnoringCase(granularity_string, "line")) + else if (EqualIgnoringASCIICase(granularity_string, "line")) granularity = TextGranularity::kLine; - else if (DeprecatedEqualIgnoringCase(granularity_string, "paragraph")) + else if (EqualIgnoringASCIICase(granularity_string, "paragraph")) granularity = TextGranularity::kParagraph; - else if (DeprecatedEqualIgnoringCase(granularity_string, "lineboundary")) + else if (EqualIgnoringASCIICase(granularity_string, "lineboundary")) granularity = TextGranularity::kLineBoundary; - else if (DeprecatedEqualIgnoringCase(granularity_string, "sentenceboundary")) + else if (EqualIgnoringASCIICase(granularity_string, "sentenceboundary")) granularity = TextGranularity::kSentenceBoundary; - else if (DeprecatedEqualIgnoringCase(granularity_string, "paragraphboundary")) + else if (EqualIgnoringASCIICase(granularity_string, "paragraphboundary")) granularity = TextGranularity::kParagraphBoundary; - else if (DeprecatedEqualIgnoringCase(granularity_string, "documentboundary")) + else if (EqualIgnoringASCIICase(granularity_string, "documentboundary")) granularity = TextGranularity::kDocumentBoundary; else return; // TODO(editing-dev): The use of UpdateStyleAndLayout // needs to be audited. See http://crbug.com/590369 for more details. - GetFrame()->GetDocument()->UpdateStyleAndLayout(); + GetFrame()->GetDocument()->UpdateStyleAndLayout( + DocumentUpdateReason::kSelection); Element* focused_element = GetFrame()->GetDocument()->FocusedElement(); GetFrame()->Selection().Modify(alter, direction, granularity, @@ -688,7 +690,8 @@ void DOMSelection::deleteFromDocument() { // TODO(editing-dev): The use of UpdateStyleAndLayout // needs to be audited. See http://crbug.com/590369 for more details. - GetFrame()->GetDocument()->UpdateStyleAndLayout(); + GetFrame()->GetDocument()->UpdateStyleAndLayout( + DocumentUpdateReason::kSelection); // The following code is necessary for // editing/selection/deleteFromDocument-crash.html, which assumes @@ -724,7 +727,8 @@ bool DOMSelection::containsNode(const Node* n, bool allow_partial) const { // TODO(editing-dev): The use of UpdateStyleAndLayout // needs to be audited. See http://crbug.com/590369 for more details. // |VisibleSelection::toNormalizedEphemeralRange| requires clean layout. - GetFrame()->GetDocument()->UpdateStyleAndLayout(); + GetFrame()->GetDocument()->UpdateStyleAndLayout( + DocumentUpdateReason::kSelection); FrameSelection& selection = GetFrame()->Selection(); const EphemeralRange selected_range = @@ -784,7 +788,8 @@ String DOMSelection::toString() { // TODO(editing-dev): The use of UpdateStyleAndLayout // needs to be audited. See http://crbug.com/590369 for more details. - GetFrame()->GetDocument()->UpdateStyleAndLayout(); + GetFrame()->GetDocument()->UpdateStyleAndLayout( + DocumentUpdateReason::kSelection); DocumentLifecycle::DisallowTransitionScope disallow_transition( GetFrame()->GetDocument()->Lifecycle()); @@ -842,15 +847,16 @@ bool DOMSelection::IsValidForPosition(Node* node) const { void DOMSelection::AddConsoleWarning(const String& message) { if (tree_scope_) { tree_scope_->GetDocument().AddConsoleMessage( - ConsoleMessage::Create(mojom::ConsoleMessageSource::kJavaScript, - mojom::ConsoleMessageLevel::kWarning, message)); + MakeGarbageCollected<ConsoleMessage>( + mojom::ConsoleMessageSource::kJavaScript, + mojom::ConsoleMessageLevel::kWarning, message)); } } void DOMSelection::Trace(Visitor* visitor) { visitor->Trace(tree_scope_); ScriptWrappable::Trace(visitor); - ContextClient::Trace(visitor); + ExecutionContextClient::Trace(visitor); } } // namespace blink diff --git a/chromium/third_party/blink/renderer/core/editing/dom_selection.h b/chromium/third_party/blink/renderer/core/editing/dom_selection.h index 4d7dd9b8d34..f3a9e52c76e 100644 --- a/chromium/third_party/blink/renderer/core/editing/dom_selection.h +++ b/chromium/third_party/blink/renderer/core/editing/dom_selection.h @@ -31,7 +31,7 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_DOM_SELECTION_H_ #include "third_party/blink/renderer/core/editing/forward.h" -#include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h" +#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" #include "third_party/blink/renderer/platform/heap/handle.h" @@ -46,7 +46,7 @@ class SetSelectionOptions; class TreeScope; class CORE_EXPORT DOMSelection final : public ScriptWrappable, - public ContextClient { + public ExecutionContextClient { DEFINE_WRAPPERTYPEINFO(); USING_GARBAGE_COLLECTED_MIXIN(DOMSelection); diff --git a/chromium/third_party/blink/renderer/core/editing/drag_caret.cc b/chromium/third_party/blink/renderer/core/editing/drag_caret.cc index c368dd36eb2..d29c09c69fb 100644 --- a/chromium/third_party/blink/renderer/core/editing/drag_caret.cc +++ b/chromium/third_party/blink/renderer/core/editing/drag_caret.cc @@ -66,7 +66,7 @@ void DragCaret::SetCaretPosition(const PositionWithAffinity& position) { Document* document = nullptr; if (Node* node = position_.AnchorNode()) { document = &node->GetDocument(); - SetContext(document); + SetDocument(document); } } diff --git a/chromium/third_party/blink/renderer/core/editing/editing_behavior.cc b/chromium/third_party/blink/renderer/core/editing/editing_behavior.cc index e47785874e6..b10407a84d6 100644 --- a/chromium/third_party/blink/renderer/core/editing/editing_behavior.cc +++ b/chromium/third_party/blink/renderer/core/editing/editing_behavior.cc @@ -27,7 +27,7 @@ #include "third_party/blink/renderer/core/editing/editing_behavior.h" #include "build/build_config.h" -#include "third_party/blink/public/platform/web_input_event.h" +#include "third_party/blink/public/common/input/web_input_event.h" #include "third_party/blink/public/web/web_settings.h" #include "third_party/blink/renderer/core/events/keyboard_event.h" #include "third_party/blink/renderer/platform/keyboard_codes.h" @@ -177,6 +177,10 @@ const KeyboardCodeKeyDownEntry kKeyboardCodeKeyDownEntries[] = { {'Z', kCtrlKey | kShiftKey, "Redo"}, {'Y', kCtrlKey, "Redo"}, #endif +#if defined(OS_WIN) + {VKEY_BACK, kAltKey, "Undo"}, + {VKEY_BACK, kAltKey | kShiftKey, "Redo"}, +#endif {VKEY_INSERT, 0, "OverWrite"}, }; diff --git a/chromium/third_party/blink/renderer/core/editing/editing_style.cc b/chromium/third_party/blink/renderer/core/editing/editing_style.cc index 645205a7471..2a3acb5cf40 100644 --- a/chromium/third_party/blink/renderer/core/editing/editing_style.cc +++ b/chromium/third_party/blink/renderer/core/editing/editing_style.cc @@ -96,12 +96,13 @@ enum EditingPropertiesType { kAllEditingProperties }; -static const Vector<const CSSProperty*>& AllEditingProperties() { +static const Vector<const CSSProperty*>& AllEditingProperties( + const ExecutionContext* execution_context) { DEFINE_STATIC_LOCAL(Vector<const CSSProperty*>, properties, ()); if (properties.IsEmpty()) { CSSProperty::FilterWebExposedCSSPropertiesIntoVector( - kStaticEditingProperties, base::size(kStaticEditingProperties), - properties); + execution_context, kStaticEditingProperties, + base::size(kStaticEditingProperties), properties); for (wtf_size_t index = 0; index < properties.size(); index++) { if (properties[index]->IDEquals(CSSPropertyID::kTextDecoration)) { properties.EraseAt(index); @@ -112,12 +113,13 @@ static const Vector<const CSSProperty*>& AllEditingProperties() { return properties; } -static const Vector<const CSSProperty*>& InheritableEditingProperties() { +static const Vector<const CSSProperty*>& InheritableEditingProperties( + const ExecutionContext* execution_context) { DEFINE_STATIC_LOCAL(Vector<const CSSProperty*>, properties, ()); if (properties.IsEmpty()) { CSSProperty::FilterWebExposedCSSPropertiesIntoVector( - kStaticEditingProperties, base::size(kStaticEditingProperties), - properties); + execution_context, kStaticEditingProperties, + base::size(kStaticEditingProperties), properties); for (wtf_size_t index = 0; index < properties.size();) { if (!properties[index]->IsInherited()) { properties.EraseAt(index); @@ -131,15 +133,19 @@ static const Vector<const CSSProperty*>& InheritableEditingProperties() { template <class StyleDeclarationType> static MutableCSSPropertyValueSet* CopyEditingProperties( + const ExecutionContext* execution_context, StyleDeclarationType* style, EditingPropertiesType type = kOnlyInheritableEditingProperties) { if (type == kAllEditingProperties) - return style->CopyPropertiesInSet(AllEditingProperties()); - return style->CopyPropertiesInSet(InheritableEditingProperties()); + return style->CopyPropertiesInSet(AllEditingProperties(execution_context)); + return style->CopyPropertiesInSet( + InheritableEditingProperties(execution_context)); } -static inline bool IsEditingProperty(CSSPropertyID id) { - static const Vector<const CSSProperty*>& properties = AllEditingProperties(); +static inline bool IsEditingProperty(ExecutionContext* execution_context, + CSSPropertyID id) { + static const Vector<const CSSProperty*>& properties = + AllEditingProperties(execution_context); for (wtf_size_t index = 0; index < properties.size(); index++) { if (properties[index]->IDEquals(id)) return true; @@ -504,7 +510,9 @@ void EditingStyle::Init(Node* node, PropertiesToInclude properties_to_include) { mutable_style_ = properties_to_include == kAllProperties && computed_style_at_position ? computed_style_at_position->CopyProperties() - : CopyEditingProperties(computed_style_at_position); + : CopyEditingProperties( + node ? node->GetDocument().ToExecutionContext() : nullptr, + computed_style_at_position); if (properties_to_include == kEditingPropertiesInEffect) { if (const CSSValue* value = @@ -700,23 +708,26 @@ static const CSSPropertyID kStaticBlockProperties[] = { CSSPropertyID::kTextAlignLast, CSSPropertyID::kTextIndent, CSSPropertyID::kTextJustify, CSSPropertyID::kWidows}; -static const Vector<const CSSProperty*>& BlockPropertiesVector() { +static const Vector<const CSSProperty*>& BlockPropertiesVector( + const ExecutionContext* execution_context) { DEFINE_STATIC_LOCAL(Vector<const CSSProperty*>, properties, ()); if (properties.IsEmpty()) { CSSProperty::FilterWebExposedCSSPropertiesIntoVector( - kStaticBlockProperties, base::size(kStaticBlockProperties), properties); + execution_context, kStaticBlockProperties, + base::size(kStaticBlockProperties), properties); } return properties; } -EditingStyle* EditingStyle::ExtractAndRemoveBlockProperties() { +EditingStyle* EditingStyle::ExtractAndRemoveBlockProperties( + const ExecutionContext* execution_context) { EditingStyle* block_properties = MakeGarbageCollected<EditingStyle>(); if (!mutable_style_) return block_properties; - block_properties->mutable_style_ = - mutable_style_->CopyPropertiesInSet(BlockPropertiesVector()); - RemoveBlockProperties(); + block_properties->mutable_style_ = mutable_style_->CopyPropertiesInSet( + BlockPropertiesVector(execution_context)); + RemoveBlockProperties(execution_context); return block_properties; } @@ -742,21 +753,25 @@ EditingStyle* EditingStyle::ExtractAndRemoveTextDirection( return text_direction; } -void EditingStyle::RemoveBlockProperties() { +void EditingStyle::RemoveBlockProperties( + const ExecutionContext* execution_context) { if (!mutable_style_) return; - mutable_style_->RemovePropertiesInSet(BlockPropertiesVector().data(), - BlockPropertiesVector().size()); + mutable_style_->RemovePropertiesInSet( + BlockPropertiesVector(execution_context).data(), + BlockPropertiesVector(execution_context).size()); } void EditingStyle::RemoveStyleAddedByElement(Element* element) { if (!element || !element->parentNode()) return; MutableCSSPropertyValueSet* parent_style = CopyEditingProperties( + element->parentNode()->GetDocument().ToExecutionContext(), MakeGarbageCollected<CSSComputedStyleDeclaration>(element->parentNode()), kAllEditingProperties); MutableCSSPropertyValueSet* node_style = CopyEditingProperties( + element->GetDocument().ToExecutionContext(), MakeGarbageCollected<CSSComputedStyleDeclaration>(element), kAllEditingProperties); node_style->RemoveEquivalentProperties(parent_style); @@ -768,9 +783,11 @@ void EditingStyle::RemoveStyleConflictingWithStyleOfElement(Element* element) { return; MutableCSSPropertyValueSet* parent_style = CopyEditingProperties( + element->parentNode()->GetDocument().ToExecutionContext(), MakeGarbageCollected<CSSComputedStyleDeclaration>(element->parentNode()), kAllEditingProperties); MutableCSSPropertyValueSet* node_style = CopyEditingProperties( + element->GetDocument().ToExecutionContext(), MakeGarbageCollected<CSSComputedStyleDeclaration>(element), kAllEditingProperties); node_style->RemoveEquivalentProperties(parent_style); @@ -804,12 +821,14 @@ void EditingStyle::CollapseTextDecorationProperties( } EditingTriState EditingStyle::TriStateOfStyle( + ExecutionContext* execution_context, EditingStyle* style, SecureContextMode secure_context_mode) const { if (!style || !style->mutable_style_) return EditingTriState::kFalse; - return TriStateOfStyle(style->mutable_style_->EnsureCSSStyleDeclaration(), - kDoNotIgnoreTextOnlyProperties, secure_context_mode); + return TriStateOfStyle( + style->mutable_style_->EnsureCSSStyleDeclaration(execution_context), + kDoNotIgnoreTextOnlyProperties, secure_context_mode); } EditingTriState EditingStyle::TriStateOfStyle( @@ -852,6 +871,7 @@ EditingTriState EditingStyle::TriStateOfStyle( if (selection.IsCaret()) { return TriStateOfStyle( + selection.Start().GetDocument()->ToExecutionContext(), EditingStyleUtilities::CreateStyleAtSelectionStart(selection), secure_context_mode); } @@ -1179,7 +1199,8 @@ bool EditingStyle::ElementIsStyledSpanOrHTMLEquivalent( if (const CSSPropertyValueSet* style = element->InlineStyle()) { unsigned property_count = style->PropertyCount(); for (unsigned i = 0; i < property_count; ++i) { - if (!IsEditingProperty(style->PropertyAt(i).Id())) + if (!IsEditingProperty(element->GetDocument().ToExecutionContext(), + style->PropertyAt(i).Id())) return false; } } @@ -1265,13 +1286,15 @@ void EditingStyle::MergeInlineStyleOfElement( MergeStyle(element->InlineStyle(), mode); return; case kOnlyEditingInheritableProperties: - MergeStyle(CopyEditingProperties(element->InlineStyle(), - kOnlyInheritableEditingProperties), + MergeStyle(CopyEditingProperties( + element->GetDocument().ToExecutionContext(), + element->InlineStyle(), kOnlyInheritableEditingProperties), mode); return; case kEditingPropertiesInEffect: MergeStyle( - CopyEditingProperties(element->InlineStyle(), kAllEditingProperties), + CopyEditingProperties(element->GetDocument().ToExecutionContext(), + element->InlineStyle(), kAllEditingProperties), mode); return; } @@ -1290,6 +1313,7 @@ static inline bool ElementMatchesAndPropertyIsNotInInlineStyleDecl( } static MutableCSSPropertyValueSet* ExtractEditingProperties( + const ExecutionContext* execution_context, const CSSPropertyValueSet* style, EditingStyle::PropertiesToInclude properties_to_include) { if (!style) @@ -1298,9 +1322,11 @@ static MutableCSSPropertyValueSet* ExtractEditingProperties( switch (properties_to_include) { case EditingStyle::kAllProperties: case EditingStyle::kEditingPropertiesInEffect: - return CopyEditingProperties(style, kAllEditingProperties); + return CopyEditingProperties(execution_context, style, + kAllEditingProperties); case EditingStyle::kOnlyEditingInheritableProperties: - return CopyEditingProperties(style, kOnlyInheritableEditingProperties); + return CopyEditingProperties(execution_context, style, + kOnlyInheritableEditingProperties); } NOTREACHED(); @@ -1319,6 +1345,7 @@ void EditingStyle::MergeInlineAndImplicitStyleOfElement( element->InlineStyle()); style_from_rules->mutable_style_ = ExtractEditingProperties( + element->GetDocument().ToExecutionContext(), style_from_rules->mutable_style_.Get(), properties_to_include); MergeStyle(style_from_rules->mutable_style_.Get(), mode); @@ -1493,10 +1520,11 @@ void EditingStyle::RemoveStyleFromRulesAndContext(Element* element, StyleFromMatchedRulesForElement(element, StyleResolver::kAllButEmptyCSSRules); if (style_from_matched_rules && !style_from_matched_rules->IsEmpty()) { - mutable_style_ = GetPropertiesNotIn( - mutable_style_.Get(), - style_from_matched_rules->EnsureCSSStyleDeclaration(), - secure_context_mode); + mutable_style_ = + GetPropertiesNotIn(mutable_style_.Get(), + style_from_matched_rules->EnsureCSSStyleDeclaration( + element->GetDocument().ToExecutionContext()), + secure_context_mode); } // 2. Remove style present in context and not overriden by matched rules. @@ -1513,7 +1541,8 @@ void EditingStyle::RemoveStyleFromRulesAndContext(Element* element, style_from_matched_rules); mutable_style_ = GetPropertiesNotIn( mutable_style_.Get(), - computed_style->mutable_style_->EnsureCSSStyleDeclaration(), + computed_style->mutable_style_->EnsureCSSStyleDeclaration( + element->GetDocument().ToExecutionContext()), secure_context_mode); } diff --git a/chromium/third_party/blink/renderer/core/editing/editing_style.h b/chromium/third_party/blink/renderer/core/editing/editing_style.h index 9700794ebce..23815f2e154 100644 --- a/chromium/third_party/blink/renderer/core/editing/editing_style.h +++ b/chromium/third_party/blink/renderer/core/editing/editing_style.h @@ -48,6 +48,7 @@ class CSSComputedStyleDeclaration; class ContainerNode; class Document; class Element; +class ExecutionContext; class HTMLElement; class LocalFrame; class MutableCSSPropertyValueSet; @@ -90,9 +91,9 @@ class CORE_EXPORT EditingStyle final : public GarbageCollected<EditingStyle> { void OverrideWithStyle(const CSSPropertyValueSet*); void Clear(); EditingStyle* Copy() const; - EditingStyle* ExtractAndRemoveBlockProperties(); + EditingStyle* ExtractAndRemoveBlockProperties(const ExecutionContext*); EditingStyle* ExtractAndRemoveTextDirection(SecureContextMode); - void RemoveBlockProperties(); + void RemoveBlockProperties(const ExecutionContext*); void RemoveStyleAddedByElement(Element*); void RemoveStyleConflictingWithStyleOfElement(Element*); void CollapseTextDecorationProperties(SecureContextMode); @@ -100,7 +101,9 @@ class CORE_EXPORT EditingStyle final : public GarbageCollected<EditingStyle> { kIgnoreTextOnlyProperties, kDoNotIgnoreTextOnlyProperties }; - EditingTriState TriStateOfStyle(EditingStyle*, SecureContextMode) const; + EditingTriState TriStateOfStyle(ExecutionContext*, + EditingStyle*, + SecureContextMode) const; EditingTriState TriStateOfStyle(const VisibleSelection&, SecureContextMode) const; bool ConflictsWithInlineStyleOfElement(HTMLElement* element) const { diff --git a/chromium/third_party/blink/renderer/core/editing/editing_utilities.cc b/chromium/third_party/blink/renderer/core/editing/editing_utilities.cc index 6def00469d7..d198257b409 100644 --- a/chromium/third_party/blink/renderer/core/editing/editing_utilities.cc +++ b/chromium/third_party/blink/renderer/core/editing/editing_utilities.cc @@ -64,6 +64,7 @@ #include "third_party/blink/renderer/core/html/html_span_element.h" #include "third_party/blink/renderer/core/html/html_table_cell_element.h" #include "third_party/blink/renderer/core/html/html_ulist_element.h" +#include "third_party/blink/renderer/core/html/image_document.h" #include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h" #include "third_party/blink/renderer/core/html_element_factory.h" #include "third_party/blink/renderer/core/html_names.h" @@ -1246,7 +1247,7 @@ bool IsDisplayInsideTable(const Node* node) { bool IsTableCell(const Node* node) { DCHECK(node); LayoutObject* r = node->GetLayoutObject(); - return r ? r->IsTableCell() : IsHTMLTableCellElement(*node); + return r ? r->IsTableCell() : IsA<HTMLTableCellElement>(*node); } HTMLElement* CreateDefaultParagraphElement(Document& document) { @@ -1580,7 +1581,7 @@ FloatQuad LocalToAbsoluteQuadOf(const LocalCaretRect& caret_rect) { const StaticRangeVector* TargetRangesForInputEvent(const Node& node) { // TODO(editing-dev): The use of UpdateStyleAndLayout // needs to be audited. see http://crbug.com/590369 for more details. - node.GetDocument().UpdateStyleAndLayout(); + node.GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); if (!HasRichlyEditableStyle(node)) return nullptr; const EphemeralRange& range = @@ -1725,15 +1726,16 @@ AtomicString GetUrlStringFromNode(const Node& node) { return AtomicString(); } -void WriteImageNodeToClipboard(const Node& node, const String& title) { +void WriteImageNodeToClipboard(SystemClipboard& system_clipboard, + const Node& node, + const String& title) { const scoped_refptr<Image> image = ImageFromNode(node); if (!image.get()) return; const KURL url_string = node.GetDocument().CompleteURL( StripLeadingAndTrailingHTMLSpaces(GetUrlStringFromNode(node))); - SystemClipboard::GetInstance().WriteImageWithTag(image.get(), url_string, - title); - SystemClipboard::GetInstance().CommitWrite(); + system_clipboard.WriteImageWithTag(image.get(), url_string, title); + system_clipboard.CommitWrite(); } Element* FindEventTargetFrom(LocalFrame& frame, @@ -1749,7 +1751,7 @@ Element* FindEventTargetFrom(LocalFrame& frame, HTMLImageElement* ImageElementFromImageDocument(const Document* document) { if (!document) return nullptr; - if (!document->IsImageDocument()) + if (!IsA<ImageDocument>(document)) return nullptr; const HTMLElement* const body = document->body(); diff --git a/chromium/third_party/blink/renderer/core/editing/editing_utilities.h b/chromium/third_party/blink/renderer/core/editing/editing_utilities.h index e2e9992852f..5597e7282e2 100644 --- a/chromium/third_party/blink/renderer/core/editing/editing_utilities.h +++ b/chromium/third_party/blink/renderer/core/editing/editing_utilities.h @@ -56,6 +56,7 @@ class HTMLElement; class HTMLSpanElement; struct LocalCaretRect; class Node; +class SystemClipboard; // This file contains a set of helper functions used by the editing commands @@ -136,7 +137,7 @@ inline ContainerNode* ParentCrossingShadowBoundaries<EditingInFlatTreeStrategy>( return FlatTreeTraversal::Parent(node); } -void WriteImageNodeToClipboard(const Node&, const String&); +void WriteImageNodeToClipboard(SystemClipboard&, const Node&, const String&); // boolean functions on Node diff --git a/chromium/third_party/blink/renderer/core/editing/editing_utilities_test.cc b/chromium/third_party/blink/renderer/core/editing/editing_utilities_test.cc index de55c5bf706..3c3a5ea8955 100644 --- a/chromium/third_party/blink/renderer/core/editing/editing_utilities_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/editing_utilities_test.cc @@ -127,7 +127,7 @@ TEST_F(EditingUtilitiesTest, isEditablePositionWithTable) { // element. So, we build DOM tree manually. // Note: This is unusual HTML taken from http://crbug.com/574230 Element* table = GetDocument().CreateRawElement(html_names::kTableTag); - table->SetInnerHTMLFromString("<caption>foo</caption>"); + table->setInnerHTML("<caption>foo</caption>"); while (GetDocument().firstChild()) GetDocument().firstChild()->remove(); GetDocument().AppendChild(table); diff --git a/chromium/third_party/blink/renderer/core/editing/editor.cc b/chromium/third_party/blink/renderer/core/editing/editor.cc index 5d656f31189..b27d63b98a8 100644 --- a/chromium/third_party/blink/renderer/core/editing/editor.cc +++ b/chromium/third_party/blink/renderer/core/editing/editor.cc @@ -26,7 +26,6 @@ #include "third_party/blink/renderer/core/editing/editor.h" -#include "third_party/blink/public/platform/web_scroll_into_view_params.h" #include "third_party/blink/renderer/core/accessibility/ax_object_cache.h" #include "third_party/blink/renderer/core/clipboard/data_object.h" #include "third_party/blink/renderer/core/clipboard/data_transfer.h" @@ -175,7 +174,7 @@ bool Editor::HandleTextEvent(TextEvent* event) { // TODO(editing-dev): The use of UpdateStyleAndLayout // needs to be audited. See http://crbug.com/590369 for more details. - frame_->GetDocument()->UpdateStyleAndLayout(); + frame_->GetDocument()->UpdateStyleAndLayout(DocumentUpdateReason::kEditing); if (event->IsPaste()) { if (event->PastingFragment()) { @@ -236,7 +235,7 @@ bool Editor::CanCopy() const { FrameSelection& selection = GetFrameSelection(); if (!selection.IsAvailable()) return false; - frame_->GetDocument()->UpdateStyleAndLayout(); + frame_->GetDocument()->UpdateStyleAndLayout(DocumentUpdateReason::kEditing); const VisibleSelectionInFlatTree& visible_selection = selection.ComputeVisibleSelectionInFlatTree(); return visible_selection.IsRange() && @@ -502,7 +501,7 @@ bool Editor::InsertTextWithoutSendingTextEvent( LocalFrame* focused_or_main_frame = To<LocalFrame>(page->GetFocusController().FocusedOrMainFrame()); focused_or_main_frame->Selection().RevealSelection( - ScrollAlignment::kAlignToEdgeIfNeeded); + ScrollAlignment::ToEdgeIfNeeded()); } } @@ -518,7 +517,7 @@ bool Editor::InsertLineBreak() { DCHECK(GetFrame().GetDocument()); if (!TypingCommand::InsertLineBreak(*GetFrame().GetDocument())) return false; - RevealSelectionAfterEditingOperation(ScrollAlignment::kAlignToEdgeIfNeeded); + RevealSelectionAfterEditingOperation(ScrollAlignment::ToEdgeIfNeeded()); return true; } @@ -536,7 +535,7 @@ bool Editor::InsertParagraphSeparator() { EditingState editing_state; if (!TypingCommand::InsertParagraphSeparator(*GetFrame().GetDocument())) return false; - RevealSelectionAfterEditingOperation(ScrollAlignment::kAlignToEdgeIfNeeded); + RevealSelectionAfterEditingOperation(ScrollAlignment::ToEdgeIfNeeded()); return true; } @@ -612,7 +611,8 @@ void Editor::CountEvent(ExecutionContext* execution_context, } void Editor::CopyImage(const HitTestResult& result) { - WriteImageNodeToClipboard(*result.InnerNodeOrImageMapImage(), + WriteImageNodeToClipboard(*frame_->GetSystemClipboard(), + *result.InnerNodeOrImageMapImage(), result.AltDisplayString()); } @@ -634,13 +634,13 @@ void Editor::Redo() { void Editor::SetBaseWritingDirection(WritingDirection direction) { Element* focused_element = GetFrame().GetDocument()->FocusedElement(); - if (IsTextControl(focused_element)) { + if (auto* text_control = ToTextControlOrNull(focused_element)) { if (direction == WritingDirection::kNatural) return; - focused_element->setAttribute( + text_control->setAttribute( html_names::kDirAttr, direction == WritingDirection::kLeftToRight ? "ltr" : "rtl"); - focused_element->DispatchInputEvent(); + text_control->DispatchInputEvent(); return; } @@ -657,7 +657,7 @@ void Editor::SetBaseWritingDirection(WritingDirection direction) { } void Editor::RevealSelectionAfterEditingOperation( - const ScrollAlignment& alignment) { + const mojom::blink::ScrollAlignment& alignment) { if (prevent_reveal_selection_) return; if (!GetFrameSelection().IsAvailable()) @@ -725,7 +725,8 @@ void Editor::ComputeAndSetTypingStyle(CSSPropertyValueSet* style, EditingStyle::kPreserveWritingDirection); // Handle block styles, substracting these from the typing style. - EditingStyle* block_style = typing_style_->ExtractAndRemoveBlockProperties(); + EditingStyle* block_style = typing_style_->ExtractAndRemoveBlockProperties( + GetFrame().GetDocument()->ToExecutionContext()); if (!block_style->IsEmpty()) { DCHECK(GetFrame().GetDocument()); MakeGarbageCollected<ApplyStyleCommand>(*GetFrame().GetDocument(), diff --git a/chromium/third_party/blink/renderer/core/editing/editor.h b/chromium/third_party/blink/renderer/core/editing/editor.h index eebbd98c3b6..e6bcb5dd76a 100644 --- a/chromium/third_party/blink/renderer/core/editing/editor.h +++ b/chromium/third_party/blink/renderer/core/editing/editor.h @@ -224,7 +224,7 @@ class CORE_EXPORT Editor final : public GarbageCollected<Editor> { void Trace(Visitor*); void RevealSelectionAfterEditingOperation( - const ScrollAlignment& = ScrollAlignment::kAlignToEdgeIfNeeded); + const mojom::blink::ScrollAlignment& = ScrollAlignment::ToEdgeIfNeeded()); private: Member<LocalFrame> frame_; diff --git a/chromium/third_party/blink/renderer/core/editing/editor_key_bindings.cc b/chromium/third_party/blink/renderer/core/editing/editor_key_bindings.cc index 4e9cca888e2..8b3aac0c93b 100644 --- a/chromium/third_party/blink/renderer/core/editing/editor_key_bindings.cc +++ b/chromium/third_party/blink/renderer/core/editing/editor_key_bindings.cc @@ -26,7 +26,7 @@ #include "third_party/blink/renderer/core/editing/editor.h" -#include "third_party/blink/public/platform/web_input_event.h" +#include "third_party/blink/public/common/input/web_input_event.h" #include "third_party/blink/renderer/core/editing/commands/editor_command.h" #include "third_party/blink/renderer/core/editing/editing_behavior.h" #include "third_party/blink/renderer/core/editing/editing_utilities.h" @@ -39,8 +39,7 @@ namespace blink { bool Editor::HandleEditingKeyboardEvent(KeyboardEvent* evt) { const WebKeyboardEvent* key_event = evt->KeyEvent(); - // do not treat this as text input if it's a system key event - if (!key_event || key_event->is_system_key) + if (!key_event) return false; String command_name = Behavior().InterpretKeyEvent(*evt); diff --git a/chromium/third_party/blink/renderer/core/editing/editor_test.cc b/chromium/third_party/blink/renderer/core/editing/editor_test.cc index 02cece851f0..8e77b8d4f62 100644 --- a/chromium/third_party/blink/renderer/core/editing/editor_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/editor_test.cc @@ -18,8 +18,8 @@ namespace blink { class EditorTest : public EditingTestBase { public: void TearDown() override { - SystemClipboard::GetInstance().WritePlainText(String("")); - SystemClipboard::GetInstance().CommitWrite(); + GetDocument().GetFrame()->GetSystemClipboard()->WritePlainText(String("")); + GetDocument().GetFrame()->GetSystemClipboard()->CommitWrite(); EditingTestBase::TearDown(); } @@ -69,7 +69,8 @@ TEST_F(EditorTest, CopyVisibleSelection) { ExecuteCopy(); - const String copied = SystemClipboard::GetInstance().ReadPlainText(); + const String copied = + GetDocument().GetFrame()->GetSystemClipboard()->ReadPlainText(); EXPECT_EQ("HEY", copied); } @@ -89,7 +90,8 @@ TEST_F(EditorTest, DontCopyHiddenSelections) { ExecuteCopy(); - const String copied = SystemClipboard::GetInstance().ReadPlainText(); + const String copied = + GetDocument().GetFrame()->GetSystemClipboard()->ReadPlainText(); EXPECT_TRUE(copied.IsEmpty()) << copied << " was copied."; } diff --git a/chromium/third_party/blink/renderer/core/editing/element_inner_text.cc b/chromium/third_party/blink/renderer/core/editing/element_inner_text.cc index 2fe5c49d329..3f9ec9020d8 100644 --- a/chromium/third_party/blink/renderer/core/editing/element_inner_text.cc +++ b/chromium/third_party/blink/renderer/core/editing/element_inner_text.cc @@ -72,7 +72,6 @@ class ElementInnerTextCollector final { static bool IsBeingRendered(const Node& node); // Returns true if used value of "display" is block-level. static bool IsDisplayBlockLevel(const Node&); - static LayoutObject* PreviousLeafOf(const LayoutObject& layout_object); static bool ShouldEmitNewlineForTableRow( const LayoutNGTableRowInterface& table_row); @@ -81,7 +80,6 @@ class ElementInnerTextCollector final { void ProcessChildrenWithRequiredLineBreaks(const Node& node, int required_line_break_count); void ProcessLayoutText(const LayoutText& layout_text, const Text& text_node); - void ProcessLayoutTextEmpty(const LayoutText& layout_text); void ProcessNode(const Node& node); void ProcessOptionElement(const HTMLOptionElement& element); void ProcessSelectElement(const HTMLSelectElement& element); @@ -181,19 +179,6 @@ bool ElementInnerTextCollector::IsDisplayBlockLevel(const Node& node) { } // static -LayoutObject* ElementInnerTextCollector::PreviousLeafOf( - const LayoutObject& layout_object) { - LayoutObject* parent = layout_object.Parent(); - for (LayoutObject* runner = layout_object.PreviousInPreOrder(); runner; - runner = runner->PreviousInPreOrder()) { - if (runner != parent) - return runner; - parent = runner->Parent(); - } - return nullptr; -} - -// static bool ElementInnerTextCollector::ShouldEmitNewlineForTableRow( const LayoutNGTableRowInterface& table_row) { const LayoutNGTableInterface* const table = table_row.TableInterface(); @@ -477,7 +462,8 @@ void ElementInnerTextCollector::Result::FlushRequiredLineBreak() { String Element::innerText() { // We need to update layout, since |ElementInnerTextCollector()| uses line // boxes in the layout tree. - GetDocument().UpdateStyleAndLayoutForNode(this); + GetDocument().UpdateStyleAndLayoutForNode(this, + DocumentUpdateReason::kJavaScript); return ElementInnerTextCollector().RunOn(*this); } diff --git a/chromium/third_party/blink/renderer/core/editing/element_inner_text_test.cc b/chromium/third_party/blink/renderer/core/editing/element_inner_text_test.cc index efc058cf6d4..b211b9f529c 100644 --- a/chromium/third_party/blink/renderer/core/editing/element_inner_text_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/element_inner_text_test.cc @@ -15,7 +15,9 @@ class ElementInnerTest : public testing::WithParamInterface<bool>, protected: ElementInnerTest() : ScopedLayoutNGForTest(GetParam()) {} - bool LayoutNGEnabled() const { return GetParam(); } + bool LayoutNGEnabled() const { + return RuntimeEnabledFeatures::LayoutNGEnabled(); + } }; INSTANTIATE_TEST_SUITE_P(All, ElementInnerTest, testing::Bool()); diff --git a/chromium/third_party/blink/renderer/core/editing/ephemeral_range.cc b/chromium/third_party/blink/renderer/core/editing/ephemeral_range.cc index 8b9e78a9a92..1d193eb467a 100644 --- a/chromium/third_party/blink/renderer/core/editing/ephemeral_range.cc +++ b/chromium/third_party/blink/renderer/core/editing/ephemeral_range.cc @@ -212,13 +212,21 @@ std::ostream& operator<<(std::ostream& ostream, EphemeralRangeInFlatTree ToEphemeralRangeInFlatTree( const EphemeralRange& range) { + // We need to update the distribution before getting the position in the flat + // tree, since that operation requires us to navigate the flat tree. + if (range.StartPosition().AnchorNode()) { + range.StartPosition() + .AnchorNode() + ->UpdateDistributionForFlatTreeTraversal(); + } + if (range.EndPosition().AnchorNode()) { + range.EndPosition().AnchorNode()->UpdateDistributionForFlatTreeTraversal(); + } PositionInFlatTree start = ToPositionInFlatTree(range.StartPosition()); PositionInFlatTree end = ToPositionInFlatTree(range.EndPosition()); if (start.IsNull() || end.IsNull() || start.GetDocument() != end.GetDocument()) return EphemeralRangeInFlatTree(); - start.AnchorNode()->UpdateDistributionForFlatTreeTraversal(); - end.AnchorNode()->UpdateDistributionForFlatTreeTraversal(); if (!start.IsValidFor(*start.GetDocument()) || !end.IsValidFor(*end.GetDocument())) return EphemeralRangeInFlatTree(); diff --git a/chromium/third_party/blink/renderer/core/editing/ephemeral_range.h b/chromium/third_party/blink/renderer/core/editing/ephemeral_range.h index 3e15fb20746..907747a3c3d 100644 --- a/chromium/third_party/blink/renderer/core/editing/ephemeral_range.h +++ b/chromium/third_party/blink/renderer/core/editing/ephemeral_range.h @@ -29,7 +29,7 @@ class TraversalRangeNodes : private TraversalRange<Iterator> { Iterator end() { return Iterator(past_end_node_); } private: - const Member<const StartNodeType> past_end_node_; + const StartNodeType* const past_end_node_; }; // This class acts like |TraversalNextIterator| but in addition diff --git a/chromium/third_party/blink/renderer/core/editing/finder/find_buffer.cc b/chromium/third_party/blink/renderer/core/editing/finder/find_buffer.cc index ed537308ac2..1367abe1212 100644 --- a/chromium/third_party/blink/renderer/core/editing/finder/find_buffer.cc +++ b/chromium/third_party/blink/renderer/core/editing/finder/find_buffer.cc @@ -24,108 +24,10 @@ #include "third_party/blink/renderer/platform/wtf/text/unicode.h" namespace blink { +namespace { -FindBuffer::FindBuffer(const EphemeralRangeInFlatTree& range) { - DCHECK(range.IsNotNull() && !range.IsCollapsed()) << range; - CollectTextUntilBlockBoundary(range); -} - -FindBuffer::Results::Results() { - empty_result_ = true; -} - -FindBuffer::Results::Results(const FindBuffer& find_buffer, - TextSearcherICU* text_searcher, - const Vector<UChar>& buffer, - const String& search_text, - const blink::FindOptions options) { - // We need to own the |search_text| because |text_searcher_| only has a - // StringView (doesn't own the search text). - search_text_ = search_text; - find_buffer_ = &find_buffer; - text_searcher_ = text_searcher; - text_searcher_->SetPattern(search_text_, options); - text_searcher_->SetText(buffer.data(), buffer.size()); - text_searcher_->SetOffset(0); -} - -FindBuffer::Results::Iterator::Iterator(const FindBuffer& find_buffer, - TextSearcherICU* text_searcher, - const String& search_text) - : find_buffer_(&find_buffer), - text_searcher_(text_searcher), - has_match_(true) { - operator++(); -} - -const FindBuffer::BufferMatchResult FindBuffer::Results::Iterator::operator*() - const { - DCHECK(has_match_); - return FindBuffer::BufferMatchResult({match_.start, match_.length}); -} - -void FindBuffer::Results::Iterator::operator++() { - DCHECK(has_match_); - has_match_ = text_searcher_->NextMatchResult(match_); - if (has_match_ && find_buffer_ && find_buffer_->IsInvalidMatch(match_)) - operator++(); -} - -bool FindBuffer::IsInvalidMatch(MatchResultICU match) const { - // Invalid matches are a result of accidentally matching elements that are - // replaced with the max code point, and may lead to crashes. To avoid - // crashing, we should skip the matches that are invalid - they would have - // either an empty position or a non-offset-in-anchor position. - const unsigned start_index = match.start; - PositionInFlatTree start_position = - PositionAtStartOfCharacterAtIndex(start_index); - if (start_position.IsNull() || !start_position.IsOffsetInAnchor()) - return true; - - const unsigned end_index = match.start + match.length; - DCHECK_LE(start_index, end_index); - PositionInFlatTree end_position = - PositionAtEndOfCharacterAtIndex(end_index - 1); - if (end_position.IsNull() || !end_position.IsOffsetInAnchor()) - return true; - return false; -} - -FindBuffer::Results::Iterator FindBuffer::Results::begin() const { - if (empty_result_) - return end(); - text_searcher_->SetOffset(0); - return Iterator(*find_buffer_, text_searcher_, search_text_); -} - -FindBuffer::Results::Iterator FindBuffer::Results::end() const { - return Iterator(); -} - -bool FindBuffer::Results::IsEmpty() const { - return begin() == end(); -} - -FindBuffer::BufferMatchResult FindBuffer::Results::front() const { - return *begin(); -} - -FindBuffer::BufferMatchResult FindBuffer::Results::back() const { - Iterator last_result; - for (Iterator it = begin(); it != end(); ++it) { - last_result = it; - } - return *last_result; -} - -unsigned FindBuffer::Results::CountForTesting() const { - unsigned result = 0; - for (Iterator it = begin(); it != end(); ++it) { - ++result; - } - return result; -} - +// Returns true if the search should ignore the given |node|'s contents. In +// other words, we don't need to recurse into the node's children. bool ShouldIgnoreContents(const Node& node) { const auto* element = DynamicTo<HTMLElement>(node); if (!element) @@ -140,10 +42,14 @@ bool ShouldIgnoreContents(const Node& node) { IsA<HTMLStyleElement>(*element) || IsA<HTMLScriptElement>(*element) || IsA<HTMLVideoElement>(*element) || IsA<HTMLAudioElement>(*element) || (element->GetDisplayLockContext() && + element->GetDisplayLockContext()->IsLocked() && !element->GetDisplayLockContext()->IsActivatable( DisplayLockActivationReason::kFindInPage)); } +// Returns the first ancestor that isn't searchable. In other words, either +// ShouldIgnoreContents() returns true for it or it has a display: none style. +// Returns nullptr if no such ancestor exists. Node* GetNonSearchableAncestor(const Node& node) { for (Node& ancestor : FlatTreeTraversal::InclusiveAncestorsOf(node)) { const ComputedStyle* style = ancestor.EnsureComputedStyle(); @@ -156,12 +62,15 @@ Node* GetNonSearchableAncestor(const Node& node) { return nullptr; } +// Returns true if the given |display| is considered a 'block' bool IsBlock(EDisplay display) { return display == EDisplay::kBlock || display == EDisplay::kTable || display == EDisplay::kFlowRoot || display == EDisplay::kGrid || display == EDisplay::kFlex || display == EDisplay::kListItem; } +// Returns the next node after |start_node| (including start node) that is a +// text node and is searchable and visible. Node* GetVisibleTextNode(Node& start_node) { Node* node = &start_node; // Move to outside display none subtree if we're inside one. @@ -192,6 +101,8 @@ Node* GetVisibleTextNode(Node& start_node) { return nullptr; } +// Returns the closest ancestor of |start_node| (including the node itself) that +// is a block. Node& GetLowestDisplayBlockInclusiveAncestor(const Node& start_node) { // Gets lowest inclusive ancestor that has block display value. // <div id=outer>a<div id=inner>b</div>c</div> @@ -204,6 +115,33 @@ Node& GetLowestDisplayBlockInclusiveAncestor(const Node& start_node) { } return *start_node.GetDocument().documentElement(); } +} // namespace + +// FindBuffer implementation. +FindBuffer::FindBuffer(const EphemeralRangeInFlatTree& range) { + DCHECK(range.IsNotNull() && !range.IsCollapsed()) << range; + CollectTextUntilBlockBoundary(range); +} + +bool FindBuffer::IsInvalidMatch(MatchResultICU match) const { + // Invalid matches are a result of accidentally matching elements that are + // replaced with the max code point, and may lead to crashes. To avoid + // crashing, we should skip the matches that are invalid - they would have + // either an empty position or a non-offset-in-anchor position. + const unsigned start_index = match.start; + PositionInFlatTree start_position = + PositionAtStartOfCharacterAtIndex(start_index); + if (start_position.IsNull() || !start_position.IsOffsetInAnchor()) + return true; + + const unsigned end_index = match.start + match.length; + DCHECK_LE(start_index, end_index); + PositionInFlatTree end_position = + PositionAtEndOfCharacterAtIndex(end_index - 1); + if (end_position.IsNull() || !end_position.IsOffsetInAnchor()) + return true; + return false; +} EphemeralRangeInFlatTree FindBuffer::FindMatchInRange( const EphemeralRangeInFlatTree& range, @@ -265,52 +203,12 @@ FindBuffer::Results FindBuffer::FindMatches(const WebString& search_text, return Results(*this, &text_searcher_, buffer_, search_text_16_bit, options); } -bool FindBuffer::PushScopedForcedUpdateIfNeeded(const Element& element) { - if (auto* context = element.GetDisplayLockContext()) { - DCHECK(context->IsActivatable(DisplayLockActivationReason::kFindInPage)); - scoped_forced_update_list_.push_back(context->GetScopedForcedUpdate()); - return true; - } - return false; -} - -void FindBuffer::CollectScopedForcedUpdates(Node& start_node, - const Node* search_range_end_node, - const Node* node_after_block) { - if (!RuntimeEnabledFeatures::DisplayLockingEnabled( - start_node.GetExecutionContext())) - return; - if (start_node.GetDocument().LockedDisplayLockCount() == - start_node.GetDocument().ActivationBlockingDisplayLockCount()) - return; - - Node* node = &start_node; - // We assume |start_node| is always visible/activatable if locked, so we don't - // need to check activatability of ancestors here. - for (Node& ancestor : FlatTreeTraversal::InclusiveAncestorsOf(*node)) { - auto* ancestor_element = DynamicTo<Element>(ancestor); - if (!ancestor_element) - continue; - PushScopedForcedUpdateIfNeeded(*ancestor_element); - } - - while (node && node != node_after_block && node != search_range_end_node) { - if (ShouldIgnoreContents(*node)) { - // Will skip display:none/non-activatable locked subtrees/etc. - node = FlatTreeTraversal::NextSkippingChildren(*node); - continue; - } - if (auto* element = DynamicTo<Element>(node)) - PushScopedForcedUpdateIfNeeded(*element); - node = FlatTreeTraversal::Next(*node); - } -} - -// Collects text until block boundary located at or after |start_node| -// to |buffer_|. Saves the next starting node after the block to -// |node_after_block_|. void FindBuffer::CollectTextUntilBlockBoundary( const EphemeralRangeInFlatTree& range) { + // Collects text until block boundary located at or after |start_node| + // to |buffer_|. Saves the next starting node after the block to + // |node_after_block_|. + DCHECK(range.IsNotNull() && !range.IsCollapsed()) << range; node_after_block_ = nullptr; @@ -337,12 +235,6 @@ void FindBuffer::CollectTextUntilBlockBoundary( // We will also stop if we encountered/passed |end_node|. Node* end_node = range.EndPosition().NodeAsRangeLastNode(); - if (node) { - CollectScopedForcedUpdates(*node, end_node, just_after_block); - if (!scoped_forced_update_list_.IsEmpty()) - node->GetDocument().UpdateStyleAndLayout(); - } - while (node && node != just_after_block) { if (ShouldIgnoreContents(*node)) { if (end_node && (end_node == node || @@ -499,4 +391,82 @@ void FindBuffer::AddTextToBuffer(const Text& text_node, } } +// FindBuffer::Results implementation. +FindBuffer::Results::Results() { + empty_result_ = true; +} + +FindBuffer::Results::Results(const FindBuffer& find_buffer, + TextSearcherICU* text_searcher, + const Vector<UChar>& buffer, + const String& search_text, + const blink::FindOptions options) { + // We need to own the |search_text| because |text_searcher_| only has a + // StringView (doesn't own the search text). + search_text_ = search_text; + find_buffer_ = &find_buffer; + text_searcher_ = text_searcher; + text_searcher_->SetPattern(search_text_, options); + text_searcher_->SetText(buffer.data(), buffer.size()); + text_searcher_->SetOffset(0); +} + +FindBuffer::Results::Iterator FindBuffer::Results::begin() const { + if (empty_result_) + return end(); + text_searcher_->SetOffset(0); + return Iterator(*find_buffer_, text_searcher_, search_text_); +} + +FindBuffer::Results::Iterator FindBuffer::Results::end() const { + return Iterator(); +} + +bool FindBuffer::Results::IsEmpty() const { + return begin() == end(); +} + +FindBuffer::BufferMatchResult FindBuffer::Results::front() const { + return *begin(); +} + +FindBuffer::BufferMatchResult FindBuffer::Results::back() const { + Iterator last_result; + for (Iterator it = begin(); it != end(); ++it) { + last_result = it; + } + return *last_result; +} + +unsigned FindBuffer::Results::CountForTesting() const { + unsigned result = 0; + for (Iterator it = begin(); it != end(); ++it) { + ++result; + } + return result; +} + +// Findbuffer::Results::Iterator implementation. +FindBuffer::Results::Iterator::Iterator(const FindBuffer& find_buffer, + TextSearcherICU* text_searcher, + const String& search_text) + : find_buffer_(&find_buffer), + text_searcher_(text_searcher), + has_match_(true) { + operator++(); +} + +const FindBuffer::BufferMatchResult FindBuffer::Results::Iterator::operator*() + const { + DCHECK(has_match_); + return FindBuffer::BufferMatchResult({match_.start, match_.length}); +} + +void FindBuffer::Results::Iterator::operator++() { + DCHECK(has_match_); + has_match_ = text_searcher_->NextMatchResult(match_); + if (has_match_ && find_buffer_ && find_buffer_->IsInvalidMatch(match_)) + operator++(); +} + } // namespace blink diff --git a/chromium/third_party/blink/renderer/core/editing/finder/find_buffer.h b/chromium/third_party/blink/renderer/core/editing/finder/find_buffer.h index bcb387c9097..97cb1ce114e 100644 --- a/chromium/third_party/blink/renderer/core/editing/finder/find_buffer.h +++ b/chromium/third_party/blink/renderer/core/editing/finder/find_buffer.h @@ -133,19 +133,6 @@ class CORE_EXPORT FindBuffer { // another LayoutBlockFlow or after |end_position|) to |node_after_block_|. void CollectTextUntilBlockBoundary(const EphemeralRangeInFlatTree& range); - // Adds the ScopedForcedUpdate of |element|'s DisplayLockContext (if it's - // there) to |scoped_forced_update_list_|. Returns true if we added a - // ScopedForceUpdate. - bool PushScopedForcedUpdateIfNeeded(const Element& element); - - // Collects all ScopedForceUpdates of any activatable-locked element - // within the range of [start_node, search_range_end_node] or - // [start_node, node_after_block) whichever is smaller, to - // |scoped_forced_update_list_|. - void CollectScopedForcedUpdates(Node& start_node, - const Node* search_range_end_node, - const Node* node_after_block); - // Mapping for position in buffer -> actual node where the text came from, // along with the offset in the NGOffsetMapping of this find_buffer. // This is needed because when we find a match in the buffer, we want to know @@ -187,10 +174,9 @@ class CORE_EXPORT FindBuffer { LayoutBlockFlow& block_flow, const EphemeralRangeInFlatTree& range); - Member<Node> node_after_block_; + Node* node_after_block_ = nullptr; Vector<UChar> buffer_; Vector<BufferNodeMapping> buffer_node_mappings_; - Vector<DisplayLockContext::ScopedForcedUpdate> scoped_forced_update_list_; TextSearcherICU text_searcher_; const NGOffsetMapping* offset_mapping_ = nullptr; diff --git a/chromium/third_party/blink/renderer/core/editing/finder/find_in_page_coordinates.cc b/chromium/third_party/blink/renderer/core/editing/finder/find_in_page_coordinates.cc index 46f2f6b312d..f0127d5567c 100644 --- a/chromium/third_party/blink/renderer/core/editing/finder/find_in_page_coordinates.cc +++ b/chromium/third_party/blink/renderer/core/editing/finder/find_in_page_coordinates.cc @@ -49,12 +49,12 @@ namespace blink { static const LayoutBlock* EnclosingScrollableAncestor( const LayoutObject* layout_object) { - DCHECK(!layout_object->IsLayoutView()); + DCHECK(!IsA<LayoutView>(layout_object)); // Trace up the containingBlocks until we reach either the layoutObject view // or a scrollable object. const LayoutBlock* container = layout_object->ContainingBlock(); - while (!container->HasOverflowClip() && !container->IsLayoutView()) + while (!container->HasOverflowClip() && !IsA<LayoutView>(container)) container = container->ContainingBlock(); return container; } @@ -64,7 +64,7 @@ static FloatRect ToNormalizedRect(const FloatRect& absolute_rect, const LayoutBlock* container) { DCHECK(layout_object); - DCHECK(container || layout_object->IsLayoutView()); + DCHECK(container || IsA<LayoutView>(layout_object)); if (!container) return FloatRect(); @@ -111,7 +111,7 @@ FloatRect FindInPageRectFromAbsoluteRect( for (const LayoutBox* layout_object = base_container; layout_object;) { // Go up the layout tree until we reach the root of the current frame (the // LayoutView). - while (!layout_object->IsLayoutView()) { + while (!IsA<LayoutView>(layout_object)) { const LayoutBlock* container = EnclosingScrollableAncestor(layout_object); // Compose the normalized rects. @@ -125,7 +125,7 @@ FloatRect FindInPageRectFromAbsoluteRect( layout_object = container; } - DCHECK(layout_object->IsLayoutView()); + DCHECK(IsA<LayoutView>(layout_object)); // Jump to the layoutObject owning the frame, if any. layout_object = layout_object->GetFrame() diff --git a/chromium/third_party/blink/renderer/core/editing/finder/find_task_controller.cc b/chromium/third_party/blink/renderer/core/editing/finder/find_task_controller.cc index d4617e7a720..594e3ff6895 100644 --- a/chromium/third_party/blink/renderer/core/editing/finder/find_task_controller.cc +++ b/chromium/third_party/blink/renderer/core/editing/finder/find_task_controller.cc @@ -5,8 +5,8 @@ #include "third_party/blink/renderer/core/editing/finder/find_task_controller.h" #include "third_party/blink/public/mojom/frame/find_in_page.mojom-blink.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_idle_request_options.h" #include "third_party/blink/renderer/core/dom/document.h" -#include "third_party/blink/renderer/core/dom/idle_request_options.h" #include "third_party/blink/renderer/core/dom/range.h" #include "third_party/blink/renderer/core/dom/scripted_idle_task_controller.h" #include "third_party/blink/renderer/core/editing/ephemeral_range.h" @@ -68,21 +68,33 @@ class FindTaskController::IdleFindTask private: void invoke(IdleDeadline* deadline) override { + const base::TimeTicks task_start_time = base::TimeTicks::Now(); + if (!controller_) + return; if (!controller_->ShouldFindMatches(search_text_, *options_)) { controller_->DidFinishTask(identifier_, search_text_, *options_, true /* finished_whole_request */, - PositionInFlatTree(), 0 /* match_count */); + PositionInFlatTree(), 0 /* match_count */, + true /* aborted */, task_start_time); + return; } - - Document& document = *controller_->GetLocalFrame()->GetDocument(); + SCOPED_UMA_HISTOGRAM_TIMER("WebCore.FindInPage.TaskDuration"); + + Document* document = controller_->GetLocalFrame()->GetDocument(); + if (!document || document_ != document) + return; + Document::ScopedForceActivatableDisplayLocks + forced_activatable_display_locks( + document->GetScopedForceActivatableLocks()); PositionInFlatTree search_start = - PositionInFlatTree::FirstPositionInNode(document); + PositionInFlatTree::FirstPositionInNode(*document); PositionInFlatTree search_end; - if (document.documentElement() && document.documentElement()->lastChild()) { + if (document->documentElement() && + document->documentElement()->lastChild()) { search_end = PositionInFlatTree::AfterNode( - *document.documentElement()->lastChild()); + *document->documentElement()->lastChild()); } else { - search_end = PositionInFlatTree::LastPositionInNode(document); + search_end = PositionInFlatTree::LastPositionInNode(*document); } DCHECK_EQ(search_start.GetDocument(), search_end.GetDocument()); @@ -96,9 +108,8 @@ class FindTaskController::IdleFindTask return; } - // TODO(editing-dev): Use of UpdateStyleAndLayout - // needs to be audited. see http://crbug.com/590369 for more details. - search_start.GetDocument()->UpdateStyleAndLayout(); + // This is required if we forced any of the display-locks. + document->UpdateStyleAndLayout(DocumentUpdateReason::kFindInPage); int match_count = 0; bool full_range_searched = false; @@ -143,10 +154,10 @@ class FindTaskController::IdleFindTask if (deadline->timeRemaining() <= 0) break; } - controller_->DidFinishTask(identifier_, search_text_, *options_, full_range_searched, next_task_start_position, - match_count); + match_count, false /* aborted */, + task_start_time); } Member<Document> document_; @@ -167,6 +178,10 @@ void FindTaskController::StartRequest( int identifier, const WebString& search_text, const mojom::blink::FindOptions& options) { + current_request_start_time_ = base::TimeTicks::Now(); + total_task_duration_for_current_request_ = base::TimeDelta(); + task_count_for_current_request_ = 0; + DCHECK(!finding_in_progress_); // This is a brand new search, so we need to reset everything. finding_in_progress_ = true; current_match_count_ = 0; @@ -174,12 +189,14 @@ void FindTaskController::StartRequest( } void FindTaskController::CancelPendingRequest() { - if (idle_find_task_) { - idle_find_task_->Dispose(); - idle_find_task_.Clear(); + if (find_task_) { + find_task_->Dispose(); + find_task_.Clear(); } - if (finding_in_progress_) + if (finding_in_progress_) { + RecordRequestMetrics(RequestEndState::ABORTED); last_find_request_completed_with_no_matches_ = false; + } finding_in_progress_ = false; resume_finding_from_range_ = nullptr; } @@ -188,14 +205,14 @@ void FindTaskController::RequestIdleFindTask( int identifier, const WebString& search_text, const mojom::blink::FindOptions& options) { - DCHECK_EQ(idle_find_task_, nullptr); - idle_find_task_ = MakeGarbageCollected<IdleFindTask>( + DCHECK_EQ(find_task_, nullptr); + find_task_ = MakeGarbageCollected<IdleFindTask>( this, GetLocalFrame()->GetDocument(), identifier, search_text, options); // If it's for testing, run the task immediately. // TODO(rakina): Change to use general solution when it's available. // https://crbug.com/875203 if (options.run_synchronously_for_testing) - idle_find_task_->ForceInvocationForTesting(); + find_task_->ForceInvocationForTesting(); } void FindTaskController::DidFinishTask( @@ -204,11 +221,17 @@ void FindTaskController::DidFinishTask( const mojom::blink::FindOptions& options, bool finished_whole_request, PositionInFlatTree next_starting_position, - int match_count) { - if (idle_find_task_) { - idle_find_task_->Dispose(); - idle_find_task_.Clear(); + int match_count, + bool aborted, + base::TimeTicks task_start_time) { + if (find_task_) { + find_task_->Dispose(); + find_task_.Clear(); } + total_task_duration_for_current_request_ += + base::TimeTicks::Now() - task_start_time; + if (find_task_) + find_task_.Clear(); // Remember what we search for last time, so we can skip searching if more // letters are added to the search string (and last outcome was 0). last_search_string_ = search_text; @@ -226,17 +249,42 @@ void FindTaskController::DidFinishTask( } if (!finished_whole_request) { - // Idle task ran out of time, request for another one. + // Task ran out of time, request for another one. RequestIdleFindTask(identifier, search_text, options); return; // Done for now, resume work later. } text_finder_->FinishCurrentScopingEffort(identifier); + RecordRequestMetrics(RequestEndState::ABORTED); last_find_request_completed_with_no_matches_ = !current_match_count_; finding_in_progress_ = false; } +void FindTaskController::RecordRequestMetrics( + RequestEndState request_end_state) { + bool aborted = (request_end_state == RequestEndState::ABORTED); + if (aborted) { + UMA_HISTOGRAM_MEDIUM_TIMES("WebCore.FindInPage.TotalTaskDuration.Aborted", + total_task_duration_for_current_request_); + UMA_HISTOGRAM_MEDIUM_TIMES( + "WebCore.FindInPage.RequestDuration.Aborted", + base::TimeTicks::Now() - current_request_start_time_); + UMA_HISTOGRAM_COUNTS_1000( + "WebCore.FindInPage.NumberOfTasksPerRequest.Aborted", + task_count_for_current_request_); + } else { + UMA_HISTOGRAM_MEDIUM_TIMES("WebCore.FindInPage.TotalTaskDuration.Finished", + total_task_duration_for_current_request_); + UMA_HISTOGRAM_MEDIUM_TIMES( + "WebCore.FindInPage.RequestDuration.Finished", + base::TimeTicks::Now() - current_request_start_time_); + UMA_HISTOGRAM_COUNTS_1000( + "WebCore.FindInPage.NumberOfTasksPerRequest.Finished", + task_count_for_current_request_); + } +} + LocalFrame* FindTaskController::GetLocalFrame() const { return OwnerFrame().GetFrame(); } @@ -244,10 +292,10 @@ LocalFrame* FindTaskController::GetLocalFrame() const { bool FindTaskController::ShouldFindMatches( const String& search_text, const mojom::blink::FindOptions& options) { - // Don't scope if we can't find a frame or a view. + // Don't scope if we can't find a frame, a document, or a view. // The user may have closed the tab/application, so abort. LocalFrame* frame = GetLocalFrame(); - if (!frame || !frame->View() || !frame->GetPage()) + if (!frame || !frame->View() || !frame->GetPage() || !frame->GetDocument()) return false; DCHECK(frame->GetDocument()); @@ -283,7 +331,7 @@ void FindTaskController::DidFindMatch(int identifier, Range* result_range) { void FindTaskController::Trace(Visitor* visitor) { visitor->Trace(owner_frame_); visitor->Trace(text_finder_); - visitor->Trace(idle_find_task_); + visitor->Trace(find_task_); visitor->Trace(resume_finding_from_range_); } diff --git a/chromium/third_party/blink/renderer/core/editing/finder/find_task_controller.h b/chromium/third_party/blink/renderer/core/editing/finder/find_task_controller.h index 58e6c8394b4..ff28a2d2849 100644 --- a/chromium/third_party/blink/renderer/core/editing/finder/find_task_controller.h +++ b/chromium/third_party/blink/renderer/core/editing/finder/find_task_controller.h @@ -48,7 +48,7 @@ class CORE_EXPORT FindTaskController final bool ShouldFindMatches(const String& search_text, const mojom::blink::FindOptions& options); - // During a run of |idle_find_task|, we found a match. + // During a run of |find_task|, we found a match. // Updates |current_match_count_| and notifies |text_finder_|. void DidFindMatch(int identifier, Range* result_range); @@ -59,12 +59,14 @@ class CORE_EXPORT FindTaskController final const mojom::blink::FindOptions& options, bool finished_whole_request, PositionInFlatTree next_starting_position, - int match_count); + int match_count, + bool aborted, + base::TimeTicks task_start_time); Range* ResumeFindingFromRange() const { return resume_finding_from_range_; } int CurrentMatchCount() const { return current_match_count_; } - // Idle task, when invoked will search for a given text and notify us + // When invoked this will search for a given text and notify us // whenever a match is found or when it finishes, through FoundMatch and // DidFinishTask. class IdleFindTask; @@ -78,11 +80,22 @@ class CORE_EXPORT FindTaskController final const WebString& search_text, const mojom::blink::FindOptions& options); + enum class RequestEndState { + // The find-in-page request got aborted before going through every text in + // the document. + ABORTED, + // The find-in-page request finished going through every text in the + // document. + FINISHED, + }; + + void RecordRequestMetrics(RequestEndState request_end_state); + Member<WebLocalFrameImpl> owner_frame_; Member<TextFinder> text_finder_; - Member<IdleFindTask> idle_find_task_; + Member<IdleFindTask> find_task_; // Keeps track if there is any ongoing find effort or not. bool finding_in_progress_; @@ -102,6 +115,13 @@ class CORE_EXPORT FindTaskController final // without finding any matches in this frame. bool last_find_request_completed_with_no_matches_; + // The start time of the current find-in-page request. + base::TimeTicks current_request_start_time_; + // The combined duration of all the tasks done for the current request. + base::TimeDelta total_task_duration_for_current_request_; + // The number of find-in-page tasks the current request has made. + int task_count_for_current_request_; + // Keeps track of the last string this frame searched for. This is used for // short-circuiting searches in the following scenarios: When a frame has // been searched and returned 0 results, we don't need to search that frame diff --git a/chromium/third_party/blink/renderer/core/editing/finder/text_finder.cc b/chromium/third_party/blink/renderer/core/editing/finder/text_finder.cc index ad3e029794a..4e83f654829 100644 --- a/chromium/third_party/blink/renderer/core/editing/finder/text_finder.cc +++ b/chromium/third_party/blink/renderer/core/editing/finder/text_finder.cc @@ -30,8 +30,9 @@ #include "third_party/blink/renderer/core/editing/finder/text_finder.h" +#include "third_party/blink/public/mojom/input/focus_type.mojom-blink.h" +#include "third_party/blink/public/mojom/scroll/scroll_into_view_params.mojom-blink.h" #include "third_party/blink/public/platform/web_float_rect.h" -#include "third_party/blink/public/platform/web_scroll_into_view_params.h" #include "third_party/blink/public/platform/web_vector.h" #include "third_party/blink/public/web/web_frame_widget.h" #include "third_party/blink/public/web/web_local_frame_client.h" @@ -75,23 +76,25 @@ void TextFinder::FindMatch::Trace(Visitor* visitor) { static void ScrollToVisible(Range* match) { const Node& first_node = *match->FirstNode(); if (RuntimeEnabledFeatures::InvisibleDOMEnabled() || - RuntimeEnabledFeatures::DisplayLockingEnabled( - first_node.GetExecutionContext())) { + RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled()) { const EphemeralRangeInFlatTree range(match); if (InvisibleDOM::ActivateRangeIfNeeded(range) || - DisplayLockUtilities::ActivateFindInPageMatchRangeIfNeeded(range)) - first_node.GetDocument().UpdateStyleAndLayout(); + DisplayLockUtilities::ActivateFindInPageMatchRangeIfNeeded(range)) { + first_node.GetDocument().UpdateStyleAndLayout( + DocumentUpdateReason::kFindInPage); + } } Settings* settings = first_node.GetDocument().GetSettings(); bool smooth_find_enabled = settings ? settings->GetSmoothScrollForFindEnabled() : false; - ScrollBehavior scroll_behavior = - smooth_find_enabled ? kScrollBehaviorSmooth : kScrollBehaviorAuto; + mojom::blink::ScrollBehavior scroll_behavior = + smooth_find_enabled ? mojom::blink::ScrollBehavior::kSmooth + : mojom::blink::ScrollBehavior::kAuto; first_node.GetLayoutObject()->ScrollRectToVisible( PhysicalRect(match->BoundingBox()), - WebScrollIntoViewParams( - ScrollAlignment::kAlignCenterIfNeeded, - ScrollAlignment::kAlignCenterIfNeeded, kUserScroll, + ScrollAlignment::CreateScrollIntoViewParams( + ScrollAlignment::CenterIfNeeded(), ScrollAlignment::CenterIfNeeded(), + mojom::blink::ScrollType::kUser, true /* make_visible_in_visual_viewport */, scroll_behavior, true /* is_for_scroll_sequence */)); first_node.GetDocument().SetSequentialFocusNavigationStartingPoint( @@ -205,7 +208,7 @@ bool TextFinder::Find(int identifier, else if (active_match_index_ < 0) active_match_index_ = find_task_controller_->CurrentMatchCount() - 1; } - WebRect selection_rect = OwnerFrame().GetFrameView()->ConvertToRootFrame( + gfx::Rect selection_rect = OwnerFrame().GetFrameView()->ConvertToRootFrame( active_match_->BoundingBox()); ReportFindInPageSelection(selection_rect, active_match_index_ + 1, identifier); @@ -242,7 +245,8 @@ void TextFinder::SetFindEndstateFocusAndSelection() { // Need to clean out style and layout state before querying // Element::isFocusable(). - GetFrame()->GetDocument()->UpdateStyleAndLayout(); + GetFrame()->GetDocument()->UpdateStyleAndLayout( + DocumentUpdateReason::kFindInPage); // Try to find the first focusable node up the chain, which will, for // example, focus links if we have found text within the link. @@ -268,7 +272,7 @@ void TextFinder::SetFindEndstateFocusAndSelection() { .Build()); GetFrame()->GetDocument()->SetFocusedElement( element, FocusParams(SelectionBehaviorOnFocus::kNone, - kWebFocusTypeNone, nullptr)); + mojom::blink::FocusType::kNone, nullptr)); return; } } @@ -284,7 +288,7 @@ void TextFinder::SetFindEndstateFocusAndSelection() { if (element->IsFocusable()) { GetFrame()->GetDocument()->SetFocusedElement( element, FocusParams(SelectionBehaviorOnFocus::kNone, - kWebFocusTypeNone, nullptr)); + mojom::blink::FocusType::kNone, nullptr)); return; } } @@ -327,9 +331,9 @@ void TextFinder::StopFindingAndClearSelection() { } void TextFinder::ReportFindInPageTerminationToAccessibility() { - if (OwnerFrame().Client()) { - OwnerFrame().Client()->HandleAccessibilityFindInPageTermination(); - } + GetFrame() + ->GetLocalFrameHostRemote() + .HandleAccessibilityFindInPageTermination(); } void TextFinder::ReportFindInPageResultToAccessibility(int identifier) { @@ -345,12 +349,14 @@ void TextFinder::ReportFindInPageResultToAccessibility(int identifier) { Node* end_node = active_match_->endContainer(); ax_object_cache->HandleTextMarkerDataAdded(start_node, end_node); - if (OwnerFrame().Client()) { - OwnerFrame().Client()->HandleAccessibilityFindInPageResult( - identifier, active_match_index_ + 1, blink::WebNode(start_node), - active_match_->startOffset(), blink::WebNode(end_node), - active_match_->endOffset()); - } + int32_t start_id = ax_object_cache->GetAXID(start_node); + int32_t end_id = ax_object_cache->GetAXID(end_node); + + auto params = mojom::blink::FindInPageResultAXParams::New( + identifier, active_match_index_ + 1, start_id, + active_match_->startOffset(), end_id, active_match_->endOffset()); + GetFrame()->GetLocalFrameHostRemote().HandleAccessibilityFindInPageResult( + std::move(params)); } void TextFinder::StartScopingStringMatches( @@ -450,11 +456,14 @@ void TextFinder::UpdateMatches(int identifier, } void TextFinder::FinishCurrentScopingEffort(int identifier) { + scoping_in_progress_ = false; + if (!OwnerFrame().GetFrame()) + return; + if (!total_match_count_) OwnerFrame().GetFrame()->Selection().Clear(); FlushCurrentScopingEffort(identifier); - scoping_in_progress_ = false; // This frame is done, so show any scrollbar tickmarks we haven't drawn yet. InvalidatePaintForTickmarks(); } @@ -476,7 +485,7 @@ void TextFinder::IncreaseMatchCount(int identifier, int count) { identifier, total_match_count_, !frame_scoping_); } -void TextFinder::ReportFindInPageSelection(const WebRect& selection_rect, +void TextFinder::ReportFindInPageSelection(const gfx::Rect& selection_rect, int active_match_ordinal, int identifier) { // Update the UI with the latest selection rect. @@ -539,17 +548,17 @@ void TextFinder::UpdateFindMatchRects() { find_match_rects_are_valid_ = true; } -WebFloatRect TextFinder::ActiveFindMatchRect() { +gfx::RectF TextFinder::ActiveFindMatchRect() { if (!current_active_match_frame_ || !active_match_) - return WebFloatRect(); + return gfx::RectF(); - return WebFloatRect(FindInPageRectFromRange(EphemeralRange(ActiveMatch()))); + return gfx::RectF(FindInPageRectFromRange(EphemeralRange(ActiveMatch()))); } -Vector<WebFloatRect> TextFinder::FindMatchRects() { +Vector<gfx::RectF> TextFinder::FindMatchRects() { UpdateFindMatchRects(); - Vector<WebFloatRect> match_rects; + Vector<gfx::RectF> match_rects; match_rects.ReserveCapacity(match_rects.size() + find_matches_cache_.size()); for (const FindMatch& match : find_matches_cache_) { DCHECK(!match.rect_.IsEmpty()); @@ -559,9 +568,9 @@ Vector<WebFloatRect> TextFinder::FindMatchRects() { return match_rects; } -int TextFinder::SelectNearestFindMatch(const WebFloatPoint& point, - WebRect* selection_rect) { - int index = NearestFindMatch(point, nullptr); +int TextFinder::SelectNearestFindMatch(const gfx::PointF& point, + gfx::Rect* selection_rect) { + int index = NearestFindMatch(FloatPoint(point), nullptr); if (index != -1) return SelectFindMatch(static_cast<unsigned>(index), selection_rect); @@ -592,7 +601,7 @@ int TextFinder::NearestFindMatch(const FloatPoint& point, return nearest; } -int TextFinder::SelectFindMatch(unsigned index, WebRect* selection_rect) { +int TextFinder::SelectFindMatch(unsigned index, gfx::Rect* selection_rect) { SECURITY_DCHECK(index < find_matches_cache_.size()); Range* range = find_matches_cache_[index].range_; @@ -630,9 +639,10 @@ int TextFinder::SelectFindMatch(unsigned index, WebRect* selection_rect) { active_match_->FirstNode()->GetLayoutObject()) { active_match_->FirstNode()->GetLayoutObject()->ScrollRectToVisible( PhysicalRect(active_match_bounding_box), - WebScrollIntoViewParams(ScrollAlignment::kAlignCenterIfNeeded, - ScrollAlignment::kAlignCenterIfNeeded, - kUserScroll)); + ScrollAlignment::CreateScrollIntoViewParams( + ScrollAlignment::CenterIfNeeded(), + ScrollAlignment::CenterIfNeeded(), + mojom::blink::ScrollType::kUser)); // Absolute coordinates are scroll-variant so the bounding box will change // if the page is scrolled by ScrollRectToVisible above. Recompute the @@ -674,8 +684,6 @@ TextFinder::TextFinder(WebLocalFrameImpl& owner_frame) scoping_in_progress_(false), find_match_rects_are_valid_(false) {} -TextFinder::~TextFinder() = default; - bool TextFinder::SetMarkerActive(Range* range, bool active) { if (!range || range->collapsed()) return false; diff --git a/chromium/third_party/blink/renderer/core/editing/finder/text_finder.h b/chromium/third_party/blink/renderer/core/editing/finder/text_finder.h index c025a326699..ebffeb7cfaf 100644 --- a/chromium/third_party/blink/renderer/core/editing/finder/text_finder.h +++ b/chromium/third_party/blink/renderer/core/editing/finder/text_finder.h @@ -33,7 +33,6 @@ #include "base/macros.h" #include "third_party/blink/public/mojom/frame/find_in_page.mojom-blink-forward.h" -#include "third_party/blink/public/platform/web_float_point.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/platform/geometry/float_rect.h" #include "third_party/blink/renderer/platform/heap/handle.h" @@ -47,9 +46,6 @@ class LocalFrame; class Range; class WebLocalFrameImpl; class WebString; -struct WebFloatPoint; -struct WebFloatRect; -struct WebRect; class CORE_EXPORT TextFinder final : public GarbageCollected<TextFinder> { public: @@ -63,12 +59,12 @@ class CORE_EXPORT TextFinder final : public GarbageCollected<TextFinder> { void StopFindingAndClearSelection(); void IncreaseMatchCount(int identifier, int count); int FindMatchMarkersVersion() const { return find_match_markers_version_; } - WebFloatRect ActiveFindMatchRect(); - Vector<WebFloatRect> FindMatchRects(); - int SelectNearestFindMatch(const WebFloatPoint&, WebRect* selection_rect); + gfx::RectF ActiveFindMatchRect(); + Vector<gfx::RectF> FindMatchRects(); + int SelectNearestFindMatch(const gfx::PointF&, gfx::Rect* selection_rect); // Starts brand new scoping request: resets the scoping state and - // asyncronously calls scopeStringMatches(). + // asynchronously calls scopeStringMatches(). void StartScopingStringMatches(int identifier, const WebString& search_text, const mojom::blink::FindOptions& options); @@ -119,7 +115,6 @@ class CORE_EXPORT TextFinder final : public GarbageCollected<TextFinder> { bool finished_whole_request); explicit TextFinder(WebLocalFrameImpl& owner_frame); - ~TextFinder(); class FindMatch { DISALLOW_NEW(); @@ -143,7 +138,7 @@ class CORE_EXPORT TextFinder final : public GarbageCollected<TextFinder> { private: // Notifies the delegate about a new selection rect. - void ReportFindInPageSelection(const WebRect& selection_rect, + void ReportFindInPageSelection(const gfx::Rect& selection_rect, int active_match_ordinal, int identifier); @@ -158,7 +153,7 @@ class CORE_EXPORT TextFinder final : public GarbageCollected<TextFinder> { // match index returned by nearestFindMatch. Returns the ordinal of the new // selected match or -1 in case of error. Also provides the bounding box of // the marker in window coordinates if selectionRect is not null. - int SelectFindMatch(unsigned index, WebRect* selection_rect); + int SelectFindMatch(unsigned index, gfx::Rect* selection_rect); // Compute and cache the rects for FindMatches if required. // Rects are automatically invalidated in case of content size changes. diff --git a/chromium/third_party/blink/renderer/core/editing/finder/text_finder_test.cc b/chromium/third_party/blink/renderer/core/editing/finder/text_finder_test.cc index f45477f6d9b..2e0035d3f9c 100644 --- a/chromium/third_party/blink/renderer/core/editing/finder/text_finder_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/finder/text_finder_test.cc @@ -37,7 +37,7 @@ class TextFinderTest : public testing::Test { WebLocalFrameImpl& frame_impl = *web_view_helper_.LocalMainFrame(); frame_impl.ViewImpl()->MainFrameWidget()->Resize(WebSize(640, 480)); frame_impl.ViewImpl()->MainFrameWidget()->UpdateAllLifecyclePhases( - WebWidget::LifecycleUpdateReason::kTest); + DocumentUpdateReason::kTest); document_ = static_cast<Document*>(frame_impl.GetDocument()); text_finder_ = &frame_impl.EnsureTextFinder(); } @@ -45,10 +45,10 @@ class TextFinderTest : public testing::Test { Document& GetDocument() const; TextFinder& GetTextFinder() const; - static WebFloatRect FindInPageRect(Node* start_container, - int start_offset, - Node* end_container, - int end_offset); + static gfx::RectF FindInPageRect(Node* start_container, + int start_offset, + Node* end_container, + int end_offset); private: frame_test_helpers::WebViewHelper web_view_helper_; @@ -64,19 +64,19 @@ TextFinder& TextFinderTest::GetTextFinder() const { return *text_finder_; } -WebFloatRect TextFinderTest::FindInPageRect(Node* start_container, - int start_offset, - Node* end_container, - int end_offset) { +gfx::RectF TextFinderTest::FindInPageRect(Node* start_container, + int start_offset, + Node* end_container, + int end_offset) { const Position start_position(start_container, start_offset); const Position end_position(end_container, end_offset); const EphemeralRange range(start_position, end_position); - return WebFloatRect(FindInPageRectFromRange(range)); + return gfx::RectF(FindInPageRectFromRange(range)); } TEST_F(TextFinderTest, FindTextSimple) { - GetDocument().body()->SetInnerHTMLFromString("XXXXFindMeYYYYfindmeZZZZ"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().body()->setInnerHTML("XXXXFindMeYYYYfindmeZZZZ"); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Node* text_node = GetDocument().body()->firstChild(); int identifier = 0; @@ -150,8 +150,8 @@ TEST_F(TextFinderTest, FindTextSimple) { } TEST_F(TextFinderTest, FindTextAutosizing) { - GetDocument().body()->SetInnerHTMLFromString("XXXXFindMeYYYYfindmeZZZZ"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().body()->setInnerHTML("XXXXFindMeYYYYfindmeZZZZ"); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); int identifier = 0; WebString search_text(String("FindMe")); @@ -170,7 +170,7 @@ TEST_F(TextFinderTest, FindTextAutosizing) { GetDocument().GetSettings()->SetTextAutosizingWindowSizeOverride( IntSize(20, 20)); GetDocument().GetTextAutosizer()->UpdatePageInfo(); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); // In case of autosizing, scale _should_ change ASSERT_TRUE(GetTextFinder().Find(identifier, search_text, *find_options, @@ -182,7 +182,7 @@ TEST_F(TextFinderTest, FindTextAutosizing) { visual_viewport.SetScale(20); GetDocument().GetSettings()->SetTextAutosizingEnabled(false); GetDocument().GetTextAutosizer()->UpdatePageInfo(); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); ASSERT_TRUE(GetTextFinder().Find(identifier, search_text, *find_options, wrap_within_frame)); @@ -191,8 +191,8 @@ TEST_F(TextFinderTest, FindTextAutosizing) { } TEST_F(TextFinderTest, FindTextNotFound) { - GetDocument().body()->SetInnerHTMLFromString("XXXXFindMeYYYYfindmeZZZZ"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().body()->setInnerHTML("XXXXFindMeYYYYfindmeZZZZ"); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); int identifier = 0; WebString search_text(String("Boo")); @@ -206,15 +206,15 @@ TEST_F(TextFinderTest, FindTextNotFound) { } TEST_F(TextFinderTest, FindTextInShadowDOM) { - GetDocument().body()->SetInnerHTMLFromString("<b>FOO</b><i>foo</i>"); + GetDocument().body()->setInnerHTML("<b>FOO</b><i>foo</i>"); ShadowRoot& shadow_root = GetDocument().body()->CreateV0ShadowRootForTesting(); - shadow_root.SetInnerHTMLFromString( + shadow_root.setInnerHTML( "<content select=\"i\"></content><u>Foo</u><content></content>"); Node* text_in_b_element = GetDocument().body()->firstChild()->firstChild(); Node* text_in_i_element = GetDocument().body()->lastChild()->firstChild(); Node* text_in_u_element = shadow_root.childNodes()->item(1)->firstChild(); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); int identifier = 0; WebString search_text(String("foo")); @@ -308,8 +308,8 @@ TEST_F(TextFinderTest, FindTextInShadowDOM) { } TEST_F(TextFinderTest, ScopeTextMatchesSimple) { - GetDocument().body()->SetInnerHTMLFromString("XXXXFindMeYYYYfindmeZZZZ"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().body()->setInnerHTML("XXXXFindMeYYYYfindmeZZZZ"); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Node* text_node = GetDocument().body()->firstChild(); @@ -324,7 +324,7 @@ TEST_F(TextFinderTest, ScopeTextMatchesSimple) { *find_options); EXPECT_EQ(2, GetTextFinder().TotalMatchCount()); - WebVector<WebFloatRect> match_rects = GetTextFinder().FindMatchRects(); + WebVector<gfx::RectF> match_rects = GetTextFinder().FindMatchRects(); ASSERT_EQ(2u, match_rects.size()); EXPECT_EQ(FindInPageRect(text_node, 4, text_node, 10), match_rects[0]); EXPECT_EQ(FindInPageRect(text_node, 14, text_node, 20), match_rects[1]); @@ -332,7 +332,7 @@ TEST_F(TextFinderTest, ScopeTextMatchesSimple) { // Modify the document size and ensure the cached match rects are recomputed // to reflect the updated layout. GetDocument().body()->setAttribute(html_names::kStyleAttr, "margin: 2000px"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); match_rects = GetTextFinder().FindMatchRects(); ASSERT_EQ(2u, match_rects.size()); @@ -341,8 +341,8 @@ TEST_F(TextFinderTest, ScopeTextMatchesSimple) { } TEST_F(TextFinderTest, ScopeTextMatchesRepeated) { - GetDocument().body()->SetInnerHTMLFromString("XXXXFindMeYYYYfindmeZZZZ"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().body()->setInnerHTML("XXXXFindMeYYYYfindmeZZZZ"); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Node* text_node = GetDocument().body()->firstChild(); @@ -361,22 +361,22 @@ TEST_F(TextFinderTest, ScopeTextMatchesRepeated) { // Only searchText2 should be highlighted. EXPECT_EQ(2, GetTextFinder().TotalMatchCount()); - WebVector<WebFloatRect> match_rects = GetTextFinder().FindMatchRects(); + WebVector<gfx::RectF> match_rects = GetTextFinder().FindMatchRects(); ASSERT_EQ(2u, match_rects.size()); EXPECT_EQ(FindInPageRect(text_node, 4, text_node, 10), match_rects[0]); EXPECT_EQ(FindInPageRect(text_node, 14, text_node, 20), match_rects[1]); } TEST_F(TextFinderTest, ScopeTextMatchesWithShadowDOM) { - GetDocument().body()->SetInnerHTMLFromString("<b>FOO</b><i>foo</i>"); + GetDocument().body()->setInnerHTML("<b>FOO</b><i>foo</i>"); ShadowRoot& shadow_root = GetDocument().body()->CreateV0ShadowRootForTesting(); - shadow_root.SetInnerHTMLFromString( + shadow_root.setInnerHTML( "<content select=\"i\"></content><u>Foo</u><content></content>"); Node* text_in_b_element = GetDocument().body()->firstChild()->firstChild(); Node* text_in_i_element = GetDocument().body()->lastChild()->firstChild(); Node* text_in_u_element = shadow_root.childNodes()->item(1)->firstChild(); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); int identifier = 0; WebString search_text(String("fOO")); @@ -392,7 +392,7 @@ TEST_F(TextFinderTest, ScopeTextMatchesWithShadowDOM) { // so in this case the matches will be returned in the order of // <i> -> <u> -> <b>. EXPECT_EQ(3, GetTextFinder().TotalMatchCount()); - WebVector<WebFloatRect> match_rects = GetTextFinder().FindMatchRects(); + WebVector<gfx::RectF> match_rects = GetTextFinder().FindMatchRects(); ASSERT_EQ(3u, match_rects.size()); EXPECT_EQ(FindInPageRect(text_in_i_element, 0, text_in_i_element, 3), match_rects[0]); @@ -403,8 +403,8 @@ TEST_F(TextFinderTest, ScopeTextMatchesWithShadowDOM) { } TEST_F(TextFinderTest, ScopeRepeatPatternTextMatches) { - GetDocument().body()->SetInnerHTMLFromString("ab ab ab ab ab"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().body()->setInnerHTML("ab ab ab ab ab"); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Node* text_node = GetDocument().body()->firstChild(); @@ -419,15 +419,15 @@ TEST_F(TextFinderTest, ScopeRepeatPatternTextMatches) { *find_options); EXPECT_EQ(2, GetTextFinder().TotalMatchCount()); - WebVector<WebFloatRect> match_rects = GetTextFinder().FindMatchRects(); + WebVector<gfx::RectF> match_rects = GetTextFinder().FindMatchRects(); ASSERT_EQ(2u, match_rects.size()); EXPECT_EQ(FindInPageRect(text_node, 0, text_node, 5), match_rects[0]); EXPECT_EQ(FindInPageRect(text_node, 6, text_node, 11), match_rects[1]); } TEST_F(TextFinderTest, OverlappingMatches) { - GetDocument().body()->SetInnerHTMLFromString("aababaa"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().body()->setInnerHTML("aababaa"); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Node* text_node = GetDocument().body()->firstChild(); @@ -443,14 +443,14 @@ TEST_F(TextFinderTest, OverlappingMatches) { // We shouldn't find overlapped matches. EXPECT_EQ(1, GetTextFinder().TotalMatchCount()); - WebVector<WebFloatRect> match_rects = GetTextFinder().FindMatchRects(); + WebVector<gfx::RectF> match_rects = GetTextFinder().FindMatchRects(); ASSERT_EQ(1u, match_rects.size()); EXPECT_EQ(FindInPageRect(text_node, 1, text_node, 4), match_rects[0]); } TEST_F(TextFinderTest, SequentialMatches) { - GetDocument().body()->SetInnerHTMLFromString("ababab"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().body()->setInnerHTML("ababab"); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Node* text_node = GetDocument().body()->firstChild(); @@ -465,7 +465,7 @@ TEST_F(TextFinderTest, SequentialMatches) { *find_options); EXPECT_EQ(3, GetTextFinder().TotalMatchCount()); - WebVector<WebFloatRect> match_rects = GetTextFinder().FindMatchRects(); + WebVector<gfx::RectF> match_rects = GetTextFinder().FindMatchRects(); ASSERT_EQ(3u, match_rects.size()); EXPECT_EQ(FindInPageRect(text_node, 0, text_node, 2), match_rects[0]); EXPECT_EQ(FindInPageRect(text_node, 2, text_node, 4), match_rects[1]); @@ -473,8 +473,8 @@ TEST_F(TextFinderTest, SequentialMatches) { } TEST_F(TextFinderTest, FindTextJavaScriptUpdatesDOM) { - GetDocument().body()->SetInnerHTMLFromString("<b>XXXXFindMeYYYY</b><i></i>"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().body()->setInnerHTML("<b>XXXXFindMeYYYY</b><i></i>"); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); int identifier = 0; WebString search_text(String("FindMe")); @@ -499,8 +499,8 @@ TEST_F(TextFinderTest, FindTextJavaScriptUpdatesDOM) { // Add new text to DOM and try FindNext. auto* i_element = To<Element>(GetDocument().body()->lastChild()); ASSERT_TRUE(i_element); - i_element->SetInnerHTMLFromString("ZZFindMe"); - GetDocument().UpdateStyleAndLayout(); + i_element->setInnerHTML("ZZFindMe"); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); ASSERT_TRUE(GetTextFinder().Find(identifier, search_text, *find_options, wrap_within_frame, &active_now)); @@ -519,7 +519,7 @@ TEST_F(TextFinderTest, FindTextJavaScriptUpdatesDOM) { EXPECT_EQ(2, GetTextFinder().TotalMatchCount()); - WebVector<WebFloatRect> match_rects = GetTextFinder().FindMatchRects(); + WebVector<gfx::RectF> match_rects = GetTextFinder().FindMatchRects(); ASSERT_EQ(2u, match_rects.size()); Node* text_in_b_element = GetDocument().body()->firstChild()->firstChild(); Node* text_in_i_element = GetDocument().body()->lastChild()->firstChild(); @@ -530,8 +530,8 @@ TEST_F(TextFinderTest, FindTextJavaScriptUpdatesDOM) { } TEST_F(TextFinderTest, FindTextJavaScriptUpdatesDOMAfterNoMatches) { - GetDocument().body()->SetInnerHTMLFromString("<b>XXXXYYYY</b><i></i>"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().body()->setInnerHTML("<b>XXXXYYYY</b><i></i>"); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); int identifier = 0; WebString search_text(String("FindMe")); @@ -553,8 +553,8 @@ TEST_F(TextFinderTest, FindTextJavaScriptUpdatesDOMAfterNoMatches) { // Add new text to DOM and try FindNext. auto* i_element = To<Element>(GetDocument().body()->lastChild()); ASSERT_TRUE(i_element); - i_element->SetInnerHTMLFromString("ZZFindMe"); - GetDocument().UpdateStyleAndLayout(); + i_element->setInnerHTML("ZZFindMe"); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); ASSERT_TRUE(GetTextFinder().Find(identifier, search_text, *find_options, wrap_within_frame, &active_now)); @@ -573,7 +573,7 @@ TEST_F(TextFinderTest, FindTextJavaScriptUpdatesDOMAfterNoMatches) { EXPECT_EQ(1, GetTextFinder().TotalMatchCount()); - WebVector<WebFloatRect> match_rects = GetTextFinder().FindMatchRects(); + WebVector<gfx::RectF> match_rects = GetTextFinder().FindMatchRects(); ASSERT_EQ(1u, match_rects.size()); Node* text_in_i_element = GetDocument().body()->lastChild()->firstChild(); EXPECT_EQ(FindInPageRect(text_in_i_element, 2, text_in_i_element, 8), @@ -593,8 +593,8 @@ TEST_F(TextFinderTest, ScopeWithTimeouts) { } } - GetDocument().body()->SetInnerHTMLFromString(text.ToString()); - GetDocument().UpdateStyleAndLayout(); + GetDocument().body()->setInnerHTML(text.ToString()); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); int identifier = 0; auto find_options = diff --git a/chromium/third_party/blink/renderer/core/editing/frame_caret_test.cc b/chromium/third_party/blink/renderer/core/editing/frame_caret_test.cc index 1081d4ccd5d..7f72172730b 100644 --- a/chromium/third_party/blink/renderer/core/editing/frame_caret_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/frame_caret_test.cc @@ -47,7 +47,7 @@ TEST_F(FrameCaretTest, BlinkAfterTyping) { base::TimeDelta::FromSecondsD(kInterval)); GetDocument().GetPage()->GetFocusController().SetActive(true); GetDocument().GetPage()->GetFocusController().SetFocused(true); - GetDocument().body()->SetInnerHTMLFromString("<textarea>"); + GetDocument().body()->setInnerHTML("<textarea>"); auto* editor = To<Element>(GetDocument().body()->firstChild()); editor->focus(); UpdateAllLifecyclePhasesForTest(); @@ -81,7 +81,7 @@ TEST_F(FrameCaretTest, ShouldNotBlinkWhenSelectionLooseFocus) { FrameCaret& caret = Selection().FrameCaretForTesting(); GetDocument().GetPage()->GetFocusController().SetActive(true); GetDocument().GetPage()->GetFocusController().SetFocused(true); - GetDocument().body()->SetInnerHTMLFromString( + GetDocument().body()->setInnerHTML( "<div id='outer' tabindex='-1'>" "<div id='input' contenteditable>foo</div>" "</div>"); diff --git a/chromium/third_party/blink/renderer/core/editing/frame_selection.cc b/chromium/third_party/blink/renderer/core/editing/frame_selection.cc index 9a5917e9008..b068e2fc56c 100644 --- a/chromium/third_party/blink/renderer/core/editing/frame_selection.cc +++ b/chromium/third_party/blink/renderer/core/editing/frame_selection.cc @@ -26,7 +26,6 @@ #include "third_party/blink/renderer/core/editing/frame_selection.h" #include <stdio.h> -#include "third_party/blink/public/platform/web_scroll_into_view_params.h" #include "third_party/blink/renderer/core/accessibility/ax_object_cache.h" #include "third_party/blink/renderer/core/css/css_property_value_set.h" #include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h" @@ -113,9 +112,13 @@ const DisplayItemClient& FrameSelection::CaretDisplayItemClientForTesting() return frame_caret_->GetDisplayItemClient(); } +bool FrameSelection::IsAvailable() const { + return SynchronousMutationObserver::GetDocument(); +} + Document& FrameSelection::GetDocument() const { - DCHECK(LifecycleContext()); - return *LifecycleContext(); + DCHECK(IsAvailable()); + return *SynchronousMutationObserver::GetDocument(); } VisibleSelection FrameSelection::ComputeVisibleSelectionInDOMTree() const { @@ -150,7 +153,7 @@ VisibleSelection FrameSelection::ComputeVisibleSelectionInDOMTreeDeprecated() const { // TODO(editing-dev): Hoist UpdateStyleAndLayout // to caller. See http://crbug.com/590369 for more details. - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kSelection); return ComputeVisibleSelectionInDOMTree(); } @@ -238,8 +241,19 @@ bool FrameSelection::SetSelectionDeprecated( if (is_changed) { AssertUserSelection(new_selection, options); selection_editor_->SetSelectionAndEndTyping(new_selection); - DisplayLockUtilities::ActivateSelectionRangeIfNeeded( - ToEphemeralRangeInFlatTree(new_selection.ComputeRange())); + + // The old selection might not be valid, and thus not iteratable. If that's + // the case, notify that all selection was removed and use an empty range as + // the old selection. + EphemeralRangeInFlatTree old_range; + if (old_selection_in_dom_tree.IsValidFor(GetDocument())) { + old_range = + ToEphemeralRangeInFlatTree(old_selection_in_dom_tree.ComputeRange()); + } else { + DisplayLockUtilities::SelectionRemovedFromDocument(GetDocument()); + } + DisplayLockUtilities::SelectionChanged( + old_range, ToEphemeralRangeInFlatTree(new_selection.ComputeRange())); } is_directional_ = options.IsDirectional(); should_shrink_next_tap_ = options.ShouldShrinkNextTap(); @@ -288,18 +302,19 @@ void FrameSelection::DidSetSelectionDeprecated( NotifyTextControlOfSelectionChange(set_selection_by); if (set_selection_by == SetSelectionBy::kUser) { const CursorAlignOnScroll align = options.GetCursorAlignOnScroll(); - ScrollAlignment alignment; + mojom::blink::ScrollAlignment alignment; if (frame_->GetEditor() .Behavior() - .ShouldCenterAlignWhenSelectionIsRevealed()) + .ShouldCenterAlignWhenSelectionIsRevealed()) { alignment = (align == CursorAlignOnScroll::kAlways) - ? ScrollAlignment::kAlignCenterAlways - : ScrollAlignment::kAlignCenterIfNeeded; - else + ? ScrollAlignment::CenterAlways() + : ScrollAlignment::CenterIfNeeded(); + } else { alignment = (align == CursorAlignOnScroll::kAlways) - ? ScrollAlignment::kAlignTopAlways - : ScrollAlignment::kAlignToEdgeIfNeeded; + ? ScrollAlignment::TopAlways() + : ScrollAlignment::ToEdgeIfNeeded(); + } RevealSelection(alignment, kRevealExtent); } @@ -422,7 +437,7 @@ void FrameSelection::Clear() { bool FrameSelection::SelectionHasFocus() const { // TODO(editing-dev): Hoist UpdateStyleAndLayout // to caller. See http://crbug.com/590369 for more details. - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kSelection); if (ComputeVisibleSelectionInFlatTree().IsNone()) return false; const Node* current = @@ -486,13 +501,13 @@ bool FrameSelection::IsHidden() const { void FrameSelection::DidAttachDocument(Document* document) { DCHECK(document); selection_editor_->DidAttachDocument(document); - SetContext(document); + SetDocument(document); } -void FrameSelection::ContextDestroyed(Document* document) { +void FrameSelection::ContextDestroyed() { granularity_ = TextGranularity::kCharacter; - layout_selection_->OnDocumentShutdown(); + layout_selection_->ContextDestroyed(); frame_->GetEditor().ClearTypingStyle(); } @@ -537,7 +552,7 @@ bool FrameSelection::ComputeAbsoluteBounds(IntRect& anchor, // TODO(editing-dev): The use of UpdateStyleAndLayout // needs to be audited. See http://crbug.com/590369 for more details. - frame_->GetDocument()->UpdateStyleAndLayout(); + frame_->GetDocument()->UpdateStyleAndLayout(DocumentUpdateReason::kSelection); if (ComputeVisibleSelectionInDOMTree().IsNone()) { // plugins/mouse-capture-inside-shadow.html reaches here. return false; @@ -618,7 +633,7 @@ void FrameSelection::SelectFrameElementInParentIfFullySelected() { // TODO(editing-dev): The use of UpdateStyleAndLayout // needs to be audited. See http://crbug.com/590369 for more details. - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kSelection); if (!IsStartOfDocument(ComputeVisibleSelectionInDOMTree().VisibleStart())) return; @@ -642,7 +657,8 @@ void FrameSelection::SelectFrameElementInParentIfFullySelected() { // TODO(editing-dev): The use of UpdateStyleAndLayout // needs to be audited. See http://crbug.com/590369 for more details. - owner_element_parent->GetDocument().UpdateStyleAndLayout(); + owner_element_parent->GetDocument().UpdateStyleAndLayout( + DocumentUpdateReason::kSelection); // This method's purpose is it to make it easier to select iframes (in order // to delete them). Don't do anything if the iframe isn't deletable. @@ -969,7 +985,7 @@ PhysicalRect FrameSelection::AbsoluteUnclippedBounds() const { if (!view || !layout_view) return PhysicalRect(); - view->UpdateLifecycleToLayoutClean(); + view->UpdateLifecycleToLayoutClean(DocumentUpdateReason::kSelection); return PhysicalRect(layout_selection_->AbsoluteSelectionBounds()); } @@ -988,14 +1004,15 @@ IntRect FrameSelection::ComputeRectToScroll( } // TODO(editing-dev): This should be done in FlatTree world. -void FrameSelection::RevealSelection(const ScrollAlignment& alignment, - RevealExtentOption reveal_extent_option) { +void FrameSelection::RevealSelection( + const mojom::blink::ScrollAlignment& alignment, + RevealExtentOption reveal_extent_option) { DCHECK(IsAvailable()); // TODO(editing-dev): The use of UpdateStyleAndLayout // needs to be audited. See http://crbug.com/590369 for more details. // Calculation of absolute caret bounds requires clean layout. - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kSelection); const VisibleSelection& selection = ComputeVisibleSelectionInDOMTree(); if (selection.IsNone()) @@ -1010,14 +1027,16 @@ void FrameSelection::RevealSelection(const ScrollAlignment& alignment, DCHECK(start.AnchorNode()->GetLayoutObject()); // This function is needed to make sure that ComputeRectToScroll below has the // sticky offset info available before the computation. - GetDocument().EnsurePaintLocationDataValidForNode(start.AnchorNode()); + GetDocument().EnsurePaintLocationDataValidForNode( + start.AnchorNode(), DocumentUpdateReason::kSelection); PhysicalRect selection_rect(ComputeRectToScroll(reveal_extent_option)); if (selection_rect == PhysicalRect() || !start.AnchorNode()->GetLayoutObject()->EnclosingBox()) return; start.AnchorNode()->GetLayoutObject()->ScrollRectToVisible( - selection_rect, WebScrollIntoViewParams(alignment, alignment)); + selection_rect, + ScrollAlignment::CreateScrollIntoViewParams(alignment, alignment)); UpdateAppearance(); } @@ -1244,6 +1263,10 @@ bool FrameSelection::IsDirectional() const { return is_directional_; } +void FrameSelection::MarkCacheDirty() { + selection_editor_->MarkCacheDirty(); +} + } // namespace blink #if DCHECK_IS_ON() diff --git a/chromium/third_party/blink/renderer/core/editing/frame_selection.h b/chromium/third_party/blink/renderer/core/editing/frame_selection.h index af6de9f2d22..263f259996a 100644 --- a/chromium/third_party/blink/renderer/core/editing/frame_selection.h +++ b/chromium/third_party/blink/renderer/core/editing/frame_selection.h @@ -87,6 +87,9 @@ struct LayoutSelectionStatus { : start(passed_start), end(passed_end), line_break(passed_line_break) { DCHECK_LE(start, end); } + + bool HasValidRange() const { return start < end; } + bool operator==(const LayoutSelectionStatus& other) const { return start == other.start && end == other.end && line_break == other.line_break; @@ -129,7 +132,7 @@ class CORE_EXPORT FrameSelection final explicit FrameSelection(LocalFrame&); ~FrameSelection(); - bool IsAvailable() const { return LifecycleContext(); } + bool IsAvailable() const; // You should not call |document()| when |!isAvailable()|. Document& GetDocument() const; LocalFrame* GetFrame() const { return frame_; } @@ -260,7 +263,7 @@ class CORE_EXPORT FrameSelection final // TODO(tkent): This function has a bug that scrolling doesn't work well in // a case of RangeSelection. crbug.com/443061 void RevealSelection( - const ScrollAlignment& = ScrollAlignment::kAlignCenterIfNeeded, + const mojom::blink::ScrollAlignment& = ScrollAlignment::CenterIfNeeded(), RevealExtentOption = kDoNotRevealExtent); void SetSelectionFromNone(); @@ -272,6 +275,10 @@ class CORE_EXPORT FrameSelection final Range* DocumentCachedRange() const; void ClearDocumentCachedRange(); + // Invalidates the cached visual selection information, like + // |VisibleSelection| and selection bounds. + void MarkCacheDirty(); + FrameCaret& FrameCaretForTesting() const { return *frame_caret_; } LayoutTextSelectionStatus ComputeLayoutSelectionStatus( @@ -304,7 +311,7 @@ class CORE_EXPORT FrameSelection final void MoveRangeSelectionInternal(const SelectionInDOMTree&, TextGranularity); // Implementation of |SynchronousMutationObserver| member functions. - void ContextDestroyed(Document*) final; + void ContextDestroyed() final; void NodeChildrenWillBeRemoved(ContainerNode&) final; void NodeWillBeRemoved(Node&) final; diff --git a/chromium/third_party/blink/renderer/core/editing/frame_selection_test.cc b/chromium/third_party/blink/renderer/core/editing/frame_selection_test.cc index 3ba2c413a9c..f1409f46337 100644 --- a/chromium/third_party/blink/renderer/core/editing/frame_selection_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/frame_selection_test.cc @@ -147,7 +147,7 @@ TEST_F(FrameSelectionTest, PaintCaretShouldNotLayout) { { GraphicsContext context(*paint_controller); paint_controller->UpdateCurrentPaintChunkProperties( - root_paint_chunk_id_, PropertyTreeState::Root()); + &root_paint_chunk_id_, PropertyTreeState::Root()); Selection().PaintCaret(context, PhysicalOffset()); } paint_controller->CommitNewDisplayItems(); @@ -272,7 +272,7 @@ TEST_F(FrameSelectionTest, MoveRangeSelectionNoLiveness) { EXPECT_EQ("xyz", Selection().SelectedText()); sample->insertBefore(Text::Create(GetDocument(), "abc"), sample->firstChild()); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); const VisibleSelection& selection = Selection().ComputeVisibleSelectionInDOMTree(); // Inserting "abc" before "xyz" should not affect to selection. @@ -307,7 +307,7 @@ TEST_F(FrameSelectionTest, SelectAllWithInputElement) { TEST_F(FrameSelectionTest, SelectAllWithUnselectableRoot) { Element* select = GetDocument().CreateRawElement(html_names::kSelectTag); GetDocument().ReplaceChild(select, GetDocument().documentElement()); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Selection().SelectAll(); EXPECT_TRUE(Selection().ComputeVisibleSelectionInDOMTree().IsNone()) << "Nothing should be selected if the " @@ -1063,8 +1063,8 @@ TEST_F(FrameSelectionTest, SelectionBounds) { // bottom is visible. The unclipped selection bounds should not be clipped. const int scroll_offset = 500; LocalFrameView* frame_view = GetDocument().View(); - frame_view->LayoutViewport()->SetScrollOffset(ScrollOffset(0, scroll_offset), - kProgrammaticScroll); + frame_view->LayoutViewport()->SetScrollOffset( + ScrollOffset(0, scroll_offset), mojom::blink::ScrollType::kProgrammatic); EXPECT_EQ(PhysicalRect(0, node_margin_top, node_width, node_height), frame_view->FrameToDocument(Selection().AbsoluteUnclippedBounds())); diff --git a/chromium/third_party/blink/renderer/core/editing/granularity_strategy_test.cc b/chromium/third_party/blink/renderer/core/editing/granularity_strategy_test.cc index 61cd633411e..659e29b7886 100644 --- a/chromium/third_party/blink/renderer/core/editing/granularity_strategy_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/granularity_strategy_test.cc @@ -91,8 +91,7 @@ Text* GranularityStrategyTest::AppendTextNode(const String& data) { } void GranularityStrategyTest::SetInnerHTML(const char* html_content) { - GetDocument().documentElement()->SetInnerHTMLFromString( - String::FromUTF8(html_content)); + GetDocument().documentElement()->setInnerHTML(String::FromUTF8(html_content)); UpdateAllLifecyclePhasesForTest(); } @@ -477,7 +476,7 @@ TEST_F(GranularityStrategyTest, Character) { GetDummyPageHolder().GetFrame().GetSettings()->SetDefaultFontSize(12); // "Foo Bar Baz," Text* text = AppendTextNode("Foo Bar Baz,"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); // "Foo B^a|>r Baz," (^ means base, | means extent, , < means start, and > // means end). @@ -638,7 +637,7 @@ TEST_F(GranularityStrategyTest, DirectionSwitchSideWordGranularityThenShrink) { String str = "ab cd efghijkl mnopqr iiin, abc"; Text* text = GetDocument().createTextNode(str); GetDocument().body()->AppendChild(text); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); GetDummyPageHolder().GetFrame().GetSettings()->SetSelectionStrategy( SelectionStrategy::kDirection); @@ -677,7 +676,7 @@ TEST_F(GranularityStrategyTest, DirectionSwitchStartOnBoundary) { String str = "ab cd efghijkl mnopqr iiin, abc"; Text* text = GetDocument().createTextNode(str); GetDocument().body()->AppendChild(text); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); GetDummyPageHolder().GetFrame().GetSettings()->SetSelectionStrategy( SelectionStrategy::kDirection); @@ -699,15 +698,15 @@ TEST_F(GranularityStrategyTest, DirectionSwitchStartOnBoundary) { TEST_F(GranularityStrategyTest, UpdateExtentWithNullPositionForCharacter) { GetDummyPageHolder().GetFrame().GetSettings()->SetSelectionStrategy( SelectionStrategy::kCharacter); - GetDocument().body()->SetInnerHTMLFromString( + GetDocument().body()->setInnerHTML( "<div id=host></div><div id=sample>ab</div>"); // Simulate VIDEO element which has a RANGE as slider of video time. Element* const host = GetDocument().getElementById("host"); ShadowRoot& shadow_root = host->AttachShadowRootInternal(ShadowRootType::kOpen); - shadow_root.SetInnerHTMLFromString("<input type=range>"); + shadow_root.setInnerHTML("<input type=range>"); Element* const sample = GetDocument().getElementById("sample"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); const SelectionInDOMTree& selection_in_dom_tree = SelectionInDOMTree::Builder() .Collapse(Position(sample->firstChild(), 2)) @@ -737,15 +736,15 @@ TEST_F(GranularityStrategyTest, UpdateExtentWithNullPositionForCharacter) { // For http://crbug.com/704529 TEST_F(GranularityStrategyTest, UpdateExtentWithNullPositionForDirectional) { - GetDocument().body()->SetInnerHTMLFromString( + GetDocument().body()->setInnerHTML( "<div id=host></div><div id=sample>ab</div>"); // Simulate VIDEO element which has a RANGE as slider of video time. Element* const host = GetDocument().getElementById("host"); ShadowRoot& shadow_root = host->AttachShadowRootInternal(ShadowRootType::kOpen); - shadow_root.SetInnerHTMLFromString("<input type=range>"); + shadow_root.setInnerHTML("<input type=range>"); Element* const sample = GetDocument().getElementById("sample"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); const SelectionInDOMTree& selection_in_dom_tree = SelectionInDOMTree::Builder() .Collapse(Position(sample->firstChild(), 2)) diff --git a/chromium/third_party/blink/renderer/core/editing/hit_testing_bidi_test.cc b/chromium/third_party/blink/renderer/core/editing/hit_testing_bidi_test.cc index 73e3e9ad888..8db2725fe17 100644 --- a/chromium/third_party/blink/renderer/core/editing/hit_testing_bidi_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/hit_testing_bidi_test.cc @@ -23,7 +23,9 @@ class ParameterizedHitTestingBidiTest ParameterizedHitTestingBidiTest() : ScopedLayoutNGForTest(GetParam()) {} protected: - bool LayoutNGEnabled() const { return GetParam(); } + bool LayoutNGEnabled() const { + return RuntimeEnabledFeatures::LayoutNGEnabled(); + } }; INSTANTIATE_TEST_SUITE_P(All, ParameterizedHitTestingBidiTest, testing::Bool()); diff --git a/chromium/third_party/blink/renderer/core/editing/ime/edit_context.cc b/chromium/third_party/blink/renderer/core/editing/ime/edit_context.cc index 6f19a2a3093..598f585111a 100644 --- a/chromium/third_party/blink/renderer/core/editing/ime/edit_context.cc +++ b/chromium/third_party/blink/renderer/core/editing/ime/edit_context.cc @@ -8,9 +8,9 @@ #include "third_party/blink/public/platform/web_vector.h" #include "third_party/blink/public/web/web_ime_text_span.h" #include "third_party/blink/public/web/web_range.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_edit_context_init.h" #include "third_party/blink/renderer/core/css/css_color_value.h" #include "third_party/blink/renderer/core/dom/document.h" -#include "third_party/blink/renderer/core/editing/ime/edit_context_init.h" #include "third_party/blink/renderer/core/editing/ime/input_method_controller.h" #include "third_party/blink/renderer/core/editing/ime/text_format_update_event.h" #include "third_party/blink/renderer/core/editing/ime/text_update_event.h" @@ -24,7 +24,7 @@ namespace blink { EditContext::EditContext(ScriptState* script_state, const EditContextInit* dict) - : ContextLifecycleObserver(ExecutionContext::From(script_state)) { + : ExecutionContextClient(ExecutionContext::From(script_state)) { DCHECK(IsMainThread()); if (dict->hasText()) @@ -58,7 +58,7 @@ const AtomicString& EditContext::InterfaceName() const { } ExecutionContext* EditContext::GetExecutionContext() const { - return ContextLifecycleObserver::GetExecutionContext(); + return ExecutionContextClient::GetExecutionContext(); } bool EditContext::HasPendingActivity() const { @@ -66,22 +66,32 @@ bool EditContext::HasPendingActivity() const { } InputMethodController& EditContext::GetInputMethodController() const { - return ContextLifecycleObserver::GetFrame()->GetInputMethodController(); + return ExecutionContextClient::GetFrame()->GetInputMethodController(); +} + +bool EditContext::IsEditContextActive() const { + return true; +} + +bool EditContext::IsInputPanelPolicyManual() const { + return GetInputMethodController() + .GetActiveEditContext() + ->inputPanelPolicy() == "manual"; } void EditContext::DispatchCompositionEndEvent(const String& text) { auto* event = MakeGarbageCollected<CompositionEvent>( event_type_names::kCompositionend, - ContextLifecycleObserver::GetFrame()->DomWindow(), text); + ExecutionContextClient::GetFrame()->DomWindow(), text); DispatchEvent(*event); } bool EditContext::DispatchCompositionStartEvent(const String& text) { auto* event = MakeGarbageCollected<CompositionEvent>( event_type_names::kCompositionstart, - ContextLifecycleObserver::GetFrame()->DomWindow(), text); + ExecutionContextClient::GetFrame()->DomWindow(), text); DispatchEvent(*event); - if (!ContextLifecycleObserver::GetFrame()) + if (!ExecutionContextClient::GetFrame()) return false; return true; } @@ -153,7 +163,7 @@ void EditContext::focus() { void EditContext::blur() { if (GetInputMethodController().GetActiveEditContext() != this) return; - // Clean up the state of the |this| EditContext + // Clean up the state of the |this| EditContext. FinishComposingText(ConfirmCompositionBehavior::kKeepSelection); GetInputMethodController().SetActiveEditContext(this); } @@ -179,7 +189,7 @@ void EditContext::updateSelection(uint32_t start, return; // There is an active composition so need to set the range of the - // composition too so that we can commit the string properly + // composition too so that we can commit the string properly. if (composition_range_start_ == 0 && composition_range_end_ == 0) { composition_range_start_ = selection_start_; composition_range_end_ = selection_end_; @@ -261,7 +271,7 @@ void EditContext::setInputPanelPolicy(const String& input_policy) { } void EditContext::setInputMode(const String& input_mode) { - // inputMode password is not supported by browsers yet + // inputMode password is not supported by browsers yet: // https://github.com/whatwg/html/issues/4875 if (input_mode == "text") @@ -299,7 +309,7 @@ String EditContext::inputMode() const { case WebTextInputMode::kWebTextInputModeUrl: return "url"; default: - return "none"; // defaulting to none + return "none"; // Defaulting to none. } } @@ -339,15 +349,15 @@ String EditContext::enterKeyHint() const { case ui::TextInputAction::kSend: return "send"; default: - // defaulting to enter + // Defaulting to enter. return "enter"; } } -void EditContext::GetLayoutBounds(WebRect& web_control_bounds, - WebRect& web_selection_bounds) { - web_control_bounds = control_bounds_; - web_selection_bounds = selection_bounds_; +void EditContext::GetLayoutBounds(WebRect* web_control_bounds, + WebRect* web_selection_bounds) { + *web_control_bounds = control_bounds_; + *web_selection_bounds = selection_bounds_; } bool EditContext::SetComposition( @@ -368,24 +378,17 @@ bool EditContext::SetComposition( composition_range_start_ = selection_start_; composition_range_end_ = selection_end_; } - // Update the selection and buffer if the composition range has changed + // Update the selection and buffer if the composition range has changed. String update_text(text); - if (composition_range_start_ != selection_start_ && - composition_range_end_ != selection_end_) { - selection_start_ = composition_range_end_; - selection_end_ = composition_range_end_; - } - text_ = text_.Substring(0, selection_start_) + update_text + - text_.Substring(selection_end_); + text_ = text_.Substring(0, composition_range_start_) + update_text + + text_.Substring(composition_range_end_); - // Fire textupdate and textformatupdate events to JS + // Fire textupdate and textformatupdate events to JS. const uint32_t update_range_start = composition_range_start_; const uint32_t update_range_end = composition_range_end_; - if (has_composition_) { - // Replace the existing composition with empty string - composition_range_start_ = selection_start_; - composition_range_end_ = selection_end_; - } + // Update the new selection. + selection_start_ = composition_range_start_ + selection_end; + selection_end_ = composition_range_start_ + selection_end; DispatchTextUpdateEvent(update_text, update_range_start, update_range_end, selection_start_, selection_end_); composition_range_end_ = composition_range_start_ + selection_end; @@ -422,7 +425,7 @@ bool EditContext::SetCompositionFromExistingText( composition_range_end_, composition_start, composition_start); DispatchTextFormatEvent(ime_text_spans); - // Update the selection range + // Update the selection range. selection_start_ = composition_start; selection_end_ = composition_start; return true; @@ -432,10 +435,10 @@ bool EditContext::CommitText(const WebString& text, const WebVector<WebImeTextSpan>& ime_text_spans, const WebRange& replacement_range, int relative_caret_position) { - // Fire textupdate and textformatupdate events to JS + // Fire textupdate and textformatupdate events to JS. // ime_text_spans can have multiple format updates so loop through and fire - // events accordingly - // Update the cached selection too + // events accordingly. + // Update the cached selection too. String update_text(text); uint32_t update_range_start; uint32_t update_range_end; @@ -462,7 +465,7 @@ bool EditContext::CommitText(const WebString& text, composition_range_end_ = 0; DispatchTextUpdateEvent(update_text, update_range_start, update_range_end, new_selection_start, new_selection_end); - // Fire composition end event + // Fire composition end event. if (!text.IsEmpty() && has_composition_) DispatchCompositionEndEvent(text); @@ -475,7 +478,7 @@ bool EditContext::FinishComposingText( WebString text; if (has_composition_) { text = text_.Substring(composition_range_start_, composition_range_end_); - // Fire composition end event + // Fire composition end event. DispatchCompositionEndEvent(text); } else { text = text_.Substring(selection_start_, selection_end_); @@ -536,7 +539,7 @@ WebTextInputMode EditContext::GetInputModeOfEditContext() const { WebTextInputInfo EditContext::TextInputInfo() { WebTextInputInfo info; - // Fetch all the text input info from edit context + // Fetch all the text input info from edit context. info.action = GetEditContextEnterKeyHint(); info.input_mode = GetInputModeOfEditContext(); info.type = TextInputType(); @@ -551,12 +554,12 @@ WebTextInputInfo EditContext::TextInputInfo() { int EditContext::TextInputFlags() const { int flags = 0; - // Disable spellcheck & autocorrect for EditContext + // Disable spellcheck & autocorrect for EditContext. flags |= kWebTextInputFlagAutocorrectOff; flags |= kWebTextInputFlagSpellcheckOff; // TODO:(snianu) Enable this once the password type - // is supported by inputMode attribute + // is supported by inputMode attribute. // if (input_mode_ == WebTextInputMode::kPassword) // flags |= kWebTextInputFlagHasBeenPasswordField; @@ -578,7 +581,7 @@ WebRange EditContext::GetSelectionOffsets() const { void EditContext::Trace(Visitor* visitor) { ActiveScriptWrappable::Trace(visitor); - ContextLifecycleObserver::Trace(visitor); + ExecutionContextClient::Trace(visitor); EventTargetWithInlineData::Trace(visitor); } diff --git a/chromium/third_party/blink/renderer/core/editing/ime/edit_context.h b/chromium/third_party/blink/renderer/core/editing/ime/edit_context.h index 38cdc12c43e..74e27ec35a2 100644 --- a/chromium/third_party/blink/renderer/core/editing/ime/edit_context.h +++ b/chromium/third_party/blink/renderer/core/editing/ime/edit_context.h @@ -14,7 +14,7 @@ #include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/dom/events/event_target.h" -#include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h" +#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h" namespace blink { @@ -29,11 +29,11 @@ class InputMethodController; // The goal of the EditContext is to expose the lower-level APIs provided by // modern operating systems to facilitate various input modalities to unlock // advanced editing scenarios. For more information please refer -// https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/master/EditContext/explainer.md +// https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/master/EditContext/explainer.md. class CORE_EXPORT EditContext final : public EventTargetWithInlineData, public ActiveScriptWrappable<EditContext>, - public ContextLifecycleObserver, + public ExecutionContextClient, public WebInputMethodController { DEFINE_WRAPPERTYPEINFO(); USING_GARBAGE_COLLECTED_MIXIN(EditContext); @@ -44,13 +44,13 @@ class CORE_EXPORT EditContext final : public EventTargetWithInlineData, const EditContextInit* dict); ~EditContext() override; - // Event listeners for an EditContext + // Event listeners for an EditContext. DEFINE_ATTRIBUTE_EVENT_LISTENER(textupdate, kTextupdate) DEFINE_ATTRIBUTE_EVENT_LISTENER(textformatupdate, kTextformatupdate) DEFINE_ATTRIBUTE_EVENT_LISTENER(compositionstart, kCompositionstart) DEFINE_ATTRIBUTE_EVENT_LISTENER(compositionend, kCompositionend) - // Public APIs for an EditContext (called from JS) + // Public APIs for an EditContext (called from JS). // When focus is called on an EditContext, it sets the active EditContext in // the document so it can use the text input state to send info about the @@ -87,51 +87,51 @@ class CORE_EXPORT EditContext final : public EventTargetWithInlineData, // updated. However, in general this should be avoided during the firing of // textupdate as it will result in a canceled composition. // Also, after calling this API, update the selection by calling - // updateSelection + // updateSelection. void updateText(uint32_t start, uint32_t end, const String& new_text, ExceptionState& exception_state); - // Returns the text of the EditContext + // Returns the text of the EditContext. String text() const; - // Returns the current selectionStart of the EditContext + // Returns the current selectionStart of the EditContext. uint32_t selectionStart() const; - // Returns the current selectionEnd of the EditContext + // Returns the current selectionEnd of the EditContext. uint32_t selectionEnd() const; - // Returns the InputMode of the EditContext + // Returns the InputMode of the EditContext. String inputMode() const; - // Returns the EnterKeyHint of the EditContext + // Returns the EnterKeyHint of the EditContext. String enterKeyHint() const; - // Returns the InputPanelPolicy of the EditContext + // Returns the InputPanelPolicy of the EditContext. String inputPanelPolicy() const; - // Sets the text of the EditContext which is used to display suggestions + // Sets the text of the EditContext which is used to display suggestions. void setText(const String& text); - // Sets the selectionStart of the EditContext + // Sets the selectionStart of the EditContext. void setSelectionStart(uint32_t selection_start, ExceptionState& exception_state); - // Sets the selectionEnd of the EditContext + // Sets the selectionEnd of the EditContext. void setSelectionEnd(uint32_t selection_end, ExceptionState& exception_state); // Sets an input mode defined in EditContextInputMode. - // This relates to the inputMode attribute defined for input element - // https://html.spec.whatwg.org/multipage/interaction.html#input-modalities:-the-inputmode-attribute + // This relates to the inputMode attribute defined for input element: + // https://html.spec.whatwg.org/multipage/interaction.html#input-modalities:-the-inputmode-attribute. void setInputMode(const String& input_mode); // Sets a specific action related to Enter key defined in - // https://html.spec.whatwg.org/multipage/interaction.html#input-modalities:-the-enterkeyhint-attribute + // https://html.spec.whatwg.org/multipage/interaction.html#input-modalities:-the-enterkeyhint-attribute. void setEnterKeyHint(const String& enter_key_hint); - // Sets a policy that determines whether the VK should be raised or dismissed - // Auto raises the VK automatically, Manual suppresses it + // Sets a policy that determines whether the VK should be raised or dismissed. + // Auto raises the VK automatically, Manual suppresses it. void setInputPanelPolicy(const String& input_policy); // EventTarget overrides @@ -163,9 +163,10 @@ class CORE_EXPORT EditContext final : public EventTargetWithInlineData, bool GetCompositionCharacterBounds(WebVector<WebRect>& bounds) override; WebRange GetSelectionOffsets() const override; - // Returns the control and selection bounds for an EditContext - void GetLayoutBounds(WebRect& web_control_bounds, - WebRect& web_selection_bounds) override; + // Populate |control_bounds| and |selection_bounds| with the bounds fetched + // from the active EditContext. + void GetLayoutBounds(WebRect* web_control_bounds, + WebRect* web_selection_bounds) override; // Sets the composition range from the already existing text // This is used for reconversion scenarios in JPN IME. @@ -174,28 +175,29 @@ class CORE_EXPORT EditContext final : public EventTargetWithInlineData, int composition_end, const WebVector<WebImeTextSpan>& ime_text_spans); - bool IsEditContextActive() const override { return true; } + bool IsInputPanelPolicyManual() const override; + bool IsEditContextActive() const override; // Called from WebLocalFrame for English compositions // such as shape-writing, handwriting panels etc. // Extends the current selection range and removes the - // characters from the buffer + // characters from the buffer. void ExtendSelectionAndDelete(int before, int after); private: - // Returns the enter key action attribute set in the EditContext + // Returns the enter key action attribute set in the EditContext. ui::TextInputAction GetEditContextEnterKeyHint() const; - // Returns the inputMode of the EditContext from enterKeyHint property + // Returns the inputMode of the EditContext from enterKeyHint property. WebTextInputMode GetInputModeOfEditContext() const; InputMethodController& GetInputMethodController() const; - // Events fired to JS - // Fires compositionstart event to JS whenever user starts a composition + // Events fired to JS. + // Fires compositionstart event to JS whenever user starts a composition. bool DispatchCompositionStartEvent(const String& text); // Fires compositionend event to JS whenever composition is terminated by the - // user + // user. void DispatchCompositionEndEvent(const String& text); // The textformatupdate event is fired when the input method desires a @@ -203,7 +205,7 @@ class CORE_EXPORT EditContext final : public EventTargetWithInlineData, // properties that correspond with the properties that are exposed on // TextFormatUpdateEvent (e.g. backgroundColor, textDecoration, etc.). The // consumer of the EditContext should update their view accordingly to provide - // the user with visual feedback as prescribed by the software keyboard + // the user with visual feedback as prescribed by the software keyboard. void DispatchTextFormatEvent(const WebVector<WebImeTextSpan>& ime_text_spans); // The textupdate event will be fired on the EditContext when user input has @@ -227,7 +229,7 @@ class CORE_EXPORT EditContext final : public EventTargetWithInlineData, uint32_t new_selection_start, uint32_t new_selection_end); - // EditContext member variables + // EditContext member variables. String text_; uint32_t selection_start_ = 0; uint32_t selection_end_ = 0; diff --git a/chromium/third_party/blink/renderer/core/editing/ime/edit_context.idl b/chromium/third_party/blink/renderer/core/editing/ime/edit_context.idl index 18bc5d02740..b085b020237 100644 --- a/chromium/third_party/blink/renderer/core/editing/ime/edit_context.idl +++ b/chromium/third_party/blink/renderer/core/editing/ime/edit_context.idl @@ -7,12 +7,11 @@ // advanced editing scenarios. For more information please refer // https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/master/EditContext/explainer.md [ - Constructor(optional EditContextInit options), - ConstructorCallWith=ScriptState, Exposed=Window, ActiveScriptWrappable, RuntimeEnabled=EditContext ] interface EditContext : EventTarget { + [CallWith=ScriptState] constructor(optional EditContextInit options = {}); void focus(); void blur(); [RaisesException] void updateSelection(unsigned long start, unsigned long end); diff --git a/chromium/third_party/blink/renderer/core/editing/ime/ime_text_span.cc b/chromium/third_party/blink/renderer/core/editing/ime/ime_text_span.cc index 6a40e77088b..359a07258ff 100644 --- a/chromium/third_party/blink/renderer/core/editing/ime/ime_text_span.cc +++ b/chromium/third_party/blink/renderer/core/editing/ime/ime_text_span.cc @@ -14,6 +14,8 @@ ImeTextSpan::ImeTextSpan(Type type, unsigned end_offset, const Color& underline_color, ui::mojom::ImeTextSpanThickness thickness, + ui::mojom::ImeTextSpanUnderlineStyle underline_style, + const Color& text_color, const Color& background_color, const Color& suggestion_highlight_color, bool remove_on_finish_composing, @@ -21,6 +23,8 @@ ImeTextSpan::ImeTextSpan(Type type, : type_(type), underline_color_(underline_color), thickness_(thickness), + underline_style_(underline_style), + text_color_(text_color), background_color_(background_color), suggestion_highlight_color_(suggestion_highlight_color), remove_on_finish_composing_(remove_on_finish_composing), @@ -67,6 +71,8 @@ ImeTextSpan::ImeTextSpan(const WebImeTextSpan& ime_text_span) ime_text_span.end_offset, Color(ime_text_span.underline_color), ime_text_span.thickness, + ime_text_span.underline_style, + Color(ime_text_span.text_color), Color(ime_text_span.background_color), Color(ime_text_span.suggestion_highlight_color), ime_text_span.remove_on_finish_composing, diff --git a/chromium/third_party/blink/renderer/core/editing/ime/ime_text_span.h b/chromium/third_party/blink/renderer/core/editing/ime/ime_text_span.h index 40fcf98a41a..5e8f42e51bf 100644 --- a/chromium/third_party/blink/renderer/core/editing/ime/ime_text_span.h +++ b/chromium/third_party/blink/renderer/core/editing/ime/ime_text_span.h @@ -48,6 +48,8 @@ class CORE_EXPORT ImeTextSpan { unsigned end_offset, const Color& underline_color, ui::mojom::ImeTextSpanThickness, + ui::mojom::ImeTextSpanUnderlineStyle, + const Color& text_color, const Color& background_color, const Color& suggestion_highlight_color = Color::kTransparent, bool remove_on_finish_composing = false, @@ -60,6 +62,10 @@ class CORE_EXPORT ImeTextSpan { unsigned EndOffset() const { return end_offset_; } const Color& UnderlineColor() const { return underline_color_; } ui::mojom::ImeTextSpanThickness Thickness() const { return thickness_; } + ui::mojom::ImeTextSpanUnderlineStyle UnderlineStyle() const { + return underline_style_; + } + const Color& TextColor() const { return text_color_; } const Color& BackgroundColor() const { return background_color_; } const Color& SuggestionHighlightColor() const { return suggestion_highlight_color_; @@ -75,6 +81,8 @@ class CORE_EXPORT ImeTextSpan { unsigned end_offset_; Color underline_color_; ui::mojom::ImeTextSpanThickness thickness_; + ui::mojom::ImeTextSpanUnderlineStyle underline_style_; + Color text_color_; Color background_color_; Color suggestion_highlight_color_; bool remove_on_finish_composing_; diff --git a/chromium/third_party/blink/renderer/core/editing/ime/ime_text_span_test.cc b/chromium/third_party/blink/renderer/core/editing/ime/ime_text_span_test.cc index 23131ca7f06..8095b83030d 100644 --- a/chromium/third_party/blink/renderer/core/editing/ime/ime_text_span_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/ime/ime_text_span_test.cc @@ -14,7 +14,18 @@ ImeTextSpan CreateImeTextSpan(unsigned start_offset, unsigned end_offset) { return ImeTextSpan(ImeTextSpan::Type::kComposition, start_offset, end_offset, Color::kTransparent, ui::mojom::ImeTextSpanThickness::kNone, - Color::kTransparent); + ui::mojom::ImeTextSpanUnderlineStyle::kNone, + Color::kTransparent, Color::kTransparent); +} + +ImeTextSpan CreateImeTextSpan( + unsigned start_offset, + unsigned end_offset, + ui::mojom::ImeTextSpanUnderlineStyle underline_style) { + return ImeTextSpan(ImeTextSpan::Type::kComposition, start_offset, end_offset, + Color::kTransparent, + ui::mojom::ImeTextSpanThickness::kNone, underline_style, + Color::kTransparent, Color::kTransparent); } TEST(ImeTextSpanTest, OneChar) { @@ -73,5 +84,24 @@ TEST(ImeTextSpanTest, LastCharEndBeforeStartZeroEnd) { EXPECT_EQ(std::numeric_limits<unsigned>::max(), ime_text_span.EndOffset()); } +TEST(ImeTextSpanTest, UnderlineStyles) { + ImeTextSpan ime_text_span = + CreateImeTextSpan(0, 5, ui::mojom::ImeTextSpanUnderlineStyle::kSolid); + EXPECT_EQ(ui::mojom::ImeTextSpanUnderlineStyle::kSolid, + ime_text_span.UnderlineStyle()); + ime_text_span = + CreateImeTextSpan(0, 5, ui::mojom::ImeTextSpanUnderlineStyle::kDot); + EXPECT_EQ(ui::mojom::ImeTextSpanUnderlineStyle::kDot, + ime_text_span.UnderlineStyle()); + ime_text_span = + CreateImeTextSpan(0, 5, ui::mojom::ImeTextSpanUnderlineStyle::kDash); + EXPECT_EQ(ui::mojom::ImeTextSpanUnderlineStyle::kDash, + ime_text_span.UnderlineStyle()); + ime_text_span = + CreateImeTextSpan(0, 5, ui::mojom::ImeTextSpanUnderlineStyle::kSquiggle); + EXPECT_EQ(ui::mojom::ImeTextSpanUnderlineStyle::kSquiggle, + ime_text_span.UnderlineStyle()); +} + } // namespace } // namespace blink diff --git a/chromium/third_party/blink/renderer/core/editing/ime/input_method_controller.cc b/chromium/third_party/blink/renderer/core/editing/ime/input_method_controller.cc index 6de4f3a2aae..64be8237804 100644 --- a/chromium/third_party/blink/renderer/core/editing/ime/input_method_controller.cc +++ b/chromium/third_party/blink/renderer/core/editing/ime/input_method_controller.cc @@ -26,12 +26,14 @@ #include "third_party/blink/renderer/core/editing/ime/input_method_controller.h" +#include "third_party/blink/public/mojom/input/focus_type.mojom-blink.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/element.h" #include "third_party/blink/renderer/core/dom/events/event_dispatcher.h" #include "third_party/blink/renderer/core/dom/events/scoped_event_queue.h" #include "third_party/blink/renderer/core/dom/range.h" #include "third_party/blink/renderer/core/dom/text.h" +#include "third_party/blink/renderer/core/editing/commands/delete_selection_command.h" #include "third_party/blink/renderer/core/editing/commands/typing_command.h" #include "third_party/blink/renderer/core/editing/commands/undo_stack.h" #include "third_party/blink/renderer/core/editing/editing_utilities.h" @@ -50,6 +52,7 @@ #include "third_party/blink/renderer/core/events/composition_event.h" #include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/core/frame/local_frame.h" +#include "third_party/blink/renderer/core/geometry/dom_rect.h" #include "third_party/blink/renderer/core/html/forms/html_input_element.h" #include "third_party/blink/renderer/core/html/forms/html_text_area_element.h" #include "third_party/blink/renderer/core/input/event_handler.h" @@ -77,7 +80,7 @@ void DispatchCompositionUpdateEvent(LocalFrame& frame, const String& text) { void DispatchCompositionEndEvent(LocalFrame& frame, const String& text) { // Verify that the caller is using an EventQueueScope to suppress the input // event from being fired until the proper time (e.g. after applying an IME - // selection update, if necesary). + // selection update, if necessary). DCHECK(ScopedEventQueue::Instance()->ShouldQueueEvents()); Element* target = frame.GetDocument()->FocusedElement(); @@ -131,7 +134,7 @@ void InsertTextDuringCompositionWithEvents( TypingCommand::TextCompositionType composition_type) { // Verify that the caller is using an EventQueueScope to suppress the input // event from being fired until the proper time (e.g. after applying an IME - // selection update, if necesary). + // selection update, if necessary). DCHECK(ScopedEventQueue::Instance()->ShouldQueueEvents()); DCHECK(composition_type == TypingCommand::TextCompositionType::kTextCompositionUpdate || @@ -163,7 +166,7 @@ void InsertTextDuringCompositionWithEvents( // TODO(editing-dev): The use of UpdateStyleAndLayout // needs to be audited. see http://crbug.com/590369 for more details. - frame.GetDocument()->UpdateStyleAndLayout(); + frame.GetDocument()->UpdateStyleAndLayout(DocumentUpdateReason::kInput); const bool is_incremental_insertion = NeedsIncrementalInsertion(frame, text); @@ -175,7 +178,7 @@ void InsertTextDuringCompositionWithEvents( // https://crbug.com/693481 if (text.IsEmpty()) TypingCommand::DeleteSelection(*frame.GetDocument(), 0); - frame.GetDocument()->UpdateStyleAndLayout(); + frame.GetDocument()->UpdateStyleAndLayout(DocumentUpdateReason::kEditing); TypingCommand::InsertText(*frame.GetDocument(), text, options, composition_type, is_incremental_insertion); break; @@ -320,7 +323,8 @@ Element* RootEditableElementOfSelection(const FrameSelection& frameSelection) { // TODO(editing-dev): Use of UpdateStyleAndLayout // needs to be audited. see http://crbug.com/590369 for more details. - frameSelection.GetDocument().UpdateStyleAndLayout(); + frameSelection.GetDocument().UpdateStyleAndLayout( + DocumentUpdateReason::kEditing); const VisibleSelection& visibleSeleciton = frameSelection.ComputeVisibleSelectionInDOMTree(); return RootEditableElementOf(visibleSeleciton.Start()); @@ -393,12 +397,12 @@ InputMethodController::InputMethodController(LocalFrame& frame) InputMethodController::~InputMethodController() = default; bool InputMethodController::IsAvailable() const { - return LifecycleContext(); + return GetExecutionContext(); } Document& InputMethodController::GetDocument() const { DCHECK(IsAvailable()); - return *LifecycleContext(); + return *Document::From(GetExecutionContext()); } bool InputMethodController::HasComposition() const { @@ -422,7 +426,7 @@ void InputMethodController::Clear() { DocumentMarker::MarkerTypes::Composition()); } -void InputMethodController::ContextDestroyed(Document*) { +void InputMethodController::ContextDestroyed() { Clear(); composition_range_ = nullptr; active_edit_context_ = nullptr; @@ -430,7 +434,7 @@ void InputMethodController::ContextDestroyed(Document*) { void InputMethodController::DidAttachDocument(Document* document) { DCHECK(document); - SetContext(document); + SetExecutionContext(document->ToExecutionContext()); } void InputMethodController::SelectComposition() const { @@ -470,9 +474,9 @@ bool InputMethodController::FinishComposingText( // clamp the text by replacing the composition with the same value. const bool is_too_long = IsTextTooLongAt(composition_range_->StartPosition()); - // TODO(editing-dev): Use of UpdateStyleAndLayoutIgnorePendingStylesheets + // TODO(editing-dev): Use of UpdateStyleAndLayout // needs to be audited. see http://crbug.com/590369 for more details. - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); const String& composing = ComposingText(); // Suppress input event (if we hit the is_too_long case) and compositionend @@ -495,9 +499,9 @@ bool InputMethodController::FinishComposingText( DispatchCompositionEndEvent(GetFrame(), composing); } - // TODO(editing-dev): Use of updateStyleAndLayoutIgnorePendingStylesheets + // TODO(editing-dev): Use of updateStyleAndLayout // needs to be audited. see http://crbug.com/590369 for more details. - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); const EphemeralRange& old_selection_range = EphemeralRangeForOffsets(old_offsets); @@ -568,7 +572,7 @@ bool InputMethodController::ReplaceText(const String& text, bool InputMethodController::ReplaceComposition(const String& text) { // Verify that the caller is using an EventQueueScope to suppress the input // event from being fired until the proper time (e.g. after applying an IME - // selection update, if necesary). + // selection update, if necessary). DCHECK(ScopedEventQueue::Instance()->ShouldQueueEvents()); if (!HasComposition()) @@ -630,7 +634,8 @@ void InputMethodController::AddImeTextSpans( case ImeTextSpan::Type::kComposition: GetDocument().Markers().AddCompositionMarker( ephemeral_line_range, ime_text_span.UnderlineColor(), - ime_text_span.Thickness(), ime_text_span.BackgroundColor()); + ime_text_span.Thickness(), ime_text_span.UnderlineStyle(), + ime_text_span.TextColor(), ime_text_span.BackgroundColor()); break; case ImeTextSpan::Type::kSuggestion: case ImeTextSpan::Type::kMisspellingSuggestion: @@ -656,6 +661,8 @@ void InputMethodController::AddImeTextSpans( .SetHighlightColor(ime_text_span.SuggestionHighlightColor()) .SetUnderlineColor(ime_text_span.UnderlineColor()) .SetThickness(ime_text_span.Thickness()) + .SetUnderlineStyle(ime_text_span.UnderlineStyle()) + .SetTextColor(ime_text_span.TextColor()) .SetBackgroundColor(ime_text_span.BackgroundColor()) .SetRemoveOnFinishComposing( ime_text_span.NeedsRemovalOnFinishComposing()) @@ -691,7 +698,7 @@ bool InputMethodController::ReplaceCompositionAndMoveCaret( // TODO(editing-dev): The use of UpdateStyleAndLayout // needs to be audited. see http://crbug.com/590369 for more details. - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); AddImeTextSpans(ime_text_spans, root_editable_element, text_start); @@ -807,7 +814,7 @@ void InputMethodController::SetComposition( // TODO(editing-dev): The use of UpdateStyleAndLayout // needs to be audited. see http://crbug.com/590369 for more details. - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); PlainTextRange selected_range = CreateSelectionRangeForSetComposition( selection_start, selection_end, text.length()); @@ -847,7 +854,7 @@ void InputMethodController::SetComposition( // TODO(editing-dev): Use of UpdateStyleAndLayout // needs to be audited. see http://crbug.com/590369 for more details. - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); SetEditableSelectionOffsets(selected_range); return; @@ -876,7 +883,7 @@ void InputMethodController::SetComposition( // TODO(editing-dev): The use of UpdateStyleAndLayout // needs to be audited. see http://crbug.com/590369 for more details. - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); // The undo stack could become empty if a JavaScript event handler calls // execCommand('undo') to pop elements off the stack. Or, the top element of @@ -915,7 +922,7 @@ void InputMethodController::SetComposition( // TODO(editing-dev): The use of UpdateStyleAndLayout // needs to be audited. see http://crbug.com/590369 for more details. - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); // We shouldn't close typing in the middle of setComposition. SetEditableSelectionOffsets(selected_range, TypingContinuation::kContinue); @@ -948,6 +955,7 @@ void InputMethodController::SetComposition( GetDocument().Markers().AddCompositionMarker( CompositionEphemeralRange(), Color::kTransparent, ui::mojom::ImeTextSpanThickness::kThin, + ui::mojom::ImeTextSpanUnderlineStyle::kSolid, Color::kTransparent, LayoutTheme::GetTheme().PlatformDefaultCompositionBackgroundColor()); return; } @@ -1158,8 +1166,50 @@ bool InputMethodController::DeleteSelection() { return IsAvailable(); } +bool InputMethodController::DeleteSelectionWithoutAdjustment() { + const SelectionInDOMTree& selection_in_dom_tree = + GetFrame().Selection().GetSelectionInDOMTree(); + if (selection_in_dom_tree.IsCaret()) + return true; + + const SelectionForUndoStep& selection = + SelectionForUndoStep::From(selection_in_dom_tree); + + Node* target = GetFrame().GetDocument()->FocusedElement(); + if (target) { + DispatchBeforeInputEditorCommand( + target, InputEvent::InputType::kDeleteContentBackward, + TargetRangesForInputEvent(*target)); + // Frame could have been destroyed by the beforeinput event. + if (!IsAvailable()) + return false; + } + + if (TypingCommand* last_typing_command = + TypingCommand::LastTypingCommandIfStillOpenForTyping(&GetFrame())) { + TypingCommand::UpdateSelectionIfDifferentFromCurrentSelection( + last_typing_command, &GetFrame()); + + last_typing_command->DeleteSelection(TypingCommand::kSmartDelete, + ASSERT_NO_EDITING_ABORT); + return true; + } + + MakeGarbageCollected<DeleteSelectionCommand>( + selection, + DeleteSelectionOptions::Builder() + .SetMergeBlocksAfterDelete(true) + .SetSanitizeMarkup(true) + .Build(), + InputEvent::InputType::kDeleteContentBackward) + ->Apply(); + + // Frame could have been destroyed by the input event. + return IsAvailable(); +} + bool InputMethodController::MoveCaret(int new_caret_position) { - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); PlainTextRange selected_range = CreateRangeForSelection(new_caret_position, new_caret_position, 0); if (selected_range.IsNull()) @@ -1206,7 +1256,9 @@ void InputMethodController::ExtendSelectionAndDelete(int before, int after) { ignore_result(DeleteSelection()); } -// TODO(yabinh): We should reduce the number of selectionchange events. +// TODO(ctzsm): We should reduce the number of selectionchange events. +// Ideally, we want to do the deletion without selection, however, there is no +// such editing command exists currently. void InputMethodController::DeleteSurroundingText(int before, int after) { if (!GetEditor().CanEdit()) return; @@ -1227,25 +1279,17 @@ void InputMethodController::DeleteSurroundingText(int before, int after) { if (before > 0 && selection_start > 0) { // In case of exceeding the left boundary. const int start = std::max(selection_start - before, 0); - const EphemeralRange& range = PlainTextRange(0, start).CreateRange(*root_editable_element); if (range.IsNull()) return; - const Position& position = range.EndPosition(); - - // Adjust the start of selection for multi-code text(a grapheme cluster - // contains more than one code point). TODO(yabinh): Adjustment should be - // based on code point instead of grapheme cluster. - const size_t diff = ComputeDistanceToLeftGraphemeBoundary(position); - const int adjusted_start = start - static_cast<int>(diff); - if (!SetSelectionOffsets(PlainTextRange(adjusted_start, selection_start))) + if (!SetSelectionOffsets(PlainTextRange(start, selection_start))) return; - if (!DeleteSelection()) + if (!DeleteSelectionWithoutAdjustment()) return; - selection_end = selection_end - (selection_start - adjusted_start); - selection_start = adjusted_start; + selection_end = selection_end - (selection_start - start); + selection_start = start; } // Select the text to be deleted after SelectionState::kEnd. @@ -1260,15 +1304,10 @@ void InputMethodController::DeleteSurroundingText(int before, int after) { return; const int end = PlainTextRange::Create(*root_editable_element, valid_range).End(); - const Position& position = valid_range.EndPosition(); - // Adjust the end of selection for multi-code text. TODO(yabinh): Adjustment - // should be based on code point instead of grapheme cluster. - const size_t diff = ComputeDistanceToRightGraphemeBoundary(position); - const int adjusted_end = end + static_cast<int>(diff); - if (!SetSelectionOffsets(PlainTextRange(selection_end, adjusted_end))) + if (!SetSelectionOffsets(PlainTextRange(selection_end, end))) return; - if (!DeleteSelection()) + if (!DeleteSelectionWithoutAdjustment()) return; } @@ -1316,6 +1355,31 @@ void InputMethodController::DeleteSurroundingTextInCodePoints(int before, return DeleteSurroundingText(before_length, after_length); } +void InputMethodController::GetLayoutBounds(WebRect* control_bounds, + WebRect* selection_bounds) { + if (!IsAvailable()) + return; + + if (GetActiveEditContext()) { + return GetActiveEditContext()->GetLayoutBounds(control_bounds, + selection_bounds); + } + if (!GetFrame().Selection().IsAvailable()) + return; + Element* element = RootEditableElementOfSelection(GetFrame().Selection()); + if (!element) + return; + // Fetch the control bounds of the active editable element. + // Selection bounds are currently populated only for EditContext. + // For editable elements we use GetCompositionCharacterBounds to fetch the + // selection bounds. + DOMRect* editable_rect = element->getBoundingClientRect(); + control_bounds->x = editable_rect->x(); + control_bounds->y = editable_rect->y(); + control_bounds->width = editable_rect->width(); + control_bounds->height = editable_rect->height(); +} + WebTextInputInfo InputMethodController::TextInputInfo() const { WebTextInputInfo info; if (!IsAvailable()) @@ -1341,7 +1405,7 @@ WebTextInputInfo InputMethodController::TextInputInfo() const { // TODO(editing-dev): The use of UpdateStyleAndLayout // needs to be audited. see http://crbug.com/590369 for more details. - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); DocumentLifecycle::DisallowTransitionScope disallow_transition( GetDocument().Lifecycle()); @@ -1428,11 +1492,11 @@ int InputMethodController::ComputeWebTextInputNextPreviousFlags() const { int flags = kWebTextInputFlagNone; if (page->GetFocusController().NextFocusableElementInForm( - element, kWebFocusTypeForward)) + element, mojom::blink::FocusType::kForward)) flags |= kWebTextInputFlagHaveNextFocusableElement; if (page->GetFocusController().NextFocusableElementInForm( - element, kWebFocusTypeBackward)) + element, mojom::blink::FocusType::kBackward)) flags |= kWebTextInputFlagHavePreviousFocusableElement; return flags; @@ -1557,7 +1621,7 @@ void InputMethodController::Trace(Visitor* visitor) { visitor->Trace(frame_); visitor->Trace(composition_range_); visitor->Trace(active_edit_context_); - DocumentShutdownObserver::Trace(visitor); + ExecutionContextLifecycleObserver::Trace(visitor); } } // namespace blink diff --git a/chromium/third_party/blink/renderer/core/editing/ime/input_method_controller.h b/chromium/third_party/blink/renderer/core/editing/ime/input_method_controller.h index 4db0f92ecb3..3ad7cd7c416 100644 --- a/chromium/third_party/blink/renderer/core/editing/ime/input_method_controller.h +++ b/chromium/third_party/blink/renderer/core/editing/ime/input_method_controller.h @@ -28,11 +28,11 @@ #include "base/gtest_prod_util.h" #include "base/macros.h" +#include "third_party/blink/public/platform/web_rect.h" #include "third_party/blink/public/platform/web_text_input_info.h" #include "third_party/blink/public/platform/web_text_input_type.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/dom/document.h" -#include "third_party/blink/renderer/core/dom/document_shutdown_observer.h" #include "third_party/blink/renderer/core/editing/forward.h" #include "third_party/blink/renderer/core/editing/ime/ime_text_span.h" #include "third_party/blink/renderer/core/editing/plain_text_range.h" @@ -49,7 +49,7 @@ enum class TypingContinuation; class CORE_EXPORT InputMethodController final : public GarbageCollected<InputMethodController>, - public DocumentShutdownObserver { + ExecutionContextLifecycleObserver { USING_GARBAGE_COLLECTED_MIXIN(InputMethodController); public: @@ -120,6 +120,10 @@ class CORE_EXPORT InputMethodController final active_edit_context_ = edit_context; } + // Returns either the focused editable element's control bounds or the + // EditContext's control and selection bounds if available. + void GetLayoutBounds(WebRect* control_bounds, WebRect* selection_bounds); + private: friend class InputMethodControllerTest; @@ -167,6 +171,12 @@ class CORE_EXPORT InputMethodController final // Returns false if the frame was destroyed, true otherwise. bool DeleteSelection() WARN_UNUSED_RESULT; + // Returns false if the frame was destroyed, true otherwise. + // The difference between this function and DeleteSelection() is that + // DeleteSelection() code path may modify the selection to visible units, + // which we don't want when deleting code point. + bool DeleteSelectionWithoutAdjustment() WARN_UNUSED_RESULT; + // Returns true if moved caret successfully. bool MoveCaret(int new_caret_position); @@ -181,8 +191,8 @@ class CORE_EXPORT InputMethodController final ui::TextInputAction InputActionOfFocusedElement() const; WebTextInputMode InputModeOfFocusedElement() const; - // Implements |DocumentShutdownObserver|. - void ContextDestroyed(Document*) final; + // Implements |ExecutionContextLifecycleObserver|. + void ContextDestroyed() final; enum class TypingContinuation; diff --git a/chromium/third_party/blink/renderer/core/editing/ime/input_method_controller_test.cc b/chromium/third_party/blink/renderer/core/editing/ime/input_method_controller_test.cc index c79051a4946..d7f61e65188 100644 --- a/chromium/third_party/blink/renderer/core/editing/ime/input_method_controller_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/ime/input_method_controller_test.cc @@ -24,6 +24,7 @@ #include "third_party/blink/renderer/core/html/forms/html_text_area_element.h" using ui::mojom::ImeTextSpanThickness; +using ui::mojom::ImeTextSpanUnderlineStyle; namespace blink { @@ -46,7 +47,7 @@ class InputMethodControllerTest : public EditingTestBase { Element* InputMethodControllerTest::InsertHTMLElement(const char* element_code, const char* element_id) { GetDocument().write(element_code); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Element* element = GetElementById(element_id); element->focus(); return element; @@ -57,7 +58,7 @@ void InputMethodControllerTest::CreateHTMLWithCompositionInputEventListeners() { Element* editable = InsertHTMLElement("<div id='sample' contenteditable></div>", "sample"); Element* script = GetDocument().CreateRawElement(html_names::kScriptTag); - script->SetInnerHTMLFromString( + script->setInnerHTML( "document.getElementById('sample').addEventListener('beforeinput', " " event => document.title = `beforeinput.data:${event.data};`);" "document.getElementById('sample').addEventListener('input', " @@ -78,14 +79,14 @@ void InputMethodControllerTest::CreateHTMLWithCompositionEndEventListener( switch (type) { case kNoSelection: - script->SetInnerHTMLFromString( + script->setInnerHTML( // If the caret position is set before firing 'compositonend' event // (and it should), the final caret position will be reset to null. "document.getElementById('sample').addEventListener('compositionend'," " event => getSelection().removeAllRanges());"); break; case kCaretSelection: - script->SetInnerHTMLFromString( + script->setInnerHTML( // If the caret position is set before firing 'compositonend' event // (and it should), the final caret position will be reset to [3,3]. "document.getElementById('sample').addEventListener('compositionend'," @@ -95,7 +96,7 @@ void InputMethodControllerTest::CreateHTMLWithCompositionEndEventListener( "});"); break; case kRangeSelection: - script->SetInnerHTMLFromString( + script->setInnerHTML( // If the caret position is set before firing 'compositonend' event // (and it should), the final caret position will be reset to [2,4]. "document.getElementById('sample').addEventListener('compositionend'," @@ -119,14 +120,14 @@ TEST_F(InputMethodControllerTest, BackspaceFromEndOfInput) { To<HTMLInputElement>(InsertHTMLElement("<input id='sample'>", "sample")); input->setValue("fooX"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Controller().SetEditableSelectionOffsets(PlainTextRange(4, 4)); EXPECT_EQ("fooX", input->value()); Controller().ExtendSelectionAndDelete(0, 0); EXPECT_EQ("fooX", input->value()); input->setValue("fooX"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Controller().SetEditableSelectionOffsets(PlainTextRange(4, 4)); EXPECT_EQ("fooX", input->value()); Controller().ExtendSelectionAndDelete(1, 0); @@ -134,7 +135,7 @@ TEST_F(InputMethodControllerTest, BackspaceFromEndOfInput) { input->setValue( String::FromUTF8("foo\xE2\x98\x85")); // U+2605 == "black star" - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Controller().SetEditableSelectionOffsets(PlainTextRange(4, 4)); EXPECT_EQ("foo\xE2\x98\x85", input->value().Utf8()); Controller().ExtendSelectionAndDelete(1, 0); @@ -142,7 +143,7 @@ TEST_F(InputMethodControllerTest, BackspaceFromEndOfInput) { input->setValue( String::FromUTF8("foo\xF0\x9F\x8F\x86")); // U+1F3C6 == "trophy" - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Controller().SetEditableSelectionOffsets(PlainTextRange(4, 4)); EXPECT_EQ("foo\xF0\x9F\x8F\x86", input->value().Utf8()); Controller().ExtendSelectionAndDelete(1, 0); @@ -150,14 +151,14 @@ TEST_F(InputMethodControllerTest, BackspaceFromEndOfInput) { // composed U+0E01 "ka kai" + U+0E49 "mai tho" input->setValue(String::FromUTF8("foo\xE0\xB8\x81\xE0\xB9\x89")); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Controller().SetEditableSelectionOffsets(PlainTextRange(4, 4)); EXPECT_EQ("foo\xE0\xB8\x81\xE0\xB9\x89", input->value().Utf8()); Controller().ExtendSelectionAndDelete(1, 0); EXPECT_EQ("foo", input->value()); input->setValue("fooX"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Controller().SetEditableSelectionOffsets(PlainTextRange(4, 4)); EXPECT_EQ("fooX", input->value()); Controller().ExtendSelectionAndDelete(0, 1); @@ -169,9 +170,9 @@ TEST_F(InputMethodControllerTest, SetCompositionFromExistingText) { "<div id='sample' contenteditable>hello world</div>", "sample"); Vector<ImeTextSpan> ime_text_spans; - ime_text_spans.push_back(ImeTextSpan(ImeTextSpan::Type::kComposition, 0, 5, - Color(255, 0, 0), - ImeTextSpanThickness::kThin, 0)); + ime_text_spans.push_back(ImeTextSpan( + ImeTextSpan::Type::kComposition, 0, 5, Color(255, 0, 0), + ImeTextSpanThickness::kThin, ImeTextSpanUnderlineStyle::kSolid, 0, 0)); Controller().SetCompositionFromExistingText(ime_text_spans, 0, 5); Range* range = GetCompositionRange(); @@ -189,11 +190,11 @@ TEST_F(InputMethodControllerTest, SetCompositionAfterEmoji) { "<div id='sample' contenteditable>🏆</div>", "sample"); Vector<ImeTextSpan> ime_text_spans; - ime_text_spans.push_back(ImeTextSpan(ImeTextSpan::Type::kComposition, 0, 2, - Color(255, 0, 0), - ImeTextSpanThickness::kThin, 0)); + ime_text_spans.push_back(ImeTextSpan( + ImeTextSpan::Type::kComposition, 0, 2, Color(255, 0, 0), + ImeTextSpanThickness::kThin, ImeTextSpanUnderlineStyle::kSolid, 0, 0)); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Controller().SetEditableSelectionOffsets(PlainTextRange(2, 2)); EXPECT_EQ(2, GetFrame() .Selection() @@ -217,10 +218,10 @@ TEST_F(InputMethodControllerTest, SetCompositionWithGraphemeCluster) { InsertHTMLElement("<div id='sample' contenteditable></div>", "sample"); Vector<ImeTextSpan> ime_text_spans; - ime_text_spans.push_back(ImeTextSpan(ImeTextSpan::Type::kComposition, 6, 6, - Color(255, 0, 0), - ImeTextSpanThickness::kThin, 0)); - GetDocument().UpdateStyleAndLayout(); + ime_text_spans.push_back(ImeTextSpan( + ImeTextSpan::Type::kComposition, 6, 6, Color(255, 0, 0), + ImeTextSpanThickness::kThin, ImeTextSpanUnderlineStyle::kSolid, 0, 0)); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); // UTF16 = 0x0939 0x0947 0x0932 0x0932. Note that 0x0932 0x0932 is a grapheme // cluster. @@ -245,10 +246,10 @@ TEST_F(InputMethodControllerTest, InsertHTMLElement("<div id='sample' contenteditable></div>", "sample"); Vector<ImeTextSpan> ime_text_spans; - ime_text_spans.push_back(ImeTextSpan(ImeTextSpan::Type::kComposition, 12, 12, - Color(255, 0, 0), - ImeTextSpanThickness::kThin, 0)); - GetDocument().UpdateStyleAndLayout(); + ime_text_spans.push_back(ImeTextSpan( + ImeTextSpan::Type::kComposition, 12, 12, Color(255, 0, 0), + ImeTextSpanThickness::kThin, ImeTextSpanUnderlineStyle::kSolid, 0, 0)); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); // UTF16 = 0x0939 0x0947 0x0932 0x094D 0x0932 0x094B. 0x0939 0x0947 0x0932 is // a grapheme cluster, so is the remainding 0x0932 0x094B. @@ -281,29 +282,26 @@ TEST_F(InputMethodControllerTest, SetCompositionKeepingStyle) { "sample"); Vector<ImeTextSpan> ime_text_spans; - ime_text_spans.push_back(ImeTextSpan(ImeTextSpan::Type::kComposition, 3, 12, - Color(255, 0, 0), - ImeTextSpanThickness::kThin, 0)); + ime_text_spans.push_back(ImeTextSpan( + ImeTextSpan::Type::kComposition, 3, 12, Color(255, 0, 0), + ImeTextSpanThickness::kThin, ImeTextSpanUnderlineStyle::kSolid, 0, 0)); Controller().SetCompositionFromExistingText(ime_text_spans, 3, 12); // Subtract a character. Controller().SetComposition(String("12345789"), ime_text_spans, 8, 8); - EXPECT_EQ("abc1<b>2</b>3457<b>8</b>9d<b>e</b>f", - div->InnerHTMLAsString().Utf8()); + EXPECT_EQ("abc1<b>2</b>3457<b>8</b>9d<b>e</b>f", div->innerHTML().Utf8()); EXPECT_EQ(11u, Controller().GetSelectionOffsets().Start()); EXPECT_EQ(11u, Controller().GetSelectionOffsets().End()); // Append a character. Controller().SetComposition(String("123456789"), ime_text_spans, 9, 9); - EXPECT_EQ("abc1<b>2</b>34567<b>8</b>9d<b>e</b>f", - div->InnerHTMLAsString().Utf8()); + EXPECT_EQ("abc1<b>2</b>34567<b>8</b>9d<b>e</b>f", div->innerHTML().Utf8()); EXPECT_EQ(12u, Controller().GetSelectionOffsets().Start()); EXPECT_EQ(12u, Controller().GetSelectionOffsets().End()); // Subtract and append characters. Controller().SetComposition(String("123hello789"), ime_text_spans, 11, 11); - EXPECT_EQ("abc1<b>2</b>3hello7<b>8</b>9d<b>e</b>f", - div->InnerHTMLAsString().Utf8()); + EXPECT_EQ("abc1<b>2</b>3hello7<b>8</b>9d<b>e</b>f", div->innerHTML().Utf8()); } TEST_F(InputMethodControllerTest, SetCompositionWithEmojiKeepingStyle) { @@ -312,9 +310,9 @@ TEST_F(InputMethodControllerTest, SetCompositionWithEmojiKeepingStyle) { "<div id='sample' contenteditable><b>🏠</b></div>", "sample"); Vector<ImeTextSpan> ime_text_spans; - ime_text_spans.push_back(ImeTextSpan(ImeTextSpan::Type::kComposition, 0, 2, - Color(255, 0, 0), - ImeTextSpanThickness::kThin, 0)); + ime_text_spans.push_back(ImeTextSpan( + ImeTextSpan::Type::kComposition, 0, 2, Color(255, 0, 0), + ImeTextSpanThickness::kThin, ImeTextSpanUnderlineStyle::kSolid, 0, 0)); Controller().SetCompositionFromExistingText(ime_text_spans, 0, 2); @@ -322,11 +320,11 @@ TEST_F(InputMethodControllerTest, SetCompositionWithEmojiKeepingStyle) { // surrogate pair to the previous one. Controller().SetComposition(String::FromUTF8("\xF0\x9F\x8F\xAB"), ime_text_spans, 2, 2); - EXPECT_EQ("<b>\xF0\x9F\x8F\xAB</b>", div->InnerHTMLAsString().Utf8()); + EXPECT_EQ("<b>\xF0\x9F\x8F\xAB</b>", div->innerHTML().Utf8()); Controller().SetComposition(String::FromUTF8("\xF0\x9F\x8F\xA0"), ime_text_spans, 2, 2); - EXPECT_EQ("<b>\xF0\x9F\x8F\xA0</b>", div->InnerHTMLAsString().Utf8()); + EXPECT_EQ("<b>\xF0\x9F\x8F\xA0</b>", div->innerHTML().Utf8()); } TEST_F(InputMethodControllerTest, @@ -338,20 +336,20 @@ TEST_F(InputMethodControllerTest, "<div id='sample' contenteditable><b>ః</b></div>", "sample"); Vector<ImeTextSpan> ime_text_spans; - ime_text_spans.push_back(ImeTextSpan(ImeTextSpan::Type::kComposition, 0, 2, - Color(255, 0, 0), - ImeTextSpanThickness::kThin, 0)); + ime_text_spans.push_back(ImeTextSpan( + ImeTextSpan::Type::kComposition, 0, 2, Color(255, 0, 0), + ImeTextSpanThickness::kThin, ImeTextSpanUnderlineStyle::kSolid, 0, 0)); Controller().SetCompositionFromExistingText(ime_text_spans, 0, 1); // 0xE0 0xB0 0x83 0xE0 0xB0 0x83, a telugu character with 2 code points in // 1 grapheme cluster. Controller().SetComposition(String::FromUTF8("\xE0\xB0\x83\xE0\xB0\x83"), ime_text_spans, 2, 2); - EXPECT_EQ("<b>\xE0\xB0\x83\xE0\xB0\x83</b>", div->InnerHTMLAsString().Utf8()); + EXPECT_EQ("<b>\xE0\xB0\x83\xE0\xB0\x83</b>", div->innerHTML().Utf8()); Controller().SetComposition(String::FromUTF8("\xE0\xB0\x83"), ime_text_spans, 1, 1); - EXPECT_EQ("<b>\xE0\xB0\x83</b>", div->InnerHTMLAsString().Utf8()); + EXPECT_EQ("<b>\xE0\xB0\x83</b>", div->innerHTML().Utf8()); } TEST_F(InputMethodControllerTest, FinishComposingTextKeepingStyle) { @@ -361,16 +359,16 @@ TEST_F(InputMethodControllerTest, FinishComposingTextKeepingStyle) { "sample"); Vector<ImeTextSpan> ime_text_spans; - ime_text_spans.push_back(ImeTextSpan(ImeTextSpan::Type::kComposition, 3, 12, - Color(255, 0, 0), - ImeTextSpanThickness::kThin, 0)); + ime_text_spans.push_back(ImeTextSpan( + ImeTextSpan::Type::kComposition, 3, 12, Color(255, 0, 0), + ImeTextSpanThickness::kThin, ImeTextSpanUnderlineStyle::kSolid, 0, 0)); Controller().SetCompositionFromExistingText(ime_text_spans, 3, 12); Controller().SetComposition(String("123hello789"), ime_text_spans, 11, 11); - EXPECT_EQ("abc1<b>2</b>3hello7<b>8</b>9", div->InnerHTMLAsString()); + EXPECT_EQ("abc1<b>2</b>3hello7<b>8</b>9", div->innerHTML()); Controller().FinishComposingText(InputMethodController::kKeepSelection); - EXPECT_EQ("abc1<b>2</b>3hello7<b>8</b>9", div->InnerHTMLAsString()); + EXPECT_EQ("abc1<b>2</b>3hello7<b>8</b>9", div->innerHTML()); } TEST_F(InputMethodControllerTest, CommitTextKeepingStyle) { @@ -380,25 +378,25 @@ TEST_F(InputMethodControllerTest, CommitTextKeepingStyle) { "sample"); Vector<ImeTextSpan> ime_text_spans; - ime_text_spans.push_back(ImeTextSpan(ImeTextSpan::Type::kComposition, 3, 12, - Color(255, 0, 0), - ImeTextSpanThickness::kThin, 0)); + ime_text_spans.push_back(ImeTextSpan( + ImeTextSpan::Type::kComposition, 3, 12, Color(255, 0, 0), + ImeTextSpanThickness::kThin, ImeTextSpanUnderlineStyle::kSolid, 0, 0)); Controller().SetCompositionFromExistingText(ime_text_spans, 3, 12); Controller().CommitText(String("123789"), ime_text_spans, 0); - EXPECT_EQ("abc1<b>2</b>37<b>8</b>9", div->InnerHTMLAsString()); + EXPECT_EQ("abc1<b>2</b>37<b>8</b>9", div->innerHTML()); } TEST_F(InputMethodControllerTest, InsertTextWithNewLine) { Element* div = InsertHTMLElement("<div id='sample' contenteditable></div>", "sample"); Vector<ImeTextSpan> ime_text_spans; - ime_text_spans.push_back(ImeTextSpan(ImeTextSpan::Type::kComposition, 0, 11, - Color(255, 0, 0), - ImeTextSpanThickness::kThin, 0)); + ime_text_spans.push_back(ImeTextSpan( + ImeTextSpan::Type::kComposition, 0, 11, Color(255, 0, 0), + ImeTextSpanThickness::kThin, ImeTextSpanUnderlineStyle::kSolid, 0, 0)); Controller().CommitText(String("hello\nworld"), ime_text_spans, 0); - EXPECT_EQ("hello<div>world</div>", div->InnerHTMLAsString()); + EXPECT_EQ("hello<div>world</div>", div->innerHTML()); } TEST_F(InputMethodControllerTest, InsertTextWithNewLineIncrementally) { @@ -408,10 +406,10 @@ TEST_F(InputMethodControllerTest, InsertTextWithNewLineIncrementally) { Vector<ImeTextSpan> ime_text_spans; Controller().CommitText("a", ime_text_spans, 0); Controller().SetComposition("bcd", ime_text_spans, 0, 2); - EXPECT_EQ("abcd", div->InnerHTMLAsString()); + EXPECT_EQ("abcd", div->innerHTML()); Controller().CommitText(String("bcd\nefgh\nijkl"), ime_text_spans, 0); - EXPECT_EQ("abcd<div>efgh</div><div>ijkl</div>", div->InnerHTMLAsString()); + EXPECT_EQ("abcd<div>efgh</div><div>ijkl</div>", div->innerHTML()); } TEST_F(InputMethodControllerTest, SelectionOnConfirmExistingText) { @@ -419,9 +417,9 @@ TEST_F(InputMethodControllerTest, SelectionOnConfirmExistingText) { "sample"); Vector<ImeTextSpan> ime_text_spans; - ime_text_spans.push_back(ImeTextSpan(ImeTextSpan::Type::kComposition, 0, 5, - Color(255, 0, 0), - ImeTextSpanThickness::kThin, 0)); + ime_text_spans.push_back(ImeTextSpan( + ImeTextSpan::Type::kComposition, 0, 5, Color(255, 0, 0), + ImeTextSpanThickness::kThin, ImeTextSpanUnderlineStyle::kSolid, 0, 0)); Controller().SetCompositionFromExistingText(ime_text_spans, 0, 5); Controller().FinishComposingText(InputMethodController::kKeepSelection); @@ -442,23 +440,23 @@ TEST_F(InputMethodControllerTest, DeleteBySettingEmptyComposition) { To<HTMLInputElement>(InsertHTMLElement("<input id='sample'>", "sample")); input->setValue("foo "); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Controller().SetEditableSelectionOffsets(PlainTextRange(4, 4)); EXPECT_EQ("foo ", input->value()); Controller().ExtendSelectionAndDelete(0, 0); EXPECT_EQ("foo ", input->value()); input->setValue("foo "); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Controller().SetEditableSelectionOffsets(PlainTextRange(4, 4)); EXPECT_EQ("foo ", input->value()); Controller().ExtendSelectionAndDelete(1, 0); EXPECT_EQ("foo", input->value()); Vector<ImeTextSpan> ime_text_spans; - ime_text_spans.push_back(ImeTextSpan(ImeTextSpan::Type::kComposition, 0, 3, - Color(255, 0, 0), - ImeTextSpanThickness::kThin, 0)); + ime_text_spans.push_back(ImeTextSpan( + ImeTextSpan::Type::kComposition, 0, 3, Color(255, 0, 0), + ImeTextSpanThickness::kThin, ImeTextSpanUnderlineStyle::kSolid, 0, 0)); Controller().SetCompositionFromExistingText(ime_text_spans, 0, 3); Controller().SetComposition(String(""), ime_text_spans, 0, 3); @@ -474,9 +472,9 @@ TEST_F(InputMethodControllerTest, "<div id='sample' contenteditable>\nhello world</div>", "sample"); Vector<ImeTextSpan> ime_text_spans; - ime_text_spans.push_back(ImeTextSpan(ImeTextSpan::Type::kComposition, 0, 5, - Color(255, 0, 0), - ImeTextSpanThickness::kThin, 0)); + ime_text_spans.push_back(ImeTextSpan( + ImeTextSpan::Type::kComposition, 0, 5, Color(255, 0, 0), + ImeTextSpanThickness::kThin, ImeTextSpanUnderlineStyle::kSolid, 0, 0)); Controller().SetCompositionFromExistingText(ime_text_spans, 0, 5); Range* range = GetCompositionRange(); @@ -493,9 +491,9 @@ TEST_F(InputMethodControllerTest, InsertHTMLElement("<div id='sample' contenteditable>test</div>", "sample"); Vector<ImeTextSpan> ime_text_spans; - ime_text_spans.push_back(ImeTextSpan(ImeTextSpan::Type::kComposition, 7, 8, - Color(255, 0, 0), - ImeTextSpanThickness::kThin, 0)); + ime_text_spans.push_back(ImeTextSpan( + ImeTextSpan::Type::kComposition, 7, 8, Color(255, 0, 0), + ImeTextSpanThickness::kThin, ImeTextSpanUnderlineStyle::kSolid, 0, 0)); Controller().SetCompositionFromExistingText(ime_text_spans, 7, 8); EXPECT_FALSE(GetCompositionRange()); @@ -506,9 +504,9 @@ TEST_F(InputMethodControllerTest, ConfirmPasswordComposition) { "<input id='sample' type='password' size='24'>", "sample")); Vector<ImeTextSpan> ime_text_spans; - ime_text_spans.push_back(ImeTextSpan(ImeTextSpan::Type::kComposition, 0, 5, - Color(255, 0, 0), - ImeTextSpanThickness::kThin, 0)); + ime_text_spans.push_back(ImeTextSpan( + ImeTextSpan::Type::kComposition, 0, 5, Color(255, 0, 0), + ImeTextSpanThickness::kThin, ImeTextSpanUnderlineStyle::kSolid, 0, 0)); Controller().SetComposition("foo", ime_text_spans, 0, 3); Controller().FinishComposingText(InputMethodController::kKeepSelection); @@ -520,25 +518,25 @@ TEST_F(InputMethodControllerTest, DeleteSurroundingTextWithEmptyText) { To<HTMLInputElement>(InsertHTMLElement("<input id='sample'>", "sample")); input->setValue(""); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); EXPECT_EQ("", input->value()); Controller().DeleteSurroundingText(0, 0); EXPECT_EQ("", input->value()); input->setValue(""); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); EXPECT_EQ("", input->value()); Controller().DeleteSurroundingText(1, 0); EXPECT_EQ("", input->value()); input->setValue(""); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); EXPECT_EQ("", input->value()); Controller().DeleteSurroundingText(0, 1); EXPECT_EQ("", input->value()); input->setValue(""); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); EXPECT_EQ("", input->value()); Controller().DeleteSurroundingText(1, 1); EXPECT_EQ("", input->value()); @@ -549,35 +547,35 @@ TEST_F(InputMethodControllerTest, DeleteSurroundingTextWithRangeSelection) { To<HTMLInputElement>(InsertHTMLElement("<input id='sample'>", "sample")); input->setValue("hello"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); EXPECT_EQ("hello", input->value()); Controller().SetEditableSelectionOffsets(PlainTextRange(1, 4)); Controller().DeleteSurroundingText(0, 0); EXPECT_EQ("hello", input->value()); input->setValue("hello"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); EXPECT_EQ("hello", input->value()); Controller().SetEditableSelectionOffsets(PlainTextRange(1, 4)); Controller().DeleteSurroundingText(1, 1); EXPECT_EQ("ell", input->value()); input->setValue("hello"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); EXPECT_EQ("hello", input->value()); Controller().SetEditableSelectionOffsets(PlainTextRange(1, 4)); Controller().DeleteSurroundingText(100, 0); EXPECT_EQ("ello", input->value()); input->setValue("hello"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); EXPECT_EQ("hello", input->value()); Controller().SetEditableSelectionOffsets(PlainTextRange(1, 4)); Controller().DeleteSurroundingText(0, 100); EXPECT_EQ("hell", input->value()); input->setValue("hello"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); EXPECT_EQ("hello", input->value()); Controller().SetEditableSelectionOffsets(PlainTextRange(1, 4)); Controller().DeleteSurroundingText(100, 100); @@ -589,63 +587,63 @@ TEST_F(InputMethodControllerTest, DeleteSurroundingTextWithCursorSelection) { To<HTMLInputElement>(InsertHTMLElement("<input id='sample'>", "sample")); input->setValue("hello"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); EXPECT_EQ("hello", input->value()); Controller().SetEditableSelectionOffsets(PlainTextRange(2, 2)); Controller().DeleteSurroundingText(1, 0); EXPECT_EQ("hllo", input->value()); input->setValue("hello"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); EXPECT_EQ("hello", input->value()); Controller().SetEditableSelectionOffsets(PlainTextRange(2, 2)); Controller().DeleteSurroundingText(0, 1); EXPECT_EQ("helo", input->value()); input->setValue("hello"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); EXPECT_EQ("hello", input->value()); Controller().SetEditableSelectionOffsets(PlainTextRange(2, 2)); Controller().DeleteSurroundingText(0, 0); EXPECT_EQ("hello", input->value()); input->setValue("hello"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); EXPECT_EQ("hello", input->value()); Controller().SetEditableSelectionOffsets(PlainTextRange(2, 2)); Controller().DeleteSurroundingText(1, 1); EXPECT_EQ("hlo", input->value()); input->setValue("hello"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); EXPECT_EQ("hello", input->value()); Controller().SetEditableSelectionOffsets(PlainTextRange(2, 2)); Controller().DeleteSurroundingText(100, 0); EXPECT_EQ("llo", input->value()); input->setValue("hello"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); EXPECT_EQ("hello", input->value()); Controller().SetEditableSelectionOffsets(PlainTextRange(2, 2)); Controller().DeleteSurroundingText(0, 100); EXPECT_EQ("he", input->value()); input->setValue("hello"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); EXPECT_EQ("hello", input->value()); Controller().SetEditableSelectionOffsets(PlainTextRange(2, 2)); Controller().DeleteSurroundingText(100, 100); EXPECT_EQ("", input->value()); input->setValue("h"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); EXPECT_EQ("h", input->value()); Controller().SetEditableSelectionOffsets(PlainTextRange(1, 1)); Controller().DeleteSurroundingText(1, 0); EXPECT_EQ("", input->value()); input->setValue("h"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); EXPECT_EQ("h", input->value()); Controller().SetEditableSelectionOffsets(PlainTextRange(0, 0)); Controller().DeleteSurroundingText(0, 1); @@ -659,7 +657,7 @@ TEST_F(InputMethodControllerTest, // U+2605 == "black star". It takes up 1 space. input->setValue(String::FromUTF8("foo\xE2\x98\x85")); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Controller().SetEditableSelectionOffsets(PlainTextRange(4, 4)); EXPECT_EQ("foo\xE2\x98\x85", input->value().Utf8()); Controller().DeleteSurroundingText(1, 0); @@ -667,23 +665,23 @@ TEST_F(InputMethodControllerTest, // U+1F3C6 == "trophy". It takes up 2 space. input->setValue(String::FromUTF8("foo\xF0\x9F\x8F\x86")); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Controller().SetEditableSelectionOffsets(PlainTextRange(5, 5)); EXPECT_EQ("foo\xF0\x9F\x8F\x86", input->value().Utf8()); Controller().DeleteSurroundingText(1, 0); - EXPECT_EQ("foo", input->value()); + EXPECT_EQ("foo\xED\xA0\xBC", input->value().Utf8()); // composed U+0E01 "ka kai" + U+0E49 "mai tho". It takes up 2 space. input->setValue(String::FromUTF8("foo\xE0\xB8\x81\xE0\xB9\x89")); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Controller().SetEditableSelectionOffsets(PlainTextRange(5, 5)); EXPECT_EQ("foo\xE0\xB8\x81\xE0\xB9\x89", input->value().Utf8()); Controller().DeleteSurroundingText(1, 0); - EXPECT_EQ("foo", input->value()); + EXPECT_EQ("foo\xE0\xB8\x81", input->value().Utf8()); // "trophy" + "trophy". input->setValue(String::FromUTF8("foo\xF0\x9F\x8F\x86\xF0\x9F\x8F\x86")); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Controller().SetEditableSelectionOffsets(PlainTextRange(7, 7)); EXPECT_EQ("foo\xF0\x9F\x8F\x86\xF0\x9F\x8F\x86", input->value().Utf8()); Controller().DeleteSurroundingText(2, 0); @@ -691,15 +689,15 @@ TEST_F(InputMethodControllerTest, // "trophy" + "trophy". input->setValue(String::FromUTF8("foo\xF0\x9F\x8F\x86\xF0\x9F\x8F\x86")); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Controller().SetEditableSelectionOffsets(PlainTextRange(7, 7)); EXPECT_EQ("foo\xF0\x9F\x8F\x86\xF0\x9F\x8F\x86", input->value().Utf8()); Controller().DeleteSurroundingText(3, 0); - EXPECT_EQ("foo", input->value()); + EXPECT_EQ("foo\xED\xA0\xBC", input->value().Utf8()); // "trophy" + "trophy". input->setValue(String::FromUTF8("foo\xF0\x9F\x8F\x86\xF0\x9F\x8F\x86")); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Controller().SetEditableSelectionOffsets(PlainTextRange(7, 7)); EXPECT_EQ("foo\xF0\x9F\x8F\x86\xF0\x9F\x8F\x86", input->value().Utf8()); Controller().DeleteSurroundingText(4, 0); @@ -707,7 +705,7 @@ TEST_F(InputMethodControllerTest, // "trophy" + "trophy". input->setValue(String::FromUTF8("foo\xF0\x9F\x8F\x86\xF0\x9F\x8F\x86")); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Controller().SetEditableSelectionOffsets(PlainTextRange(7, 7)); EXPECT_EQ("foo\xF0\x9F\x8F\x86\xF0\x9F\x8F\x86", input->value().Utf8()); Controller().DeleteSurroundingText(5, 0); @@ -721,7 +719,7 @@ TEST_F(InputMethodControllerTest, // U+2605 == "black star". It takes up 1 space. input->setValue(String::FromUTF8("\xE2\x98\x85 foo")); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Controller().SetEditableSelectionOffsets(PlainTextRange(0, 0)); EXPECT_EQ("\xE2\x98\x85 foo", input->value().Utf8()); Controller().DeleteSurroundingText(0, 1); @@ -729,23 +727,23 @@ TEST_F(InputMethodControllerTest, // U+1F3C6 == "trophy". It takes up 2 space. input->setValue(String::FromUTF8("\xF0\x9F\x8F\x86 foo")); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Controller().SetEditableSelectionOffsets(PlainTextRange(0, 0)); EXPECT_EQ("\xF0\x9F\x8F\x86 foo", input->value().Utf8()); Controller().DeleteSurroundingText(0, 1); - EXPECT_EQ(" foo", input->value()); + EXPECT_EQ("\xED\xBF\x86 foo", input->value().Utf8()); // composed U+0E01 "ka kai" + U+0E49 "mai tho". It takes up 2 space. input->setValue(String::FromUTF8("\xE0\xB8\x81\xE0\xB9\x89 foo")); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Controller().SetEditableSelectionOffsets(PlainTextRange(0, 0)); EXPECT_EQ("\xE0\xB8\x81\xE0\xB9\x89 foo", input->value().Utf8()); Controller().DeleteSurroundingText(0, 1); - EXPECT_EQ(" foo", input->value()); + EXPECT_EQ("\xE0\xB9\x89 foo", input->value().Utf8()); // "trophy" + "trophy". input->setValue(String::FromUTF8("\xF0\x9F\x8F\x86\xF0\x9F\x8F\x86 foo")); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Controller().SetEditableSelectionOffsets(PlainTextRange(0, 0)); EXPECT_EQ("\xF0\x9F\x8F\x86\xF0\x9F\x8F\x86 foo", input->value().Utf8()); Controller().DeleteSurroundingText(0, 2); @@ -753,15 +751,15 @@ TEST_F(InputMethodControllerTest, // "trophy" + "trophy". input->setValue(String::FromUTF8("\xF0\x9F\x8F\x86\xF0\x9F\x8F\x86 foo")); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Controller().SetEditableSelectionOffsets(PlainTextRange(0, 0)); EXPECT_EQ("\xF0\x9F\x8F\x86\xF0\x9F\x8F\x86 foo", input->value().Utf8()); Controller().DeleteSurroundingText(0, 3); - EXPECT_EQ(" foo", input->value()); + EXPECT_EQ("\xED\xBF\x86 foo", input->value().Utf8()); // "trophy" + "trophy". input->setValue(String::FromUTF8("\xF0\x9F\x8F\x86\xF0\x9F\x8F\x86 foo")); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Controller().SetEditableSelectionOffsets(PlainTextRange(0, 0)); EXPECT_EQ("\xF0\x9F\x8F\x86\xF0\x9F\x8F\x86 foo", input->value().Utf8()); Controller().DeleteSurroundingText(0, 4); @@ -769,7 +767,7 @@ TEST_F(InputMethodControllerTest, // "trophy" + "trophy". input->setValue(String::FromUTF8("\xF0\x9F\x8F\x86\xF0\x9F\x8F\x86 foo")); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Controller().SetEditableSelectionOffsets(PlainTextRange(0, 0)); EXPECT_EQ("\xF0\x9F\x8F\x86\xF0\x9F\x8F\x86 foo", input->value().Utf8()); Controller().DeleteSurroundingText(0, 5); @@ -783,11 +781,29 @@ TEST_F(InputMethodControllerTest, // "trophy" + "trophy". input->setValue(String::FromUTF8("\xF0\x9F\x8F\x86\xF0\x9F\x8F\x86")); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Controller().SetEditableSelectionOffsets(PlainTextRange(2, 2)); EXPECT_EQ("\xF0\x9F\x8F\x86\xF0\x9F\x8F\x86", input->value().Utf8()); Controller().DeleteSurroundingText(1, 1); - EXPECT_EQ("", input->value()); + // Deleted second half of the first trophy and the first half of the second + // trophy, so we ended up with a complete trophy. + EXPECT_EQ("\xF0\x9F\x8F\x86", input->value().Utf8()); +} + +// This test comes from http://crbug.com/1024738. It is basically the same to +// composed text (U+0E01 "ka kai" + U+0E49 "mai tho"), but easier to understand. +TEST_F(InputMethodControllerTest, DeleteSurroundingTextForComposedCharacter) { + auto* input = + To<HTMLInputElement>(InsertHTMLElement("<input id='sample'>", "sample")); + // pÌ‚pÌ‚ (U+0070 U+0302 U+0070 U+0302) + input->setValue(String::FromUTF8("\x70\xCC\x82\x70\xCC\x82")); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); + Controller().SetEditableSelectionOffsets(PlainTextRange(4, 4)); + EXPECT_EQ("\x70\xCC\x82\x70\xCC\x82", input->value().Utf8()); + Controller().DeleteSurroundingText(1, 0); + EXPECT_EQ("\x70\xCC\x82\x70", input->value().Utf8()); + Controller().DeleteSurroundingText(1, 0); + EXPECT_EQ("\x70\xCC\x82", input->value().Utf8()); } TEST_F(InputMethodControllerTest, DeleteSurroundingTextForMultipleNodes) { @@ -833,7 +849,7 @@ TEST_F(InputMethodControllerTest, // [1,2,2]. input->setValue(String::FromUTF8( "a\xE2\x98\x85 \xF0\x9F\x8F\x86 \xE0\xB8\x81\xE0\xB9\x89")); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); // The cursor is at the end of the text. Controller().SetEditableSelectionOffsets(PlainTextRange(8, 8)); @@ -845,15 +861,14 @@ TEST_F(InputMethodControllerTest, // 'a' + "black star" + SPACE + "trophy" + SPACE + composed text input->setValue(String::FromUTF8( "a\xE2\x98\x85 \xF0\x9F\x8F\x86 \xE0\xB8\x81\xE0\xB9\x89")); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); // The cursor is at the end of the text. Controller().SetEditableSelectionOffsets(PlainTextRange(8, 8)); - // TODO(yabinh): We should only delete 1 code point instead of the entire - // grapheme cluster (2 code points). The root cause is that we adjust the - // selection by grapheme cluster in deleteSurroundingText(). + // We should only delete 1 code point. Controller().DeleteSurroundingTextInCodePoints(1, 0); - EXPECT_EQ("a\xE2\x98\x85 \xF0\x9F\x8F\x86 ", input->value().Utf8()); + EXPECT_EQ("a\xE2\x98\x85 \xF0\x9F\x8F\x86 \xE0\xB8\x81", + input->value().Utf8()); } TEST_F(InputMethodControllerTest, @@ -864,15 +879,15 @@ TEST_F(InputMethodControllerTest, // 'a' + "black star" + SPACE + "trophy" + SPACE + composed text input->setValue(String::FromUTF8( "a\xE2\x98\x85 \xF0\x9F\x8F\x86 \xE0\xB8\x81\xE0\xB9\x89")); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Controller().SetEditableSelectionOffsets(PlainTextRange(0, 0)); Controller().DeleteSurroundingTextInCodePoints(0, 5); EXPECT_EQ("\xE0\xB8\x81\xE0\xB9\x89", input->value().Utf8()); Controller().DeleteSurroundingTextInCodePoints(0, 1); - // TODO(yabinh): Same here. We should only delete 1 code point. - EXPECT_EQ("", input->value()); + // We should only delete 1 code point. + EXPECT_EQ("\xE0\xB9\x89", input->value().Utf8()); } TEST_F(InputMethodControllerTest, @@ -883,7 +898,7 @@ TEST_F(InputMethodControllerTest, // 'a' + "black star" + SPACE + "trophy" + SPACE + composed text input->setValue(String::FromUTF8( "a\xE2\x98\x85 \xF0\x9F\x8F\x86 \xE0\xB8\x81\xE0\xB9\x89")); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Controller().SetEditableSelectionOffsets(PlainTextRange(3, 3)); Controller().DeleteSurroundingTextInCodePoints(2, 2); EXPECT_EQ("a\xE0\xB8\x81\xE0\xB9\x89", input->value().Utf8()); @@ -913,7 +928,7 @@ TEST_F(InputMethodControllerTest, const String& text = String(kUText); input->setValue(text); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); // The invalid high surrogate is encoded as '\xED\xA0\xBC', and invalid low // surrogate is encoded as '\xED\xBF\x86'. EXPECT_EQ("a\xED\xA0\xBC\xE2\x98\x85\xED\xBF\x86 ", input->value().Utf8()); @@ -940,16 +955,16 @@ TEST_F(InputMethodControllerTest, SetCompositionForInputWithNewCaretPositions) { To<HTMLInputElement>(InsertHTMLElement("<input id='sample'>", "sample")); input->setValue("hello"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Controller().SetEditableSelectionOffsets(PlainTextRange(2, 2)); EXPECT_EQ("hello", input->value()); EXPECT_EQ(2u, Controller().GetSelectionOffsets().Start()); EXPECT_EQ(2u, Controller().GetSelectionOffsets().End()); Vector<ImeTextSpan> ime_text_spans; - ime_text_spans.push_back(ImeTextSpan(ImeTextSpan::Type::kComposition, 0, 2, - Color(255, 0, 0), - ImeTextSpanThickness::kThin, 0)); + ime_text_spans.push_back(ImeTextSpan( + ImeTextSpan::Type::kComposition, 0, 2, Color(255, 0, 0), + ImeTextSpanThickness::kThin, ImeTextSpanUnderlineStyle::kSolid, 0, 0)); // The caret exceeds left boundary. // "*heABllo", where * stands for caret. @@ -1013,9 +1028,9 @@ TEST_F(InputMethodControllerTest, EXPECT_EQ(17u, Controller().GetSelectionOffsets().End()); Vector<ImeTextSpan> ime_text_spans; - ime_text_spans.push_back(ImeTextSpan(ImeTextSpan::Type::kComposition, 0, 2, - Color(255, 0, 0), - ImeTextSpanThickness::kThin, 0)); + ime_text_spans.push_back(ImeTextSpan( + ImeTextSpan::Type::kComposition, 0, 2, Color(255, 0, 0), + ImeTextSpanThickness::kThin, ImeTextSpanUnderlineStyle::kSolid, 0, 0)); // The caret exceeds left boundary. // "*hello\nworld\n\n01234AB56789", where * stands for caret. @@ -1105,13 +1120,13 @@ TEST_F(InputMethodControllerTest, SetCompositionWithEmptyText) { EXPECT_EQ(2u, Controller().GetSelectionOffsets().End()); Vector<ImeTextSpan> ime_text_spans0; - ime_text_spans0.push_back(ImeTextSpan(ImeTextSpan::Type::kComposition, 0, 0, - Color(255, 0, 0), - ImeTextSpanThickness::kThin, 0)); + ime_text_spans0.push_back(ImeTextSpan( + ImeTextSpan::Type::kComposition, 0, 0, Color(255, 0, 0), + ImeTextSpanThickness::kThin, ImeTextSpanUnderlineStyle::kSolid, 0, 0)); Vector<ImeTextSpan> ime_text_spans2; - ime_text_spans2.push_back(ImeTextSpan(ImeTextSpan::Type::kComposition, 0, 2, - Color(255, 0, 0), - ImeTextSpanThickness::kThin, 0)); + ime_text_spans2.push_back(ImeTextSpan( + ImeTextSpan::Type::kComposition, 0, 2, Color(255, 0, 0), + ImeTextSpanThickness::kThin, ImeTextSpanUnderlineStyle::kSolid, 0, 0)); Controller().SetComposition("AB", ime_text_spans2, 2, 2); // With previous composition. @@ -1132,9 +1147,9 @@ TEST_F(InputMethodControllerTest, InsertLineBreakWhileComposingText) { InsertHTMLElement("<div id='sample' contenteditable></div>", "sample"); Vector<ImeTextSpan> ime_text_spans; - ime_text_spans.push_back(ImeTextSpan(ImeTextSpan::Type::kComposition, 0, 5, - Color(255, 0, 0), - ImeTextSpanThickness::kThin, 0)); + ime_text_spans.push_back(ImeTextSpan( + ImeTextSpan::Type::kComposition, 0, 5, Color(255, 0, 0), + ImeTextSpanThickness::kThin, ImeTextSpanUnderlineStyle::kSolid, 0, 0)); Controller().SetComposition("hello", ime_text_spans, 5, 5); EXPECT_EQ("hello", div->innerText()); EXPECT_EQ(5u, Controller().GetSelectionOffsets().Start()); @@ -1151,9 +1166,9 @@ TEST_F(InputMethodControllerTest, InsertLineBreakAfterConfirmingText) { InsertHTMLElement("<div id='sample' contenteditable></div>", "sample"); Vector<ImeTextSpan> ime_text_spans; - ime_text_spans.push_back(ImeTextSpan(ImeTextSpan::Type::kComposition, 0, 2, - Color(255, 0, 0), - ImeTextSpanThickness::kThin, 0)); + ime_text_spans.push_back(ImeTextSpan( + ImeTextSpan::Type::kComposition, 0, 2, Color(255, 0, 0), + ImeTextSpanThickness::kThin, ImeTextSpanUnderlineStyle::kSolid, 0, 0)); Controller().CommitText("hello", ime_text_spans, 0); EXPECT_EQ("hello", div->innerText()); @@ -1172,7 +1187,7 @@ TEST_F(InputMethodControllerTest, CompositionInputEventIsComposing) { Element* editable = InsertHTMLElement("<div id='sample' contenteditable></div>", "sample"); Element* script = GetDocument().CreateRawElement(html_names::kScriptTag); - script->SetInnerHTMLFromString( + script->setInnerHTML( "document.getElementById('sample').addEventListener('beforeinput', " " event => document.title = " " `beforeinput.isComposing:${event.isComposing};`);" @@ -1184,9 +1199,9 @@ TEST_F(InputMethodControllerTest, CompositionInputEventIsComposing) { // Simulate composition in the |contentEditable|. Vector<ImeTextSpan> ime_text_spans; - ime_text_spans.push_back(ImeTextSpan(ImeTextSpan::Type::kComposition, 0, 5, - Color(255, 0, 0), - ImeTextSpanThickness::kThin, 0)); + ime_text_spans.push_back(ImeTextSpan( + ImeTextSpan::Type::kComposition, 0, 5, Color(255, 0, 0), + ImeTextSpanThickness::kThin, ImeTextSpanUnderlineStyle::kSolid, 0, 0)); editable->focus(); GetDocument().setTitle(g_empty_string); @@ -1206,9 +1221,9 @@ TEST_F(InputMethodControllerTest, CompositionInputEventForReplace) { // Simulate composition in the |contentEditable|. Vector<ImeTextSpan> ime_text_spans; - ime_text_spans.push_back(ImeTextSpan(ImeTextSpan::Type::kComposition, 0, 5, - Color(255, 0, 0), - ImeTextSpanThickness::kThin, 0)); + ime_text_spans.push_back(ImeTextSpan( + ImeTextSpan::Type::kComposition, 0, 5, Color(255, 0, 0), + ImeTextSpanThickness::kThin, ImeTextSpanUnderlineStyle::kSolid, 0, 0)); GetDocument().setTitle(g_empty_string); Controller().SetComposition("hell", ime_text_spans, 4, 4); @@ -1225,9 +1240,9 @@ TEST_F(InputMethodControllerTest, CompositionInputEventForConfirm) { // Simulate composition in the |contentEditable|. Vector<ImeTextSpan> ime_text_spans; - ime_text_spans.push_back(ImeTextSpan(ImeTextSpan::Type::kComposition, 0, 5, - Color(255, 0, 0), - ImeTextSpanThickness::kThin, 0)); + ime_text_spans.push_back(ImeTextSpan( + ImeTextSpan::Type::kComposition, 0, 5, Color(255, 0, 0), + ImeTextSpanThickness::kThin, ImeTextSpanUnderlineStyle::kSolid, 0, 0)); GetDocument().setTitle(g_empty_string); Controller().SetComposition("hello", ime_text_spans, 5, 5); @@ -1244,9 +1259,9 @@ TEST_F(InputMethodControllerTest, CompositionInputEventForDelete) { // Simulate composition in the |contentEditable|. Vector<ImeTextSpan> ime_text_spans; - ime_text_spans.push_back(ImeTextSpan(ImeTextSpan::Type::kComposition, 0, 5, - Color(255, 0, 0), - ImeTextSpanThickness::kThin, 0)); + ime_text_spans.push_back(ImeTextSpan( + ImeTextSpan::Type::kComposition, 0, 5, Color(255, 0, 0), + ImeTextSpanThickness::kThin, ImeTextSpanUnderlineStyle::kSolid, 0, 0)); GetDocument().setTitle(g_empty_string); Controller().SetComposition("hello", ime_text_spans, 5, 5); @@ -1264,13 +1279,13 @@ TEST_F(InputMethodControllerTest, CompositionInputEventForInsert) { // Simulate composition in the |contentEditable|. Vector<ImeTextSpan> ime_text_spans; - ime_text_spans.push_back(ImeTextSpan(ImeTextSpan::Type::kComposition, 0, 5, - Color(255, 0, 0), - ImeTextSpanThickness::kThin, 0)); + ime_text_spans.push_back(ImeTextSpan( + ImeTextSpan::Type::kComposition, 0, 5, Color(255, 0, 0), + ImeTextSpanThickness::kThin, ImeTextSpanUnderlineStyle::kSolid, 0, 0)); // Insert new text without previous composition. GetDocument().setTitle(g_empty_string); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Controller().CommitText("hello", ime_text_spans, 0); EXPECT_EQ("beforeinput.data:hello;input.data:hello;", GetDocument().title()); @@ -1280,7 +1295,7 @@ TEST_F(InputMethodControllerTest, CompositionInputEventForInsert) { // Insert new text with previous composition. GetDocument().setTitle(g_empty_string); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Controller().CommitText("hello", ime_text_spans, 1); EXPECT_EQ( "beforeinput.data:hello;input.data:hello;compositionend.data:hello;", @@ -1292,13 +1307,13 @@ TEST_F(InputMethodControllerTest, CompositionInputEventForInsertEmptyText) { // Simulate composition in the |contentEditable|. Vector<ImeTextSpan> ime_text_spans; - ime_text_spans.push_back(ImeTextSpan(ImeTextSpan::Type::kComposition, 0, 5, - Color(255, 0, 0), - ImeTextSpanThickness::kThin, 0)); + ime_text_spans.push_back(ImeTextSpan( + ImeTextSpan::Type::kComposition, 0, 5, Color(255, 0, 0), + ImeTextSpanThickness::kThin, ImeTextSpanUnderlineStyle::kSolid, 0, 0)); // Insert empty text without previous composition. GetDocument().setTitle(g_empty_string); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Controller().CommitText("", ime_text_spans, 0); EXPECT_EQ("", GetDocument().title().Utf8()); @@ -1308,7 +1323,7 @@ TEST_F(InputMethodControllerTest, CompositionInputEventForInsertEmptyText) { // Insert empty text with previous composition. GetDocument().setTitle(g_empty_string); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Controller().CommitText("", ime_text_spans, 1); EXPECT_EQ("beforeinput.data:;input.data:null;compositionend.data:;", GetDocument().title()); @@ -1319,19 +1334,19 @@ TEST_F(InputMethodControllerTest, CompositionEndEventWithNoSelection) { // Simulate composition in the |contentEditable|. Vector<ImeTextSpan> ime_text_spans; - ime_text_spans.push_back(ImeTextSpan(ImeTextSpan::Type::kComposition, 0, 5, - Color(255, 0, 0), - ImeTextSpanThickness::kThin, 0)); + ime_text_spans.push_back(ImeTextSpan( + ImeTextSpan::Type::kComposition, 0, 5, Color(255, 0, 0), + ImeTextSpanThickness::kThin, ImeTextSpanUnderlineStyle::kSolid, 0, 0)); Controller().SetComposition("hello", ime_text_spans, 1, 1); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); EXPECT_EQ(1u, Controller().GetSelectionOffsets().Start()); EXPECT_EQ(1u, Controller().GetSelectionOffsets().End()); // Confirm the ongoing composition. Note that it moves the caret to the end of // text [5,5] before firing 'compositonend' event. Controller().FinishComposingText(InputMethodController::kDoNotKeepSelection); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); EXPECT_TRUE(Controller().GetSelectionOffsets().IsNull()); } @@ -1346,7 +1361,7 @@ TEST_F(InputMethodControllerTest, FinishCompositionRemovedRange) { EXPECT_EQ(kWebTextInputTypeText, Controller().TextInputType()); // Remove element 'a'. - input_a->SetOuterHTMLFromString("", ASSERT_NO_EXCEPTION); + input_a->setOuterHTML("", ASSERT_NO_EXCEPTION); EXPECT_EQ(kWebTextInputTypeNone, Controller().TextInputType()); GetDocument().getElementById("b")->focus(); @@ -1374,9 +1389,9 @@ TEST_F(InputMethodControllerTest, SetCompositionPlainTextWithIme_Text_Span) { InsertHTMLElement("<div id='sample' contenteditable></div>", "sample"); Vector<ImeTextSpan> ime_text_spans; - ime_text_spans.push_back(ImeTextSpan(ImeTextSpan::Type::kComposition, 0, 1, - Color(255, 0, 0), - ImeTextSpanThickness::kThin, 0)); + ime_text_spans.push_back(ImeTextSpan( + ImeTextSpan::Type::kComposition, 0, 1, Color(255, 0, 0), + ImeTextSpanThickness::kThin, ImeTextSpanUnderlineStyle::kSolid, 0, 0)); Controller().SetComposition(" ", ime_text_spans, 1, 1); @@ -1394,9 +1409,9 @@ TEST_F(InputMethodControllerTest, CommitPlainTextWithIme_Text_SpanInsert) { Controller().SetEditableSelectionOffsets(PlainTextRange(8, 8)); - ime_text_spans.push_back(ImeTextSpan(ImeTextSpan::Type::kComposition, 1, 11, - Color(255, 0, 0), - ImeTextSpanThickness::kThin, 0)); + ime_text_spans.push_back(ImeTextSpan( + ImeTextSpan::Type::kComposition, 1, 11, Color(255, 0, 0), + ImeTextSpanThickness::kThin, ImeTextSpanUnderlineStyle::kSolid, 0, 0)); Controller().CommitText(String("ime_text_spand"), ime_text_spans, 0); @@ -1414,9 +1429,9 @@ TEST_F(InputMethodControllerTest, CommitPlainTextWithIme_Text_SpanReplace) { Controller().SetCompositionFromExistingText(ime_text_spans, 8, 12); - ime_text_spans.push_back(ImeTextSpan(ImeTextSpan::Type::kComposition, 1, 11, - Color(255, 0, 0), - ImeTextSpanThickness::kThin, 0)); + ime_text_spans.push_back(ImeTextSpan( + ImeTextSpan::Type::kComposition, 1, 11, Color(255, 0, 0), + ImeTextSpanThickness::kThin, ImeTextSpanUnderlineStyle::kSolid, 0, 0)); Controller().CommitText(String("string"), ime_text_spans, 0); @@ -1437,9 +1452,9 @@ TEST_F(InputMethodControllerTest, ImeTextSpanAppearsCorrectlyAfterNewline) { Controller().SetCompositionFromExistingText(ime_text_spans, 8, 8); - ime_text_spans.push_back(ImeTextSpan(ImeTextSpan::Type::kComposition, 0, 5, - Color(255, 0, 0), - ImeTextSpanThickness::kThin, 0)); + ime_text_spans.push_back(ImeTextSpan( + ImeTextSpan::Type::kComposition, 0, 5, Color(255, 0, 0), + ImeTextSpanThickness::kThin, ImeTextSpanUnderlineStyle::kSolid, 0, 0)); Controller().SetComposition(String("world"), ime_text_spans, 0, 0); ASSERT_EQ(1u, GetDocument().Markers().Markers().size()); @@ -1473,9 +1488,9 @@ TEST_F(InputMethodControllerTest, SelectionWhenFocusChangeFinishesComposition) { // Simulate composition in the |contentEditable|. Vector<ImeTextSpan> ime_text_spans; - ime_text_spans.push_back(ImeTextSpan(ImeTextSpan::Type::kComposition, 0, 5, - Color(255, 0, 0), - ImeTextSpanThickness::kThin, 0)); + ime_text_spans.push_back(ImeTextSpan( + ImeTextSpan::Type::kComposition, 0, 5, Color(255, 0, 0), + ImeTextSpanThickness::kThin, ImeTextSpanUnderlineStyle::kSolid, 0, 0)); Controller().SetComposition("foo", ime_text_spans, 3, 3); EXPECT_TRUE(Controller().HasComposition()); @@ -1516,13 +1531,13 @@ TEST_F(InputMethodControllerTest, SetEmptyCompositionShouldNotMoveCaret) { To<HTMLTextAreaElement>(InsertHTMLElement("<textarea id='txt'>", "txt")); textarea->setValue("abc\n"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Controller().SetEditableSelectionOffsets(PlainTextRange(4, 4)); Vector<ImeTextSpan> ime_text_spans; - ime_text_spans.push_back(ImeTextSpan(ImeTextSpan::Type::kComposition, 0, 3, - Color(255, 0, 0), - ImeTextSpanThickness::kThin, 0)); + ime_text_spans.push_back(ImeTextSpan( + ImeTextSpan::Type::kComposition, 0, 3, Color(255, 0, 0), + ImeTextSpanThickness::kThin, ImeTextSpanUnderlineStyle::kSolid, 0, 0)); Controller().SetComposition(String("def"), ime_text_spans, 0, 3); Controller().SetComposition(String(""), ime_text_spans, 0, 3); Controller().CommitText(String("def"), ime_text_spans, 0); @@ -1541,14 +1556,14 @@ TEST_F(InputMethodControllerTest, WhitespaceFixup) { // The space at the beginning of the string should have been converted to an // nbsp - EXPECT_EQ(" text blah", div->InnerHTMLAsString()); + EXPECT_EQ(" text blah", div->innerHTML()); // Delete "blah" Controller().SetCompositionFromExistingText(empty_ime_text_spans, 6, 10); Controller().CommitText(String(""), empty_ime_text_spans, 0); // The space at the end of the string should have been converted to an nbsp - EXPECT_EQ(" text ", div->InnerHTMLAsString()); + EXPECT_EQ(" text ", div->innerHTML()); } TEST_F(InputMethodControllerTest, CommitEmptyTextDeletesSelection) { @@ -1556,7 +1571,7 @@ TEST_F(InputMethodControllerTest, CommitEmptyTextDeletesSelection) { To<HTMLInputElement>(InsertHTMLElement("<input id='sample'>", "sample")); input->setValue("Abc Def Ghi"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Vector<ImeTextSpan> empty_ime_text_spans; Controller().SetEditableSelectionOffsets(PlainTextRange(4, 8)); Controller().CommitText(String(""), empty_ime_text_spans, 0); @@ -1585,7 +1600,8 @@ TEST_F(InputMethodControllerTest, // persist across editing operations) EphemeralRange marker_range = PlainTextRange(8, 12).CreateRange(*div); GetDocument().Markers().AddActiveSuggestionMarker( - marker_range, Color::kBlack, ImeTextSpanThickness::kThin, Color::kBlack); + marker_range, Color::kBlack, ImeTextSpanThickness::kThin, + ImeTextSpanUnderlineStyle::kSolid, Color::kBlack, Color::kBlack); // Delete "Initial" Vector<ImeTextSpan> empty_ime_text_spans; Controller().SetCompositionFromExistingText(empty_ime_text_spans, 0, 7); @@ -1613,7 +1629,8 @@ TEST_F(InputMethodControllerTest, // persist across editing operations) EphemeralRange marker_range = PlainTextRange(7, 12).CreateRange(*div); GetDocument().Markers().AddActiveSuggestionMarker( - marker_range, Color::kBlack, ImeTextSpanThickness::kThin, Color::kBlack); + marker_range, Color::kBlack, ImeTextSpanThickness::kThin, + ImeTextSpanUnderlineStyle::kSolid, Color::kBlack, Color::kBlack); // Delete "Initial" Vector<ImeTextSpan> empty_ime_text_spans; Controller().SetCompositionFromExistingText(empty_ime_text_spans, 0, 7); @@ -1640,7 +1657,8 @@ TEST_F(InputMethodControllerTest, // persist across editing operations) EphemeralRange marker_range = PlainTextRange(8, 13).CreateRange(*div); GetDocument().Markers().AddActiveSuggestionMarker( - marker_range, Color::kBlack, ImeTextSpanThickness::kThin, Color::kBlack); + marker_range, Color::kBlack, ImeTextSpanThickness::kThin, + ImeTextSpanUnderlineStyle::kSolid, Color::kBlack, Color::kBlack); // Delete "Initial" Vector<ImeTextSpan> empty_ime_text_spans; Controller().SetCompositionFromExistingText(empty_ime_text_spans, 0, 7); @@ -1668,7 +1686,8 @@ TEST_F( // persist across editing operations) EphemeralRange marker_range = PlainTextRange(7, 13).CreateRange(*div); GetDocument().Markers().AddActiveSuggestionMarker( - marker_range, Color::kBlack, ImeTextSpanThickness::kThin, Color::kBlack); + marker_range, Color::kBlack, ImeTextSpanThickness::kThin, + ImeTextSpanUnderlineStyle::kSolid, Color::kBlack, Color::kBlack); // Delete "Initial" Vector<ImeTextSpan> empty_ime_text_spans; @@ -1713,7 +1732,8 @@ TEST_F(InputMethodControllerTest, // Add marker under "Initial text" EphemeralRange marker_range = PlainTextRange(0, 12).CreateRange(*div); GetDocument().Markers().AddActiveSuggestionMarker( - marker_range, Color::kBlack, ImeTextSpanThickness::kThin, Color::kBlack); + marker_range, Color::kBlack, ImeTextSpanThickness::kThin, + ImeTextSpanUnderlineStyle::kSolid, Color::kBlack, Color::kBlack); // Replace "Initial" with "Original" Vector<ImeTextSpan> empty_ime_text_spans; @@ -1756,7 +1776,8 @@ TEST_F(InputMethodControllerTest, // Add marker under "initial text" EphemeralRange marker_range = PlainTextRange(13, 25).CreateRange(*div); GetDocument().Markers().AddActiveSuggestionMarker( - marker_range, Color::kBlack, ImeTextSpanThickness::kThin, Color::kBlack); + marker_range, Color::kBlack, ImeTextSpanThickness::kThin, + ImeTextSpanUnderlineStyle::kSolid, Color::kBlack, Color::kBlack); // Replace "some initial" with "boring" Vector<ImeTextSpan> empty_ime_text_spans; @@ -1794,7 +1815,8 @@ TEST_F(InputMethodControllerTest, ContentIndependentMarker_ReplaceEndOfMarker) { // Add marker under "Initial text" EphemeralRange marker_range = PlainTextRange(0, 12).CreateRange(*div); GetDocument().Markers().AddActiveSuggestionMarker( - marker_range, Color::kBlack, ImeTextSpanThickness::kThin, Color::kBlack); + marker_range, Color::kBlack, ImeTextSpanThickness::kThin, + ImeTextSpanUnderlineStyle::kSolid, Color::kBlack, Color::kBlack); // Replace "text" with "string" Vector<ImeTextSpan> empty_ime_text_spans; @@ -1824,7 +1846,7 @@ TEST_F(InputMethodControllerTest, Controller().SetCompositionFromExistingText(empty_ime_text_spans, 13, 25); Controller().CommitText(String("content"), empty_ime_text_spans, 0); - EXPECT_EQ("This is some content", div->InnerHTMLAsString()); + EXPECT_EQ("This is some content", div->innerHTML()); // Verify marker was removed EXPECT_EQ(0u, GetDocument().Markers().Markers().size()); @@ -1839,14 +1861,15 @@ TEST_F(InputMethodControllerTest, // Add marker under "some initial" EphemeralRange marker_range = PlainTextRange(8, 20).CreateRange(*div); GetDocument().Markers().AddActiveSuggestionMarker( - marker_range, Color::kBlack, ImeTextSpanThickness::kThin, Color::kBlack); + marker_range, Color::kBlack, ImeTextSpanThickness::kThin, + ImeTextSpanUnderlineStyle::kSolid, Color::kBlack, Color::kBlack); // Replace "initial text" with "content" Vector<ImeTextSpan> empty_ime_text_spans; Controller().SetCompositionFromExistingText(empty_ime_text_spans, 13, 25); Controller().CommitText(String("content"), empty_ime_text_spans, 0); - EXPECT_EQ("This is some content", div->InnerHTMLAsString()); + EXPECT_EQ("This is some content", div->innerHTML()); // Verify marker is under "some " EXPECT_EQ(1u, GetDocument().Markers().Markers().size()); @@ -1880,7 +1903,8 @@ TEST_F(InputMethodControllerTest, // Add marker under "text" EphemeralRange marker_range = PlainTextRange(8, 12).CreateRange(*div); GetDocument().Markers().AddActiveSuggestionMarker( - marker_range, Color::kBlack, ImeTextSpanThickness::kThin, Color::kBlack); + marker_range, Color::kBlack, ImeTextSpanThickness::kThin, + ImeTextSpanUnderlineStyle::kSolid, Color::kBlack, Color::kBlack); // Replace "text" with "string" Vector<ImeTextSpan> empty_ime_text_spans; @@ -1923,7 +1947,8 @@ TEST_F(InputMethodControllerTest, // Add marker under "Initial" EphemeralRange marker_range = PlainTextRange(0, 7).CreateRange(*div); GetDocument().Markers().AddActiveSuggestionMarker( - marker_range, Color::kBlack, ImeTextSpanThickness::kThin, Color::kBlack); + marker_range, Color::kBlack, ImeTextSpanThickness::kThin, + ImeTextSpanUnderlineStyle::kSolid, Color::kBlack, Color::kBlack); EXPECT_EQ(1u, GetDocument().Markers().Markers().size()); @@ -1965,7 +1990,8 @@ TEST_F(InputMethodControllerTest, // Add marker under "text" EphemeralRange marker_range = PlainTextRange(8, 12).CreateRange(*div); GetDocument().Markers().AddActiveSuggestionMarker( - marker_range, Color::kBlack, ImeTextSpanThickness::kThin, Color::kBlack); + marker_range, Color::kBlack, ImeTextSpanThickness::kThin, + ImeTextSpanUnderlineStyle::kSolid, Color::kBlack, Color::kBlack); EXPECT_EQ(1u, GetDocument().Markers().Markers().size()); @@ -2027,23 +2053,28 @@ TEST_F(InputMethodControllerTest, ContentIndependentMarker_Deletions) { EphemeralRange marker_range = PlainTextRange(0, 5).CreateRange(*div); GetDocument().Markers().AddActiveSuggestionMarker( - marker_range, Color::kBlack, ImeTextSpanThickness::kThin, Color::kBlack); + marker_range, Color::kBlack, ImeTextSpanThickness::kThin, + ImeTextSpanUnderlineStyle::kSolid, Color::kBlack, Color::kBlack); marker_range = PlainTextRange(5, 10).CreateRange(*div); GetDocument().Markers().AddActiveSuggestionMarker( - marker_range, Color::kBlack, ImeTextSpanThickness::kThin, Color::kBlack); + marker_range, Color::kBlack, ImeTextSpanThickness::kThin, + ImeTextSpanUnderlineStyle::kSolid, Color::kBlack, Color::kBlack); marker_range = PlainTextRange(10, 15).CreateRange(*div); GetDocument().Markers().AddActiveSuggestionMarker( - marker_range, Color::kBlack, ImeTextSpanThickness::kThin, Color::kBlack); + marker_range, Color::kBlack, ImeTextSpanThickness::kThin, + ImeTextSpanUnderlineStyle::kSolid, Color::kBlack, Color::kBlack); marker_range = PlainTextRange(15, 20).CreateRange(*div); GetDocument().Markers().AddActiveSuggestionMarker( - marker_range, Color::kBlack, ImeTextSpanThickness::kThin, Color::kBlack); + marker_range, Color::kBlack, ImeTextSpanThickness::kThin, + ImeTextSpanUnderlineStyle::kSolid, Color::kBlack, Color::kBlack); marker_range = PlainTextRange(20, 25).CreateRange(*div); GetDocument().Markers().AddActiveSuggestionMarker( - marker_range, Color::kBlack, ImeTextSpanThickness::kThin, Color::kBlack); + marker_range, Color::kBlack, ImeTextSpanThickness::kThin, + ImeTextSpanUnderlineStyle::kSolid, Color::kBlack, Color::kBlack); EXPECT_EQ(5u, GetDocument().Markers().Markers().size()); @@ -2095,7 +2126,8 @@ TEST_F(InputMethodControllerTest, EphemeralRange marker_range = PlainTextRange(5, 10).CreateRange(*div); GetDocument().Markers().AddActiveSuggestionMarker( - marker_range, Color::kBlack, ImeTextSpanThickness::kThin, Color::kBlack); + marker_range, Color::kBlack, ImeTextSpanThickness::kThin, + ImeTextSpanUnderlineStyle::kSolid, 0, Color::kBlack); EXPECT_EQ(1u, GetDocument().Markers().Markers().size()); @@ -2132,7 +2164,8 @@ TEST_F(InputMethodControllerTest, EphemeralRange marker_range = PlainTextRange(5, 10).CreateRange(*div); GetDocument().Markers().AddActiveSuggestionMarker( - marker_range, Color::kBlack, ImeTextSpanThickness::kThin, Color::kBlack); + marker_range, Color::kBlack, ImeTextSpanThickness::kThin, + ImeTextSpanUnderlineStyle::kSolid, 0, Color::kBlack); // Delete middle of marker Vector<ImeTextSpan> empty_ime_text_spans; @@ -2187,15 +2220,18 @@ TEST_F(InputMethodControllerTest, EphemeralRange marker_range = PlainTextRange(0, 5).CreateRange(*div); GetDocument().Markers().AddActiveSuggestionMarker( - marker_range, Color::kBlack, ImeTextSpanThickness::kThin, Color::kBlack); + marker_range, Color::kBlack, ImeTextSpanThickness::kThin, + ImeTextSpanUnderlineStyle::kSolid, 0, Color::kBlack); marker_range = PlainTextRange(5, 10).CreateRange(*div); GetDocument().Markers().AddActiveSuggestionMarker( - marker_range, Color::kBlack, ImeTextSpanThickness::kThin, Color::kBlack); + marker_range, Color::kBlack, ImeTextSpanThickness::kThin, + ImeTextSpanUnderlineStyle::kSolid, 0, Color::kBlack); marker_range = PlainTextRange(10, 15).CreateRange(*div); GetDocument().Markers().AddActiveSuggestionMarker( - marker_range, Color::kBlack, ImeTextSpanThickness::kThin, Color::kBlack); + marker_range, Color::kBlack, ImeTextSpanThickness::kThin, + ImeTextSpanUnderlineStyle::kSolid, 0, Color::kBlack); EXPECT_EQ(3u, GetDocument().Markers().Markers().size()); @@ -2259,15 +2295,18 @@ TEST_F(InputMethodControllerTest, EphemeralRange marker_range = PlainTextRange(0, 5).CreateRange(*div); GetDocument().Markers().AddActiveSuggestionMarker( - marker_range, Color::kBlack, ImeTextSpanThickness::kThin, Color::kBlack); + marker_range, Color::kBlack, ImeTextSpanThickness::kThin, + ImeTextSpanUnderlineStyle::kSolid, 0, Color::kBlack); marker_range = PlainTextRange(5, 15).CreateRange(*div); GetDocument().Markers().AddActiveSuggestionMarker( - marker_range, Color::kBlack, ImeTextSpanThickness::kThin, Color::kBlack); + marker_range, Color::kBlack, ImeTextSpanThickness::kThin, + ImeTextSpanUnderlineStyle::kSolid, 0, Color::kBlack); marker_range = PlainTextRange(15, 20).CreateRange(*div); GetDocument().Markers().AddActiveSuggestionMarker( - marker_range, Color::kBlack, ImeTextSpanThickness::kThin, Color::kBlack); + marker_range, Color::kBlack, ImeTextSpanThickness::kThin, + ImeTextSpanUnderlineStyle::kSolid, 0, Color::kBlack); EXPECT_EQ(3u, GetDocument().Markers().Markers().size()); @@ -2297,7 +2336,8 @@ TEST_F(InputMethodControllerTest, // Try to commit a non-misspelling suggestion marker. ime_text_spans.push_back( ImeTextSpan(ImeTextSpan::Type::kSuggestion, 0, 5, Color::kTransparent, - ImeTextSpanThickness::kNone, Color::kTransparent)); + ImeTextSpanThickness::kNone, ImeTextSpanUnderlineStyle::kNone, + Color::kTransparent, Color::kTransparent)); Controller().CommitText("hello", ime_text_spans, 1); // The marker should have been added. @@ -2314,7 +2354,8 @@ TEST_F(InputMethodControllerTest, // Try to commit a non-misspelling suggestion marker. ime_text_spans.push_back(ImeTextSpan( ImeTextSpan::Type::kMisspellingSuggestion, 0, 5, Color::kTransparent, - ImeTextSpanThickness::kNone, Color::kTransparent)); + ImeTextSpanThickness::kNone, ImeTextSpanUnderlineStyle::kNone, + Color::kTransparent, Color::kTransparent)); Controller().CommitText("hello", ime_text_spans, 1); // The marker should not have been added since the div has spell checking @@ -2330,7 +2371,8 @@ TEST_F(InputMethodControllerTest, RemoveSuggestionMarkerInRangeOnFinish) { Vector<ImeTextSpan> ime_text_spans; ime_text_spans.push_back(ImeTextSpan( ImeTextSpan::Type::kMisspellingSuggestion, 0, 5, Color::kTransparent, - ImeTextSpanThickness::kNone, Color::kTransparent, Color ::kTransparent, + ImeTextSpanThickness::kNone, ImeTextSpanUnderlineStyle::kNone, + Color::kTransparent, Color::kTransparent, Color ::kTransparent, /* remove_on_finish_composing */ true)); // Case 1: SetComposition() -> FinishComposingText() removes the suggestion @@ -2402,9 +2444,9 @@ TEST_F(InputMethodControllerTest, CompositionUnderlineSpansMultipleNodes) { Element* div = InsertHTMLElement( "<div id='sample' contenteditable><b>t</b>est</div>", "sample"); Vector<ImeTextSpan> ime_text_spans; - ime_text_spans.push_back(ImeTextSpan(ImeTextSpan::Type::kComposition, 0, 4, - Color(255, 0, 0), - ImeTextSpanThickness::kThin, 0)); + ime_text_spans.push_back(ImeTextSpan( + ImeTextSpan::Type::kComposition, 0, 4, Color(255, 0, 0), + ImeTextSpanThickness::kThin, ImeTextSpanUnderlineStyle::kSolid, 0, 0)); Controller().SetCompositionFromExistingText(Vector<ImeTextSpan>(), 0, 4); Controller().SetComposition("test", ime_text_spans, 0, 4); @@ -2483,9 +2525,9 @@ TEST_F(InputMethodControllerTest, InsertHTMLElement("<div id='sample' contenteditable></div>", "sample"); Vector<ImeTextSpan> ime_text_spans; - ime_text_spans.push_back(ImeTextSpan(ImeTextSpan::Type::kComposition, 0, 1, - Color(255, 0, 0), - ImeTextSpanThickness::kThin, 0)); + ime_text_spans.push_back(ImeTextSpan( + ImeTextSpan::Type::kComposition, 0, 1, Color(255, 0, 0), + ImeTextSpanThickness::kThin, ImeTextSpanUnderlineStyle::kSolid, 0, 0)); Controller().CommitText(" ", ime_text_spans, 0); // Add character U+094D: 'DEVANAGARI SIGN VIRAMA' Controller().SetComposition(String::FromUTF8("\xE0\xA5\x8D"), ime_text_spans, @@ -2545,7 +2587,7 @@ TEST_F(InputMethodControllerTest, GetDocument().GetSettings()->SetScriptEnabled(true); Element* script = GetDocument().CreateRawElement(html_names::kScriptTag); - script->SetInnerHTMLFromString( + script->setInnerHTML( "document.getElementById('sample').addEventListener('input', " " event => {" " const node = event.currentTarget;" @@ -2580,7 +2622,7 @@ TEST_F(InputMethodControllerTest, GetDocument().GetSettings()->SetScriptEnabled(true); Element* script = GetDocument().CreateRawElement(html_names::kScriptTag); - script->SetInnerHTMLFromString( + script->setInnerHTML( "document.getElementById('sample').addEventListener('input', " " event => {" " const node = event.currentTarget;" @@ -2618,7 +2660,7 @@ TEST_F( GetDocument().GetSettings()->SetScriptEnabled(true); Element* script = GetDocument().CreateRawElement(html_names::kScriptTag); - script->SetInnerHTMLFromString( + script->setInnerHTML( "document.getElementById('sample').addEventListener('input', " " event => {" " const node = event.currentTarget;" @@ -2651,7 +2693,7 @@ TEST_F(InputMethodControllerTest, GetDocument().GetSettings()->SetScriptEnabled(true); Element* script = GetDocument().CreateRawElement(html_names::kScriptTag); - script->SetInnerHTMLFromString( + script->setInnerHTML( "document.getElementById('sample').addEventListener('input', " " event => {" " const node = event.currentTarget;" @@ -2685,7 +2727,7 @@ TEST_F(InputMethodControllerTest, GetDocument().GetSettings()->SetScriptEnabled(true); Element* script = GetDocument().CreateRawElement(html_names::kScriptTag); - script->SetInnerHTMLFromString( + script->setInnerHTML( "document.getElementById('sample').addEventListener('input', " " event => {" " const node = event.currentTarget;" @@ -2719,7 +2761,7 @@ TEST_F(InputMethodControllerTest, GetDocument().GetSettings()->SetScriptEnabled(true); Element* script = GetDocument().CreateRawElement(html_names::kScriptTag); - script->SetInnerHTMLFromString( + script->setInnerHTML( "document.getElementById('sample').addEventListener('input', " " event => {" " const node = event.currentTarget;" @@ -2752,7 +2794,7 @@ TEST_F(InputMethodControllerTest, GetDocument().GetSettings()->SetScriptEnabled(true); Element* script = GetDocument().CreateRawElement(html_names::kScriptTag); - script->SetInnerHTMLFromString( + script->setInnerHTML( "document.getElementById('sample').addEventListener('input', " " event => {" " const node = event.currentTarget;" @@ -2789,7 +2831,7 @@ TEST_F(InputMethodControllerTest, GetDocument().GetSettings()->SetScriptEnabled(true); Element* script = GetDocument().CreateRawElement(html_names::kScriptTag); - script->SetInnerHTMLFromString( + script->setInnerHTML( "document.getElementById('sample').addEventListener('compositionend', " " event => {" " const node = event.currentTarget;" @@ -2825,7 +2867,7 @@ TEST_F( GetDocument().GetSettings()->SetScriptEnabled(true); Element* script = GetDocument().CreateRawElement(html_names::kScriptTag); - script->SetInnerHTMLFromString( + script->setInnerHTML( "document.getElementById('sample').addEventListener('compositionend', " " event => {" " const node = event.currentTarget;" @@ -2859,7 +2901,7 @@ TEST_F( GetDocument().GetSettings()->SetScriptEnabled(true); Element* script = GetDocument().CreateRawElement(html_names::kScriptTag); - script->SetInnerHTMLFromString( + script->setInnerHTML( "document.getElementById('sample').addEventListener('compositionend', " " event => {" " const node = event.currentTarget;" @@ -2892,7 +2934,7 @@ TEST_F(InputMethodControllerTest, GetDocument().GetSettings()->SetScriptEnabled(true); Element* script = GetDocument().CreateRawElement(html_names::kScriptTag); - script->SetInnerHTMLFromString( + script->setInnerHTML( "document.getElementById('sample').addEventListener('compositionend', " " event => {" " const node = event.currentTarget;" @@ -2924,7 +2966,7 @@ TEST_F(InputMethodControllerTest, GetDocument().GetSettings()->SetScriptEnabled(true); Element* script = GetDocument().CreateRawElement(html_names::kScriptTag); - script->SetInnerHTMLFromString( + script->setInnerHTML( "document.getElementById('sample').addEventListener('compositionend', " " event => {" " const node = event.currentTarget;" @@ -2956,7 +2998,7 @@ TEST_F(InputMethodControllerTest, GetDocument().GetSettings()->SetScriptEnabled(true); Element* script = GetDocument().CreateRawElement(html_names::kScriptTag); - script->SetInnerHTMLFromString( + script->setInnerHTML( "document.getElementById('sample').addEventListener('input', " " event => {" " const node = event.currentTarget;" @@ -2986,7 +3028,7 @@ TEST_F(InputMethodControllerTest, GetDocument().GetSettings()->SetScriptEnabled(true); Element* script = GetDocument().CreateRawElement(html_names::kScriptTag); - script->SetInnerHTMLFromString( + script->setInnerHTML( "document.getElementById('sample').addEventListener('input', " " event => {" " const node = event.currentTarget;" @@ -3016,7 +3058,7 @@ TEST_F(InputMethodControllerTest, GetDocument().GetSettings()->SetScriptEnabled(true); Element* script = GetDocument().CreateRawElement(html_names::kScriptTag); - script->SetInnerHTMLFromString( + script->setInnerHTML( "document.getElementById('sample').addEventListener('compositionend', " " event => {" " const node = event.currentTarget;" @@ -3048,7 +3090,7 @@ TEST_F( GetDocument().GetSettings()->SetScriptEnabled(true); Element* script = GetDocument().CreateRawElement(html_names::kScriptTag); - script->SetInnerHTMLFromString( + script->setInnerHTML( "document.getElementById('sample').addEventListener('compositionend', " " event => {" " const node = event.currentTarget;" @@ -3163,7 +3205,7 @@ TEST_F(InputMethodControllerTest, AutocapitalizeTextInputFlags) { const int expected_flags = element_and_expected_flags_pair.second; GetDocument().write(element); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); To<Element>(GetDocument().body()->lastChild())->focus(); EXPECT_EQ(expected_flags, @@ -3186,7 +3228,7 @@ TEST_F(InputMethodControllerTest, ExecCommandDuringComposition) { Vector<ImeTextSpan>(), 10, 10); // "world" should be bold. - EXPECT_EQ("hello<b>world</b>", div->InnerHTMLAsString()); + EXPECT_EQ("hello<b>world</b>", div->innerHTML()); } TEST_F(InputMethodControllerTest, SetCompositionAfterNonEditableElement) { @@ -3235,4 +3277,32 @@ TEST_F(InputMethodControllerTest, SetCompositionInTableCell) { EXPECT_EQ(1u, range->endOffset()); } +TEST_F(InputMethodControllerTest, SetCompositionInMyanmar) { + Element* div = + InsertHTMLElement("<div id='sample' contenteditable></div>", "sample"); + + // Add character U+200C: 'kZeroWidthNonJoinerCharacter' and Myanmar vowel + Controller().SetComposition(String::FromUTF8("\xE2\x80\x8C\xE1\x80\xB1"), + Vector<ImeTextSpan>(), 0, 0); + + EXPECT_EQ(1u, div->CountChildren()); + EXPECT_EQ(String::FromUTF8("\xE2\x80\x8C\xE1\x80\xB1"), div->innerHTML()); + + Range* range = GetCompositionRange(); + EXPECT_EQ(0u, range->startOffset()); + EXPECT_EQ(2u, range->endOffset()); + Controller().CommitText(String::FromUTF8("\xE2\x80\x8C\xE1\x80\xB1"), + Vector<ImeTextSpan>(), 1); + EXPECT_EQ(String::FromUTF8("\xE2\x80\x8C\xE1\x80\xB1"), div->innerHTML()); + + // Add character U+200C: 'kZeroWidthNonJoinerCharacter' and Myanmar vowel + Controller().SetComposition(String::FromUTF8("\xE2\x80\x8C\xE1\x80\xB1"), + Vector<ImeTextSpan>(), 2, 2); + Controller().CommitText(String::FromUTF8("\xE2\x80\x8C\xE1\x80\xB1"), + Vector<ImeTextSpan>(), 1); + EXPECT_EQ( + String::FromUTF8("\xE2\x80\x8C\xE1\x80\xB1\xE2\x80\x8C\xE1\x80\xB1"), + div->innerHTML()); +} + } // namespace blink diff --git a/chromium/third_party/blink/renderer/core/editing/ime/text_format_update_event.cc b/chromium/third_party/blink/renderer/core/editing/ime/text_format_update_event.cc index 8152313f19e..2a5696c3096 100644 --- a/chromium/third_party/blink/renderer/core/editing/ime/text_format_update_event.cc +++ b/chromium/third_party/blink/renderer/core/editing/ime/text_format_update_event.cc @@ -4,7 +4,7 @@ #include "third_party/blink/renderer/core/editing/ime/text_format_update_event.h" -#include "third_party/blink/renderer/core/editing/ime/text_format_update_event_init.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_text_format_update_event_init.h" #include "third_party/blink/renderer/core/event_interface_names.h" #include "third_party/blink/renderer/core/event_type_names.h" diff --git a/chromium/third_party/blink/renderer/core/editing/ime/text_format_update_event.idl b/chromium/third_party/blink/renderer/core/editing/ime/text_format_update_event.idl index eb6046133b9..cbf87a6faae 100644 --- a/chromium/third_party/blink/renderer/core/editing/ime/text_format_update_event.idl +++ b/chromium/third_party/blink/renderer/core/editing/ime/text_format_update_event.idl @@ -8,10 +8,10 @@ // (e.g. backgroundColor, textDecoration, etc.). // Explainer: https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/master/EditContext/explainer.md [ - Constructor(optional TextFormatUpdateEventInit options), Exposed=Window, RuntimeEnabled=EditContext ] interface TextFormatUpdateEvent : Event { + constructor(optional TextFormatUpdateEventInit options = {}); readonly attribute unsigned long formatRangeStart; readonly attribute unsigned long formatRangeEnd; readonly attribute DOMString underlineColor; diff --git a/chromium/third_party/blink/renderer/core/editing/ime/text_update_event.cc b/chromium/third_party/blink/renderer/core/editing/ime/text_update_event.cc index bbf5d8bc1ea..4448dee70da 100644 --- a/chromium/third_party/blink/renderer/core/editing/ime/text_update_event.cc +++ b/chromium/third_party/blink/renderer/core/editing/ime/text_update_event.cc @@ -4,7 +4,7 @@ #include "third_party/blink/renderer/core/editing/ime/text_update_event.h" -#include "third_party/blink/renderer/core/editing/ime/text_update_event_init.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_text_update_event_init.h" #include "third_party/blink/renderer/core/event_interface_names.h" #include "third_party/blink/renderer/core/event_type_names.h" diff --git a/chromium/third_party/blink/renderer/core/editing/ime/text_update_event.idl b/chromium/third_party/blink/renderer/core/editing/ime/text_update_event.idl index 5c1122fb292..f622e1862d1 100644 --- a/chromium/third_party/blink/renderer/core/editing/ime/text_update_event.idl +++ b/chromium/third_party/blink/renderer/core/editing/ime/text_update_event.idl @@ -9,10 +9,10 @@ // fired). // Explainer: https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/master/EditContext/explainer.md [ - Constructor(optional TextUpdateEventInit options), Exposed=Window, RuntimeEnabled=EditContext ] interface TextUpdateEvent : Event { + constructor(optional TextUpdateEventInit options = {}); readonly attribute unsigned long updateRangeStart; readonly attribute unsigned long updateRangeEnd; readonly attribute DOMString updateText; diff --git a/chromium/third_party/blink/renderer/core/editing/inline_box_position_test.cc b/chromium/third_party/blink/renderer/core/editing/inline_box_position_test.cc index 44d1ff78963..9aa084812dd 100644 --- a/chromium/third_party/blink/renderer/core/editing/inline_box_position_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/inline_box_position_test.cc @@ -25,6 +25,8 @@ std::ostream& operator<<(std::ostream& ostream, class InlineBoxPositionTest : public EditingTestBase {}; TEST_F(InlineBoxPositionTest, ComputeInlineBoxPositionBidiIsolate) { + if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) + return; // InlineBoxPosition is a legacy-only data structure. ScopedLayoutNGForTest scoped_layout_ng(false); @@ -43,6 +45,8 @@ TEST_F(InlineBoxPositionTest, ComputeInlineBoxPositionBidiIsolate) { // http://crbug.com/716093 TEST_F(InlineBoxPositionTest, ComputeInlineBoxPositionMixedEditable) { + if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) + return; // InlineBoxPosition is a legacy-only data structure. ScopedLayoutNGForTest scoped_layout_ng(false); @@ -62,6 +66,8 @@ TEST_F(InlineBoxPositionTest, ComputeInlineBoxPositionMixedEditable) { // http://crbug.com/841363 TEST_F(InlineBoxPositionTest, InFlatTreeAfterInputWithPlaceholderDoesntCrash) { + if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) + return; // InlineBoxPosition is a legacy-only data structure. ScopedLayoutNGForTest scoped_layout_ng(false); @@ -79,6 +85,8 @@ TEST_F(InlineBoxPositionTest, InFlatTreeAfterInputWithPlaceholderDoesntCrash) { } TEST_F(InlineBoxPositionTest, DownstreamBeforeLineBreakLTR) { + if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) + return; // InlineBoxPosition is a legacy-only data structure. ScopedLayoutNGForTest scoped_layout_ng(false); @@ -101,6 +109,8 @@ TEST_F(InlineBoxPositionTest, DownstreamBeforeLineBreakLTR) { } TEST_F(InlineBoxPositionTest, DownstreamBeforeLineBreakRTL) { + if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) + return; // InlineBoxPosition is a legacy-only data structure. ScopedLayoutNGForTest scoped_layout_ng(false); diff --git a/chromium/third_party/blink/renderer/core/editing/inline_box_traversal.cc b/chromium/third_party/blink/renderer/core/editing/inline_box_traversal.cc index e6f9b75cc84..b3748d258a8 100644 --- a/chromium/third_party/blink/renderer/core/editing/inline_box_traversal.cc +++ b/chromium/third_party/blink/renderer/core/editing/inline_box_traversal.cc @@ -74,13 +74,13 @@ class AbstractInlineBox { UBiDiLevel BidiLevel() const { DCHECK(IsNotNull()); return IsOldLayout() ? GetInlineBox().BidiLevel() - : line_cursor_.CurrentBidiLevel(); + : line_cursor_.Current().BidiLevel(); } TextDirection Direction() const { DCHECK(IsNotNull()); return IsOldLayout() ? GetInlineBox().Direction() - : line_cursor_.CurrentResolvedDirection(); + : line_cursor_.Current().ResolvedDirection(); } AbstractInlineBox PrevLeafChild() const { @@ -131,7 +131,7 @@ class AbstractInlineBox { DCHECK(IsNotNull()); if (IsOldLayout()) return ParagraphDirectionOf(GetInlineBox()); - return GetLineBox(line_cursor_).CurrentBaseDirection(); + return GetLineBox(line_cursor_).Current().BaseDirection(); } private: @@ -189,7 +189,7 @@ bool IsAtFragmentStart(const NGCaretPosition& caret_position) { case NGCaretPositionType::kAtTextOffset: DCHECK(caret_position.text_offset.has_value()); return *caret_position.text_offset == - caret_position.cursor.CurrentTextStartOffset(); + caret_position.cursor.Current().TextStartOffset(); } NOTREACHED(); return false; @@ -205,7 +205,7 @@ bool IsAtFragmentEnd(const NGCaretPosition& caret_position) { case NGCaretPositionType::kAtTextOffset: DCHECK(caret_position.text_offset.has_value()); return *caret_position.text_offset == - caret_position.cursor.CurrentTextEndOffset(); + caret_position.cursor.Current().TextEndOffset(); } NOTREACHED(); return false; @@ -217,7 +217,7 @@ SideAffinity GetSideAffinity(const NGCaretPosition& caret_position) { DCHECK(IsAtFragmentStart(caret_position) || IsAtFragmentEnd(caret_position)); const bool is_at_start = IsAtFragmentStart(caret_position); const bool is_at_left_side = - is_at_start == IsLtr(caret_position.cursor.CurrentResolvedDirection()); + is_at_start == IsLtr(caret_position.cursor.Current().ResolvedDirection()); return is_at_left_side ? SideAffinity::kLeft : SideAffinity::kRight; } @@ -260,7 +260,7 @@ class AbstractInlineBoxAndSideAffinity { const bool is_at_start = IsLtr(box_.Direction()) == AtLeftSide(); NGInlineCursor cursor(box_.GetCursor()); - if (!cursor.IsText()) { + if (!cursor.Current().IsText()) { return {cursor, is_at_start ? NGCaretPositionType::kBeforeBox : NGCaretPositionType::kAfterBox, @@ -268,8 +268,8 @@ class AbstractInlineBoxAndSideAffinity { } return {cursor, NGCaretPositionType::kAtTextOffset, - is_at_start ? cursor.CurrentTextStartOffset() - : cursor.CurrentTextEndOffset()}; + is_at_start ? cursor.Current().TextStartOffset() + : cursor.Current().TextEndOffset()}; } PositionInFlatTree GetPosition() const { diff --git a/chromium/third_party/blink/renderer/core/editing/iterators/character_iterator_test.cc b/chromium/third_party/blink/renderer/core/editing/iterators/character_iterator_test.cc index b6450e7cb53..845cf94c0d7 100644 --- a/chromium/third_party/blink/renderer/core/editing/iterators/character_iterator_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/iterators/character_iterator_test.cc @@ -48,7 +48,9 @@ class ParameterizedCharacterIteratorTest ParameterizedCharacterIteratorTest() : ScopedLayoutNGForTest(GetParam()) {} protected: - bool LayoutNGEnabled() const { return GetParam(); } + bool LayoutNGEnabled() const { + return RuntimeEnabledFeatures::LayoutNGEnabled(); + } }; INSTANTIATE_TEST_SUITE_P(All, diff --git a/chromium/third_party/blink/renderer/core/editing/iterators/fully_clipped_state_stack.cc b/chromium/third_party/blink/renderer/core/editing/iterators/fully_clipped_state_stack.cc index d19897a1f1f..0709db472e5 100644 --- a/chromium/third_party/blink/renderer/core/editing/iterators/fully_clipped_state_stack.cc +++ b/chromium/third_party/blink/renderer/core/editing/iterators/fully_clipped_state_stack.cc @@ -9,6 +9,7 @@ #include "third_party/blink/renderer/core/editing/editing_utilities.h" #include "third_party/blink/renderer/core/layout/layout_box.h" #include "third_party/blink/renderer/core/layout/layout_object.h" +#include "third_party/blink/renderer/core/layout/layout_view.h" namespace blink { @@ -17,7 +18,7 @@ namespace { inline bool FullyClipsContents(const Node* node) { LayoutObject* layout_object = node->GetLayoutObject(); if (!layout_object || !layout_object->IsBox() || - !layout_object->HasOverflowClip() || layout_object->IsLayoutView()) + !layout_object->HasOverflowClip() || IsA<LayoutView>(layout_object)) return false; return ToLayoutBox(layout_object)->Size().IsEmpty(); } diff --git a/chromium/third_party/blink/renderer/core/editing/iterators/simplified_backwards_text_iterator.cc b/chromium/third_party/blink/renderer/core/editing/iterators/simplified_backwards_text_iterator.cc index 9128e858a11..6ba981cca82 100644 --- a/chromium/third_party/blink/renderer/core/editing/iterators/simplified_backwards_text_iterator.cc +++ b/chromium/third_party/blink/renderer/core/editing/iterators/simplified_backwards_text_iterator.cc @@ -224,7 +224,7 @@ bool SimplifiedBackwardsTextIteratorAlgorithm<Strategy>::HandleTextNode() { return true; String text = layout_object->GetText(); - if (!layout_object->HasTextBoxes() && text.length() > 0) + if (!layout_object->HasInlineFragments() && text.length() > 0) return true; const int position_end_offset = offset_; diff --git a/chromium/third_party/blink/renderer/core/editing/iterators/simplified_backwards_text_iterator.h b/chromium/third_party/blink/renderer/core/editing/iterators/simplified_backwards_text_iterator.h index 4d41206bf82..128bc4849df 100644 --- a/chromium/third_party/blink/renderer/core/editing/iterators/simplified_backwards_text_iterator.h +++ b/chromium/third_party/blink/renderer/core/editing/iterators/simplified_backwards_text_iterator.h @@ -104,17 +104,17 @@ class SimplifiedBackwardsTextIteratorAlgorithm { // Current position, not necessarily of the text being returned, but position // as we walk through the DOM tree. - Member<const Node> node_; + const Node* node_; int offset_; bool handled_node_; bool handled_children_; FullyClippedStateStackAlgorithm<Strategy> fully_clipped_stack_; // End of the range. - Member<const Node> start_node_; + const Node* start_node_; int start_offset_; // Start of the range. - Member<const Node> end_node_; + const Node* end_node_; int end_offset_; // Whether |node_| has advanced beyond the iteration range (i.e. start_node_). diff --git a/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator.cc b/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator.cc index 3e8c64b5c2c..31a98194236 100644 --- a/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator.cc +++ b/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator.cc @@ -176,9 +176,12 @@ bool ShouldHandleChildren(const Node& node, if (!behavior.EntersTextControls() && IsTextControl(node)) return false; - if (auto* element = DynamicTo<Element>(node)) { - if (auto* context = element->GetDisplayLockContext()) { - return context->IsActivatable(DisplayLockActivationReason::kSelection); + if (!behavior.IgnoresDisplayLock()) { + if (auto* element = DynamicTo<Element>(node)) { + if (auto* context = element->GetDisplayLockContext()) { + return !context->IsLocked() || + context->IsActivatable(DisplayLockActivationReason::kSelection); + } } } return true; @@ -267,7 +270,7 @@ bool TextIteratorAlgorithm<Strategy>::HandleRememberedProgress() { // FIXME: It would be cleaner if we emitted two newlines during the last // iteration, instead of using needs_another_newline_. Node* last_child = Strategy::LastChild(*node_); - const Node* base_node = last_child ? last_child : node_.Get(); + const Node* base_node = last_child ? last_child : node_; EmitChar16AfterNode('\n', *base_node); needs_another_newline_ = false; return true; @@ -310,26 +313,32 @@ void TextIteratorAlgorithm<Strategy>::Advance() { node_ = nullptr; return; } + + // If an element is locked, we shouldn't recurse down into its children + // since they might not have up-to-date layout. In particular, they might + // not have the NG offset mapping which is required. The display lock can + // still be bypassed by marking the iterator behavior to ignore display + // lock. const bool locked = + !behavior_.IgnoresDisplayLock() && DisplayLockUtilities::NearestLockedInclusiveAncestor(*node_); LayoutObject* layout_object = node_->GetLayoutObject(); if (!layout_object || locked) { - if (!locked && - (IsA<ShadowRoot>(node_.Get()) || HasDisplayContents(*node_))) { + if (!locked && (IsA<ShadowRoot>(node_) || HasDisplayContents(*node_))) { // Shadow roots or display: contents elements don't have LayoutObjects, // but we want to visit children anyway. iteration_progress_ = iteration_progress_ < kHandledNode ? kHandledNode : iteration_progress_; - handle_shadow_root_ = IsA<ShadowRoot>(node_.Get()); + handle_shadow_root_ = IsA<ShadowRoot>(node_); } else { iteration_progress_ = kHandledChildren; } } else { // Enter author shadow roots, from youngest, if any and if necessary. if (iteration_progress_ < kHandledOpenShadowRoots) { - auto* element = DynamicTo<Element>(node_.Get()); + auto* element = DynamicTo<Element>(node_); if (std::is_same<Strategy, EditingStrategy>::value && EntersOpenShadowRoots() && element && element->OpenShadowRoot()) { ShadowRoot* youngest_shadow_root = element->OpenShadowRoot(); @@ -350,7 +359,7 @@ void TextIteratorAlgorithm<Strategy>::Advance() { if (std::is_same<Strategy, EditingStrategy>::value && EntersTextControls() && layout_object->IsTextControl()) { ShadowRoot* user_agent_shadow_root = - To<Element>(node_.Get())->UserAgentShadowRoot(); + To<Element>(node_)->UserAgentShadowRoot(); DCHECK(user_agent_shadow_root->IsUserAgent()); node_ = user_agent_shadow_root; iteration_progress_ = kHandledNone; @@ -374,7 +383,7 @@ void TextIteratorAlgorithm<Strategy>::Advance() { (layout_object->IsImage() || layout_object->IsLayoutEmbeddedContent() || (html_element && - (IsHTMLFormControlElement(html_element) || + (IsA<HTMLFormControlElement>(html_element) || IsA<HTMLLegendElement>(html_element) || IsA<HTMLImageElement>(html_element) || IsA<HTMLMeterElement>(html_element) || @@ -427,7 +436,7 @@ void TextIteratorAlgorithm<Strategy>::Advance() { // 4. Reached the top of a shadow root. If it's created by author, // then try to visit the next // sibling shadow root, if any. - const auto* shadow_root = DynamicTo<ShadowRoot>(node_.Get()); + const auto* shadow_root = DynamicTo<ShadowRoot>(node_); if (!shadow_root) { NOTREACHED(); should_stop_ = true; @@ -483,7 +492,7 @@ void TextIteratorAlgorithm<Strategy>::HandleTextNode() { DCHECK_NE(last_text_node_, node_) << "We should never call HandleTextNode on the same node twice"; - const auto* text = To<Text>(node_.Get()); + const auto* text = To<Text>(node_); last_text_node_ = text; // TODO(editing-dev): Introduce a |DOMOffsetRange| class so that we can pass @@ -810,7 +819,7 @@ void TextIteratorAlgorithm<Strategy>::ExitNode() { // case it is a block, because the run should start where the // emitted character is positioned visually. Node* last_child = Strategy::LastChild(*node_); - const Node* base_node = last_child ? last_child : node_.Get(); + const Node* base_node = last_child ? last_child : node_; // FIXME: This shouldn't require the last_text_node to be true, but we can't // change that without making the logic in _web_attributedStringFromRange // match. We'll get that for free when we switch to use TextIterator in diff --git a/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator.h b/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator.h index 1f6e69d5285..c7cba216a98 100644 --- a/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator.h +++ b/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator.h @@ -198,18 +198,18 @@ class TextIteratorAlgorithm { void EnsurePositionContainer() const; // The range. - const Member<const Node> start_container_; + const Node* const start_container_; const unsigned start_offset_; - const Member<const Node> end_container_; + const Node* const end_container_; const unsigned end_offset_; // |end_node_| stores |Strategy::ChildAt(*end_container_, end_offfset_ - 1)|, // if it exists, or |nullptr| otherwise. - const Member<const Node> end_node_; - const Member<const Node> past_end_node_; + const Node* const end_node_; + const Node* const past_end_node_; // Current position, not necessarily of the text being returned, but position // as we walk through the DOM tree. - Member<const Node> node_; + const Node* node_; IterationProgress iteration_progress_; FullyClippedStateStackAlgorithm<Strategy> fully_clipped_stack_; unsigned shadow_depth_; @@ -219,7 +219,7 @@ class TextIteratorAlgorithm { bool needs_another_newline_ = false; bool needs_handle_replaced_element_ = false; - Member<const Text> last_text_node_; + const Text* last_text_node_ = nullptr; const TextIteratorBehavior behavior_; diff --git a/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_behavior.cc b/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_behavior.cc index d8291acea5a..98cabe8caca 100644 --- a/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_behavior.cc +++ b/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_behavior.cc @@ -130,6 +130,12 @@ TextIteratorBehavior::Builder::SetSuppressesExtraNewlineEmission(bool value) { behavior_.values_.bits.suppresses_newline_emission = value; return *this; } + +TextIteratorBehavior::Builder& +TextIteratorBehavior::Builder::SetIgnoresDisplayLock(bool value) { + behavior_.values_.bits.ignores_display_lock = value; + return *this; +} // - TextIteratorBehavior::TextIteratorBehavior(const TextIteratorBehavior& other) = default; @@ -138,8 +144,6 @@ TextIteratorBehavior::TextIteratorBehavior() { values_.all = 0; } -TextIteratorBehavior::~TextIteratorBehavior() = default; - bool TextIteratorBehavior::operator==(const TextIteratorBehavior& other) const { return values_.all == other.values_.all; } diff --git a/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_behavior.h b/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_behavior.h index 232842e603a..f198a7a4457 100644 --- a/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_behavior.h +++ b/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_behavior.h @@ -19,7 +19,6 @@ class CORE_EXPORT TextIteratorBehavior final { TextIteratorBehavior(const TextIteratorBehavior& other); TextIteratorBehavior(); - ~TextIteratorBehavior(); bool operator==(const TextIteratorBehavior& other) const; bool operator!=(const TextIteratorBehavior& other) const; @@ -72,6 +71,8 @@ class CORE_EXPORT TextIteratorBehavior final { bool SuppressesExtraNewlineEmission() const { return values_.bits.suppresses_newline_emission; } + + bool IgnoresDisplayLock() const { return values_.bits.ignores_display_lock; } static TextIteratorBehavior EmitsObjectReplacementCharacterBehavior(); static TextIteratorBehavior IgnoresStyleVisibilityBehavior(); static TextIteratorBehavior DefaultRangeLengthBehavior(); @@ -101,6 +102,7 @@ class CORE_EXPORT TextIteratorBehavior final { bool does_not_emit_space_beyond_range_end : 1; bool skips_unselectable_content : 1; bool suppresses_newline_emission : 1; + bool ignores_display_lock : 1; } bits; } values_; }; @@ -134,6 +136,7 @@ class CORE_EXPORT TextIteratorBehavior::Builder final { Builder& SetDoesNotEmitSpaceBeyondRangeEnd(bool); Builder& SetSkipsUnselectableContent(bool); Builder& SetSuppressesExtraNewlineEmission(bool); + Builder& SetIgnoresDisplayLock(bool); private: TextIteratorBehavior behavior_; diff --git a/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_test.cc b/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_test.cc index 1bfddc2cf6f..7f7f2a2fd7d 100644 --- a/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_test.cc @@ -97,7 +97,9 @@ class TextIteratorTest : public testing::WithParamInterface<bool>, protected: TextIteratorTest() : ScopedLayoutNGForTest(GetParam()) {} - bool LayoutNGEnabled() const { return GetParam(); } + bool LayoutNGEnabled() const { + return RuntimeEnabledFeatures::LayoutNGEnabled(); + } template <typename Tree> std::string Iterate(const TextIteratorBehavior& = TextIteratorBehavior()); @@ -945,7 +947,7 @@ TEST_P(TextIteratorTest, BasicIterationInputiWithBr) { const ShadowRoot* shadow_root = input_element->UserAgentShadowRoot(); const Position start = Position::FirstPositionInNode(*shadow_root); const Position end = Position::LastPositionInNode(*shadow_root); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); EXPECT_EQ("[b]", IteratePartial<DOMTree>(start, end)); } @@ -978,8 +980,8 @@ TEST_P(TextIteratorTest, PositionInShadowTree) { Element& host = *GetDocument().getElementById("host"); ShadowRoot& shadow_root = host.AttachShadowRootInternal(ShadowRootType::kOpen); - shadow_root.SetInnerHTMLFromString("A<slot name=c></slot>"); - GetDocument().UpdateStyleAndLayout(); + shadow_root.setInnerHTML("A<slot name=c></slot>"); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Element& body = *GetDocument().body(); Node& text_a = *shadow_root.firstChild(); Node& slot = *shadow_root.lastChild(); @@ -1034,8 +1036,8 @@ TEST_P(TextIteratorTest, EmitsSpaceForNbsp) { TEST_P(TextIteratorTest, IterateWithLockedSubtree) { SetBodyContent("<div id='parent'>foo<div id='locked'>text</div>bar</div>"); auto* locked = GetDocument().getElementById("locked"); - locked->setAttribute("rendersubtree", "invisible activatable"); - GetDocument().UpdateStyleAndLayout(); + locked->setAttribute(html_names::kStyleAttr, "subtree-visibility: auto"); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); auto* parent = GetDocument().getElementById("parent"); const Position start_position = Position::FirstPositionInNode(*parent); const Position end_position = Position::LastPositionInNode(*parent); diff --git a/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_text_node_handler.h b/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_text_node_handler.h index 72ab43606bb..e1ffb8fc480 100644 --- a/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_text_node_handler.h +++ b/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_text_node_handler.h @@ -76,7 +76,7 @@ class TextIteratorTextNodeHandler { unsigned text_end_offset); // The current text node and offset range, from which text should be emitted. - Member<const Text> text_node_; + const Text* text_node_ = nullptr; unsigned offset_ = 0; unsigned end_offset_ = 0; diff --git a/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_text_state.cc b/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_text_state.cc index 156f67c69d4..4ee6e5ad040 100644 --- a/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_text_state.cc +++ b/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_text_state.cc @@ -108,7 +108,7 @@ void TextIteratorTextState::ResetPositionContainerNode( DCHECK_NE(node_type, PositionNodeType::kNone); position_node_type_ = node_type; position_container_node_ = nullptr; - position_node_ = node; + position_node_ = &node; position_start_offset_ = base::nullopt; position_end_offset_ = base::nullopt; } diff --git a/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_text_state.h b/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_text_state.h index dce6a069d87..b508e5ad516 100644 --- a/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_text_state.h +++ b/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_text_state.h @@ -145,9 +145,9 @@ class CORE_EXPORT TextIteratorTextState { unsigned text_start_offset_ = 0; // Position of the current text, in the form to be returned from the iterator. - Member<const Node> position_node_; + const Node* position_node_ = nullptr; // |Text| node when |position_node_type_ == kInText| or |ContainerNode|. - mutable Member<const Node> position_container_node_; + mutable const Node* position_container_node_ = nullptr; mutable base::Optional<unsigned> position_start_offset_; mutable base::Optional<unsigned> position_end_offset_; PositionNodeType position_node_type_ = PositionNodeType::kNone; diff --git a/chromium/third_party/blink/renderer/core/editing/keyboard_test.cc b/chromium/third_party/blink/renderer/core/editing/keyboard_test.cc index 356c4353370..f208b02608e 100644 --- a/chromium/third_party/blink/renderer/core/editing/keyboard_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/keyboard_test.cc @@ -34,8 +34,8 @@ #include "build/build_config.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/input/web_input_event.h" #include "third_party/blink/public/platform/platform.h" -#include "third_party/blink/public/platform/web_input_event.h" #include "third_party/blink/renderer/core/dom/events/event_target.h" #include "third_party/blink/renderer/core/editing/editor.h" #include "third_party/blink/renderer/core/events/keyboard_event.h" diff --git a/chromium/third_party/blink/renderer/core/editing/layout_selection.cc b/chromium/third_party/blink/renderer/core/editing/layout_selection.cc index dcbd563e350..a1e219fd9d2 100644 --- a/chromium/third_party/blink/renderer/core/editing/layout_selection.cc +++ b/chromium/third_party/blink/renderer/core/editing/layout_selection.cc @@ -191,7 +191,7 @@ struct OldSelectedNodes { selected_map = std::move(other.selected_map); } - Member<SelectionPaintRange> paint_range; + SelectionPaintRange* paint_range; HeapHashMap<Member<const Node>, SelectionState> selected_map; private: @@ -230,7 +230,7 @@ struct NewPaintRangeAndSelectedNodes { #endif } - Member<SelectionPaintRange> paint_range; + SelectionPaintRange* paint_range; HeapHashSet<Member<const Node>> selected_objects; private: @@ -584,9 +584,10 @@ static SelectionState GetSelectionStateFor(const LayoutText& layout_text) { } static SelectionState GetSelectionStateFor(const NGInlineCursor& cursor) { - DCHECK(cursor.CurrentLayoutObject() && - cursor.CurrentLayoutObject()->IsText()); - return GetSelectionStateFor(ToLayoutText(*cursor.CurrentLayoutObject())); + DCHECK(cursor.Current().GetLayoutObject() && + cursor.Current().GetLayoutObject()->IsText()); + return GetSelectionStateFor( + ToLayoutText(*cursor.Current().GetLayoutObject())); } bool LayoutSelection::IsSelected(const LayoutObject& layout_object) { @@ -661,10 +662,11 @@ LayoutTextSelectionStatus FrameSelection::ComputeLayoutSelectionStatus( LayoutSelectionStatus LayoutSelection::ComputeSelectionStatus( const NGInlineCursor& cursor) const { // We don't paint selection on ellipsis. - if (cursor.IsEllipsis()) + if (cursor.Current().IsEllipsis()) return {0, 0, SelectSoftLineBreak::kNotSelected}; - const unsigned start_offset = cursor.CurrentTextStartOffset(); - const unsigned end_offset = cursor.CurrentTextEndOffset(); + const NGTextOffset offset = cursor.Current().TextOffset(); + const unsigned start_offset = offset.start; + const unsigned end_offset = offset.end; switch (GetSelectionStateFor(cursor)) { case SelectionState::kStart: { const unsigned start_in_block = paint_range_->start_offset.value(); @@ -802,7 +804,7 @@ void LayoutSelection::Commit() { paint_range_ = new_range.paint_range; } -void LayoutSelection::OnDocumentShutdown() { +void LayoutSelection::ContextDestroyed() { has_pending_selection_ = false; paint_range_->start_node = nullptr; paint_range_->start_offset = base::nullopt; diff --git a/chromium/third_party/blink/renderer/core/editing/layout_selection.h b/chromium/third_party/blink/renderer/core/editing/layout_selection.h index c7c218ca402..5939c51400a 100644 --- a/chromium/third_party/blink/renderer/core/editing/layout_selection.h +++ b/chromium/third_party/blink/renderer/core/editing/layout_selection.h @@ -52,7 +52,7 @@ class LayoutSelection final : public GarbageCollected<LayoutSelection> { LayoutSelectionStatus ComputeSelectionStatus(const NGInlineCursor&) const; static bool IsSelected(const LayoutObject&); - void OnDocumentShutdown(); + void ContextDestroyed(); void Trace(Visitor*); diff --git a/chromium/third_party/blink/renderer/core/editing/layout_selection_test.cc b/chromium/third_party/blink/renderer/core/editing/layout_selection_test.cc index 5e84a2c9931..8d14afd7cf4 100644 --- a/chromium/third_party/blink/renderer/core/editing/layout_selection_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/layout_selection_test.cc @@ -5,7 +5,7 @@ #include "third_party/blink/renderer/core/editing/layout_selection.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h" -#include "third_party/blink/renderer/core/dom/shadow_root_init.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_shadow_root_init.h" #include "third_party/blink/renderer/core/editing/frame_selection.h" #include "third_party/blink/renderer/core/editing/selection_template.h" #include "third_party/blink/renderer/core/editing/testing/editing_test_base.h" @@ -43,7 +43,7 @@ class LayoutSelectionTestBase : public EditingTestBase { cursor.MoveTo(layout_text); if (!cursor) return; - const unsigned text_start = cursor.CurrentTextStartOffset(); + const unsigned text_start = cursor.Current().TextStartOffset(); for (; cursor; cursor.MoveToNextForSameLayoutObject()) { const LayoutSelectionStatus status = selection.ComputeLayoutSelectionStatus(cursor); @@ -148,7 +148,9 @@ class LayoutSelectionTest : public ::testing::WithParamInterface<bool>, protected: LayoutSelectionTest() : ScopedLayoutNGForTest(GetParam()) {} - bool LayoutNGEnabled() const { return GetParam(); } + bool LayoutNGEnabled() const { + return RuntimeEnabledFeatures::LayoutNGEnabled(); + } }; INSTANTIATE_TEST_SUITE_P(All, LayoutSelectionTest, ::testing::Bool()); @@ -776,7 +778,7 @@ TEST_P(LayoutSelectionTest, ClearByRemoveNode) { Node* baz = GetDocument().body()->lastChild(); baz->remove(); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Selection().CommitAppearanceIfNeeded(); EXPECT_EQ( "BODY, Contain, NotInvalidate \n" @@ -809,7 +811,7 @@ TEST_P(LayoutSelectionTest, ClearByRemoveLayoutObject) { auto* span_baz = To<Element>(GetDocument().body()->lastChild()); span_baz->SetInlineStyleProperty(CSSPropertyID::kDisplay, CSSValueID::kNone); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Selection().CommitAppearanceIfNeeded(); EXPECT_EQ( "BODY, Contain, NotInvalidate \n" @@ -853,7 +855,7 @@ TEST_P(LayoutSelectionTest, ClearBySlotChange) { GetDocument().body()->firstChild()->GetShadowRoot()->QuerySelector( "slot"); slot->setAttribute("name", "s2"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Selection().CommitAppearanceIfNeeded(); EXPECT_EQ( "BODY, Contain, NotInvalidate \n" diff --git a/chromium/third_party/blink/renderer/core/editing/link_selection_test.cc b/chromium/third_party/blink/renderer/core/editing/link_selection_test.cc index 5f0e04ca791..69e1e4c06f6 100644 --- a/chromium/third_party/blink/renderer/core/editing/link_selection_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/link_selection_test.cc @@ -16,9 +16,10 @@ #include "third_party/blink/renderer/core/page/context_menu_controller.h" #include "third_party/blink/renderer/core/page/focus_controller.h" #include "third_party/blink/renderer/core/page/page.h" -#include "third_party/blink/renderer/platform/cursor.h" #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h" #include "third_party/blink/renderer/platform/testing/url_test_helpers.h" +#include "ui/base/cursor/cursor.h" +#include "ui/base/mojom/cursor_type.mojom-blink.h" using testing::_; @@ -194,7 +195,7 @@ TEST_F(LinkSelectionTest, HandCursorDuringLinkDrag) { test::RunDelayedTasks(base::TimeDelta::FromMilliseconds(50)); const auto& cursor = main_frame_->GetFrame()->GetChromeClient().LastSetCursorForTesting(); - EXPECT_EQ(ui::CursorType::kHand, cursor.GetType()); + EXPECT_EQ(ui::mojom::blink::CursorType::kHand, cursor.type()); } TEST_F(LinkSelectionTest, DragOnNothingShowsPointer) { @@ -206,7 +207,7 @@ TEST_F(LinkSelectionTest, DragOnNothingShowsPointer) { test::RunDelayedTasks(base::TimeDelta::FromMilliseconds(50)); const auto& cursor = main_frame_->GetFrame()->GetChromeClient().LastSetCursorForTesting(); - EXPECT_EQ(ui::CursorType::kPointer, cursor.GetType()); + EXPECT_EQ(ui::mojom::blink::CursorType::kPointer, cursor.type()); } TEST_F(LinkSelectionTest, CaretCursorOverLinkDuringSelection) { @@ -219,7 +220,7 @@ TEST_F(LinkSelectionTest, CaretCursorOverLinkDuringSelection) { test::RunDelayedTasks(base::TimeDelta::FromMilliseconds(50)); const auto& cursor = main_frame_->GetFrame()->GetChromeClient().LastSetCursorForTesting(); - EXPECT_EQ(ui::CursorType::kIBeam, cursor.GetType()); + EXPECT_EQ(ui::mojom::blink::CursorType::kIBeam, cursor.type()); } TEST_F(LinkSelectionTest, HandCursorOverLinkAfterContextMenu) { @@ -238,7 +239,7 @@ TEST_F(LinkSelectionTest, HandCursorOverLinkAfterContextMenu) { test::RunDelayedTasks(base::TimeDelta::FromMilliseconds(50)); const auto& cursor = main_frame_->GetFrame()->GetChromeClient().LastSetCursorForTesting(); - EXPECT_EQ(ui::CursorType::kHand, cursor.GetType()); + EXPECT_EQ(ui::mojom::blink::CursorType::kHand, cursor.type()); } TEST_F(LinkSelectionTest, SingleClickWithAltStartsDownload) { diff --git a/chromium/third_party/blink/renderer/core/editing/local_caret_rect_bidi_test.cc b/chromium/third_party/blink/renderer/core/editing/local_caret_rect_bidi_test.cc index 3bb8e08951d..b4439331f43 100644 --- a/chromium/third_party/blink/renderer/core/editing/local_caret_rect_bidi_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/local_caret_rect_bidi_test.cc @@ -23,7 +23,9 @@ class ParameterizedLocalCaretRectBidiTest ParameterizedLocalCaretRectBidiTest() : ScopedLayoutNGForTest(GetParam()) {} protected: - bool LayoutNGEnabled() const { return GetParam(); } + bool LayoutNGEnabled() const { + return RuntimeEnabledFeatures::LayoutNGEnabled(); + } }; INSTANTIATE_TEST_SUITE_P(All, diff --git a/chromium/third_party/blink/renderer/core/editing/local_caret_rect_test.cc b/chromium/third_party/blink/renderer/core/editing/local_caret_rect_test.cc index 71cda0c29fd..941499d8f2c 100644 --- a/chromium/third_party/blink/renderer/core/editing/local_caret_rect_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/local_caret_rect_test.cc @@ -36,7 +36,9 @@ class ParameterizedLocalCaretRectTest ParameterizedLocalCaretRectTest() : ScopedLayoutNGForTest(GetParam()) {} protected: - bool LayoutNGEnabled() const { return GetParam(); } + bool LayoutNGEnabled() const { + return RuntimeEnabledFeatures::LayoutNGEnabled(); + } }; INSTANTIATE_TEST_SUITE_P(All, ParameterizedLocalCaretRectTest, testing::Bool()); diff --git a/chromium/third_party/blink/renderer/core/editing/markers/active_suggestion_marker.cc b/chromium/third_party/blink/renderer/core/editing/markers/active_suggestion_marker.cc index 926d2c85509..21fef20291c 100644 --- a/chromium/third_party/blink/renderer/core/editing/markers/active_suggestion_marker.cc +++ b/chromium/third_party/blink/renderer/core/editing/markers/active_suggestion_marker.cc @@ -11,11 +11,15 @@ ActiveSuggestionMarker::ActiveSuggestionMarker( unsigned end_offset, Color underline_color, ui::mojom::ImeTextSpanThickness thickness, + ui::mojom::ImeTextSpanUnderlineStyle underline_style, + Color text_color, Color background_color) : StyleableMarker(start_offset, end_offset, underline_color, thickness, + underline_style, + text_color, background_color) {} DocumentMarker::MarkerType ActiveSuggestionMarker::GetType() const { diff --git a/chromium/third_party/blink/renderer/core/editing/markers/active_suggestion_marker.h b/chromium/third_party/blink/renderer/core/editing/markers/active_suggestion_marker.h index 62a99d9bb89..645e49e17bd 100644 --- a/chromium/third_party/blink/renderer/core/editing/markers/active_suggestion_marker.h +++ b/chromium/third_party/blink/renderer/core/editing/markers/active_suggestion_marker.h @@ -18,6 +18,8 @@ class CORE_EXPORT ActiveSuggestionMarker final : public StyleableMarker { unsigned end_offset, Color underline_color, ui::mojom::ImeTextSpanThickness, + ui::mojom::ImeTextSpanUnderlineStyle underline_style, + Color text_color, Color background_color); // DocumentMarker implementations diff --git a/chromium/third_party/blink/renderer/core/editing/markers/active_suggestion_marker_list_impl_test.cc b/chromium/third_party/blink/renderer/core/editing/markers/active_suggestion_marker_list_impl_test.cc index 3278806ce74..8ccff83e0d5 100644 --- a/chromium/third_party/blink/renderer/core/editing/markers/active_suggestion_marker_list_impl_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/markers/active_suggestion_marker_list_impl_test.cc @@ -17,7 +17,9 @@ class ActiveSuggestionMarkerListImplTest : public EditingTestBase { DocumentMarker* CreateMarker(unsigned start_offset, unsigned end_offset) { return MakeGarbageCollected<ActiveSuggestionMarker>( start_offset, end_offset, Color::kTransparent, - ui::mojom::ImeTextSpanThickness::kThin, Color::kBlack); + ui::mojom::ImeTextSpanThickness::kThin, + ui::mojom::ImeTextSpanUnderlineStyle::kSolid, Color::kBlack, + Color::kBlack); } Persistent<ActiveSuggestionMarkerListImpl> marker_list_; diff --git a/chromium/third_party/blink/renderer/core/editing/markers/active_suggestion_marker_test.cc b/chromium/third_party/blink/renderer/core/editing/markers/active_suggestion_marker_test.cc index 1e3872be954..2c478280954 100644 --- a/chromium/third_party/blink/renderer/core/editing/markers/active_suggestion_marker_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/markers/active_suggestion_marker_test.cc @@ -7,6 +7,7 @@ #include "testing/gtest/include/gtest/gtest.h" using ui::mojom::ImeTextSpanThickness; +using ui::mojom::ImeTextSpanUnderlineStyle; namespace blink { @@ -15,6 +16,7 @@ class ActiveSuggestionMarkerTest : public testing::Test {}; TEST_F(ActiveSuggestionMarkerTest, MarkerType) { DocumentMarker* marker = MakeGarbageCollected<ActiveSuggestionMarker>( 0, 1, Color::kTransparent, ImeTextSpanThickness::kNone, + ImeTextSpanUnderlineStyle::kNone, Color::kTransparent, Color::kTransparent); EXPECT_EQ(DocumentMarker::kActiveSuggestion, marker->GetType()); } @@ -22,21 +24,28 @@ TEST_F(ActiveSuggestionMarkerTest, MarkerType) { TEST_F(ActiveSuggestionMarkerTest, IsStyleableMarker) { DocumentMarker* marker = MakeGarbageCollected<ActiveSuggestionMarker>( 0, 1, Color::kTransparent, ImeTextSpanThickness::kNone, + ImeTextSpanUnderlineStyle::kNone, Color::kTransparent, Color::kTransparent); EXPECT_TRUE(IsStyleableMarker(*marker)); } TEST_F(ActiveSuggestionMarkerTest, ConstructorAndGetters) { ActiveSuggestionMarker* marker = MakeGarbageCollected<ActiveSuggestionMarker>( - 0, 1, Color::kDarkGray, ImeTextSpanThickness::kThin, Color::kGray); + 0, 1, Color::kDarkGray, ImeTextSpanThickness::kThin, + ImeTextSpanUnderlineStyle::kSolid, Color::kTransparent, Color::kGray); EXPECT_EQ(Color::kDarkGray, marker->UnderlineColor()); EXPECT_FALSE(marker->HasThicknessThick()); + EXPECT_EQ(ImeTextSpanUnderlineStyle::kSolid, marker->UnderlineStyle()); + EXPECT_EQ(Color::kTransparent, marker->TextColor()); EXPECT_EQ(Color::kGray, marker->BackgroundColor()); ActiveSuggestionMarker* thick_marker = MakeGarbageCollected<ActiveSuggestionMarker>( - 0, 1, Color::kDarkGray, ImeTextSpanThickness::kThick, Color::kGray); + 0, 1, Color::kDarkGray, ImeTextSpanThickness::kThick, + ImeTextSpanUnderlineStyle::kSolid, Color::kTransparent, Color::kGray); EXPECT_EQ(true, thick_marker->HasThicknessThick()); + EXPECT_EQ(ImeTextSpanUnderlineStyle::kSolid, marker->UnderlineStyle()); + EXPECT_EQ(Color::kTransparent, marker->TextColor()); } } // namespace blink diff --git a/chromium/third_party/blink/renderer/core/editing/markers/composition_marker.cc b/chromium/third_party/blink/renderer/core/editing/markers/composition_marker.cc index 954fa2ae1e1..d35e03485f0 100644 --- a/chromium/third_party/blink/renderer/core/editing/markers/composition_marker.cc +++ b/chromium/third_party/blink/renderer/core/editing/markers/composition_marker.cc @@ -6,15 +6,20 @@ namespace blink { -CompositionMarker::CompositionMarker(unsigned start_offset, - unsigned end_offset, - Color underline_color, - ui::mojom::ImeTextSpanThickness thickness, - Color background_color) +CompositionMarker::CompositionMarker( + unsigned start_offset, + unsigned end_offset, + Color underline_color, + ui::mojom::ImeTextSpanThickness thickness, + ui::mojom::ImeTextSpanUnderlineStyle underline_style, + Color text_color, + Color background_color) : StyleableMarker(start_offset, end_offset, underline_color, thickness, + underline_style, + text_color, background_color) {} DocumentMarker::MarkerType CompositionMarker::GetType() const { diff --git a/chromium/third_party/blink/renderer/core/editing/markers/composition_marker.h b/chromium/third_party/blink/renderer/core/editing/markers/composition_marker.h index 81f853f86b5..994bb4fcbe5 100644 --- a/chromium/third_party/blink/renderer/core/editing/markers/composition_marker.h +++ b/chromium/third_party/blink/renderer/core/editing/markers/composition_marker.h @@ -20,6 +20,8 @@ class CORE_EXPORT CompositionMarker final : public StyleableMarker { unsigned end_offset, Color underline_color, ui::mojom::ImeTextSpanThickness, + ui::mojom::ImeTextSpanUnderlineStyle, + Color text_color, Color background_color); // DocumentMarker implementations diff --git a/chromium/third_party/blink/renderer/core/editing/markers/composition_marker_list_impl_test.cc b/chromium/third_party/blink/renderer/core/editing/markers/composition_marker_list_impl_test.cc index d1d3b4049c2..5760908bde2 100644 --- a/chromium/third_party/blink/renderer/core/editing/markers/composition_marker_list_impl_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/markers/composition_marker_list_impl_test.cc @@ -18,7 +18,9 @@ class CompositionMarkerListImplTest : public EditingTestBase { DocumentMarker* CreateMarker(unsigned start_offset, unsigned end_offset) { return MakeGarbageCollected<CompositionMarker>( start_offset, end_offset, Color::kTransparent, - ui::mojom::ImeTextSpanThickness::kThin, Color::kBlack); + ui::mojom::ImeTextSpanThickness::kThin, + ui::mojom::ImeTextSpanUnderlineStyle::kSolid, Color::kBlack, + Color::kBlack); } Persistent<CompositionMarkerListImpl> marker_list_; diff --git a/chromium/third_party/blink/renderer/core/editing/markers/composition_marker_test.cc b/chromium/third_party/blink/renderer/core/editing/markers/composition_marker_test.cc index 5bf0d806048..d0c8083a91d 100644 --- a/chromium/third_party/blink/renderer/core/editing/markers/composition_marker_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/markers/composition_marker_test.cc @@ -7,6 +7,7 @@ #include "testing/gtest/include/gtest/gtest.h" using ui::mojom::ImeTextSpanThickness; +using ui::mojom::ImeTextSpanUnderlineStyle; namespace blink { @@ -15,6 +16,7 @@ class CompositionMarkerTest : public testing::Test {}; TEST_F(CompositionMarkerTest, MarkerType) { DocumentMarker* marker = MakeGarbageCollected<CompositionMarker>( 0, 1, Color::kTransparent, ImeTextSpanThickness::kNone, + ImeTextSpanUnderlineStyle::kNone, Color::kTransparent, Color::kTransparent); EXPECT_EQ(DocumentMarker::kComposition, marker->GetType()); } @@ -22,20 +24,81 @@ TEST_F(CompositionMarkerTest, MarkerType) { TEST_F(CompositionMarkerTest, IsStyleableMarker) { DocumentMarker* marker = MakeGarbageCollected<CompositionMarker>( 0, 1, Color::kTransparent, ImeTextSpanThickness::kNone, + ImeTextSpanUnderlineStyle::kNone, Color::kTransparent, Color::kTransparent); EXPECT_TRUE(IsStyleableMarker(*marker)); } TEST_F(CompositionMarkerTest, ConstructorAndGetters) { CompositionMarker* marker = MakeGarbageCollected<CompositionMarker>( - 0, 1, Color::kDarkGray, ImeTextSpanThickness::kThin, Color::kGray); + 0, 1, Color::kDarkGray, ImeTextSpanThickness::kThin, + ImeTextSpanUnderlineStyle::kSolid, Color::kTransparent, Color::kGray); EXPECT_EQ(Color::kDarkGray, marker->UnderlineColor()); EXPECT_TRUE(marker->HasThicknessThin()); + EXPECT_EQ(ImeTextSpanUnderlineStyle::kSolid, marker->UnderlineStyle()); + EXPECT_EQ(Color::kTransparent, marker->TextColor()); EXPECT_EQ(Color::kGray, marker->BackgroundColor()); CompositionMarker* thick_marker = MakeGarbageCollected<CompositionMarker>( - 0, 1, Color::kDarkGray, ImeTextSpanThickness::kThick, Color::kGray); + 0, 1, Color::kDarkGray, ImeTextSpanThickness::kThick, + ImeTextSpanUnderlineStyle::kSolid, Color::kTransparent, Color::kGray); EXPECT_TRUE(thick_marker->HasThicknessThick()); + EXPECT_EQ(ImeTextSpanUnderlineStyle::kSolid, marker->UnderlineStyle()); + EXPECT_EQ(Color::kTransparent, marker->TextColor()); +} + +TEST_F(CompositionMarkerTest, UnderlineStyleDottedAndGrayText) { + CompositionMarker* marker = MakeGarbageCollected<CompositionMarker>( + 0, 1, Color::kDarkGray, ImeTextSpanThickness::kThin, + ImeTextSpanUnderlineStyle::kDot, Color::kGray, Color::kGray); + EXPECT_EQ(Color::kDarkGray, marker->UnderlineColor()); + EXPECT_TRUE(marker->HasThicknessThin()); + EXPECT_EQ(ImeTextSpanUnderlineStyle::kDot, marker->UnderlineStyle()); + EXPECT_EQ(Color::kGray, marker->TextColor()); + EXPECT_EQ(Color::kGray, marker->BackgroundColor()); + + CompositionMarker* thick_marker = MakeGarbageCollected<CompositionMarker>( + 0, 1, Color::kDarkGray, ImeTextSpanThickness::kThick, + ImeTextSpanUnderlineStyle::kDot, Color::kGray, Color::kGray); + EXPECT_TRUE(thick_marker->HasThicknessThick()); + EXPECT_EQ(ImeTextSpanUnderlineStyle::kDot, marker->UnderlineStyle()); + EXPECT_EQ(Color::kGray, marker->TextColor()); +} + +TEST_F(CompositionMarkerTest, UnderlineStyleDashed) { + CompositionMarker* marker = MakeGarbageCollected<CompositionMarker>( + 0, 1, Color::kDarkGray, ImeTextSpanThickness::kThin, + ImeTextSpanUnderlineStyle::kDash, Color::kTransparent, Color::kGray); + EXPECT_EQ(Color::kDarkGray, marker->UnderlineColor()); + EXPECT_TRUE(marker->HasThicknessThin()); + EXPECT_EQ(ImeTextSpanUnderlineStyle::kDash, marker->UnderlineStyle()); + EXPECT_EQ(Color::kTransparent, marker->TextColor()); + EXPECT_EQ(Color::kGray, marker->BackgroundColor()); + + CompositionMarker* thick_marker = MakeGarbageCollected<CompositionMarker>( + 0, 1, Color::kDarkGray, ImeTextSpanThickness::kThick, + ImeTextSpanUnderlineStyle::kDash, Color::kTransparent, Color::kGray); + EXPECT_TRUE(thick_marker->HasThicknessThick()); + EXPECT_EQ(ImeTextSpanUnderlineStyle::kDash, marker->UnderlineStyle()); + EXPECT_EQ(Color::kTransparent, marker->TextColor()); +} + +TEST_F(CompositionMarkerTest, UnderlineStyleSquiggled) { + CompositionMarker* marker = MakeGarbageCollected<CompositionMarker>( + 0, 1, Color::kDarkGray, ImeTextSpanThickness::kThin, + ImeTextSpanUnderlineStyle::kSquiggle, Color::kTransparent, Color::kGray); + EXPECT_EQ(Color::kDarkGray, marker->UnderlineColor()); + EXPECT_TRUE(marker->HasThicknessThin()); + EXPECT_EQ(ImeTextSpanUnderlineStyle::kSquiggle, marker->UnderlineStyle()); + EXPECT_EQ(Color::kTransparent, marker->TextColor()); + EXPECT_EQ(Color::kGray, marker->BackgroundColor()); + + CompositionMarker* thick_marker = MakeGarbageCollected<CompositionMarker>( + 0, 1, Color::kDarkGray, ImeTextSpanThickness::kThick, + ImeTextSpanUnderlineStyle::kSquiggle, Color::kTransparent, Color::kGray); + EXPECT_TRUE(thick_marker->HasThicknessThick()); + EXPECT_EQ(ImeTextSpanUnderlineStyle::kSquiggle, marker->UnderlineStyle()); + EXPECT_EQ(Color::kTransparent, marker->TextColor()); } } // namespace blink diff --git a/chromium/third_party/blink/renderer/core/editing/markers/document_marker_controller.cc b/chromium/third_party/blink/renderer/core/editing/markers/document_marker_controller.cc index 5df64a5db9b..e9c3deffee1 100644 --- a/chromium/third_party/blink/renderer/core/editing/markers/document_marker_controller.cc +++ b/chromium/third_party/blink/renderer/core/editing/markers/document_marker_controller.cc @@ -150,7 +150,7 @@ DocumentMarkerController::DocumentMarkerController(Document& document) void DocumentMarkerController::Clear() { markers_.clear(); possibly_existing_marker_types_ = DocumentMarker::MarkerTypes(); - SetContext(nullptr); + SetDocument(nullptr); } void DocumentMarkerController::AddSpellingMarker(const EphemeralRange& range, @@ -173,10 +173,16 @@ void DocumentMarkerController::AddTextMatchMarker( const EphemeralRange& range, TextMatchMarker::MatchStatus match_status) { DCHECK(!document_->NeedsLayoutTreeUpdate()); - AddMarkerInternal(range, [match_status](int start_offset, int end_offset) { - return MakeGarbageCollected<TextMatchMarker>(start_offset, end_offset, - match_status); - }); + AddMarkerInternal( + range, + [match_status](int start_offset, int end_offset) { + return MakeGarbageCollected<TextMatchMarker>(start_offset, end_offset, + match_status); + }, + // Since we've already determined to have a match in the given range (via + // FindBuffer), we can ignore the display lock for the purposes of finding + // where to put the marker. + TextIteratorBehavior::Builder().SetIgnoresDisplayLock(true).Build()); // Don't invalidate tickmarks here. TextFinder invalidates tickmarks using a // throttling algorithm. crbug.com/6819. } @@ -185,26 +191,34 @@ void DocumentMarkerController::AddCompositionMarker( const EphemeralRange& range, Color underline_color, ui::mojom::ImeTextSpanThickness thickness, + ui::mojom::ImeTextSpanUnderlineStyle underline_style, + Color text_color, Color background_color) { DCHECK(!document_->NeedsLayoutTreeUpdate()); - AddMarkerInternal(range, [underline_color, thickness, background_color]( - int start_offset, int end_offset) { - return MakeGarbageCollected<CompositionMarker>( - start_offset, end_offset, underline_color, thickness, background_color); - }); + AddMarkerInternal(range, + [underline_color, thickness, underline_style, text_color, + background_color](int start_offset, int end_offset) { + return MakeGarbageCollected<CompositionMarker>( + start_offset, end_offset, underline_color, thickness, + underline_style, text_color, background_color); + }); } void DocumentMarkerController::AddActiveSuggestionMarker( const EphemeralRange& range, Color underline_color, ui::mojom::ImeTextSpanThickness thickness, + ui::mojom::ImeTextSpanUnderlineStyle underline_style, + Color text_color, Color background_color) { DCHECK(!document_->NeedsLayoutTreeUpdate()); - AddMarkerInternal(range, [underline_color, thickness, background_color]( - int start_offset, int end_offset) { - return MakeGarbageCollected<ActiveSuggestionMarker>( - start_offset, end_offset, underline_color, thickness, background_color); - }); + AddMarkerInternal(range, + [underline_color, thickness, underline_style, text_color, + background_color](int start_offset, int end_offset) { + return MakeGarbageCollected<ActiveSuggestionMarker>( + start_offset, end_offset, underline_color, thickness, + underline_style, text_color, background_color); + }); } void DocumentMarkerController::AddSuggestionMarker( @@ -258,8 +272,10 @@ void DocumentMarkerController::RemoveMarkersInRange( void DocumentMarkerController::AddMarkerInternal( const EphemeralRange& range, - std::function<DocumentMarker*(int, int)> create_marker_from_offsets) { - for (TextIterator marked_text(range.StartPosition(), range.EndPosition()); + std::function<DocumentMarker*(int, int)> create_marker_from_offsets, + const TextIteratorBehavior& iterator_behavior) { + for (TextIterator marked_text(range.StartPosition(), range.EndPosition(), + iterator_behavior); !marked_text.AtEnd(); marked_text.Advance()) { const int start_offset_in_current_container = marked_text.StartOffsetInCurrentContainer(); @@ -292,7 +308,7 @@ void DocumentMarkerController::AddMarkerToNode(const Text& text, DCHECK_GE(text.length(), new_marker->EndOffset()); possibly_existing_marker_types_ = possibly_existing_marker_types_.Add( DocumentMarker::MarkerTypes(new_marker->GetType())); - SetContext(document_); + SetDocument(document_); Member<MarkerLists>& markers = markers_.insert(&text, nullptr).stored_value->value; @@ -395,7 +411,7 @@ void DocumentMarkerController::RemoveMarkersInternal( markers_.erase(&text); if (markers_.IsEmpty()) { possibly_existing_marker_types_ = DocumentMarker::MarkerTypes(); - SetContext(nullptr); + SetDocument(nullptr); } } @@ -851,7 +867,7 @@ void DocumentMarkerController::RemoveMarkersOfTypes( if (PossiblyHasMarkers(DocumentMarker::MarkerTypes::AllBut(marker_types))) return; - SetContext(nullptr); + SetDocument(nullptr); } void DocumentMarkerController::RemoveMarkersFromList( @@ -897,7 +913,7 @@ void DocumentMarkerController::RemoveMarkersFromList( markers_.erase(iterator); if (markers_.IsEmpty()) { possibly_existing_marker_types_ = DocumentMarker::MarkerTypes(); - SetContext(nullptr); + SetDocument(nullptr); } } } diff --git a/chromium/third_party/blink/renderer/core/editing/markers/document_marker_controller.h b/chromium/third_party/blink/renderer/core/editing/markers/document_marker_controller.h index 64274cd6eed..a5d7b850598 100644 --- a/chromium/third_party/blink/renderer/core/editing/markers/document_marker_controller.h +++ b/chromium/third_party/blink/renderer/core/editing/markers/document_marker_controller.h @@ -67,10 +67,14 @@ class CORE_EXPORT DocumentMarkerController final void AddCompositionMarker(const EphemeralRange&, Color underline_color, ui::mojom::ImeTextSpanThickness, + ui::mojom::ImeTextSpanUnderlineStyle, + Color text_color, Color background_color); void AddActiveSuggestionMarker(const EphemeralRange&, Color underline_color, ui::mojom::ImeTextSpanThickness, + ui::mojom::ImeTextSpanUnderlineStyle, + Color text_color, Color background_color); void AddSuggestionMarker(const EphemeralRange&, const SuggestionMarkerProperties&); @@ -166,7 +170,8 @@ class CORE_EXPORT DocumentMarkerController final private: void AddMarkerInternal( const EphemeralRange&, - std::function<DocumentMarker*(int, int)> create_marker_from_offsets); + std::function<DocumentMarker*(int, int)> create_marker_from_offsets, + const TextIteratorBehavior& iterator_behavior = {}); void AddMarkerToNode(const Text&, DocumentMarker*); using MarkerLists = HeapVector<Member<DocumentMarkerList>, diff --git a/chromium/third_party/blink/renderer/core/editing/markers/document_marker_controller_test.cc b/chromium/third_party/blink/renderer/core/editing/markers/document_marker_controller_test.cc index 5453ea97203..b2685cff5aa 100644 --- a/chromium/third_party/blink/renderer/core/editing/markers/document_marker_controller_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/markers/document_marker_controller_test.cc @@ -65,7 +65,7 @@ Text* DocumentMarkerControllerTest::CreateTextNode(const char* text_contents) { void DocumentMarkerControllerTest::MarkNodeContents(Node* node) { // Force layoutObjects to be created; TextIterator, which is used in // DocumentMarkerControllerTest::addMarker(), needs them. - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); auto range = EphemeralRange::RangeOfContents(*node); MarkerController().AddSpellingMarker(range); } @@ -73,7 +73,7 @@ void DocumentMarkerControllerTest::MarkNodeContents(Node* node) { void DocumentMarkerControllerTest::MarkNodeContentsTextMatch(Node* node) { // Force layoutObjects to be created; TextIterator, which is used in // DocumentMarkerControllerTest::addMarker(), needs them. - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); auto range = EphemeralRange::RangeOfContents(*node); MarkerController().AddTextMatchMarker(range, TextMatchMarker::MatchStatus::kActive); @@ -228,7 +228,7 @@ TEST_F(DocumentMarkerControllerTest, UpdateRenderedRects) { EXPECT_EQ(1u, rendered_rects.size()); div->setAttribute(html_names::kStyleAttr, "margin: 200px"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Vector<IntRect> new_rendered_rects = MarkerController().LayoutRectsForTextMatchMarkers(); EXPECT_EQ(1u, new_rendered_rects.size()); @@ -240,10 +240,14 @@ TEST_F(DocumentMarkerControllerTest, CompositionMarkersNotMerged) { Node* text = GetDocument().body()->firstChild()->firstChild(); MarkerController().AddCompositionMarker( EphemeralRange(Position(text, 0), Position(text, 1)), Color::kTransparent, - ui::mojom::ImeTextSpanThickness::kThin, Color::kBlack); + ui::mojom::ImeTextSpanThickness::kThin, + ui::mojom::ImeTextSpanUnderlineStyle::kSolid, Color::kBlack, + Color::kBlack); MarkerController().AddCompositionMarker( EphemeralRange(Position(text, 1), Position(text, 3)), Color::kTransparent, - ui::mojom::ImeTextSpanThickness::kThick, Color::kBlack); + ui::mojom::ImeTextSpanThickness::kThick, + ui::mojom::ImeTextSpanUnderlineStyle::kSolid, Color::kBlack, + Color::kBlack); EXPECT_EQ(2u, MarkerController().Markers().size()); } @@ -420,7 +424,7 @@ TEST_F(DocumentMarkerControllerTest, RemoveSuggestionMarkerInRangeOnFinish) { TEST_F(DocumentMarkerControllerTest, FirstMarkerIntersectingOffsetRange) { SetBodyContent("<div contenteditable>123456789</div>"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Element* div = GetDocument().QuerySelector("div"); auto* text = To<Text>(div->firstChild()); @@ -441,7 +445,7 @@ TEST_F(DocumentMarkerControllerTest, FirstMarkerIntersectingOffsetRange) { TEST_F(DocumentMarkerControllerTest, FirstMarkerIntersectingOffsetRange_collapsed) { SetBodyContent("<div contenteditable>123456789</div>"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Element* div = GetDocument().QuerySelector("div"); auto* text = To<Text>(div->firstChild()); diff --git a/chromium/third_party/blink/renderer/core/editing/markers/styleable_marker.cc b/chromium/third_party/blink/renderer/core/editing/markers/styleable_marker.cc index 51691b29762..e4bb6533c34 100644 --- a/chromium/third_party/blink/renderer/core/editing/markers/styleable_marker.cc +++ b/chromium/third_party/blink/renderer/core/editing/markers/styleable_marker.cc @@ -5,6 +5,7 @@ #include "third_party/blink/renderer/core/editing/markers/styleable_marker.h" using ui::mojom::ImeTextSpanThickness; +using ui::mojom::ImeTextSpanUnderlineStyle; namespace blink { @@ -12,11 +13,15 @@ StyleableMarker::StyleableMarker(unsigned start_offset, unsigned end_offset, Color underline_color, ImeTextSpanThickness thickness, + ImeTextSpanUnderlineStyle underline_style, + Color text_color, Color background_color) : DocumentMarker(start_offset, end_offset), underline_color_(underline_color), background_color_(background_color), - thickness_(thickness) {} + thickness_(thickness), + underline_style_(underline_style), + text_color_(text_color) {} Color StyleableMarker::UnderlineColor() const { return underline_color_; @@ -34,6 +39,14 @@ bool StyleableMarker::HasThicknessThick() const { return thickness_ == ImeTextSpanThickness::kThick; } +ui::mojom::ImeTextSpanUnderlineStyle StyleableMarker::UnderlineStyle() const { + return underline_style_; +} + +Color StyleableMarker::TextColor() const { + return text_color_; +} + bool StyleableMarker::UseTextColor() const { return thickness_ != ImeTextSpanThickness::kNone && underline_color_ == Color::kTransparent; diff --git a/chromium/third_party/blink/renderer/core/editing/markers/styleable_marker.h b/chromium/third_party/blink/renderer/core/editing/markers/styleable_marker.h index 801afb125a1..13994f2e74e 100644 --- a/chromium/third_party/blink/renderer/core/editing/markers/styleable_marker.h +++ b/chromium/third_party/blink/renderer/core/editing/markers/styleable_marker.h @@ -19,6 +19,8 @@ class CORE_EXPORT StyleableMarker : public DocumentMarker { unsigned end_offset, Color underline_color, ui::mojom::ImeTextSpanThickness, + ui::mojom::ImeTextSpanUnderlineStyle, + Color text_color, Color background_color); // StyleableMarker-specific @@ -26,13 +28,17 @@ class CORE_EXPORT StyleableMarker : public DocumentMarker { bool HasThicknessNone() const; bool HasThicknessThin() const; bool HasThicknessThick() const; + ui::mojom::ImeTextSpanUnderlineStyle UnderlineStyle() const; bool UseTextColor() const; Color BackgroundColor() const; + Color TextColor() const; private: const Color underline_color_; const Color background_color_; const ui::mojom::ImeTextSpanThickness thickness_; + const ui::mojom::ImeTextSpanUnderlineStyle underline_style_; + const Color text_color_; DISALLOW_COPY_AND_ASSIGN(StyleableMarker); }; diff --git a/chromium/third_party/blink/renderer/core/editing/markers/suggestion_marker.cc b/chromium/third_party/blink/renderer/core/editing/markers/suggestion_marker.cc index 57b25336eec..8d4ce2822ae 100644 --- a/chromium/third_party/blink/renderer/core/editing/markers/suggestion_marker.cc +++ b/chromium/third_party/blink/renderer/core/editing/markers/suggestion_marker.cc @@ -17,6 +17,8 @@ SuggestionMarker::SuggestionMarker(unsigned start_offset, end_offset, properties.UnderlineColor(), properties.Thickness(), + properties.UnderlineStyle(), + properties.TextColor(), properties.BackgroundColor()), tag_(NextTag()), suggestions_(properties.Suggestions()), diff --git a/chromium/third_party/blink/renderer/core/editing/markers/suggestion_marker_properties.cc b/chromium/third_party/blink/renderer/core/editing/markers/suggestion_marker_properties.cc index 4e446603ee3..95e2fff765b 100644 --- a/chromium/third_party/blink/renderer/core/editing/markers/suggestion_marker_properties.cc +++ b/chromium/third_party/blink/renderer/core/editing/markers/suggestion_marker_properties.cc @@ -70,4 +70,17 @@ SuggestionMarkerProperties::Builder::SetThickness( return *this; } +SuggestionMarkerProperties::Builder& +SuggestionMarkerProperties::Builder::SetUnderlineStyle( + ui::mojom::ImeTextSpanUnderlineStyle underline_style) { + data_.underline_style_ = underline_style; + return *this; +} + +SuggestionMarkerProperties::Builder& +SuggestionMarkerProperties::Builder::SetTextColor(Color text_color) { + data_.text_color_ = text_color; + return *this; +} + } // namespace blink diff --git a/chromium/third_party/blink/renderer/core/editing/markers/suggestion_marker_properties.h b/chromium/third_party/blink/renderer/core/editing/markers/suggestion_marker_properties.h index a69b47a1cff..e6d9d229be0 100644 --- a/chromium/third_party/blink/renderer/core/editing/markers/suggestion_marker_properties.h +++ b/chromium/third_party/blink/renderer/core/editing/markers/suggestion_marker_properties.h @@ -10,6 +10,7 @@ #include "third_party/blink/renderer/core/editing/markers/suggestion_marker.h" using ui::mojom::ImeTextSpanThickness; +using ui::mojom::ImeTextSpanUnderlineStyle; namespace blink { @@ -33,6 +34,8 @@ class CORE_EXPORT SuggestionMarkerProperties final { Color UnderlineColor() const { return underline_color_; } Color BackgroundColor() const { return background_color_; } ImeTextSpanThickness Thickness() const { return thickness_; } + ImeTextSpanUnderlineStyle UnderlineStyle() const { return underline_style_; } + Color TextColor() const { return text_color_; } private: SuggestionMarker::SuggestionType type_ = @@ -44,6 +47,9 @@ class CORE_EXPORT SuggestionMarkerProperties final { Color underline_color_ = Color::kTransparent; Color background_color_ = Color::kTransparent; ImeTextSpanThickness thickness_ = ImeTextSpanThickness::kThin; + ImeTextSpanUnderlineStyle underline_style_ = + ImeTextSpanUnderlineStyle::kSolid; + Color text_color_ = Color::kTransparent; }; // This class is used for building SuggestionMarkerProperties objects. @@ -63,6 +69,8 @@ class CORE_EXPORT SuggestionMarkerProperties::Builder final { Builder& SetUnderlineColor(Color); Builder& SetBackgroundColor(Color); Builder& SetThickness(ImeTextSpanThickness); + Builder& SetUnderlineStyle(ImeTextSpanUnderlineStyle); + Builder& SetTextColor(Color); private: SuggestionMarkerProperties data_; diff --git a/chromium/third_party/blink/renderer/core/editing/markers/text_match_marker_list_impl.cc b/chromium/third_party/blink/renderer/core/editing/markers/text_match_marker_list_impl.cc index 767ba9fe1a9..f9c8599dd5f 100644 --- a/chromium/third_party/blink/renderer/core/editing/markers/text_match_marker_list_impl.cc +++ b/chromium/third_party/blink/renderer/core/editing/markers/text_match_marker_list_impl.cc @@ -4,6 +4,7 @@ #include "third_party/blink/renderer/core/editing/markers/text_match_marker_list_impl.h" +#include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h" #include "third_party/blink/renderer/core/dom/node.h" #include "third_party/blink/renderer/core/dom/range.h" #include "third_party/blink/renderer/core/editing/ephemeral_range.h" @@ -11,6 +12,7 @@ #include "third_party/blink/renderer/core/editing/visible_units.h" #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/local_frame_view.h" +#include "third_party/blink/renderer/core/layout/layout_object.h" namespace blink { @@ -19,14 +21,32 @@ DocumentMarker::MarkerType TextMatchMarkerListImpl::MarkerType() const { } static void UpdateMarkerLayoutRect(const Node& node, TextMatchMarker& marker) { - const Position start_position(node, marker.StartOffset()); - const Position end_position(node, marker.EndOffset()); - EphemeralRange range(start_position, end_position); - DCHECK(node.GetDocument().GetFrame()); LocalFrameView* frame_view = node.GetDocument().GetFrame()->View(); DCHECK(frame_view); + + // If we have a locked ancestor, then the only reliable place to have a marker + // is at the locked root rect, since the elements under a locked root might + // not have up-to-date layout information. + if (auto* locked_root = + DisplayLockUtilities::HighestLockedInclusiveAncestor(node)) { + if (auto* locked_root_layout_object = locked_root->GetLayoutObject()) { + marker.SetRect(frame_view->FrameToDocument( + PhysicalRect(locked_root_layout_object->AbsoluteBoundingBoxRect()))); + } else { + // If the locked root doesn't have a layout object, then we don't have the + // information needed to place the tickmark. Set the marker rect to an + // empty rect. + marker.SetRect(PhysicalRect()); + } + return; + } + + const Position start_position(node, marker.StartOffset()); + const Position end_position(node, marker.EndOffset()); + EphemeralRange range(start_position, end_position); + marker.SetRect( frame_view->FrameToDocument(PhysicalRect(ComputeTextRect(range)))); } diff --git a/chromium/third_party/blink/renderer/core/editing/position.h b/chromium/third_party/blink/renderer/core/editing/position.h index 7584f3e90d3..c9cde1a6d58 100644 --- a/chromium/third_party/blink/renderer/core/editing/position.h +++ b/chromium/third_party/blink/renderer/core/editing/position.h @@ -184,7 +184,7 @@ class PositionTemplate { // Note: Comparison of positions require both parameters are non-null. You // should check null-position before comparing them. // TODO(yosin): We should use |Position::operator<()| instead of - // |Position::comapreTo()| to utilize |DHCECK_XX()|. + // |Position::compareTo()| to utilize |DCHECK_XX()|. int16_t CompareTo(const PositionTemplate<Strategy>&) const; bool operator<(const PositionTemplate<Strategy>&) const; bool operator<=(const PositionTemplate<Strategy>&) const; diff --git a/chromium/third_party/blink/renderer/core/editing/position_iterator.cc b/chromium/third_party/blink/renderer/core/editing/position_iterator.cc index d5a5c9e2011..eae88822ceb 100644 --- a/chromium/third_party/blink/renderer/core/editing/position_iterator.cc +++ b/chromium/third_party/blink/renderer/core/editing/position_iterator.cc @@ -39,6 +39,11 @@ bool ShouldTraverseChildren(const Node& node) { return Strategy::HasChildren(node) && !IsUserSelectContain(node); } +template <typename Strategy> +int LastOffsetForPositionIterator(const Node* node) { + return IsUserSelectContain(*node) ? 1 : Strategy::LastOffsetForEditing(node); +} + // TODO(editing-dev): We should replace usages of |parent()| in // |PositionIterator| to |selectableParentOf()|. template <typename Strategy> @@ -187,7 +192,8 @@ void PositionIteratorAlgorithm<Strategy>::Increment() { if (anchor_node_->GetLayoutObject() && !ShouldTraverseChildren<Strategy>(*anchor_node_) && - offset_in_anchor_ < Strategy::LastOffsetForEditing(anchor_node_)) { + offset_in_anchor_ < + LastOffsetForPositionIterator<Strategy>(anchor_node_)) { // Case #2. This is the next of Case #1 or #2 itself. // Position is (|anchor|, |offset_in_anchor_|). // In this case |anchor| is a leaf(E,F,C,G or H) and @@ -249,9 +255,10 @@ void PositionIteratorAlgorithm<Strategy>::Decrement() { // Let |anchor| is B and |child| is F, // next |anchor| is E and |child| is null. node_after_position_in_anchor_ = nullptr; - offset_in_anchor_ = ShouldTraverseChildren<Strategy>(*anchor_node_) - ? 0 - : Strategy::LastOffsetForEditing(anchor_node_); + offset_in_anchor_ = + ShouldTraverseChildren<Strategy>(*anchor_node_) + ? 0 + : LastOffsetForPositionIterator<Strategy>(anchor_node_); // Decrement offset of |child| or initialize if it have never been // used. if (offsets_in_anchor_node_[depth_to_anchor_node_] == kInvalidOffset) @@ -293,9 +300,10 @@ void PositionIteratorAlgorithm<Strategy>::Decrement() { // Case #2. This is a reverse of increment()::Case3-b. // Let |anchor| is B, next |anchor| is F. anchor_node_ = Strategy::LastChild(*anchor_node_); - offset_in_anchor_ = ShouldTraverseChildren<Strategy>(*anchor_node_) - ? 0 - : Strategy::LastOffsetForEditing(anchor_node_); + offset_in_anchor_ = + ShouldTraverseChildren<Strategy>(*anchor_node_) + ? 0 + : LastOffsetForPositionIterator<Strategy>(anchor_node_); // Decrement depth initializing with -1 because // |node_after_position_in_anchor_| is null so still unneeded. if (depth_to_anchor_node_ >= offsets_in_anchor_node_.size()) diff --git a/chromium/third_party/blink/renderer/core/editing/position_iterator.h b/chromium/third_party/blink/renderer/core/editing/position_iterator.h index 7a43559b737..582f22f247e 100644 --- a/chromium/third_party/blink/renderer/core/editing/position_iterator.h +++ b/chromium/third_party/blink/renderer/core/editing/position_iterator.h @@ -77,10 +77,10 @@ class PositionIteratorAlgorithm { dom_tree_version_ == anchor_node_->GetDocument().DomTreeVersion(); } - Member<Node> anchor_node_; + Node* anchor_node_ = nullptr; // If this is non-null, Strategy::Parent(*node_after_position_in_anchor_) == // anchor_node_; - Member<Node> node_after_position_in_anchor_; + Node* node_after_position_in_anchor_ = nullptr; int offset_in_anchor_; wtf_size_t depth_to_anchor_node_; // If |node_after_position_in_anchor_| is not null, diff --git a/chromium/third_party/blink/renderer/core/editing/position_iterator_test.cc b/chromium/third_party/blink/renderer/core/editing/position_iterator_test.cc index 5fa5a32f9a0..08525dd7136 100644 --- a/chromium/third_party/blink/renderer/core/editing/position_iterator_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/position_iterator_test.cc @@ -10,238 +10,110 @@ namespace blink { -class PositionIteratorTest : public EditingTestBase {}; - -// For http://crbug.com/695317 -TEST_F(PositionIteratorTest, decrementWithInputElement) { - SetBodyContent("123<input value='abc'>"); - Element* const input = GetDocument().QuerySelector("input"); - Node* const text = input->previousSibling(); - - // Decrement until start of "123" from INPUT on DOM tree - PositionIterator dom_iterator( - Position::LastPositionInNode(*GetDocument().body())); - EXPECT_EQ(Position::LastPositionInNode(*GetDocument().body()), +class PositionIteratorTest : public EditingTestBase { + protected: + void TestDecrement(const char* markup); + void TestIncrement(const char* markup); +}; + +void PositionIteratorTest::TestDecrement(const char* markup) { + SetBodyContent(markup); + const Element& element = *GetDocument().QuerySelector("#target"); + const Node* const text = element.previousSibling(); + const Element* const body = element.GetDocument().body(); + + // Decrement until start of Text "123" from |element| on DOM tree. + PositionIterator dom_iterator(Position::LastPositionInNode(*body)); + EXPECT_EQ(Position::LastPositionInNode(*body), dom_iterator.ComputePosition()); dom_iterator.Decrement(); - EXPECT_EQ(Position::AfterNode(*input), dom_iterator.ComputePosition()); + EXPECT_EQ(Position::AfterNode(element), dom_iterator.ComputePosition()); dom_iterator.Decrement(); - EXPECT_EQ(Position::BeforeNode(*input), dom_iterator.ComputePosition()); + EXPECT_EQ(Position::BeforeNode(element), dom_iterator.ComputePosition()); dom_iterator.Decrement(); - EXPECT_EQ(Position(GetDocument().body(), 1), dom_iterator.ComputePosition()); + EXPECT_EQ(Position(body, 1), dom_iterator.ComputePosition()); dom_iterator.Decrement(); EXPECT_EQ(Position(text, 3), dom_iterator.ComputePosition()); - // Decrement until start of "123" from INPUT on flat tree + // Decrement until start of Text "123" from |element| on flat tree. PositionIteratorInFlatTree flat_iterator( - PositionInFlatTree::LastPositionInNode(*GetDocument().body())); - EXPECT_EQ(PositionInFlatTree::LastPositionInNode(*GetDocument().body()), + PositionInFlatTree::LastPositionInNode(*body)); + EXPECT_EQ(PositionInFlatTree::LastPositionInNode(*body), flat_iterator.ComputePosition()); flat_iterator.Decrement(); - EXPECT_EQ(PositionInFlatTree::AfterNode(*input), + EXPECT_EQ(PositionInFlatTree::AfterNode(element), flat_iterator.ComputePosition()); flat_iterator.Decrement(); - EXPECT_EQ(PositionInFlatTree::BeforeNode(*input), + EXPECT_EQ(PositionInFlatTree::BeforeNode(element), flat_iterator.ComputePosition()); flat_iterator.Decrement(); - EXPECT_EQ(PositionInFlatTree(GetDocument().body(), 1), - flat_iterator.ComputePosition()); + EXPECT_EQ(PositionInFlatTree(body, 1), flat_iterator.ComputePosition()); flat_iterator.Decrement(); EXPECT_EQ(PositionInFlatTree(text, 3), flat_iterator.ComputePosition()); } -TEST_F(PositionIteratorTest, decrementWithSelectElement) { - SetBodyContent("123<select><option>1</option><option>2</option></select>"); - Element* const select = GetDocument().QuerySelector("select"); - Node* text = select->previousSibling(); - - // Decrement until start of "123" from SELECT on DOM tree - PositionIterator dom_iterator( - Position::LastPositionInNode(*GetDocument().body())); - EXPECT_EQ(Position::LastPositionInNode(*GetDocument().body()), - dom_iterator.ComputePosition()); - dom_iterator.Decrement(); - EXPECT_EQ(Position::AfterNode(*select), dom_iterator.ComputePosition()); - dom_iterator.Decrement(); - EXPECT_EQ(Position::AfterNode(*select), dom_iterator.ComputePosition()) - << "This is redundant result, we should not have. see " - "http://crbug.com/697283"; - dom_iterator.Decrement(); - EXPECT_EQ(Position::BeforeNode(*select), dom_iterator.ComputePosition()); - dom_iterator.Decrement(); - EXPECT_EQ(Position(GetDocument().body(), 1), dom_iterator.ComputePosition()); - dom_iterator.Decrement(); - EXPECT_EQ(Position(text, 3), dom_iterator.ComputePosition()); +void PositionIteratorTest::TestIncrement(const char* markup) { + SetBodyContent(markup); + const Element& element = *GetDocument().QuerySelector("#target"); + Node* const text = element.nextSibling(); + const Element* body = element.GetDocument().body(); - // Decrement until start of "123" from SELECT on flat tree - PositionIteratorInFlatTree flat_iterator( - PositionInFlatTree::LastPositionInNode(*GetDocument().body())); - EXPECT_EQ(PositionInFlatTree::LastPositionInNode(*GetDocument().body()), - flat_iterator.ComputePosition()); - flat_iterator.Decrement(); - EXPECT_EQ(PositionInFlatTree::AfterNode(*select), - flat_iterator.ComputePosition()); - flat_iterator.Decrement(); - EXPECT_EQ(PositionInFlatTree::BeforeNode(*select), - flat_iterator.ComputePosition()); - flat_iterator.Decrement(); - EXPECT_EQ(PositionInFlatTree(GetDocument().body(), 1), - flat_iterator.ComputePosition()); - flat_iterator.Decrement(); - EXPECT_EQ(PositionInFlatTree(text, 3), flat_iterator.ComputePosition()); -} - -// For http://crbug.com/695317 -TEST_F(PositionIteratorTest, decrementWithTextAreaElement) { - SetBodyContent("123<textarea>456</textarea>"); - Element* const textarea = GetDocument().QuerySelector("textarea"); - Node* const text = textarea->previousSibling(); - - // Decrement until end of "123" from after TEXTAREA on DOM tree - PositionIterator dom_iterator( - Position::LastPositionInNode(*GetDocument().body())); - EXPECT_EQ(Position::LastPositionInNode(*GetDocument().body()), - dom_iterator.ComputePosition()); - dom_iterator.Decrement(); - EXPECT_EQ(Position::AfterNode(*textarea), dom_iterator.ComputePosition()); - dom_iterator.Decrement(); - EXPECT_EQ(Position::BeforeNode(*textarea), dom_iterator.ComputePosition()); - dom_iterator.Decrement(); - EXPECT_EQ(Position(GetDocument().body(), 1), dom_iterator.ComputePosition()); - dom_iterator.Decrement(); - EXPECT_EQ(Position(text, 3), dom_iterator.ComputePosition()); - - // Decrement until end of "123" from after TEXTAREA on flat tree - PositionIteratorInFlatTree flat_iterator( - PositionInFlatTree::LastPositionInNode(*GetDocument().body())); - EXPECT_EQ(PositionInFlatTree::LastPositionInNode(*GetDocument().body()), - flat_iterator.ComputePosition()); - flat_iterator.Decrement(); - EXPECT_EQ(PositionInFlatTree::AfterNode(*textarea), - flat_iterator.ComputePosition()); - flat_iterator.Decrement(); - EXPECT_EQ(PositionInFlatTree::BeforeNode(*textarea), - flat_iterator.ComputePosition()); - flat_iterator.Decrement(); - EXPECT_EQ(PositionInFlatTree(GetDocument().body(), 1), - flat_iterator.ComputePosition()); - flat_iterator.Decrement(); - EXPECT_EQ(PositionInFlatTree(text, 3), flat_iterator.ComputePosition()); -} - -// For http://crbug.com/695317 -TEST_F(PositionIteratorTest, incrementWithInputElement) { - SetBodyContent("<input value='abc'>123"); - Element* const input = GetDocument().QuerySelector("input"); - Node* const text = input->nextSibling(); - - // Increment until start of "123" from INPUT on DOM tree - PositionIterator dom_iterator( - Position::FirstPositionInNode(*GetDocument().body())); - EXPECT_EQ(Position(GetDocument().body(), 0), dom_iterator.ComputePosition()); + // Increment until start of Text "123" from |element| on DOM tree. + PositionIterator dom_iterator(Position::FirstPositionInNode(*body)); + EXPECT_EQ(Position(body, 0), dom_iterator.ComputePosition()); dom_iterator.Increment(); - EXPECT_EQ(Position::BeforeNode(*input), dom_iterator.ComputePosition()); + EXPECT_EQ(Position::BeforeNode(element), dom_iterator.ComputePosition()); dom_iterator.Increment(); - EXPECT_EQ(Position::AfterNode(*input), dom_iterator.ComputePosition()); + EXPECT_EQ(Position::AfterNode(element), dom_iterator.ComputePosition()); dom_iterator.Increment(); - EXPECT_EQ(Position(GetDocument().body(), 1), dom_iterator.ComputePosition()); + EXPECT_EQ(Position(body, 1), dom_iterator.ComputePosition()); dom_iterator.Increment(); EXPECT_EQ(Position(text, 0), dom_iterator.ComputePosition()); - // Increment until start of "123" from INPUT on flat tree + // Increment until start of Text "123" from |element| on flat tree. PositionIteratorInFlatTree flat_iterator( - PositionInFlatTree::FirstPositionInNode(*GetDocument().body())); - EXPECT_EQ(PositionInFlatTree(GetDocument().body(), 0), - flat_iterator.ComputePosition()); + PositionInFlatTree::FirstPositionInNode(*body)); + EXPECT_EQ(PositionInFlatTree(body, 0), flat_iterator.ComputePosition()); flat_iterator.Increment(); - EXPECT_EQ(PositionInFlatTree::BeforeNode(*input), + EXPECT_EQ(PositionInFlatTree::BeforeNode(element), flat_iterator.ComputePosition()); flat_iterator.Increment(); - EXPECT_EQ(PositionInFlatTree::AfterNode(*input), + EXPECT_EQ(PositionInFlatTree::AfterNode(element), flat_iterator.ComputePosition()); flat_iterator.Increment(); - EXPECT_EQ(PositionInFlatTree(GetDocument().body(), 1), - flat_iterator.ComputePosition()); + EXPECT_EQ(PositionInFlatTree(body, 1), flat_iterator.ComputePosition()); flat_iterator.Increment(); EXPECT_EQ(PositionInFlatTree(text, 0), flat_iterator.ComputePosition()); } -TEST_F(PositionIteratorTest, incrementWithSelectElement) { - SetBodyContent("<select><option>1</option><option>2</option></select>123"); - Element* const select = GetDocument().QuerySelector("select"); - Node* const text = select->nextSibling(); - - // Increment until start of "123" from SELECT on DOM tree - PositionIterator dom_iterator( - Position::FirstPositionInNode(*GetDocument().body())); - EXPECT_EQ(Position(GetDocument().body(), 0), dom_iterator.ComputePosition()); - dom_iterator.Increment(); - EXPECT_EQ(Position::BeforeNode(*select), dom_iterator.ComputePosition()); - dom_iterator.Increment(); - EXPECT_EQ(Position::AfterNode(*select), dom_iterator.ComputePosition()); - dom_iterator.Increment(); - EXPECT_EQ(Position::AfterNode(*select), dom_iterator.ComputePosition()) - << "This is redundant result, we should not have. see " - "http://crbug.com/697283"; - dom_iterator.Increment(); - EXPECT_EQ(Position(GetDocument().body(), 1), dom_iterator.ComputePosition()); - dom_iterator.Increment(); - EXPECT_EQ(Position(text, 0), dom_iterator.ComputePosition()); +// For http://crbug.com/695317 +TEST_F(PositionIteratorTest, decrementWithInputElement) { + TestDecrement("123<input id=target value='abc'>"); +} - // Increment until start of "123" from SELECT on flat tree - PositionIteratorInFlatTree flat_iterator( - PositionInFlatTree::FirstPositionInNode(*GetDocument().body())); - EXPECT_EQ(PositionInFlatTree(GetDocument().body(), 0), - flat_iterator.ComputePosition()); - flat_iterator.Increment(); - EXPECT_EQ(PositionInFlatTree::BeforeNode(*select), - flat_iterator.ComputePosition()); - flat_iterator.Increment(); - EXPECT_EQ(PositionInFlatTree::AfterNode(*select), - flat_iterator.ComputePosition()); - flat_iterator.Increment(); - EXPECT_EQ(PositionInFlatTree(GetDocument().body(), 1), - flat_iterator.ComputePosition()); - flat_iterator.Increment(); - EXPECT_EQ(PositionInFlatTree(text, 0), flat_iterator.ComputePosition()); +TEST_F(PositionIteratorTest, decrementWithSelectElement) { + TestDecrement( + "123<select id=target><option>1</option><option>2</option></select>"); } // For http://crbug.com/695317 -TEST_F(PositionIteratorTest, incrementWithTextAreaElement) { - SetBodyContent("<textarea>123</textarea>456"); - Element* const textarea = GetDocument().QuerySelector("textarea"); - Node* const text = textarea->nextSibling(); - - // Increment until start of "123" from TEXTAREA on DOM tree - PositionIterator dom_iterator( - Position::FirstPositionInNode(*GetDocument().body())); - EXPECT_EQ(Position(GetDocument().body(), 0), dom_iterator.ComputePosition()); - dom_iterator.Increment(); - EXPECT_EQ(Position::BeforeNode(*textarea), dom_iterator.ComputePosition()); - dom_iterator.Increment(); - EXPECT_EQ(Position::AfterNode(*textarea), dom_iterator.ComputePosition()); - dom_iterator.Increment(); - EXPECT_EQ(Position(GetDocument().body(), 1), dom_iterator.ComputePosition()); - dom_iterator.Increment(); - EXPECT_EQ(Position(text, 0), dom_iterator.ComputePosition()); +TEST_F(PositionIteratorTest, decrementWithTextAreaElement) { + TestDecrement("123<textarea id=target>456</textarea>"); +} - // Increment until start of "123" from TEXTAREA on flat tree - PositionIteratorInFlatTree flat_iterator( - PositionInFlatTree::FirstPositionInNode(*GetDocument().body())); - EXPECT_EQ(PositionInFlatTree(GetDocument().body(), 0), - flat_iterator.ComputePosition()); - // TODO(yosin): We should not traverse inside TEXTAREA - flat_iterator.Increment(); - EXPECT_EQ(PositionInFlatTree::BeforeNode(*textarea), - flat_iterator.ComputePosition()); - flat_iterator.Increment(); - EXPECT_EQ(PositionInFlatTree::AfterNode(*textarea), - flat_iterator.ComputePosition()); - flat_iterator.Increment(); - EXPECT_EQ(PositionInFlatTree(GetDocument().body(), 1), - flat_iterator.ComputePosition()); - flat_iterator.Increment(); - EXPECT_EQ(PositionInFlatTree(text, 0), flat_iterator.ComputePosition()); +// For http://crbug.com/695317 +TEST_F(PositionIteratorTest, incrementWithInputElement) { + TestIncrement("<input id=target value='abc'>123"); +} + +TEST_F(PositionIteratorTest, incrementWithSelectElement) { + TestIncrement( + "<select id=target><option>1</option><option>2</option></select>123"); +} + +// For http://crbug.com/695317 +TEST_F(PositionIteratorTest, incrementWithTextAreaElement) { + TestIncrement("<textarea id=target>123</textarea>456"); } } // namespace blink diff --git a/chromium/third_party/blink/renderer/core/editing/relocatable_position.h b/chromium/third_party/blink/renderer/core/editing/relocatable_position.h index 796c64745db..99fa3ba0eb7 100644 --- a/chromium/third_party/blink/renderer/core/editing/relocatable_position.h +++ b/chromium/third_party/blink/renderer/core/editing/relocatable_position.h @@ -25,7 +25,7 @@ class CORE_EXPORT RelocatablePosition final { Position GetPosition() const; private: - const Member<Range> range_; + Range* const range_; DISALLOW_COPY_AND_ASSIGN(RelocatablePosition); }; diff --git a/chromium/third_party/blink/renderer/core/editing/relocatable_position_test.cc b/chromium/third_party/blink/renderer/core/editing/relocatable_position_test.cc index f72c2016c6a..b65dccd840d 100644 --- a/chromium/third_party/blink/renderer/core/editing/relocatable_position_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/relocatable_position_test.cc @@ -19,7 +19,7 @@ TEST_F(RelocatablePositionTest, position) { RelocatablePosition relocatable_position( Position(textarea, PositionAnchorType::kBeforeAnchor)); textarea->remove(); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); // RelocatablePosition should track the given Position even if its original // anchor node is moved away from the document. diff --git a/chromium/third_party/blink/renderer/core/editing/reveal_selection_scope.cc b/chromium/third_party/blink/renderer/core/editing/reveal_selection_scope.cc index f21b51312cc..18e7a3bf8cf 100644 --- a/chromium/third_party/blink/renderer/core/editing/reveal_selection_scope.cc +++ b/chromium/third_party/blink/renderer/core/editing/reveal_selection_scope.cc @@ -47,7 +47,7 @@ RevealSelectionScope::~RevealSelectionScope() { return; if (!frame_->Selection().IsAvailable()) return; - frame_->Selection().RevealSelection(ScrollAlignment::kAlignToEdgeIfNeeded, + frame_->Selection().RevealSelection(ScrollAlignment::ToEdgeIfNeeded(), kRevealExtent); } diff --git a/chromium/third_party/blink/renderer/core/editing/selection.idl b/chromium/third_party/blink/renderer/core/editing/selection.idl index c789c376c11..465a945ceab 100644 --- a/chromium/third_party/blink/renderer/core/editing/selection.idl +++ b/chromium/third_party/blink/renderer/core/editing/selection.idl @@ -67,7 +67,7 @@ [MeasureAs=SelectionExtentOffset] readonly attribute unsigned long extentOffset; // https://github.com/w3c/selection-api/issues/37 - [MeasureAs=SelectionModify] void modify([DefaultValue=Undefined] optional DOMString alter, - [DefaultValue=Undefined] optional DOMString direction, - [DefaultValue=Undefined] optional DOMString granularity); + [MeasureAs=SelectionModify] void modify(optional DOMString alter = "", + optional DOMString direction = "", + optional DOMString granularity = ""); }; diff --git a/chromium/third_party/blink/renderer/core/editing/selection_adjuster_test.cc b/chromium/third_party/blink/renderer/core/editing/selection_adjuster_test.cc index 34765590077..447cc6a84a1 100644 --- a/chromium/third_party/blink/renderer/core/editing/selection_adjuster_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/selection_adjuster_test.cc @@ -246,7 +246,7 @@ TEST_F(SelectionAdjusterTest, ShadowDistributedNodesWithoutEditingBoundary) { Element* host = GetDocument().getElementById("host"); ShadowRoot& shadow_root = host->AttachShadowRootInternal(ShadowRootType::kOpen); - shadow_root.SetInnerHTMLFromString(shadow_content); + shadow_root.setInnerHTML(shadow_content); Element* foo = GetDocument().getElementById("foo"); Element* s1 = shadow_root.QuerySelector("#s1"); @@ -312,7 +312,7 @@ TEST_F(SelectionAdjusterTest, ShadowDistributedNodesWithEditingBoundary) { Element* host = GetDocument().getElementById("host"); ShadowRoot& shadow_root = host->AttachShadowRootInternal(ShadowRootType::kOpen); - shadow_root.SetInnerHTMLFromString(shadow_content); + shadow_root.setInnerHTML(shadow_content); Element* foo = GetDocument().getElementById("foo"); Element* bar = GetDocument().getElementById("bar"); diff --git a/chromium/third_party/blink/renderer/core/editing/selection_controller.cc b/chromium/third_party/blink/renderer/core/editing/selection_controller.cc index 8a9ee855603..8ed3c295c8a 100644 --- a/chromium/third_party/blink/renderer/core/editing/selection_controller.cc +++ b/chromium/third_party/blink/renderer/core/editing/selection_controller.cc @@ -30,7 +30,7 @@ #include "third_party/blink/renderer/core/editing/selection_controller.h" #include "base/auto_reset.h" -#include "third_party/blink/public/platform/web_menu_source_type.h" +#include "third_party/blink/public/common/input/web_menu_source_type.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/events/event.h" #include "third_party/blink/renderer/core/dom/node_computed_style.h" @@ -62,7 +62,8 @@ namespace blink { SelectionController::SelectionController(LocalFrame& frame) - : frame_(&frame), + : ExecutionContextLifecycleObserver(frame.GetDocument()), + frame_(&frame), mouse_down_may_start_select_(false), mouse_down_was_single_click_in_selection_(false), mouse_down_allows_multi_click_(false), @@ -71,7 +72,7 @@ SelectionController::SelectionController(LocalFrame& frame) void SelectionController::Trace(Visitor* visitor) { visitor->Trace(frame_); visitor->Trace(original_base_in_flat_tree_); - DocumentShutdownObserver::Trace(visitor); + ExecutionContextLifecycleObserver::Trace(visitor); } namespace { @@ -123,8 +124,9 @@ bool CanMouseDownStartSelect(Node* node) { PositionInFlatTreeWithAffinity PositionWithAffinityOfHitTestResult( const HitTestResult& hit_test_result) { return FromPositionInDOMTree<EditingInFlatTreeStrategy>( - hit_test_result.InnerNode()->GetLayoutObject()->PositionForPoint( - hit_test_result.LocalPoint())); + hit_test_result.InnerPossiblyPseudoNode() + ->GetLayoutObject() + ->PositionForPoint(hit_test_result.LocalPoint())); } DocumentMarker* SpellCheckMarkerAtPosition( @@ -167,7 +169,7 @@ Document& SelectionController::GetDocument() const { return *frame_->GetDocument(); } -void SelectionController::ContextDestroyed(Document*) { +void SelectionController::ContextDestroyed() { original_base_in_flat_tree_ = PositionInFlatTreeWithAffinity(); } @@ -311,8 +313,9 @@ bool SelectionController::HandleSingleClick( DCHECK(!frame_->GetDocument()->NeedsLayoutTreeUpdate()); Node* inner_node = event.InnerNode(); - if (!(inner_node && inner_node->GetLayoutObject() && - mouse_down_may_start_select_)) + Node* inner_pseudo = event.GetHitTestResult().InnerPossiblyPseudoNode(); + if (!(inner_node && inner_node->GetLayoutObject() && inner_pseudo && + inner_pseudo->GetLayoutObject() && mouse_down_may_start_select_)) return false; // Extend the selection if the Shift key is down, unless the click is in a @@ -477,13 +480,13 @@ void SelectionController::UpdateSelectionForMouseDrag( if (!mouse_down_may_start_select_) return; - Node* target = hit_test_result.InnerNode(); + Node* target = hit_test_result.InnerPossiblyPseudoNode(); if (!target) return; // TODO(editing-dev): Use of UpdateStyleAndLayout // needs to be audited. See http://crbug.com/590369 for more details. - frame_->GetDocument()->UpdateStyleAndLayout(); + frame_->GetDocument()->UpdateStyleAndLayout(DocumentUpdateReason::kSelection); const PositionWithAffinity& raw_target_position = Selection().SelectionHasFocus() @@ -581,7 +584,7 @@ bool SelectionController::UpdateSelectionForMouseDownDispatchingSelectStart( // TODO(editing-dev): Use of UpdateStyleAndLayout // needs to be audited. See http://crbug.com/590369 for more details. - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kSelection); const SelectionInFlatTree visible_selection = CreateVisibleSelection(selection).AsSelection(); @@ -602,7 +605,7 @@ bool SelectionController::SelectClosestWordFromHitTestResult( const HitTestResult& result, AppendTrailingWhitespace append_trailing_whitespace, SelectInputEventType select_input_event_type) { - Node* const inner_node = result.InnerNode(); + Node* const inner_node = result.InnerPossiblyPseudoNode(); if (!inner_node || !inner_node->GetLayoutObject() || !inner_node->GetLayoutObject()->IsSelectable()) @@ -615,8 +618,8 @@ bool SelectionController::SelectClosestWordFromHitTestResult( HitTestResult adjusted_hit_test_result = result; if (select_input_event_type == SelectInputEventType::kTouch && result.GetImage()) { - adjusted_hit_test_result.SetNodeAndPosition(result.InnerNode(), - PhysicalOffset()); + adjusted_hit_test_result.SetNodeAndPosition( + result.InnerPossiblyPseudoNode(), PhysicalOffset()); } const PositionInFlatTreeWithAffinity pos = @@ -681,7 +684,7 @@ bool SelectionController::SelectClosestWordFromHitTestResult( void SelectionController::SelectClosestMisspellingFromHitTestResult( const HitTestResult& result, AppendTrailingWhitespace append_trailing_whitespace) { - Node* inner_node = result.InnerNode(); + Node* inner_node = result.InnerPossiblyPseudoNode(); if (!inner_node || !inner_node->GetLayoutObject()) return; @@ -830,7 +833,7 @@ void SelectionController::SetNonDirectionalSelectionIfNeeded( if (adjusted_selection.Base() != base.GetPosition() || adjusted_selection.Extent() != extent.GetPosition()) { original_base_in_flat_tree_ = base; - SetContext(&GetDocument()); + SetExecutionContext(GetDocument().ToExecutionContext()); builder.SetBaseAndExtent(adjusted_selection.Base(), adjusted_selection.Extent()); } else if (original_base.IsNotNull()) { @@ -871,7 +874,7 @@ void SelectionController::SetNonDirectionalSelectionIfNeeded( void SelectionController::SetCaretAtHitTestResult( const HitTestResult& hit_test_result) { - Node* inner_node = hit_test_result.InnerNode(); + Node* inner_node = hit_test_result.InnerPossiblyPseudoNode(); DCHECK(inner_node); const PositionInFlatTreeWithAffinity visible_hit_pos = CreateVisiblePosition( @@ -1078,7 +1081,8 @@ bool SelectionController::HandleMouseReleaseEvent( event.Event().button != WebPointerProperties::Button::kRight) { // TODO(editing-dev): Use of UpdateStyleAndLayout // needs to be audited. See http://crbug.com/590369 for more details. - frame_->GetDocument()->UpdateStyleAndLayout(); + frame_->GetDocument()->UpdateStyleAndLayout( + DocumentUpdateReason::kSelection); SelectionInFlatTree::Builder builder; Node* node = event.InnerNode(); @@ -1156,7 +1160,7 @@ bool SelectionController::HandleGestureLongPress( if (hit_test_result.IsLiveLink()) return false; - Node* inner_node = hit_test_result.InnerNode(); + Node* inner_node = hit_test_result.InnerPossiblyPseudoNode(); inner_node->GetDocument().UpdateStyleAndLayoutTree(); bool inner_node_is_selectable = HasEditableStyle(*inner_node) || inner_node->IsTextNode() || @@ -1182,15 +1186,8 @@ void SelectionController::HandleGestureTwoFingerTap( SetCaretAtHitTestResult(targeted_event.GetHitTestResult()); } -void SelectionController::HandleGestureLongTap( - const GestureEventWithHitTestResults& targeted_event) { - TRACE_EVENT0("blink", "SelectionController::handleGestureLongTap"); - - SetCaretAtHitTestResult(targeted_event.GetHitTestResult()); -} - static bool HitTestResultIsMisspelled(const HitTestResult& result) { - Node* inner_node = result.InnerNode(); + Node* inner_node = result.InnerPossiblyPseudoNode(); if (!inner_node || !inner_node->GetLayoutObject()) return false; PositionWithAffinity pos_with_affinity = @@ -1206,7 +1203,7 @@ static bool HitTestResultIsMisspelled(const HitTestResult& result) { ToPositionInFlatTree(marker_position)); } -void SelectionController::SendContextMenuEvent( +void SelectionController::UpdateSelectionForContextMenuEvent( const MouseEventWithHitTestResults& mev, const PhysicalOffset& position) { if (!Selection().IsAvailable()) @@ -1241,7 +1238,7 @@ void SelectionController::PassMousePressEventToSubframe( const MouseEventWithHitTestResults& mev) { // TODO(editing-dev): The use of UpdateStyleAndLayout // needs to be audited. See http://crbug.com/590369 for more details. - frame_->GetDocument()->UpdateStyleAndLayout(); + frame_->GetDocument()->UpdateStyleAndLayout(DocumentUpdateReason::kInput); // If we're clicking into a frame that is selected, the frame will appear // greyed out even though we're clicking on the selection. This looks diff --git a/chromium/third_party/blink/renderer/core/editing/selection_controller.h b/chromium/third_party/blink/renderer/core/editing/selection_controller.h index 20fb1033163..3b7ac5e7ed6 100644 --- a/chromium/third_party/blink/renderer/core/editing/selection_controller.h +++ b/chromium/third_party/blink/renderer/core/editing/selection_controller.h @@ -30,7 +30,6 @@ #include "base/macros.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/dom/document.h" -#include "third_party/blink/renderer/core/dom/document_shutdown_observer.h" #include "third_party/blink/renderer/core/editing/frame_selection.h" #include "third_party/blink/renderer/core/editing/position_with_affinity.h" #include "third_party/blink/renderer/core/editing/text_granularity.h" @@ -44,7 +43,7 @@ class LocalFrame; class CORE_EXPORT SelectionController final : public GarbageCollected<SelectionController>, - public DocumentShutdownObserver { + public ExecutionContextLifecycleObserver { USING_GARBAGE_COLLECTED_MIXIN(SelectionController); public: @@ -62,15 +61,14 @@ class CORE_EXPORT SelectionController final bool HandlePasteGlobalSelection(const WebMouseEvent&); bool HandleGestureLongPress(const HitTestResult&); void HandleGestureTwoFingerTap(const GestureEventWithHitTestResults&); - void HandleGestureLongTap(const GestureEventWithHitTestResults&); void UpdateSelectionForMouseDrag(const PhysicalOffset&, const PhysicalOffset&); void UpdateSelectionForMouseDrag(const HitTestResult&, const PhysicalOffset&, const PhysicalOffset&); - void SendContextMenuEvent(const MouseEventWithHitTestResults&, - const PhysicalOffset&); + void UpdateSelectionForContextMenuEvent(const MouseEventWithHitTestResults&, + const PhysicalOffset&); void PassMousePressEventToSubframe(const MouseEventWithHitTestResults&); void InitializeSelectionState(); @@ -117,10 +115,10 @@ class CORE_EXPORT SelectionController final FrameSelection& Selection() const; - // Implements |DocumentShutdownObserver|. + // Implements |ExecutionContextLifecycleObserver|. // TODO(yosin): We should relocate |original_base_in_flat_tree_| when DOM tree // changed. - void ContextDestroyed(Document*) final; + void ContextDestroyed() final; bool HandleSingleClick(const MouseEventWithHitTestResults&); bool HandleDoubleClick(const MouseEventWithHitTestResults&); diff --git a/chromium/third_party/blink/renderer/core/editing/selection_controller_test.cc b/chromium/third_party/blink/renderer/core/editing/selection_controller_test.cc index 8ad90dc4410..39db548a9d0 100644 --- a/chromium/third_party/blink/renderer/core/editing/selection_controller_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/selection_controller_test.cc @@ -161,7 +161,7 @@ TEST_F(SelectionControllerTest, setCaretAtHitTestResult) { SetBodyContent(body_content); GetDocument().GetSettings()->SetScriptEnabled(true); Element* script = GetDocument().CreateRawElement(html_names::kScriptTag); - script->SetInnerHTMLFromString( + script->setInnerHTML( "var sample = document.getElementById('sample');" "sample.addEventListener('onselectstart', " " event => elem.parentNode.removeChild(elem));"); @@ -195,7 +195,7 @@ TEST_F(SelectionControllerTest, SetCaretAtHitTestResultWithDisconnectedPosition) { GetDocument().GetSettings()->SetScriptEnabled(true); Element* script = GetDocument().CreateRawElement(html_names::kScriptTag); - script->SetInnerHTMLFromString( + script->setInnerHTML( "document.designMode = 'on';" "const selection = window.getSelection();" "const html = document.getElementsByTagName('html')[0];" diff --git a/chromium/third_party/blink/renderer/core/editing/selection_editor.cc b/chromium/third_party/blink/renderer/core/editing/selection_editor.cc index 506e7b7d146..3b89e99469c 100644 --- a/chromium/third_party/blink/renderer/core/editing/selection_editor.cc +++ b/chromium/third_party/blink/renderer/core/editing/selection_editor.cc @@ -59,8 +59,8 @@ void SelectionEditor::ClearVisibleSelection() { selection_ = SelectionInDOMTree(); cached_visible_selection_in_dom_tree_ = VisibleSelection(); cached_visible_selection_in_flat_tree_ = VisibleSelectionInFlatTree(); - cached_visible_selection_in_dom_tree_is_dirty_ = false; - cached_visible_selection_in_flat_tree_is_dirty_ = false; + cached_visible_selection_in_dom_tree_is_dirty_ = true; + cached_visible_selection_in_flat_tree_is_dirty_ = true; } void SelectionEditor::Dispose() { @@ -69,8 +69,8 @@ void SelectionEditor::Dispose() { } Document& SelectionEditor::GetDocument() const { - DCHECK(LifecycleContext()); - return *LifecycleContext(); + DCHECK(SynchronousMutationObserver::GetDocument()); + return *SynchronousMutationObserver::GetDocument(); } VisibleSelection SelectionEditor::ComputeVisibleSelectionInDOMTree() const { @@ -164,24 +164,29 @@ void SelectionEditor::DidFinishDOMMutation() { void SelectionEditor::DidAttachDocument(Document* document) { DCHECK(document); - DCHECK(!LifecycleContext()) << LifecycleContext(); + DCHECK(!SynchronousMutationObserver::GetDocument()) + << SynchronousMutationObserver::GetDocument(); +#if DCHECK_IS_ON() style_version_for_dom_tree_ = static_cast<uint64_t>(-1); style_version_for_flat_tree_ = static_cast<uint64_t>(-1); +#endif ClearVisibleSelection(); - SetContext(document); + SetDocument(document); } -void SelectionEditor::ContextDestroyed(Document*) { +void SelectionEditor::ContextDestroyed() { Dispose(); +#if DCHECK_IS_ON() style_version_for_dom_tree_ = static_cast<uint64_t>(-1); style_version_for_flat_tree_ = static_cast<uint64_t>(-1); style_version_for_absolute_bounds_ = static_cast<uint64_t>(-1); +#endif selection_ = SelectionInDOMTree(); cached_visible_selection_in_dom_tree_ = VisibleSelection(); cached_visible_selection_in_flat_tree_ = VisibleSelectionInFlatTree(); - cached_visible_selection_in_dom_tree_is_dirty_ = false; - cached_visible_selection_in_flat_tree_is_dirty_ = false; - cached_absolute_bounds_are_dirty_ = false; + cached_visible_selection_in_dom_tree_is_dirty_ = true; + cached_visible_selection_in_flat_tree_is_dirty_ = true; + cached_absolute_bounds_are_dirty_ = true; has_selection_bounds_ = false; cached_anchor_bounds_ = IntRect(); cached_focus_bounds_ = IntRect(); @@ -395,8 +400,12 @@ bool SelectionEditor::ShouldAlwaysUseDirectionalSelection() const { } bool SelectionEditor::NeedsUpdateVisibleSelection() const { - return cached_visible_selection_in_dom_tree_is_dirty_ || - style_version_for_dom_tree_ != GetDocument().StyleVersion(); +#if DCHECK_IS_ON() + // Verify that cache has been marked dirty on style changes + DCHECK(cached_visible_selection_in_dom_tree_is_dirty_ || + style_version_for_dom_tree_ == GetDocument().StyleVersion()); +#endif + return cached_visible_selection_in_dom_tree_is_dirty_; } void SelectionEditor::UpdateCachedVisibleSelectionIfNeeded() const { @@ -408,19 +417,27 @@ void SelectionEditor::UpdateCachedVisibleSelectionIfNeeded() const { AssertSelectionValid(); if (!NeedsUpdateVisibleSelection()) return; +#if DCHECK_IS_ON() style_version_for_dom_tree_ = GetDocument().StyleVersion(); +#endif cached_visible_selection_in_dom_tree_is_dirty_ = false; cached_visible_selection_in_dom_tree_ = CreateVisibleSelection(selection_); if (!cached_visible_selection_in_dom_tree_.IsNone()) return; +#if DCHECK_IS_ON() style_version_for_flat_tree_ = GetDocument().StyleVersion(); +#endif cached_visible_selection_in_flat_tree_is_dirty_ = false; cached_visible_selection_in_flat_tree_ = VisibleSelectionInFlatTree(); } bool SelectionEditor::NeedsUpdateVisibleSelectionInFlatTree() const { - return cached_visible_selection_in_flat_tree_is_dirty_ || - style_version_for_flat_tree_ != GetDocument().StyleVersion(); +#if DCHECK_IS_ON() + // Verify that cache has been marked dirty on style changes + DCHECK(cached_visible_selection_in_flat_tree_is_dirty_ || + style_version_for_flat_tree_ == GetDocument().StyleVersion()); +#endif + return cached_visible_selection_in_flat_tree_is_dirty_; } void SelectionEditor::UpdateCachedVisibleSelectionInFlatTreeIfNeeded() const { @@ -432,7 +449,9 @@ void SelectionEditor::UpdateCachedVisibleSelectionInFlatTreeIfNeeded() const { AssertSelectionValid(); if (!NeedsUpdateVisibleSelectionInFlatTree()) return; +#if DCHECK_IS_ON() style_version_for_flat_tree_ = GetDocument().StyleVersion(); +#endif cached_visible_selection_in_flat_tree_is_dirty_ = false; SelectionInFlatTree::Builder builder; const PositionInFlatTree& base = ToPositionInFlatTree(selection_.Base()); @@ -448,14 +467,20 @@ void SelectionEditor::UpdateCachedVisibleSelectionInFlatTreeIfNeeded() const { CreateVisibleSelection(builder.Build()); if (!cached_visible_selection_in_flat_tree_.IsNone()) return; +#if DCHECK_IS_ON() style_version_for_dom_tree_ = GetDocument().StyleVersion(); +#endif cached_visible_selection_in_dom_tree_is_dirty_ = false; cached_visible_selection_in_dom_tree_ = VisibleSelection(); } bool SelectionEditor::NeedsUpdateAbsoluteBounds() const { - return cached_absolute_bounds_are_dirty_ || - style_version_for_absolute_bounds_ != GetDocument().StyleVersion(); +#if DCHECK_IS_ON() + // Verify that cache has been marked dirty on style changes + DCHECK(cached_absolute_bounds_are_dirty_ || + style_version_for_absolute_bounds_ == GetDocument().StyleVersion()); +#endif + return cached_absolute_bounds_are_dirty_; } void SelectionEditor::UpdateCachedAbsoluteBoundsIfNeeded() const { @@ -471,7 +496,9 @@ void SelectionEditor::UpdateCachedAbsoluteBoundsIfNeeded() const { DocumentLifecycle::DisallowTransitionScope disallow_transition( frame_->GetDocument()->Lifecycle()); +#if DCHECK_IS_ON() style_version_for_absolute_bounds_ = GetDocument().StyleVersion(); +#endif cached_absolute_bounds_are_dirty_ = false; const VisibleSelection selection = ComputeVisibleSelectionInDOMTree(); diff --git a/chromium/third_party/blink/renderer/core/editing/selection_editor.h b/chromium/third_party/blink/renderer/core/editing/selection_editor.h index 51cf56c352a..fb05474d37f 100644 --- a/chromium/third_party/blink/renderer/core/editing/selection_editor.h +++ b/chromium/third_party/blink/renderer/core/editing/selection_editor.h @@ -62,6 +62,8 @@ class SelectionEditor final : public GarbageCollected<SelectionEditor>, Range* DocumentCachedRange() const; void ClearDocumentCachedRange(); + void MarkCacheDirty(); + void Trace(Visitor*) override; private: @@ -70,7 +72,6 @@ class SelectionEditor final : public GarbageCollected<SelectionEditor>, void AssertSelectionValid() const; void ClearVisibleSelection(); - void MarkCacheDirty(); bool ShouldAlwaysUseDirectionalSelection() const; // VisibleSelection cache related @@ -87,7 +88,7 @@ class SelectionEditor final : public GarbageCollected<SelectionEditor>, void DidFinishDOMMutation(); // Implementation of |SynchronousMutationObsderver| member functions. - void ContextDestroyed(Document*) final; + void ContextDestroyed() final; void DidChangeChildren(const ContainerNode&) final; void DidMergeTextNodes(const Text& merged_node, const NodeWithIndex& node_to_be_removed_with_index, @@ -110,17 +111,22 @@ class SelectionEditor final : public GarbageCollected<SelectionEditor>, mutable VisibleSelection cached_visible_selection_in_dom_tree_; mutable VisibleSelectionInFlatTree cached_visible_selection_in_flat_tree_; - mutable uint64_t style_version_for_dom_tree_ = static_cast<uint64_t>(-1); - mutable uint64_t style_version_for_flat_tree_ = static_cast<uint64_t>(-1); - mutable bool cached_visible_selection_in_dom_tree_is_dirty_ = false; - mutable bool cached_visible_selection_in_flat_tree_is_dirty_ = false; + mutable bool cached_visible_selection_in_dom_tree_is_dirty_ = true; + mutable bool cached_visible_selection_in_flat_tree_is_dirty_ = true; mutable IntRect cached_anchor_bounds_; mutable IntRect cached_focus_bounds_; + mutable bool cached_absolute_bounds_are_dirty_ = true; + mutable bool has_selection_bounds_ = false; + +#if DCHECK_IS_ON() + // TODO(xiaochengh): We should move these style versions into VisibleSelection + // and a new structure for absolute bounds, instead of maintaining them here. + mutable uint64_t style_version_for_dom_tree_ = static_cast<uint64_t>(-1); + mutable uint64_t style_version_for_flat_tree_ = static_cast<uint64_t>(-1); mutable uint64_t style_version_for_absolute_bounds_ = static_cast<uint64_t>(-1); - mutable bool cached_absolute_bounds_are_dirty_ = false; - mutable bool has_selection_bounds_ = false; +#endif DISALLOW_COPY_AND_ASSIGN(SelectionEditor); }; diff --git a/chromium/third_party/blink/renderer/core/editing/selection_modifier.cc b/chromium/third_party/blink/renderer/core/editing/selection_modifier.cc index 8ba37d66319..5b4c215906a 100644 --- a/chromium/third_party/blink/renderer/core/editing/selection_modifier.cc +++ b/chromium/third_party/blink/renderer/core/editing/selection_modifier.cc @@ -161,7 +161,7 @@ base::Optional<TextDirection> DirectionAt(const VisiblePosition& position) { if (NGInlineFormattingContextOf(adjusted.GetPosition())) { const NGInlineCursor& cursor = ComputeNGCaretPosition(adjusted).cursor; if (cursor) - return cursor.CurrentResolvedDirection(); + return cursor.Current().ResolvedDirection(); return base::nullopt; } @@ -185,7 +185,7 @@ base::Optional<TextDirection> LineDirectionAt(const VisiblePosition& position) { if (!line) return base::nullopt; line.MoveToContainingLine(); - return line.CurrentBaseDirection(); + return line.Current().BaseDirection(); } if (const InlineBox* box = diff --git a/chromium/third_party/blink/renderer/core/editing/selection_modifier.h b/chromium/third_party/blink/renderer/core/editing/selection_modifier.h index 1620aea5126..3aebd05b90e 100644 --- a/chromium/third_party/blink/renderer/core/editing/selection_modifier.h +++ b/chromium/third_party/blink/renderer/core/editing/selection_modifier.h @@ -111,7 +111,7 @@ class CORE_EXPORT SelectionModifier { static VisiblePosition NextParagraphPosition(const VisiblePosition&, LayoutUnit line_direction_point); - Member<const LocalFrame> frame_; + const LocalFrame* frame_; // TODO(editing-dev): We should get rid of |selection_| once we change // all member functions not to use |selection_|. // |selection_| is used as implicit parameter or a cache instead of pass it. diff --git a/chromium/third_party/blink/renderer/core/editing/selection_modifier_line.cc b/chromium/third_party/blink/renderer/core/editing/selection_modifier_line.cc index da5eabd4d9b..fffc06a48b4 100644 --- a/chromium/third_party/blink/renderer/core/editing/selection_modifier_line.cc +++ b/chromium/third_party/blink/renderer/core/editing/selection_modifier_line.cc @@ -63,11 +63,11 @@ class AbstractLineBox { return GetRootInlineBox().LogicalHeight() && GetRootInlineBox().FirstLeafChild(); } - if (cursor_.IsEmptyLineBox()) + if (cursor_.Current().IsEmptyLineBox()) return false; - const PhysicalSize physical_size = cursor_.CurrentSize(); - const LogicalSize logical_size = - physical_size.ConvertToLogical(cursor_.CurrentStyle().GetWritingMode()); + const PhysicalSize physical_size = cursor_.Current().Size(); + const LogicalSize logical_size = physical_size.ConvertToLogical( + cursor_.Current().Style().GetWritingMode()); if (!logical_size.block_size) return false; // Use |ClosestLeafChildForPoint| to check if there's any leaf child. @@ -127,7 +127,8 @@ class AbstractLineBox { return GetRootInlineBox().ClosestLeafChildForPoint( GetBlock().FlipForWritingMode(point), only_editable_leaves); } - const PhysicalOffset local_physical_point = point - cursor_.CurrentOffset(); + const PhysicalOffset local_physical_point = + point - cursor_.Current().OffsetInContainerBlock(); return ClosestLeafChildForPoint(cursor_, local_physical_point, only_editable_leaves); } @@ -138,7 +139,7 @@ class AbstractLineBox { explicit AbstractLineBox(const NGInlineCursor& cursor) : cursor_(cursor), type_(Type::kLayoutNG) { - DCHECK(cursor_.IsLineBox()); + DCHECK(cursor_.Current().IsLineBox()); } const LayoutBlockFlow& GetBlock() const { @@ -156,8 +157,9 @@ class AbstractLineBox { return GetBlock().FlipForWritingMode( GetRootInlineBox().BlockDirectionPointInLine()); } - const PhysicalOffset physical_offset = cursor_.CurrentOffset(); - return cursor_.CurrentStyle().IsHorizontalWritingMode() + const PhysicalOffset physical_offset = + cursor_.Current().OffsetInContainerBlock(); + return cursor_.Current().Style().IsHorizontalWritingMode() ? physical_offset.top : physical_offset.left; } @@ -172,7 +174,8 @@ class AbstractLineBox { } static bool IsEditable(const NGInlineCursor& cursor) { - const LayoutObject* const layout_object = cursor.CurrentLayoutObject(); + const LayoutObject* const layout_object = + cursor.Current().GetLayoutObject(); return layout_object && layout_object->GetNode() && HasEditableStyle(*layout_object->GetNode()); } @@ -183,14 +186,14 @@ class AbstractLineBox { bool only_editable_leaves) { const PhysicalSize unit_square(LayoutUnit(1), LayoutUnit(1)); const LogicalOffset logical_point = point.ConvertToLogical( - line.CurrentStyle().GetWritingMode(), line.CurrentBaseDirection(), - line.CurrentSize(), unit_square); + line.Current().Style().GetWritingMode(), line.Current().BaseDirection(), + line.Current().Size(), unit_square); const LayoutUnit inline_offset = logical_point.inline_offset; const LayoutObject* closest_leaf_child = nullptr; LayoutUnit closest_leaf_distance; NGInlineCursor cursor(line); for (cursor.MoveToNext(); cursor; cursor.MoveToNext()) { - if (!cursor.CurrentLayoutObject()) + if (!cursor.Current().GetLayoutObject()) continue; if (!cursor.IsInlineLeaf()) continue; @@ -198,21 +201,22 @@ class AbstractLineBox { continue; const LogicalRect fragment_logical_rect = - cursor.CurrentRect().ConvertToLogical( - line.CurrentStyle().GetWritingMode(), line.CurrentBaseDirection(), - line.CurrentSize(), cursor.CurrentSize()); + cursor.Current().RectInContainerBlock().ConvertToLogical( + line.Current().Style().GetWritingMode(), + line.Current().BaseDirection(), line.Current().Size(), + cursor.Current().Size()); const LayoutUnit inline_min = fragment_logical_rect.offset.inline_offset; const LayoutUnit inline_max = fragment_logical_rect.offset.inline_offset + fragment_logical_rect.size.inline_size; if (inline_offset >= inline_min && inline_offset < inline_max) - return cursor.CurrentLayoutObject(); + return cursor.Current().GetLayoutObject(); const LayoutUnit distance = inline_offset < inline_min ? inline_min - inline_offset : inline_offset - inline_max + LayoutUnit(1); if (!closest_leaf_child || distance < closest_leaf_distance) { - closest_leaf_child = cursor.CurrentLayoutObject(); + closest_leaf_child = cursor.Current().GetLayoutObject(); closest_leaf_distance = distance; } } diff --git a/chromium/third_party/blink/renderer/core/editing/selection_template.h b/chromium/third_party/blink/renderer/core/editing/selection_template.h index 80b9ff306c5..8e302f604d6 100644 --- a/chromium/third_party/blink/renderer/core/editing/selection_template.h +++ b/chromium/third_party/blink/renderer/core/editing/selection_template.h @@ -130,6 +130,7 @@ class SelectionTemplate final { private: friend class SelectionEditor; + friend class FrameSelection; enum class Direction { kNotComputed, diff --git a/chromium/third_party/blink/renderer/core/editing/serializers/create_markup_options.h b/chromium/third_party/blink/renderer/core/editing/serializers/create_markup_options.h index 109fb8a3b91..1f1a14aae6c 100644 --- a/chromium/third_party/blink/renderer/core/editing/serializers/create_markup_options.h +++ b/chromium/third_party/blink/renderer/core/editing/serializers/create_markup_options.h @@ -34,7 +34,7 @@ class CORE_EXPORT CreateMarkupOptions final { bool IsForMarkupSanitization() const { return is_for_markup_sanitization_; } private: - Member<const Node> constraining_ancestor_; + const Node* constraining_ancestor_ = nullptr; AbsoluteURLs should_resolve_urls_ = kDoNotResolveURLs; bool should_annotate_for_interchange_ = false; bool should_convert_blocks_to_inlines_ = false; diff --git a/chromium/third_party/blink/renderer/core/editing/serializers/markup_accumulator.cc b/chromium/third_party/blink/renderer/core/editing/serializers/markup_accumulator.cc index 94e5aeef795..508c0337557 100644 --- a/chromium/third_party/blink/renderer/core/editing/serializers/markup_accumulator.cc +++ b/chromium/third_party/blink/renderer/core/editing/serializers/markup_accumulator.cc @@ -45,6 +45,10 @@ namespace blink { +namespace { +const char kShadowRootAttributeName[] = "shadowroot"; +} + class MarkupAccumulator::NamespaceContext final { USING_FAST_MALLOC(MarkupAccumulator::NamespaceContext); @@ -136,8 +140,10 @@ class MarkupAccumulator::ElementSerializationData final { }; MarkupAccumulator::MarkupAccumulator(AbsoluteURLs resolve_urls_method, - SerializationType serialization_type) - : formatter_(resolve_urls_method, serialization_type) {} + SerializationType serialization_type, + IncludeShadowRoots include_shadow_roots) + : formatter_(resolve_urls_method, serialization_type), + include_shadow_roots_(include_shadow_roots) {} MarkupAccumulator::~MarkupAccumulator() = default; @@ -538,7 +544,31 @@ bool MarkupAccumulator::SerializeAsHTML() const { std::pair<Node*, Element*> MarkupAccumulator::GetAuxiliaryDOMTree( const Element& element) const { - return std::pair<Node*, Element*>(); + ShadowRoot* shadow_root = element.GetShadowRoot(); + if (!shadow_root || include_shadow_roots_ != kIncludeShadowRoots) + return std::pair<Node*, Element*>(); + DCHECK(RuntimeEnabledFeatures::DeclarativeShadowDOMEnabled()); + AtomicString shadowroot_type; + switch (shadow_root->GetType()) { + case ShadowRootType::V0: + case ShadowRootType::kUserAgent: + // Don't serialize user agent shadow roots, only explicit shadow roots. + return std::pair<Node*, Element*>(); + case ShadowRootType::kOpen: + shadowroot_type = "open"; + break; + case ShadowRootType::kClosed: + shadowroot_type = "closed"; + break; + } + // Wrap the shadowroot into a declarative Shadow DOM <template shadowroot> + // element. + auto* template_element = MakeGarbageCollected<Element>( + html_names::kTemplateTag, &(element.GetDocument())); + template_element->setAttribute( + QualifiedName(g_null_atom, kShadowRootAttributeName, g_null_atom), + shadowroot_type); + return std::pair<Node*, Element*>(shadow_root, template_element); } template <typename Strategy> diff --git a/chromium/third_party/blink/renderer/core/editing/serializers/markup_accumulator.h b/chromium/third_party/blink/renderer/core/editing/serializers/markup_accumulator.h index 0b936ae89aa..454bb5d4eff 100644 --- a/chromium/third_party/blink/renderer/core/editing/serializers/markup_accumulator.h +++ b/chromium/third_party/blink/renderer/core/editing/serializers/markup_accumulator.h @@ -46,7 +46,7 @@ class MarkupAccumulator { STACK_ALLOCATED(); public: - MarkupAccumulator(AbsoluteURLs, SerializationType); + MarkupAccumulator(AbsoluteURLs, SerializationType, IncludeShadowRoots); virtual ~MarkupAccumulator(); template <typename Strategy> @@ -59,6 +59,7 @@ class MarkupAccumulator { MarkupFormatter formatter_; StringBuilder markup_; + IncludeShadowRoots include_shadow_roots_; private: bool SerializeAsHTML() const; diff --git a/chromium/third_party/blink/renderer/core/editing/serializers/markup_formatter.cc b/chromium/third_party/blink/renderer/core/editing/serializers/markup_formatter.cc index 12badfab696..7993c70f88d 100644 --- a/chromium/third_party/blink/renderer/core/editing/serializers/markup_formatter.cc +++ b/chromium/third_party/blink/renderer/core/editing/serializers/markup_formatter.cc @@ -126,8 +126,6 @@ MarkupFormatter::MarkupFormatter(AbsoluteURLs resolve_urls_method, : resolve_urls_method_(resolve_urls_method), serialization_type_(serialization_type) {} -MarkupFormatter::~MarkupFormatter() = default; - String MarkupFormatter::ResolveURLIfNeeded(const Element& element, const Attribute& attribute) const { String value = attribute.Value(); diff --git a/chromium/third_party/blink/renderer/core/editing/serializers/markup_formatter.h b/chromium/third_party/blink/renderer/core/editing/serializers/markup_formatter.h index 48112fc4181..984cefbaa02 100644 --- a/chromium/third_party/blink/renderer/core/editing/serializers/markup_formatter.h +++ b/chromium/third_party/blink/renderer/core/editing/serializers/markup_formatter.h @@ -95,7 +95,6 @@ class MarkupFormatter final { static void AppendXMLDeclaration(StringBuilder&, const Document&); MarkupFormatter(AbsoluteURLs, SerializationType); - ~MarkupFormatter(); void AppendStartMarkup(StringBuilder&, const Node&); void AppendEndMarkup(StringBuilder&, const Element&); diff --git a/chromium/third_party/blink/renderer/core/editing/serializers/serialization.cc b/chromium/third_party/blink/renderer/core/editing/serializers/serialization.cc index f6a318053fd..21b74b91f87 100644 --- a/chromium/third_party/blink/renderer/core/editing/serializers/serialization.cc +++ b/chromium/third_party/blink/renderer/core/editing/serializers/serialization.cc @@ -56,6 +56,7 @@ #include "third_party/blink/renderer/core/html/html_body_element.h" #include "third_party/blink/renderer/core/html/html_br_element.h" #include "third_party/blink/renderer/core/html/html_div_element.h" +#include "third_party/blink/renderer/core/html/html_document.h" #include "third_party/blink/renderer/core/html/html_element.h" #include "third_party/blink/renderer/core/html/html_quote_element.h" #include "third_party/blink/renderer/core/html/html_span_element.h" @@ -66,6 +67,7 @@ #include "third_party/blink/renderer/core/loader/empty_clients.h" #include "third_party/blink/renderer/core/page/page.h" #include "third_party/blink/renderer/core/svg/svg_style_element.h" +#include "third_party/blink/renderer/core/svg/svg_use_element.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/bindings/runtime_call_stats.h" #include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h" @@ -125,7 +127,8 @@ static void CompleteURLs(DocumentFragment& fragment, const String& base_url) { static bool IsHTMLBlockElement(const Node* node) { DCHECK(node); - return IsHTMLTableCellElement(*node) || IsNonTableCellHTMLBlockElement(node); + return IsA<HTMLTableCellElement>(*node) || + IsNonTableCellHTMLBlockElement(node); } static HTMLElement* AncestorToRetainStructureAndAppearanceForBlock( @@ -446,14 +449,16 @@ DocumentFragment* CreateFragmentFromMarkupWithContext( String CreateMarkup(const Node* node, ChildrenOnly children_only, - AbsoluteURLs should_resolve_urls) { + AbsoluteURLs should_resolve_urls, + IncludeShadowRoots include_shadow_roots) { if (!node) return ""; MarkupAccumulator accumulator(should_resolve_urls, - node->GetDocument().IsHTMLDocument() + IsA<HTMLDocument>(node->GetDocument()) ? SerializationType::kHTML - : SerializationType::kXML); + : SerializationType::kXML, + include_shadow_roots); return accumulator.SerializeNodes<EditingStrategy>(*node, children_only); } @@ -609,7 +614,7 @@ DocumentFragment* CreateFragmentForInnerOuterHTML( : context_element->GetDocument(); DocumentFragment* fragment = DocumentFragment::Create(document); - if (document.IsHTMLDocument()) { + if (IsA<HTMLDocument>(document)) { fragment->ParseHTML(markup, context_element, parser_content_policy); return fragment; } @@ -768,6 +773,8 @@ static Document* CreateStagingDocumentForMarkupSanitization() { page->GetSettings().SetScriptEnabled(false); page->GetSettings().SetPluginsEnabled(false); page->GetSettings().SetAcceleratedCompositingEnabled(false); + page->GetSettings().SetParserScriptingFlagPolicy( + ParserScriptingFlagPolicy::kEnabled); LocalFrame* frame = MakeGarbageCollected<LocalFrame>( MakeGarbageCollected<EmptyLocalFrameClient>(), *page, @@ -783,7 +790,7 @@ static Document* CreateStagingDocumentForMarkupSanitization() { Document* document = frame->GetDocument(); DCHECK(document); - DCHECK(document->IsHTMLDocument()); + DCHECK(IsA<HTMLDocument>(document)); DCHECK(document->body()); document->SetIsForMarkupSanitization(true); @@ -799,6 +806,25 @@ static bool ContainsStyleElements(const DocumentFragment& fragment) { return false; } +// Returns true if any svg <use> element is removed. +static bool StripSVGUseDataURLs(Node& node) { + if (IsA<SVGUseElement>(node)) { + SVGUseElement& use = To<SVGUseElement>(node); + SVGURLReferenceResolver resolver(use.HrefString(), use.GetDocument()); + if (resolver.AbsoluteUrl().ProtocolIsData()) + node.remove(); + return true; + } + bool stripped = false; + for (Node* child = node.firstChild(); child;) { + Node* next = child->nextSibling(); + if (StripSVGUseDataURLs(*child)) + stripped = true; + child = next; + } + return stripped; +} + DocumentFragment* CreateSanitizedFragmentFromMarkupWithContext( Document& document, const String& raw_markup, @@ -819,7 +845,13 @@ DocumentFragment* CreateSanitizedFragmentFromMarkupWithContext( return nullptr; } - if (!ContainsStyleElements(*fragment)) { + bool needs_sanitization = false; + if (ContainsStyleElements(*fragment)) + needs_sanitization = true; + if (StripSVGUseDataURLs(*fragment)) + needs_sanitization = true; + + if (!needs_sanitization) { staging_document->GetPage()->WillBeDestroyed(); return CreateFragmentFromMarkupWithContext( document, raw_markup, fragment_start, fragment_end, base_url, @@ -827,7 +859,7 @@ DocumentFragment* CreateSanitizedFragmentFromMarkupWithContext( } body->appendChild(fragment); - staging_document->UpdateStyleAndLayout(); + staging_document->UpdateStyleAndLayout(DocumentUpdateReason::kEditing); // This sanitizes stylesheets in the markup into element inline styles String markup = CreateMarkup(Position::FirstPositionInNode(*body), diff --git a/chromium/third_party/blink/renderer/core/editing/serializers/serialization.h b/chromium/third_party/blink/renderer/core/editing/serializers/serialization.h index 004d323b4a8..e5d456a8d0f 100644 --- a/chromium/third_party/blink/renderer/core/editing/serializers/serialization.h +++ b/chromium/third_party/blink/renderer/core/editing/serializers/serialization.h @@ -46,6 +46,7 @@ class Node; class CSSPropertyValueSet; enum ChildrenOnly { kIncludeNode, kChildrenOnly }; +enum IncludeShadowRoots { kNoShadowRoots, kIncludeShadowRoots }; DocumentFragment* CreateFragmentFromText(const EphemeralRange& context, const String& text); @@ -85,7 +86,8 @@ void ReplaceChildrenWithText(ContainerNode*, const String&, ExceptionState&); CORE_EXPORT String CreateMarkup(const Node*, ChildrenOnly = kIncludeNode, - AbsoluteURLs = kDoNotResolveURLs); + AbsoluteURLs = kDoNotResolveURLs, + IncludeShadowRoots = kNoShadowRoots); CORE_EXPORT String CreateMarkup(const Position& start, diff --git a/chromium/third_party/blink/renderer/core/editing/serializers/styled_markup_accumulator.cc b/chromium/third_party/blink/renderer/core/editing/serializers/styled_markup_accumulator.cc index 7563aaaf2a2..b1b21ef1fe3 100644 --- a/chromium/third_party/blink/renderer/core/editing/serializers/styled_markup_accumulator.cc +++ b/chromium/third_party/blink/renderer/core/editing/serializers/styled_markup_accumulator.cc @@ -34,6 +34,7 @@ #include "third_party/blink/renderer/core/editing/editing_utilities.h" #include "third_party/blink/renderer/core/editing/ephemeral_range.h" #include "third_party/blink/renderer/core/editing/iterators/text_iterator.h" +#include "third_party/blink/renderer/core/html/html_document.h" #include "third_party/blink/renderer/platform/wtf/text/string_builder.h" namespace blink { @@ -55,8 +56,8 @@ StyledMarkupAccumulator::StyledMarkupAccumulator( Document* document, const CreateMarkupOptions& options) : formatter_(options.ShouldResolveURLs(), - document->IsHTMLDocument() ? SerializationType::kHTML - : SerializationType::kXML), + IsA<HTMLDocument>(document) ? SerializationType::kHTML + : SerializationType::kXML), start_(start), end_(end), document_(document), @@ -107,7 +108,7 @@ void StyledMarkupAccumulator::AppendTextWithInlineStyle( result_.Append("<span style=\""); MarkupFormatter::AppendAttributeValue( - result_, inline_style->Style()->AsText(), document_->IsHTMLDocument()); + result_, inline_style->Style()->AsText(), IsA<HTMLDocument>(document_)); result_.Append("\">"); } if (!ShouldAnnotate()) { @@ -141,7 +142,7 @@ void StyledMarkupAccumulator::AppendElementWithInlineStyle( StringBuilder& out, const Element& element, EditingStyle* style) { - const bool document_is_html = element.GetDocument().IsHTMLDocument(); + const bool document_is_html = IsA<HTMLDocument>(element.GetDocument()); formatter_.AppendStartTagOpen(out, element); AttributeCollection attributes = element.Attributes(); for (const auto& attribute : attributes) { @@ -194,7 +195,7 @@ void StyledMarkupAccumulator::WrapWithStyleNode(CSSPropertyValueSet* style) { StringBuilder open_tag; open_tag.Append("<div style=\""); MarkupFormatter::AppendAttributeValue(open_tag, style->AsText(), - document_->IsHTMLDocument()); + IsA<HTMLDocument>(document_)); open_tag.Append("\">"); reversed_preceding_markup_.push_back(open_tag.ToString()); diff --git a/chromium/third_party/blink/renderer/core/editing/serializers/styled_markup_accumulator.h b/chromium/third_party/blink/renderer/core/editing/serializers/styled_markup_accumulator.h index 32cda2c3669..bb1f1d8ccb6 100644 --- a/chromium/third_party/blink/renderer/core/editing/serializers/styled_markup_accumulator.h +++ b/chromium/third_party/blink/renderer/core/editing/serializers/styled_markup_accumulator.h @@ -92,7 +92,7 @@ class StyledMarkupAccumulator final { MarkupFormatter formatter_; const TextOffset start_; const TextOffset end_; - const Member<Document> document_; + Document* const document_; const CreateMarkupOptions options_; StringBuilder result_; Vector<String> reversed_preceding_markup_; diff --git a/chromium/third_party/blink/renderer/core/editing/serializers/styled_markup_serializer.cc b/chromium/third_party/blink/renderer/core/editing/serializers/styled_markup_serializer.cc index d941a65dff8..d150e8ca331 100644 --- a/chromium/third_party/blink/renderer/core/editing/serializers/styled_markup_serializer.cc +++ b/chromium/third_party/blink/renderer/core/editing/serializers/styled_markup_serializer.cc @@ -105,8 +105,8 @@ class StyledMarkupTraverser { bool ShouldSerializeUnrenderedElement(const Node&) const; StyledMarkupAccumulator* accumulator_; - Member<Node> last_closed_; - Member<EditingStyle> wrapping_style_; + Node* last_closed_; + EditingStyle* wrapping_style_; DISALLOW_COPY_AND_ASSIGN(StyledMarkupTraverser); }; @@ -135,7 +135,8 @@ StyledMarkupSerializer<Strategy>::StyledMarkupSerializer( end_(end), highest_node_to_be_serialized_(highest_node_to_be_serialized), options_(options), - last_closed_(highest_node_to_be_serialized) {} + last_closed_(highest_node_to_be_serialized), + wrapping_style_(nullptr) {} template <typename Strategy> static bool NeedInterchangeNewlineAfter( @@ -358,9 +359,9 @@ Node* StyledMarkupTraverser<Strategy>::Traverse(Node* start_node, // If |n| is a selection boundary such as <input>, traverse the child // nodes in the DOM tree instead of the flat tree. if (HandleSelectionBoundary<Strategy>(*n)) { - last_closed = StyledMarkupTraverser<EditingStrategy>(accumulator_, - last_closed_.Get()) - .Traverse(n, EditingStrategy::NextSkippingChildren(*n)); + last_closed = + StyledMarkupTraverser<EditingStrategy>(accumulator_, last_closed_) + .Traverse(n, EditingStrategy::NextSkippingChildren(*n)); next = EditingInFlatTreeStrategy::NextSkippingChildren(*n); } else { next = Strategy::Next(*n); diff --git a/chromium/third_party/blink/renderer/core/editing/serializers/styled_markup_serializer.h b/chromium/third_party/blink/renderer/core/editing/serializers/styled_markup_serializer.h index afb9bd72cec..115207de85d 100644 --- a/chromium/third_party/blink/renderer/core/editing/serializers/styled_markup_serializer.h +++ b/chromium/third_party/blink/renderer/core/editing/serializers/styled_markup_serializer.h @@ -59,10 +59,10 @@ class StyledMarkupSerializer final { const PositionTemplate<Strategy> start_; const PositionTemplate<Strategy> end_; - const Member<Node> highest_node_to_be_serialized_; + Node* const highest_node_to_be_serialized_; const CreateMarkupOptions options_; - Member<Node> last_closed_; - Member<EditingStyle> wrapping_style_; + Node* last_closed_; + EditingStyle* wrapping_style_; }; extern template class StyledMarkupSerializer<EditingStrategy>; diff --git a/chromium/third_party/blink/renderer/core/editing/serializers/text_offset.h b/chromium/third_party/blink/renderer/core/editing/serializers/text_offset.h index f5367f7190a..27c96b8cb1e 100644 --- a/chromium/third_party/blink/renderer/core/editing/serializers/text_offset.h +++ b/chromium/third_party/blink/renderer/core/editing/serializers/text_offset.h @@ -20,14 +20,14 @@ class TextOffset { TextOffset(Text*, int); TextOffset(const TextOffset&); - Text* GetText() const { return text_.Get(); } + Text* GetText() const { return text_; } int Offset() const { return offset_; } bool IsNull() const; bool IsNotNull() const; private: - Member<Text> text_; + Text* text_ = nullptr; int offset_; }; diff --git a/chromium/third_party/blink/renderer/core/editing/spellcheck/cold_mode_spell_check_requester.cc b/chromium/third_party/blink/renderer/core/editing/spellcheck/cold_mode_spell_check_requester.cc index a01a37b8201..1821a5e93fc 100644 --- a/chromium/third_party/blink/renderer/core/editing/spellcheck/cold_mode_spell_check_requester.cc +++ b/chromium/third_party/blink/renderer/core/editing/spellcheck/cold_mode_spell_check_requester.cc @@ -78,7 +78,8 @@ void ColdModeSpellCheckRequester::Invoke(IdleDeadline* deadline) { TRACE_EVENT0("blink", "ColdModeSpellCheckRequester::invoke"); // TODO(xiaochengh): Figure out if this has any performance impact. - GetFrame().GetDocument()->UpdateStyleAndLayout(); + GetFrame().GetDocument()->UpdateStyleAndLayout( + DocumentUpdateReason::kSpellCheck); const Element* current_focused = CurrentFocusedEditable(); if (!current_focused) { diff --git a/chromium/third_party/blink/renderer/core/editing/spellcheck/hot_mode_spell_check_requester.cc b/chromium/third_party/blink/renderer/core/editing/spellcheck/hot_mode_spell_check_requester.cc index 6a97ae4a32e..28b2d10dfa7 100644 --- a/chromium/third_party/blink/renderer/core/editing/spellcheck/hot_mode_spell_check_requester.cc +++ b/chromium/third_party/blink/renderer/core/editing/spellcheck/hot_mode_spell_check_requester.cc @@ -96,7 +96,7 @@ EphemeralRange CalculateHotModeCheckingRange(const Element& editable, HotModeSpellCheckRequester::HotModeSpellCheckRequester( SpellCheckRequester& requester) - : requester_(requester) {} + : requester_(&requester) {} void HotModeSpellCheckRequester::CheckSpellingAt(const Position& position) { const Element* root_editable = RootEditableElementOf(position); diff --git a/chromium/third_party/blink/renderer/core/editing/spellcheck/hot_mode_spell_check_requester.h b/chromium/third_party/blink/renderer/core/editing/spellcheck/hot_mode_spell_check_requester.h index 2d9971fb821..c1c667f342c 100644 --- a/chromium/third_party/blink/renderer/core/editing/spellcheck/hot_mode_spell_check_requester.h +++ b/chromium/third_party/blink/renderer/core/editing/spellcheck/hot_mode_spell_check_requester.h @@ -25,7 +25,7 @@ class HotModeSpellCheckRequester { private: HeapVector<Member<const Element>> processed_root_editables_; - Member<SpellCheckRequester> requester_; + SpellCheckRequester* requester_; DISALLOW_COPY_AND_ASSIGN(HotModeSpellCheckRequester); }; diff --git a/chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.cc b/chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.cc index 66d209feb0b..c3bda605135 100644 --- a/chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.cc +++ b/chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.cc @@ -5,7 +5,7 @@ #include "third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.h" #include "third_party/blink/public/platform/task_type.h" -#include "third_party/blink/renderer/core/dom/idle_request_options.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_idle_request_options.h" #include "third_party/blink/renderer/core/editing/commands/undo_stack.h" #include "third_party/blink/renderer/core/editing/commands/undo_step.h" #include "third_party/blink/renderer/core/editing/editing_utilities.h" @@ -63,7 +63,7 @@ IdleSpellCheckController::~IdleSpellCheckController() = default; void IdleSpellCheckController::Trace(Visitor* visitor) { visitor->Trace(frame_); visitor->Trace(cold_mode_requester_); - DocumentShutdownObserver::Trace(visitor); + ExecutionContextLifecycleObserver::Trace(visitor); } IdleSpellCheckController::IdleSpellCheckController(LocalFrame& frame) @@ -161,7 +161,7 @@ void IdleSpellCheckController::HotModeInvocation(IdleDeadline* deadline) { TRACE_EVENT0("blink", "IdleSpellCheckController::hotModeInvocation"); // TODO(xiaochengh): Figure out if this has any performance impact. - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing); HotModeSpellCheckRequester requester(GetSpellCheckRequester()); @@ -212,10 +212,10 @@ void IdleSpellCheckController::Invoke(IdleDeadline* deadline) { } void IdleSpellCheckController::DidAttachDocument(Document* document) { - SetContext(document); + SetExecutionContext(document->ToExecutionContext()); } -void IdleSpellCheckController::ContextDestroyed(Document*) { +void IdleSpellCheckController::ContextDestroyed() { Deactivate(); } diff --git a/chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.h b/chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.h index c380d5fecdf..171a8adc367 100644 --- a/chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.h +++ b/chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.h @@ -6,9 +6,9 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_SPELLCHECK_IDLE_SPELL_CHECK_CONTROLLER_H_ #include "third_party/blink/renderer/core/dom/document.h" -#include "third_party/blink/renderer/core/dom/document_shutdown_observer.h" #include "third_party/blink/renderer/core/dom/scripted_idle_task_controller.h" #include "third_party/blink/renderer/core/editing/forward.h" +#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h" #include "third_party/blink/renderer/platform/timer.h" namespace blink { @@ -29,7 +29,7 @@ class SpellCheckRequester; // See design doc for details: https://goo.gl/zONC3v class CORE_EXPORT IdleSpellCheckController final : public GarbageCollected<IdleSpellCheckController>, - public DocumentShutdownObserver { + public ExecutionContextLifecycleObserver { DISALLOW_COPY_AND_ASSIGN(IdleSpellCheckController); USING_GARBAGE_COLLECTED_MIXIN(IdleSpellCheckController); @@ -70,12 +70,12 @@ class CORE_EXPORT IdleSpellCheckController final LocalFrame& GetFrame() const { return *frame_; } // Returns whether there is an active document to work on. - bool IsAvailable() const { return LifecycleContext(); } + bool IsAvailable() const { return GetExecutionContext(); } // Return the document to work on. Callable only when IsAvailable() is true. Document& GetDocument() const { DCHECK(IsAvailable()); - return *LifecycleContext(); + return *Document::From(GetExecutionContext()); } // Returns whether spell checking is globally enabled. @@ -95,8 +95,8 @@ class CORE_EXPORT IdleSpellCheckController final void ColdModeTimerFired(TimerBase*); void ColdModeInvocation(IdleDeadline*); - // Implements |DocumentShutdownObserver|. - void ContextDestroyed(Document*) final; + // Implements |ExecutionContextLifecycleObserver|. + void ContextDestroyed() final; void DisposeIdleCallback(); diff --git a/chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller_test.cc b/chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller_test.cc index e0f8e8dee28..fb13b4cac86 100644 --- a/chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller_test.cc @@ -7,6 +7,7 @@ #include "third_party/blink/renderer/core/dom/element.h" #include "third_party/blink/renderer/core/editing/spellcheck/spell_check_test_base.h" #include "third_party/blink/renderer/core/editing/spellcheck/spell_checker.h" +#include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/html/html_object_element.h" @@ -115,25 +116,25 @@ TEST_F(IdleSpellCheckControllerTest, ColdModeToInactive) { TEST_F(IdleSpellCheckControllerTest, DetachWhenInactive) { TransitTo(State::kInactive); - GetDocument().Shutdown(); + GetFrame().DomWindow()->FrameDestroyed(); EXPECT_EQ(State::kInactive, IdleChecker().GetState()); } TEST_F(IdleSpellCheckControllerTest, DetachWhenHotModeRequested) { TransitTo(State::kHotModeRequested); - GetDocument().Shutdown(); + GetFrame().DomWindow()->FrameDestroyed(); EXPECT_EQ(State::kInactive, IdleChecker().GetState()); } TEST_F(IdleSpellCheckControllerTest, DetachWhenColdModeTimerStarted) { TransitTo(State::kColdModeTimerStarted); - GetDocument().Shutdown(); + GetFrame().DomWindow()->FrameDestroyed(); EXPECT_EQ(State::kInactive, IdleChecker().GetState()); } TEST_F(IdleSpellCheckControllerTest, DetachWhenColdModeRequested) { TransitTo(State::kColdModeRequested); - GetDocument().Shutdown(); + GetFrame().DomWindow()->FrameDestroyed(); EXPECT_EQ(State::kInactive, IdleChecker().GetState()); } diff --git a/chromium/third_party/blink/renderer/core/editing/spellcheck/spell_checker.cc b/chromium/third_party/blink/renderer/core/editing/spellcheck/spell_checker.cc index e110e675994..d5b3c0c0f19 100644 --- a/chromium/third_party/blink/renderer/core/editing/spellcheck/spell_checker.cc +++ b/chromium/third_party/blink/renderer/core/editing/spellcheck/spell_checker.cc @@ -221,7 +221,9 @@ void SpellChecker::AdvanceToNextMisspelling(bool start_before_selection) { FindFirstMisspelling(spelling_search_start, spelling_search_end); } - if (!misspelled_word.IsEmpty()) { + if (misspelled_word.IsEmpty()) { + SpellCheckPanelHostClient().UpdateSpellingUIWithMisspelledWord({}); + } else { // We found a misspelling. Select the misspelling, update the spelling // panel, and store a marker so we draw the red squiggle later. @@ -303,10 +305,8 @@ void SpellChecker::MarkAndReplaceFor( // TODO(editing-dev): The use of UpdateStyleAndLayout // needs to be audited. See http://crbug.com/590369 for more details. - GetFrame().GetDocument()->UpdateStyleAndLayout(); - - DocumentLifecycle::DisallowTransitionScope disallow_transition( - GetFrame().GetDocument()->Lifecycle()); + GetFrame().GetDocument()->UpdateStyleAndLayout( + DocumentUpdateReason::kSpellCheck); EphemeralRange checking_range(request->CheckingRange()); @@ -490,7 +490,7 @@ void SpellChecker::ReplaceMisspelledRange(const String& text) { // TODO(editing-dev): The use of UpdateStyleAndLayout // needs to be audited. See http://crbug.com/590369 for more details. - current_document.UpdateStyleAndLayout(); + current_document.UpdateStyleAndLayout(DocumentUpdateReason::kSpellCheck); // Dispatch 'beforeinput'. Element* const target = FindEventTargetFrom( @@ -510,7 +510,8 @@ void SpellChecker::ReplaceMisspelledRange(const String& text) { // TODO(editing-dev): The use of UpdateStyleAndLayout // needs to be audited. See http://crbug.com/590369 for more details. - GetFrame().GetDocument()->UpdateStyleAndLayout(); + GetFrame().GetDocument()->UpdateStyleAndLayout( + DocumentUpdateReason::kSpellCheck); if (cancel) return; @@ -545,9 +546,9 @@ static Node* FindFirstMarkable(Node* node) { return nullptr; if (node->GetLayoutObject()->IsText()) return node; - if (node->GetLayoutObject()->IsTextControl()) - node = ToLayoutTextControl(node->GetLayoutObject()) - ->GetTextControlElement() + if (auto* text_control = + DynamicTo<LayoutTextControl>(node->GetLayoutObject())) + node = text_control->GetTextControlElement() ->VisiblePositionForIndex(1) .DeepEquivalent() .AnchorNode(); diff --git a/chromium/third_party/blink/renderer/core/editing/spellcheck/spell_checker_test.cc b/chromium/third_party/blink/renderer/core/editing/spellcheck/spell_checker_test.cc index de50eee1b3c..cc7882e46be 100644 --- a/chromium/third_party/blink/renderer/core/editing/spellcheck/spell_checker_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/spellcheck/spell_checker_test.cc @@ -35,7 +35,7 @@ void SpellCheckerTest::ForceLayout() { frame_rect.SetWidth(frame_rect.Width() + 1); frame_rect.SetHeight(frame_rect.Height() + 1); Page().GetFrameView().SetFrameRect(frame_rect); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); } TEST_F(SpellCheckerTest, AdvanceToNextMisspellingWithEmptyInputNoCrash) { @@ -83,7 +83,7 @@ TEST_F(SpellCheckerTest, SpellCheckDoesNotCauseUpdateLayout) { auto* input = To<HTMLInputElement>(GetDocument().QuerySelector("input")); input->focus(); input->setValue("Hello, input field"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Position new_position(input->InnerEditorElement()->firstChild(), 3); GetDocument().GetFrame()->Selection().SetSelectionAndEndTyping( diff --git a/chromium/third_party/blink/renderer/core/editing/state_machines/state_machine_util.cc b/chromium/third_party/blink/renderer/core/editing/state_machines/state_machine_util.cc index 9f3c4eb386f..13d35c58583 100644 --- a/chromium/third_party/blink/renderer/core/editing/state_machines/state_machine_util.cc +++ b/chromium/third_party/blink/renderer/core/editing/state_machines/state_machine_util.cc @@ -38,7 +38,7 @@ bool IsIndicSyllabicCategoryVirama(uint32_t code_point) { bool IsGraphemeBreak(UChar32 prev_code_point, UChar32 next_code_point) { // The following breaking rules come from Unicode Standard Annex #29 on - // Unicode Text Segmaentation. See http://www.unicode.org/reports/tr29/ + // Unicode Text Segmentation. See http://www.unicode.org/reports/tr29/ int prev_prop = u_getIntPropertyValue(prev_code_point, UCHAR_GRAPHEME_CLUSTER_BREAK); int next_prop = @@ -85,6 +85,13 @@ bool IsGraphemeBreak(UChar32 prev_code_point, UChar32 next_code_point) { Character::IsRegionalIndicator(next_code_point)) NOTREACHED() << "Do not use this function for regional indicators."; + // This is an exception for Myanmar IMEs that uses zwnj character as base + // character during a composition to avoid merging the actively composed text + // into the previous character. We intentionally diverge from UAX#29. + // Please see crbug.com/1027695 for more details. + if (next_code_point == kZeroWidthNonJoinerCharacter) + return true; + // Rule GB9, x (Extend | ZWJ) // Rule GB9a, x SpacingMark if (next_prop == U_GCB_EXTEND || diff --git a/chromium/third_party/blink/renderer/core/editing/state_machines/state_machine_util_test.cc b/chromium/third_party/blink/renderer/core/editing/state_machines/state_machine_util_test.cc index 3a1c58751d3..f473c1f8b7e 100644 --- a/chromium/third_party/blink/renderer/core/editing/state_machines/state_machine_util_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/state_machines/state_machine_util_test.cc @@ -168,4 +168,10 @@ TEST(StateMachineUtilTest, IsGraphmeBreak_IndicSyllabicCategoryVirama) { EXPECT_TRUE(IsGraphemeBreak(kTamilVirama, kDevangariKa)); } +TEST(StateMachineUtilTest, IsGraphmeBreak_ZWNJSequecne) { + // U+200C (kZeroWidthNonJoinerCharacter) + EXPECT_TRUE(IsGraphemeBreak('a', WTF::unicode::kZeroWidthNonJoinerCharacter)); + EXPECT_TRUE(IsGraphemeBreak(WTF::unicode::kZeroWidthNonJoinerCharacter, 'a')); +} + } // namespace blink diff --git a/chromium/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.cc b/chromium/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.cc index 75b21990cd5..748094ca5cf 100644 --- a/chromium/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.cc +++ b/chromium/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.cc @@ -152,8 +152,8 @@ SuggestionInfosWithNodeAndHighlightColor ComputeSuggestionInfos( Vector<TextSuggestionInfo>& suggestion_infos = suggestion_infos_with_node_and_highlight_color.suggestion_infos; - for (const std::pair<const Text*, DocumentMarker*>& node_marker_pair : - node_suggestion_marker_pairs_sorted_by_length) { + for (const std::pair<Member<const Text>, Member<DocumentMarker>>& + node_marker_pair : node_suggestion_marker_pairs_sorted_by_length) { if (node_marker_pair.first != suggestion_infos_with_node_and_highlight_color.text_node) continue; @@ -161,7 +161,7 @@ SuggestionInfosWithNodeAndHighlightColor ComputeSuggestionInfos( if (suggestion_infos.size() == max_number_of_suggestions) break; - const auto* marker = To<SuggestionMarker>(node_marker_pair.second); + const auto* marker = To<SuggestionMarker>(node_marker_pair.second.Get()); const Vector<String>& marker_suggestions = marker->Suggestions(); for (wtf_size_t suggestion_index = 0; suggestion_index < marker_suggestions.size(); ++suggestion_index) { @@ -197,7 +197,7 @@ TextSuggestionController::TextSuggestionController(LocalFrame& frame) void TextSuggestionController::DidAttachDocument(Document* document) { DCHECK(document); - SetContext(document); + SetExecutionContext(document->ToExecutionContext()); } bool TextSuggestionController::IsMenuOpen() const { @@ -206,8 +206,18 @@ bool TextSuggestionController::IsMenuOpen() const { void TextSuggestionController::HandlePotentialSuggestionTap( const PositionInFlatTree& caret_position) { + if (!IsAvailable()) { + // TODO(crbug.com/1054955): We should fix caller not to make this happens. + NOTREACHED(); + return; + } + if (GetFrame() != GetDocument().GetFrame()) { + // TODO(crbug.com/1054955): We should fix caller not to make this happens. + NOTREACHED(); + return; + } // TODO(crbug.com/779126): add support for suggestions in immersive mode. - if (GetDocument().GetSettings()->GetImmersiveModeEnabled()) + if (GetFrame().GetSettings()->GetImmersiveModeEnabled()) return; // It's theoretically possible, but extremely unlikely, that the user has @@ -243,7 +253,7 @@ void TextSuggestionController::HandlePotentialSuggestionTap( void TextSuggestionController::Trace(Visitor* visitor) { visitor->Trace(frame_); - DocumentShutdownObserver::Trace(visitor); + ExecutionContextLifecycleObserver::Trace(visitor); } void TextSuggestionController::ReplaceActiveSuggestionRange( @@ -420,6 +430,7 @@ void TextSuggestionController::ShowSpellCheckMenu( GetDocument().Markers().AddActiveSuggestionMarker( active_suggestion_range, SK_ColorTRANSPARENT, ui::mojom::ImeTextSpanThickness::kNone, + ui::mojom::ImeTextSpanUnderlineStyle::kSolid, SK_ColorTRANSPARENT, LayoutTheme::GetTheme().PlatformActiveSpellingMarkerHighlightColor()); Vector<String> suggestions; @@ -485,6 +496,7 @@ void TextSuggestionController::ShowSuggestionMenu( GetDocument().Markers().AddActiveSuggestionMarker( marker_range, SK_ColorTRANSPARENT, ui::mojom::ImeTextSpanThickness::kThin, + ui::mojom::ImeTextSpanUnderlineStyle::kSolid, SK_ColorTRANSPARENT, suggestion_infos_with_node_and_highlight_color.highlight_color); is_suggestion_menu_open_ = true; @@ -523,11 +535,11 @@ void TextSuggestionController::CallMojoShowTextSuggestionMenu( Document& TextSuggestionController::GetDocument() const { DCHECK(IsAvailable()); - return *LifecycleContext(); + return *Document::From(GetExecutionContext()); } bool TextSuggestionController::IsAvailable() const { - return LifecycleContext(); + return GetExecutionContext(); } LocalFrame& TextSuggestionController::GetFrame() const { @@ -612,7 +624,8 @@ void TextSuggestionController::ReplaceRangeWithText(const EphemeralRange& range, // available or not. // TODO(editing-dev): The use of UpdateStyleAndLayout // needs to be audited. See http://crbug.com/590369 for more details. - GetFrame().GetDocument()->UpdateStyleAndLayout(); + GetFrame().GetDocument()->UpdateStyleAndLayout( + DocumentUpdateReason::kSpellCheck); // Dispatch 'beforeinput'. Element* const target = FindEventTargetFrom( @@ -634,7 +647,8 @@ void TextSuggestionController::ReplaceRangeWithText(const EphemeralRange& range, // TODO(editing-dev): The use of UpdateStyleAndLayout // needs to be audited. See http://crbug.com/590369 for more details. - GetFrame().GetDocument()->UpdateStyleAndLayout(); + GetFrame().GetDocument()->UpdateStyleAndLayout( + DocumentUpdateReason::kSpellCheck); if (is_canceled) return; diff --git a/chromium/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.h b/chromium/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.h index 61702afe3e0..29b70a243ef 100644 --- a/chromium/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.h +++ b/chromium/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.h @@ -10,9 +10,9 @@ #include "third_party/blink/public/mojom/input/input_host.mojom-blink.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/dom/document.h" -#include "third_party/blink/renderer/core/dom/document_shutdown_observer.h" #include "third_party/blink/renderer/core/editing/forward.h" #include "third_party/blink/renderer/core/editing/markers/document_marker.h" +#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h" #include "third_party/blink/renderer/platform/heap/handle.h" namespace blink { @@ -27,7 +27,7 @@ struct TextSuggestionInfo; // suggestions. Android is currently the only platform that has such a menu. class CORE_EXPORT TextSuggestionController final : public GarbageCollected<TextSuggestionController>, - public DocumentShutdownObserver { + public ExecutionContextLifecycleObserver { USING_GARBAGE_COLLECTED_MIXIN(TextSuggestionController); public: @@ -46,6 +46,9 @@ class CORE_EXPORT TextSuggestionController final void OnSuggestionMenuClosed(); void SuggestionMenuTimeoutCallback(size_t max_number_of_suggestions); + // ExecutionContextLifecycleObserver methods: + void ContextDestroyed() override {} + void Trace(Visitor*) override; private: diff --git a/chromium/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller_test.cc b/chromium/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller_test.cc index 65ca6e7f00d..d2a6e5a1f8a 100644 --- a/chromium/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller_test.cc @@ -12,8 +12,10 @@ #include "third_party/blink/renderer/core/editing/spellcheck/spell_checker.h" #include "third_party/blink/renderer/core/editing/testing/editing_test_base.h" #include "third_party/blink/renderer/core/editing/visible_selection.h" +#include "third_party/blink/renderer/core/frame/local_dom_window.h" using ui::mojom::ImeTextSpanThickness; +using ui::mojom::ImeTextSpanUnderlineStyle; namespace blink { @@ -56,7 +58,8 @@ TEST_F(TextSuggestionControllerTest, ApplySpellCheckSuggestion) { GetDocument().Markers().AddActiveSuggestionMarker( EphemeralRange(Position(text, 0), Position(text, 8)), Color::kBlack, - ImeTextSpanThickness::kThin, Color::kBlack); + ImeTextSpanThickness::kThin, ImeTextSpanUnderlineStyle::kSolid, + Color::kBlack, Color::kBlack); // Select immediately before misspelling GetDocument().GetFrame()->Selection().SetSelectionAndEndTyping( SelectionInDOMTree::Builder() @@ -237,7 +240,8 @@ TEST_F(TextSuggestionControllerTest, DeleteActiveSuggestionRange_DeleteAtEnd) { // Mark "word2" as the active suggestion range GetDocument().Markers().AddActiveSuggestionMarker( EphemeralRange(Position(text, 6), Position(text, 11)), - Color::kTransparent, ImeTextSpanThickness::kThin, Color::kBlack); + Color::kTransparent, ImeTextSpanThickness::kThin, + ImeTextSpanUnderlineStyle::kSolid, Color::kBlack, Color::kBlack); // Select immediately before word2 GetDocument().GetFrame()->Selection().SetSelectionAndEndTyping( SelectionInDOMTree::Builder() @@ -263,7 +267,8 @@ TEST_F(TextSuggestionControllerTest, // Mark "word2" as the active suggestion range GetDocument().Markers().AddActiveSuggestionMarker( EphemeralRange(Position(text, 6), Position(text, 11)), - Color::kTransparent, ImeTextSpanThickness::kThin, Color::kBlack); + Color::kTransparent, ImeTextSpanThickness::kThin, + ImeTextSpanUnderlineStyle::kSolid, Color::kBlack, Color::kBlack); // Select immediately before word2 GetDocument().GetFrame()->Selection().SetSelectionAndEndTyping( SelectionInDOMTree::Builder() @@ -290,7 +295,8 @@ TEST_F(TextSuggestionControllerTest, // Mark "word1" as the active suggestion range GetDocument().Markers().AddActiveSuggestionMarker( EphemeralRange(Position(text, 0), Position(text, 5)), Color::kTransparent, - ImeTextSpanThickness::kThin, Color::kBlack); + ImeTextSpanThickness::kThin, ImeTextSpanUnderlineStyle::kSolid, + Color::kBlack, Color::kBlack); // Select immediately before word1 GetDocument().GetFrame()->Selection().SetSelectionAndEndTyping( SelectionInDOMTree::Builder() @@ -318,7 +324,8 @@ TEST_F(TextSuggestionControllerTest, // Mark "word1" as the active suggestion range GetDocument().Markers().AddActiveSuggestionMarker( EphemeralRange(Position(text, 0), Position(text, 5)), Color::kTransparent, - ImeTextSpanThickness::kThin, Color::kBlack); + ImeTextSpanThickness::kThin, ImeTextSpanUnderlineStyle::kSolid, + Color::kBlack, Color::kBlack); // Select immediately before word1 GetDocument().GetFrame()->Selection().SetSelectionAndEndTyping( SelectionInDOMTree::Builder() @@ -349,7 +356,8 @@ TEST_F(TextSuggestionControllerTest, // Mark "word2" as the active suggestion range GetDocument().Markers().AddActiveSuggestionMarker( EphemeralRange(Position(text, 5), Position(text, 10)), - Color::kTransparent, ImeTextSpanThickness::kThin, Color::kBlack); + Color::kTransparent, ImeTextSpanThickness::kThin, + ImeTextSpanUnderlineStyle::kSolid, Color::kBlack, Color::kBlack); // Select immediately before word2 GetDocument().GetFrame()->Selection().SetSelectionAndEndTyping( SelectionInDOMTree::Builder() @@ -375,7 +383,8 @@ TEST_F(TextSuggestionControllerTest, // Mark "word2" as the active suggestion range GetDocument().Markers().AddActiveSuggestionMarker( EphemeralRange(Position(text, 6), Position(text, 11)), - Color::kTransparent, ImeTextSpanThickness::kThin, Color::kBlack); + Color::kTransparent, ImeTextSpanThickness::kThin, + ImeTextSpanUnderlineStyle::kSolid, Color::kBlack, Color::kBlack); // Select immediately before word2 GetDocument().GetFrame()->Selection().SetSelectionAndEndTyping( SelectionInDOMTree::Builder() @@ -401,7 +410,8 @@ TEST_F(TextSuggestionControllerTest, // Mark "word1" as the active suggestion range GetDocument().Markers().AddActiveSuggestionMarker( EphemeralRange(Position(text, 0), Position(text, 5)), Color::kTransparent, - ImeTextSpanThickness::kThin, Color::kBlack); + ImeTextSpanThickness::kThin, ImeTextSpanUnderlineStyle::kSolid, + Color::kBlack, Color::kBlack); // Select immediately before word1 GetDocument().GetFrame()->Selection().SetSelectionAndEndTyping( SelectionInDOMTree::Builder() @@ -460,7 +470,7 @@ TEST_F(TextSuggestionControllerTest, TEST_F(TextSuggestionControllerTest, CallbackHappensAfterDocumentDestroyed) { LocalFrame& frame = *GetDocument().GetFrame(); - GetDocument().Shutdown(); + frame.DomWindow()->FrameDestroyed(); // Shouldn't crash frame.GetTextSuggestionController().SuggestionMenuTimeoutCallback(0); diff --git a/chromium/third_party/blink/renderer/core/editing/surrounding_text.cc b/chromium/third_party/blink/renderer/core/editing/surrounding_text.cc index cb9d29a8b4f..c2dab2267de 100644 --- a/chromium/third_party/blink/renderer/core/editing/surrounding_text.cc +++ b/chromium/third_party/blink/renderer/core/editing/surrounding_text.cc @@ -42,7 +42,7 @@ namespace { EphemeralRange ComputeRangeFromFrameSelection(LocalFrame* frame) { // TODO(editing-dev): The use of UpdateStyleAndLayout // needs to be audited. See http://crbug.com/590369 for more details. - frame->GetDocument()->UpdateStyleAndLayout(); + frame->GetDocument()->UpdateStyleAndLayout(DocumentUpdateReason::kEditing); return frame->Selection() .ComputeVisibleSelectionInDOMTree() diff --git a/chromium/third_party/blink/renderer/core/editing/surrounding_text_test.cc b/chromium/third_party/blink/renderer/core/editing/surrounding_text_test.cc index 4809afae953..56d0ad75763 100644 --- a/chromium/third_party/blink/renderer/core/editing/surrounding_text_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/surrounding_text_test.cc @@ -36,8 +36,8 @@ void SurroundingTextTest::SetUp() { } void SurroundingTextTest::SetHTML(const String& content) { - GetDocument().body()->SetInnerHTMLFromString(content); - GetDocument().UpdateStyleAndLayout(); + GetDocument().body()->setInnerHTML(content); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); } EphemeralRange SurroundingTextTest::Select(int start, int end) { @@ -307,7 +307,7 @@ TEST_F(SurroundingTextTest, EmptyInputElementWithChild) { TextControlElement* input_element = reinterpret_cast<TextControlElement*>( GetDocument().getElementById("input_name")); input_element->SetInnerEditorValue("John Smith"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); // BODY // INPUT diff --git a/chromium/third_party/blink/renderer/core/editing/testing/editing_test_base.cc b/chromium/third_party/blink/renderer/core/editing/testing/editing_test_base.cc index b66976cf71d..945ddbace93 100644 --- a/chromium/third_party/blink/renderer/core/editing/testing/editing_test_base.cc +++ b/chromium/third_party/blink/renderer/core/editing/testing/editing_test_base.cc @@ -73,10 +73,10 @@ ShadowRoot* EditingTestBase::CreateShadowRootForElementWithIDAndSetInnerHTML( ShadowRoot& shadow_root = scope.getElementById(AtomicString::FromUTF8(host_element_id)) ->CreateV0ShadowRootForTesting(); - shadow_root.SetInnerHTMLFromString(String::FromUTF8(shadow_root_content), - ASSERT_NO_EXCEPTION); + shadow_root.setInnerHTML(String::FromUTF8(shadow_root_content), + ASSERT_NO_EXCEPTION); scope.GetDocument().View()->UpdateAllLifecyclePhases( - DocumentLifecycle::LifecycleUpdateReason::kTest); + DocumentUpdateReason::kTest); return &shadow_root; } diff --git a/chromium/third_party/blink/renderer/core/editing/testing/selection_sample.cc b/chromium/third_party/blink/renderer/core/editing/testing/selection_sample.cc index 9ae865ebf77..4d9fbc36087 100644 --- a/chromium/third_party/blink/renderer/core/editing/testing/selection_sample.cc +++ b/chromium/third_party/blink/renderer/core/editing/testing/selection_sample.cc @@ -6,12 +6,12 @@ #include <algorithm> +#include "third_party/blink/renderer/bindings/core/v8/v8_shadow_root_init.h" #include "third_party/blink/renderer/core/dom/attribute.h" #include "third_party/blink/renderer/core/dom/character_data.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/element.h" #include "third_party/blink/renderer/core/dom/processing_instruction.h" -#include "third_party/blink/renderer/core/dom/shadow_root_init.h" #include "third_party/blink/renderer/core/editing/editing_utilities.h" #include "third_party/blink/renderer/core/editing/selection_template.h" #include "third_party/blink/renderer/core/html/html_collection.h" @@ -60,7 +60,7 @@ class Parser final { // |SelectionInDOMTree| marked up within |selection_text|. SelectionInDOMTree SetSelectionText(HTMLElement* element, const std::string& selection_text) { - element->SetInnerHTMLFromString(String::FromUTF8(selection_text.c_str())); + element->setInnerHTML(String::FromUTF8(selection_text.c_str())); ConvertTemplatesToShadowRoots(*element); Traverse(element); if (anchor_node_ && focus_node_) { @@ -162,8 +162,8 @@ class Parser final { NOTREACHED() << node; } - Member<Node> anchor_node_; - Member<Node> focus_node_; + Node* anchor_node_ = nullptr; + Node* focus_node_ = nullptr; int anchor_offset_ = 0; int focus_offset_ = 0; }; diff --git a/chromium/third_party/blink/renderer/core/editing/testing/selection_sample_test.cc b/chromium/third_party/blink/renderer/core/editing/testing/selection_sample_test.cc index f266eb74594..85a0d2de848 100644 --- a/chromium/third_party/blink/renderer/core/editing/testing/selection_sample_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/testing/selection_sample_test.cc @@ -42,7 +42,7 @@ TEST_F(SelectionSampleTest, GetSelectionTextFlatTree) { TEST_F(SelectionSampleTest, SetCommentInBody) { const SelectionInDOMTree& selection = SelectionSample::SetSelectionText( GetDocument().body(), "<!--^-->foo<!--|-->"); - EXPECT_EQ("foo", GetDocument().body()->InnerHTMLAsString()); + EXPECT_EQ("foo", GetDocument().body()->innerHTML()); EXPECT_EQ(SelectionInDOMTree::Builder() .Collapse(Position(GetDocument().body(), 0)) .Extend(Position(GetDocument().body(), 1)) @@ -55,7 +55,7 @@ TEST_F(SelectionSampleTest, SetCommentInElement) { GetDocument().body(), "<span id=sample><!--^-->foo<!--|--></span>"); const Element* const sample = GetDocument().body()->getElementById("sample"); EXPECT_EQ("<span id=\"sample\">foo</span>", - GetDocument().body()->InnerHTMLAsString()); + GetDocument().body()->innerHTML()); EXPECT_EQ(SelectionInDOMTree::Builder() .Collapse(Position(sample, 0)) .Extend(Position(sample, 1)) @@ -66,7 +66,7 @@ TEST_F(SelectionSampleTest, SetCommentInElement) { TEST_F(SelectionSampleTest, SetEmpty1) { const SelectionInDOMTree& selection = SelectionSample::SetSelectionText(GetDocument().body(), "|"); - EXPECT_EQ("", GetDocument().body()->InnerHTMLAsString()); + EXPECT_EQ("", GetDocument().body()->innerHTML()); EXPECT_EQ(0u, GetDocument().body()->CountChildren()); EXPECT_EQ(SelectionInDOMTree::Builder() .Collapse(Position(GetDocument().body(), 0)) @@ -77,7 +77,7 @@ TEST_F(SelectionSampleTest, SetEmpty1) { TEST_F(SelectionSampleTest, SetEmpty2) { const SelectionInDOMTree& selection = SelectionSample::SetSelectionText(GetDocument().body(), "^|"); - EXPECT_EQ("", GetDocument().body()->InnerHTMLAsString()); + EXPECT_EQ("", GetDocument().body()->innerHTML()); EXPECT_EQ(0u, GetDocument().body()->CountChildren()); EXPECT_EQ(SelectionInDOMTree::Builder() .Collapse(Position(GetDocument().body(), 0)) @@ -102,7 +102,7 @@ TEST_F(SelectionSampleTest, SetText) { { const auto& selection = SelectionSample::SetSelectionText(GetDocument().body(), "^ab|c"); - EXPECT_EQ("abc", GetDocument().body()->InnerHTMLAsString()); + EXPECT_EQ("abc", GetDocument().body()->innerHTML()); EXPECT_EQ(SelectionInDOMTree::Builder() .Collapse(Position(GetDocument().body()->firstChild(), 0)) .Extend(Position(GetDocument().body()->firstChild(), 2)) @@ -112,7 +112,7 @@ TEST_F(SelectionSampleTest, SetText) { { const auto& selection = SelectionSample::SetSelectionText(GetDocument().body(), "a^b|c"); - EXPECT_EQ("abc", GetDocument().body()->InnerHTMLAsString()); + EXPECT_EQ("abc", GetDocument().body()->innerHTML()); EXPECT_EQ(SelectionInDOMTree::Builder() .Collapse(Position(GetDocument().body()->firstChild(), 1)) .Extend(Position(GetDocument().body()->firstChild(), 2)) @@ -122,7 +122,7 @@ TEST_F(SelectionSampleTest, SetText) { { const auto& selection = SelectionSample::SetSelectionText(GetDocument().body(), "ab^|c"); - EXPECT_EQ("abc", GetDocument().body()->InnerHTMLAsString()); + EXPECT_EQ("abc", GetDocument().body()->innerHTML()); EXPECT_EQ(SelectionInDOMTree::Builder() .Collapse(Position(GetDocument().body()->firstChild(), 2)) .Build(), @@ -131,7 +131,7 @@ TEST_F(SelectionSampleTest, SetText) { { const auto& selection = SelectionSample::SetSelectionText(GetDocument().body(), "ab|c^"); - EXPECT_EQ("abc", GetDocument().body()->InnerHTMLAsString()); + EXPECT_EQ("abc", GetDocument().body()->innerHTML()); EXPECT_EQ(SelectionInDOMTree::Builder() .Collapse(Position(GetDocument().body()->firstChild(), 3)) .Extend(Position(GetDocument().body()->firstChild(), 2)) @@ -267,7 +267,7 @@ TEST_F(SelectionSampleTest, ConvertTemplatesToShadowRoots) { ShadowRoot* shadow_root = host->ShadowRootIfV1(); ASSERT_TRUE(shadow_root->IsShadowRoot()); EXPECT_EQ("<div>shadow_first</div><div>shadow_second</div>", - shadow_root->InnerHTMLAsString()); + shadow_root->innerHTML()); } TEST_F(SelectionSampleTest, ConvertTemplatesToShadowRootsNoTemplates) { @@ -281,7 +281,7 @@ TEST_F(SelectionSampleTest, ConvertTemplatesToShadowRootsNoTemplates) { SelectionSample::ConvertTemplatesToShadowRootsForTesring( *(To<HTMLElement>(host))); EXPECT_FALSE(host->ShadowRootIfV1()); - EXPECT_EQ("<div>first</div><div>second</div>", host->InnerHTMLAsString()); + EXPECT_EQ("<div>first</div><div>second</div>", host->innerHTML()); } TEST_F(SelectionSampleTest, ConvertTemplatesToShadowRootsMultipleTemplates) { @@ -308,10 +308,10 @@ TEST_F(SelectionSampleTest, ConvertTemplatesToShadowRootsMultipleTemplates) { EXPECT_TRUE(shadow_root_1->IsShadowRoot()); EXPECT_EQ("<div>shadow_first</div><div>shadow_second</div>", - shadow_root_1->InnerHTMLAsString()); + shadow_root_1->innerHTML()); EXPECT_TRUE(shadow_root_2->IsShadowRoot()); EXPECT_EQ("<div>shadow_third</div><div>shadow_forth</div>", - shadow_root_2->InnerHTMLAsString()); + shadow_root_2->innerHTML()); } TEST_F(SelectionSampleTest, TraverseShadowContent) { @@ -324,7 +324,7 @@ TEST_F(SelectionSampleTest, TraverseShadowContent) { "</div>"; const SelectionInDOMTree& selection = SelectionSample::SetSelectionText(body, content); - EXPECT_EQ("<div id=\"host\"></div>", body->InnerHTMLAsString()); + EXPECT_EQ("<div id=\"host\"></div>", body->innerHTML()); Element* host = body->getElementById("host"); ShadowRoot* shadow_root = host->ShadowRootIfV1(); @@ -332,7 +332,7 @@ TEST_F(SelectionSampleTest, TraverseShadowContent) { EXPECT_EQ( "<div id=\"shadow1\">shadow_first</div>" "<div id=\"shadow2\">shadow_second</div>", - shadow_root->InnerHTMLAsString()); + shadow_root->innerHTML()); EXPECT_EQ(Position(shadow_root->getElementById("shadow1")->firstChild(), 0), selection.Base()); @@ -353,7 +353,7 @@ TEST_F(SelectionSampleTest, TraverseShadowContentWithSlot) { const SelectionInDOMTree& selection = SelectionSample::SetSelectionText(body, content); EXPECT_EQ("<div id=\"host\">foo<span slot=\"slot1\">bar</span></div>", - body->InnerHTMLAsString()); + body->innerHTML()); Element* host = body->getElementById("host"); ShadowRoot* shadow_root = host->ShadowRootIfV1(); @@ -362,7 +362,7 @@ TEST_F(SelectionSampleTest, TraverseShadowContentWithSlot) { "<div id=\"shadow1\">shadow_first</div>" "<slot name=\"slot1\">slot</slot>" "<div id=\"shadow2\">shadow_second</div>", - shadow_root->InnerHTMLAsString()); + shadow_root->innerHTML()); EXPECT_EQ(Position(GetDocument().getElementById("host")->firstChild(), 0), selection.Base()); @@ -388,7 +388,7 @@ TEST_F(SelectionSampleTest, TraverseMultipleShadowContents) { const SelectionInDOMTree& selection = SelectionSample::SetSelectionText(body, content); EXPECT_EQ("<div id=\"host1\"></div><div id=\"host2\"></div>", - body->InnerHTMLAsString()); + body->innerHTML()); Element* host1 = body->getElementById("host1"); ShadowRoot* shadow_root1 = host1->ShadowRootIfV1(); @@ -399,11 +399,11 @@ TEST_F(SelectionSampleTest, TraverseMultipleShadowContents) { EXPECT_EQ( "<div id=\"shadow1\">shadow_first</div>" "<div id=\"shadow2\">shadow_second</div>", - shadow_root1->InnerHTMLAsString()); + shadow_root1->innerHTML()); EXPECT_EQ( "<div id=\"shadow3\">shadow_third</div>" "<div id=\"shadow4\">shadow_forth</div>", - shadow_root2->InnerHTMLAsString()); + shadow_root2->innerHTML()); EXPECT_EQ(Position(shadow_root1->getElementById("shadow1")->firstChild(), 0), selection.Base()); diff --git a/chromium/third_party/blink/renderer/core/editing/text_offset_mapping.cc b/chromium/third_party/blink/renderer/core/editing/text_offset_mapping.cc index a49900ca1a4..fd564038fa9 100644 --- a/chromium/third_party/blink/renderer/core/editing/text_offset_mapping.cc +++ b/chromium/third_party/blink/renderer/core/editing/text_offset_mapping.cc @@ -52,6 +52,17 @@ bool CanBeInlineContentsContainer(const LayoutObject& layout_object) { return HasNonPsuedoNode(*block_flow); } +Node* PreviousNodeSkippingAncestors(const Node& node) { + ContainerNode* parent = FlatTreeTraversal::Parent(node); + for (Node* runner = FlatTreeTraversal::Previous(node); runner; + runner = FlatTreeTraversal::Previous(*runner)) { + if (runner != parent) + return runner; + parent = FlatTreeTraversal::Parent(*runner); + } + return nullptr; +} + // Returns outer most nested inline formatting context. const LayoutBlockFlow& RootInlineContentsContainerOf( const LayoutBlockFlow& block_flow) { @@ -60,8 +71,9 @@ const LayoutBlockFlow& RootInlineContentsContainerOf( for (const LayoutBlock* runner = block_flow.ContainingBlock(); runner; runner = runner->ContainingBlock()) { auto* containing_block_flow = DynamicTo<LayoutBlockFlow>(runner); - if (containing_block_flow && runner->ChildrenInline()) - root_block_flow = containing_block_flow; + if (!containing_block_flow || !runner->ChildrenInline()) + break; + root_block_flow = containing_block_flow; } DCHECK(!root_block_flow->IsAtomicInlineLevel()) << block_flow << ' ' << root_block_flow; @@ -118,6 +130,7 @@ const LayoutBlockFlow* ComputeInlineContentsAsBlockFlow( TextOffsetMapping::InlineContents CreateInlineContentsFromBlockFlow( const LayoutBlockFlow& block_flow) { + DCHECK(block_flow.ChildrenInline()) << block_flow; const LayoutObject* first = nullptr; for (const LayoutObject* runner = block_flow.FirstChild(); runner; runner = runner->NextInPreOrder(&block_flow)) { @@ -270,7 +283,7 @@ TextOffsetMapping::InlineContents TextOffsetMapping::FindBackwardInlineContents( auto previous_skipping_text_control = [](const Node& node) -> const Node* { DCHECK(!EnclosingTextControl(&node)); - const Node* previous = FlatTreeTraversal::Previous(node); + const Node* previous = PreviousNodeSkippingAncestors(node); const TextControlElement* previous_text_control = EnclosingTextControl(previous); if (!previous_text_control) diff --git a/chromium/third_party/blink/renderer/core/editing/text_offset_mapping_test.cc b/chromium/third_party/blink/renderer/core/editing/text_offset_mapping_test.cc index e6db282def1..9c6412805bb 100644 --- a/chromium/third_party/blink/renderer/core/editing/text_offset_mapping_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/text_offset_mapping_test.cc @@ -391,6 +391,7 @@ TEST_P(ParameterizedTextOffsetMappingTest, RangeWithNestedPosition) { TEST_P(ParameterizedTextOffsetMappingTest, RangeWithSelect) { EXPECT_EQ( "^<select>" + "<div aria-hidden=\"true\"></div>" "<slot name=\"user-agent-custom-assign-slot\"></slot>" "</select>foo|", GetRange("<select>|</select>foo")); diff --git a/chromium/third_party/blink/renderer/core/editing/visible_position_test.cc b/chromium/third_party/blink/renderer/core/editing/visible_position_test.cc index cabb3c35026..9a5adde5b36 100644 --- a/chromium/third_party/blink/renderer/core/editing/visible_position_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/visible_position_test.cc @@ -89,15 +89,15 @@ TEST_F(VisiblePositionTest, NonNullInvalidatedAfterStyleChange) { Position position(paragraph->firstChild(), 1); VisiblePosition visible_position1 = CreateVisiblePosition(position); - div->style()->setProperty(&GetDocument(), "color", "red", "important", - ASSERT_NO_EXCEPTION); + div->style()->setProperty(GetDocument().ToExecutionContext(), "color", "red", + "important", ASSERT_NO_EXCEPTION); EXPECT_FALSE(visible_position1.IsValid()); UpdateAllLifecyclePhasesForTest(); VisiblePosition visible_position2 = CreateVisiblePosition(position); - div->style()->setProperty(&GetDocument(), "display", "none", "important", - ASSERT_NO_EXCEPTION); + div->style()->setProperty(GetDocument().ToExecutionContext(), "display", + "none", "important", ASSERT_NO_EXCEPTION); EXPECT_FALSE(visible_position2.IsValid()); UpdateAllLifecyclePhasesForTest(); diff --git a/chromium/third_party/blink/renderer/core/editing/visible_selection_test.cc b/chromium/third_party/blink/renderer/core/editing/visible_selection_test.cc index 77e481324ce..0fed925d2de 100644 --- a/chromium/third_party/blink/renderer/core/editing/visible_selection_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/visible_selection_test.cc @@ -687,7 +687,7 @@ TEST_F(VisibleSelectionTest, updateIfNeededWithShadowHost) { // Simulates modifying DOM tree to invalidate distribution. Element* host = GetDocument().getElementById("host"); host->AppendChild(sample); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); // Simulates to restore selection from undo stack. selection = CreateVisibleSelection(selection.AsSelection()); @@ -699,7 +699,7 @@ TEST_F(VisibleSelectionTest, BackwardSelectionWithMultipleEmptyBodies) { Element* body = GetDocument().body(); Element* new_body = GetDocument().CreateRawElement(html_names::kBodyTag); body->appendChild(new_body); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); const SelectionInDOMTree selection = SelectionInDOMTree::Builder() diff --git a/chromium/third_party/blink/renderer/core/editing/visible_units_line.cc b/chromium/third_party/blink/renderer/core/editing/visible_units_line.cc index 014e69a138d..46334945df3 100644 --- a/chromium/third_party/blink/renderer/core/editing/visible_units_line.cc +++ b/chromium/third_party/blink/renderer/core/editing/visible_units_line.cc @@ -69,10 +69,10 @@ PositionWithAffinityTemplate<Strategy> StartPositionForLine( } NGInlineCursor line_box = caret_position.cursor; line_box.MoveToContainingLine(); - DCHECK(line_box.IsLineBox()) << line_box; + DCHECK(line_box.Current().IsLineBox()) << line_box; const PhysicalOffset start_point = line_box.LineStartPoint(); return FromPositionInDOMTree<Strategy>( - line_box.CursorForDescendants().PositionForPoint(start_point)); + line_box.PositionForPointInInlineBox(start_point)); } const InlineBox* inline_box = @@ -254,7 +254,7 @@ static PositionWithAffinityTemplate<Strategy> EndPositionForLine( line_box.MoveToContainingLine(); const PhysicalOffset end_point = line_box.LineEndPoint(); return FromPositionInDOMTree<Strategy>( - line_box.CursorForDescendants().PositionForPoint(end_point)); + line_box.PositionForPointInInlineBox(end_point)); } const InlineBox* inline_box = diff --git a/chromium/third_party/blink/renderer/core/editing/visible_units_line_test.cc b/chromium/third_party/blink/renderer/core/editing/visible_units_line_test.cc index f2cc911f76c..1e6bf188ee5 100644 --- a/chromium/third_party/blink/renderer/core/editing/visible_units_line_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/visible_units_line_test.cc @@ -60,7 +60,9 @@ class ParameterizedVisibleUnitsLineTest protected: ParameterizedVisibleUnitsLineTest() : ScopedLayoutNGForTest(GetParam()) {} - bool LayoutNGEnabled() const { return GetParam(); } + bool LayoutNGEnabled() const { + return RuntimeEnabledFeatures::LayoutNGEnabled(); + } }; INSTANTIATE_TEST_SUITE_P(All, diff --git a/chromium/third_party/blink/renderer/core/editing/visible_units_sentence_test.cc b/chromium/third_party/blink/renderer/core/editing/visible_units_sentence_test.cc index 2f172c12ee0..c71d3ad0a16 100644 --- a/chromium/third_party/blink/renderer/core/editing/visible_units_sentence_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/visible_units_sentence_test.cc @@ -56,7 +56,9 @@ class ParameterizedVisibleUnitsSentenceTest protected: ParameterizedVisibleUnitsSentenceTest() : ScopedLayoutNGForTest(GetParam()) {} - bool LayoutNGEnabled() const { return GetParam(); } + bool LayoutNGEnabled() const { + return RuntimeEnabledFeatures::LayoutNGEnabled(); + } }; INSTANTIATE_TEST_SUITE_P(All, diff --git a/chromium/third_party/blink/renderer/core/editing/visible_units_test.cc b/chromium/third_party/blink/renderer/core/editing/visible_units_test.cc index 6e002c7c73a..69ef2db0725 100644 --- a/chromium/third_party/blink/renderer/core/editing/visible_units_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/visible_units_test.cc @@ -331,7 +331,7 @@ TEST_F(VisibleUnitsTest, isVisuallyEquivalentCandidateWithHTMLBodyElement) { body->AppendChild(three); body->AppendChild(four); one->appendChild(body); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); EXPECT_FALSE(IsVisuallyEquivalentCandidate( Position(GetDocument().documentElement(), 0))); diff --git a/chromium/third_party/blink/renderer/core/editing/visible_units_word_test.cc b/chromium/third_party/blink/renderer/core/editing/visible_units_word_test.cc index e6481fb213a..d3e11728af2 100644 --- a/chromium/third_party/blink/renderer/core/editing/visible_units_word_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/visible_units_word_test.cc @@ -82,7 +82,9 @@ class ParameterizedVisibleUnitsWordTest protected: ParameterizedVisibleUnitsWordTest() : ScopedLayoutNGForTest(GetParam()) {} - bool LayoutNGEnabled() const { return GetParam(); } + bool LayoutNGEnabled() const { + return RuntimeEnabledFeatures::LayoutNGEnabled(); + } }; INSTANTIATE_TEST_SUITE_P(All, @@ -652,6 +654,108 @@ TEST_P(ParameterizedVisibleUnitsWordTest, PreviousWordCrossingPlaceholderBR) { EXPECT_EQ("<p>|<br></p><p>abc</p>", DoPreviousWord("<p><br></p><p>|abc</p>")); } +TEST_P(ParameterizedVisibleUnitsWordTest, PreviousWordInFloat) { + InsertStyleElement( + "c { display: block; float: right; }" + "e { display: block; }"); + + // To "|abc" + EXPECT_EQ("<c><e>|abc def ghi</e></c>", + DoPreviousWord("<c><e>|abc def ghi</e></c>")); + EXPECT_EQ("<c><e>|abc def ghi</e></c>", + DoPreviousWord("<c><e>a|bc def ghi</e></c>")); + EXPECT_EQ("<c><e>|abc def ghi</e></c>", + DoPreviousWord("<c><e>ab|c def ghi</e></c>")); + EXPECT_EQ("<c><e>|abc def ghi</e></c>", + DoPreviousWord("<c><e>abc| def ghi</e></c>")); + EXPECT_EQ("<c><e>|abc def ghi</e></c>", + DoPreviousWord("<c><e>abc |def ghi</e></c>")); + // To "|def" + EXPECT_EQ("<c><e>abc |def ghi</e></c>", + DoPreviousWord("<c><e>abc d|ef ghi</e></c>")); + EXPECT_EQ("<c><e>abc |def ghi</e></c>", + DoPreviousWord("<c><e>abc de|f ghi</e></c>")); + EXPECT_EQ("<c><e>abc |def ghi</e></c>", + DoPreviousWord("<c><e>abc def| ghi</e></c>")); + EXPECT_EQ("<c><e>abc |def ghi</e></c>", + DoPreviousWord("<c><e>abc def |ghi</e></c>")); + // To "|ghi" + EXPECT_EQ("<c><e>abc def |ghi</e></c>", + DoPreviousWord("<c><e>abc def g|hi</e></c>")); + EXPECT_EQ("<c><e>abc def |ghi</e></c>", + DoPreviousWord("<c><e>abc def gh|i</e></c>")); + EXPECT_EQ("<c><e>abc def |ghi</e></c>", + DoPreviousWord("<c><e>abc def ghi|</e></c>")); +} + +TEST_P(ParameterizedVisibleUnitsWordTest, PreviousWordInInlineBlock) { + InsertStyleElement( + "c { display: inline-block; }" + "e { display: block; }"); + + // To "|abc" + EXPECT_EQ("<c><e>|abc def ghi</e></c>", + DoPreviousWord("<c><e>|abc def ghi</e></c>")); + EXPECT_EQ("<c><e>|abc def ghi</e></c>", + DoPreviousWord("<c><e>a|bc def ghi</e></c>")); + EXPECT_EQ("<c><e>|abc def ghi</e></c>", + DoPreviousWord("<c><e>ab|c def ghi</e></c>")); + EXPECT_EQ("<c><e>|abc def ghi</e></c>", + DoPreviousWord("<c><e>abc| def ghi</e></c>")); + EXPECT_EQ("<c><e>|abc def ghi</e></c>", + DoPreviousWord("<c><e>abc |def ghi</e></c>")); + // To "|def" + EXPECT_EQ("<c><e>abc |def ghi</e></c>", + DoPreviousWord("<c><e>abc d|ef ghi</e></c>")); + EXPECT_EQ("<c><e>abc |def ghi</e></c>", + DoPreviousWord("<c><e>abc de|f ghi</e></c>")); + EXPECT_EQ("<c><e>abc |def ghi</e></c>", + DoPreviousWord("<c><e>abc def| ghi</e></c>")); + EXPECT_EQ("<c><e>abc |def ghi</e></c>", + DoPreviousWord("<c><e>abc def |ghi</e></c>")); + // To "|ghi" + EXPECT_EQ("<c><e>abc def |ghi</e></c>", + DoPreviousWord("<c><e>abc def g|hi</e></c>")); + EXPECT_EQ("<c><e>abc def |ghi</e></c>", + DoPreviousWord("<c><e>abc def gh|i</e></c>")); + EXPECT_EQ("<c><e>abc def |ghi</e></c>", + DoPreviousWord("<c><e>abc def ghi|</e></c>")); +} + +TEST_P(ParameterizedVisibleUnitsWordTest, PreviousWordInPositionAbsolute) { + InsertStyleElement( + "c { display: block; position: absolute; }" + "e { display: block; }"); + + // To "|abc" + EXPECT_EQ("<c><e>|abc def ghi</e></c>", + DoPreviousWord("<c><e>|abc def ghi</e></c>")); + EXPECT_EQ("<c><e>|abc def ghi</e></c>", + DoPreviousWord("<c><e>a|bc def ghi</e></c>")); + EXPECT_EQ("<c><e>|abc def ghi</e></c>", + DoPreviousWord("<c><e>ab|c def ghi</e></c>")); + EXPECT_EQ("<c><e>|abc def ghi</e></c>", + DoPreviousWord("<c><e>abc| def ghi</e></c>")); + EXPECT_EQ("<c><e>|abc def ghi</e></c>", + DoPreviousWord("<c><e>abc |def ghi</e></c>")); + // To "|def" + EXPECT_EQ("<c><e>abc |def ghi</e></c>", + DoPreviousWord("<c><e>abc d|ef ghi</e></c>")); + EXPECT_EQ("<c><e>abc |def ghi</e></c>", + DoPreviousWord("<c><e>abc de|f ghi</e></c>")); + EXPECT_EQ("<c><e>abc |def ghi</e></c>", + DoPreviousWord("<c><e>abc def| ghi</e></c>")); + EXPECT_EQ("<c><e>abc |def ghi</e></c>", + DoPreviousWord("<c><e>abc def |ghi</e></c>")); + // To "|ghi" + EXPECT_EQ("<c><e>abc def |ghi</e></c>", + DoPreviousWord("<c><e>abc def g|hi</e></c>")); + EXPECT_EQ("<c><e>abc def |ghi</e></c>", + DoPreviousWord("<c><e>abc def gh|i</e></c>")); + EXPECT_EQ("<c><e>abc def |ghi</e></c>", + DoPreviousWord("<c><e>abc def ghi|</e></c>")); +} + TEST_P(ParameterizedVisibleUnitsWordTest, PreviousWordSkipTextControl) { EXPECT_EQ("|foo<input value=\"bla\">bar", DoPreviousWord("|foo<input value=\"bla\">bar")); diff --git a/chromium/third_party/blink/renderer/core/editing/web_substring_util.mm b/chromium/third_party/blink/renderer/core/editing/web_substring_util.mm index 327b82aa565..a966c7852ed 100644 --- a/chromium/third_party/blink/renderer/core/editing/web_substring_util.mm +++ b/chromium/third_party/blink/renderer/core/editing/web_substring_util.mm @@ -77,7 +77,8 @@ NSAttributedString* AttributedSubstringFromRange(const EphemeralRange& range, // TODO(editing-dev): The use of updateStyleAndLayout // needs to be audited. see http://crbug.com/590369 for more details. - range.StartPosition().GetDocument()->UpdateStyleAndLayout(); + range.StartPosition().GetDocument()->UpdateStyleAndLayout( + DocumentUpdateReason::kEditing); for (TextIterator it(range.StartPosition(), range.EndPosition()); !it.AtEnd() && [string length] < length; it.Advance()) { @@ -138,9 +139,9 @@ NSAttributedString* AttributedSubstringFromRange(const EphemeralRange& range, return [string autorelease]; } -WebPoint GetBaselinePoint(LocalFrameView* frame_view, - const EphemeralRange& range, - NSAttributedString* string) { +gfx::Point GetBaselinePoint(LocalFrameView* frame_view, + const EphemeralRange& range, + NSAttributedString* string) { IntRect string_rect = frame_view->FrameToViewport(FirstRectForRange(range)); IntPoint string_point = string_rect.MinXMaxYCorner(); @@ -157,8 +158,8 @@ WebPoint GetBaselinePoint(LocalFrameView* frame_view, NSAttributedString* WebSubstringUtil::AttributedWordAtPoint( WebFrameWidget* frame_widget, - WebPoint point, - WebPoint& baseline_point) { + gfx::Point point, + gfx::Point& baseline_point) { HitTestResult result = static_cast<WebFrameWidgetBase*>(frame_widget) ->CoreHitTestResultAt(IntPoint(point)); @@ -195,7 +196,7 @@ NSAttributedString* WebSubstringUtil::AttributedSubstringInRange( WebLocalFrame* web_frame, size_t location, size_t length, - WebPoint* baseline_point) { + gfx::Point* baseline_point) { LocalFrame* frame = To<WebLocalFrameImpl>(web_frame)->GetFrame(); if (frame->View()->NeedsLayout()) frame->View()->UpdateLayout(); |