/webview/native/Source/WebCore/dom/Document.cpp
C++ | 6127 lines | 4589 code | 989 blank | 549 comment | 1212 complexity | bd9f26ee639f73684538d18164e3df14 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.1, GPL-2.0, LGPL-2.0
Large files files are truncated, but you can click here to view the full file
- /*
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- * (C) 1999 Antti Koivisto (koivisto@kde.org)
- * (C) 2001 Dirk Mueller (mueller@kde.org)
- * (C) 2006 Alexey Proskuryakov (ap@webkit.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2011, 2012 Apple Inc. All rights reserved.
- * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
- * Copyright (C) 2008, 2009, 2011 Google Inc. All rights reserved.
- * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
- * Copyright (C) Research In Motion Limited 2010-2011. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
- #include "config.h"
- #include "Document.h"
- #include "AXObjectCache.h"
- #include "AnimationController.h"
- #include "Attr.h"
- #include "Attribute.h"
- #include "CDATASection.h"
- #include "CSSParser.h"
- #include "CSSStyleDeclaration.h"
- #include "CSSStyleSheet.h"
- #include "CSSValueKeywords.h"
- #include "CachedCSSStyleSheet.h"
- #include "CachedResourceLoader.h"
- #include "Chrome.h"
- #include "ChromeClient.h"
- #include "Comment.h"
- #include "Console.h"
- #include "ContentSecurityPolicy.h"
- #include "ContextFeatures.h"
- #include "CookieJar.h"
- #include "DOMImplementation.h"
- #include "DOMSelection.h"
- #include "DOMWindow.h"
- #include "DateComponents.h"
- #include "DeviceMotionController.h"
- #include "DeviceMotionEvent.h"
- #include "DeviceOrientationController.h"
- #include "DeviceOrientationEvent.h"
- #include "DocumentEventQueue.h"
- #include "DocumentFragment.h"
- #include "DocumentLoader.h"
- #include "DocumentMarkerController.h"
- #include "DocumentType.h"
- #include "EditingText.h"
- #include "Editor.h"
- #include "Element.h"
- #include "ElementShadow.h"
- #include "EntityReference.h"
- #include "Event.h"
- #include "EventFactory.h"
- #include "EventHandler.h"
- #include "EventListener.h"
- #include "EventNames.h"
- #include "ExceptionCode.h"
- #include "FlowThreadController.h"
- #include "FocusController.h"
- #include "FormController.h"
- #include "Frame.h"
- #include "FrameLoader.h"
- #include "FrameLoaderClient.h"
- #include "FrameSelection.h"
- #include "FrameTree.h"
- #include "FrameView.h"
- #include "GeolocationController.h"
- #include "HashChangeEvent.h"
- #include "HistogramSupport.h"
- #include "History.h"
- #include "HTMLAllCollection.h"
- #include "HTMLAnchorElement.h"
- #include "HTMLBodyElement.h"
- #include "HTMLCanvasElement.h"
- #include "HTMLCollection.h"
- #include "HTMLDocument.h"
- #include "HTMLElementFactory.h"
- #include "HTMLFrameOwnerElement.h"
- #include "HTMLHeadElement.h"
- #include "HTMLIFrameElement.h"
- #include "HTMLLinkElement.h"
- #include "HTMLMapElement.h"
- #include "HTMLNameCollection.h"
- #include "HTMLNames.h"
- #include "HTMLParserIdioms.h"
- #include "HTMLStyleElement.h"
- #include "HTMLTitleElement.h"
- #include "HTTPParsers.h"
- #include "HitTestRequest.h"
- #include "HitTestResult.h"
- #include "ImageLoader.h"
- #include "InspectorCounters.h"
- #include "InspectorInstrumentation.h"
- #include "Logging.h"
- #include "MediaQueryList.h"
- #include "MediaQueryMatcher.h"
- #include "MemoryInstrumentation.h"
- #include "MouseEventWithHitTestResults.h"
- #include "NameNodeList.h"
- #include "NestingLevelIncrementer.h"
- #include "NewXMLDocumentParser.h"
- #include "NodeFilter.h"
- #include "NodeIterator.h"
- #include "NodeRareData.h"
- #include "NodeWithIndex.h"
- #include "Page.h"
- #include "PageGroup.h"
- #include "PageTransitionEvent.h"
- #include "PlatformKeyboardEvent.h"
- #include "PluginDocument.h"
- #include "PointerLockController.h"
- #include "PopStateEvent.h"
- #include "ProcessingInstruction.h"
- #include "RegisteredEventListener.h"
- #include "RenderArena.h"
- #include "RenderNamedFlowThread.h"
- #include "RenderTextControl.h"
- #include "RenderView.h"
- #include "RenderWidget.h"
- #include "SchemeRegistry.h"
- #include "ScopedEventQueue.h"
- #include "ScriptCallStack.h"
- #include "ScriptController.h"
- #include "ScriptElement.h"
- #include "ScriptEventListener.h"
- #include "ScriptRunner.h"
- #include "ScrollingCoordinator.h"
- #include "SecurityOrigin.h"
- #include "SecurityPolicy.h"
- #include "SegmentedString.h"
- #include "SelectorQuery.h"
- #include "Settings.h"
- #include "ShadowRoot.h"
- #include "StaticHashSetNodeList.h"
- #include "StyleResolver.h"
- #include "StyleSheetContents.h"
- #include "StyleSheetList.h"
- #include "TextResourceDecoder.h"
- #include "Timer.h"
- #include "TransformSource.h"
- #include "TreeWalker.h"
- #include "UndoManager.h"
- #include "UserContentURLPattern.h"
- #include "WebKitNamedFlow.h"
- #include "WebKitNamedFlowCollection.h"
- #include "XMLDocumentParser.h"
- #include "XMLHttpRequest.h"
- #include "XMLNSNames.h"
- #include "XMLNames.h"
- #include "XPathEvaluator.h"
- #include "XPathExpression.h"
- #include "XPathNSResolver.h"
- #include "XPathResult.h"
- #include "htmlediting.h"
- #include <wtf/CurrentTime.h>
- #include <wtf/HashFunctions.h>
- #include <wtf/MainThread.h>
- #include <wtf/PassRefPtr.h>
- #include <wtf/StdLibExtras.h>
- #include <wtf/text/StringBuffer.h>
- #if ENABLE(SHARED_WORKERS)
- #include "SharedWorkerRepository.h"
- #endif
- #if ENABLE(XSLT)
- #include "XSLTProcessor.h"
- #endif
- #if ENABLE(SVG)
- #include "SVGDocumentExtensions.h"
- #include "SVGElementFactory.h"
- #include "SVGNames.h"
- #include "SVGSVGElement.h"
- #include "SVGStyleElement.h"
- #endif
- #if ENABLE(TOUCH_EVENTS)
- #include "TouchList.h"
- #endif
- #if ENABLE(MATHML)
- #include "MathMLElement.h"
- #include "MathMLElementFactory.h"
- #include "MathMLNames.h"
- #endif
- #if ENABLE(FULLSCREEN_API)
- #include "RenderFullScreen.h"
- #endif
- #if ENABLE(REQUEST_ANIMATION_FRAME)
- #include "RequestAnimationFrameCallback.h"
- #include "ScriptedAnimationController.h"
- #endif
- #if ENABLE(MICRODATA)
- #include "MicroDataItemList.h"
- #include "NodeRareData.h"
- #endif
- #if ENABLE(LINK_PRERENDER)
- #include "Prerenderer.h"
- #endif
- #if ENABLE(TEXT_AUTOSIZING)
- #include "TextAutosizer.h"
- #endif
- using namespace std;
- using namespace WTF;
- using namespace Unicode;
- namespace WebCore {
- using namespace HTMLNames;
- // #define INSTRUMENT_LAYOUT_SCHEDULING 1
- static const unsigned cMaxWriteRecursionDepth = 21;
- // This amount of time must have elapsed before we will even consider scheduling a layout without a delay.
- // FIXME: For faster machines this value can really be lowered to 200. 250 is adequate, but a little high
- // for dual G5s. :)
- static const int cLayoutScheduleThreshold = 250;
- // DOM Level 2 says (letters added):
- //
- // a) Name start characters must have one of the categories Ll, Lu, Lo, Lt, Nl.
- // b) Name characters other than Name-start characters must have one of the categories Mc, Me, Mn, Lm, or Nd.
- // c) Characters in the compatibility area (i.e. with character code greater than #xF900 and less than #xFFFE) are not allowed in XML names.
- // d) Characters which have a font or compatibility decomposition (i.e. those with a "compatibility formatting tag" in field 5 of the database -- marked by field 5 beginning with a "<") are not allowed.
- // e) The following characters are treated as name-start characters rather than name characters, because the property file classifies them as Alphabetic: [#x02BB-#x02C1], #x0559, #x06E5, #x06E6.
- // f) Characters #x20DD-#x20E0 are excluded (in accordance with Unicode, section 5.14).
- // g) Character #x00B7 is classified as an extender, because the property list so identifies it.
- // h) Character #x0387 is added as a name character, because #x00B7 is its canonical equivalent.
- // i) Characters ':' and '_' are allowed as name-start characters.
- // j) Characters '-' and '.' are allowed as name characters.
- //
- // It also contains complete tables. If we decide it's better, we could include those instead of the following code.
- static inline bool isValidNameStart(UChar32 c)
- {
- // rule (e) above
- if ((c >= 0x02BB && c <= 0x02C1) || c == 0x559 || c == 0x6E5 || c == 0x6E6)
- return true;
- // rule (i) above
- if (c == ':' || c == '_')
- return true;
- // rules (a) and (f) above
- const uint32_t nameStartMask = Letter_Lowercase | Letter_Uppercase | Letter_Other | Letter_Titlecase | Number_Letter;
- if (!(Unicode::category(c) & nameStartMask))
- return false;
- // rule (c) above
- if (c >= 0xF900 && c < 0xFFFE)
- return false;
- // rule (d) above
- DecompositionType decompType = decompositionType(c);
- if (decompType == DecompositionFont || decompType == DecompositionCompat)
- return false;
- return true;
- }
- static inline bool isValidNamePart(UChar32 c)
- {
- // rules (a), (e), and (i) above
- if (isValidNameStart(c))
- return true;
- // rules (g) and (h) above
- if (c == 0x00B7 || c == 0x0387)
- return true;
- // rule (j) above
- if (c == '-' || c == '.')
- return true;
- // rules (b) and (f) above
- const uint32_t otherNamePartMask = Mark_NonSpacing | Mark_Enclosing | Mark_SpacingCombining | Letter_Modifier | Number_DecimalDigit;
- if (!(Unicode::category(c) & otherNamePartMask))
- return false;
- // rule (c) above
- if (c >= 0xF900 && c < 0xFFFE)
- return false;
- // rule (d) above
- DecompositionType decompType = decompositionType(c);
- if (decompType == DecompositionFont || decompType == DecompositionCompat)
- return false;
- return true;
- }
- static bool shouldInheritSecurityOriginFromOwner(const KURL& url)
- {
- // http://www.whatwg.org/specs/web-apps/current-work/#origin-0
- //
- // If a Document has the address "about:blank"
- // The origin of the Document is the origin it was assigned when its browsing context was created.
- //
- // Note: We generalize this to all "blank" URLs and invalid URLs because we
- // treat all of these URLs as about:blank.
- //
- return !url.isValid() || url.isBlankURL();
- }
- static Widget* widgetForNode(Node* focusedNode)
- {
- if (!focusedNode)
- return 0;
- RenderObject* renderer = focusedNode->renderer();
- if (!renderer || !renderer->isWidget())
- return 0;
- return toRenderWidget(renderer)->widget();
- }
- static bool acceptsEditingFocus(Node* node)
- {
- ASSERT(node);
- ASSERT(node->rendererIsEditable());
- Node* root = node->rootEditableElement();
- Frame* frame = node->document()->frame();
- if (!frame || !root)
- return false;
- return frame->editor()->shouldBeginEditing(rangeOfContents(root).get());
- }
- static bool canAccessAncestor(const SecurityOrigin* activeSecurityOrigin, Frame* targetFrame)
- {
- // targetFrame can be 0 when we're trying to navigate a top-level frame
- // that has a 0 opener.
- if (!targetFrame)
- return false;
- const bool isLocalActiveOrigin = activeSecurityOrigin->isLocal();
- for (Frame* ancestorFrame = targetFrame; ancestorFrame; ancestorFrame = ancestorFrame->tree()->parent()) {
- Document* ancestorDocument = ancestorFrame->document();
- // FIXME: Should be an ASSERT? Frames should alway have documents.
- if (!ancestorDocument)
- return true;
- const SecurityOrigin* ancestorSecurityOrigin = ancestorDocument->securityOrigin();
- if (activeSecurityOrigin->canAccess(ancestorSecurityOrigin))
- return true;
-
- // Allow file URL descendant navigation even when allowFileAccessFromFileURLs is false.
- // FIXME: It's a bit strange to special-case local origins here. Should we be doing
- // something more general instead?
- if (isLocalActiveOrigin && ancestorSecurityOrigin->isLocal())
- return true;
- }
- return false;
- }
- static void printNavigationErrorMessage(Frame* frame, const KURL& activeURL)
- {
- // FIXME: this error message should contain more specifics of why the navigation change is not allowed.
- String message = "Unsafe JavaScript attempt to initiate a navigation change for frame with URL " +
- frame->document()->url().string() + " from frame with URL " + activeURL.string() + ".\n";
- // FIXME: should we print to the console of the document performing the navigation instead?
- frame->domWindow()->printErrorMessage(message);
- }
- static HashSet<Document*>* documentsThatNeedStyleRecalc = 0;
- class DocumentWeakReference : public ThreadSafeRefCounted<DocumentWeakReference> {
- public:
- static PassRefPtr<DocumentWeakReference> create(Document* document)
- {
- return adoptRef(new DocumentWeakReference(document));
- }
- Document* document()
- {
- ASSERT(isMainThread());
- return m_document;
- }
- void clear()
- {
- ASSERT(isMainThread());
- m_document = 0;
- }
- private:
- DocumentWeakReference(Document* document)
- : m_document(document)
- {
- ASSERT(isMainThread());
- }
- Document* m_document;
- };
- uint64_t Document::s_globalTreeVersion = 0;
- Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML)
- : ContainerNode(0, CreateDocument)
- , TreeScope(this)
- , m_guardRefCount(0)
- , m_contextFeatures(ContextFeatures::defaultSwitch())
- , m_compatibilityMode(NoQuirksMode)
- , m_compatibilityModeLocked(false)
- , m_domTreeVersion(++s_globalTreeVersion)
- #if ENABLE(MUTATION_OBSERVERS)
- , m_mutationObserverTypes(0)
- #endif
- , m_styleSheets(StyleSheetList::create(this))
- , m_hadActiveLoadingStylesheet(false)
- , m_readyState(Complete)
- , m_styleRecalcTimer(this, &Document::styleRecalcTimerFired)
- , m_pendingStyleRecalcShouldForce(false)
- , m_frameElementsShouldIgnoreScrolling(false)
- , m_containsValidityStyleRules(false)
- , m_updateFocusAppearanceRestoresSelection(false)
- , m_ignoreDestructiveWriteCount(0)
- , m_titleSetExplicitly(false)
- , m_updateFocusAppearanceTimer(this, &Document::updateFocusAppearanceTimerFired)
- , m_loadEventFinished(false)
- , m_startTime(currentTime())
- , m_overMinimumLayoutThreshold(false)
- , m_scriptRunner(ScriptRunner::create(this))
- , m_xmlVersion("1.0")
- , m_xmlStandalone(StandaloneUnspecified)
- , m_hasXMLDeclaration(0)
- , m_savedRenderer(0)
- , m_designMode(inherit)
- #if ENABLE(DASHBOARD_SUPPORT)
- , m_hasDashboardRegions(false)
- , m_dashboardRegionsDirty(false)
- #endif
- , m_createRenderers(true)
- , m_inPageCache(false)
- , m_accessKeyMapValid(false)
- , m_useSecureKeyboardEntryWhenActive(false)
- , m_isXHTML(isXHTML)
- , m_isHTML(isHTML)
- , m_isViewSource(false)
- , m_sawElementsInKnownNamespaces(false)
- , m_isSrcdocDocument(false)
- , m_documentRareData(0)
- , m_eventQueue(DocumentEventQueue::create(this))
- , m_weakReference(DocumentWeakReference::create(this))
- , m_idAttributeName(idAttr)
- #if ENABLE(FULLSCREEN_API)
- , m_areKeysEnabledInFullScreen(0)
- , m_fullScreenRenderer(0)
- , m_fullScreenChangeDelayTimer(this, &Document::fullScreenChangeDelayTimerFired)
- , m_isAnimatingFullScreen(false)
- #endif
- , m_loadEventDelayCount(0)
- , m_loadEventDelayTimer(this, &Document::loadEventDelayTimerFired)
- , m_referrerPolicy(ReferrerPolicyDefault)
- , m_directionSetOnDocumentElement(false)
- , m_writingModeSetOnDocumentElement(false)
- , m_writeRecursionIsTooDeep(false)
- , m_writeRecursionDepth(0)
- , m_wheelEventHandlerCount(0)
- , m_touchEventHandlerCount(0)
- #if ENABLE(UNDO_MANAGER)
- , m_undoManager(0)
- #endif
- , m_pendingTasksTimer(this, &Document::pendingTasksTimerFired)
- , m_scheduledTasksAreSuspended(false)
- , m_visualUpdatesAllowed(true)
- , m_visualUpdatesSuppressionTimer(this, &Document::visualUpdatesSuppressionTimerFired)
- #ifndef NDEBUG
- , m_didDispatchViewportPropertiesChanged(false)
- #endif
- {
- m_document = this;
- m_pageGroupUserSheetCacheValid = false;
- m_printing = false;
- m_paginatedForScreen = false;
- m_ignoreAutofocus = false;
- m_frame = frame;
- if (m_frame)
- provideContextFeaturesToDocumentFrom(this, m_frame->page());
- // We depend on the url getting immediately set in subframes, but we
- // also depend on the url NOT getting immediately set in opened windows.
- // See fast/dom/early-frame-url.html
- // and fast/dom/location-new-window-no-crash.html, respectively.
- // FIXME: Can/should we unify this behavior?
- if ((frame && frame->ownerElement()) || !url.isEmpty())
- setURL(url);
- m_axObjectCache = 0;
- m_markers = adoptPtr(new DocumentMarkerController);
- m_cachedResourceLoader = adoptPtr(new CachedResourceLoader(this));
- #if ENABLE(LINK_PRERENDER)
- m_prerenderer = Prerenderer::create(this);
- #endif
- #if ENABLE(TEXT_AUTOSIZING)
- m_textAutosizer = TextAutosizer::create(this);
- #endif
- m_visuallyOrdered = false;
- m_bParsing = false;
- m_wellFormed = false;
- m_textColor = Color::black;
- m_listenerTypes = 0;
- m_inStyleRecalc = false;
- m_closeAfterStyleRecalc = false;
- m_usesSiblingRules = false;
- m_usesSiblingRulesOverride = false;
- m_usesFirstLineRules = false;
- m_usesFirstLetterRules = false;
- m_usesBeforeAfterRules = false;
- m_usesBeforeAfterRulesOverride = false;
- m_usesRemUnits = false;
- m_usesLinkRules = false;
- m_gotoAnchorNeededAfterStylesheetsLoad = false;
- m_didCalculateStyleResolver = false;
- m_hasDirtyStyleResolver = false;
- m_pendingStylesheets = 0;
- m_ignorePendingStylesheets = false;
- m_hasNodesWithPlaceholderStyle = false;
- m_pendingSheetLayout = NoLayoutWithPendingSheets;
- m_cssTarget = 0;
- resetLinkColor();
- resetVisitedLinkColor();
- resetActiveLinkColor();
- m_processingLoadEvent = false;
-
- initSecurityContext();
- initDNSPrefetch();
- static int docID = 0;
- m_docID = docID++;
- for (unsigned i = 0; i < WTF_ARRAY_LENGTH(m_nodeListCounts); i++)
- m_nodeListCounts[i] = 0;
- for (unsigned i = 0; i < WTF_ARRAY_LENGTH(m_collections); i++)
- m_collections[i] = 0;
- InspectorCounters::incrementCounter(InspectorCounters::DocumentCounter);
- }
- static void histogramMutationEventUsage(const unsigned short& listenerTypes)
- {
- HistogramSupport::histogramEnumeration("DOMAPI.PerDocumentMutationEventUsage.DOMSubtreeModified", static_cast<bool>(listenerTypes & Document::DOMSUBTREEMODIFIED_LISTENER), 2);
- HistogramSupport::histogramEnumeration("DOMAPI.PerDocumentMutationEventUsage.DOMNodeInserted", static_cast<bool>(listenerTypes & Document::DOMNODEINSERTED_LISTENER), 2);
- HistogramSupport::histogramEnumeration("DOMAPI.PerDocumentMutationEventUsage.DOMNodeRemoved", static_cast<bool>(listenerTypes & Document::DOMNODEREMOVED_LISTENER), 2);
- HistogramSupport::histogramEnumeration("DOMAPI.PerDocumentMutationEventUsage.DOMNodeRemovedFromDocument", static_cast<bool>(listenerTypes & Document::DOMNODEREMOVEDFROMDOCUMENT_LISTENER), 2);
- HistogramSupport::histogramEnumeration("DOMAPI.PerDocumentMutationEventUsage.DOMNodeInsertedIntoDocument", static_cast<bool>(listenerTypes & Document::DOMNODEINSERTEDINTODOCUMENT_LISTENER), 2);
- HistogramSupport::histogramEnumeration("DOMAPI.PerDocumentMutationEventUsage.DOMCharacterDataModified", static_cast<bool>(listenerTypes & Document::DOMCHARACTERDATAMODIFIED_LISTENER), 2);
- }
- #if ENABLE(FULLSCREEN_API)
- static bool isAttributeOnAllOwners(const WebCore::QualifiedName& attribute, const HTMLFrameOwnerElement* owner)
- {
- if (!owner)
- return true;
- do {
- if (!owner->hasAttribute(attribute))
- return false;
- } while ((owner = owner->document()->ownerElement()));
- return true;
- }
- #endif
- Document::~Document()
- {
- ASSERT(!renderer());
- ASSERT(!m_inPageCache);
- ASSERT(!m_savedRenderer);
- ASSERT(m_ranges.isEmpty());
- ASSERT(!m_styleRecalcTimer.isActive());
- ASSERT(!m_parentTreeScope);
- ASSERT(!m_guardRefCount);
- m_scriptRunner.clear();
- histogramMutationEventUsage(m_listenerTypes);
- removeAllEventListeners();
- // Currently we believe that Document can never outlive the parser.
- // Although the Document may be replaced synchronously, DocumentParsers
- // generally keep at least one reference to an Element which would in turn
- // has a reference to the Document. If you hit this ASSERT, then that
- // assumption is wrong. DocumentParser::detach() should ensure that even
- // if the DocumentParser outlives the Document it won't cause badness.
- ASSERT(!m_parser || m_parser->refCount() == 1);
- detachParser();
- m_renderArena.clear();
- clearAXObjectCache();
- m_decoder = 0;
- if (m_styleSheets)
- m_styleSheets->documentDestroyed();
- if (m_namedFlows)
- m_namedFlows->documentDestroyed();
- if (m_elemSheet)
- m_elemSheet->clearOwnerNode();
- if (m_pageUserSheet)
- m_pageUserSheet->clearOwnerNode();
- if (m_pageGroupUserSheets) {
- for (size_t i = 0; i < m_pageGroupUserSheets->size(); ++i)
- (*m_pageGroupUserSheets)[i]->clearOwnerNode();
- }
- if (m_userSheets) {
- for (size_t i = 0; i < m_userSheets->size(); ++i)
- (*m_userSheets)[i]->clearOwnerNode();
- }
- deleteCustomFonts();
- m_weakReference->clear();
- if (m_mediaQueryMatcher)
- m_mediaQueryMatcher->documentDestroyed();
- clearStyleResolver(); // We need to destory CSSFontSelector before destroying m_cachedResourceLoader.
- m_cachedResourceLoader.clear();
- #if ENABLE(UNDO_MANAGER)
- if (m_undoManager)
- m_undoManager->undoScopeHostDestroyed();
- #endif
- // We must call clearRareData() here since a Document class inherits TreeScope
- // as well as Node. See a comment on TreeScope.h for the reason.
- if (hasRareData())
- clearRareData();
- ASSERT(!m_listsInvalidatedAtDocument.size());
- for (unsigned i = 0; i < WTF_ARRAY_LENGTH(m_nodeListCounts); i++)
- ASSERT(!m_nodeListCounts[i]);
- for (unsigned i = 0; i < WTF_ARRAY_LENGTH(m_collections); i++)
- ASSERT(!m_collections[i]);
- m_document = 0;
- InspectorCounters::decrementCounter(InspectorCounters::DocumentCounter);
- }
- void Document::removedLastRef()
- {
- ASSERT(!m_deletionHasBegun);
- if (m_guardRefCount) {
- // If removing a child removes the last self-only ref, we don't
- // want the scope to be destructed until after
- // removeAllChildren returns, so we guard ourselves with an
- // extra self-only ref.
- guardRef();
- // We must make sure not to be retaining any of our children through
- // these extra pointers or we will create a reference cycle.
- m_docType = 0;
- m_focusedNode = 0;
- m_hoverNode = 0;
- m_activeNode = 0;
- m_titleElement = 0;
- m_documentElement = 0;
- m_contextFeatures = ContextFeatures::defaultSwitch();
- #if ENABLE(FULLSCREEN_API)
- m_fullScreenElement = 0;
- m_fullScreenElementStack.clear();
- #endif
- detachParser();
- // removeAllChildren() doesn't always unregister IDs,
- // so tear down scope information upfront to avoid having stale references in the map.
- destroyTreeScopeData();
- removeAllChildren();
- m_markers->detach();
- m_cssCanvasElements.clear();
- #if ENABLE(REQUEST_ANIMATION_FRAME)
- // FIXME: consider using ActiveDOMObject.
- if (m_scriptedAnimationController)
- m_scriptedAnimationController->clearDocumentPointer();
- m_scriptedAnimationController.clear();
- #endif
- #ifndef NDEBUG
- m_inRemovedLastRefFunction = false;
- #endif
- guardDeref();
- } else {
- #ifndef NDEBUG
- m_deletionHasBegun = true;
- #endif
- delete this;
- }
- }
- Element* Document::getElementById(const AtomicString& id) const
- {
- return TreeScope::getElementById(id);
- }
- Element* Document::getElementByAccessKey(const String& key)
- {
- if (key.isEmpty())
- return 0;
- if (!m_accessKeyMapValid) {
- buildAccessKeyMap(this);
- m_accessKeyMapValid = true;
- }
- return m_elementsByAccessKey.get(key.impl());
- }
- void Document::buildAccessKeyMap(TreeScope* scope)
- {
- ASSERT(scope);
- Node* rootNode = scope->rootNode();
- for (Node* node = rootNode; node; node = node->traverseNextNode(rootNode)) {
- if (!node->isElementNode())
- continue;
- Element* element = static_cast<Element*>(node);
- const AtomicString& accessKey = element->getAttribute(accesskeyAttr);
- if (!accessKey.isEmpty())
- m_elementsByAccessKey.set(accessKey.impl(), element);
- for (ShadowRoot* root = node->youngestShadowRoot(); root; root = root->olderShadowRoot())
- buildAccessKeyMap(root);
- }
- }
- void Document::invalidateAccessKeyMap()
- {
- m_accessKeyMapValid = false;
- m_elementsByAccessKey.clear();
- }
- SelectorQueryCache* Document::selectorQueryCache()
- {
- if (!m_selectorQueryCache)
- m_selectorQueryCache = adoptPtr(new SelectorQueryCache());
- return m_selectorQueryCache.get();
- }
- MediaQueryMatcher* Document::mediaQueryMatcher()
- {
- if (!m_mediaQueryMatcher)
- m_mediaQueryMatcher = MediaQueryMatcher::create(this);
- return m_mediaQueryMatcher.get();
- }
- void Document::setCompatibilityMode(CompatibilityMode mode)
- {
- if (m_compatibilityModeLocked || mode == m_compatibilityMode)
- return;
- ASSERT(!m_styleSheets->length());
- bool wasInQuirksMode = inQuirksMode();
- m_compatibilityMode = mode;
- selectorQueryCache()->invalidate();
- if (inQuirksMode() != wasInQuirksMode) {
- // All user stylesheets have to reparse using the different mode.
- clearPageUserSheet();
- clearPageGroupUserSheets();
- }
- }
- String Document::compatMode() const
- {
- return inQuirksMode() ? "BackCompat" : "CSS1Compat";
- }
- void Document::resetLinkColor()
- {
- m_linkColor = Color(0, 0, 238);
- }
- void Document::resetVisitedLinkColor()
- {
- m_visitedLinkColor = Color(85, 26, 139);
- }
- void Document::resetActiveLinkColor()
- {
- m_activeLinkColor.setNamedColor("red");
- }
- void Document::setDocType(PassRefPtr<DocumentType> docType)
- {
- // This should never be called more than once.
- ASSERT(!m_docType || !docType);
- m_docType = docType;
- if (m_docType) {
- this->adoptIfNeeded(m_docType.get());
- #if ENABLE(LEGACY_VIEWPORT_ADAPTION)
- if (m_docType->publicId().startsWith("-//wapforum//dtd xhtml mobile 1.", /* caseSensitive */ false))
- processViewport("width=device-width, height=device-height", ViewportArguments::XHTMLMobileProfile);
- #endif
- }
- // Doctype affects the interpretation of the stylesheets.
- clearStyleResolver();
- }
- DOMImplementation* Document::implementation()
- {
- if (!m_implementation)
- m_implementation = DOMImplementation::create(this);
- return m_implementation.get();
- }
- void Document::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
- {
- ContainerNode::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
-
- Element* newDocumentElement = firstElementChild(this);
- if (newDocumentElement == m_documentElement)
- return;
- m_documentElement = newDocumentElement;
- // The root style used for media query matching depends on the document element.
- clearStyleResolver();
- }
- PassRefPtr<Element> Document::createElement(const AtomicString& name, ExceptionCode& ec)
- {
- if (!isValidName(name)) {
- ec = INVALID_CHARACTER_ERR;
- return 0;
- }
- if (m_isXHTML)
- return HTMLElementFactory::createHTMLElement(QualifiedName(nullAtom, name, xhtmlNamespaceURI), this, 0, false);
- return createElement(QualifiedName(nullAtom, name, nullAtom), false);
- }
- PassRefPtr<DocumentFragment> Document::createDocumentFragment()
- {
- return DocumentFragment::create(document());
- }
- PassRefPtr<Text> Document::createTextNode(const String& data)
- {
- return Text::create(this, data);
- }
- PassRefPtr<Comment> Document::createComment(const String& data)
- {
- return Comment::create(this, data);
- }
- PassRefPtr<CDATASection> Document::createCDATASection(const String& data, ExceptionCode& ec)
- {
- if (isHTMLDocument()) {
- ec = NOT_SUPPORTED_ERR;
- return 0;
- }
- return CDATASection::create(this, data);
- }
- PassRefPtr<ProcessingInstruction> Document::createProcessingInstruction(const String& target, const String& data, ExceptionCode& ec)
- {
- if (!isValidName(target)) {
- ec = INVALID_CHARACTER_ERR;
- return 0;
- }
- if (isHTMLDocument()) {
- ec = NOT_SUPPORTED_ERR;
- return 0;
- }
- return ProcessingInstruction::create(this, target, data);
- }
- PassRefPtr<EntityReference> Document::createEntityReference(const String& name, ExceptionCode& ec)
- {
- if (!isValidName(name)) {
- ec = INVALID_CHARACTER_ERR;
- return 0;
- }
- if (isHTMLDocument()) {
- ec = NOT_SUPPORTED_ERR;
- return 0;
- }
- return EntityReference::create(this, name);
- }
- PassRefPtr<EditingText> Document::createEditingTextNode(const String& text)
- {
- return EditingText::create(this, text);
- }
- PassRefPtr<CSSStyleDeclaration> Document::createCSSStyleDeclaration()
- {
- return StylePropertySet::create()->ensureCSSStyleDeclaration();
- }
- PassRefPtr<Node> Document::importNode(Node* importedNode, bool deep, ExceptionCode& ec)
- {
- ec = 0;
-
- if (!importedNode) {
- ec = NOT_SUPPORTED_ERR;
- return 0;
- }
- switch (importedNode->nodeType()) {
- case TEXT_NODE:
- return createTextNode(importedNode->nodeValue());
- case CDATA_SECTION_NODE:
- return createCDATASection(importedNode->nodeValue(), ec);
- case ENTITY_REFERENCE_NODE:
- return createEntityReference(importedNode->nodeName(), ec);
- case PROCESSING_INSTRUCTION_NODE:
- return createProcessingInstruction(importedNode->nodeName(), importedNode->nodeValue(), ec);
- case COMMENT_NODE:
- return createComment(importedNode->nodeValue());
- case ELEMENT_NODE: {
- Element* oldElement = static_cast<Element*>(importedNode);
- // FIXME: The following check might be unnecessary. Is it possible that
- // oldElement has mismatched prefix/namespace?
- if (!hasValidNamespaceForElements(oldElement->tagQName())) {
- ec = NAMESPACE_ERR;
- return 0;
- }
- RefPtr<Element> newElement = createElement(oldElement->tagQName(), ec);
- if (ec)
- return 0;
- newElement->cloneDataFromElement(*oldElement);
- if (deep) {
- for (Node* oldChild = oldElement->firstChild(); oldChild; oldChild = oldChild->nextSibling()) {
- RefPtr<Node> newChild = importNode(oldChild, true, ec);
- if (ec)
- return 0;
- newElement->appendChild(newChild.release(), ec);
- if (ec)
- return 0;
- }
- }
- return newElement.release();
- }
- case ATTRIBUTE_NODE:
- return Attr::create(this, QualifiedName(nullAtom, static_cast<Attr*>(importedNode)->name(), nullAtom), static_cast<Attr*>(importedNode)->value());
- case DOCUMENT_FRAGMENT_NODE: {
- if (importedNode->isShadowRoot()) {
- // ShadowRoot nodes should not be explicitly importable.
- // Either they are imported along with their host node, or created implicitly.
- break;
- }
- DocumentFragment* oldFragment = static_cast<DocumentFragment*>(importedNode);
- RefPtr<DocumentFragment> newFragment = createDocumentFragment();
- if (deep) {
- for (Node* oldChild = oldFragment->firstChild(); oldChild; oldChild = oldChild->nextSibling()) {
- RefPtr<Node> newChild = importNode(oldChild, true, ec);
- if (ec)
- return 0;
- newFragment->appendChild(newChild.release(), ec);
- if (ec)
- return 0;
- }
- }
-
- return newFragment.release();
- }
- case ENTITY_NODE:
- case NOTATION_NODE:
- // FIXME: It should be possible to import these node types, however in DOM3 the DocumentType is readonly, so there isn't much sense in doing that.
- // Ability to add these imported nodes to a DocumentType will be considered for addition to a future release of the DOM.
- case DOCUMENT_NODE:
- case DOCUMENT_TYPE_NODE:
- case XPATH_NAMESPACE_NODE:
- break;
- }
- ec = NOT_SUPPORTED_ERR;
- return 0;
- }
- PassRefPtr<Node> Document::adoptNode(PassRefPtr<Node> source, ExceptionCode& ec)
- {
- if (!source) {
- ec = NOT_SUPPORTED_ERR;
- return 0;
- }
- if (source->isReadOnlyNode()) {
- ec = NO_MODIFICATION_ALLOWED_ERR;
- return 0;
- }
- EventQueueScope scope;
- switch (source->nodeType()) {
- case ENTITY_NODE:
- case NOTATION_NODE:
- case DOCUMENT_NODE:
- case DOCUMENT_TYPE_NODE:
- case XPATH_NAMESPACE_NODE:
- ec = NOT_SUPPORTED_ERR;
- return 0;
- case ATTRIBUTE_NODE: {
- Attr* attr = static_cast<Attr*>(source.get());
- if (attr->ownerElement())
- attr->ownerElement()->removeAttributeNode(attr, ec);
- attr->setSpecified(true);
- break;
- }
- default:
- if (source->isShadowRoot()) {
- // ShadowRoot cannot disconnect itself from the host node.
- ec = HIERARCHY_REQUEST_ERR;
- return 0;
- }
- // FIXME: What about <frame> and <object>?
- if (source->hasTagName(iframeTag)) {
- HTMLIFrameElement* iframe = static_cast<HTMLIFrameElement*>(source.get());
- if (frame() && frame()->tree()->isDescendantOf(iframe->contentFrame())) {
- ec = HIERARCHY_REQUEST_ERR;
- return 0;
- }
- }
- if (source->parentNode())
- source->parentNode()->removeChild(source.get(), ec);
- }
- this->adoptIfNeeded(source.get());
- return source;
- }
- bool Document::hasValidNamespaceForElements(const QualifiedName& qName)
- {
- // These checks are from DOM Core Level 2, createElementNS
- // http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-DocCrElNS
- if (!qName.prefix().isEmpty() && qName.namespaceURI().isNull()) // createElementNS(null, "html:div")
- return false;
- if (qName.prefix() == xmlAtom && qName.namespaceURI() != XMLNames::xmlNamespaceURI) // createElementNS("http://www.example.com", "xml:lang")
- return false;
- // Required by DOM Level 3 Core and unspecified by DOM Level 2 Core:
- // http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#ID-DocCrElNS
- // createElementNS("http://www.w3.org/2000/xmlns/", "foo:bar"), createElementNS(null, "xmlns:bar")
- if ((qName.prefix() == xmlnsAtom && qName.namespaceURI() != XMLNSNames::xmlnsNamespaceURI) || (qName.prefix() != xmlnsAtom && qName.namespaceURI() == XMLNSNames::xmlnsNamespaceURI))
- return false;
- return true;
- }
- bool Document::hasValidNamespaceForAttributes(const QualifiedName& qName)
- {
- // Spec: DOM Level 2 Core: http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-ElSetAttrNS
- if (qName.prefix().isEmpty() && qName.localName() == xmlnsAtom) {
- // Note: The case of an "xmlns" qualified name with a namespace of
- // xmlnsNamespaceURI is specifically allowed (See <http://www.w3.org/2000/xmlns/>).
- return qName.namespaceURI() == XMLNSNames::xmlnsNamespaceURI;
- }
- return hasValidNamespaceForElements(qName);
- }
- // FIXME: This should really be in a possible ElementFactory class
- PassRefPtr<Element> Document::createElement(const QualifiedName& qName, bool createdByParser)
- {
- RefPtr<Element> e;
- // FIXME: Use registered namespaces and look up in a hash to find the right factory.
- if (qName.namespaceURI() == xhtmlNamespaceURI)
- e = HTMLElementFactory::createHTMLElement(qName, this, 0, createdByParser);
- #if ENABLE(SVG)
- else if (qName.namespaceURI() == SVGNames::svgNamespaceURI)
- e = SVGElementFactory::createSVGElement(qName, this, createdByParser);
- #endif
- #if ENABLE(MATHML)
- else if (qName.namespaceURI() == MathMLNames::mathmlNamespaceURI)
- e = MathMLElementFactory::createMathMLElement(qName, this, createdByParser);
- #endif
- if (e)
- m_sawElementsInKnownNamespaces = true;
- else
- e = Element::create(qName, document());
- // <image> uses imgTag so we need a special rule.
- ASSERT((qName.matches(imageTag) && e->tagQName().matches(imgTag) && e->tagQName().prefix() == qName.prefix()) || qName == e->tagQName());
- return e.release();
- }
- bool Document::regionBasedColumnsEnabled() const
- {
- return settings() && settings()->regionBasedColumnsEnabled();
- }
- bool Document::cssRegionsEnabled() const
- {
- return settings() && settings()->cssRegionsEnabled();
- }
- bool Document::cssGridLayoutEnabled() const
- {
- return settings() && settings()->cssGridLayoutEnabled();
- }
- #if ENABLE(CSS_REGIONS)
- PassRefPtr<WebKitNamedFlow> Document::webkitGetFlowByName(const String& flowName)
- {
- if (!cssRegionsEnabled() || !renderer())
- return 0;
- // It's possible to have pending styles not applied that affect the existing flows.
- updateStyleIfNeeded();
- return namedFlows()->flowByName(flowName);
- }
- #endif
- WebKitNamedFlowCollection* Document::namedFlows()
- {
- if (!m_namedFlows)
- m_namedFlows = WebKitNamedFlowCollection::create(this);
- return m_namedFlows.get();
- }
- PassRefPtr<Element> Document::createElementNS(const String& namespaceURI, const String& qualifiedName, ExceptionCode& ec)
- {
- String prefix, localName;
- if (!parseQualifiedName(qualifiedName, prefix, localName, ec))
- return 0;
- QualifiedName qName(prefix, localName, namespaceURI);
- if (!hasValidNamespaceForElements(qName)) {
- ec = NAMESPACE_ERR;
- return 0;
- }
- return createElement(qName, false);
- }
- String Document::readyState() const
- {
- DEFINE_STATIC_LOCAL(const String, loading, ("loading"));
- DEFINE_STATIC_LOCAL(const String, interactive, ("interactive"));
- DEFINE_STATIC_LOCAL(const String, complete, ("complete"));
- switch (m_readyState) {
- case Loading:
- return loading;
- case Interactive:
- return interactive;
- case Complete:
- return complete;
- }
- ASSERT_NOT_REACHED();
- return String();
- }
- void Document::setReadyState(ReadyState readyState)
- {
- if (readyState == m_readyState)
- return;
- switch (readyState) {
- case Loading:
- if (!m_documentTiming.domLoading)
- m_documentTiming.domLoading = monotonicallyIncreasingTime();
- break;
- case Interactive:
- if (!m_documentTiming.domInteractive)
- m_documentTiming.domInteractive = monotonicallyIncreasingTime();
- break;
- case Complete:
- if (!m_documentTiming.domComplete)
- m_documentTiming.domComplete = monotonicallyIncreasingTime();
- break;
- }
- m_readyState = readyState;
- dispatchEvent(Event::create(eventNames().readystatechangeEvent, false, false));
-
- if (settings() && settings()->suppressesIncrementalRendering())
- setVisualUpdatesAllowed(readyState);
- }
- void Document::setVisualUpdatesAllowed(ReadyState readyState)
- {
- ASSERT(settings() && settings()->suppressesIncrementalRendering());
- switch (readyState) {
- case Loading:
- ASSERT(!m_visualUpdatesSuppressionTimer.isActive());
- ASSERT(m_visualUpdatesAllowed);
- m_visualUpdatesSuppressionTimer.startOneShot(settings()->incrementalRenderingSuppressionTimeoutInSeconds());
- setVisualUpdatesAllowed(false);
- break;
- case Interactive:
- ASSERT(m_visualUpdatesSuppressionTimer.isActive() || m_visualUpdatesAllowed);
- break;
- case Complete:
- if (m_visualUpdatesSuppressionTimer.isActive()) {
- ASSERT(!m_visualUpdatesAllowed);
- m_visualUpdatesSuppressionTimer.stop();
- setVisualUpdatesAllowed(true);
- } else
- ASSERT(m_visualUpdatesAllowed);
- break;
- }
- }
-
- void Document::setVisualUpdatesAllowed(bool visualUpdatesAllowed)
- {
- if (m_visualUpdatesAllowed == visualUpdatesAllowed)
- return;
- m_visualUpdatesAllowed = visualUpdatesAllowed;
- if (!visualUpdatesAllowed)
- return;
- #if USE(ACCELERATED_COMPOSITING)
- if (view())
- view()->updateCompositingLayersAfterLayout();
- #endif
- if (renderer())
- renderer()->repaint();
- }
- void Document::visualUpdatesSuppressionTimerFired(Timer<Document>*)
- {
- ASSERT(!m_visualUpdatesAllowed);
- setVisualUpdatesAllowed(true);
- }
- String Document::encoding() const
- {
- if (TextResourceDecoder* d = decoder())
- return d->encoding().domName();
- return String();
- }
- String Document::defaultCharset() const
- {
- if (Settings* settings = this->settings())
- return settings->defaultTextEncodingName();
- return String();
- }
- void Document::setCharset(const String& charset)
- {
- if (!decoder())
- return;
- decoder()->setEncoding(charset, TextResourceDecoder::UserChosenEncoding);
- }
- void Document::setContentLanguage(const String& language)
- {
- if (m_contentLanguage == language)
- return;
- m_contentLanguage = language;
- // Recalculate style so language is used when selecting the initial font.
- styleResolverChanged(DeferRecalcStyle);
- }
- void Document::setXMLVersion(const String& version, ExceptionCode& ec)
- {
- if (!implementation()->hasFeature("XML", String())) {
- ec = NOT_SUPPORTED_ERR;
- return;
- }
- if (!XMLDocumentParser::supportsXMLVersion(version)) {
- ec = NOT_SUPPORTED_ERR;
- return;
- }
- m_xmlVersion = version;
- }
- void Document::setXMLStandalone(bool standalone, ExceptionCode& ec)
- {
- if (!implementation()->hasFeature("XML", String())) {
- ec = NOT_SUPPORTED_ERR;
- return;
- }
- m_xmlStandalone = standalone ? Standalone : NotStandalone;
- }
- void Document::setDocumentURI(const String& uri)
- {
- // This property is read-only from JavaScript, but writable from Objective-C.
- m_documentURI = uri;
- updateBaseURL();
- }
- KURL Document::baseURI() const
- {
- return m_baseURL;
- }
- void Document::setContent(const String& content)
- {
- open();
- m_parser->append(content);
- close();
- }
- String Document::suggestedMIMEType() const
- {
- if (m_document->isXHTMLDocument())
- return "application/xhtml+xml";
- if (m_document->isSVGDocument())
- return "image/svg+xml";
- if (m_document->xmlStandalone())
- return "text/xml";
- if (m_document->isHTMLDocument())
- return "text/html";
- if (DocumentLoader* documentLoader = loader())
- return documentLoader->responseMIMEType();
- return String();
- }
- // FIXME: We need to discuss the DOM API here at some point. Ideas:
- // * making it receive a rect as parameter, i.e. nodesFromRect(x, y, w, h);
- // * making it receive the expading size of each direction separately,
- // i.e. nodesFromRect(x, y, topSize, rightSize, bottomSize, leftSize);
- PassRefPtr<NodeList> Document::nodesFromRect(int centerX, int centerY, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding, bool ignoreClipping, bool allowShadowContent) const
- {
- // FIXME: Share code between this, elementFromPoint and caretRangeFromPoint.
- if (!renderer())
- return 0;
- Frame* frame = this->frame();
- if (!frame)
- return 0;
- FrameView* frameView = frame->view();
- if (!frameView)
- return 0;
- float zoomFactor = frame->pageZoomFactor();
- LayoutPoint point = roundedLayoutPoint(FloatPoint(centerX * zoomFactor + view()->scrollX(), centerY * zoomFactor + view()->scrollY()));
- int type = HitTestRequest::ReadOnly | HitTestRequest::Active;
- // When ignoreClipping is false, this method returns null for coordinates outside of the viewport.
- if (ignoreClipping)
- type |= HitTestRequest::IgnoreClipping;
- else if (!frameView->visibleContentRect().intersects(HitTestResult::rectForPoint(point, topPadding, rightPadding, bottomPadding, leftPadding)))
- return 0;
- HitTestRequest request(type);
- // Passing a zero padding will trigger a rect hit test, however for the purposes of nodesFromRect,
- // we special handle this case in order to return a valid NodeList.
- if (!topPadding && !rightPadding && !bottomPadding && !leftPadding) {
- HitTestResult result(point);
- return handleZeroPadding(request, result);
- }
- enum ShadowContentFilterPolicy shadowContentFilterPolicy = allowShadowContent ? AllowShadowContent : DoNotAllowShadowContent;
- HitTestResult result(point, topPadding, rightPadding, bottomPadding, leftPadding, shadowContentFilterPolicy);
- renderView()->hitTest(request, result);
- return StaticHashSetNodeList::adopt(result.rectBasedTestResult());
- }
- PassRefPtr<NodeList> Document::handleZeroPadding(const HitTestRequest& request, HitTestResult& result) const
- {
- renderView()->hitTest(request, result);
- Node* node = result.innerNode();
- if (!node)
- return 0;
- node = node->shadowAncestorNode();
- ListHashSet<RefPtr<Node> > list;
- list.add(node);
- return StaticHashSetNodeList::adopt(list);
- }
- static Node* nodeFromPoint(Frame* frame, RenderView* renderView, int x, int y, LayoutPoint* localPoint = 0)
- {
- if (!frame)
- return 0;
- FrameView* frameView = frame->view();
- if (!frameView)
- return 0;
- float zoomFactor = frame->pageZoomFactor();
- IntPoint point = roundedIntPoint(FloatPoint(x * zoomFactor + frameView->scrollX(), y * zoomFactor + frameView->scrollY()));
- if (!frameView->visibleContentRect().contains(point))
- return 0;
- HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active);
- HitTestResult result(point);
- renderView->hitTest(request, result);
- if (localPoint)
- *localPoint = result.localPoint();
- return result.innerNode();
- }
- Element* Document::elementFromPoint(int x, int y) const
- {
- if (!renderer())
- return 0;
- Node* node = nodeFromPoint(frame(), renderView(), x, y);
- while (node && !node->isElementNode())
- node = node->parentNode();
- if (node)
- node = ancestorInThisScope(node);
- return static_cast<Element*>(node);
- }
- PassRefPtr<Range> Document::caretRangeFromPoint(int x, int y)
- {
- if (!renderer())
- return 0;
- LayoutPoint localPoint;
- Node* node = nodeFromPoint(frame(), renderView(), x, y, &localPoint);
- if (!node)
- return 0;
- Node* shadowAncestorNode = ancestorInThisScope(node);
- if (shadowAncestorNode != node) {
- unsigned offset = shadowAncestorNode->nodeIndex();
- ContainerNode* container = shadowAncestorNode->parentNode();
- return Range::create(this, container, offset, container, offset);
- }
- RenderObject* renderer = node->renderer();
- if (!renderer)
- return 0;
- VisiblePosition visiblePosition = renderer->positionForPoint(localPoint);
- if (visiblePosition.isNull())
- return 0;
- Position rangeCompliantPosition = visiblePosition.deepEquivalent().parentAnchoredEquivalent();
- return Range::create(this, rangeCompliantPosition, rangeCompliantPosition);
- }
- /*
- * Performs three operations:
- * 1. Convert control characters to spaces
- * 2. Trim leading and trailing spaces
- * 3. Collapse internal whitespace.
- */
- static inline StringWithDirection canonicalizedTitle(Document* document, const StringWithDirection& titleWithDirection)
- {
- const String& title = titleWithDirection.string();
- const UChar* characters = title.characters();
- unsigned length = title.length();
- unsigned i;
- StringBuffer<UChar> buffer(length);
- unsigned builderIndex = 0;
- // Skip leading spaces and leading characters that would convert to spaces
- for (i = 0; i < length; ++i) {
- UChar c = characters[i];
- if (!(c <= 0x20 || c == 0x7F))
- break;
- }
- if (i == length)
- return StringWithDirection();
- // Replace control characters with spaces, and backslashes with currency symbols, and collapse whitespace.
- bool previousCharWasWS = false;
- for (; i < length; ++i) {
- UChar c = characters[i];
- if (c <= 0x20 || c == 0x7F || (WTF::Unicode::category(c) & (WTF::Unicode::Separator_Line | WTF::Unicode::Separator_Paragraph))) {
- if (previousCharWasWS)
- continue;
- buffer[builderIndex++] = ' ';
- previousCharWasWS = true;
- } else {
- buffer[builderIndex++] = c;
- previousCharWasWS = false;
- }
- }
- // Strip trailing spaces
- while (builderIndex > 0) {
- --builderIndex;
- if (buffer[builderIndex] != ' ')
- break;
- }
- if (!builderIndex && buffer[builderIndex] == ' ')
- return StringWithDirection();
- buffer.shrink(builderIndex + 1);
- // Replace the backslashes with currency symbols if the encoding requires it.
- document->displayBufferModifiedByEncoding(buffer.characters(), buffer.length());
-
- return StringWithDirection(String::adopt(buffer), titleWithDirection.direction());
- }
- void Document::updateTitle(const StringWithDirection& title)
- {
- if (m_rawTitle == title)
- return;
- m_rawTitle = title;
- m_title = canonicalizedTitle(this, m_rawTitle);
- if (Frame* f = frame())
- f->loader()->setTitle(m_title);
- }
- void Document::setTitle(const String& title)
- {
- // Title set by JavaScript -- overrides any title elements.
- m_titleSetExplicitly = true;
- if (!isHTMLDocument() && !isXHTMLDocument())
- m_titleElement = 0;
- else if (!m_titleElement) {
- if (HTMLElement* headEle…
Large files files are truncated, but you can click here to view the full file