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
|
/* 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 nsIConsoleListenerWatcher = require("devtools/server/actors/resources/utils/nsi-console-listener-watcher");
const { Ci } = require("chrome");
const { DevToolsServer } = require("devtools/server/devtools-server");
const { createStringGrip } = require("devtools/server/actors/object/utils");
const {
getActorIdForInternalSourceId,
} = require("devtools/server/actors/utils/dbg-source");
const {
TYPES: { CSS_MESSAGE },
} = require("devtools/server/actors/resources/index");
const { MESSAGE_CATEGORY } = require("devtools/shared/constants");
class CSSMessageWatcher extends nsIConsoleListenerWatcher {
/**
* Start watching for all CSS messages related to a given Target Actor.
* This will notify about existing messages, but also the one created in future.
*
* @param TargetActor targetActor
* The target actor from which we should observe messages
* @param Object options
* Dictionary object with following attributes:
* - onAvailable: mandatory function
* This will be called for each resource.
*/
async watch(targetActor, { onAvailable }) {
super.watch(targetActor, { onAvailable });
// Calling ensureCSSErrorReportingEnabled will make the server parse the stylesheets to
// retrieve the warnings if the docShell wasn't already watching for CSS messages.
if (targetActor.ensureCSSErrorReportingEnabled) {
targetActor.ensureCSSErrorReportingEnabled();
}
}
/**
* Returns true if the message is considered a CSS message, and as a result, should
* be sent to the client.
*
* @param {nsIConsoleMessage|nsIScriptError} message
*/
shouldHandleMessage(targetActor, message) {
// The listener we use can be called either with a nsIConsoleMessage or as nsIScriptError.
// In this file, we want to ignore anything but nsIScriptError.
if (
// We only care about CSS Parser nsIScriptError
!(message instanceof Ci.nsIScriptError) ||
message.category !== MESSAGE_CATEGORY.CSS_PARSER
) {
return false;
}
// Process targets listen for everything but messages from private windows.
if (this.isProcessTarget(targetActor)) {
return !message.isFromPrivateWindow;
}
if (!message.innerWindowID) {
return false;
}
const { window } = targetActor;
const win = window?.WindowGlobalChild?.getByInnerWindowId(
message.innerWindowID
);
return targetActor.browserId === win?.browsingContext?.browserId;
}
/**
* Prepare an nsIScriptError to be sent to the client.
*
* @param nsIScriptError error
* The page error we need to send to the client.
* @return object
* The object you can send to the remote client.
*/
buildResource(targetActor, error) {
const stack = this.prepareStackForRemote(targetActor, error.stack);
let lineText = error.sourceLine;
if (
lineText &&
lineText.length > DevToolsServer.LONG_STRING_INITIAL_LENGTH
) {
lineText = lineText.substr(0, DevToolsServer.LONG_STRING_INITIAL_LENGTH);
}
const notesArray = this.prepareNotesForRemote(targetActor, error.notes);
// If there is no location information in the error but we have a stack,
// fill in the location with the first frame on the stack.
let { sourceName, sourceId, lineNumber, columnNumber } = error;
if (!sourceName && !sourceId && !lineNumber && !columnNumber && stack) {
sourceName = stack[0].filename;
sourceId = stack[0].sourceId;
lineNumber = stack[0].lineNumber;
columnNumber = stack[0].columnNumber;
}
const pageError = {
errorMessage: createStringGrip(targetActor, error.errorMessage),
sourceName,
sourceId: getActorIdForInternalSourceId(targetActor, sourceId),
lineText,
lineNumber,
columnNumber,
category: error.category,
innerWindowID: error.innerWindowID,
timeStamp: error.timeStamp,
warning: !!(error.flags & error.warningFlag),
error: !(error.flags & (error.warningFlag | error.infoFlag)),
info: !!(error.flags & error.infoFlag),
private: error.isFromPrivateWindow,
stacktrace: stack,
notes: notesArray,
chromeContext: error.isFromChromeContext,
isForwardedFromContentProcess: error.isForwardedFromContentProcess,
};
return {
pageError,
resourceType: CSS_MESSAGE,
cssSelectors: error.cssSelectors,
};
}
}
module.exports = CSSMessageWatcher;
|