Lab fixes for 2024
This commit is contained in:
parent
cfbf09b7e9
commit
b7b3a02bfe
16
automate.py
16
automate.py
|
@ -14,20 +14,15 @@ from selenium.webdriver.chrome.options import Options
|
|||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--browser", type=str, choices=["chrome", "firefox", "safari"], default="chrome", help="Browser to run automation in.")
|
||||
parser.add_argument("--domains", type=str, default="google.com,youtube.com,baidu.com,facebook.com", help="Comma-separated list of domain names to collect traces from. Defaults to google.com,youtube.com,baidu.com,facebook.com")
|
||||
parser.add_argument("--enable_countermeasure", type=bool, default=False, help="Set to true to enable the countermeasure. Browser must be set to Chrome. Defaults to false.")
|
||||
parser.add_argument("--num_traces_per_domain", type=int, default=40, help="Number of traces to collect per domain.")
|
||||
parser.add_argument("--trace_length", type=int, default=5000, help="The length of each recorded trace, in milliseconds. Defaults to 5000.")
|
||||
|
||||
required = parser.add_argument_group("required arguments")
|
||||
required.add_argument("--out_filename", type=str, required=True, help="Name of the output file to save traces to.")
|
||||
required.add_argument("--part", type=int, choices=[2, 3, 4], required=True, help="Set to the part of the lab you're working on.")
|
||||
required.add_argument("--part", type=int, choices=[2, 3], required=True, help="Set to the part of the lab you're working on.")
|
||||
|
||||
opts = parser.parse_args()
|
||||
|
||||
if opts.browser != "chrome" and opts.enable_countermeasure:
|
||||
print("Browser must be set to Chrome in order to enable the countermeasure.")
|
||||
sys.exit(1)
|
||||
|
||||
if os.path.exists(opts.out_filename):
|
||||
print(f"WARNING: Data already exists at {opts.out_filename}. What do you want to do?")
|
||||
res = input("[C]ancel [O]verwrite ").lower()
|
||||
|
@ -40,11 +35,6 @@ if os.path.exists(opts.out_filename):
|
|||
# Start serving attacker app
|
||||
app = Flask(__name__)
|
||||
|
||||
# Disable Flask logs
|
||||
os.environ["WERKZEUG_RUN_MAIN"] = "true"
|
||||
log = logging.getLogger("werkzeug")
|
||||
log.disabled = True
|
||||
|
||||
@app.route("/")
|
||||
def root():
|
||||
return send_from_directory(f"part{opts.part}", "index.html")
|
||||
|
@ -63,10 +53,6 @@ def get_browser(victim):
|
|||
chrome_opts = Options()
|
||||
chrome_opts.add_experimental_option("excludeSwitches", ["enable-automation"])
|
||||
|
||||
if opts.enable_countermeasure and victim:
|
||||
# Victim has the extension enabled -- attacker does not
|
||||
chrome_opts.add_extension("part4/extension.crx")
|
||||
|
||||
return webdriver.Chrome(options=chrome_opts)
|
||||
elif opts.browser == "firefox":
|
||||
return webdriver.Firefox()
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
../index.html
|
|
@ -0,0 +1,185 @@
|
|||
<!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>
|
|
@ -1,7 +1,11 @@
|
|||
// Duration of your trace, in milliseconds
|
||||
let TRACE_LENGTH;
|
||||
// Number of sweep counts
|
||||
// TODO: Choose an appropriate value!
|
||||
let P;
|
||||
|
||||
// Array of length TRACE_LENGTH with your trace's values
|
||||
// Number of elements in your trace
|
||||
let K = 5 * 1000 / P;
|
||||
|
||||
// Array of length K with your trace's values
|
||||
let T;
|
||||
|
||||
// Value of performance.now() when you started recording your trace
|
||||
|
@ -9,7 +13,7 @@ let start;
|
|||
|
||||
function record() {
|
||||
// Create empty array for saving trace values
|
||||
T = new Array(TRACE_LENGTH);
|
||||
T = new Array(K);
|
||||
|
||||
// Fill array with -1 so we can be sure memory is allocated
|
||||
T.fill(-1, 0, T.length);
|
||||
|
@ -17,7 +21,7 @@ function record() {
|
|||
// Save start timestamp
|
||||
start = performance.now();
|
||||
|
||||
// TODO (Exercise 2-2): Record data for TRACE_LENGTH seconds and save values to T.
|
||||
// TODO: Record data for 5 seconds and save values to T.
|
||||
|
||||
// Once done recording, send result to main thread
|
||||
postMessage(JSON.stringify(T));
|
||||
|
@ -26,7 +30,6 @@ function record() {
|
|||
// DO NOT MODIFY BELOW THIS LINE -- PROVIDED BY COURSE STAFF
|
||||
self.onmessage = (e) => {
|
||||
if (e.data.type === "start") {
|
||||
TRACE_LENGTH = e.data.trace_length;
|
||||
setTimeout(record, 0);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
../index.html
|
|
@ -0,0 +1,185 @@
|
|||
<!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>
|
|
@ -1,7 +1,11 @@
|
|||
// Duration of your trace, in milliseconds
|
||||
let TRACE_LENGTH;
|
||||
// Number of sweep counts
|
||||
// TODO: Choose an appropriate value!
|
||||
let P;
|
||||
|
||||
// Array of length TRACE_LENGTH with your trace's values
|
||||
// Number of elements in your trace
|
||||
let K = 5 * 1000 / P;
|
||||
|
||||
// Array of length K with your trace's values
|
||||
let T;
|
||||
|
||||
// Value of performance.now() when you started recording your trace
|
||||
|
@ -9,7 +13,7 @@ let start;
|
|||
|
||||
function record() {
|
||||
// Create empty array for saving trace values
|
||||
T = new Array(TRACE_LENGTH);
|
||||
T = new Array(K);
|
||||
|
||||
// Fill array with -1 so we can be sure memory is allocated
|
||||
T.fill(-1, 0, T.length);
|
||||
|
@ -17,7 +21,7 @@ function record() {
|
|||
// Save start timestamp
|
||||
start = performance.now();
|
||||
|
||||
// TODO (Exercise 3-1): Record data for TRACE_LENGTH seconds and save values to T.
|
||||
// TODO: Record data for 5 seconds and save values to T.
|
||||
|
||||
// Once done recording, send result to main thread
|
||||
postMessage(JSON.stringify(T));
|
||||
|
@ -26,7 +30,6 @@ function record() {
|
|||
// DO NOT MODIFY BELOW THIS LINE -- PROVIDED BY COURSE STAFF
|
||||
self.onmessage = (e) => {
|
||||
if (e.data.type === "start") {
|
||||
TRACE_LENGTH = e.data.trace_length;
|
||||
setTimeout(record, 0);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
import json
|
||||
import numpy as np
|
||||
|
||||
from sklearn.ensemble import RandomForestClassifier
|
||||
from sklearn.metrics import classification_report
|
||||
from sklearn.model_selection import train_test_split
|
||||
|
||||
def eval():
|
||||
y_pred_full, y_test_full = [], []
|
||||
|
||||
# Re-train 10 times in order to reduce effects of randomness
|
||||
for i in range(10):
|
||||
### TODO: Exercise 4-1
|
||||
### 1. Load data from traces file
|
||||
### 2. Split data into X_train, X_test, y_train, y_test with train_test_split
|
||||
### 3. Train classifier with X_train and y_train
|
||||
### 4. Use classifier to make predictions on X_test. Save the result to a variable called y_pred
|
||||
|
||||
# Do not modify the next two lines
|
||||
y_test_full.extend(y_test)
|
||||
y_pred_full.extend(y_pred)
|
||||
|
||||
### TODO: Exercise 4-1 (continued)
|
||||
### 5. Print classification report using y_test_full and y_pred_full
|
||||
|
||||
if __name__ == "__main__":
|
||||
eval()
|
Binary file not shown.
|
@ -1,162 +0,0 @@
|
|||
const domains = [
|
||||
"https://www.google.com/",
|
||||
"https://www.youtube.com/",
|
||||
"https://www.tmall.com/",
|
||||
"https://www.qq.com/",
|
||||
"https://www.baidu.com/",
|
||||
"https://www.sohu.com/",
|
||||
"https://www.facebook.com/",
|
||||
"https://www.taobao.com/",
|
||||
"https://www.jd.com/",
|
||||
"https://www.amazon.com/",
|
||||
"https://www.yahoo.com/",
|
||||
"https://www.wikipedia.org/",
|
||||
"https://www.weibo.com/",
|
||||
"https://sina.com.cn/",
|
||||
"https://www.zoom.us/",
|
||||
"http://www.xinhuanet.com/",
|
||||
"https://www.live.com/",
|
||||
"https://www.reddit.com/",
|
||||
"https://www.netflix.com/",
|
||||
"https://www.microsoft.com/",
|
||||
"https://www.instagram.com/",
|
||||
"https://www.office.com/",
|
||||
"https://panda.tv/",
|
||||
"https://www.zhanqi.tv/",
|
||||
"https://www.alipay.com/",
|
||||
"https://www.bing.com/",
|
||||
"https://www.csdn.net/",
|
||||
"https://www.vk.com/",
|
||||
"https://www.myshopify.com/",
|
||||
"https://www.naver.com/",
|
||||
"https://www.okezone.com/",
|
||||
"https://www.twitch.tv/",
|
||||
"https://www.twitter.com/",
|
||||
"https://www.ebay.com/",
|
||||
"https://www.adobe.com/",
|
||||
"https://www.tianya.cn/",
|
||||
"https://www.huanqiu.com/",
|
||||
"https://www.yy.com/",
|
||||
"https://www.aliexpress.com/",
|
||||
"https://www.linkedin.com/",
|
||||
"https://www.force.com/",
|
||||
"https://www.aparat.com/",
|
||||
"https://www.mail.ru/",
|
||||
"https://www.msn.com/",
|
||||
"https://www.dropbox.com/",
|
||||
"https://www.whatsapp.com/",
|
||||
"https://www.apple.com/",
|
||||
"https://www.1688.com/",
|
||||
"https://www.wordpress.com/",
|
||||
"https://www.canva.com/",
|
||||
"https://www.indeed.com/",
|
||||
"https://www.stackoverflow.com/",
|
||||
"https://www.ok.ru/",
|
||||
"https://www.so.com/",
|
||||
"https://www.chase.com/",
|
||||
"https://www.imdb.com/",
|
||||
"https://www.slack.com/",
|
||||
"https://www.etsy.com/",
|
||||
"https://www.tiktok.com/",
|
||||
"https://www.booking.com/",
|
||||
"https://www.babytree.com/",
|
||||
"https://rakuten.co.jp/",
|
||||
"https://www.salesforce.com/",
|
||||
"https://www.spotify.com/",
|
||||
"https://www.tribunnews.com/",
|
||||
"https://www.fandom.com/",
|
||||
"https://www.tradingview.com/",
|
||||
"https://www.github.com/",
|
||||
"https://www.haosou.com/",
|
||||
"https://www.paypal.com/",
|
||||
"https://www.cnblogs.com/",
|
||||
"https://www.alibaba.com/",
|
||||
"https://www.kompas.com/",
|
||||
"https://gome.com.cn/",
|
||||
"https://www.walmart.com/",
|
||||
"https://www.roblox.com/",
|
||||
"https://www.6.cn/",
|
||||
"https://www.zillow.com/",
|
||||
"https://www.godaddy.com/",
|
||||
"https://www.imgur.com/",
|
||||
"https://www.espn.com/",
|
||||
"https://www.bbc.com/",
|
||||
"https://www.hao123.com/",
|
||||
"https://www.pikiran-rakyat.com/",
|
||||
"https://www.grammarly.com/",
|
||||
"https://www.cnn.com/",
|
||||
"https://www.telegram.org/",
|
||||
"https://www.tumblr.com/",
|
||||
"https://www.nytimes.com/",
|
||||
"https://www.detik.com/",
|
||||
"https://www.wetransfer.com/",
|
||||
"https://www.savefrom.net/",
|
||||
"https://www.rednet.cn/",
|
||||
"https://www.freepik.com/",
|
||||
"https://www.ilovepdf.com/",
|
||||
"https://www.daum.net/",
|
||||
"https://www.pinterest.com/",
|
||||
"https://www.primevideo.com/",
|
||||
"https://www.intuit.com/",
|
||||
"https://www.medium.com/",
|
||||
];
|
||||
|
||||
const loadTime = 5000;
|
||||
let loading = false;
|
||||
let startTime = 0;
|
||||
|
||||
function randomPing() {
|
||||
const controller = new AbortController();
|
||||
const id = setTimeout(
|
||||
() => controller.abort(),
|
||||
loadTime - (performance.now() - startTime)
|
||||
);
|
||||
|
||||
fetch(
|
||||
domains[Math.floor(Math.random() * domains.length)] +
|
||||
"?" +
|
||||
new Date().getTime(),
|
||||
{
|
||||
signal: controller.signal,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function activityBurst() {
|
||||
switch (Math.floor(Math.random() * 2)) {
|
||||
case 0:
|
||||
let start = performance.now();
|
||||
let counter = 0;
|
||||
|
||||
while (performance.now() - start < 5) {
|
||||
counter += 1;
|
||||
}
|
||||
|
||||
console.log(counter);
|
||||
break;
|
||||
case 1:
|
||||
randomPing();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
|
||||
if (changeInfo.status === "loading") {
|
||||
if (loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
startTime = performance.now();
|
||||
loading = true;
|
||||
|
||||
for (let i = 0; i < 20; i++) {
|
||||
randomPing();
|
||||
}
|
||||
|
||||
for (let i = 0; i < loadTime / 10; i++) {
|
||||
setTimeout(activityBurst, Math.random() * loadTime);
|
||||
}
|
||||
} else if (changeInfo.status === "complete") {
|
||||
loading = false;
|
||||
}
|
||||
});
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"name": "Lab Countermeasure",
|
||||
"version": "1.0",
|
||||
"manifest_version": 3,
|
||||
"background": {
|
||||
"service_worker": "background.js"
|
||||
},
|
||||
"action": {},
|
||||
"host_permissions": ["*://*/*"]
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
../index.html
|
|
@ -1,32 +0,0 @@
|
|||
// Duration of your trace, in milliseconds
|
||||
let TRACE_LENGTH;
|
||||
|
||||
// Array of length TRACE_LENGTH with your trace's values
|
||||
let T;
|
||||
|
||||
// Value of performance.now() when you started recording your trace
|
||||
let start;
|
||||
|
||||
function record() {
|
||||
// Create empty array for saving trace values
|
||||
T = new Array(TRACE_LENGTH);
|
||||
|
||||
// Fill array with -1 so we can be sure memory is allocated
|
||||
T.fill(-1, 0, T.length);
|
||||
|
||||
// Save start timestamp
|
||||
start = performance.now();
|
||||
|
||||
// TODO (Exercise 4-4): Copy your solution from part 3. Optionally make changes to your part 3 solution if you need to.
|
||||
|
||||
// Once done recording, send result to main thread
|
||||
postMessage(JSON.stringify(T));
|
||||
}
|
||||
|
||||
// DO NOT MODIFY BELOW THIS LINE -- PROVIDED BY COURSE STAFF
|
||||
self.onmessage = (e) => {
|
||||
if (e.data.type === "start") {
|
||||
TRACE_LENGTH = e.data.trace_length;
|
||||
setTimeout(record, 0);
|
||||
}
|
||||
};
|
Loading…
Reference in New Issue