mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Remove a lot of API surface from Element.
R=ojan@chromium.org Review URL: https://codereview.chromium.org/696903002
This commit is contained in:
parent
0fadb1e50c
commit
ca3b2661ef
@ -757,21 +757,6 @@ bool Element::shouldInvalidateDistributionWhenAttributeChanged(ElementShadow* el
|
||||
return featureSet.hasSelectorForAttribute(name.localName());
|
||||
}
|
||||
|
||||
void Element::stripScriptingAttributes(Vector<Attribute>& attributeVector) const
|
||||
{
|
||||
size_t destination = 0;
|
||||
for (size_t source = 0; source < attributeVector.size(); ++source) {
|
||||
if (isHTMLContentAttribute(attributeVector[source]))
|
||||
continue;
|
||||
|
||||
if (source != destination)
|
||||
attributeVector[destination] = attributeVector[source];
|
||||
|
||||
++destination;
|
||||
}
|
||||
attributeVector.shrink(destination);
|
||||
}
|
||||
|
||||
void Element::parserSetAttributes(const Vector<Attribute>& attributeVector)
|
||||
{
|
||||
ASSERT(!inDocument());
|
||||
@ -1088,13 +1073,6 @@ ElementShadow& Element::ensureShadow()
|
||||
return ensureElementRareData().ensureShadow();
|
||||
}
|
||||
|
||||
void Element::didAffectSelector(AffectedSelectorMask mask)
|
||||
{
|
||||
setNeedsStyleRecalc(SubtreeStyleChange);
|
||||
if (ElementShadow* elementShadow = shadowWhereNodeCanBeDistributed(*this))
|
||||
elementShadow->didAffectSelector(mask);
|
||||
}
|
||||
|
||||
void Element::setAnimationStyleChange(bool animationStyleChange)
|
||||
{
|
||||
if (animationStyleChange && document().inStyleRecalc())
|
||||
@ -1172,11 +1150,6 @@ void Element::childrenChanged(const ChildrenChange& change)
|
||||
shadow->setNeedsDistributionRecalc();
|
||||
}
|
||||
|
||||
void Element::finishParsingChildren()
|
||||
{
|
||||
setIsFinishedParsingChildren(true);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
void Element::formatForDebugger(char* buffer, unsigned length) const
|
||||
{
|
||||
@ -1223,18 +1196,6 @@ void Element::parseAttribute(const QualifiedName& name, const AtomicString& valu
|
||||
}
|
||||
}
|
||||
|
||||
bool Element::parseAttributeName(QualifiedName& out, const AtomicString& namespaceURI, const AtomicString& qualifiedName, ExceptionState& exceptionState)
|
||||
{
|
||||
AtomicString prefix, localName;
|
||||
if (!Document::parseQualifiedName(qualifiedName, prefix, localName, exceptionState))
|
||||
return false;
|
||||
ASSERT(!exceptionState.hadException());
|
||||
|
||||
QualifiedName qName(localName);
|
||||
out = qName;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Element::removeAttributeInternal(size_t index, SynchronizationOfLazyAttribute inSynchronizationOfLazyAttribute)
|
||||
{
|
||||
MutableAttributeCollection attributes = ensureUniqueElementData().attributes();
|
||||
@ -1421,27 +1382,6 @@ void Element::dispatchFocusOutEvent(const AtomicString& eventType, Element* newF
|
||||
dispatchScopedEventDispatchMediator(FocusOutEventDispatchMediator::create(FocusEvent::create(eventType, true, false, document().domWindow(), 0, newFocusedElement)));
|
||||
}
|
||||
|
||||
String Element::innerText()
|
||||
{
|
||||
// We need to update layout, since plainText uses line boxes in the render tree.
|
||||
document().updateLayoutIgnorePendingStylesheets();
|
||||
|
||||
if (!renderer())
|
||||
return textContent(true);
|
||||
|
||||
return plainText(rangeOfContents(const_cast<Element*>(this)).get());
|
||||
}
|
||||
|
||||
String Element::outerText()
|
||||
{
|
||||
// Getting outerText is the same as getting innerText, only
|
||||
// setting is different. You would think this should get the plain
|
||||
// text for the outer range, but this is wrong, <br> for instance
|
||||
// would return different values for inner and outer text by such
|
||||
// a rule, but it doesn't in WinIE, and we want to match that.
|
||||
return innerText();
|
||||
}
|
||||
|
||||
String Element::textFromChildren()
|
||||
{
|
||||
Text* firstTextNode = 0;
|
||||
@ -1482,21 +1422,6 @@ String Element::textFromChildren()
|
||||
return content.toString();
|
||||
}
|
||||
|
||||
bool Element::isInDescendantTreeOf(const Element* shadowHost) const
|
||||
{
|
||||
ASSERT(shadowHost);
|
||||
ASSERT(isShadowHost(shadowHost));
|
||||
|
||||
const ShadowRoot* shadowRoot = containingShadowRoot();
|
||||
while (shadowRoot) {
|
||||
const Element* ancestorShadowHost = shadowRoot->shadowHost();
|
||||
if (ancestorShadowHost == shadowHost)
|
||||
return true;
|
||||
shadowRoot = ancestorShadowHost->containingShadowRoot();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
LayoutSize Element::minimumSizeForResizing() const
|
||||
{
|
||||
return hasRareData() ? elementRareData()->minimumSizeForResizing() : defaultMinimumSizeForResizing();
|
||||
@ -1986,14 +1911,4 @@ bool Element::supportsStyleSharing() const
|
||||
return true;
|
||||
}
|
||||
|
||||
void Element::trace(Visitor* visitor)
|
||||
{
|
||||
#if ENABLE(OILPAN)
|
||||
if (hasRareData())
|
||||
visitor->trace(elementRareData());
|
||||
visitor->trace(m_elementData);
|
||||
#endif
|
||||
ContainerNode::trace(visitor);
|
||||
}
|
||||
|
||||
} // namespace blink
|
||||
|
||||
@ -59,16 +59,6 @@ class PseudoElement;
|
||||
class ShadowRoot;
|
||||
class StylePropertySet;
|
||||
|
||||
enum AffectedSelectorType {
|
||||
AffectedSelectorChecked = 1,
|
||||
AffectedSelectorEnabled = 1 << 1,
|
||||
AffectedSelectorDisabled = 1 << 2,
|
||||
AffectedSelectorIndeterminate = 1 << 3,
|
||||
AffectedSelectorLink = 1 << 4,
|
||||
AffectedSelectorVisited = 1 << 5
|
||||
};
|
||||
typedef int AffectedSelectorMask;
|
||||
|
||||
enum SpellcheckAttributeState {
|
||||
SpellcheckAttributeTrue,
|
||||
SpellcheckAttributeFalse,
|
||||
@ -89,15 +79,18 @@ public:
|
||||
|
||||
bool hasAttribute(const QualifiedName&) const;
|
||||
const AtomicString& getAttribute(const QualifiedName&) const;
|
||||
|
||||
Vector<RefPtr<Attr>> getAttributes();
|
||||
bool hasAttributes() const;
|
||||
bool hasAttribute(const AtomicString& name) const;
|
||||
const AtomicString& getAttribute(const AtomicString& name) const;
|
||||
void setAttribute(const AtomicString& name, const AtomicString& value, ExceptionState&);
|
||||
void removeAttribute(const AtomicString& name);
|
||||
void removeAttribute(const QualifiedName&);
|
||||
|
||||
// Passing nullAtom as the second parameter removes the attribute when calling either of these set methods.
|
||||
void setAttribute(const QualifiedName&, const AtomicString& value);
|
||||
void setSynchronizedLazyAttribute(const QualifiedName&, const AtomicString& value);
|
||||
|
||||
void removeAttribute(const QualifiedName&);
|
||||
|
||||
// Typed getters and setters for language bindings.
|
||||
int getIntegralAttribute(const QualifiedName& attributeName) const;
|
||||
void setIntegralAttribute(const QualifiedName& attributeName, int value);
|
||||
@ -106,15 +99,6 @@ public:
|
||||
double getFloatingPointAttribute(const QualifiedName& attributeName, double fallbackValue = std::numeric_limits<double>::quiet_NaN()) const;
|
||||
void setFloatingPointAttribute(const QualifiedName& attributeName, double value);
|
||||
|
||||
bool hasAttributes() const;
|
||||
|
||||
bool hasAttribute(const AtomicString& name) const;
|
||||
|
||||
const AtomicString& getAttribute(const AtomicString& name) const;
|
||||
|
||||
void setAttribute(const AtomicString& name, const AtomicString& value, ExceptionState&);
|
||||
static bool parseAttributeName(QualifiedName&, const AtomicString& namespaceURI, const AtomicString& qualifiedName, ExceptionState&);
|
||||
|
||||
const AtomicString& getIdAttribute() const;
|
||||
void setIdAttribute(const AtomicString&);
|
||||
|
||||
@ -161,8 +145,6 @@ public:
|
||||
|
||||
virtual void didMoveToNewDocument(Document&) override;
|
||||
|
||||
void removeAttribute(const AtomicString& name);
|
||||
|
||||
CSSStyleDeclaration* style();
|
||||
|
||||
const QualifiedName& tagQName() const { return m_tagName; }
|
||||
@ -200,7 +182,6 @@ public:
|
||||
ModifiedByCloning
|
||||
};
|
||||
|
||||
virtual void attributeChanged(const QualifiedName&, const AtomicString&, AttributeModificationReason = ModifiedDirectly);
|
||||
virtual void parseAttribute(const QualifiedName&, const AtomicString&);
|
||||
|
||||
virtual bool hasLegalLinkAttribute(const QualifiedName&) const;
|
||||
@ -209,9 +190,6 @@ public:
|
||||
// Only called by the parser immediately after element construction.
|
||||
void parserSetAttributes(const Vector<Attribute>&);
|
||||
|
||||
// Remove attributes that might introduce scripting from the vector leaving the element unchanged.
|
||||
void stripScriptingAttributes(Vector<Attribute>&) const;
|
||||
|
||||
bool sharesSameElementData(const Element& other) const { return elementData() == other.elementData(); }
|
||||
|
||||
// Clones attributes only.
|
||||
@ -227,7 +205,6 @@ public:
|
||||
virtual RenderObject* createRenderer(RenderStyle*);
|
||||
virtual bool rendererIsNeeded(const RenderStyle&);
|
||||
void recalcStyle(StyleRecalcChange, Text* nextTextSibling = 0);
|
||||
void didAffectSelector(AffectedSelectorMask);
|
||||
void setAnimationStyleChange(bool);
|
||||
void setNeedsAnimationStyleRecalc();
|
||||
|
||||
@ -243,8 +220,6 @@ public:
|
||||
|
||||
bool hasAuthorShadowRoot() const { return shadowRoot(); }
|
||||
|
||||
bool isInDescendantTreeOf(const Element* shadowHost) const;
|
||||
|
||||
RenderStyle* computedStyle(PseudoId = NOPSEUDO);
|
||||
|
||||
bool isUpgradedCustomElement() { return customElementState() == Upgraded; }
|
||||
@ -256,7 +231,6 @@ public:
|
||||
virtual void accessKeyAction(bool /*sendToAnyEvent*/) { }
|
||||
|
||||
virtual bool isURLAttribute(const Attribute&) const { return false; }
|
||||
virtual bool isHTMLContentAttribute(const Attribute&) const { return false; }
|
||||
|
||||
virtual bool isLiveLink() const { return false; }
|
||||
KURL hrefURL() const;
|
||||
@ -277,19 +251,14 @@ public:
|
||||
virtual bool supportsFocus() const;
|
||||
// Whether the node can actually be focused.
|
||||
bool isFocusable() const;
|
||||
virtual bool isKeyboardFocusable() const;
|
||||
bool isKeyboardFocusable() const;
|
||||
virtual bool isMouseFocusable() const;
|
||||
virtual void willCallDefaultEventHandler(const Event&) override final;
|
||||
virtual void dispatchFocusEvent(Element* oldFocusedElement, FocusType);
|
||||
virtual void dispatchBlurEvent(Element* newFocusedElement);
|
||||
void dispatchFocusEvent(Element* oldFocusedElement, FocusType);
|
||||
void dispatchBlurEvent(Element* newFocusedElement);
|
||||
void dispatchFocusInEvent(const AtomicString& eventType, Element* oldFocusedElement);
|
||||
void dispatchFocusOutEvent(const AtomicString& eventType, Element* newFocusedElement);
|
||||
|
||||
String innerText();
|
||||
String outerText();
|
||||
|
||||
String textFromChildren();
|
||||
|
||||
virtual String title() const { return String(); }
|
||||
|
||||
LayoutSize minimumSizeForResizing() const;
|
||||
@ -301,14 +270,9 @@ public:
|
||||
// until they know all of their nested <param>s. [Radar 3603191, 4040848].
|
||||
// Also used for script elements and some SVG elements for similar purposes,
|
||||
// but making parsing a special case in this respect should be avoided if possible.
|
||||
virtual void finishParsingChildren();
|
||||
virtual void finishParsingChildren() { }
|
||||
|
||||
void beginParsingChildren() { setIsFinishedParsingChildren(false); }
|
||||
|
||||
virtual bool matchesReadOnlyPseudoClass() const { return false; }
|
||||
virtual bool matchesReadWritePseudoClass() const { return false; }
|
||||
bool matches(const String& selectors, ExceptionState&);
|
||||
virtual bool shouldAppearIndeterminate() const { return false; }
|
||||
|
||||
DOMTokenList& classList();
|
||||
|
||||
@ -344,7 +308,7 @@ public:
|
||||
void setTabIndex(int);
|
||||
virtual short tabIndex() const override;
|
||||
|
||||
virtual void trace(Visitor*) override;
|
||||
String textFromChildren();
|
||||
|
||||
protected:
|
||||
Element(const QualifiedName& tagName, Document*, ConstructionType);
|
||||
@ -381,6 +345,8 @@ protected:
|
||||
PassRefPtr<RenderStyle> originalStyleForRenderer();
|
||||
|
||||
private:
|
||||
void attributeChanged(const QualifiedName&, const AtomicString&, AttributeModificationReason = ModifiedDirectly);
|
||||
|
||||
bool hasElementFlag(ElementFlags mask) const { return hasRareData() && hasElementFlagInternal(mask); }
|
||||
void setElementFlag(ElementFlags, bool value = true);
|
||||
void clearElementFlag(ElementFlags);
|
||||
|
||||
@ -572,8 +572,6 @@ public:
|
||||
void setAlreadySpellChecked(bool flag) { setFlag(flag, AlreadySpellCheckedFlag); }
|
||||
bool isAlreadySpellChecked() { return getFlag(AlreadySpellCheckedFlag); }
|
||||
|
||||
bool isFinishedParsingChildren() const { return getFlag(IsFinishedParsingChildrenFlag); }
|
||||
|
||||
virtual void trace(Visitor*) override;
|
||||
|
||||
unsigned lengthOfContents() const;
|
||||
@ -605,12 +603,9 @@ private:
|
||||
InDocumentFlag = 1 << 10,
|
||||
IsInShadowTreeFlag = 1 << 11,
|
||||
|
||||
// Set by the parser when the children are done parsing.
|
||||
IsFinishedParsingChildrenFlag = 1 << 12,
|
||||
|
||||
// Flags related to recalcStyle.
|
||||
|
||||
// FIXME(sky): Flag 13 is free.
|
||||
// FIXME(sky): Flags 12 and 13 are free.
|
||||
|
||||
HasCustomStyleCallbacksFlag = 1 << 14,
|
||||
ChildNeedsStyleInvalidationFlag = 1 << 15,
|
||||
@ -628,10 +623,10 @@ private:
|
||||
HasEventTargetDataFlag = 1 << 26,
|
||||
AlreadySpellCheckedFlag = 1 << 27,
|
||||
|
||||
DefaultNodeFlags = IsFinishedParsingChildrenFlag | ChildNeedsStyleRecalcFlag | NeedsReattachStyleChange
|
||||
DefaultNodeFlags = ChildNeedsStyleRecalcFlag | NeedsReattachStyleChange
|
||||
};
|
||||
|
||||
// 5 bits remaining.
|
||||
// 6 bits remaining.
|
||||
|
||||
bool getFlag(NodeFlags mask) const { return m_nodeFlags & mask; }
|
||||
void setFlag(bool f, NodeFlags mask) { m_nodeFlags = (m_nodeFlags & ~mask) | (-(int32_t)f & mask); }
|
||||
@ -683,8 +678,6 @@ protected:
|
||||
|
||||
void markAncestorsWithChildNeedsStyleRecalc();
|
||||
|
||||
void setIsFinishedParsingChildren(bool value) { setFlag(value, IsFinishedParsingChildrenFlag); }
|
||||
|
||||
private:
|
||||
friend class TreeShared<Node>;
|
||||
friend class WeakNodeMap;
|
||||
|
||||
@ -324,12 +324,6 @@ void ElementShadow::collectSelectFeatureSetFrom(ShadowRoot& root)
|
||||
}
|
||||
}
|
||||
|
||||
void ElementShadow::didAffectSelector(AffectedSelectorMask mask)
|
||||
{
|
||||
if (ensureSelectFeatureSet().hasSelectorFor(mask))
|
||||
setNeedsDistributionRecalc();
|
||||
}
|
||||
|
||||
void ElementShadow::willAffectSelector()
|
||||
{
|
||||
for (ElementShadow* shadow = this; shadow; shadow = shadow->containingShadow()) {
|
||||
|
||||
@ -57,7 +57,6 @@ public:
|
||||
void attach(const Node::AttachContext&);
|
||||
void detach(const Node::AttachContext&);
|
||||
|
||||
void didAffectSelector(AffectedSelectorMask);
|
||||
void willAffectSelector();
|
||||
const SelectRuleFeatureSet& ensureSelectFeatureSet();
|
||||
|
||||
|
||||
@ -38,20 +38,17 @@
|
||||
namespace blink {
|
||||
|
||||
SelectRuleFeatureSet::SelectRuleFeatureSet()
|
||||
: m_featureFlags(0)
|
||||
{
|
||||
}
|
||||
|
||||
void SelectRuleFeatureSet::add(const SelectRuleFeatureSet& featureSet)
|
||||
{
|
||||
m_cssRuleFeatureSet.add(featureSet.m_cssRuleFeatureSet);
|
||||
m_featureFlags |= featureSet.m_featureFlags;
|
||||
}
|
||||
|
||||
void SelectRuleFeatureSet::clear()
|
||||
{
|
||||
m_cssRuleFeatureSet.clear();
|
||||
m_featureFlags = 0;
|
||||
}
|
||||
|
||||
void SelectRuleFeatureSet::collectFeaturesFromSelector(const CSSSelector& selector)
|
||||
|
||||
@ -51,25 +51,13 @@ public:
|
||||
bool hasSelectorForClass(const AtomicString&) const;
|
||||
bool hasSelectorForAttribute(const AtomicString&) const;
|
||||
|
||||
bool hasSelectorForChecked() const { return hasSelectorFor(AffectedSelectorChecked); }
|
||||
bool hasSelectorForEnabled() const { return hasSelectorFor(AffectedSelectorEnabled); }
|
||||
bool hasSelectorForDisabled() const { return hasSelectorFor(AffectedSelectorDisabled); }
|
||||
bool hasSelectorForIndeterminate() const { return hasSelectorFor(AffectedSelectorIndeterminate); }
|
||||
bool hasSelectorForLink() const { return hasSelectorFor(AffectedSelectorLink); }
|
||||
bool hasSelectorForVisited() const { return hasSelectorFor(AffectedSelectorVisited); }
|
||||
|
||||
bool hasSelectorFor(AffectedSelectorMask features) const { return m_featureFlags & features; }
|
||||
|
||||
bool checkSelectorsForClassChange(const SpaceSplitString& changedClasses) const;
|
||||
bool checkSelectorsForClassChange(const SpaceSplitString& oldClasses, const SpaceSplitString& newClasses) const;
|
||||
|
||||
void trace(Visitor* visitor) { visitor->trace(m_cssRuleFeatureSet); }
|
||||
|
||||
private:
|
||||
void setSelectRuleFeature(AffectedSelectorType feature) { m_featureFlags |= feature; }
|
||||
|
||||
RuleFeatureSet m_cssRuleFeatureSet;
|
||||
int m_featureFlags;
|
||||
};
|
||||
|
||||
inline bool SelectRuleFeatureSet::hasSelectorForId(const AtomicString& idValue) const
|
||||
|
||||
@ -191,8 +191,6 @@ public:
|
||||
SVGPointMatrixTransform = 209,
|
||||
DOMFocusInOutEvent = 211,
|
||||
FileGetLastModifiedDate = 212,
|
||||
HTMLElementInnerText = 213,
|
||||
HTMLElementOuterText = 214,
|
||||
ElementPrefixedMatchesSelector = 217,
|
||||
CSSStyleSheetRules = 219,
|
||||
CSSStyleSheetAddRule = 220,
|
||||
|
||||
@ -135,26 +135,6 @@ bool HTMLElement::isInteractiveContent() const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HTMLElement::matchesReadOnlyPseudoClass() const
|
||||
{
|
||||
return !matchesReadWritePseudoClass();
|
||||
}
|
||||
|
||||
bool HTMLElement::matchesReadWritePseudoClass() const
|
||||
{
|
||||
if (hasAttribute(HTMLNames::contenteditableAttr)) {
|
||||
const AtomicString& value = getAttribute(HTMLNames::contenteditableAttr);
|
||||
|
||||
if (value.isEmpty() || equalIgnoringCase(value, "true") || equalIgnoringCase(value, "plaintext-only"))
|
||||
return true;
|
||||
if (equalIgnoringCase(value, "false"))
|
||||
return false;
|
||||
// All other values should be treated as "inherit".
|
||||
}
|
||||
|
||||
return parentElement() && parentElement()->hasEditableStyle();
|
||||
}
|
||||
|
||||
const AtomicString& HTMLElement::eventParameterName()
|
||||
{
|
||||
DEFINE_STATIC_LOCAL(const AtomicString, eventString, ("event", AtomicString::ConstructFromLiteral));
|
||||
|
||||
@ -56,9 +56,6 @@ public:
|
||||
// http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#interactive-content
|
||||
virtual bool isInteractiveContent() const;
|
||||
|
||||
virtual bool matchesReadOnlyPseudoClass() const override;
|
||||
virtual bool matchesReadWritePseudoClass() const override;
|
||||
|
||||
static const AtomicString& eventParameterName();
|
||||
|
||||
virtual v8::Handle<v8::Object> wrap(v8::Handle<v8::Object> creationContext, v8::Isolate*) override;
|
||||
|
||||
@ -48,7 +48,6 @@ static const unsigned maximumHTMLParserDOMTreeDepth = 512;
|
||||
|
||||
static inline void setAttributes(Element* element, AtomicHTMLToken* token)
|
||||
{
|
||||
element->stripScriptingAttributes(token->attributes());
|
||||
element->parserSetAttributes(token->attributes());
|
||||
}
|
||||
|
||||
@ -90,7 +89,6 @@ static inline void executeInsertTask(HTMLConstructionSiteTask& task)
|
||||
|
||||
if (task.child->isElementNode()) {
|
||||
Element& child = toElement(*task.child);
|
||||
child.beginParsingChildren();
|
||||
if (task.selfClosing)
|
||||
child.finishParsingChildren();
|
||||
}
|
||||
|
||||
@ -57,7 +57,6 @@ public:
|
||||
BLINK_EXPORT void removeAttribute(const WebString&);
|
||||
BLINK_EXPORT WebString getAttribute(const WebString&) const;
|
||||
BLINK_EXPORT bool setAttribute(const WebString& name, const WebString& value);
|
||||
BLINK_EXPORT WebString innerText();
|
||||
BLINK_EXPORT void requestFullScreen();
|
||||
BLINK_EXPORT WebString attributeLocalName(unsigned index) const;
|
||||
BLINK_EXPORT WebString attributeValue(unsigned index) const;
|
||||
|
||||
@ -117,11 +117,6 @@ WebString WebElement::attributeValue(unsigned index) const
|
||||
return constUnwrap<Element>()->attributes().at(index).value();
|
||||
}
|
||||
|
||||
WebString WebElement::innerText()
|
||||
{
|
||||
return unwrap<Element>()->innerText();
|
||||
}
|
||||
|
||||
WebString WebElement::computeInheritedLanguage() const
|
||||
{
|
||||
return WebString(constUnwrap<Element>()->computeInheritedLanguage());
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user