| // Copyright 2016 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import type {DragWrapperDelegate} from 'chrome://resources/js/drag_wrapper.js'; |
| |
| import {Service} from './service.js'; |
| |
| |
| declare global { |
| interface HTMLElementEventMap { |
| 'drag-and-drop-load-error': |
| CustomEvent<Error|chrome.developerPrivate.LoadError>; |
| } |
| } |
| |
| export class DragAndDropHandler implements DragWrapperDelegate { |
| dragEnabled: boolean; |
| private eventTarget_: EventTarget; |
| |
| constructor(dragEnabled: boolean, target: EventTarget) { |
| this.dragEnabled = dragEnabled; |
| this.eventTarget_ = target; |
| } |
| |
| shouldAcceptDrag(e: DragEvent): boolean { |
| // External Extension installation can be disabled globally, e.g. while a |
| // different overlay is already showing. |
| if (!this.dragEnabled) { |
| return false; |
| } |
| |
| // We can't access filenames during the 'dragenter' event, so we have to |
| // wait until 'drop' to decide whether to do something with the file or |
| // not. |
| // See: http://www.w3.org/TR/2011/WD-html5-20110113/dnd.html#concept-dnd-p |
| return !!e.dataTransfer!.types && |
| e.dataTransfer!.types.indexOf('Files') > -1; |
| } |
| |
| doDragEnter() { |
| Service.getInstance().notifyDragInstallInProgress(); |
| this.eventTarget_.dispatchEvent(new CustomEvent('extension-drag-started')); |
| } |
| |
| doDragLeave() { |
| this.fireDragEnded_(); |
| } |
| |
| doDragOver(e: DragEvent) { |
| e.preventDefault(); |
| } |
| |
| doDrop(e: DragEvent) { |
| this.fireDragEnded_(); |
| if (e.dataTransfer!.files.length !== 1) { |
| return; |
| } |
| |
| let handled = false; |
| |
| // Files lack a check if they're a directory, but we can find out through |
| // its item entry. |
| const item = e.dataTransfer!.items[0]!; |
| if (item.kind === 'file' && item.webkitGetAsEntry()!.isDirectory) { |
| handled = true; |
| this.handleDirectoryDrop_(); |
| } else if (/\.(crx|user\.js|zip)$/i.test(e.dataTransfer!.files[0]!.name)) { |
| // Only process files that look like extensions. Other files should |
| // navigate the browser normally. |
| handled = true; |
| this.handleFileDrop_(); |
| } |
| |
| if (handled) { |
| e.preventDefault(); |
| } |
| } |
| |
| /** |
| * Handles a dropped file. |
| */ |
| private handleFileDrop_() { |
| Service.getInstance().installDroppedFile(); |
| } |
| |
| /** |
| * Handles a dropped directory. |
| */ |
| private handleDirectoryDrop_() { |
| Service.getInstance().loadUnpackedFromDrag().catch(loadError => { |
| this.eventTarget_.dispatchEvent( |
| new CustomEvent('drag-and-drop-load-error', {detail: loadError})); |
| }); |
| } |
| |
| private fireDragEnded_() { |
| this.eventTarget_.dispatchEvent(new CustomEvent('extension-drag-ended')); |
| } |
| } |