summaryrefslogtreecommitdiffstats
path: root/devtools/client/netmonitor/src/selectors/messages.js
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--devtools/client/netmonitor/src/selectors/messages.js162
1 files changed, 162 insertions, 0 deletions
diff --git a/devtools/client/netmonitor/src/selectors/messages.js b/devtools/client/netmonitor/src/selectors/messages.js
new file mode 100644
index 0000000000..d12b465b94
--- /dev/null
+++ b/devtools/client/netmonitor/src/selectors/messages.js
@@ -0,0 +1,162 @@
+/* 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 {
+ createSelector,
+} = require("resource://devtools/client/shared/vendor/reselect.js");
+
+/**
+ * Returns list of messages that are visible to the user.
+ * Filtered messages by types and text are factored in.
+ */
+const getDisplayedMessages = createSelector(
+ state => state.messages,
+ ({
+ messages,
+ messageFilterType,
+ showControlFrames,
+ messageFilterText,
+ currentChannelId,
+ }) => {
+ if (!currentChannelId || !messages.get(currentChannelId)) {
+ return [];
+ }
+
+ const messagesArray = messages.get(currentChannelId);
+ if (messageFilterType === "all" && messageFilterText.length === 0) {
+ return messagesArray.filter(message =>
+ typeFilter(message, messageFilterType, showControlFrames)
+ );
+ }
+
+ const filter = searchFilter(messageFilterText);
+
+ // If message payload is > 10,000 characters long, we check the LongStringActor payload string
+ return messagesArray.filter(
+ message =>
+ (message.payload.initial
+ ? filter(message.payload.initial)
+ : filter(message.payload)) &&
+ typeFilter(message, messageFilterType, showControlFrames)
+ );
+ }
+);
+
+function typeFilter(message, messageFilterType, showControlFrames) {
+ const controlFrames = [0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf];
+ const isControlFrame = controlFrames.includes(message.opCode);
+ if (messageFilterType === "all" || messageFilterType === message.type) {
+ return showControlFrames || !isControlFrame;
+ }
+ return false;
+}
+
+function searchFilter(messageFilterText) {
+ let regex;
+ if (looksLikeRegex(messageFilterText)) {
+ try {
+ regex = regexFromText(messageFilterText);
+ } catch (e) {}
+ }
+
+ return regex
+ ? payload => regex.test(payload)
+ : payload => payload.includes(messageFilterText);
+}
+
+function looksLikeRegex(text) {
+ return text.startsWith("/") && text.endsWith("/") && text.length > 2;
+}
+
+function regexFromText(text) {
+ return new RegExp(text.slice(1, -1), "im");
+}
+
+/**
+ * Checks if the selected message is visible.
+ * If the selected message is not visible, the SplitBox component
+ * should not show the MessagePayload component.
+ */
+const isSelectedMessageVisible = createSelector(
+ state => state.messages,
+ getDisplayedMessages,
+ ({ selectedMessage }, displayedMessages) =>
+ displayedMessages.some(message => message === selectedMessage)
+);
+
+/**
+ * Returns the current selected message.
+ */
+const getSelectedMessage = createSelector(
+ state => state.messages,
+ ({ selectedMessage }) => (selectedMessage ? selectedMessage : undefined)
+);
+
+/**
+ * Returns summary data of the list of messages that are visible to the user.
+ * Filtered messages by types and text are factored in.
+ */
+const getDisplayedMessagesSummary = createSelector(
+ getDisplayedMessages,
+ displayedMessages => {
+ let firstStartedMs = +Infinity;
+ let lastEndedMs = -Infinity;
+ let sentSize = 0;
+ let receivedSize = 0;
+ let totalSize = 0;
+
+ displayedMessages.forEach(message => {
+ if (message.type == "received") {
+ receivedSize += message.payload.length;
+ } else if (message.type == "sent") {
+ sentSize += message.payload.length;
+ }
+ totalSize += message.payload.length;
+ if (message.timeStamp < firstStartedMs) {
+ firstStartedMs = message.timeStamp;
+ }
+ if (message.timeStamp > lastEndedMs) {
+ lastEndedMs = message.timeStamp;
+ }
+ });
+
+ return {
+ count: displayedMessages.length,
+ totalMs: (lastEndedMs - firstStartedMs) / 1000,
+ sentSize,
+ receivedSize,
+ totalSize,
+ };
+ }
+);
+
+/**
+ * Returns if the currentChannelId is closed
+ */
+const isCurrentChannelClosed = createSelector(
+ state => state.messages,
+ ({ closedConnections, currentChannelId }) =>
+ closedConnections.has(currentChannelId)
+);
+
+/**
+ * Returns the closed connection details of the currentChannelId
+ * Null, if the connection is still open
+ */
+const getClosedConnectionDetails = createSelector(
+ state => state.messages,
+ ({ closedConnections, currentChannelId }) =>
+ closedConnections.get(currentChannelId)
+);
+
+module.exports = {
+ getSelectedMessage,
+ isSelectedMessageVisible,
+ getDisplayedMessages,
+ getDisplayedMessagesSummary,
+ isCurrentChannelClosed,
+ getClosedConnectionDetails,
+};