function _installUsingDragAndDrop() {
        var installZips = [],
            updateZips = [],
            deferred = new $.Deferred(),
            validatePromise;

        brackets.app.getDroppedFiles(function (err, paths) {
            if (err) {
                // Only possible error is invalid params, silently ignore
                console.error(err);
                deferred.resolve();
                return;
            }

            // Parse zip files and separate new installs vs. updates
            validatePromise = Async.doInParallel_aggregateErrors(paths, function (path) {
                var result = new $.Deferred();

                FileSystem.resolve(path, function (err, file) {
                    var extension = FileUtils.getFileExtension(path),
                        isZip = file.isFile && (extension === "zip"),
                        errStr;

                    if (err) {
                        errStr = FileUtils.getFileErrorString(err);
                    } else if (!isZip) {
                        errStr = Strings.INVALID_ZIP_FILE;
                    }

                    if (errStr) {
                        result.reject(errStr);
                        return;
                    }

                    // Call validate() so that we open the local zip file and parse the
                    // package.json. We need the name to detect if this zip will be a
                    // new install or an update.
                    Package.validate(path, { requirePackageJSON: true }).done(function (info) {
                        if (info.errors.length) {
                            result.reject(info.errors.map(Package.formatError).join(" "));
                            return;
                        }

                        var extensionName = info.metadata.name,
                            extensionInfo = ExtensionManager.extensions[extensionName],
                            isUpdate = extensionInfo && !!extensionInfo.installInfo;

                        if (isUpdate) {
                            updateZips.push(file);
                        } else {
                            installZips.push(file);
                        }

                        result.resolve();
                    }).fail(function (err) {
                        result.reject(Package.formatError(err));
                    });
                });

                return result.promise();
            });

            validatePromise.done(function () {
                var installPromise = Async.doSequentially(installZips, function (file) {
                    return InstallExtensionDialog.installUsingDialog(file);
                });

                var updatePromise = installPromise.then(function () {
                    return Async.doSequentially(updateZips, function (file) {
                        return InstallExtensionDialog.updateUsingDialog(file).done(function (result) {
                            ExtensionManager.updateFromDownload(result);
                        });
                    });
                });

                // InstallExtensionDialog displays it's own errors, always
                // resolve the outer promise
                updatePromise.always(deferred.resolve);
            }).fail(function (errorArray) {
                deferred.reject(errorArray);
            });
        });

        return deferred.promise();
    }
@private
Install extensions from the local file system using the install dialog.
@return {$.Promise}