summaryrefslogtreecommitdiff
path: root/devtools/client/webconsole/new-console-output/components/grip-message-body.js
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/client/webconsole/new-console-output/components/grip-message-body.js')
-rw-r--r--devtools/client/webconsole/new-console-output/components/grip-message-body.js101
1 files changed, 101 insertions, 0 deletions
diff --git a/devtools/client/webconsole/new-console-output/components/grip-message-body.js b/devtools/client/webconsole/new-console-output/components/grip-message-body.js
new file mode 100644
index 000000000..9e353be0a
--- /dev/null
+++ b/devtools/client/webconsole/new-console-output/components/grip-message-body.js
@@ -0,0 +1,101 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* 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";
+
+// If this is being run from Mocha, then the browser loader hasn't set up
+// define. We need to do that before loading Rep.
+if (typeof define === "undefined") {
+ require("amd-loader");
+}
+
+// React
+const {
+ createFactory,
+ PropTypes
+} = require("devtools/client/shared/vendor/react");
+const { createFactories } = require("devtools/client/shared/components/reps/rep-utils");
+const { Rep } = createFactories(require("devtools/client/shared/components/reps/rep"));
+const StringRep = createFactories(require("devtools/client/shared/components/reps/string").StringRep).rep;
+const VariablesViewLink = createFactory(require("devtools/client/webconsole/new-console-output/components/variables-view-link"));
+const { Grip } = require("devtools/client/shared/components/reps/grip");
+
+GripMessageBody.displayName = "GripMessageBody";
+
+GripMessageBody.propTypes = {
+ grip: PropTypes.oneOfType([
+ PropTypes.string,
+ PropTypes.number,
+ PropTypes.object,
+ ]).isRequired,
+ serviceContainer: PropTypes.shape({
+ createElement: PropTypes.func.isRequired,
+ }),
+ userProvidedStyle: PropTypes.string,
+};
+
+function GripMessageBody(props) {
+ const { grip, userProvidedStyle, serviceContainer } = props;
+
+ let styleObject;
+ if (userProvidedStyle && userProvidedStyle !== "") {
+ styleObject = cleanupStyle(userProvidedStyle, serviceContainer.createElement);
+ }
+
+ return (
+ // @TODO once there is a longString rep, also turn off quotes for those.
+ typeof grip === "string"
+ ? StringRep({
+ object: grip,
+ useQuotes: false,
+ mode: props.mode,
+ style: styleObject
+ })
+ : Rep({
+ object: grip,
+ objectLink: VariablesViewLink,
+ defaultRep: Grip,
+ mode: props.mode,
+ })
+ );
+}
+
+function cleanupStyle(userProvidedStyle, createElement) {
+ // Regular expression that matches the allowed CSS property names.
+ const allowedStylesRegex = new RegExp(
+ "^(?:-moz-)?(?:background|border|box|clear|color|cursor|display|float|font|line|" +
+ "margin|padding|text|transition|outline|white-space|word|writing|" +
+ "(?:min-|max-)?width|(?:min-|max-)?height)"
+ );
+
+ // Regular expression that matches the forbidden CSS property values.
+ const forbiddenValuesRegexs = [
+ // url(), -moz-element()
+ /\b(?:url|(?:-moz-)?element)[\s('"]+/gi,
+
+ // various URL protocols
+ /['"(]*(?:chrome|resource|about|app|data|https?|ftp|file):+\/*/gi,
+ ];
+
+ // Use a dummy element to parse the style string.
+ let dummy = createElement("div");
+ dummy.style = userProvidedStyle;
+
+ // Return a style object as expected by React DOM components, e.g.
+ // {color: "red"}
+ // without forbidden properties and values.
+ return [...dummy.style]
+ .filter(name => {
+ return allowedStylesRegex.test(name)
+ && !forbiddenValuesRegexs.some(regex => regex.test(dummy.style[name]));
+ })
+ .reduce((object, name) => {
+ return Object.assign({
+ [name]: dummy.style[name]
+ }, object);
+ }, {});
+}
+
+module.exports = GripMessageBody;