summaryrefslogtreecommitdiffstats
path: root/WebCore/wml
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2009-08-11 17:01:47 +0100
committerBen Murdoch <benm@google.com>2009-08-11 18:21:02 +0100
commit0bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5 (patch)
tree2943df35f62d885c89d01063cc528dd73b480fea /WebCore/wml
parent7e7a70bfa49a1122b2597a1e6367d89eb4035eca (diff)
downloadexternal_webkit-0bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5.zip
external_webkit-0bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5.tar.gz
external_webkit-0bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5.tar.bz2
Merge in WebKit r47029.
Diffstat (limited to 'WebCore/wml')
-rw-r--r--WebCore/wml/WMLAElement.cpp2
-rw-r--r--WebCore/wml/WMLAccessElement.cpp15
-rw-r--r--WebCore/wml/WMLAccessElement.h4
-rw-r--r--WebCore/wml/WMLAnchorElement.cpp13
-rw-r--r--WebCore/wml/WMLAnchorElement.h3
-rw-r--r--WebCore/wml/WMLCardElement.cpp41
-rw-r--r--WebCore/wml/WMLDoElement.cpp44
-rw-r--r--WebCore/wml/WMLDoElement.h8
-rw-r--r--WebCore/wml/WMLDocument.cpp61
-rw-r--r--WebCore/wml/WMLDocument.h5
-rw-r--r--WebCore/wml/WMLElement.cpp9
-rw-r--r--WebCore/wml/WMLElement.h6
-rw-r--r--WebCore/wml/WMLErrorHandling.cpp5
-rw-r--r--WebCore/wml/WMLEventHandlingElement.cpp12
-rw-r--r--WebCore/wml/WMLEventHandlingElement.h1
-rw-r--r--WebCore/wml/WMLFieldSetElement.cpp15
-rw-r--r--WebCore/wml/WMLFieldSetElement.h2
-rw-r--r--WebCore/wml/WMLGoElement.cpp17
-rw-r--r--WebCore/wml/WMLGoElement.h1
-rw-r--r--WebCore/wml/WMLImageLoader.cpp2
-rw-r--r--WebCore/wml/WMLInputElement.cpp2
-rw-r--r--WebCore/wml/WMLIntrinsicEventHandler.cpp6
-rw-r--r--WebCore/wml/WMLIntrinsicEventHandler.h1
-rw-r--r--WebCore/wml/WMLNoopElement.cpp9
-rw-r--r--WebCore/wml/WMLOnEventElement.cpp25
-rw-r--r--WebCore/wml/WMLOnEventElement.h1
-rw-r--r--WebCore/wml/WMLOptGroupElement.cpp7
-rw-r--r--WebCore/wml/WMLOptGroupElement.h3
-rw-r--r--WebCore/wml/WMLOptionElement.cpp10
-rw-r--r--WebCore/wml/WMLPageState.cpp253
-rw-r--r--WebCore/wml/WMLPageState.h31
-rw-r--r--WebCore/wml/WMLPostfieldElement.cpp38
-rw-r--r--WebCore/wml/WMLPostfieldElement.h10
-rw-r--r--WebCore/wml/WMLSelectElement.cpp331
-rw-r--r--WebCore/wml/WMLSelectElement.h21
-rw-r--r--WebCore/wml/WMLSetvarElement.cpp32
-rw-r--r--WebCore/wml/WMLSetvarElement.h9
-rw-r--r--WebCore/wml/WMLTaskElement.cpp46
-rw-r--r--WebCore/wml/WMLTaskElement.h6
-rw-r--r--WebCore/wml/WMLTimerElement.cpp30
-rw-r--r--WebCore/wml/WMLTimerElement.h4
-rw-r--r--WebCore/wml/WMLVariables.cpp4
42 files changed, 910 insertions, 235 deletions
diff --git a/WebCore/wml/WMLAElement.cpp b/WebCore/wml/WMLAElement.cpp
index 5fbeac6..9c84193 100644
--- a/WebCore/wml/WMLAElement.cpp
+++ b/WebCore/wml/WMLAElement.cpp
@@ -150,7 +150,7 @@ void WMLAElement::defaultEventHandler(Event* event)
}
if (!event->defaultPrevented() && document()->frame()) {
- KURL url = document()->completeURL(parseURL(getAttribute(HTMLNames::hrefAttr)));
+ KURL url = document()->completeURL(deprecatedParseURL(getAttribute(HTMLNames::hrefAttr)));
document()->frame()->loader()->urlSelected(url, target(), event, false, false, true);
}
diff --git a/WebCore/wml/WMLAccessElement.cpp b/WebCore/wml/WMLAccessElement.cpp
index db0ab67..a633260 100644
--- a/WebCore/wml/WMLAccessElement.cpp
+++ b/WebCore/wml/WMLAccessElement.cpp
@@ -43,16 +43,14 @@ void WMLAccessElement::parseMappedAttribute(MappedAttribute* attr)
String value = parseValueForbiddingVariableReferences(attr->value());
if (value.isEmpty())
return;
-
- if (WMLPageState* pageState = wmlPageStateForDocument(document()))
- pageState->restrictDeckAccessToDomain(value);
+
+ m_domain = value;
} else if (attr->name() == pathAttr) {
String value = parseValueForbiddingVariableReferences(attr->value());
if (value.isEmpty())
return;
- if (WMLPageState* pageState = wmlPageStateForDocument(document()))
- pageState->restrictDeckAccessToPath(value);
+ m_path = value;
} else
WMLElement::parseMappedAttribute(attr);
}
@@ -62,8 +60,11 @@ void WMLAccessElement::insertedIntoDocument()
WMLElement::insertedIntoDocument();
WMLPageState* pageState = wmlPageStateForDocument(document());
- if (pageState && !pageState->setNeedCheckDeckAccess(true))
- reportWMLError(document(), WMLErrorMultipleAccessElements);
+ if (!pageState || pageState->processAccessControlData(m_domain, m_path))
+ return;
+
+ pageState->resetAccessControlData();
+ reportWMLError(document(), WMLErrorMultipleAccessElements);
}
}
diff --git a/WebCore/wml/WMLAccessElement.h b/WebCore/wml/WMLAccessElement.h
index 023d113..1bc44ab 100644
--- a/WebCore/wml/WMLAccessElement.h
+++ b/WebCore/wml/WMLAccessElement.h
@@ -32,6 +32,10 @@ public:
virtual void parseMappedAttribute(MappedAttribute*);
virtual void insertedIntoDocument();
+
+private:
+ String m_domain;
+ String m_path;
};
}
diff --git a/WebCore/wml/WMLAnchorElement.cpp b/WebCore/wml/WMLAnchorElement.cpp
index 300cbf6..91526b9 100644
--- a/WebCore/wml/WMLAnchorElement.cpp
+++ b/WebCore/wml/WMLAnchorElement.cpp
@@ -32,6 +32,7 @@ namespace WebCore {
WMLAnchorElement::WMLAnchorElement(const QualifiedName& tagName, Document* doc)
: WMLAElement(tagName, doc)
+ , m_task(0)
{
// Calling setIsLink(true), and returning a non-null value on CSSStyleSelectors' linkAttribute
// method, makes it possible to 'appear as link' (just like <a href="..">) without the need to
@@ -62,6 +63,18 @@ void WMLAnchorElement::defaultEventHandler(Event* event)
WMLElement::defaultEventHandler(event);
}
+void WMLAnchorElement::registerTask(WMLTaskElement* task)
+{
+ ASSERT(!m_task);
+ m_task = task;
+}
+
+void WMLAnchorElement::deregisterTask(WMLTaskElement* task)
+{
+ ASSERT(m_task == task);
+ m_task = 0;
+}
+
}
#endif
diff --git a/WebCore/wml/WMLAnchorElement.h b/WebCore/wml/WMLAnchorElement.h
index f4afee4..abc01c9 100644
--- a/WebCore/wml/WMLAnchorElement.h
+++ b/WebCore/wml/WMLAnchorElement.h
@@ -37,7 +37,8 @@ public:
private:
friend class WMLTaskElement;
- void registerTask(WMLTaskElement* task) { m_task = task; }
+ void registerTask(WMLTaskElement*);
+ void deregisterTask(WMLTaskElement*);
WMLTaskElement* m_task;
};
diff --git a/WebCore/wml/WMLCardElement.cpp b/WebCore/wml/WMLCardElement.cpp
index c8e92af..63240f3 100644
--- a/WebCore/wml/WMLCardElement.cpp
+++ b/WebCore/wml/WMLCardElement.cpp
@@ -28,12 +28,14 @@
#include "HTMLNames.h"
#include "MappedAttribute.h"
#include "NodeList.h"
+#include "Page.h"
#include "RenderStyle.h"
#include "WMLDocument.h"
#include "WMLDoElement.h"
#include "WMLInputElement.h"
#include "WMLIntrinsicEventHandler.h"
#include "WMLNames.h"
+#include "WMLSelectElement.h"
#include "WMLTemplateElement.h"
#include "WMLTimerElement.h"
#include "WMLVariables.h"
@@ -130,20 +132,24 @@ void WMLCardElement::handleIntrinsicEventIfNeeded()
FrameLoader* loader = frame->loader();
if (!loader)
return;
-
- int currentHistoryLength = loader->getHistoryLength();
- int lastHistoryLength = pageState->historyLength();
// Calculate the entry method of current card
WMLIntrinsicEventType eventType = WMLIntrinsicEventUnknown;
- if (lastHistoryLength > currentHistoryLength)
+
+ switch (loader->loadType()) {
+ case FrameLoadTypeReload:
+ break;
+ case FrameLoadTypeBack:
eventType = WMLIntrinsicEventOnEnterBackward;
- else if (lastHistoryLength < currentHistoryLength)
+ break;
+ case FrameLoadTypeBackWMLDeckNotAccessible:
+ reportWMLError(document(), WMLErrorDeckNotAccessible);
+ return;
+ default:
eventType = WMLIntrinsicEventOnEnterForward;
+ break;
+ }
- // Synchronize history length with WMLPageState
- pageState->setHistoryLength(currentHistoryLength);
-
// Figure out target event handler
WMLIntrinsicEventHandler* eventHandler = this->eventHandler();
bool hasIntrinsicEvent = false;
@@ -165,17 +171,14 @@ void WMLCardElement::handleIntrinsicEventIfNeeded()
if (m_eventTimer)
m_eventTimer->start();
- // FIXME: Initialize select elements in this card
for (Node* node = traverseNextNode(); node != 0; node = node->traverseNextNode()) {
if (!node->isElementNode())
continue;
if (node->hasTagName(inputTag))
static_cast<WMLInputElement*>(node)->initialize();
- /*
else if (node->hasTagName(selectTag))
static_cast<WMLSelectElement*>(node)->selectInitialOptions();
- */
}
}
@@ -238,13 +241,25 @@ void WMLCardElement::parseMappedAttribute(MappedAttribute* attr)
void WMLCardElement::insertedIntoDocument()
{
WMLElement::insertedIntoDocument();
+ Document* document = this->document();
// The first card inserted into a document, is visible by default.
if (!m_isVisible) {
- RefPtr<NodeList> nodeList = document()->getElementsByTagName("card");
+ RefPtr<NodeList> nodeList = document->getElementsByTagName("card");
if (nodeList && nodeList->length() == 1 && nodeList->item(0) == this)
m_isVisible = true;
}
+
+ // For the WML layout tests we embed WML content in a XHTML document. Navigating to different cards
+ // within the same deck has a different behaviour in HTML than in WML. HTML wants to "scroll to anchor"
+ // (see FrameLoader) but WML wants a reload. Notify the root document of the layout test that we want
+ // to mimic WML behaviour. This is rather tricky, but has been tested extensively. Usually it's not possible
+ // at all to embed WML in HTML, it's not designed that way, we're just "abusing" it for dynamically created layout tests.
+ if (document->page() && document->page()->mainFrame()) {
+ Document* rootDocument = document->page()->mainFrame()->document();
+ if (rootDocument && rootDocument != document)
+ rootDocument->setContainsWMLContent(true);
+ }
}
RenderObject* WMLCardElement::createRenderer(RenderArena* arena, RenderStyle* style)
@@ -296,7 +311,7 @@ WMLCardElement* WMLCardElement::determineActiveCard(Document* doc)
return 0;
// Figure out the new target card
- String cardName = doc->url().ref();
+ String cardName = doc->url().fragmentIdentifier();
WMLCardElement* activeCard = findNamedCardInDocument(doc, cardName);
if (activeCard) {
diff --git a/WebCore/wml/WMLDoElement.cpp b/WebCore/wml/WMLDoElement.cpp
index 916bc6e..34be6df 100644
--- a/WebCore/wml/WMLDoElement.cpp
+++ b/WebCore/wml/WMLDoElement.cpp
@@ -98,8 +98,6 @@ void WMLDoElement::parseMappedAttribute(MappedAttribute* attr)
m_type = parseValueForbiddingVariableReferences(attr->value());
else if (attr->name() == HTMLNames::nameAttr)
m_name = parseValueForbiddingVariableReferences(attr->value());
- else if (attr->name() == HTMLNames::labelAttr)
- m_label = parseValueSubstitutingVariableReferences(attr->value());
else if (attr->name() == optionalAttr)
m_isOptional = (attr->value() == "true");
else
@@ -115,8 +113,6 @@ void WMLDoElement::insertedIntoDocument()
m_name = m_type;
Node* parent = parentNode();
- ASSERT(parent);
-
if (!parent || !parent->isWMLElement())
return;
@@ -124,6 +120,29 @@ void WMLDoElement::insertedIntoDocument()
eventHandlingElement->registerDoElement(this, document());
}
+void WMLDoElement::removedFromDocument()
+{
+ Node* parent = parentNode();
+
+ if (parent && parent->isWMLElement()) {
+ if (WMLEventHandlingElement* eventHandlingElement = toWMLEventHandlingElement(static_cast<WMLElement*>(parent)))
+ eventHandlingElement->deregisterDoElement(this);
+ }
+
+ WMLElement::removedFromDocument();
+}
+
+void WMLDoElement::attach()
+{
+ WMLElement::attach();
+
+ // The call to updateFromElement() needs to go after the call through
+ // to the base class's attach() because that can sometimes do a close
+ // on the renderer.
+ if (renderer())
+ renderer()->updateFromElement();
+}
+
RenderObject* WMLDoElement::createRenderer(RenderArena* arena, RenderStyle* style)
{
if (!m_isActive || m_isOptional || m_isNoop)
@@ -145,6 +164,23 @@ void WMLDoElement::recalcStyle(StyleChange change)
renderer()->updateFromElement();
}
+void WMLDoElement::registerTask(WMLTaskElement* task)
+{
+ ASSERT(!m_task);
+ m_task = task;
+}
+
+void WMLDoElement::deregisterTask(WMLTaskElement* task)
+{
+ ASSERT(m_task == task);
+ m_task = 0;
+}
+
+String WMLDoElement::label() const
+{
+ return parseValueSubstitutingVariableReferences(getAttribute(HTMLNames::labelAttr));
+}
+
}
#endif
diff --git a/WebCore/wml/WMLDoElement.h b/WebCore/wml/WMLDoElement.h
index 98e97cc..fe48eae 100644
--- a/WebCore/wml/WMLDoElement.h
+++ b/WebCore/wml/WMLDoElement.h
@@ -35,14 +35,17 @@ public:
virtual void defaultEventHandler(Event*);
virtual void parseMappedAttribute(MappedAttribute*);
virtual void insertedIntoDocument();
+ virtual void removedFromDocument();
+ virtual void attach();
virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
virtual void recalcStyle(StyleChange);
- void registerTask(WMLTaskElement* task) { m_task = task; }
+ void registerTask(WMLTaskElement*);
+ void deregisterTask(WMLTaskElement*);
bool isActive() const { return m_isActive; }
- String label() const { return m_label; }
+ String label() const;
String name() const { return m_name; }
void setActive(bool active) { m_isActive = active; }
@@ -53,7 +56,6 @@ private:
bool m_isActive;
bool m_isNoop;
bool m_isOptional;
- String m_label;
String m_name;
String m_type;
};
diff --git a/WebCore/wml/WMLDocument.cpp b/WebCore/wml/WMLDocument.cpp
index 7f73848..f2287be 100644
--- a/WebCore/wml/WMLDocument.cpp
+++ b/WebCore/wml/WMLDocument.cpp
@@ -23,6 +23,7 @@
#if ENABLE(WML)
#include "WMLDocument.h"
+#include "Frame.h"
#include "Page.h"
#include "Tokenizer.h"
#include "WMLCardElement.h"
@@ -34,6 +35,7 @@ namespace WebCore {
WMLDocument::WMLDocument(Frame* frame)
: Document(frame, false)
+ , m_activeCard(0)
{
clearXMLVersion();
}
@@ -51,38 +53,65 @@ void WMLDocument::finishedParsing()
}
}
- WMLPageState* wmlPageState = wmlPageStateForDocument(this);
- if (!wmlPageState->isDeckAccessible()) {
- reportWMLError(this, WMLErrorDeckNotAccessible);
- Document::finishedParsing();
+ bool hasAccess = initialize(true);
+ Document::finishedParsing();
+
+ if (!hasAccess) {
+ m_activeCard = 0;
+
+ WMLPageState* wmlPageState = wmlPageStateForDocument(this);
+ if (!wmlPageState)
+ return;
+
+ Page* page = wmlPageState->page();
+ if (!page)
+ return;
+
+ BackForwardList* list = page->backForwardList();
+ if (!list)
+ return;
+
+ HistoryItem* item = list->backItem();
+ if (!item)
+ return;
+
+ page->goToItem(item, FrameLoadTypeBackWMLDeckNotAccessible);
return;
}
- // Remember that we'e successfully entered the deck
- wmlPageState->setNeedCheckDeckAccess(false);
-
- initialize();
- Document::finishedParsing();
+ if (m_activeCard) {
+ m_activeCard->handleIntrinsicEventIfNeeded();
+ m_activeCard = 0;
+ }
}
-void WMLDocument::initialize()
+bool WMLDocument::initialize(bool aboutToFinishParsing)
{
+ WMLPageState* wmlPageState = wmlPageStateForDocument(this);
+ if (!wmlPageState || !wmlPageState->canAccessDeck())
+ return false;
+
+ // Remember that we'e successfully entered the deck
+ wmlPageState->resetAccessControlData();
+
// Notify the existance of templates to all cards of the current deck
WMLTemplateElement::registerTemplatesInDocument(this);
// Set destination card
- WMLCardElement* card = WMLCardElement::determineActiveCard(this);
- if (!card) {
+ m_activeCard = WMLCardElement::determineActiveCard(this);
+ if (!m_activeCard) {
reportWMLError(this, WMLErrorNoCardInDocument);
- Document::finishedParsing();
- return;
+ return true;
}
// Handle deck-level task overrides
- card->handleDeckLevelTaskOverridesIfNeeded();
+ m_activeCard->handleDeckLevelTaskOverridesIfNeeded();
// Handle card-level intrinsic event
- card->handleIntrinsicEventIfNeeded();
+ if (!aboutToFinishParsing)
+ m_activeCard->handleIntrinsicEventIfNeeded();
+
+ return true;
}
WMLPageState* wmlPageStateForDocument(Document* doc)
diff --git a/WebCore/wml/WMLDocument.h b/WebCore/wml/WMLDocument.h
index 9189085..fb3e62e 100644
--- a/WebCore/wml/WMLDocument.h
+++ b/WebCore/wml/WMLDocument.h
@@ -28,6 +28,8 @@
namespace WebCore {
+class WMLCardElement;
+
class WMLDocument : public Document {
public:
static PassRefPtr<WMLDocument> create(Frame* frame)
@@ -40,10 +42,11 @@ public:
virtual bool isWMLDocument() const { return true; }
virtual void finishedParsing();
- void initialize();
+ bool initialize(bool aboutToFinishParsing = false);
private:
WMLDocument(Frame*);
+ WMLCardElement* m_activeCard;
};
WMLPageState* wmlPageStateForDocument(Document*);
diff --git a/WebCore/wml/WMLElement.cpp b/WebCore/wml/WMLElement.cpp
index e818f9d..a9e4b5d 100644
--- a/WebCore/wml/WMLElement.cpp
+++ b/WebCore/wml/WMLElement.cpp
@@ -77,6 +77,11 @@ void WMLElement::parseMappedAttribute(MappedAttribute* attr)
}
}
+String WMLElement::title() const
+{
+ return parseValueSubstitutingVariableReferences(getAttribute(HTMLNames::titleAttr));
+}
+
bool WMLElement::rendererIsNeeded(RenderStyle* style)
{
return document()->documentElement() == this || style->display() != NONE;
@@ -87,7 +92,7 @@ RenderObject* WMLElement::createRenderer(RenderArena*, RenderStyle* style)
return RenderObject::createObject(this, style);
}
-String WMLElement::parseValueSubstitutingVariableReferences(const AtomicString& value, WMLErrorCode defaultErrorCode)
+String WMLElement::parseValueSubstitutingVariableReferences(const AtomicString& value, WMLErrorCode defaultErrorCode) const
{
bool isValid = false;
if (!containsVariableReference(value, isValid))
@@ -101,7 +106,7 @@ String WMLElement::parseValueSubstitutingVariableReferences(const AtomicString&
return substituteVariableReferences(value, document());
}
-String WMLElement::parseValueForbiddingVariableReferences(const AtomicString& value)
+String WMLElement::parseValueForbiddingVariableReferences(const AtomicString& value) const
{
bool isValid = false;
if (containsVariableReference(value, isValid)) {
diff --git a/WebCore/wml/WMLElement.h b/WebCore/wml/WMLElement.h
index 61bd98f..46b0ff4 100644
--- a/WebCore/wml/WMLElement.h
+++ b/WebCore/wml/WMLElement.h
@@ -37,13 +37,15 @@ public:
virtual bool mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const;
virtual void parseMappedAttribute(MappedAttribute*);
+ virtual String title() const;
+
virtual bool rendererIsNeeded(RenderStyle*);
virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
protected:
// Helper function for derived classes
- String parseValueSubstitutingVariableReferences(const AtomicString&, WMLErrorCode defaultErrorCode = WMLErrorInvalidVariableReference);
- String parseValueForbiddingVariableReferences(const AtomicString&);
+ String parseValueSubstitutingVariableReferences(const AtomicString&, WMLErrorCode defaultErrorCode = WMLErrorInvalidVariableReference) const;
+ String parseValueForbiddingVariableReferences(const AtomicString&) const;
};
}
diff --git a/WebCore/wml/WMLErrorHandling.cpp b/WebCore/wml/WMLErrorHandling.cpp
index a228299..d62ccb7 100644
--- a/WebCore/wml/WMLErrorHandling.cpp
+++ b/WebCore/wml/WMLErrorHandling.cpp
@@ -38,7 +38,8 @@ void reportWMLError(Document* doc, WMLErrorCode error)
return;
String errorMessage = errorMessageForErrorCode(error);
- if (XMLTokenizer* tokenizer = static_cast<XMLTokenizer*>(doc->tokenizer())) {
+ XMLTokenizer* tokenizer = static_cast<XMLTokenizer*>(doc->tokenizer());
+ if (tokenizer && error != WMLErrorDeckNotAccessible) {
// Some errors are reported as result of an insertedIntoDocument() call.
// If this happened, parsing has been stopped, and the document fragment
// is wrapped in a XHTML error document. That means insertedIntoDocument()
@@ -61,7 +62,7 @@ void reportWMLError(Document* doc, WMLErrorCode error)
if (!console)
return;
- console->addMessage(WMLMessageSource, ErrorMessageLevel, errorMessage, 0, String());
+ console->addMessage(WMLMessageSource, LogMessageType, ErrorMessageLevel, errorMessage, 0, String());
}
}
diff --git a/WebCore/wml/WMLEventHandlingElement.cpp b/WebCore/wml/WMLEventHandlingElement.cpp
index 2848985..faa80c7 100644
--- a/WebCore/wml/WMLEventHandlingElement.cpp
+++ b/WebCore/wml/WMLEventHandlingElement.cpp
@@ -61,10 +61,22 @@ void WMLEventHandlingElement::registerDoElement(WMLDoElement* doElement, Documen
}
}
+ ASSERT(m_doElements.find(doElement) == WTF::notFound);
m_doElements.append(doElement);
doElement->setActive(true);
}
+void WMLEventHandlingElement::deregisterDoElement(WMLDoElement* doElement)
+{
+ doElement->setActive(false);
+
+ size_t position = m_doElements.find(doElement);
+ if (position == WTF::notFound)
+ return;
+
+ m_doElements.remove(position);
+}
+
WMLEventHandlingElement* toWMLEventHandlingElement(WMLElement* element)
{
if (!element->isWMLElement())
diff --git a/WebCore/wml/WMLEventHandlingElement.h b/WebCore/wml/WMLEventHandlingElement.h
index 92ae289..15cef7b 100644
--- a/WebCore/wml/WMLEventHandlingElement.h
+++ b/WebCore/wml/WMLEventHandlingElement.h
@@ -42,6 +42,7 @@ public:
Vector<WMLDoElement*>& doElements() { return m_doElements; }
void registerDoElement(WMLDoElement*, Document*);
+ void deregisterDoElement(WMLDoElement*);
private:
OwnPtr<WMLIntrinsicEventHandler> m_eventHandler;
diff --git a/WebCore/wml/WMLFieldSetElement.cpp b/WebCore/wml/WMLFieldSetElement.cpp
index 8146375..3930de2 100644
--- a/WebCore/wml/WMLFieldSetElement.cpp
+++ b/WebCore/wml/WMLFieldSetElement.cpp
@@ -43,19 +43,12 @@ WMLFieldSetElement::~WMLFieldSetElement()
{
}
-void WMLFieldSetElement::parseMappedAttribute(MappedAttribute* attr)
-{
- if (attr->name() == HTMLNames::titleAttr)
- m_title = parseValueSubstitutingVariableReferences(attr->value());
- else
- WMLElement::parseMappedAttribute(attr);
-}
-
void WMLFieldSetElement::insertedIntoDocument()
{
WMLElement::insertedIntoDocument();
- if (m_title.isEmpty())
+ String title = parseValueSubstitutingVariableReferences(getAttribute(HTMLNames::titleAttr));
+ if (title.isEmpty())
return;
m_insertedLegendElement = WMLElementFactory::createWMLElement(insertedLegendTag, document());
@@ -67,14 +60,14 @@ void WMLFieldSetElement::insertedIntoDocument()
ASSERT(ec == 0);
// Create text node holding the 'title' attribute value
- m_insertedLegendElement->appendChild(document()->createTextNode(m_title), ec);
+ m_insertedLegendElement->appendChild(document()->createTextNode(title), ec);
ASSERT(ec == 0);
}
void WMLFieldSetElement::removedFromDocument()
{
- WMLElement::removedFromDocument();
m_insertedLegendElement.clear();
+ WMLElement::removedFromDocument();
}
RenderObject* WMLFieldSetElement::createRenderer(RenderArena* arena, RenderStyle*)
diff --git a/WebCore/wml/WMLFieldSetElement.h b/WebCore/wml/WMLFieldSetElement.h
index 2043364..1087fa1 100644
--- a/WebCore/wml/WMLFieldSetElement.h
+++ b/WebCore/wml/WMLFieldSetElement.h
@@ -31,14 +31,12 @@ public:
WMLFieldSetElement(const QualifiedName& tagName, Document*);
virtual ~WMLFieldSetElement();
- virtual void parseMappedAttribute(MappedAttribute*);
virtual void insertedIntoDocument();
virtual void removedFromDocument();
virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
private:
- String m_title;
RefPtr<WMLElement> m_insertedLegendElement;
};
diff --git a/WebCore/wml/WMLGoElement.cpp b/WebCore/wml/WMLGoElement.cpp
index 7293e66..635302f 100644
--- a/WebCore/wml/WMLGoElement.cpp
+++ b/WebCore/wml/WMLGoElement.cpp
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -50,8 +50,16 @@ WMLGoElement::WMLGoElement(const QualifiedName& tagName, Document* doc)
void WMLGoElement::registerPostfieldElement(WMLPostfieldElement* postfield)
{
+ ASSERT(m_postfieldElements.find(postfield) == WTF::notFound);
m_postfieldElements.append(postfield);
}
+
+void WMLGoElement::deregisterPostfieldElement(WMLPostfieldElement* postfield)
+{
+ size_t position = m_postfieldElements.find(postfield);
+ ASSERT(position != WTF::notFound);
+ m_postfieldElements.remove(position);
+}
void WMLGoElement::parseMappedAttribute(MappedAttribute* attr)
{
@@ -101,11 +109,8 @@ void WMLGoElement::executeTask(Event*)
// FIXME: 'newcontext' handling not implemented for external cards
bool inSameDeck = doc->url().path() == url.path();
- if (inSameDeck && url.hasRef()) {
- // Force frame loader to load the URL with fragment identifier
- loader->setForceReloadWmlDeck(true);
-
- if (WMLCardElement* card = WMLCardElement::findNamedCardInDocument(doc, url.ref())) {
+ if (inSameDeck && url.hasFragmentIdentifier()) {
+ if (WMLCardElement* card = WMLCardElement::findNamedCardInDocument(doc, url.fragmentIdentifier())) {
if (card->isNewContext())
pageState->reset();
}
diff --git a/WebCore/wml/WMLGoElement.h b/WebCore/wml/WMLGoElement.h
index 3c70289..75c1858 100644
--- a/WebCore/wml/WMLGoElement.h
+++ b/WebCore/wml/WMLGoElement.h
@@ -36,6 +36,7 @@ public:
WMLGoElement(const QualifiedName& tagName, Document*);
void registerPostfieldElement(WMLPostfieldElement*);
+ void deregisterPostfieldElement(WMLPostfieldElement*);
virtual void parseMappedAttribute(MappedAttribute*);
virtual void executeTask(Event*);
diff --git a/WebCore/wml/WMLImageLoader.cpp b/WebCore/wml/WMLImageLoader.cpp
index c77b511..3c40215 100644
--- a/WebCore/wml/WMLImageLoader.cpp
+++ b/WebCore/wml/WMLImageLoader.cpp
@@ -49,7 +49,7 @@ void WMLImageLoader::dispatchLoadEvent()
String WMLImageLoader::sourceURI(const AtomicString& attr) const
{
- return parseURL(KURL(element()->baseURI(), attr).string());
+ return deprecatedParseURL(KURL(element()->baseURI(), attr).string());
}
void WMLImageLoader::notifyFinished(CachedResource* image)
diff --git a/WebCore/wml/WMLInputElement.cpp b/WebCore/wml/WMLInputElement.cpp
index cb824d1..d6fa79a 100644
--- a/WebCore/wml/WMLInputElement.cpp
+++ b/WebCore/wml/WMLInputElement.cpp
@@ -298,7 +298,7 @@ void WMLInputElement::defaultEventHandler(Event* evt)
InputElement::handleBeforeTextInsertedEvent(m_data, this, document(), evt);
if (renderer() && (evt->isMouseEvent() || evt->isDragEvent() || evt->isWheelEvent() || evt->type() == eventNames().blurEvent || evt->type() == eventNames().focusEvent))
- static_cast<RenderTextControlSingleLine*>(renderer())->forwardEvent(evt);
+ toRenderTextControlSingleLine(renderer())->forwardEvent(evt);
}
void WMLInputElement::cacheSelection(int start, int end)
diff --git a/WebCore/wml/WMLIntrinsicEventHandler.cpp b/WebCore/wml/WMLIntrinsicEventHandler.cpp
index 46cdb8c..67364d9 100644
--- a/WebCore/wml/WMLIntrinsicEventHandler.cpp
+++ b/WebCore/wml/WMLIntrinsicEventHandler.cpp
@@ -38,6 +38,12 @@ bool WMLIntrinsicEventHandler::registerIntrinsicEvent(WMLIntrinsicEventType type
return true;
}
+void WMLIntrinsicEventHandler::deregisterIntrinsicEvent(WMLIntrinsicEventType type)
+{
+ if (m_events.contains(type))
+ m_events.remove(type);
+}
+
void WMLIntrinsicEventHandler::triggerIntrinsicEvent(WMLIntrinsicEventType type) const
{
RefPtr<WMLIntrinsicEvent> event = m_events.get(type);
diff --git a/WebCore/wml/WMLIntrinsicEventHandler.h b/WebCore/wml/WMLIntrinsicEventHandler.h
index b24bb54..8ac6d1b 100644
--- a/WebCore/wml/WMLIntrinsicEventHandler.h
+++ b/WebCore/wml/WMLIntrinsicEventHandler.h
@@ -44,6 +44,7 @@ public:
WMLIntrinsicEventHandler();
bool registerIntrinsicEvent(WMLIntrinsicEventType, PassRefPtr<WMLIntrinsicEvent>);
+ void deregisterIntrinsicEvent(WMLIntrinsicEventType);
void triggerIntrinsicEvent(WMLIntrinsicEventType) const;
bool hasIntrinsicEvent(WMLIntrinsicEventType) const;
diff --git a/WebCore/wml/WMLNoopElement.cpp b/WebCore/wml/WMLNoopElement.cpp
index 1ba1c18..b2ce506 100644
--- a/WebCore/wml/WMLNoopElement.cpp
+++ b/WebCore/wml/WMLNoopElement.cpp
@@ -45,15 +45,18 @@ void WMLNoopElement::insertedIntoDocument()
WMLElement::insertedIntoDocument();
Node* parent = parentNode();
- ASSERT(parent);
-
if (!parent || !parent->isWMLElement())
return;
if (parent->hasTagName(doTag)) {
WMLDoElement* doElement = static_cast<WMLDoElement*>(parent);
doElement->setNoop(true);
- doElement->setNeedsStyleRecalc();
+
+ if (doElement->attached())
+ doElement->detach();
+
+ ASSERT(!doElement->attached());
+ doElement->attach();
} else if (parent->hasTagName(anchorTag))
reportWMLError(document(), WMLErrorForbiddenTaskInAnchorElement);
}
diff --git a/WebCore/wml/WMLOnEventElement.cpp b/WebCore/wml/WMLOnEventElement.cpp
index a8d35a0..6fc4e8b 100644
--- a/WebCore/wml/WMLOnEventElement.cpp
+++ b/WebCore/wml/WMLOnEventElement.cpp
@@ -60,19 +60,21 @@ void WMLOnEventElement::parseMappedAttribute(MappedAttribute* attr)
WMLElement::parseMappedAttribute(attr);
}
+static inline WMLEventHandlingElement* eventHandlingParent(Node* parent)
+{
+ if (!parent || !parent->isWMLElement())
+ return 0;
+
+ return toWMLEventHandlingElement(static_cast<WMLElement*>(parent));
+}
+
void WMLOnEventElement::registerTask(WMLTaskElement* task)
{
if (m_type == WMLIntrinsicEventUnknown)
return;
// Register intrinsic event to the event handler of the owner of onevent element
- Node* parent = parentNode();
- ASSERT(parent);
-
- if (!parent || !parent->isWMLElement())
- return;
-
- WMLEventHandlingElement* eventHandlingElement = toWMLEventHandlingElement(static_cast<WMLElement*>(parent));
+ WMLEventHandlingElement* eventHandlingElement = eventHandlingParent(parentNode());
if (!eventHandlingElement)
return;
@@ -83,6 +85,15 @@ void WMLOnEventElement::registerTask(WMLTaskElement* task)
reportWMLError(document(), WMLErrorConflictingEventBinding);
}
+void WMLOnEventElement::deregisterTask(WMLTaskElement*)
+{
+ WMLEventHandlingElement* eventHandlingElement = eventHandlingParent(parentNode());
+ if (!eventHandlingElement)
+ return;
+
+ eventHandlingElement->eventHandler()->deregisterIntrinsicEvent(m_type);
+}
+
}
#endif
diff --git a/WebCore/wml/WMLOnEventElement.h b/WebCore/wml/WMLOnEventElement.h
index bb004fe..de33600 100644
--- a/WebCore/wml/WMLOnEventElement.h
+++ b/WebCore/wml/WMLOnEventElement.h
@@ -36,6 +36,7 @@ public:
virtual void parseMappedAttribute(MappedAttribute*);
void registerTask(WMLTaskElement*);
+ void deregisterTask(WMLTaskElement*);
private:
WMLIntrinsicEventType m_type;
diff --git a/WebCore/wml/WMLOptGroupElement.cpp b/WebCore/wml/WMLOptGroupElement.cpp
index d70731c..9a7ea88 100644
--- a/WebCore/wml/WMLOptGroupElement.cpp
+++ b/WebCore/wml/WMLOptGroupElement.cpp
@@ -120,11 +120,6 @@ void WMLOptGroupElement::childrenChanged(bool changedByParser, Node* beforeChang
void WMLOptGroupElement::parseMappedAttribute(MappedAttribute* attr)
{
- if (attr->name() == HTMLNames::titleAttr) {
- m_title = parseValueSubstitutingVariableReferences(attr->value());
- return;
- }
-
WMLFormControlElement::parseMappedAttribute(attr);
recalcSelectOptions();
}
@@ -154,7 +149,7 @@ RenderStyle* WMLOptGroupElement::nonRendererRenderStyle() const
String WMLOptGroupElement::groupLabelText() const
{
- String itemText = document()->displayStringModifiedByEncoding(m_title);
+ String itemText = document()->displayStringModifiedByEncoding(title());
// In WinIE, leading and trailing whitespace is ignored in options and optgroups. We match this behavior.
itemText = itemText.stripWhiteSpace();
diff --git a/WebCore/wml/WMLOptGroupElement.h b/WebCore/wml/WMLOptGroupElement.h
index 1ba5ac1..e1b9217 100644
--- a/WebCore/wml/WMLOptGroupElement.h
+++ b/WebCore/wml/WMLOptGroupElement.h
@@ -32,8 +32,6 @@ public:
WMLOptGroupElement(const QualifiedName& tagName, Document*);
virtual ~WMLOptGroupElement();
- String title() const { return m_title; }
-
virtual const AtomicString& formControlType() const;
virtual bool rendererIsNeeded(RenderStyle*) { return false; }
@@ -59,7 +57,6 @@ private:
void recalcSelectOptions();
private:
- String m_title;
RefPtr<RenderStyle> m_style;
};
diff --git a/WebCore/wml/WMLOptionElement.cpp b/WebCore/wml/WMLOptionElement.cpp
index 1087134..764d3a1 100644
--- a/WebCore/wml/WMLOptionElement.cpp
+++ b/WebCore/wml/WMLOptionElement.cpp
@@ -125,7 +125,15 @@ bool WMLOptionElement::selected() const
void WMLOptionElement::setSelectedState(bool selected)
{
+ if (this->selected() == selected)
+ return;
+
OptionElement::setSelectedState(m_data, this, selected);
+
+ if (WMLSelectElement* select = ownerSelectElement(this)) {
+ if (select->multiple() || selected)
+ handleIntrinsicEventIfNeeded();
+ }
}
String WMLOptionElement::value() const
@@ -135,7 +143,7 @@ String WMLOptionElement::value() const
String WMLOptionElement::text() const
{
- return OptionElement::collectOptionText(m_data, this);
+ return OptionElement::collectOptionLabelOrText(m_data, this);
}
String WMLOptionElement::textIndentedToRespectGroupLabel() const
diff --git a/WebCore/wml/WMLPageState.cpp b/WebCore/wml/WMLPageState.cpp
index 15ae9ca..5f431bb 100644
--- a/WebCore/wml/WMLPageState.cpp
+++ b/WebCore/wml/WMLPageState.cpp
@@ -1,6 +1,5 @@
/*
- * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
- *
+ * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
* Copyright (C) 2004-2007 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
@@ -25,6 +24,9 @@
#if ENABLE(WML)
#include "WMLPageState.h"
+#include "CString.h"
+#include "Document.h"
+#include "Frame.h"
#include "HistoryItem.h"
#include "KURL.h"
#include "Page.h"
@@ -33,9 +35,8 @@ namespace WebCore {
WMLPageState::WMLPageState(Page* page)
: m_page(page)
- , m_historyLength(0)
, m_activeCard(0)
- , m_hasDeckAccess(false)
+ , m_hasAccessControlData(false)
{
}
@@ -44,87 +45,223 @@ WMLPageState::~WMLPageState()
m_variables.clear();
}
+#ifndef NDEBUG
+// Debugging helper for use within gdb
+void WMLPageState::dump()
+{
+ WMLVariableMap::iterator it = m_variables.begin();
+ WMLVariableMap::iterator end = m_variables.end();
+
+ fprintf(stderr, "Dumping WMLPageState (this=%p) associated with Page (page=%p)...\n", this, m_page);
+ for (; it != end; ++it)
+ fprintf(stderr, "\t-> name: '%s'\tvalue: '%s'\n", (*it).first.latin1().data(), (*it).second.latin1().data());
+}
+#endif
+
void WMLPageState::reset()
{
- // remove all the variables in the current browser context
+ // Remove all the variables
m_variables.clear();
- // clear the navigation history state
- if (m_page)
- m_page->backForwardList()->clearWmlPageHistory();
+ // Clear the navigation history state
+ if (BackForwardList* list = m_page ? m_page->backForwardList() : 0)
+ list->clearWMLPageHistory();
+}
+
+static inline String normalizedHostName(const String& passedHost)
+{
+ if (passedHost.contains("127.0.0.1")) {
+ String host = passedHost;
+ return host.replace("127.0.0.1", "localhost");
+ }
+
+ return passedHost;
+}
+
+static inline String hostFromURL(const KURL& url)
+{
+ // Default to "localhost"
+ String host = normalizedHostName(url.host());
+ return host.isEmpty() ? "localhost" : host;
+}
+
+static KURL urlForHistoryItem(Frame* frame, HistoryItem* item)
+{
+ // For LayoutTests we need to find the corresponding WML frame in the test document
+ // to be able to test access-control correctly. Remember that WML is never supposed
+ // to be embedded anywhere, so the purpose is to simulate a standalone WML document.
+ if (frame->document()->isWMLDocument())
+ return item->url();
+
+ const HistoryItemVector& childItems = item->children();
+ HistoryItemVector::const_iterator it = childItems.begin();
+ const HistoryItemVector::const_iterator end = childItems.end();
+
+ for (; it != end; ++it) {
+ const RefPtr<HistoryItem> childItem = *it;
+ Frame* childFrame = frame->tree()->child(childItem->target());
+ if (!childFrame)
+ continue;
+
+ if (Document* childDocument = childFrame->document()) {
+ if (childDocument->isWMLDocument())
+ return childItem->url();
+ }
+ }
- // reset implementation-specfic state if UA has
- m_historyLength = 1;
+ return item->url();
}
-bool WMLPageState::setNeedCheckDeckAccess(bool need)
+static bool tryAccessHistoryURLs(Page* page, KURL& previousURL, KURL& currentURL)
{
- if (m_hasDeckAccess && need)
+ if (!page)
return false;
- m_hasDeckAccess = need;
- m_accessPath = String();
- m_accessDomain = String();
+ Frame* frame = page->mainFrame();
+ if (!frame || !frame->document())
+ return false;
+
+ BackForwardList* list = page->backForwardList();
+ if (!list)
+ return false;
+
+ HistoryItem* previousItem = list->backItem();
+ if (!previousItem)
+ return false;
+
+ HistoryItem* currentItem = list->currentItem();
+ if (!currentItem)
+ return false;
+
+ previousURL = urlForHistoryItem(frame, previousItem);
+ currentURL = urlForHistoryItem(frame, currentItem);
+
return true;
}
-// FIXME: We may want another name, it does far more than just checking wheter the deck is accessable
-bool WMLPageState::isDeckAccessible()
+bool WMLPageState::processAccessControlData(const String& domain, const String& path)
{
- if (!m_hasDeckAccess || !m_page || !m_page->backForwardList() || !m_page->backForwardList()->backItem())
+ if (m_hasAccessControlData)
+ return false;
+
+ m_hasAccessControlData = true;
+
+ KURL previousURL, currentURL;
+ if (!tryAccessHistoryURLs(m_page, previousURL, currentURL))
return true;
- HistoryItem* histItem = m_page->backForwardList()->backItem();
- KURL url(histItem->urlString());
+ // Spec: The path attribute defaults to the value "/"
+ m_accessPath = path.isEmpty() ? "/" : path;
- String prevHost = url.host();
- String prevPath = url.path();
+ // Spec: The domain attribute defaults to the current decks domain.
+ String previousHost = hostFromURL(previousURL);
+ m_accessDomain = domain.isEmpty() ? previousHost : normalizedHostName(domain);
- // for 'file' URI, the host part may be empty, so we should complete it.
- if (prevHost.isEmpty())
- prevHost = "localhost";
+ // Spec: To simplify the development of applications that may not know the absolute path to the
+ // current deck, the path attribute accepts relative URIs. The user agent converts the relative
+ // path to an absolute path and then performs prefix matching against the PATH attribute.
+ Document* document = m_page->mainFrame() ? m_page->mainFrame()->document() : 0;
+ if (document && previousHost == m_accessDomain && !m_accessPath.startsWith("/")) {
+ String currentPath = currentURL.path();
- histItem = m_page->backForwardList()->currentItem();
- KURL curUrl(histItem->urlString());
- String curPath = curUrl.path();
+ size_t index = currentPath.reverseFind('/');
+ if (index != WTF::notFound)
+ m_accessPath = document->completeURL(currentPath.left(index + 1) + m_accessPath).path();
+ }
- if (equalIgnoringRef(url, curUrl))
+ return true;
+}
+
+void WMLPageState::resetAccessControlData()
+{
+ m_hasAccessControlData = false;
+ m_accessDomain = String();
+ m_accessPath = String();
+}
+
+bool WMLPageState::canAccessDeck() const
+{
+ if (!m_hasAccessControlData)
+ return true;
+
+ KURL previousURL, currentURL;
+ if (!tryAccessHistoryURLs(m_page, previousURL, currentURL))
+ return true;
+
+ if (equalIgnoringFragmentIdentifier(previousURL, currentURL))
return true;
- // "/" is the default value if not specified
- if (m_accessPath.isEmpty())
- m_accessPath = "/";
- else if (m_accessPath.endsWith("/") && (m_accessPath != "/"))
- m_accessPath = m_accessPath.left((m_accessPath.length()-1));
-
-
- // current deck domain is the default value if not specified
- if (m_accessDomain.isEmpty())
- m_accessDomain = prevHost;
-
- // convert relative URL to absolute URL before performing path matching
- if (prevHost == m_accessDomain) {
- if (!m_accessPath.startsWith("/")) {
- int index = curPath.reverseFind('/');
- if (index != -1) {
- curPath = curPath.left(index + 1);
- curPath += m_accessPath;
- curUrl.setPath(curPath);
- m_accessPath = curUrl.path();
- }
+ return hostIsAllowedToAccess(hostFromURL(previousURL)) && pathIsAllowedToAccess(previousURL.path());
+}
+
+bool WMLPageState::hostIsAllowedToAccess(const String& host) const
+{
+ // Spec: The access domain is suffix-matched against the domain name portion of the referring URI
+ Vector<String> subdomainsAllowed;
+ if (m_accessDomain.contains('.'))
+ m_accessDomain.split('.', subdomainsAllowed);
+ else
+ subdomainsAllowed.append(m_accessDomain);
+
+ Vector<String> subdomainsCheck;
+ if (host.contains('.'))
+ host.split('.', subdomainsCheck);
+ else
+ subdomainsCheck.append(host);
+
+ Vector<String>::iterator itAllowed = subdomainsAllowed.end() - 1;
+ Vector<String>::iterator beginAllowed = subdomainsAllowed.begin();
+
+ Vector<String>::iterator itCheck = subdomainsCheck.end() - 1;
+ Vector<String>::iterator beginCheck = subdomainsCheck.begin();
+
+ bool hostOk = true;
+ for (; itAllowed >= beginAllowed && itCheck >= beginCheck; ) {
+ if (*itAllowed != *itCheck) {
+ hostOk = false;
+ break;
}
+
+ --itAllowed;
+ --itCheck;
}
- // path prefix matching
- if (prevPath.startsWith(m_accessPath) &&
- (prevPath[m_accessPath.length()] == '/' || prevPath.length() == m_accessPath.length())) {
- // domain suffix matching
- unsigned domainLength = m_accessDomain.length();
- unsigned hostLength = prevHost.length();
- return (prevHost.endsWith(m_accessDomain) && prevHost[hostLength - domainLength - 1] == '.') || hostLength == domainLength;
+ return hostOk;
+}
+
+bool WMLPageState::pathIsAllowedToAccess(const String& path) const
+{
+ // Spec: The access path is prefix matched against the path portion of the referring URI
+ Vector<String> subpathsAllowed;
+ if (m_accessPath.contains('/'))
+ m_accessPath.split('/', subpathsAllowed);
+ else
+ subpathsAllowed.append(m_accessPath);
+
+ Vector<String> subpathsCheck;
+ if (path.contains('/'))
+ path.split('/', subpathsCheck);
+ else
+ subpathsCheck.append(path);
+
+ Vector<String>::iterator itAllowed = subpathsAllowed.begin();
+ Vector<String>::iterator endAllowed = subpathsAllowed.end();
+
+ Vector<String>::iterator itCheck = subpathsCheck.begin();
+ Vector<String>::iterator endCheck = subpathsCheck.end();
+
+ bool pathOk = true;
+ for (; itAllowed != endAllowed && itCheck != endCheck; ) {
+ if (*itAllowed != *itCheck) {
+ pathOk = false;
+ break;
+ }
+
+ ++itAllowed;
+ ++itCheck;
}
- return false;
+ return pathOk;
}
}
diff --git a/WebCore/wml/WMLPageState.h b/WebCore/wml/WMLPageState.h
index 6a1d960..de0af91 100644
--- a/WebCore/wml/WMLPageState.h
+++ b/WebCore/wml/WMLPageState.h
@@ -39,40 +39,41 @@ public:
WMLPageState(Page*);
virtual ~WMLPageState();
- // reset the browser context when 'newcontext' attribute
- // of card element is performed as part of go task
+#ifndef NDEBUG
+ void dump();
+#endif
+
+ // Reset the browser context
void reset();
- // variables operations
+ // Variable handling
void storeVariable(const String& name, const String& value) { m_variables.set(name, value); }
void storeVariables(WMLVariableMap& variables) { m_variables = variables; }
String getVariable(const String& name) const { return m_variables.get(name); }
bool hasVariables() const { return !m_variables.isEmpty(); }
- int historyLength() const { return m_historyLength; }
- void setHistoryLength(int length) { m_historyLength = length; }
-
Page* page() const { return m_page; }
WMLCardElement* activeCard() const { return m_activeCard; }
void setActiveCard(WMLCardElement* card) { m_activeCard = card; }
- // deck access control
- void restrictDeckAccessToDomain(const String& domain) { m_accessDomain = domain; }
- void restrictDeckAccessToPath(const String& path) { m_accessPath = path; }
- bool hasDeckAccess() const { return m_hasDeckAccess; }
-
- bool setNeedCheckDeckAccess(bool);
- bool isDeckAccessible();
+ // Deck access control
+ bool processAccessControlData(const String& dmain, const String& path);
+ void resetAccessControlData();
+
+ bool canAccessDeck() const;
+
+private:
+ bool hostIsAllowedToAccess(const String&) const;
+ bool pathIsAllowedToAccess(const String&) const;
private:
Page* m_page;
WMLVariableMap m_variables;
- int m_historyLength;
WMLCardElement* m_activeCard;
String m_accessDomain;
String m_accessPath;
- bool m_hasDeckAccess;
+ bool m_hasAccessControlData;
};
}
diff --git a/WebCore/wml/WMLPostfieldElement.cpp b/WebCore/wml/WMLPostfieldElement.cpp
index 69f61f5..21f4c5b 100644
--- a/WebCore/wml/WMLPostfieldElement.cpp
+++ b/WebCore/wml/WMLPostfieldElement.cpp
@@ -26,7 +26,6 @@
#include "CString.h"
#include "TextEncoding.h"
#include "HTMLNames.h"
-#include "MappedAttribute.h"
#include "WMLDocument.h"
#include "WMLGoElement.h"
#include "WMLNames.h"
@@ -40,27 +39,32 @@ WMLPostfieldElement::WMLPostfieldElement(const QualifiedName& tagName, Document*
{
}
-void WMLPostfieldElement::parseMappedAttribute(MappedAttribute* attr)
-{
- if (attr->name() == HTMLNames::nameAttr)
- m_name = parseValueSubstitutingVariableReferences(attr->value());
- else if (attr->name() == HTMLNames::valueAttr)
- m_value = parseValueSubstitutingVariableReferences(attr->value());
- else
- WMLElement::parseMappedAttribute(attr);
-}
-
void WMLPostfieldElement::insertedIntoDocument()
{
WMLElement::insertedIntoDocument();
Node* parent = parentNode();
- ASSERT(parent);
+ if (parent && parent->hasTagName(goTag))
+ static_cast<WMLGoElement*>(parent)->registerPostfieldElement(this);
+}
+
+void WMLPostfieldElement::removedFromDocument()
+{
+ Node* parent = parentNode();
+ if (parent && parent->hasTagName(goTag))
+ static_cast<WMLGoElement*>(parent)->deregisterPostfieldElement(this);
+
+ WMLElement::removedFromDocument();
+}
- if (!parent->hasTagName(goTag))
- return;
+String WMLPostfieldElement::name() const
+{
+ return parseValueSubstitutingVariableReferences(getAttribute(HTMLNames::nameAttr));
+}
- static_cast<WMLGoElement*>(parent)->registerPostfieldElement(this);
+String WMLPostfieldElement::value() const
+{
+ return parseValueSubstitutingVariableReferences(getAttribute(HTMLNames::valueAttr));
}
static inline CString encodedString(const TextEncoding& encoding, const String& data)
@@ -70,8 +74,8 @@ static inline CString encodedString(const TextEncoding& encoding, const String&
void WMLPostfieldElement::encodeData(const TextEncoding& encoding, CString& name, CString& value)
{
- name = encodedString(encoding, m_name);
- value = encodedString(encoding, m_value);
+ name = encodedString(encoding, this->name());
+ value = encodedString(encoding, this->value());
}
}
diff --git a/WebCore/wml/WMLPostfieldElement.h b/WebCore/wml/WMLPostfieldElement.h
index 59b7f64..dd10b47 100644
--- a/WebCore/wml/WMLPostfieldElement.h
+++ b/WebCore/wml/WMLPostfieldElement.h
@@ -30,18 +30,14 @@ class WMLPostfieldElement : public WMLElement {
public:
WMLPostfieldElement(const QualifiedName& tagName, Document*);
- virtual void parseMappedAttribute(MappedAttribute*);
virtual void insertedIntoDocument();
+ virtual void removedFromDocument();
- String name() const { return m_name; }
- String value() const { return m_value; }
+ String name() const;
+ String value() const;
// Encode name() and value() in a CString using the passed encoding
void encodeData(const TextEncoding&, CString& name, CString& value);
-
-private:
- String m_name;
- String m_value;
};
}
diff --git a/WebCore/wml/WMLSelectElement.cpp b/WebCore/wml/WMLSelectElement.cpp
index 5b5aed1..2d03a3f 100644
--- a/WebCore/wml/WMLSelectElement.cpp
+++ b/WebCore/wml/WMLSelectElement.cpp
@@ -22,16 +22,21 @@
#if ENABLE(WML)
#include "WMLSelectElement.h"
-
+#include "CString.h"
#include "HTMLNames.h"
#include "MappedAttribute.h"
+#include "OptionElement.h"
#include "RenderListBox.h"
#include "RenderMenuList.h"
-
+#include "WMLDocument.h"
+#include "WMLNames.h"
+#include "WMLVariables.h"
#include <wtf/StdLibExtras.h>
namespace WebCore {
+using namespace WMLNames;
+
WMLSelectElement::WMLSelectElement(const QualifiedName& tagName, Document* document)
: WMLFormControlElement(tagName, document)
{
@@ -41,6 +46,12 @@ WMLSelectElement::~WMLSelectElement()
{
}
+const AtomicString& WMLSelectElement::formControlName() const
+{
+ AtomicString name = this->name();
+ return name.isNull() ? emptyAtom : name;
+}
+
const AtomicString& WMLSelectElement::formControlType() const
{
DEFINE_STATIC_LOCAL(const AtomicString, selectMultiple, ("select-multiple"));
@@ -92,9 +103,14 @@ int WMLSelectElement::selectedIndex() const
return SelectElement::selectedIndex(m_data, this);
}
-void WMLSelectElement::setSelectedIndex(int index, bool deselect, bool fireOnChange)
+void WMLSelectElement::setSelectedIndex(int optionIndex, bool deselect)
{
- SelectElement::setSelectedIndex(m_data, this, index, deselect, fireOnChange);
+ SelectElement::setSelectedIndex(m_data, this, optionIndex, deselect, false, false);
+}
+
+void WMLSelectElement::setSelectedIndexByUser(int optionIndex, bool deselect, bool fireOnChangeNow)
+{
+ SelectElement::setSelectedIndex(m_data, this, optionIndex, deselect, fireOnChangeNow, true);
}
bool WMLSelectElement::saveFormControlState(String& value) const
@@ -151,6 +167,14 @@ void WMLSelectElement::reset()
void WMLSelectElement::defaultEventHandler(Event* event)
{
SelectElement::defaultEventHandler(m_data, this, event);
+
+ // FIXME: There must be a better place to update the page variable state. Investigate.
+ updateVariables();
+
+ if (event->defaultHandled())
+ return;
+
+ WMLFormControlElement::defaultEventHandler(event);
}
void WMLSelectElement::accessKeyAction(bool sendToAnyElement)
@@ -213,12 +237,311 @@ void WMLSelectElement::scrollToSelection()
SelectElement::scrollToSelection(m_data, this);
}
+void WMLSelectElement::selectInitialOptions()
+{
+ // Spec: Step 1 - the default option index is determined using iname and ivalue
+ calculateDefaultOptionIndices();
+
+ if (m_defaultOptionIndices.isEmpty())
+ return;
+
+ // Spec: Step 2 – initialise variables
+ initializeVariables();
+
+ // Spec: Step 3 – pre-select option(s) specified by the default option index
+ selectDefaultOptions();
+}
+
void WMLSelectElement::insertedIntoTree(bool deep)
{
SelectElement::insertedIntoTree(m_data, this);
WMLFormControlElement::insertedIntoTree(deep);
}
+void WMLSelectElement::calculateDefaultOptionIndices()
+{
+ WMLPageState* pageState = wmlPageStateForDocument(document());
+ if (!pageState)
+ return;
+
+ String variable;
+
+ // Spec: If the 'iname' attribute is specified and names a variable that is set,
+ // then the default option index is the validated value of that variable.
+ String iname = this->iname();
+ if (!iname.isEmpty()) {
+ variable = pageState->getVariable(iname);
+ if (!variable.isEmpty())
+ m_defaultOptionIndices = parseIndexValueString(variable);
+ }
+
+ // Spec: If the default option index is empty and the 'ivalue' attribute is specified,
+ // then the default option index is the validated attribute value.
+ String ivalue = this->ivalue();
+ if (m_defaultOptionIndices.isEmpty() && !ivalue.isEmpty())
+ m_defaultOptionIndices = parseIndexValueString(ivalue);
+
+ // Spec: If the default option index is empty, and the 'name' attribute is specified
+ // and the 'name' ttribute names a variable that is set, then for each value in the 'name'
+ // variable that is present as a value in the select's option elements, the index of the
+ // first option element containing that value is added to the default index if that
+ // index has not been previously added.
+ String name = this->name();
+ if (m_defaultOptionIndices.isEmpty() && !name.isEmpty()) {
+ variable = pageState->getVariable(name);
+ if (!variable.isEmpty())
+ m_defaultOptionIndices = valueStringToOptionIndices(variable);
+ }
+
+ String value = parseValueSubstitutingVariableReferences(getAttribute(HTMLNames::valueAttr));
+
+ // Spec: If the default option index is empty and the 'value' attribute is specified then
+ // for each value in the 'value' attribute that is present as a value in the select's
+ // option elements, the index of the first option element containing that value is added
+ // to the default index if that index has not been previously added.
+ if (m_defaultOptionIndices.isEmpty() && !value.isEmpty())
+ m_defaultOptionIndices = valueStringToOptionIndices(value);
+
+ // Spec: If the default option index is empty and the select is a multi-choice, then the
+ // default option index is set to zero. If the select is single-choice, then the default
+ // option index is set to one.
+ if (m_defaultOptionIndices.isEmpty())
+ m_defaultOptionIndices.append((unsigned) !m_data.multiple());
+}
+
+void WMLSelectElement::selectDefaultOptions()
+{
+ ASSERT(!m_defaultOptionIndices.isEmpty());
+
+ if (!m_data.multiple()) {
+ setSelectedIndex(m_defaultOptionIndices.first() - 1, false);
+ return;
+ }
+
+ Vector<unsigned>::const_iterator end = m_defaultOptionIndices.end();
+ for (Vector<unsigned>::const_iterator it = m_defaultOptionIndices.begin(); it != end; ++it)
+ setSelectedIndex((*it) - 1, false);
+}
+
+void WMLSelectElement::initializeVariables()
+{
+ ASSERT(!m_defaultOptionIndices.isEmpty());
+
+ WMLPageState* pageState = wmlPageStateForDocument(document());
+ if (!pageState)
+ return;
+
+ const Vector<Element*>& items = m_data.listItems(this);
+ if (items.isEmpty())
+ return;
+
+ // Spec: If the 'iname' attribute is specified, then the named variable is set with the default option index.
+ String iname = this->iname();
+ if (!iname.isEmpty())
+ pageState->storeVariable(iname, optionIndicesToString());
+
+ String name = this->name();
+ if (name.isEmpty())
+ return;
+
+ if (m_data.multiple()) {
+ // Spec: If the 'name' attribute is specified and the select is a multiple-choice element,
+ // then for each index greater than zero, the value of the 'value' attribute on the option
+ // element at the index is added to the name variable.
+ pageState->storeVariable(name, optionIndicesToValueString());
+ return;
+ }
+
+ // Spec: If the 'name' attribute is specified and the select is a single-choice element,
+ // then the named variable is set with the value of the 'value' attribute on the option
+ // element at the default option index.
+ unsigned optionIndex = m_defaultOptionIndices.first();
+ ASSERT(optionIndex >= 1);
+
+ int listIndex = optionToListIndex(optionIndex - 1);
+ ASSERT(listIndex >= 0);
+ ASSERT(listIndex < (int) items.size());
+
+ if (OptionElement* optionElement = toOptionElement(items[listIndex]))
+ pageState->storeVariable(name, optionElement->value());
+}
+
+void WMLSelectElement::updateVariables()
+{
+ WMLPageState* pageState = wmlPageStateForDocument(document());
+ if (!pageState)
+ return;
+
+ String name = this->name();
+ String iname = this->iname();
+ if (iname.isEmpty() && name.isEmpty())
+ return;
+
+ String nameString;
+ String inameString;
+
+ unsigned optionIndex = 0;
+ const Vector<Element*>& items = m_data.listItems(this);
+
+ for (unsigned i = 0; i < items.size(); ++i) {
+ OptionElement* optionElement = toOptionElement(items[i]);
+ if (!optionElement)
+ continue;
+
+ ++optionIndex;
+ if (!optionElement->selected())
+ continue;
+
+ if (!nameString.isEmpty())
+ nameString += ";";
+
+ if (!inameString.isEmpty())
+ inameString += ";";
+
+ nameString += optionElement->value();
+ inameString += String::number(optionIndex);
+ }
+
+ if (!name.isEmpty())
+ pageState->storeVariable(name, nameString);
+
+ if (!iname.isEmpty())
+ pageState->storeVariable(iname, inameString);
+}
+
+Vector<unsigned> WMLSelectElement::parseIndexValueString(const String& indexValue) const
+{
+ Vector<unsigned> indices;
+ if (indexValue.isEmpty())
+ return indices;
+
+ Vector<String> indexStrings;
+ indexValue.split(';', indexStrings);
+
+ bool ok = false;
+ unsigned optionCount = SelectElement::optionCount(m_data, this);
+
+ Vector<String>::const_iterator end = indexStrings.end();
+ for (Vector<String>::const_iterator it = indexStrings.begin(); it != end; ++it) {
+ unsigned parsedValue = (*it).toUIntStrict(&ok);
+ // Spec: Remove all non-integer indices from the value. Remove all out-of-range indices
+ // from the value, where out-of-range is defined as any index with a value greater than
+ // the number of options in the select or with a value less than one.
+ if (!ok || parsedValue < 1 || parsedValue > optionCount)
+ continue;
+
+ // Spec: Remove duplicate indices.
+ if (indices.find(parsedValue) == notFound)
+ indices.append(parsedValue);
+ }
+
+ return indices;
+}
+
+Vector<unsigned> WMLSelectElement::valueStringToOptionIndices(const String& value) const
+{
+ Vector<unsigned> indices;
+ if (value.isEmpty())
+ return indices;
+
+ const Vector<Element*>& items = m_data.listItems(this);
+ if (items.isEmpty())
+ return indices;
+
+ Vector<String> indexStrings;
+ value.split(';', indexStrings);
+
+ unsigned optionIndex = 0;
+
+ Vector<String>::const_iterator end = indexStrings.end();
+ for (Vector<String>::const_iterator it = indexStrings.begin(); it != end; ++it) {
+ String value = *it;
+
+ for (unsigned i = 0; i < items.size(); ++i) {
+ if (!isOptionElement(items[i]))
+ continue;
+
+ ++optionIndex;
+ if (OptionElement* optionElement = toOptionElement(items[i])) {
+ if (optionElement->value() == value) {
+ indices.append(optionIndex);
+ break;
+ }
+ }
+ }
+ }
+
+ return indices;
+}
+
+String WMLSelectElement::optionIndicesToValueString() const
+{
+ String valueString;
+ if (m_defaultOptionIndices.isEmpty())
+ return valueString;
+
+ const Vector<Element*>& items = m_data.listItems(this);
+ if (items.isEmpty())
+ return valueString;
+
+ Vector<unsigned>::const_iterator end = m_defaultOptionIndices.end();
+ for (Vector<unsigned>::const_iterator it = m_defaultOptionIndices.begin(); it != end; ++it) {
+ unsigned optionIndex = (*it);
+ if (optionIndex < 1 || optionIndex > items.size())
+ continue;
+
+ int listIndex = optionToListIndex((*it) - 1);
+ ASSERT(listIndex >= 0);
+ ASSERT(listIndex < (int) items.size());
+
+ if (OptionElement* optionElement = toOptionElement(items[listIndex])) {
+ if (!valueString.isEmpty())
+ valueString += ";";
+
+ valueString += optionElement->value();
+ }
+ }
+
+ return valueString;
+}
+
+String WMLSelectElement::optionIndicesToString() const
+{
+ String valueString;
+ if (m_defaultOptionIndices.isEmpty())
+ return valueString;
+
+ Vector<unsigned>::const_iterator end = m_defaultOptionIndices.end();
+ for (Vector<unsigned>::const_iterator it = m_defaultOptionIndices.begin(); it != end; ++it) {
+ if (!valueString.isEmpty())
+ valueString += ";";
+
+ valueString += String::number(*it);
+ }
+
+ return valueString;
+}
+
+String WMLSelectElement::name() const
+{
+ return parseValueForbiddingVariableReferences(getAttribute(HTMLNames::nameAttr));
+}
+
+String WMLSelectElement::value() const
+{
+ return parseValueSubstitutingVariableReferences(getAttribute(HTMLNames::valueAttr));
+}
+
+String WMLSelectElement::iname() const
+{
+ return parseValueForbiddingVariableReferences(getAttribute(inameAttr));
+}
+
+String WMLSelectElement::ivalue() const
+{
+ return parseValueSubstitutingVariableReferences(getAttribute(ivalueAttr));
+}
+
}
#endif
diff --git a/WebCore/wml/WMLSelectElement.h b/WebCore/wml/WMLSelectElement.h
index 8d3e0f9..412a950 100644
--- a/WebCore/wml/WMLSelectElement.h
+++ b/WebCore/wml/WMLSelectElement.h
@@ -32,6 +32,7 @@ public:
WMLSelectElement(const QualifiedName&, Document*);
virtual ~WMLSelectElement();
+ virtual const AtomicString& formControlName() const;
virtual const AtomicString& formControlType() const;
virtual bool isKeyboardFocusable(KeyboardEvent*) const;
@@ -47,7 +48,8 @@ public:
virtual bool canStartSelection() const { return false; }
virtual int selectedIndex() const;
- virtual void setSelectedIndex(int index, bool deselect = true, bool fireOnChange = false);
+ virtual void setSelectedIndex(int index, bool deselect = true);
+ virtual void setSelectedIndexByUser(int index, bool deselect = true, bool fireOnChangeNow = false);
virtual int size() const { return m_data.size(); }
virtual bool multiple() const { return m_data.multiple(); }
@@ -81,11 +83,28 @@ public:
void accessKeySetSelectedIndex(int);
void setRecalcListItems();
void scrollToSelection();
+ void selectInitialOptions();
private:
virtual void insertedIntoTree(bool);
+ void calculateDefaultOptionIndices();
+ void selectDefaultOptions();
+ void initializeVariables();
+ void updateVariables();
+
+ Vector<unsigned> parseIndexValueString(const String&) const;
+ Vector<unsigned> valueStringToOptionIndices(const String&) const;
+ String optionIndicesToValueString() const;
+ String optionIndicesToString() const;
+
+ String name() const;
+ String value() const;
+ String iname() const;
+ String ivalue() const;
+
SelectElementData m_data;
+ Vector<unsigned> m_defaultOptionIndices;
};
}
diff --git a/WebCore/wml/WMLSetvarElement.cpp b/WebCore/wml/WMLSetvarElement.cpp
index da9a1f4..5e10ca8 100644
--- a/WebCore/wml/WMLSetvarElement.cpp
+++ b/WebCore/wml/WMLSetvarElement.cpp
@@ -43,16 +43,11 @@ WMLSetvarElement::~WMLSetvarElement()
void WMLSetvarElement::parseMappedAttribute(MappedAttribute* attr)
{
if (attr->name() == HTMLNames::nameAttr) {
- String name = parseValueSubstitutingVariableReferences(attr->value(), WMLErrorInvalidVariableName);
- if (!isValidVariableName(name)) {
+ if (!isValidVariableName(parseValueSubstitutingVariableReferences(attr->value(), WMLErrorInvalidVariableName))) {
reportWMLError(document(), WMLErrorInvalidVariableName);
return;
}
-
- m_name = name;
- } else if (attr->name() == HTMLNames::valueAttr)
- m_value = parseValueSubstitutingVariableReferences(attr->value());
- else
+ } else
WMLElement::parseMappedAttribute(attr);
}
@@ -61,8 +56,6 @@ void WMLSetvarElement::insertedIntoDocument()
WMLElement::insertedIntoDocument();
Node* parent = parentNode();
- ASSERT(parent);
-
if (!parent || !parent->isWMLElement())
return;
@@ -70,6 +63,27 @@ void WMLSetvarElement::insertedIntoDocument()
static_cast<WMLTaskElement*>(parent)->registerVariableSetter(this);
}
+void WMLSetvarElement::removedFromDocument()
+{
+ Node* parent = parentNode();
+ if (parent && parent->isWMLElement()) {
+ if (static_cast<WMLElement*>(parent)->isWMLTaskElement())
+ static_cast<WMLTaskElement*>(parent)->deregisterVariableSetter(this);
+ }
+
+ WMLElement::removedFromDocument();
+}
+
+String WMLSetvarElement::name() const
+{
+ return parseValueSubstitutingVariableReferences(getAttribute(HTMLNames::nameAttr), WMLErrorInvalidVariableName);
+}
+
+String WMLSetvarElement::value() const
+{
+ return parseValueSubstitutingVariableReferences(getAttribute(HTMLNames::valueAttr));
+}
+
}
#endif
diff --git a/WebCore/wml/WMLSetvarElement.h b/WebCore/wml/WMLSetvarElement.h
index ebedbc8..0171b95 100644
--- a/WebCore/wml/WMLSetvarElement.h
+++ b/WebCore/wml/WMLSetvarElement.h
@@ -33,13 +33,10 @@ public:
virtual void parseMappedAttribute(MappedAttribute*);
virtual void insertedIntoDocument();
+ virtual void removedFromDocument();
- String name() const { return m_name; }
- String value() const { return m_value; }
-
-private:
- String m_name;
- String m_value;
+ String name() const;
+ String value() const;
};
}
diff --git a/WebCore/wml/WMLTaskElement.cpp b/WebCore/wml/WMLTaskElement.cpp
index 1add1da..d49a03e 100644
--- a/WebCore/wml/WMLTaskElement.cpp
+++ b/WebCore/wml/WMLTaskElement.cpp
@@ -48,8 +48,6 @@ void WMLTaskElement::insertedIntoDocument()
WMLElement::insertedIntoDocument();
Node* parent = parentNode();
- ASSERT(parent);
-
if (!parent || !parent->isWMLElement())
return;
@@ -61,10 +59,32 @@ void WMLTaskElement::insertedIntoDocument()
static_cast<WMLOnEventElement*>(parent)->registerTask(this);
}
+void WMLTaskElement::removedFromDocument()
+{
+ Node* parent = parentNode();
+ if (parent && parent->isWMLElement()) {
+ if (parent->hasTagName(anchorTag))
+ static_cast<WMLAnchorElement*>(parent)->deregisterTask(this);
+ else if (parent->hasTagName(doTag))
+ static_cast<WMLDoElement*>(parent)->deregisterTask(this);
+ else if (parent->hasTagName(oneventTag))
+ static_cast<WMLOnEventElement*>(parent)->deregisterTask(this);
+ }
+
+ WMLElement::removedFromDocument();
+}
+
void WMLTaskElement::registerVariableSetter(WMLSetvarElement* element)
{
- ASSERT(element);
- m_variableSetterElements.add(element);
+ ASSERT(m_variableSetterElements.find(element) == WTF::notFound);
+ m_variableSetterElements.append(element);
+}
+
+void WMLTaskElement::deregisterVariableSetter(WMLSetvarElement* element)
+{
+ size_t position = m_variableSetterElements.find(element);
+ ASSERT(position != WTF::notFound);
+ m_variableSetterElements.remove(position);
}
void WMLTaskElement::storeVariableState(WMLPageState* pageState)
@@ -73,19 +93,23 @@ void WMLTaskElement::storeVariableState(WMLPageState* pageState)
return;
WMLVariableMap variables;
- HashSet<WMLSetvarElement*>::iterator it = m_variableSetterElements.begin();
- HashSet<WMLSetvarElement*>::iterator end = m_variableSetterElements.end();
+ Vector<WMLSetvarElement*>::iterator it = m_variableSetterElements.begin();
+ Vector<WMLSetvarElement*>::iterator end = m_variableSetterElements.end();
for (; it != end; ++it) {
WMLSetvarElement* setterElement = (*it);
- if (setterElement->name().isEmpty())
+
+ String name = setterElement->name();
+ if (name.isEmpty())
continue;
- variables.set(setterElement->name(), setterElement->value());
- }
+ String value = setterElement->value();
+ variables.set(name, value);
- if (variables.isEmpty())
- return;
+ // The next setvar element may depend on this variable value. It's safe to store the current
+ // name value pair in the page state, as the whole page state is replaced soon by this new map
+ pageState->storeVariable(name, value);
+ }
pageState->storeVariables(variables);
}
diff --git a/WebCore/wml/WMLTaskElement.h b/WebCore/wml/WMLTaskElement.h
index f28571a..b5dab8c 100644
--- a/WebCore/wml/WMLTaskElement.h
+++ b/WebCore/wml/WMLTaskElement.h
@@ -24,7 +24,7 @@
#if ENABLE(WML)
#include "WMLElement.h"
-#include <wtf/HashSet.h>
+#include <wtf/Vector.h>
namespace WebCore {
@@ -39,15 +39,17 @@ public:
virtual bool isWMLTaskElement() const { return true; }
virtual void insertedIntoDocument();
+ virtual void removedFromDocument();
virtual void executeTask(Event*) = 0;
void registerVariableSetter(WMLSetvarElement*);
+ void deregisterVariableSetter(WMLSetvarElement*);
protected:
void storeVariableState(WMLPageState*);
private:
- HashSet<WMLSetvarElement*> m_variableSetterElements;
+ Vector<WMLSetvarElement*> m_variableSetterElements;
};
}
diff --git a/WebCore/wml/WMLTimerElement.cpp b/WebCore/wml/WMLTimerElement.cpp
index 00c7036..c6476f7 100644
--- a/WebCore/wml/WMLTimerElement.cpp
+++ b/WebCore/wml/WMLTimerElement.cpp
@@ -46,8 +46,6 @@ void WMLTimerElement::parseMappedAttribute(MappedAttribute* attr)
{
if (attr->name() == HTMLNames::nameAttr)
m_name = parseValueForbiddingVariableReferences(attr->value());
- else if (attr->name() == HTMLNames::valueAttr)
- m_value = parseValueSubstitutingVariableReferences(attr->value());
else
WMLElement::parseMappedAttribute(attr);
}
@@ -57,12 +55,10 @@ void WMLTimerElement::insertedIntoDocument()
WMLElement::insertedIntoDocument();
// If the value of timeout is not a positive integer, ignore it
- if (m_value.toInt() <= 0)
+ if (value().toInt() <= 0)
return;
Node* parent = parentNode();
- ASSERT(parent);
-
if (!parent || !parent->isWMLElement())
return;
@@ -72,6 +68,17 @@ void WMLTimerElement::insertedIntoDocument()
}
}
+void WMLTimerElement::removedFromDocument()
+{
+ Node* parent = parentNode();
+ if (parent && parent->isWMLElement() && parent->hasTagName(cardTag)) {
+ m_card->setIntrinsicEventTimer(0);
+ m_card = 0;
+ }
+
+ WMLElement::removedFromDocument();
+}
+
void WMLTimerElement::timerFired(Timer<WMLTimerElement>*)
{
if (!m_card)
@@ -81,10 +88,12 @@ void WMLTimerElement::timerFired(Timer<WMLTimerElement>*)
if (!pageState)
return;
+ String value = this->value();
+
// When the timer expires, set the name varialbe of timer to '0'
if (!m_name.isEmpty()) {
- m_value = "0";
- pageState->storeVariable(m_name, m_value);
+ value = "0";
+ pageState->storeVariable(m_name, value);
}
WMLIntrinsicEventType eventType = WMLIntrinsicEventOnTimer;
@@ -114,7 +123,7 @@ void WMLTimerElement::start(int interval)
}
if (interval <= 0)
- interval = m_value.toInt();
+ interval = value().toInt();
if (interval > 0)
m_timer.startOneShot(interval / 10.0f);
@@ -137,6 +146,11 @@ void WMLTimerElement::storeIntervalToPageState()
pageState->storeVariable(m_name, String::number(interval));
}
+String WMLTimerElement::value() const
+{
+ return parseValueSubstitutingVariableReferences(getAttribute(HTMLNames::valueAttr));
+}
+
}
#endif
diff --git a/WebCore/wml/WMLTimerElement.h b/WebCore/wml/WMLTimerElement.h
index eecacf3..8402027 100644
--- a/WebCore/wml/WMLTimerElement.h
+++ b/WebCore/wml/WMLTimerElement.h
@@ -35,6 +35,7 @@ public:
virtual void parseMappedAttribute(MappedAttribute*);
virtual void insertedIntoDocument();
+ virtual void removedFromDocument();
void timerFired(Timer<WMLTimerElement>*);
@@ -42,10 +43,11 @@ public:
void stop();
void storeIntervalToPageState();
+ String value() const;
+
private:
WMLCardElement* m_card;
String m_name;
- String m_value;
Timer<WMLTimerElement> m_timer;
};
diff --git a/WebCore/wml/WMLVariables.cpp b/WebCore/wml/WMLVariables.cpp
index f206234..f48aa1c 100644
--- a/WebCore/wml/WMLVariables.cpp
+++ b/WebCore/wml/WMLVariables.cpp
@@ -117,8 +117,6 @@ bool containsVariableReference(const String& text, bool& isValid)
if (!isValidVariableNameCharacter(text[nameEndPosition]))
break;
}
-
- --nameEndPosition;
}
if (nameEndPosition < nameStartPosition) {
@@ -127,7 +125,7 @@ bool containsVariableReference(const String& text, bool& isValid)
break;
}
- // Eventually split of conversion string, and check it's syntax afterwards
+ // Eventually split of conversion string, and check its syntax afterwards
String conversionString;
String variableName = text.substring(nameStartPosition, nameEndPosition - nameStartPosition);