Commit cb6e4560 authored by tonyg@chromium.org's avatar tonyg@chromium.org

Call XSSAuditor's didBlockScript() for the threaded HTML parser

https://bugs.webkit.org/show_bug.cgi?id=108726

Reviewed by Adam Barth.

Source/WebCore:

This patch causes us to call didBlockScript() on the main thread if the CompactHTML token has XSSInfo.
To do so, we:
1. Rename DidBlockScriptRequest to XSSInfo.
2. Add an OwnPtr<XSSInfo> field to CompactHTMLToken.
3. Add an isSafeToSendToAnotherThread() method to String and KURL.

We don't yet populate didBlockScriptRequest on the background thread, but this should just work once we do.

No new tests because no new functionality.

* html/parser/BackgroundHTMLParser.cpp:
(WebCore::BackgroundHTMLParser::pumpTokenizer): Update comment for rename.
* html/parser/CompactHTMLToken.cpp:
(SameSizeAsCompactHTMLToken):
(WebCore::CompactHTMLToken::CompactHTMLToken): Add a copy constructor used by Vector.
(WebCore::CompactHTMLToken::isSafeToSendToAnotherThread): Include new m_xssInfo field in safety check.
(WebCore):
(WebCore::CompactHTMLToken::xssInfo): Added.
(WebCore::CompactHTMLToken::setXSSInfo): Added.
* html/parser/CompactHTMLToken.h: Add an OwnPtr<XSSInfo> field to CompactHTMLToken.
(WebCore):
(CompactHTMLToken):
(WTF): Add VectorTraits necessary for copying Vector fields objects that contain an OwnPtr.
* html/parser/HTMLDocumentParser.cpp:
(WebCore::HTMLDocumentParser::processParsedChunkFromBackgroundParser): Add new didBlockScript() call.
(WebCore::HTMLDocumentParser::pumpTokenizer):
* html/parser/XSSAuditor.cpp: Renaming.
(WebCore::XSSAuditor::filterToken):
* html/parser/XSSAuditor.h: Renaming.
(WebCore):
(XSSAuditor):
* html/parser/XSSAuditorDelegate.cpp:
(WebCore::XSSInfo::isSafeToSendToAnotherThread):
(WebCore):
(WebCore::XSSAuditorDelegate::didBlockScript):
* html/parser/XSSAuditorDelegate.h:
(WebCore::XSSInfo::create):
(XSSInfo):
(WebCore::XSSInfo::XSSInfo):
(XSSAuditorDelegate):
* platform/KURL.cpp:
(WebCore::KURL::isSafeToSendToAnotherThread): Added.
(WebCore):
* platform/KURL.h:
(KURL):
* platform/KURLGoogle.cpp:
(WebCore):
(WebCore::KURLGooglePrivate::isSafeToSendToAnotherThread): Added.
* platform/KURLGooglePrivate.h:
(KURLGooglePrivate):
* platform/KURLWTFURLImpl.h:
(WebCore::KURLWTFURLImpl::isSafeToSendToAnotherThread): Added.

Source/WTF:

This patch adds isSafeToSendToAnotherThread() methods to CString, String, ParsedURL and URLString.
These methods check to ensure there are 0 or 1 references.

