blob: 20584ad605de94e579c75556d32f7cde24215fc5 [file] [log] [blame]
/*
* Copyright (C) 2011 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_SHADOW_ROOT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_SHADOW_ROOT_H_
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/css/style_sheet_list.h"
#include "third_party/blink/renderer/core/dom/container_node.h"
#include "third_party/blink/renderer/core/dom/document_fragment.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/tree_scope.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/casting.h"
namespace blink {
class Document;
class ExceptionState;
class GetInnerHTMLOptions;
class SlotAssignment;
class WhitespaceAttacher;
enum class ShadowRootType { kOpen, kClosed, kUserAgent };
class CORE_EXPORT ShadowRoot final : public DocumentFragment, public TreeScope {
DEFINE_WRAPPERTYPEINFO();
public:
ShadowRoot(Document&, ShadowRootType);
~ShadowRoot() override;
ShadowRoot(const ShadowRoot&) = delete;
ShadowRoot& operator=(const ShadowRoot&) = delete;
// Disambiguate between Node and TreeScope hierarchies; TreeScope's
// implementation is simpler.
using TreeScope::GetDocument;
using TreeScope::getElementById;
// Make protected methods from base class public here.
using TreeScope::SetDocument;
using TreeScope::SetParentTreeScope;
Element& host() const {
DCHECK(ParentOrShadowHostNode());
return *To<Element>(ParentOrShadowHostNode());
}
ShadowRootType GetType() const { return static_cast<ShadowRootType>(type_); }
String mode() const {
switch (GetType()) {
case ShadowRootType::kUserAgent:
// UA ShadowRoot should not be exposed to the Web.
NOTREACHED();
return "";
case ShadowRootType::kOpen:
return "open";
case ShadowRootType::kClosed:
return "closed";
default:
NOTREACHED();
return "";
}
}
bool IsOpen() const { return GetType() == ShadowRootType::kOpen; }
bool IsUserAgent() const { return GetType() == ShadowRootType::kUserAgent; }
InsertionNotificationRequest InsertedInto(ContainerNode&) override;
void RemovedFrom(ContainerNode&) override;
void SetNeedsAssignmentRecalc();
bool NeedsSlotAssignmentRecalc() const;
// For Internals, don't use this.
unsigned ChildShadowRootCount() const { return child_shadow_root_count_; }
void RebuildLayoutTree(WhitespaceAttacher&);
void DetachLayoutTree(bool performing_reattach) override;
void RegisterScopedHTMLStyleChild();
void UnregisterScopedHTMLStyleChild();
SlotAssignment& GetSlotAssignment() {
DCHECK(slot_assignment_);
return *slot_assignment_;
}
bool HasSlotAssignment() { return slot_assignment_; }
HTMLSlotElement* AssignedSlotFor(const Node&);
void DidAddSlot(HTMLSlotElement&);
void DidChangeHostChildSlotName(const AtomicString& old_value,
const AtomicString& new_value);
void DistributeIfNeeded();
Element* ActiveElement() const;
String innerHTML() const;
String getInnerHTML(const GetInnerHTMLOptions* options) const;
void setInnerHTML(const String&, ExceptionState& = ASSERT_NO_EXCEPTION);
Node* Clone(Document&, CloneChildrenFlag) const override;
void SetDelegatesFocus(bool flag) { delegates_focus_ = flag; }
bool delegatesFocus() const { return delegates_focus_; }
void SetSlotAssignmentMode(SlotAssignmentMode assignment);
bool IsManualSlotting() const {
return slot_assignment_mode_ ==
static_cast<unsigned>(SlotAssignmentMode::kManual);
}
SlotAssignmentMode GetSlotAssignmentMode() const {
return static_cast<SlotAssignmentMode>(slot_assignment_mode_);
}
String slotAssignment() const {
return IsManualSlotting() ? "manual" : "auto";
}
void SetIsDeclarativeShadowRoot(bool flag) {
DCHECK(!flag || GetType() == ShadowRootType::kOpen ||
GetType() == ShadowRootType::kClosed);
is_declarative_shadow_root_ = flag;
}
bool IsDeclarativeShadowRoot() const { return is_declarative_shadow_root_; }
void SetAvailableToElementInternals(bool flag) {
DCHECK(!flag || GetType() == ShadowRootType::kOpen ||
GetType() == ShadowRootType::kClosed);
available_to_element_internals_ = flag;
}
bool IsAvailableToElementInternals() const {
return available_to_element_internals_;
}
void SetNeedsDirAutoAttributeUpdate(bool flag) {
needs_dir_auto_attribute_update_ = flag;
}
bool NeedsDirAutoAttributeUpdate() const {
return needs_dir_auto_attribute_update_;
}
bool ContainsShadowRoots() const { return child_shadow_root_count_; }
StyleSheetList& StyleSheets();
void SetStyleSheets(StyleSheetList* style_sheet_list) {
style_sheet_list_ = style_sheet_list;
}
void Trace(Visitor*) const override;
private:
void ChildrenChanged(const ChildrenChange&) override;
SlotAssignment& EnsureSlotAssignment();
void AddChildShadowRoot() { ++child_shadow_root_count_; }
void RemoveChildShadowRoot() {
DCHECK_GT(child_shadow_root_count_, 0u);
--child_shadow_root_count_;
}
Member<StyleSheetList> style_sheet_list_;
Member<SlotAssignment> slot_assignment_;
unsigned child_shadow_root_count_ : 16;
unsigned type_ : 2;
unsigned registered_with_parent_shadow_root_ : 1;
unsigned delegates_focus_ : 1;
unsigned slot_assignment_mode_ : 1;
unsigned is_declarative_shadow_root_ : 1;
unsigned available_to_element_internals_ : 1;
unsigned needs_dir_auto_attribute_update_ : 1;
unsigned unused_ : 8;
};
inline Element* ShadowRoot::ActiveElement() const {
return AdjustedFocusedElement();
}
inline bool Node::IsInUserAgentShadowRoot() const {
return ContainingShadowRoot() && ContainingShadowRoot()->IsUserAgent();
}
inline ShadowRoot* Node::GetShadowRoot() const {
auto* this_element = DynamicTo<Element>(this);
if (!this_element)
return nullptr;
return this_element->GetShadowRoot();
}
template <>
struct DowncastTraits<ShadowRoot> {
static bool AllowFrom(const Node& node) { return node.IsShadowRoot(); }
static bool AllowFrom(const TreeScope& tree_scope) {
return tree_scope.RootNode().IsShadowRoot();
}
};
CORE_EXPORT std::ostream& operator<<(std::ostream&, const ShadowRootType&);
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_DOM_SHADOW_ROOT_H_