summaryrefslogtreecommitdiffstats
path: root/WebCore/xml
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/xml')
-rw-r--r--WebCore/xml/DOMParser.idl2
-rw-r--r--WebCore/xml/XMLHttpRequest.cpp568
-rw-r--r--WebCore/xml/XMLHttpRequest.h81
-rw-r--r--WebCore/xml/XMLHttpRequest.idl2
-rw-r--r--WebCore/xml/XMLHttpRequestException.idl1
-rw-r--r--WebCore/xml/XMLHttpRequestProgressEvent.h2
-rw-r--r--WebCore/xml/XMLHttpRequestProgressEvent.idl1
-rw-r--r--WebCore/xml/XMLHttpRequestUpload.cpp94
-rw-r--r--WebCore/xml/XMLHttpRequestUpload.h48
-rw-r--r--WebCore/xml/XMLHttpRequestUpload.idl2
-rw-r--r--WebCore/xml/XMLSerializer.idl2
-rw-r--r--WebCore/xml/XPathEvaluator.idl2
-rw-r--r--WebCore/xml/XPathException.idl1
-rw-r--r--WebCore/xml/XPathExpression.idl3
-rw-r--r--WebCore/xml/XPathExpressionNode.h2
-rw-r--r--WebCore/xml/XPathFunctions.cpp9
-rw-r--r--WebCore/xml/XPathNSResolver.idl2
-rw-r--r--WebCore/xml/XPathNamespace.cpp10
-rw-r--r--WebCore/xml/XPathNamespace.h13
-rw-r--r--WebCore/xml/XPathNodeSet.h2
-rw-r--r--WebCore/xml/XPathResult.idl2
-rw-r--r--WebCore/xml/XPathStep.cpp15
-rw-r--r--WebCore/xml/XPathStep.h2
-rw-r--r--WebCore/xml/XSLImportRule.cpp14
-rw-r--r--WebCore/xml/XSLImportRule.h2
-rw-r--r--WebCore/xml/XSLStyleSheet.h42
-rw-r--r--WebCore/xml/XSLStyleSheetLibxslt.cpp (renamed from WebCore/xml/XSLStyleSheet.cpp)43
-rw-r--r--WebCore/xml/XSLStyleSheetQt.cpp103
-rw-r--r--WebCore/xml/XSLTProcessor.cpp319
-rw-r--r--WebCore/xml/XSLTProcessor.h10
-rw-r--r--WebCore/xml/XSLTProcessor.idl3
-rw-r--r--WebCore/xml/XSLTProcessorLibxslt.cpp336
-rw-r--r--WebCore/xml/XSLTProcessorQt.cpp181
-rw-r--r--WebCore/xml/xmlnsattrs.in4
34 files changed, 921 insertions, 1002 deletions
diff --git a/WebCore/xml/DOMParser.idl b/WebCore/xml/DOMParser.idl
index 9caaa21..90a8b52 100644
--- a/WebCore/xml/DOMParser.idl
+++ b/WebCore/xml/DOMParser.idl
@@ -18,7 +18,7 @@
*/
module xpath {
- interface [GenerateConstructor, CanBeConstructed] DOMParser {
+ interface [CanBeConstructed] DOMParser {
Document parseFromString(in DOMString str, in DOMString contentType);
};
}
diff --git a/WebCore/xml/XMLHttpRequest.cpp b/WebCore/xml/XMLHttpRequest.cpp
index 5e20252..32818df 100644
--- a/WebCore/xml/XMLHttpRequest.cpp
+++ b/WebCore/xml/XMLHttpRequest.cpp
@@ -22,18 +22,18 @@
#include "config.h"
#include "XMLHttpRequest.h"
+#include "Blob.h"
#include "Cache.h"
#include "CString.h"
#include "CrossOriginAccessControl.h"
-#include "CrossOriginPreflightResultCache.h"
#include "DOMImplementation.h"
#include "Document.h"
#include "Event.h"
#include "EventException.h"
#include "EventListener.h"
#include "EventNames.h"
-#include "File.h"
#include "HTTPParsers.h"
+#include "InspectorTimelineAgent.h"
#include "ResourceError.h"
#include "ResourceRequest.h"
#include "SecurityOrigin.h"
@@ -45,14 +45,21 @@
#include "XMLHttpRequestUpload.h"
#include "markup.h"
#include <wtf/StdLibExtras.h>
+#include <wtf/RefCountedLeakCounter.h>
#if USE(JSC)
+#include "JSDOMBinding.h"
#include "JSDOMWindow.h"
+#include <runtime/Protect.h>
#endif
namespace WebCore {
-struct XMLHttpRequestStaticData {
+#ifndef NDEBUG
+static WTF::RefCountedLeakCounter xmlHttpRequestCounter("XMLHttpRequest");
+#endif
+
+struct XMLHttpRequestStaticData : Noncopyable {
XMLHttpRequestStaticData();
String m_proxyHeaderPrefix;
String m_secHeaderPrefix;
@@ -93,25 +100,25 @@ static bool isValidToken(const String& name)
unsigned length = name.length();
for (unsigned i = 0; i < length; i++) {
UChar c = name[i];
-
+
if (c >= 127 || c <= 32)
return false;
-
+
if (c == '(' || c == ')' || c == '<' || c == '>' || c == '@' ||
c == ',' || c == ';' || c == ':' || c == '\\' || c == '\"' ||
c == '/' || c == '[' || c == ']' || c == '?' || c == '=' ||
c == '{' || c == '}')
return false;
}
-
+
return true;
}
-
+
static bool isValidHeaderValue(const String& name)
{
- // FIXME: This should really match name against
+ // FIXME: This should really match name against
// field-value in section 4.2 of RFC 2616.
-
+
return !name.contains('\r') && !name.contains('\n');
}
@@ -143,15 +150,18 @@ XMLHttpRequest::XMLHttpRequest(ScriptExecutionContext* context)
, m_responseText("")
, m_createdDocument(false)
, m_error(false)
+ , m_uploadEventsAllowed(true)
, m_uploadComplete(false)
, m_sameOriginRequest(true)
- , m_inPreflight(false)
, m_didTellLoaderAboutRequest(false)
, m_receivedLength(0)
, m_lastSendLineNumber(0)
, m_exceptionCode(0)
{
initializeXMLHttpRequestStaticData();
+#ifndef NDEBUG
+ xmlHttpRequestCounter.increment();
+#endif
}
XMLHttpRequest::~XMLHttpRequest()
@@ -162,6 +172,10 @@ XMLHttpRequest::~XMLHttpRequest()
}
if (m_upload)
m_upload->disconnectXMLHttpRequest();
+
+#ifndef NDEBUG
+ xmlHttpRequestCounter.decrement();
+#endif
}
Document* XMLHttpRequest::document() const
@@ -207,7 +221,7 @@ Document* XMLHttpRequest::responseXML() const
m_responseXML->write(String(m_responseText));
m_responseXML->finishParsing();
m_responseXML->close();
-
+
if (!m_responseXML->wellFormed())
m_responseXML = 0;
}
@@ -224,56 +238,6 @@ XMLHttpRequestUpload* XMLHttpRequest::upload()
return m_upload.get();
}
-void XMLHttpRequest::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> eventListener, bool)
-{
- EventListenersMap::iterator iter = m_eventListeners.find(eventType);
- if (iter == m_eventListeners.end()) {
- ListenerVector listeners;
- listeners.append(eventListener);
- m_eventListeners.add(eventType, listeners);
- } else {
- ListenerVector& listeners = iter->second;
- for (ListenerVector::iterator listenerIter = listeners.begin(); listenerIter != listeners.end(); ++listenerIter)
- if (*listenerIter == eventListener)
- return;
-
- listeners.append(eventListener);
- m_eventListeners.add(eventType, listeners);
- }
-}
-
-void XMLHttpRequest::removeEventListener(const AtomicString& eventType, EventListener* eventListener, bool)
-{
- EventListenersMap::iterator iter = m_eventListeners.find(eventType);
- if (iter == m_eventListeners.end())
- return;
-
- ListenerVector& listeners = iter->second;
- for (ListenerVector::const_iterator listenerIter = listeners.begin(); listenerIter != listeners.end(); ++listenerIter)
- if (*listenerIter == eventListener) {
- listeners.remove(listenerIter - listeners.begin());
- return;
- }
-}
-
-bool XMLHttpRequest::dispatchEvent(PassRefPtr<Event> evt, ExceptionCode& ec)
-{
- // FIXME: check for other error conditions enumerated in the spec.
- if (!evt || evt->type().isEmpty()) {
- ec = EventException::UNSPECIFIED_EVENT_TYPE_ERR;
- return true;
- }
-
- ListenerVector listenersCopy = m_eventListeners.get(evt->type());
- for (ListenerVector::const_iterator listenerIter = listenersCopy.begin(); listenerIter != listenersCopy.end(); ++listenerIter) {
- evt->setTarget(this);
- evt->setCurrentTarget(this);
- listenerIter->get()->handleEvent(evt.get(), false);
- }
-
- return !evt->defaultPrevented();
-}
-
void XMLHttpRequest::changeState(State newState)
{
if (m_state != newState) {
@@ -287,10 +251,35 @@ void XMLHttpRequest::callReadyStateChangeListener()
if (!scriptExecutionContext())
return;
- dispatchReadyStateChangeEvent();
+#if ENABLE(INSPECTOR)
+ InspectorTimelineAgent* timelineAgent = InspectorTimelineAgent::retrieve(scriptExecutionContext());
+ bool callTimelineAgentOnReadyStateChange = timelineAgent && hasEventListeners(eventNames().readystatechangeEvent);
+ if (callTimelineAgentOnReadyStateChange)
+ timelineAgent->willChangeXHRReadyState(m_url.string(), m_state);
+#endif
+
+ dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().readystatechangeEvent));
+
+#if ENABLE(INSPECTOR)
+ if (callTimelineAgentOnReadyStateChange && (timelineAgent = InspectorTimelineAgent::retrieve(scriptExecutionContext())))
+ timelineAgent->didChangeXHRReadyState();
+#endif
+
+ if (m_state == DONE && !m_error) {
+#if ENABLE(INSPECTOR)
+ timelineAgent = InspectorTimelineAgent::retrieve(scriptExecutionContext());
+ bool callTimelineAgentOnLoad = timelineAgent && hasEventListeners(eventNames().loadEvent);
+ if (callTimelineAgentOnLoad)
+ timelineAgent->willLoadXHR(m_url.string());
+#endif
+
+ dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().loadEvent));
- if (m_state == DONE && !m_error)
- dispatchLoadEvent();
+#if ENABLE(INSPECTOR)
+ if (callTimelineAgentOnLoad && (timelineAgent = InspectorTimelineAgent::retrieve(scriptExecutionContext())))
+ timelineAgent->didLoadXHR();
+#endif
+ }
}
void XMLHttpRequest::setWithCredentials(bool value, ExceptionCode& ec)
@@ -322,10 +311,10 @@ void XMLHttpRequest::open(const String& method, const KURL& url, bool async, Exc
ec = SYNTAX_ERR;
return;
}
-
+
// Method names are case sensitive. But since Firefox uppercases method names it knows, we'll do the same.
String methodUpper(method.upper());
-
+
if (methodUpper == "TRACE" || methodUpper == "TRACK" || methodUpper == "CONNECT") {
ec = SECURITY_ERR;
return;
@@ -335,7 +324,7 @@ void XMLHttpRequest::open(const String& method, const KURL& url, bool async, Exc
if (methodUpper == "COPY" || methodUpper == "DELETE" || methodUpper == "GET" || methodUpper == "HEAD"
|| methodUpper == "INDEX" || methodUpper == "LOCK" || methodUpper == "M-POST" || methodUpper == "MKCOL" || methodUpper == "MOVE"
- || methodUpper == "OPTIONS" || methodUpper == "POST" || methodUpper == "PROPFIND" || methodUpper == "PROPPATCH" || methodUpper == "PUT"
+ || methodUpper == "OPTIONS" || methodUpper == "POST" || methodUpper == "PROPFIND" || methodUpper == "PROPPATCH" || methodUpper == "PUT"
|| methodUpper == "UNLOCK")
m_method = methodUpper;
else
@@ -357,7 +346,7 @@ void XMLHttpRequest::open(const String& method, const KURL& url, bool async, con
{
KURL urlWithCredentials(url);
urlWithCredentials.setUser(user);
-
+
open(method, urlWithCredentials, async, ec);
}
@@ -366,7 +355,7 @@ void XMLHttpRequest::open(const String& method, const KURL& url, bool async, con
KURL urlWithCredentials(url);
urlWithCredentials.setUser(user);
urlWithCredentials.setPass(password);
-
+
open(method, urlWithCredentials, async, ec);
}
@@ -446,7 +435,7 @@ void XMLHttpRequest::send(const String& body, ExceptionCode& ec)
createRequest(ec);
}
-void XMLHttpRequest::send(File* body, ExceptionCode& ec)
+void XMLHttpRequest::send(Blob* body, ExceptionCode& ec)
{
if (!initSend(ec))
return;
@@ -463,34 +452,23 @@ void XMLHttpRequest::send(File* body, ExceptionCode& ec)
void XMLHttpRequest::createRequest(ExceptionCode& ec)
{
- // Upload event listeners should be disallowed for simple cross-origin requests, because POSTing to an URL that does not
- // permit cross origin requests should look exactly like POSTing to an URL that does not respond at all. If a listener exists
- // when creating the request, it will force preflight.
+ // The presence of upload event listeners forces us to use preflighting because POSTing to an URL that does not
+ // permit cross origin requests should look exactly like POSTing to an URL that does not respond at all.
// Also, only async requests support upload progress events.
- m_uploadEventsAllowed = false;
+ bool forcePreflight = false;
if (m_async) {
- dispatchLoadStartEvent();
+ dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().loadstartEvent));
if (m_requestEntityBody && m_upload) {
- m_uploadEventsAllowed = m_upload->hasListeners();
- m_upload->dispatchLoadStartEvent();
+ forcePreflight = m_upload->hasEventListeners();
+ m_upload->dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().loadstartEvent));
}
}
m_sameOriginRequest = scriptExecutionContext()->securityOrigin()->canRequest(m_url);
- if (!m_sameOriginRequest) {
- makeCrossOriginAccessRequest(ec);
- return;
- }
-
- m_uploadEventsAllowed = true;
-
- makeSameOriginRequest(ec);
-}
-
-void XMLHttpRequest::makeSameOriginRequest(ExceptionCode& ec)
-{
- ASSERT(m_sameOriginRequest);
+ // We also remember whether upload events should be allowed for this request in case the upload listeners are
+ // added after the request is started.
+ m_uploadEventsAllowed = !isSimpleCrossOriginAccessRequest(m_method, m_requestHeaders);
ResourceRequest request(m_url);
request.setHTTPMethod(m_method);
@@ -504,202 +482,49 @@ void XMLHttpRequest::makeSameOriginRequest(ExceptionCode& ec)
if (m_requestHeaders.size() > 0)
request.addHTTPHeaderFields(m_requestHeaders);
- if (m_async)
- loadRequestAsynchronously(request);
- else
- loadRequestSynchronously(request, ec);
-}
-
-void XMLHttpRequest::makeCrossOriginAccessRequest(ExceptionCode& ec)
-{
- ASSERT(!m_sameOriginRequest);
+ ThreadableLoaderOptions options;
+ options.sendLoadCallbacks = true;
+ options.sniffContent = false;
+ options.forcePreflight = forcePreflight;
+ options.allowCredentials = m_sameOriginRequest || m_includeCredentials;
+ options.crossOriginRequestPolicy = UseAccessControl;
- if (!m_uploadEventsAllowed && isSimpleCrossOriginAccessRequest(m_method, m_requestHeaders))
- makeSimpleCrossOriginAccessRequest(ec);
- else
- makeCrossOriginAccessRequestWithPreflight(ec);
-}
-
-void XMLHttpRequest::makeSimpleCrossOriginAccessRequest(ExceptionCode& ec)
-{
- ASSERT(isSimpleCrossOriginAccessRequest(m_method, m_requestHeaders));
-
- // Cross-origin requests are only defined for HTTP. We would catch this when checking response headers later, but there is no reason to send a request that's guaranteed to be denied.
- if (!m_url.protocolInHTTPFamily()) {
- ec = XMLHttpRequestException::NETWORK_ERR;
- networkError();
- return;
- }
-
- KURL url = m_url;
- url.setUser(String());
- url.setPass(String());
-
- ResourceRequest request(url);
- request.setHTTPMethod(m_method);
- request.setAllowHTTPCookies(m_includeCredentials);
- request.setHTTPOrigin(scriptExecutionContext()->securityOrigin()->toString());
-
- if (m_requestHeaders.size() > 0)
- request.addHTTPHeaderFields(m_requestHeaders);
-
- if (m_requestEntityBody) {
- ASSERT(m_method != "GET");
- ASSERT(m_method != "HEAD");
- request.setHTTPBody(m_requestEntityBody.release());
- }
-
- if (m_async)
- loadRequestAsynchronously(request);
- else
- loadRequestSynchronously(request, ec);
-}
+ m_exceptionCode = 0;
+ m_error = false;
-void XMLHttpRequest::makeCrossOriginAccessRequestWithPreflight(ExceptionCode& ec)
-{
- String origin = scriptExecutionContext()->securityOrigin()->toString();
- KURL url = m_url;
- url.setUser(String());
- url.setPass(String());
-
- if (!CrossOriginPreflightResultCache::shared().canSkipPreflight(origin, url, m_includeCredentials, m_method, m_requestHeaders)) {
- m_inPreflight = true;
- ResourceRequest preflightRequest(url);
- preflightRequest.setHTTPMethod("OPTIONS");
- preflightRequest.setHTTPHeaderField("Origin", origin);
- preflightRequest.setHTTPHeaderField("Access-Control-Request-Method", m_method);
-
- if (m_requestHeaders.size() > 0) {
- Vector<UChar> headerBuffer;
- HTTPHeaderMap::const_iterator it = m_requestHeaders.begin();
- append(headerBuffer, it->first);
- ++it;
-
- HTTPHeaderMap::const_iterator end = m_requestHeaders.end();
- for (; it != end; ++it) {
- headerBuffer.append(',');
- headerBuffer.append(' ');
- append(headerBuffer, it->first);
+ if (m_async) {
+ if (m_upload)
+ request.setReportUploadProgress(true);
+
+ // ThreadableLoader::create can return null here, for example if we're no longer attached to a page.
+ // This is true while running onunload handlers.
+ // FIXME: Maybe we need to be able to send XMLHttpRequests from onunload, <http://bugs.webkit.org/show_bug.cgi?id=10904>.
+ // FIXME: Maybe create() can return null for other reasons too?
+ m_loader = ThreadableLoader::create(scriptExecutionContext(), this, request, options);
+ if (m_loader) {
+ // Neither this object nor the JavaScript wrapper should be deleted while
+ // a request is in progress because we need to keep the listeners alive,
+ // and they are referenced by the JavaScript wrapper.
+ setPendingActivity(this);
+
+ // For now we should only balance the nonCached request count for main-thread XHRs and not
+ // Worker XHRs, as the Cache is not thread-safe.
+ // This will become irrelevant after https://bugs.webkit.org/show_bug.cgi?id=27165 is resolved.
+ if (!scriptExecutionContext()->isWorkerContext()) {
+ ASSERT(isMainThread());
+ ASSERT(!m_didTellLoaderAboutRequest);
+ cache()->loader()->nonCacheRequestInFlight(m_url);
+ m_didTellLoaderAboutRequest = true;
}
-
- preflightRequest.setHTTPHeaderField("Access-Control-Request-Headers", String::adopt(headerBuffer));
- preflightRequest.addHTTPHeaderFields(m_requestHeaders);
}
+ } else
+ ThreadableLoader::loadResourceSynchronously(scriptExecutionContext(), request, *this, options);
- if (m_async) {
- m_uploadEventsAllowed = true;
- loadRequestAsynchronously(preflightRequest);
- return;
- }
-
- loadRequestSynchronously(preflightRequest, ec);
- m_inPreflight = false;
-
- if (ec)
- return;
- }
-
- // Send the actual request.
- ResourceRequest request(url);
- request.setHTTPMethod(m_method);
- request.setAllowHTTPCookies(m_includeCredentials);
- request.setHTTPHeaderField("Origin", origin);
-
- if (m_requestHeaders.size() > 0)
- request.addHTTPHeaderFields(m_requestHeaders);
-
- if (m_requestEntityBody) {
- ASSERT(m_method != "GET");
- ASSERT(m_method != "HEAD");
- request.setHTTPBody(m_requestEntityBody.release());
- }
-
- if (m_async) {
- m_uploadEventsAllowed = true;
- loadRequestAsynchronously(request);
- return;
- }
-
- loadRequestSynchronously(request, ec);
-}
-
-void XMLHttpRequest::handleAsynchronousPreflightResult()
-{
- ASSERT(m_inPreflight);
- ASSERT(m_async);
-
- m_inPreflight = false;
-
- KURL url = m_url;
- url.setUser(String());
- url.setPass(String());
-
- ResourceRequest request(url);
- request.setHTTPMethod(m_method);
- request.setAllowHTTPCookies(m_includeCredentials);
- request.setHTTPOrigin(scriptExecutionContext()->securityOrigin()->toString());
-
- if (m_requestHeaders.size() > 0)
- request.addHTTPHeaderFields(m_requestHeaders);
-
- if (m_requestEntityBody) {
- ASSERT(m_method != "GET");
- ASSERT(m_method != "HEAD");
- request.setHTTPBody(m_requestEntityBody.release());
- }
-
- m_uploadEventsAllowed = true;
- loadRequestAsynchronously(request);
-}
-
-void XMLHttpRequest::loadRequestSynchronously(ResourceRequest& request, ExceptionCode& ec)
-{
- ASSERT(!m_async);
-
- m_loader = 0;
- m_exceptionCode = 0;
- StoredCredentials storedCredentials = (m_sameOriginRequest || m_includeCredentials) ? AllowStoredCredentials : DoNotAllowStoredCredentials;
-
- ThreadableLoader::loadResourceSynchronously(scriptExecutionContext(), request, *this, storedCredentials);
if (!m_exceptionCode && m_error)
m_exceptionCode = XMLHttpRequestException::NETWORK_ERR;
ec = m_exceptionCode;
}
-void XMLHttpRequest::loadRequestAsynchronously(ResourceRequest& request)
-{
- ASSERT(m_async);
- m_exceptionCode = 0;
- // SubresourceLoader::create can return null here, for example if we're no longer attached to a page.
- // This is true while running onunload handlers.
- // FIXME: We need to be able to send XMLHttpRequests from onunload, <http://bugs.webkit.org/show_bug.cgi?id=10904>.
- // FIXME: Maybe create can return null for other reasons too?
- LoadCallbacks callbacks = m_inPreflight ? DoNotSendLoadCallbacks : SendLoadCallbacks;
- StoredCredentials storedCredentials = (m_sameOriginRequest || m_includeCredentials) ? AllowStoredCredentials : DoNotAllowStoredCredentials;
-
- if (m_upload)
- request.setReportUploadProgress(true);
-
- m_loader = ThreadableLoader::create(scriptExecutionContext(), this, request, callbacks, DoNotSniffContent, storedCredentials, DenyCrossOriginRedirect);
-
- if (m_loader) {
- // Neither this object nor the JavaScript wrapper should be deleted while
- // a request is in progress because we need to keep the listeners alive,
- // and they are referenced by the JavaScript wrapper.
- setPendingActivity(this);
-
- // For now we should only balance the nonCached request count for main-thread XHRs and not
- // Worker XHRs, as the Cache is not thread-safe.
- // This will become irrelevant after https://bugs.webkit.org/show_bug.cgi?id=27165 is resolved.
- if (!scriptExecutionContext()->isWorkerContext()) {
- ASSERT(isMainThread());
- ASSERT(!m_didTellLoaderAboutRequest);
- cache()->loader()->nonCacheRequestInFlight(m_url);
- m_didTellLoaderAboutRequest = true;
- }
- }
-}
-
void XMLHttpRequest::abort()
{
// internalAbort() calls dropProtection(), which may release the last reference.
@@ -709,9 +534,13 @@ void XMLHttpRequest::abort()
internalAbort();
+ m_responseText = "";
+ m_createdDocument = false;
+ m_responseXML = 0;
+
// Clear headers as required by the spec
m_requestHeaders.clear();
-
+
if ((m_state <= OPENED && !sendFlag) || m_state == DONE)
m_state = UNSENT;
else {
@@ -720,11 +549,11 @@ void XMLHttpRequest::abort()
m_state = UNSENT;
}
- dispatchAbortEvent();
+ dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().abortEvent));
if (!m_uploadComplete) {
m_uploadComplete = true;
if (m_upload && m_uploadEventsAllowed)
- m_upload->dispatchAbortEvent();
+ m_upload->dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().abortEvent));
}
}
@@ -774,11 +603,11 @@ void XMLHttpRequest::genericError()
void XMLHttpRequest::networkError()
{
genericError();
- dispatchErrorEvent();
+ dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().errorEvent));
if (!m_uploadComplete) {
m_uploadComplete = true;
if (m_upload && m_uploadEventsAllowed)
- m_upload->dispatchErrorEvent();
+ m_upload->dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().errorEvent));
}
internalAbort();
}
@@ -786,15 +615,15 @@ void XMLHttpRequest::networkError()
void XMLHttpRequest::abortError()
{
genericError();
- dispatchAbortEvent();
+ dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().abortEvent));
if (!m_uploadComplete) {
m_uploadComplete = true;
if (m_upload && m_uploadEventsAllowed)
- m_upload->dispatchAbortEvent();
+ m_upload->dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().abortEvent));
}
}
-void XMLHttpRequest::dropProtection()
+void XMLHttpRequest::dropProtection()
{
#if USE(JSC)
// The XHR object itself holds on to the responseText, and
@@ -803,10 +632,9 @@ void XMLHttpRequest::dropProtection()
// out. But it is protected from GC while loading, so this
// can't be recouped until the load is done, so only
// report the extra cost at that point.
-
- if (JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(scriptExecutionContext()))
- if (DOMObject* wrapper = getCachedDOMObjectWrapper(*globalObject->globalData(), this))
- JSC::Heap::heap(wrapper)->reportExtraMemoryCost(m_responseText.size() * 2);
+ JSC::JSGlobalData* globalData = scriptExecutionContext()->globalData();
+ if (hasCachedDOMObjectWrapper(globalData, this))
+ globalData->heap.reportExtraMemoryCost(m_responseText.size() * 2);
#endif
unsetPendingActivity(this);
@@ -854,7 +682,7 @@ void XMLHttpRequest::setRequestHeader(const AtomicString& name, const String& va
void XMLHttpRequest::setRequestHeaderInternal(const AtomicString& name, const String& value)
{
- pair<HTTPHeaderMap::iterator, bool> result = m_requestHeaders.add(name, value);
+ pair<HTTPHeaderMap::iterator, bool> result = m_requestHeaders.add(name, value);
if (!result.second)
result.first->second += ", " + value;
}
@@ -872,7 +700,7 @@ String XMLHttpRequest::getRequestHeader(const AtomicString& name) const
String XMLHttpRequest::getAllResponseHeaders(ExceptionCode& ec) const
{
- if (m_state < LOADING) {
+ if (m_state < HEADERS_RECEIVED) {
ec = INVALID_STATE_ERR;
return "";
}
@@ -906,25 +734,21 @@ String XMLHttpRequest::getAllResponseHeaders(ExceptionCode& ec) const
String XMLHttpRequest::getResponseHeader(const AtomicString& name, ExceptionCode& ec) const
{
- if (m_state < LOADING) {
+ if (m_state < HEADERS_RECEIVED) {
ec = INVALID_STATE_ERR;
- return "";
+ return String();
}
- if (!isValidToken(name))
- return "";
-
// See comment in getAllResponseHeaders above.
if (isSetCookieHeader(name) && !scriptExecutionContext()->securityOrigin()->canLoadLocalResources()) {
reportUnsafeUsage(scriptExecutionContext(), "Refused to get unsafe header \"" + name + "\"");
- return "";
+ return String();
}
if (!m_sameOriginRequest && !isOnAccessControlResponseHeaderWhitelist(name)) {
reportUnsafeUsage(scriptExecutionContext(), "Refused to get unsafe header \"" + name + "\"");
- return "";
+ return String();
}
-
return m_response.httpHeaderField(name);
}
@@ -939,7 +763,7 @@ String XMLHttpRequest::responseMIMEType() const
}
if (mimeType.isEmpty())
mimeType = "text/xml";
-
+
return mimeType;
}
@@ -981,7 +805,7 @@ void XMLHttpRequest::didFail(const ResourceError& error)
cache()->loader()->nonCacheRequestComplete(m_url);
m_didTellLoaderAboutRequest = false;
}
-
+
// If we are already in an error state, for instance we called abort(), bail out early.
if (m_error)
return;
@@ -1011,11 +835,6 @@ void XMLHttpRequest::didFinishLoading(unsigned long identifier)
if (m_error)
return;
- if (m_inPreflight) {
- didFinishLoadingPreflight();
- return;
- }
-
if (m_state < HEADERS_RECEIVED)
changeState(HEADERS_RECEIVED);
@@ -1023,7 +842,9 @@ void XMLHttpRequest::didFinishLoading(unsigned long identifier)
m_responseText += m_decoder->flush();
scriptExecutionContext()->resourceRetrievedByXMLHttpRequest(identifier, m_responseText);
+#if ENABLE(INSPECTOR)
scriptExecutionContext()->addMessage(InspectorControllerDestination, JSMessageSource, LogMessageType, LogMessageLevel, "XHR finished loading: \"" + m_url + "\".", m_lastSendLineNumber, m_lastSendURL);
+#endif
bool hadLoader = m_loader;
m_loader = 0;
@@ -1035,75 +856,29 @@ void XMLHttpRequest::didFinishLoading(unsigned long identifier)
dropProtection();
}
-void XMLHttpRequest::didFinishLoadingPreflight()
-{
- ASSERT(m_inPreflight);
- ASSERT(!m_sameOriginRequest);
-
- // FIXME: this can probably be moved to didReceiveResponsePreflight.
- if (m_async)
- handleAsynchronousPreflightResult();
-
- if (m_loader)
- unsetPendingActivity(this);
-}
-
void XMLHttpRequest::didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent)
{
if (!m_upload)
return;
if (m_uploadEventsAllowed)
- m_upload->dispatchProgressEvent(bytesSent, totalBytesToBeSent);
+ m_upload->dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().progressEvent, true, static_cast<unsigned>(bytesSent), static_cast<unsigned>(totalBytesToBeSent)));
if (bytesSent == totalBytesToBeSent && !m_uploadComplete) {
m_uploadComplete = true;
if (m_uploadEventsAllowed)
- m_upload->dispatchLoadEvent();
+ m_upload->dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().loadEvent));
}
}
void XMLHttpRequest::didReceiveResponse(const ResourceResponse& response)
{
- if (m_inPreflight) {
- didReceiveResponsePreflight(response);
- return;
- }
-
- if (!m_sameOriginRequest) {
- if (!passesAccessControlCheck(response, m_includeCredentials, scriptExecutionContext()->securityOrigin())) {
- networkError();
- return;
- }
- }
-
m_response = response;
m_responseEncoding = extractCharsetFromMediaType(m_mimeTypeOverride);
if (m_responseEncoding.isEmpty())
m_responseEncoding = response.textEncodingName();
}
-void XMLHttpRequest::didReceiveResponsePreflight(const ResourceResponse& response)
-{
- ASSERT(m_inPreflight);
- ASSERT(!m_sameOriginRequest);
-
- if (!passesAccessControlCheck(response, m_includeCredentials, scriptExecutionContext()->securityOrigin())) {
- networkError();
- return;
- }
-
- OwnPtr<CrossOriginPreflightResultCacheItem> preflightResult(new CrossOriginPreflightResultCacheItem(m_includeCredentials));
- if (!preflightResult->parse(response)
- || !preflightResult->allowsCrossOriginMethod(m_method)
- || !preflightResult->allowsCrossOriginHeaders(m_requestHeaders)) {
- networkError();
- return;
- }
-
- CrossOriginPreflightResultCache::shared().appendEntry(scriptExecutionContext()->securityOrigin()->toString(), m_url, preflightResult.release());
-}
-
void XMLHttpRequest::didReceiveAuthenticationCancellation(const ResourceResponse& failureResponse)
{
m_response = failureResponse;
@@ -1111,12 +886,12 @@ void XMLHttpRequest::didReceiveAuthenticationCancellation(const ResourceResponse
void XMLHttpRequest::didReceiveData(const char* data, int len)
{
- if (m_inPreflight || m_error)
+ if (m_error)
return;
if (m_state < HEADERS_RECEIVED)
changeState(HEADERS_RECEIVED);
-
+
if (!m_decoder) {
if (!m_responseEncoding.isEmpty())
m_decoder = TextResourceDecoder::create("text/plain", m_responseEncoding);
@@ -1140,7 +915,12 @@ void XMLHttpRequest::didReceiveData(const char* data, int len)
m_responseText += m_decoder->decode(data, len);
if (!m_error) {
- updateAndDispatchOnProgress(len);
+ long long expectedLength = m_response.expectedContentLength();
+ m_receivedLength += len;
+
+ // FIXME: the spec requires that we dispatch the event according to the least
+ // frequent method between every 350ms (+/-200ms) and for every byte received.
+ dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().progressEvent, expectedLength && m_receivedLength <= expectedLength, static_cast<unsigned>(m_receivedLength), static_cast<unsigned>(expectedLength)));
if (m_state != LOADING)
changeState(LOADING);
@@ -1150,70 +930,6 @@ void XMLHttpRequest::didReceiveData(const char* data, int len)
}
}
-void XMLHttpRequest::updateAndDispatchOnProgress(unsigned int len)
-{
- long long expectedLength = m_response.expectedContentLength();
- m_receivedLength += len;
-
- // FIXME: the spec requires that we dispatch the event according to the least
- // frequent method between every 350ms (+/-200ms) and for every byte received.
- dispatchProgressEvent(expectedLength);
-}
-
-void XMLHttpRequest::dispatchReadyStateChangeEvent()
-{
- RefPtr<Event> evt = Event::create(eventNames().readystatechangeEvent, false, false);
- if (m_onReadyStateChangeListener) {
- evt->setTarget(this);
- evt->setCurrentTarget(this);
- m_onReadyStateChangeListener->handleEvent(evt.get(), false);
- }
-
- ExceptionCode ec = 0;
- dispatchEvent(evt.release(), ec);
- ASSERT(!ec);
-}
-
-void XMLHttpRequest::dispatchXMLHttpRequestProgressEvent(EventListener* listener, const AtomicString& type, bool lengthComputable, unsigned loaded, unsigned total)
-{
- RefPtr<XMLHttpRequestProgressEvent> evt = XMLHttpRequestProgressEvent::create(type, lengthComputable, loaded, total);
- if (listener) {
- evt->setTarget(this);
- evt->setCurrentTarget(this);
- listener->handleEvent(evt.get(), false);
- }
-
- ExceptionCode ec = 0;
- dispatchEvent(evt.release(), ec);
- ASSERT(!ec);
-}
-
-void XMLHttpRequest::dispatchAbortEvent()
-{
- dispatchXMLHttpRequestProgressEvent(m_onAbortListener.get(), eventNames().abortEvent, false, 0, 0);
-}
-
-void XMLHttpRequest::dispatchErrorEvent()
-{
- dispatchXMLHttpRequestProgressEvent(m_onErrorListener.get(), eventNames().errorEvent, false, 0, 0);
-}
-
-void XMLHttpRequest::dispatchLoadEvent()
-{
- dispatchXMLHttpRequestProgressEvent(m_onLoadListener.get(), eventNames().loadEvent, false, 0, 0);
-}
-
-void XMLHttpRequest::dispatchLoadStartEvent()
-{
- dispatchXMLHttpRequestProgressEvent(m_onLoadStartListener.get(), eventNames().loadstartEvent, false, 0, 0);
-}
-
-void XMLHttpRequest::dispatchProgressEvent(long long expectedLength)
-{
- dispatchXMLHttpRequestProgressEvent(m_onProgressListener.get(), eventNames().progressEvent, expectedLength && m_receivedLength <= expectedLength,
- static_cast<unsigned>(m_receivedLength), static_cast<unsigned>(expectedLength));
-}
-
bool XMLHttpRequest::canSuspend() const
{
return !m_loader;
@@ -1235,4 +951,14 @@ ScriptExecutionContext* XMLHttpRequest::scriptExecutionContext() const
return ActiveDOMObject::scriptExecutionContext();
}
-} // namespace WebCore
+EventTargetData* XMLHttpRequest::eventTargetData()
+{
+ return &m_eventTargetData;
+}
+
+EventTargetData* XMLHttpRequest::ensureEventTargetData()
+{
+ return &m_eventTargetData;
+}
+
+} // namespace WebCore
diff --git a/WebCore/xml/XMLHttpRequest.h b/WebCore/xml/XMLHttpRequest.h
index d581d3d..2cea5c6 100644
--- a/WebCore/xml/XMLHttpRequest.h
+++ b/WebCore/xml/XMLHttpRequest.h
@@ -23,6 +23,7 @@
#include "ActiveDOMObject.h"
#include "AtomicStringHash.h"
#include "EventListener.h"
+#include "EventNames.h"
#include "EventTarget.h"
#include "FormData.h"
#include "ResourceResponse.h"
@@ -32,9 +33,9 @@
namespace WebCore {
+class Blob;
class Document;
-class File;
-struct ResourceRequest;
+class ResourceRequest;
class TextResourceDecoder;
class ThreadableLoader;
@@ -71,7 +72,7 @@ public:
void send(ExceptionCode&);
void send(Document*, ExceptionCode&);
void send(const String&, ExceptionCode&);
- void send(File*, ExceptionCode&);
+ void send(Blob*, ExceptionCode&);
void abort();
void setRequestHeader(const AtomicString& name, const String& value, ExceptionCode&);
void overrideMimeType(const String& override);
@@ -85,41 +86,23 @@ public:
XMLHttpRequestUpload* upload();
XMLHttpRequestUpload* optionalUpload() const { return m_upload.get(); }
- void setOnreadystatechange(PassRefPtr<EventListener> eventListener) { m_onReadyStateChangeListener = eventListener; }
- EventListener* onreadystatechange() const { return m_onReadyStateChangeListener.get(); }
-
- void setOnabort(PassRefPtr<EventListener> eventListener) { m_onAbortListener = eventListener; }
- EventListener* onabort() const { return m_onAbortListener.get(); }
-
- void setOnerror(PassRefPtr<EventListener> eventListener) { m_onErrorListener = eventListener; }
- EventListener* onerror() const { return m_onErrorListener.get(); }
-
- void setOnload(PassRefPtr<EventListener> eventListener) { m_onLoadListener = eventListener; }
- EventListener* onload() const { return m_onLoadListener.get(); }
-
- void setOnloadstart(PassRefPtr<EventListener> eventListener) { m_onLoadStartListener = eventListener; }
- EventListener* onloadstart() const { return m_onLoadStartListener.get(); }
-
- void setOnprogress(PassRefPtr<EventListener> eventListener) { m_onProgressListener = eventListener; }
- EventListener* onprogress() const { return m_onProgressListener.get(); }
-
- typedef Vector<RefPtr<EventListener> > ListenerVector;
- typedef HashMap<AtomicString, ListenerVector> EventListenersMap;
-
- // useCapture is not used, even for add/remove pairing (for Firefox compatibility).
- virtual void addEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture);
- virtual void removeEventListener(const AtomicString& eventType, EventListener*, bool useCapture);
- virtual bool dispatchEvent(PassRefPtr<Event>, ExceptionCode&);
- EventListenersMap& eventListeners() { return m_eventListeners; }
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(readystatechange);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(abort);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(error);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(load);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(loadstart);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(progress);
using RefCounted<XMLHttpRequest>::ref;
using RefCounted<XMLHttpRequest>::deref;
private:
XMLHttpRequest(ScriptExecutionContext*);
-
+
virtual void refEventTarget() { ref(); }
virtual void derefEventTarget() { deref(); }
+ virtual EventTargetData* eventTargetData();
+ virtual EventTargetData* ensureEventTargetData();
Document* document() const;
@@ -135,12 +118,6 @@ private:
virtual void didFailRedirectCheck();
virtual void didReceiveAuthenticationCancellation(const ResourceResponse&);
- // Special versions for the preflight
- void didReceiveResponsePreflight(const ResourceResponse&);
- void didFinishLoadingPreflight();
-
- void updateAndDispatchOnProgress(unsigned int len);
-
String responseMIMEType() const;
bool responseIsXML() const;
@@ -159,36 +136,10 @@ private:
void createRequest(ExceptionCode&);
- void makeSameOriginRequest(ExceptionCode&);
- void makeCrossOriginAccessRequest(ExceptionCode&);
-
- void makeSimpleCrossOriginAccessRequest(ExceptionCode&);
- void makeCrossOriginAccessRequestWithPreflight(ExceptionCode&);
- void handleAsynchronousPreflightResult();
-
- void loadRequestSynchronously(ResourceRequest&, ExceptionCode&);
- void loadRequestAsynchronously(ResourceRequest&);
-
void genericError();
void networkError();
void abortError();
- void dispatchReadyStateChangeEvent();
- void dispatchXMLHttpRequestProgressEvent(EventListener* listener, const AtomicString& type, bool lengthComputable, unsigned loaded, unsigned total);
- void dispatchAbortEvent();
- void dispatchErrorEvent();
- void dispatchLoadEvent();
- void dispatchLoadStartEvent();
- void dispatchProgressEvent(long long expectedLength);
-
- RefPtr<EventListener> m_onReadyStateChangeListener;
- RefPtr<EventListener> m_onAbortListener;
- RefPtr<EventListener> m_onErrorListener;
- RefPtr<EventListener> m_onLoadListener;
- RefPtr<EventListener> m_onLoadStartListener;
- RefPtr<EventListener> m_onProgressListener;
- EventListenersMap m_eventListeners;
-
RefPtr<XMLHttpRequestUpload> m_upload;
KURL m_url;
@@ -223,16 +174,16 @@ private:
bool m_uploadComplete;
bool m_sameOriginRequest;
- bool m_allowAccess;
- bool m_inPreflight;
bool m_didTellLoaderAboutRequest;
// Used for onprogress tracking
long long m_receivedLength;
-
+
unsigned m_lastSendLineNumber;
String m_lastSendURL;
ExceptionCode m_exceptionCode;
+
+ EventTargetData m_eventTargetData;
};
} // namespace WebCore
diff --git a/WebCore/xml/XMLHttpRequest.idl b/WebCore/xml/XMLHttpRequest.idl
index 79005e2..70cd58a 100644
--- a/WebCore/xml/XMLHttpRequest.idl
+++ b/WebCore/xml/XMLHttpRequest.idl
@@ -29,7 +29,9 @@
module xml {
interface [
+ CustomConstructor,
CustomMarkFunction,
+ EventTarget,
NoStaticTables
] XMLHttpRequest {
// From XMLHttpRequestEventTarget
diff --git a/WebCore/xml/XMLHttpRequestException.idl b/WebCore/xml/XMLHttpRequestException.idl
index 380e426..7121468 100644
--- a/WebCore/xml/XMLHttpRequestException.idl
+++ b/WebCore/xml/XMLHttpRequestException.idl
@@ -29,7 +29,6 @@
module xml {
interface [
- GenerateConstructor,
NoStaticTables
] XMLHttpRequestException {
diff --git a/WebCore/xml/XMLHttpRequestProgressEvent.h b/WebCore/xml/XMLHttpRequestProgressEvent.h
index 02bfdea..27f3b8c 100644
--- a/WebCore/xml/XMLHttpRequestProgressEvent.h
+++ b/WebCore/xml/XMLHttpRequestProgressEvent.h
@@ -37,7 +37,7 @@ namespace WebCore {
{
return adoptRef(new XMLHttpRequestProgressEvent);
}
- static PassRefPtr<XMLHttpRequestProgressEvent> create(const AtomicString& type, bool lengthComputable, unsigned loaded, unsigned total)
+ static PassRefPtr<XMLHttpRequestProgressEvent> create(const AtomicString& type, bool lengthComputable = false, unsigned loaded = 0, unsigned total = 0)
{
return adoptRef(new XMLHttpRequestProgressEvent(type, lengthComputable, loaded, total));
}
diff --git a/WebCore/xml/XMLHttpRequestProgressEvent.idl b/WebCore/xml/XMLHttpRequestProgressEvent.idl
index 549308b..bc5055a 100644
--- a/WebCore/xml/XMLHttpRequestProgressEvent.idl
+++ b/WebCore/xml/XMLHttpRequestProgressEvent.idl
@@ -26,7 +26,6 @@
module events {
interface [
- GenerateConstructor,
NoStaticTables
// We should also inherit from LSProgressEvent when the idl is added.
] XMLHttpRequestProgressEvent : ProgressEvent {
diff --git a/WebCore/xml/XMLHttpRequestUpload.cpp b/WebCore/xml/XMLHttpRequestUpload.cpp
index d8a76d5..9d0fafc 100644
--- a/WebCore/xml/XMLHttpRequestUpload.cpp
+++ b/WebCore/xml/XMLHttpRequestUpload.cpp
@@ -41,11 +41,6 @@ XMLHttpRequestUpload::XMLHttpRequestUpload(XMLHttpRequest* xmlHttpRequest)
{
}
-bool XMLHttpRequestUpload::hasListeners() const
-{
- return m_onAbortListener || m_onErrorListener || m_onLoadListener || m_onLoadStartListener || m_onProgressListener || !m_eventListeners.isEmpty();
-}
-
ScriptExecutionContext* XMLHttpRequestUpload::scriptExecutionContext() const
{
XMLHttpRequest* xmlHttpRequest = associatedXMLHttpRequest();
@@ -54,95 +49,14 @@ ScriptExecutionContext* XMLHttpRequestUpload::scriptExecutionContext() const
return xmlHttpRequest->scriptExecutionContext();
}
-void XMLHttpRequestUpload::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> eventListener, bool)
-{
- EventListenersMap::iterator iter = m_eventListeners.find(eventType);
- if (iter == m_eventListeners.end()) {
- ListenerVector listeners;
- listeners.append(eventListener);
- m_eventListeners.add(eventType, listeners);
- } else {
- ListenerVector& listeners = iter->second;
- for (ListenerVector::iterator listenerIter = listeners.begin(); listenerIter != listeners.end(); ++listenerIter) {
- if (*listenerIter == eventListener)
- return;
- }
-
- listeners.append(eventListener);
- m_eventListeners.add(eventType, listeners);
- }
-}
-
-void XMLHttpRequestUpload::removeEventListener(const AtomicString& eventType, EventListener* eventListener, bool)
-{
- EventListenersMap::iterator iter = m_eventListeners.find(eventType);
- if (iter == m_eventListeners.end())
- return;
-
- ListenerVector& listeners = iter->second;
- for (ListenerVector::const_iterator listenerIter = listeners.begin(); listenerIter != listeners.end(); ++listenerIter) {
- if (*listenerIter == eventListener) {
- listeners.remove(listenerIter - listeners.begin());
- return;
- }
- }
-}
-
-bool XMLHttpRequestUpload::dispatchEvent(PassRefPtr<Event> evt, ExceptionCode& ec)
-{
- // FIXME: check for other error conditions enumerated in the spec.
- if (!evt || evt->type().isEmpty()) {
- ec = EventException::UNSPECIFIED_EVENT_TYPE_ERR;
- return true;
- }
-
- ListenerVector listenersCopy = m_eventListeners.get(evt->type());
- for (ListenerVector::const_iterator listenerIter = listenersCopy.begin(); listenerIter != listenersCopy.end(); ++listenerIter) {
- evt->setTarget(this);
- evt->setCurrentTarget(this);
- listenerIter->get()->handleEvent(evt.get(), false);
- }
-
- return !evt->defaultPrevented();
-}
-
-void XMLHttpRequestUpload::dispatchXMLHttpRequestProgressEvent(EventListener* listener, const AtomicString& type, bool lengthComputable, unsigned loaded, unsigned total)
-{
- RefPtr<XMLHttpRequestProgressEvent> evt = XMLHttpRequestProgressEvent::create(type, lengthComputable, loaded, total);
- if (listener) {
- evt->setTarget(this);
- evt->setCurrentTarget(this);
- listener->handleEvent(evt.get(), false);
- }
-
- ExceptionCode ec = 0;
- dispatchEvent(evt.release(), ec);
- ASSERT(!ec);
-}
-
-void XMLHttpRequestUpload::dispatchAbortEvent()
-{
- dispatchXMLHttpRequestProgressEvent(m_onAbortListener.get(), eventNames().abortEvent, false, 0, 0);
-}
-
-void XMLHttpRequestUpload::dispatchErrorEvent()
-{
- dispatchXMLHttpRequestProgressEvent(m_onErrorListener.get(), eventNames().errorEvent, false, 0, 0);
-}
-
-void XMLHttpRequestUpload::dispatchLoadEvent()
-{
- dispatchXMLHttpRequestProgressEvent(m_onLoadListener.get(), eventNames().loadEvent, false, 0, 0);
-}
-
-void XMLHttpRequestUpload::dispatchLoadStartEvent()
+EventTargetData* XMLHttpRequestUpload::eventTargetData()
{
- dispatchXMLHttpRequestProgressEvent(m_onLoadStartListener.get(), eventNames().loadstartEvent, false, 0, 0);
+ return &m_eventTargetData;
}
-void XMLHttpRequestUpload::dispatchProgressEvent(long long bytesSent, long long totalBytesToBeSent)
+EventTargetData* XMLHttpRequestUpload::ensureEventTargetData()
{
- dispatchXMLHttpRequestProgressEvent(m_onProgressListener.get(), eventNames().progressEvent, true, static_cast<unsigned>(bytesSent), static_cast<unsigned>(totalBytesToBeSent));
+ return &m_eventTargetData;
}
} // namespace WebCore
diff --git a/WebCore/xml/XMLHttpRequestUpload.h b/WebCore/xml/XMLHttpRequestUpload.h
index b4f40e0..7640643 100644
--- a/WebCore/xml/XMLHttpRequestUpload.h
+++ b/WebCore/xml/XMLHttpRequestUpload.h
@@ -28,6 +28,7 @@
#include "AtomicStringHash.h"
#include "EventListener.h"
+#include "EventNames.h"
#include "EventTarget.h"
#include <wtf/HashMap.h>
#include <wtf/RefCounted.h>
@@ -48,8 +49,6 @@ namespace WebCore {
return adoptRef(new XMLHttpRequestUpload(xmlHttpRequest));
}
- bool hasListeners() const;
-
virtual XMLHttpRequestUpload* toXMLHttpRequestUpload() { return this; }
XMLHttpRequest* associatedXMLHttpRequest() const { return m_xmlHttpRequest; }
@@ -57,34 +56,11 @@ namespace WebCore {
ScriptExecutionContext* scriptExecutionContext() const;
- void dispatchAbortEvent();
- void dispatchErrorEvent();
- void dispatchLoadEvent();
- void dispatchLoadStartEvent();
- void dispatchProgressEvent(long long bytesSent, long long totalBytesToBeSent);
-
- void setOnabort(PassRefPtr<EventListener> eventListener) { m_onAbortListener = eventListener; }
- EventListener* onabort() const { return m_onAbortListener.get(); }
-
- void setOnerror(PassRefPtr<EventListener> eventListener) { m_onErrorListener = eventListener; }
- EventListener* onerror() const { return m_onErrorListener.get(); }
-
- void setOnload(PassRefPtr<EventListener> eventListener) { m_onLoadListener = eventListener; }
- EventListener* onload() const { return m_onLoadListener.get(); }
-
- void setOnloadstart(PassRefPtr<EventListener> eventListener) { m_onLoadStartListener = eventListener; }
- EventListener* onloadstart() const { return m_onLoadStartListener.get(); }
-
- void setOnprogress(PassRefPtr<EventListener> eventListener) { m_onProgressListener = eventListener; }
- EventListener* onprogress() const { return m_onProgressListener.get(); }
-
- typedef Vector<RefPtr<EventListener> > ListenerVector;
- typedef HashMap<AtomicString, ListenerVector> EventListenersMap;
-
- virtual void addEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture);
- virtual void removeEventListener(const AtomicString& eventType, EventListener*, bool useCapture);
- virtual bool dispatchEvent(PassRefPtr<Event>, ExceptionCode&);
- EventListenersMap& eventListeners() { return m_eventListeners; }
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(abort);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(error);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(load);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(loadstart);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(progress);
using RefCounted<XMLHttpRequestUpload>::ref;
using RefCounted<XMLHttpRequestUpload>::deref;
@@ -92,19 +68,13 @@ namespace WebCore {
private:
XMLHttpRequestUpload(XMLHttpRequest*);
- void dispatchXMLHttpRequestProgressEvent(EventListener*, const AtomicString& type, bool lengthComputable, unsigned loaded, unsigned total);
-
virtual void refEventTarget() { ref(); }
virtual void derefEventTarget() { deref(); }
-
- RefPtr<EventListener> m_onAbortListener;
- RefPtr<EventListener> m_onErrorListener;
- RefPtr<EventListener> m_onLoadListener;
- RefPtr<EventListener> m_onLoadStartListener;
- RefPtr<EventListener> m_onProgressListener;
- EventListenersMap m_eventListeners;
+ virtual EventTargetData* eventTargetData();
+ virtual EventTargetData* ensureEventTargetData();
XMLHttpRequest* m_xmlHttpRequest;
+ EventTargetData m_eventTargetData;
};
} // namespace WebCore
diff --git a/WebCore/xml/XMLHttpRequestUpload.idl b/WebCore/xml/XMLHttpRequestUpload.idl
index 3172f68..ce392f3 100644
--- a/WebCore/xml/XMLHttpRequestUpload.idl
+++ b/WebCore/xml/XMLHttpRequestUpload.idl
@@ -29,8 +29,8 @@
module xml {
interface [
- GenerateConstructor,
CustomMarkFunction,
+ EventTarget,
NoStaticTables
] XMLHttpRequestUpload {
// From XMLHttpRequestEventTarget
diff --git a/WebCore/xml/XMLSerializer.idl b/WebCore/xml/XMLSerializer.idl
index 6dcc3a4..8c59446 100644
--- a/WebCore/xml/XMLSerializer.idl
+++ b/WebCore/xml/XMLSerializer.idl
@@ -20,7 +20,7 @@
module xpath {
- interface [GenerateConstructor, CanBeConstructed] XMLSerializer {
+ interface [CanBeConstructed] XMLSerializer {
DOMString serializeToString(in Node node)
raises(DOMException);
};
diff --git a/WebCore/xml/XPathEvaluator.idl b/WebCore/xml/XPathEvaluator.idl
index da6155b..c075b01 100644
--- a/WebCore/xml/XPathEvaluator.idl
+++ b/WebCore/xml/XPathEvaluator.idl
@@ -18,7 +18,7 @@
*/
module xpath {
- interface [GenerateConstructor, CanBeConstructed, Conditional=XPATH] XPathEvaluator {
+ interface [CanBeConstructed, Conditional=XPATH] XPathEvaluator {
XPathExpression createExpression(in DOMString expression,
in XPathNSResolver resolver)
raises(core::DOMException);
diff --git a/WebCore/xml/XPathException.idl b/WebCore/xml/XPathException.idl
index c3c95e3..d5a9af6 100644
--- a/WebCore/xml/XPathException.idl
+++ b/WebCore/xml/XPathException.idl
@@ -29,7 +29,6 @@
module xpath {
interface [
- GenerateConstructor,
Conditional=XPATH
] XPathException {
diff --git a/WebCore/xml/XPathExpression.idl b/WebCore/xml/XPathExpression.idl
index c1fc15e..6b6ceeb 100644
--- a/WebCore/xml/XPathExpression.idl
+++ b/WebCore/xml/XPathExpression.idl
@@ -22,8 +22,7 @@ module xpath {
interface [
- Conditional=XPATH,
- GenerateConstructor
+ Conditional=XPATH
] XPathExpression {
[OldStyleObjC] XPathResult evaluate(in Node contextNode,
in unsigned short type,
diff --git a/WebCore/xml/XPathExpressionNode.h b/WebCore/xml/XPathExpressionNode.h
index 74b134e..38070b9 100644
--- a/WebCore/xml/XPathExpressionNode.h
+++ b/WebCore/xml/XPathExpressionNode.h
@@ -39,7 +39,7 @@ namespace WebCore {
namespace XPath {
- struct EvaluationContext {
+ struct EvaluationContext : FastAllocBase {
RefPtr<Node> node;
unsigned long size;
unsigned long position;
diff --git a/WebCore/xml/XPathFunctions.cpp b/WebCore/xml/XPathFunctions.cpp
index da39443..1089f7c 100644
--- a/WebCore/xml/XPathFunctions.cpp
+++ b/WebCore/xml/XPathFunctions.cpp
@@ -667,12 +667,13 @@ Value FunRound::evaluate() const
return round(arg(0)->evaluate().toNumber());
}
+struct FunctionMapping {
+ const char* name;
+ FunctionRec function;
+};
+
static void createFunctionMap()
{
- struct FunctionMapping {
- const char *name;
- FunctionRec function;
- };
static const FunctionMapping functions[] = {
{ "boolean", { &createFunBoolean, 1 } },
{ "ceiling", { &createFunCeiling, 1 } },
diff --git a/WebCore/xml/XPathNSResolver.idl b/WebCore/xml/XPathNSResolver.idl
index 48c0113..4e996c2 100644
--- a/WebCore/xml/XPathNSResolver.idl
+++ b/WebCore/xml/XPathNSResolver.idl
@@ -20,7 +20,7 @@
module xpath {
- interface [ObjCProtocol, Conditional=XPATH] XPathNSResolver {
+ interface [ObjCProtocol, Conditional=XPATH, OmitConstructor] XPathNSResolver {
[ConvertNullStringTo=Null] DOMString lookupNamespaceURI(in DOMString prefix);
};
diff --git a/WebCore/xml/XPathNamespace.cpp b/WebCore/xml/XPathNamespace.cpp
index 3c8c42c..9646402 100644
--- a/WebCore/xml/XPathNamespace.cpp
+++ b/WebCore/xml/XPathNamespace.cpp
@@ -1,6 +1,6 @@
/*
* Copyright 2005 Frerich Raabe <raabe@kde.org>
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006, 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -33,18 +33,14 @@
namespace WebCore {
-XPathNamespace::XPathNamespace(PassRefPtr<Element> ownerElement, const String& prefix, const String& uri)
- : Node(ownerElement->document())
+XPathNamespace::XPathNamespace(PassRefPtr<Element> ownerElement, const AtomicString& prefix, const AtomicString& uri)
+ : Node(ownerElement->document(), CreateOther)
, m_ownerElement(ownerElement)
, m_prefix(prefix)
, m_uri(uri)
{
}
-XPathNamespace::~XPathNamespace()
-{
-}
-
Document* XPathNamespace::ownerDocument() const
{
return m_ownerElement->ownerDocument();
diff --git a/WebCore/xml/XPathNamespace.h b/WebCore/xml/XPathNamespace.h
index c0e4280..996cb9a 100644
--- a/WebCore/xml/XPathNamespace.h
+++ b/WebCore/xml/XPathNamespace.h
@@ -1,6 +1,6 @@
/*
* Copyright 2005 Frerich Raabe <raabe@kde.org>
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006, 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -34,13 +34,11 @@
namespace WebCore {
- class Document;
- class Element;
+ // FIXME: This class is never instantiated. Maybe it should be removed.
class XPathNamespace : public Node {
- public:
- XPathNamespace(PassRefPtr<Element> ownerElement, const String& prefix, const String& uri);
- virtual ~XPathNamespace();
+ private:
+ XPathNamespace(PassRefPtr<Element> ownerElement, const AtomicString& prefix, const AtomicString& uri);
virtual Document* ownerDocument() const;
virtual Element* ownerElement() const;
@@ -50,9 +48,8 @@ namespace WebCore {
virtual String nodeValue() const;
virtual const AtomicString& namespaceURI() const;
- virtual Node::NodeType nodeType() const;
+ virtual NodeType nodeType() const;
- private:
RefPtr<Element> m_ownerElement;
AtomicString m_prefix;
AtomicString m_uri;
diff --git a/WebCore/xml/XPathNodeSet.h b/WebCore/xml/XPathNodeSet.h
index 1130488..d5c47be 100644
--- a/WebCore/xml/XPathNodeSet.h
+++ b/WebCore/xml/XPathNodeSet.h
@@ -37,7 +37,7 @@ namespace WebCore {
namespace XPath {
- class NodeSet {
+ class NodeSet : public FastAllocBase {
public:
NodeSet() : m_isSorted(true), m_subtreesAreDisjoint(false) { }
diff --git a/WebCore/xml/XPathResult.idl b/WebCore/xml/XPathResult.idl
index bc36c3e..ebbff42 100644
--- a/WebCore/xml/XPathResult.idl
+++ b/WebCore/xml/XPathResult.idl
@@ -19,7 +19,7 @@
module xpath {
- interface [GenerateConstructor, Conditional=XPATH] XPathResult {
+ interface [Conditional=XPATH] XPathResult {
const unsigned short ANY_TYPE = 0;
const unsigned short NUMBER_TYPE = 1;
const unsigned short STRING_TYPE = 2;
diff --git a/WebCore/xml/XPathStep.cpp b/WebCore/xml/XPathStep.cpp
index 411b616..6e60952 100644
--- a/WebCore/xml/XPathStep.cpp
+++ b/WebCore/xml/XPathStep.cpp
@@ -34,6 +34,7 @@
#include "Document.h"
#include "Element.h"
#include "NamedNodeMap.h"
+#include "XMLNSNames.h"
#include "XPathParser.h"
#include "XPathUtil.h"
@@ -173,7 +174,7 @@ static inline bool nodeMatchesBasicTest(Node* node, Step::Axis axis, const Step:
ASSERT(node->isAttributeNode());
// In XPath land, namespace nodes are not accessible on the attribute axis.
- if (node->namespaceURI() == "http://www.w3.org/2000/xmlns/")
+ if (node->namespaceURI() == XMLNSNames::xmlnsNamespaceURI)
return false;
if (name == starAtom)
@@ -193,9 +194,13 @@ static inline bool nodeMatchesBasicTest(Node* node, Step::Axis axis, const Step:
if (name == starAtom)
return namespaceURI.isEmpty() || namespaceURI == node->namespaceURI();
- if (node->isHTMLElement() && node->document()->isHTMLDocument()) {
- // Paths without namespaces should match HTML elements in HTML documents despite those having an XHTML namespace. Names are compared case-insensitively.
- return equalIgnoringCase(static_cast<Element*>(node)->localName(), name) && (namespaceURI.isNull() || namespaceURI == node->namespaceURI());
+ if (node->document()->isHTMLDocument()) {
+ if (node->isHTMLElement()) {
+ // Paths without namespaces should match HTML elements in HTML documents despite those having an XHTML namespace. Names are compared case-insensitively.
+ return equalIgnoringCase(static_cast<Element*>(node)->localName(), name) && (namespaceURI.isNull() || namespaceURI == node->namespaceURI());
+ }
+ // An expression without any prefix shouldn't match no-namespace nodes (because HTML5 says so).
+ return static_cast<Element*>(node)->hasLocalName(name) && namespaceURI == node->namespaceURI() && !namespaceURI.isNull();
}
return static_cast<Element*>(node)->hasLocalName(name) && namespaceURI == node->namespaceURI();
}
@@ -331,7 +336,7 @@ void Step::nodesInAxis(Node* context, NodeSet& nodes) const
// Avoid lazily creating attribute nodes for attributes that we do not need anyway.
if (m_nodeTest.kind() == NodeTest::NameTest && m_nodeTest.data() != starAtom) {
RefPtr<Node> n = static_cast<Element*>(context)->getAttributeNodeNS(m_nodeTest.namespaceURI(), m_nodeTest.data());
- if (n && n->namespaceURI() != "http://www.w3.org/2000/xmlns/") { // In XPath land, namespace nodes are not accessible on the attribute axis.
+ if (n && n->namespaceURI() != XMLNSNames::xmlnsNamespaceURI) { // In XPath land, namespace nodes are not accessible on the attribute axis.
if (nodeMatches(n.get(), AttributeAxis, m_nodeTest)) // Still need to check merged predicates.
nodes.append(n.release());
}
diff --git a/WebCore/xml/XPathStep.h b/WebCore/xml/XPathStep.h
index 11612e9..ec022b3 100644
--- a/WebCore/xml/XPathStep.h
+++ b/WebCore/xml/XPathStep.h
@@ -49,7 +49,7 @@ namespace WebCore {
SelfAxis
};
- class NodeTest {
+ class NodeTest : public FastAllocBase {
public:
enum Kind {
TextNodeTest, CommentNodeTest, ProcessingInstructionNodeTest, AnyNodeTest, NameTest
diff --git a/WebCore/xml/XSLImportRule.cpp b/WebCore/xml/XSLImportRule.cpp
index 6ceb108..0908d75 100644
--- a/WebCore/xml/XSLImportRule.cpp
+++ b/WebCore/xml/XSLImportRule.cpp
@@ -52,13 +52,13 @@ XSLStyleSheet* XSLImportRule::parentStyleSheet() const
return (parent() && parent()->isXSLStyleSheet()) ? static_cast<XSLStyleSheet*>(parent()) : 0;
}
-void XSLImportRule::setXSLStyleSheet(const String& url, const String& sheet)
+void XSLImportRule::setXSLStyleSheet(const String& href, const KURL& baseURL, const String& sheet)
{
if (m_styleSheet)
m_styleSheet->setParent(0);
-
- m_styleSheet = XSLStyleSheet::create(this, url);
-
+
+ m_styleSheet = XSLStyleSheet::create(this, href, baseURL);
+
XSLStyleSheet* parent = parentStyleSheet();
if (parent)
m_styleSheet->setParentStyleSheet(parent);
@@ -87,14 +87,14 @@ void XSLImportRule::loadSheet()
String absHref = m_strHref;
XSLStyleSheet* parentSheet = parentStyleSheet();
- if (!parentSheet->href().isNull())
+ if (!parentSheet->finalURL().isNull())
// use parent styleheet's URL as the base URL
- absHref = KURL(KURL(parentSheet->href()), m_strHref).string();
+ absHref = KURL(parentSheet->finalURL(), m_strHref).string();
// Check for a cycle in our import chain. If we encounter a stylesheet
// in our parent chain with the same URL, then just bail.
for (parent = this->parent(); parent; parent = parent->parent()) {
- if (parent->isXSLStyleSheet() && absHref == static_cast<XSLStyleSheet*>(parent)->href())
+ if (parent->isXSLStyleSheet() && absHref == static_cast<XSLStyleSheet*>(parent)->finalURL().string())
return;
}
diff --git a/WebCore/xml/XSLImportRule.h b/WebCore/xml/XSLImportRule.h
index fc7a7f8..f3a9318 100644
--- a/WebCore/xml/XSLImportRule.h
+++ b/WebCore/xml/XSLImportRule.h
@@ -57,7 +57,7 @@ private:
virtual bool isImportRule() { return true; }
// from CachedResourceClient
- virtual void setXSLStyleSheet(const String& url, const String& sheet);
+ virtual void setXSLStyleSheet(const String& href, const KURL& baseURL, const String& sheet);
String m_strHref;
RefPtr<XSLStyleSheet> m_styleSheet;
diff --git a/WebCore/xml/XSLStyleSheet.h b/WebCore/xml/XSLStyleSheet.h
index fe97b54..e6e4063 100644
--- a/WebCore/xml/XSLStyleSheet.h
+++ b/WebCore/xml/XSLStyleSheet.h
@@ -26,8 +26,12 @@
#if ENABLE(XSLT)
#include "StyleSheet.h"
+
+#if !USE(QXMLQUERY)
#include <libxml/parser.h>
#include <libxslt/transform.h>
+#endif
+
#include <wtf/PassRefPtr.h>
namespace WebCore {
@@ -38,17 +42,19 @@ class XSLImportRule;
class XSLStyleSheet : public StyleSheet {
public:
- static PassRefPtr<XSLStyleSheet> create(XSLImportRule* parentImport, const String& href)
+#if !USE(QXMLQUERY)
+ static PassRefPtr<XSLStyleSheet> create(XSLImportRule* parentImport, const String& originalURL, const KURL& finalURL)
{
- return adoptRef(new XSLStyleSheet(parentImport, href));
+ return adoptRef(new XSLStyleSheet(parentImport, originalURL, finalURL));
}
- static PassRefPtr<XSLStyleSheet> create(Node* parentNode, const String& href)
+#endif
+ static PassRefPtr<XSLStyleSheet> create(Node* parentNode, const String& originalURL, const KURL& finalURL)
{
- return adoptRef(new XSLStyleSheet(parentNode, href, false));
+ return adoptRef(new XSLStyleSheet(parentNode, originalURL, finalURL, false));
}
- static PassRefPtr<XSLStyleSheet> createEmbedded(Node* parentNode, const String& href)
+ static PassRefPtr<XSLStyleSheet> createInline(Node* parentNode, const KURL& finalURL)
{
- return adoptRef(new XSLStyleSheet(parentNode, href, true));
+ return adoptRef(new XSLStyleSheet(parentNode, finalURL.string(), finalURL, true));
}
virtual ~XSLStyleSheet();
@@ -65,31 +71,41 @@ public:
void loadChildSheets();
void loadChildSheet(const String& href);
- xsltStylesheetPtr compileStyleSheet();
-
DocLoader* docLoader();
Document* ownerDocument() { return m_ownerDocument; }
void setParentStyleSheet(XSLStyleSheet* parent);
+#if USE(QXMLQUERY)
+ String sheetString() const { return m_sheetString; }
+#else
xmlDocPtr document();
+ xsltStylesheetPtr compileStyleSheet();
+ xmlDocPtr locateStylesheetSubResource(xmlDocPtr parentDoc, const xmlChar* uri);
+#endif
void clearDocuments();
- xmlDocPtr locateStylesheetSubResource(xmlDocPtr parentDoc, const xmlChar* uri);
-
void markAsProcessed();
bool processed() const { return m_processed; }
private:
- XSLStyleSheet(Node* parentNode, const String& href, bool embedded);
- XSLStyleSheet(XSLImportRule* parentImport, const String& href);
+ XSLStyleSheet(Node* parentNode, const String& originalURL, const KURL& finalURL, bool embedded);
+#if !USE(QXMLQUERY)
+ XSLStyleSheet(XSLImportRule* parentImport, const String& originalURL, const KURL& finalURL);
+#endif
Document* m_ownerDocument;
- xmlDocPtr m_stylesheetDoc;
bool m_embedded;
bool m_processed;
+
+#if USE(QXMLQUERY)
+ String m_sheetString;
+#else
+ xmlDocPtr m_stylesheetDoc;
bool m_stylesheetDocTaken;
+#endif
+
XSLStyleSheet* m_parentStyleSheet;
};
diff --git a/WebCore/xml/XSLStyleSheet.cpp b/WebCore/xml/XSLStyleSheetLibxslt.cpp
index b7d52f8..dbd806a 100644
--- a/WebCore/xml/XSLStyleSheet.cpp
+++ b/WebCore/xml/XSLStyleSheetLibxslt.cpp
@@ -31,6 +31,7 @@
#include "Document.h"
#include "Frame.h"
#include "Node.h"
+#include "TransformSource.h"
#include "XMLTokenizer.h"
#include "XMLTokenizerScope.h"
#include "XSLImportRule.h"
@@ -54,23 +55,23 @@ SOFT_LINK(libxslt, xsltLoadStylesheetPI, xsltStylesheetPtr, (xmlDocPtr doc), (do
namespace WebCore {
-XSLStyleSheet::XSLStyleSheet(XSLImportRule* parentRule, const String& href)
- : StyleSheet(parentRule, href)
+XSLStyleSheet::XSLStyleSheet(XSLImportRule* parentRule, const String& originalURL, const KURL& finalURL)
+ : StyleSheet(parentRule, originalURL, finalURL)
, m_ownerDocument(0)
- , m_stylesheetDoc(0)
, m_embedded(false)
, m_processed(false) // Child sheets get marked as processed when the libxslt engine has finally seen them.
+ , m_stylesheetDoc(0)
, m_stylesheetDocTaken(false)
, m_parentStyleSheet(0)
{
}
-XSLStyleSheet::XSLStyleSheet(Node* parentNode, const String& href, bool embedded)
- : StyleSheet(parentNode, href)
+XSLStyleSheet::XSLStyleSheet(Node* parentNode, const String& originalURL, const KURL& finalURL, bool embedded)
+ : StyleSheet(parentNode, originalURL, finalURL)
, m_ownerDocument(parentNode->document())
- , m_stylesheetDoc(0)
, m_embedded(embedded)
, m_processed(true) // The root sheet starts off processed.
+ , m_stylesheetDoc(0)
, m_stylesheetDocTaken(false)
, m_parentStyleSheet(0)
{
@@ -98,7 +99,7 @@ bool XSLStyleSheet::isLoading()
void XSLStyleSheet::checkLoaded()
{
- if (isLoading())
+ if (isLoading())
return;
if (parent())
parent()->checkLoaded();
@@ -108,8 +109,8 @@ void XSLStyleSheet::checkLoaded()
xmlDocPtr XSLStyleSheet::document()
{
- if (m_embedded && ownerDocument())
- return (xmlDocPtr)ownerDocument()->transformSource();
+ if (m_embedded && ownerDocument() && ownerDocument()->transformSource())
+ return (xmlDocPtr)ownerDocument()->transformSource()->platformSource();
return m_stylesheetDoc;
}
@@ -167,8 +168,8 @@ bool XSLStyleSheet::parseString(const String& string, bool)
}
m_stylesheetDoc = xmlCtxtReadMemory(ctxt, buffer, size,
- href().utf8().data(),
- BOMHighByte == 0xFF ? "UTF-16LE" : "UTF-16BE",
+ finalURL().string().utf8().data(),
+ BOMHighByte == 0xFF ? "UTF-16LE" : "UTF-16BE",
XML_PARSE_NOENT | XML_PARSE_DTDATTR | XML_PARSE_NOWARNING | XML_PARSE_NOCDATA);
xmlFreeParserCtxt(ctxt);
@@ -181,17 +182,17 @@ void XSLStyleSheet::loadChildSheets()
{
if (!document())
return;
-
+
xmlNodePtr stylesheetRoot = document()->children;
-
+
// Top level children may include other things such as DTD nodes, we ignore those.
while (stylesheetRoot && stylesheetRoot->type != XML_ELEMENT_NODE)
stylesheetRoot = stylesheetRoot->next;
-
+
if (m_embedded) {
- // We have to locate (by ID) the appropriate embedded stylesheet element, so that we can walk the
+ // We have to locate (by ID) the appropriate embedded stylesheet element, so that we can walk the
// import/include list.
- xmlAttrPtr idNode = xmlGetID(document(), (const xmlChar*)(href().utf8().data()));
+ xmlAttrPtr idNode = xmlGetID(document(), (const xmlChar*)(finalURL().string().utf8().data()));
if (!idNode)
return;
stylesheetRoot = idNode->parent;
@@ -199,7 +200,7 @@ void XSLStyleSheet::loadChildSheets()
// FIXME: Need to handle an external URI with a # in it. This is a pretty minor edge case, so we'll deal
// with it later.
}
-
+
if (stylesheetRoot) {
// Walk the children of the root element and look for import/include elements.
// Imports must occur first.
@@ -210,7 +211,7 @@ void XSLStyleSheet::loadChildSheets()
continue;
}
if (IS_XSLT_ELEM(curr) && IS_XSLT_NAME(curr, "import")) {
- xmlChar* uriRef = xsltGetNsProp(curr, (const xmlChar*)"href", XSLT_NAMESPACE);
+ xmlChar* uriRef = xsltGetNsProp(curr, (const xmlChar*)"href", XSLT_NAMESPACE);
loadChildSheet(String::fromUTF8((const char*)uriRef));
xmlFree(uriRef);
} else
@@ -242,7 +243,7 @@ xsltStylesheetPtr XSLStyleSheet::compileStyleSheet()
// FIXME: Hook up error reporting for the stylesheet compilation process.
if (m_embedded)
return xsltLoadStylesheetPI(document());
-
+
// xsltParseStylesheetDoc makes the document part of the stylesheet
// so we have to release our pointer to it.
ASSERT(!m_stylesheetDocTaken);
@@ -273,7 +274,7 @@ xmlDocPtr XSLStyleSheet::locateStylesheetSubResource(xmlDocPtr parentDoc, const
if (matchedParent) {
if (child->processed())
continue; // libxslt has been given this sheet already.
-
+
// Check the URI of the child stylesheet against the doc URI.
// In order to ensure that libxml canonicalized both URLs, we get the original href
// string from the import rule and canonicalize it using libxml before comparing it
@@ -295,7 +296,7 @@ xmlDocPtr XSLStyleSheet::locateStylesheetSubResource(xmlDocPtr parentDoc, const
}
}
}
-
+
return 0;
}
diff --git a/WebCore/xml/XSLStyleSheetQt.cpp b/WebCore/xml/XSLStyleSheetQt.cpp
new file mode 100644
index 0000000..cb55993
--- /dev/null
+++ b/WebCore/xml/XSLStyleSheetQt.cpp
@@ -0,0 +1,103 @@
+/*
+ * This file is part of the XSL implementation.
+ *
+ * Copyright (C) 2009 Jakub Wieczorek <faw217@gmail.com>
+ *
+ * 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.
+ */
+
+#include "config.h"
+#include "XSLStyleSheet.h"
+
+#if ENABLE(XSLT)
+
+#include "DOMWindow.h"
+#include "Document.h"
+#include "Node.h"
+#include "NotImplemented.h"
+#include "XSLTProcessor.h"
+#include "loader.h"
+
+namespace WebCore {
+
+XSLStyleSheet::XSLStyleSheet(Node* parentNode, const String& originalURL, const KURL& finalURL, bool embedded)
+ : StyleSheet(parentNode, originalURL, finalURL)
+ , m_ownerDocument(parentNode->document())
+ , m_embedded(embedded)
+{
+}
+
+XSLStyleSheet::~XSLStyleSheet()
+{
+}
+
+bool XSLStyleSheet::isLoading()
+{
+ notImplemented();
+ return false;
+}
+
+void XSLStyleSheet::checkLoaded()
+{
+ if (ownerNode())
+ ownerNode()->sheetLoaded();
+}
+
+void XSLStyleSheet::clearDocuments()
+{
+ notImplemented();
+}
+
+DocLoader* XSLStyleSheet::docLoader()
+{
+ if (!m_ownerDocument)
+ return 0;
+ return m_ownerDocument->docLoader();
+}
+
+bool XSLStyleSheet::parseString(const String& string, bool)
+{
+ // FIXME: Fix QXmlQuery so that it allows compiling the stylesheet before setting the document
+ // to be transformed. This way we could not only check if the stylesheet is correct before using it
+ // but also turn XSLStyleSheet::sheetString() into XSLStyleSheet::query() that returns a QXmlQuery.
+
+ m_sheetString = string;
+ return !m_sheetString.isEmpty();
+}
+
+void XSLStyleSheet::loadChildSheets()
+{
+ notImplemented();
+}
+
+void XSLStyleSheet::loadChildSheet(const String&)
+{
+ notImplemented();
+}
+
+void XSLStyleSheet::setParentStyleSheet(XSLStyleSheet*)
+{
+ notImplemented();
+}
+
+void XSLStyleSheet::markAsProcessed()
+{
+ notImplemented();
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(XSLT)
diff --git a/WebCore/xml/XSLTProcessor.cpp b/WebCore/xml/XSLTProcessor.cpp
index a26fe77..b182243 100644
--- a/WebCore/xml/XSLTProcessor.cpp
+++ b/WebCore/xml/XSLTProcessor.cpp
@@ -26,10 +26,7 @@
#include "XSLTProcessor.h"
-#include "CString.h"
-#include "Console.h"
#include "DOMImplementation.h"
-#include "DOMWindow.h"
#include "DocLoader.h"
#include "DocumentFragment.h"
#include "Frame.h"
@@ -38,166 +35,17 @@
#include "HTMLDocument.h"
#include "HTMLTokenizer.h" // for parseHTMLDocumentFragment
#include "Page.h"
-#include "ResourceError.h"
-#include "ResourceHandle.h"
-#include "ResourceRequest.h"
-#include "ResourceResponse.h"
#include "Text.h"
#include "TextResourceDecoder.h"
#include "XMLTokenizer.h"
-#include "XSLTExtensions.h"
-#include "XSLTUnicodeSort.h"
#include "loader.h"
#include "markup.h"
-#include <libxslt/imports.h>
-#include <libxslt/variables.h>
-#include <libxslt/xsltutils.h>
#include <wtf/Assertions.h>
#include <wtf/Platform.h>
#include <wtf/Vector.h>
-#if PLATFORM(MAC)
-#include "SoftLinking.h"
-
-SOFT_LINK_LIBRARY(libxslt);
-SOFT_LINK(libxslt, xsltFreeStylesheet, void, (xsltStylesheetPtr sheet), (sheet))
-SOFT_LINK(libxslt, xsltFreeTransformContext, void, (xsltTransformContextPtr ctxt), (ctxt))
-SOFT_LINK(libxslt, xsltNewTransformContext, xsltTransformContextPtr, (xsltStylesheetPtr style, xmlDocPtr doc), (style, doc))
-SOFT_LINK(libxslt, xsltApplyStylesheetUser, xmlDocPtr, (xsltStylesheetPtr style, xmlDocPtr doc, const char** params, const char* output, FILE* profile, xsltTransformContextPtr userCtxt), (style, doc, params, output, profile, userCtxt))
-SOFT_LINK(libxslt, xsltQuoteUserParams, int, (xsltTransformContextPtr ctxt, const char** params), (ctxt, params))
-SOFT_LINK(libxslt, xsltSetCtxtSortFunc, void, (xsltTransformContextPtr ctxt, xsltSortFunc handler), (ctxt, handler))
-SOFT_LINK(libxslt, xsltSetLoaderFunc, void, (xsltDocLoaderFunc f), (f))
-SOFT_LINK(libxslt, xsltSaveResultTo, int, (xmlOutputBufferPtr buf, xmlDocPtr result, xsltStylesheetPtr style), (buf, result, style))
-SOFT_LINK(libxslt, xsltNextImport, xsltStylesheetPtr, (xsltStylesheetPtr style), (style))
-#endif
-
namespace WebCore {
-void XSLTProcessor::genericErrorFunc(void*, const char*, ...)
-{
- // It would be nice to do something with this error message.
-}
-
-void XSLTProcessor::parseErrorFunc(void* userData, xmlError* error)
-{
- Console* console = static_cast<Console*>(userData);
- if (!console)
- return;
-
- MessageLevel level;
- switch (error->level) {
- case XML_ERR_NONE:
- level = TipMessageLevel;
- break;
- case XML_ERR_WARNING:
- level = WarningMessageLevel;
- break;
- case XML_ERR_ERROR:
- case XML_ERR_FATAL:
- default:
- level = ErrorMessageLevel;
- break;
- }
-
- console->addMessage(XMLMessageSource, LogMessageType, level, error->message, error->line, error->file);
-}
-
-// FIXME: There seems to be no way to control the ctxt pointer for loading here, thus we have globals.
-static XSLTProcessor* globalProcessor = 0;
-static DocLoader* globalDocLoader = 0;
-static xmlDocPtr docLoaderFunc(const xmlChar* uri,
- xmlDictPtr,
- int options,
- void* ctxt,
- xsltLoadType type)
-{
- if (!globalProcessor)
- return 0;
-
- switch (type) {
- case XSLT_LOAD_DOCUMENT: {
- xsltTransformContextPtr context = (xsltTransformContextPtr)ctxt;
- xmlChar* base = xmlNodeGetBase(context->document->doc, context->node);
- KURL url(KURL(reinterpret_cast<const char*>(base)), reinterpret_cast<const char*>(uri));
- xmlFree(base);
- ResourceError error;
- ResourceResponse response;
-
- Vector<char> data;
-
- bool requestAllowed = globalDocLoader->frame() && globalDocLoader->doc()->securityOrigin()->canRequest(url);
- if (requestAllowed) {
- globalDocLoader->frame()->loader()->loadResourceSynchronously(url, AllowStoredCredentials, error, response, data);
- requestAllowed = globalDocLoader->doc()->securityOrigin()->canRequest(response.url());
- }
- if (!requestAllowed) {
- data.clear();
- globalDocLoader->printAccessDeniedMessage(url);
- }
-
- Console* console = 0;
- if (Frame* frame = globalProcessor->xslStylesheet()->ownerDocument()->frame())
- console = frame->domWindow()->console();
- xmlSetStructuredErrorFunc(console, XSLTProcessor::parseErrorFunc);
- xmlSetGenericErrorFunc(console, XSLTProcessor::genericErrorFunc);
-
- // We don't specify an encoding here. Neither Gecko nor WinIE respects
- // the encoding specified in the HTTP headers.
- xmlDocPtr doc = xmlReadMemory(data.data(), data.size(), (const char*)uri, 0, options);
-
- xmlSetStructuredErrorFunc(0, 0);
- xmlSetGenericErrorFunc(0, 0);
-
- return doc;
- }
- case XSLT_LOAD_STYLESHEET:
- return globalProcessor->xslStylesheet()->locateStylesheetSubResource(((xsltStylesheetPtr)ctxt)->doc, uri);
- default:
- break;
- }
-
- return 0;
-}
-
-static inline void setXSLTLoadCallBack(xsltDocLoaderFunc func, XSLTProcessor* processor, DocLoader* loader)
-{
- xsltSetLoaderFunc(func);
- globalProcessor = processor;
- globalDocLoader = loader;
-}
-
-static int writeToVector(void* context, const char* buffer, int len)
-{
- Vector<UChar>& resultOutput = *static_cast<Vector<UChar>*>(context);
- String decodedChunk = String::fromUTF8(buffer, len);
- resultOutput.append(decodedChunk.characters(), decodedChunk.length());
- return len;
-}
-
-static bool saveResultToString(xmlDocPtr resultDoc, xsltStylesheetPtr sheet, String& resultString)
-{
- xmlOutputBufferPtr outputBuf = xmlAllocOutputBuffer(0);
- if (!outputBuf)
- return false;
-
- Vector<UChar> resultVector;
- outputBuf->context = &resultVector;
- outputBuf->writecallback = writeToVector;
-
- int retval = xsltSaveResultTo(outputBuf, resultDoc, sheet);
- xmlOutputBufferClose(outputBuf);
- if (retval < 0)
- return false;
-
- // Workaround for <http://bugzilla.gnome.org/show_bug.cgi?id=495668>: libxslt appends an extra line feed to the result.
- if (resultVector.size() > 0 && resultVector[resultVector.size() - 1] == '\n')
- resultVector.removeLast();
-
- resultString = String::adopt(resultVector);
-
- return true;
-}
-
static inline void transformTextStringToXHTMLDocumentString(String& text)
{
// Modify the output so that it is a well-formed XHTML document with a <pre> tag enclosing the text.
@@ -213,38 +61,6 @@ static inline void transformTextStringToXHTMLDocumentString(String& text)
"</html>\n";
}
-static const char** xsltParamArrayFromParameterMap(XSLTProcessor::ParameterMap& parameters)
-{
- if (parameters.isEmpty())
- return 0;
-
- const char** parameterArray = (const char**)fastMalloc(((parameters.size() * 2) + 1) * sizeof(char*));
-
- XSLTProcessor::ParameterMap::iterator end = parameters.end();
- unsigned index = 0;
- for (XSLTProcessor::ParameterMap::iterator it = parameters.begin(); it != end; ++it) {
- parameterArray[index++] = strdup(it->first.utf8().data());
- parameterArray[index++] = strdup(it->second.utf8().data());
- }
- parameterArray[index] = 0;
-
- return parameterArray;
-}
-
-static void freeXsltParamArray(const char** params)
-{
- const char** temp = params;
- if (!params)
- return;
-
- while (*temp) {
- free((void*)*(temp++)); // strdup returns malloc'd blocks, so we have to use free() here
- free((void*)*(temp++));
- }
- fastFree(params);
-}
-
-
PassRefPtr<Document> XSLTProcessor::createDocumentFromSource(const String& sourceString,
const String& sourceEncoding, const String& sourceMIMEType, Node* sourceNode, Frame* frame)
{
@@ -258,7 +74,7 @@ PassRefPtr<Document> XSLTProcessor::createDocumentFromSource(const String& sourc
transformTextStringToXHTMLDocumentString(documentSource);
} else
result = ownerDocument->implementation()->createDocument(sourceMIMEType, frame, false);
-
+
// Before parsing, we need to save & detach the old document and get the new document
// in place. We have to do this only if we're rendering the result document.
if (frame) {
@@ -267,15 +83,15 @@ PassRefPtr<Document> XSLTProcessor::createDocumentFromSource(const String& sourc
result->setTransformSourceDocument(frame->document());
frame->setDocument(result);
}
-
+
if (sourceIsDocument)
result->setURL(ownerDocument->url());
result->open();
-
+
RefPtr<TextResourceDecoder> decoder = TextResourceDecoder::create(sourceMIMEType);
decoder->setEncoding(sourceEncoding.isEmpty() ? UTF8Encoding() : TextEncoding(sourceEncoding), TextResourceDecoder::EncodingFromXMLHeader);
result->setDecoder(decoder.release());
-
+
result->write(documentSource);
result->finishParsing();
result->close();
@@ -285,129 +101,21 @@ PassRefPtr<Document> XSLTProcessor::createDocumentFromSource(const String& sourc
static inline RefPtr<DocumentFragment> createFragmentFromSource(const String& sourceString, const String& sourceMIMEType, Document* outputDoc)
{
- RefPtr<DocumentFragment> fragment = new DocumentFragment(outputDoc);
-
+ RefPtr<DocumentFragment> fragment = DocumentFragment::create(outputDoc);
+
if (sourceMIMEType == "text/html")
parseHTMLDocumentFragment(sourceString, fragment.get());
else if (sourceMIMEType == "text/plain")
- fragment->addChild(new Text(outputDoc, sourceString));
+ fragment->addChild(Text::create(outputDoc, sourceString));
else {
bool successfulParse = parseXMLDocumentFragment(sourceString, fragment.get(), outputDoc->documentElement());
if (!successfulParse)
return 0;
}
-
- // FIXME: Do we need to mess with URLs here?
-
- return fragment;
-}
-
-static xsltStylesheetPtr xsltStylesheetPointer(RefPtr<XSLStyleSheet>& cachedStylesheet, Node* stylesheetRootNode)
-{
- if (!cachedStylesheet && stylesheetRootNode) {
- cachedStylesheet = XSLStyleSheet::create(stylesheetRootNode->parent() ? stylesheetRootNode->parent() : stylesheetRootNode,
- stylesheetRootNode->document()->url().string());
- cachedStylesheet->parseString(createMarkup(stylesheetRootNode));
- }
-
- if (!cachedStylesheet || !cachedStylesheet->document())
- return 0;
-
- return cachedStylesheet->compileStyleSheet();
-}
-static inline xmlDocPtr xmlDocPtrFromNode(Node* sourceNode, bool& shouldDelete)
-{
- RefPtr<Document> ownerDocument = sourceNode->document();
- bool sourceIsDocument = (sourceNode == ownerDocument.get());
-
- xmlDocPtr sourceDoc = 0;
- if (sourceIsDocument)
- sourceDoc = (xmlDocPtr)ownerDocument->transformSource();
- if (!sourceDoc) {
- sourceDoc = (xmlDocPtr)xmlDocPtrForString(ownerDocument->docLoader(), createMarkup(sourceNode),
- sourceIsDocument ? ownerDocument->url().string() : String());
- shouldDelete = (sourceDoc != 0);
- }
- return sourceDoc;
-}
-
-static inline String resultMIMEType(xmlDocPtr resultDoc, xsltStylesheetPtr sheet)
-{
- // There are three types of output we need to be able to deal with:
- // HTML (create an HTML document), XML (create an XML document),
- // and text (wrap in a <pre> and create an XML document).
-
- const xmlChar* resultType = 0;
- XSLT_GET_IMPORT_PTR(resultType, sheet, method);
- if (resultType == 0 && resultDoc->type == XML_HTML_DOCUMENT_NODE)
- resultType = (const xmlChar*)"html";
-
- if (xmlStrEqual(resultType, (const xmlChar*)"html"))
- return "text/html";
- else if (xmlStrEqual(resultType, (const xmlChar*)"text"))
- return "text/plain";
-
- return "application/xml";
-}
-
-bool XSLTProcessor::transformToString(Node* sourceNode, String& mimeType, String& resultString, String& resultEncoding)
-{
- RefPtr<Document> ownerDocument = sourceNode->document();
-
- setXSLTLoadCallBack(docLoaderFunc, this, ownerDocument->docLoader());
- xsltStylesheetPtr sheet = xsltStylesheetPointer(m_stylesheet, m_stylesheetRootNode.get());
- if (!sheet) {
- setXSLTLoadCallBack(0, 0, 0);
- return false;
- }
- m_stylesheet->clearDocuments();
-
- xmlChar* origMethod = sheet->method;
- if (!origMethod && mimeType == "text/html")
- sheet->method = (xmlChar*)"html";
-
- bool success = false;
- bool shouldFreeSourceDoc = false;
- if (xmlDocPtr sourceDoc = xmlDocPtrFromNode(sourceNode, shouldFreeSourceDoc)) {
- // The XML declaration would prevent parsing the result as a fragment, and it's not needed even for documents,
- // as the result of this function is always immediately parsed.
- sheet->omitXmlDeclaration = true;
-
- xsltTransformContextPtr transformContext = xsltNewTransformContext(sheet, sourceDoc);
- registerXSLTExtensions(transformContext);
-
- // <http://bugs.webkit.org/show_bug.cgi?id=16077>: XSLT processor <xsl:sort> algorithm only compares by code point
- xsltSetCtxtSortFunc(transformContext, xsltUnicodeSortFunction);
-
- // This is a workaround for a bug in libxslt.
- // The bug has been fixed in version 1.1.13, so once we ship that this can be removed.
- if (transformContext->globalVars == NULL)
- transformContext->globalVars = xmlHashCreate(20);
-
- const char** params = xsltParamArrayFromParameterMap(m_parameters);
- xsltQuoteUserParams(transformContext, params);
- xmlDocPtr resultDoc = xsltApplyStylesheetUser(sheet, sourceDoc, 0, 0, 0, transformContext);
-
- xsltFreeTransformContext(transformContext);
- freeXsltParamArray(params);
-
- if (shouldFreeSourceDoc)
- xmlFreeDoc(sourceDoc);
-
- if (success = saveResultToString(resultDoc, sheet, resultString)) {
- mimeType = resultMIMEType(resultDoc, sheet);
- resultEncoding = (char*)resultDoc->encoding;
- }
- xmlFreeDoc(resultDoc);
- }
-
- sheet->method = origMethod;
- setXSLTLoadCallBack(0, 0, 0);
- xsltFreeStylesheet(sheet);
- m_stylesheet = 0;
+ // FIXME: Do we need to mess with URLs here?
- return success;
+ return fragment;
}
PassRefPtr<Document> XSLTProcessor::transformToDocument(Node* sourceNode)
@@ -429,7 +137,7 @@ PassRefPtr<DocumentFragment> XSLTProcessor::transformToFragment(Node* sourceNode
// If the output document is HTML, default to HTML method.
if (outputDoc->isHTMLDocument())
resultMIMEType = "text/html";
-
+
if (!transformToString(sourceNode, resultMIMEType, resultString, resultEncoding))
return 0;
return createFragmentFromSource(resultString, resultMIMEType, outputDoc);
@@ -455,6 +163,13 @@ void XSLTProcessor::removeParameter(const String& /*namespaceURI*/, const String
m_parameters.remove(localName);
}
+void XSLTProcessor::reset()
+{
+ m_stylesheet.clear();
+ m_stylesheetRootNode.clear();
+ m_parameters.clear();
+}
+
} // namespace WebCore
#endif // ENABLE(XSLT)
diff --git a/WebCore/xml/XSLTProcessor.h b/WebCore/xml/XSLTProcessor.h
index 9ee2aad..9b91017 100644
--- a/WebCore/xml/XSLTProcessor.h
+++ b/WebCore/xml/XSLTProcessor.h
@@ -28,9 +28,12 @@
#include "Node.h"
#include "StringHash.h"
#include "XSLStyleSheet.h"
+#include <wtf/HashMap.h>
+
+#if !USE(QXMLQUERY)
#include <libxml/parserInternals.h>
#include <libxslt/documents.h>
-#include <wtf/HashMap.h>
+#endif
namespace WebCore {
@@ -56,14 +59,15 @@ public:
void removeParameter(const String& namespaceURI, const String& localName);
void clearParameters() { m_parameters.clear(); }
- void reset() { m_stylesheet.clear(); m_stylesheetRootNode.clear(); m_parameters.clear(); }
+ void reset();
+#if !USE(QXMLQUERY)
static void parseErrorFunc(void* userData, xmlError*);
static void genericErrorFunc(void* userData, const char* msg, ...);
-public:
// Only for libXSLT callbacks
XSLStyleSheet* xslStylesheet() const { return m_stylesheet.get(); }
+#endif
typedef HashMap<String, String> ParameterMap;
diff --git a/WebCore/xml/XSLTProcessor.idl b/WebCore/xml/XSLTProcessor.idl
index 0a6ff93..28bd878 100644
--- a/WebCore/xml/XSLTProcessor.idl
+++ b/WebCore/xml/XSLTProcessor.idl
@@ -33,7 +33,8 @@ module xml {
// http://bugs.webkit.org/show_bug.cgi?id=5446
interface [
- Conditional=XSLT
+ Conditional=XSLT,
+ CustomConstructor
] XSLTProcessor {
[Custom] void importStylesheet(in Node stylesheet);
diff --git a/WebCore/xml/XSLTProcessorLibxslt.cpp b/WebCore/xml/XSLTProcessorLibxslt.cpp
new file mode 100644
index 0000000..e2da3ed
--- /dev/null
+++ b/WebCore/xml/XSLTProcessorLibxslt.cpp
@@ -0,0 +1,336 @@
+/*
+ * This file is part of the XSL implementation.
+ *
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple, Inc. All rights reserved.
+ * Copyright (C) 2005, 2006 Alexey Proskuryakov <ap@webkit.org>
+ *
+ * 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.
+ */
+
+#include "config.h"
+
+#if ENABLE(XSLT)
+
+#include "XSLTProcessor.h"
+
+#include "Console.h"
+#include "CString.h"
+#include "DOMWindow.h"
+#include "DocLoader.h"
+#include "Frame.h"
+#include "ResourceError.h"
+#include "ResourceHandle.h"
+#include "ResourceRequest.h"
+#include "ResourceResponse.h"
+#include "TransformSource.h"
+#include "XMLTokenizer.h"
+#include "XSLStyleSheet.h"
+#include "XSLTExtensions.h"
+#include "XSLTUnicodeSort.h"
+#include "loader.h"
+#include "markup.h"
+#include <libxslt/imports.h>
+#include <libxslt/variables.h>
+#include <libxslt/xsltutils.h>
+#include <wtf/Assertions.h>
+#include <wtf/Platform.h>
+#include <wtf/Vector.h>
+
+#if PLATFORM(MAC)
+#include "SoftLinking.h"
+
+SOFT_LINK_LIBRARY(libxslt);
+SOFT_LINK(libxslt, xsltFreeStylesheet, void, (xsltStylesheetPtr sheet), (sheet))
+SOFT_LINK(libxslt, xsltFreeTransformContext, void, (xsltTransformContextPtr ctxt), (ctxt))
+SOFT_LINK(libxslt, xsltNewTransformContext, xsltTransformContextPtr, (xsltStylesheetPtr style, xmlDocPtr doc), (style, doc))
+SOFT_LINK(libxslt, xsltApplyStylesheetUser, xmlDocPtr, (xsltStylesheetPtr style, xmlDocPtr doc, const char** params, const char* output, FILE* profile, xsltTransformContextPtr userCtxt), (style, doc, params, output, profile, userCtxt))
+SOFT_LINK(libxslt, xsltQuoteUserParams, int, (xsltTransformContextPtr ctxt, const char** params), (ctxt, params))
+SOFT_LINK(libxslt, xsltSetCtxtSortFunc, void, (xsltTransformContextPtr ctxt, xsltSortFunc handler), (ctxt, handler))
+SOFT_LINK(libxslt, xsltSetLoaderFunc, void, (xsltDocLoaderFunc f), (f))
+SOFT_LINK(libxslt, xsltSaveResultTo, int, (xmlOutputBufferPtr buf, xmlDocPtr result, xsltStylesheetPtr style), (buf, result, style))
+SOFT_LINK(libxslt, xsltNextImport, xsltStylesheetPtr, (xsltStylesheetPtr style), (style))
+#endif
+
+namespace WebCore {
+
+void XSLTProcessor::genericErrorFunc(void*, const char*, ...)
+{
+ // It would be nice to do something with this error message.
+}
+
+void XSLTProcessor::parseErrorFunc(void* userData, xmlError* error)
+{
+ Console* console = static_cast<Console*>(userData);
+ if (!console)
+ return;
+
+ MessageLevel level;
+ switch (error->level) {
+ case XML_ERR_NONE:
+ level = TipMessageLevel;
+ break;
+ case XML_ERR_WARNING:
+ level = WarningMessageLevel;
+ break;
+ case XML_ERR_ERROR:
+ case XML_ERR_FATAL:
+ default:
+ level = ErrorMessageLevel;
+ break;
+ }
+
+ console->addMessage(XMLMessageSource, LogMessageType, level, error->message, error->line, error->file);
+}
+
+// FIXME: There seems to be no way to control the ctxt pointer for loading here, thus we have globals.
+static XSLTProcessor* globalProcessor = 0;
+static DocLoader* globalDocLoader = 0;
+static xmlDocPtr docLoaderFunc(const xmlChar* uri,
+ xmlDictPtr,
+ int options,
+ void* ctxt,
+ xsltLoadType type)
+{
+ if (!globalProcessor)
+ return 0;
+
+ switch (type) {
+ case XSLT_LOAD_DOCUMENT: {
+ xsltTransformContextPtr context = (xsltTransformContextPtr)ctxt;
+ xmlChar* base = xmlNodeGetBase(context->document->doc, context->node);
+ KURL url(KURL(ParsedURLString, reinterpret_cast<const char*>(base)), reinterpret_cast<const char*>(uri));
+ xmlFree(base);
+ ResourceError error;
+ ResourceResponse response;
+
+ Vector<char> data;
+
+ bool requestAllowed = globalDocLoader->frame() && globalDocLoader->doc()->securityOrigin()->canRequest(url);
+ if (requestAllowed) {
+ globalDocLoader->frame()->loader()->loadResourceSynchronously(url, AllowStoredCredentials, error, response, data);
+ requestAllowed = globalDocLoader->doc()->securityOrigin()->canRequest(response.url());
+ }
+ if (!requestAllowed) {
+ data.clear();
+ globalDocLoader->printAccessDeniedMessage(url);
+ }
+
+ Console* console = 0;
+ if (Frame* frame = globalProcessor->xslStylesheet()->ownerDocument()->frame())
+ console = frame->domWindow()->console();
+ xmlSetStructuredErrorFunc(console, XSLTProcessor::parseErrorFunc);
+ xmlSetGenericErrorFunc(console, XSLTProcessor::genericErrorFunc);
+
+ // We don't specify an encoding here. Neither Gecko nor WinIE respects
+ // the encoding specified in the HTTP headers.
+ xmlDocPtr doc = xmlReadMemory(data.data(), data.size(), (const char*)uri, 0, options);
+
+ xmlSetStructuredErrorFunc(0, 0);
+ xmlSetGenericErrorFunc(0, 0);
+
+ return doc;
+ }
+ case XSLT_LOAD_STYLESHEET:
+ return globalProcessor->xslStylesheet()->locateStylesheetSubResource(((xsltStylesheetPtr)ctxt)->doc, uri);
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static inline void setXSLTLoadCallBack(xsltDocLoaderFunc func, XSLTProcessor* processor, DocLoader* loader)
+{
+ xsltSetLoaderFunc(func);
+ globalProcessor = processor;
+ globalDocLoader = loader;
+}
+
+static int writeToVector(void* context, const char* buffer, int len)
+{
+ Vector<UChar>& resultOutput = *static_cast<Vector<UChar>*>(context);
+ String decodedChunk = String::fromUTF8(buffer, len);
+ resultOutput.append(decodedChunk.characters(), decodedChunk.length());
+ return len;
+}
+
+static bool saveResultToString(xmlDocPtr resultDoc, xsltStylesheetPtr sheet, String& resultString)
+{
+ xmlOutputBufferPtr outputBuf = xmlAllocOutputBuffer(0);
+ if (!outputBuf)
+ return false;
+
+ Vector<UChar> resultVector;
+ outputBuf->context = &resultVector;
+ outputBuf->writecallback = writeToVector;
+
+ int retval = xsltSaveResultTo(outputBuf, resultDoc, sheet);
+ xmlOutputBufferClose(outputBuf);
+ if (retval < 0)
+ return false;
+
+ // Workaround for <http://bugzilla.gnome.org/show_bug.cgi?id=495668>: libxslt appends an extra line feed to the result.
+ if (resultVector.size() > 0 && resultVector[resultVector.size() - 1] == '\n')
+ resultVector.removeLast();
+
+ resultString = String::adopt(resultVector);
+
+ return true;
+}
+
+static const char** xsltParamArrayFromParameterMap(XSLTProcessor::ParameterMap& parameters)
+{
+ if (parameters.isEmpty())
+ return 0;
+
+ const char** parameterArray = (const char**)fastMalloc(((parameters.size() * 2) + 1) * sizeof(char*));
+
+ XSLTProcessor::ParameterMap::iterator end = parameters.end();
+ unsigned index = 0;
+ for (XSLTProcessor::ParameterMap::iterator it = parameters.begin(); it != end; ++it) {
+ parameterArray[index++] = fastStrDup(it->first.utf8().data());
+ parameterArray[index++] = fastStrDup(it->second.utf8().data());
+ }
+ parameterArray[index] = 0;
+
+ return parameterArray;
+}
+
+static void freeXsltParamArray(const char** params)
+{
+ const char** temp = params;
+ if (!params)
+ return;
+
+ while (*temp) {
+ fastFree((void*)*(temp++));
+ fastFree((void*)*(temp++));
+ }
+ fastFree(params);
+}
+
+static xsltStylesheetPtr xsltStylesheetPointer(RefPtr<XSLStyleSheet>& cachedStylesheet, Node* stylesheetRootNode)
+{
+ if (!cachedStylesheet && stylesheetRootNode) {
+ cachedStylesheet = XSLStyleSheet::create(stylesheetRootNode->parent() ? stylesheetRootNode->parent() : stylesheetRootNode,
+ stylesheetRootNode->document()->url().string(),
+ stylesheetRootNode->document()->url()); // FIXME: Should we use baseURL here?
+ cachedStylesheet->parseString(createMarkup(stylesheetRootNode));
+ }
+
+ if (!cachedStylesheet || !cachedStylesheet->document())
+ return 0;
+
+ return cachedStylesheet->compileStyleSheet();
+}
+
+static inline xmlDocPtr xmlDocPtrFromNode(Node* sourceNode, bool& shouldDelete)
+{
+ RefPtr<Document> ownerDocument = sourceNode->document();
+ bool sourceIsDocument = (sourceNode == ownerDocument.get());
+
+ xmlDocPtr sourceDoc = 0;
+ if (sourceIsDocument && ownerDocument->transformSource())
+ sourceDoc = (xmlDocPtr)ownerDocument->transformSource()->platformSource();
+ if (!sourceDoc) {
+ sourceDoc = (xmlDocPtr)xmlDocPtrForString(ownerDocument->docLoader(), createMarkup(sourceNode),
+ sourceIsDocument ? ownerDocument->url().string() : String());
+ shouldDelete = sourceDoc;
+ }
+ return sourceDoc;
+}
+
+static inline String resultMIMEType(xmlDocPtr resultDoc, xsltStylesheetPtr sheet)
+{
+ // There are three types of output we need to be able to deal with:
+ // HTML (create an HTML document), XML (create an XML document),
+ // and text (wrap in a <pre> and create an XML document).
+
+ const xmlChar* resultType = 0;
+ XSLT_GET_IMPORT_PTR(resultType, sheet, method);
+ if (!resultType && resultDoc->type == XML_HTML_DOCUMENT_NODE)
+ resultType = (const xmlChar*)"html";
+
+ if (xmlStrEqual(resultType, (const xmlChar*)"html"))
+ return "text/html";
+ if (xmlStrEqual(resultType, (const xmlChar*)"text"))
+ return "text/plain";
+
+ return "application/xml";
+}
+
+bool XSLTProcessor::transformToString(Node* sourceNode, String& mimeType, String& resultString, String& resultEncoding)
+{
+ RefPtr<Document> ownerDocument = sourceNode->document();
+
+ setXSLTLoadCallBack(docLoaderFunc, this, ownerDocument->docLoader());
+ xsltStylesheetPtr sheet = xsltStylesheetPointer(m_stylesheet, m_stylesheetRootNode.get());
+ if (!sheet) {
+ setXSLTLoadCallBack(0, 0, 0);
+ return false;
+ }
+ m_stylesheet->clearDocuments();
+
+ xmlChar* origMethod = sheet->method;
+ if (!origMethod && mimeType == "text/html")
+ sheet->method = (xmlChar*)"html";
+
+ bool success = false;
+ bool shouldFreeSourceDoc = false;
+ if (xmlDocPtr sourceDoc = xmlDocPtrFromNode(sourceNode, shouldFreeSourceDoc)) {
+ // The XML declaration would prevent parsing the result as a fragment, and it's not needed even for documents,
+ // as the result of this function is always immediately parsed.
+ sheet->omitXmlDeclaration = true;
+
+ xsltTransformContextPtr transformContext = xsltNewTransformContext(sheet, sourceDoc);
+ registerXSLTExtensions(transformContext);
+
+ // <http://bugs.webkit.org/show_bug.cgi?id=16077>: XSLT processor <xsl:sort> algorithm only compares by code point
+ xsltSetCtxtSortFunc(transformContext, xsltUnicodeSortFunction);
+
+ // This is a workaround for a bug in libxslt.
+ // The bug has been fixed in version 1.1.13, so once we ship that this can be removed.
+ if (!transformContext->globalVars)
+ transformContext->globalVars = xmlHashCreate(20);
+
+ const char** params = xsltParamArrayFromParameterMap(m_parameters);
+ xsltQuoteUserParams(transformContext, params);
+ xmlDocPtr resultDoc = xsltApplyStylesheetUser(sheet, sourceDoc, 0, 0, 0, transformContext);
+
+ xsltFreeTransformContext(transformContext);
+ freeXsltParamArray(params);
+
+ if (shouldFreeSourceDoc)
+ xmlFreeDoc(sourceDoc);
+
+ if (success = saveResultToString(resultDoc, sheet, resultString)) {
+ mimeType = resultMIMEType(resultDoc, sheet);
+ resultEncoding = (char*)resultDoc->encoding;
+ }
+ xmlFreeDoc(resultDoc);
+ }
+
+ sheet->method = origMethod;
+ setXSLTLoadCallBack(0, 0, 0);
+ xsltFreeStylesheet(sheet);
+ m_stylesheet = 0;
+
+ return success;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(XSLT)
diff --git a/WebCore/xml/XSLTProcessorQt.cpp b/WebCore/xml/XSLTProcessorQt.cpp
new file mode 100644
index 0000000..9ac3f5d
--- /dev/null
+++ b/WebCore/xml/XSLTProcessorQt.cpp
@@ -0,0 +1,181 @@
+/*
+ * This file is part of the XSL implementation.
+ *
+ * Copyright (C) 2009 Jakub Wieczorek <faw217@gmail.com>
+ *
+ * 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.
+ */
+
+#include "config.h"
+
+#if ENABLE(XSLT)
+
+#include "XSLTProcessor.h"
+
+#include "Console.h"
+#include "DOMWindow.h"
+#include "Frame.h"
+#include "TransformSource.h"
+#include "loader.h"
+#include "markup.h"
+#include <wtf/Assertions.h>
+#include <wtf/Platform.h>
+#include <wtf/Vector.h>
+
+#include <qabstractmessagehandler.h>
+#include <qabstracturiresolver.h>
+#include <qbuffer.h>
+#include <qsourcelocation.h>
+#include <qxmlquery.h>
+
+namespace WebCore {
+
+class XSLTMessageHandler : public QAbstractMessageHandler {
+
+public:
+ XSLTMessageHandler(Document* document = 0);
+ virtual void handleMessage(QtMsgType type, const QString& description,
+ const QUrl& identifier, const QSourceLocation& sourceLocation);
+
+private:
+ Document* m_document;
+};
+
+XSLTMessageHandler::XSLTMessageHandler(Document* document)
+ : QAbstractMessageHandler()
+ , m_document(document)
+{
+}
+
+void XSLTMessageHandler::handleMessage(QtMsgType type, const QString& description,
+ const QUrl&, const QSourceLocation& sourceLocation)
+{
+ if (!m_document->frame())
+ return;
+
+ MessageLevel level;
+ switch (type) {
+ case QtDebugMsg:
+ level = TipMessageLevel;
+ break;
+ case QtWarningMsg:
+ level = WarningMessageLevel;
+ break;
+ case QtCriticalMsg:
+ case QtFatalMsg:
+ level = ErrorMessageLevel;
+ break;
+ default:
+ level = LogMessageLevel;
+ break;
+ }
+
+ Console* console = m_document->frame()->domWindow()->console();
+ console->addMessage(XMLMessageSource, LogMessageType, level, description,
+ sourceLocation.line(), sourceLocation.uri().toString());
+}
+
+class XSLTUriResolver : public QAbstractUriResolver {
+
+public:
+ XSLTUriResolver(Document* document);
+ virtual QUrl resolve(const QUrl& relative, const QUrl& baseURI) const;
+
+private:
+ Document* m_document;
+};
+
+XSLTUriResolver::XSLTUriResolver(Document* document)
+ : QAbstractUriResolver()
+ , m_document(document)
+{
+}
+
+QUrl XSLTUriResolver::resolve(const QUrl& relative, const QUrl& baseURI) const
+{
+ QUrl url = baseURI.resolved(relative);
+
+ if (!m_document->frame() || !m_document->securityOrigin()->canRequest(url))
+ return QUrl();
+ return url;
+}
+
+bool XSLTProcessor::transformToString(Node* sourceNode, String&, String& resultString, String&)
+{
+ bool success = false;
+
+ RefPtr<XSLStyleSheet> stylesheet = m_stylesheet;
+ if (!stylesheet && m_stylesheetRootNode) {
+ Node* node = m_stylesheetRootNode.get();
+ stylesheet = XSLStyleSheet::create(node->parent() ? node->parent() : node,
+ node->document()->url().string(),
+ node->document()->url()); // FIXME: Should we use baseURL here?
+ stylesheet->parseString(createMarkup(node));
+ }
+
+ if (!stylesheet || stylesheet->sheetString().isEmpty())
+ return success;
+
+ RefPtr<Document> ownerDocument = sourceNode->document();
+ bool sourceIsDocument = (sourceNode == ownerDocument.get());
+
+ QXmlQuery query(QXmlQuery::XSLT20);
+
+ XSLTMessageHandler messageHandler(ownerDocument.get());
+ XSLTUriResolver uriResolver(ownerDocument.get());
+ query.setMessageHandler(&messageHandler);
+
+ XSLTProcessor::ParameterMap::iterator end = m_parameters.end();
+ for (XSLTProcessor::ParameterMap::iterator it = m_parameters.begin(); it != end; ++it)
+ query.bindVariable(QString(it->first), QXmlItem(QVariant(it->second)));
+
+ QString source;
+ if (sourceIsDocument && ownerDocument->transformSource())
+ source = ownerDocument->transformSource()->platformSource();
+ if (!sourceIsDocument || source.isEmpty())
+ source = createMarkup(sourceNode);
+
+ QBuffer inputBuffer;
+ QBuffer styleSheetBuffer;
+ QBuffer outputBuffer;
+
+ inputBuffer.setData(source.toUtf8());
+ styleSheetBuffer.setData(QString(stylesheet->sheetString()).toUtf8());
+
+ inputBuffer.open(QIODevice::ReadOnly);
+ styleSheetBuffer.open(QIODevice::ReadOnly);
+ outputBuffer.open(QIODevice::ReadWrite);
+
+ query.setFocus(&inputBuffer);
+ query.setQuery(&styleSheetBuffer, QUrl(stylesheet->href()));
+
+ query.setUriResolver(&uriResolver);
+
+ success = query.evaluateTo(&outputBuffer);
+ outputBuffer.reset();
+ resultString = QString::fromUtf8(outputBuffer.readAll()).trimmed();
+
+ if (m_stylesheet) {
+ m_stylesheet->clearDocuments();
+ m_stylesheet = 0;
+ }
+
+ return success;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(XSLT)
diff --git a/WebCore/xml/xmlnsattrs.in b/WebCore/xml/xmlnsattrs.in
new file mode 100644
index 0000000..7ac415a
--- /dev/null
+++ b/WebCore/xml/xmlnsattrs.in
@@ -0,0 +1,4 @@
+namespace="XMLNS"
+namespaceURI="http://www.w3.org/2000/xmlns/"
+
+xmlns