mirror of
https://wiilab.wiimart.org/wiimart/wiimart-extension
synced 2025-09-02 19:41:00 +02:00
309 lines
14 KiB
JavaScript
309 lines
14 KiB
JavaScript
// content.js
|
|
|
|
console.log("Wii Shop Extension Content Script: Running at document_start.");
|
|
|
|
const runtimeAPI = typeof browser !== 'undefined' ? browser : chrome;
|
|
|
|
// Define storageAPI more robustly
|
|
let storageAPI;
|
|
try {
|
|
storageAPI = runtimeAPI.storage.local;
|
|
} catch (e) {
|
|
console.error("Content script: Could not access storage API!", e);
|
|
// Fallback if storage API is unavailable (e.g., in a non-extension context)
|
|
storageAPI = { get: async () => ({}), set: async () => {} };
|
|
}
|
|
|
|
// --- Font Loading Logic ---
|
|
function loadFont() {
|
|
console.log("Wii Shop Extension: Attempting to load custom font.");
|
|
const fontUrl = runtimeAPI.runtime.getURL("fonts/fot_rodin_pro_m.ttf");
|
|
const style = document.createElement('style');
|
|
style.textContent = `
|
|
@font-face {
|
|
font-family: 'Wii NTLG PGothic JPN Regular';
|
|
src: url('${fontUrl}') format('truetype');
|
|
}
|
|
body, #text03-01, #text05-01, #text06-01, .buttonTextBlackM {
|
|
font-family: 'Wii NTLG PGothic JPN Regular', sans-serif !important;
|
|
}
|
|
#text03-01, #text05-01, #text06-01 {
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
height: 100vh;
|
|
width: 100%;
|
|
}
|
|
.buttonTextBlackM {
|
|
font-size: 24px;
|
|
color: black;
|
|
text-align: center;
|
|
}
|
|
`;
|
|
|
|
const head = document.head || document.getElementsByTagName('head')[0];
|
|
if (head) {
|
|
head.appendChild(style);
|
|
console.log("Wii Shop Extension: Font loaded into <head>.");
|
|
} else {
|
|
// Fallback for when head is not yet available at document_start
|
|
const observer = new MutationObserver((mutations, obs) => {
|
|
const currentHead = document.head || document.getElementsByTagName('head')[0];
|
|
if (currentHead) {
|
|
currentHead.appendChild(style);
|
|
obs.disconnect();
|
|
console.log("Wii Shop Extension: Font loaded into <head> via MutationObserver fallback.");
|
|
}
|
|
});
|
|
observer.observe(document.documentElement || document, { childList: true, subtree: true });
|
|
}
|
|
}
|
|
|
|
// Check the font state and load if not disabled
|
|
async function checkFontState() {
|
|
try {
|
|
const result = await storageAPI.get(['fontDisabled']);
|
|
if (!result.fontDisabled) {
|
|
//loadFont(); disabled
|
|
} else {
|
|
console.log("Wii Shop Extension: Font loading disabled by user preference.");
|
|
}
|
|
} catch (error) {
|
|
console.error("Wii Shop Extension: Error checking font state:", error);
|
|
}
|
|
}
|
|
|
|
|
|
// --- Sound and BGM File Paths (Ensure these are correctly mapped to web-accessible resources) ---
|
|
const soundFilePaths = [
|
|
'', // Index 0 (unused)
|
|
'audio/1.wav', 'audio/2.wav', 'audio/3.wav', 'audio/4.wav',
|
|
'audio/5.wav', 'audio/6.wav', 'audio/7.wav', 'audio/8.wav',
|
|
'audio/9.wav', 'audio/10.wav', 'audio/11.wav', 'audio/12.wav',
|
|
'audio/13.wav', 'audio/14.wav', 'audio/15.wav', 'audio/16.wav'
|
|
];
|
|
const bgmFilePath = 'audio/bgm.wav';
|
|
|
|
// Generate the full, web-accessible URLs. These MUST be defined at the top level.
|
|
const generatedSoundUrls = soundFilePaths.map(path => path ? runtimeAPI.runtime.getURL(path) : '');
|
|
const generatedBgmUrl = runtimeAPI.runtime.getURL(bgmFilePath);
|
|
|
|
|
|
// --- Function to load class definitions and inject globals ---
|
|
const loadClassDefinitions = async () => {
|
|
const classDefinitionsUrl = runtimeAPI.runtime.getURL('classDefinitions.js');
|
|
console.log("Wii Shop Extension: Attempting to fetch classDefinitions.js from:", classDefinitionsUrl);
|
|
|
|
try {
|
|
const response = await fetch(classDefinitionsUrl);
|
|
if (!response.ok) {
|
|
throw new Error(`HTTP error! status: ${response.status} fetching ${classDefinitionsUrl}`);
|
|
}
|
|
const classDefinitionsText = await response.text();
|
|
console.log("Wii Shop Extension: classDefinitions.js fetched successfully. Length:", classDefinitionsText.length);
|
|
|
|
// Get initial BGM and Font state from storage for globals
|
|
const storageResult = await storageAPI.get(['bgmEnabled', 'fontDisabled']);
|
|
const bgmInitiallyEnabled = storageResult.bgmEnabled === true;
|
|
const fontInitiallyDisabled = storageResult.fontDisabled === true;
|
|
|
|
// Construct the script content to prepend to classDefinitions.js
|
|
const prependedGlobals = `
|
|
(function() {
|
|
// Ensure these are globally available within the page context
|
|
window._wiiShopSoundUrls_ = ${JSON.stringify(generatedSoundUrls)};
|
|
window._wiiShopBgmUrl_ = ${JSON.stringify(generatedBgmUrl)};
|
|
window._bgmInitiallyEnabled = ${JSON.stringify(bgmInitiallyEnabled)};
|
|
window._fontInitiallyDisabled = ${JSON.stringify(fontInitiallyDisabled)};
|
|
|
|
// Define the bridge function for the page context to communicate with content script
|
|
const _sendMessageToContentScript = (action, payload = {}) => {
|
|
window.postMessage({
|
|
type: 'WiiShopExtension_MessageFromPage', // Unique type for messages from page to content script
|
|
action: action, // The specific action like 'getStorage', 'playBGM', etc.
|
|
payload: payload
|
|
}, window.location.origin);
|
|
};
|
|
window.WiiShopExtension_sendMessage = _sendMessageToContentScript; // Expose globally for page's use
|
|
|
|
// Redefine/Expose extensionStorage if it's used by original page code or other injected scripts
|
|
// This makes sure get/set calls from page go through our background script
|
|
window.extensionStorage = {
|
|
get: async function(key) {
|
|
const response = await new Promise(resolve => {
|
|
_sendMessageToContentScript('getStorage', { key: key });
|
|
// Listen for the response back from the content script
|
|
const listener = (event) => {
|
|
if (event.source === window && event.data && event.data.type === 'WiiShopExtension_ResponseToPage' && event.data.action === 'getStorage' && event.data.key === key) {
|
|
window.removeEventListener('message', listener);
|
|
resolve(event.data.payload.value); // Extract the value
|
|
}
|
|
};
|
|
window.addEventListener('message', listener);
|
|
});
|
|
return response;
|
|
},
|
|
set: async function(key, value) {
|
|
await _sendMessageToContentScript('setStorage', { key: key, value: value });
|
|
},
|
|
slog: async function(message) {
|
|
await _sendMessageToContentScript('setStorage', { key: 'slog', value: message });
|
|
},
|
|
spts: async function(points) {
|
|
await _sendMessageToContentScript('setStorage', { key: 'spts', value: points });
|
|
},
|
|
clearLogs: async function() {
|
|
await _sendMessageToContentScript('clearLogs');
|
|
},
|
|
clearPoints: async function() {
|
|
await _sendMessageToContentScript('clearPoints');
|
|
},
|
|
playBGM: async function(url) {
|
|
await _sendMessageToContentScript('playBGM', { url: url });
|
|
},
|
|
stopBGM: async function() {
|
|
await _sendMessageToContentScript('stopBGM');
|
|
}
|
|
};
|
|
})();
|
|
`;
|
|
|
|
const scriptToInject = document.createElement('script');
|
|
scriptToInject.setAttribute('type', 'text/javascript');
|
|
scriptToInject.setAttribute('data-injected-id', 'wii-shop-cdjs');
|
|
scriptToInject.textContent = prependedGlobals + classDefinitionsText;
|
|
|
|
let targetElement = document.head || document.documentElement;
|
|
if (targetElement && !document.querySelector('[data-injected-id="wii-shop-cdjs"]')) {
|
|
targetElement.insertBefore(scriptToInject, targetElement.firstChild);
|
|
console.log("Wii Shop Extension: classDefinitions.js injected into page context.");
|
|
|
|
setTimeout(() => {
|
|
if (scriptToInject.parentNode) {
|
|
scriptToInject.parentNode.removeChild(scriptToInject);
|
|
console.log("Wii Shop Extension: Injected classDefinitions.js script removed from DOM.");
|
|
}
|
|
}, 100);
|
|
} else {
|
|
console.warn("Wii Shop Extension: classDefinitions.js already injected or target element (head/html) not found.");
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error("Wii Shop Extension: Failed to load class definitions:", error);
|
|
}
|
|
};
|
|
|
|
// --- Message Listener (from injected page script to content script) ---
|
|
window.addEventListener('message', async (event) => {
|
|
if (event.source !== window || !event.data || event.data.type !== 'WiiShopExtension_MessageFromPage') {
|
|
return;
|
|
}
|
|
|
|
const { action, payload } = event.data;
|
|
console.log("Content script received message from page:", action, payload);
|
|
|
|
try {
|
|
let responsePayload;
|
|
|
|
switch (action) {
|
|
case 'getStorage':
|
|
responsePayload = await runtimeAPI.runtime.sendMessage({ action: 'getStorage', key: payload.key });
|
|
window.postMessage({
|
|
type: 'WiiShopExtension_ResponseToPage',
|
|
action: 'getStorage',
|
|
key: payload.key,
|
|
payload: responsePayload
|
|
}, event.origin);
|
|
break;
|
|
|
|
case 'setStorage':
|
|
await runtimeAPI.runtime.sendMessage({ action: 'setStorage', key: payload.key, value: payload.value });
|
|
break;
|
|
|
|
case 'clearLogs':
|
|
await runtimeAPI.runtime.sendMessage({ action: 'clearLogs' });
|
|
break;
|
|
|
|
case 'clearPoints':
|
|
await runtimeAPI.runtime.sendMessage({ action: 'clearPoints' });
|
|
break;
|
|
|
|
case 'playBGM':
|
|
await runtimeAPI.runtime.sendMessage({ action: 'playBGM', url: payload.url });
|
|
break;
|
|
|
|
case 'stopBGM':
|
|
await runtimeAPI.runtime.sendMessage({ action: 'stopBGM' });
|
|
break;
|
|
|
|
case 'setBGMEnabled':
|
|
await runtimeAPI.runtime.sendMessage({ action: 'setBGMEnabled', enabled: payload.enabled });
|
|
break;
|
|
|
|
case 'getBGMEnabled':
|
|
responsePayload = await runtimeAPI.runtime.sendMessage({ action: 'getBGMEnabled' });
|
|
window.postMessage({
|
|
type: 'WiiShopExtension_ResponseToPage',
|
|
action: 'getBGMEnabled',
|
|
payload: responsePayload
|
|
}, event.origin);
|
|
break;
|
|
|
|
case 'setFontDisabled':
|
|
await runtimeAPI.runtime.sendMessage({ action: 'setFontDisabled', disabled: payload.disabled });
|
|
break;
|
|
|
|
case 'getFontDisabled':
|
|
responsePayload = await runtimeAPI.runtime.sendMessage({ action: 'getFontDisabled' });
|
|
window.postMessage({
|
|
type: 'WiiShopExtension_ResponseToPage',
|
|
action: 'getFontDisabled',
|
|
payload: responsePayload
|
|
}, event.origin);
|
|
break;
|
|
|
|
// Removed: case 'injectedScriptReady' as content.js no longer waits for it explicitly.
|
|
|
|
default:
|
|
console.warn("Content script: Unhandled message from page:", action, payload);
|
|
}
|
|
} catch (error) {
|
|
console.error(`Content script error handling action "${action}":`, error);
|
|
if (action === 'getStorage' || action === 'getBGMEnabled' || action === 'getFontDisabled') {
|
|
window.postMessage({
|
|
type: 'WiiShopExtension_ResponseToPage',
|
|
action: action,
|
|
key: payload ? payload.key : undefined,
|
|
error: error.message
|
|
}, event.origin);
|
|
}
|
|
}
|
|
}, false);
|
|
|
|
// --- Main Initialization ---
|
|
// Load the class definitions immediately at document_start.
|
|
loadClassDefinitions();
|
|
checkFontState(); // Check and load font if enabled.
|
|
|
|
// Removed: The specific window.onload listener for debug.jsp
|
|
// The debug.jsp page will now execute its original onload attribute.
|
|
|
|
|
|
// --- Listener for messages from the popup (if any) ---
|
|
runtimeAPI.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
|
if (request.action === "toggleBGMImmediate") {
|
|
if (request.enabled) {
|
|
console.log("Content: Received toggleBGMImmediate from popup: Play BGM.");
|
|
runtimeAPI.runtime.sendMessage({
|
|
action: "playBGM",
|
|
url: generatedBgmUrl
|
|
}).catch(error => console.error("Content: Error sending playBGM (immediate) to background:", error));
|
|
} else {
|
|
console.log("Content: Received toggleBGMImmediate from popup: Stop BGM.");
|
|
runtimeAPI.runtime.sendMessage({
|
|
action: "stopBGM"
|
|
}).catch(error => console.error("Content: Error sending stopBGM (immediate) to background:", error));
|
|
}
|
|
}
|
|
});
|