diff -r 000000000000 -r 6474c204b198 browser/devtools/app-manager/content/manifest-editor.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/browser/devtools/app-manager/content/manifest-editor.js Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,146 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +Cu.import("resource://gre/modules/osfile.jsm"); +const {VariablesView} = + Cu.import("resource:///modules/devtools/VariablesView.jsm", {}); + +const VARIABLES_VIEW_URL = + "chrome://browser/content/devtools/widgets/VariablesView.xul"; + +function ManifestEditor(project) { + this.project = project; + this._onContainerReady = this._onContainerReady.bind(this); + this._onEval = this._onEval.bind(this); + this._onSwitch = this._onSwitch.bind(this); + this._onDelete = this._onDelete.bind(this); + this._onNew = this._onNew.bind(this); +} + +ManifestEditor.prototype = { + get manifest() { return this.project.manifest; }, + + get editable() { return this.project.type == "packaged"; }, + + show: function(containerElement) { + let deferred = promise.defer(); + let iframe = this._iframe = document.createElement("iframe"); + + iframe.addEventListener("load", function onIframeLoad() { + iframe.removeEventListener("load", onIframeLoad, true); + deferred.resolve(iframe.contentWindow); + }, true); + + iframe.setAttribute("src", VARIABLES_VIEW_URL); + iframe.classList.add("variables-view"); + containerElement.appendChild(iframe); + + return deferred.promise.then(this._onContainerReady); + }, + + _onContainerReady: function(varWindow) { + let variablesContainer = varWindow.document.querySelector("#variables"); + + variablesContainer.classList.add("manifest-editor"); + + let editor = this.editor = new VariablesView(variablesContainer); + + editor.onlyEnumVisible = true; + editor.alignedValues = true; + editor.actionsFirst = true; + + if (this.editable) { + editor.eval = this._onEval; + editor.switch = this._onSwitch; + editor.delete = this._onDelete; + editor.new = this._onNew; + } + + return this.update(); + }, + + _onEval: function(variable, value) { + let parent = this._descend(variable.ownerView.symbolicPath); + try { + parent[variable.name] = JSON.parse(value); + } catch(e) { + Cu.reportError(e); + } + + this.update(); + }, + + _onSwitch: function(variable, newName) { + if (variable.name == newName) { + return; + } + + let parent = this._descend(variable.ownerView.symbolicPath); + parent[newName] = parent[variable.name]; + delete parent[variable.name]; + + this.update(); + }, + + _onDelete: function(variable) { + let parent = this._descend(variable.ownerView.symbolicPath); + delete parent[variable.name]; + }, + + _onNew: function(variable, newName, newValue) { + let parent = this._descend(variable.symbolicPath); + try { + parent[newName] = JSON.parse(newValue); + } catch(e) { + Cu.reportError(e); + } + + this.update(); + }, + + /** + * Returns the value located at a given path in the manifest. + * @param path array + * A string for each path component: ["developer", "name"] + */ + _descend: function(path) { + let parent = this.manifest; + while (path.length) { + parent = parent[path.shift()]; + } + return parent; + }, + + update: function() { + this.editor.rawObject = this.manifest; + this.editor.commitHierarchy(); + + // Wait until the animation from commitHierarchy has completed + let deferred = promise.defer(); + setTimeout(deferred.resolve, this.editor.lazyEmptyDelay + 1); + return deferred.promise; + }, + + save: function() { + if (this.editable) { + let validator = new AppValidator(this.project); + let manifestFile = validator._getPackagedManifestFile(); + let path = manifestFile.path; + + let encoder = new TextEncoder(); + let data = encoder.encode(JSON.stringify(this.manifest, null, 2)); + + return OS.File.writeAtomic(path, data, { tmpPath: path + ".tmp" }); + } + + return promise.resolve(); + }, + + destroy: function() { + if (this._iframe) { + this._iframe.remove(); + } + } +};