blob: e23f6acc1df3f1d53ccf6d66037e619544fe1ed7 [file] [log] [blame]
// Copyright 2015 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Class to represent a PSML Document.
* @see http://www.nbee.org/doku.php?id=netpdl:psml_specification
*/
'use strict';
/**
* Namespace for the Packet Trace Analyzer app.
*/
var pcap = pcap || {};
/**
* Acts as a container for the PSML Structure and Packets.
*
* @constructor
* @extends {pcap.XmlDocument}
*/
pcap.PsmlDocument = function() {
pcap.XmlDocument.call(this);
/**
* @type {PsmlStructure}
* @private
*/
this.structure_ = null;
/**
* @type {Array<PsmlPacket>}
* @private
*/
this.packets_ = [];
// End of properties. Seal the object.
Object.seal(this);
};
pcap.PsmlDocument.prototype = {
__proto__: pcap.XmlDocument.prototype
};
/**
* Method to load the PsmlDocument from PSML.
*
* @override
* @param {XMLDocument} psmlXmlDoc Summary information of a decoded packet.
* @return {boolean} True if successfully set; false otherwise.
*/
pcap.PsmlDocument.prototype.read = function(psmlXmlDoc) {
console.log('psml-read: Reading PSML Document.');
this.structure_ = null;
this.packets_ = [];
if (!psmlXmlDoc || !(psmlXmlDoc instanceof XMLDocument)) {
console.error('psml-read: Invalid input type.');
return false;
}
var psmlXml = psmlXmlDoc.getElementsByTagName('psml');
if (!psmlXml || !psmlXml[0]) {
console.error('psml-read: Invalid PSML Document - Missing psml tag.');
return false;
}
var structuresXml = psmlXml[0].getElementsByTagName('structure');
if (!structuresXml || !structuresXml[0]) {
console.error('psml-read: Invalid PSML Document - Missing structure tag.');
return false;
}
var packetsXml = psmlXml[0].getElementsByTagName('packet');
if (!packetsXml || !packetsXml[0]) {
console.error('psml-read: Invalid PSML Document - Missing psml packets.');
return false;
}
var structure = new pcap.PsmlStructure();
if (!structure.read(structuresXml[0])) {
console.error('psml-read: Failed to read PSML structure.');
return false;
}
this.structure_ = structure;
for (var i = 0; i < packetsXml.length; i++) {
var packet = new pcap.PsmlPacket();
if (!packet.read(packetsXml[i])) {
console.error('psml-read: Failed to read PSML packets.');
return false;
}
this.packets_.push(packet);
}
console.log('psml-read: Successfully read PSML Document.');
return true;
};
/**
* Generates an HTML representation of the PsmlDocument and inserts
* it into the target element.
*
* @override
* @throws Error if structure or packets are missing or invalid.
*/
pcap.PsmlDocument.prototype.display = function() {
var targetEl = document.getElementById('psml_display');
if (!this.structure_) {
throw new Error('Structure is missing');
}
if (!(this.structure_ instanceof pcap.PsmlStructure)) {
throw new Error('Invalid Structure type');
}
if (!this.packets_ || !this.packets_.length) {
throw new Error('Packets are missing');
}
var root = document.createElement('div');
root.className = 'psml';
var table = document.createElement('table');
table.className = 'table';
table.id = 'structure';
var thead = document.createElement('thead');
thead.appendChild(this.structure_.html());
var tbody = document.createElement('tbody');
var packetCount = this.packets_.length;
for (var i = 0; i < packetCount; i++) {
var packet = this.packets_[i];
if (!(packet instanceof pcap.PsmlPacket)) {
throw new Error('Invalid Packet type');
}
tbody.appendChild(packet.html());
}
table.appendChild(thead);
table.appendChild(tbody);
root.appendChild(table);
targetEl.innerText = '';
targetEl.appendChild(root);
console.log('psml-display: Successfully displayed PSML Document.');
};
/**
* Acts as a container for the PSML Structure Sections.
*
* @constructor
*/
pcap.PsmlStructure = function() {
/**
* @type {Array<string>}
* @private
*/
this.sections_ = [];
};
/**
* Method to load the Structures from the PSML structure tag.
*
* @param {Element} structureXml Structure section from the PSML document.
* @return {boolean} True if succeeded; false otherwise.
*/
pcap.PsmlStructure.prototype.read = function(structureXml) {
if (!structureXml || !(structureXml instanceof Element)) {
return false;
}
var sectionsXml = structureXml.getElementsByTagName('section');
if (!sectionsXml || !sectionsXml[0]) {
return false;
}
for (var i = 0; i < sectionsXml.length; i++) {
var sectionText = sectionsXml[i].textContent;
this.sections_.push(sectionText);
}
return true;
};
/**
* Method to create an HTML representation of the PsmlStructure.
*
* @throws Error if the sections are missing or invalid.
* @return {Element} The root node of the generated HTML.
*/
pcap.PsmlStructure.prototype.html = function() {
if (!this.sections_ || !this.sections_.length) {
throw new Error('Missing sections');
}
var tr = document.createElement('tr');
for (var i = 0; i < this.sections_.length; i++) {
var sectionText = this.sections_[i];
if (typeof sectionText !== 'string') {
throw new Error('Invalid section type');
}
var th = document.createElement('th');
th.innerText = sectionText;
tr.appendChild(th);
}
return tr;
};
/**
* Acts as a container for the PSML Packet Sections.
*
* @constructor
*/
pcap.PsmlPacket = function() {
/**
* @type {Array<string>}
* @private
*/
this.sections_ = [];
};
/**
* Method to load the Packets from the PSML packet tag.
*
* @param {Element} packetXml Packet section from the PSML document.
* @return {boolean} True if succeeded; false otherwise.
*/
pcap.PsmlPacket.prototype.read = function(packetXml) {
if (!packetXml || !(packetXml instanceof Element)) {
return false;
}
var sectionsXml = packetXml.getElementsByTagName('section');
if (!sectionsXml || !sectionsXml[0]) {
return false;
}
for (var i = 0; i < sectionsXml.length; i++) {
var sectionText = sectionsXml[i].textContent;
this.sections_.push(sectionText);
}
return true;
};
/**
* Method to create an HTML representation of the PsmlPacket.
*
* @throws Error if the packets are missing or invalid.
* @return {Element} The root node of the generated HTML.
*/
pcap.PsmlPacket.prototype.html = function() {
if (!this.sections_ || !this.sections_.length) {
throw new Error('Missing sections');
}
var root = document.createElement('tr');
for (var i = 0; i < this.sections_.length; i++) {
var sectionText = this.sections_[i];
if (typeof sectionText !== 'string') {
throw new Error('Invalid section type');
}
var td = document.createElement('td');
td.innerText = sectionText;
root.appendChild(td);
}
return root;
};