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

Commit 314d7ff

Browse files
committed
Support disabling extensions via .disabled file.
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.
1 parent 5ef8413 commit 314d7ff

File tree

3 files changed

+70
-27
lines changed

3 files changed

+70
-27
lines changed

src/extensibility/ExtensionManager.js

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ define(function (require, exports, module) {
6767
* Extension status constants.
6868
*/
6969
var ENABLED = "enabled",
70+
DISABLED = "disabled",
7071
START_FAILED = "startFailed";
7172

7273
/**
@@ -240,8 +241,9 @@ define(function (require, exports, module) {
240241
* @param {string} path The local path of the loaded extension's folder.
241242
*/
242243
function _handleExtensionLoad(e, path) {
243-
function setData(id, metadata) {
244+
function setData(metadata) {
244245
var locationType,
246+
id = metadata.name,
245247
userExtensionPath = ExtensionLoader.getUserExtensionPath();
246248
if (path.indexOf(userExtensionPath) === 0) {
247249
locationType = LOCATION_USER;
@@ -265,27 +267,33 @@ define(function (require, exports, module) {
265267
metadata: metadata,
266268
path: path,
267269
locationType: locationType,
268-
status: (e.type === "loadFailed" ? START_FAILED : ENABLED)
270+
status: (e.type === "loadFailed" ? START_FAILED : (metadata.disabled ? DISABLED : ENABLED))
269271
};
270272

271273
synchronizeEntry(id);
272274
loadTheme(id);
273275
exports.trigger("statusChange", id);
274276
}
277+
278+
function deduceMetadata() {
279+
var match = path.match(/\/([^\/]+)$/),
280+
name = (match && match[1]) || path,
281+
metadata = { name: name, title: name };
282+
return metadata;
283+
}
275284

276-
ExtensionUtils.loadPackageJson(path)
285+
ExtensionUtils.loadMetadata(path)
277286
.done(function (metadata) {
278-
setData(metadata.name, metadata);
287+
setData(metadata);
279288
})
280-
.fail(function () {
289+
.fail(function (disabled) {
281290
// If there's no package.json, this is a legacy extension. It was successfully loaded,
282291
// but we don't have an official ID or metadata for it, so we just create an id and
283292
// "title" for it (which is the last segment of its pathname)
284293
// and record that it's enabled.
285-
var match = path.match(/\/([^\/]+)$/),
286-
name = (match && match[1]) || path,
287-
metadata = { name: name, title: name };
288-
setData(name, metadata);
294+
var metadata = deduceMetadata();
295+
metadata.disabled = disabled;
296+
setData(metadata);
289297
});
290298
}
291299

@@ -764,7 +772,8 @@ define(function (require, exports, module) {
764772
// Listen to extension load and loadFailed events
765773
ExtensionLoader
766774
.on("load", _handleExtensionLoad)
767-
.on("loadFailed", _handleExtensionLoad);
775+
.on("loadFailed", _handleExtensionLoad)
776+
.on("disabled", _handleExtensionLoad);
768777

769778

770779
EventDispatcher.makeEventDispatcher(exports);

src/utils/ExtensionLoader.js

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ define(function (require, exports, module) {
242242
var promise = new $.Deferred();
243243

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

247247
return promise
248248
.then(function (metadata) {
@@ -251,12 +251,20 @@ define(function (require, exports, module) {
251251
return;
252252
}
253253

254-
return loadExtensionModule(name, config, entryPoint);
254+
if (!metadata.disabled) {
255+
return loadExtensionModule(name, config, entryPoint);
256+
} else {
257+
return new $.Deferred().resolve().reject("disabled");
258+
}
255259
})
256260
.then(function () {
257261
exports.trigger("load", config.baseUrl);
258262
}, function (err) {
259-
exports.trigger("loadFailed", config.baseUrl);
263+
if (err === "disabled") {
264+
exports.trigger("disabled", config.baseUrl);
265+
} else {
266+
exports.trigger("loadFailed", config.baseUrl);
267+
}
260268
});
261269
}
262270

src/utils/ExtensionUtils.js

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@
3131
define(function (require, exports, module) {
3232
"use strict";
3333

34-
var FileSystem = require("filesystem/FileSystem"),
34+
var Async = require("utils/Async"),
35+
FileSystem = require("filesystem/FileSystem"),
3536
FileUtils = require("file/FileUtils");
3637

3738
/**
@@ -233,26 +234,51 @@ define(function (require, exports, module) {
233234
}
234235

235236
/**
236-
* Loads the package.json file in the given extension folder.
237+
* Loads the package.json file in the given extension folder as well as any additional
238+
* metadata.
239+
*
240+
* If there's a .disabled file in the extension directory, then the content of package.json
241+
* will be augmented with disabled property set to true. It will override whatever value of
242+
* disabled might be set.
237243
*
238244
* @param {string} folder The extension folder.
239245
* @return {$.Promise} A promise object that is resolved with the parsed contents of the package.json file,
240-
* or rejected if there is no package.json or the contents are not valid JSON.
246+
* or rejected if there is no package.json with the boolean indicating whether .disabled file exists.
241247
*/
242-
function loadPackageJson(folder) {
243-
var file = FileSystem.getFileForPath(folder + "/package.json"),
244-
result = new $.Deferred();
245-
FileUtils.readAsText(file)
246-
.done(function (text) {
248+
function loadMetadata(folder) {
249+
var packageJSONFile = FileSystem.getFileForPath(folder + "/package.json"),
250+
disabledFile = FileSystem.getFileForPath(folder + "/.disabled"),
251+
result = new $.Deferred(),
252+
jsonPromise = new $.Deferred(),
253+
disabledPromise = new $.Deferred(),
254+
json,
255+
disabled;
256+
FileUtils.readAsText(packageJSONFile)
257+
.then(function (text) {
247258
try {
248-
var json = JSON.parse(text);
249-
result.resolve(json);
259+
json = JSON.parse(text);
260+
jsonPromise.resolve();
250261
} catch (e) {
251-
result.reject();
262+
jsonPromise.reject();
252263
}
253264
})
254-
.fail(function () {
255-
result.reject();
265+
.fail(jsonPromise.reject);
266+
disabledFile.exists(function (err, exists) {
267+
if (err) {
268+
disabled = false;
269+
} else {
270+
disabled = exists;
271+
}
272+
disabledPromise.resolve();
273+
});
274+
Async.waitForAll([jsonPromise, disabledPromise])
275+
.always(function () {
276+
if (!json) {
277+
result.reject(disabled);
278+
} else {
279+
json.disabled = disabled;
280+
result.resolve(json);
281+
}
256282
});
257283
return result.promise();
258284
}
@@ -264,5 +290,5 @@ define(function (require, exports, module) {
264290
exports.getModuleUrl = getModuleUrl;
265291
exports.loadFile = loadFile;
266292
exports.loadStyleSheet = loadStyleSheet;
267-
exports.loadPackageJson = loadPackageJson;
293+
exports.loadMetadata = loadMetadata;
268294
});

0 commit comments

Comments
 (0)