Bug 833808 part 2. Add some utilities for working with selectors to inspector utils. r=dbaron

This commit is contained in:
Boris Zbarsky 2013-02-13 10:11:53 -05:00
Родитель 3aa2cf5f0e
Коммит 1c99b91077
3 изменённых файлов: 155 добавлений и 10 удалений

Просмотреть файл

@ -16,13 +16,31 @@ interface nsIDOMFontFaceList;
interface nsIDOMRange;
interface nsIDOMCSSStyleSheet;
[scriptable, uuid(f7a37305-a963-4a2a-b951-2c97a6b27fb4)]
[scriptable, uuid(dd8a9dfd-336f-4cce-8ec1-0365ede9a3a8)]
interface inIDOMUtils : nsISupports
{
// CSS utilities
nsISupportsArray getCSSStyleRules(in nsIDOMElement aElement, [optional] in DOMString aPseudo);
unsigned long getRuleLine(in nsIDOMCSSStyleRule aRule);
// Utilities for working with selectors. We don't have a JS OM representation
// of a single selector or a selector list yet, but given a rule we can index
// into the selector list.
//
// This is a somewhat backwards API; once we move StyleRule to WebIDL we
// should consider using [ChromeOnly] APIs on that.
unsigned long getSelectorCount(in nsIDOMCSSStyleRule aRule);
// For all three functions below, aSelectorIndex is 0-based
AString getSelectorText(in nsIDOMCSSStyleRule aRule,
in unsigned long aSelectorIndex);
unsigned long long getSpecificity(in nsIDOMCSSStyleRule aRule,
in unsigned long aSelectorIndex);
// Note: This does not handle scoped selectors correctly, because it has no
// idea what the right scope is.
bool selectorMatchesElement(in nsIDOMElement aElement,
in nsIDOMCSSStyleRule aRule,
in unsigned long aSelectorIndex);
// Returns true if the string names a property that is inherited by default.
bool isInheritedProperty(in AString aPropertyName);

Просмотреть файл

@ -27,7 +27,13 @@
#include "nsRange.h"
#include "mozilla/dom/Element.h"
#include "nsCSSStyleSheet.h"
#include "nsRuleWalker.h"
#include "nsRuleProcessorData.h"
#include "nsCSSRuleProcessor.h"
using namespace mozilla;
using namespace mozilla::css;
using namespace mozilla::dom;
///////////////////////////////////////////////////////////////////////////////
@ -188,19 +194,136 @@ inDOMUtils::GetCSSStyleRules(nsIDOMElement *aElement,
return NS_OK;
}
static already_AddRefed<StyleRule>
GetRuleFromDOMRule(nsIDOMCSSStyleRule *aRule, ErrorResult& rv)
{
nsCOMPtr<nsICSSStyleRuleDOMWrapper> rule = do_QueryInterface(aRule);
if (!rule) {
rv.Throw(NS_ERROR_INVALID_ARG);
return nullptr;
}
nsRefPtr<StyleRule> cssrule;
rv = rule->GetCSSStyleRule(getter_AddRefs(cssrule));
if (rv.Failed()) {
return nullptr;
}
if (!cssrule) {
rv.Throw(NS_ERROR_FAILURE);
}
return cssrule.forget();
}
NS_IMETHODIMP
inDOMUtils::GetRuleLine(nsIDOMCSSStyleRule *aRule, uint32_t *_retval)
{
*_retval = 0;
ErrorResult rv;
nsRefPtr<StyleRule> rule = GetRuleFromDOMRule(aRule, rv);
if (rv.Failed()) {
return rv.ErrorCode();
}
NS_ENSURE_ARG_POINTER(aRule);
*_retval = rule->GetLineNumber();
return NS_OK;
}
nsCOMPtr<nsICSSStyleRuleDOMWrapper> rule = do_QueryInterface(aRule);
nsRefPtr<mozilla::css::StyleRule> cssrule;
nsresult rv = rule->GetCSSStyleRule(getter_AddRefs(cssrule));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(cssrule != nullptr, NS_ERROR_FAILURE);
*_retval = cssrule->GetLineNumber();
NS_IMETHODIMP
inDOMUtils::GetSelectorCount(nsIDOMCSSStyleRule* aRule, uint32_t *aCount)
{
ErrorResult rv;
nsRefPtr<StyleRule> rule = GetRuleFromDOMRule(aRule, rv);
if (rv.Failed()) {
return rv.ErrorCode();
}
uint32_t count = 0;
for (nsCSSSelectorList* sel = rule->Selector(); sel; sel = sel->mNext) {
++count;
}
*aCount = count;
return NS_OK;
}
static nsCSSSelectorList*
GetSelectorAtIndex(nsIDOMCSSStyleRule* aRule, uint32_t aIndex, ErrorResult& rv)
{
nsRefPtr<StyleRule> rule = GetRuleFromDOMRule(aRule, rv);
if (rv.Failed()) {
return nullptr;
}
for (nsCSSSelectorList* sel = rule->Selector(); sel;
sel = sel->mNext, --aIndex) {
if (aIndex == 0) {
return sel;
}
}
// Ran out of selectors
rv.Throw(NS_ERROR_INVALID_ARG);
return nullptr;
}
NS_IMETHODIMP
inDOMUtils::GetSelectorText(nsIDOMCSSStyleRule* aRule,
uint32_t aSelectorIndex,
nsAString& aText)
{
ErrorResult rv;
nsCSSSelectorList* sel = GetSelectorAtIndex(aRule, aSelectorIndex, rv);
if (rv.Failed()) {
return rv.ErrorCode();
}
nsRefPtr<StyleRule> rule = GetRuleFromDOMRule(aRule, rv);
MOZ_ASSERT(!rv.Failed(), "How could we get a selector but not a rule?");
sel->mSelectors->ToString(aText, rule->GetStyleSheet(), false);
return NS_OK;
}
NS_IMETHODIMP
inDOMUtils::GetSpecificity(nsIDOMCSSStyleRule* aRule,
uint32_t aSelectorIndex,
uint64_t* aSpecificity)
{
ErrorResult rv;
nsCSSSelectorList* sel = GetSelectorAtIndex(aRule, aSelectorIndex, rv);
if (rv.Failed()) {
return rv.ErrorCode();
}
*aSpecificity = sel->mWeight;
return NS_OK;
}
NS_IMETHODIMP
inDOMUtils::SelectorMatchesElement(nsIDOMElement* aElement,
nsIDOMCSSStyleRule* aRule,
uint32_t aSelectorIndex,
bool* aMatches)
{
nsCOMPtr<Element> element = do_QueryInterface(aElement);
NS_ENSURE_ARG_POINTER(element);
ErrorResult rv;
nsCSSSelectorList* tail = GetSelectorAtIndex(aRule, aSelectorIndex, rv);
if (rv.Failed()) {
return rv.ErrorCode();
}
// We want just the one list item, not the whole list tail
nsAutoPtr<nsCSSSelectorList> sel(tail->Clone(false));
element->OwnerDoc()->FlushPendingLinkUpdates();
// XXXbz what exactly should we do with visited state here?
TreeMatchContext matchingContext(false,
nsRuleWalker::eRelevantLinkUnvisited,
element->OwnerDoc(),
TreeMatchContext::eNeverMatchVisited);
*aMatches = nsCSSRuleProcessor::SelectorListMatches(element, matchingContext,
sel);
return NS_OK;
}

Просмотреть файл

@ -220,6 +220,8 @@ private:
* items (where each |nsCSSSelectorList| object's |mSelectors| has
* an |mNext| for the P or H1). We represent them as linked lists.
*/
class inDOMUtils;
struct nsCSSSelectorList {
nsCSSSelectorList(void);
~nsCSSSelectorList(void);
@ -250,9 +252,11 @@ struct nsCSSSelectorList {
nsCSSSelector* mSelectors;
int32_t mWeight;
nsCSSSelectorList* mNext;
private:
protected:
friend class inDOMUtils;
nsCSSSelectorList* Clone(bool aDeep) const;
private:
nsCSSSelectorList(const nsCSSSelectorList& aCopy) MOZ_DELETE;
nsCSSSelectorList& operator=(const nsCSSSelectorList& aCopy) MOZ_DELETE;
};