186 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			HTML
		
	
	
	
			
		
		
	
	
			186 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			HTML
		
	
	
	
<!DOCTYPE html>
 | 
						|
<html>
 | 
						|
  <head>
 | 
						|
    <meta charset="utf-8" />
 | 
						|
    <title>Website Fingerprinting Lab</title>
 | 
						|
    <style>
 | 
						|
      * {
 | 
						|
        margin: 0;
 | 
						|
        padding: 0;
 | 
						|
      }
 | 
						|
 | 
						|
      body {
 | 
						|
        font-family: Arial, Helvetica, sans-serif;
 | 
						|
        padding: 64px;
 | 
						|
      }
 | 
						|
 | 
						|
      h1 {
 | 
						|
        font-size: 32px;
 | 
						|
        margin-bottom: 16px;
 | 
						|
      }
 | 
						|
 | 
						|
      p {
 | 
						|
        margin-bottom: 8px;
 | 
						|
      }
 | 
						|
 | 
						|
      #buttons {
 | 
						|
        margin-bottom: 16px;
 | 
						|
      }
 | 
						|
 | 
						|
      button {
 | 
						|
        background: #fff;
 | 
						|
        border: 2px solid #3498db;
 | 
						|
        border-radius: 4px;
 | 
						|
        color: #3498db;
 | 
						|
        cursor: pointer;
 | 
						|
        display: inline-block;
 | 
						|
        font-size: 16px;
 | 
						|
        margin-right: 16px;
 | 
						|
        padding: 8px 16px;
 | 
						|
      }
 | 
						|
 | 
						|
      button.disabled {
 | 
						|
        background: #ccc;
 | 
						|
        border-color: #ccc;
 | 
						|
        color: #666;
 | 
						|
        cursor: default;
 | 
						|
      }
 | 
						|
 | 
						|
      .trace {
 | 
						|
        margin-bottom: 16px;
 | 
						|
      }
 | 
						|
    </style>
 | 
						|
  </head>
 | 
						|
  <body>
 | 
						|
    <h1>Website Fingerprinting Lab</h1>
 | 
						|
    <div id="buttons">
 | 
						|
      <button id="collect-trace">Collect trace</button>
 | 
						|
      <button id="download-traces">Download traces</button>
 | 
						|
    </div>
 | 
						|
    <div id="traces"></div>
 | 
						|
    <script src="https://d3js.org/d3.v6.js"></script>
 | 
						|
    <script type="text/javascript">
 | 
						|
      const worker = new Worker("worker.js");
 | 
						|
 | 
						|
      const collectTraceButton = document.getElementById("collect-trace");
 | 
						|
      const downloadTracesButton = document.getElementById("download-traces");
 | 
						|
 | 
						|
      // Default values for when the automation script isn't being used. When
 | 
						|
      // the script is in use, these values will get overwritten.
 | 
						|
      window.trace_length = 5000;
 | 
						|
      window.using_automation_script = false;
 | 
						|
 | 
						|
      window.recording = false;
 | 
						|
      window.traces = [];
 | 
						|
 | 
						|
      let traceIds = [];
 | 
						|
 | 
						|
      worker.onmessage = (e) => {
 | 
						|
        window.recording = false;
 | 
						|
 | 
						|
        const trace = JSON.parse(e.data);
 | 
						|
        window.traces.push(trace);
 | 
						|
 | 
						|
        if (window.using_automation_script) {
 | 
						|
          // Don't display traces when automation script is in use
 | 
						|
          return;
 | 
						|
        }
 | 
						|
 | 
						|
        // Create new trace div
 | 
						|
        const parent = document.getElementById("traces");
 | 
						|
        const div = document.createElement("div");
 | 
						|
        const traceId = "a" + Math.random().toString().substring(2, 10);
 | 
						|
        div.setAttribute("id", traceId);
 | 
						|
        div.className = "trace";
 | 
						|
        parent.appendChild(div);
 | 
						|
        traceIds.push(traceId);
 | 
						|
 | 
						|
        // Trace dimensions
 | 
						|
        const width = parent.getBoundingClientRect().width;
 | 
						|
        const height = 64;
 | 
						|
 | 
						|
        // Create div for new trace
 | 
						|
        const svg = d3
 | 
						|
          .select("#" + traceId)
 | 
						|
          .append("svg")
 | 
						|
          .attr("width", width)
 | 
						|
          .attr("height", height);
 | 
						|
 | 
						|
        // Find largest value across all traces
 | 
						|
        const maxVal = d3.max(window.traces, (d) => d3.max(d));
 | 
						|
 | 
						|
        for (let i = 0; i < window.traces.length; i++) {
 | 
						|
          // Re-visualize all traces each time in case maxVal changes
 | 
						|
          const x = d3
 | 
						|
            .scaleLinear()
 | 
						|
            .domain([0, window.traces[i].length])
 | 
						|
            .range([0, width]);
 | 
						|
 | 
						|
          const color = d3
 | 
						|
            .scaleQuantize()
 | 
						|
            .range(["#0d0887", "#7e03a8", "#cc4778", "#f89540", "#f0f921"])
 | 
						|
            .domain([0, maxVal]);
 | 
						|
 | 
						|
          svg
 | 
						|
            .selectAll()
 | 
						|
            .data(window.traces[i].map((x, i) => ({ index: i, value: x })))
 | 
						|
            .join("rect")
 | 
						|
            .attr("x", (d) => x(d.index))
 | 
						|
            .attr("y", 0)
 | 
						|
            .attr("width", x(1))
 | 
						|
            .attr("height", height)
 | 
						|
            .style("fill", (d) => color(d.value));
 | 
						|
        }
 | 
						|
 | 
						|
        // Reset UI
 | 
						|
        collectTraceButton.innerText = "Collect trace";
 | 
						|
        collectTraceButton.className = "";
 | 
						|
      };
 | 
						|
 | 
						|
      function collectTrace() {
 | 
						|
        collectTraceButton.innerText = "Collecting trace...";
 | 
						|
        collectTraceButton.className = "disabled";
 | 
						|
        window.recording = true;
 | 
						|
 | 
						|
        worker.postMessage({
 | 
						|
          type: "start",
 | 
						|
          trace_length: window.trace_length,
 | 
						|
        });
 | 
						|
      }
 | 
						|
 | 
						|
      collectTraceButton.onclick = () => {
 | 
						|
        if (window.recording) return;
 | 
						|
 | 
						|
        window.recording = true;
 | 
						|
        collectTraceButton.innerText = "Starting in 3...";
 | 
						|
        collectTraceButton.className = "disabled";
 | 
						|
 | 
						|
        setTimeout(() => {
 | 
						|
          collectTraceButton.innerText = "Starting in 2...";
 | 
						|
 | 
						|
          setTimeout(() => {
 | 
						|
            collectTraceButton.innerText = "Starting in 1...";
 | 
						|
            setTimeout(collectTrace, 1000);
 | 
						|
          }, 1000);
 | 
						|
        }, 1000);
 | 
						|
      };
 | 
						|
 | 
						|
      downloadTracesButton.onclick = () => {
 | 
						|
        const blob = new Blob([JSON.stringify({ traces: window.traces })], {
 | 
						|
          type: "application/json",
 | 
						|
        });
 | 
						|
 | 
						|
        const url = URL.createObjectURL(blob);
 | 
						|
 | 
						|
        const elem = document.createElement("a");
 | 
						|
        elem.href = url;
 | 
						|
        elem.download = "traces.json";
 | 
						|
        document.body.appendChild(elem);
 | 
						|
 | 
						|
        elem.click();
 | 
						|
        document.body.removeChild(elem);
 | 
						|
      };
 | 
						|
    </script>
 | 
						|
  </body>
 | 
						|
</html>
 |