function install(path, nameHint, _doUpdate) {
        return _extensionManagerCall(function (extensionManager) {
            var d                       = new $.Deferred(),
                destinationDirectory    = ExtensionLoader.getUserExtensionPath(),
                disabledDirectory       = destinationDirectory.replace(/\/user$/, "/disabled"),
                systemDirectory         = FileUtils.getNativeBracketsDirectoryPath() + "/extensions/default/";

            var operation = _doUpdate ? "update" : "install";
            extensionManager[operation](path, destinationDirectory, {
                disabledDirectory: disabledDirectory,
                systemExtensionDirectory: systemDirectory,
                apiVersion: brackets.metadata.apiVersion,
                nameHint: nameHint,
                proxy: PreferencesManager.get("proxy")
            })
                .done(function (result) {
                    result.keepFile = false;

                    if (result.installationStatus !== InstallationStatuses.INSTALLED || _doUpdate) {
                        d.resolve(result);
                    } else {
                        // This was a new extension and everything looked fine.
                        // We load it into Brackets right away.
                        ExtensionLoader.loadExtension(result.name, {
                            // On Windows, it looks like Node converts Unix-y paths to backslashy paths.
                            // We need to convert them back.
                            baseUrl: FileUtils.convertWindowsPathToUnixPath(result.installedTo)
                        }, "main").then(function () {
                            d.resolve(result);
                        }, function () {
                            d.reject(Errors.ERROR_LOADING);
                        });
                    }
                })
                .fail(function (error) {
                    d.reject(error);
                });

            return d.promise();
        });
    }
Validates and installs the package at the given path. Validation and
installation is handled by the Node process.

The extension will be installed into the user's extensions directory.
If the user already has the extension installed, it will instead go
into their disabled extensions directory.

The promise is resolved with an object:
{ errors: Array.<{string}>, metadata: { name:string, version:string, ... },
disabledReason:string, installedTo:string, commonPrefix:string }
metadata is pulled straight from package.json and is likely to be undefined
if there are errors. It is null if there was no package.json.

disabledReason is either null or the reason the extension was installed disabled.

@param {string} path Absolute path to the package zip file
@param {?string} nameHint Hint for the extension folder's name (used in favor of
         path's filename if present, and if no package metadata present).
@param {?boolean} _doUpdate private argument used to signal an update
@return {$.Promise} A promise that is resolved with information about the package
         (which may include errors, in which case the extension was disabled), or
         rejected with an error object.