1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/browser/devtools/app-manager/content/manifest-editor.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,146 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 +"use strict"; 1.8 + 1.9 +Cu.import("resource://gre/modules/osfile.jsm"); 1.10 +const {VariablesView} = 1.11 + Cu.import("resource:///modules/devtools/VariablesView.jsm", {}); 1.12 + 1.13 +const VARIABLES_VIEW_URL = 1.14 + "chrome://browser/content/devtools/widgets/VariablesView.xul"; 1.15 + 1.16 +function ManifestEditor(project) { 1.17 + this.project = project; 1.18 + this._onContainerReady = this._onContainerReady.bind(this); 1.19 + this._onEval = this._onEval.bind(this); 1.20 + this._onSwitch = this._onSwitch.bind(this); 1.21 + this._onDelete = this._onDelete.bind(this); 1.22 + this._onNew = this._onNew.bind(this); 1.23 +} 1.24 + 1.25 +ManifestEditor.prototype = { 1.26 + get manifest() { return this.project.manifest; }, 1.27 + 1.28 + get editable() { return this.project.type == "packaged"; }, 1.29 + 1.30 + show: function(containerElement) { 1.31 + let deferred = promise.defer(); 1.32 + let iframe = this._iframe = document.createElement("iframe"); 1.33 + 1.34 + iframe.addEventListener("load", function onIframeLoad() { 1.35 + iframe.removeEventListener("load", onIframeLoad, true); 1.36 + deferred.resolve(iframe.contentWindow); 1.37 + }, true); 1.38 + 1.39 + iframe.setAttribute("src", VARIABLES_VIEW_URL); 1.40 + iframe.classList.add("variables-view"); 1.41 + containerElement.appendChild(iframe); 1.42 + 1.43 + return deferred.promise.then(this._onContainerReady); 1.44 + }, 1.45 + 1.46 + _onContainerReady: function(varWindow) { 1.47 + let variablesContainer = varWindow.document.querySelector("#variables"); 1.48 + 1.49 + variablesContainer.classList.add("manifest-editor"); 1.50 + 1.51 + let editor = this.editor = new VariablesView(variablesContainer); 1.52 + 1.53 + editor.onlyEnumVisible = true; 1.54 + editor.alignedValues = true; 1.55 + editor.actionsFirst = true; 1.56 + 1.57 + if (this.editable) { 1.58 + editor.eval = this._onEval; 1.59 + editor.switch = this._onSwitch; 1.60 + editor.delete = this._onDelete; 1.61 + editor.new = this._onNew; 1.62 + } 1.63 + 1.64 + return this.update(); 1.65 + }, 1.66 + 1.67 + _onEval: function(variable, value) { 1.68 + let parent = this._descend(variable.ownerView.symbolicPath); 1.69 + try { 1.70 + parent[variable.name] = JSON.parse(value); 1.71 + } catch(e) { 1.72 + Cu.reportError(e); 1.73 + } 1.74 + 1.75 + this.update(); 1.76 + }, 1.77 + 1.78 + _onSwitch: function(variable, newName) { 1.79 + if (variable.name == newName) { 1.80 + return; 1.81 + } 1.82 + 1.83 + let parent = this._descend(variable.ownerView.symbolicPath); 1.84 + parent[newName] = parent[variable.name]; 1.85 + delete parent[variable.name]; 1.86 + 1.87 + this.update(); 1.88 + }, 1.89 + 1.90 + _onDelete: function(variable) { 1.91 + let parent = this._descend(variable.ownerView.symbolicPath); 1.92 + delete parent[variable.name]; 1.93 + }, 1.94 + 1.95 + _onNew: function(variable, newName, newValue) { 1.96 + let parent = this._descend(variable.symbolicPath); 1.97 + try { 1.98 + parent[newName] = JSON.parse(newValue); 1.99 + } catch(e) { 1.100 + Cu.reportError(e); 1.101 + } 1.102 + 1.103 + this.update(); 1.104 + }, 1.105 + 1.106 + /** 1.107 + * Returns the value located at a given path in the manifest. 1.108 + * @param path array 1.109 + * A string for each path component: ["developer", "name"] 1.110 + */ 1.111 + _descend: function(path) { 1.112 + let parent = this.manifest; 1.113 + while (path.length) { 1.114 + parent = parent[path.shift()]; 1.115 + } 1.116 + return parent; 1.117 + }, 1.118 + 1.119 + update: function() { 1.120 + this.editor.rawObject = this.manifest; 1.121 + this.editor.commitHierarchy(); 1.122 + 1.123 + // Wait until the animation from commitHierarchy has completed 1.124 + let deferred = promise.defer(); 1.125 + setTimeout(deferred.resolve, this.editor.lazyEmptyDelay + 1); 1.126 + return deferred.promise; 1.127 + }, 1.128 + 1.129 + save: function() { 1.130 + if (this.editable) { 1.131 + let validator = new AppValidator(this.project); 1.132 + let manifestFile = validator._getPackagedManifestFile(); 1.133 + let path = manifestFile.path; 1.134 + 1.135 + let encoder = new TextEncoder(); 1.136 + let data = encoder.encode(JSON.stringify(this.manifest, null, 2)); 1.137 + 1.138 + return OS.File.writeAtomic(path, data, { tmpPath: path + ".tmp" }); 1.139 + } 1.140 + 1.141 + return promise.resolve(); 1.142 + }, 1.143 + 1.144 + destroy: function() { 1.145 + if (this._iframe) { 1.146 + this._iframe.remove(); 1.147 + } 1.148 + } 1.149 +};