Код: Выделить всё
Iframe Script Test
iframe {
width: 100%;
height: 600px;
border: 2px solid #ccc;
border-radius: 8px;
}
Iframe Script Injection Test
Inject Test Script
function injectScript() {
const iframe = document.getElementById('test-iframe');
try {
const doc = iframe.contentDocument || iframe.contentWindow.document;
if (!doc) {
console.log('ERROR: Cannot access iframe document');
return;
}
// Check if script already exists
if (doc.querySelector('script[data-test-injected]')) {
console.log('Script already exists, removing old one...');
doc.querySelector('script[data-test-injected]').remove();
}
const script = doc.createElement('script');
script.setAttribute('data-test-injected', 'true');
script.textContent = `
let heartbeat = 0;
console.log('IFRAME: Test script injected successfully!');
setInterval(() => {
heartbeat++;
console.log('IFRAME: Heartbeat ' + heartbeat + ' - Script still alive!');
}, 1000);
console.log('IFRAME: Script setup complete, heartbeat started');
`;
doc.head.appendChild(script);
console.log('SUCCESS: Test script injected into iframe');
} catch (error) {
console.log('ERROR: Failed to inject script - ' + error.message);
}
}
< /code>
Я размещаю это в домене HTTPS (извините, не могу поделиться этим здесь, это туннель Ngrok, который я использую для разных вещей в разное время). Я могу получить доступ к этому через Firefox Desktop и Safari Mobile на симуляторе iPhone.
Для обоих браузеров все работает, как и ожидалось < /strong>. Нажав кнопку, внедряя скрипт, я вижу приветственное сообщение, а затем периодическое сердцебиение. Затем я добавил небольшой сценарий контента в расширение моего браузера. Это автономный сценарий контента, который сканирует для iFrames и добавляет тег сценария. В основном точно та же логика, что и для index.html
function injectScriptIntoIframe(iframe: HTMLIFrameElement) {
try {
const doc = iframe.contentDocument || iframe.contentWindow?.document;
if (!doc) {
console.warn('[INJECT] Could not access iframe document:', iframe);
return;
}
console.log('[INJECT] Injecting test script into iframe');
const testScript = doc.createElement('script');
testScript.setAttribute('data-timely-test-injected', 'true');
testScript.textContent = `
let count = 0;
console.log('Injected via contentscript: Test script injected successfully!');
setInterval(() => {
count++;
console.log('Injected via contentscript: count ' + count + ' - Script still alive!');
}, 1000);
console.log('Injected via contentscript: Script setup complete, count started');
`;
doc.head.appendChild(testScript);
console.log('[INJECT] Successfully injected script into iframe');
} catch (e) {
console.warn('[INJECT] Could not inject into iframe (likely cross-origin):', e);
}
}
function scanAndInjectIframes() {
const iframes = Array.from(document.getElementsByTagName('iframe'));
console.log(`[INJECT] Scanning ${iframes.length} iframes`);
for (const iframe of iframes) {
const inject = () => {
if (iframe.contentDocument && iframe.contentDocument.readyState === 'complete') {
injectScriptIntoIframe(iframe);
} else {
iframe.addEventListener('load', () => injectScriptIntoIframe(iframe), { once: true });
}
};
inject();
}
}
function initializeIframeInjector() {
console.log('[INJECT] Initializing iframe injector...');
// Initial scan
scanAndInjectIframes();
// Set up mutation observer for dynamically added iframes
const observer = new MutationObserver((mutations) => {
for (const mutation of mutations) {
if (mutation.type === 'childList') {
const hasNewIframe = Array.from(mutation.addedNodes).some(
(node) => node.nodeType === Node.ELEMENT_NODE && (node as Element).tagName === 'IFRAME'
);
if (hasNewIframe) {
console.log('[INJECT] Detected new iframe in DOM');
scanAndInjectIframes();
}
}
}
});
observer.observe(document.body, { childList: true, subtree: true });
console.log('[INJECT] Mutation observer set up for iframe detection');
}
// Initialize when DOM is ready
if (document.readyState === 'loading') {
console.log('[INJECT] Document still loading, waiting for DOMContentLoaded');
document.addEventListener('DOMContentLoaded', initializeIframeInjector, { once: true });
} else {
console.log('[INJECT] Document already loaded, starting immediately');
initializeIframeInjector();
}
< /code>
Теперь, на рабочем столе Firefox, это работает. Я вижу журналы: < /p>
[INJECT] Content script loaded injectIntoIframe.js:22:9
[INJECT] Document already loaded, starting immediately injectIntoIframe.js:107:13
[INJECT] Initializing iframe injector... injectIntoIframe.js:72:13
[INJECT] Scanning 1 iframes injectIntoIframe.js:45:13
[INJECT] Mutation observer set up for iframe detection injectIntoIframe.js:99:13
[INJECT] Injecting test script into iframe injectIntoIframe.js:31:17
Injected via contentscript: Test script injected successfully! srcdoc:3:21
Injected via contentscript: Script setup complete, count started srcdoc:10:21
[INJECT] Successfully injected script into iframe injectIntoIframe.js:36:17
Injected via contentscript: count 1 - Script still alive!
Injected via contentscript: count 2 - Script still alive!
...
< /code>
Приведенные выше журналы взяты из Firefox Desktop. Они хорошо выглядят. Теперь я показываю журналы из iOS Safari в эмуляторе: < /p>
[Log] [INJECT] Initializing iframe injector... (injectIntoIframe.js, line 70)
[Log] [INJECT] Scanning 1 iframes (injectIntoIframe.js, line 43)
[Log] [INJECT] Injecting test script into iframe (injectIntoIframe.js, line 29)
[Log] Injected via contentscript: Test script injected successfully! (about:srcdoc, line 3)
[Log] Injected via contentscript: Script setup complete, count started (about:srcdoc, line 10)
[Log] [INJECT] Successfully injected script into iframe (injectIntoIframe.js, line 34)
[Log] [INJECT] Mutation observer set up for iframe detection (injectIntoIframe.js, line 97)
< /code>
Журналы останавливаются здесь, не периодическое сообщение «все еще живое» из инъекционного сценария.
Это довольно удивительно для меня. Самый первый «вводится через содержимое: тестовый скрипт успешно вводится!» и «вводится через содержимое: настройка скрипта заполнена, count запускается» сообщения поступают из инъекционного сценария. Но после этого это просто исчезает.
Нет сообщения об ошибке. Глядя на вкладку Iframe на вкладке «Элементы» инструментов разработчика Safari также показывает, что в iframe нет введенного сценария. Он остается там и продолжает регистрировать свое сообщение «Я жив». Это так: < /p>
Откройте веб -сайт на сафари iOS в симуляторе < /li>
Переключить на XCode, нажмите «Стройте и запустите» < /li>
На симуляторе, которое мое приложение доведено на передний план. Расширения Safari iOS всегда находятся в пакете приложений вместе с каким -то компаньоном. Это нормальное приложение, оно имеет значок, его можно открыть и т. Д. Если пользователь удаляет это приложение, расширение тоже исчезает. Поэтому при запуске проекта Xcode это приложение открывается и доставляется на переднюю часть. Сообщения журнала теперь выглядят так: < /li>
< /ul>
[Log] [INJECT] Document already loaded, starting immediately (injectIntoIframe.js, line 105)
[Log] [INJECT] Initializing iframe injector... (injectIntoIframe.js, line 70)
[Log] [INJECT] Scanning 1 iframes (injectIntoIframe.js, line 43)
[Log] [INJECT] Injecting test script into iframe (injectIntoIframe.js, line 29)
[Log] Injected via contentscript: Test script injected successfully! (about:blank, line 3)
[Log] Injected via contentscript: Script setup complete, count started (about:blank, line 10)
[Log] [INJECT] Successfully injected script into iframe (injectIntoIframe.js, line 34)
[Log] [INJECT] Mutation observer set up for iframe detection (injectIntoIframe.js, line 97)
[Log] [INJECT] Document already loaded, starting immediately (injectIntoIframe.js, line 105)
[Log] [INJECT] Initializing iframe injector... (injectIntoIframe.js, line 70)
[Log] [INJECT] Scanning 1 iframes (injectIntoIframe.js, line 43)
[Log] [INJECT] Injecting test script into iframe (injectIntoIframe.js, line 29)
[Log] Injected via contentscript: Test script injected successfully! (about:srcdoc, line 3)
[Log] Injected via contentscript: Script setup complete, count started (about:srcdoc, line 10)
[Log] [INJECT] Successfully injected script into iframe (injectIntoIframe.js, line 34)
[Log] [INJECT] Mutation observer set up for iframe detection (injectIntoIframe.js, line 97)
[Log] Injected via contentscript: count 1 - Script still alive! (about:srcdoc, line 7)
[Log] Injected via contentscript: count 2 - Script still alive! (about:srcdoc, line 7)
[Log] Injected via contentscript: count 3 - Script still alive! (about:srcdoc, line 7)
[Log] Injected via contentscript: count 4 - Script still alive! (about:srcdoc, line 7)
[Log] Injected via contentscript: count 5 - Script still alive! (about:srcdoc, line 7)
[Log] Injected via contentscript: count 6 - Script still alive! (about:srcdoc, line 7)
[Log] Injected via contentscript: count 7 - Script still alive! (about:srcdoc, line 7)
[Log] Injected via contentscript: count 8 - Script still alive! (about:srcdoc, line 7)
[Log] Injected via contentscript: count 9 - Script still alive! (about:srcdoc, line 7)
[Log] Injected via contentscript: count 10 - Script still alive! (about:srcdoc, line 7)
< /code>
Также обратите внимание, сценарий контента, кажется, работает дважды. По -прежнему существуют прерванные журналы, когда я впервые открыл страницу (впрыскиваемый скрипт дает один журнал, но не продолжает журнал), а затем те же журналы появляются снова, но теперь с периоическими обновлениями, которые говорят, что скрипт все еще жив. Журналы показывают, что скрипт вводится, но он не продолжает регистрироваться.
Что здесь происходит?
Подробнее здесь: https://stackoverflow.com/questions/797 ... -extension