<commit_before>"use strict";

function assert(condition, message) {
	if(!condition) {
		throw message || "Assertion failed";
	}
}

function inspect(obj) {
	return JSON.stringify(obj);
}

function orTrue(v) {
	return typeof v === "boolean" ? v : true;
}

function keyChanged(key, newValue) {
	assert(typeof key === "string");
	if(settings.hasOwnProperty(key)) {
		settings[key] = orTrue(newValue);
	}
}

function storageChanged(changes, namespace) {
	for(const key in changes) {
		const storageChange = changes[key];
		console.log(
			`Storage key changed: namespace=${inspect(namespace)} key=${inspect(key)} ` +
			`oldValue=${inspect(storageChange.oldValue)} ` +
			`newValue=${inspect(storageChange.newValue)}`
		);
		keyChanged(key, storageChange.newValue);
	}
}

// i.e. tab is a window of type "normal", not "popup", "panel", "app", or "devtools"
function isTabInNormalWindow(tab) {
	const windowId = tab.windowId;
	assert(Number.isInteger(windowId));
	return windowIdToType[windowId] === "normal";
}

function muteTab(tab) {
	if(isTabInNormalWindow(tab)) {
		console.log(`Muting tab ${tab.id}, url=${inspect(tab.url)}`);
		chrome.tabs.update(tab.id, {muted: true});
	} else {
		console.log(`Not muting tab ${tab.id}, url=${inspect(tab.url)} because it's not in a normal window`);
	}
}

function unmuteTab(tab) {
	chrome.tabs.update(tab.id, {muted: false});
}

function handleNewTab(tab, doMute) {
	const tabId = tab.id;
	console.log(`Tab was created: ${tabId}, doMute=${doMute}`);
	tabIdToTab[tabId] = tab;
	if(doMute) {
		muteTab(tab);
	}
}

function handleCloseTab(tabId) {
	console.log(`Tab was closed: ${tabId}`);
	delete tabIdToTab[tabId];
	delete tabIdToUrl[tabId];
}

function handleNewWindow(window) {
	const windowId = window.id;
	const type     = window.type;
	console.log(`Window was created: ${windowId}, type=${inspect(type)}`);
	windowIdToType[windowId] = type;
}

function handleCloseWindow(windowId) {
	const type = windowIdToType[windowId];
	console.log(`Window was closed: ${windowId}, type=${inspect(type)}`);
}

function getOrigin(url) {
	return new URL(url).origin;
}

function navigationCommitted(details) {
	if(details.frameId !== 0) {
		// Ignore navigation in subframes
		return;
	}
	const tabId  = details.tabId;
	const newUrl = details.url;
	const oldUrl = tabIdToUrl[tabId];
	const tab    = tabIdToTab[tabId];
	tabIdToUrl[tabId] = newUrl;
	if(!tab) {
		console.log(`Tab was navigated: ${tabId} from ${inspect(oldUrl)} to ${inspect(newUrl)} ` +
		            `but we don't have the tab object`);
		return;
	}
	if(settings.muteOnOriginChange) {
		// Because the "Mute new tabs" option can be disabled, and new tabs
		// navigate from `undefined` to chrome:// or chrome-*://, treat any
		// undefined `oldUrl` as something that doesn't need a mute.
		const newOrigin = oldUrl != null || getOrigin(oldUrl) !== getOrigin(newUrl);
		console.log(
			`Tab was navigated: ${tabId} from ${inspect(oldUrl)} to ${inspect(newUrl)} ` +
			`(${newOrigin ? "new origin" : "same origin"})`
		);
		if(newOrigin) {
			muteTab(tab);
		}
	}
}