* wtf/text/CString.cpp:
(WTF::CString::isSafeToSendToAnotherThread): Added.
(WTF):
* wtf/text/CString.h:
(CString):
* wtf/text/WTFString.cpp:
(WTF::String::isSafeToSendToAnotherThread): Added.
(WTF):
* wtf/text/WTFString.h:
(String):
* wtf/url/api/ParsedURL.h:
(WTF::ParsedURL::isSafeToSendToAnotherThread): Added.
* wtf/url/api/URLString.h:
(WTF::URLString::isSafeToSendToAnotherThread): Added.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@141905 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent d8ec6409
2013-02-05 Tony Gentilcore <tonyg@chromium.org>
Call XSSAuditor's didBlockScript() for the threaded HTML parser
https://bugs.webkit.org/show_bug.cgi?id=108726
Reviewed by Adam Barth.
This patch adds isSafeToSendToAnotherThread() methods to CString, String, ParsedURL and URLString.
These methods check to ensure there are 0 or 1 references.
* wtf/text/CString.cpp:
(WTF::CString::isSafeToSendToAnotherThread): Added.
(WTF):
* wtf/text/CString.h:
(CString):
* wtf/text/WTFString.cpp:
(WTF::String::isSafeToSendToAnotherThread): Added.
(WTF):
* wtf/text/WTFString.h:
(String):
* wtf/url/api/ParsedURL.h:
(WTF::ParsedURL::isSafeToSendToAnotherThread): Added.
* wtf/url/api/URLString.h:
(WTF::URLString::isSafeToSendToAnotherThread): Added.
2013-02-04 Benjamin Poulain <bpoulain@apple.com>
Build fix for AtomicString on iOS
......
......@@ -99,6 +99,11 @@ void CString::copyBufferIfNeeded()
memcpy(m_buffer->mutableData(), buffer->data(), length + 1);
}
bool CString::isSafeToSendToAnotherThread() const
{
return !m_buffer || m_buffer->hasOneRef();
}
bool operator==(const CString& a, const CString& b)
{
if (a.isNull() != b.isNull())
......
......@@ -72,6 +72,7 @@ public:
}
bool isNull() const { return !m_buffer; }
bool isSafeToSendToAnotherThread() const;
CStringBuffer* buffer() const { return m_buffer.get(); }
......
......@@ -661,6 +661,17 @@ String String::isolatedCopy() const
return m_impl->isolatedCopy();
}
bool String::isSafeToSendToAnotherThread() const
{
if (!impl())
return true;
if (impl()->hasOneRef())
return true;
if (isEmpty())
return true;
return false;
}
void String::split(const String& separator, bool allowEmptyEntries, Vector<String>& result) const
{
result.clear();
......
......@@ -394,6 +394,7 @@ public:
bool percentage(int& percentage) const;
WTF_EXPORT_STRING_API String isolatedCopy() const;
bool isSafeToSendToAnotherThread() const;
// Prevent Strings from being implicitly convertable to bool as it will be ambiguous on any platform that
// allows implicit conversion to another pointer type (e.g., Mac allows implicit conversion to NSString*).
......
......@@ -49,6 +49,7 @@ public:
WTF_EXPORT_PRIVATE explicit ParsedURL(const ParsedURL& base, const String& relative, URLQueryCharsetConverter*);
WTF_EXPORT_PRIVATE ParsedURL isolatedCopy() const;
bool isSafeToSendToAnotherThread() const { return m_spec.isSafeToSendToAnotherThread(); }
bool isValid() const { return !m_spec.string().isNull(); }
......
......@@ -39,6 +39,7 @@ public:
URLString() { }
const String& string() const { return m_string;}
bool isSafeToSendToAnotherThread() const { return m_string.isSafeToSendToAnotherThread(); }
#ifndef NDEBUG
WTF_EXPORT_PRIVATE void print() const;
......
2013-02-05 Tony Gentilcore <tonyg@chromium.org>
Call XSSAuditor's didBlockScript() for the threaded HTML parser
https://bugs.webkit.org/show_bug.cgi?id=108726
Reviewed by Adam Barth.
This patch causes us to call didBlockScript() on the main thread if the CompactHTML token has XSSInfo.
To do so, we:
1. Rename DidBlockScriptRequest to XSSInfo.
2. Add an OwnPtr<XSSInfo> field to CompactHTMLToken.
3. Add an isSafeToSendToAnotherThread() method to String and KURL.
We don't yet populate didBlockScriptRequest on the background thread, but this should just work once we do.
No new tests because no new functionality.
* html/parser/BackgroundHTMLParser.cpp:
(WebCore::BackgroundHTMLParser::pumpTokenizer): Update comment for rename.
* html/parser/CompactHTMLToken.cpp:
(SameSizeAsCompactHTMLToken):
(WebCore::CompactHTMLToken::CompactHTMLToken): Add a copy constructor used by Vector.
(WebCore::CompactHTMLToken::isSafeToSendToAnotherThread): Include new m_xssInfo field in safety check.
(WebCore):
(WebCore::CompactHTMLToken::xssInfo): Added.
(WebCore::CompactHTMLToken::setXSSInfo): Added.
* html/parser/CompactHTMLToken.h: Add an OwnPtr<XSSInfo> field to CompactHTMLToken.
(WebCore):
(CompactHTMLToken):
(WTF): Add VectorTraits necessary for copying Vector fields objects that contain an OwnPtr.
* html/parser/HTMLDocumentParser.cpp:
(WebCore::HTMLDocumentParser::processParsedChunkFromBackgroundParser): Add new didBlockScript() call.
(WebCore::HTMLDocumentParser::pumpTokenizer):
* html/parser/XSSAuditor.cpp: Renaming.
(WebCore::XSSAuditor::filterToken):
* html/parser/XSSAuditor.h: Renaming.
(WebCore):
(XSSAuditor):
* html/parser/XSSAuditorDelegate.cpp:
(WebCore::XSSInfo::isSafeToSendToAnotherThread):
(WebCore):
(WebCore::XSSAuditorDelegate::didBlockScript):
* html/parser/XSSAuditorDelegate.h:
(WebCore::XSSInfo::create):
(XSSInfo):
(WebCore::XSSInfo::XSSInfo):
(XSSAuditorDelegate):
* platform/KURL.cpp:
(WebCore::KURL::isSafeToSendToAnotherThread): Added.
(WebCore):
* platform/KURL.h:
(KURL):
* platform/KURLGoogle.cpp:
(WebCore):
(WebCore::KURLGooglePrivate::isSafeToSendToAnotherThread): Added.
* platform/KURLGooglePrivate.h:
(KURLGooglePrivate):
* platform/KURLWTFURLImpl.h:
(WebCore::KURLWTFURLImpl::isSafeToSendToAnotherThread): Added.
2013-02-05 Anton Vayvod <avayvod@chromium.org>
TextAutosizing: adjust the maximum difference between cluster text width and its descendant
......@@ -153,7 +153,7 @@ bool BackgroundHTMLParser::simulateTreeBuilder(const CompactHTMLToken& token)
void BackgroundHTMLParser::pumpTokenizer()
{
while (m_tokenizer->nextToken(m_input.current(), *m_token.get())) {
// FIXME: Call m_xssAuditor.filterToken(m_token) and put resulting DidBlockScriptRequest into CompactHTMLToken.
// FIXME: Call m_xssAuditor.filterToken(m_token) and put resulting XSSInfo into CompactHTMLToken.
m_pendingTokens->append(CompactHTMLToken(m_token.get(), TextPosition(m_input.current().currentLine(), m_input.current().currentColumn())));
m_token->clear();
......
......@@ -30,6 +30,7 @@
#include "CompactHTMLToken.h"
#include "HTMLToken.h"
#include "XSSAuditorDelegate.h"
namespace WebCore {
......@@ -38,6 +39,7 @@ struct SameSizeAsCompactHTMLToken {
String name;
Vector<CompactAttribute> vector;
TextPosition textPosition;
OwnPtr<XSSInfo> xssInfo;
};
COMPILE_ASSERT(sizeof(CompactHTMLToken) == sizeof(SameSizeAsCompactHTMLToken), CompactHTMLToken_should_stay_small);
......@@ -86,27 +88,37 @@ CompactHTMLToken::CompactHTMLToken(const HTMLToken* token, const TextPosition& t
}
}
static bool isStringSafeToSendToAnotherThread(const String& string)
CompactHTMLToken::CompactHTMLToken(const CompactHTMLToken& other)
: m_type(other.type())
, m_isAll8BitData(other.isAll8BitData())
, m_doctypeForcesQuirks(other.doctypeForcesQuirks())
, m_textPosition(other.textPosition())
{
StringImpl* impl = string.impl();
if (!impl)
return true;
if (impl->hasOneRef())
return true;
if (string.isEmpty())
return true;
return false;
if (other.xssInfo())
m_xssInfo = adoptPtr(new XSSInfo(*other.xssInfo()));
}
bool CompactHTMLToken::isSafeToSendToAnotherThread() const
{
for (Vector<CompactAttribute>::const_iterator it = m_attributes.begin(); it != m_attributes.end(); ++it) {
if (!isStringSafeToSendToAnotherThread(it->name()))
if (!it->name().isSafeToSendToAnotherThread())
return false;
if (!isStringSafeToSendToAnotherThread(it->value()))
if (!it->value().isSafeToSendToAnotherThread())
return false;
}
return isStringSafeToSendToAnotherThread(m_data);
if (m_xssInfo && !m_xssInfo->isSafeToSendToAnotherThread())
return false;
return m_data.isSafeToSendToAnotherThread();
}
XSSInfo* CompactHTMLToken::xssInfo() const
{
return m_xssInfo.get();
}
void CompactHTMLToken::setXSSInfo(PassOwnPtr<XSSInfo> xssInfo)
{
m_xssInfo = xssInfo;
}
}
......
......@@ -29,6 +29,8 @@
#if ENABLE(THREADED_HTML_PARSER)
#include "HTMLTokenTypes.h"
#include <wtf/OwnPtr.h>
#include <wtf/PassOwnPtr.h>
#include <wtf/RefCounted.h>
#include <wtf/RefPtr.h>
#include <wtf/Vector.h>
......@@ -38,6 +40,7 @@
namespace WebCore {
class HTMLToken;
class XSSInfo;
class CompactAttribute {
public:
......@@ -58,6 +61,7 @@ private:
class CompactHTMLToken {
public:
CompactHTMLToken(const HTMLToken*, const TextPosition&);
CompactHTMLToken(const CompactHTMLToken&);
bool isSafeToSendToAnotherThread() const;
......@@ -73,6 +77,8 @@ public:
const String& publicIdentifier() const { return m_attributes[0].name(); }
const String& systemIdentifier() const { return m_attributes[0].value(); }
bool doctypeForcesQuirks() const { return m_doctypeForcesQuirks; }
XSSInfo* xssInfo() const;
void setXSSInfo(PassOwnPtr<XSSInfo>);
private:
unsigned m_type : 4;
......@@ -83,12 +89,19 @@ private:
String m_data; // "name", "characters", or "data" depending on m_type
Vector<CompactAttribute> m_attributes;
TextPosition m_textPosition;
OwnPtr<XSSInfo> m_xssInfo;
};
typedef Vector<CompactHTMLToken> CompactHTMLTokenStream;
}
namespace WTF {
// This is required for a struct with OwnPtr. We know CompactHTMLToken is simple enough that
// initializing to 0 and moving with memcpy (and then not destructing the original) will work.
template<> struct VectorTraits<WebCore::CompactHTMLToken> : SimpleClassVectorTraits { };
}
#endif // ENABLE(THREADED_HTML_PARSER)
#endif
......@@ -302,7 +302,7 @@ void HTMLDocumentParser::processParsedChunkFromBackgroundParser(PassOwnPtr<Parse
{
ASSERT(shouldUseThreading());
// didReceiveTokensFromBackgroundParser can cause this parser to be detached from the Document,
// This method can cause this parser to be detached from the Document,
// but we need to ensure it isn't deleted yet.
RefPtr<HTMLDocumentParser> protect(this);
......@@ -316,8 +316,10 @@ void HTMLDocumentParser::processParsedChunkFromBackgroundParser(PassOwnPtr<Parse
for (Vector<CompactHTMLToken>::const_iterator it = tokens->begin(); it != tokens->end(); ++it) {
ASSERT(!isWaitingForScripts());
// FIXME: Call m_xssAuditorDelegate.didBlockScript() with DidBlockScriptRequest from the CompactHTMLToken.
m_textPosition = it->textPosition();
if (XSSInfo* xssInfo = it->xssInfo())
m_xssAuditorDelegate.didBlockScript(*xssInfo);
constructTreeFromCompactHTMLToken(*it);
if (isStopped())
......@@ -378,9 +380,9 @@ void HTMLDocumentParser::pumpTokenizer(SynchronousMode mode)
// We do not XSS filter innerHTML, which means we (intentionally) fail
// http/tests/security/xssAuditor/dom-write-innerHTML.html
OwnPtr<DidBlockScriptRequest> request = m_xssAuditor.filterToken(FilterTokenRequest(token(), m_sourceTracker, document()->decoder()));
if (request)
m_xssAuditorDelegate.didBlockScript(request.release());
OwnPtr<XSSInfo> xssInfo = m_xssAuditor.filterToken(FilterTokenRequest(token(), m_sourceTracker, document()->decoder()));
if (xssInfo)
m_xssAuditorDelegate.didBlockScript(*xssInfo);
}
constructTreeFromHTMLToken(token());
......
......@@ -278,7 +278,7 @@ void XSSAuditor::init(Document* document)
}
}
PassOwnPtr<DidBlockScriptRequest> XSSAuditor::filterToken(const FilterTokenRequest& request)
PassOwnPtr<XSSInfo> XSSAuditor::filterToken(const FilterTokenRequest& request)
{
ASSERT(m_state == Initialized);
if (!m_isEnabled || m_xssProtection == XSSProtectionDisabled)
......@@ -296,13 +296,13 @@ PassOwnPtr<DidBlockScriptRequest> XSSAuditor::filterToken(const FilterTokenReque
if (didBlockScript) {
bool didBlockEntirePage = (m_xssProtection == XSSProtectionBlockEnabled);
OwnPtr<DidBlockScriptRequest> didBlockScriptRequest = DidBlockScriptRequest::create(m_reportURL, m_originalURL, m_originalHTTPBody, didBlockEntirePage);
OwnPtr<XSSInfo> xssInfo = XSSInfo::create(m_reportURL, m_originalURL, m_originalHTTPBody, didBlockEntirePage);
if (!m_reportURL.isEmpty()) {
m_reportURL = KURL();
m_originalURL = String();
m_originalHTTPBody = String();
}
return didBlockScriptRequest.release();
return xssInfo.release();
}
return nullptr;
}
......
......@@ -33,11 +33,11 @@
namespace WebCore {
class DidBlockScriptRequest;
class Document;
class HTMLDocumentParser;
class HTMLSourceTracker;
class TextResourceDecoder;
class XSSInfo;
struct FilterTokenRequest {
FilterTokenRequest(HTMLToken& token, HTMLSourceTracker& sourceTracker, const TextResourceDecoder* decoder)
......@@ -57,7 +57,7 @@ public:
explicit XSSAuditor(HTMLDocumentParser*);
void init(Document*);
PassOwnPtr<DidBlockScriptRequest> filterToken(const FilterTokenRequest&);
PassOwnPtr<XSSInfo> filterToken(const FilterTokenRequest&);
private:
static const size_t kMaximumFragmentLengthTarget = 100;
......
......@@ -32,12 +32,20 @@
#include "FormData.h"
#include "Frame.h"
#include "FrameLoaderClient.h"
#include "HTMLParserIdioms.h"
#include "InspectorValues.h"
#include "PingLoader.h"
#include "SecurityOrigin.h"
namespace WebCore {
bool XSSInfo::isSafeToSendToAnotherThread() const
{
return m_reportURL.isSafeToSendToAnotherThread()
&& m_originalURL.isSafeToSendToAnotherThread()
&& m_originalHTTPBody.isSafeToSendToAnotherThread();
}
XSSAuditorDelegate::XSSAuditorDelegate(Document* document)
: m_document(document)
, m_didNotifyClient(false)
......@@ -46,7 +54,7 @@ XSSAuditorDelegate::XSSAuditorDelegate(Document* document)
ASSERT(m_document);
}
void XSSAuditorDelegate::didBlockScript(PassOwnPtr<DidBlockScriptRequest> request)
void XSSAuditorDelegate::didBlockScript(const XSSInfo& xssInfo)
{
ASSERT(isMainThread());
......@@ -54,27 +62,27 @@ void XSSAuditorDelegate::didBlockScript(PassOwnPtr<DidBlockScriptRequest> reques
DEFINE_STATIC_LOCAL(String, consoleMessage, (ASCIILiteral("Refused to execute a JavaScript script. Source code of script found within request.\n")));
m_document->addConsoleMessage(JSMessageSource, ErrorMessageLevel, consoleMessage);
if (request->m_didBlockEntirePage)
if (xssInfo.m_didBlockEntirePage)
m_document->frame()->loader()->stopAllLoaders();
if (!m_didNotifyClient) {
m_document->frame()->loader()->client()->didDetectXSS(m_document->url(), request->m_didBlockEntirePage);
m_document->frame()->loader()->client()->didDetectXSS(m_document->url(), xssInfo.m_didBlockEntirePage);
m_didNotifyClient = true;
}
if (!request->m_reportURL.isEmpty()) {
if (!xssInfo.m_reportURL.isEmpty()) {
RefPtr<InspectorObject> reportDetails = InspectorObject::create();
reportDetails->setString("request-url", request->m_originalURL);
reportDetails->setString("request-body", request->m_originalHTTPBody);
reportDetails->setString("request-url", xssInfo.m_originalURL);
reportDetails->setString("request-body", xssInfo.m_originalHTTPBody);
RefPtr<InspectorObject> reportObject = InspectorObject::create();
reportObject->setObject("xss-report", reportDetails.release());
RefPtr<FormData> report = FormData::create(reportObject->toJSONString().utf8().data());
PingLoader::sendViolationReport(m_document->frame(), request->m_reportURL, report);
PingLoader::sendViolationReport(m_document->frame(), xssInfo.m_reportURL, report);
}
if (request->m_didBlockEntirePage)
if (xssInfo.m_didBlockEntirePage)
m_document->frame()->navigationScheduler()->scheduleLocationChange(m_document->securityOrigin(), blankURL(), String());
}
......
......@@ -34,20 +34,22 @@ namespace WebCore {
class Document;
class DidBlockScriptRequest {
class XSSInfo {
public:
static PassOwnPtr<DidBlockScriptRequest> create(const KURL& reportURL, const String& originalURL, const String& originalHTTPBody, bool didBlockEntirePage)
static PassOwnPtr<XSSInfo> create(const KURL& reportURL, const String& originalURL, const String& originalHTTPBody, bool didBlockEntirePage)
{
return adoptPtr(new DidBlockScriptRequest(reportURL, originalURL, originalHTTPBody, didBlockEntirePage));
return adoptPtr(new XSSInfo(reportURL, originalURL, originalHTTPBody, didBlockEntirePage));
}
bool isSafeToSendToAnotherThread() const;
KURL m_reportURL;
String m_originalURL;
String m_originalHTTPBody;
bool m_didBlockEntirePage;
private:
DidBlockScriptRequest(const KURL& reportURL, const String& originalURL, const String& originalHTTPBody, bool didBlockEntirePage)
XSSInfo(const KURL& reportURL, const String& originalURL, const String& originalHTTPBody, bool didBlockEntirePage)
: m_reportURL(reportURL)
, m_originalURL(originalURL)
, m_originalHTTPBody(originalHTTPBody)
......@@ -60,7 +62,7 @@ class XSSAuditorDelegate {
public:
explicit XSSAuditorDelegate(Document*);
void didBlockScript(PassOwnPtr<DidBlockScriptRequest>);
void didBlockScript(const XSSInfo&);
private:
Document* m_document;
......
......@@ -1935,4 +1935,15 @@ void KURL::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
#endif
}
bool KURL::isSafeToSendToAnotherThread() const
{
#if USE(GOOGLEURL)
return m_url.isSafeToSendToAnotherThread();
#elif USE(WTFURL)
return m_urlImpl.isSafeToSendToAnotherThread();
#else // !USE(GOOGLEURL)
return m_string.isSafeToSendToAnotherThread();
#endif
}
}
......@@ -227,6 +227,7 @@ public:
#endif
void reportMemoryUsage(MemoryObjectInfo*) const;
bool isSafeToSendToAnotherThread() const;
private:
void invalidate();
......
......@@ -399,6 +399,14 @@ void KURLGooglePrivate::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) co
info.addMember(m_innerURL, "innerURL");
info.addMember(m_parsed, "parsed");
}
bool KURLGooglePrivate::isSafeToSendToAnotherThread() const
{
return m_string.isSafeToSendToAnotherThread()
&& m_utf8.isSafeToSendToAnotherThread()
&& (!m_innerURL || m_innerURL->isSafeToSendToAnotherThread());
}
// KURL ------------------------------------------------------------------------
// Initializes with a string representing an absolute URL. No encoding
......
......@@ -101,6 +101,7 @@ namespace WebCore {
KURL* innerURL() const { return m_innerURL.get(); }
void reportMemoryUsage(MemoryObjectInfo*) const;
bool isSafeToSendToAnotherThread() const;
private:
void initInnerURL();
......
......@@ -49,6 +49,11 @@ public:
info.addMember(m_parsedURL, "parsedURL");
info.addMember(m_invalidUrlString, "invalidUrlString");
}
bool isSafeToSendToAnotherThread() const
{
return m_invalidUrlString.isSafeToSendToAnotherThread()
&& m_parsedURL.isSafeToSendToAnotherThread();
}
PassRefPtr<KURLWTFURLImpl> copy() const;
};
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment