2015-05-05 15:21:45 +00:00
|
|
|
requestStyles();
|
|
|
|
|
|
|
|
function requestStyles() {
|
|
|
|
var request = {method: "getStyles", matchUrl: location.href, enabled: true, asHash: true};
|
|
|
|
if (location.href.indexOf(chrome.extension.getURL("")) == 0) {
|
|
|
|
var bg = chrome.extension.getBackgroundPage();
|
|
|
|
if (bg && bg.getStyles) {
|
|
|
|
bg.getStyles(request, applyStyles);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2015-03-31 21:35:06 +00:00
|
|
|
chrome.extension.sendMessage(request, applyStyles);
|
|
|
|
}
|
2015-01-30 03:32:14 +00:00
|
|
|
|
|
|
|
chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
|
2015-04-07 17:07:45 +00:00
|
|
|
// Also handle special request just for the pop-up
|
|
|
|
switch (request.method == "updatePopup" ? request.reason : request.method) {
|
2015-01-30 03:32:14 +00:00
|
|
|
case "styleDeleted":
|
2015-03-03 16:48:29 +00:00
|
|
|
removeStyle(request.id, document);
|
2015-01-30 03:32:14 +00:00
|
|
|
break;
|
|
|
|
case "styleUpdated":
|
2015-03-03 16:48:29 +00:00
|
|
|
removeStyle(request.style.id, document);
|
2015-01-30 03:32:14 +00:00
|
|
|
//fallthrough
|
|
|
|
case "styleAdded":
|
|
|
|
if (request.style.enabled == "true") {
|
2015-01-30 16:36:46 +00:00
|
|
|
chrome.extension.sendMessage({method: "getStyles", matchUrl: location.href, enabled: true, id: request.style.id, asHash: true}, applyStyles);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case "styleApply":
|
2015-03-17 18:03:20 +00:00
|
|
|
applyStyles(request.styles);
|
2015-02-23 05:14:22 +00:00
|
|
|
break;
|
|
|
|
case "styleReplaceAll":
|
2015-03-05 18:02:26 +00:00
|
|
|
replaceAll(request.styles, document);
|
2015-02-23 05:14:22 +00:00
|
|
|
break;
|
2015-03-17 18:03:20 +00:00
|
|
|
case "realURL":
|
|
|
|
sendResponse(location.href);
|
|
|
|
break;
|
|
|
|
case "styleDisableAll":
|
|
|
|
disableAll(request.disableAll);
|
2015-03-23 18:56:11 +00:00
|
|
|
break;
|
2015-01-30 03:32:14 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2015-03-17 18:03:20 +00:00
|
|
|
var g_disableAll = false;
|
|
|
|
function disableAll(disable) {
|
|
|
|
if (!disable === !g_disableAll) return;
|
|
|
|
g_disableAll = disable;
|
|
|
|
disableSheets(g_disableAll, document);
|
|
|
|
|
|
|
|
function disableSheets(disable, doc) {
|
|
|
|
Array.prototype.forEach.call(doc.styleSheets, function(stylesheet) {
|
|
|
|
if (stylesheet.ownerNode.classList.contains("stylish")) {
|
|
|
|
stylesheet.disabled = disable;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
getDynamicIFrames(doc).forEach(function(iframe) {
|
|
|
|
disableSheets(disable, iframe.contentDocument);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-03 16:48:29 +00:00
|
|
|
function removeStyle(id, doc) {
|
|
|
|
var e = doc.getElementById("stylish-" + id);
|
2015-01-30 03:32:14 +00:00
|
|
|
if (e) {
|
|
|
|
e.parentNode.removeChild(e);
|
|
|
|
}
|
2015-03-03 16:48:29 +00:00
|
|
|
getDynamicIFrames(doc).forEach(function(iframe) {
|
|
|
|
removeStyle(id, iframe.contentDocument);
|
|
|
|
});
|
2015-01-30 03:32:14 +00:00
|
|
|
}
|
|
|
|
|
2015-01-30 16:36:46 +00:00
|
|
|
function applyStyles(styleHash) {
|
2015-05-05 15:21:45 +00:00
|
|
|
if (!styleHash) { // Chrome is starting up
|
|
|
|
requestStyles();
|
|
|
|
return;
|
|
|
|
}
|
2015-03-17 18:03:20 +00:00
|
|
|
if ("disableAll" in styleHash) {
|
|
|
|
disableAll(styleHash.disableAll);
|
|
|
|
delete styleHash.disableAll;
|
|
|
|
}
|
|
|
|
|
2015-01-30 16:36:46 +00:00
|
|
|
for (var styleId in styleHash) {
|
|
|
|
applySections(styleId, styleHash[styleId]);
|
|
|
|
}
|
2015-01-30 03:32:14 +00:00
|
|
|
}
|
|
|
|
|
2015-01-30 16:36:46 +00:00
|
|
|
function applySections(styleId, sections) {
|
|
|
|
var styleElement = document.getElementById("stylish-" + styleId);
|
|
|
|
// Already there.
|
|
|
|
if (styleElement) {
|
|
|
|
return;
|
|
|
|
}
|
2015-01-30 03:32:14 +00:00
|
|
|
if (document.documentElement instanceof SVGSVGElement) {
|
|
|
|
// SVG document, make an SVG style element.
|
|
|
|
styleElement = document.createElementNS("http://www.w3.org/2000/svg", "style");
|
|
|
|
} else {
|
|
|
|
// This will make an HTML style element. If there's SVG embedded in an HTML document, this works on the SVG too.
|
|
|
|
styleElement = document.createElement("style");
|
|
|
|
}
|
2015-01-30 16:36:46 +00:00
|
|
|
styleElement.setAttribute("id", "stylish-" + styleId);
|
2015-01-30 03:32:14 +00:00
|
|
|
styleElement.setAttribute("class", "stylish");
|
|
|
|
styleElement.setAttribute("type", "text/css");
|
|
|
|
styleElement.appendChild(document.createTextNode(sections.map(function(section) {
|
|
|
|
return section.code;
|
|
|
|
}).join("\n")));
|
2015-03-03 16:48:29 +00:00
|
|
|
addStyleElement(styleElement, document);
|
|
|
|
}
|
|
|
|
|
|
|
|
function addStyleElement(styleElement, doc) {
|
2015-03-17 18:03:20 +00:00
|
|
|
doc.documentElement.appendChild(doc.importNode(styleElement, true))
|
|
|
|
.disabled = g_disableAll;
|
2015-03-03 16:48:29 +00:00
|
|
|
getDynamicIFrames(doc).forEach(function(iframe) {
|
|
|
|
addStyleElement(styleElement, iframe.contentDocument);
|
|
|
|
});
|
2015-01-30 03:32:14 +00:00
|
|
|
}
|
2015-02-23 05:14:22 +00:00
|
|
|
|
2015-03-03 16:48:29 +00:00
|
|
|
// Only dynamic iframes get the parent document's styles. Other ones should get styles based on their own URLs.
|
|
|
|
function getDynamicIFrames(doc) {
|
|
|
|
return Array.prototype.filter.call(doc.getElementsByTagName('iframe'), iframeIsDynamic);
|
|
|
|
}
|
|
|
|
|
|
|
|
function iframeIsDynamic(f) {
|
|
|
|
var href;
|
|
|
|
try {
|
|
|
|
href = f.contentDocument.location.href;
|
|
|
|
} catch (ex) {
|
|
|
|
// Cross-origin, so it's not a dynamic iframe
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return href == document.location.href || href.indexOf("about:") == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
function replaceAll(newStyles, doc) {
|
|
|
|
Array.prototype.forEach.call(doc.querySelectorAll("STYLE.stylish"), function(style) {
|
2015-02-23 05:14:22 +00:00
|
|
|
style.parentNode.removeChild(style);
|
|
|
|
});
|
|
|
|
applyStyles(newStyles);
|
2015-03-03 16:48:29 +00:00
|
|
|
getDynamicIFrames(doc).forEach(function(iframe) {
|
|
|
|
replaceAll(newStyles, iframe.contentDocument);
|
|
|
|
});
|
2015-02-23 05:14:22 +00:00
|
|
|
}
|
2015-03-03 16:48:29 +00:00
|
|
|
|
|
|
|
// Observe dynamic IFRAMEs being added
|
|
|
|
var iframeObserver = new MutationObserver(function(mutations) {
|
2015-03-04 20:03:29 +00:00
|
|
|
var styles = Array.prototype.slice.call(document.querySelectorAll('STYLE.stylish'));
|
2015-03-03 16:48:29 +00:00
|
|
|
if (styles.length == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
mutations.filter(function(mutation) {
|
|
|
|
return "childList" === mutation.type;
|
|
|
|
}).forEach(function(mutation) {
|
|
|
|
Array.prototype.filter.call(mutation.addedNodes, function(node) { return "IFRAME" === node.tagName; }).filter(iframeIsDynamic).forEach(function(iframe) {
|
2015-03-04 20:03:29 +00:00
|
|
|
var doc = iframe.contentDocument;
|
2015-03-03 16:48:29 +00:00
|
|
|
styles.forEach(function(style) {
|
2015-03-17 18:03:20 +00:00
|
|
|
doc.documentElement.appendChild(doc.importNode(style, true))
|
|
|
|
.disabled = g_disableAll;
|
2015-03-03 16:48:29 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
2015-03-17 18:03:20 +00:00
|
|
|
iframeObserver.observe(document, {childList: true, subtree: true});
|