summaryrefslogtreecommitdiffstats
path: root/devtools/shared/gcli/commands/cmd.js
blob: 1777ed96041c193d3d81d4309b78557914d4b660 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
/* 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";

const { Cc, Ci, Cu } = require("chrome");

const { OS } = Cu.import("resource://gre/modules/osfile.jsm", {});
const { TextEncoder, TextDecoder } = Cu.import('resource://gre/modules/commonjs/toolkit/loader.js', {});
const gcli = require("gcli/index");
const l10n = require("gcli/l10n");

loader.lazyGetter(this, "prefBranch", function() {
  let prefService = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService);
  return prefService.getBranch(null).QueryInterface(Ci.nsIPrefBranch2);
});

loader.lazyGetter(this, "supportsString", function() {
  return Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
});

loader.lazyImporter(this, "NetUtil", "resource://gre/modules/NetUtil.jsm");

const PREF_DIR = "devtools.commands.dir";

/**
 * Load all the .mozcmd files in the directory pointed to by PREF_DIR
 * @return A promise of an array of items suitable for gcli.addItems or
 * using in gcli.addItemsByModule
 */
function loadItemsFromMozDir() {
  let dirName = prefBranch.getComplexValue(PREF_DIR,
                                           Ci.nsISupportsString).data.trim();
  if (dirName == "") {
    return Promise.resolve([]);
  }

  // replaces ~ with the home directory path in unix and windows
  if (dirName.indexOf("~") == 0) {
    let dirService = Cc["@mozilla.org/file/directory_service;1"]
                      .getService(Ci.nsIProperties);
    let homeDirFile = dirService.get("Home", Ci.nsIFile);
    let homeDir = homeDirFile.path;
    dirName = dirName.substr(1);
    dirName = homeDir + dirName;
  }

  // statPromise resolves to nothing if dirName is a directory, or it
  // rejects with an error message otherwise
  let statPromise = OS.File.stat(dirName);
  statPromise = statPromise.then(
    function onSuccess(stat) {
      if (!stat.isDir) {
        throw new Error("'" + dirName + "' is not a directory.");
      }
    },
    function onFailure(reason) {
      if (reason instanceof OS.File.Error && reason.becauseNoSuchFile) {
        throw new Error("'" + dirName + "' does not exist.");
      } else {
        throw reason;
      }
    }
  );

  // We need to return (a promise of) an array of items from the *.mozcmd
  // files in dirName (which we can assume to be a valid directory now)
  return statPromise.then(() => {
    let itemPromises = [];

    let iterator = new OS.File.DirectoryIterator(dirName);
    let iterPromise = iterator.forEach(entry => {
      if (entry.name.match(/.*\.mozcmd$/) && !entry.isDir) {
        itemPromises.push(loadCommandFile(entry));
      }
    });

    return iterPromise.then(() => {
      iterator.close();
      return Promise.all(itemPromises).then((itemsArray) => {
        return itemsArray.reduce((prev, curr) => {
          return prev.concat(curr);
        }, []);
      });
    }, reason => { iterator.close(); throw reason; });
  });
}

exports.mozDirLoader = function(name) {
  return loadItemsFromMozDir().then(items => {
    return { items: items };
  });
};

/**
 * Load the commands from a single file
 * @param OS.File.DirectoryIterator.Entry entry The DirectoryIterator
 * Entry of the file containing the commands that we should read
 */
function loadCommandFile(entry) {
  let readPromise = OS.File.read(entry.path);
  return readPromise = readPromise.then(array => {
    let decoder = new TextDecoder();
    let source = decoder.decode(array);
    var principal = Cc["@mozilla.org/systemprincipal;1"]
                      .createInstance(Ci.nsIPrincipal);

    let sandbox = new Cu.Sandbox(principal, {
      sandboxName: entry.path
    });
    let data = Cu.evalInSandbox(source, sandbox, "1.8", entry.name, 1);

    if (!Array.isArray(data)) {
      console.error("Command file '" + entry.name + "' does not have top level array.");
      return;
    }

    return data;
  });
}

exports.items = [
  {
    name: "cmd",
    get hidden() {
      return !prefBranch.prefHasUserValue(PREF_DIR);
    },
    description: l10n.lookup("cmdDesc")
  },
  {
    item: "command",
    runAt: "client",
    name: "cmd refresh",
    description: l10n.lookup("cmdRefreshDesc"),
    get hidden() {
      return !prefBranch.prefHasUserValue(PREF_DIR);
    },
    exec: function(args, context) {
      gcli.load();

      let dirName = prefBranch.getComplexValue(PREF_DIR,
                                              Ci.nsISupportsString).data.trim();
      return l10n.lookupFormat("cmdStatus3", [ dirName ]);
    }
  },
  {
    item: "command",
    runAt: "client",
    name: "cmd setdir",
    description: l10n.lookup("cmdSetdirDesc"),
    manual: l10n.lookup("cmdSetdirManual3"),
    params: [
      {
        name: "directory",
        description: l10n.lookup("cmdSetdirDirectoryDesc"),
        type: {
          name: "file",
          filetype: "directory",
          existing: "yes"
        },
        defaultValue: null
      }
    ],
    returnType: "string",
    get hidden() {
      return true; // !prefBranch.prefHasUserValue(PREF_DIR);
    },
    exec: function(args, context) {
      supportsString.data = args.directory;
      prefBranch.setComplexValue(PREF_DIR, Ci.nsISupportsString, supportsString);

      gcli.load();

      return l10n.lookupFormat("cmdStatus3", [ args.directory ]);
    }
  }
];