mirror of
https://github.com/yaklang/yaklang-chrome-extension.git
synced 2026-09-22 03:10:43 +08:00
add proxy switch demo
This commit is contained in:
@@ -1,10 +1,13 @@
|
||||
import {ActionType, injectScriptAndSendMessage, WebSocketManager} from './socket.js';
|
||||
|
||||
import { setupProxyHandlers } from './proxy.js';
|
||||
import { ProxyActionType } from './types/action.js';
|
||||
|
||||
console.info("Chrome Extenstion Background is loaded")
|
||||
|
||||
const websocketManager = new WebSocketManager();
|
||||
|
||||
// 设置代理处理器
|
||||
setupProxyHandlers();
|
||||
|
||||
chrome.runtime.onMessage.addListener(function (msg, sender, sendResponse) {
|
||||
console.log("msg", msg)
|
||||
|
||||
+7
-3
@@ -3,6 +3,7 @@
|
||||
return;
|
||||
}
|
||||
window.contentScriptInjected = true;
|
||||
window.badgeCount = 0;
|
||||
// 检查并插入 CSS 样式
|
||||
const styleId = 'injected-css-style';
|
||||
if (!document.getElementById(styleId)) {
|
||||
@@ -38,18 +39,21 @@
|
||||
script.remove();
|
||||
};
|
||||
(document.head || document.documentElement).appendChild(script);
|
||||
window.addEventListener('message', function onMessage(event) {
|
||||
window.addEventListener('message', async function onMessage(event) {
|
||||
if (event.source !== window || event.data.type !== 'FROM_INJECT_JS') {
|
||||
return;
|
||||
}
|
||||
window.removeEventListener('message', onMessage);
|
||||
// Send the result to the background script
|
||||
// chrome.runtime.sendMessage({ action: 'yakit_to_extension_page', result: event.data.result });
|
||||
window.badgeCount += 1;
|
||||
// 直接向向发送端返回结果
|
||||
sendResponse({action: 'yakit_to_extension_page', result: event.data.result});
|
||||
// Send updated badge count to background script
|
||||
await chrome.runtime.sendMessage({action: 'yakit_badge', data: window.badgeCount.toString()});
|
||||
});
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
})()
|
||||
|
||||
|
||||
+17
-10
@@ -3,36 +3,43 @@
|
||||
"name": "Yakit Chrome Endpoint",
|
||||
"version": "1.0",
|
||||
"description": "A Endpoint for Yakit MITM or more",
|
||||
"options_ui": {
|
||||
"page": "proxy/options.html",
|
||||
"open_in_tab": true
|
||||
},
|
||||
"action": {
|
||||
"default_popup": "index.html",
|
||||
"default_title": "Click to open panel",
|
||||
"default_icon": {
|
||||
"16": "/images/icon16.png",
|
||||
"48": "/images/icon48.png",
|
||||
"128": "/images/icon128.png"
|
||||
}
|
||||
},
|
||||
"side_panel": {
|
||||
"default_path" : "index.html"
|
||||
},
|
||||
"background": {
|
||||
"service_worker": "background.js",
|
||||
"type": "module"
|
||||
},
|
||||
"permissions": [
|
||||
"webNavigation",
|
||||
"activeTab",
|
||||
"scripting",
|
||||
"tabs",
|
||||
"proxy",
|
||||
"storage",
|
||||
"webRequest"
|
||||
"sidePanel"
|
||||
],
|
||||
"host_permissions": [
|
||||
"<all_urls>"
|
||||
"*://*/*"
|
||||
],
|
||||
|
||||
"web_accessible_resources": [
|
||||
{
|
||||
"resources": ["inject.js"],
|
||||
"matches": ["<all_urls>"],
|
||||
"use_dynamic_url": true
|
||||
"resources": [
|
||||
"types/*.js",
|
||||
"proxy/*.js",
|
||||
"socket.js",
|
||||
"proxy.js"
|
||||
],
|
||||
"matches": ["<all_urls>"]
|
||||
}
|
||||
],
|
||||
"icons": {
|
||||
|
||||
+214
@@ -0,0 +1,214 @@
|
||||
import { ProxyManager } from './proxy/proxy-manager.js';
|
||||
import { ProxySettings } from './proxy/proxy-settings.js';
|
||||
import { ProxyAuth } from './proxy/proxy-auth.js';
|
||||
import { ProxyActionType } from './types/action.js';
|
||||
|
||||
// 记录代理日志
|
||||
async function logProxyRequest(details, proxyConfig, error = null) {
|
||||
const log = {
|
||||
id: Date.now().toString(),
|
||||
timestamp: Date.now(),
|
||||
url: details.url,
|
||||
proxyId: proxyConfig.id,
|
||||
proxyName: proxyConfig.name,
|
||||
status: error ? 'error' : 'success',
|
||||
errorMessage: error?.message
|
||||
};
|
||||
|
||||
const result = await chrome.storage.local.get('proxyLogs');
|
||||
const logs = result.proxyLogs || [];
|
||||
const updatedLogs = [log, ...logs].slice(0, 1000);
|
||||
await chrome.storage.local.set({ proxyLogs: updatedLogs });
|
||||
}
|
||||
|
||||
async function handleSetProxyConfig(config, sendResponse) {
|
||||
try {
|
||||
if (!config || !config.host || !config.port) {
|
||||
sendResponse({
|
||||
success: false,
|
||||
error: '无效的代理配置'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const proxyConfig = {
|
||||
mode: "fixed_servers",
|
||||
rules: {
|
||||
singleProxy: {
|
||||
scheme: config.scheme || 'http',
|
||||
host: config.host,
|
||||
port: parseInt(config.port)
|
||||
},
|
||||
bypassList: ["localhost", "127.0.0.1"]
|
||||
}
|
||||
};
|
||||
|
||||
await chrome.proxy.settings.set({
|
||||
value: proxyConfig,
|
||||
scope: 'regular'
|
||||
});
|
||||
|
||||
const settings = await chrome.proxy.settings.get({});
|
||||
const isSuccess = settings.value.mode === "fixed_servers" &&
|
||||
settings.value.rules.singleProxy.host === config.host &&
|
||||
settings.value.rules.singleProxy.port === parseInt(config.port);
|
||||
|
||||
if (isSuccess) {
|
||||
await chrome.storage.local.set({
|
||||
currentProxy: {
|
||||
...config,
|
||||
timestamp: Date.now()
|
||||
}
|
||||
});
|
||||
|
||||
const result = await chrome.storage.local.get('proxyConfigs');
|
||||
if (result.proxyConfigs) {
|
||||
const updatedConfigs = result.proxyConfigs.map(c => ({
|
||||
...c,
|
||||
enabled: c.id === config.id
|
||||
}));
|
||||
await chrome.storage.local.set({ proxyConfigs: updatedConfigs });
|
||||
}
|
||||
|
||||
console.log('Proxy successfully set:', settings.value);
|
||||
sendResponse({ success: true });
|
||||
} else {
|
||||
console.error('Proxy settings verification failed');
|
||||
sendResponse({
|
||||
success: false,
|
||||
error: '代理设置验证失败'
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error setting proxy:', error);
|
||||
sendResponse({
|
||||
success: false,
|
||||
error: error.message || '设置代理时发生错误'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function handleClearProxyConfig(sendResponse) {
|
||||
try {
|
||||
await chrome.proxy.settings.clear({
|
||||
scope: 'regular'
|
||||
});
|
||||
|
||||
await chrome.proxy.settings.set({
|
||||
value: { mode: "system" },
|
||||
scope: 'regular'
|
||||
});
|
||||
|
||||
// 只移除当前代理配置,保留代理列表
|
||||
await chrome.storage.local.remove([
|
||||
'currentProxy',
|
||||
'proxyAuthHandlers'
|
||||
]);
|
||||
|
||||
// 更新所有代理的启用状态
|
||||
const result = await chrome.storage.local.get('proxyConfigs');
|
||||
if (result.proxyConfigs) {
|
||||
const updatedConfigs = result.proxyConfigs.map(config => ({
|
||||
...config,
|
||||
enabled: false
|
||||
}));
|
||||
await chrome.storage.local.set({ proxyConfigs: updatedConfigs });
|
||||
}
|
||||
|
||||
const settings = await chrome.proxy.settings.get({});
|
||||
const isSuccess = settings.value.mode === "system";
|
||||
|
||||
if (isSuccess) {
|
||||
console.log('Proxy successfully cleared');
|
||||
sendResponse({ success: true });
|
||||
} else {
|
||||
console.error('Failed to clear proxy settings');
|
||||
sendResponse({
|
||||
success: false,
|
||||
error: '无法清除代理设置'
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error clearing proxy:', error);
|
||||
sendResponse({
|
||||
success: false,
|
||||
error: error.message || '清除代理时发生错误'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function handleGetProxyStatus(sendResponse) {
|
||||
try {
|
||||
const settings = await chrome.proxy.settings.get({});
|
||||
const currentProxy = await chrome.storage.local.get('currentProxy');
|
||||
|
||||
const status = {
|
||||
enabled: settings.value.mode === "fixed_servers",
|
||||
config: currentProxy.currentProxy || null,
|
||||
mode: settings.value.mode
|
||||
};
|
||||
|
||||
console.log('Current proxy status:', status);
|
||||
sendResponse({
|
||||
success: true,
|
||||
data: status
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error getting proxy status:', error);
|
||||
sendResponse({
|
||||
success: false,
|
||||
error: error.message || '获取代理状态时发生错误'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 导出代理处理器设置函数
|
||||
export function setupProxyHandlers() {
|
||||
// 设置代理错误处理和认证
|
||||
ProxyAuth.setupErrorHandler();
|
||||
ProxyAuth.setupAuthListener();
|
||||
|
||||
// 消息监听器
|
||||
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
|
||||
console.log("Proxy message:", msg);
|
||||
|
||||
switch (msg.action) {
|
||||
case ProxyActionType.SET_PROXY_CONFIG:
|
||||
handleSetProxyConfig(msg.config, sendResponse);
|
||||
return true;
|
||||
|
||||
case ProxyActionType.CLEAR_PROXY_CONFIG:
|
||||
handleClearProxyConfig(sendResponse);
|
||||
return true;
|
||||
|
||||
case ProxyActionType.GET_PROXY_STATUS:
|
||||
handleGetProxyStatus(sendResponse);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
// 在扩展启动时初始化
|
||||
chrome.runtime.onInstalled.addListener(async () => {
|
||||
try {
|
||||
// 确保默认配置存在
|
||||
await ProxySettings.setDefaultConfigs();
|
||||
|
||||
// 清除之前的代理设置
|
||||
await handleClearProxyConfig(() => {});
|
||||
|
||||
// 设置认证监听
|
||||
await ProxyAuth.setupAuthListener();
|
||||
|
||||
// 初始化存储
|
||||
const storage = await chrome.storage.local.get(['proxyConfigs', 'proxyLogs']);
|
||||
if (!storage.proxyConfigs) {
|
||||
await chrome.storage.local.set({ proxyConfigs: [] });
|
||||
}
|
||||
if (!storage.proxyLogs) {
|
||||
await chrome.storage.local.set({ proxyLogs: [] });
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error during installation:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
background: white;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
padding-bottom: 20px;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
.header h1 {
|
||||
margin: 0;
|
||||
font-size: 24px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.proxy-item {
|
||||
background: white;
|
||||
border: 1px solid #e8e8e8;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 16px;
|
||||
padding: 16px;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.proxy-item:hover {
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.09);
|
||||
}
|
||||
|
||||
.proxy-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.proxy-name {
|
||||
font-size: 14px;
|
||||
padding: 4px 8px;
|
||||
border: 1px solid #d9d9d9;
|
||||
border-radius: 4px;
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.proxy-name:focus {
|
||||
border-color: #40a9ff;
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 2px rgba(24,144,255,0.2);
|
||||
}
|
||||
|
||||
.proxy-type-select,
|
||||
.proxy-scheme,
|
||||
.proxy-host,
|
||||
.proxy-port {
|
||||
width: 100%;
|
||||
height: 32px;
|
||||
padding: 4px 11px;
|
||||
border: 1px solid #d9d9d9;
|
||||
border-radius: 4px;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.proxy-type-select:focus,
|
||||
.proxy-scheme:focus,
|
||||
.proxy-host:focus,
|
||||
.proxy-port:focus {
|
||||
border-color: #40a9ff;
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 2px rgba(24,144,255,0.2);
|
||||
}
|
||||
|
||||
.proxy-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.proxy-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.form-group label {
|
||||
display: block;
|
||||
margin-bottom: 8px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: #1890ff;
|
||||
border: none;
|
||||
color: white;
|
||||
padding: 4px 15px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background: #40a9ff;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background: white;
|
||||
border: 1px solid #d9d9d9;
|
||||
color: rgba(0,0,0,0.85);
|
||||
padding: 4px 15px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
border-color: #40a9ff;
|
||||
color: #40a9ff;
|
||||
}
|
||||
|
||||
.header-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.delete-btn {
|
||||
padding: 4px 8px;
|
||||
background: #ff4d4f;
|
||||
}
|
||||
|
||||
.delete-btn:hover {
|
||||
background: #ff7875;
|
||||
}
|
||||
|
||||
.pac-script {
|
||||
font-family: monospace;
|
||||
min-height: 200px;
|
||||
}
|
||||
|
||||
.options-page {
|
||||
min-height: 100vh;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>代理设置</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script src="../options.bundle.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,170 @@
|
||||
console.log('Options page script loaded');
|
||||
|
||||
import { ProxySettings } from './proxy-settings.js';
|
||||
import { ProxyManager } from './proxy-manager.js';
|
||||
|
||||
let currentConfigs = [];
|
||||
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
try {
|
||||
await initOptionsPage();
|
||||
setupEventListeners();
|
||||
} catch (error) {
|
||||
console.error('Failed to initialize options page:', error);
|
||||
showError(error.message);
|
||||
}
|
||||
});
|
||||
|
||||
async function initOptionsPage() {
|
||||
const result = await ProxySettings.exportSettings();
|
||||
currentConfigs = result.settings || [];
|
||||
renderProxyConfigs();
|
||||
}
|
||||
|
||||
function renderProxyConfigs() {
|
||||
const proxyList = document.getElementById('proxyList');
|
||||
const template = document.getElementById('proxyItemTemplate');
|
||||
|
||||
// 清除除了直接连接以外的所有配置
|
||||
const items = proxyList.querySelectorAll('.proxy-item:not([data-id="direct"])');
|
||||
items.forEach(item => item.remove());
|
||||
|
||||
// 渲染其他代理配置
|
||||
currentConfigs.forEach(config => {
|
||||
if (config.id === 'direct') return; // 跳过直接连接
|
||||
|
||||
const clone = template.content.cloneNode(true);
|
||||
const proxyItem = clone.querySelector('.proxy-item');
|
||||
|
||||
proxyItem.dataset.id = config.id;
|
||||
proxyItem.querySelector('.proxy-name').value = config.name;
|
||||
proxyItem.querySelector('.proxy-type-select').value = config.proxyType;
|
||||
|
||||
updateProxyTypeSettings(proxyItem, config);
|
||||
proxyList.appendChild(proxyItem);
|
||||
});
|
||||
}
|
||||
|
||||
function updateProxyTypeSettings(proxyItem, config) {
|
||||
const serverSettings = proxyItem.querySelector('.proxy-server-settings');
|
||||
const pacSettings = proxyItem.querySelector('.pac-script-settings');
|
||||
|
||||
if (config.proxyType === 'fixed_server') {
|
||||
serverSettings.style.display = 'block';
|
||||
pacSettings.style.display = 'none';
|
||||
|
||||
proxyItem.querySelector('.proxy-scheme').value = config.scheme || 'http';
|
||||
proxyItem.querySelector('.proxy-host').value = config.host || '';
|
||||
proxyItem.querySelector('.proxy-port').value = config.port || '';
|
||||
}
|
||||
else if (config.proxyType === 'pac_script') {
|
||||
serverSettings.style.display = 'none';
|
||||
pacSettings.style.display = 'block';
|
||||
|
||||
proxyItem.querySelector('.pac-script').value = config.pacScript || '';
|
||||
}
|
||||
else {
|
||||
serverSettings.style.display = 'none';
|
||||
pacSettings.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
function setupEventListeners() {
|
||||
// 添加代理按钮
|
||||
document.getElementById('addProxy').addEventListener('click', addNewProxy);
|
||||
|
||||
// 代理列表变更事件
|
||||
document.getElementById('proxyList').addEventListener('change', handleProxyChange);
|
||||
|
||||
// 删除代理按钮
|
||||
document.getElementById('proxyList').addEventListener('click', handleProxyDelete);
|
||||
}
|
||||
|
||||
async function addNewProxy() {
|
||||
const newConfig = {
|
||||
id: Date.now().toString(),
|
||||
name: '新建代理',
|
||||
proxyType: 'fixed_server',
|
||||
scheme: 'http',
|
||||
host: '127.0.0.1',
|
||||
port: 8080
|
||||
};
|
||||
|
||||
currentConfigs = [...currentConfigs, newConfig];
|
||||
await ProxySettings.importSettings(currentConfigs);
|
||||
renderProxyConfigs();
|
||||
}
|
||||
|
||||
async function handleProxyChange(e) {
|
||||
const proxyItem = e.target.closest('.proxy-item');
|
||||
if (!proxyItem) return;
|
||||
|
||||
const configId = proxyItem.dataset.id;
|
||||
const configIndex = currentConfigs.findIndex(c => c.id === configId);
|
||||
if (configIndex === -1) return;
|
||||
|
||||
const updatedConfig = { ...currentConfigs[configIndex] };
|
||||
|
||||
if (e.target.classList.contains('proxy-name')) {
|
||||
updatedConfig.name = e.target.value;
|
||||
} else if (e.target.classList.contains('proxy-type-select')) {
|
||||
updatedConfig.proxyType = e.target.value;
|
||||
// 如果切换到固定服务器模式,设置默认值
|
||||
if (updatedConfig.proxyType === 'fixed_server' && !updatedConfig.scheme) {
|
||||
updatedConfig.scheme = 'http';
|
||||
updatedConfig.host = '127.0.0.1';
|
||||
updatedConfig.port = 8080;
|
||||
}
|
||||
} else if (e.target.classList.contains('proxy-scheme')) {
|
||||
updatedConfig.scheme = e.target.value;
|
||||
} else if (e.target.classList.contains('proxy-host')) {
|
||||
updatedConfig.host = e.target.value;
|
||||
} else if (e.target.classList.contains('proxy-port')) {
|
||||
updatedConfig.port = parseInt(e.target.value) || '';
|
||||
} else if (e.target.classList.contains('pac-script')) {
|
||||
updatedConfig.pacScript = e.target.value;
|
||||
}
|
||||
|
||||
currentConfigs[configIndex] = updatedConfig;
|
||||
await ProxySettings.importSettings(currentConfigs);
|
||||
|
||||
// 如果代理类型改变,需要更新UI
|
||||
if (e.target.classList.contains('proxy-type-select')) {
|
||||
updateProxyTypeSettings(proxyItem, updatedConfig);
|
||||
}
|
||||
}
|
||||
|
||||
async function handleProxyDelete(e) {
|
||||
const deleteBtn = e.target.closest('.delete-btn');
|
||||
if (!deleteBtn) return;
|
||||
|
||||
const proxyItem = deleteBtn.closest('.proxy-item');
|
||||
const configId = proxyItem.dataset.id;
|
||||
|
||||
currentConfigs = currentConfigs.filter(c => c.id !== configId);
|
||||
await ProxySettings.importSettings(currentConfigs);
|
||||
renderProxyConfigs();
|
||||
}
|
||||
|
||||
function showError(message) {
|
||||
const container = document.querySelector('.container');
|
||||
const errorDiv = document.createElement('div');
|
||||
errorDiv.className = 'error-message';
|
||||
errorDiv.style.cssText = `
|
||||
color: #ff4d4f;
|
||||
padding: 8px 16px;
|
||||
margin-bottom: 16px;
|
||||
background-color: #fff2f0;
|
||||
border: 1px solid #ffccc7;
|
||||
border-radius: 4px;
|
||||
`;
|
||||
errorDiv.textContent = message;
|
||||
container.insertBefore(errorDiv, container.firstChild);
|
||||
|
||||
// 5秒后自动移除错误信息
|
||||
setTimeout(() => {
|
||||
errorDiv.remove();
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
// ... 其他代码保持不变
|
||||
@@ -0,0 +1,98 @@
|
||||
// 代理认证管理
|
||||
export class ProxyAuth {
|
||||
static async setupAuthListener() {
|
||||
try {
|
||||
// 保存认证信息到 storage
|
||||
const saveAuth = async (config) => {
|
||||
await chrome.storage.local.set({
|
||||
proxyAuth: {
|
||||
username: config.username,
|
||||
password: config.password,
|
||||
timestamp: Date.now()
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 获取认证信息
|
||||
const getAuth = async () => {
|
||||
const result = await chrome.storage.local.get('proxyAuth');
|
||||
return result.proxyAuth;
|
||||
};
|
||||
|
||||
// 清除认证信息
|
||||
const clearAuth = async () => {
|
||||
await chrome.storage.local.remove('proxyAuth');
|
||||
};
|
||||
|
||||
return {
|
||||
saveAuth,
|
||||
getAuth,
|
||||
clearAuth
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Error setting up auth listener:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static setupErrorHandler() {
|
||||
// 在 Manifest V3 中,我们不能使用 chrome.proxy.onProxyError
|
||||
// 所以我们只记录错误到 storage
|
||||
try {
|
||||
const logError = async (error) => {
|
||||
const errors = await chrome.storage.local.get('proxyErrors') || [];
|
||||
errors.push({
|
||||
timestamp: Date.now(),
|
||||
error: error.message || error
|
||||
});
|
||||
await chrome.storage.local.set({
|
||||
proxyErrors: errors.slice(-100) // 只保留最近100条错误记录
|
||||
});
|
||||
};
|
||||
|
||||
return { logError };
|
||||
} catch (error) {
|
||||
console.error('Error setting up error handler:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// 设置代理认证信息
|
||||
static async setProxyAuth(username, password) {
|
||||
try {
|
||||
await chrome.storage.local.set({
|
||||
proxyAuth: {
|
||||
username,
|
||||
password,
|
||||
timestamp: Date.now()
|
||||
}
|
||||
});
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Error setting proxy auth:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 获取代理认证信息
|
||||
static async getProxyAuth() {
|
||||
try {
|
||||
const result = await chrome.storage.local.get('proxyAuth');
|
||||
return result.proxyAuth || null;
|
||||
} catch (error) {
|
||||
console.error('Error getting proxy auth:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// 清除代理认证信息
|
||||
static async clearProxyAuth() {
|
||||
try {
|
||||
await chrome.storage.local.remove('proxyAuth');
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Error clearing proxy auth:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
// 代理配置管理
|
||||
export class ProxyManager {
|
||||
static async setProxy(config) {
|
||||
try {
|
||||
const proxyConfig = {
|
||||
mode: "fixed_servers",
|
||||
rules: {
|
||||
singleProxy: {
|
||||
scheme: config.scheme,
|
||||
host: config.host,
|
||||
port: config.port
|
||||
},
|
||||
bypassList: ["localhost", "127.0.0.1"]
|
||||
}
|
||||
};
|
||||
|
||||
await chrome.proxy.settings.set({
|
||||
value: proxyConfig,
|
||||
scope: 'regular'
|
||||
});
|
||||
|
||||
// 保存当前配置
|
||||
await chrome.storage.local.set({
|
||||
currentProxy: {
|
||||
...config,
|
||||
timestamp: Date.now()
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Error setting proxy:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static async clearProxy() {
|
||||
try {
|
||||
await chrome.proxy.settings.clear({scope: 'regular'});
|
||||
await chrome.storage.local.remove('currentProxy');
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Error clearing proxy:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static async getProxyStatus() {
|
||||
try {
|
||||
const settings = await chrome.proxy.settings.get({});
|
||||
const currentProxy = await chrome.storage.local.get('currentProxy');
|
||||
return {
|
||||
enabled: settings.value.mode === "fixed_servers",
|
||||
config: currentProxy.currentProxy || null
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Error getting proxy status:', error);
|
||||
return {
|
||||
enabled: false,
|
||||
config: null
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
static async deleteProxy(proxyId) {
|
||||
try {
|
||||
// 获取当前代理配置
|
||||
const result = await chrome.storage.local.get(['proxyConfigs', 'currentProxy']);
|
||||
const configs = result.proxyConfigs || [];
|
||||
const currentProxy = result.currentProxy;
|
||||
|
||||
// 如果要删除的代理正在使用中,先清除代理设置
|
||||
if (currentProxy && currentProxy.id === proxyId) {
|
||||
await clearProxyConfig();
|
||||
}
|
||||
|
||||
// 从配置列表中删除代理
|
||||
const updatedConfigs = configs.filter(config => config.id !== proxyId);
|
||||
await chrome.storage.local.set({ proxyConfigs: updatedConfigs });
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Error deleting proxy:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
// 代理配置存储和管理
|
||||
export const ProxySettings = {
|
||||
async importSettings(settings) {
|
||||
try {
|
||||
if (Array.isArray(settings) && settings.every(s => s.proxyType)) {
|
||||
await chrome.storage.local.set({proxyConfigs: settings});
|
||||
return {success: true};
|
||||
}
|
||||
return {success: false, error: "Invalid settings format"};
|
||||
} catch (error) {
|
||||
return {success: false, error: error.message};
|
||||
}
|
||||
},
|
||||
|
||||
async exportSettings() {
|
||||
try {
|
||||
const {proxyConfigs} = await chrome.storage.local.get('proxyConfigs');
|
||||
return {success: true, settings: proxyConfigs || []};
|
||||
} catch (error) {
|
||||
return {success: false, error: error.message};
|
||||
}
|
||||
},
|
||||
|
||||
async setDefaultConfigs() {
|
||||
const result = await chrome.storage.local.get('proxyConfigs');
|
||||
if (!result.proxyConfigs) {
|
||||
const defaultConfigs = [{
|
||||
id: 'direct',
|
||||
name: '直接连接',
|
||||
proxyType: 'direct',
|
||||
enabled: false
|
||||
}];
|
||||
await chrome.storage.local.set({ proxyConfigs: defaultConfigs });
|
||||
}
|
||||
// 确保 proxyLogs 存在
|
||||
const logsResult = await chrome.storage.local.get('proxyLogs');
|
||||
if (!logsResult.proxyLogs) {
|
||||
await chrome.storage.local.set({ proxyLogs: [] });
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>My Sidepanel</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>All sites sidepanel extension</h1>
|
||||
<p>This side panel is enabled on all sites</p>
|
||||
</body>
|
||||
</html>
|
||||
+3
-2
@@ -8,6 +8,7 @@ export const ActionType = {
|
||||
CLEAR_PROXY: 'clear_proxy',
|
||||
INJECT_SCRIPT: 'yakit_inject_script',
|
||||
TO_EXTENSION_PAGE: "yakit_to_extension_page",
|
||||
BADGE_COUNT: "yakit_badge",
|
||||
}
|
||||
|
||||
export class WebSocketManager {
|
||||
@@ -22,7 +23,7 @@ export class WebSocketManager {
|
||||
|
||||
this.socket.onopen = () => {
|
||||
chrome.runtime.sendMessage({action: ActionType.STATUS, connected: true, port: port});
|
||||
// this.startHeartbeat();
|
||||
this.startHeartbeat();
|
||||
};
|
||||
|
||||
this.socket.onmessage = (event) => {
|
||||
@@ -66,7 +67,7 @@ export class WebSocketManager {
|
||||
}
|
||||
|
||||
startHeartbeat() {
|
||||
this.intervalId = setInterval(() => this.heartbeat(), 3000);
|
||||
this.intervalId = setInterval(() => this.heartbeat(), 25000);
|
||||
}
|
||||
|
||||
stopHeartbeat() {
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
export const ProxyActionType = {
|
||||
SET_PROXY_CONFIG: "SET_PROXY_CONFIG",
|
||||
CLEAR_PROXY_CONFIG: "CLEAR_PROXY_CONFIG",
|
||||
GET_PROXY_STATUS: "GET_PROXY_STATUS"
|
||||
};
|
||||
Reference in New Issue
Block a user