299 lines
8.7 KiB
JavaScript
299 lines
8.7 KiB
JavaScript
/**
|
|
* Quality Recticel Print Service - Background Script
|
|
* Handles communication between web pages and Windows print service
|
|
*/
|
|
|
|
// Configuration
|
|
const PRINT_SERVICE_URL = 'http://localhost:8765';
|
|
const SERVICE_CHECK_INTERVAL = 30000; // 30 seconds
|
|
|
|
// Service status
|
|
let serviceStatus = {
|
|
available: false,
|
|
lastCheck: null,
|
|
printers: []
|
|
};
|
|
|
|
// Initialize extension
|
|
chrome.runtime.onInstalled.addListener(() => {
|
|
console.log('Quality Recticel Print Service extension installed');
|
|
checkServiceStatus();
|
|
|
|
// Set up periodic service check
|
|
setInterval(checkServiceStatus, SERVICE_CHECK_INTERVAL);
|
|
});
|
|
|
|
// Handle messages from content scripts or web pages
|
|
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|
console.log('Background script received message:', message);
|
|
|
|
switch (message.action) {
|
|
case 'print_pdf':
|
|
handlePrintPDF(message.data).then(sendResponse);
|
|
return true; // Keep message channel open for async response
|
|
|
|
case 'silent_print':
|
|
handleSilentPrint(message.data).then(sendResponse);
|
|
return true;
|
|
|
|
case 'get_printers':
|
|
handleGetPrinters().then(sendResponse);
|
|
return true;
|
|
|
|
case 'check_service':
|
|
checkServiceStatus().then(sendResponse);
|
|
return true;
|
|
|
|
default:
|
|
sendResponse({ error: 'Unknown action', success: false });
|
|
}
|
|
});
|
|
|
|
// Handle external messages from web pages
|
|
chrome.runtime.onMessageExternal.addListener((message, sender, sendResponse) => {
|
|
console.log('External message received:', message, 'from:', sender);
|
|
|
|
// Verify sender origin for security
|
|
const allowedOrigins = [
|
|
'http://localhost:5000',
|
|
'http://localhost:8000',
|
|
'http://127.0.0.1:5000',
|
|
'http://127.0.0.1:8000'
|
|
];
|
|
|
|
if (!allowedOrigins.includes(sender.origin)) {
|
|
sendResponse({ error: 'Unauthorized origin', success: false });
|
|
return;
|
|
}
|
|
|
|
// Handle the message
|
|
switch (message.action) {
|
|
case 'print_pdf':
|
|
case 'silent_print':
|
|
handleSilentPrint(message.data).then(sendResponse);
|
|
return true;
|
|
|
|
case 'get_printers':
|
|
handleGetPrinters().then(sendResponse);
|
|
return true;
|
|
|
|
case 'ping':
|
|
sendResponse({
|
|
success: true,
|
|
service_available: serviceStatus.available,
|
|
extension_version: chrome.runtime.getManifest().version
|
|
});
|
|
break;
|
|
|
|
default:
|
|
sendResponse({ error: 'Unknown action', success: false });
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Check if the Windows print service is available
|
|
*/
|
|
async function checkServiceStatus() {
|
|
try {
|
|
const response = await fetch(`${PRINT_SERVICE_URL}/health`, {
|
|
method: 'GET',
|
|
timeout: 5000
|
|
});
|
|
|
|
if (response.ok) {
|
|
const data = await response.json();
|
|
serviceStatus.available = true;
|
|
serviceStatus.lastCheck = new Date();
|
|
|
|
console.log('Print service is available:', data);
|
|
|
|
// Update extension badge
|
|
chrome.action.setBadgeText({ text: '✓' });
|
|
chrome.action.setBadgeBackgroundColor({ color: '#28a745' });
|
|
|
|
return { success: true, status: data };
|
|
} else {
|
|
throw new Error(`Service returned status ${response.status}`);
|
|
}
|
|
|
|
} catch (error) {
|
|
console.warn('Print service not available:', error);
|
|
|
|
serviceStatus.available = false;
|
|
serviceStatus.lastCheck = new Date();
|
|
|
|
// Update extension badge
|
|
chrome.action.setBadgeText({ text: '✗' });
|
|
chrome.action.setBadgeBackgroundColor({ color: '#dc3545' });
|
|
|
|
return { success: false, error: error.message };
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle PDF printing request
|
|
*/
|
|
async function handlePrintPDF(printData) {
|
|
try {
|
|
if (!serviceStatus.available) {
|
|
await checkServiceStatus();
|
|
|
|
if (!serviceStatus.available) {
|
|
throw new Error('Print service is not available');
|
|
}
|
|
}
|
|
|
|
const response = await fetch(`${PRINT_SERVICE_URL}/print/pdf`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify(printData)
|
|
});
|
|
|
|
const result = await response.json();
|
|
|
|
if (response.ok) {
|
|
console.log('Print job completed:', result);
|
|
|
|
// Show notification
|
|
chrome.notifications.create({
|
|
type: 'basic',
|
|
iconUrl: 'icons/icon48.png',
|
|
title: 'Quality Recticel Print Service',
|
|
message: 'PDF printed successfully'
|
|
});
|
|
|
|
return { success: true, result };
|
|
} else {
|
|
throw new Error(result.error || 'Print job failed');
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error('Print PDF error:', error);
|
|
|
|
// Show error notification
|
|
chrome.notifications.create({
|
|
type: 'basic',
|
|
iconUrl: 'icons/icon48.png',
|
|
title: 'Quality Recticel Print Service',
|
|
message: `Print failed: ${error.message}`
|
|
});
|
|
|
|
return { success: false, error: error.message };
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle silent printing request
|
|
*/
|
|
async function handleSilentPrint(printData) {
|
|
try {
|
|
if (!serviceStatus.available) {
|
|
await checkServiceStatus();
|
|
|
|
if (!serviceStatus.available) {
|
|
// Try direct browser printing as fallback
|
|
return await handleDirectPrint(printData);
|
|
}
|
|
}
|
|
|
|
const response = await fetch(`${PRINT_SERVICE_URL}/print/silent`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify(printData)
|
|
});
|
|
|
|
const result = await response.json();
|
|
|
|
if (response.ok) {
|
|
console.log('Silent print completed:', result);
|
|
return { success: true, result };
|
|
} else {
|
|
throw new Error(result.error || 'Silent print failed');
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error('Silent print error:', error);
|
|
|
|
// Fallback to direct printing
|
|
return await handleDirectPrint(printData);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle direct browser printing (fallback)
|
|
*/
|
|
async function handleDirectPrint(printData) {
|
|
try {
|
|
// Create hidden iframe for printing
|
|
const printFrame = document.createElement('iframe');
|
|
printFrame.style.display = 'none';
|
|
printFrame.src = printData.pdf_url || 'data:application/pdf;base64,' + printData.pdf_data;
|
|
|
|
document.body.appendChild(printFrame);
|
|
|
|
// Wait for load and print
|
|
return new Promise((resolve) => {
|
|
printFrame.onload = () => {
|
|
setTimeout(() => {
|
|
printFrame.contentWindow.print();
|
|
document.body.removeChild(printFrame);
|
|
resolve({ success: true, method: 'browser_fallback' });
|
|
}, 1000);
|
|
};
|
|
});
|
|
|
|
} catch (error) {
|
|
console.error('Direct print error:', error);
|
|
return { success: false, error: error.message };
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get available printers
|
|
*/
|
|
async function handleGetPrinters() {
|
|
try {
|
|
if (!serviceStatus.available) {
|
|
await checkServiceStatus();
|
|
|
|
if (!serviceStatus.available) {
|
|
return {
|
|
success: false,
|
|
error: 'Print service not available',
|
|
printers: []
|
|
};
|
|
}
|
|
}
|
|
|
|
const response = await fetch(`${PRINT_SERVICE_URL}/printers`, {
|
|
method: 'GET'
|
|
});
|
|
|
|
const result = await response.json();
|
|
|
|
if (response.ok) {
|
|
serviceStatus.printers = result.printers || [];
|
|
return { success: true, printers: result.printers };
|
|
} else {
|
|
throw new Error(result.error || 'Failed to get printers');
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error('Get printers error:', error);
|
|
return { success: false, error: error.message, printers: [] };
|
|
}
|
|
}
|
|
|
|
// Export for testing
|
|
if (typeof module !== 'undefined' && module.exports) {
|
|
module.exports = {
|
|
checkServiceStatus,
|
|
handlePrintPDF,
|
|
handleSilentPrint,
|
|
handleGetPrinters
|
|
};
|
|
} |