зеркало из https://github.com/mozilla/gecko-dev.git
282 строки
7.9 KiB
JavaScript
282 строки
7.9 KiB
JavaScript
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
|
/* vim: set ft=javascript 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";
|
|
|
|
const {Utils: WebConsoleUtils} = require("devtools/client/webconsole/utils");
|
|
const EventEmitter = require("devtools/shared/event-emitter");
|
|
const promise = require("promise");
|
|
const defer = require("devtools/shared/defer");
|
|
const Services = require("Services");
|
|
const { gDevTools } = require("devtools/client/framework/devtools");
|
|
const { JSTerm } = require("devtools/client/webconsole/jsterm");
|
|
const { WebConsoleConnectionProxy } = require("devtools/client/webconsole/webconsole-connection-proxy");
|
|
|
|
const PREF_MESSAGE_TIMESTAMP = "devtools.webconsole.timestampMessages";
|
|
|
|
// XXX: This file is incomplete (see bug 1326937).
|
|
// It's used when loading the webconsole with devtools-launchpad, but will ultimately be
|
|
// the entry point for the new frontend
|
|
|
|
/**
|
|
* A WebConsoleFrame instance is an interactive console initialized *per target*
|
|
* that displays console log data as well as provides an interactive terminal to
|
|
* manipulate the target's document content.
|
|
*
|
|
* The WebConsoleFrame is responsible for the actual Web Console UI
|
|
* implementation.
|
|
*
|
|
* @constructor
|
|
* @param object webConsoleOwner
|
|
* The WebConsole owner object.
|
|
*/
|
|
function NewWebConsoleFrame(webConsoleOwner) {
|
|
this.owner = webConsoleOwner;
|
|
this.hudId = this.owner.hudId;
|
|
this.isBrowserConsole = this.owner._browserConsole;
|
|
this.NEW_CONSOLE_OUTPUT_ENABLED = true;
|
|
this.window = this.owner.iframeWindow;
|
|
|
|
this._onToolboxPrefChanged = this._onToolboxPrefChanged.bind(this);
|
|
|
|
EventEmitter.decorate(this);
|
|
}
|
|
NewWebConsoleFrame.prototype = {
|
|
/**
|
|
* Getter for the debugger WebConsoleClient.
|
|
* @type object
|
|
*/
|
|
get webConsoleClient() {
|
|
return this.proxy ? this.proxy.webConsoleClient : null;
|
|
},
|
|
|
|
/**
|
|
* Initialize the WebConsoleFrame instance.
|
|
* @return object
|
|
* A promise object that resolves once the frame is ready to use.
|
|
*/
|
|
init() {
|
|
this._initUI();
|
|
let connectionInited = this._initConnection();
|
|
|
|
// Don't reject if the history fails to load for some reason.
|
|
// This would be fine, the panel will just start with empty history.
|
|
let allReady = this.jsterm.historyLoaded.catch(() => {}).then(() => {
|
|
return connectionInited;
|
|
});
|
|
|
|
// This notification is only used in tests. Don't chain it onto
|
|
// the returned promise because the console panel needs to be attached
|
|
// to the toolbox before the web-console-created event is receieved.
|
|
let notifyObservers = () => {
|
|
let id = WebConsoleUtils.supportsString(this.hudId);
|
|
if (Services.obs) {
|
|
Services.obs.notifyObservers(id, "web-console-created");
|
|
}
|
|
};
|
|
allReady.then(notifyObservers, notifyObservers)
|
|
.then(this.newConsoleOutput.init);
|
|
|
|
return allReady;
|
|
},
|
|
|
|
destroy() {
|
|
if (this._destroyer) {
|
|
return this._destroyer.promise;
|
|
}
|
|
|
|
this._destroyer = defer();
|
|
|
|
Services.prefs.addObserver(PREF_MESSAGE_TIMESTAMP, this._onToolboxPrefChanged);
|
|
this.React = this.ReactDOM = this.FrameView = null;
|
|
|
|
let onDestroy = () => {
|
|
this._destroyer.resolve(null);
|
|
};
|
|
if (this.proxy) {
|
|
this.proxy.disconnect().then(onDestroy);
|
|
this.proxy = null;
|
|
} else {
|
|
onDestroy();
|
|
}
|
|
|
|
return this._destroyer.promise;
|
|
},
|
|
|
|
_onUpdateListeners() {
|
|
|
|
},
|
|
|
|
logWarningAboutReplacedAPI() {
|
|
|
|
},
|
|
|
|
handleNetworkEventUpdate() {
|
|
|
|
},
|
|
|
|
/**
|
|
* Setter for saving of network request and response bodies.
|
|
*
|
|
* @param boolean value
|
|
* The new value you want to set.
|
|
*/
|
|
setSaveRequestAndResponseBodies(value) {
|
|
if (!this.webConsoleClient) {
|
|
// Don't continue if the webconsole disconnected.
|
|
return promise.resolve(null);
|
|
}
|
|
|
|
let deferred = defer();
|
|
let newValue = !!value;
|
|
let toSet = {
|
|
"NetworkMonitor.saveRequestAndResponseBodies": newValue,
|
|
};
|
|
|
|
// Make sure the web console client connection is established first.
|
|
this.webConsoleClient.setPreferences(toSet, response => {
|
|
if (!response.error) {
|
|
this._saveRequestAndResponseBodies = newValue;
|
|
deferred.resolve(response);
|
|
} else {
|
|
deferred.reject(response.error);
|
|
}
|
|
});
|
|
|
|
return deferred.promise;
|
|
},
|
|
|
|
/**
|
|
* Connect to the server using the remote debugging protocol.
|
|
*
|
|
* @private
|
|
* @return object
|
|
* A promise object that is resolved/reject based on the connection
|
|
* result.
|
|
*/
|
|
_initConnection: function () {
|
|
if (this._initDefer) {
|
|
return this._initDefer.promise;
|
|
}
|
|
|
|
this._initDefer = defer();
|
|
this.proxy = new WebConsoleConnectionProxy(this, this.owner.target);
|
|
|
|
this.proxy.connect().then(() => {
|
|
// on success
|
|
this._initDefer.resolve(this);
|
|
}, (reason) => {
|
|
// on failure
|
|
// TODO Print a message to console
|
|
this._initDefer.reject(reason);
|
|
});
|
|
|
|
return this._initDefer.promise;
|
|
},
|
|
|
|
_initUI: function () {
|
|
this.document = this.window.document;
|
|
this.rootElement = this.document.documentElement;
|
|
|
|
this.outputNode = this.document.getElementById("output-container");
|
|
this.completeNode = this.document.querySelector(".jsterm-complete-node");
|
|
this.inputNode = this.document.querySelector(".jsterm-input-node");
|
|
|
|
this.jsterm = new JSTerm(this);
|
|
this.jsterm.init();
|
|
|
|
let toolbox = gDevTools.getToolbox(this.owner.target);
|
|
|
|
// @TODO Remove this once JSTerm is handled with React/Redux.
|
|
this.window.jsterm = this.jsterm;
|
|
// @TODO Once the toolbox has been converted to React, see if passing
|
|
// in JSTerm is still necessary.
|
|
|
|
// Handle both launchpad and toolbox loading
|
|
let Wrapper = this.owner.NewConsoleOutputWrapper || this.window.NewConsoleOutput;
|
|
this.newConsoleOutput = new Wrapper(
|
|
this.outputNode, this.jsterm, toolbox, this.owner, this.document);
|
|
|
|
// Toggle the timestamp on preference change
|
|
Services.prefs.addObserver(PREF_MESSAGE_TIMESTAMP, this._onToolboxPrefChanged);
|
|
this._onToolboxPrefChanged();
|
|
},
|
|
|
|
/**
|
|
* Handler for page location changes.
|
|
*
|
|
* @param string uri
|
|
* New page location.
|
|
* @param string title
|
|
* New page title.
|
|
*/
|
|
onLocationChange: function (uri, title) {
|
|
this.contentLocation = uri;
|
|
if (this.owner.onLocationChange) {
|
|
this.owner.onLocationChange(uri, title);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Release an actor.
|
|
*
|
|
* @private
|
|
* @param string actor
|
|
* The actor ID you want to release.
|
|
*/
|
|
_releaseObject: function (actor) {
|
|
if (this.proxy) {
|
|
this.proxy.releaseActor(actor);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Called when the message timestamp pref changes.
|
|
*/
|
|
_onToolboxPrefChanged: function () {
|
|
let newValue = Services.prefs.getBoolPref(PREF_MESSAGE_TIMESTAMP);
|
|
this.newConsoleOutput.dispatchTimestampsToggle(newValue);
|
|
},
|
|
|
|
/**
|
|
* Handler for the tabNavigated notification.
|
|
*
|
|
* @param string event
|
|
* Event name.
|
|
* @param object packet
|
|
* Notification packet received from the server.
|
|
*/
|
|
handleTabNavigated: function (event, packet) {
|
|
if (event == "will-navigate") {
|
|
if (this.persistLog) {
|
|
// Add a _type to hit convertCachedPacket.
|
|
packet._type = true;
|
|
this.newConsoleOutput.dispatchMessageAdd(packet);
|
|
} else {
|
|
this.clearOutput(false);
|
|
}
|
|
}
|
|
|
|
if (packet.url) {
|
|
this.onLocationChange(packet.url, packet.title);
|
|
}
|
|
|
|
if (event == "navigate" && !packet.nativeConsoleAPI) {
|
|
this.logWarningAboutReplacedAPI();
|
|
}
|
|
},
|
|
|
|
clearOutput(clearStorage) {
|
|
this.newConsoleOutput.dispatchMessagesClear();
|
|
this.webConsoleClient.clearNetworkRequests();
|
|
if (clearStorage) {
|
|
this.webConsoleClient.clearMessagesCache();
|
|
}
|
|
},
|
|
};
|
|
|
|
exports.NewWebConsoleFrame = NewWebConsoleFrame;
|