function evalCallback(styleSheets) {
            if (progressMonitor.canceled)
                return;

            if (!styleSheets.length)
                return callback(null);

            var pseudoSelectorRegexp = /:hover|:link|:active|:visited|:focus|:before|:after/;
            var selectors = [];
            var testedSelectors = {};
            for (var i = 0; i < styleSheets.length; ++i) {
                var styleSheet = styleSheets[i];
                for (var curRule = 0; curRule < styleSheet.rules.length; ++curRule) {
                    var selectorText = styleSheet.rules[curRule].selectorText;
                    if (selectorText.match(pseudoSelectorRegexp) || testedSelectors[selectorText])
                        continue;
                    selectors.push(selectorText);
                    testedSelectors[selectorText] = 1;
                }
            }

            function selectorsCallback(callback, styleSheets, testedSelectors, foundSelectors)
            {
                if (progressMonitor.canceled)
                    return;

                var inlineBlockOrdinal = 0;
                var totalStylesheetSize = 0;
                var totalUnusedStylesheetSize = 0;
                var summary;

                for (var i = 0; i < styleSheets.length; ++i) {
                    var styleSheet = styleSheets[i];
                    var stylesheetSize = 0;
                    var unusedStylesheetSize = 0;
                    var unusedRules = [];
                    for (var curRule = 0; curRule < styleSheet.rules.length; ++curRule) {
                        var rule = styleSheet.rules[curRule];
                        // Exact computation whenever source ranges are available.
                        var textLength = (rule.selectorRange && rule.style.range && rule.style.range.end) ? rule.style.range.end - rule.selectorRange.start + 1 : 0;
                        if (!textLength && rule.style.cssText)
                            textLength = rule.style.cssText.length + rule.selectorText.length;
                        stylesheetSize += textLength;
                        if (!testedSelectors[rule.selectorText] || foundSelectors[rule.selectorText])
                            continue;
                        unusedStylesheetSize += textLength;
                        unusedRules.push(rule.selectorText);
                    }
                    totalStylesheetSize += stylesheetSize;
                    totalUnusedStylesheetSize += unusedStylesheetSize;

                    if (!unusedRules.length)
                        continue;

                    var resource = WebInspector.resourceForURL(styleSheet.sourceURL);
                    var isInlineBlock = resource && resource.type == WebInspector.Resource.Type.Document;
                    var url = !isInlineBlock ? WebInspector.AuditRuleResult.linkifyDisplayName(styleSheet.sourceURL) : String.sprintf("Inline block #%d", ++inlineBlockOrdinal);
                    var pctUnused = Math.round(100 * unusedStylesheetSize / stylesheetSize);
                    if (!summary)
                        summary = result.addChild("", true);
                    var entry = summary.addFormatted("%s: %s (%d%) is not used by the current page.", url, Number.bytesToString(unusedStylesheetSize), pctUnused);

                    for (var j = 0; j < unusedRules.length; ++j)
                        entry.addSnippet(unusedRules[j]);

                    result.violationCount += unusedRules.length;
                }

                if (!totalUnusedStylesheetSize)
                    return callback(null);

                var totalUnusedPercent = Math.round(100 * totalUnusedStylesheetSize / totalStylesheetSize);
                summary.value = String.sprintf("%s (%d%) of CSS is not used by the current page.", Number.bytesToString(totalUnusedStylesheetSize), totalUnusedPercent);

                callback(result);
            }

            var foundSelectors = {};
            function queryCallback(boundSelectorsCallback, selector, styleSheets, testedSelectors, nodeId)
            {
                if (nodeId)
                    foundSelectors[selector] = true;
                if (boundSelectorsCallback)
                    boundSelectorsCallback(foundSelectors);
            }

            function documentLoaded(selectors, document) {
                for (var i = 0; i < selectors.length; ++i) {
                    if (progressMonitor.canceled)
                        return;
                    WebInspector.domAgent.querySelector(document.id, selectors[i], queryCallback.bind(null, i === selectors.length - 1 ? selectorsCallback.bind(null, callback, styleSheets, testedSelectors) : null, selectors[i], styleSheets, testedSelectors));
                }
            }

            WebInspector.domAgent.requestDocument(documentLoaded.bind(null, selectors));
        }
The reported CSS rule size is incorrect (parsed != original in WebKit),
so use percentages instead, which gives a better approximation.
@constructor
@extends {WebInspector.AuditRule}