CSSAgent keeps track of loaded style sheets and allows reloading them from a {Document}.
CSSAgent dispatches styleSheetAdded and styleSheetRemoved events, passing the URL for the added/removed style sheet.
Create a canonicalized version of the given URL, stripping off query strings and hashes.
function _canonicalize(url) {
return PathUtils.parseUrl(url).hrefNoSearch;
}
function _onFrameNavigated(event, res) {
// Clear maps when navigating to a new page, but not if an iframe was loaded
if (!res.frame.parentId) {
_styleSheetDetails = {};
}
}
function _onFrameStoppedLoading(event, res) {
var regexChromeUA,
userAgent,
uaMatch;
// Check for undefined so user agent string is only parsed once
if (_getAllStyleSheetsNotFound === undefined) {
regexChromeUA = /Chrome\/(\d+)\./; // Example: "... Chrome/34.0.1847.131 ..."
userAgent = Inspector.getUserAgent();
uaMatch = userAgent.match(regexChromeUA);
// If we have user agent string, and Chrome is >= 34, then don't use getAllStyleSheets
if (uaMatch && parseInt(uaMatch[1], 10) >= 34) {
_getAllStyleSheetsNotFound = true;
Inspector.Page.off("frameStoppedLoading.CSSAgent", _onFrameStoppedLoading);
return;
}
}
// Manually fire getAllStyleSheets since it will be removed from
// Inspector.json in a future update
Inspector.send("CSS", "getAllStyleSheets").done(function (res) {
res.headers.forEach(function (header) {
// _styleSheetAdded will ignore duplicates
_getAllStyleSheetsNotFound = false;
_styleSheetAdded(null, { header: header });
});
}).fail(function (err) {
// Disable getAllStyleSheets if the first call fails
_getAllStyleSheetsNotFound = (err.code === -32601);
Inspector.Page.off("frameStoppedLoading.CSSAgent", _onFrameStoppedLoading);
});
}
function _styleSheetAdded(event, res) {
var url = _canonicalize(res.header.sourceURL),
existing = styleForURL(res.header.sourceURL),
styleSheetId = res.header.styleSheetId,
duplicate;
// detect duplicates
duplicate = _.some(existing, function (styleSheet) {
return styleSheet && styleSheet.styleSheetId === styleSheetId;
});
if (duplicate) {
return;
}
_styleSheetDetails[styleSheetId] = res.header;
_styleSheetDetails[styleSheetId].canonicalizedURL = url; // canonicalized URL
exports.trigger("styleSheetAdded", url, res.header);
}
function _styleSheetRemoved(event, res) {
var header = _styleSheetDetails[res.styleSheetId];
delete _styleSheetDetails[res.styleSheetId];
exports.trigger("styleSheetRemoved", header.canonicalizedURL, header);
}
Empties a CSS style sheet given a document that has been deleted
function clearCSSForDocument(doc) {
return reloadCSSForDocument(doc, "");
}
Initialize the agent
function load() {
Inspector.Page.on("frameNavigated.CSSAgent", _onFrameNavigated);
Inspector.CSS.on("styleSheetAdded.CSSAgent", _styleSheetAdded);
Inspector.CSS.on("styleSheetRemoved.CSSAgent", _styleSheetRemoved);
// getAllStyleSheets was deleted beginning with Chrome 34
if (!_getAllStyleSheetsNotFound) {
Inspector.Page.on("frameStoppedLoading.CSSAgent", _onFrameStoppedLoading);
}
}
Reload a CSS style sheet from a document
function reloadCSSForDocument(doc, newContent) {
var styles = styleForURL(doc.url),
styleSheetId,
deferreds = [];
if (newContent === undefined) {
newContent = doc.getText();
}
for (styleSheetId in styles) {
deferreds.push(Inspector.CSS.setStyleSheetText(styles[styleSheetId].styleSheetId, newContent));
}
if (!deferreds.length) {
console.error("Style Sheet for document not loaded: " + doc.url);
return new $.Deferred().reject().promise();
}
// return master deferred
return $.when.apply($, deferreds);
}
Get the style sheets for a url
function styleForURL(url) {
var styleSheetId, styles = {};
url = _canonicalize(url);
for (styleSheetId in _styleSheetDetails) {
if (_styleSheetDetails[styleSheetId].canonicalizedURL === url) {
styles[styleSheetId] = _styleSheetDetails[styleSheetId];
}
}
return styles;
}
Clean up
function unload() {
Inspector.Page.off(".CSSAgent");
Inspector.CSS.off(".CSSAgent");
}
EventDispatcher.makeEventDispatcher(exports);
// Export public functions
exports.enable = enable;
exports.styleForURL = styleForURL;
exports.reloadCSSForDocument = reloadCSSForDocument;
exports.clearCSSForDocument = clearCSSForDocument;
exports.load = load;
exports.unload = unload;
});