diff --git a/devtools/client/aboutdebugging/components/addons-tab.js b/devtools/client/aboutdebugging/components/addons-tab.js --- a/devtools/client/aboutdebugging/components/addons-tab.js +++ b/devtools/client/aboutdebugging/components/addons-tab.js @@ -72,23 +72,25 @@ module.exports = createClass({ let debugDisabled = !Services.prefs.getBoolPref(CHROME_ENABLED_PREF) || !Services.prefs.getBoolPref(REMOTE_ENABLED_PREF); this.setState({ debugDisabled }); }, updateAddonsList() { - AddonManager.getAllAddons(addons => { - let extensions = addons.filter(addon => addon.isDebuggable).map(addon => { + this.props.client.listAddons(({ addons }) => { + let extensions = addons.filter(addon => addon.debuggable).map(addon => { return { name: addon.name, icon: addon.iconURL || ExtensionIcon, type: addon.type, - addonID: addon.id + addonID: addon.id, + addonActor: addon.actor, + isRestartless: addon.isRestartless }; }); this.setState({ extensions }); }); }, /** * Mandatory callback as AddonManager listener. diff --git a/devtools/client/aboutdebugging/components/target.js b/devtools/client/aboutdebugging/components/target.js --- a/devtools/client/aboutdebugging/components/target.js +++ b/devtools/client/aboutdebugging/components/target.js @@ -25,16 +25,18 @@ const Strings = Services.strings.createB module.exports = createClass({ displayName: "Target", render() { let { target, debugDisabled } = this.props; let isServiceWorker = (target.type === "serviceworker"); let isRunning = (!isServiceWorker || target.workerActor); + let isReloadable = (target.type === "extension" && + target.isRestartless); return dom.div({ className: "target" }, dom.img({ className: "target-icon", role: "presentation", src: target.icon }), dom.div({ className: "target-details" }, dom.div({ className: "target-name" }, target.name) ), @@ -50,16 +52,22 @@ module.exports = createClass({ className: "debug-button", onClick: this.debug, disabled: debugDisabled, }, Strings.GetStringFromName("debug")) : dom.button({ className: "start-button", onClick: this.start }, Strings.GetStringFromName("start")) + ), + (isReloadable ? + dom.button({ + onClick: this.reloadAddon + }, Strings.GetStringFromName("reload")) : + null ) ); }, debug() { let { target } = this.props; switch (target.type) { case "extension": @@ -87,16 +95,27 @@ module.exports = createClass({ if (target.workerActor) { client.request({ to: target.workerActor, type: "push" }); } }, + reloadAddon() { + let { client, target } = this.props; + if (target.addonActor) { + console.log('target.js: asking actor to reload'); + client.request({ + to: target.addonActor, + type: "reload" + }); + } + }, + start() { let { client, target } = this.props; if (target.type === "serviceworker" && !target.workerActor) { client.request({ to: target.registrationActor, type: "start" }); } diff --git a/devtools/client/locales/en-US/aboutdebugging.properties b/devtools/client/locales/en-US/aboutdebugging.properties --- a/devtools/client/locales/en-US/aboutdebugging.properties +++ b/devtools/client/locales/en-US/aboutdebugging.properties @@ -8,16 +8,17 @@ start = Start addons = Add-ons addonDebugging.label = Enable add-on debugging addonDebugging.tooltip = Turning this on will allow you to debug add-ons and various other parts of the browser chrome addonDebugging.moreInfo = more info loadTemporaryAddon = Load Temporary Add-on extensions = Extensions selectAddonFromFile2 = Select Manifest File or Package (.xpi) +reload = Reload workers = Workers serviceWorkers = Service Workers sharedWorkers = Shared Workers otherWorkers = Other Workers nothing = Nothing yet. diff --git a/devtools/server/actors/addon.js b/devtools/server/actors/addon.js --- a/devtools/server/actors/addon.js +++ b/devtools/server/actors/addon.js @@ -78,16 +78,19 @@ BrowserAddonActor.prototype = { this._contextPool.addActor(this._consoleActor); } return { actor: this.actorID, id: this.id, name: this._addon.name, url: this.url, + iconURL: this._addon.iconURL, + isRestartless: this._addon.isRestartless, + type: this._addon.type, debuggable: this._addon.isDebuggable, consoleActor: this._consoleActor.actorID, traits: { highlightable: false, networkMonitor: false, }, }; @@ -150,16 +153,21 @@ BrowserAddonActor.prototype = { this._contextPool.removeActor(this.threadActor); this.threadActor = null; this._sources = null; return { type: "detached" }; }, + onReload: function BAA_onReload() { + console.log('actor: reloading', this._addon); + this._addon.reload(); + }, + preNest: function() { let e = Services.wm.getEnumerator(null); while (e.hasMoreElements()) { let win = e.getNext(); let windowUtils = win.QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsIDOMWindowUtils); windowUtils.suppressEventHandling(true); windowUtils.suspendTimeouts(); @@ -244,17 +252,18 @@ BrowserAddonActor.prototype = { */ _findDebuggees: function (dbg) { return dbg.findAllGlobals().filter(this._shouldAddNewGlobalAsDebuggee); } }; BrowserAddonActor.prototype.requestTypes = { "attach": BrowserAddonActor.prototype.onAttach, - "detach": BrowserAddonActor.prototype.onDetach + "detach": BrowserAddonActor.prototype.onDetach, + "reload": BrowserAddonActor.prototype.onReload }; /** * The AddonConsoleActor implements capabilities needed for the add-on web * console feature. * * @constructor * @param object aAddon diff --git a/toolkit/mozapps/extensions/internal/XPIProvider.jsm b/toolkit/mozapps/extensions/internal/XPIProvider.jsm --- a/toolkit/mozapps/extensions/internal/XPIProvider.jsm +++ b/toolkit/mozapps/extensions/internal/XPIProvider.jsm @@ -6983,16 +6983,21 @@ AddonWrapper.prototype = { if(this.isActive && addon.icon64URL){ icons[64] = addon.icon64URL; } Object.freeze(icons); return icons; }, + get isRestartless() { + let addon = addonFor(this); + return addon.bootstrap; + }, + get screenshots() { let addon = addonFor(this); let repositoryAddon = addon._repositoryAddon; if (repositoryAddon && ("screenshots" in repositoryAddon)) { let repositoryScreenshots = repositoryAddon.screenshots; if (repositoryScreenshots && repositoryScreenshots.length > 0) return repositoryScreenshots; } @@ -7269,16 +7274,22 @@ AddonWrapper.prototype = { addon._hasResourceCache.set(aPath, false); return false; } finally { zipReader.close(); } }, + reload: function() { + this.userDisabled = true; + flushStartupCache(); + this.userDisabled = false; + }, + /** * Returns a URI to the selected resource or to the add-on bundle if aPath * is null. URIs to the bundle will always be file: URIs. URIs to resources * will be file: URIs if the add-on is unpacked or jar: URIs if the add-on is * still an XPI file. * * @param aPath * The path in the add-on to get the URI for or null to get a URI to