summaryrefslogtreecommitdiffstats
path: root/WebCore/inspector/InspectorResource.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/inspector/InspectorResource.cpp')
-rw-r--r--WebCore/inspector/InspectorResource.cpp109
1 files changed, 103 insertions, 6 deletions
diff --git a/WebCore/inspector/InspectorResource.cpp b/WebCore/inspector/InspectorResource.cpp
index be77827..ac2c9a0 100644
--- a/WebCore/inspector/InspectorResource.cpp
+++ b/WebCore/inspector/InspectorResource.cpp
@@ -43,14 +43,39 @@
#include "ResourceLoadTiming.h"
#include "ResourceRequest.h"
#include "ResourceResponse.h"
+#include "StringBuffer.h"
#include "TextEncoding.h"
+#include "WebSocketHandshakeRequest.h"
+#include "WebSocketHandshakeResponse.h"
+
+#include <wtf/Assertions.h>
namespace WebCore {
+#if ENABLE(WEB_SOCKETS)
+// Create human-readable binary representation, like "01:23:45:67:89:AB:CD:EF".
+static String createReadableStringFromBinary(const unsigned char* value, size_t length)
+{
+ ASSERT(length > 0);
+ static const char hexDigits[17] = "0123456789ABCDEF";
+ size_t bufferSize = length * 3 - 1;
+ StringBuffer buffer(bufferSize);
+ size_t index = 0;
+ for (size_t i = 0; i < length; ++i) {
+ if (i > 0)
+ buffer[index++] = ':';
+ buffer[index++] = hexDigits[value[i] >> 4];
+ buffer[index++] = hexDigits[value[i] & 0xF];
+ }
+ ASSERT(index == bufferSize);
+ return String::adopt(buffer);
+}
+#endif
+
InspectorResource::InspectorResource(unsigned long identifier, DocumentLoader* loader, const KURL& requestURL)
: m_identifier(identifier)
, m_loader(loader)
- , m_frame(loader->frame())
+ , m_frame(loader ? loader->frame() : 0)
, m_requestURL(requestURL)
, m_expectedContentLength(0)
, m_cached(false)
@@ -66,6 +91,9 @@ InspectorResource::InspectorResource(unsigned long identifier, DocumentLoader* l
, m_connectionID(0)
, m_connectionReused(false)
, m_isMainResource(false)
+#if ENABLE(WEB_SOCKETS)
+ , m_isWebSocket(false)
+#endif
{
}
@@ -88,6 +116,12 @@ PassRefPtr<InspectorResource> InspectorResource::appendRedirect(unsigned long id
return redirect;
}
+PassRefPtr<InspectorResource> InspectorResource::create(unsigned long identifier, DocumentLoader* loader, const KURL& requestURL)
+{
+ ASSERT(loader);
+ return adoptRef(new InspectorResource(identifier, loader, requestURL));
+}
+
PassRefPtr<InspectorResource> InspectorResource::createCached(unsigned long identifier, DocumentLoader* loader, const CachedResource* cachedResource)
{
PassRefPtr<InspectorResource> resource = create(identifier, loader, KURL(ParsedURLString, cachedResource->url()));
@@ -107,6 +141,16 @@ PassRefPtr<InspectorResource> InspectorResource::createCached(unsigned long iden
return resource;
}
+#if ENABLE(WEB_SOCKETS)
+PassRefPtr<InspectorResource> InspectorResource::createWebSocket(unsigned long identifier, const KURL& requestURL, const KURL& documentURL)
+{
+ RefPtr<InspectorResource> resource = adoptRef(new InspectorResource(identifier, 0, requestURL));
+ resource->markWebSocket();
+ resource->m_documentURL = documentURL;
+ return resource.release();
+}
+#endif
+
void InspectorResource::updateRequest(const ResourceRequest& request)
{
m_requestHeaderFields = request.httpHeaderFields();
@@ -117,6 +161,11 @@ void InspectorResource::updateRequest(const ResourceRequest& request)
m_changes.set(RequestChange);
}
+void InspectorResource::markAsCached()
+{
+ m_cached = true;
+}
+
void InspectorResource::updateResponse(const ResourceResponse& response)
{
m_expectedContentLength = response.expectedContentLength();
@@ -134,7 +183,7 @@ void InspectorResource::updateResponse(const ResourceResponse& response)
m_connectionID = response.connectionID();
m_connectionReused = response.connectionReused();
m_loadTiming = response.resourceLoadTiming();
- m_cached = response.wasCached();
+ m_cached = m_cached || response.wasCached();
if (!m_cached && m_loadTiming && m_loadTiming->requestTime)
m_responseReceivedTime = m_loadTiming->requestTime + m_loadTiming->receiveHeadersEnd / 1000.0;
@@ -146,6 +195,27 @@ void InspectorResource::updateResponse(const ResourceResponse& response)
m_changes.set(TypeChange);
}
+#if ENABLE(WEB_SOCKETS)
+void InspectorResource::updateWebSocketRequest(const WebSocketHandshakeRequest& request)
+{
+ m_requestHeaderFields = request.headerFields();
+ m_requestMethod = "GET"; // Currently we always use "GET" to request handshake.
+ m_webSocketRequestKey3.set(new WebSocketHandshakeRequest::Key3(request.key3()));
+ m_changes.set(RequestChange);
+ m_changes.set(TypeChange);
+}
+
+void InspectorResource::updateWebSocketResponse(const WebSocketHandshakeResponse& response)
+{
+ m_responseStatusCode = response.statusCode();
+ m_responseStatusText = response.statusText();
+ m_responseHeaderFields = response.headerFields();
+ m_webSocketChallengeResponse.set(new WebSocketHandshakeResponse::ChallengeResponse(response.challengeResponse()));
+ m_changes.set(ResponseChange);
+ m_changes.set(TypeChange);
+}
+#endif // ENABLE(WEB_SOCKETS)
+
static PassRefPtr<InspectorObject> buildHeadersObject(const HTTPHeaderMap& headers)
{
RefPtr<InspectorObject> object = InspectorObject::create();
@@ -183,8 +253,10 @@ void InspectorResource::updateScriptObject(InspectorFrontend* frontend)
RefPtr<InspectorObject> jsonObject = InspectorObject::create();
jsonObject->setNumber("id", m_identifier);
if (m_changes.hasChange(RequestChange)) {
+ if (m_frame)
+ m_documentURL = m_frame->document()->url();
jsonObject->setString("url", m_requestURL.string());
- jsonObject->setString("documentURL", m_frame->document()->url().string());
+ jsonObject->setString("documentURL", m_documentURL.string());
jsonObject->setString("host", m_requestURL.host());
jsonObject->setString("path", m_requestURL.path());
jsonObject->setString("lastPathComponent", m_requestURL.lastPathComponent());
@@ -194,6 +266,10 @@ void InspectorResource::updateScriptObject(InspectorFrontend* frontend)
jsonObject->setString("requestMethod", m_requestMethod);
jsonObject->setString("requestFormData", m_requestFormData);
jsonObject->setBoolean("didRequestChange", true);
+#if ENABLE(WEB_SOCKETS)
+ if (m_webSocketRequestKey3)
+ jsonObject->setString("webSocketRequestKey3", createReadableStringFromBinary(m_webSocketRequestKey3->value, sizeof(m_webSocketRequestKey3->value)));
+#endif
}
if (m_changes.hasChange(ResponseChange)) {
@@ -209,6 +285,10 @@ void InspectorResource::updateScriptObject(InspectorFrontend* frontend)
jsonObject->setBoolean("cached", m_cached);
if (m_loadTiming && !m_cached)
jsonObject->setObject("timing", buildObjectForTiming(m_loadTiming.get()));
+#if ENABLE(WEB_SOCKETS)
+ if (m_webSocketChallengeResponse)
+ jsonObject->setString("webSocketChallengeResponse", createReadableStringFromBinary(m_webSocketChallengeResponse->value, sizeof(m_webSocketChallengeResponse->value)));
+#endif
jsonObject->setBoolean("didResponseChange", true);
}
@@ -267,6 +347,8 @@ CachedResource* InspectorResource::cachedResource() const
// Try hard to find a corresponding CachedResource. During preloading, CachedResourceLoader may not have the resource in document resources set yet,
// but Inspector will already try to fetch data that is only available via CachedResource (and it won't update once the resource is added,
// because m_changes will not have the appropriate bits set).
+ if (!m_frame)
+ return 0;
const String& url = m_requestURL.string();
CachedResource* cachedResource = m_frame->document()->cachedResourceLoader()->cachedResource(url);
if (!cachedResource)
@@ -303,6 +385,12 @@ InspectorResource::Type InspectorResource::type() const
if (!m_overrideContent.isNull())
return m_overrideContentType;
+#if ENABLE(WEB_SOCKETS)
+ if (m_isWebSocket)
+ return WebSocket;
+#endif
+
+ ASSERT(m_loader);
if (equalIgnoringFragmentIdentifier(m_requestURL, m_loader->requestURL())) {
InspectorResource::Type resourceType = cachedResourceType();
if (resourceType == Other)
@@ -342,7 +430,7 @@ String InspectorResource::sourceString() const
PassRefPtr<SharedBuffer> InspectorResource::resourceData(String* textEncodingName) const
{
- if (equalIgnoringFragmentIdentifier(m_requestURL, m_loader->requestURL())) {
+ if (m_loader && equalIgnoringFragmentIdentifier(m_requestURL, m_loader->requestURL())) {
*textEncodingName = m_frame->document()->inputEncoding();
return m_loader->mainResourceData();
}
@@ -372,9 +460,18 @@ void InspectorResource::startTiming()
m_changes.set(TimingChange);
}
-void InspectorResource::endTiming()
+void InspectorResource::endTiming(double actualEndTime)
{
- m_endTime = currentTime();
+ if (actualEndTime) {
+ m_endTime = actualEndTime;
+ // In case of fast load (or in case of cached resources), endTime on network stack
+ // can be less then m_responseReceivedTime measured in WebCore. Normalize it here,
+ // prefer actualEndTime to m_responseReceivedTime.
+ if (m_endTime < m_responseReceivedTime)
+ m_responseReceivedTime = m_endTime;
+ } else
+ m_endTime = currentTime();
+
m_finished = true;
m_changes.set(TimingChange);
m_changes.set(CompletionChange);