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; |
} |
} |