+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.
CSSCanvasValue::~CSSCanvasValue()
{
if (m_element)
- m_element->setObserver(0);
+ m_element->removeObserver(this);
}
String CSSCanvasValue::cssText() const
m_element = document->getCSSCanvasElement(m_name);
if (!m_element)
return 0;
- m_element->setObserver(this);
+ m_element->addObserver(this);
}
return m_element;
}
for (; it != end; ++it) {
SVGElement* referencedElement = *it;
- referencedElement->cursorElementRemoved();
+ referencedElement->cursorImageValueRemoved();
if (SVGCursorElement* cursorElement = resourceReferencedByCursorElement(url, referencedElement->document()))
cursorElement->removeClient(referencedElement);
}
return;
}
+ m_lstCSSRules[index]->setParent(0);
m_lstCSSRules.remove(index);
}
}
ec = 0;
+ item(index)->setParent(0);
remove(index);
styleSheetChanged();
}
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);
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));
#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
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());
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();
} 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();
}
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)
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)
#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 };
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);
// 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
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
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)
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)
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));
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()
}
}
- 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)
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(); }
void setSurfaceSize(const IntSize&);
bool hasCreatedImageBuffer() const { return m_hasCreatedImageBuffer; }
- CanvasObserver* m_observer;
+ HashSet<CanvasObserver*> m_observers;
IntSize m_size;
// 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;
// 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;
focus();
}
+void HTMLFormControlElement::willMoveToNewOwnerDocument()
+{
+ if (fastHasAttribute(formAttr))
+ document()->unregisterFormElementWithFormAttribute(this);
+ HTMLElement::willMoveToNewOwnerDocument();
+}
+
void HTMLFormControlElement::insertedIntoTree(bool deep)
{
if (fastHasAttribute(formAttr)) {
m_form->registerFormElement(this);
else
document()->checkedRadioButtons().addButton(this);
+ document()->unregisterFormElementWithFormAttribute(this);
} else
resetFormOwner(0);
}
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;
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();
}
}
}
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());
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();
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();
}
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;
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();
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);
}
} 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;
}
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.
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.
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;
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;
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;
}
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)
}
}
-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);
}
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;
#define InspectorStyleSheet_h
#include "CSSPropertySourceData.h"
+#include "CSSStyleDeclaration.h"
#include "InspectorValues.h"
#include "PlatformString.h"
namespace WebCore {
class CSSRuleList;
-class CSSStyleDeclaration;
class CSSStyleSheet;
class Document;
class Element;
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;
Vector<String> longhandProperties(const String& shorthandProperty) const;
InspectorCSSId m_styleId;
- CSSStyleDeclaration* m_style;
+ RefPtr<CSSStyleDeclaration> m_style;
InspectorStyleSheet* m_parentStyleSheet;
Vector<InspectorStyleProperty> m_disabledProperties;
};
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);
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;
PassRefPtr<InspectorArray> buildArrayForRuleList(CSSRuleList*);
String m_id;
- CSSStyleSheet* m_pageStyleSheet;
+ RefPtr<CSSStyleSheet> m_pageStyleSheet;
String m_origin;
String m_documentURL;
bool m_isRevalidating;
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; }
CSSStyleDeclaration* inlineStyle() const;
bool getStyleAttributeRanges(RefPtr<CSSStyleSourceData>* result);
- Element* m_element;
+ RefPtr<Element> m_element;
RefPtr<CSSRuleSourceData> m_ruleSourceData;
RefPtr<InspectorStyle> m_inspectorStyle;
};
}
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;
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);
this._contentElement.appendChild(this._buttonContainerElement);
this._selectAllClicked(this._selectAllCheckboxElement.checked);
- this.updateResourceTrackingState();
this._updateButton();
this._updateResourceProgress();
},
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();
this.viewsContainerElement.style.left = width + "px";
},
- _updateLauncherViewControls: function(isTracking)
- {
- if (this._launcherView)
- this._launcherView.updateResourceTrackingState(isTracking);
- },
-
_clearButtonClicked: function()
{
this.auditsItemTreeElement.reveal();
if (mainResource) {
WebInspector.mainResource = mainResource;
mainResource.isMainResource = true;
+ WebInspector.panels.network.refreshResource(mainResource);
}
}
},
this.valueElement = valueElement;
if (value) {
+ var self = this;
+
function processValue(regex, processor, nextProcessor, valueText)
{
var container = document.createDocumentFragment();
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;
}
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();
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)
m_frame->document()->updateLayoutIgnorePendingStylesheets();
- FrameView* view = m_frame->view();
+ RefPtr<FrameView> view = m_frame->view();
if (!view)
return;
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());
+ }
}
}
}
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,
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.
// 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);
// 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)
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);
}
}
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;
}
if (!last)
last = lastChild();
if (last && last->isAnonymous() && last->isTableCell()) {
- last->addChild(child);
+ if (beforeChild == last)
+ beforeChild = last->firstChild();
+ last->addChild(child, beforeChild);
return;
}
if (!last)
last = lastChild();
if (last && last->isAnonymous()) {
- last->addChild(child);
+ if (beforeChild == last)
+ beforeChild = last->firstChild();
+ last->addChild(child, beforeChild);
return;
}
rareData->setCursorImageValue(cursorImageValue);
}
-void SVGElement::cursorImageElementRemoved()
+void SVGElement::cursorImageValueRemoved()
{
ASSERT(hasRareSVGData());
rareSVGData()->setCursorImageValue(0);
void setCursorElement(SVGCursorElement*);
void cursorElementRemoved();
void setCursorImageValue(CSSCursorImageValue*);
- void cursorImageElementRemoved();
+ void cursorImageValueRemoved();
virtual void updateAnimatedSVGAttribute(const QualifiedName&) const;
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
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();
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;
void SVGUseElement::removedFromDocument()
{
SVGStyledTransformableElement::removedFromDocument();
- m_targetElementInstance = 0;
+ detachInstance();
}
void SVGUseElement::svgAttributeChanged(const QualifiedName& attrName)
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.
// 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;
}
// Do NOT leave an inconsistent instance tree around, instead destruct it.
if (!m_targetElementInstance->shadowTreeElement()) {
shadowRoot->removeAllChildren();
- m_targetElementInstance = 0;
+ detachInstance();
return;
}
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);
void SVGUseElement::detach()
{
SVGStyledTransformableElement::detach();
- m_targetElementInstance = 0;
+ detachInstance();
}
static bool isDirectReference(Node* n)
friend class RenderSVGShadowTreeRootContainer;
bool isPendingResource() const { return m_isPendingResource; }
void buildShadowAndInstanceTree(SVGShadowTreeRootElement*);
+ void detachInstance();
virtual bool selfHasRelativeLengths() const;