diff options
author | Andrei Popescu <andreip@google.com> | 2009-08-19 14:09:30 +0100 |
---|---|---|
committer | Andrei Popescu <andreip@google.com> | 2009-08-19 14:09:30 +0100 |
commit | 058ccc7ba0a4d59b9f6e92808332aa9895425fc7 (patch) | |
tree | 276aad5a2bbc2fd7d65d21bfca42c9de88b3dd20 /WebCore/xml | |
parent | 2796dd1bf3b4b01e7e1d96ea91bd3a212f647579 (diff) | |
download | external_webkit-058ccc7ba0a4d59b9f6e92808332aa9895425fc7.zip external_webkit-058ccc7ba0a4d59b9f6e92808332aa9895425fc7.tar.gz external_webkit-058ccc7ba0a4d59b9f6e92808332aa9895425fc7.tar.bz2 |
Revert "Merge WebKit r47420"
This reverts commit d227fc870c7a697500a3c900c31baf05fb9a8524.
Diffstat (limited to 'WebCore/xml')
-rw-r--r-- | WebCore/xml/XMLHttpRequest.cpp | 323 | ||||
-rw-r--r-- | WebCore/xml/XMLHttpRequest.h | 20 | ||||
-rw-r--r-- | WebCore/xml/XPathNamespace.cpp | 10 | ||||
-rw-r--r-- | WebCore/xml/XPathNamespace.h | 13 | ||||
-rw-r--r-- | WebCore/xml/XSLTProcessor.cpp | 4 |
5 files changed, 315 insertions, 55 deletions
diff --git a/WebCore/xml/XMLHttpRequest.cpp b/WebCore/xml/XMLHttpRequest.cpp index 0b2fabb..5e20252 100644 --- a/WebCore/xml/XMLHttpRequest.cpp +++ b/WebCore/xml/XMLHttpRequest.cpp @@ -25,6 +25,7 @@ #include "Cache.h" #include "CString.h" #include "CrossOriginAccessControl.h" +#include "CrossOriginPreflightResultCache.h" #include "DOMImplementation.h" #include "Document.h" #include "Event.h" @@ -92,25 +93,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'); } @@ -142,9 +143,9 @@ 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) @@ -206,7 +207,7 @@ Document* XMLHttpRequest::responseXML() const m_responseXML->write(String(m_responseText)); m_responseXML->finishParsing(); m_responseXML->close(); - + if (!m_responseXML->wellFormed()) m_responseXML = 0; } @@ -235,7 +236,7 @@ void XMLHttpRequest::addEventListener(const AtomicString& eventType, PassRefPtr< for (ListenerVector::iterator listenerIter = listeners.begin(); listenerIter != listeners.end(); ++listenerIter) if (*listenerIter == eventListener) return; - + listeners.append(eventListener); m_eventListeners.add(eventType, listeners); } @@ -321,10 +322,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; @@ -334,7 +335,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 @@ -356,7 +357,7 @@ void XMLHttpRequest::open(const String& method, const KURL& url, bool async, con { KURL urlWithCredentials(url); urlWithCredentials.setUser(user); - + open(method, urlWithCredentials, async, ec); } @@ -365,7 +366,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); } @@ -462,23 +463,34 @@ void XMLHttpRequest::send(File* body, ExceptionCode& ec) void XMLHttpRequest::createRequest(ExceptionCode& ec) { - // 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. + // 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. // Also, only async requests support upload progress events. - bool forcePreflight = false; + m_uploadEventsAllowed = false; if (m_async) { dispatchLoadStartEvent(); if (m_requestEntityBody && m_upload) { - forcePreflight = m_upload->hasListeners(); + m_uploadEventsAllowed = m_upload->hasListeners(); m_upload->dispatchLoadStartEvent(); } } m_sameOriginRequest = scriptExecutionContext()->securityOrigin()->canRequest(m_url); - // 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); + if (!m_sameOriginRequest) { + makeCrossOriginAccessRequest(ec); + return; + } + + m_uploadEventsAllowed = true; + + makeSameOriginRequest(ec); +} + +void XMLHttpRequest::makeSameOriginRequest(ExceptionCode& ec) +{ + ASSERT(m_sameOriginRequest); ResourceRequest request(m_url); request.setHTTPMethod(m_method); @@ -492,28 +504,202 @@ void XMLHttpRequest::createRequest(ExceptionCode& ec) if (m_requestHeaders.size() > 0) request.addHTTPHeaderFields(m_requestHeaders); - ThreadableLoaderOptions options; - options.sendLoadCallbacks = true; - options.sniffContent = false; - options.forcePreflight = forcePreflight; - options.allowCredentials = m_sameOriginRequest || m_includeCredentials; - options.crossOriginRequestPolicy = UseAccessControl; + if (m_async) + loadRequestAsynchronously(request); + else + loadRequestSynchronously(request, ec); +} - m_exceptionCode = 0; - m_error = false; +void XMLHttpRequest::makeCrossOriginAccessRequest(ExceptionCode& ec) +{ + ASSERT(!m_sameOriginRequest); + + 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); +} + +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); + } + + preflightRequest.setHTTPHeaderField("Access-Control-Request-Headers", String::adopt(headerBuffer)); + preflightRequest.addHTTPHeaderFields(m_requestHeaders); + } + + 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) { - request.setReportUploadProgress(true); - setPendingActivity(this); - m_loader = ThreadableLoader::create(scriptExecutionContext(), this, request, options); - } else - ThreadableLoader::loadResourceSynchronously(scriptExecutionContext(), request, *this, options); + 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. @@ -525,7 +711,7 @@ void XMLHttpRequest::abort() // Clear headers as required by the spec m_requestHeaders.clear(); - + if ((m_state <= OPENED && !sendFlag) || m_state == DONE) m_state = UNSENT; else { @@ -608,7 +794,7 @@ void XMLHttpRequest::abortError() } } -void XMLHttpRequest::dropProtection() +void XMLHttpRequest::dropProtection() { #if USE(JSC) // The XHR object itself holds on to the responseText, and @@ -668,7 +854,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; } @@ -753,7 +939,7 @@ String XMLHttpRequest::responseMIMEType() const } if (mimeType.isEmpty()) mimeType = "text/xml"; - + return mimeType; } @@ -795,7 +981,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; @@ -825,6 +1011,11 @@ void XMLHttpRequest::didFinishLoading(unsigned long identifier) if (m_error) return; + if (m_inPreflight) { + didFinishLoadingPreflight(); + return; + } + if (m_state < HEADERS_RECEIVED) changeState(HEADERS_RECEIVED); @@ -844,6 +1035,19 @@ 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) @@ -861,12 +1065,45 @@ void XMLHttpRequest::didSendData(unsigned long long bytesSent, unsigned long lon 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; @@ -874,12 +1111,12 @@ void XMLHttpRequest::didReceiveAuthenticationCancellation(const ResourceResponse void XMLHttpRequest::didReceiveData(const char* data, int len) { - if (m_error) + if (m_inPreflight || 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); @@ -973,7 +1210,7 @@ void XMLHttpRequest::dispatchLoadStartEvent() void XMLHttpRequest::dispatchProgressEvent(long long expectedLength) { - dispatchXMLHttpRequestProgressEvent(m_onProgressListener.get(), eventNames().progressEvent, expectedLength && m_receivedLength <= expectedLength, + dispatchXMLHttpRequestProgressEvent(m_onProgressListener.get(), eventNames().progressEvent, expectedLength && m_receivedLength <= expectedLength, static_cast<unsigned>(m_receivedLength), static_cast<unsigned>(expectedLength)); } @@ -998,4 +1235,4 @@ ScriptExecutionContext* XMLHttpRequest::scriptExecutionContext() const return ActiveDOMObject::scriptExecutionContext(); } -} // namespace WebCore +} // namespace WebCore diff --git a/WebCore/xml/XMLHttpRequest.h b/WebCore/xml/XMLHttpRequest.h index aa33b8b..d581d3d 100644 --- a/WebCore/xml/XMLHttpRequest.h +++ b/WebCore/xml/XMLHttpRequest.h @@ -117,7 +117,7 @@ public: private: XMLHttpRequest(ScriptExecutionContext*); - + virtual void refEventTarget() { ref(); } virtual void derefEventTarget() { deref(); } @@ -135,6 +135,10 @@ 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; @@ -155,6 +159,16 @@ 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(); @@ -209,11 +223,13 @@ 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; diff --git a/WebCore/xml/XPathNamespace.cpp b/WebCore/xml/XPathNamespace.cpp index 9646402..3c8c42c 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, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2006 Apple Computer, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -33,14 +33,18 @@ namespace WebCore { -XPathNamespace::XPathNamespace(PassRefPtr<Element> ownerElement, const AtomicString& prefix, const AtomicString& uri) - : Node(ownerElement->document(), CreateOther) +XPathNamespace::XPathNamespace(PassRefPtr<Element> ownerElement, const String& prefix, const String& uri) + : Node(ownerElement->document()) , 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 996cb9a..c0e4280 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, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2006 Apple Computer, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -34,11 +34,13 @@ namespace WebCore { - // FIXME: This class is never instantiated. Maybe it should be removed. + class Document; + class Element; class XPathNamespace : public Node { - private: - XPathNamespace(PassRefPtr<Element> ownerElement, const AtomicString& prefix, const AtomicString& uri); + public: + XPathNamespace(PassRefPtr<Element> ownerElement, const String& prefix, const String& uri); + virtual ~XPathNamespace(); virtual Document* ownerDocument() const; virtual Element* ownerElement() const; @@ -48,8 +50,9 @@ namespace WebCore { virtual String nodeValue() const; virtual const AtomicString& namespaceURI() const; - virtual NodeType nodeType() const; + virtual Node::NodeType nodeType() const; + private: RefPtr<Element> m_ownerElement; AtomicString m_prefix; AtomicString m_uri; diff --git a/WebCore/xml/XSLTProcessor.cpp b/WebCore/xml/XSLTProcessor.cpp index 9fdf31f..a26fe77 100644 --- a/WebCore/xml/XSLTProcessor.cpp +++ b/WebCore/xml/XSLTProcessor.cpp @@ -285,12 +285,12 @@ PassRefPtr<Document> XSLTProcessor::createDocumentFromSource(const String& sourc static inline RefPtr<DocumentFragment> createFragmentFromSource(const String& sourceString, const String& sourceMIMEType, Document* outputDoc) { - RefPtr<DocumentFragment> fragment = DocumentFragment::create(outputDoc); + RefPtr<DocumentFragment> fragment = new DocumentFragment(outputDoc); if (sourceMIMEType == "text/html") parseHTMLDocumentFragment(sourceString, fragment.get()); else if (sourceMIMEType == "text/plain") - fragment->addChild(Text::create(outputDoc, sourceString)); + fragment->addChild(new Text(outputDoc, sourceString)); else { bool successfulParse = parseXMLDocumentFragment(sourceString, fragment.get(), outputDoc->documentElement()); if (!successfulParse) |