new file mode 100755
--- /dev/null
+++ b/devtools/client/inspector/inspector-html-server/bin/cypress-server.js
@@ -0,0 +1,47 @@
+"use strict";
+
+const express = require("express");
+const bodyParser = require("body-parser");
+const fs = require('fs');
+const path = require('path');
+
+/**
+ saves a fixture file to public/js/test/fixtures
+
+ @param name - name of the fixture file
+ @param text - fixture json text
+*/
+function saveFixture(name, text) {
+ function getFixtureFile(name) {
+ const fixturePath = path.join(__dirname, "../public/js/test/fixtures");
+ const fixtureFile = path.join(fixturePath, name + ".json");
+ if (!fs.existsSync(fixturePath)) {
+ throw new Error("Could not find fixture " + name);
+ }
+
+ return fixtureFile;
+ }
+
+ const fixtureFile = getFixtureFile(name);
+ fs.writeFileSync(fixtureFile, text)
+}
+
+const app = express();
+app.use(bodyParser.urlencoded({ extended: false }));
+app.use(bodyParser.json({ limit: "50mb" }));
+
+app.post("/save-fixture", function(req, res) {
+ const fixtureName = req.body.fixtureName;
+ const fixtureText = req.body.fixtureText;
+ saveFixture(fixtureName, fixtureText);
+
+ res.send(`saved fixture ${fixtureName}`);
+});
+
+app.listen(8001, "localhost", function(err, result) {
+ if (err) {
+ console.log(err);
+ }
+
+ console.log("Development Server Listening at http://localhost:8001");
+});
new file mode 100755
--- /dev/null
+++ b/devtools/client/inspector/inspector-html-server/bin/development-server.js
@@ -0,0 +1,158 @@
+#!/usr/bin/env node
+
+"use strict";
+
+require("babel-register");
+
+const path = require("path");
+const fs = require("fs");
+const Mustache = require("mustache");
+const webpack = require("webpack");
+const express = require("express");
+const webpackDevMiddleware = require("webpack-dev-middleware");
+const webpackHotMiddleware = require("webpack-hot-middleware");
+const http = require("http");
+const serveIndex = require("serve-index");
+
+// Setup Config
+const getConfig = require("../config/config").getConfig;
+const feature = require("../config/feature");
+const config = getConfig();
+
+feature.setConfig(config);
+
+if (!feature.getValue("firefox.webSocketConnection")) {
+ const firefoxProxy = require("./firefox-proxy");
+ firefoxProxy({ logging: feature.getValue("logging.firefoxProxy") });
+}
+
+function httpGet(url, onResponse) {
+ return http.get(url, (response) => {
+ if (response.statusCode !== 200) {
+ console.error(`error response: ${response.statusCode} to ${url}`);
+ response.emit("statusCode", new Error(response.statusCode));
+ return onResponse("{}");
+ }
+ let body = "";
+ response.on("data", function(d) {
+ body += d;
+ });
+ response.on("end", () => onResponse(body));
+ });
+}
+
+const app = express();
+
+// Webpack middleware
+// const webpackConfig = require("../../webpack.config");
+// const compiler = webpack(webpackConfig);
+
+// app.use(webpackDevMiddleware(compiler, {
+// publicPath: webpackConfig.output.publicPath,
+// noInfo: true,
+// stats: { colors: true }
+// }));
+
+if (feature.getValue("hotReloading")) {
+ app.use(webpackHotMiddleware(compiler));
+} else {
+ console.log("Hot Reloading can be enabled by adding " +
+ "\"hotReloading\": true to your local.json config");
+}
+
+// Static middleware
+app.use(express.static("public"));
+
+function sendFile(res, src, encoding) {
+ const filePath = path.join(__dirname, src);
+ const file = encoding ? fs.readFileSync(filePath, encoding) : fs.readFileSync(filePath);
+ res.send(file);
+}
+
+function addFileRoute(from, to) {
+ app.get(from, function(req, res) {
+ sendFile(res, to, "utf-8");
+ });
+}
+// Routes
+
+addFileRoute("/", "../../inspector.xhtml");
+addFileRoute("/markup/markup.xhtml", "../../markup/markup.xhtml");
+addFileRoute("/inspector.bundle.js", "../../inspector.bundle.js");
+addFileRoute("/devtools/content/inspector/inspector-html-bootstrap.js", "../../inspector-html-bootstrap.js");
+
+app.get("/devtools/skin/images/:file.png", function (req, res) {
+ res.contentType("image/png");
+ sendFile(res, "../../../themes/images/" + req.params.file + ".png");
+});
+
+app.get("/devtools/skin/images/:file.svg", function (req, res) {
+ res.contentType("image/svg+xml");
+ sendFile(res, "../../../themes/images/" + req.params.file + ".svg", "utf-8");
+});
+
+app.get("/images/:file.svg", function (req, res) {
+ res.contentType("image/svg+xml");
+ sendFile(res, "../../../themes/images/" + req.params.file + ".svg", "utf-8");
+});
+
+app.get("/devtools/skin/:file.css", function (req, res) {
+ res.contentType("text/css; charset=utf-8");
+ sendFile(res, "../../../themes/" + req.params.file + ".css", "utf-8");
+});
+
+app.get(/^\/devtools\/client\/(.*)\.css$/, function (req, res) {
+ res.contentType("text/css; charset=utf-8");
+ sendFile(res, "../../../" + req.params[0] + ".css");
+});
+
+app.get(/^\/devtools\/content\/(.*)\.css$/, function (req, res) {
+ res.contentType("text/css; charset=utf-8");
+ sendFile(res, "../../../" + req.params[0] + ".css");
+});
+
+app.get("/get", function(req, res) {
+ const url = req.query.url;
+ if(url.indexOf("file://") === 0) {
+ const path = url.replace("file://", "");
+ res.json(JSON.parse(fs.readFileSync(path, "utf8")));
+ }
+ else {
+ const httpReq = httpGet(
+ req.query.url,
+ body => {
+ try {
+ res.send(body);
+ } catch (e) {
+ res.status(500).send("Malformed json");
+ }
+ }
+ );
+
+ httpReq.on("error", err => res.status(500).send(err.code));
+ httpReq.on("statusCode", err => res.status(err.message).send(err.message));
+ }
+});
+
+// Listen'
+const serverPort = feature.getValue("development.serverPort");
+app.listen(serverPort, "0.0.0.0", function(err, result) {
+ if (err) {
+ console.log(err);
+ } else {
+ console.log(`Development Server Listening at http://localhost:${serverPort}`);
+ }
+});
+
+const examples = express();
+examples.use(express.static("public/js/test/examples"));
+examples.use(serveIndex("public/js/test/examples", { icons: true }));
+
+const examplesPort = feature.getValue("development.examplesPort");
+examples.listen(examplesPort, "0.0.0.0", function(err, result) {
+ if (err) {
+ console.log(err);
+ } else {
+ console.log(`View debugger examples at http://localhost:${examplesPort}`);
+ }
+});
new file mode 100755
--- /dev/null
+++ b/devtools/client/inspector/inspector-html-server/bin/download-firefox-artifact
@@ -0,0 +1,50 @@
+#!/usr/bin/env bash
+
+ROOT=`dirname $0`
+FIREFOX_PATH="$ROOT/../firefox"
+
+# check that mercurial is installed
+if [ -z "`command -v hg`" ]; then
+ echo >&2 "mercurial is required for mochitests, use 'brew install mercurial' on MacOS";
+ exit 1;
+fi
+
+if [ -d "$FIREFOX_PATH" ]; then
+ # convert path to absolute path
+ FIREFOX_PATH=$(cd "$ROOT/../firefox"; pwd)
+
+ # If we already have Firefox locally, just update it
+ cd "$FIREFOX_PATH";
+
+ if [ -n "`hg status`" ]; then
+ read -p "There are local changes to Firefox which will be overwritten. Are you sure? [Y/n] " -r
+ if [[ $REPLY == "n" ]]; then
+ exit 0;
+ fi
+
+ # If the mochitest dir has been symlinked, remove it as revert
+ # does not follow symlinks.
+ if [ -h "$FIREFOX_PATH/devtools/client/debugger/new/test/mochitest" ]; then
+ rm "$FIREFOX_PATH/devtools/client/debugger/new/test/mochitest";
+ fi
+
+ hg revert -a
+ fi
+
+ hg pull
+ hg update -C
+else
+ echo "Downloading Firefox source code, requires about 10-30min depending on connection"
+ hg clone https://hg.mozilla.org/mozilla-central/ "$FIREFOX_PATH"
+ # if somebody cancels (ctrl-c) out of the long download don't continue
+ if [ $? -ne 0 ]; then
+ exit 1;
+ fi
+ cd "$FIREFOX_PATH"
+
+ # Make an artifact build so it builds much faster
+ echo "
+ac_add_options --enable-artifact-builds
+mk_add_options MOZ_OBJDIR=./objdir-frontend
+" > .mozconfig
+fi
new file mode 100755
--- /dev/null
+++ b/devtools/client/inspector/inspector-html-server/bin/firefox-driver.js
@@ -0,0 +1,69 @@
+"use strict";
+
+const webdriver = require("selenium-webdriver");
+const firefox = require("selenium-webdriver/firefox");
+const By = webdriver.By;
+const until = webdriver.until;
+const Key = webdriver.Key;
+const minimist = require("minimist");
+
+const args = minimist(process.argv.slice(2),
+{ boolean: ["start", "tests", "websocket"] });
+
+const isWindows = /^win/.test(process.platform);
+const shouldStart = args.start;
+const isTests = args.tests;
+const useWebSocket = args.websocket;
+
+function firefoxBinary() {
+ let binary = new firefox.Binary();
+ binary.addArguments((!isWindows ? "-" : "") + "-start-debugger-server",
+ useWebSocket ? "ws:6080" : "6080");
+
+ return binary;
+}
+
+function firefoxProfile() {
+ let profile = new firefox.Profile();
+ profile.setPreference("devtools.debugger.remote-port", 6080);
+ profile.setPreference("devtools.debugger.remote-enabled", true);
+ profile.setPreference("devtools.chrome.enabled", true);
+ profile.setPreference("devtools.debugger.prompt-connection", false);
+ profile.setPreference("devtools.debugger.remote-websocket", useWebSocket);
+
+ return profile;
+}
+
+function start() {
+ let options = new firefox.Options();
+ options.setProfile(firefoxProfile());
+ options.setBinary(firefoxBinary());
+
+ const driver = new firefox.Driver(options);
+ return driver;
+}
+
+if (shouldStart) {
+ const driver = start();
+ driver.get("http://localhost:7999/todomvc");
+ setInterval(() => {}, 100);
+}
+
+function getResults(driver) {
+ driver
+ .findElement(By.id("mocha-stats"))
+ .getText().then(results => {
+ console.log("results ", results);
+ const match = results.match(/failures: (\d*)/);
+ const resultCode = parseInt(match[1], 10) > 0 ? 1 : 0;
+ process.exit(resultCode);
+ });
+}
+
+if (isTests) {
+ const driver = start();
+ driver.get("http://localhost:8003");
+ setTimeout(() => getResults(driver), 5000);
+}
+
+module.exports = { start, By, Key, until };
new file mode 100755
--- /dev/null
+++ b/devtools/client/inspector/inspector-html-server/bin/firefox-proxy
@@ -0,0 +1,77 @@
+#!/usr/bin/env node
+"use strict";
+
+const minimist = require("minimist");
+const ws = require("ws");
+const net = require("net");
+
+function proxy(webSocketPort, tcpPort, logging) {
+ console.log("Listening for WS on *:" + webSocketPort);
+ console.log("Will proxy to TCP on *:" + tcpPort + " on first WS connection");
+ if (!logging) {
+ console.log("Protocol messages can be logged by enabling " +
+ "logging.firefoxProtocol in your local.json config");
+ }
+ let wsServer = new ws.Server({ port: webSocketPort });
+ wsServer.on("connection", function onConnection(wsConnection) {
+ let tcpClient = net.connect({ port: tcpPort });
+ tcpClient.setEncoding("utf8");
+
+ tcpClient.on("connect", () => {
+ console.log("TCP connection succeeded");
+ });
+
+ tcpClient.on("error", e => {
+ wsConnection.close();
+ console.log("TCP connection failed: " + e);
+ });
+
+ tcpClient.on("data", data => {
+ if (logging) {
+ console.log("TCP -> WS: " + data);
+ }
+ try {
+ wsConnection.send(data);
+ } catch (e) {
+ tcpClient.end();
+ console.log("WS send failed, disconnected from TCP");
+ }
+ });
+
+ wsConnection.on("message", msg => {
+ if (logging) {
+ console.log("WS -> TCP: " + msg);
+ }
+ tcpClient.write(msg);
+ });
+
+ wsConnection.on("close", () => {
+ tcpClient.end();
+ console.log("WS connection closed, disconnected from TCP");
+ });
+
+ wsConnection.on("error", () => {
+ tcpClient.end();
+ console.log("WS connection error, disconnected from TCP");
+ });
+ });
+}
+
+const args = minimist(process.argv.slice(2));
+
+const WEB_SOCKET_PORT = args["web-socket-port"] || 9000;
+const TCP_PORT = args["tcp-port"] || 6080;
+const shouldStart = args.start;
+
+function start(options) {
+ const webSocketPort = options.webSocketPort || 9000;
+ const tcpPort = options.tcpPort || 6080;
+ const logging = !!options.logging;
+ proxy(webSocketPort, tcpPort, logging);
+}
+
+if (shouldStart) {
+ start({ webSocketPort: WEB_SOCKET_PORT, tcpPort: TCP_PORT });
+} else {
+ module.exports = start;
+}
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/inspector-html-server/bin/import-deps.js
@@ -0,0 +1,26 @@
+"use strict";
+
+const fs = require("fs");
+const glob = require("glob").sync;
+const path = require("path");
+
+const getConfig = require("../config/config").getConfig;
+const feature = require("../config/feature");
+const config = getConfig();
+feature.setConfig(config);
+
+const geckoDir = feature.getValue("firefox.geckoDir");
+if (!geckoDir) {
+ console.log("Set firefox.geckoDir in your local.json config.")
+ exit();
+}
+
+glob("public/js/lib/devtools/**/*.js").forEach((debuggerFile) => {
+ const geckoFilePath = path.join(
+ geckoDir,
+ path.relative("public/js/lib/", debuggerFile)
+ );
+
+ const fileText = fs.readFileSync(geckoFilePath, 'utf8');
+ fs.writeFileSync(debuggerFile, fileText);
+})
new file mode 100755
--- /dev/null
+++ b/devtools/client/inspector/inspector-html-server/bin/install-chrome
@@ -0,0 +1,6 @@
+#!/usr/bin/env bash
+
+curl -L -o google-chrome.deb https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
+sudo dpkg -i google-chrome.deb
+sudo sed -i 's|HERE/chrome\"|HERE/chrome\" --disable-setuid-sandbox|g' /opt/google/chrome/google-chrome
+rm google-chrome.deb
new file mode 100755
--- /dev/null
+++ b/devtools/client/inspector/inspector-html-server/bin/install-firefox
@@ -0,0 +1,8 @@
+#!/usr/bin/env bash
+
+wget https://ftp.mozilla.org/pub/firefox/releases/46.0/linux-x86_64/en-US/firefox-46.0.tar.bz2
+tar -xjf firefox-46.0.tar.bz2
+sudo rm -rf /opt/firefox46
+sudo rm /usr/bin/firefox
+sudo mv firefox /opt/firefox46
+sudo ln -s /opt/firefox46/firefox /usr/bin/firefox
new file mode 100755
--- /dev/null
+++ b/devtools/client/inspector/inspector-html-server/bin/make-firefox-bundle
@@ -0,0 +1,45 @@
+#!/bin/sh
+
+if [ -z "$1" ]; then
+ echo "Usage: $0 <path-to-firefox-repo>"
+ exit 1
+fi
+
+if [ "$2" == "--symlink-mochitests" ]; then
+ SYMLINK_MOCHITESTS=1
+fi
+
+ROOT=`dirname $0`
+DEBUGGER_PATH="$1/devtools/client/debugger/new"
+REV=`git log -1 --pretty=oneline`
+
+if [ ! -d "$DEBUGGER_PATH" ]; then
+ echo "Cannot find debugger at $DEBUGGER_PATH"
+ exit 2
+fi
+
+(
+ cd "$DEBUGGER_PATH";
+ if [ -d "DEBUGGER_PATH/.git" ]; then
+ if ! git log --oneline bundle.js | head -n 1 |
+ grep "UPDATE_BUNDLE" > /dev/null; then
+ echo "\033[31mWARNING\033[0m: bundle has changed on mozilla-central";
+ fi
+ fi
+);
+
+TARGET=firefox-panel node_modules/.bin/webpack
+echo "// Generated from: $REV\n" | cat - public/build/bundle.js > "$DEBUGGER_PATH/bundle.js"
+cp public/build/pretty-print-worker.js "$DEBUGGER_PATH"
+cp public/build/styles.css "$DEBUGGER_PATH"
+cp public/images/* "$DEBUGGER_PATH/images"
+
+rm -r "$DEBUGGER_PATH/test/mochitest"
+if [ -n "$SYMLINK_MOCHITESTS" ]; then
+ ln -s `pwd -P`"/$ROOT/../public/js/test/mochitest/" "$DEBUGGER_PATH/test/mochitest"
+else
+ rsync -avz public/js/test/mochitest/ "$DEBUGGER_PATH/test/mochitest"
+fi
+
+# Make sure a rebuild uses the new tests
+touch "$DEBUGGER_PATH/test/mochitest/browser.ini"
new file mode 100755
--- /dev/null
+++ b/devtools/client/inspector/inspector-html-server/bin/mocha-server.js
@@ -0,0 +1,67 @@
+#!/usr/bin/env node
+"use strict";
+
+const path = require("path");
+const webpack = require("webpack");
+const express = require("express");
+const projectConfig = require("../webpack.config");
+const webpackDevMiddleware = require("webpack-dev-middleware");
+const fs = require("fs");
+
+function recursiveReaddirSync(dir) {
+ let list = [];
+ const files = fs.readdirSync(dir);
+
+ files.forEach(function(file) {
+ const stats = fs.lstatSync(path.join(dir, file));
+ if (stats.isDirectory()) {
+ list = list.concat(recursiveReaddirSync(path.join(dir, file)));
+ } else {
+ list.push(path.join(dir, file));
+ }
+ });
+
+ return list;
+}
+
+function getTestPaths(dir) {
+ const paths = recursiveReaddirSync(dir);
+
+ return paths.filter(p => {
+ const inTestDirectory = path.dirname(p).includes("tests");
+ const inIntegrationDir = path.dirname(p).includes("integration");
+ const aHiddenFile = path.basename(p).charAt(0) == ".";
+ return inTestDirectory && !aHiddenFile && !inIntegrationDir;
+ });
+}
+
+const testPaths = getTestPaths(path.join(__dirname, "../public/js"));
+
+projectConfig.entry.bundle = projectConfig.entry.bundle.concat(testPaths);
+const config = Object.assign({}, projectConfig, {});
+
+const app = express();
+const compiler = webpack(config);
+
+app.use(express.static("public"));
+app.use(express.static("node_modules"));
+
+app.use(webpackDevMiddleware(compiler, {
+ publicPath: projectConfig.output.publicPath,
+ noInfo: true,
+ stats: {
+ colors: true
+ }
+}));
+
+app.get("/", function(req, res) {
+ res.sendFile(path.join(__dirname, "../mocha-runner.html"));
+});
+
+app.listen(8003, "localhost", function(err, result) {
+ if (err) {
+ console.log(err);
+ }
+
+ console.log("Listening at http://localhost:8003");
+});
new file mode 100755
--- /dev/null
+++ b/devtools/client/inspector/inspector-html-server/bin/prepare-mochitests-dev
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+
+ROOT=`dirname $0`
+FIREFOX_PATH="$ROOT/../firefox"
+
+# This will either download or update the local Firefox repo
+"$ROOT/download-firefox-artifact"
+
+# Update the debugger files, build firefox, and run all the mochitests
+"$ROOT/make-firefox-bundle" "$FIREFOX_PATH" --symlink-mochitests
+cd "$FIREFOX_PATH"
+./mach build
new file mode 100755
--- /dev/null
+++ b/devtools/client/inspector/inspector-html-server/bin/run-mochitests-docker
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+TARGET=firefox-panel ./node_modules/.bin/webpack
+
+docker run -it \
+ -v `pwd`/public/build/bundle.js:/firefox/devtools/client/debugger/new/bundle.js \
+ -v `pwd`/public/build/pretty-print-worker.js:/firefox/devtools/client/debugger/new/pretty-print-worker.js \
+ -v `pwd`/public/build/styles.css:/firefox/devtools/client/debugger/new/styles.css \
+ -v `pwd`/public/images:/firefox/devtools/client/debugger/new/images \
+ -v `pwd`/public/js/test/mochitest:/firefox/devtools/client/debugger/new/test/mochitest \
+ -v "/tmp/.X11-unix:/tmp/.X11-unix:rw" \
+ -e "DISPLAY=unix$DISPLAY" \
+ --ipc host \
+ jlongster/mochitest-runner \
+ /bin/bash -c "export SHELL=/bin/bash; touch devtools/client/debugger/new/test/mochitest/browser.ini && ./mach mochitest --subsuite devtools devtools/client/debugger/new/test/mochitest/"
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/inspector-html-server/config/README.md
@@ -0,0 +1,31 @@
+## Configuration
+
+All default config values are in [`config/development.json`](./development.json), to override these values you need to [create a local config file](#create-a-local-config-file).
+
+* `logging`
+ * `client` Enables logging the Firefox protocol in the devtools console of the debugger
+ * `firefoxProxy` Enables logging the Firefox protocol in the terminal running `npm start`
+ * `actions` Enables logging the redux actions
+* `features` debugger related features
+ * `tabs` Enables source view tabs in the editor (CodeMirror)
+ * `sourceMaps` Enables source map loading when available
+ * `watchExpressions` Enables accordion component for working with watch expressions
+* `chrome` Chrome browser related flags
+ * `debug` Enables listening for remotely debuggable Chrome browsers
+ * `webSocketPort` Configures the web socket port specified when launching Chrome from the command line
+* `firefox` Firefox browser related flags
+ * `proxyPort` Port used by the development server run with `npm start`
+ * `webSocketConnection` Favours Firefox WebSocket connection over the [firefox-proxy](../bin/firefox-proxy), :warning: Experimental feature and requires [bug 1286281](https://bugzilla.mozilla.org/show_bug.cgi?id=1286281)
+ * `geckoDir` Local location of Firefox source code _only needed by project maintainers_
+* `development` Development server related settings
+ * `serverPort` Listen Port used by the development server
+ * `examplesPort` Listen Port used to serve examples
+* `hotReloading` enables [Hot Reloading](../docs/local-development.md#hot-reloading) of CSS and React
+
+### Create a local config file
+
+To override any of the default configuration values above you need to create a new file in the config directory called `local.json`; it is easiest if you copy the `development.json` file.
+
+* Copy the [`config/development.json`](./development.json) to `config/local.json`
+
+> The `local.json` will be ignored by git so any changes you make won't be published, only make changes to the `development.json` file when related to features removed or added to the project.
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/inspector-html-server/config/ci.json
@@ -0,0 +1,10 @@
+{
+ "features": {
+ "sourceMaps": true,
+ "prettyPrint": true,
+ "watchExpressions": true
+ },
+ "chrome": {
+ "debug": true
+ }
+}
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/inspector-html-server/config/config.js
@@ -0,0 +1,30 @@
+"use strict";
+
+const _ = require("lodash");
+const fs = require("fs");
+const path = require("path");
+
+const firefoxPanel = require("./firefox-panel.json");
+const development = require("./development.json");
+const envConfig = process.env.TARGET === "firefox-panel" ?
+ firefoxPanel : development;
+
+let config;
+
+if(process.env.TARGET === "firefox-panel") {
+ config = firefoxPanel;
+}
+else {
+ const localConfig = fs.existsSync(path.join(__dirname, "./local.json")) ?
+ require("./local.json") : {};
+
+ config = _.merge({}, envConfig, localConfig);
+}
+
+function getConfig() {
+ return config;
+}
+
+module.exports = {
+ getConfig
+};
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/inspector-html-server/config/development.json
@@ -0,0 +1,29 @@
+{
+ "environment": "development",
+ "baseWorkerURL": "public/build/",
+ "logging": {
+ "client": false,
+ "firefoxProxy": false,
+ "actions": false
+ },
+ "features": {
+ "tabs": true,
+ "sourceMaps": true,
+ "prettyPrint": false,
+ "watchExpressions": false,
+ "search": true
+ },
+ "chrome": {
+ "debug": true,
+ "webSocketPort": 9222
+ },
+ "firefox": {
+ "proxyPort": 9000,
+ "webSocketConnection": false,
+ "webSocketPort": 6080
+ },
+ "development": {
+ "serverPort": 8000,
+ "examplesPort": 7999
+ }
+}
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/inspector-html-server/config/feature.js
@@ -0,0 +1,56 @@
+"use strict";
+
+const flag = false;
+const pick = require("lodash/get");
+let config;
+
+/**
+ * Gets a config value for a given key
+ * e.g "chrome.webSocketPort"
+ */
+function getValue(key) {
+ return pick(config, key);
+}
+
+function isEnabled(key) {
+ return config.features[key];
+}
+
+function isDevelopment() {
+ if(isFirefoxPanel()) {
+ // Default to production if compiling for the Firefox panel
+ return process.env.NODE_ENV === "development";
+ }
+ return process.env.NODE_ENV !== "production";
+}
+
+function isTesting() {
+ return flag.testing;
+}
+
+function isFirefoxPanel() {
+ return process.env.TARGET == "firefox-panel";
+}
+
+function isFirefox() {
+ return /firefox/i.test(navigator.userAgent);
+}
+
+function setConfig(value) {
+ config = value;
+}
+
+function getConfig() {
+ return config;
+}
+
+module.exports = {
+ isEnabled,
+ getValue,
+ isDevelopment,
+ isTesting,
+ isFirefoxPanel,
+ isFirefox,
+ getConfig,
+ setConfig
+};
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/inspector-html-server/config/firefox-panel.json
@@ -0,0 +1,9 @@
+{
+ "environment": "firefox-panel",
+ "baseWorkerURL": "resource://devtools/client/debugger/new/",
+ "logging": false,
+ "clientLogging": false,
+ "features": {
+ "tabs": true
+ }
+}
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/inspector-html-server/config/local.sample.json
@@ -0,0 +1,5 @@
+{
+ "firefox": {
+ "geckoDir": "/Users/jlaster/src/mozilla/gecko"
+ }
+}
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/inspector-html-server/config/tests/.eslintrc
@@ -0,0 +1,32 @@
+{
+ "globals": {
+ "after": true,
+ "afterEach": true,
+ "before": true,
+ "beforeEach": true,
+ "context": true,
+ "describe": true,
+ "it": true,
+ "mocha": true,
+ "setup": true,
+ "specify": true,
+ "suite": true,
+ "suiteSetup": true,
+ "suiteTeardown": true,
+ "teardown": true,
+ "test": true,
+ "xcontext": true,
+ "xdescribe": true,
+ "xit": true,
+ "xspecify": true,
+ "assert": true,
+ "expect": true,
+ "equal": true,
+ "ok": true
+ },
+ "rules": {
+ "camelcase": 0,
+ "no-unused-vars": [2, {"vars": "all", "args": "none", "varsIgnorePattern": "run_test"}],
+ "max-nested-callbacks": [2, 4],
+ }
+}
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/inspector-html-server/config/tests/feature.js
@@ -0,0 +1,39 @@
+const { isDevelopment, getValue, isEnabled, setConfig } = require("../feature");
+const expect = require("expect.js");
+
+describe("feature", () => {
+ it("isDevelopment", () => {
+ setConfig({ development: true });
+ expect(isDevelopment()).to.be.truthy;
+ });
+
+ it("isDevelopment - not defined", () => {
+ setConfig({ });
+ expect(isDevelopment()).to.be.falsey;
+ });
+
+ it("getValue - enabled", function() {
+ setConfig({ featureA: true });
+ expect(getValue("featureA")).to.be.truthy;
+ });
+
+ it("getValue - disabled", function() {
+ setConfig({ featureA: false });
+ expect(getValue("featureA")).to.be.falsey;
+ });
+
+ it("getValue - not present", function() {
+ setConfig({});
+ expect(getValue("featureA")).to.be.undefined;
+ });
+
+ it("isEnabled - enabled", function() {
+ setConfig({ features: { featureA: true }});
+ expect(isEnabled("featureA")).to.be.truthy;
+ });
+
+ it("isEnabled - disabled", function() {
+ setConfig({ features: { featureA: false }});
+ expect(isEnabled("featureA")).to.be.falsey;
+ });
+});
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/inspector-html-server/npm-debug.log
@@ -0,0 +1,45 @@
+0 info it worked if it ends with ok
+1 verbose cli [ '/usr/local/bin/node', '/usr/local/bin/npm', 'start' ]
+2 info using npm@3.8.3
+3 info using node@v5.10.1
+4 verbose run-script [ 'prestart', 'start', 'poststart' ]
+5 info lifecycle inspector.html@0.0.1~prestart: inspector.html@0.0.1
+6 silly lifecycle inspector.html@0.0.1~prestart: no script for prestart, continuing
+7 info lifecycle inspector.html@0.0.1~start: inspector.html@0.0.1
+8 verbose lifecycle inspector.html@0.0.1~start: unsafe-perm in lifecycle true
+9 verbose lifecycle inspector.html@0.0.1~start: PATH: /usr/local/lib/node_modules/npm/bin/node-gyp-bin:/Users/jdescottes/Development/hg/fx-team/devtools/client/inspector/inspector.html/node_modules/.bin:/usr/local/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
+10 verbose lifecycle inspector.html@0.0.1~start: CWD: /Users/jdescottes/Development/hg/fx-team/devtools/client/inspector/inspector.html
+11 silly lifecycle inspector.html@0.0.1~start: Args: [ '-c', 'node bin/development-server' ]
+12 silly lifecycle inspector.html@0.0.1~start: Returned: code: 1 signal: null
+13 info lifecycle inspector.html@0.0.1~start: Failed to exec start script
+14 verbose stack Error: inspector.html@0.0.1 start: `node bin/development-server`
+14 verbose stack Exit status 1
+14 verbose stack at EventEmitter.<anonymous> (/usr/local/lib/node_modules/npm/lib/utils/lifecycle.js:239:16)
+14 verbose stack at emitTwo (events.js:100:13)
+14 verbose stack at EventEmitter.emit (events.js:185:7)
+14 verbose stack at ChildProcess.<anonymous> (/usr/local/lib/node_modules/npm/lib/utils/spawn.js:24:14)
+14 verbose stack at emitTwo (events.js:100:13)
+14 verbose stack at ChildProcess.emit (events.js:185:7)
+14 verbose stack at maybeClose (internal/child_process.js:850:16)
+14 verbose stack at Process.ChildProcess._handle.onexit (internal/child_process.js:215:5)
+15 verbose pkgid inspector.html@0.0.1
+16 verbose cwd /Users/jdescottes/Development/hg/fx-team/devtools/client/inspector/inspector.html
+17 error Darwin 15.6.0
+18 error argv "/usr/local/bin/node" "/usr/local/bin/npm" "start"
+19 error node v5.10.1
+20 error npm v3.8.3
+21 error code ELIFECYCLE
+22 error inspector.html@0.0.1 start: `node bin/development-server`
+22 error Exit status 1
+23 error Failed at the inspector.html@0.0.1 start script 'node bin/development-server'.
+23 error Make sure you have the latest version of node.js and npm installed.
+23 error If you do, this is most likely a problem with the inspector.html package,
+23 error not with npm itself.
+23 error Tell the author that this fails on your system:
+23 error node bin/development-server
+23 error You can get information on how to open an issue for this project with:
+23 error npm bugs inspector.html
+23 error Or if that isn't available, you can get their info via:
+23 error npm owner ls inspector.html
+23 error There is likely additional logging output above.
+24 verbose exit [ 1, true ]
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/inspector-html-server/package.json
@@ -0,0 +1,97 @@
+{
+ "name": "inspector.html",
+ "version": "0.0.1",
+ "scripts": {
+ "start": "node bin/development-server"
+ },
+ "engineStrict": true,
+ "engines": {
+ "node": ">=5.0.0"
+ },
+ "dependencies": {
+ "classnames": "^2.2.5",
+ "codemirror": "^5.1.0",
+ "express": "^4.13.4",
+ "fuzzaldrin-plus": "^0.3.1",
+ "immutable": "^3.7.6",
+ "invariant": "^2.2.1",
+ "lodash": "^4.13.1",
+ "md5": "^2.2.1",
+ "mock-require": "^1.3.0",
+ "pretty-fast": "^0.2.0",
+ "react": "=0.14.7",
+ "react-dom": "=0.14.7",
+ "react-immutable-proptypes": "^1.7.1",
+ "react-inlinesvg": "^0.5.3",
+ "react-redux": "4.4.5",
+ "redux": "3.5.2",
+ "source-map": "^0.5.6",
+ "svg-inline-loader": "^0.7.1",
+ "svg-inline-react": "^1.0.2",
+ "tcomb": "^3.1.0"
+ },
+ "devDependencies": {
+ "amd-loader": "0.0.5",
+ "babel": "^6.5.2",
+ "babel-cli": "^6.7.5",
+ "babel-core": "^6.7.6",
+ "babel-eslint": "^6.1.2",
+ "babel-loader": "^6.2.4",
+ "babel-plugin-module-alias": "^1.4.0",
+ "babel-plugin-transform-async-to-generator": "^6.8.0",
+ "babel-plugin-transform-es2015-block-scoping": "^6.7.1",
+ "babel-plugin-transform-es2015-destructuring": "^6.6.5",
+ "babel-plugin-transform-es2015-parameters": "^6.7.0",
+ "babel-plugin-transform-es2015-spread": "^6.6.5",
+ "babel-plugin-transform-flow-strip-types": "^6.8.0",
+ "babel-plugin-transform-runtime": "^6.7.5",
+ "babel-polyfill": "^6.7.4",
+ "babel-preset-es2015": "^6.6.0",
+ "babel-preset-stage-0": "^6.5.0",
+ "babel-register": "^6.7.2",
+ "body-parser": "^1.15.0",
+ "check-node-version": "^1.1.2",
+ "co": "=4.6.0",
+ "css-loader": "^0.25.0",
+ "documentation": "^4.0.0-beta10",
+ "expect.js": "^0.3.1",
+ "extract-text-webpack-plugin": "^1.0.1",
+ "firefox-profile": "^0.4.0",
+ "flow-bin": "^0.33.0",
+ "geckodriver": "^1.1.2",
+ "glob": "^7.0.3",
+ "husky": "^0.11.7",
+ "install": "^0.8.1",
+ "json-loader": "^0.5.4",
+ "minimist": "^1.2.0",
+ "mocha": "^2.4.5",
+ "mocha-circleci-reporter": "0.0.1",
+ "mustache": "^2.2.1",
+ "net": "^1.0.2",
+ "node-static": "^0.7.7",
+ "npm": "^3.10.7",
+ "react-hot-loader": "^1.3.0",
+ "rimraf": "^2.5.2",
+ "selenium-webdriver": "^3.0.0-beta-2",
+ "serve-index": "^1.8.0",
+ "style-loader": "^0.13.1",
+ "stylelint": "^7.2.0",
+ "webpack": "1.13.1",
+ "webpack-dev-middleware": "^1.6.1",
+ "webpack-hot-middleware": "^2.12.0",
+ "workerjs": "^0.1.1",
+ "ws": "^1.0.1"
+ },
+ "files": [
+ "public"
+ ],
+ "greenkeeper": {
+ "ignore": [
+ "react",
+ "react-dom",
+ "react-redux",
+ "redux",
+ "codemirror"
+ ]
+ }
+}