toolkit/devtools/gcli/commands/cmd.js

changeset 0
6474c204b198
     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 +];

mercurial