OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2006, 2007, 2008, 2011 Apple Inc. All rights reserved. | 2 * Copyright (C) 2006, 2007, 2008, 2011 Apple Inc. All rights reserved. |
3 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) | 3 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
7 * are met: | 7 * are met: |
8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
74 #include "core/html/HTMLHtmlElement.h" | 74 #include "core/html/HTMLHtmlElement.h" |
75 #include "core/html/HTMLImageElement.h" | 75 #include "core/html/HTMLImageElement.h" |
76 #include "core/html/HTMLInputElement.h" | 76 #include "core/html/HTMLInputElement.h" |
77 #include "core/html/HTMLTextAreaElement.h" | 77 #include "core/html/HTMLTextAreaElement.h" |
78 #include "core/html/parser/HTMLParserIdioms.h" | 78 #include "core/html/parser/HTMLParserIdioms.h" |
79 #include "core/input/EventHandler.h" | 79 #include "core/input/EventHandler.h" |
80 #include "core/inspector/ConsoleMessage.h" | 80 #include "core/inspector/ConsoleMessage.h" |
81 #include "core/layout/HitTestResult.h" | 81 #include "core/layout/HitTestResult.h" |
82 #include "core/layout/LayoutImage.h" | 82 #include "core/layout/LayoutImage.h" |
83 #include "core/loader/EmptyClients.h" | 83 #include "core/loader/EmptyClients.h" |
| 84 #include "core/page/DragData.h" |
84 #include "core/page/EditorClient.h" | 85 #include "core/page/EditorClient.h" |
85 #include "core/page/FocusController.h" | 86 #include "core/page/FocusController.h" |
86 #include "core/page/Page.h" | 87 #include "core/page/Page.h" |
87 #include "core/svg/SVGImageElement.h" | 88 #include "core/svg/SVGImageElement.h" |
88 #include "platform/KillRing.h" | 89 #include "platform/KillRing.h" |
89 #include "platform/weborigin/KURL.h" | 90 #include "platform/weborigin/KURL.h" |
90 #include "wtf/PtrUtil.h" | 91 #include "wtf/PtrUtil.h" |
91 #include "wtf/text/CharacterNames.h" | 92 #include "wtf/text/CharacterNames.h" |
92 | 93 |
93 namespace blink { | 94 namespace blink { |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
321 if (isTypingAction) { | 322 if (isTypingAction) { |
322 DCHECK(frame().document()); | 323 DCHECK(frame().document()); |
323 TypingCommand::deleteKeyPressed( | 324 TypingCommand::deleteKeyPressed( |
324 *frame().document(), | 325 *frame().document(), |
325 canSmartCopyOrDelete() ? TypingCommand::SmartDelete : 0, granularity); | 326 canSmartCopyOrDelete() ? TypingCommand::SmartDelete : 0, granularity); |
326 revealSelectionAfterEditingOperation(); | 327 revealSelectionAfterEditingOperation(); |
327 } else { | 328 } else { |
328 if (killRing) | 329 if (killRing) |
329 addToKillRing(selectedRange()); | 330 addToKillRing(selectedRange()); |
330 deleteSelectionWithSmartDelete( | 331 deleteSelectionWithSmartDelete( |
331 canSmartCopyOrDelete(), | 332 canSmartCopyOrDelete() ? DeleteMode::Smart : DeleteMode::Simple, |
332 deletionInputTypeFromTextGranularity(direction, granularity)); | 333 deletionInputTypeFromTextGranularity(direction, granularity)); |
333 // Implicitly calls revealSelectionAfterEditingOperation(). | 334 // Implicitly calls revealSelectionAfterEditingOperation(). |
334 } | 335 } |
335 } else { | 336 } else { |
336 TypingCommand::Options options = 0; | 337 TypingCommand::Options options = 0; |
337 if (canSmartCopyOrDelete()) | 338 if (canSmartCopyOrDelete()) |
338 options |= TypingCommand::SmartDelete; | 339 options |= TypingCommand::SmartDelete; |
339 if (killRing) | 340 if (killRing) |
340 options |= TypingCommand::KillRing; | 341 options |= TypingCommand::KillRing; |
341 switch (direction) { | 342 switch (direction) { |
(...skipping 15 matching lines...) Expand all Loading... |
357 | 358 |
358 // FIXME: We should to move this down into deleteKeyPressed. | 359 // FIXME: We should to move this down into deleteKeyPressed. |
359 // clear the "start new kill ring sequence" setting, because it was set to tru
e | 360 // clear the "start new kill ring sequence" setting, because it was set to tru
e |
360 // when the selection was updated by deleting the range | 361 // when the selection was updated by deleting the range |
361 if (killRing) | 362 if (killRing) |
362 setStartNewKillRingSequence(false); | 363 setStartNewKillRingSequence(false); |
363 | 364 |
364 return true; | 365 return true; |
365 } | 366 } |
366 | 367 |
367 void Editor::deleteSelectionWithSmartDelete(bool smartDelete, | 368 void Editor::deleteSelectionWithSmartDelete( |
368 InputEvent::InputType inputType) { | 369 DeleteMode deleteMode, |
| 370 InputEvent::InputType inputType, |
| 371 const Position& referenceMovePosition) { |
369 if (frame().selection().isNone()) | 372 if (frame().selection().isNone()) |
370 return; | 373 return; |
371 | 374 |
372 const bool kMergeBlocksAfterDelete = true; | 375 const bool kMergeBlocksAfterDelete = true; |
373 const bool kExpandForSpecialElements = false; | 376 const bool kExpandForSpecialElements = false; |
374 const bool kSanitizeMarkup = true; | 377 const bool kSanitizeMarkup = true; |
375 DCHECK(frame().document()); | 378 DCHECK(frame().document()); |
376 DeleteSelectionCommand::create( | 379 DeleteSelectionCommand::create( |
377 *frame().document(), smartDelete, kMergeBlocksAfterDelete, | 380 *frame().document(), deleteMode == DeleteMode::Smart, |
378 kExpandForSpecialElements, kSanitizeMarkup, inputType) | 381 kMergeBlocksAfterDelete, kExpandForSpecialElements, kSanitizeMarkup, |
| 382 inputType, referenceMovePosition) |
379 ->apply(); | 383 ->apply(); |
380 } | 384 } |
381 | 385 |
382 void Editor::pasteAsPlainText(const String& pastingText, bool smartReplace) { | 386 void Editor::pasteAsPlainText(const String& pastingText, bool smartReplace) { |
383 Element* target = findEventTargetFromSelection(); | 387 Element* target = findEventTargetFromSelection(); |
384 if (!target) | 388 if (!target) |
385 return; | 389 return; |
386 target->dispatchEvent(TextEvent::createForPlainTextPaste( | 390 target->dispatchEvent(TextEvent::createForPlainTextPaste( |
387 frame().domWindow(), pastingText, smartReplace)); | 391 frame().domWindow(), pastingText, smartReplace)); |
388 } | 392 } |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
572 | 576 |
573 void Editor::replaceSelectionWithText(const String& text, | 577 void Editor::replaceSelectionWithText(const String& text, |
574 bool selectReplacement, | 578 bool selectReplacement, |
575 bool smartReplace) { | 579 bool smartReplace) { |
576 replaceSelectionWithFragment(createFragmentFromText(selectedRange(), text), | 580 replaceSelectionWithFragment(createFragmentFromText(selectedRange(), text), |
577 selectReplacement, smartReplace, true); | 581 selectReplacement, smartReplace, true); |
578 } | 582 } |
579 | 583 |
580 // TODO(xiaochengh): Merge it with |replaceSelectionWithFragment()|. | 584 // TODO(xiaochengh): Merge it with |replaceSelectionWithFragment()|. |
581 void Editor::replaceSelectionAfterDragging(DocumentFragment* fragment, | 585 void Editor::replaceSelectionAfterDragging(DocumentFragment* fragment, |
582 bool smartReplace, | 586 InsertMode insertMode, |
583 bool plainText) { | 587 DragSourceType dragSourceType) { |
584 ReplaceSelectionCommand::CommandOptions options = | 588 ReplaceSelectionCommand::CommandOptions options = |
585 ReplaceSelectionCommand::SelectReplacement | | 589 ReplaceSelectionCommand::SelectReplacement | |
586 ReplaceSelectionCommand::PreventNesting; | 590 ReplaceSelectionCommand::PreventNesting; |
587 if (smartReplace) | 591 if (insertMode == InsertMode::Smart) |
588 options |= ReplaceSelectionCommand::SmartReplace; | 592 options |= ReplaceSelectionCommand::SmartReplace; |
589 if (plainText) | 593 if (dragSourceType == DragSourceType::PlainTextSource) |
590 options |= ReplaceSelectionCommand::MatchStyle; | 594 options |= ReplaceSelectionCommand::MatchStyle; |
591 DCHECK(frame().document()); | 595 DCHECK(frame().document()); |
592 ReplaceSelectionCommand::create(*frame().document(), fragment, options, | 596 ReplaceSelectionCommand::create(*frame().document(), fragment, options, |
593 InputEvent::InputType::Drag) | 597 InputEvent::InputType::InsertFromDrop) |
594 ->apply(); | 598 ->apply(); |
595 } | 599 } |
596 | 600 |
597 void Editor::moveSelectionAfterDragging(DocumentFragment* fragment, | 601 bool Editor::deleteSelectionAfterDraggingWithEvents( |
598 const Position& pos, | 602 Element* dragSource, |
599 bool smartInsert, | 603 DeleteMode deleteMode, |
600 bool smartDelete) { | 604 const Position& referenceMovePosition) { |
601 MoveSelectionCommand::create(fragment, pos, smartInsert, smartDelete) | 605 if (!dragSource || !dragSource->isConnected()) |
602 ->apply(); | 606 return true; |
| 607 |
| 608 // Dispatch 'beforeinput'. |
| 609 const bool shouldDelete = dispatchBeforeInputEditorCommand( |
| 610 dragSource, InputEvent::InputType::DeleteByDrag, |
| 611 nullptr) == DispatchEventResult::NotCanceled; |
| 612 |
| 613 // 'beforeinput' event handler may destroy frame, return false to cancel remai
ning actions; |
| 614 if (m_frame->document()->frame() != m_frame) |
| 615 return false; |
| 616 |
| 617 if (shouldDelete && dragSource->isConnected()) { |
| 618 deleteSelectionWithSmartDelete( |
| 619 deleteMode, InputEvent::InputType::DeleteByDrag, referenceMovePosition); |
| 620 } |
| 621 |
| 622 return true; |
| 623 } |
| 624 |
| 625 bool Editor::replaceSelectionAfterDraggingWithEvents( |
| 626 Element* dropTarget, |
| 627 DragData* dragData, |
| 628 DocumentFragment* fragment, |
| 629 Range* dropCaretRange, |
| 630 InsertMode insertMode, |
| 631 DragSourceType dragSourceType) { |
| 632 if (!dropTarget || !dropTarget->isConnected()) |
| 633 return true; |
| 634 |
| 635 // Dispatch 'beforeinput'. |
| 636 DataTransfer* dataTransfer = |
| 637 DataTransfer::create(DataTransfer::DragAndDrop, DataTransferReadable, |
| 638 dragData->platformData()); |
| 639 dataTransfer->setSourceOperation(dragData->draggingSourceOperationMask()); |
| 640 const bool shouldInsert = |
| 641 dispatchBeforeInputDataTransfer( |
| 642 dropTarget, InputEvent::InputType::InsertFromDrop, dataTransfer, |
| 643 nullptr) == DispatchEventResult::NotCanceled; |
| 644 |
| 645 // 'beforeinput' event handler may destroy frame, return false to cancel remai
ning actions; |
| 646 if (m_frame->document()->frame() != m_frame) |
| 647 return false; |
| 648 |
| 649 if (shouldInsert && dropTarget->isConnected()) |
| 650 replaceSelectionAfterDragging(fragment, insertMode, dragSourceType); |
| 651 |
| 652 return true; |
603 } | 653 } |
604 | 654 |
605 EphemeralRange Editor::selectedRange() { | 655 EphemeralRange Editor::selectedRange() { |
606 return frame().selection().selection().toNormalizedEphemeralRange(); | 656 return frame().selection().selection().toNormalizedEphemeralRange(); |
607 } | 657 } |
608 | 658 |
609 bool Editor::canDeleteRange(const EphemeralRange& range) const { | 659 bool Editor::canDeleteRange(const EphemeralRange& range) const { |
610 if (range.isCollapsed()) | 660 if (range.isCollapsed()) |
611 return false; | 661 return false; |
612 | 662 |
(...skipping 20 matching lines...) Expand all Loading... |
633 | 683 |
634 spellChecker().updateMarkersForWordsAffectedByEditing(true); | 684 spellChecker().updateMarkersForWordsAffectedByEditing(true); |
635 client().respondToChangedContents(); | 685 client().respondToChangedContents(); |
636 } | 686 } |
637 | 687 |
638 void Editor::removeFormattingAndStyle() { | 688 void Editor::removeFormattingAndStyle() { |
639 DCHECK(frame().document()); | 689 DCHECK(frame().document()); |
640 RemoveFormatCommand::create(*frame().document())->apply(); | 690 RemoveFormatCommand::create(*frame().document())->apply(); |
641 } | 691 } |
642 | 692 |
| 693 void Editor::registerCommandGroup(CompositeEditCommand* commandGroupWrapper) { |
| 694 DCHECK(commandGroupWrapper->isCommandGroupWrapper()); |
| 695 m_lastEditCommand = commandGroupWrapper; |
| 696 } |
| 697 |
643 void Editor::clearLastEditCommand() { | 698 void Editor::clearLastEditCommand() { |
644 m_lastEditCommand.clear(); | 699 m_lastEditCommand.clear(); |
645 } | 700 } |
646 | 701 |
647 Element* Editor::findEventTargetFrom(const VisibleSelection& selection) const { | 702 Element* Editor::findEventTargetFrom(const VisibleSelection& selection) const { |
648 Element* target = associatedElementOf(selection.start()); | 703 Element* target = associatedElementOf(selection.start()); |
649 if (!target) | 704 if (!target) |
650 target = frame().document()->body(); | 705 target = frame().document()->body(); |
651 | 706 |
652 return target; | 707 return target; |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
733 Element* endRoot) { | 788 Element* endRoot) { |
734 if (startRoot) | 789 if (startRoot) |
735 startRoot->dispatchEvent( | 790 startRoot->dispatchEvent( |
736 Event::create(EventTypeNames::webkitEditableContentChanged)); | 791 Event::create(EventTypeNames::webkitEditableContentChanged)); |
737 if (endRoot && endRoot != startRoot) | 792 if (endRoot && endRoot != startRoot) |
738 endRoot->dispatchEvent( | 793 endRoot->dispatchEvent( |
739 Event::create(EventTypeNames::webkitEditableContentChanged)); | 794 Event::create(EventTypeNames::webkitEditableContentChanged)); |
740 } | 795 } |
741 | 796 |
742 void Editor::appliedEditing(CompositeEditCommand* cmd) { | 797 void Editor::appliedEditing(CompositeEditCommand* cmd) { |
| 798 DCHECK(!cmd->isCommandGroupWrapper()); |
743 EventQueueScope scope; | 799 EventQueueScope scope; |
744 frame().document()->updateStyleAndLayout(); | 800 frame().document()->updateStyleAndLayout(); |
745 | 801 |
746 // Request spell checking before any further DOM change. | 802 // Request spell checking before any further DOM change. |
747 spellChecker().markMisspellingsAfterApplyingCommand(*cmd); | 803 spellChecker().markMisspellingsAfterApplyingCommand(*cmd); |
748 | 804 |
749 EditCommandComposition* composition = cmd->composition(); | 805 EditCommandComposition* composition = cmd->composition(); |
750 DCHECK(composition); | 806 DCHECK(composition); |
751 dispatchEditableContentChangedEvents( | 807 dispatchEditableContentChangedEvents( |
752 composition->startingRootEditableElement(), | 808 composition->startingRootEditableElement(), |
753 composition->endingRootEditableElement()); | 809 composition->endingRootEditableElement()); |
754 // TODO(chongz): Filter empty InputType after spec is finalized. | 810 // TODO(chongz): Filter empty InputType after spec is finalized. |
755 dispatchInputEventEditableContentChanged( | 811 dispatchInputEventEditableContentChanged( |
756 composition->startingRootEditableElement(), | 812 composition->startingRootEditableElement(), |
757 composition->endingRootEditableElement(), cmd->inputType(), | 813 composition->endingRootEditableElement(), cmd->inputType(), |
758 cmd->textDataForInputEvent(), isComposingFromCommand(cmd)); | 814 cmd->textDataForInputEvent(), isComposingFromCommand(cmd)); |
759 VisibleSelection newSelection(cmd->endingSelection()); | 815 VisibleSelection newSelection(cmd->endingSelection()); |
760 | 816 |
761 // Don't clear the typing style with this selection change. We do those things
elsewhere if necessary. | 817 // Don't clear the typing style with this selection change. We do those things
elsewhere if necessary. |
762 changeSelectionAfterCommand(newSelection, 0); | 818 changeSelectionAfterCommand(newSelection, 0); |
763 | 819 |
764 if (!cmd->preservesTypingStyle()) | 820 if (!cmd->preservesTypingStyle()) |
765 frame().selection().clearTypingStyle(); | 821 frame().selection().clearTypingStyle(); |
766 | 822 |
767 // Command will be equal to last edit command only in the case of typing | 823 // Command will be equal to last edit command only in the case of typing |
768 if (m_lastEditCommand.get() == cmd) { | 824 if (m_lastEditCommand.get() == cmd) { |
769 DCHECK(cmd->isTypingCommand()); | 825 DCHECK(cmd->isTypingCommand()); |
| 826 } else if (m_lastEditCommand && m_lastEditCommand->isDragAndDropCommand() && |
| 827 (cmd->inputType() == InputEvent::InputType::DeleteByDrag || |
| 828 cmd->inputType() == InputEvent::InputType::InsertFromDrop)) { |
| 829 // Only register undo entry when combined with other commands. |
| 830 if (!m_lastEditCommand->composition()) |
| 831 m_undoStack->registerUndoStep(m_lastEditCommand->ensureComposition()); |
| 832 m_lastEditCommand->appendCommandToComposite(cmd); |
770 } else { | 833 } else { |
771 // Only register a new undo command if the command passed in is | 834 // Only register a new undo command if the command passed in is |
772 // different from the last command | 835 // different from the last command |
773 m_lastEditCommand = cmd; | 836 m_lastEditCommand = cmd; |
774 m_undoStack->registerUndoStep(m_lastEditCommand->ensureComposition()); | 837 m_undoStack->registerUndoStep(m_lastEditCommand->ensureComposition()); |
775 } | 838 } |
776 | 839 |
777 respondToChangedContents(newSelection); | 840 respondToChangedContents(newSelection); |
778 } | 841 } |
779 | 842 |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
954 if (source == CommandFromMenuOrKeyBinding) { | 1017 if (source == CommandFromMenuOrKeyBinding) { |
955 if (dispatchBeforeInputDataTransfer(findEventTargetFromSelection(), | 1018 if (dispatchBeforeInputDataTransfer(findEventTargetFromSelection(), |
956 InputEvent::InputType::DeleteByCut, | 1019 InputEvent::InputType::DeleteByCut, |
957 nullptr, nullptr) != | 1020 nullptr, nullptr) != |
958 DispatchEventResult::NotCanceled) | 1021 DispatchEventResult::NotCanceled) |
959 return; | 1022 return; |
960 // 'beforeinput' event handler may destroy target frame. | 1023 // 'beforeinput' event handler may destroy target frame. |
961 if (m_frame->document()->frame() != m_frame) | 1024 if (m_frame->document()->frame() != m_frame) |
962 return; | 1025 return; |
963 } | 1026 } |
964 deleteSelectionWithSmartDelete(canSmartCopyOrDelete(), | 1027 deleteSelectionWithSmartDelete( |
965 InputEvent::InputType::DeleteByCut); | 1028 canSmartCopyOrDelete() ? DeleteMode::Smart : DeleteMode::Simple, |
| 1029 InputEvent::InputType::DeleteByCut); |
966 } | 1030 } |
967 } | 1031 } |
968 | 1032 |
969 void Editor::copy() { | 1033 void Editor::copy() { |
970 if (tryDHTMLCopy()) | 1034 if (tryDHTMLCopy()) |
971 return; // DHTML did the whole operation | 1035 return; // DHTML did the whole operation |
972 if (!canCopy()) | 1036 if (!canCopy()) |
973 return; | 1037 return; |
974 if (enclosingTextFormControl(frame().selection().start())) { | 1038 if (enclosingTextFormControl(frame().selection().start())) { |
975 Pasteboard::generalPasteboard()->writePlainText( | 1039 Pasteboard::generalPasteboard()->writePlainText( |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1030 spellChecker().updateMarkersForWordsAffectedByEditing(false); | 1094 spellChecker().updateMarkersForWordsAffectedByEditing(false); |
1031 pasteAsPlainTextWithPasteboard(Pasteboard::generalPasteboard()); | 1095 pasteAsPlainTextWithPasteboard(Pasteboard::generalPasteboard()); |
1032 } | 1096 } |
1033 | 1097 |
1034 void Editor::performDelete() { | 1098 void Editor::performDelete() { |
1035 if (!canDelete()) | 1099 if (!canDelete()) |
1036 return; | 1100 return; |
1037 addToKillRing(selectedRange()); | 1101 addToKillRing(selectedRange()); |
1038 // TODO(chongz): |Editor::performDelete()| has no direction. | 1102 // TODO(chongz): |Editor::performDelete()| has no direction. |
1039 // https://github.com/w3c/editing/issues/130 | 1103 // https://github.com/w3c/editing/issues/130 |
1040 deleteSelectionWithSmartDelete(canSmartCopyOrDelete(), | 1104 deleteSelectionWithSmartDelete( |
1041 InputEvent::InputType::DeleteContentBackward); | 1105 canSmartCopyOrDelete() ? DeleteMode::Smart : DeleteMode::Simple, |
| 1106 InputEvent::InputType::DeleteContentBackward); |
1042 | 1107 |
1043 // clear the "start new kill ring sequence" setting, because it was set to tru
e | 1108 // clear the "start new kill ring sequence" setting, because it was set to tru
e |
1044 // when the selection was updated by deleting the range | 1109 // when the selection was updated by deleting the range |
1045 setStartNewKillRingSequence(false); | 1110 setStartNewKillRingSequence(false); |
1046 } | 1111 } |
1047 | 1112 |
1048 static void countEditingEvent(ExecutionContext* executionContext, | 1113 static void countEditingEvent(ExecutionContext* executionContext, |
1049 const Event* event, | 1114 const Event* event, |
1050 UseCounter::Feature featureOnInput, | 1115 UseCounter::Feature featureOnInput, |
1051 UseCounter::Feature featureOnTextArea, | 1116 UseCounter::Feature featureOnTextArea, |
(...skipping 495 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1547 } | 1612 } |
1548 | 1613 |
1549 DEFINE_TRACE(Editor) { | 1614 DEFINE_TRACE(Editor) { |
1550 visitor->trace(m_frame); | 1615 visitor->trace(m_frame); |
1551 visitor->trace(m_lastEditCommand); | 1616 visitor->trace(m_lastEditCommand); |
1552 visitor->trace(m_undoStack); | 1617 visitor->trace(m_undoStack); |
1553 visitor->trace(m_mark); | 1618 visitor->trace(m_mark); |
1554 } | 1619 } |
1555 | 1620 |
1556 } // namespace blink | 1621 } // namespace blink |
OLD | NEW |