зеркало из https://github.com/mozilla/gecko-dev.git
1251 строка
33 KiB
JavaScript
1251 строка
33 KiB
JavaScript
/* -*- Mode: js2; js2-basic-offset: 2; indent-tabs-mode: nil; -*- */
|
|
/* vim: set ts=2 et sw=2 tw=80: */
|
|
/* 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";
|
|
|
|
let Cc = Components.classes;
|
|
let Ci = Components.interfaces;
|
|
let Cu = Components.utils;
|
|
|
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|
|
|
XPCOMUtils.defineLazyModuleGetter(this, "Services",
|
|
"resource://gre/modules/Services.jsm");
|
|
|
|
XPCOMUtils.defineLazyModuleGetter(this, "WebConsoleUtils",
|
|
"resource://gre/modules/devtools/WebConsoleUtils.jsm");
|
|
|
|
XPCOMUtils.defineLazyModuleGetter(this, "PageErrorListener",
|
|
"resource://gre/modules/devtools/WebConsoleUtils.jsm");
|
|
|
|
XPCOMUtils.defineLazyModuleGetter(this, "ConsoleAPIListener",
|
|
"resource://gre/modules/devtools/WebConsoleUtils.jsm");
|
|
|
|
XPCOMUtils.defineLazyModuleGetter(this, "ConsoleProgressListener",
|
|
"resource://gre/modules/devtools/WebConsoleUtils.jsm");
|
|
|
|
XPCOMUtils.defineLazyModuleGetter(this, "JSTermHelpers",
|
|
"resource://gre/modules/devtools/WebConsoleUtils.jsm");
|
|
|
|
XPCOMUtils.defineLazyModuleGetter(this, "JSPropertyProvider",
|
|
"resource://gre/modules/devtools/WebConsoleUtils.jsm");
|
|
|
|
XPCOMUtils.defineLazyModuleGetter(this, "NetworkMonitor",
|
|
"resource://gre/modules/devtools/WebConsoleUtils.jsm");
|
|
|
|
XPCOMUtils.defineLazyModuleGetter(this, "ConsoleAPIStorage",
|
|
"resource://gre/modules/ConsoleAPIStorage.jsm");
|
|
|
|
|
|
/**
|
|
* The WebConsoleActor implements capabilities needed for the Web Console
|
|
* feature.
|
|
*
|
|
* @constructor
|
|
* @param object aConnection
|
|
* The connection to the client, DebuggerServerConnection.
|
|
* @param object [aParentActor]
|
|
* Optional, the parent actor.
|
|
*/
|
|
function WebConsoleActor(aConnection, aParentActor)
|
|
{
|
|
this.conn = aConnection;
|
|
|
|
if (aParentActor instanceof BrowserTabActor &&
|
|
aParentActor.browser instanceof Ci.nsIDOMWindow) {
|
|
this._window = aParentActor.browser;
|
|
}
|
|
else if (aParentActor instanceof BrowserTabActor &&
|
|
aParentActor.browser instanceof Ci.nsIDOMElement) {
|
|
this._window = aParentActor.browser.contentWindow;
|
|
}
|
|
else {
|
|
this._window = Services.wm.getMostRecentWindow("navigator:browser");
|
|
this._isGlobalActor = true;
|
|
}
|
|
|
|
this._actorPool = new ActorPool(this.conn);
|
|
this.conn.addActorPool(this._actorPool);
|
|
|
|
this._prefs = {};
|
|
}
|
|
|
|
WebConsoleActor.prototype =
|
|
{
|
|
/**
|
|
* Tells if this Web Console actor is a global actor or not.
|
|
* @private
|
|
* @type boolean
|
|
*/
|
|
_isGlobalActor: false,
|
|
|
|
/**
|
|
* Actor pool for all of the actors we send to the client.
|
|
* @private
|
|
* @type object
|
|
* @see ActorPool
|
|
*/
|
|
_actorPool: null,
|
|
|
|
/**
|
|
* Web Console-related preferences.
|
|
* @private
|
|
* @type object
|
|
*/
|
|
_prefs: null,
|
|
|
|
/**
|
|
* Tells the current inner window associated to the sandbox. When the page
|
|
* is navigated, we recreate the sandbox.
|
|
* @private
|
|
* @type object
|
|
*/
|
|
_sandboxWindowId: 0,
|
|
|
|
/**
|
|
* The JavaScript Sandbox where code is evaluated.
|
|
* @type object
|
|
*/
|
|
sandbox: null,
|
|
|
|
/**
|
|
* The debugger server connection instance.
|
|
* @type object
|
|
*/
|
|
conn: null,
|
|
|
|
/**
|
|
* The content window we work with.
|
|
* @type nsIDOMWindow
|
|
*/
|
|
get window() this._window,
|
|
|
|
_window: null,
|
|
|
|
/**
|
|
* The PageErrorListener instance.
|
|
* @type object
|
|
*/
|
|
pageErrorListener: null,
|
|
|
|
/**
|
|
* The ConsoleAPIListener instance.
|
|
*/
|
|
consoleAPIListener: null,
|
|
|
|
/**
|
|
* The NetworkMonitor instance.
|
|
*/
|
|
networkMonitor: null,
|
|
|
|
/**
|
|
* The ConsoleProgressListener instance.
|
|
*/
|
|
consoleProgressListener: null,
|
|
|
|
/**
|
|
* Getter for the NetworkMonitor.saveRequestAndResponseBodies preference.
|
|
* @type boolean
|
|
*/
|
|
get saveRequestAndResponseBodies()
|
|
this._prefs["NetworkMonitor.saveRequestAndResponseBodies"],
|
|
|
|
actorPrefix: "console",
|
|
|
|
grip: function WCA_grip()
|
|
{
|
|
return { actor: this.actorID };
|
|
},
|
|
|
|
hasNativeConsoleAPI: BrowserTabActor.prototype.hasNativeConsoleAPI,
|
|
|
|
/**
|
|
* Destroy the current WebConsoleActor instance.
|
|
*/
|
|
disconnect: function WCA_disconnect()
|
|
{
|
|
if (this.pageErrorListener) {
|
|
this.pageErrorListener.destroy();
|
|
this.pageErrorListener = null;
|
|
}
|
|
if (this.consoleAPIListener) {
|
|
this.consoleAPIListener.destroy();
|
|
this.consoleAPIListener = null;
|
|
}
|
|
if (this.networkMonitor) {
|
|
this.networkMonitor.destroy();
|
|
this.networkMonitor = null;
|
|
}
|
|
if (this.consoleProgressListener) {
|
|
this.consoleProgressListener.destroy();
|
|
this.consoleProgressListener = null;
|
|
}
|
|
this.conn.removeActorPool(this._actorPool);
|
|
this._actorPool = null;
|
|
this.sandbox = null;
|
|
this._sandboxWindowId = 0;
|
|
this.conn = this._window = null;
|
|
},
|
|
|
|
/**
|
|
* Create a grip for the given value. If the value is an object,
|
|
* a WebConsoleObjectActor will be created.
|
|
*
|
|
* @param mixed aValue
|
|
* @return object
|
|
*/
|
|
createValueGrip: function WCA_createValueGrip(aValue)
|
|
{
|
|
return WebConsoleUtils.createValueGrip(aValue,
|
|
this.createObjectActor.bind(this));
|
|
},
|
|
|
|
/**
|
|
* Create a grip for the given object.
|
|
*
|
|
* @param object aObject
|
|
* The object you want.
|
|
* @param object
|
|
* The object grip.
|
|
*/
|
|
createObjectActor: function WCA_createObjectActor(aObject)
|
|
{
|
|
if (typeof aObject == "string") {
|
|
return this.createStringGrip(aObject);
|
|
}
|
|
|
|
// We need to unwrap the object, otherwise we cannot access the properties
|
|
// and methods added by the content scripts.
|
|
let obj = WebConsoleUtils.unwrap(aObject);
|
|
let actor = new WebConsoleObjectActor(obj, this);
|
|
this._actorPool.addActor(actor);
|
|
return actor.grip();
|
|
},
|
|
|
|
/**
|
|
* Create a grip for the given string. If the given string is a long string,
|
|
* then a LongStringActor grip will be used.
|
|
*
|
|
* @param string aString
|
|
* The string you want to create the grip for.
|
|
* @return string|object
|
|
* The same string, as is, or a LongStringActor object that wraps the
|
|
* given string.
|
|
*/
|
|
createStringGrip: function WCA_createStringGrip(aString)
|
|
{
|
|
if (aString.length >= DebuggerServer.LONG_STRING_LENGTH) {
|
|
let actor = new LongStringActor(aString, this);
|
|
this._actorPool.addActor(actor);
|
|
return actor.grip();
|
|
}
|
|
return aString;
|
|
},
|
|
|
|
/**
|
|
* Get an object actor by its ID.
|
|
*
|
|
* @param string aActorID
|
|
* @return object
|
|
*/
|
|
getActorByID: function WCA_getActorByID(aActorID)
|
|
{
|
|
return this._actorPool.get(aActorID);
|
|
},
|
|
|
|
/**
|
|
* Release an actor.
|
|
*
|
|
* @param object aActor
|
|
* The actor instance you want to release.
|
|
*/
|
|
releaseActor: function WCA_releaseActor(aActor)
|
|
{
|
|
this._actorPool.removeActor(aActor.actorID);
|
|
},
|
|
|
|
//////////////////
|
|
// Request handlers for known packet types.
|
|
//////////////////
|
|
|
|
/**
|
|
* Handler for the "startListeners" request.
|
|
*
|
|
* @param object aRequest
|
|
* The JSON request object received from the Web Console client.
|
|
* @return object
|
|
* The response object which holds the startedListeners array.
|
|
*/
|
|
onStartListeners: function WCA_onStartListeners(aRequest)
|
|
{
|
|
let startedListeners = [];
|
|
let window = !this._isGlobalActor ? this.window : null;
|
|
|
|
while (aRequest.listeners.length > 0) {
|
|
let listener = aRequest.listeners.shift();
|
|
switch (listener) {
|
|
case "PageError":
|
|
if (!this.pageErrorListener) {
|
|
this.pageErrorListener =
|
|
new PageErrorListener(window, this);
|
|
this.pageErrorListener.init();
|
|
}
|
|
startedListeners.push(listener);
|
|
break;
|
|
case "ConsoleAPI":
|
|
if (!this.consoleAPIListener) {
|
|
this.consoleAPIListener =
|
|
new ConsoleAPIListener(window, this);
|
|
this.consoleAPIListener.init();
|
|
}
|
|
startedListeners.push(listener);
|
|
break;
|
|
case "NetworkActivity":
|
|
if (!this.networkMonitor) {
|
|
this.networkMonitor =
|
|
new NetworkMonitor(window, this);
|
|
this.networkMonitor.init();
|
|
}
|
|
startedListeners.push(listener);
|
|
break;
|
|
case "FileActivity":
|
|
if (!this.consoleProgressListener) {
|
|
this.consoleProgressListener =
|
|
new ConsoleProgressListener(this.window, this);
|
|
}
|
|
this.consoleProgressListener.startMonitor(this.consoleProgressListener.
|
|
MONITOR_FILE_ACTIVITY);
|
|
startedListeners.push(listener);
|
|
break;
|
|
}
|
|
}
|
|
return {
|
|
startedListeners: startedListeners,
|
|
nativeConsoleAPI: this.hasNativeConsoleAPI(this.window),
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Handler for the "stopListeners" request.
|
|
*
|
|
* @param object aRequest
|
|
* The JSON request object received from the Web Console client.
|
|
* @return object
|
|
* The response packet to send to the client: holds the
|
|
* stoppedListeners array.
|
|
*/
|
|
onStopListeners: function WCA_onStopListeners(aRequest)
|
|
{
|
|
let stoppedListeners = [];
|
|
|
|
// If no specific listeners are requested to be detached, we stop all
|
|
// listeners.
|
|
let toDetach = aRequest.listeners ||
|
|
["PageError", "ConsoleAPI", "NetworkActivity",
|
|
"FileActivity"];
|
|
|
|
while (toDetach.length > 0) {
|
|
let listener = toDetach.shift();
|
|
switch (listener) {
|
|
case "PageError":
|
|
if (this.pageErrorListener) {
|
|
this.pageErrorListener.destroy();
|
|
this.pageErrorListener = null;
|
|
}
|
|
stoppedListeners.push(listener);
|
|
break;
|
|
case "ConsoleAPI":
|
|
if (this.consoleAPIListener) {
|
|
this.consoleAPIListener.destroy();
|
|
this.consoleAPIListener = null;
|
|
}
|
|
stoppedListeners.push(listener);
|
|
break;
|
|
case "NetworkActivity":
|
|
if (this.networkMonitor) {
|
|
this.networkMonitor.destroy();
|
|
this.networkMonitor = null;
|
|
}
|
|
stoppedListeners.push(listener);
|
|
break;
|
|
case "FileActivity":
|
|
if (this.consoleProgressListener) {
|
|
this.consoleProgressListener.stopMonitor(this.consoleProgressListener.
|
|
MONITOR_FILE_ACTIVITY);
|
|
}
|
|
stoppedListeners.push(listener);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return { stoppedListeners: stoppedListeners };
|
|
},
|
|
|
|
/**
|
|
* Handler for the "getCachedMessages" request. This method sends the cached
|
|
* error messages and the window.console API calls to the client.
|
|
*
|
|
* @param object aRequest
|
|
* The JSON request object received from the Web Console client.
|
|
* @return object
|
|
* The response packet to send to the client: it holds the cached
|
|
* messages array.
|
|
*/
|
|
onGetCachedMessages: function WCA_onGetCachedMessages(aRequest)
|
|
{
|
|
let types = aRequest.messageTypes;
|
|
if (!types) {
|
|
return {
|
|
error: "missingParameter",
|
|
message: "The messageTypes parameter is missing.",
|
|
};
|
|
}
|
|
|
|
let messages = [];
|
|
|
|
while (types.length > 0) {
|
|
let type = types.shift();
|
|
switch (type) {
|
|
case "ConsoleAPI":
|
|
if (this.consoleAPIListener) {
|
|
let cache = this.consoleAPIListener.getCachedMessages();
|
|
cache.forEach(function(aMessage) {
|
|
let message = this.prepareConsoleMessageForRemote(aMessage);
|
|
message._type = type;
|
|
messages.push(message);
|
|
}, this);
|
|
}
|
|
break;
|
|
case "PageError":
|
|
if (this.pageErrorListener) {
|
|
let cache = this.pageErrorListener.getCachedMessages();
|
|
cache.forEach(function(aMessage) {
|
|
let message = this.preparePageErrorForRemote(aMessage);
|
|
message._type = type;
|
|
messages.push(message);
|
|
}, this);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
messages.sort(function(a, b) { return a.timeStamp - b.timeStamp; });
|
|
|
|
return {
|
|
from: this.actorID,
|
|
messages: messages,
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Handler for the "evaluateJS" request. This method evaluates the given
|
|
* JavaScript string and sends back the result.
|
|
*
|
|
* @param object aRequest
|
|
* The JSON request object received from the Web Console client.
|
|
* @return object
|
|
* The evaluation response packet.
|
|
*/
|
|
onEvaluateJS: function WCA_onEvaluateJS(aRequest)
|
|
{
|
|
let input = aRequest.text;
|
|
let result, error = null;
|
|
let timestamp;
|
|
|
|
this.helperResult = null;
|
|
this.evalInput = input;
|
|
try {
|
|
timestamp = Date.now();
|
|
result = this.evalInSandbox(input);
|
|
}
|
|
catch (ex) {
|
|
error = ex;
|
|
}
|
|
|
|
let helperResult = this.helperResult;
|
|
delete this.helperResult;
|
|
delete this.evalInput;
|
|
|
|
return {
|
|
from: this.actorID,
|
|
input: input,
|
|
result: this.createValueGrip(result),
|
|
timestamp: timestamp,
|
|
error: error,
|
|
errorMessage: error ? String(error) : null,
|
|
helperResult: helperResult,
|
|
};
|
|
},
|
|
|
|
/**
|
|
* The Autocomplete request handler.
|
|
*
|
|
* @param object aRequest
|
|
* The request message - what input to autocomplete.
|
|
* @return object
|
|
* The response message - matched properties.
|
|
*/
|
|
onAutocomplete: function WCA_onAutocomplete(aRequest)
|
|
{
|
|
let result = JSPropertyProvider(this.window, aRequest.text) || {};
|
|
return {
|
|
from: this.actorID,
|
|
matches: result.matches || [],
|
|
matchProp: result.matchProp,
|
|
};
|
|
},
|
|
|
|
/**
|
|
* The "clearMessagesCache" request handler.
|
|
*/
|
|
onClearMessagesCache: function WCA_onClearMessagesCache()
|
|
{
|
|
// TODO: Bug 717611 - Web Console clear button does not clear cached errors
|
|
let windowId = !this._isGlobalActor ?
|
|
WebConsoleUtils.getInnerWindowId(this.window) : null;
|
|
ConsoleAPIStorage.clearEvents(windowId);
|
|
return {};
|
|
},
|
|
|
|
/**
|
|
* The "setPreferences" request handler.
|
|
*
|
|
* @param object aRequest
|
|
* The request message - which preferences need to be updated.
|
|
*/
|
|
onSetPreferences: function WCA_onSetPreferences(aRequest)
|
|
{
|
|
for (let key in aRequest.preferences) {
|
|
this._prefs[key] = aRequest.preferences[key];
|
|
}
|
|
return { updated: Object.keys(aRequest.preferences) };
|
|
},
|
|
|
|
//////////////////
|
|
// End of request handlers.
|
|
//////////////////
|
|
|
|
/**
|
|
* Create the JavaScript sandbox where user input is evaluated.
|
|
* @private
|
|
*/
|
|
_createSandbox: function WCA__createSandbox()
|
|
{
|
|
this._sandboxWindowId = WebConsoleUtils.getInnerWindowId(this.window);
|
|
this.sandbox = new Cu.Sandbox(this.window, {
|
|
sandboxPrototype: this.window,
|
|
wantXrays: false,
|
|
});
|
|
|
|
this.sandbox.console = this.window.console;
|
|
|
|
JSTermHelpers(this);
|
|
},
|
|
|
|
/**
|
|
* Evaluates a string in the sandbox.
|
|
*
|
|
* @param string aString
|
|
* String to evaluate in the sandbox.
|
|
* @return mixed
|
|
* The result of the evaluation.
|
|
*/
|
|
evalInSandbox: function WCA_evalInSandbox(aString)
|
|
{
|
|
// If the user changed to a different location, we need to update the
|
|
// sandbox.
|
|
if (this._sandboxWindowId !== WebConsoleUtils.getInnerWindowId(this.window)) {
|
|
this._createSandbox();
|
|
}
|
|
|
|
// The help function needs to be easy to guess, so we make the () optional
|
|
if (aString.trim() == "help" || aString.trim() == "?") {
|
|
aString = "help()";
|
|
}
|
|
|
|
let window = WebConsoleUtils.unwrap(this.sandbox.window);
|
|
let $ = null, $$ = null;
|
|
|
|
// We prefer to execute the page-provided implementations for the $() and
|
|
// $$() functions.
|
|
if (typeof window.$ == "function") {
|
|
$ = this.sandbox.$;
|
|
delete this.sandbox.$;
|
|
}
|
|
if (typeof window.$$ == "function") {
|
|
$$ = this.sandbox.$$;
|
|
delete this.sandbox.$$;
|
|
}
|
|
|
|
let result = Cu.evalInSandbox(aString, this.sandbox, "1.8",
|
|
"Web Console", 1);
|
|
|
|
if ($) {
|
|
this.sandbox.$ = $;
|
|
}
|
|
if ($$) {
|
|
this.sandbox.$$ = $$;
|
|
}
|
|
|
|
return result;
|
|
},
|
|
|
|
//////////////////
|
|
// Event handlers for various listeners.
|
|
//////////////////
|
|
|
|
/**
|
|
* Handler for page errors received from the PageErrorListener. This method
|
|
* sends the nsIScriptError to the remote Web Console client.
|
|
*
|
|
* @param nsIScriptError aPageError
|
|
* The page error we need to send to the client.
|
|
*/
|
|
onPageError: function WCA_onPageError(aPageError)
|
|
{
|
|
let packet = {
|
|
from: this.actorID,
|
|
type: "pageError",
|
|
pageError: this.preparePageErrorForRemote(aPageError),
|
|
};
|
|
this.conn.send(packet);
|
|
},
|
|
|
|
/**
|
|
* Prepare an nsIScriptError to be sent to the client.
|
|
*
|
|
* @param nsIScriptError aPageError
|
|
* The page error we need to send to the client.
|
|
* @return object
|
|
* The object you can send to the remote client.
|
|
*/
|
|
preparePageErrorForRemote: function WCA_preparePageErrorForRemote(aPageError)
|
|
{
|
|
return {
|
|
message: aPageError.message,
|
|
errorMessage: aPageError.errorMessage,
|
|
sourceName: aPageError.sourceName,
|
|
lineText: aPageError.sourceLine,
|
|
lineNumber: aPageError.lineNumber,
|
|
columnNumber: aPageError.columnNumber,
|
|
category: aPageError.category,
|
|
timeStamp: aPageError.timeStamp,
|
|
warning: !!(aPageError.flags & aPageError.warningFlag),
|
|
error: !!(aPageError.flags & aPageError.errorFlag),
|
|
exception: !!(aPageError.flags & aPageError.exceptionFlag),
|
|
strict: !!(aPageError.flags & aPageError.strictFlag),
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Handler for window.console API calls received from the ConsoleAPIListener.
|
|
* This method sends the object to the remote Web Console client.
|
|
*
|
|
* @see ConsoleAPIListener
|
|
* @param object aMessage
|
|
* The console API call we need to send to the remote client.
|
|
*/
|
|
onConsoleAPICall: function WCA_onConsoleAPICall(aMessage)
|
|
{
|
|
let packet = {
|
|
from: this.actorID,
|
|
type: "consoleAPICall",
|
|
message: this.prepareConsoleMessageForRemote(aMessage),
|
|
};
|
|
this.conn.send(packet);
|
|
},
|
|
|
|
/**
|
|
* Handler for network events. This method is invoked when a new network event
|
|
* is about to be recorded.
|
|
*
|
|
* @see NetworkEventActor
|
|
* @see NetworkMonitor from WebConsoleUtils.jsm
|
|
*
|
|
* @param object aEvent
|
|
* The initial network request event information.
|
|
* @return object
|
|
* A new NetworkEventActor is returned. This is used for tracking the
|
|
* network request and response.
|
|
*/
|
|
onNetworkEvent: function WCA_onNetworkEvent(aEvent)
|
|
{
|
|
let actor = new NetworkEventActor(aEvent, this);
|
|
this._actorPool.addActor(actor);
|
|
|
|
let packet = {
|
|
from: this.actorID,
|
|
type: "networkEvent",
|
|
eventActor: actor.grip(),
|
|
};
|
|
|
|
this.conn.send(packet);
|
|
|
|
return actor;
|
|
},
|
|
|
|
/**
|
|
* Handler for file activity. This method sends the file request information
|
|
* to the remote Web Console client.
|
|
*
|
|
* @see ConsoleProgressListener
|
|
* @param string aFileURI
|
|
* The requested file URI.
|
|
*/
|
|
onFileActivity: function WCA_onFileActivity(aFileURI)
|
|
{
|
|
let packet = {
|
|
from: this.actorID,
|
|
type: "fileActivity",
|
|
uri: aFileURI,
|
|
};
|
|
this.conn.send(packet);
|
|
},
|
|
|
|
//////////////////
|
|
// End of event handlers for various listeners.
|
|
//////////////////
|
|
|
|
/**
|
|
* Prepare a message from the console API to be sent to the remote Web Console
|
|
* instance.
|
|
*
|
|
* @param object aMessage
|
|
* The original message received from console-api-log-event.
|
|
* @return object
|
|
* The object that can be sent to the remote client.
|
|
*/
|
|
prepareConsoleMessageForRemote:
|
|
function WCA_prepareConsoleMessageForRemote(aMessage)
|
|
{
|
|
let result = WebConsoleUtils.cloneObject(aMessage);
|
|
delete result.wrappedJSObject;
|
|
|
|
result.arguments = Array.map(aMessage.arguments || [],
|
|
function(aObj) {
|
|
return this.createValueGrip(aObj);
|
|
}, this);
|
|
|
|
if (result.level == "dir") {
|
|
result.objectProperties = [];
|
|
let first = result.arguments[0];
|
|
if (typeof first == "object" && first && first.inspectable) {
|
|
let actor = this.getActorByID(first.actor);
|
|
result.objectProperties = actor.onInspectProperties().properties;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
},
|
|
|
|
/**
|
|
* Find the XUL window that owns the content window.
|
|
*
|
|
* @return Window
|
|
* The XUL window that owns the content window.
|
|
*/
|
|
chromeWindow: function WCA_chromeWindow()
|
|
{
|
|
return this.window.QueryInterface(Ci.nsIInterfaceRequestor)
|
|
.getInterface(Ci.nsIWebNavigation).QueryInterface(Ci.nsIDocShell)
|
|
.chromeEventHandler.ownerDocument.defaultView;
|
|
},
|
|
};
|
|
|
|
WebConsoleActor.prototype.requestTypes =
|
|
{
|
|
startListeners: WebConsoleActor.prototype.onStartListeners,
|
|
stopListeners: WebConsoleActor.prototype.onStopListeners,
|
|
getCachedMessages: WebConsoleActor.prototype.onGetCachedMessages,
|
|
evaluateJS: WebConsoleActor.prototype.onEvaluateJS,
|
|
autocomplete: WebConsoleActor.prototype.onAutocomplete,
|
|
clearMessagesCache: WebConsoleActor.prototype.onClearMessagesCache,
|
|
setPreferences: WebConsoleActor.prototype.onSetPreferences,
|
|
};
|
|
|
|
/**
|
|
* Creates an actor for the specified object.
|
|
*
|
|
* @constructor
|
|
* @param object aObj
|
|
* The object you want.
|
|
* @param object aWebConsoleActor
|
|
* The parent WebConsoleActor instance for this object.
|
|
*/
|
|
function WebConsoleObjectActor(aObj, aWebConsoleActor)
|
|
{
|
|
this.obj = aObj;
|
|
this.parent = aWebConsoleActor;
|
|
}
|
|
|
|
WebConsoleObjectActor.prototype =
|
|
{
|
|
actorPrefix: "consoleObj",
|
|
|
|
/**
|
|
* Returns a grip for this actor for returning in a protocol message.
|
|
*/
|
|
grip: function WCOA_grip()
|
|
{
|
|
let grip = WebConsoleUtils.getObjectGrip(this.obj);
|
|
grip.actor = this.actorID;
|
|
grip.displayString = this.parent.createStringGrip(grip.displayString);
|
|
return grip;
|
|
},
|
|
|
|
/**
|
|
* Releases this actor from the pool.
|
|
*/
|
|
release: function WCOA_release()
|
|
{
|
|
this.parent.releaseActor(this);
|
|
this.parent = this.obj = null;
|
|
},
|
|
|
|
/**
|
|
* Handle a protocol request to inspect the properties of the object.
|
|
*
|
|
* @return object
|
|
* Message to send to the client. This holds the 'properties' property
|
|
* - an array with a descriptor for each property in the object.
|
|
*/
|
|
onInspectProperties: function WCOA_onInspectProperties()
|
|
{
|
|
let createObjectActor = this.parent.createObjectActor.bind(this.parent);
|
|
let props = WebConsoleUtils.inspectObject(this.obj, createObjectActor);
|
|
return {
|
|
from: this.actorID,
|
|
properties: props,
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Handle a protocol request to release a grip.
|
|
*/
|
|
onRelease: function WCOA_onRelease()
|
|
{
|
|
this.release();
|
|
return {};
|
|
},
|
|
};
|
|
|
|
WebConsoleObjectActor.prototype.requestTypes =
|
|
{
|
|
"inspectProperties": WebConsoleObjectActor.prototype.onInspectProperties,
|
|
"release": WebConsoleObjectActor.prototype.onRelease,
|
|
};
|
|
|
|
|
|
/**
|
|
* Creates an actor for a network event.
|
|
*
|
|
* @constructor
|
|
* @param object aNetworkEvent
|
|
* The network event you want to use the actor for.
|
|
* @param object aWebConsoleActor
|
|
* The parent WebConsoleActor instance for this object.
|
|
*/
|
|
function NetworkEventActor(aNetworkEvent, aWebConsoleActor)
|
|
{
|
|
this.parent = aWebConsoleActor;
|
|
this.conn = this.parent.conn;
|
|
|
|
this._startedDateTime = aNetworkEvent.startedDateTime;
|
|
|
|
this._request = {
|
|
method: aNetworkEvent.method,
|
|
url: aNetworkEvent.url,
|
|
httpVersion: aNetworkEvent.httpVersion,
|
|
headers: [],
|
|
cookies: [],
|
|
headersSize: aNetworkEvent.headersSize,
|
|
postData: {},
|
|
};
|
|
|
|
this._response = {
|
|
headers: [],
|
|
cookies: [],
|
|
content: {},
|
|
};
|
|
|
|
this._timings = {};
|
|
this._longStringActors = new Set();
|
|
|
|
this._discardRequestBody = aNetworkEvent.discardRequestBody;
|
|
this._discardResponseBody = aNetworkEvent.discardResponseBody;
|
|
}
|
|
|
|
NetworkEventActor.prototype =
|
|
{
|
|
_request: null,
|
|
_response: null,
|
|
_timings: null,
|
|
_longStringActors: null,
|
|
|
|
actorPrefix: "netEvent",
|
|
|
|
/**
|
|
* Returns a grip for this actor for returning in a protocol message.
|
|
*/
|
|
grip: function NEA_grip()
|
|
{
|
|
return {
|
|
actor: this.actorID,
|
|
startedDateTime: this._startedDateTime,
|
|
url: this._request.url,
|
|
method: this._request.method,
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Releases this actor from the pool.
|
|
*/
|
|
release: function NEA_release()
|
|
{
|
|
for (let grip of this._longStringActors) {
|
|
let actor = this.parent.getActorByID(grip.actor);
|
|
if (actor) {
|
|
this.parent.releaseActor(actor);
|
|
}
|
|
}
|
|
this._longStringActors = new Set();
|
|
this.parent.releaseActor(this);
|
|
},
|
|
|
|
/**
|
|
* Handle a protocol request to release a grip.
|
|
*/
|
|
onRelease: function NEA_onRelease()
|
|
{
|
|
this.release();
|
|
return {};
|
|
},
|
|
|
|
/**
|
|
* The "getRequestHeaders" packet type handler.
|
|
*
|
|
* @return object
|
|
* The response packet - network request headers.
|
|
*/
|
|
onGetRequestHeaders: function NEA_onGetRequestHeaders()
|
|
{
|
|
return {
|
|
from: this.actorID,
|
|
headers: this._request.headers,
|
|
headersSize: this._request.headersSize,
|
|
};
|
|
},
|
|
|
|
/**
|
|
* The "getRequestCookies" packet type handler.
|
|
*
|
|
* @return object
|
|
* The response packet - network request cookies.
|
|
*/
|
|
onGetRequestCookies: function NEA_onGetRequestCookies()
|
|
{
|
|
return {
|
|
from: this.actorID,
|
|
cookies: this._request.cookies,
|
|
};
|
|
},
|
|
|
|
/**
|
|
* The "getRequestPostData" packet type handler.
|
|
*
|
|
* @return object
|
|
* The response packet - network POST data.
|
|
*/
|
|
onGetRequestPostData: function NEA_onGetRequestPostData()
|
|
{
|
|
return {
|
|
from: this.actorID,
|
|
postData: this._request.postData,
|
|
postDataDiscarded: this._discardRequestBody,
|
|
};
|
|
},
|
|
|
|
/**
|
|
* The "getResponseHeaders" packet type handler.
|
|
*
|
|
* @return object
|
|
* The response packet - network response headers.
|
|
*/
|
|
onGetResponseHeaders: function NEA_onGetResponseHeaders()
|
|
{
|
|
return {
|
|
from: this.actorID,
|
|
headers: this._response.headers,
|
|
headersSize: this._response.headersSize,
|
|
};
|
|
},
|
|
|
|
/**
|
|
* The "getResponseCookies" packet type handler.
|
|
*
|
|
* @return object
|
|
* The response packet - network response cookies.
|
|
*/
|
|
onGetResponseCookies: function NEA_onGetResponseCookies()
|
|
{
|
|
return {
|
|
from: this.actorID,
|
|
cookies: this._response.cookies,
|
|
};
|
|
},
|
|
|
|
/**
|
|
* The "getResponseContent" packet type handler.
|
|
*
|
|
* @return object
|
|
* The response packet - network response content.
|
|
*/
|
|
onGetResponseContent: function NEA_onGetResponseContent()
|
|
{
|
|
return {
|
|
from: this.actorID,
|
|
content: this._response.content,
|
|
contentDiscarded: this._discardResponseBody,
|
|
};
|
|
},
|
|
|
|
/**
|
|
* The "getEventTimings" packet type handler.
|
|
*
|
|
* @return object
|
|
* The response packet - network event timings.
|
|
*/
|
|
onGetEventTimings: function NEA_onGetEventTimings()
|
|
{
|
|
return {
|
|
from: this.actorID,
|
|
timings: this._timings,
|
|
totalTime: this._totalTime,
|
|
};
|
|
},
|
|
|
|
/******************************************************************
|
|
* Listeners for new network event data coming from NetworkMonitor.
|
|
******************************************************************/
|
|
|
|
/**
|
|
* Add network request headers.
|
|
*
|
|
* @param array aHeaders
|
|
* The request headers array.
|
|
*/
|
|
addRequestHeaders: function NEA_addRequestHeaders(aHeaders)
|
|
{
|
|
this._request.headers = aHeaders;
|
|
this._prepareHeaders(aHeaders);
|
|
|
|
let packet = {
|
|
from: this.actorID,
|
|
type: "networkEventUpdate",
|
|
updateType: "requestHeaders",
|
|
headers: aHeaders.length,
|
|
headersSize: this._request.headersSize,
|
|
};
|
|
|
|
this.conn.send(packet);
|
|
},
|
|
|
|
/**
|
|
* Add network request cookies.
|
|
*
|
|
* @param array aCookies
|
|
* The request cookies array.
|
|
*/
|
|
addRequestCookies: function NEA_addRequestCookies(aCookies)
|
|
{
|
|
this._request.cookies = aCookies;
|
|
this._prepareHeaders(aCookies);
|
|
|
|
let packet = {
|
|
from: this.actorID,
|
|
type: "networkEventUpdate",
|
|
updateType: "requestCookies",
|
|
cookies: aCookies.length,
|
|
};
|
|
|
|
this.conn.send(packet);
|
|
},
|
|
|
|
/**
|
|
* Add network request POST data.
|
|
*
|
|
* @param object aPostData
|
|
* The request POST data.
|
|
*/
|
|
addRequestPostData: function NEA_addRequestPostData(aPostData)
|
|
{
|
|
this._request.postData = aPostData;
|
|
aPostData.text = this.parent.createStringGrip(aPostData.text);
|
|
if (typeof aPostData.text == "object") {
|
|
this._longStringActors.add(aPostData.text);
|
|
}
|
|
|
|
let packet = {
|
|
from: this.actorID,
|
|
type: "networkEventUpdate",
|
|
updateType: "requestPostData",
|
|
dataSize: aPostData.text.length,
|
|
discardRequestBody: this._discardRequestBody,
|
|
};
|
|
|
|
this.conn.send(packet);
|
|
},
|
|
|
|
/**
|
|
* Add the initial network response information.
|
|
*
|
|
* @param object aInfo
|
|
* The response information.
|
|
*/
|
|
addResponseStart: function NEA_addResponseStart(aInfo)
|
|
{
|
|
this._response.httpVersion = aInfo.httpVersion;
|
|
this._response.status = aInfo.status;
|
|
this._response.statusText = aInfo.statusText;
|
|
this._response.headersSize = aInfo.headersSize;
|
|
this._discardResponseBody = aInfo.discardResponseBody;
|
|
|
|
let packet = {
|
|
from: this.actorID,
|
|
type: "networkEventUpdate",
|
|
updateType: "responseStart",
|
|
response: aInfo,
|
|
};
|
|
|
|
this.conn.send(packet);
|
|
},
|
|
|
|
/**
|
|
* Add network response headers.
|
|
*
|
|
* @param array aHeaders
|
|
* The response headers array.
|
|
*/
|
|
addResponseHeaders: function NEA_addResponseHeaders(aHeaders)
|
|
{
|
|
this._response.headers = aHeaders;
|
|
this._prepareHeaders(aHeaders);
|
|
|
|
let packet = {
|
|
from: this.actorID,
|
|
type: "networkEventUpdate",
|
|
updateType: "responseHeaders",
|
|
headers: aHeaders.length,
|
|
headersSize: this._response.headersSize,
|
|
};
|
|
|
|
this.conn.send(packet);
|
|
},
|
|
|
|
/**
|
|
* Add network response cookies.
|
|
*
|
|
* @param array aCookies
|
|
* The response cookies array.
|
|
*/
|
|
addResponseCookies: function NEA_addResponseCookies(aCookies)
|
|
{
|
|
this._response.cookies = aCookies;
|
|
this._prepareHeaders(aCookies);
|
|
|
|
let packet = {
|
|
from: this.actorID,
|
|
type: "networkEventUpdate",
|
|
updateType: "responseCookies",
|
|
cookies: aCookies.length,
|
|
};
|
|
|
|
this.conn.send(packet);
|
|
},
|
|
|
|
/**
|
|
* Add network response content.
|
|
*
|
|
* @param object aContent
|
|
* The response content.
|
|
* @param boolean aDiscardedResponseBody
|
|
* Tells if the response content was recorded or not.
|
|
*/
|
|
addResponseContent:
|
|
function NEA_addResponseContent(aContent, aDiscardedResponseBody)
|
|
{
|
|
this._response.content = aContent;
|
|
aContent.text = this.parent.createStringGrip(aContent.text);
|
|
if (typeof aContent.text == "object") {
|
|
this._longStringActors.add(aContent.text);
|
|
}
|
|
|
|
let packet = {
|
|
from: this.actorID,
|
|
type: "networkEventUpdate",
|
|
updateType: "responseContent",
|
|
mimeType: aContent.mimeType,
|
|
contentSize: aContent.text.length,
|
|
discardResponseBody: aDiscardedResponseBody,
|
|
};
|
|
|
|
this.conn.send(packet);
|
|
},
|
|
|
|
/**
|
|
* Add network event timing information.
|
|
*
|
|
* @param number aTotal
|
|
* The total time of the network event.
|
|
* @param object aTimings
|
|
* Timing details about the network event.
|
|
*/
|
|
addEventTimings: function NEA_addEventTimings(aTotal, aTimings)
|
|
{
|
|
this._totalTime = aTotal;
|
|
this._timings = aTimings;
|
|
|
|
let packet = {
|
|
from: this.actorID,
|
|
type: "networkEventUpdate",
|
|
updateType: "eventTimings",
|
|
totalTime: aTotal,
|
|
};
|
|
|
|
this.conn.send(packet);
|
|
},
|
|
|
|
/**
|
|
* Prepare the headers array to be sent to the client by using the
|
|
* LongStringActor for the header values, when needed.
|
|
*
|
|
* @private
|
|
* @param array aHeaders
|
|
*/
|
|
_prepareHeaders: function NEA__prepareHeaders(aHeaders)
|
|
{
|
|
for (let header of aHeaders) {
|
|
header.value = this.parent.createStringGrip(header.value);
|
|
if (typeof header.value == "object") {
|
|
this._longStringActors.add(header.value);
|
|
}
|
|
}
|
|
},
|
|
};
|
|
|
|
NetworkEventActor.prototype.requestTypes =
|
|
{
|
|
"release": NetworkEventActor.prototype.onRelease,
|
|
"getRequestHeaders": NetworkEventActor.prototype.onGetRequestHeaders,
|
|
"getRequestCookies": NetworkEventActor.prototype.onGetRequestCookies,
|
|
"getRequestPostData": NetworkEventActor.prototype.onGetRequestPostData,
|
|
"getResponseHeaders": NetworkEventActor.prototype.onGetResponseHeaders,
|
|
"getResponseCookies": NetworkEventActor.prototype.onGetResponseCookies,
|
|
"getResponseContent": NetworkEventActor.prototype.onGetResponseContent,
|
|
"getEventTimings": NetworkEventActor.prototype.onGetEventTimings,
|
|
};
|
|
|