manifest.json
{
"manifest_version": 3,
"name": "Proxy Settings Extension",
"version": "1.0",
"description": "Set proxy type, IP, and port for Chrome.",
"permissions": [
"proxy",
"storage"
],
"host_permissions": [
"http://*/*",
"https://*/*"
],
"background": {
"service_worker": "background.js"
},
"action": {
"default_popup": "popup.html"
}
}
background.js
chrome.runtime.onInstalled.addListener(() => {
// Инициализация значений по умолчанию для прокси
for (let i = 1; i <= 3; i++) {
chrome.storage.sync.get([`proxyType${i}`, `proxyIP${i}`, `proxyPort${i}`], (data) => {
if (!data[`proxyType${i}`]) {
chrome.storage.sync.set({
[`proxyType${i}`]: 'SOCKS5',
[`proxyIP${i}`]: '0.0.0.0',
[`proxyPort${i}`]: '1080'
});
}
});
}
});
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.action === 'get-proxy-status') {
chrome.proxy.settings.get({}, (config) => {
const proxyIsActive = config.value && config.value.mode === 'fixed_servers';
if (proxyIsActive) {
chrome.storage.sync.get(['activeProxyProfile'], (data) => {
const activeProfile = data.activeProxyProfile || 1;
sendResponse({ active: true, activeProfile });
});
} else {
sendResponse({ active: false });
}
});
return true;
}
if (message.action === 'apply-proxy') {
const profile = message.profile;
chrome.storage.sync.get([`proxyType${profile}`, `proxyIP${profile}`, `proxyPort${profile}`], (data) => {
const proxyType = data[`proxyType${profile}`] || 'SOCKS5';
const proxyIP = data[`proxyIP${profile}`] || '0.0.0.0';
const proxyPort = data[`proxyPort${profile}`] || '1080';
if (!isValidPort(proxyPort)) {
sendResponse({ success: false, error: 'Invalid proxy port number' });
return;
}
const config = {
mode: "fixed_servers",
rules: {
singleProxy: {
scheme: proxyType.toLowerCase(),
host: proxyIP,
port: parseInt(proxyPort, 10)
},
bypassList: []
}
};
chrome.proxy.settings.set({ value: config, scope: 'regular' }, () => {
if (chrome.runtime.lastError) {
sendResponse({ success: false, error: chrome.runtime.lastError.message });
} else {
chrome.storage.sync.set({ activeProxyProfile: profile }, () => {
sendResponse({ success: true });
});
}
});
});
return true;
}
if (message.action === 'disable-all-proxies') {
const config = { mode: "direct" };
chrome.proxy.settings.set({ value: config, scope: 'regular' }, () => {
if (chrome.runtime.lastError) {
sendResponse({ success: false, error: chrome.runtime.lastError.message });
} else {
chrome.storage.sync.remove('activeProxyProfile', () => {
sendResponse({ success: true });
});
}
});
return true;
}
});
function isValidPort(port) {
const parsedPort = parseInt(port, 10);
return !isNaN(parsedPort) && parsedPort > 0 && parsedPort <= 65535;
}
function isValidIP(ip) {
// Простейшая проверка на формат IP-адреса
const regex = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
return regex.test(ip);
}
popup.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Proxy Settings</title>
<style>
body {
width: 600px;
padding: 20px;
font-family: Arial, sans-serif;
background: linear-gradient(to bottom, #F7F7F7, #ECECEC);
}
.header-container {
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 20px;
}
h3 {
margin: 0;
font-size: 16px;
text-align: left;
margin-left: 20px;
color: #333;
}
#disable-proxy {
font-size: 12px;
padding: 5px 10px;
background-color: #e57373;
color: white;
border: none;
cursor: pointer;
border-radius: 5px;
display: inline-block;
opacity: 0.8;
}
#disable-proxy:hover {
opacity: 1;
background-color: #f44336;
}
#disable-proxy:disabled {
background-color: #ccc;
cursor: not-allowed;
opacity: 0.8;
}
label {
display: block;
margin-top: 10px;
font-weight: bold;
color: #555;
}
input, select {
width: 100%;
padding: 5px;
margin-top: 5px;
box-sizing: border-box;
border: 1px solid #ddd;
border-radius: 4px;
}
.profiles-container {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
margin: 0;
padding: 0;
}
.profile {
flex: 1 1 170px;
border: 1px solid #ddd;
padding: 15px;
border-radius: 5px;
margin: 10px;
box-sizing: border-box;
max-width: 170px;
background-color: #fff;
}
.apply-proxy {
width: 100%;
margin-top: 20px;
margin-bottom: 10px;
padding: 10px;
background-color: #64b5f6;
color: white;
border: none;
cursor: pointer;
border-radius: 5px;
text-align: center;
opacity: 0.8;
}
.apply-proxy:hover {
background-color: #42a5f5;
opacity: 1;
}
.apply-proxy:disabled {
background-color: #ccc;
cursor: not-allowed;
opacity: 0.8;
}
</style>
</head>
<body>
<div class="header-container">
<button id="disable-proxy" disabled>Disable Proxy</button>
<h3 id="proxy-status">Proxy OFF</h3>
</div>
<div class="profiles-container">
<div class="profile">
<label for="proxy-type-1">Proxy Type</label>
<select id="proxy-type-1">
<option value="SOCKS5">SOCKS5</option>
<option value="HTTP">HTTP</option>
<option value="HTTPS">HTTPS</option>
</select>
<label for="proxy-ip-1">Proxy IP</label>
<input type="text" id="proxy-ip-1" value="0.0.0.0">
<label for="proxy-port-1">Proxy Port</label>
<input type="number" id="proxy-port-1" value="1080">
<button class="apply-proxy" id="apply-proxy-1">Apply Proxy</button>
</div>
<div class="profile">
<label for="proxy-type-2">Proxy Type</label>
<select id="proxy-type-2">
<option value="SOCKS5">SOCKS5</option>
<option value="HTTP">HTTP</option>
<option value="HTTPS">HTTPS</option>
</select>
<label for="proxy-ip-2">Proxy IP</label>
<input type="text" id="proxy-ip-2" value="0.0.0.0">
<label for="proxy-port-2">Proxy Port</label>
<input type="number" id="proxy-port-2" value="1080">
<button class="apply-proxy" id="apply-proxy-2">Apply Proxy</button>
</div>
<div class="profile">
<label for="proxy-type-3">Proxy Type</label>
<select id="proxy-type-3">
<option value="SOCKS5">SOCKS5</option>
<option value="HTTP">HTTP</option>
<option value="HTTPS">HTTPS</option>
</select>
<label for="proxy-ip-3">Proxy IP</label>
<input type="text" id="proxy-ip-3" value="0.0.0.0">
<label for="proxy-port-3">Proxy Port</label>
<input type="number" id="proxy-port-3" value="1080">
<button class="apply-proxy" id="apply-proxy-3">Apply Proxy</button>
</div>
</div>
<script src="popup.js"></script>
</body>
</html>
popup.js
document.addEventListener('DOMContentLoaded', () => {
chrome.runtime.sendMessage({ action: 'get-proxy-status' }, (response) => {
if (response && response.active) {
document.getElementById('proxy-status').textContent = `Proxy Active (Profile ${response.activeProfile})`;
document.getElementById('disable-proxy').disabled = false;
} else {
document.getElementById('proxy-status').textContent = 'Proxy OFF';
document.getElementById('disable-proxy').disabled = true;
}
// Загрузка сохраненных значений в поля ввода
for (let i = 1; i <= 3; i++) {
chrome.storage.sync.get([`proxyType${i}`, `proxyIP${i}`, `proxyPort${i}`], (data) => {
document.getElementById(`proxy-type-${i}`).value = data[`proxyType${i}`] || 'SOCKS5';
document.getElementById(`proxy-ip-${i}`).value = data[`proxyIP${i}`] || '0.0.0.0';
document.getElementById(`proxy-port-${i}`).value = data[`proxyPort${i}`] || '1080';
});
}
});
// Обработчик для кнопки "Применить прокси"
for (let i = 1; i <= 3; i++) {
const applyButton = document.getElementById(`apply-proxy-${i}`);
if (applyButton) {
applyButton.addEventListener('click', () => {
const proxyType = document.getElementById(`proxy-type-${i}`).value;
const proxyIP = document.getElementById(`proxy-ip-${i}`).value;
const proxyPort = document.getElementById(`proxy-port-${i}`).value;
if (!isValidPort(proxyPort)) {
alert('Invalid proxy port number');
return;
}
if (!isValidIP(proxyIP)) {
alert('Invalid proxy IP address');
return;
}
chrome.storage.sync.set({ [`proxyType${i}`]: proxyType, [`proxyIP${i}`]: proxyIP, [`proxyPort${i}`]: proxyPort }, () => {
chrome.runtime.sendMessage({ action: 'apply-proxy', profile: i }, (response) => {
if (response.success) {
document.getElementById('proxy-status').textContent = `Proxy Active (Profile ${i})`;
document.getElementById('disable-proxy').disabled = false;
} else {
alert(`Error applying proxy: ${response.error || 'Unknown error'}`);
}
});
});
});
} else {
console.error(`Button with id 'apply-proxy-${i}' not found.`);
}
}
// Обработчик для кнопки "Отключить прокси"
const disableProxyButton = document.getElementById('disable-proxy');
if (disableProxyButton) {
disableProxyButton.addEventListener('click', () => {
chrome.runtime.sendMessage({ action: 'disable-all-proxies' }, (response) => {
if (response.success) {
document.getElementById('proxy-status').textContent = 'Proxy OFF';
document.getElementById('disable-proxy').disabled = true;
} else {
alert(`Error disabling proxy: ${response.error || 'Unknown error'}`);
}
});
});
}
// Слушаем изменения в полях ввода, чтобы сохранять данные при вводе
for (let i = 1; i <= 3; i++) {
const proxyTypeElement = document.getElementById(`proxy-type-${i}`);
const proxyIPElement = document.getElementById(`proxy-ip-${i}`);
const proxyPortElement = document.getElementById(`proxy-port-${i}`);
if (proxyTypeElement) {
proxyTypeElement.addEventListener('input', () => {
saveProxyData(i);
});
}
if (proxyIPElement) {
proxyIPElement.addEventListener('input', () => {
saveProxyData(i);
});
}
if (proxyPortElement) {
proxyPortElement.addEventListener('input', () => {
saveProxyData(i);
});
}
}
});
// Функция для сохранения данных в chrome.storage
function saveProxyData(profileIndex) {
const proxyType = document.getElementById(`proxy-type-${profileIndex}`).value;
const proxyIP = document.getElementById(`proxy-ip-${profileIndex}`).value;
const proxyPort = document.getElementById(`proxy-port-${profileIndex}`).value;
chrome.storage.sync.set({
[`proxyType${profileIndex}`]: proxyType,
[`proxyIP${profileIndex}`]: proxyIP,
[`proxyPort${profileIndex}`]: proxyPort
});
}
// Проверка на корректность IP адреса
function isValidIP(ip) {
const regex = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
return regex.test(ip);
}
// Проверка на корректность порта
function isValidPort(port) {
const portNumber = parseInt(port, 10);
return portNumber >= 1 && portNumber <= 65535;
}