diff options
author | Ben Murdoch <benm@google.com> | 2011-01-16 13:59:45 +0000 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2011-01-16 14:14:41 +0000 |
commit | 8a26975f9657a07318a10d481d7f332dad759325 (patch) | |
tree | 3d4270ff2d0aa27bdbb26e83c1de9d6ac18cb4fc | |
parent | e137c43847f22807f1276afc87027711cc3f4e77 (diff) | |
download | external_webkit-8a26975f9657a07318a10d481d7f332dad759325.zip external_webkit-8a26975f9657a07318a10d481d7f332dad759325.tar.gz external_webkit-8a26975f9657a07318a10d481d7f332dad759325.tar.bz2 |
Merge WebKit at Chromium 9.0.597.69: Trivial merge by Git.
http://svn.webkit.org/repository/webkit/branches/chromium/597/WebCore@75681
Change-Id: Ibe552cf7af31f74b81e337eadf3d3b73a53daf60
36 files changed, 366 insertions, 204 deletions
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog index 2f8e863..b56a885 100644 --- a/WebCore/ChangeLog +++ b/WebCore/ChangeLog @@ -1,3 +1,69 @@ +2011-01-12 Kenichi Ishibashi <bashi@google.com> + + Reviewed by Kent Tamura. + + M_formElementsWithFormAttribute not cleared when FormAssociatedElement is inserted with a null m_form and then removed. + https://bugs.webkit.org/show_bug.cgi?id=51905 + + Calls unregisterFormElementWithFormAttribute() when 'form' attribute + is removed. + + Tests: fast/forms/form-associated-element-crash.html + fast/forms/form-associated-element-crash2.html + + * html/FormAssociatedElement.cpp: + (WebCore::FormAssociatedElement::formAttributeChanged): + +2011-01-12 Kenichi Ishibashi <bashi@google.com> + + Reviewed by Kent Tamura. + + M_formElementsWithFormAttribute not cleared when Node is moved to another document. + https://bugs.webkit.org/show_bug.cgi?id=51418 + + Calls unregisterFormElementWithFormAttribute() when form associated elements + are moved to another document. + + Test: fast/forms/change-form-element-document-crash.html + + * html/FormAssociatedElement.cpp: + (WebCore::FormAssociatedElement::willMoveToNewOwnerDocument): Added. + * html/FormAssociatedElement.h: Added willMoveToNewOwnerDocument(). + * html/HTMLFormControlElement.cpp: + (WebCore::HTMLFormControlElement::willMoveToNewOwnerDocument): Added. + * html/HTMLFormControlElement.h: Added willMoveToNewOwnerDocument(). + * html/HTMLObjectElement.cpp: + (WebCore::HTMLObjectElement::willMoveToNewOwnerDocument): Added. + * html/HTMLObjectElement.h: Added willMoveToNewOwnerDocument(). + * html/HTMLPlugInImageElement.h: Moves willMoveToNewOwnerDocument() to protected. + +2011-01-11 Merge 75548 - BUGCR69275 - Abhishek Arya <inferno@chromium.org> + + Reviewed by Dimitri Glazkov. + + RefPtr the FrameView to prevent scrollbar from getting deleted inside + its scroll event. + https://bugs.webkit.org/show_bug.cgi?id=52238 + + Test: scrollbars/scrollable-iframe-remove-crash.html + + * page/DOMWindow.cpp: + (WebCore::DOMWindow::scrollTo): + +2011-01-11 Abhishek Arya <inferno@chromium.org> + + Reviewed by Dimitri Glazkov. + + RefPtr text node in setOuterText since calling appendData + on a text node can fire away dom event listener which might + remove the text node from underneath. + https://bugs.webkit.org/show_bug.cgi?id=52163 + + Test: fast/dom/text-node-append-data-remove-crash.html + + * html/HTMLElement.cpp: + (WebCore::HTMLElement::setOuterText): + 2010-12-07 Jeremy Orlow <jorlow@chromium.org> Reviewed by Steve Block. diff --git a/WebCore/css/CSSCanvasValue.cpp b/WebCore/css/CSSCanvasValue.cpp index 767c11e..948dc74 100644 --- a/WebCore/css/CSSCanvasValue.cpp +++ b/WebCore/css/CSSCanvasValue.cpp @@ -34,7 +34,7 @@ namespace WebCore { CSSCanvasValue::~CSSCanvasValue() { if (m_element) - m_element->setObserver(0); + m_element->removeObserver(this); } String CSSCanvasValue::cssText() const @@ -79,7 +79,7 @@ HTMLCanvasElement* CSSCanvasValue::element(Document* document) m_element = document->getCSSCanvasElement(m_name); if (!m_element) return 0; - m_element->setObserver(this); + m_element->addObserver(this); } return m_element; } diff --git a/WebCore/css/CSSCursorImageValue.cpp b/WebCore/css/CSSCursorImageValue.cpp index 2ebbece..c4b5de7 100644 --- a/WebCore/css/CSSCursorImageValue.cpp +++ b/WebCore/css/CSSCursorImageValue.cpp @@ -70,7 +70,7 @@ CSSCursorImageValue::~CSSCursorImageValue() for (; it != end; ++it) { SVGElement* referencedElement = *it; - referencedElement->cursorElementRemoved(); + referencedElement->cursorImageValueRemoved(); if (SVGCursorElement* cursorElement = resourceReferencedByCursorElement(url, referencedElement->document())) cursorElement->removeClient(referencedElement); } diff --git a/WebCore/css/CSSRuleList.cpp b/WebCore/css/CSSRuleList.cpp index 7367ab2..0a312af 100644 --- a/WebCore/css/CSSRuleList.cpp +++ b/WebCore/css/CSSRuleList.cpp @@ -76,6 +76,7 @@ void CSSRuleList::deleteRule(unsigned index) return; } + m_lstCSSRules[index]->setParent(0); m_lstCSSRules.remove(index); } diff --git a/WebCore/css/CSSStyleSheet.cpp b/WebCore/css/CSSStyleSheet.cpp index 04df693..d5487a1 100644 --- a/WebCore/css/CSSStyleSheet.cpp +++ b/WebCore/css/CSSStyleSheet.cpp @@ -164,6 +164,7 @@ void CSSStyleSheet::deleteRule(unsigned index, ExceptionCode& ec) } ec = 0; + item(index)->setParent(0); remove(index); styleSheetChanged(); } diff --git a/WebCore/dom/Node.cpp b/WebCore/dom/Node.cpp index 42a200b..23096df 100644 --- a/WebCore/dom/Node.cpp +++ b/WebCore/dom/Node.cpp @@ -2642,6 +2642,22 @@ static const EventContext* topEventContext(const Vector<EventContext>& ancestors return ancestors.isEmpty() ? 0 : &ancestors.last(); } +static EventDispatchBehavior determineDispatchBehavior(Event* event) +{ + // Per XBL 2.0 spec, mutation events should never cross shadow DOM boundary: + // http://dev.w3.org/2006/xbl2/#event-flow-and-targeting-across-shadow-s + if (event->isMutationEvent()) + return StayInsideShadowDOM; + + // WebKit never allowed selectstart event to cross the the shadow DOM boundary. + // Changing this breaks existing sites. + // See https://bugs.webkit.org/show_bug.cgi?id=52195 for details. + if (event->type() == eventNames().selectstartEvent) + return StayInsideShadowDOM; + + return RetargetEvent; +} + bool Node::dispatchGenericEvent(PassRefPtr<Event> prpEvent) { RefPtr<Event> event(prpEvent); @@ -2656,7 +2672,7 @@ bool Node::dispatchGenericEvent(PassRefPtr<Event> prpEvent) RefPtr<Node> thisNode(this); RefPtr<EventTarget> originalTarget = event->target(); Vector<EventContext> ancestors; - getEventAncestors(ancestors, originalTarget.get(), event->isMutationEvent() ? StayInsideShadowDOM : RetargetEvent); + getEventAncestors(ancestors, originalTarget.get(), determineDispatchBehavior(event.get())); WindowEventContext windowContext(event.get(), this, topEventContext(ancestors)); diff --git a/WebCore/dom/Range.cpp b/WebCore/dom/Range.cpp index 5507b83..71bf08e 100644 --- a/WebCore/dom/Range.cpp +++ b/WebCore/dom/Range.cpp @@ -41,9 +41,12 @@ #include <stdio.h> #include <wtf/text/CString.h> #include <wtf/RefCountedLeakCounter.h> +#include <wtf/Vector.h> namespace WebCore { +typedef Vector<RefPtr<Node> > NodeVector; + using namespace std; #ifndef NDEBUG @@ -595,9 +598,6 @@ bool Range::intersectsNode(Node* refNode, ExceptionCode& ec) PassRefPtr<DocumentFragment> Range::processContents(ActionType action, ExceptionCode& ec) { - // FIXME: To work properly with mutation events, we will have to take into account - // situations where the tree is being transformed while we work on it - ugh! - RefPtr<DocumentFragment> fragment; if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) fragment = DocumentFragment::create(m_ownerDocument.get()); @@ -655,21 +655,20 @@ PassRefPtr<DocumentFragment> Range::processContents(ActionType action, Exception pi->setData(data, ec); } } else { - Node* n = m_start.container()->firstChild(); + RefPtr<Node> n = m_start.container()->firstChild(); int i; for (i = 0; n && i < m_start.offset(); i++) // skip until start offset n = n->nextSibling(); int endOffset = m_end.offset(); - while (n && i < endOffset) { // delete until end offset - Node* next = n->nextSibling(); + RefPtr<Node> next; + for (; n && i < endOffset; n = next, i++) { // delete until end offset + next = n->nextSibling(); if (action == EXTRACT_CONTENTS) fragment->appendChild(n, ec); // will remove n from its parent else if (action == CLONE_CONTENTS) fragment->appendChild(n->cloneNode(true), ec); else - toContainerNode(m_start.container())->removeChild(n, ec); - n = next; - i++; + m_start.container()->removeChild(n.get(), ec); } } return fragment.release(); @@ -720,39 +719,47 @@ PassRefPtr<DocumentFragment> Range::processContents(ActionType action, Exception } else { if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) leftContents = m_start.container()->cloneNode(false); + NodeVector nodes; Node* n = m_start.container()->firstChild(); - for (int i = 0; n && i < m_start.offset(); i++) // skip until start offset - n = n->nextSibling(); - while (n) { // process until end - Node* next = n->nextSibling(); + for (int i = 0; n; n = n->nextSibling(), i++) { + if (i < m_start.offset()) + continue; // Skip until start offset. + nodes.append(n); + } + for (NodeVector::const_iterator it = nodes.begin(); it != nodes.end(); it++) { + Node* n = it->get(); if (action == EXTRACT_CONTENTS) - leftContents->appendChild(n, ec); // will remove n from start container + leftContents->appendChild(n, ec); // Will remove n from start container. else if (action == CLONE_CONTENTS) leftContents->appendChild(n->cloneNode(true), ec); else toContainerNode(m_start.container())->removeChild(n, ec); - n = next; } } - ContainerNode* leftParent = m_start.container()->parentNode(); - Node* n = m_start.container()->nextSibling(); - for (; leftParent != commonRoot; leftParent = leftParent->parentNode()) { + NodeVector ancestorNodes; + for (ContainerNode* n = m_start.container()->parentNode(); n && n != commonRoot; n = n->parentNode()) + ancestorNodes.append(n); + RefPtr<Node> n = m_start.container()->nextSibling(); + for (NodeVector::const_iterator it = ancestorNodes.begin(); it != ancestorNodes.end(); it++) { + Node* leftParent = it->get(); if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) { RefPtr<Node> leftContentsParent = leftParent->cloneNode(false); - leftContentsParent->appendChild(leftContents, ec); - leftContents = leftContentsParent; + if (leftContentsParent) { // Might have been removed already during mutation event. + leftContentsParent->appendChild(leftContents, ec); + leftContents = leftContentsParent; + } } - Node* next; + RefPtr<Node> next; for (; n; n = next) { next = n->nextSibling(); if (action == EXTRACT_CONTENTS) - leftContents->appendChild(n, ec); // will remove n from leftParent + leftContents->appendChild(n.get(), ec); // will remove n from leftParent else if (action == CLONE_CONTENTS) leftContents->appendChild(n->cloneNode(true), ec); else - leftParent->removeChild(n, ec); + leftParent->removeChild(n.get(), ec); } n = leftParent->nextSibling(); } @@ -786,15 +793,16 @@ PassRefPtr<DocumentFragment> Range::processContents(ActionType action, Exception rightContents = m_end.container()->cloneNode(false); Node* n = m_end.container()->firstChild(); if (n && m_end.offset()) { - for (int i = 0; i + 1 < m_end.offset(); i++) { // skip to end.offset() - Node* next = n->nextSibling(); - if (!next) + NodeVector nodes; + int i = 0; + do { + nodes.append(n); + if (!n->nextSibling()) break; - n = next; - } - Node* prev; - for (; n; n = prev) { - prev = n->previousSibling(); + n = n->nextSibling(); + } while (i + 1 < m_end.offset()); + for (int i = nodes.size() - 1; i >= 0; i--) { + n = nodes[i].get(); if (action == EXTRACT_CONTENTS) rightContents->insertBefore(n, rightContents->firstChild(), ec); // will remove n from its parent else if (action == CLONE_CONTENTS) @@ -868,11 +876,12 @@ PassRefPtr<DocumentFragment> Range::processContents(ActionType action, Exception if ((action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) && leftContents) fragment->appendChild(leftContents, ec); - Node* next; - Node* n; if (processStart) { - for (n = processStart; n && n != processEnd; n = next) { - next = n->nextSibling(); + NodeVector nodes; + for (Node* n = processStart; n && n != processEnd; n = n->nextSibling()) + nodes.append(n); + for (NodeVector::const_iterator it = nodes.begin(); it != nodes.end(); it++) { + Node* n = it->get(); if (action == EXTRACT_CONTENTS) fragment->appendChild(n, ec); // will remove from commonRoot else if (action == CLONE_CONTENTS) diff --git a/WebCore/editing/ReplaceSelectionCommand.cpp b/WebCore/editing/ReplaceSelectionCommand.cpp index fb52e56..d7b101a 100644 --- a/WebCore/editing/ReplaceSelectionCommand.cpp +++ b/WebCore/editing/ReplaceSelectionCommand.cpp @@ -50,9 +50,12 @@ #include "markup.h" #include "visible_units.h" #include <wtf/StdLibExtras.h> +#include <wtf/Vector.h> namespace WebCore { +typedef Vector<RefPtr<Node> > NodeVector; + using namespace HTMLNames; enum EFragmentType { EmptyFragment, SingleTextNodeFragment, TreeFragment }; @@ -682,7 +685,12 @@ void ReplaceSelectionCommand::handleStyleSpans() void ReplaceSelectionCommand::copyStyleToChildren(Node* parentNode, const CSSMutableStyleDeclaration* parentStyle) { ASSERT(parentNode->hasTagName(spanTag)); - for (Node* childNode = parentNode->firstChild(); childNode; childNode = childNode->nextSibling()) { + NodeVector childNodes; + for (RefPtr<Node> childNode = parentNode->firstChild(); childNode; childNode = childNode->nextSibling()) + childNodes.append(childNode); + + for (NodeVector::const_iterator it = childNodes.begin(); it != childNodes.end(); it++) { + Node* childNode = it->get(); if (childNode->isTextNode() || !isBlock(childNode) || childNode->hasTagName(preTag)) { // In this case, put a span tag around the child node. RefPtr<Node> newNode = parentNode->cloneNode(false); @@ -864,6 +872,10 @@ void ReplaceSelectionCommand::doApply() // Inserting content could cause whitespace to collapse, e.g. inserting <div>foo</div> into hello^ world. prepareWhitespaceAtPositionForSplit(insertionPos); + + // If the downstream node has been removed there's no point in continuing. + if (!insertionPos.downstream().node()) + return; // NOTE: This would be an incorrect usage of downstream() if downstream() were changed to mean the last position after // p that maps to the same visible position as p (since in the case where a br is at the end of a block and collapsed @@ -942,8 +954,8 @@ void ReplaceSelectionCommand::doApply() bool plainTextFragment = isPlainTextMarkup(refNode.get()); while (node) { - Node* next = node->nextSibling(); - fragment.removeNode(node); + RefPtr<Node> next = node->nextSibling(); + fragment.removeNode(node.get()); insertNodeAfterAndUpdateNodesInserted(node, refNode.get()); // Mutation events (bug 22634) may have already removed the inserted content diff --git a/WebCore/html/HTMLCanvasElement.cpp b/WebCore/html/HTMLCanvasElement.cpp index fea70d1..e8ffe5e 100644 --- a/WebCore/html/HTMLCanvasElement.cpp +++ b/WebCore/html/HTMLCanvasElement.cpp @@ -71,7 +71,6 @@ static const float MaxSkiaDim = 32767.0F; // Maximum width/height in CSS pixels. HTMLCanvasElement::HTMLCanvasElement(const QualifiedName& tagName, Document* document) : HTMLElement(tagName, document) - , m_observer(0) , m_size(DefaultWidth, DefaultHeight) , m_ignoreReset(false) , m_pageScaleFactor(document->frame() ? document->frame()->page()->chrome()->scaleFactor() : 1) @@ -93,8 +92,9 @@ PassRefPtr<HTMLCanvasElement> HTMLCanvasElement::create(const QualifiedName& tag HTMLCanvasElement::~HTMLCanvasElement() { - if (m_observer) - m_observer->canvasDestroyed(this); + HashSet<CanvasObserver*>::iterator end = m_observers.end(); + for (HashSet<CanvasObserver*>::iterator it = m_observers.begin(); it != end; ++it) + (*it)->canvasDestroyed(this); } void HTMLCanvasElement::parseMappedAttribute(Attribute* attr) @@ -117,6 +117,16 @@ RenderObject* HTMLCanvasElement::createRenderer(RenderArena* arena, RenderStyle* return HTMLElement::createRenderer(arena, style); } +void HTMLCanvasElement::addObserver(CanvasObserver* observer) +{ + m_observers.add(observer); +} + +void HTMLCanvasElement::removeObserver(CanvasObserver* observer) +{ + m_observers.remove(observer); +} + void HTMLCanvasElement::setHeight(int value) { setAttribute(heightAttr, String::number(value)); @@ -200,8 +210,9 @@ void HTMLCanvasElement::didDraw(const FloatRect& rect) ro->repaintRectangle(enclosingIntRect(m_dirtyRect)); } - if (m_observer) - m_observer->canvasChanged(this, rect); + HashSet<CanvasObserver*>::iterator end = m_observers.end(); + for (HashSet<CanvasObserver*>::iterator it = m_observers.begin(); it != end; ++it) + (*it)->canvasChanged(this, rect); } void HTMLCanvasElement::reset() @@ -238,8 +249,9 @@ void HTMLCanvasElement::reset() } } - if (m_observer) - m_observer->canvasResized(this); + HashSet<CanvasObserver*>::iterator end = m_observers.end(); + for (HashSet<CanvasObserver*>::iterator it = m_observers.begin(); it != end; ++it) + (*it)->canvasResized(this); } void HTMLCanvasElement::paint(GraphicsContext* context, const IntRect& r) diff --git a/WebCore/html/HTMLCanvasElement.h b/WebCore/html/HTMLCanvasElement.h index e6c0155..30f0d35 100644 --- a/WebCore/html/HTMLCanvasElement.h +++ b/WebCore/html/HTMLCanvasElement.h @@ -65,7 +65,8 @@ public: static PassRefPtr<HTMLCanvasElement> create(const QualifiedName&, Document*); virtual ~HTMLCanvasElement(); - void setObserver(CanvasObserver* observer) { m_observer = observer; } + void addObserver(CanvasObserver* observer); + void removeObserver(CanvasObserver* observer); // Attributes and functions exposed to script int width() const { return size().width(); } @@ -154,7 +155,7 @@ private: void setSurfaceSize(const IntSize&); bool hasCreatedImageBuffer() const { return m_hasCreatedImageBuffer; } - CanvasObserver* m_observer; + HashSet<CanvasObserver*> m_observers; IntSize m_size; diff --git a/WebCore/html/HTMLElement.cpp b/WebCore/html/HTMLElement.cpp index 4dcf998..0bd6ba5 100644 --- a/WebCore/html/HTMLElement.cpp +++ b/WebCore/html/HTMLElement.cpp @@ -474,7 +474,7 @@ void HTMLElement::setOuterText(const String &text, ExceptionCode& ec) // Is previous node a text node? If so, merge into it. Node* prev = t->previousSibling(); if (prev && prev->isTextNode()) { - Text* textPrev = static_cast<Text*>(prev); + RefPtr<Text> textPrev = static_cast<Text*>(prev); textPrev->appendData(t->data(), ec); if (ec) return; @@ -487,7 +487,7 @@ void HTMLElement::setOuterText(const String &text, ExceptionCode& ec) // Is next node a text node? If so, merge it in. Node* next = t->nextSibling(); if (next && next->isTextNode()) { - Text* textNext = static_cast<Text*>(next); + RefPtr<Text> textNext = static_cast<Text*>(next); t->appendData(textNext->data(), ec); if (ec) return; diff --git a/WebCore/html/HTMLFormControlElement.cpp b/WebCore/html/HTMLFormControlElement.cpp index 2f5d414..daf4b93 100644 --- a/WebCore/html/HTMLFormControlElement.cpp +++ b/WebCore/html/HTMLFormControlElement.cpp @@ -152,6 +152,13 @@ void HTMLFormControlElement::attach() focus(); } +void HTMLFormControlElement::willMoveToNewOwnerDocument() +{ + if (fastHasAttribute(formAttr)) + document()->unregisterFormElementWithFormAttribute(this); + HTMLElement::willMoveToNewOwnerDocument(); +} + void HTMLFormControlElement::insertedIntoTree(bool deep) { if (fastHasAttribute(formAttr)) { @@ -482,6 +489,7 @@ void HTMLFormControlElement::attributeChanged(Attribute* attr, bool preserveDecl m_form->registerFormElement(this); else document()->checkedRadioButtons().addButton(this); + document()->unregisterFormElementWithFormAttribute(this); } else resetFormOwner(0); } diff --git a/WebCore/html/HTMLFormControlElement.h b/WebCore/html/HTMLFormControlElement.h index 568f63e..c5ed013 100644 --- a/WebCore/html/HTMLFormControlElement.h +++ b/WebCore/html/HTMLFormControlElement.h @@ -109,6 +109,7 @@ protected: virtual void attach(); virtual void insertedIntoTree(bool deep); virtual void removedFromTree(bool deep); + virtual void willMoveToNewOwnerDocument(); virtual bool isKeyboardFocusable(KeyboardEvent*) const; virtual bool isMouseFocusable() const; diff --git a/WebCore/html/MediaDocument.cpp b/WebCore/html/MediaDocument.cpp index af66795..d6fe6dd 100644 --- a/WebCore/html/MediaDocument.cpp +++ b/WebCore/html/MediaDocument.cpp @@ -131,47 +131,52 @@ PassRefPtr<DocumentParser> MediaDocument::createParser() return MediaDocumentParser::create(this); } +static inline HTMLVideoElement* descendentVideoElement(Node* node) +{ + ASSERT(node); + + if (node->hasTagName(videoTag)) + return static_cast<HTMLVideoElement*>(node); + + RefPtr<NodeList> nodeList = node->getElementsByTagNameNS(videoTag.namespaceURI(), videoTag.localName()); + + if (nodeList.get()->length() > 0) + return static_cast<HTMLVideoElement*>(nodeList.get()->item(0)); + + return 0; +} + void MediaDocument::defaultEventHandler(Event* event) { // Match the default Quicktime plugin behavior to allow // clicking and double-clicking to pause and play the media. Node* targetNode = event->target()->toNode(); - if (targetNode && targetNode->hasTagName(videoTag)) { - HTMLVideoElement* video = static_cast<HTMLVideoElement*>(targetNode); - if (event->type() == eventNames().clickEvent) { - if (!video->canPlay()) { - video->pause(event->fromUserGesture()); - event->setDefaultHandled(); - } - } else if (event->type() == eventNames().dblclickEvent) { - if (video->canPlay()) { - video->play(event->fromUserGesture()); - event->setDefaultHandled(); - } - } - } + if (!targetNode) + return; + + HTMLVideoElement* video = descendentVideoElement(targetNode); + if (!video) + return; - if (event->type() == eventNames().keydownEvent && event->isKeyboardEvent()) { - HTMLVideoElement* video = 0; - if (targetNode) { - if (targetNode->hasTagName(videoTag)) - video = static_cast<HTMLVideoElement*>(targetNode); - else { - RefPtr<NodeList> nodeList = targetNode->getElementsByTagName("video"); - if (nodeList.get()->length() > 0) - video = static_cast<HTMLVideoElement*>(nodeList.get()->item(0)); - } + if (event->type() == eventNames().clickEvent) { + if (!video->canPlay()) { + video->pause(event->fromUserGesture()); + event->setDefaultHandled(); } - if (video) { - KeyboardEvent* keyboardEvent = static_cast<KeyboardEvent*>(event); - if (keyboardEvent->keyIdentifier() == "U+0020") { // space - if (video->paused()) { - if (video->canPlay()) - video->play(event->fromUserGesture()); - } else - video->pause(event->fromUserGesture()); - event->setDefaultHandled(); - } + } else if (event->type() == eventNames().dblclickEvent) { + if (video->canPlay()) { + video->play(event->fromUserGesture()); + event->setDefaultHandled(); + } + } else if (event->type() == eventNames().keydownEvent && event->isKeyboardEvent()) { + KeyboardEvent* keyboardEvent = static_cast<KeyboardEvent*>(event); + if (keyboardEvent->keyIdentifier() == "U+0020") { // space + if (video->paused()) { + if (video->canPlay()) + video->play(event->fromUserGesture()); + } else + video->pause(event->fromUserGesture()); + event->setDefaultHandled(); } } } @@ -196,11 +201,7 @@ void MediaDocument::replaceMediaElementTimerFired(Timer<MediaDocument>*) htmlBody->setAttribute(marginwidthAttr, "0"); htmlBody->setAttribute(marginheightAttr, "0"); - RefPtr<NodeList> nodeList = htmlBody->getElementsByTagName("video"); - - if (nodeList.get()->length() > 0) { - HTMLVideoElement* videoElement = static_cast<HTMLVideoElement*>(nodeList.get()->item(0)); - + if (HTMLVideoElement* videoElement = descendentVideoElement(htmlBody)) { RefPtr<Element> element = Document::createElement(embedTag, false); HTMLEmbedElement* embedElement = static_cast<HTMLEmbedElement*>(element.get()); diff --git a/WebCore/inspector/InspectorCSSAgent.cpp b/WebCore/inspector/InspectorCSSAgent.cpp index 31d951a..ee06e54 100644 --- a/WebCore/inspector/InspectorCSSAgent.cpp +++ b/WebCore/inspector/InspectorCSSAgent.cpp @@ -186,7 +186,7 @@ void InspectorCSSAgent::getStylesForNode2(long nodeId, RefPtr<InspectorValue>* r resultObject->setObject("inlineStyle", styleSheet->buildObjectForStyle(element->style())); RefPtr<CSSComputedStyleDeclaration> computedStyleInfo = computedStyle(element, true); // Support the viewing of :visited information in computed style. - RefPtr<InspectorStyle> computedInspectorStyle = InspectorStyle::create(InspectorCSSId(), computedStyleInfo.get(), 0); + RefPtr<InspectorStyle> computedInspectorStyle = InspectorStyle::create(InspectorCSSId(), computedStyleInfo, 0); resultObject->setObject("computedStyle", computedInspectorStyle->buildObjectForStyle()); CSSStyleSelector* selector = element->ownerDocument()->styleSelector(); @@ -248,7 +248,7 @@ void InspectorCSSAgent::getComputedStyleForNode2(long nodeId, RefPtr<InspectorVa return; RefPtr<CSSComputedStyleDeclaration> computedStyleInfo = computedStyle(element, true); - RefPtr<InspectorStyle> inspectorStyle = InspectorStyle::create(InspectorCSSId(), computedStyleInfo.get(), 0); + RefPtr<InspectorStyle> inspectorStyle = InspectorStyle::create(InspectorCSSId(), computedStyleInfo, 0); *style = inspectorStyle->buildObjectForStyle(); } diff --git a/WebCore/inspector/InspectorController.cpp b/WebCore/inspector/InspectorController.cpp index 243b7ac..d0ae442 100644 --- a/WebCore/inspector/InspectorController.cpp +++ b/WebCore/inspector/InspectorController.cpp @@ -839,11 +839,12 @@ void InspectorController::willSendRequest(unsigned long identifier, ResourceRequ if (!enabled()) return; - request.setReportLoadTiming(true); - // Only enable raw headers if front-end is attached, as otherwise we may lack + // Only enable load timing and raw headers if front-end is attached, as otherwise we may produce overhead. // permissions to fetch the headers. - if (m_frontend) + if (m_frontend) { + request.setReportLoadTiming(true); request.setReportRawHeaders(true); + } bool isMainResource = m_mainResourceIdentifier == identifier; diff --git a/WebCore/inspector/InspectorStyleSheet.cpp b/WebCore/inspector/InspectorStyleSheet.cpp index c468e3b..b115d85 100644 --- a/WebCore/inspector/InspectorStyleSheet.cpp +++ b/WebCore/inspector/InspectorStyleSheet.cpp @@ -131,6 +131,19 @@ static PassRefPtr<CSSRuleList> asCSSRuleList(StyleBase* styleBase) return 0; } +PassRefPtr<InspectorStyle> InspectorStyle::create(const InspectorCSSId& styleId, PassRefPtr<CSSStyleDeclaration> style, InspectorStyleSheet* parentStyleSheet) +{ + return adoptRef(new InspectorStyle(styleId, style, parentStyleSheet)); +} + +InspectorStyle::InspectorStyle(const InspectorCSSId& styleId, PassRefPtr<CSSStyleDeclaration> style, InspectorStyleSheet* parentStyleSheet) + : m_styleId(styleId) + , m_style(style) + , m_parentStyleSheet(parentStyleSheet) +{ + ASSERT(m_style); +} + PassRefPtr<InspectorObject> InspectorStyle::buildObjectForStyle() const { RefPtr<InspectorObject> result = InspectorObject::create(); @@ -141,7 +154,7 @@ PassRefPtr<InspectorObject> InspectorStyle::buildObjectForStyle() const propertiesObject->setString("width", m_style->getPropertyValue("width")); propertiesObject->setString("height", m_style->getPropertyValue("height")); - RefPtr<CSSRuleSourceData> sourceData = m_parentStyleSheet ? m_parentStyleSheet->ruleSourceDataFor(m_style) : 0; + RefPtr<CSSRuleSourceData> sourceData = m_parentStyleSheet ? m_parentStyleSheet->ruleSourceDataFor(m_style.get()) : 0; if (sourceData) { propertiesObject->setNumber("startOffset", sourceData->styleSourceData->styleBodyRange.start); propertiesObject->setNumber("endOffset", sourceData->styleSourceData->styleBodyRange.end); @@ -215,7 +228,7 @@ bool InspectorStyle::setPropertyText(unsigned index, const String& propertyText, } } else { // Insert at index. - RefPtr<CSSRuleSourceData> sourceData = m_parentStyleSheet->ruleSourceDataFor(m_style); + RefPtr<CSSRuleSourceData> sourceData = m_parentStyleSheet->ruleSourceDataFor(m_style.get()); if (!sourceData) return false; String text; @@ -255,7 +268,7 @@ bool InspectorStyle::setPropertyText(unsigned index, const String& propertyText, } text.insert(textToSet, propertyStart); - m_parentStyleSheet->setStyleText(m_style, text); + m_parentStyleSheet->setStyleText(m_style.get(), text); } // Recompute subsequent disabled property ranges if acting on a non-disabled property. @@ -269,7 +282,7 @@ bool InspectorStyle::toggleProperty(unsigned index, bool disable) ASSERT(m_parentStyleSheet); if (!m_parentStyleSheet->ensureParsedDataReady()) return false; // Can toggle only source-based properties. - RefPtr<CSSRuleSourceData> sourceData = m_parentStyleSheet->ruleSourceDataFor(m_style); + RefPtr<CSSRuleSourceData> sourceData = m_parentStyleSheet->ruleSourceDataFor(m_style.get()); if (!sourceData) return false; // No source data for the style. @@ -310,7 +323,7 @@ unsigned InspectorStyle::disabledIndexByOrdinal(unsigned ordinal, bool canUseSub bool InspectorStyle::styleText(String* result) const { // Precondition: m_parentStyleSheet->ensureParsedDataReady() has been called successfully. - RefPtr<CSSRuleSourceData> sourceData = m_parentStyleSheet->ruleSourceDataFor(m_style); + RefPtr<CSSRuleSourceData> sourceData = m_parentStyleSheet->ruleSourceDataFor(m_style.get()); if (!sourceData) return false; @@ -379,7 +392,7 @@ bool InspectorStyle::populateAllProperties(Vector<InspectorStyleProperty>* resul if (disabledIndex < disabledLength) disabledProperty = m_disabledProperties.at(disabledIndex); - RefPtr<CSSRuleSourceData> sourceData = (m_parentStyleSheet && m_parentStyleSheet->ensureParsedDataReady()) ? m_parentStyleSheet->ruleSourceDataFor(m_style) : 0; + RefPtr<CSSRuleSourceData> sourceData = (m_parentStyleSheet && m_parentStyleSheet->ensureParsedDataReady()) ? m_parentStyleSheet->ruleSourceDataFor(m_style.get()) : 0; Vector<CSSPropertySourceData>* sourcePropertyData = sourceData ? &(sourceData->styleSourceData->propertyData) : 0; if (sourcePropertyData) { String styleDeclaration; @@ -506,7 +519,7 @@ bool InspectorStyle::replacePropertyInStyleText(const InspectorStyleProperty& pr return false; const SourceRange& range = property.sourceData.range; text.replace(range.start, range.end - range.start, newText); - success = m_parentStyleSheet->setStyleText(m_style, text); + success = m_parentStyleSheet->setStyleText(m_style.get(), text); return success; } @@ -561,7 +574,12 @@ Vector<String> InspectorStyle::longhandProperties(const String& shorthandPropert return properties; } -InspectorStyleSheet::InspectorStyleSheet(const String& id, CSSStyleSheet* pageStyleSheet, const String& origin, const String& documentURL) +PassRefPtr<InspectorStyleSheet> InspectorStyleSheet::create(const String& id, PassRefPtr<CSSStyleSheet> pageStyleSheet, const String& origin, const String& documentURL) +{ + return adoptRef(new InspectorStyleSheet(id, pageStyleSheet, origin, documentURL)); +} + +InspectorStyleSheet::InspectorStyleSheet(const String& id, PassRefPtr<CSSStyleSheet> pageStyleSheet, const String& origin, const String& documentURL) : m_id(id) , m_pageStyleSheet(pageStyleSheet) , m_origin(origin) @@ -1090,12 +1108,17 @@ void InspectorStyleSheet::collectFlatRules(PassRefPtr<CSSRuleList> ruleList, Vec } } -InspectorStyleSheetForInlineStyle::InspectorStyleSheetForInlineStyle(const String& id, Element* element, const String& origin) +PassRefPtr<InspectorStyleSheetForInlineStyle> InspectorStyleSheetForInlineStyle::create(const String& id, PassRefPtr<Element> element, const String& origin) +{ + return adoptRef(new InspectorStyleSheetForInlineStyle(id, element, origin)); +} + +InspectorStyleSheetForInlineStyle::InspectorStyleSheetForInlineStyle(const String& id, PassRefPtr<Element> element, const String& origin) : InspectorStyleSheet(id, 0, origin, "") , m_element(element) , m_ruleSourceData(0) { - ASSERT(element); + ASSERT(m_element); m_inspectorStyle = InspectorStyle::create(InspectorCSSId(id, 0), inlineStyle(), this); } @@ -1152,7 +1175,7 @@ bool InspectorStyleSheetForInlineStyle::getStyleAttributeRanges(RefPtr<CSSStyleS if (!m_element->isStyledElement()) return false; - String styleText = static_cast<StyledElement*>(m_element)->getAttribute(styleAttributeName); + String styleText = static_cast<StyledElement*>(m_element.get())->getAttribute(styleAttributeName); if (styleText.isEmpty()) { (*result)->styleBodyRange.start = 0; (*result)->styleBodyRange.end = 0; diff --git a/WebCore/inspector/InspectorStyleSheet.h b/WebCore/inspector/InspectorStyleSheet.h index b649bed..2e5f2bc 100644 --- a/WebCore/inspector/InspectorStyleSheet.h +++ b/WebCore/inspector/InspectorStyleSheet.h @@ -26,6 +26,7 @@ #define InspectorStyleSheet_h #include "CSSPropertySourceData.h" +#include "CSSStyleDeclaration.h" #include "InspectorValues.h" #include "PlatformString.h" @@ -40,7 +41,6 @@ class ParsedStyleSheet; namespace WebCore { class CSSRuleList; -class CSSStyleDeclaration; class CSSStyleSheet; class Document; class Element; @@ -121,26 +121,17 @@ struct InspectorStyleProperty { class InspectorStyle : public RefCounted<InspectorStyle> { public: - static PassRefPtr<InspectorStyle> create(const InspectorCSSId& styleId, CSSStyleDeclaration* style, InspectorStyleSheet* parentStyleSheet) - { - return adoptRef(new InspectorStyle(styleId, style, parentStyleSheet)); - } - - InspectorStyle(const InspectorCSSId& styleId, CSSStyleDeclaration* style, InspectorStyleSheet* parentStyleSheet) - : m_styleId(styleId) - , m_style(style) - , m_parentStyleSheet(parentStyleSheet) - { - ASSERT(style); - } + static PassRefPtr<InspectorStyle> create(const InspectorCSSId& styleId, PassRefPtr<CSSStyleDeclaration> style, InspectorStyleSheet* parentStyleSheet); - CSSStyleDeclaration* cssStyle() const { return m_style; } + CSSStyleDeclaration* cssStyle() const { return m_style.get(); } PassRefPtr<InspectorObject> buildObjectForStyle() const; bool hasDisabledProperties() const { return !m_disabledProperties.isEmpty(); } bool setPropertyText(unsigned index, const String& text, bool overwrite); bool toggleProperty(unsigned index, bool disable); private: + InspectorStyle(const InspectorCSSId& styleId, PassRefPtr<CSSStyleDeclaration> style, InspectorStyleSheet* parentStyleSheet); + static unsigned disabledIndexByOrdinal(unsigned ordinal, bool canUseSubsequent, Vector<InspectorStyleProperty>& allProperties); bool styleText(String* result) const; @@ -155,7 +146,7 @@ private: Vector<String> longhandProperties(const String& shorthandProperty) const; InspectorCSSId m_styleId; - CSSStyleDeclaration* m_style; + RefPtr<CSSStyleDeclaration> m_style; InspectorStyleSheet* m_parentStyleSheet; Vector<InspectorStyleProperty> m_disabledProperties; }; @@ -163,17 +154,13 @@ private: class InspectorStyleSheet : public RefCounted<InspectorStyleSheet> { public: typedef HashMap<CSSStyleDeclaration*, RefPtr<InspectorStyle> > InspectorStyleMap; - static PassRefPtr<InspectorStyleSheet> create(const String& id, CSSStyleSheet* pageStyleSheet, const String& origin, const String& documentURL) - { - return adoptRef(new InspectorStyleSheet(id, pageStyleSheet, origin, documentURL)); - } + static PassRefPtr<InspectorStyleSheet> create(const String& id, PassRefPtr<CSSStyleSheet> pageStyleSheet, const String& origin, const String& documentURL); - InspectorStyleSheet(const String& id, CSSStyleSheet* pageStyleSheet, const String& origin, const String& documentURL); virtual ~InspectorStyleSheet(); String id() const { return m_id; } String finalURL() const; - CSSStyleSheet* pageStyleSheet() const { return m_pageStyleSheet; } + CSSStyleSheet* pageStyleSheet() const { return m_pageStyleSheet.get(); } void reparseStyleSheet(const String&); bool setText(const String&); bool setRuleSelector(const InspectorCSSId&, const String& selector); @@ -189,6 +176,8 @@ public: virtual CSSStyleDeclaration* styleForId(const InspectorCSSId&) const; protected: + InspectorStyleSheet(const String& id, PassRefPtr<CSSStyleSheet> pageStyleSheet, const String& origin, const String& documentURL); + bool canBind() const { return m_origin != "userAgent" && m_origin != "user"; } InspectorCSSId ruleOrStyleId(CSSStyleDeclaration* style) const; virtual Document* ownerDocument() const; @@ -218,7 +207,7 @@ private: PassRefPtr<InspectorArray> buildArrayForRuleList(CSSRuleList*); String m_id; - CSSStyleSheet* m_pageStyleSheet; + RefPtr<CSSStyleSheet> m_pageStyleSheet; String m_origin; String m_documentURL; bool m_isRevalidating; @@ -231,16 +220,14 @@ private: class InspectorStyleSheetForInlineStyle : public InspectorStyleSheet { public: - static PassRefPtr<InspectorStyleSheetForInlineStyle> create(const String& id, Element* element, const String& origin) - { - return adoptRef(new InspectorStyleSheetForInlineStyle(id, element, origin)); - } + static PassRefPtr<InspectorStyleSheetForInlineStyle> create(const String& id, PassRefPtr<Element> element, const String& origin); - InspectorStyleSheetForInlineStyle(const String& id, Element* element, const String& origin); virtual bool text(String* result) const; virtual CSSStyleDeclaration* styleForId(const InspectorCSSId& id) const { ASSERT_UNUSED(id, !id.ordinal()); return inlineStyle(); } protected: + InspectorStyleSheetForInlineStyle(const String& id, PassRefPtr<Element> element, const String& origin); + virtual Document* ownerDocument() const; virtual RefPtr<CSSRuleSourceData> ruleSourceDataFor(CSSStyleDeclaration* style) const { ASSERT_UNUSED(style, style == inlineStyle()); return m_ruleSourceData; } virtual unsigned ruleIndexByStyle(CSSStyleDeclaration*) const { return 0; } @@ -256,7 +243,7 @@ private: CSSStyleDeclaration* inlineStyle() const; bool getStyleAttributeRanges(RefPtr<CSSStyleSourceData>* result); - Element* m_element; + RefPtr<Element> m_element; RefPtr<CSSRuleSourceData> m_ruleSourceData; RefPtr<InspectorStyle> m_inspectorStyle; }; diff --git a/WebCore/inspector/front-end/AuditLauncherView.js b/WebCore/inspector/front-end/AuditLauncherView.js index d4bbf90..3ec4ba2 100644 --- a/WebCore/inspector/front-end/AuditLauncherView.js +++ b/WebCore/inspector/front-end/AuditLauncherView.js @@ -53,24 +53,6 @@ WebInspector.AuditLauncherView = function(runnerCallback) } WebInspector.AuditLauncherView.prototype = { - updateResourceTrackingState: function(isTracking) - { - if (!this._auditPresentStateLabelElement) - return; - - if (isTracking) { - this._auditPresentStateLabelElement.nodeValue = WebInspector.UIString("Audit Present State"); - this._auditPresentStateElement.disabled = false; - this._auditPresentStateElement.parentElement.removeStyleClass("disabled"); - } else { - this._resetResourceCount(); - this._auditPresentStateLabelElement.nodeValue = WebInspector.UIString("Audit Present State (Resource Tracking must be enabled)"); - this._auditPresentStateElement.disabled = true; - this._auditPresentStateElement.parentElement.addStyleClass("disabled"); - this.auditReloadedStateElement.checked = true; - } - }, - get totalResources() { return this._totalResources; @@ -237,7 +219,7 @@ WebInspector.AuditLauncherView.prototype = { this._auditPresentStateElement.name = "audit-mode"; this._auditPresentStateElement.type = "radio"; this._auditPresentStateElement.checked = true; - this._auditPresentStateLabelElement = document.createTextNode(""); + this._auditPresentStateLabelElement = document.createTextNode(WebInspector.UIString("Audit Present State")); labelElement.appendChild(this._auditPresentStateElement); labelElement.appendChild(this._auditPresentStateLabelElement); this._buttonContainerElement.appendChild(labelElement); @@ -267,7 +249,6 @@ WebInspector.AuditLauncherView.prototype = { this._contentElement.appendChild(this._buttonContainerElement); this._selectAllClicked(this._selectAllCheckboxElement.checked); - this.updateResourceTrackingState(); this._updateButton(); this._updateResourceProgress(); }, diff --git a/WebCore/inspector/front-end/AuditsPanel.js b/WebCore/inspector/front-end/AuditsPanel.js index 096f8ce..c42077f 100644 --- a/WebCore/inspector/front-end/AuditsPanel.js +++ b/WebCore/inspector/front-end/AuditsPanel.js @@ -248,12 +248,6 @@ WebInspector.AuditsPanel.prototype = { x.show(this.viewsContainerElement); }, - show: function() - { - WebInspector.Panel.prototype.show.call(this); - this._updateLauncherViewControls(!WebInspector.panels.resources || WebInspector.panels.resources.resourceTrackingEnabled); - }, - reset: function() { this._launcherView.reset(); @@ -271,12 +265,6 @@ WebInspector.AuditsPanel.prototype = { this.viewsContainerElement.style.left = width + "px"; }, - _updateLauncherViewControls: function(isTracking) - { - if (this._launcherView) - this._launcherView.updateResourceTrackingState(isTracking); - }, - _clearButtonClicked: function() { this.auditsItemTreeElement.reveal(); diff --git a/WebCore/inspector/front-end/ResourceManager.js b/WebCore/inspector/front-end/ResourceManager.js index 8c1ddac..992d8c7 100644 --- a/WebCore/inspector/front-end/ResourceManager.js +++ b/WebCore/inspector/front-end/ResourceManager.js @@ -268,6 +268,7 @@ WebInspector.ResourceManager.prototype = { if (mainResource) { WebInspector.mainResource = mainResource; mainResource.isMainResource = true; + WebInspector.panels.network.refreshResource(mainResource); } } }, diff --git a/WebCore/inspector/front-end/StylesSidebarPane.js b/WebCore/inspector/front-end/StylesSidebarPane.js index db72486..5399953 100644 --- a/WebCore/inspector/front-end/StylesSidebarPane.js +++ b/WebCore/inspector/front-end/StylesSidebarPane.js @@ -1202,6 +1202,8 @@ WebInspector.StylePropertyTreeElement.prototype = { this.valueElement = valueElement; if (value) { + var self = this; + function processValue(regex, processor, nextProcessor, valueText) { var container = document.createDocumentFragment(); @@ -1225,10 +1227,19 @@ WebInspector.StylePropertyTreeElement.prototype = { function linkifyURL(url) { + var hrefUrl = url; + var match = hrefUrl.match(/['"]?([^'"]+)/); + if (match) + hrefUrl = match[1]; var container = document.createDocumentFragment(); container.appendChild(document.createTextNode("url(")); - var hasResource = !!WebInspector.resourceForURL(url); - container.appendChild(WebInspector.linkifyURLAsNode(url, url, null, hasResource)); + if (self._styleRule.sourceURL) + hrefUrl = WebInspector.completeURL(self._styleRule.sourceURL, hrefUrl); + else if (WebInspector.panels.elements.focusedDOMNode) + hrefUrl = WebInspector.resourceURLForRelatedNode(WebInspector.panels.elements.focusedDOMNode, hrefUrl); + var hasResource = !!WebInspector.resourceForURL(hrefUrl); + // FIXME: WebInspector.linkifyURLAsNode() should really use baseURI. + container.appendChild(WebInspector.linkifyURLAsNode(hrefUrl, url, null, hasResource)); container.appendChild(document.createTextNode(")")); return container; } @@ -1330,7 +1341,7 @@ WebInspector.StylePropertyTreeElement.prototype = { var colorRegex = /((?:rgb|hsl)a?\([^)]+\)|#[0-9a-fA-F]{6}|#[0-9a-fA-F]{3}|\b\w+\b(?!-))/g; var colorProcessor = processValue.bind(window, colorRegex, processColor, null); - valueElement.appendChild(processValue(/url\(([^)]+)\)/g, linkifyURL, colorProcessor, value)); + valueElement.appendChild(processValue(/url\(\s*([^)\s]+)\s*\)/g, linkifyURL, colorProcessor, value)); } this.listItemElement.removeChildren(); diff --git a/WebCore/loader/ResourceLoadNotifier.cpp b/WebCore/loader/ResourceLoadNotifier.cpp index d002ef3..a36ed94 100644 --- a/WebCore/loader/ResourceLoadNotifier.cpp +++ b/WebCore/loader/ResourceLoadNotifier.cpp @@ -128,6 +128,10 @@ void ResourceLoadNotifier::dispatchWillSendRequest(DocumentLoader* loader, unsig if (Page* page = m_frame->page()) page->inspectorController()->willSendRequest(identifier, request, redirectResponse); #endif + + // Report WebTiming for all frames. + if (loader && !request.isNull() && request.url() == loader->requestURL()) + request.setReportLoadTiming(true); } void ResourceLoadNotifier::dispatchDidReceiveResponse(DocumentLoader* loader, unsigned long identifier, const ResourceResponse& r) diff --git a/WebCore/page/DOMWindow.cpp b/WebCore/page/DOMWindow.cpp index fb64a76..22e1355 100644 --- a/WebCore/page/DOMWindow.cpp +++ b/WebCore/page/DOMWindow.cpp @@ -1341,7 +1341,7 @@ void DOMWindow::scrollBy(int x, int y) const m_frame->document()->updateLayoutIgnorePendingStylesheets(); - FrameView* view = m_frame->view(); + RefPtr<FrameView> view = m_frame->view(); if (!view) return; diff --git a/WebCore/page/FrameView.cpp b/WebCore/page/FrameView.cpp index 0e2404e..3154a67 100644 --- a/WebCore/page/FrameView.cpp +++ b/WebCore/page/FrameView.cpp @@ -1254,8 +1254,11 @@ bool FrameView::scrollToAnchor(const String& name) if (anchorNode && anchorNode->hasTagName(SVGNames::viewTag)) { RefPtr<SVGViewElement> viewElement = anchorNode->hasTagName(SVGNames::viewTag) ? static_cast<SVGViewElement*>(anchorNode) : 0; if (viewElement.get()) { - RefPtr<SVGSVGElement> svg = static_cast<SVGSVGElement*>(SVGLocatable::nearestViewportElement(viewElement.get())); - svg->inheritViewAttributes(viewElement.get()); + SVGElement* element = SVGLocatable::nearestViewportElement(viewElement.get()); + if (element->hasTagName(SVGNames::svgTag)) { + RefPtr<SVGSVGElement> svg = static_cast<SVGSVGElement*>(element); + svg->inheritViewAttributes(viewElement.get()); + } } } } diff --git a/WebCore/rendering/RenderBlock.cpp b/WebCore/rendering/RenderBlock.cpp index 8c5b994..4609f1b 100644 --- a/WebCore/rendering/RenderBlock.cpp +++ b/WebCore/rendering/RenderBlock.cpp @@ -393,10 +393,15 @@ RenderBlock* RenderBlock::containingColumnsBlock(bool allowAnonymousColumnBlock) RenderBlock* RenderBlock::clone() const { - RenderBlock* o = new (renderArena()) RenderBlock(node()); - o->setStyle(style()); - o->setChildrenInline(childrenInline()); - return o; + RenderBlock* cloneBlock; + if (isAnonymousBlock()) + cloneBlock = createAnonymousBlock(); + else { + cloneBlock = new (renderArena()) RenderBlock(node()); + cloneBlock->setStyle(style()); + } + cloneBlock->setChildrenInline(childrenInline()); + return cloneBlock; } void RenderBlock::splitBlocks(RenderBlock* fromBlock, RenderBlock* toBlock, @@ -404,13 +409,9 @@ void RenderBlock::splitBlocks(RenderBlock* fromBlock, RenderBlock* toBlock, RenderObject* beforeChild, RenderBoxModelObject* oldCont) { // Create a clone of this inline. - RenderBlock* cloneBlock; - if (isAnonymousBlock()) - cloneBlock = createAnonymousBlock(); - else { - cloneBlock = clone(); + RenderBlock* cloneBlock = clone(); + if (!isAnonymousBlock()) cloneBlock->setContinuation(oldCont); - } // Now take all of the children from beforeChild to the end and remove // them from |this| and place them in the clone. @@ -435,7 +436,7 @@ void RenderBlock::splitBlocks(RenderBlock* fromBlock, RenderBlock* toBlock, // Create a new clone. RenderBlock* cloneChild = cloneBlock; - cloneBlock = blockCurr->isAnonymousBlock() ? blockCurr->createAnonymousBlock() : blockCurr->clone(); + cloneBlock = blockCurr->clone(); // Insert our child clone as the first child. cloneBlock->children()->appendChildNode(cloneBlock, cloneChild); @@ -946,7 +947,7 @@ static bool canMergeContiguousAnonymousBlocks(RenderObject* oldChild, RenderObje // Make sure the types of the anonymous blocks match up. return prev->isAnonymousColumnsBlock() == next->isAnonymousColumnsBlock() - && prev->isAnonymousColumnSpanBlock() == prev->isAnonymousColumnSpanBlock(); + && prev->isAnonymousColumnSpanBlock() == next->isAnonymousColumnSpanBlock(); } void RenderBlock::removeChild(RenderObject* oldChild) @@ -980,14 +981,36 @@ void RenderBlock::removeChild(RenderObject* oldChild) blockChildrenBlock->children()->insertChildNode(blockChildrenBlock, inlineChildrenBlock, prev == inlineChildrenBlock ? blockChildrenBlock->firstChild() : 0, inlineChildrenBlock->hasLayer() || blockChildrenBlock->hasLayer()); next->setNeedsLayoutAndPrefWidthsRecalc(); + + // inlineChildrenBlock got reparented to blockChildrenBlock, so it is no longer a child + // of "this". we null out prev or next so that is not used later in the function. + if (inlineChildrenBlock == prevBlock) + prev = 0; + else + next = 0; } else { // Take all the children out of the |next| block and put them in // the |prev| block. nextBlock->moveAllChildrenTo(prevBlock, nextBlock->hasLayer() || prevBlock->hasLayer()); - + + // FIXME: When we destroy nextBlock, it might happen that nextBlock's next sibling block and + // oldChild can get merged. Since oldChild is getting removed, we do not want to move + // nextBlock's next sibling block's children into it. By setting a fake continuation, + // we prevent this from happening. + RenderBlock* oldChildBlock = 0; + if (oldChild->isAnonymous() && oldChild->isRenderBlock() && !toRenderBlock(oldChild)->continuation()) { + oldChildBlock = toRenderBlock(oldChild); + oldChildBlock->setContinuation(oldChildBlock); + } + // Delete the now-empty block's lines and nuke it. nextBlock->deleteLineBoxTree(); nextBlock->destroy(); + next = 0; + + // FIXME: Revert the continuation change done above. + if (oldChildBlock) + oldChildBlock->setContinuation(0); } } diff --git a/WebCore/rendering/RenderTable.cpp b/WebCore/rendering/RenderTable.cpp index de10680..43b6b03 100644 --- a/WebCore/rendering/RenderTable.cpp +++ b/WebCore/rendering/RenderTable.cpp @@ -183,6 +183,8 @@ void RenderTable::addChild(RenderObject* child, RenderObject* beforeChild) while (lastBox && lastBox->parent()->isAnonymous() && !lastBox->isTableSection() && lastBox->style()->display() != TABLE_CAPTION && lastBox->style()->display() != TABLE_COLUMN_GROUP) lastBox = lastBox->parent(); if (lastBox && lastBox->isAnonymous() && !isAfterContent(lastBox)) { + if (beforeChild == lastBox) + beforeChild = lastBox->firstChild(); lastBox->addChild(child, beforeChild); return; } diff --git a/WebCore/rendering/RenderTableRow.cpp b/WebCore/rendering/RenderTableRow.cpp index 98544a6..ec523b0 100644 --- a/WebCore/rendering/RenderTableRow.cpp +++ b/WebCore/rendering/RenderTableRow.cpp @@ -73,7 +73,9 @@ void RenderTableRow::addChild(RenderObject* child, RenderObject* beforeChild) if (!last) last = lastChild(); if (last && last->isAnonymous() && last->isTableCell()) { - last->addChild(child); + if (beforeChild == last) + beforeChild = last->firstChild(); + last->addChild(child, beforeChild); return; } diff --git a/WebCore/rendering/RenderTableSection.cpp b/WebCore/rendering/RenderTableSection.cpp index 30620d2..3598053 100644 --- a/WebCore/rendering/RenderTableSection.cpp +++ b/WebCore/rendering/RenderTableSection.cpp @@ -100,7 +100,9 @@ void RenderTableSection::addChild(RenderObject* child, RenderObject* beforeChild if (!last) last = lastChild(); if (last && last->isAnonymous()) { - last->addChild(child); + if (beforeChild == last) + beforeChild = last->firstChild(); + last->addChild(child, beforeChild); return; } diff --git a/WebCore/svg/SVGElement.cpp b/WebCore/svg/SVGElement.cpp index 615aaab..09773d3 100644 --- a/WebCore/svg/SVGElement.cpp +++ b/WebCore/svg/SVGElement.cpp @@ -222,7 +222,7 @@ void SVGElement::setCursorImageValue(CSSCursorImageValue* cursorImageValue) rareData->setCursorImageValue(cursorImageValue); } -void SVGElement::cursorImageElementRemoved() +void SVGElement::cursorImageValueRemoved() { ASSERT(hasRareSVGData()); rareSVGData()->setCursorImageValue(0); diff --git a/WebCore/svg/SVGElement.h b/WebCore/svg/SVGElement.h index 3098335..0471fcc 100644 --- a/WebCore/svg/SVGElement.h +++ b/WebCore/svg/SVGElement.h @@ -77,7 +77,7 @@ namespace WebCore { void setCursorElement(SVGCursorElement*); void cursorElementRemoved(); void setCursorImageValue(CSSCursorImageValue*); - void cursorImageElementRemoved(); + void cursorImageValueRemoved(); virtual void updateAnimatedSVGAttribute(const QualifiedName&) const; diff --git a/WebCore/svg/SVGElementInstance.cpp b/WebCore/svg/SVGElementInstance.cpp index f2812dd..a873f0b 100644 --- a/WebCore/svg/SVGElementInstance.cpp +++ b/WebCore/svg/SVGElementInstance.cpp @@ -103,7 +103,8 @@ void SVGElementInstance::invalidateAllInstancesOfElement(SVGElement* element) const HashSet<SVGElementInstance*>::const_iterator end = set.end(); for (HashSet<SVGElementInstance*>::const_iterator it = set.begin(); it != end; ++it) { ASSERT((*it)->correspondingElement() == element); - (*it)->correspondingUseElement()->invalidateShadowTree(); + if (SVGUseElement* element = (*it)->correspondingUseElement()) + element->invalidateShadowTree(); } // Be sure to rebuild use trees, if needed diff --git a/WebCore/svg/SVGElementInstance.h b/WebCore/svg/SVGElementInstance.h index 54471c1..160a366 100644 --- a/WebCore/svg/SVGElementInstance.h +++ b/WebCore/svg/SVGElementInstance.h @@ -57,6 +57,7 @@ namespace WebCore { SVGElement* correspondingElement() const { return m_element.get(); } SVGUseElement* correspondingUseElement() const { return m_useElement; } SVGElement* shadowTreeElement() const { return m_shadowTreeElement.get(); } + void clearUseElement() { m_useElement = 0; } SVGElementInstance* parentNode() const { return parent(); } PassRefPtr<SVGElementInstanceList> childNodes(); diff --git a/WebCore/svg/SVGLength.cpp b/WebCore/svg/SVGLength.cpp index 8168cf6..5377c7f 100644 --- a/WebCore/svg/SVGLength.cpp +++ b/WebCore/svg/SVGLength.cpp @@ -92,13 +92,9 @@ inline SVGLengthType stringToLengthType(const UChar*& ptr, const UChar* end) return LengthTypeNumber; const UChar firstChar = *ptr; - ++ptr; - if (firstChar == '%') { - if (ptr == end) - return LengthTypePercentage; - return LengthTypeUnknown; - } + if (++ptr == end) + return firstChar == '%' ? LengthTypePercentage : LengthTypeUnknown; const UChar secondChar = *ptr; diff --git a/WebCore/svg/SVGUseElement.cpp b/WebCore/svg/SVGUseElement.cpp index fc01fd9..909c663 100644 --- a/WebCore/svg/SVGUseElement.cpp +++ b/WebCore/svg/SVGUseElement.cpp @@ -130,7 +130,7 @@ void SVGUseElement::insertedIntoDocument() void SVGUseElement::removedFromDocument() { SVGStyledTransformableElement::removedFromDocument(); - m_targetElementInstance = 0; + detachInstance(); } void SVGUseElement::svgAttributeChanged(const QualifiedName& attrName) @@ -496,8 +496,7 @@ void SVGUseElement::buildShadowAndInstanceTree(SVGShadowTreeRootElement* shadowR if (targetElement && targetElement->isSVGElement()) target = static_cast<SVGElement*>(targetElement); - if (m_targetElementInstance) - m_targetElementInstance = 0; + detachInstance(); // Do not allow self-referencing. // 'target' may be null, if it's a non SVG namespaced element. @@ -523,7 +522,7 @@ void SVGUseElement::buildShadowAndInstanceTree(SVGShadowTreeRootElement* shadowR // SVG specification does not say a word about <use> & cycles. My view on this is: just ignore it! // Non-appearing <use> content is easier to debug, then half-appearing content. if (foundProblem) { - m_targetElementInstance = 0; + detachInstance(); return; } @@ -556,7 +555,7 @@ void SVGUseElement::buildShadowAndInstanceTree(SVGShadowTreeRootElement* shadowR // Do NOT leave an inconsistent instance tree around, instead destruct it. if (!m_targetElementInstance->shadowTreeElement()) { shadowRoot->removeAllChildren(); - m_targetElementInstance = 0; + detachInstance(); return; } @@ -595,6 +594,14 @@ void SVGUseElement::buildShadowAndInstanceTree(SVGShadowTreeRootElement* shadowR updateRelativeLengthsInformation(); } +void SVGUseElement::detachInstance() +{ + if (!m_targetElementInstance) + return; + m_targetElementInstance->clearUseElement(); + m_targetElementInstance = 0; +} + RenderObject* SVGUseElement::createRenderer(RenderArena* arena, RenderStyle*) { return new (arena) RenderSVGShadowTreeRootContainer(this); @@ -617,7 +624,7 @@ void SVGUseElement::attach() void SVGUseElement::detach() { SVGStyledTransformableElement::detach(); - m_targetElementInstance = 0; + detachInstance(); } static bool isDirectReference(Node* n) diff --git a/WebCore/svg/SVGUseElement.h b/WebCore/svg/SVGUseElement.h index b127450..845270d 100644 --- a/WebCore/svg/SVGUseElement.h +++ b/WebCore/svg/SVGUseElement.h @@ -78,6 +78,7 @@ namespace WebCore { friend class RenderSVGShadowTreeRootContainer; bool isPendingResource() const { return m_isPendingResource; } void buildShadowAndInstanceTree(SVGShadowTreeRootElement*); + void detachInstance(); virtual bool selfHasRelativeLengths() const; |