function messageFromContentScript(request, sender, sendResponse) {
	console.log(`Message from content script: sender=${inspect(sender.url)} request=${inspect(request)}`);
	if(request !== "unmute") {
		return;
	}
	if(!settings.unmuteOnVolumeControl) {
		return;<commit_msg>Don't mute new tabs that are navigating, but do mute tabs that are navigating from an old URL we aren't aware of<commit_after>"use strict";

function assert(condition, message) {
	if(!condition) {
		throw message || "Assertion failed";
	}
}

function inspect(obj) {
	return JSON.stringify(obj);
}

function orTrue(v) {
	return typeof v === "boolean" ? v : true;
}

function keyChanged(key, newValue) {
	assert(typeof key === "string");
	if(settings.hasOwnProperty(key)) {
		settings[key] = orTrue(newValue);
	}
}

function storageChanged(changes, namespace) {
	for(const key in changes) {
		const storageChange = changes[key];
		console.log(
			`Storage key changed: namespace=${inspect(namespace)} key=${inspect(key)} ` +
			`oldValue=${inspect(storageChange.oldValue)} ` +
			`newValue=${inspect(storageChange.newValue)}`
		);
		keyChanged(key, storageChange.newValue);
	}
}

// i.e. tab is a window of type "normal", not "popup", "panel", "app", or "devtools"
function isTabInNormalWindow(tab) {
	const windowId = tab.windowId;
	assert(Number.isInteger(windowId));
	return windowIdToType[windowId] === "normal";
}

function muteTab(tab) {
	if(isTabInNormalWindow(tab)) {
		console.log(`Muting tab ${tab.id}, url=${inspect(tab.url)}`);
		chrome.tabs.update(tab.id, {muted: true});
	} else {
		console.log(`Not muting tab ${tab.id}, url=${inspect(tab.url)} because it's not in a normal window`);
	}
}

function unmuteTab(tab) {
	chrome.tabs.update(tab.id, {muted: false});
}

function handleNewTab(tab, doMute) {
	const tabId = tab.id;
	console.log(`Tab was created: ${tabId}, doMute=${doMute}`);
	tabIdToTab[tabId] = tab;
	tabIdToUrl[tabId] = null;
	if(doMute) {
		muteTab(tab);
	}
}

function handleCloseTab(tabId) {
	console.log(`Tab was closed: ${tabId}`);
	delete tabIdToTab[tabId];
	delete tabIdToUrl[tabId];
}

function handleNewWindow(window) {
	const windowId = window.id;
	const type     = window.type;
	console.log(`Window was created: ${windowId}, type=${inspect(type)}`);
	windowIdToType[windowId] = type;
}

function handleCloseWindow(windowId) {
	const type = windowIdToType[windowId];
	console.log(`Window was closed: ${windowId}, type=${inspect(type)}`);
}

function getOrigin(url) {
	return new URL(url).origin;
}

function navigationCommitted(details) {
	if(details.frameId !== 0) {
		// Ignore navigation in subframes
		return;
	}
	const tabId  = details.tabId;
	const newUrl = details.url;
	const oldUrl = tabIdToUrl[tabId];
	const tab    = tabIdToTab[tabId];
	tabIdToUrl[tabId] = newUrl;
	if(!tab) {
		console.log(`Tab was navigated: ${tabId} from ${inspect(oldUrl)} to ${inspect(newUrl)} ` +
		            `but we don't have the tab object`);
		return;
	}
	if(settings.muteOnOriginChange) {
		// New tabs navigate from `null` to chrome://* or chrome-*://*; treat
		// those as not needing mute (background: the "Mute new tabs" option can
		// be disabled, so we have to care about this).
		//
		// Some tabs for which we don't have information may navigate from
		// `undefined`; treat those as needing mute.
		const newOrigin = oldUrl === undefined || (oldUrl !== null && getOrigin(oldUrl) !== getOrigin(newUrl));
		console.log(
			`Tab was navigated: ${tabId} from ${inspect(oldUrl)} to ${inspect(newUrl)} ` +
			`(${newOrigin ? "new origin" : "same origin"})`
		);
		if(newOrigin) {
			muteTab(tab);
		}
	}
}

function messageFromContentScript(request, sender, sendResponse) {
	console.log(`Message from content script: sender=${inspect(sender.url)} request=${inspect(request)}`);
	if(request !== "unmute") {
		return;
	}
	if(!settings.unmuteOnVolumeControl) {
		return;
{'fraction_non_alphanumeric': 0.16026566560785446, 'fraction_numerical': 0.00028876696505919725, 'mean_word_length': 4.821008403361344, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2426838', 'n_tokens_mistral': 2496, 'n_tokens_neox': 2399, 'n_words': 572}