В расширениях Chrome вы не можете получить доступ или изменить содержимое из протоколов, отличных от file:
, http:
, ftp:
и chrome-extension:
(data:
, blob:
и filesystem:
, когда страница создала ресурс сами по себе).
Я рассмотрел четыре подхода к решению проблемы:
- Привязать событие
beforeload
к документу и изменить URL-адрес, если оно соответствует about:blank
.
Не работает : CSP активируется до запуска этого события.
- Привязать событие
DOMNodeInserted
к документу и проверить наличие about:blank
фреймов.
Не работает : CSP активируется до запуска этого события.
- Используйте API
webRequest
для перехвата запроса.
Не работает : строгое соответствие шаблонам не разрешает протокол about:
.
- Измените свойство
src
перед вставкой в документ IFRAME:
- Либо вручную (лучший вариант), либо
- Изменить
document.createElement
для IFrames или
- Измените методы
appendChild
, insertBefore
и replaceChild
для фреймов.
Для всех методов вы должны создать фиктивную страницу, скажем, blank.html
в вашем добавочном номере и разрешить доступ через web_accessible_resources
.
Пример файла манифеста (важны последние четыре строки):
{
"name": "Name",
"version": "1.0",
"background": {"scripts": ["aboutblank.js"]},
"manifest_version": 2,
"content_security_policy": "default-src 'self'",
"web_accessible_resources": ["blank.html"]
}
aboutblank.js
var BLANK_PAGE = chrome.extension.getURL("blank.html");
(function(BLANK_PAGE, createElement, appendChild, insertBefore, replaceChild) {
HTMLDocument.prototype.createElement = function(str) {
var elem = createElement.call(this, str);
if (str.toUpperCase() == 'IFRAME') {
elem.src = BLANK_PAGE;
}
return elem;
};
Element.prototype.appendChild = function(newChild) {
iframe_check(newChild);
return appendChild.call(this, newChild);
};
Element.prototype.insertBefore = function(newChild, refChild) {
iframe_check(newChild);
return insertBefore.call(this, newChild, refChild);
};
Element.prototype.replaceChild = function(newChild, refChild) {
iframe_check(newChild);
return replaceChild.call(this, newChild, refChild);
};
function iframe_check(elem) {
if (elem instanceof HTMLIFrameElement && (elem.src == '' || elem.src.slice(0,11) == 'about:blank')) {
elem.src = BLANK_PAGE;
}
}
})(BLANK_PAGE,
HTMLDocument.prototype.createElement,
Element.prototype.appendChild,
Element.prototype.insertBefore,
Element.prototype.replaceChild);
Примечание. Рекомендуется использовать вариант 1 для изменения этих методов-прототипов. Также способ-прототип не работает для <iframes>
, введенного с использованием .innerHTML
.