Skip to content
This repository has been archived by the owner on Sep 6, 2021. It is now read-only.

Commit

Permalink
Support disabling extensions via .disabled file.
Browse files Browse the repository at this point in the history
Extension can also be disabled using `"disable": true` in the package.json.

Details:
    - Rename getPackageJson to getMetadata.
    - Check for presence of .disabled file in the extension directory and add
      it to the metadata.
    - Do not load extension if it is disabled instead, reject with disabled
      status.
    - Add DISABLED extension state.
    - Extension is still gets on record and is enumerated with all its
      metadata, but it's not started.
  • Loading branch information
busykai committed May 29, 2015
1 parent 5ef8413 commit 314d7ff
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 27 deletions.
29 changes: 19 additions & 10 deletions src/extensibility/ExtensionManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ define(function (require, exports, module) {
* Extension status constants.
*/
var ENABLED = "enabled",
DISABLED = "disabled",
START_FAILED = "startFailed";

/**
Expand Down Expand Up @@ -240,8 +241,9 @@ define(function (require, exports, module) {
* @param {string} path The local path of the loaded extension's folder.
*/
function _handleExtensionLoad(e, path) {
function setData(id, metadata) {
function setData(metadata) {
var locationType,
id = metadata.name,
userExtensionPath = ExtensionLoader.getUserExtensionPath();
if (path.indexOf(userExtensionPath) === 0) {
locationType = LOCATION_USER;
Expand All @@ -265,27 +267,33 @@ define(function (require, exports, module) {
metadata: metadata,
path: path,
locationType: locationType,
status: (e.type === "loadFailed" ? START_FAILED : ENABLED)
status: (e.type === "loadFailed" ? START_FAILED : (metadata.disabled ? DISABLED : ENABLED))
};

synchronizeEntry(id);
loadTheme(id);
exports.trigger("statusChange", id);
}

function deduceMetadata() {
var match = path.match(/\/([^\/]+)$/),
name = (match && match[1]) || path,
metadata = { name: name, title: name };
return metadata;
}

ExtensionUtils.loadPackageJson(path)
ExtensionUtils.loadMetadata(path)
.done(function (metadata) {
setData(metadata.name, metadata);
setData(metadata);
})
.fail(function () {
.fail(function (disabled) {
// If there's no package.json, this is a legacy extension. It was successfully loaded,
// but we don't have an official ID or metadata for it, so we just create an id and
// "title" for it (which is the last segment of its pathname)
// and record that it's enabled.
var match = path.match(/\/([^\/]+)$/),
name = (match && match[1]) || path,
metadata = { name: name, title: name };
setData(name, metadata);
var metadata = deduceMetadata();
metadata.disabled = disabled;
setData(metadata);
});
}

Expand Down Expand Up @@ -764,7 +772,8 @@ define(function (require, exports, module) {
// Listen to extension load and loadFailed events
ExtensionLoader
.on("load", _handleExtensionLoad)
.on("loadFailed", _handleExtensionLoad);
.on("loadFailed", _handleExtensionLoad)
.on("disabled", _handleExtensionLoad);


EventDispatcher.makeEventDispatcher(exports);
Expand Down
14 changes: 11 additions & 3 deletions src/utils/ExtensionLoader.js
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ define(function (require, exports, module) {
var promise = new $.Deferred();

// Try to load the package.json to figure out if we are loading a theme.
ExtensionUtils.loadPackageJson(config.baseUrl).always(promise.resolve);
ExtensionUtils.loadMetadata(config.baseUrl).always(promise.resolve);

return promise
.then(function (metadata) {
Expand All @@ -251,12 +251,20 @@ define(function (require, exports, module) {
return;
}

return loadExtensionModule(name, config, entryPoint);
if (!metadata.disabled) {
return loadExtensionModule(name, config, entryPoint);
} else {
return new $.Deferred().resolve().reject("disabled");
}
})
.then(function () {
exports.trigger("load", config.baseUrl);
}, function (err) {
exports.trigger("loadFailed", config.baseUrl);
if (err === "disabled") {
exports.trigger("disabled", config.baseUrl);
} else {
exports.trigger("loadFailed", config.baseUrl);
}
});
}

Expand Down
54 changes: 40 additions & 14 deletions src/utils/ExtensionUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
define(function (require, exports, module) {
"use strict";

var FileSystem = require("filesystem/FileSystem"),
var Async = require("utils/Async"),
FileSystem = require("filesystem/FileSystem"),
FileUtils = require("file/FileUtils");

/**
Expand Down Expand Up @@ -233,26 +234,51 @@ define(function (require, exports, module) {
}

/**
* Loads the package.json file in the given extension folder.
* Loads the package.json file in the given extension folder as well as any additional
* metadata.
*
* If there's a .disabled file in the extension directory, then the content of package.json
* will be augmented with disabled property set to true. It will override whatever value of
* disabled might be set.
*
* @param {string} folder The extension folder.
* @return {$.Promise} A promise object that is resolved with the parsed contents of the package.json file,
* or rejected if there is no package.json or the contents are not valid JSON.
* or rejected if there is no package.json with the boolean indicating whether .disabled file exists.
*/
function loadPackageJson(folder) {
var file = FileSystem.getFileForPath(folder + "/package.json"),
result = new $.Deferred();
FileUtils.readAsText(file)
.done(function (text) {
function loadMetadata(folder) {
var packageJSONFile = FileSystem.getFileForPath(folder + "/package.json"),
disabledFile = FileSystem.getFileForPath(folder + "/.disabled"),
result = new $.Deferred(),
jsonPromise = new $.Deferred(),
disabledPromise = new $.Deferred(),
json,
disabled;
FileUtils.readAsText(packageJSONFile)
.then(function (text) {
try {
var json = JSON.parse(text);
result.resolve(json);
json = JSON.parse(text);
jsonPromise.resolve();
} catch (e) {
result.reject();
jsonPromise.reject();
}
})
.fail(function () {
result.reject();
.fail(jsonPromise.reject);
disabledFile.exists(function (err, exists) {
if (err) {
disabled = false;
} else {
disabled = exists;
}
disabledPromise.resolve();
});
Async.waitForAll([jsonPromise, disabledPromise])
.always(function () {
if (!json) {
result.reject(disabled);
} else {
json.disabled = disabled;
result.resolve(json);
}
});
return result.promise();
}
Expand All @@ -264,5 +290,5 @@ define(function (require, exports, module) {
exports.getModuleUrl = getModuleUrl;
exports.loadFile = loadFile;
exports.loadStyleSheet = loadStyleSheet;
exports.loadPackageJson = loadPackageJson;
exports.loadMetadata = loadMetadata;
});

0 comments on commit 314d7ff

Please sign in to comment.