blob: b121b7123b7f199d65665b771bd3bc3831176354 [file] [log] [blame]
// Copyright 2019 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
(function(debugScriptRunner) {
// Attach methods to handle commands in the 'CSS' devtools domain.
// https://chromedevtools.github.io/devtools-protocol/tot/CSS
var commands = debugScriptRunner.CSS = {};
// https://chromedevtools.github.io/devtools-protocol/tot/CSS#method-getComputedStyleForNode
commands.getComputedStyleForNode = function(params) {
var node = debugScriptRunner.DOM._findNode(params);
return '{}';
}
// https://chromedevtools.github.io/devtools-protocol/tot/CSS#method-getInlineStylesForNode
commands.getInlineStylesForNode = function(params) {
var node = debugScriptRunner.DOM._findNode(params);
return '{}';
}
// https://chromedevtools.github.io/devtools-protocol/tot/CSS#method-getMatchedStylesForNode
commands.getMatchedStylesForNode = function(params) {
var node = debugScriptRunner.DOM._findNode(params);
if (!node) {
return JSON.stringify({error: {message: 'Invalid Node'}});
}
var result = {};
result.matchedCSSRules = _matchedRules(node);
return JSON.stringify(result);
}
var _matchedRules = function(node) {
// TODO: Use debugScriptRunner to get the matches cached in C++.
return _allRules().reduce(
function(accum, cssRule) {
// TODO: Report other rule types
if (cssRule.type === CSSRule.STYLE_RULE
&& node.matches(cssRule.selectorText)) {
accum.push(new devtools.RuleMatch(cssRule, node));
}
return accum;
}, []);
}
// Returns an array of all CSSRule objects from all stylesheets in the document.
var _allRules = function() {
// Array.slice() converts document.styleSheets to a proper array, which we can
// iterate with reduce().
return [].slice.call(document.styleSheets).reduce(
function(accum, styleSheet) {
try {
// Do the slice() trick to get the cssRules from each styleSheet as an
// array that we concat() into a single reduced array with all rules.
return accum.concat([].slice.call(styleSheet.cssRules));
} catch (e) {
// CSP blocks reading some rules, but the debugger should be allowed.
console.error(styleSheet.href, '\n', e);
return accum;
}
}, []);
}
// Namespace for constructors of types defined in the Devtools protocol.
var devtools = {};
// https://chromedevtools.github.io/devtools-protocol/tot/CSS#type-RuleMatch
devtools.RuleMatch = function(cssRule, node) {
this.rule = new devtools.CSSRule(cssRule);
this.matchingSelectors = [];
var selectors = this.rule.selectorList.selectors;
for (var i = 0; i < selectors.length; i++) {
if (node.matches(selectors[i].text)) {
this.matchingSelectors.push(i);
}
}
}
// https://chromedevtools.github.io/devtools-protocol/tot/CSS#type-CSSRule
devtools.CSSRule = function(cssRule) {
// TODO: this.styleSheetId
this.origin = 'regular'; // TODO
this.selectorList = new devtools.SelectorList(cssRule.selectorText);
if (cssRule.type === CSSRule.STYLE_RULE) {
this.style = new devtools.CSSStyle(cssRule.style);
}
}
// https://chromedevtools.github.io/devtools-protocol/tot/CSS#type-SelectorList
devtools.SelectorList = function(cssSelectorText) {
this.text = cssSelectorText;
this.selectors = cssSelectorText.split(',').map(
selector => new devtools.Value(selector.trim()));
}
// https://chromedevtools.github.io/devtools-protocol/tot/CSS#type-Value
devtools.Value = function(value) {
this.text = value;
// TODO: this.range
}
// https://chromedevtools.github.io/devtools-protocol/tot/CSS#type-CSSStyle
devtools.CSSStyle = function(cssStyleDecl) {
this.shorthandEntries = []; // TODO
this.text = cssStyleDecl.cssText;
this.cssProperties = [].slice.apply(cssStyleDecl).map(
property => new devtools.CSSProperty(cssStyleDecl, property));
}
// https://chromedevtools.github.io/devtools-protocol/tot/CSS#type-CSSProperty
devtools.CSSProperty = function(cssStyleDecl, property) {
this.name = property;
this.value = cssStyleDecl.getPropertyValue(property);
// this.important = cssStyleDecl.getPropertyPriority(property) === 'important';
}
// Polyfill Element.matches()
// https://developer.mozilla.org/en-US/docs/Web/API/Element/matches
Element.prototype.matches = Element.prototype.matches || function(s) {
var matches = document.querySelectorAll(s), i = matches.length;
while (--i >= 0 && matches.item(i) != this) {}
return i > -1;
};
// TODO: Pass debugScriptRunner from C++ instead of getting it from the window.
})(window.debugScriptRunner);