1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/devtools/gcli/commands/cmd.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,174 @@ 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 + 1.8 +"use strict"; 1.9 + 1.10 +const { Cc, Ci, Cu } = require("chrome"); 1.11 + 1.12 +const { Promise: promise } = require("resource://gre/modules/Promise.jsm"); 1.13 + 1.14 +const { OS } = Cu.import("resource://gre/modules/osfile.jsm", {}); 1.15 +const { TextEncoder, TextDecoder } = Cu.import('resource://gre/modules/commonjs/toolkit/loader.js', {}); 1.16 +const gcli = require("gcli/index"); 1.17 + 1.18 +loader.lazyGetter(this, "prefBranch", function() { 1.19 + let prefService = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService); 1.20 + return prefService.getBranch(null).QueryInterface(Ci.nsIPrefBranch2); 1.21 +}); 1.22 + 1.23 +loader.lazyGetter(this, "supportsString", function() { 1.24 + return Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString); 1.25 +}); 1.26 + 1.27 +loader.lazyImporter(this, "NetUtil", "resource://gre/modules/NetUtil.jsm"); 1.28 + 1.29 +const PREF_DIR = "devtools.commands.dir"; 1.30 + 1.31 +/** 1.32 + * Load all the .mozcmd files in the directory pointed to by PREF_DIR 1.33 + * @return A promise of an array of items suitable for gcli.addItems or 1.34 + * using in gcli.addItemsByModule 1.35 + */ 1.36 +function loadItemsFromMozDir() { 1.37 + let dirName = prefBranch.getComplexValue(PREF_DIR, 1.38 + Ci.nsISupportsString).data.trim(); 1.39 + if (dirName == "") { 1.40 + return promise.resolve([]); 1.41 + } 1.42 + 1.43 + // replaces ~ with the home directory path in unix and windows 1.44 + if (dirName.indexOf("~") == 0) { 1.45 + let dirService = Cc["@mozilla.org/file/directory_service;1"] 1.46 + .getService(Ci.nsIProperties); 1.47 + let homeDirFile = dirService.get("Home", Ci.nsIFile); 1.48 + let homeDir = homeDirFile.path; 1.49 + dirName = dirName.substr(1); 1.50 + dirName = homeDir + dirName; 1.51 + } 1.52 + 1.53 + // statPromise resolves to nothing if dirName is a directory, or it 1.54 + // rejects with an error message otherwise 1.55 + let statPromise = OS.File.stat(dirName); 1.56 + statPromise = statPromise.then( 1.57 + function onSuccess(stat) { 1.58 + if (!stat.isDir) { 1.59 + throw new Error("'" + dirName + "' is not a directory."); 1.60 + } 1.61 + }, 1.62 + function onFailure(reason) { 1.63 + if (reason instanceof OS.File.Error && reason.becauseNoSuchFile) { 1.64 + throw new Error("'" + dirName + "' does not exist."); 1.65 + } else { 1.66 + throw reason; 1.67 + } 1.68 + } 1.69 + ); 1.70 + 1.71 + // We need to return (a promise of) an array of items from the *.mozcmd 1.72 + // files in dirName (which we can assume to be a valid directory now) 1.73 + return statPromise.then(() => { 1.74 + let itemPromises = []; 1.75 + 1.76 + let iterator = new OS.File.DirectoryIterator(dirName); 1.77 + let iterPromise = iterator.forEach(entry => { 1.78 + if (entry.name.match(/.*\.mozcmd$/) && !entry.isDir) { 1.79 + itemPromises.push(loadCommandFile(entry)); 1.80 + } 1.81 + }); 1.82 + 1.83 + return iterPromise.then(() => { 1.84 + iterator.close(); 1.85 + return promise.all(itemPromises).then((itemsArray) => { 1.86 + return itemsArray.reduce((prev, curr) => { 1.87 + return prev.concat(curr); 1.88 + }, []); 1.89 + }); 1.90 + }, reason => { iterator.close(); throw reason; }); 1.91 + }); 1.92 +} 1.93 + 1.94 +exports.mozDirLoader = function(name) { 1.95 + return loadItemsFromMozDir().then(items => { 1.96 + return { items: items }; 1.97 + }); 1.98 +}; 1.99 + 1.100 +/** 1.101 + * Load the commands from a single file 1.102 + * @param OS.File.DirectoryIterator.Entry entry The DirectoryIterator 1.103 + * Entry of the file containing the commands that we should read 1.104 + */ 1.105 +function loadCommandFile(entry) { 1.106 + let readPromise = OS.File.read(entry.path); 1.107 + return readPromise = readPromise.then(array => { 1.108 + let decoder = new TextDecoder(); 1.109 + let source = decoder.decode(array); 1.110 + var principal = Cc["@mozilla.org/systemprincipal;1"] 1.111 + .createInstance(Ci.nsIPrincipal); 1.112 + 1.113 + let sandbox = new Cu.Sandbox(principal, { 1.114 + sandboxName: entry.path 1.115 + }); 1.116 + let data = Cu.evalInSandbox(source, sandbox, "1.8", entry.name, 1); 1.117 + 1.118 + if (!Array.isArray(data)) { 1.119 + console.error("Command file '" + entry.name + "' does not have top level array."); 1.120 + return; 1.121 + } 1.122 + 1.123 + return data; 1.124 + }); 1.125 +} 1.126 + 1.127 +exports.items = [ 1.128 + { 1.129 + name: "cmd", 1.130 + get hidden() { 1.131 + return !prefBranch.prefHasUserValue(PREF_DIR); 1.132 + }, 1.133 + description: gcli.lookup("cmdDesc") 1.134 + }, 1.135 + { 1.136 + name: "cmd refresh", 1.137 + description: gcli.lookup("cmdRefreshDesc"), 1.138 + get hidden() { 1.139 + return !prefBranch.prefHasUserValue(PREF_DIR); 1.140 + }, 1.141 + exec: function(args, context) { 1.142 + gcli.load(); 1.143 + 1.144 + let dirName = prefBranch.getComplexValue(PREF_DIR, 1.145 + Ci.nsISupportsString).data.trim(); 1.146 + return gcli.lookupFormat("cmdStatus2", [ dirName ]); 1.147 + } 1.148 + }, 1.149 + { 1.150 + name: "cmd setdir", 1.151 + description: gcli.lookup("cmdSetdirDesc"), 1.152 + params: [ 1.153 + { 1.154 + name: "directory", 1.155 + description: gcli.lookup("cmdSetdirDirectoryDesc"), 1.156 + type: { 1.157 + name: "file", 1.158 + filetype: "directory", 1.159 + existing: "yes" 1.160 + }, 1.161 + defaultValue: null 1.162 + } 1.163 + ], 1.164 + returnType: "string", 1.165 + get hidden() { 1.166 + return true; // !prefBranch.prefHasUserValue(PREF_DIR); 1.167 + }, 1.168 + exec: function(args, context) { 1.169 + supportsString.data = args.directory; 1.170 + prefBranch.setComplexValue(PREF_DIR, Ci.nsISupportsString, supportsString); 1.171 + 1.172 + gcli.load(); 1.173 + 1.174 + return gcli.lookupFormat("cmdStatus2", [ args.directory ]); 1.175 + } 1.176 + } 1.177 +];