WebUI Tab Strip: Remove placeholder tab on dragleave

Fixed: 1056293
Change-Id: I988cd0d273bd8d5a2e771181f3da7f186b013acf
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2075545
Commit-Queue: John Lee <[email protected]>
Reviewed-by: Demetrios Papadopoulos <[email protected]>
Cr-Commit-Position: refs/heads/master@{#744904}
diff --git a/chrome/browser/resources/tab_strip/drag_manager.js b/chrome/browser/resources/tab_strip/drag_manager.js
index 362062f..e995086 100644
--- a/chrome/browser/resources/tab_strip/drag_manager.js
+++ b/chrome/browser/resources/tab_strip/drag_manager.js
@@ -182,8 +182,7 @@
   }
 
   cancel() {
-    if (isTabElement(this.element_) &&
-        this.element_.tab.id === PLACEHOLDER_TAB_ID) {
+    if (this.isDraggingPlaceholder()) {
       this.element_.remove();
       return;
     }
@@ -200,10 +199,15 @@
     this.element_.setDragging(false);
   }
 
+  /** @return {boolean} */
+  isDraggingPlaceholder() {
+    return isTabElement(this.element_) &&
+        this.element_.tab.id == PLACEHOLDER_TAB_ID;
+  }
+
   /** @param {!DragEvent} event */
   finish(event) {
-    if (isTabElement(this.element_) &&
-        this.element_.tab.id === PLACEHOLDER_TAB_ID) {
+    if (this.isDraggingPlaceholder()) {
       const id = Number(event.dataTransfer.getData(getTabIdDataType()));
       this.element_.tab = Object.assign({}, this.element_.tab, {id});
     }
@@ -351,6 +355,11 @@
 
   /** @private */
   onDragLeave_() {
+    if (this.dragSession_ && this.dragSession_.isDraggingPlaceholder()) {
+      this.dragSession_.cancel();
+      this.dragSession_ = null;
+    }
+
     // TODO(johntlee): Handle drag and drop groups from other windows with
     // DragSession.
     this.dropPlaceholder_.remove();
diff --git a/chrome/test/data/webui/tab_strip/drag_manager_test.js b/chrome/test/data/webui/tab_strip/drag_manager_test.js
index ce7aa18..af16e81 100644
--- a/chrome/test/data/webui/tab_strip/drag_manager_test.js
+++ b/chrome/test/data/webui/tab_strip/drag_manager_test.js
@@ -421,4 +421,27 @@
     draggedTab.dispatchEvent(new DragEvent('dragend', {bubbles: true}));
     assertEquals(draggedTab, delegate.children[draggedIndex]);
   });
+
+  test('DragLeaveRemovesExternalTab', () => {
+    const externalTabId = 1000;
+    const mockDataTransfer = new MockDataTransfer();
+    mockDataTransfer.setData(strings.tabIdDataType, `${externalTabId}`);
+    const dragEnterEvent = new DragEvent('dragenter', {
+      bubbles: true,
+      composed: true,
+      dataTransfer: mockDataTransfer,
+    });
+    delegate.dispatchEvent(dragEnterEvent);
+    assertTrue(
+        !!delegate.querySelector(`[data-tab-id="${PLACEHOLDER_TAB_ID}"]`));
+
+    const dragLeaveEvent = new DragEvent('dragleave', {
+      bubbles: true,
+      composed: true,
+      dataTransfer: mockDataTransfer,
+    });
+    delegate.dispatchEvent(dragLeaveEvent);
+    assertFalse(
+        !!delegate.querySelector(`[data-tab-id="${PLACEHOLDER_TAB_ID}"]`));
+  });
 });