Chromium Code Reviews| Index: third_party/WebKit/Source/core/page/DragController.cpp |
| diff --git a/third_party/WebKit/Source/core/page/DragController.cpp b/third_party/WebKit/Source/core/page/DragController.cpp |
| index 70e4290a77a1b481e6320b4fce4f54f1837486a4..296f88e4d52f5f188edead036c4e0001f19cdabc 100644 |
| --- a/third_party/WebKit/Source/core/page/DragController.cpp |
| +++ b/third_party/WebKit/Source/core/page/DragController.cpp |
| @@ -92,6 +92,96 @@ |
| namespace blink { |
| +namespace { |
| + |
| +DataTransfer* createDraggingDataTransfer(DataTransferAccessPolicy policy, DragData* dragData) |
| +{ |
| + return DataTransfer::create(DataTransfer::DragAndDrop, policy, dragData->platformData()); |
| +} |
| + |
| +DocumentFragment* documentFragmentFromDragData(DragData* dragData, LocalFrame* frame, Range* context, bool allowPlainText, bool& chosePlainText) |
| +{ |
| + DCHECK(dragData); |
| + chosePlainText = false; |
| + |
| + Document& document = context->ownerDocument(); |
| + if (dragData->containsCompatibleContent()) { |
| + if (DocumentFragment* fragment = dragData->asFragment(frame)) |
| + return fragment; |
| + |
| + if (dragData->containsURL(DragData::DoNotConvertFilenames)) { |
| + String title; |
| + String url = dragData->asURL(DragData::DoNotConvertFilenames, &title); |
| + if (!url.isEmpty()) { |
| + HTMLAnchorElement* anchor = HTMLAnchorElement::create(document); |
| + anchor->setHref(AtomicString(url)); |
| + if (title.isEmpty()) { |
| + // Try the plain text first because the url might be normalized or escaped. |
| + if (dragData->containsPlainText()) |
| + title = dragData->asPlainText(); |
| + if (title.isEmpty()) |
| + title = url; |
| + } |
| + Node* anchorText = document.createTextNode(title); |
| + anchor->appendChild(anchorText); |
| + DocumentFragment* fragment = document.createDocumentFragment(); |
| + fragment->appendChild(anchor); |
| + return fragment; |
| + } |
| + } |
| + } |
| + if (allowPlainText && dragData->containsPlainText()) { |
| + chosePlainText = true; |
| + return createFragmentFromText(EphemeralRange(context), dragData->asPlainText()); |
| + } |
| + |
| + return nullptr; |
| +} |
| + |
| +bool doDeleteByDragWithEvents(Element* dragTarget, bool smartDelete, const Position& referenceMovePosition) |
|
yosin_UTC9
2016/09/28 04:19:03
Please add comment about |bool| return value.
chongz
2016/09/29 02:36:22
Done.
|
| +{ |
|
yosin_UTC9
2016/09/28 04:19:03
This function should be in Editor class and avoid
chongz
2016/09/29 02:36:22
Done.
|
| + if (!dragTarget || !dragTarget->isConnected()) |
| + return true; |
| + |
| + LocalFrame* dragFrame = dragTarget->document().frame(); |
| + |
| + // Dispatch 'beforeinput'. |
| + const bool shouldDelete = dispatchBeforeInputEditorCommand(dragTarget, InputEvent::InputType::DeleteByDrag, nullptr) == DispatchEventResult::NotCanceled; |
|
yosin_UTC9
2016/09/28 04:19:03
I think we should dispatch event to drag source ra
chongz
2016/09/29 02:36:22
Sorry for the confusion, I've renamed it to |dragS
|
| + |
| + // 'beforeinput' event handler may destroy frame, return false to cancel remaining actions; |
| + if (dragFrame != dragTarget->document().frame()) |
| + return false; |
| + |
| + if (shouldDelete && dragTarget->isConnected()) |
| + dragFrame->editor().deleteSelectionWithSmartDelete(smartDelete, InputEvent::InputType::DeleteByDrag, referenceMovePosition); |
| + |
| + return true; |
| +} |
| + |
| +bool doInsertFromDropWithEvents(Element* dropTarget, DragData* dragData, DocumentFragment* fragment, Range* dropCaretRange, bool smartInsert, bool chosePlainText) |
|
yosin_UTC9
2016/09/28 04:19:03
Please add comment about |bool| return value.
chongz
2016/09/29 02:36:22
Done.
|
| +{ |
|
yosin_UTC9
2016/09/28 04:19:03
This function should be in Editor class and avoid
chongz
2016/09/29 02:36:22
Done.
|
| + if (!dropTarget || !dropTarget->isConnected()) |
| + return true; |
| + |
| + LocalFrame* dropFrame = dropTarget->document().frame(); |
| + |
| + // Dispatch 'beforeinput'. |
| + DataTransfer* dataTransfer = createDraggingDataTransfer(DataTransferReadable, dragData); |
| + dataTransfer->setSourceOperation(dragData->draggingSourceOperationMask()); |
| + const bool shouldInsert = dispatchBeforeInputDataTransfer(dropTarget, InputEvent::InputType::InsertFromDrop, dataTransfer, nullptr) == DispatchEventResult::NotCanceled; |
| + |
| + // 'beforeinput' event handler may destroy frame, return false to cancel remaining actions; |
| + if (dropFrame != dropTarget->document().frame()) |
| + return false; |
| + |
| + if (shouldInsert && dropTarget->isConnected()) |
| + dropFrame->editor().replaceSelectionAfterDragging(fragment, smartInsert, chosePlainText); |
| + |
| + return true; |
| +} |
| + |
| +} // anonymous namespace |
| + |
| const int DragController::DragIconRightInset = 7; |
| const int DragController::DragIconBottomInset = 3; |
| @@ -124,11 +214,6 @@ static PlatformMouseEvent createMouseEvent(DragData* dragData) |
| PlatformMouseEvent::RealOrIndistinguishable, monotonicallyIncreasingTime()); |
| } |
| -static DataTransfer* createDraggingDataTransfer(DataTransferAccessPolicy policy, DragData* dragData) |
| -{ |
| - return DataTransfer::create(DataTransfer::DragAndDrop, policy, dragData->platformData()); |
| -} |
| - |
| DragController::DragController(Page* page) |
| : m_page(page) |
| , m_documentUnderMouse(nullptr) |
| @@ -145,45 +230,6 @@ DragController* DragController::create(Page* page) |
| return new DragController(page); |
| } |
| -static DocumentFragment* documentFragmentFromDragData(DragData* dragData, LocalFrame* frame, Range* context, bool allowPlainText, bool& chosePlainText) |
| -{ |
| - ASSERT(dragData); |
| - chosePlainText = false; |
| - |
| - Document& document = context->ownerDocument(); |
| - if (dragData->containsCompatibleContent()) { |
| - if (DocumentFragment* fragment = dragData->asFragment(frame)) |
| - return fragment; |
| - |
| - if (dragData->containsURL(DragData::DoNotConvertFilenames)) { |
| - String title; |
| - String url = dragData->asURL(DragData::DoNotConvertFilenames, &title); |
| - if (!url.isEmpty()) { |
| - HTMLAnchorElement* anchor = HTMLAnchorElement::create(document); |
| - anchor->setHref(AtomicString(url)); |
| - if (title.isEmpty()) { |
| - // Try the plain text first because the url might be normalized or escaped. |
| - if (dragData->containsPlainText()) |
| - title = dragData->asPlainText(); |
| - if (title.isEmpty()) |
| - title = url; |
| - } |
| - Node* anchorText = document.createTextNode(title); |
| - anchor->appendChild(anchorText); |
| - DocumentFragment* fragment = document.createDocumentFragment(); |
| - fragment->appendChild(anchor); |
| - return fragment; |
| - } |
| - } |
| - } |
| - if (allowPlainText && dragData->containsPlainText()) { |
| - chosePlainText = true; |
| - return createFragmentFromText(EphemeralRange(context), dragData->asPlainText()); |
| - } |
| - |
| - return nullptr; |
| -} |
| - |
| bool DragController::dragIsMove(FrameSelection& selection, DragData* dragData) |
| { |
| return m_documentUnderMouse == m_dragInitiator && selection.isContentEditable() && selection.isRange() && !isCopyKeyDown(dragData); |
| @@ -513,13 +559,23 @@ bool DragController::concludeEditDrag(DragData* dragData) |
| if (dragIsMove(innerFrame->selection(), dragData)) { |
| // NSTextView behavior is to always smart delete on moving a selection, |
| // but only to smart insert if the selection granularity is word granularity. |
| - bool smartDelete = innerFrame->editor().smartInsertDeleteEnabled(); |
| - bool smartInsert = smartDelete && innerFrame->selection().granularity() == WordGranularity && dragData->canSmartReplace(); |
| - innerFrame->editor().moveSelectionAfterDragging(fragment, dragCaret.base(), smartInsert, smartDelete); |
| + const bool smartDelete = innerFrame->editor().smartInsertDeleteEnabled(); |
| + const bool smartInsert = smartDelete && innerFrame->selection().granularity() == WordGranularity && dragData->canSmartReplace(); |
| + |
| + if (!doDeleteByDragWithEvents(innerFrame->editor().findEventTargetFromSelection(), smartDelete, dragCaret.base())) |
| + return false; |
| + |
| + innerFrame->selection().setSelection(VisibleSelection(range->startPosition(), range->endPosition())); |
| + if (innerFrame->selection().isAvailable()) { |
| + DCHECK(m_documentUnderMouse); |
| + if (!doInsertFromDropWithEvents(element, dragData, fragment, range, smartInsert, chosePlainText)) |
| + return false; |
| + } |
| } else { |
| if (setSelectionToDragCaret(innerFrame, dragCaret, range, point)) { |
| - ASSERT(m_documentUnderMouse); |
| - m_documentUnderMouse->frame()->editor().replaceSelectionAfterDragging(fragment, dragData->canSmartReplace(), chosePlainText); |
| + DCHECK(m_documentUnderMouse); |
| + if (!doInsertFromDropWithEvents(element, dragData, fragment, range, dragData->canSmartReplace(), chosePlainText)) |
| + return false; |
| } |
| } |
| } else { |
| @@ -530,8 +586,9 @@ bool DragController::concludeEditDrag(DragData* dragData) |
| if (setSelectionToDragCaret(innerFrame, dragCaret, range, point)) { |
| const bool canSmartReplace = false; |
| const bool chosePlainText = true; |
| - ASSERT(m_documentUnderMouse); |
| - m_documentUnderMouse->frame()->editor().replaceSelectionAfterDragging(createFragmentFromText(EphemeralRange(range), text), canSmartReplace, chosePlainText); |
| + DCHECK(m_documentUnderMouse); |
| + if (!doInsertFromDropWithEvents(element, dragData, createFragmentFromText(EphemeralRange(range), text), range, canSmartReplace, chosePlainText)) |
| + return false; |
| } |
| } |