blob: b129933ab7ab62d1b5caa2399784c3bd45003beb [file] [log] [blame]
<!--
The res/js/fuzzer.js file must be included before this file.
This in an HTML Import-able file that contains the definition
of the following elements:
<fuzzer-info-sk>
This element will query /json/details for all of the detailed fuzz reports of a given file (passed in by query params) and displayed.
This may be further scoped by function, line number and fuzz-type (either binary or api)
To use this file import it:
<link href="/res/imp/fuzzer-info-sk.html" rel="import" />
Usage:
<fuzzer-info-sk></fuzzer-info-sk>
Properties:
category: String.
exclude: Array of String, all fuzzes that have one or more of these strings as a flag will not
be shown. This array must be sorted lexographically.
include: Array of String, all fuzzes must have one or more of these strings as a flag to be
shown. This array must be sorted lexographically.
Methods:
None.
Events:
None.
-->
<link rel="import" href="/res/imp/bower_components/iron-ajax/iron-ajax.html">
<link rel="import" href="/res/imp/bower_components/paper-input/paper-input.html">
<link rel="import" href="/res/common/imp/url-params-sk.html">
<link rel="import" href="fuzzer-collapse-file-sk.html">
<link rel="import" href="fuzzer-filter-sk.html">
<dom-module id="fuzzer-info-sk">
<template>
<iron-ajax auto url="/json/details"
handle-as="json"
params="[[_urlParams]]"
last-response="{{_fuzzDetails}}">
</iron-ajax>
<template is="dom-repeat" items="[[_filteredFileDetails]]" as="file" sort="_byCount" filter="_excludeEmpty">
<fuzzer-collapse-file-sk file="{{file}}"
category="[[category]]"
expand="[[_shouldExpand()]]">
</fuzzer-collapse-file-sk>
</template>
<template is="dom-if" if="[[_isEmpty]]">
<div>No results found (or server is still loading). Try refreshing this page later or adjusting your filters.</div>
</template>
</template>
<script>
Polymer({
is: 'fuzzer-info-sk',
properties: {
architecture: {
type: String,
value: function() {
return [];
}
},
category: {
type: String,
value: "",
},
include: {
type: Array,
value: function() {
return [];
}
},
exclude: {
type: Array,
value: function() {
return [];
}
},
_fuzzDetails: {
type: Array,
value: function() {
return [];
},
},
_filteredFileDetails: {
type: Array,
computed: "_filter(_fuzzDetails, architecture.*, include.*, exclude.*)",
},
_isEmpty: {
type: Boolean,
computed: "_empty(_filteredFileDetails)",
},
_urlParams: {
type: String,
computed: "_getURLParams(category)",
},
},
_byCount: function(a, b) {
// Higher counts come first
return b.count - a.count;
},
_excludeEmpty: function(a) {
return a.count;
},
_empty: function(a) {
return !a || !a.length;
},
_filter: function(fuzzDetails){
if (this._empty(fuzzDetails)) {
return [];
}
var exclude = this.exclude || [];
var include = this.include || [];
var architecture = this.architecture || [];
var fileDetails = this._group(fuzzDetails);
// make a fresh copy of the data. This way, we can just completely replace the array
// without having to do Polymer's special array manipulation.
var retVal = JSON.parse(JSON.stringify(fileDetails));
retVal.forEach(function(file){
var fileCount = 0;
file.byFunction.forEach(function(func) {
var funcCount = 0;
func.byLineNumber.forEach(function(line) {
line.reports = line.reports.filter(function(report) {
if (architecture.length > 0 && architecture.indexOf(report.architecture) === -1) {
return false;
}
for (let flags of Object.values(report.flags)) {
if (sk.sharesElement(exclude, flags)) {
return false;
}
}
if (include.length === 0) {
return true;
}
let sharedSomething = false;
for (let flags of Object.values(report.flags)) {
if (sk.sharesElement(include, flags)) {
sharedSomething = true;
}
}
return sharedSomething;
});
line.count = line.reports.length;
funcCount += line.count;
});
func.count = funcCount;
fileCount += funcCount
});
file.count = fileCount;
});
return retVal;
},
_getURLParams: function(category) {
return {
"category": category,
"file": fuzzer.paramFromPath("file"),
"func": fuzzer.paramFromPath("func"),
"line": fuzzer.paramFromPath("line"),
"name": fuzzer.paramFromPath("name"),
// TODO(kjlubick) Maybe make this user changeable
"badOrGrey": "bad",
};
},
_group: function(fuzzes) {
var files = {};
// files is a flat array of fuzzes. We want to turn it into an array
// of objects like:
// {
// fileName: String,
// count: Integer,
// byFunction: Array<{
// functionName: String,
// count: Integer,
// byLineNumber: Array<{
// lineNumber: Integer,
// count: Integer,
// reports: Array<Fuzz>
// }>
// }>
// }
// where Fuzz is the original object given to us by the server. See
// fuzzer-collapse-details-sk for the Fuzz schema.
// First we group up the fuzzes by file, func, and line number
fuzzes.forEach(function(f){
var file = f.fileName || "UNKNOWN";
var func = f.functionName || "UNKNOWN";
var line = f.lineNumber || -1;
if (!files[file]) {
files[file] = {};
}
if (!files[file][func]) {
files[file][func] = {};
}
if (!files[file][func][line]) {
files[file][func][line] = [];
}
files[file][func][line].push(f)
});
// Take the object and put it into arrays, so Polymer can use dom-repeats.
var fileData = [];
for (var file in files) {
var funcs = files[file];
var byFunction = [];
for (var func in funcs) {
var lines = funcs[func];
var byLineNumber = [];
for (line in lines) {
byLineNumber.push({
count: 0,
lineNumber: line,
reports: lines[line],
});
}
byFunction.push({
count: 0,
functionName: func,
byLineNumber: byLineNumber,
});
}
fileData.push({
count: 0,
fileName: file,
byFunction: byFunction,
})
}
return fileData;
},
_shouldExpand: function(){
return fuzzer.paramFromPath("file").length > 0 || fuzzer.paramFromPath("name").length > 0;
},
});
</script>
</dom-module>