Have is<>(T*) function do a null check on the pointer argument
[WebKit-https.git] / Source / WebCore / Modules / websockets / WebSocketHandshake.cpp
index f5f4620..c730461 100644 (file)
 #include "CookieJar.h"
 #include "Document.h"
 #include "HTTPHeaderMap.h"
+#include "HTTPHeaderNames.h"
 #include "HTTPParsers.h"
-#include "KURL.h"
+#include "URL.h"
 #include "Logging.h"
-#include "ScriptCallStack.h"
+#include "ResourceRequest.h"
 #include "ScriptExecutionContext.h"
 #include "SecurityOrigin.h"
 #include <wtf/CryptographicallyRandomNumber.h>
@@ -60,9 +61,7 @@
 
 namespace WebCore {
 
-static const char randomCharacterInSecWebSocketKey[] = "!\"#$%&'()*+,-./:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
-
-static String resourceName(const KURL& url)
+static String resourceName(const URL& url)
 {
     StringBuilder name;
     name.append(url.path());
@@ -78,7 +77,7 @@ static String resourceName(const KURL& url)
     return result;
 }
 
-static String hostName(const KURL& url, bool secure)
+static String hostName(const URL& url, bool secure)
 {
     ASSERT(url.protocolIs("wss") == secure);
     StringBuilder builder;
@@ -104,23 +103,22 @@ static String generateSecWebSocketKey()
     static const size_t nonceSize = 16;
     unsigned char key[nonceSize];
     cryptographicallyRandomValues(key, nonceSize);
-    return base64Encode(reinterpret_cast<char*>(key), nonceSize);
+    return base64Encode(key, nonceSize);
 }
 
 String WebSocketHandshake::getExpectedWebSocketAccept(const String& secWebSocketKey)
 {
     static const char* const webSocketKeyGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
-    static const size_t sha1HashSize = 20; // FIXME: This should be defined in SHA1.h.
     SHA1 sha1;
     CString keyData = secWebSocketKey.ascii();
     sha1.addBytes(reinterpret_cast<const uint8_t*>(keyData.data()), keyData.length());
     sha1.addBytes(reinterpret_cast<const uint8_t*>(webSocketKeyGUID), strlen(webSocketKeyGUID));
-    Vector<uint8_t, sha1HashSize> hash;
+    SHA1::Digest hash;
     sha1.computeHash(hash);
-    return base64Encode(reinterpret_cast<const char*>(hash.data()), sha1HashSize);
+    return base64Encode(hash.data(), SHA1::hashSize);
 }
 
-WebSocketHandshake::WebSocketHandshake(const KURL& url, const String& protocol, ScriptExecutionContext* context)
+WebSocketHandshake::WebSocketHandshake(const URL& url, const String& protocol, ScriptExecutionContext* context)
     : m_url(url)
     , m_clientProtocol(protocol)
     , m_secure(m_url.protocolIs("wss"))
@@ -135,12 +133,12 @@ WebSocketHandshake::~WebSocketHandshake()
 {
 }
 
-const KURL& WebSocketHandshake::url() const
+const URL& WebSocketHandshake::url() const
 {
     return m_url;
 }
 
-void WebSocketHandshake::setURL(const KURL& url)
+void WebSocketHandshake::setURL(const URL& url)
 {
     m_url = url.copy();
 }
@@ -174,7 +172,7 @@ String WebSocketHandshake::clientLocation() const
 {
     StringBuilder builder;
     builder.append(m_secure ? "wss" : "ws");
-    builder.append("://");
+    builder.appendLiteral("://");
     builder.append(hostName(m_url, m_secure));
     builder.append(resourceName(m_url));
     return builder.toString();
@@ -185,9 +183,9 @@ CString WebSocketHandshake::clientHandshakeMessage() const
     // Keep the following consistent with clientHandshakeRequest().
     StringBuilder builder;
 
-    builder.append("GET ");
+    builder.appendLiteral("GET ");
     builder.append(resourceName(m_url));
-    builder.append(" HTTP/1.1\r\n");
+    builder.appendLiteral(" HTTP/1.1\r\n");
 
     Vector<String> fields;
     fields.append("Upgrade: websocket");
@@ -197,10 +195,10 @@ CString WebSocketHandshake::clientHandshakeMessage() const
     if (!m_clientProtocol.isEmpty())
         fields.append("Sec-WebSocket-Protocol: " + m_clientProtocol);
 
-    KURL url = httpURLForAuthenticationAndCookies();
-    if (m_context->isDocument()) {
-        Document* document = toDocument(m_context);
-        String cookie = cookieRequestHeaderFieldValue(document, url);
+    URL url = httpURLForAuthenticationAndCookies();
+    if (is<Document>(*m_context)) {
+        Document& document = downcast<Document>(*m_context);
+        String cookie = cookieRequestHeaderFieldValue(&document, url);
         if (!cookie.isEmpty())
             fields.append("Cookie: " + cookie);
         // Set "Cookie2: <cookie>" if cookies 2 exists for url?
@@ -228,49 +226,48 @@ CString WebSocketHandshake::clientHandshakeMessage() const
 
     for (size_t i = 0; i < fields.size(); i++) {
         builder.append(fields[i]);
-        builder.append("\r\n");
+        builder.appendLiteral("\r\n");
     }
 
-    builder.append("\r\n");
+    builder.appendLiteral("\r\n");
 
     return builder.toString().utf8();
 }
 
-PassRefPtr<WebSocketHandshakeRequest> WebSocketHandshake::clientHandshakeRequest() const
+ResourceRequest WebSocketHandshake::clientHandshakeRequest() const
 {
     // Keep the following consistent with clientHandshakeMessage().
-    // FIXME: do we need to store m_secWebSocketKey1, m_secWebSocketKey2 and
-    // m_key3 in WebSocketHandshakeRequest?
-    RefPtr<WebSocketHandshakeRequest> request = WebSocketHandshakeRequest::create("GET", m_url);
-    request->addHeaderField("Upgrade", "websocket");
-    request->addHeaderField("Connection", "Upgrade");
-    request->addHeaderField("Host", hostName(m_url, m_secure));
-    request->addHeaderField("Origin", clientOrigin());
+    ResourceRequest request(m_url);
+    request.setHTTPMethod("GET");
+
+    request.setHTTPHeaderField(HTTPHeaderName::Connection, "Upgrade");
+    request.setHTTPHeaderField(HTTPHeaderName::Host, hostName(m_url, m_secure));
+    request.setHTTPHeaderField(HTTPHeaderName::Origin, clientOrigin());
     if (!m_clientProtocol.isEmpty())
-        request->addHeaderField("Sec-WebSocket-Protocol", m_clientProtocol);
+        request.setHTTPHeaderField(HTTPHeaderName::SecWebSocketProtocol, m_clientProtocol);
 
-    KURL url = httpURLForAuthenticationAndCookies();
-    if (m_context->isDocument()) {
-        Document* document = toDocument(m_context);
-        String cookie = cookieRequestHeaderFieldValue(document, url);
+    URL url = httpURLForAuthenticationAndCookies();
+    if (is<Document>(*m_context)) {
+        Document& document = downcast<Document>(*m_context);
+        String cookie = cookieRequestHeaderFieldValue(&document, url);
         if (!cookie.isEmpty())
-            request->addHeaderField("Cookie", cookie);
+            request.setHTTPHeaderField(HTTPHeaderName::Cookie, cookie);
         // Set "Cookie2: <cookie>" if cookies 2 exists for url?
     }
 
-    request->addHeaderField("Pragma", "no-cache");
-    request->addHeaderField("Cache-Control", "no-cache");
+    request.setHTTPHeaderField(HTTPHeaderName::Pragma, "no-cache");
+    request.setHTTPHeaderField(HTTPHeaderName::CacheControl, "no-cache");
 
-    request->addHeaderField("Sec-WebSocket-Key", m_secWebSocketKey);
-    request->addHeaderField("Sec-WebSocket-Version", "13");
+    request.setHTTPHeaderField(HTTPHeaderName::SecWebSocketKey, m_secWebSocketKey);
+    request.setHTTPHeaderField(HTTPHeaderName::SecWebSocketVersion, "13");
     const String extensionValue = m_extensionDispatcher.createHeaderValue();
     if (extensionValue.length())
-        request->addHeaderField("Sec-WebSocket-Extensions", extensionValue);
+        request.setHTTPHeaderField(HTTPHeaderName::SecWebSocketExtensions, extensionValue);
 
     // Add a User-Agent header.
-    request->addHeaderField("User-Agent", m_context->userAgent(m_context->url()));
+    request.setHTTPHeaderField(HTTPHeaderName::UserAgent, m_context->userAgent(m_context->url()));
 
-    return request.release();
+    return request;
 }
 
 void WebSocketHandshake::reset()
@@ -297,8 +294,11 @@ int WebSocketHandshake::readServerHandshake(const char* header, size_t len)
         return len;
     }
     LOG(Network, "WebSocketHandshake %p readServerHandshake() Status code is %d", this, statusCode);
-    m_response.setStatusCode(statusCode);
-    m_response.setStatusText(statusText);
+
+    m_serverHandshakeResponse = ResourceResponse();
+    m_serverHandshakeResponse.setHTTPStatusCode(statusCode);
+    m_serverHandshakeResponse.setHTTPStatusText(statusText);
+
     if (statusCode != 101) {
         m_mode = Failed;
         m_failureReason = "Unexpected response code: " + String::number(statusCode);
@@ -338,32 +338,32 @@ String WebSocketHandshake::failureReason() const
 
 String WebSocketHandshake::serverWebSocketProtocol() const
 {
-    return m_response.headerFields().get("sec-websocket-protocol");
+    return m_serverHandshakeResponse.httpHeaderFields().get(HTTPHeaderName::SecWebSocketProtocol);
 }
 
 String WebSocketHandshake::serverSetCookie() const
 {
-    return m_response.headerFields().get("set-cookie");
+    return m_serverHandshakeResponse.httpHeaderFields().get(HTTPHeaderName::SetCookie);
 }
 
 String WebSocketHandshake::serverSetCookie2() const
 {
-    return m_response.headerFields().get("set-cookie2");
+    return m_serverHandshakeResponse.httpHeaderFields().get(HTTPHeaderName::SetCookie2);
 }
 
 String WebSocketHandshake::serverUpgrade() const
 {
-    return m_response.headerFields().get("upgrade");
+    return m_serverHandshakeResponse.httpHeaderFields().get(HTTPHeaderName::Upgrade);
 }
 
 String WebSocketHandshake::serverConnection() const
 {
-    return m_response.headerFields().get("connection");
+    return m_serverHandshakeResponse.httpHeaderFields().get(HTTPHeaderName::Connection);
 }
 
 String WebSocketHandshake::serverWebSocketAccept() const
 {
-    return m_response.headerFields().get("sec-websocket-accept");
+    return m_serverHandshakeResponse.httpHeaderFields().get(HTTPHeaderName::SecWebSocketAccept);
 }
 
 String WebSocketHandshake::acceptedExtensions() const
@@ -371,9 +371,9 @@ String WebSocketHandshake::acceptedExtensions() const
     return m_extensionDispatcher.acceptedExtensions();
 }
 
-const WebSocketHandshakeResponse& WebSocketHandshake::serverHandshakeResponse() const
+const ResourceResponse& WebSocketHandshake::serverHandshakeResponse() const
 {
-    return m_response;
+    return m_serverHandshakeResponse;
 }
 
 void WebSocketHandshake::addExtensionProcessor(PassOwnPtr<WebSocketExtensionProcessor> processor)
@@ -381,9 +381,9 @@ void WebSocketHandshake::addExtensionProcessor(PassOwnPtr<WebSocketExtensionProc
     m_extensionDispatcher.addProcessor(processor);
 }
 
-KURL WebSocketHandshake::httpURLForAuthenticationAndCookies() const
+URL WebSocketHandshake::httpURLForAuthenticationAndCookies() const
 {
-    KURL url = m_url.copy();
+    URL url = m_url.copy();
     bool couldSetProtocol = url.setProtocol(m_secure ? "https" : "http");
     ASSERT_UNUSED(couldSetProtocol, couldSetProtocol);
     return url;
@@ -461,9 +461,7 @@ int WebSocketHandshake::readStatusLine(const char* header, size_t headerLength,
 
 const char* WebSocketHandshake::readHTTPHeaders(const char* start, const char* end)
 {
-    m_response.clearHeaderFields();
-
-    AtomicString name;
+    String name;
     String value;
     bool sawSecWebSocketExtensionsHeaderField = false;
     bool sawSecWebSocketAcceptHeaderField = false;
@@ -494,17 +492,17 @@ const char* WebSocketHandshake::readHTTPHeaders(const char* start, const char* e
                 m_failureReason = "The Sec-WebSocket-Accept header MUST NOT appear more than once in an HTTP response";
                 return 0;
             }
-            m_response.addHeaderField(name, value);
+            m_serverHandshakeResponse.addHTTPHeaderField(name, value);
             sawSecWebSocketAcceptHeaderField = true;
         } else if (equalIgnoringCase("Sec-WebSocket-Protocol", name)) {
             if (sawSecWebSocketProtocolHeaderField) {
                 m_failureReason = "The Sec-WebSocket-Protocol header MUST NOT appear more than once in an HTTP response";
                 return 0;
             }
-            m_response.addHeaderField(name, value);
+            m_serverHandshakeResponse.addHTTPHeaderField(name, value);
             sawSecWebSocketProtocolHeaderField = true;
         } else
-            m_response.addHeaderField(name, value);
+            m_serverHandshakeResponse.addHTTPHeaderField(name, value);
     }
     return p;
 }