diff options
Diffstat (limited to 'WebCore/dom')
31 files changed, 608 insertions, 266 deletions
diff --git a/WebCore/dom/ActiveDOMObject.cpp b/WebCore/dom/ActiveDOMObject.cpp index 98c9761..0b70b24 100644 --- a/WebCore/dom/ActiveDOMObject.cpp +++ b/WebCore/dom/ActiveDOMObject.cpp @@ -66,7 +66,7 @@ bool ActiveDOMObject::canSuspend() const return false; } -void ActiveDOMObject::suspend() +void ActiveDOMObject::suspend(ReasonForSuspension) { } diff --git a/WebCore/dom/ActiveDOMObject.h b/WebCore/dom/ActiveDOMObject.h index 73b52d5..a6ec7d3 100644 --- a/WebCore/dom/ActiveDOMObject.h +++ b/WebCore/dom/ActiveDOMObject.h @@ -48,8 +48,13 @@ namespace WebCore { // However, 'suspend' can be called even if canSuspend() would return 'false'. That // happens in step-by-step JS debugging for example - in this case it would be incorrect // to stop the object. Exact semantics of suspend is up to the object then. + enum ReasonForSuspension { + JavaScriptDebuggerPaused, + WillShowDialog, + DocumentWillBecomeInactive + }; virtual bool canSuspend() const; - virtual void suspend(); + virtual void suspend(ReasonForSuspension); virtual void resume(); virtual void stop(); diff --git a/WebCore/dom/AsyncScriptRunner.cpp b/WebCore/dom/AsyncScriptRunner.cpp index 86251b8..a72df7c 100644 --- a/WebCore/dom/AsyncScriptRunner.cpp +++ b/WebCore/dom/AsyncScriptRunner.cpp @@ -78,6 +78,8 @@ void AsyncScriptRunner::timerFired(Timer<AsyncScriptRunner>* timer) { ASSERT_UNUSED(timer, timer == &m_timer); + RefPtr<Document> protect(m_document); + Vector<pair<ScriptElementData*, CachedResourceHandle<CachedScript> > > scripts; scripts.swap(m_scriptsToExecuteSoon); size_t size = scripts.size(); diff --git a/WebCore/dom/ContainerNode.cpp b/WebCore/dom/ContainerNode.cpp index 46de749..2dd50bb 100644 --- a/WebCore/dom/ContainerNode.cpp +++ b/WebCore/dom/ContainerNode.cpp @@ -72,7 +72,6 @@ void ContainerNode::removeAllChildren() removeAllChildrenInContainer<Node, ContainerNode>(this); } - void ContainerNode::takeAllChildrenFrom(ContainerNode* oldParent) { NodeVector children; @@ -82,10 +81,14 @@ void ContainerNode::takeAllChildrenFrom(ContainerNode* oldParent) for (unsigned i = 0; i < children.size(); ++i) { ExceptionCode ec = 0; + if (children[i]->attached()) + children[i]->detach(); // FIXME: We need a no mutation event version of adoptNode. RefPtr<Node> child = document()->adoptNode(children[i].release(), ec); ASSERT(!ec); - parserAddChild(child.release()); + parserAddChild(child.get()); + if (attached() && !child->attached()) + child->attach(); } } @@ -359,9 +362,7 @@ static void willRemoveChild(Node* child) // fire removed from document mutation events. dispatchChildRemovalEvents(child); - - if (child->attached()) - child->willRemove(); + child->willRemove(); } static void willRemoveChildren(ContainerNode* container) @@ -373,9 +374,7 @@ static void willRemoveChildren(ContainerNode* container) for (RefPtr<Node> child = container->firstChild(); child; child = child->nextSibling()) { // fire removed from document mutation events. dispatchChildRemovalEvents(child.get()); - - if (child->attached()) - child->willRemove(); + child->willRemove(); } } diff --git a/WebCore/dom/DOMStringMap.h b/WebCore/dom/DOMStringMap.h index e91d884..86a22b0 100644 --- a/WebCore/dom/DOMStringMap.h +++ b/WebCore/dom/DOMStringMap.h @@ -32,6 +32,7 @@ namespace WebCore { +class Element; typedef int ExceptionCode; class DOMStringMap : public Noncopyable { @@ -47,6 +48,8 @@ public: virtual void setItem(const String& name, const String& value, ExceptionCode&) = 0; virtual void deleteItem(const String& name, ExceptionCode&) = 0; + virtual Element* element() = 0; + protected: DOMStringMap() { diff --git a/WebCore/dom/DatasetDOMStringMap.h b/WebCore/dom/DatasetDOMStringMap.h index f82eaa5..632e365 100644 --- a/WebCore/dom/DatasetDOMStringMap.h +++ b/WebCore/dom/DatasetDOMStringMap.h @@ -49,6 +49,8 @@ public: virtual void setItem(const String& name, const String& value, ExceptionCode&); virtual void deleteItem(const String& name, ExceptionCode&); + virtual Element* element() { return m_element; } + private: DatasetDOMStringMap(Element* element) : m_element(element) diff --git a/WebCore/dom/Document.cpp b/WebCore/dom/Document.cpp index a92c5ab..262dad2 100644 --- a/WebCore/dom/Document.cpp +++ b/WebCore/dom/Document.cpp @@ -43,6 +43,7 @@ #include "Console.h" #include "CookieJar.h" #include "CustomEvent.h" +#include "DateComponents.h" #include "DOMImplementation.h" #include "DOMWindow.h" #include "DeviceMotionEvent.h" @@ -64,6 +65,7 @@ #include "FrameLoader.h" #include "FrameTree.h" #include "FrameView.h" +#include "HashChangeEvent.h" #include "HTMLAllCollection.h" #include "HTMLAnchorElement.h" #include "HTMLBodyElement.h" @@ -369,7 +371,7 @@ private: Document* m_document; }; -Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML) +Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML, const KURL& baseURL) : ContainerNode(0) , m_compatibilityMode(NoQuirksMode) , m_compatibilityModeLocked(false) @@ -439,7 +441,15 @@ Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML) if (frame || !url.isEmpty()) setURL(url); +<<<<<<< HEAD #if !PLATFORM(ANDROID) +======= + // Setting of m_baseURL needs to happen after the setURL call, since that + // calls updateBaseURL, which would clobber the passed in value. + if (!baseURL.isNull()) + m_baseURL = baseURL; + +>>>>>>> webkit.org at r67908 m_axObjectCache = 0; #endif @@ -623,6 +633,11 @@ void Document::setCompatibilityMode(CompatibilityMode mode) } } +String Document::compatMode() const +{ + return inQuirksMode() ? "BackCompat" : "CSS1Compat"; +} + void Document::resetLinkColor() { m_linkColor = Color(0, 0, 238); @@ -1079,7 +1094,7 @@ PassRefPtr<NodeList> Document::nodesFromRect(int centerX, int centerY, unsigned if (!frameView) return 0; - float zoomFactor = frameView->pageZoomFactor(); + float zoomFactor = frame->pageZoomFactor(); IntPoint point = roundedIntPoint(FloatPoint(centerX * zoomFactor + view()->scrollX(), centerY * zoomFactor + view()->scrollY())); IntSize padding(hPadding, vPadding); @@ -1132,7 +1147,7 @@ Element* Document::elementFromPoint(int x, int y) const if (!frameView) return 0; - float zoomFactor = frameView->pageZoomFactor(); + float zoomFactor = frame->pageZoomFactor(); IntPoint point = roundedIntPoint(FloatPoint(x * zoomFactor + view()->scrollX(), y * zoomFactor + view()->scrollY())); if (!frameView->visibleContentRect().contains(point)) @@ -1162,7 +1177,7 @@ PassRefPtr<Range> Document::caretRangeFromPoint(int x, int y) if (!frameView) return 0; - float zoomFactor = frameView->pageZoomFactor(); + float zoomFactor = frame->pageZoomFactor(); IntPoint point = roundedIntPoint(FloatPoint(x * zoomFactor + view()->scrollX(), y * zoomFactor + view()->scrollY())); if (!frameView->visibleContentRect().contains(point)) @@ -2000,26 +2015,6 @@ void Document::close() } } -// FIXME: These settings probably don't work anymore. We should either remove -// them or make them work properly. -#ifdef BUILDING_ON_LEOPARD -static bool shouldCreateImplicitHead(Document* document) -{ - ASSERT(document); - Settings* settings = document->page() ? document->page()->settings() : 0; - return settings ? !settings->needsLeopardMailQuirks() : true; -} -#elif defined(BUILDING_ON_TIGER) -static bool shouldCreateImplicitHead(Document* document) -{ - ASSERT(document); - Settings* settings = document->page() ? document->page()->settings() : 0; - return settings ? !settings->needsTigerMailQuirks() : true; -} -#else -inline bool shouldCreateImplicitHead(Document*) { return true; } -#endif - void Document::implicitClose() { // If we're in the middle of recalcStyle, we need to defer the close until the style information is accurate and all elements are re-attached. @@ -2046,21 +2041,6 @@ void Document::implicitClose() // Parser should have picked up all preloads by now m_cachedResourceLoader->clearPreloads(); - // Create a head and a body if we don't have those yet (e.g. for about:blank). - if (!this->body() && isHTMLDocument()) { - if (Node* documentElement = this->documentElement()) { - ExceptionCode ec = 0; - - // The implicit <head> isn't expected in older versions of Mail - <rdar://problem/6863795> - if (!head() && shouldCreateImplicitHead(this)) { - documentElement->appendChild(HTMLHeadElement::create(this), ec); - ASSERT(!ec); - } - documentElement->appendChild(HTMLBodyElement::create(this), ec); - ASSERT(!ec); - } - } - // FIXME: We kick off the icon loader when the Document is done parsing. // There are earlier opportunities we could start it: // -When the <head> finishes parsing @@ -2591,13 +2571,15 @@ void Document::processHttpEquiv(const String& equiv, const String& content) else if (equalIgnoringCase(equiv, "x-dns-prefetch-control")) parseDNSPrefetchControlHeader(content); else if (equalIgnoringCase(equiv, "x-frame-options")) { - FrameLoader* frameLoader = frame->loader(); - if (frameLoader->shouldInterruptLoadForXFrameOptions(content, url())) { - frameLoader->stopAllLoaders(); - frame->redirectScheduler()->scheduleLocationChange(blankURL(), String()); - - DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to display document because display forbidden by X-Frame-Options.\n")); - frame->domWindow()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, consoleMessage, 1, String()); + if (frame) { + FrameLoader* frameLoader = frame->loader(); + if (frameLoader->shouldInterruptLoadForXFrameOptions(content, url())) { + frameLoader->stopAllLoaders(); + frame->redirectScheduler()->scheduleLocationChange(blankURL(), String()); + + DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to display document because display forbidden by X-Frame-Options.\n")); + frame->domWindow()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, consoleMessage, 1, String()); + } } } } @@ -3321,7 +3303,7 @@ void Document::nodeChildrenWillBeRemoved(ContainerNode* container) if (Frame* frame = this->frame()) { for (Node* n = container->firstChild(); n; n = n->nextSibling()) { frame->selection()->nodeWillBeRemoved(n); - frame->dragCaretController()->nodeWillBeRemoved(n); + frame->page()->dragCaretController()->nodeWillBeRemoved(n); } } } @@ -3340,7 +3322,7 @@ void Document::nodeWillBeRemoved(Node* n) if (Frame* frame = this->frame()) { frame->selection()->nodeWillBeRemoved(n); - frame->dragCaretController()->nodeWillBeRemoved(n); + frame->page()->dragCaretController()->nodeWillBeRemoved(n); } #if ENABLE(FULLSCREEN_API) @@ -3695,15 +3677,24 @@ void Document::setDomain(const String& newDomain, ExceptionCode& ec) m_frame->script()->updateSecurityOrigin(); } +// http://www.whatwg.org/specs/web-apps/current-work/#dom-document-lastmodified String Document::lastModified() const { - Frame* f = frame(); - if (!f) - return String(); - DocumentLoader* loader = f->loader()->documentLoader(); - if (!loader) - return String(); - return loader->response().httpHeaderField("Last-Modified"); + DateComponents date; + bool foundDate = false; + if (m_frame) { + String httpLastModified = m_frame->loader()->documentLoader()->response().httpHeaderField("Last-Modified"); + if (!httpLastModified.isEmpty()) { + date.setMillisecondsSinceEpochForDateTime(parseDate(httpLastModified)); + foundDate = true; + } + } + // FIXME: If this document came from the file system, the HTML5 + // specificiation tells us to read the last modification date from the file + // system. + if (!foundDate) + date.setMillisecondsSinceEpochForDateTime(currentTimeMS()); + return String::format("%02d/%02d/%04d %02d:%02d:%02d", date.month() + 1, date.monthDay(), date.fullYear(), date.hour(), date.minute(), date.second()); } static bool isValidNameNonASCII(const UChar* characters, unsigned length) @@ -4037,10 +4028,9 @@ bool Document::inDesignMode() const Document* Document::parentDocument() const { - Frame* childPart = frame(); - if (!childPart) + if (!m_frame) return 0; - Frame* parent = childPart->tree()->parent(); + Frame* parent = m_frame->tree()->parent(); if (!parent) return 0; return parent->document(); @@ -4711,11 +4701,9 @@ void Document::enqueuePageshowEvent(PageshowEventPersistence persisted) dispatchWindowEvent(PageTransitionEvent::create(eventNames().pageshowEvent, persisted), this); } -void Document::enqueueHashchangeEvent(const String& /*oldURL*/, const String& /*newURL*/) +void Document::enqueueHashchangeEvent(const String& oldURL, const String& newURL) { - // FIXME: https://bugs.webkit.org/show_bug.cgi?id=36335 Hashchange event is now its own interface and takes two - // URL arguments which we need to pass in here. - enqueueEvent(Event::create(eventNames().hashchangeEvent, false, false)); + enqueueEvent(HashChangeEvent::create(oldURL, newURL)); } void Document::enqueuePopstateEvent(PassRefPtr<SerializedScriptValue> stateObject) diff --git a/WebCore/dom/Document.h b/WebCore/dom/Document.h index a8e3562..c1065fb 100644 --- a/WebCore/dom/Document.h +++ b/WebCore/dom/Document.h @@ -579,6 +579,8 @@ public: void lockCompatibilityMode() { m_compatibilityModeLocked = true; } CompatibilityMode compatibilityMode() const { return m_compatibilityMode; } + String compatMode() const; + bool inQuirksMode() const { return m_compatibilityMode == QuirksMode; } bool inLimitedQuirksMode() const { return m_compatibilityMode == LimitedQuirksMode; } bool inNoQuirksMode() const { return m_compatibilityMode == NoQuirksMode; } @@ -1033,7 +1035,7 @@ public: bool isDelayingLoadEvent() const { return m_loadEventDelayCount; } protected: - Document(Frame*, const KURL&, bool isXHTML, bool isHTML); + Document(Frame*, const KURL& url, bool isXHTML, bool isHTML, const KURL& baseURL = KURL()); void clearXMLVersion() { m_xmlVersion = String(); } diff --git a/WebCore/dom/Document.idl b/WebCore/dom/Document.idl index 0bd93b8..296bd44 100644 --- a/WebCore/dom/Document.idl +++ b/WebCore/dom/Document.idl @@ -233,6 +233,8 @@ module core { // HTML 5 NodeList getElementsByClassName(in DOMString tagname); + readonly attribute DOMString compatMode; + // NodeSelector - Selector API Element querySelector(in DOMString selectors) raises(DOMException); diff --git a/WebCore/dom/Element.cpp b/WebCore/dom/Element.cpp index 6ff47e0..5f53c2d 100644 --- a/WebCore/dom/Element.cpp +++ b/WebCore/dom/Element.cpp @@ -50,6 +50,7 @@ #include "RenderLayer.h" #include "RenderView.h" #include "RenderWidget.h" +#include "SVGStyledLocatableElement.h" #include "Settings.h" #include "TextIterator.h" #include "XMLNames.h" @@ -476,12 +477,25 @@ PassRefPtr<ClientRectList> Element::getClientRects() const PassRefPtr<ClientRect> Element::getBoundingClientRect() const { document()->updateLayoutIgnorePendingStylesheets(); - RenderBoxModelObject* renderBoxModelObject = this->renderBoxModelObject(); - if (!renderBoxModelObject) - return ClientRect::create(); Vector<FloatQuad> quads; - renderBoxModelObject->absoluteQuads(quads); +#if ENABLE(SVG) + if (isSVGElement()) { + // Get the bounding rectangle from the SVG model. + const SVGElement* svgElement = static_cast<const SVGElement*>(this); + if (svgElement->isStyledLocatable()) { + if (renderer()) { + const FloatRect& localRect = static_cast<const SVGStyledLocatableElement*>(svgElement)->getBBox(); + quads.append(renderer()->localToAbsoluteQuad(localRect)); + } + } + } else +#endif + { + // Get the bounding rectangle from the box model. + if (renderBoxModelObject()) + renderBoxModelObject()->absoluteQuads(quads); + } if (quads.isEmpty()) return ClientRect::create(); @@ -495,7 +509,8 @@ PassRefPtr<ClientRect> Element::getBoundingClientRect() const result.move(-visibleContentRect.x(), -visibleContentRect.y()); } - adjustIntRectForAbsoluteZoom(result, renderBoxModelObject); + if (renderBoxModelObject()) + adjustIntRectForAbsoluteZoom(result, renderBoxModelObject()); return ClientRect::create(result); } @@ -1347,9 +1362,9 @@ void Element::updateFocusAppearance(bool /*restorePreviousSelection*/) // FIXME: We should restore the previous selection if there is one. VisibleSelection newSelection = VisibleSelection(Position(this, 0), DOWNSTREAM); - if (frame->shouldChangeSelection(newSelection)) { + if (frame->selection()->shouldChangeSelection(newSelection)) { frame->selection()->setSelection(newSelection); - frame->revealSelection(); + frame->selection()->revealSelection(); } } else if (renderer() && !renderer()->isWidget()) renderer()->enclosingLayer()->scrollRectToVisible(getRect()); diff --git a/WebCore/dom/Event.cpp b/WebCore/dom/Event.cpp index c76f951..bb404fa 100644 --- a/WebCore/dom/Event.cpp +++ b/WebCore/dom/Event.cpp @@ -172,6 +172,11 @@ bool Event::isBeforeLoadEvent() const return false; } +bool Event::isHashChangeEvent() const +{ + return false; +} + #if ENABLE(SVG) bool Event::isSVGZoomEvent() const { diff --git a/WebCore/dom/Event.h b/WebCore/dom/Event.h index b992237..2a00eee 100644 --- a/WebCore/dom/Event.h +++ b/WebCore/dom/Event.h @@ -123,6 +123,7 @@ namespace WebCore { virtual bool isWebKitAnimationEvent() const; virtual bool isWebKitTransitionEvent() const; virtual bool isBeforeLoadEvent() const; + virtual bool isHashChangeEvent() const; #if ENABLE(SVG) virtual bool isSVGZoomEvent() const; #endif diff --git a/WebCore/dom/EventTarget.cpp b/WebCore/dom/EventTarget.cpp index effd2a2..d2b6f49 100644 --- a/WebCore/dom/EventTarget.cpp +++ b/WebCore/dom/EventTarget.cpp @@ -162,7 +162,7 @@ FileReader* EventTarget::toFileReader() return 0; } #endif -#if ENABLE(FILE_WRITER) +#if ENABLE(FILE_SYSTEM) FileWriter* EventTarget::toFileWriter() { return 0; diff --git a/WebCore/dom/EventTarget.h b/WebCore/dom/EventTarget.h index b2985f7..de7c2e0 100644 --- a/WebCore/dom/EventTarget.h +++ b/WebCore/dom/EventTarget.h @@ -124,7 +124,7 @@ namespace WebCore { #if ENABLE(BLOB) virtual FileReader* toFileReader(); #endif -#if ENABLE(FILE_WRITER) +#if ENABLE(FILE_SYSTEM) virtual FileWriter* toFileWriter(); #endif diff --git a/WebCore/dom/ExceptionCode.h b/WebCore/dom/ExceptionCode.h index ed15a2e..cbbf650 100644 --- a/WebCore/dom/ExceptionCode.h +++ b/WebCore/dom/ExceptionCode.h @@ -61,7 +61,7 @@ namespace WebCore { // Introduced in File API: // http://www.w3.org/TR/file-upload/#dfn-fileerror -#if ENABLE(BLOB) || ENABLE(FILE_WRITER) +#if ENABLE(BLOB) || ENABLE(FILE_SYSTEM) NOT_READABLE_ERR = 24, ENCODING_ERR = 26, #endif diff --git a/WebCore/dom/HashChangeEvent.h b/WebCore/dom/HashChangeEvent.h new file mode 100644 index 0000000..f1fa6af --- /dev/null +++ b/WebCore/dom/HashChangeEvent.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef HashChangeEvent_h +#define HashChangeEvent_h + +#include "Event.h" +#include "EventNames.h" + +namespace WebCore { + +class HashChangeEvent : public Event { +public: + virtual bool isHashChangeEvent() const { return true; } + + static PassRefPtr<HashChangeEvent> create(const String& oldURL, const String& newURL) + { + return adoptRef(new HashChangeEvent(oldURL, newURL)); + } + + void initHashChangeEvent(const AtomicString& eventType, bool canBubble, bool cancelable, const String& oldURL, const String& newURL) + { + if (dispatched()) + return; + + initEvent(eventType, canBubble, cancelable); + + m_oldURL = oldURL; + m_newURL = newURL; + } + + const String& oldURL() const { return m_oldURL; } + const String& newURL() const { return m_newURL; } + +private: + HashChangeEvent(const String& oldURL, const String& newURL) + : Event(eventNames().hashchangeEvent, false, false) + , m_oldURL(oldURL) + , m_newURL(newURL) + {} + + String m_oldURL; + String m_newURL; +}; + +} // namespace WebCore + +#endif // HashChangeEvent_h diff --git a/WebCore/dom/HashChangeEvent.idl b/WebCore/dom/HashChangeEvent.idl new file mode 100644 index 0000000..63073c4 --- /dev/null +++ b/WebCore/dom/HashChangeEvent.idl @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +module events { + + // Introduced in http://www.whatwg.org/specs/web-apps/current-work/multipage/history.html#event-hashchange + interface [ + GenerateConstructor + ] HashChangeEvent : Event { + void initHashChangeEvent(in DOMString type, + in boolean canBubble, + in boolean cancelable, + in DOMString oldURL, + in DOMString newURL); + readonly attribute DOMString oldURL; + readonly attribute DOMString newURL; + }; + +} diff --git a/WebCore/dom/InputElement.cpp b/WebCore/dom/InputElement.cpp index f0284d8..b2a9714 100644 --- a/WebCore/dom/InputElement.cpp +++ b/WebCore/dom/InputElement.cpp @@ -99,7 +99,7 @@ void InputElement::updateFocusAppearance(InputElementData& data, InputElement* i Document* document = element->document(); if (document && document->frame()) - document->frame()->revealSelection(); + document->frame()->selection()->revealSelection(); } void InputElement::updateSelectionRange(InputElement* inputElement, Element* element, int start, int end) diff --git a/WebCore/dom/MouseRelatedEvent.cpp b/WebCore/dom/MouseRelatedEvent.cpp index ce4c175..61c35e8 100644 --- a/WebCore/dom/MouseRelatedEvent.cpp +++ b/WebCore/dom/MouseRelatedEvent.cpp @@ -57,7 +57,7 @@ static int contentsX(AbstractView* abstractView) FrameView* frameView = frame->view(); if (!frameView) return 0; - return frameView->scrollX() / frameView->pageZoomFactor(); + return frameView->scrollX() / frame->pageZoomFactor(); } static int contentsY(AbstractView* abstractView) @@ -70,7 +70,7 @@ static int contentsY(AbstractView* abstractView) FrameView* frameView = frame->view(); if (!frameView) return 0; - return frameView->scrollY() / frameView->pageZoomFactor(); + return frameView->scrollY() / frame->pageZoomFactor(); } MouseRelatedEvent::MouseRelatedEvent(const AtomicString& eventType, bool canBubble, bool cancelable, PassRefPtr<AbstractView> viewArg, @@ -126,10 +126,7 @@ static float pageZoomFactor(UIEvent* event) Frame* frame = window->frame(); if (!frame) return 1; - FrameView* view = frame->view(); - if (!view) - return 1; - return view->pageZoomFactor(); + return frame->pageZoomFactor(); } void MouseRelatedEvent::computePageLocation() diff --git a/WebCore/dom/Node.cpp b/WebCore/dom/Node.cpp index 9b27089..92b42fe 100644 --- a/WebCore/dom/Node.cpp +++ b/WebCore/dom/Node.cpp @@ -723,6 +723,15 @@ inline void Node::setStyleChange(StyleChangeType changeType) m_nodeFlags = (m_nodeFlags & ~StyleChangeMask) | changeType; } +inline void Node::markAncestorsWithChildNeedsStyleRecalc() +{ + for (Node* p = parentNode(); p && !p->childNeedsStyleRecalc(); p = p->parentNode()) + p->setChildNeedsStyleRecalc(); + + if (document()->childNeedsStyleRecalc()) + document()->scheduleStyleRecalc(); +} + void Node::setNeedsStyleRecalc(StyleChangeType changeType) { ASSERT(changeType != NoStyleChange); @@ -733,49 +742,20 @@ void Node::setNeedsStyleRecalc(StyleChangeType changeType) if (changeType > existingChangeType) setStyleChange(changeType); - if (existingChangeType == NoStyleChange) { - for (Node* p = parentNode(); p && !p->childNeedsStyleRecalc(); p = p->parentNode()) - p->setChildNeedsStyleRecalc(); - - if (document()->childNeedsStyleRecalc()) - document()->scheduleStyleRecalc(); - } + if (existingChangeType == NoStyleChange) + markAncestorsWithChildNeedsStyleRecalc(); } -static Node* outermostLazyAttachedAncestor(Node* start) +void Node::lazyAttach(ShouldSetAttached shouldSetAttached) { - Node* p = start; - for (Node* next = p->parentNode(); !next->renderer(); p = next, next = next->parentNode()) {} - return p; -} - -void Node::lazyAttach() -{ - bool mustDoFullAttach = false; - for (Node* n = this; n; n = n->traverseNextNode(this)) { - if (!n->canLazyAttach()) { - mustDoFullAttach = true; - break; - } - if (n->firstChild()) n->setChildNeedsStyleRecalc(); n->setStyleChange(FullStyleChange); - n->setAttached(); - } - - if (mustDoFullAttach) { - Node* lazyAttachedAncestor = outermostLazyAttachedAncestor(this); - if (lazyAttachedAncestor->attached()) - lazyAttachedAncestor->detach(); - lazyAttachedAncestor->attach(); - } else { - for (Node* p = parentNode(); p && !p->childNeedsStyleRecalc(); p = p->parentNode()) - p->setChildNeedsStyleRecalc(); - if (document()->childNeedsStyleRecalc()) - document()->scheduleStyleRecalc(); + if (shouldSetAttached == SetAttached) + n->setAttached(); } + markAncestorsWithChildNeedsStyleRecalc(); } void Node::setFocus(bool b) @@ -2939,8 +2919,8 @@ bool Node::dispatchMouseEvent(const AtomicString& eventType, int button, int det int adjustedPageX = pageX; int adjustedPageY = pageY; - if (FrameView* view = document()->view()) { - float pageZoom = view->pageZoomFactor(); + if (Frame* frame = document()->frame()) { + float pageZoom = frame->pageZoomFactor(); if (pageZoom != 1.0f) { // Adjust our pageX and pageY to account for the page zoom. adjustedPageX = lroundf(pageX / pageZoom); @@ -2996,8 +2976,8 @@ void Node::dispatchWheelEvent(PlatformWheelEvent& e) int adjustedPageX = pos.x(); int adjustedPageY = pos.y(); - if (FrameView* view = document()->view()) { - float pageZoom = view->pageZoomFactor(); + if (Frame* frame = document()->frame()) { + float pageZoom = frame->pageZoomFactor(); if (pageZoom != 1.0f) { // Adjust our pageX and pageY to account for the page zoom. adjustedPageX = lroundf(pos.x() / pageZoom); diff --git a/WebCore/dom/Node.h b/WebCore/dom/Node.h index c7f07f1..603829b 100644 --- a/WebCore/dom/Node.h +++ b/WebCore/dom/Node.h @@ -310,8 +310,11 @@ public: void setIsLink() { setFlag(IsLinkFlag); } void clearIsLink() { clearFlag(IsLinkFlag); } - void lazyAttach(); - virtual bool canLazyAttach() { return true; } + enum ShouldSetAttached { + SetAttached, + DoNotSetAttached + }; + void lazyAttach(ShouldSetAttached = SetAttached); virtual void setFocus(bool b = true); virtual void setActive(bool f = true, bool /*pause*/ = false) { setFlag(f, IsActiveFlag); } @@ -693,6 +696,9 @@ private: void setStyleChange(StyleChangeType); + // Used to share code between lazyAttach and setNeedsStyleRecalc. + void markAncestorsWithChildNeedsStyleRecalc(); + virtual void refEventTarget() { ref(); } virtual void derefEventTarget() { deref(); } diff --git a/WebCore/dom/Range.cpp b/WebCore/dom/Range.cpp index d93a58e..95502df 100644 --- a/WebCore/dom/Range.cpp +++ b/WebCore/dom/Range.cpp @@ -107,6 +107,17 @@ Range::~Range() #endif } +void Range::setDocument(Document* document) +{ + ASSERT(m_ownerDocument != document); + if (m_ownerDocument) + m_ownerDocument->detachRange(this); + m_ownerDocument = document; + m_start.setToStartOfNode(document); + m_end.setToStartOfNode(document); + m_ownerDocument->attachRange(this); +} + Node* Range::startContainer(ExceptionCode& ec) const { if (!m_start.container()) { @@ -1316,6 +1327,9 @@ void Range::selectNode(Node* refNode, ExceptionCode& ec) return; } + if (m_ownerDocument != refNode->document()) + setDocument(refNode->document()); + ec = 0; setStartBefore(refNode, ec); if (ec) @@ -1358,6 +1372,9 @@ void Range::selectNodeContents(Node* refNode, ExceptionCode& ec) } } + if (m_ownerDocument != refNode->document()) + setDocument(refNode->document()); + m_start.setToStartOfNode(refNode); m_end.setToEndOfNode(refNode); } diff --git a/WebCore/dom/Range.h b/WebCore/dom/Range.h index c81bf45..9834aec 100644 --- a/WebCore/dom/Range.h +++ b/WebCore/dom/Range.h @@ -135,6 +135,8 @@ private: Range(PassRefPtr<Document>); Range(PassRefPtr<Document>, PassRefPtr<Node> startContainer, int startOffset, PassRefPtr<Node> endContainer, int endOffset); + void setDocument(Document*); + Node* checkNodeWOffset(Node*, int offset, ExceptionCode&) const; void checkNodeBA(Node*, ExceptionCode&) const; void checkDeleteExtract(ExceptionCode&); diff --git a/WebCore/dom/ScriptElement.cpp b/WebCore/dom/ScriptElement.cpp index bb46f0a..46c85e3 100644 --- a/WebCore/dom/ScriptElement.cpp +++ b/WebCore/dom/ScriptElement.cpp @@ -264,6 +264,8 @@ bool ScriptElementData::shouldExecuteAsJavaScript() const WinIE 7 accepts ecmascript and jscript, but Mozilla 1.8 doesn't. Neither Mozilla 1.8 nor WinIE 7 accept leading or trailing whitespace. We want to accept all the values that either of these browsers accept, but not other values. + + FIXME: Is this HTML5 compliant? */ String type = m_scriptElement->typeAttributeValue(); if (!type.isEmpty()) { @@ -276,20 +278,20 @@ bool ScriptElementData::shouldExecuteAsJavaScript() const } // No type or language is specified, so we assume the script to be JavaScript. - // We don't yet support setting event listeners via the 'for' attribute for scripts. - // If there is such an attribute it's likely better to not execute the script than to do so - // immediately and unconditionally. - // FIXME: After <rdar://problem/4471751> / https://bugs.webkit.org/show_bug.cgi?id=16915 are resolved - // and we support the for syntax in script tags, this check can be removed and we should just - // return 'true' here. + String forAttribute = m_scriptElement->forAttributeValue(); String eventAttribute = m_scriptElement->eventAttributeValue(); - if (forAttribute.isEmpty() || eventAttribute.isEmpty()) - return true; + if (!forAttribute.isEmpty() && !eventAttribute.isEmpty()) { + forAttribute = forAttribute.stripWhiteSpace(); + if (!equalIgnoringCase(forAttribute, "window")) + return false; + + eventAttribute = eventAttribute.stripWhiteSpace(); + if (!equalIgnoringCase(eventAttribute, "onload") && !equalIgnoringCase(eventAttribute, "onload()")) + return false; + } - forAttribute = forAttribute.stripWhiteSpace(); - eventAttribute = eventAttribute.stripWhiteSpace(); - return equalIgnoringCase(forAttribute, "window") && (equalIgnoringCase(eventAttribute, "onload") || equalIgnoringCase(eventAttribute, "onload()")); + return true; } String ScriptElementData::scriptCharset() const diff --git a/WebCore/dom/ScriptExecutionContext.cpp b/WebCore/dom/ScriptExecutionContext.cpp index d014d47..bfda17b 100644 --- a/WebCore/dom/ScriptExecutionContext.cpp +++ b/WebCore/dom/ScriptExecutionContext.cpp @@ -87,20 +87,17 @@ ScriptExecutionContext::~ScriptExecutionContext() m_databaseThread = 0; } #endif -#if ENABLE(BLOB) || ENABLE(FILE_WRITER) +#if ENABLE(BLOB) || ENABLE(FILE_SYSTEM) if (m_fileThread) { m_fileThread->stop(); m_fileThread = 0; } #endif - HashSet<Blob*>::iterator blobsEnd = m_blobs.end(); - for (HashSet<Blob*>::iterator iter = m_blobs.begin(); iter != blobsEnd; ++iter) - (*iter)->contextDestroyed(); #if ENABLE(BLOB) HashSet<String>::iterator publicBlobURLsEnd = m_publicBlobURLs.end(); for (HashSet<String>::iterator iter = m_publicBlobURLs.begin(); iter != publicBlobURLsEnd; ++iter) - ThreadableBlobRegistry::unregisterBlobURL(this, KURL(ParsedURLString, *iter)); + ThreadableBlobRegistry::unregisterBlobURL(KURL(ParsedURLString, *iter)); #endif } @@ -175,18 +172,6 @@ void ScriptExecutionContext::destroyedMessagePort(MessagePort* port) m_messagePorts.remove(port); } -void ScriptExecutionContext::addBlob(Blob* blob) -{ - ASSERT(blob); - m_blobs.add(blob); -} - -void ScriptExecutionContext::removeBlob(Blob* blob) -{ - ASSERT(blob); - m_blobs.remove(blob); -} - bool ScriptExecutionContext::canSuspendActiveDOMObjects() { // No protection against m_activeDOMObjects changing during iteration: canSuspend() shouldn't execute arbitrary JS. @@ -199,13 +184,13 @@ bool ScriptExecutionContext::canSuspendActiveDOMObjects() return true; } -void ScriptExecutionContext::suspendActiveDOMObjects() +void ScriptExecutionContext::suspendActiveDOMObjects(ActiveDOMObject::ReasonForSuspension why) { // No protection against m_activeDOMObjects changing during iteration: suspend() shouldn't execute arbitrary JS. HashMap<ActiveDOMObject*, void*>::iterator activeObjectsEnd = m_activeDOMObjects.end(); for (HashMap<ActiveDOMObject*, void*>::iterator iter = m_activeDOMObjects.begin(); iter != activeObjectsEnd; ++iter) { ASSERT(iter->first->scriptExecutionContext() == this); - iter->first->suspend(); + iter->first->suspend(why); } } @@ -277,8 +262,10 @@ DOMTimer* ScriptExecutionContext::findTimeout(int timeoutId) #if ENABLE(BLOB) KURL ScriptExecutionContext::createPublicBlobURL(Blob* blob) { - KURL publicURL = BlobURL::createURL(this); - ThreadableBlobRegistry::registerBlobURL(this, publicURL, blob->url()); + if (!blob) + return KURL(); + KURL publicURL = BlobURL::createPublicURL(securityOrigin()); + ThreadableBlobRegistry::registerBlobURL(publicURL, blob->url()); m_publicBlobURLs.add(publicURL.string()); return publicURL; } @@ -286,13 +273,13 @@ KURL ScriptExecutionContext::createPublicBlobURL(Blob* blob) void ScriptExecutionContext::revokePublicBlobURL(const KURL& url) { if (m_publicBlobURLs.contains(url.string())) { - ThreadableBlobRegistry::unregisterBlobURL(this, url); + ThreadableBlobRegistry::unregisterBlobURL(url); m_publicBlobURLs.remove(url.string()); } } #endif -#if ENABLE(BLOB) || ENABLE(FILE_WRITER) +#if ENABLE(BLOB) || ENABLE(FILE_SYSTEM) FileThread* ScriptExecutionContext::fileThread() { if (!m_fileThread) { diff --git a/WebCore/dom/ScriptExecutionContext.h b/WebCore/dom/ScriptExecutionContext.h index 30c12e5..d39cb64 100644 --- a/WebCore/dom/ScriptExecutionContext.h +++ b/WebCore/dom/ScriptExecutionContext.h @@ -27,6 +27,7 @@ #ifndef ScriptExecutionContext_h #define ScriptExecutionContext_h +#include "ActiveDOMObject.h" #include "Console.h" #include "KURL.h" #include <wtf/Forward.h> @@ -44,7 +45,6 @@ namespace WebCore { - class ActiveDOMObject; class Blob; #if ENABLE(DATABASE) class Database; @@ -52,7 +52,7 @@ namespace WebCore { class DatabaseThread; #endif class DOMTimer; -#if ENABLE(BLOB) || ENABLE(FILE_WRITER) +#if ENABLE(BLOB) || ENABLE(FILE_SYSTEM) class FileThread; #endif class MessagePort; @@ -99,7 +99,7 @@ namespace WebCore { bool canSuspendActiveDOMObjects(); // Active objects can be asked to suspend even if canSuspendActiveDOMObjects() returns 'false' - // step-by-step JS debugging is one example. - void suspendActiveDOMObjects(); + void suspendActiveDOMObjects(ActiveDOMObject::ReasonForSuspension); void resumeActiveDOMObjects(); void stopActiveDOMObjects(); void createdActiveDOMObject(ActiveDOMObject*, void* upcastPointer); @@ -131,8 +131,6 @@ namespace WebCore { void removeTimeout(int timeoutId); DOMTimer* findTimeout(int timeoutId); - void addBlob(Blob*); - void removeBlob(Blob*); #if ENABLE(BLOB) KURL createPublicBlobURL(Blob*); void revokePublicBlobURL(const KURL&); @@ -142,7 +140,7 @@ namespace WebCore { JSC::JSGlobalData* globalData(); #endif -#if ENABLE(BLOB) || ENABLE(FILE_WRITER) +#if ENABLE(BLOB) || ENABLE(FILE_SYSTEM) FileThread* fileThread(); void stopFileThread(); #endif @@ -167,7 +165,6 @@ namespace WebCore { HashMap<int, DOMTimer*> m_timeouts; - HashSet<Blob*> m_blobs; #if ENABLE(BLOB) HashSet<String> m_publicBlobURLs; #endif @@ -180,7 +177,7 @@ namespace WebCore { bool m_hasOpenDatabases; // This never changes back to false, even after the database thread is closed. #endif -#if ENABLE(BLOB) || ENABLE(FILE_WRITER) +#if ENABLE(BLOB) || ENABLE(FILE_SYSTEM) RefPtr<FileThread> m_fileThread; #endif }; diff --git a/WebCore/dom/Touch.cpp b/WebCore/dom/Touch.cpp index 585d9d4..fbb3fed 100644 --- a/WebCore/dom/Touch.cpp +++ b/WebCore/dom/Touch.cpp @@ -40,7 +40,7 @@ static int contentsX(Frame* frame) FrameView* frameView = frame->view(); if (!frameView) return 0; - return frameView->scrollX() / frameView->pageZoomFactor(); + return frameView->scrollX() / frame->pageZoomFactor(); } static int contentsY(Frame* frame) @@ -50,11 +50,10 @@ static int contentsY(Frame* frame) FrameView* frameView = frame->view(); if (!frameView) return 0; - return frameView->scrollY() / frameView->pageZoomFactor(); + return frameView->scrollY() / frame->pageZoomFactor(); } -Touch::Touch(Frame* frame, EventTarget* target, unsigned identifier, - int screenX, int screenY, int pageX, int pageY) +Touch::Touch(Frame* frame, EventTarget* target, unsigned identifier, int screenX, int screenY, int pageX, int pageY) : m_target(target) , m_identifier(identifier) , m_clientX(pageX - contentsX(frame)) @@ -69,4 +68,3 @@ Touch::Touch(Frame* frame, EventTarget* target, unsigned identifier, } // namespace WebCore #endif - diff --git a/WebCore/dom/ViewportArguments.cpp b/WebCore/dom/ViewportArguments.cpp index 9f831dd..356f9ed 100644 --- a/WebCore/dom/ViewportArguments.cpp +++ b/WebCore/dom/ViewportArguments.cpp @@ -5,6 +5,7 @@ * (C) 2006 Alexey Proskuryakov (ap@webkit.org) * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -31,76 +32,275 @@ #include "DOMWindow.h" #include "Document.h" #include "Frame.h" +#include "IntSize.h" #include "Page.h" #include "PlatformString.h" #include "ScriptableDocumentParser.h" +using namespace std; + namespace WebCore { +ViewportConfiguration findConfigurationForViewportData(ViewportArguments args, int desktopWidth, int deviceWidth, int deviceHeight, int deviceDPI, IntSize visibleViewport) +{ + ViewportConfiguration result; + + float availableWidth = visibleViewport.width(); + float availableHeight = visibleViewport.height(); + + ASSERT(availableWidth > 0 && availableHeight > 0); + + switch (int(args.width)) { + case ViewportArguments::ValueDesktopWidth: + args.width = desktopWidth; + break; + case ViewportArguments::ValueDeviceWidth: + args.width = deviceWidth; + break; + case ViewportArguments::ValueDeviceHeight: + args.width = deviceHeight; + break; + } + + switch (int(args.height)) { + case ViewportArguments::ValueDesktopWidth: + args.height = desktopWidth; + break; + case ViewportArguments::ValueDeviceWidth: + args.height = deviceWidth; + break; + case ViewportArguments::ValueDeviceHeight: + args.height = deviceHeight; + break; + } + + result.devicePixelRatio = float(deviceDPI / 160.0); + + // Resolve non-'auto' width and height to pixel values. + if (deviceDPI != 1.0) { + deviceWidth /= result.devicePixelRatio; + deviceHeight /= result.devicePixelRatio; + + if (args.width != ViewportArguments::ValueAuto) + args.width /= result.devicePixelRatio; + if (args.height != ViewportArguments::ValueAuto) + args.height /= result.devicePixelRatio; + } + + // Clamp values to range defined by spec and resolve minimum-scale and maximum-scale values + if (args.width != ViewportArguments::ValueAuto) + args.width = min(float(10000), max(args.width, float(1))); + if (args.height != ViewportArguments::ValueAuto) + args.height = min(float(10000), max(args.height, float(1))); + + if (args.initialScale != ViewportArguments::ValueAuto) + args.initialScale = min(float(10), max(args.initialScale, float(0.1))); + if (args.minimumScale != ViewportArguments::ValueAuto) + args.minimumScale = min(float(10), max(args.minimumScale, float(0.1))); + if (args.maximumScale != ViewportArguments::ValueAuto) + args.maximumScale = min(float(10), max(args.maximumScale, float(0.1))); + + // Resolve minimum-scale and maximum-scale values according to spec. + if (args.minimumScale == ViewportArguments::ValueAuto) + result.minimumScale = float(0.25); + else + result.minimumScale = args.minimumScale; + + if (args.maximumScale == ViewportArguments::ValueAuto) { + result.maximumScale = float(5.0); + result.minimumScale = min(float(5.0), result.minimumScale); + } else + result.maximumScale = args.maximumScale; + result.maximumScale = max(result.minimumScale, result.maximumScale); + + // Resolve initial-scale value. + result.initialScale = args.initialScale; + if (result.initialScale == ViewportArguments::ValueAuto) { + result.initialScale = availableWidth / desktopWidth; + if (args.width != ViewportArguments::ValueAuto) + result.initialScale = availableWidth / args.width; + if (args.height != ViewportArguments::ValueAuto) { + // if 'auto', the initial-scale will be negative here and thus ignored. + result.initialScale = max(result.initialScale, availableHeight / args.height); + } + } + + // Constrain initial-scale value to minimum-scale/maximum-scale range. + result.initialScale = min(result.maximumScale, max(result.minimumScale, result.initialScale)); + + // Resolve width value. + float width; + if (args.width != ViewportArguments::ValueAuto) + width = args.width; + else { + if (args.initialScale == ViewportArguments::ValueAuto) + width = desktopWidth; + else if (args.height != ViewportArguments::ValueAuto) + width = args.height * (availableWidth / availableHeight); + else + width = availableWidth / result.initialScale; + } + + // Resolve height value. + float height; + if (args.height != ViewportArguments::ValueAuto) + height = args.height; + else + height = width * availableHeight / availableWidth; + + // Extend width and height to fill the visual viewport for the resolved initial-scale. + width = max(width, availableWidth / result.initialScale); + height = max(height, availableHeight / result.initialScale); + result.layoutViewport.setWidth(width); + result.layoutViewport.setHeight(height); + + // Update minimum scale factor, to never allow zooming out more than viewport + result.minimumScale = max(result.minimumScale, max(availableWidth / width, availableHeight / height)); + + return result; +} + +static float findSizeValue(const String& keyString, const String& valueString, Document* document) +{ + // 1) Non-negative number values are translated to px lengths. + // 2) Negative number values are translated to auto. + // 3) device-width and device-height are used as keywords. + // 4) Other keywords and unknown values translate to 0.0. + + if (equalIgnoringCase(valueString, "desktop-width")) + return ViewportArguments::ValueDesktopWidth; + if (equalIgnoringCase(valueString, "device-width")) + return ViewportArguments::ValueDeviceWidth; + if (equalIgnoringCase(valueString, "device-height")) + return ViewportArguments::ValueDeviceHeight; + + bool ok; + float value = valueString.toFloat(&ok); + if (!ok) { + reportViewportWarning(document, UnrecognizedViewportArgumentError, keyString); + return float(0.0); + } + + if (value < 0) + return ViewportArguments::ValueAuto; + + if (keyString == "width") + reportViewportWarning(document, DeviceWidthShouldBeUsedWarning, keyString); + else if (keyString == "height") + reportViewportWarning(document, DeviceHeightShouldBeUsedWarning, keyString); + + return value; +} + +static float findScaleValue(const String& keyString, const String& valueString, Document* document) +{ + // 1) Non-negative number values are translated to <number> values. + // 2) Negative number values are translated to auto. + // 3) yes is translated to 1.0. + // 4) device-width and device-height are translated to 10.0. + // 5) no and unknown values are translated to 0.0 + + if (equalIgnoringCase(valueString, "yes")) + return float(1.0); + if (equalIgnoringCase(valueString, "no")) + return float(0.0); + if (equalIgnoringCase(valueString, "desktop-width")) + return float(10.0); + if (equalIgnoringCase(valueString, "device-width")) + return float(10.0); + if (equalIgnoringCase(valueString, "device-height")) + return float(10.0); + + bool ok; + float value = valueString.toFloat(&ok); + if (!ok) { + reportViewportWarning(document, UnrecognizedViewportArgumentError, keyString); + return float(0.0); + } + + if (value < 0) + return ViewportArguments::ValueAuto; + + if (value > 10.0) + reportViewportWarning(document, MaximumScaleTooLargeError, keyString); + + return value; +} + +static bool findUserScalableValue(const String& keyString, const String& valueString, Document* document) +{ + // yes and no are used as keywords. + // Numbers >= 1, numbers <= -1, device-width and device-height are mapped to yes. + // Numbers in the range <-1, 1>, and unknown values, are mapped to no. + + if (equalIgnoringCase(valueString, "yes")) + return true; + if (equalIgnoringCase(valueString, "no")) + return false; + if (equalIgnoringCase(valueString, "desktop-width")) + return true; + if (equalIgnoringCase(valueString, "device-width")) + return true; + if (equalIgnoringCase(valueString, "device-height")) + return true; + + bool ok; + float value = valueString.toFloat(&ok); + if (!ok) { + reportViewportWarning(document, UnrecognizedViewportArgumentError, keyString); + return false; + } + + if (fabs(value) < 1) + return false; + + return true; +} + +static float findTargetDensityDPIValue(const String& keyString, const String& valueString, Document* document) +{ + if (equalIgnoringCase(valueString, "device-dpi")) + return ViewportArguments::ValueDeviceDPI; + if (equalIgnoringCase(valueString, "low-dpi")) + return ViewportArguments::ValueLowDPI; + if (equalIgnoringCase(valueString, "medium-dpi")) + return ViewportArguments::ValueMediumDPI; + if (equalIgnoringCase(valueString, "high-dpi")) + return ViewportArguments::ValueHighDPI; + + bool ok; + float value = valueString.toFloat(&ok); + if (!ok) { + reportViewportWarning(document, UnrecognizedViewportArgumentError, keyString); + return ViewportArguments::ValueAuto; + } + + if (value < 70 || value > 400) { + reportViewportWarning(document, TargetDensityDpiTooSmallOrLargeError, keyString); + return ViewportArguments::ValueAuto; + } + + return value; +} + void setViewportFeature(const String& keyString, const String& valueString, Document* document, void* data) { ViewportArguments* arguments = static_cast<ViewportArguments*>(data); - float value = ViewportArguments::ValueUndefined; - bool didUseConstants = false; - if (equalIgnoringCase(valueString, "yes")) - value = 1; - else if (equalIgnoringCase(valueString, "device-width")) { - didUseConstants = true; - if (document->page()) - value = document->page()->chrome()->windowRect().width(); - } else if (equalIgnoringCase(valueString, "device-height")) { - didUseConstants = true; - if (document->page()) - value = document->page()->chrome()->windowRect().height(); - } else if (equalIgnoringCase(valueString, "device-dpi")) { - didUseConstants = true; - // Default of today is 160dpi, resulting in a scaleFactor of 1.0. - if (document->page()) - value = 160 * document->page()->chrome()->scaleFactor(); - } else if (equalIgnoringCase(valueString, "low-dpi")) { - didUseConstants = true; - value = 120; - } else if (equalIgnoringCase(valueString, "medium-dpi")) { - didUseConstants = true; - value = 160; - } else if (equalIgnoringCase(valueString, "high-dpi")) { - didUseConstants = true; - value = 240; - } else if (equalIgnoringCase(valueString, "default")) // This allows us to distinguish the omission of a key from asking for the default value. - value = -2; - else if (valueString.length()) // listing a key with no value is shorthand for key=default - value = valueString.toFloat(); - - if (keyString == "initial-scale") - arguments->initialScale = value; + if (keyString == "width") + arguments->width = findSizeValue(keyString, valueString, document); + else if (keyString == "height") + arguments->height = findSizeValue(keyString, valueString, document); + else if (keyString == "initial-scale") + arguments->initialScale = findScaleValue(keyString, valueString, document); else if (keyString == "minimum-scale") - arguments->minimumScale = value; - else if (keyString == "maximum-scale") { - arguments->maximumScale = value; - if (value > 10.0) - reportViewportWarning(document, MaximumScaleTooLargeError, keyString); - } else if (keyString == "user-scalable") - arguments->userScalable = value; - else if (keyString == "width") { - if (document->page() && value == document->page()->chrome()->windowRect().width() && !didUseConstants) - reportViewportWarning(document, DeviceWidthShouldBeUsedWarning, keyString); - else if (document->page() && value == document->page()->chrome()->windowRect().height() && !didUseConstants) - reportViewportWarning(document, DeviceHeightShouldBeUsedWarning, keyString); - - arguments->width = value; - } else if (keyString == "height") { - if (document->page() && value == document->page()->chrome()->windowRect().width() && !didUseConstants) - reportViewportWarning(document, DeviceWidthShouldBeUsedWarning, keyString); - else if (document->page() && value == document->page()->chrome()->windowRect().height() && !didUseConstants) - reportViewportWarning(document, DeviceHeightShouldBeUsedWarning, keyString); - arguments->height = value; - } else if (keyString == "target-densitydpi" || keyString == "target-densityDpi") { - if (!didUseConstants && (value < 70 || value > 400)) - reportViewportWarning(document, TargetDensityDpiTooSmallOrLargeError, keyString); - arguments->targetDensityDpi = value; - } else - reportViewportWarning(document, UnrecognizedViewportArgumentError, keyString); + arguments->minimumScale = findScaleValue(keyString, valueString, document); + else if (keyString == "maximum-scale") + arguments->maximumScale = findScaleValue(keyString, valueString, document); + else if (keyString == "user-scalable") + arguments->userScalable = findUserScalableValue(keyString, valueString, document); + else if (keyString == "target-densitydpi") + arguments->targetDensityDpi = findTargetDensityDPIValue(keyString, valueString, document); } static const char* viewportErrorMessageTemplate(ViewportErrorCode errorCode) diff --git a/WebCore/dom/ViewportArguments.h b/WebCore/dom/ViewportArguments.h index 1fac0df..5731842 100644 --- a/WebCore/dom/ViewportArguments.h +++ b/WebCore/dom/ViewportArguments.h @@ -5,6 +5,7 @@ * (C) 2006 Alexey Proskuryakov (ap@webkit.org) * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -26,6 +27,7 @@ #ifndef ViewportArguments_h #define ViewportArguments_h +#include "IntSize.h" #include <wtf/Forward.h> namespace WebCore { @@ -40,18 +42,37 @@ enum ViewportErrorCode { TargetDensityDpiTooSmallOrLargeError }; +struct ViewportConfiguration { + IntSize layoutViewport; + + float devicePixelRatio; + + float initialScale; + float minimumScale; + float maximumScale; +}; + struct ViewportArguments { - enum { ValueUndefined = -1 }; + enum { + ValueAuto = -1, + ValueDesktopWidth = -2, + ValueDeviceWidth = -3, + ValueDeviceHeight = -4, + ValueDeviceDPI = -5, + ValueLowDPI = -6, + ValueMediumDPI = -7, + ValueHighDPI = -8 + }; ViewportArguments() - : initialScale(ValueUndefined) - , minimumScale(ValueUndefined) - , maximumScale(ValueUndefined) - , width(ValueUndefined) - , height(ValueUndefined) - , targetDensityDpi(ValueUndefined) - , userScalable(ValueUndefined) + : initialScale(ValueAuto) + , minimumScale(ValueAuto) + , maximumScale(ValueAuto) + , width(ValueAuto) + , height(ValueAuto) + , targetDensityDpi(ValueAuto) + , userScalable(ValueAuto) { } @@ -66,10 +87,12 @@ struct ViewportArguments { bool hasCustomArgument() const { - return initialScale != ValueUndefined || minimumScale != ValueUndefined || maximumScale != ValueUndefined || width != ValueUndefined || height != ValueUndefined || userScalable != ValueUndefined || targetDensityDpi != ValueUndefined; + return initialScale != ValueAuto || minimumScale != ValueAuto || maximumScale != ValueAuto || width != ValueAuto || height != ValueAuto || userScalable != ValueAuto || targetDensityDpi != ValueAuto; } }; +ViewportConfiguration findConfigurationForViewportData(ViewportArguments args, int desktopWidth, int deviceWidth, int deviceHeight, int deviceDPI, IntSize visibleViewport); + void setViewportFeature(const String& keyString, const String& valueString, Document*, void* data); void reportViewportWarning(Document*, ViewportErrorCode, const String& replacement); diff --git a/WebCore/dom/XMLDocumentParser.h b/WebCore/dom/XMLDocumentParser.h index 47e65c6..358be1f 100644 --- a/WebCore/dom/XMLDocumentParser.h +++ b/WebCore/dom/XMLDocumentParser.h @@ -320,9 +320,9 @@ public: int m_scriptStartLine; bool m_parsingFragment; - String m_defaultNamespaceURI; + AtomicString m_defaultNamespaceURI; - typedef HashMap<String, String> PrefixForNamespaceMap; + typedef HashMap<AtomicString, AtomicString> PrefixForNamespaceMap; PrefixForNamespaceMap m_prefixToNamespaceMap; SegmentedString m_pendingSrc; FragmentScriptingPermission m_scriptingPermission; diff --git a/WebCore/dom/XMLDocumentParserLibxml2.cpp b/WebCore/dom/XMLDocumentParserLibxml2.cpp index 927fbbe..5539072 100644 --- a/WebCore/dom/XMLDocumentParserLibxml2.cpp +++ b/WebCore/dom/XMLDocumentParserLibxml2.cpp @@ -1,11 +1,12 @@ /* - * Copyright (C) 2000 Peter Kelly (pmk@post.com) + * Copyright (C) 2000 Peter Kelly <pmk@post.com> * Copyright (C) 2005, 2006, 2008 Apple Inc. All rights reserved. - * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) - * Copyright (C) 2007 Samuel Weinig (sam@webkit.org) + * Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org> + * Copyright (C) 2007 Samuel Weinig <sam@webkit.org> * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) * Copyright (C) 2008 Holger Hans Peter Freyther * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -671,17 +672,26 @@ void XMLDocumentParser::doWrite(const String& parseString) } } -static inline String toString(const xmlChar* str, unsigned len) +static inline String toString(const xmlChar* string, size_t size) { - return UTF8Encoding().decode(reinterpret_cast<const char*>(str), len); + return String::fromUTF8(reinterpret_cast<const char*>(string), size); } -static inline String toString(const xmlChar* str) +static inline String toString(const xmlChar* string) { - if (!str) - return String(); + return String::fromUTF8(reinterpret_cast<const char*>(string)); +} - return UTF8Encoding().decode(reinterpret_cast<const char*>(str), strlen(reinterpret_cast<const char*>(str))); +static inline AtomicString toAtomicString(const xmlChar* string, size_t size) +{ + // FIXME: Use AtomicString::fromUTF8. + return AtomicString(toString(string, size)); +} + +static inline AtomicString toAtomicString(const xmlChar* string) +{ + // FIXME: Use AtomicString::fromUTF8. + return AtomicString(toString(string)); } struct _xmlSAX2Namespace { @@ -695,7 +705,7 @@ static inline void handleElementNamespaces(Element* newElement, const xmlChar** xmlSAX2Namespace* namespaces = reinterpret_cast<xmlSAX2Namespace*>(libxmlNamespaces); for (int i = 0; i < nb_namespaces; i++) { AtomicString namespaceQName = xmlnsAtom; - String namespaceURI = toString(namespaces[i].uri); + AtomicString namespaceURI = toAtomicString(namespaces[i].uri); if (namespaces[i].prefix) namespaceQName = "xmlns:" + toString(namespaces[i].prefix); newElement->setAttributeNS(XMLNSNames::xmlnsNamespaceURI, namespaceQName, namespaceURI, ec, scriptingPermission); @@ -717,12 +727,11 @@ static inline void handleElementAttributes(Element* newElement, const xmlChar** { xmlSAX2Attributes* attributes = reinterpret_cast<xmlSAX2Attributes*>(libxmlAttributes); for (int i = 0; i < nb_attributes; i++) { - String attrLocalName = toString(attributes[i].localname); - int valueLength = (int) (attributes[i].end - attributes[i].value); - String attrValue = toString(attributes[i].value, valueLength); + int valueLength = static_cast<int>(attributes[i].end - attributes[i].value); + AtomicString attrValue = toAtomicString(attributes[i].value, valueLength); String attrPrefix = toString(attributes[i].prefix); - String attrURI = attrPrefix.isEmpty() ? String() : toString(attributes[i].uri); - String attrQName = attrPrefix.isEmpty() ? attrLocalName : attrPrefix + ":" + attrLocalName; + AtomicString attrURI = attrPrefix.isEmpty() ? AtomicString() : toAtomicString(attributes[i].uri); + AtomicString attrQName = attrPrefix.isEmpty() ? toAtomicString(attributes[i].localname) : AtomicString(attrPrefix + ":" + toString(attributes[i].localname)); newElement->setAttributeNS(attrURI, attrQName, attrValue, ec, scriptingPermission); if (ec) // exception setting attributes @@ -752,9 +761,9 @@ void XMLDocumentParser::startElementNs(const xmlChar* xmlLocalName, const xmlCha exitText(); - String localName = toString(xmlLocalName); - String uri = toString(xmlURI); - String prefix = toString(xmlPrefix); + AtomicString localName = toAtomicString(xmlLocalName); + AtomicString uri = toAtomicString(xmlURI); + AtomicString prefix = toAtomicString(xmlPrefix); if (m_parsingFragment && uri.isNull()) { if (!prefix.isNull()) |