/* * Copyright (c) 2014-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ package com.facebook.stetho.inspector.elements; import com.facebook.stetho.common.Accumulator; import com.facebook.stetho.common.ThreadBound; import com.facebook.stetho.common.Util; import com.facebook.stetho.inspector.protocol.module.DOM; import javax.annotation.Nullable; /** * This class derives from {@link Descriptor} and provides a canonical implementation of * {@link ChainedDescriptor}.<p/> * * This class implements the thread safety enforcement policy prescribed by * {@link ThreadBound}. Namely, that {@link #verifyThreadAccess()}} needs to be called in the * prologue for every method. Your derived class SHOULD NOT call {@link #verifyThreadAccess()}} in * any of its on___() methods.<p/> * * (NOTE: As an optimization, {@link #verifyThreadAccess()} is not actually called in the * prologue for every method. Instead, we rely on {@link DocumentProvider#getNodeDescriptor(Object)} * calling it in order to get most of our enforcement coverage. We still call * {@link #verifyThreadAccess()} in a few important methods such as {@link #hook(Object)} and * {@link #unhook(Object)} (anything that writes or is potentially really dangerous if misused).<p/> * * @param <E> the class that this descriptor will be describing for {@link DocumentProvider}, * {@link Document}, and ultimately {@link DOM}. */ public abstract class AbstractChainedDescriptor<E> extends Descriptor<E> implements ChainedDescriptor<E> { private Descriptor<? super E> mSuper; @Override public void setSuper(Descriptor<? super E> superDescriptor) { Util.throwIfNull(superDescriptor); if (superDescriptor != mSuper) { if (mSuper != null) { throw new IllegalStateException(); } mSuper = superDescriptor; } } final Descriptor<? super E> getSuper() { return mSuper; } @Override public final void hook(E element) { verifyThreadAccess(); mSuper.hook(element); onHook(element); } protected void onHook(E element) { } @Override public final void unhook(E element) { verifyThreadAccess(); onUnhook(element); mSuper.unhook(element); } protected void onUnhook(E element) { } @Override public final NodeType getNodeType(E element) { return onGetNodeType(element); } protected NodeType onGetNodeType(E element) { return mSuper.getNodeType(element); } @Override public final String getNodeName(E element) { return onGetNodeName(element); } protected String onGetNodeName(E element) { return mSuper.getNodeName(element); } @Override public final String getLocalName(E element) { return onGetLocalName(element); } protected String onGetLocalName(E element) { return mSuper.getLocalName(element); } @Override public final String getNodeValue(E element) { return onGetNodeValue(element); } @Nullable public String onGetNodeValue(E element) { return mSuper.getNodeValue(element); } @Override public final void getChildren(E element, Accumulator<Object> children) { mSuper.getChildren(element, children); onGetChildren(element, children); } protected void onGetChildren(E element, Accumulator<Object> children) { } @Override public final void getAttributes(E element, AttributeAccumulator attributes) { mSuper.getAttributes(element, attributes); onGetAttributes(element, attributes); } protected void onGetAttributes(E element, AttributeAccumulator attributes) { } @Override public final void setAttributesAsText(E element, String text) { onSetAttributesAsText(element, text); } protected void onSetAttributesAsText(E element, String text) { mSuper.setAttributesAsText(element, text); } @Override public final void getStyleRuleNames(E element, StyleRuleNameAccumulator accumulator) { mSuper.getStyleRuleNames(element, accumulator); onGetStyleRuleNames(element, accumulator); } protected void onGetStyleRuleNames(E element, StyleRuleNameAccumulator accumulator) { } @Override public final void getStyles(E element, String ruleName, StyleAccumulator accumulator) { mSuper.getStyles(element, ruleName, accumulator); onGetStyles(element, ruleName, accumulator); } protected void onGetStyles(E element, String ruleName, StyleAccumulator accumulator) { } @Override public final void setStyle(E element, String ruleName, String name, String value) { mSuper.setStyle(element, ruleName, name, value); onSetStyle(element, ruleName, name, value); } protected void onSetStyle(E element, String ruleName, String name, String value) { } @Override public void getComputedStyles(E element, ComputedStyleAccumulator accumulator) { mSuper.getComputedStyles(element, accumulator); onGetComputedStyles(element, accumulator); } protected void onGetComputedStyles(E element, ComputedStyleAccumulator accumulator) { } }