311 lines
8.5 KiB
JavaScript
311 lines
8.5 KiB
JavaScript
// EShip Extension Content Script
|
|
// Injects into protected website to enforce auth and apply tools
|
|
|
|
(function() {
|
|
'use strict';
|
|
|
|
// State
|
|
let isAuthenticated = false;
|
|
let currentTools = [];
|
|
let blockedOverlay = null;
|
|
|
|
// Initialize on page load
|
|
init();
|
|
|
|
async function init() {
|
|
// Check auth status immediately
|
|
const authResponse = await sendMessage({ action: 'CHECK_AUTH' });
|
|
|
|
if (authResponse.success && authResponse.authenticated) {
|
|
isAuthenticated = true;
|
|
await loadAndApplyTools();
|
|
} else {
|
|
isAuthenticated = false;
|
|
showBlockedScreen();
|
|
}
|
|
|
|
// Listen for messages from service worker (settings updates)
|
|
chrome.runtime.onMessage.addListener(handleMessage);
|
|
}
|
|
|
|
// Send message to service worker
|
|
function sendMessage(message) {
|
|
return new Promise((resolve) => {
|
|
chrome.runtime.sendMessage(message, (response) => {
|
|
if (chrome.runtime.lastError) {
|
|
resolve({ success: false, error: chrome.runtime.lastError.message });
|
|
} else {
|
|
resolve(response || { success: false, error: 'No response' });
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
// Handle incoming messages
|
|
function handleMessage(request, sender, sendResponse) {
|
|
switch (request.action) {
|
|
case 'SETTINGS_UPDATED':
|
|
currentTools = request.tools;
|
|
applyTools();
|
|
sendResponse({ success: true });
|
|
break;
|
|
|
|
case 'AUTH_CHANGED':
|
|
if (request.authenticated) {
|
|
isAuthenticated = true;
|
|
hideBlockedScreen();
|
|
loadAndApplyTools();
|
|
} else {
|
|
isAuthenticated = false;
|
|
showBlockedScreen();
|
|
}
|
|
sendResponse({ success: true });
|
|
break;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// Show blocked screen when not authenticated
|
|
function showBlockedScreen() {
|
|
// Wait for DOM to be ready
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', createBlockedOverlay);
|
|
} else {
|
|
createBlockedOverlay();
|
|
}
|
|
}
|
|
|
|
function createBlockedOverlay() {
|
|
// Remove existing overlay if any
|
|
hideBlockedScreen();
|
|
|
|
// Create overlay
|
|
blockedOverlay = document.createElement('div');
|
|
blockedOverlay.id = 'eship-blocked-overlay';
|
|
blockedOverlay.innerHTML = `
|
|
<style>
|
|
#eship-blocked-overlay {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
z-index: 999999;
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
}
|
|
#eship-blocked-overlay .blocked-icon {
|
|
font-size: 64px;
|
|
margin-bottom: 24px;
|
|
}
|
|
#eship-blocked-overlay h1 {
|
|
color: #FD366E;
|
|
font-size: 28px;
|
|
margin: 0 0 16px 0;
|
|
font-weight: 600;
|
|
}
|
|
#eship-blocked-overlay p {
|
|
color: #9ca3af;
|
|
font-size: 16px;
|
|
margin: 0 0 32px 0;
|
|
text-align: center;
|
|
max-width: 400px;
|
|
line-height: 1.6;
|
|
}
|
|
#eship-blocked-overlay .instructions {
|
|
background: rgba(255, 255, 255, 0.05);
|
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
border-radius: 12px;
|
|
padding: 24px;
|
|
max-width: 400px;
|
|
}
|
|
#eship-blocked-overlay .instructions h2 {
|
|
color: #fff;
|
|
font-size: 14px;
|
|
margin: 0 0 16px 0;
|
|
text-transform: uppercase;
|
|
letter-spacing: 1px;
|
|
}
|
|
#eship-blocked-overlay .instructions ol {
|
|
color: #d1d5db;
|
|
font-size: 14px;
|
|
margin: 0;
|
|
padding-left: 20px;
|
|
line-height: 2;
|
|
}
|
|
#eship-blocked-overlay .instructions li {
|
|
margin-bottom: 4px;
|
|
}
|
|
</style>
|
|
<div class="blocked-icon">🔒</div>
|
|
<h1>Zugriff gesperrt</h1>
|
|
<p>Diese Website ist geschuetzt und erfordert eine Authentifizierung ueber die EShip Browser-Extension.</p>
|
|
<div class="instructions">
|
|
<h2>So melden Sie sich an:</h2>
|
|
<ol>
|
|
<li>Klicken Sie auf das EShip-Icon in der Browser-Toolbar</li>
|
|
<li>Geben Sie Ihre E-Mail und Passwort ein</li>
|
|
<li>Klicken Sie auf "Anmelden"</li>
|
|
<li>Die Seite wird automatisch freigeschaltet</li>
|
|
</ol>
|
|
</div>
|
|
`;
|
|
|
|
document.body.appendChild(blockedOverlay);
|
|
|
|
// Prevent scrolling on body
|
|
document.body.style.overflow = 'hidden';
|
|
}
|
|
|
|
// Hide blocked screen
|
|
function hideBlockedScreen() {
|
|
if (blockedOverlay) {
|
|
blockedOverlay.remove();
|
|
blockedOverlay = null;
|
|
document.body.style.overflow = '';
|
|
}
|
|
}
|
|
|
|
// Load and apply tool settings
|
|
async function loadAndApplyTools() {
|
|
const response = await sendMessage({ action: 'GET_SETTINGS' });
|
|
if (response.success) {
|
|
currentTools = response.tools;
|
|
applyTools();
|
|
}
|
|
}
|
|
|
|
// Apply all enabled tools
|
|
function applyTools() {
|
|
if (!isAuthenticated) return;
|
|
|
|
// Wait for DOM to be ready
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', () => executeTools());
|
|
} else {
|
|
executeTools();
|
|
}
|
|
}
|
|
|
|
function executeTools() {
|
|
currentTools.forEach(tool => {
|
|
if (tool.enabled) {
|
|
applyTool(tool);
|
|
} else {
|
|
removeTool(tool);
|
|
}
|
|
});
|
|
}
|
|
|
|
// Apply a specific tool
|
|
function applyTool(tool) {
|
|
switch (tool.id) {
|
|
case 'highlight_prices':
|
|
applyHighlightPrices(tool.settings);
|
|
break;
|
|
// Add more tools here as needed
|
|
default:
|
|
console.log('[EShip] Unknown tool:', tool.id);
|
|
}
|
|
}
|
|
|
|
// Remove a specific tool's effects
|
|
function removeTool(tool) {
|
|
switch (tool.id) {
|
|
case 'highlight_prices':
|
|
removeHighlightPrices(tool.settings);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// ============================================
|
|
// TOOL: Highlight Prices
|
|
// ============================================
|
|
|
|
function applyHighlightPrices(settings) {
|
|
const selector = settings.selector || '.price';
|
|
const borderColor = settings.borderColor || '#ff0000';
|
|
const borderWidth = settings.borderWidth || '2px';
|
|
|
|
// Add custom style if not exists
|
|
let styleEl = document.getElementById('eship-highlight-prices-style');
|
|
if (!styleEl) {
|
|
styleEl = document.createElement('style');
|
|
styleEl.id = 'eship-highlight-prices-style';
|
|
document.head.appendChild(styleEl);
|
|
}
|
|
|
|
styleEl.textContent = `
|
|
${selector} {
|
|
border: ${borderWidth} solid ${borderColor} !important;
|
|
box-shadow: 0 0 8px ${borderColor}40 !important;
|
|
border-radius: 4px !important;
|
|
padding: 2px 4px !important;
|
|
transition: all 0.2s ease !important;
|
|
}
|
|
`;
|
|
|
|
// Also add data attribute to track highlighted elements
|
|
document.querySelectorAll(selector).forEach(el => {
|
|
el.dataset.eshipHighlighted = 'true';
|
|
});
|
|
|
|
console.log('[EShip] Highlight Prices applied with selector:', selector);
|
|
}
|
|
|
|
function removeHighlightPrices(settings) {
|
|
// Remove style element
|
|
const styleEl = document.getElementById('eship-highlight-prices-style');
|
|
if (styleEl) {
|
|
styleEl.remove();
|
|
}
|
|
|
|
// Remove data attributes
|
|
document.querySelectorAll('[data-eship-highlighted]').forEach(el => {
|
|
delete el.dataset.eshipHighlighted;
|
|
});
|
|
|
|
console.log('[EShip] Highlight Prices removed');
|
|
}
|
|
|
|
// ============================================
|
|
// Mutation Observer for dynamic content
|
|
// ============================================
|
|
|
|
// Re-apply tools when new content is added
|
|
const observer = new MutationObserver((mutations) => {
|
|
if (!isAuthenticated) return;
|
|
|
|
let shouldReapply = false;
|
|
mutations.forEach(mutation => {
|
|
if (mutation.addedNodes.length > 0) {
|
|
shouldReapply = true;
|
|
}
|
|
});
|
|
|
|
if (shouldReapply) {
|
|
// Debounce reapplication
|
|
clearTimeout(observer.timeout);
|
|
observer.timeout = setTimeout(() => {
|
|
applyTools();
|
|
}, 100);
|
|
}
|
|
});
|
|
|
|
// Start observing once DOM is ready
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
observer.observe(document.body, { childList: true, subtree: true });
|
|
});
|
|
} else {
|
|
observer.observe(document.body, { childList: true, subtree: true });
|
|
}
|
|
|
|
})();
|