mirror of
https://github.com/SickleSec/SnowEyes.git
synced 2026-10-24 17:04:31 +00:00
v0.2.1
This commit is contained in:
1 parent
8c528c18c8
commit
c72f580320
6 files changed
+451
-613
No files matched your search
@@ -1,8 +1,28 @@
|
||||
// 统一的扫描器配置
|
||||
const SCANNER_CONFIG = {
|
||||
// API 相关配置 - 只保留正则表达式
|
||||
// 白名单配置
|
||||
WHITELIST: [
|
||||
'github.com',
|
||||
'stackoverflow.com',
|
||||
'npmjs.com',
|
||||
'google.com',
|
||||
'youtube.com',
|
||||
'microsoft.com',
|
||||
'apple.com',
|
||||
'mozilla.org',
|
||||
'cdn.jsdelivr.net',
|
||||
'cdnjs.cloudflare.com',
|
||||
'unpkg.com',
|
||||
'jquery.com',
|
||||
'bootstrapcdn.com',
|
||||
'fontawesome.com'
|
||||
],
|
||||
|
||||
// API 相关配置
|
||||
API: {
|
||||
PATTERN: /['"](?:\/|\.\.\/|\.\/)[^\/\>\< \)\(\{\}\,\'\"\\]([^\>\< \)\(\{\}\,\'\"\\])*?[\'"]/g
|
||||
PATTERN: /['"](?:\/|\.\.\/|\.\/)[^\/\>\< \)\(\{\}\,\'\"\\]([^\>\< \)\(\{\}\,\'\"\\])*?[\'"]/g,
|
||||
// 静态文件后缀
|
||||
STATIC_FILE_PATTERN: /\.(js|css|ico|png|webp|jpg|jpeg|gif|svg|woff|woff2|ttf|eot|map|json)$/i
|
||||
},
|
||||
|
||||
// 域名相关配置
|
||||
|
||||
+38
-15
@@ -26,6 +26,7 @@ const waitForDependencies = () => {
|
||||
const latestResults = {
|
||||
domains: new Set(), // 域名结果集
|
||||
apis: new Set(), // API 结果集
|
||||
staticFiles: new Set(), // 静态文件结果集
|
||||
ips: new Set(), // IP 地址结果集
|
||||
internalIps: new Set(), // 内网 IP 结果集
|
||||
phones: new Set(), // 手机号结果集
|
||||
@@ -292,12 +293,27 @@ function scanSources(sources) {
|
||||
sendUpdate();
|
||||
}
|
||||
|
||||
// 检查域名是否在白名单中
|
||||
function isInWhitelist(hostname) {
|
||||
return SCANNER_CONFIG.WHITELIST.some(domain => {
|
||||
// 完全匹配或者是子域名
|
||||
return hostname === domain || hostname.endsWith('.' + domain);
|
||||
});
|
||||
}
|
||||
|
||||
// 初始化扫描
|
||||
async function initScan() {
|
||||
try {
|
||||
await waitForDependencies();
|
||||
window.logger.info('开始扫描...');
|
||||
|
||||
// 检查当前域名是否在白名单中
|
||||
const currentHostname = window.location.hostname.toLowerCase();
|
||||
if (isInWhitelist(currentHostname)) {
|
||||
window.logger.info('当前域名在白名单中,跳过扫描');
|
||||
return;
|
||||
}
|
||||
|
||||
// 清空之前的结果
|
||||
Object.keys(latestResults).forEach(key => {
|
||||
if (key === 'hashes') {
|
||||
@@ -447,11 +463,23 @@ async function collectAndScanResources() {
|
||||
// 监听来自 popup 的消息
|
||||
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
||||
if (request.type === 'GET_RESULTS') {
|
||||
// 检查是否在白名单中
|
||||
const currentHostname = window.location.hostname.toLowerCase();
|
||||
if (isInWhitelist(currentHostname)) {
|
||||
sendResponse('WHITELISTED');
|
||||
return;
|
||||
}
|
||||
// 返回当前的扫描结果
|
||||
sendResponse(Object.fromEntries(
|
||||
Object.entries(latestResults).map(([key, value]) => [key, Array.from(value)])
|
||||
));
|
||||
} else if (request.type === 'REFRESH_SCAN') {
|
||||
// 检查是否在白名单中
|
||||
const currentHostname = window.location.hostname.toLowerCase();
|
||||
if (isInWhitelist(currentHostname)) {
|
||||
sendResponse('WHITELISTED');
|
||||
return;
|
||||
}
|
||||
// 重新执行扫描
|
||||
initScan().then(() => {
|
||||
sendResponse(Object.fromEntries(
|
||||
@@ -462,23 +490,18 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
||||
} else if (request.type === 'GET_CONFIG') {
|
||||
// 返回配置信息,将正则表达式转换为字符串
|
||||
const config = {
|
||||
WHITELIST: SCANNER_CONFIG.WHITELIST,
|
||||
API: {
|
||||
PATTERN: SCANNER_CONFIG.API.PATTERN.toString()
|
||||
PATTERN: SCANNER_CONFIG.API.PATTERN.toString(),
|
||||
STATIC_FILE_PATTERN: SCANNER_CONFIG.API.STATIC_FILE_PATTERN.toString()
|
||||
},
|
||||
PATTERNS: {
|
||||
DOMAIN: SCANNER_CONFIG.PATTERNS.DOMAIN.toString(),
|
||||
IP: SCANNER_CONFIG.PATTERNS.IP.toString(),
|
||||
PHONE: SCANNER_CONFIG.PATTERNS.PHONE.toString(),
|
||||
EMAIL: SCANNER_CONFIG.PATTERNS.EMAIL.toString(),
|
||||
IDCARD: SCANNER_CONFIG.PATTERNS.IDCARD.toString(),
|
||||
URL: SCANNER_CONFIG.PATTERNS.URL.toString(),
|
||||
JWT: SCANNER_CONFIG.PATTERNS.JWT.toString(),
|
||||
AWS_KEY: SCANNER_CONFIG.PATTERNS.AWS_KEY.toString(),
|
||||
HASH: {
|
||||
MD5: SCANNER_CONFIG.PATTERNS.HASH.MD5.toString(),
|
||||
SHA1: SCANNER_CONFIG.PATTERNS.HASH.SHA1.toString(),
|
||||
SHA256: SCANNER_CONFIG.PATTERNS.HASH.SHA256.toString()
|
||||
}
|
||||
DOMAIN: {
|
||||
BLACKLIST: SCANNER_CONFIG.DOMAIN.BLACKLIST,
|
||||
SPECIAL_DOMAINS: SCANNER_CONFIG.DOMAIN.SPECIAL_DOMAINS
|
||||
},
|
||||
IP: {
|
||||
PRIVATE_RANGES: SCANNER_CONFIG.IP.PRIVATE_RANGES.map(pattern => pattern.toString()),
|
||||
SPECIAL_RANGES: SCANNER_CONFIG.IP.SPECIAL_RANGES.map(pattern => pattern.toString())
|
||||
}
|
||||
};
|
||||
sendResponse({ config });
|
||||
|
||||
@@ -6,8 +6,12 @@ const SCANNER_FILTER = {
|
||||
// 去除首尾的引号
|
||||
match = match.slice(1, -1);
|
||||
|
||||
// 只添加到结果集
|
||||
resultsSet?.apis?.add(match);
|
||||
// 检查是否是静态文件
|
||||
if (SCANNER_CONFIG.API.STATIC_FILE_PATTERN.test(match)) {
|
||||
resultsSet?.staticFiles?.add(match);
|
||||
} else {
|
||||
resultsSet?.apis?.add(match);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
})(),
|
||||
|
||||
+222
-188
@@ -1,39 +1,68 @@
|
||||
/* 基础页面布局 */
|
||||
/* 基础样式 */
|
||||
body {
|
||||
width: 400px;
|
||||
height: 600px;
|
||||
margin: 0;
|
||||
font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
|
||||
padding: 0;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
background: #fff;
|
||||
color: #333;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 导航栏样式 */
|
||||
.nav {
|
||||
.nav-bar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 12px 16px;
|
||||
padding: 0;
|
||||
border-bottom: 1px solid #e9ecef;
|
||||
background: #fff;
|
||||
border-bottom: 1px solid #eee;
|
||||
height: 40px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* 导航栏标题 */
|
||||
.nav-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #2c2c2c;
|
||||
.nav-left {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.nav-right {
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.nav-tab {
|
||||
padding: 10px 20px;
|
||||
border: none;
|
||||
background: none;
|
||||
color: #495057;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.nav-tab.active {
|
||||
color: #228be6;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.nav-tab.active::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: -1px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 2px;
|
||||
background: #228be6;
|
||||
}
|
||||
|
||||
/* 刷新按钮样式 */
|
||||
.refresh-btn {
|
||||
padding: 4px 12px;
|
||||
font-size: 13px;
|
||||
padding: 6px 12px;
|
||||
color: #5c7cfa;
|
||||
background: #edf2ff;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 13px;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
@@ -41,138 +70,204 @@ body {
|
||||
background: #dbe4ff;
|
||||
}
|
||||
|
||||
/* 主容器样式 */
|
||||
.container {
|
||||
padding: 8px 16px 12px;
|
||||
height: calc(100% - 50px);
|
||||
/* 页面容器样式 */
|
||||
.page {
|
||||
height: calc(100vh - 40px);
|
||||
overflow-y: auto;
|
||||
padding: 10px 10px 10px 12px;
|
||||
width: 400px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* 自定义滚动条样式 */
|
||||
.container::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
.page.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.container::-webkit-scrollbar-track {
|
||||
background: #f1f3f5;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.container::-webkit-scrollbar-thumb {
|
||||
background: #dee2e6;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.container::-webkit-scrollbar-thumb:hover {
|
||||
background: #ced4da;
|
||||
/* 内容容器样式 */
|
||||
.container {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* 结果区域样式 */
|
||||
.section {
|
||||
margin-bottom: 12px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
/* 结果区域标题栏 */
|
||||
.section-header {
|
||||
margin-bottom: 6px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
/* 标题文本样式 */
|
||||
.title {
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
color: #495057;
|
||||
letter-spacing: 0.3px;
|
||||
}
|
||||
|
||||
/* 结果数量样式 */
|
||||
.count {
|
||||
font-size: 13px;
|
||||
color: #868e96;
|
||||
margin-left: 2px;
|
||||
font-weight: normal;
|
||||
letter-spacing: 0.2px;
|
||||
}
|
||||
|
||||
/* 结果内容区域 */
|
||||
.section-content {
|
||||
background: #f8f9fa;
|
||||
border-radius: 4px;
|
||||
padding: 8px;
|
||||
display: block;
|
||||
padding: 6px 10px 6px 6px;
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
/* 结果区域滚动条样式 */
|
||||
.section-content::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
}
|
||||
|
||||
.section-content::-webkit-scrollbar-track {
|
||||
background: #f1f3f5;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.section-content::-webkit-scrollbar-thumb {
|
||||
background: #dee2e6;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.section-content::-webkit-scrollbar-thumb:hover {
|
||||
background: #ced4da;
|
||||
}
|
||||
|
||||
/* 结果项包装器 */
|
||||
.content-wrapper {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
padding: 4px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* 单个结果项样式 */
|
||||
/* 结果项样式 */
|
||||
.item {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 6px 12px;
|
||||
padding: 4px 10px;
|
||||
background: #fff;
|
||||
border-radius: 4px;
|
||||
font-size: 13px;
|
||||
color: #495057;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
box-shadow: 0 1px 2px rgba(0,0,0,0.03);
|
||||
transition: all 0.15s ease;
|
||||
width: fit-content;
|
||||
min-width: unset;
|
||||
max-width: calc(100% - 16px);
|
||||
white-space: normal;
|
||||
margin: 3px;
|
||||
box-shadow: 0 1px 2px rgba(0,0,0,0.05);
|
||||
}
|
||||
|
||||
.item:hover {
|
||||
background: #f8f9fa;
|
||||
}
|
||||
|
||||
/* 配置页面样式 */
|
||||
.config-section {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.config-group {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.config-group h3 {
|
||||
font-size: 14px;
|
||||
color: #495057;
|
||||
margin-bottom: 8px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.config-content {
|
||||
background: #f8f9fa;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
color: #495057;
|
||||
word-break: break-all;
|
||||
margin-right: 8px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
/* 白名单项样式 */
|
||||
.whitelist {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.whitelist-item {
|
||||
background: #e9ecef;
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
color: #495057;
|
||||
}
|
||||
|
||||
/* 配置项样式 */
|
||||
.config-item {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
/* 添加悬停效果 */
|
||||
.item:hover {
|
||||
background: #f8f9fa;
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.05);
|
||||
.config-item:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* 点击效果 */
|
||||
.item:active {
|
||||
transform: scale(0.98);
|
||||
.config-label {
|
||||
font-weight: 500;
|
||||
margin-bottom: 4px;
|
||||
color: #495057;
|
||||
}
|
||||
|
||||
.config-value {
|
||||
font-family: monospace;
|
||||
word-break: break-all;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
/* 黑名单项样式 */
|
||||
.blacklist {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.blacklist-item {
|
||||
background: #f1f3f5;
|
||||
padding: 3px 6px;
|
||||
border-radius: 3px;
|
||||
font-size: 11px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* 状态提示样式 */
|
||||
.loading, .error {
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.error {
|
||||
color: #ff6b6b;
|
||||
}
|
||||
|
||||
/* 白名单提示样式 */
|
||||
.whitelisted {
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
color: #2b8a3e;
|
||||
background: #ebfbee;
|
||||
border-radius: 4px;
|
||||
margin: 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* 复制提示样式 */
|
||||
.copy-tooltip {
|
||||
position: fixed;
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
color: white;
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
z-index: 1001;
|
||||
}
|
||||
|
||||
/* 计数样式 */
|
||||
.count {
|
||||
font-size: 13px;
|
||||
color: #868e96;
|
||||
margin-left: 4px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
/* 无结果提示样式 */
|
||||
.no-results {
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
color: #868e96;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* 内容包装器样式 */
|
||||
.content-wrapper {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
/* 为不同类型的结果添加左侧彩色边框 */
|
||||
@@ -182,7 +277,7 @@ body {
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 2.5px;
|
||||
width: 3px;
|
||||
border-radius: 4px 0 0 4px;
|
||||
}
|
||||
|
||||
@@ -195,12 +290,12 @@ body {
|
||||
background: #b197fc; /* 紫色 - API */
|
||||
}
|
||||
|
||||
.ip-list .item::before {
|
||||
background: #ffd43b; /* 黄色 - IP */
|
||||
.static-list .item::before {
|
||||
background: #20c997; /* 青绿色 - 静态文件 */
|
||||
}
|
||||
|
||||
.port-list .item::before {
|
||||
background: #868e96; /* 灰色 - 端口 */
|
||||
.ip-list .item::before {
|
||||
background: #ffd43b; /* 黄色 - IP */
|
||||
}
|
||||
|
||||
.phone-list .item::before {
|
||||
@@ -219,14 +314,6 @@ body {
|
||||
background: #4dabf7; /* 浅蓝 - URL */
|
||||
}
|
||||
|
||||
.btc-list .item::before {
|
||||
background: #fab005; /* 金色 - 比特币地址 */
|
||||
}
|
||||
|
||||
.eth-list .item::before {
|
||||
background: #7950f2; /* 深紫 - 以太坊地址 */
|
||||
}
|
||||
|
||||
.jwt-list .item::before {
|
||||
background: #ff922b; /* 橙色 - JWT Token */
|
||||
}
|
||||
@@ -247,92 +334,39 @@ body {
|
||||
background: #82c91e; /* 黄绿色 - SHA256哈希 */
|
||||
}
|
||||
|
||||
/* 复制按钮样式 */
|
||||
.copy-all-btn {
|
||||
padding: 4px;
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
color: #868e96;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 4px;
|
||||
transition: all 0.2s;
|
||||
position: relative;
|
||||
/* 自定义滚动条样式 */
|
||||
::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
}
|
||||
|
||||
.copy-all-btn:hover {
|
||||
background: #f1f3f5;
|
||||
color: #495057;
|
||||
::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.copy-all-btn:active {
|
||||
transform: translateY(1px);
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: #e9ecef;
|
||||
border-radius: 3px;
|
||||
transition: background 0.2s;
|
||||
}
|
||||
|
||||
/* 复制提示动画 */
|
||||
@keyframes fadeInOut {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translate(-50%, -40%);
|
||||
}
|
||||
20% {
|
||||
opacity: 1;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
80% {
|
||||
opacity: 1;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: translate(-50%, -60%);
|
||||
}
|
||||
/* 当鼠标悬停在页面上时,滚动条变深 */
|
||||
.page:hover::-webkit-scrollbar-thumb {
|
||||
background: #adb5bd;
|
||||
}
|
||||
|
||||
/* 复制提示样式 */
|
||||
.copy-tooltip {
|
||||
position: fixed;
|
||||
background: rgba(33, 37, 41, 0.9);
|
||||
color: white;
|
||||
padding: 6px 12px;
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
pointer-events: none;
|
||||
white-space: nowrap;
|
||||
z-index: 1000;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
animation: fadeInOut 1s ease;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
|
||||
/* 结果区域的滚动条样式 */
|
||||
.section-content::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
}
|
||||
|
||||
/* 状态提示样式 */
|
||||
.loading, .error, .no-results {
|
||||
padding: 8px;
|
||||
text-align: center;
|
||||
color: #868e96;
|
||||
font-style: italic;
|
||||
font-size: 13px;
|
||||
.section-content::-webkit-scrollbar-thumb {
|
||||
background: #e9ecef;
|
||||
}
|
||||
|
||||
.error {
|
||||
color: #ff6b6b;
|
||||
}
|
||||
|
||||
/* 优化标签间距 */
|
||||
.content-wrapper {
|
||||
gap: unset;
|
||||
}
|
||||
|
||||
/* 移除结果项间的分隔符 */
|
||||
.item::after {
|
||||
content: none;
|
||||
}
|
||||
|
||||
.item:last-child::after {
|
||||
content: none;
|
||||
/* 当鼠标悬停在结果区域时,滚动条变深 */
|
||||
.section-content:hover::-webkit-scrollbar-thumb {
|
||||
background: #adb5bd;
|
||||
}
|
||||
|
||||
+14
-238
@@ -2,219 +2,24 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<!-- 引入样式文件 -->
|
||||
<link rel="stylesheet" href="highlight.css">
|
||||
<style>
|
||||
/* 基础样式设置 */
|
||||
body {
|
||||
width: 400px; /* 固定弹出窗口宽度 */
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
background: #f8f9fa;
|
||||
}
|
||||
|
||||
/* 主容器样式 */
|
||||
.container {
|
||||
width: 400px; /* 与body同宽 */
|
||||
max-height: 600px; /* 最大高度限制 */
|
||||
overflow-y: auto; /* 内容超出时显示滚动条 */
|
||||
padding: 15px;
|
||||
margin: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* 结果区域样式 */
|
||||
.result-section {
|
||||
width: 370px; /* 考虑内边距的容器宽度 */
|
||||
margin: 10px 0;
|
||||
padding: 10px;
|
||||
border: 1px solid #8f8c8c;
|
||||
border-radius: 4px;
|
||||
background: #f2eeee;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* 结果列表样式 */
|
||||
.result-list {
|
||||
width: 350px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* 结果项样式 */
|
||||
.result-item {
|
||||
width: 350px;
|
||||
padding: 8px;
|
||||
border-bottom: 1px solid #eee;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* 结果项包装器样式 */
|
||||
.result-wrapper {
|
||||
width: 334px;
|
||||
position: relative;
|
||||
padding-right: 30px; /* 为复制按钮预留空间 */
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* URL 内容样式 */
|
||||
.url-content {
|
||||
width: 304px;
|
||||
display: inline-block;
|
||||
padding: 8px;
|
||||
margin: 0;
|
||||
background: #f5f5f5;
|
||||
border-radius: 3px;
|
||||
font-family: monospace;
|
||||
font-size: 12px;
|
||||
line-height: 1.4;
|
||||
overflow-wrap: anywhere;
|
||||
word-break: break-all;
|
||||
white-space: pre-wrap;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
/* 复制按钮样式 */
|
||||
.copy-btn {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 8px;
|
||||
padding: 4px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
opacity: 0.6;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
|
||||
.copy-btn:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* 导航栏样式 */
|
||||
.nav {
|
||||
width: 400px;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
background: white;
|
||||
z-index: 1000;
|
||||
padding: 10px 15px;
|
||||
border-bottom: 1px solid #eee;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* 标题样式 */
|
||||
h3 {
|
||||
margin: 0 0 10px 0;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
/* 按钮通用样式 */
|
||||
button {
|
||||
padding: 6px 12px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
background: #fff;
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
/* 状态提示样式 */
|
||||
.loading, .error {
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* 复制提示工具提示样式 */
|
||||
.copy-tooltip {
|
||||
position: fixed;
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
color: white;
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
z-index: 1001;
|
||||
}
|
||||
|
||||
/* 导航栏样式 */
|
||||
.nav-tabs {
|
||||
display: flex;
|
||||
background: #fff;
|
||||
border-bottom: 1px solid #ddd;
|
||||
padding: 0;
|
||||
height: 600px;
|
||||
margin: 0;
|
||||
height: 40px;
|
||||
justify-content: space-between; /* 两端对齐 */
|
||||
align-items: center; /* 垂直居中 */
|
||||
}
|
||||
|
||||
.nav-left {
|
||||
display: flex; /* 左侧标签容器 */
|
||||
}
|
||||
|
||||
.nav-right {
|
||||
padding-right: 10px; /* 右侧按钮容器 */
|
||||
}
|
||||
|
||||
.nav-tab {
|
||||
padding: 10px 20px;
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
background: none;
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.nav-tab.active {
|
||||
color: #1a73e8;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.nav-tab.active::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: -1px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 2px;
|
||||
background: #1a73e8;
|
||||
}
|
||||
|
||||
/* 刷新按钮样式 */
|
||||
.refresh-btn {
|
||||
padding: 6px 12px;
|
||||
color: #5c7cfa;
|
||||
background: #edf2ff;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 13px;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.refresh-btn:hover {
|
||||
background: #dbe4ff;
|
||||
padding: 0;
|
||||
font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
|
||||
background: #fff;
|
||||
color: #333;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* 页面容器样式 */
|
||||
.page {
|
||||
display: none;
|
||||
height: calc(100vh - 40px); /* 减去导航栏高度 */
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
@@ -222,41 +27,16 @@
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* 配置页面样式 */
|
||||
.config-page {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.config-section {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.config-section h4 {
|
||||
margin: 0 0 10px 0;
|
||||
color: #333;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.config-item {
|
||||
background: #f5f5f5;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 10px;
|
||||
font-family: monospace;
|
||||
font-size: 12px;
|
||||
word-break: break-all;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
/* 内容容器样式 */
|
||||
.container {
|
||||
padding: 15px;
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- 导航栏 -->
|
||||
<div class="nav-tabs">
|
||||
<div class="nav-bar">
|
||||
<div class="nav-left">
|
||||
<button class="nav-tab active" data-page="scanner">信息搜集</button>
|
||||
<button class="nav-tab" data-page="config">配置</button>
|
||||
@@ -266,18 +46,14 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 信息搜集页面 -->
|
||||
<!-- 扫描页面 -->
|
||||
<div class="page scanner-page active">
|
||||
<div class="container">
|
||||
<!-- 内容将由 JavaScript 动态生成 -->
|
||||
</div>
|
||||
<div class="container"></div>
|
||||
</div>
|
||||
|
||||
<!-- 配置页面 -->
|
||||
<div class="page config-page">
|
||||
<div class="config-container">
|
||||
<!-- 配置内容将由 JavaScript 动态生成 -->
|
||||
</div>
|
||||
<div class="container"></div>
|
||||
</div>
|
||||
|
||||
<script src="popup.js"></script>
|
||||
|
||||
+149
-168
@@ -7,10 +7,7 @@ function switchPage(pageName) {
|
||||
|
||||
// 更新页面显示状态
|
||||
document.querySelectorAll('.page').forEach(page => {
|
||||
const isScanner = page.classList.contains('scanner-page');
|
||||
const isConfig = page.classList.contains('config-page');
|
||||
|
||||
if ((isScanner && pageName === 'scanner') || (isConfig && pageName === 'config')) {
|
||||
if (page.classList.contains(`${pageName}-page`)) {
|
||||
page.classList.add('active');
|
||||
} else {
|
||||
page.classList.remove('active');
|
||||
@@ -25,88 +22,91 @@ function switchPage(pageName) {
|
||||
|
||||
// 显示配置信息
|
||||
function displayConfig() {
|
||||
const configContainer = document.querySelector('.config-container');
|
||||
configContainer.innerHTML = '<div class="loading">加载配置中...</div>';
|
||||
|
||||
// 获取当前标签页
|
||||
const container = document.querySelector('.config-page .container');
|
||||
container.innerHTML = '<div class="loading">加载配置中...</div>';
|
||||
|
||||
chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
|
||||
if (tabs[0]) {
|
||||
// 向content script发送消息获取配置
|
||||
chrome.tabs.sendMessage(tabs[0].id, {type: 'GET_CONFIG'}, response => {
|
||||
if (response && response.config) {
|
||||
const config = response.config;
|
||||
|
||||
// 构建配置页面内容
|
||||
let html = '';
|
||||
|
||||
// API 配置
|
||||
html += `
|
||||
<div class="config-section">
|
||||
<h4>API 路径匹配</h4>
|
||||
<div class="config-item">${config.API.PATTERN}</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// 域名配置
|
||||
html += `
|
||||
<div class="config-section">
|
||||
<h4>域名匹配</h4>
|
||||
<div class="config-item">${config.PATTERNS.DOMAIN}</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// IP 配置
|
||||
html += `
|
||||
<div class="config-section">
|
||||
<h4>IP 地址匹配</h4>
|
||||
<div class="config-item">${config.PATTERNS.IP}</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// 其他敏感信息匹配
|
||||
html += `
|
||||
<div class="config-section">
|
||||
<h4>手机号码匹配</h4>
|
||||
<div class="config-item">${config.PATTERNS.PHONE}</div>
|
||||
</div>
|
||||
|
||||
<div class="config-section">
|
||||
<h4>邮箱匹配</h4>
|
||||
<div class="config-item">${config.PATTERNS.EMAIL}</div>
|
||||
</div>
|
||||
|
||||
<div class="config-section">
|
||||
<h4>身份证号匹配</h4>
|
||||
<div class="config-item">${config.PATTERNS.IDCARD}</div>
|
||||
</div>
|
||||
|
||||
<div class="config-section">
|
||||
<h4>URL 匹配</h4>
|
||||
<div class="config-item">${config.PATTERNS.URL}</div>
|
||||
</div>
|
||||
|
||||
<div class="config-section">
|
||||
<h4>JWT Token 匹配</h4>
|
||||
<div class="config-item">${config.PATTERNS.JWT}</div>
|
||||
</div>
|
||||
|
||||
<div class="config-section">
|
||||
<h4>AWS Key 匹配</h4>
|
||||
<div class="config-item">${config.PATTERNS.AWS_KEY}</div>
|
||||
</div>
|
||||
|
||||
<div class="config-section">
|
||||
<h4>哈希值匹配</h4>
|
||||
<div class="config-item">MD5: ${config.PATTERNS.HASH.MD5}</div>
|
||||
<div class="config-item">SHA1: ${config.PATTERNS.HASH.SHA1}</div>
|
||||
<div class="config-item">SHA256: ${config.PATTERNS.HASH.SHA256}</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
configContainer.innerHTML = html;
|
||||
} else {
|
||||
configContainer.innerHTML = '<div class="error">无法加载配置</div>';
|
||||
if (chrome.runtime.lastError) {
|
||||
container.innerHTML = '<div class="error">无法获取配置信息</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
const { config } = response;
|
||||
if (!config) {
|
||||
container.innerHTML = '<div class="error">配置信息为空</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
// 构建配置展示HTML
|
||||
let html = '<div class="config-section">';
|
||||
|
||||
// 添加白名单展示
|
||||
html += `
|
||||
<div class="config-group">
|
||||
<h3>白名单域名</h3>
|
||||
<div class="config-content whitelist">
|
||||
${config.WHITELIST.map(domain => `<div class="whitelist-item">${domain}</div>`).join('')}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// API 配置展示
|
||||
html += `
|
||||
<div class="config-group">
|
||||
<h3>API 配置</h3>
|
||||
<div class="config-content">
|
||||
<div class="config-item">
|
||||
<div class="config-label">路径匹配模式:</div>
|
||||
<div class="config-value">${config.API.PATTERN}</div>
|
||||
</div>
|
||||
<div class="config-item">
|
||||
<div class="config-label">静态文件模式:</div>
|
||||
<div class="config-value">${config.API.STATIC_FILE_PATTERN}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// 域名配置展示
|
||||
html += `
|
||||
<div class="config-group">
|
||||
<h3>域名配置</h3>
|
||||
<div class="config-content">
|
||||
<div class="config-item">
|
||||
<div class="config-label">黑名单:</div>
|
||||
<div class="config-value blacklist">
|
||||
${config.DOMAIN.BLACKLIST.map(domain => `<div class="blacklist-item">${domain}</div>`).join('')}
|
||||
</div>
|
||||
</div>
|
||||
<div class="config-item">
|
||||
<div class="config-label">特殊域名:</div>
|
||||
<div class="config-value">${config.DOMAIN.SPECIAL_DOMAINS.join(', ')}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// IP 配置展示
|
||||
html += `
|
||||
<div class="config-group">
|
||||
<h3>IP 配置</h3>
|
||||
<div class="config-content">
|
||||
<div class="config-item">
|
||||
<div class="config-label">内网 IP 范围:</div>
|
||||
<div class="config-value">${config.IP.PRIVATE_RANGES.join('<br>')}</div>
|
||||
</div>
|
||||
<div class="config-item">
|
||||
<div class="config-label">特殊 IP 范围:</div>
|
||||
<div class="config-value">${config.IP.SPECIAL_RANGES.join('<br>')}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
html += '</div>';
|
||||
container.innerHTML = html;
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -118,89 +118,56 @@ function displayResults(results) {
|
||||
const sections = [
|
||||
{ id: 'domain-list', data: results.domains, title: '域名' },
|
||||
{ id: 'api-list', data: results.apis, title: 'API接口' },
|
||||
{ id: 'static-list', data: results.staticFiles, title: '静态文件' },
|
||||
{ id: 'ip-list', data: results.ips, title: 'IP地址' },
|
||||
{ id: 'port-list', data: results.ports, title: '端口号' },
|
||||
{ id: 'phone-list', data: results.phones, title: '手机号码' },
|
||||
{ id: 'email-list', data: results.emails, title: '邮箱' },
|
||||
{ id: 'idcard-list', data: results.idcards, title: '身份证号' },
|
||||
{ id: 'url-list', data: results.urls, title: 'URL' },
|
||||
{ id: 'jwt-list', data: results.jwts, title: 'JWT Token' },
|
||||
{ id: 'aws-list', data: results.awsKeys, title: 'AWS Key' },
|
||||
{ id: 'hash-md5-list', data: results.hashes.md5, title: 'MD5哈希' },
|
||||
{ id: 'hash-sha1-list', data: results.hashes.sha1, title: 'SHA1哈希' },
|
||||
{ id: 'hash-sha256-list', data: results.hashes.sha256, title: 'SHA256哈希' }
|
||||
{ id: 'hash-md5-list', data: results.hashes?.md5, title: 'MD5哈希' },
|
||||
{ id: 'hash-sha1-list', data: results.hashes?.sha1, title: 'SHA1哈希' },
|
||||
{ id: 'hash-sha256-list', data: results.hashes?.sha256, title: 'SHA256哈希' }
|
||||
];
|
||||
|
||||
// 获取或创建容器
|
||||
const container = document.querySelector('.container');
|
||||
|
||||
// 获取容器
|
||||
const container = document.querySelector('.scanner-page .container');
|
||||
let html = '';
|
||||
|
||||
// 遍历所有部分
|
||||
sections.forEach(({ id, data, title }) => {
|
||||
// 如果数据存在且不为空
|
||||
if (data && data.length > 0) {
|
||||
// 检查section是否已存在
|
||||
let section = document.getElementById(`section-${id}`);
|
||||
if (!section) {
|
||||
// 如果section不存在,创建新的section
|
||||
section = document.createElement('div');
|
||||
section.className = 'section';
|
||||
section.id = `section-${id}`;
|
||||
section.innerHTML = `
|
||||
html += `
|
||||
<div class="section">
|
||||
<div class="section-header">
|
||||
<div>
|
||||
<span class="title">${title}</span><span class="count">(${data.length})</span>
|
||||
<span class="title">${title} <span class="count">(${data.length})</span></span>
|
||||
</div>
|
||||
<div class="section-content">
|
||||
<div class="content-wrapper ${id}">
|
||||
${Array.from(data).map(item => `
|
||||
<div class="item" title="${item}">
|
||||
${item}
|
||||
</div>
|
||||
`).join('')}
|
||||
</div>
|
||||
<button class="copy-all-btn" title="复制所有${title}">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M16 3H4C3.45 3 3 3.45 3 4V16C3 16.55 3.45 17 4 17H16C16.55 17 17 16.55 17 16V4C17 3.45 16.55 3 16 3ZM15 15H5V5H15V15Z" fill="currentColor"/>
|
||||
<path d="M20 7H18V19H6V21C6 21.55 6.45 22 7 22H20C20.55 22 21 21.55 21 21V8C21 7.45 20.55 7 20 7Z" fill="currentColor"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="section-content ${id}" id="${id}">
|
||||
<div class="content-wrapper"></div>
|
||||
</div>
|
||||
`;
|
||||
container.appendChild(section);
|
||||
|
||||
// 添加复制所有按钮功能
|
||||
section.querySelector('.copy-all-btn').addEventListener('click', () => {
|
||||
const allText = data.join('\n');
|
||||
copyText(allText, section.querySelector('.copy-all-btn'), '已复制全部');
|
||||
});
|
||||
} else {
|
||||
// 如果section已存在,更新计数
|
||||
section.querySelector('.count').textContent = `(${data.length})`;
|
||||
}
|
||||
|
||||
// 更新内容
|
||||
const contentWrapper = section.querySelector('.content-wrapper');
|
||||
const existingItems = new Set(Array.from(contentWrapper.children).map(el => el.getAttribute('data-full-text')));
|
||||
|
||||
// 添加新项
|
||||
data.forEach(item => {
|
||||
if (!existingItems.has(item)) {
|
||||
const itemDiv = document.createElement('div');
|
||||
itemDiv.className = 'item';
|
||||
itemDiv.setAttribute('data-full-text', item);
|
||||
itemDiv.title = item;
|
||||
itemDiv.textContent = item;
|
||||
|
||||
// 添加右键复制功能
|
||||
itemDiv.addEventListener('contextmenu', (e) => {
|
||||
e.preventDefault();
|
||||
copyText(item, itemDiv, '已复制');
|
||||
});
|
||||
|
||||
contentWrapper.appendChild(itemDiv);
|
||||
}
|
||||
});
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
});
|
||||
|
||||
// 移除loading状态
|
||||
const loading = container.querySelector('.loading');
|
||||
if (loading) {
|
||||
loading.remove();
|
||||
// 如果没有任何结果
|
||||
if (!html) {
|
||||
html = '<div class="no-results">未发现敏感信息</div>';
|
||||
}
|
||||
|
||||
// 更新容器内容
|
||||
container.innerHTML = html;
|
||||
|
||||
// 处理长文本
|
||||
handleLongText();
|
||||
}
|
||||
|
||||
// 显示复制成功的提示框
|
||||
@@ -249,6 +216,18 @@ function copyText(text, element, message) {
|
||||
|
||||
// 页面加载完成时的初始化
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
// 获取当前激活的页面
|
||||
const activePage = document.querySelector('.nav-tab.active').dataset.page;
|
||||
|
||||
// 初始化页面显示
|
||||
document.querySelectorAll('.page').forEach(page => {
|
||||
if (page.classList.contains(`${activePage}-page`)) {
|
||||
page.classList.add('active');
|
||||
} else {
|
||||
page.classList.remove('active');
|
||||
}
|
||||
});
|
||||
|
||||
// 添加导航标签点击事件
|
||||
document.querySelectorAll('.nav-tab').forEach(tab => {
|
||||
tab.addEventListener('click', () => {
|
||||
@@ -256,8 +235,28 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
});
|
||||
});
|
||||
|
||||
// 添加刷新按钮点击事件
|
||||
document.querySelector('.refresh-btn').addEventListener('click', () => {
|
||||
const container = document.querySelector('.scanner-page .container');
|
||||
container.innerHTML = '<div class="loading">正在扫描...</div>';
|
||||
|
||||
chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
|
||||
if (tabs[0]) {
|
||||
chrome.tabs.sendMessage(tabs[0].id, {type: 'REFRESH_SCAN'}, response => {
|
||||
if (chrome.runtime.lastError) {
|
||||
container.innerHTML = '<div class="error">无法连接到页面</div>';
|
||||
} else if (response === 'WHITELISTED') {
|
||||
container.innerHTML = '<div class="whitelisted">当前域名在白名单中,已跳过扫描</div>';
|
||||
} else if (response) {
|
||||
displayResults(response);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 初始化扫描页面
|
||||
const container = document.querySelector('.container');
|
||||
const container = document.querySelector('.scanner-page .container');
|
||||
container.innerHTML = '<div class="loading">正在扫描...</div>';
|
||||
|
||||
chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
|
||||
@@ -265,32 +264,14 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
chrome.tabs.sendMessage(tabs[0].id, {type: 'GET_RESULTS'}, response => {
|
||||
if (chrome.runtime.lastError) {
|
||||
container.innerHTML = '<div class="error">无法连接到页面</div>';
|
||||
} else if (response === 'WHITELISTED') {
|
||||
container.innerHTML = '<div class="whitelisted">当前域名在白名单中,已跳过扫描</div>';
|
||||
} else if (response) {
|
||||
displayResults(response);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener('resize', handleLongText);
|
||||
});
|
||||
|
||||
// 刷新按钮点击事件处理
|
||||
document.querySelector('.refresh-btn').addEventListener('click', () => {
|
||||
const container = document.querySelector('.container');
|
||||
// 显示加载状态
|
||||
container.innerHTML = '<div class="loading">正在扫描...</div>';
|
||||
|
||||
// 触发重新扫描
|
||||
chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
|
||||
if (tabs[0]) {
|
||||
chrome.tabs.sendMessage(tabs[0].id, {type: 'REFRESH_SCAN'}, response => {
|
||||
if (response) {
|
||||
displayResults(response);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 监听来自 content script 的消息
|
||||
|
||||
Reference in new issue
Block a user