summaryrefslogtreecommitdiffstats
path: root/WebCore/dom/Document.cpp
diff options
context:
space:
mode:
authorFeng Qian <fqian@google.com>2009-06-17 12:12:20 -0700
committerFeng Qian <fqian@google.com>2009-06-17 12:12:20 -0700
commit5f1ab04193ad0130ca8204aadaceae083aca9881 (patch)
tree5a92cd389e2cfe7fb67197ce14b38469462379f8 /WebCore/dom/Document.cpp
parent194315e5a908cc8ed67d597010544803eef1ac59 (diff)
downloadexternal_webkit-5f1ab04193ad0130ca8204aadaceae083aca9881.zip
external_webkit-5f1ab04193ad0130ca8204aadaceae083aca9881.tar.gz
external_webkit-5f1ab04193ad0130ca8204aadaceae083aca9881.tar.bz2
Get WebKit r44544.
Diffstat (limited to 'WebCore/dom/Document.cpp')
-rw-r--r--WebCore/dom/Document.cpp601
1 files changed, 337 insertions, 264 deletions
diff --git a/WebCore/dom/Document.cpp b/WebCore/dom/Document.cpp
index e280c81..ec8dfee 100644
--- a/WebCore/dom/Document.cpp
+++ b/WebCore/dom/Document.cpp
@@ -4,7 +4,7 @@
* (C) 2001 Dirk Mueller (mueller@kde.org)
* (C) 2006 Alexey Proskuryakov (ap@webkit.org)
* Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
- * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
* Copyright (C) 2008 David Levin (levin@chromium.org)
*
* This library is free software; you can redistribute it and/or
@@ -25,8 +25,9 @@
#include "config.h"
#include "Document.h"
-#include "AnimationController.h"
#include "AXObjectCache.h"
+#include "AnimationController.h"
+#include "Attr.h"
#include "CDATASection.h"
#include "CSSHelper.h"
#include "CSSStyleSelector.h"
@@ -59,6 +60,7 @@
#include "HTMLAnchorElement.h"
#include "HTMLBodyElement.h"
#include "HTMLCanvasElement.h"
+#include "HTMLCollection.h"
#include "HTMLDocument.h"
#include "HTMLElementFactory.h"
#include "HTMLFrameOwnerElement.h"
@@ -68,6 +70,7 @@
#include "HTMLMapElement.h"
#include "HTMLNameCollection.h"
#include "HTMLNames.h"
+#include "HTMLParser.h"
#include "HTMLStyleElement.h"
#include "HTMLTitleElement.h"
#include "HTTPParsers.h"
@@ -76,8 +79,10 @@
#include "HitTestResult.h"
#include "ImageLoader.h"
#include "InspectorController.h"
+#include "ScriptEventListener.h"
#include "KeyboardEvent.h"
#include "Logging.h"
+#include "MappedAttribute.h"
#include "MessageEvent.h"
#include "MouseEvent.h"
#include "MouseEventWithHitTestResults.h"
@@ -97,6 +102,7 @@
#include "RenderView.h"
#include "RenderWidget.h"
#include "ScriptController.h"
+#include "ScriptElement.h"
#include "SecurityOrigin.h"
#include "SegmentedString.h"
#include "SelectionController.h"
@@ -105,8 +111,8 @@
#include "TextEvent.h"
#include "TextIterator.h"
#include "TextResourceDecoder.h"
-#include "TreeWalker.h"
#include "Timer.h"
+#include "TreeWalker.h"
#include "UIEvent.h"
#include "WebKitAnimationEvent.h"
#include "WebKitTransitionEvent.h"
@@ -114,15 +120,11 @@
#include "XMLHttpRequest.h"
#include "XMLNames.h"
#include "XMLTokenizer.h"
-#if USE(JSC)
-#include "JSDOMBinding.h"
-#endif
-#include "ScriptController.h"
#include <wtf/CurrentTime.h>
#include <wtf/HashFunctions.h>
#include <wtf/MainThread.h>
-#include <wtf/StdLibExtras.h>
#include <wtf/PassRefPtr.h>
+#include <wtf/StdLibExtras.h>
#if ENABLE(DATABASE)
#include "Database.h"
@@ -182,6 +184,10 @@
#include "WMLNames.h"
#endif
+#if ENABLE(XHTMLMP)
+#include "HTMLNoScriptElement.h"
+#endif
+
using namespace std;
using namespace WTF;
using namespace Unicode;
@@ -307,16 +313,18 @@ static bool disableRangeMutation(Page* page)
#endif
}
-static HashSet<Document*>* changedDocuments = 0;
+static HashSet<Document*>* documentsThatNeedStyleRecalc = 0;
Document::Document(Frame* frame, bool isXHTML)
: ContainerNode(0)
, m_domtree_version(0)
, m_styleSheets(StyleSheetList::create(this))
+ , m_styleRecalcTimer(this, &Document::styleRecalcTimerFired)
, m_frameElementsShouldIgnoreScrolling(false)
, m_title("")
, m_titleSetExplicitly(false)
, m_updateFocusAppearanceTimer(this, &Document::updateFocusAppearanceTimerFired)
+ , m_executeScriptSoonTimer(this, &Document::executeScriptSoonTimerFired)
#if ENABLE(XSLT)
, m_transformSource(0)
#endif
@@ -358,14 +366,13 @@ Document::Document(Frame* frame, bool isXHTML)
m_frame = frame;
m_renderArena = 0;
-
+#if !PLATFORM(ANDROID)
m_axObjectCache = 0;
-
+#endif
m_docLoader = new DocLoader(this);
visuallyOrdered = false;
m_bParsing = false;
- m_docChanged = false;
m_tokenizer = 0;
m_wellFormed = false;
@@ -405,6 +412,9 @@ Document::Document(Frame* frame, bool isXHTML)
static int docID = 0;
m_docID = docID++;
+#if ENABLE(XHTMLMP)
+ m_shouldProcessNoScriptElement = settings() && !settings()->isJavaScriptEnabled();
+#endif
}
void Document::removedLastRef()
@@ -454,16 +464,17 @@ Document::~Document()
ASSERT(!m_inPageCache);
ASSERT(!m_savedRenderer);
ASSERT(m_ranges.isEmpty());
+ ASSERT(!m_styleRecalcTimer.isActive());
- removeAllEventListeners();
+ for (size_t i = 0; i < m_scriptsToExecuteSoon.size(); ++i)
+ m_scriptsToExecuteSoon[i].first->element()->deref(); // Balances ref() in executeScriptSoon().
+ removeAllEventListeners();
#if USE(JSC)
forgetAllDOMNodesForDocument(this);
#endif
- if (m_docChanged && changedDocuments)
- changedDocuments->remove(this);
delete m_tokenizer;
m_document.resetSkippingRef(0);
delete m_styleSelector;
@@ -661,7 +672,7 @@ PassRefPtr<Node> Document::importNode(Node* importedNode, bool deep, ExceptionCo
if (ec)
return 0;
- NamedAttrMap* attrs = oldElement->attributes(true);
+ NamedNodeMap* attrs = oldElement->attributes(true);
if (attrs) {
unsigned length = attrs->length();
for (unsigned i = 0; i < length; i++) {
@@ -796,14 +807,19 @@ PassRefPtr<Element> Document::createElement(const QualifiedName& qName, bool cre
e = SVGElementFactory::createSVGElement(qName, this, createdByParser);
#endif
#if ENABLE(WML)
- else if (qName.namespaceURI() == WMLNames::wmlNamespaceURI || isWMLDocument())
+ else if (qName.namespaceURI() == WMLNames::wmlNamespaceURI)
e = WMLElementFactory::createWMLElement(qName, this, createdByParser);
+ else if (isWMLDocument())
+ e = WMLElementFactory::createWMLElement(QualifiedName(nullAtom, qName.localName(), WMLNames::wmlNamespaceURI), this, createdByParser);
#endif
if (!e)
e = new Element(qName, document());
// <image> uses imgTag so we need a special rule.
+#if ENABLE(WML)
+ if (!isWMLDocument())
+#endif
ASSERT((qName.matches(imageTag) && e->tagQName().matches(imgTag) && e->tagQName().prefix() == qName.prefix()) || qName == e->tagQName());
return e.release();
@@ -867,7 +883,7 @@ String Document::readyState() const
String Document::encoding() const
{
if (TextResourceDecoder* d = decoder())
- return d->encoding().name();
+ return d->encoding().domName();
return String();
}
@@ -1103,24 +1119,39 @@ PassRefPtr<TreeWalker> Document::createTreeWalker(Node *root, unsigned whatToSho
return TreeWalker::create(root, whatToShow, filter, expandEntityReferences);
}
-void Document::setDocumentChanged(bool b)
+void Document::scheduleStyleRecalc()
{
- if (b) {
- if (!m_docChanged) {
- if (!changedDocuments)
- changedDocuments = new HashSet<Document*>;
- changedDocuments->add(this);
- }
- if (m_accessKeyMapValid) {
- m_accessKeyMapValid = false;
- m_elementsByAccessKey.clear();
- }
- } else {
- if (m_docChanged && changedDocuments)
- changedDocuments->remove(this);
+ if (m_styleRecalcTimer.isActive() || inPageCache())
+ return;
+
+ ASSERT(childNeedsStyleRecalc());
+
+ if (!documentsThatNeedStyleRecalc)
+ documentsThatNeedStyleRecalc = new HashSet<Document*>;
+ documentsThatNeedStyleRecalc->add(this);
+
+ // FIXME: Why on earth is this here? This is clearly misplaced.
+ if (m_accessKeyMapValid) {
+ m_accessKeyMapValid = false;
+ m_elementsByAccessKey.clear();
}
+
+ m_styleRecalcTimer.startOneShot(0);
+}
+
+void Document::unscheduleStyleRecalc()
+{
+ ASSERT(!childNeedsStyleRecalc());
- m_docChanged = b;
+ if (documentsThatNeedStyleRecalc)
+ documentsThatNeedStyleRecalc->remove(this);
+
+ m_styleRecalcTimer.stop();
+}
+
+void Document::styleRecalcTimerFired(Timer<Document>*)
+{
+ updateStyleIfNeeded();
}
void Document::recalcStyle(StyleChange change)
@@ -1183,28 +1214,26 @@ void Document::recalcStyle(StyleChange change)
}
for (Node* n = firstChild(); n; n = n->nextSibling())
- if (change >= Inherit || n->hasChangedChild() || n->changed())
+ if (change >= Inherit || n->childNeedsStyleRecalc() || n->needsStyleRecalc())
n->recalcStyle(change);
#ifdef ANDROID_INSTRUMENT
android::TimeCounter::record(android::TimeCounter::CalculateStyleTimeCounter, __FUNCTION__);
#endif
- if (view()) {
- if (changed())
- view()->layout();
#if USE(ACCELERATED_COMPOSITING)
- else {
- // If we didn't update compositing layers because of layout(), we need to do so here.
+ if (view()) {
+ bool layoutPending = view()->layoutPending() || renderer()->needsLayout();
+ // If we didn't update compositing layers because of layout(), we need to do so here.
+ if (!layoutPending)
view()->updateCompositingLayers();
- }
-#endif
}
+#endif
bail_out:
- setChanged(NoStyleChange);
- setHasChangedChild(false);
- setDocumentChanged(false);
+ setNeedsStyleRecalc(NoStyleChange);
+ setChildNeedsStyleRecalc(false);
+ unscheduleStyleRecalc();
if (view())
view()->resumeScheduledEvents();
@@ -1218,9 +1247,9 @@ bail_out:
}
}
-void Document::updateRendering()
+void Document::updateStyleIfNeeded()
{
- if (!hasChangedChild() || inPageCache())
+ if (!childNeedsStyleRecalc() || inPageCache())
return;
if (m_frame)
@@ -1228,23 +1257,22 @@ void Document::updateRendering()
recalcStyle(NoChange);
- // Tell the animation controller that updateRendering is finished and it can do any post-processing
+ // Tell the animation controller that updateStyleIfNeeded is finished and it can do any post-processing
if (m_frame)
m_frame->animation()->endAnimationUpdate();
}
-void Document::updateDocumentsRendering()
+void Document::updateStyleForAllDocuments()
{
- if (!changedDocuments)
+ if (!documentsThatNeedStyleRecalc)
return;
- while (changedDocuments->size()) {
- HashSet<Document*>::iterator it = changedDocuments->begin();
+ while (documentsThatNeedStyleRecalc->size()) {
+ HashSet<Document*>::iterator it = documentsThatNeedStyleRecalc->begin();
Document* doc = *it;
- changedDocuments->remove(it);
-
- doc->m_docChanged = false;
- doc->updateRendering();
+ documentsThatNeedStyleRecalc->remove(doc);
+ ASSERT(doc->childNeedsStyleRecalc() && !doc->inPageCache());
+ doc->updateStyleIfNeeded();
}
}
@@ -1253,7 +1281,7 @@ void Document::updateLayout()
if (Element* oe = ownerElement())
oe->document()->updateLayout();
- updateRendering();
+ updateStyleIfNeeded();
// Only do a layout if changes have occurred that make it necessary.
FrameView* v = view();
@@ -1298,8 +1326,9 @@ void Document::attach()
{
ASSERT(!attached());
ASSERT(!m_inPageCache);
+#if !PLATFORM(ANDROID)
ASSERT(!m_axObjectCache);
-
+#endif
if (!m_renderArena)
m_renderArena = new RenderArena();
@@ -1349,14 +1378,17 @@ void Document::detach()
ContainerNode::detach();
+ unscheduleStyleRecalc();
+
if (render)
render->destroy();
// This is required, as our Frame might delete itself as soon as it detaches
- // us. However, this violates Node::detach() symantics, as it's never
- // possible to re-attach. Eventually Document::detach() should be renamed
- // or this call made explicit in each of the callers of Document::detach().
- clearFramePointer();
+ // us. However, this violates Node::detach() symantics, as it's never
+ // possible to re-attach. Eventually Document::detach() should be renamed,
+ // or this setting of the frame to 0 could be made explicit in each of the
+ // callers of Document::detach().
+ m_frame = 0;
if (m_renderArena) {
delete m_renderArena;
@@ -1364,17 +1396,10 @@ void Document::detach()
}
}
-void Document::clearFramePointer()
+void Document::removeAllEventListeners()
{
- m_frame = 0;
-}
-
-void Document::removeAllEventListenersFromAllNodes()
-{
- size_t size = m_windowEventListeners.size();
- for (size_t i = 0; i < size; ++i)
- m_windowEventListeners[i]->setRemoved(true);
- m_windowEventListeners.clear();
+ if (DOMWindow* domWindow = this->domWindow())
+ domWindow->removeAllEventListeners();
removeAllDisconnectedNodeEventListeners();
for (Node* node = this; node; node = node->traverseNextNode())
node->removeAllEventListeners();
@@ -1405,6 +1430,9 @@ RenderView* Document::renderView() const
void Document::clearAXObjectCache()
{
+#if PLATFORM(ANDROID)
+ return;
+#else
// clear cache in top document
if (m_axObjectCache) {
delete m_axObjectCache;
@@ -1416,10 +1444,14 @@ void Document::clearAXObjectCache()
Document* doc = topDocument();
if (doc != this)
doc->clearAXObjectCache();
+#endif
}
AXObjectCache* Document::axObjectCache() const
{
+#if PLATFORM(ANDROID)
+ return 0;
+#else
// The only document that actually has a AXObjectCache is the top-level
// document. This is because we need to be able to get from any WebCoreAXObject
// to any other WebCoreAXObject on the same page. Using a single cache allows
@@ -1453,6 +1485,7 @@ AXObjectCache* Document::axObjectCache() const
// this is the top-level document, so install a new cache
m_axObjectCache = new AXObjectCache;
return m_axObjectCache;
+#endif // ANDROID
}
void Document::setVisuallyOrdered()
@@ -1510,6 +1543,11 @@ void Document::implicitOpen()
clear();
m_tokenizer = createTokenizer();
setParsing(true);
+
+ // If we reload, the animation controller sticks around and has
+ // a stale animation time. We need to update it here.
+ if (m_frame && m_frame->animation())
+ m_frame->animation()->beginAnimationUpdate();
}
HTMLElement* Document::body() const
@@ -1599,10 +1637,16 @@ void Document::implicitClose()
// Parser should have picked up all preloads by now
m_docLoader->clearPreloads();
- // Create a body element if we don't already have one. See Radar 3758785.
+ // Create a head and a body if we don't have those yet (e.g. for about:blank).
if (!this->body() && isHTMLDocument()) {
if (Node* documentElement = this->documentElement()) {
ExceptionCode ec = 0;
+
+ // The implicit <head> isn't expected in older versions of Mail - <rdar://problem/6863795>
+ if (!head() && shouldCreateImplicitHead(this)) {
+ documentElement->appendChild(new HTMLHeadElement(headTag, this), ec);
+ ASSERT(!ec);
+ }
documentElement->appendChild(new HTMLBodyElement(bodyTag, this), ec);
ASSERT(!ec);
}
@@ -1623,7 +1667,7 @@ void Document::implicitClose()
f->animation()->resumeAnimations(this);
ImageLoader::dispatchPendingLoadEvents();
- dispatchWindowEvent(eventNames().loadEvent, false, false);
+ dispatchLoadEvent();
if (f)
f->loader()->handledOnloadEvents();
#ifdef INSTRUMENT_LAYOUT_SCHEDULING
@@ -1650,30 +1694,21 @@ void Document::implicitClose()
frame()->loader()->checkCallImplicitClose();
- // Now do our painting/layout, but only if we aren't in a subframe or if we're in a subframe
- // that has been sized already. Otherwise, our view size would be incorrect, so doing any
- // layout/painting now would be pointless.
+ // We used to force a synchronous display and flush here. This really isn't
+ // necessary and can in fact be actively harmful if pages are loading at a rate of > 60fps
+ // (if your platform is syncing flushes and limiting them to 60fps).
+ m_overMinimumLayoutThreshold = true;
if (!ownerElement() || (ownerElement()->renderer() && !ownerElement()->renderer()->needsLayout())) {
- updateRendering();
+ updateStyleIfNeeded();
// Always do a layout after loading if needed.
if (view() && renderer() && (!renderer()->firstChild() || renderer()->needsLayout()))
view()->layout();
-
- // Paint immediately after the document is ready. We do this to ensure that any timers set by the
- // onload don't have a chance to fire before we would have painted. To avoid over-flushing we only
- // worry about this for the top-level document. For platforms that use native widgets for ScrollViews, this
- // call does nothing (Mac, wx).
- // FIXME: This causes a timing issue with the dispatchDidFinishLoad delegate callback on Mac, so think
- // before enabling it, even if Mac becomes viewless later.
- // See <rdar://problem/5092361>
- if (view() && !ownerElement())
- view()->hostWindow()->paint();
}
#if PLATFORM(MAC)
if (f && renderer() && this == topDocument() && AXObjectCache::accessibilityEnabled())
- axObjectCache()->postNotificationToElement(renderer(), "AXLoadComplete");
+ axObjectCache()->postNotification(renderer(), "AXLoadComplete", true);
#endif
#if ENABLE(SVG)
@@ -1778,11 +1813,8 @@ void Document::clear()
m_tokenizer = 0;
removeChildren();
-
- size_t size = m_windowEventListeners.size();
- for (size_t i = 0; i < size; ++i)
- m_windowEventListeners[i]->setRemoved(true);
- m_windowEventListeners.clear();
+ if (DOMWindow* domWindow = this->domWindow())
+ domWindow->removeAllEventListeners();
}
const KURL& Document::virtualURL() const
@@ -2071,11 +2103,11 @@ void Document::processMetadataSettings(const String& content)
}
#endif
-void Document::processHttpEquiv(const String &equiv, const String &content)
+void Document::processHttpEquiv(const String& equiv, const String& content)
{
ASSERT(!equiv.isNull() && !content.isNull());
- Frame *frame = this->frame();
+ Frame* frame = this->frame();
if (equalIgnoringCase(equiv, "default-style")) {
// The preferred style set has been overridden as per section
@@ -2105,6 +2137,13 @@ void Document::processHttpEquiv(const String &equiv, const String &content)
setContentLanguage(content);
else if (equalIgnoringCase(equiv, "x-dns-prefetch-control"))
parseDNSPrefetchControlHeader(content);
+ else if (equalIgnoringCase(equiv, "x-frame-options")) {
+ FrameLoader* frameLoader = frame->loader();
+ if (frameLoader->shouldInterruptLoadForXFrameOptions(content, url())) {
+ frameLoader->stopAllLoaders();
+ frameLoader->scheduleHTTPRedirection(0, blankURL());
+ }
+ }
}
MouseEventWithHitTestResults Document::prepareMouseEvent(const HitTestRequest& request, const IntPoint& documentPoint, const PlatformMouseEvent& event)
@@ -2118,7 +2157,7 @@ MouseEventWithHitTestResults Document::prepareMouseEvent(const HitTestRequest& r
renderView()->layer()->hitTest(request, result);
if (!request.readOnly())
- updateRendering();
+ updateStyleIfNeeded();
return MouseEventWithHitTestResults(event, result);
}
@@ -2574,7 +2613,7 @@ bool Document::setFocusedNode(PassRefPtr<Node> newFocusedNode)
// Dispatch a change event for text fields or textareas that have been edited
RenderObject* r = static_cast<RenderObject*>(oldFocusedNode.get()->renderer());
if (r && r->isTextControl() && toRenderTextControl(r)->isEdited()) {
- oldFocusedNode->dispatchEventForType(eventNames().changeEvent, true, false);
+ oldFocusedNode->dispatchEvent(eventNames().changeEvent, true, false);
if ((r = static_cast<RenderObject*>(oldFocusedNode.get()->renderer()))) {
if (r->isTextControl())
toRenderTextControl(r)->setEdited(false);
@@ -2649,23 +2688,45 @@ bool Document::setFocusedNode(PassRefPtr<Node> newFocusedNode)
}
}
-#if PLATFORM(MAC)
+#if PLATFORM(MAC) && !PLATFORM(CHROMIUM)
if (!focusChangeBlocked && m_focusedNode && AXObjectCache::accessibilityEnabled())
axObjectCache()->handleFocusedUIElementChanged();
+#elif PLATFORM(GTK)
+ if (!focusChangeBlocked && m_focusedNode && AXObjectCache::accessibilityEnabled()) {
+ RenderObject* oldFocusedRenderer = 0;
+ RenderObject* newFocusedRenderer = 0;
+
+ if (oldFocusedNode)
+ oldFocusedRenderer = oldFocusedNode.get()->renderer();
+ if (newFocusedNode)
+ newFocusedRenderer = newFocusedNode.get()->renderer();
+
+ axObjectCache()->handleFocusedUIElementChangedWithRenderers(oldFocusedRenderer, newFocusedRenderer);
+ }
#endif
SetFocusedNodeDone:
- updateRendering();
+ updateStyleIfNeeded();
return !focusChangeBlocked;
- }
+}
+
+void Document::getFocusableNodes(Vector<RefPtr<Node> >& nodes)
+{
+ updateLayout();
+
+ for (Node* node = firstChild(); node; node = node->traverseNextNode()) {
+ if (node->isFocusable())
+ nodes.append(node);
+ }
+}
void Document::setCSSTarget(Element* n)
{
if (m_cssTarget)
- m_cssTarget->setChanged();
+ m_cssTarget->setNeedsStyleRecalc();
m_cssTarget = n;
if (n)
- n->setChanged();
+ n->setNeedsStyleRecalc();
}
void Document::attachNodeIterator(NodeIterator *ni)
@@ -2758,9 +2819,51 @@ DOMWindow* Document::domWindow() const
{
if (!frame())
return 0;
+
+ // The m_frame pointer is not (not always?) zeroed out when the document is put into b/f cache, so the frame can hold an unrelated document/window pair.
+ // FIXME: We should always zero out the frame pointer on navigation to avoid accidentally accessing the new frame content.
+ if (m_frame->document() != this)
+ return 0;
+
return frame()->domWindow();
}
+void Document::setWindowAttributeEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener)
+{
+ DOMWindow* domWindow = this->domWindow();
+ if (!domWindow)
+ return;
+ domWindow->setAttributeEventListener(eventType, listener);
+}
+
+void Document::dispatchWindowEvent(PassRefPtr<Event> event)
+{
+ ASSERT(!eventDispatchForbidden());
+ DOMWindow* domWindow = this->domWindow();
+ if (!domWindow)
+ return;
+ ExceptionCode ec;
+ domWindow->dispatchEvent(event, ec);
+}
+
+void Document::dispatchWindowEvent(const AtomicString& eventType, bool canBubbleArg, bool cancelableArg)
+{
+ ASSERT(!eventDispatchForbidden());
+ DOMWindow* domWindow = this->domWindow();
+ if (!domWindow)
+ return;
+ domWindow->dispatchEvent(eventType, canBubbleArg, cancelableArg);
+}
+
+void Document::dispatchLoadEvent()
+{
+ ASSERT(!eventDispatchForbidden());
+ DOMWindow* domWindow = this->domWindow();
+ if (!domWindow)
+ return;
+ domWindow->dispatchLoadEvent();
+}
+
PassRefPtr<Event> Document::createEvent(const String& eventType, ExceptionCode& ec)
{
if (eventType == "Event" || eventType == "Events" || eventType == "HTMLEvents")
@@ -2838,141 +2941,6 @@ CSSStyleDeclaration* Document::getOverrideStyle(Element*, const String&)
return 0;
}
-void Document::handleWindowEvent(Event* event, bool useCapture)
-{
- if (m_windowEventListeners.isEmpty())
- return;
-
- // If any HTML event listeners are registered on the window, dispatch them here.
- RegisteredEventListenerVector listenersCopy = m_windowEventListeners;
- size_t size = listenersCopy.size();
- for (size_t i = 0; i < size; ++i) {
- RegisteredEventListener& r = *listenersCopy[i];
- if (r.eventType() == event->type() && r.useCapture() == useCapture && !r.removed())
- r.listener()->handleEvent(event, true);
- }
-}
-
-void Document::setWindowInlineEventListenerForType(const AtomicString& eventType, PassRefPtr<EventListener> listener)
-{
- // If we already have it we don't want removeWindowEventListener to delete it
- removeWindowInlineEventListenerForType(eventType);
- if (listener)
- addWindowEventListener(eventType, listener, false);
-}
-
-EventListener* Document::windowInlineEventListenerForType(const AtomicString& eventType)
-{
- size_t size = m_windowEventListeners.size();
- for (size_t i = 0; i < size; ++i) {
- RegisteredEventListener& r = *m_windowEventListeners[i];
- if (r.eventType() == eventType && r.listener()->isInline())
- return r.listener();
- }
- return 0;
-}
-
-void Document::removeWindowInlineEventListenerForType(const AtomicString& eventType)
-{
- size_t size = m_windowEventListeners.size();
- for (size_t i = 0; i < size; ++i) {
- RegisteredEventListener& r = *m_windowEventListeners[i];
- if (r.eventType() == eventType && r.listener()->isInline()) {
- if (eventType == eventNames().unloadEvent)
- removePendingFrameUnloadEventCount();
- else if (eventType == eventNames().beforeunloadEvent)
- removePendingFrameBeforeUnloadEventCount();
- r.setRemoved(true);
- m_windowEventListeners.remove(i);
- return;
- }
- }
-}
-
-void Document::addWindowEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
-{
- if (eventType == eventNames().unloadEvent)
- addPendingFrameUnloadEventCount();
- else if (eventType == eventNames().beforeunloadEvent)
- addPendingFrameBeforeUnloadEventCount();
- // Remove existing identical listener set with identical arguments.
- // The DOM 2 spec says that "duplicate instances are discarded" in this case.
- removeWindowEventListener(eventType, listener.get(), useCapture);
- addListenerTypeIfNeeded(eventType);
- m_windowEventListeners.append(RegisteredEventListener::create(eventType, listener, useCapture));
-}
-
-void Document::removeWindowEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture)
-{
- size_t size = m_windowEventListeners.size();
- for (size_t i = 0; i < size; ++i) {
- RegisteredEventListener& r = *m_windowEventListeners[i];
- if (r.eventType() == eventType && r.listener() == listener && r.useCapture() == useCapture) {
- if (eventType == eventNames().unloadEvent)
- removePendingFrameUnloadEventCount();
- else if (eventType == eventNames().beforeunloadEvent)
- removePendingFrameBeforeUnloadEventCount();
- r.setRemoved(true);
- m_windowEventListeners.remove(i);
- return;
- }
- }
-}
-
-bool Document::hasWindowEventListener(const AtomicString& eventType)
-{
- size_t size = m_windowEventListeners.size();
- for (size_t i = 0; i < size; ++i) {
- if (m_windowEventListeners[i]->eventType() == eventType)
- return true;
- }
- return false;
-}
-
-void Document::addPendingFrameUnloadEventCount()
-{
- if (m_frame)
- m_frame->eventHandler()->addPendingFrameUnloadEventCount();
-}
-
-void Document::removePendingFrameUnloadEventCount()
-{
- if (m_frame)
- m_frame->eventHandler()->removePendingFrameUnloadEventCount();
-}
-
-void Document::addPendingFrameBeforeUnloadEventCount()
-{
- if (m_frame)
- m_frame->eventHandler()->addPendingFrameBeforeUnloadEventCount();
-}
-
-void Document::removePendingFrameBeforeUnloadEventCount()
-{
- if (m_frame)
- m_frame->eventHandler()->removePendingFrameBeforeUnloadEventCount();
-}
-
-PassRefPtr<EventListener> Document::createEventListener(const String& functionName, const String& code, Node* node)
-{
- Frame* frm = frame();
- if (!frm || !frm->script()->isEnabled())
- return 0;
-
-#if ENABLE(SVG)
- if (node ? node->isSVGElement() : isSVGDocument())
- return frm->script()->createSVGEventHandler(functionName, code, node);
-#endif
-
- // We may want to treat compound document event handlers in a different way, in future.
- return frm->script()->createInlineEventListener(functionName, code, node);
-}
-
-void Document::setWindowInlineEventListenerForTypeAndAttribute(const AtomicString& eventType, Attribute* attr)
-{
- setWindowInlineEventListenerForType(eventType, createEventListener(attr->localName().string(), attr->value(), 0));
-}
-
Element* Document::ownerElement() const
{
if (!frame())
@@ -3001,7 +2969,7 @@ void Document::setCookie(const String& value)
if (cookieURL.isEmpty())
return;
- setCookies(this, cookieURL, policyBaseURL(), value);
+ setCookies(this, cookieURL, value);
}
String Document::referrer() const
@@ -3236,11 +3204,14 @@ void Document::setInPageCache(bool flag)
m_savedRenderer = renderer();
if (FrameView* v = view())
v->resetScrollbars();
+ unscheduleStyleRecalc();
} else {
ASSERT(renderer() == 0 || renderer() == m_savedRenderer);
ASSERT(m_renderArena);
setRenderer(m_savedRenderer);
m_savedRenderer = 0;
+ if (childNeedsStyleRecalc())
+ scheduleStyleRecalc();
}
}
@@ -3357,7 +3328,7 @@ void Document::addMarker(Range *range, DocumentMarker::MarkerType type, String d
for (TextIterator markedText(range); !markedText.atEnd(); markedText.advance()) {
RefPtr<Range> textPiece = markedText.range();
int exception = 0;
- DocumentMarker marker = {type, textPiece->startOffset(exception), textPiece->endOffset(exception), description};
+ DocumentMarker marker = {type, textPiece->startOffset(exception), textPiece->endOffset(exception), description, false};
addMarker(textPiece->startContainer(exception), marker);
}
}
@@ -3782,6 +3753,53 @@ void Document::shiftMarkers(Node *node, unsigned startOffset, int delta, Documen
node->renderer()->repaint();
}
+void Document::setMarkersActive(Range* range, bool active)
+{
+ if (m_markers.isEmpty())
+ return;
+
+ ExceptionCode ec = 0;
+ Node* startContainer = range->startContainer(ec);
+ Node* endContainer = range->endContainer(ec);
+
+ Node* pastLastNode = range->pastLastNode();
+ for (Node* node = range->firstNode(); node != pastLastNode; node = node->traverseNextNode()) {
+ int startOffset = node == startContainer ? range->startOffset(ec) : 0;
+ int endOffset = node == endContainer ? range->endOffset(ec) : INT_MAX;
+ setMarkersActive(node, startOffset, endOffset, active);
+ }
+}
+
+void Document::setMarkersActive(Node* node, unsigned startOffset, unsigned endOffset, bool active)
+{
+ MarkerMapVectorPair* vectorPair = m_markers.get(node);
+ if (!vectorPair)
+ return;
+
+ Vector<DocumentMarker>& markers = vectorPair->first;
+ ASSERT(markers.size() == vectorPair->second.size());
+
+ bool docDirty = false;
+ for (size_t i = 0; i != markers.size(); ++i) {
+ DocumentMarker &marker = markers[i];
+
+ // Markers are returned in order, so stop if we are now past the specified range.
+ if (marker.startOffset >= endOffset)
+ break;
+
+ // Skip marker that is wrong type or before target.
+ if (marker.endOffset < startOffset || marker.type != DocumentMarker::TextMatch)
+ continue;
+
+ marker.activeMatch = active;
+ docDirty = true;
+ }
+
+ // repaint the affected node
+ if (docDirty && node->renderer())
+ node->renderer()->repaint();
+}
+
#if ENABLE(XSLT)
void Document::applyXSLTransform(ProcessingInstruction* pi)
@@ -3848,6 +3866,11 @@ Document *Document::topDocument() const
return doc;
}
+PassRefPtr<Attr> Document::createAttribute(const String& name, ExceptionCode& ec)
+{
+ return createAttributeNS(String(), name, ec, true);
+}
+
PassRefPtr<Attr> Document::createAttributeNS(const String& namespaceURI, const String& qualifiedName, ExceptionCode& ec, bool shouldIgnoreNamespaceChecks)
{
String prefix, localName;
@@ -3887,75 +3910,75 @@ SVGDocumentExtensions* Document::accessSVGExtensions()
PassRefPtr<HTMLCollection> Document::images()
{
- return HTMLCollection::create(this, HTMLCollection::DocImages);
+ return HTMLCollection::create(this, DocImages);
}
PassRefPtr<HTMLCollection> Document::applets()
{
- return HTMLCollection::create(this, HTMLCollection::DocApplets);
+ return HTMLCollection::create(this, DocApplets);
}
PassRefPtr<HTMLCollection> Document::embeds()
{
- return HTMLCollection::create(this, HTMLCollection::DocEmbeds);
+ return HTMLCollection::create(this, DocEmbeds);
}
PassRefPtr<HTMLCollection> Document::plugins()
{
// This is an alias for embeds() required for the JS DOM bindings.
- return HTMLCollection::create(this, HTMLCollection::DocEmbeds);
+ return HTMLCollection::create(this, DocEmbeds);
}
PassRefPtr<HTMLCollection> Document::objects()
{
- return HTMLCollection::create(this, HTMLCollection::DocObjects);
+ return HTMLCollection::create(this, DocObjects);
}
PassRefPtr<HTMLCollection> Document::scripts()
{
- return HTMLCollection::create(this, HTMLCollection::DocScripts);
+ return HTMLCollection::create(this, DocScripts);
}
PassRefPtr<HTMLCollection> Document::links()
{
- return HTMLCollection::create(this, HTMLCollection::DocLinks);
+ return HTMLCollection::create(this, DocLinks);
}
PassRefPtr<HTMLCollection> Document::forms()
{
- return HTMLCollection::create(this, HTMLCollection::DocForms);
+ return HTMLCollection::create(this, DocForms);
}
PassRefPtr<HTMLCollection> Document::anchors()
{
- return HTMLCollection::create(this, HTMLCollection::DocAnchors);
+ return HTMLCollection::create(this, DocAnchors);
}
PassRefPtr<HTMLCollection> Document::all()
{
- return HTMLCollection::create(this, HTMLCollection::DocAll);
+ return HTMLCollection::create(this, DocAll);
}
PassRefPtr<HTMLCollection> Document::windowNamedItems(const String &name)
{
- return HTMLNameCollection::create(this, HTMLCollection::WindowNamedItems, name);
+ return HTMLNameCollection::create(this, WindowNamedItems, name);
}
PassRefPtr<HTMLCollection> Document::documentNamedItems(const String &name)
{
- return HTMLNameCollection::create(this, HTMLCollection::DocumentNamedItems, name);
+ return HTMLNameCollection::create(this, DocumentNamedItems, name);
}
-HTMLCollection::CollectionInfo* Document::nameCollectionInfo(HTMLCollection::Type type, const AtomicString& name)
+CollectionCache* Document::nameCollectionInfo(CollectionType type, const AtomicString& name)
{
- ASSERT(type >= HTMLCollection::FirstNamedDocumentCachedType);
- unsigned index = type - HTMLCollection::FirstNamedDocumentCachedType;
- ASSERT(index < HTMLCollection::NumNamedDocumentCachedTypes);
+ ASSERT(type >= FirstNamedDocumentCachedType);
+ unsigned index = type - FirstNamedDocumentCachedType;
+ ASSERT(index < NumNamedDocumentCachedTypes);
NamedCollectionMap& map = m_nameCollectionInfo[index];
NamedCollectionMap::iterator iter = map.find(name.impl());
if (iter == map.end())
- iter = map.add(name.impl(), new HTMLCollection::CollectionInfo).first;
+ iter = map.add(name.impl(), new CollectionCache).first;
return iter->second;
}
@@ -3974,17 +3997,14 @@ Vector<String> Document::formElementsState() const
{
Vector<String> stateVector;
stateVector.reserveInitialCapacity(m_formElementsWithState.size() * 3);
- typedef ListHashSet<FormControlElementWithState*>::const_iterator Iterator;
+ typedef ListHashSet<Element*>::const_iterator Iterator;
Iterator end = m_formElementsWithState.end();
for (Iterator it = m_formElementsWithState.begin(); it != end; ++it) {
- FormControlElementWithState* e = *it;
+ Element* e = *it;
String value;
- if (e->saveState(value)) {
- FormControlElement* formControlElement = e->toFormControlElement();
- ASSERT(formControlElement);
-
- stateVector.append(formControlElement->name().string());
- stateVector.append(formControlElement->type().string());
+ if (e->saveFormControlState(value)) {
+ stateVector.append(e->formControlName().string());
+ stateVector.append(e->formControlType().string());
stateVector.append(value);
}
}
@@ -4259,6 +4279,34 @@ void Document::updateFocusAppearanceTimerFired(Timer<Document>*)
element->updateFocusAppearance(false);
}
+void Document::executeScriptSoonTimerFired(Timer<Document>* timer)
+{
+ ASSERT_UNUSED(timer, timer == &m_executeScriptSoonTimer);
+
+ Vector<pair<ScriptElementData*, CachedResourceHandle<CachedScript> > > scripts;
+ scripts.swap(m_scriptsToExecuteSoon);
+ size_t size = scripts.size();
+ for (size_t i = 0; i < size; ++i) {
+ scripts[i].first->execute(scripts[i].second.get());
+ scripts[i].first->element()->deref(); // Balances ref() in executeScriptSoon().
+ }
+}
+
+void Document::executeScriptSoon(ScriptElementData* data, CachedResourceHandle<CachedScript> cachedScript)
+{
+ ASSERT_ARG(data, data);
+
+ Element* element = data->element();
+ ASSERT(element);
+ ASSERT(element->document() == this);
+ ASSERT(element->inDocument());
+
+ m_scriptsToExecuteSoon.append(make_pair(data, cachedScript));
+ element->ref(); // Balanced by deref()s in executeScriptSoonTimerFired() and ~Document().
+ if (!m_executeScriptSoonTimer.isActive())
+ m_executeScriptSoonTimer.startOneShot(0);
+}
+
// FF method for accessing the selection added for compatability.
DOMSelection* Document::getSelection() const
{
@@ -4322,6 +4370,14 @@ void Document::resetWMLPageState()
if (WMLPageState* pageState = wmlPageStateForDocument(this))
pageState->reset();
}
+
+void Document::initializeWMLPageState()
+{
+ if (!isWMLDocument())
+ return;
+
+ static_cast<WMLDocument*>(this)->initialize();
+}
#endif
void Document::attachRange(Range* range)
@@ -4435,6 +4491,11 @@ void Document::resourceRetrievedByXMLHttpRequest(unsigned long identifier, const
{
if (page())
page()->inspectorController()->resourceRetrievedByXMLHttpRequest(identifier, sourceString);
+ Frame* frame = this->frame();
+ if (frame) {
+ FrameLoader* frameLoader = frame->loader();
+ frameLoader->didLoadResourceByXMLHttpRequest(identifier, sourceString);
+ }
}
void Document::scriptImported(unsigned long identifier, const String& sourceString)
@@ -4533,4 +4594,16 @@ void Document::displayBufferModifiedByEncoding(UChar* buffer, unsigned len) cons
m_decoder->encoding().displayBuffer(buffer, len);
}
+#if ENABLE(XHTMLMP)
+bool Document::isXHTMLMPDocument() const
+{
+ if (!frame() || !frame()->loader())
+ return false;
+ // As per section 7.2 of OMA-WAP-XHTMLMP-V1_1-20061020-A.pdf, a conforming user agent
+ // MUST accept XHTMLMP document identified as "application/vnd.wap.xhtml+xml"
+ // and SHOULD accept it identified as "application/xhtml+xml"
+ return frame()->loader()->responseMIMEType() == "application/vnd.wap.xhtml+xml" || frame()->loader()->responseMIMEType() == "application/xhtml+xml";
+}
+#endif
+
} // namespace WebCore