Chrome / ium或Firefox浏览器扩展(也称为附加组件/ WebExtensions)是否可以以某种方式覆盖媒体查询的结果?
我的意思是,对于JS window.matchMedia()
,这可能很容易:只需注入一个覆盖该JS函数的内容脚本即可。
但是,如果使用“真实的” CSS媒体查询(在css文件内部),这是不可能的,不是吗?
我显然可以注入自己的CSS,但这不是我想要的:我只想触发网站的CSS做不同的事情,即假设不同的媒体查询结果。
某些背景:如果您想知道为什么,我的用例是覆盖Firefox 67中引入的新prefers-color-scheme
CSS media feature。(目前尚不支持任何其他支持浏览器/ WebExtensions的浏览器。)
答案 0 :(得分:0)
感谢所有其他人,他们为我指明了正确的方向。基本上,没有简单的方法,但是您可以:
document.styleSheets
,所有已解析的样式表均已加载到该脚本中。那是艰巨的任务。
但是,这些都是只读的,因此您不能直接对其进行修改。browser.tabs.insertCSS
手动应用CSS。对于第一个任务,这是代码片段(一次以功能方式编写,而一次仅以结构方式编写)返回给定媒体查询的所有CSS。
你是可以调用getCssForMediaQueryFunc("(prefers-color-scheme: dark)")
并获取适用于深色方案的所有CSS。
/**
* Return CSS from the website for a specific query string.
*
* (functional implementation)
*
* @private
* @param {string} queryString
* @returns {string}
*/
function getCssForMediaQueryFunc(queryString) {
return Array.from(document.styleSheets).reduce((prev, styleSheet) => {
/* workaround for crazy HTML spec throwing an SecurityError here,
* see https://discourse.mozilla.org/t/accessing-some-fonts-css-style-sheet-via-stylesheet/38717?u=rugkx
* and https://stackoverflow.com/questions/21642277/security-error-the-operation-is-insecure-in-firefox-document-stylesheets */
try {
styleSheet.cssRules; // eslint-disable-line no-unused-expressions
} catch (e) {
return prev;
}
return Array.from(styleSheet.cssRules).reduce((prev, cssRule) => {
if (cssRule instanceof CSSMediaRule) {
if (cssRule.conditionText === queryString) {
return Array.from(cssRule.cssRules).reduce((prev, subCssRule) => {
return prev + subCssRule.cssText;
}, prev);
}
}
return prev;
}, prev);
}, "");
}
/**
* Return CSS from the website for a specific query string.
*
* @private
* @param {string} queryString
* @returns {string}
*/
function getCssForMediaQuery(queryString) { // eslint-disable-line no-unused-vars
let cssRules = "";
for (const styleSheet of document.styleSheets) {
/* workaround for crazy HTML spec throwing an SecurityError here,
* see https://discourse.mozilla.org/t/accessing-some-fonts-css-style-sheet-via-stylesheet/38717?u=rugkx
* and https://stackoverflow.com/questions/21642277/security-error-the-operation-is-insecure-in-firefox-document-stylesheets */
try {
styleSheet.cssRules; // eslint-disable-line no-unused-expressions
} catch (e) {
continue;
}
for (const cssRule of styleSheet.cssRules) {
if (cssRule instanceof CSSMediaRule) {
if (cssRule.conditionText === queryString) {
for (const subCssRule of cssRule.cssRules) {
cssRules = cssRules + subCssRule.cssText;
}
}
}
}
}
return cssRules;
}
window.matchMedia()
,以伪造可能使用JS进行检测的网站的结果。但是,这也是it's own non-trivial task,需要将此功能从内容脚本导出到网站。 (也很难伪造。)我已经在an add-on here和available on addons.mozilla.org (AMO)中将这件事作为或多或少的概念验证来实现。 (我在这里使用了永久链接,但是将来当然可以对附加组件进行更新。)
显然,这不是一个好方法,因此I've created a new Bugzilla issue为此找到了一个更好的解决方案,例如特殊的Firefox API。