#include "config.h"
#include "ShadowRoot.h"
#include "DOMSelection.h"
#include "DOMWindow.h"
#include "Document.h"
#include "DocumentFragment.h"
#include "Element.h"
#include "HTMLContentElement.h"
#include "HTMLContentSelector.h"
#include "HTMLNames.h"
#include "InsertionPoint.h"
#include "NodeRareData.h"
#include "ShadowTree.h"
#include "SVGNames.h"
#include "StyleResolver.h"
#include "markup.h"
namespace WebCore {
ShadowRoot::ShadowRoot(Document* document)
: DocumentFragment(document, CreateShadowRoot)
, TreeScope(this)
, m_prev(0)
, m_next(0)
, m_applyAuthorSheets(false)
, m_insertionPointAssignedTo(0)
{
ASSERT(document);
setParentTreeScope(document);
ensureRareData()->setTreeScope(this);
}
ShadowRoot::~ShadowRoot()
{
ASSERT(!m_prev);
ASSERT(!m_next);
if (hasRareData())
clearRareData();
}
static bool allowsAuthorShadowRoot(Element* element)
{
if (element->hasTagName(HTMLNames::videoTag) || element->hasTagName(HTMLNames::audioTag))
return false;
if (element->isFormControlElement())
return false;
if (element->isSVGElement())
return false;
return true;
}
PassRefPtr<ShadowRoot> ShadowRoot::create(Element* element, ExceptionCode& ec)
{
return create(element, CreatingAuthorShadowRoot, ec);
}
PassRefPtr<ShadowRoot> ShadowRoot::create(Element* element, ShadowRootCreationPurpose purpose, ExceptionCode& ec)
{
if (!element) {
ec = HIERARCHY_REQUEST_ERR;
return 0;
}
if (purpose == CreatingAuthorShadowRoot && !allowsAuthorShadowRoot(element)) {
ec = HIERARCHY_REQUEST_ERR;
return 0;
}
RefPtr<ShadowRoot> shadowRoot = adoptRef(new ShadowRoot(element->document()));
ec = 0;
element->ensureShadowTree()->addShadowRoot(element, shadowRoot, ec);
if (ec)
return 0;
ASSERT(element == shadowRoot->host());
ASSERT(element->hasShadowRoot());
return shadowRoot.release();
}
String ShadowRoot::nodeName() const
{
return "#shadow-root";
}
PassRefPtr<Node> ShadowRoot::cloneNode(bool)
{
return 0;
}
String ShadowRoot::innerHTML() const
{
return createMarkup(this, ChildrenOnly);
}
void ShadowRoot::setInnerHTML(const String& markup, ExceptionCode& ec)
{
RefPtr<DocumentFragment> fragment = createFragmentFromSource(markup, host(), ec);
if (fragment)
replaceChildrenWithFragment(this, fragment.release(), ec);
}
DOMSelection* ShadowRoot::selection()
{
if (document() && document()->domWindow())
return document()->domWindow()->getSelection();
return 0;
}
bool ShadowRoot::childTypeAllowed(NodeType type) const
{
switch (type) {
case ELEMENT_NODE:
case PROCESSING_INSTRUCTION_NODE:
case COMMENT_NODE:
case TEXT_NODE:
case CDATA_SECTION_NODE:
case ENTITY_REFERENCE_NODE:
return true;
default:
return false;
}
}
ShadowTree* ShadowRoot::tree() const
{
if (host())
return host()->shadowTree();
return 0;
}
bool ShadowRoot::hasInsertionPoint() const
{
for (Node* n = firstChild(); n; n = n->traverseNextNode(this)) {
if (isInsertionPoint(n))
return true;
}
return false;
}
bool ShadowRoot::applyAuthorSheets() const
{
return m_applyAuthorSheets;
}
void ShadowRoot::setApplyAuthorSheets(bool value)
{
m_applyAuthorSheets = value;
}
void ShadowRoot::attach()
{
StyleResolver* styleResolver = document()->styleResolver();
styleResolver->pushParentShadowRoot(this);
DocumentFragment::attach();
styleResolver->popParentShadowRoot(this);
}
}