blob: 2db79f0fc178beb649cc434be40d7c8e6c8847dc [file] [log] [blame]
// Copyright 2014 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.
#ifndef COBALT_DOM_ELEMENT_H_
#define COBALT_DOM_ELEMENT_H_
#include <string>
#include "base/containers/hash_tables.h"
#include "base/containers/small_map.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/strings/string_piece.h"
#include "cobalt/base/token.h"
#include "cobalt/cssom/style_sheet_list.h"
#include "cobalt/dom/dom_exception.h"
#include "cobalt/dom/element_intersection_observer_module.h"
#include "cobalt/dom/intersection_observer.h"
#include "cobalt/dom/node.h"
#include "cobalt/script/exception_state.h"
#include "cobalt/web_animations/animation_set.h"
namespace cobalt {
namespace dom {
class DOMRect;
class DOMRectList;
class DOMTokenList;
class HTMLCollection;
class HTMLElement;
class HTMLElementContext;
class NamedNodeMap;
// The Element interface represents an object of a Document. This interface
// describes methods and properties common to all kinds of elements.
// https://www.w3.org/TR/2014/WD-dom-20140710/#interface-element
class Element : public Node {
public:
// NOTE1: The array size of base::small_map and the decision to use
// base::hash_map as the underlying container type are based on extensive
// performance testing. Do not change these unless additional profiling data
// justifies it.
// NOTE2: Using base::small_map rather than base::hash_map also results in
// substantial memory gains when live videos are played. These videos trigger
// the creation of XML documents with over 20k elements, of which over 99%
// contain a single attribute. By using base::small_map, these single
// attribute elements are contained within arrays rather than hash_maps.
typedef base::small_map<std::unordered_map<std::string, std::string>, 1>
AttributeMap;
explicit Element(Document* document);
Element(Document* document, base::Token local_name);
// Web API: Node
//
base::Token node_name() const override { return tag_name(); }
NodeType node_type() const override { return Node::kElementNode; }
base::Optional<std::string> text_content() const override;
void set_text_content(
const base::Optional<std::string>& text_content) override;
bool HasAttributes() const override;
// Web API: Element
//
base::Token local_name() const { return local_name_; }
base::Token tag_name() const;
base::Token id() const { return id_attribute_; }
void set_id(const std::string& value) { SetAttribute("id", value); }
std::string class_name() const { return GetAttribute("class").value_or(""); }
void set_class_name(const std::string& value) {
SetAttribute("class", value);
}
const scoped_refptr<DOMTokenList>& class_list();
scoped_refptr<NamedNodeMap> attributes();
base::Optional<std::string> GetAttribute(const std::string& name) const;
void SetAttribute(const std::string& name, const std::string& value);
void RemoveAttribute(const std::string& name);
bool HasAttribute(const std::string& name) const;
base::Optional<std::string> GetAttributeNS(const std::string& namespace_uri,
const std::string& name) const;
bool HasAttributeNS(const std::string& namespace_uri,
const std::string& name) const;
bool Matches(const std::string& selectors,
script::ExceptionState* exception_state);
scoped_refptr<HTMLCollection> GetElementsByTagName(
const std::string& local_name) const;
scoped_refptr<HTMLCollection> GetElementsByClassName(
const std::string& class_name) const;
// Web API: CSSOM View Module: Extensions to the Element Interface (partial
// interface)
// https://www.w3.org/TR/2013/WD-cssom-view-20131217/#extensions-to-the-element-interface
scoped_refptr<DOMRect> GetBoundingClientRect();
virtual scoped_refptr<DOMRectList> GetClientRects();
virtual float client_top();
virtual float client_left();
virtual float client_width();
virtual float client_height();
// Updated version of the CSSOM View Module extensions:
// https://www.w3.org/TR/cssom-view-1/#extension-to-the-element-interface
// If the element does not have any associated CSS layout box return zero.
virtual int32 scroll_width() { return 0; }
virtual int32 scroll_height() { return 0; }
virtual float scroll_left() { return 0.0f; }
virtual float scroll_top() { return 0.0f; }
// If the element does not have any associated CSS layout box, the element
// has no associated scrolling box, or the element has no overflow, terminate
// these steps.
virtual void set_scroll_left(float x) {}
virtual void set_scroll_top(float y) {}
// Web API: DOM Parsing and Serialization (partial interface)
// https://www.w3.org/TR/DOM-Parsing/#extensions-to-the-element-interface
//
std::string inner_html() const;
void set_inner_html(const std::string& inner_html);
std::string outer_html(script::ExceptionState* exception_state) const;
void set_outer_html(const std::string& outer_html,
script::ExceptionState* exception_state);
// Web API: Pointer Events: Extensions to the Element Interface (partial
// interface)
// https://www.w3.org/TR/2015/REC-pointerevents-20150224/#extensions-to-the-element-interface
void SetPointerCapture(int32_t pointer_id,
script::ExceptionState* exception_state);
void ReleasePointerCapture(int32_t pointer_id,
script::ExceptionState* exception_state);
bool HasPointerCapture(int32_t pointer_id);
// Custom, not in any spec: Node.
//
Element* AsElement() override { return this; }
void Accept(NodeVisitor* visitor) override;
void Accept(ConstNodeVisitor* visitor) const override;
scoped_refptr<Node> Duplicate() const override;
// Custom, not in any spec.
//
// Returns whether the element has no children at all except comments or
// processing instructions.
// https://www.w3.org/TR/selectors4/#empty-pseudo
bool IsEmpty();
// Returns whether the element has focus.
// https://www.w3.org/TR/selectors4/#focus-pseudo
bool HasFocus();
// Returns a map that holds the actual attributes of the element.
const AttributeMap& attribute_map() const { return attribute_map_; }
// These are called when the element is generated by the parser, rather than
// by javascript.
// opening_tag_location points to ">" of opening tag.
virtual void OnParserStartTag(
const base::SourceLocation& opening_tag_location) {
}
virtual void OnParserEndTag() {}
// Used to ensure that the style attribute value reflects the style
// declaration.
// https://www.w3.org/TR/html50/dom.html#the-style-attribute
virtual base::Optional<std::string> GetStyleAttribute() const;
virtual void SetStyleAttribute(const std::string& value);
virtual void RemoveStyleAttribute();
// Adds all style sheets contained within the this element and its descendants
// to the style sheet vector. The style sheets are added in depth-first
// pre-order.
void CollectStyleSheetsOfElementAndDescendants(
cssom::StyleSheetVector* style_sheets) const;
virtual scoped_refptr<HTMLElement> AsHTMLElement();
const scoped_refptr<web_animations::AnimationSet>& animations() {
return animations_;
}
void RegisterIntersectionObserverRoot(IntersectionObserver* observer);
void UnregisterIntersectionObserverRoot(IntersectionObserver* observer);
void RegisterIntersectionObserverTarget(IntersectionObserver* observer);
void UnregisterIntersectionObserverTarget(IntersectionObserver* observer);
ElementIntersectionObserverModule::LayoutIntersectionObserverRootVector
GetLayoutIntersectionObserverRoots();
ElementIntersectionObserverModule::LayoutIntersectionObserverTargetVector
GetLayoutIntersectionObserverTargets();
DEFINE_WRAPPABLE_TYPE(Element);
void TraceMembers(script::Tracer* tracer) override;
protected:
~Element() override;
// Getting and setting boolean attribute.
// https://www.w3.org/TR/html50/infrastructure.html#boolean-attribute
bool GetBooleanAttribute(const std::string& name) const;
void SetBooleanAttribute(const std::string& name, bool value);
void CopyAttributes(const Element& other);
HTMLElementContext* html_element_context();
private:
// From EventTarget.
std::string GetDebugName() override;
virtual void OnSetAttribute(const std::string& name,
const std::string& value) {}
virtual void OnRemoveAttribute(const std::string& name) {}
// Adds this element's style sheet to the style sheet vector. By default, this
// function does nothing, but is implemented by element subclasses that
// generate style sheets (HTMLStyleElement and HTMLLinkElement).
virtual void CollectStyleSheet(cssom::StyleSheetVector* style_sheets) const {}
// Callback for error when parsing inner / outer HTML.
void HTMLParseError(const std::string& error);
void EnsureIntersectionObserverModuleInitialized();
// Local name of the element.
base::Token local_name_;
// A map that holds the actual element attributes.
AttributeMap attribute_map_;
// The "id" attribute for this element. Stored here in addition to being
// stored in |attribute_map_| as an optimization for id().
base::Token id_attribute_;
// A weak pointer to a NamedNodeMap that proxies the actual attributes.
// This heavy weight object is kept in memory only when needed by the user.
base::WeakPtr<NamedNodeMap> named_node_map_;
// Lazily created list of CSS classes.
// After creation this is kept in memory because of the significant negative
// performance impact of repeatedly recreating it.
scoped_refptr<DOMTokenList> class_list_;
// A set of all animations currently applied to this element.
scoped_refptr<web_animations::AnimationSet> animations_;
std::unique_ptr<ElementIntersectionObserverModule>
element_intersection_observer_module_;
};
} // namespace dom
} // namespace cobalt
#endif // COBALT_DOM_ELEMENT_H_