diff options
Diffstat (limited to 'WebCore/dom/Document.cpp')
| -rw-r--r-- | WebCore/dom/Document.cpp | 616 |
1 files changed, 407 insertions, 209 deletions
diff --git a/WebCore/dom/Document.cpp b/WebCore/dom/Document.cpp index e4c5741..13c2fae 100644 --- a/WebCore/dom/Document.cpp +++ b/WebCore/dom/Document.cpp @@ -22,6 +22,7 @@ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ + #include "config.h" #include "Document.h" @@ -57,6 +58,7 @@ #include "FrameLoader.h" #include "FrameTree.h" #include "FrameView.h" +#include "HTMLAllCollection.h" #include "HTMLAnchorElement.h" #include "HTMLBodyElement.h" #include "HTMLCanvasElement.h" @@ -79,7 +81,7 @@ #include "HitTestResult.h" #include "ImageLoader.h" #include "InspectorController.h" -#include "ScriptEventListener.h" +#include "InspectorTimelineAgent.h" #include "KeyboardEvent.h" #include "Logging.h" #include "MappedAttribute.h" @@ -93,7 +95,10 @@ #include "NodeWithIndex.h" #include "OverflowEvent.h" #include "Page.h" +#include "PageGroup.h" +#include "PageTransitionEvent.h" #include "PlatformKeyboardEvent.h" +#include "PopStateEvent.h" #include "ProcessingInstruction.h" #include "ProgressEvent.h" #include "RegisteredEventListener.h" @@ -103,6 +108,7 @@ #include "RenderWidget.h" #include "ScriptController.h" #include "ScriptElement.h" +#include "ScriptEventListener.h" #include "SecurityOrigin.h" #include "SegmentedString.h" #include "SelectionController.h" @@ -112,14 +118,17 @@ #include "TextIterator.h" #include "TextResourceDecoder.h" #include "Timer.h" +#include "TransformSource.h" #include "TreeWalker.h" #include "UIEvent.h" +#include "UserContentURLPattern.h" #include "WebKitAnimationEvent.h" #include "WebKitTransitionEvent.h" #include "WheelEvent.h" #include "XMLHttpRequest.h" #include "XMLNames.h" #include "XMLTokenizer.h" +#include "htmlediting.h" #include <wtf/CurrentTime.h> #include <wtf/HashFunctions.h> #include <wtf/MainThread.h> @@ -131,6 +140,10 @@ #include "DatabaseThread.h" #endif +#if ENABLE(SHARED_WORKERS) +#include "SharedWorkerRepository.h" +#endif + #if ENABLE(DOM_STORAGE) #include "StorageEvent.h" #endif @@ -153,6 +166,7 @@ #if ENABLE(SVG) #include "SVGDocumentExtensions.h" #include "SVGElementFactory.h" +#include "SVGNames.h" #include "SVGZoomEvent.h" #include "SVGStyleElement.h" #endif @@ -184,6 +198,12 @@ #include "WMLNames.h" #endif +#if ENABLE(MATHML) +#include "MathMLElement.h" +#include "MathMLElementFactory.h" +#include "MathMLNames.h" +#endif + #if ENABLE(XHTMLMP) #include "HTMLNoScriptElement.h" #endif @@ -325,9 +345,6 @@ Document::Document(Frame* frame, bool isXHTML) , m_titleSetExplicitly(false) , m_updateFocusAppearanceTimer(this, &Document::updateFocusAppearanceTimerFired) , m_executeScriptSoonTimer(this, &Document::executeScriptSoonTimerFired) -#if ENABLE(XSLT) - , m_transformSource(0) -#endif , m_xmlVersion("1.0") , m_xmlStandalone(false) #if ENABLE(XBL) @@ -354,29 +371,28 @@ Document::Document(Frame* frame, bool isXHTML) , m_hasOpenDatabases(false) #endif , m_usingGeolocation(false) -#ifdef ANDROID_MOBILE - , mExtraLayoutDelay(0) -#endif #if ENABLE(WML) , m_containsWMLContent(false) #endif { - m_document.resetSkippingRef(this); + m_document = this; + + m_pageGroupUserSheetCacheValid = false; m_printing = false; m_ignoreAutofocus = false; m_frame = frame; - m_renderArena = 0; + #if !PLATFORM(ANDROID) m_axObjectCache = 0; -#endif +#endif + m_docLoader = new DocLoader(this); visuallyOrdered = false; m_bParsing = false; - m_tokenizer = 0; m_wellFormed = false; setParseMode(Strict); @@ -412,6 +428,7 @@ Document::Document(Frame* frame, bool isXHTML) m_processingLoadEvent = false; m_startTime = currentTime(); m_overMinimumLayoutThreshold = false; + m_extraLayoutDelay = 0; initSecurityContext(); initDNSPrefetch(); @@ -431,8 +448,7 @@ void Document::removedLastRef() // want the document to be destructed until after // removeAllChildren returns, so we guard ourselves with an // extra self-only ref. - - DocPtr<Document> guard(this); + selfOnlyRef(); // We must make sure not to be retaining any of our children through // these extra pointers or we will create a reference cycle. @@ -448,14 +464,15 @@ void Document::removedLastRef() deleteAllValues(m_markers); m_markers.clear(); - delete m_tokenizer; - m_tokenizer = 0; + m_tokenizer.clear(); m_cssCanvasElements.clear(); #ifndef NDEBUG m_inRemovedLastRefFunction = false; #endif + + selfOnlyDeref(); } else { #ifndef NDEBUG m_deletionHasBegun = true; @@ -481,22 +498,15 @@ Document::~Document() forgetAllDOMNodesForDocument(this); #endif - delete m_tokenizer; - m_document.resetSkippingRef(0); + m_tokenizer.clear(); + m_document = 0; delete m_styleSelector; - delete m_docLoader; - - if (m_renderArena) { - delete m_renderArena; - m_renderArena = 0; - } + m_docLoader.clear(); -#if ENABLE(XSLT) - xmlFreeDoc((xmlDocPtr)m_transformSource); -#endif + m_renderArena.clear(); #if ENABLE(XBL) - delete m_bindingManager; + m_bindingManager.clear(); #endif deleteAllValues(m_markers); @@ -518,8 +528,16 @@ Document::~Document() if (m_styleSheets) m_styleSheets->documentDestroyed(); +} - m_document = 0; +Document::JSWrapperCache* Document::createWrapperCache(DOMWrapperWorld* world) +{ + JSWrapperCache* wrapperCache = new JSWrapperCache(); + m_wrapperCacheMap.set(world, wrapperCache); +#if USE(JSC) + world->rememberDocument(this); +#endif + return wrapperCache; } void Document::resetLinkColor() @@ -599,17 +617,17 @@ PassRefPtr<Element> Document::createElement(const AtomicString& name, ExceptionC PassRefPtr<DocumentFragment> Document::createDocumentFragment() { - return new DocumentFragment(document()); + return DocumentFragment::create(document()); } PassRefPtr<Text> Document::createTextNode(const String& data) { - return new Text(this, data); + return Text::create(this, data); } PassRefPtr<Comment> Document::createComment(const String& data) { - return new Comment(this, data); + return Comment::create(this, data); } PassRefPtr<CDATASection> Document::createCDATASection(const String& data, ExceptionCode& ec) @@ -618,7 +636,7 @@ PassRefPtr<CDATASection> Document::createCDATASection(const String& data, Except ec = NOT_SUPPORTED_ERR; return 0; } - return new CDATASection(this, data); + return CDATASection::create(this, data); } PassRefPtr<ProcessingInstruction> Document::createProcessingInstruction(const String& target, const String& data, ExceptionCode& ec) @@ -631,7 +649,7 @@ PassRefPtr<ProcessingInstruction> Document::createProcessingInstruction(const St ec = NOT_SUPPORTED_ERR; return 0; } - return new ProcessingInstruction(this, target, data); + return ProcessingInstruction::create(this, target, data); } PassRefPtr<EntityReference> Document::createEntityReference(const String& name, ExceptionCode& ec) @@ -644,12 +662,12 @@ PassRefPtr<EntityReference> Document::createEntityReference(const String& name, ec = NOT_SUPPORTED_ERR; return 0; } - return new EntityReference(this, name); + return EntityReference::create(this, name); } PassRefPtr<EditingText> Document::createEditingTextNode(const String& text) { - return new EditingText(this, text); + return EditingText::create(this, text); } PassRefPtr<CSSStyleDeclaration> Document::createCSSStyleDeclaration() @@ -714,11 +732,8 @@ PassRefPtr<Node> Document::importNode(Node* importedNode, bool deep, ExceptionCo return newElement.release(); } - case ATTRIBUTE_NODE: { - RefPtr<Attr> newAttr = new Attr(0, this, static_cast<Attr*>(importedNode)->attr()->clone()); - newAttr->createTextChild(); - return newAttr.release(); - } + case ATTRIBUTE_NODE: + return Attr::create(0, this, static_cast<Attr*>(importedNode)->attr()->clone()); case DOCUMENT_FRAGMENT_NODE: { DocumentFragment* oldFragment = static_cast<DocumentFragment*>(importedNode); RefPtr<DocumentFragment> newFragment = createDocumentFragment(); @@ -828,9 +843,13 @@ PassRefPtr<Element> Document::createElement(const QualifiedName& qName, bool cre else if (isWMLDocument()) e = WMLElementFactory::createWMLElement(QualifiedName(nullAtom, qName.localName(), WMLNames::wmlNamespaceURI), this, createdByParser); #endif +#if ENABLE(MATHML) + else if (qName.namespaceURI() == MathMLNames::mathmlNamespaceURI) + e = MathMLElementFactory::createMathMLElement(qName, this, createdByParser); +#endif if (!e) - e = new Element(qName, document()); + e = Element::create(qName, document()); // <image> uses imgTag so we need a special rule. #if ENABLE(WML) @@ -952,16 +971,25 @@ KURL Document::baseURI() const Element* Document::elementFromPoint(int x, int y) const { + // FIXME: Share code between this and caretRangeFromPoint. if (!renderer()) return 0; + Frame* frame = this->frame(); + if (!frame) + return 0; + FrameView* frameView = frame->view(); + if (!frameView) + return 0; - HitTestRequest request(HitTestRequest::ReadOnly | - HitTestRequest::Active); + float zoomFactor = frame->pageZoomFactor(); + IntPoint point = roundedIntPoint(FloatPoint(x * zoomFactor + view()->scrollX(), y * zoomFactor + view()->scrollY())); - float zoomFactor = frame() ? frame()->pageZoomFactor() : 1.0f; + if (!frameView->visibleContentRect().contains(point)) + return 0; - HitTestResult result(roundedIntPoint(FloatPoint(x * zoomFactor, y * zoomFactor))); - renderView()->layer()->hitTest(request, result); + HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active); + HitTestResult result(point); + renderView()->layer()->hitTest(request, result); Node* n = result.innerNode(); while (n && !n->isElementNode()) @@ -971,6 +999,50 @@ Element* Document::elementFromPoint(int x, int y) const return static_cast<Element*>(n); } +PassRefPtr<Range> Document::caretRangeFromPoint(int x, int y) +{ + // FIXME: Share code between this and elementFromPoint. + if (!renderer()) + return 0; + Frame* frame = this->frame(); + if (!frame) + return 0; + FrameView* frameView = frame->view(); + if (!frameView) + return 0; + + float zoomFactor = frame->pageZoomFactor(); + IntPoint point = roundedIntPoint(FloatPoint(x * zoomFactor + view()->scrollX(), y * zoomFactor + view()->scrollY())); + + if (!frameView->visibleContentRect().contains(point)) + return 0; + + HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active); + HitTestResult result(point); + renderView()->layer()->hitTest(request, result); + + Node* node = result.innerNode(); + if (!node) + return 0; + + Node* shadowAncestorNode = node->shadowAncestorNode(); + if (shadowAncestorNode != node) { + unsigned offset = shadowAncestorNode->nodeIndex(); + Node* container = shadowAncestorNode->parentNode(); + return Range::create(this, container, offset, container, offset); + } + + RenderObject* renderer = node->renderer(); + if (!renderer) + return 0; + VisiblePosition visiblePosition = renderer->positionForPoint(result.localPoint()); + if (visiblePosition.isNull()) + return 0; + + Position rangeCompliantPosition = rangeCompliantEquivalent(visiblePosition); + return Range::create(this, rangeCompliantPosition, rangeCompliantPosition); +} + void Document::addElementById(const AtomicString& elementId, Element* element) { typedef HashMap<AtomicStringImpl*, Element*>::iterator iterator; @@ -1186,8 +1258,14 @@ void Document::recalcStyle(StyleChange change) if (m_inStyleRecalc) return; // Guard against re-entrancy. -dwh +#if ENABLE(INSPECTOR) + if (InspectorTimelineAgent* timelineAgent = inspectorTimelineAgent()) + timelineAgent->willRecalculateStyle(); +#endif + m_inStyleRecalc = true; suspendPostAttachCallbacks(); + RenderWidget::suspendWidgetHierarchyUpdates(); if (view()) view()->pauseScheduledEvents(); @@ -1258,6 +1336,7 @@ bail_out: if (view()) view()->resumeScheduledEvents(); + RenderWidget::resumeWidgetHierarchyUpdates(); resumePostAttachCallbacks(); m_inStyleRecalc = false; @@ -1266,6 +1345,11 @@ bail_out: m_closeAfterStyleRecalc = false; implicitClose(); } + +#if ENABLE(INSPECTOR) + if (InspectorTimelineAgent* timelineAgent = inspectorTimelineAgent()) + timelineAgent->didRecalculateStyle(); +#endif } void Document::updateStyleIfNeeded() @@ -1350,11 +1434,12 @@ void Document::attach() #if !PLATFORM(ANDROID) ASSERT(!m_axObjectCache); #endif + if (!m_renderArena) m_renderArena = new RenderArena(); // Create the rendering tree - setRenderer(new (m_renderArena) RenderView(this, view())); + setRenderer(new (m_renderArena.get()) RenderView(this, view())); #if USE(ACCELERATED_COMPOSITING) renderView()->didMoveOnscreen(); #endif @@ -1363,7 +1448,8 @@ void Document::attach() bool matchAuthorAndUserStyles = true; if (Settings* docSettings = settings()) matchAuthorAndUserStyles = docSettings->authorAndUserStylesEnabled(); - m_styleSelector = new CSSStyleSelector(this, userStyleSheet(), m_styleSheets.get(), m_mappedElementSheet.get(), !inCompatMode(), matchAuthorAndUserStyles); + m_styleSelector = new CSSStyleSelector(this, m_styleSheets.get(), m_mappedElementSheet.get(), pageUserSheet(), pageGroupUserSheets(), + !inCompatMode(), matchAuthorAndUserStyles); } recalcStyle(Force); @@ -1389,7 +1475,11 @@ void Document::detach() // Send out documentWillBecomeInactive() notifications to registered elements, // in order to stop media elements documentWillBecomeInactive(); - + +#if ENABLE(SHARED_WORKERS) + SharedWorkerRepository::documentDetached(this); +#endif + if (m_frame) { FrameView* view = m_frame->view(); if (view) @@ -1421,46 +1511,31 @@ void Document::detach() if (render) render->destroy(); + HashSet<RefPtr<HistoryItem> > associatedHistoryItems; + associatedHistoryItems.swap(m_associatedHistoryItems); + HashSet<RefPtr<HistoryItem> >::iterator end = associatedHistoryItems.end(); + for (HashSet<RefPtr<HistoryItem> >::iterator i = associatedHistoryItems.begin(); i != end; ++i) + (*i)->documentDetached(this); + // 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 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; - m_renderArena = 0; - } + m_renderArena.clear(); } void Document::removeAllEventListeners() { + EventTarget::removeAllEventListeners(); + if (DOMWindow* domWindow = this->domWindow()) domWindow->removeAllEventListeners(); - removeAllDisconnectedNodeEventListeners(); - for (Node* node = this; node; node = node->traverseNextNode()) + for (Node* node = firstChild(); node; node = node->traverseNextNode()) node->removeAllEventListeners(); } -void Document::registerDisconnectedNodeWithEventListeners(Node* node) -{ - m_disconnectedNodesWithEventListeners.add(node); -} - -void Document::unregisterDisconnectedNodeWithEventListeners(Node* node) -{ - m_disconnectedNodesWithEventListeners.remove(node); -} - -void Document::removeAllDisconnectedNodeEventListeners() -{ - HashSet<Node*>::iterator end = m_disconnectedNodesWithEventListeners.end(); - for (HashSet<Node*>::iterator i = m_disconnectedNodesWithEventListeners.begin(); i != end; ++i) - (*i)->removeAllEventListeners(); - m_disconnectedNodesWithEventListeners.clear(); -} - RenderView* Document::renderView() const { return toRenderView(renderer()); @@ -1557,6 +1632,9 @@ void Document::open(Document* ownerDocument) implicitOpen(); + if (DOMWindow* domWindow = this->domWindow()) + domWindow->removeAllEventListeners(); + if (m_frame) m_frame->loader()->didExplicitOpen(); } @@ -1568,8 +1646,7 @@ void Document::cancelParsing() // the onload handler when closing as a side effect of a cancel-style // change, such as opening a new document or closing the window while // still parsing - delete m_tokenizer; - m_tokenizer = 0; + m_tokenizer.clear(); close(); } } @@ -1578,7 +1655,10 @@ void Document::implicitOpen() { cancelParsing(); - clear(); + m_tokenizer.clear(); + + removeChildren(); + m_tokenizer = createTokenizer(); setParsing(true); @@ -1660,7 +1740,7 @@ void Document::implicitClose() return; } - bool wasLocationChangePending = frame() && frame()->loader()->isScheduledLocationChangePending(); + bool wasLocationChangePending = frame() && frame()->redirectScheduler()->locationChangePending(); bool doload = !parsing() && m_tokenizer && !m_processingLoadEvent && !wasLocationChangePending; if (!doload) @@ -1672,8 +1752,7 @@ void Document::implicitClose() // We have to clear the tokenizer, in case someone document.write()s from the // onLoad event handler, as in Radar 3206524. - delete m_tokenizer; - m_tokenizer = 0; + m_tokenizer.clear(); // Parser should have picked up all preloads by now m_docLoader->clearPreloads(); @@ -1707,8 +1786,12 @@ void Document::implicitClose() if (f) f->animation()->resumeAnimations(this); - ImageLoader::dispatchPendingLoadEvents(); - dispatchLoadEvent(); + ImageLoader::dispatchPendingEvents(); + dispatchWindowLoadEvent(); + dispatchWindowEvent(PageTransitionEvent::create(eventNames().pageshowEvent, false), this); + if (m_pendingStateObject) + dispatchWindowEvent(PopStateEvent::create(m_pendingStateObject.release())); + if (f) f->loader()->handledOnloadEvents(); #ifdef INSTRUMENT_LAYOUT_SCHEDULING @@ -1726,7 +1809,7 @@ void Document::implicitClose() // fires. This will improve onload scores, and other browsers do it. // If they wanna cheat, we can too. -dwh - if (frame()->loader()->isScheduledLocationChangePending() && elapsedTime() < cLayoutScheduleThreshold) { + if (frame()->redirectScheduler()->locationChangePending() && elapsedTime() < cLayoutScheduleThreshold) { // Just bail out. Before or during the onload we were shifted to another page. // The old i-Bench suite does this. When this happens don't bother painting or laying out. view()->unscheduleRelayout(); @@ -1755,7 +1838,7 @@ void Document::implicitClose() // exists in the cache (we ignore the return value because we don't need it here). This is // only safe to call when a layout is not in progress, so it can not be used in postNotification. axObjectCache()->getOrCreate(renderObject); - axObjectCache()->postNotification(renderObject, "AXLoadComplete", true); + axObjectCache()->postNotification(renderObject, AXObjectCache::AXLoadComplete, true); } #endif @@ -1795,13 +1878,13 @@ bool Document::shouldScheduleLayout() int Document::minimumLayoutDelay() { if (m_overMinimumLayoutThreshold) - return 0; + return m_extraLayoutDelay; int elapsed = elapsedTime(); m_overMinimumLayoutThreshold = elapsed > cLayoutScheduleThreshold; // We'll want to schedule the timer to fire at the minimum layout threshold. - return max(0, cLayoutScheduleThreshold - elapsed); + return max(0, cLayoutScheduleThreshold - elapsed) + m_extraLayoutDelay; } int Document::elapsedTime() const @@ -1855,16 +1938,6 @@ void Document::finishParsing() m_tokenizer->finish(); } -void Document::clear() -{ - delete m_tokenizer; - m_tokenizer = 0; - - removeChildren(); - if (DOMWindow* domWindow = this->domWindow()) - domWindow->removeAllEventListeners(); -} - const KURL& Document::virtualURL() const { return m_url; @@ -1917,34 +1990,72 @@ String Document::userAgent(const KURL& url) const return frame() ? frame()->loader()->userAgent(url) : String(); } -void Document::setCSSStyleSheet(const String& url, const String& charset, const CachedCSSStyleSheet* sheet) +CSSStyleSheet* Document::pageUserSheet() { - m_sheet = CSSStyleSheet::create(this, url, charset); - m_sheet->parseString(sheet->sheetText()); + if (m_pageUserSheet) + return m_pageUserSheet.get(); + + Page* owningPage = page(); + if (!owningPage) + return 0; + + String userSheetText = owningPage->userStyleSheet(); + if (userSheetText.isEmpty()) + return 0; + + // Parse the sheet and cache it. + m_pageUserSheet = CSSStyleSheet::create(this, settings()->userStyleSheetLocation()); + m_pageUserSheet->setIsUserStyleSheet(true); + m_pageUserSheet->parseString(userSheetText, !inCompatMode()); + return m_pageUserSheet.get(); +} +void Document::clearPageUserSheet() +{ + m_pageUserSheet = 0; updateStyleSelector(); } -#if FRAME_LOADS_USER_STYLESHEET -void Document::setUserStyleSheet(const String& sheet) +const Vector<RefPtr<CSSStyleSheet> >* Document::pageGroupUserSheets() const { - if (m_usersheet != sheet) { - m_usersheet = sheet; - updateStyleSelector(); + if (m_pageGroupUserSheetCacheValid) + return m_pageGroupUserSheets.get(); + + m_pageGroupUserSheetCacheValid = true; + + Page* owningPage = page(); + if (!owningPage) + return 0; + + const PageGroup& pageGroup = owningPage->group(); + const UserStyleSheetMap* sheetsMap = pageGroup.userStyleSheets(); + if (!sheetsMap) + return 0; + + UserStyleSheetMap::const_iterator end = sheetsMap->end(); + for (UserStyleSheetMap::const_iterator it = sheetsMap->begin(); it != end; ++it) { + const UserStyleSheetVector* sheets = it->second; + for (unsigned i = 0; i < sheets->size(); ++i) { + const UserStyleSheet* sheet = sheets->at(i).get(); + if (!UserContentURLPattern::matchesPatterns(url(), sheet->whitelist(), sheet->blacklist())) + continue; + RefPtr<CSSStyleSheet> parsedSheet = CSSStyleSheet::create(const_cast<Document*>(this), sheet->url()); + parsedSheet->setIsUserStyleSheet(true); + parsedSheet->parseString(sheet->source(), !inCompatMode()); + if (!m_pageGroupUserSheets) + m_pageGroupUserSheets.set(new Vector<RefPtr<CSSStyleSheet> >); + m_pageGroupUserSheets->append(parsedSheet.release()); + } } + + return m_pageGroupUserSheets.get(); } -#endif -String Document::userStyleSheet() const +void Document::clearPageGroupUserSheets() { -#if FRAME_LOADS_USER_STYLESHEET - return m_usersheet; -#else - Page* page = this->page(); - if (!page) - return String(); - return page->userStyleSheet(); -#endif + m_pageGroupUserSheets.clear(); + m_pageGroupUserSheetCacheValid = false; + updateStyleSelector(); } CSSStyleSheet* Document::elementSheet() @@ -2175,12 +2286,14 @@ void Document::processHttpEquiv(const String& equiv, const String& content) url = frame->loader()->url().string(); else url = completeURL(url).string(); - frame->loader()->scheduleHTTPRedirection(delay, url); + frame->redirectScheduler()->scheduleRedirect(delay, url); } } else if (equalIgnoringCase(equiv, "set-cookie")) { // FIXME: make setCookie work on XML documents too; e.g. in case of <html:meta .....> - if (isHTMLDocument()) - static_cast<HTMLDocument*>(this)->setCookie(content); + if (isHTMLDocument()) { + ExceptionCode ec; // Exception (for sandboxed documents) ignored. + static_cast<HTMLDocument*>(this)->setCookie(content, ec); + } } else if (equalIgnoringCase(equiv, "content-language")) setContentLanguage(content); else if (equalIgnoringCase(equiv, "x-dns-prefetch-control")) @@ -2189,7 +2302,7 @@ void Document::processHttpEquiv(const String& equiv, const String& content) FrameLoader* frameLoader = frame->loader(); if (frameLoader->shouldInterruptLoadForXFrameOptions(content, url())) { frameLoader->stopAllLoaders(); - frameLoader->scheduleHTTPRedirection(0, blankURL()); + frame->redirectScheduler()->scheduleLocationChange(blankURL(), String()); } } } @@ -2372,8 +2485,8 @@ void Document::removePendingSheet() if (!m_pendingStylesheets && m_tokenizer) m_tokenizer->executeScriptsWaitingForStylesheets(); - if (!m_pendingStylesheets && m_gotoAnchorNeededAfterStylesheetsLoad && m_frame) - m_frame->loader()->gotoAnchor(); + if (!m_pendingStylesheets && m_gotoAnchorNeededAfterStylesheetsLoad && view()) + view()->scrollToFragment(m_frame->loader()->url()); } void Document::updateStyleSelector() @@ -2496,7 +2609,7 @@ void Document::recalcStyleSelector() sheet = cssSheet.get(); } } - } else if (n->isHTMLElement() && (n->hasTagName(linkTag) || n->hasTagName(styleTag)) + } else if ((n->isHTMLElement() && (n->hasTagName(linkTag) || n->hasTagName(styleTag))) #if ENABLE(SVG) || (n->isSVGElement() && n->hasTagName(SVGNames::styleTag)) #endif @@ -2566,7 +2679,8 @@ void Document::recalcStyleSelector() // Create a new style selector delete m_styleSelector; - m_styleSelector = new CSSStyleSelector(this, userStyleSheet(), m_styleSheets.get(), m_mappedElementSheet.get(), !inCompatMode(), matchAuthorAndUserStyles); + m_styleSelector = new CSSStyleSelector(this, m_styleSheets.get(), m_mappedElementSheet.get(), + pageUserSheet(), pageGroupUserSheets(), !inCompatMode(), matchAuthorAndUserStyles); m_didCalculateStyleSelector = true; } @@ -2657,14 +2771,14 @@ bool Document::setFocusedNode(PassRefPtr<Node> newFocusedNode) oldFocusedNode->setActive(false); oldFocusedNode->setFocus(false); - + // Dispatch a change event for text fields or textareas that have been edited RenderObject* r = oldFocusedNode->renderer(); - if (r && r->isTextControl() && toRenderTextControl(r)->isEdited()) { - oldFocusedNode->dispatchEvent(eventNames().changeEvent, true, false); + if (r && r->isTextControl() && toRenderTextControl(r)->wasChangedSinceLastChangeEvent()) { + static_cast<Element*>(oldFocusedNode.get())->dispatchFormControlChangeEvent(); r = oldFocusedNode->renderer(); if (r && r->isTextControl()) - toRenderTextControl(r)->setEdited(false); + toRenderTextControl(r)->setChangedSinceLastChangeEvent(false); } // Dispatch the blur event and let the node do any other blur related activities (important for text fields) @@ -2681,10 +2795,10 @@ bool Document::setFocusedNode(PassRefPtr<Node> newFocusedNode) focusChangeBlocked = true; newFocusedNode = 0; } - if ((oldFocusedNode.get() == this) && oldFocusedNode->hasOneRef()) + if (oldFocusedNode == this && oldFocusedNode->hasOneRef()) return true; - if (oldFocusedNode.get() == oldFocusedNode->rootEditableElement()) + if (oldFocusedNode == oldFocusedNode->rootEditableElement()) frame()->editor()->didEndEditing(); } @@ -2713,7 +2827,7 @@ bool Document::setFocusedNode(PassRefPtr<Node> newFocusedNode) } m_focusedNode->setFocus(); - if (m_focusedNode.get() == m_focusedNode->rootEditableElement()) + if (m_focusedNode == m_focusedNode->rootEditableElement()) frame()->editor()->didBeginEditing(); // eww, I suck. set the qt focus correctly @@ -2735,22 +2849,21 @@ bool Document::setFocusedNode(PassRefPtr<Node> newFocusedNode) } } -#if PLATFORM(MAC) && !PLATFORM(CHROMIUM) - if (!focusChangeBlocked && m_focusedNode && AXObjectCache::accessibilityEnabled()) - axObjectCache()->handleFocusedUIElementChanged(); -#elif PLATFORM(GTK) +#if ((PLATFORM(MAC) || PLATFORM(WIN)) && !PLATFORM(CHROMIUM)) || PLATFORM(GTK) if (!focusChangeBlocked && m_focusedNode && AXObjectCache::accessibilityEnabled()) { RenderObject* oldFocusedRenderer = 0; RenderObject* newFocusedRenderer = 0; if (oldFocusedNode) - oldFocusedRenderer = oldFocusedNode.get()->renderer(); + oldFocusedRenderer = oldFocusedNode->renderer(); if (newFocusedNode) - newFocusedRenderer = newFocusedNode.get()->renderer(); + newFocusedRenderer = newFocusedNode->renderer(); - axObjectCache()->handleFocusedUIElementChangedWithRenderers(oldFocusedRenderer, newFocusedRenderer); + axObjectCache()->handleFocusedUIElementChanged(oldFocusedRenderer, newFocusedRenderer); } #endif + if (!focusChangeBlocked) + page()->chrome()->focusedNodeChanged(m_focusedNode.get()); SetFocusedNodeDone: updateStyleIfNeeded(); @@ -2891,26 +3004,16 @@ EventListener* Document::getWindowAttributeEventListener(const AtomicString& eve return domWindow->getAttributeEventListener(eventType); } -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) +void Document::dispatchWindowEvent(PassRefPtr<Event> event, PassRefPtr<EventTarget> target) { ASSERT(!eventDispatchForbidden()); DOMWindow* domWindow = this->domWindow(); if (!domWindow) return; - domWindow->dispatchEvent(eventType, canBubbleArg, cancelableArg); + domWindow->dispatchEvent(event, target); } -void Document::dispatchLoadEvent() +void Document::dispatchWindowLoadEvent() { ASSERT(!eventDispatchForbidden()); DOMWindow* domWindow = this->domWindow(); @@ -2921,44 +3024,51 @@ void Document::dispatchLoadEvent() PassRefPtr<Event> Document::createEvent(const String& eventType, ExceptionCode& ec) { + RefPtr<Event> event; if (eventType == "Event" || eventType == "Events" || eventType == "HTMLEvents") - return Event::create(); - if (eventType == "KeyboardEvent" || eventType == "KeyboardEvents") - return KeyboardEvent::create(); - if (eventType == "MessageEvent") - return MessageEvent::create(); - if (eventType == "MouseEvent" || eventType == "MouseEvents") - return MouseEvent::create(); - if (eventType == "MutationEvent" || eventType == "MutationEvents") - return MutationEvent::create(); - if (eventType == "OverflowEvent") - return OverflowEvent::create(); - if (eventType == "ProgressEvent") - return ProgressEvent::create(); + event = Event::create(); + else if (eventType == "KeyboardEvent" || eventType == "KeyboardEvents") + event = KeyboardEvent::create(); + else if (eventType == "MessageEvent") + event = MessageEvent::create(); + else if (eventType == "MouseEvent" || eventType == "MouseEvents") + event = MouseEvent::create(); + else if (eventType == "MutationEvent" || eventType == "MutationEvents") + event = MutationEvent::create(); + else if (eventType == "OverflowEvent") + event = OverflowEvent::create(); + else if (eventType == "PageTransitionEvent") + event = PageTransitionEvent::create(); + else if (eventType == "ProgressEvent") + event = ProgressEvent::create(); #if ENABLE(DOM_STORAGE) - if (eventType == "StorageEvent") - return StorageEvent::create(); + else if (eventType == "StorageEvent") + event = StorageEvent::create(); #endif - if (eventType == "TextEvent") - return TextEvent::create(); - if (eventType == "UIEvent" || eventType == "UIEvents") - return UIEvent::create(); - if (eventType == "WebKitAnimationEvent") - return WebKitAnimationEvent::create(); - if (eventType == "WebKitTransitionEvent") - return WebKitTransitionEvent::create(); - if (eventType == "WheelEvent") - return WheelEvent::create(); + else if (eventType == "TextEvent") + event = TextEvent::create(); + else if (eventType == "UIEvent" || eventType == "UIEvents") + event = UIEvent::create(); + else if (eventType == "WebKitAnimationEvent") + event = WebKitAnimationEvent::create(); + else if (eventType == "WebKitTransitionEvent") + event = WebKitTransitionEvent::create(); + else if (eventType == "WheelEvent") + event = WheelEvent::create(); #if ENABLE(SVG) - if (eventType == "SVGEvents") - return Event::create(); - if (eventType == "SVGZoomEvents") - return SVGZoomEvent::create(); + else if (eventType == "SVGEvents") + event = Event::create(); + else if (eventType == "SVGZoomEvents") + event = SVGZoomEvent::create(); #endif #if ENABLE(TOUCH_EVENTS) // Android - if (eventType == "TouchEvent") - return TouchEvent::create(); + else if (eventType == "TouchEvent") + event = TouchEvent::create(); #endif + if (event) { + event->setCreatedByDOM(true); + return event.release(); + } ec = NOT_SUPPORTED_ERR; return 0; } @@ -2989,6 +3099,8 @@ void Document::addListenerTypeIfNeeded(const AtomicString& eventType) addListenerType(ANIMATIONITERATION_LISTENER); else if (eventType == eventNames().webkitTransitionEndEvent) addListenerType(TRANSITIONEND_LISTENER); + else if (eventType == eventNames().beforeloadEvent) + addListenerType(BEFORELOAD_LISTENER); } CSSStyleDeclaration* Document::getOverrideStyle(Element*, const String&) @@ -3003,11 +3115,20 @@ Element* Document::ownerElement() const return frame()->ownerElement(); } -String Document::cookie() const +String Document::cookie(ExceptionCode& ec) const { if (page() && !page()->cookieEnabled()) return String(); + // FIXME: The HTML5 DOM spec states that this attribute can raise an + // INVALID_STATE_ERR exception on getting if the Document has no + // browsing context. + + if (securityOrigin()->isSandboxed(SandboxOrigin)) { + ec = SECURITY_ERR; + return String(); + } + KURL cookieURL = this->cookieURL(); if (cookieURL.isEmpty()) return String(); @@ -3015,11 +3136,20 @@ String Document::cookie() const return cookies(this, cookieURL); } -void Document::setCookie(const String& value) +void Document::setCookie(const String& value, ExceptionCode& ec) { if (page() && !page()->cookieEnabled()) return; + // FIXME: The HTML5 DOM spec states that this attribute can raise an + // INVALID_STATE_ERR exception on setting if the Document has no + // browsing context. + + if (securityOrigin()->isSandboxed(SandboxOrigin)) { + ec = SECURITY_ERR; + return; + } + KURL cookieURL = this->cookieURL(); if (cookieURL.isEmpty()) return; @@ -3039,7 +3169,7 @@ String Document::domain() const return securityOrigin()->domain(); } -void Document::setDomain(const String& newDomain) +void Document::setDomain(const String& newDomain, ExceptionCode& ec) { // Both NS and IE specify that changing the domain is only allowed when // the new domain is a suffix of the old domain. @@ -3062,19 +3192,25 @@ void Document::setDomain(const String& newDomain) int oldLength = domain().length(); int newLength = newDomain.length(); // e.g. newDomain = webkit.org (10) and domain() = www.webkit.org (14) - if (newLength >= oldLength) + if (newLength >= oldLength) { + ec = SECURITY_ERR; return; + } String test = domain(); // Check that it's a subdomain, not e.g. "ebkit.org" - if (test[oldLength - newLength - 1] != '.') + if (test[oldLength - newLength - 1] != '.') { + ec = SECURITY_ERR; return; + } // Now test is "webkit.org" from domain() // and we check that it's the same thing as newDomain test.remove(0, oldLength - newLength); - if (test != newDomain) + if (test != newDomain) { + ec = SECURITY_ERR; return; + } securityOrigin()->setDomainFromDOM(newDomain); if (m_frame) @@ -3740,7 +3876,7 @@ void Document::repaintMarkers(DocumentMarker::MarkerType markerType) } } -void Document::setRenderedRectForMarker(Node* node, DocumentMarker marker, const IntRect& r) +void Document::setRenderedRectForMarker(Node* node, const DocumentMarker& marker, const IntRect& r) { MarkerMapVectorPair* vectorPair = m_markers.get(node); if (!vectorPair) { @@ -3870,13 +4006,11 @@ void Document::applyXSLTransform(ProcessingInstruction* pi) processor->createDocumentFromSource(newSource, resultEncoding, resultMIMEType, this, frame()); } -void Document::setTransformSource(void* doc) +void Document::setTransformSource(PassOwnPtr<TransformSource> source) { - if (doc == m_transformSource) + if (m_transformSource == source) return; - - xmlFreeDoc((xmlDocPtr)m_transformSource); - m_transformSource = doc; + m_transformSource = source; } #endif @@ -3946,7 +4080,7 @@ PassRefPtr<Attr> Document::createAttributeNS(const String& namespaceURI, const S // FIXME: Assume this is a mapped attribute, since createAttribute isn't namespace-aware. There's no harm to XML // documents if we're wrong. - return new Attr(0, this, MappedAttribute::create(qName, StringImpl::empty())); + return Attr::create(0, this, MappedAttribute::create(qName, StringImpl::empty())); } #if ENABLE(SVG) @@ -4009,9 +4143,9 @@ PassRefPtr<HTMLCollection> Document::anchors() return HTMLCollection::create(this, DocAnchors); } -PassRefPtr<HTMLCollection> Document::all() +PassRefPtr<HTMLAllCollection> Document::all() { - return HTMLCollection::create(this, DocAll); + return HTMLAllCollection::create(this); } PassRefPtr<HTMLCollection> Document::windowNamedItems(const String &name) @@ -4040,12 +4174,18 @@ CollectionCache* Document::nameCollectionInfo(CollectionType type, const AtomicS void Document::finishedParsing() { setParsing(false); + dispatchEvent(Event::create(eventNames().DOMContentLoadedEvent, true, false)); + if (Frame* f = frame()) { + f->loader()->finishedParsing(); - ExceptionCode ec = 0; - dispatchEvent(Event::create(eventNames().DOMContentLoadedEvent, true, false), ec); +#if ENABLE(INSPECTOR) + if (!page()) + return; - if (Frame* f = frame()) - f->loader()->finishedParsing(); + if (InspectorController* controller = page()->inspectorController()) + controller->mainResourceFiredDOMContentEvent(f->loader()->documentLoader(), url()); +#endif + } } Vector<String> Document::formElementsState() const @@ -4247,7 +4387,7 @@ void Document::initSecurityContext() if (!m_frame) { // No source for a security context. // This can occur via document.implementation.createDocument(). - m_cookieURL = KURL(""); + m_cookieURL = KURL(ParsedURLString, ""); ScriptExecutionContext::setSecurityOrigin(SecurityOrigin::createEmpty()); return; } @@ -4258,7 +4398,9 @@ void Document::initSecurityContext() m_cookieURL = url; ScriptExecutionContext::setSecurityOrigin(SecurityOrigin::create(url)); - if (FrameLoader::allowSubstituteDataAccessToLocal()) { + updateSandboxFlags(); + + if (SecurityOrigin::allowSubstituteDataAccessToLocal()) { // If this document was loaded with substituteData, then the document can // load local resources. See https://bugs.webkit.org/show_bug.cgi?id=16756 // and https://bugs.webkit.org/show_bug.cgi?id=19760 for further @@ -4308,6 +4450,46 @@ void Document::setSecurityOrigin(SecurityOrigin* securityOrigin) initDNSPrefetch(); } +void Document::updateURLForPushOrReplaceState(const KURL& url) +{ + Frame* f = frame(); + if (!f) + return; + + setURL(url); + f->loader()->documentLoader()->replaceRequestURLForSameDocumentNavigation(url); +} + +void Document::statePopped(SerializedScriptValue* stateObject) +{ + Frame* f = frame(); + if (!f) + return; + + if (f->loader()->isComplete()) + dispatchWindowEvent(PopStateEvent::create(stateObject)); + else + m_pendingStateObject = stateObject; +} + +void Document::registerHistoryItem(HistoryItem* item) +{ + ASSERT(!m_associatedHistoryItems.contains(item)); + m_associatedHistoryItems.add(item); +} + +void Document::unregisterHistoryItem(HistoryItem* item) +{ + ASSERT(m_associatedHistoryItems.contains(item) || m_associatedHistoryItems.isEmpty()); + m_associatedHistoryItems.remove(item); +} + +void Document::updateSandboxFlags() +{ + if (m_frame && securityOrigin()) + securityOrigin()->setSandboxFlags(m_frame->loader()->sandboxFlags()); +} + void Document::updateFocusAppearanceSoon() { if (!m_updateFocusAppearanceTimer.isActive()) @@ -4448,7 +4630,7 @@ void Document::detachRange(Range* range) m_ranges.remove(range); } -CanvasRenderingContext2D* Document::getCSSCanvasContext(const String& type, const String& name, int width, int height) +CanvasRenderingContext* Document::getCSSCanvasContext(const String& type, const String& name, int width, int height) { HTMLCanvasElement* result = getCSSCanvasElement(name); if (!result) @@ -4531,10 +4713,12 @@ void Document::reportException(const String& errorMessage, int lineNumber, const void Document::addMessage(MessageDestination destination, MessageSource source, MessageType type, MessageLevel level, const String& message, unsigned lineNumber, const String& sourceURL) { switch (destination) { +#if ENABLE(INSPECTOR) case InspectorControllerDestination: if (page()) page()->inspectorController()->addMessageToConsole(source, type, level, message, lineNumber, sourceURL); return; +#endif case ConsoleDestination: if (DOMWindow* window = domWindow()) window->console()->addMessage(source, type, level, message, lineNumber, sourceURL); @@ -4545,24 +4729,31 @@ void Document::addMessage(MessageDestination destination, MessageSource source, void Document::resourceRetrievedByXMLHttpRequest(unsigned long identifier, const ScriptString& sourceString) { +#if ENABLE(INSPECTOR) if (page()) page()->inspectorController()->resourceRetrievedByXMLHttpRequest(identifier, sourceString); +#endif Frame* frame = this->frame(); if (frame) { FrameLoader* frameLoader = frame->loader(); - frameLoader->didLoadResourceByXMLHttpRequest(identifier, sourceString); + frameLoader->notifier()->didLoadResourceByXMLHttpRequest(identifier, sourceString); } } void Document::scriptImported(unsigned long identifier, const String& sourceString) { +#if ENABLE(INSPECTOR) if (page()) page()->inspectorController()->scriptImported(identifier, sourceString); +#else + UNUSED_PARAM(identifier); + UNUSED_PARAM(sourceString); +#endif } class ScriptExecutionContextTaskTimer : public TimerBase { public: - ScriptExecutionContextTaskTimer(PassRefPtr<Document> context, PassRefPtr<ScriptExecutionContext::Task> task) + ScriptExecutionContextTaskTimer(PassRefPtr<Document> context, PassOwnPtr<ScriptExecutionContext::Task> task) : m_context(context) , m_task(task) { @@ -4576,18 +4767,18 @@ private: } RefPtr<Document> m_context; - RefPtr<ScriptExecutionContext::Task> m_task; + OwnPtr<ScriptExecutionContext::Task> m_task; }; -struct PerformTaskContext { - PerformTaskContext(ScriptExecutionContext* scriptExecutionContext, PassRefPtr<ScriptExecutionContext::Task> task) +struct PerformTaskContext : Noncopyable { + PerformTaskContext(ScriptExecutionContext* scriptExecutionContext, PassOwnPtr<ScriptExecutionContext::Task> task) : scriptExecutionContext(scriptExecutionContext) , task(task) { } ScriptExecutionContext* scriptExecutionContext; // The context should exist until task execution. - RefPtr<ScriptExecutionContext::Task> task; + OwnPtr<ScriptExecutionContext::Task> task; }; static void performTask(void* ctx) @@ -4597,7 +4788,7 @@ static void performTask(void* ctx) delete ptctx; } -void Document::postTask(PassRefPtr<Task> task) +void Document::postTask(PassOwnPtr<Task> task) { if (isMainThread()) { ScriptExecutionContextTaskTimer* timer = new ScriptExecutionContextTaskTimer(static_cast<Document*>(this), task); @@ -4662,4 +4853,11 @@ bool Document::isXHTMLMPDocument() const } #endif +#if ENABLE(INSPECTOR) +InspectorTimelineAgent* Document::inspectorTimelineAgent() const +{ + return page() ? page()->inspectorTimelineAgent() : 0; +} +#endif + } // namespace WebCore |
