2009-12-08 Alexander Pavlov <apavlov@chromium.org>
authoreric@webkit.org <eric@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 8 Dec 2009 13:21:03 +0000 (13:21 +0000)
committereric@webkit.org <eric@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 8 Dec 2009 13:21:03 +0000 (13:21 +0000)
        Reviewed by Pavel Feldman.

        Change the way cookies are retrieved in the WebInspector frontend.

        Moved the cookie filtering from the native code into the frontend so that
        all cookies can be retrieved regardless of the associated domain
        (required for certain audits to run.)
        https://bugs.webkit.org/show_bug.cgi?id=32160

        * inspector/cookie-resource-match-expected.txt: Added.
        * inspector/cookie-resource-match.html: Added.
2009-12-08  Alexander Pavlov  <apavlov@chromium.org>

        Reviewed by Pavel Feldman.

        Change the way cookies are retrieved in the WebInspector frontend.

        Moved the cookie filtering from the native code into the frontend so that
        all cookies can be retrieved regardless of the associated domain
        (required for certain audits to run.)
        https://bugs.webkit.org/show_bug.cgi?id=32160

        Test: inspector/cookie-resource-match.html

        * inspector/InspectorBackend.cpp:
        (WebCore::InspectorBackend::getCookies):
        * inspector/InspectorBackend.h:
        * inspector/InspectorBackend.idl:
        * inspector/InspectorController.cpp:
        (WebCore::InspectorController::getCookies):
        * inspector/InspectorController.h:
        * inspector/front-end/CookieItemsView.js:
        (WebInspector.CookieItemsView.prototype.update.callback):
        (WebInspector.CookieItemsView.prototype.update):
        (WebInspector.CookieItemsView.prototype._cookiesForDomain):
        * inspector/front-end/DOMAgent.js:
        (WebInspector.Cookies.getCookiesAsync):
        (WebInspector.Cookies.cookieMatchesResourceURL):
        (WebInspector.Cookies.cookieDomainMatchesResourceDomain):
        * inspector/front-end/Resource.js:
        (WebInspector.Resource):
        (WebInspector.Resource.prototype.get documentURL):
        (WebInspector.Resource.prototype.set documentURL):
        * inspector/front-end/inspector.js:
        (WebInspector.addResource):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@51846 268f45cc-cd09-0410-ab3c-d52691b4dbfc

13 files changed:
LayoutTests/ChangeLog
LayoutTests/inspector/cookie-resource-match-expected.txt [new file with mode: 0644]
LayoutTests/inspector/cookie-resource-match.html [new file with mode: 0644]
WebCore/ChangeLog
WebCore/inspector/InspectorBackend.cpp
WebCore/inspector/InspectorBackend.h
WebCore/inspector/InspectorBackend.idl
WebCore/inspector/InspectorController.cpp
WebCore/inspector/InspectorController.h
WebCore/inspector/front-end/CookieItemsView.js
WebCore/inspector/front-end/DOMAgent.js
WebCore/inspector/front-end/Resource.js
WebCore/inspector/front-end/inspector.js

index dbc1d1c..e8f8b14 100644 (file)
@@ -1,3 +1,17 @@
+2009-12-08  Alexander Pavlov  <apavlov@chromium.org>
+
+        Reviewed by Pavel Feldman.
+
+        Change the way cookies are retrieved in the WebInspector frontend.
+
+        Moved the cookie filtering from the native code into the frontend so that
+        all cookies can be retrieved regardless of the associated domain
+        (required for certain audits to run.)
+        https://bugs.webkit.org/show_bug.cgi?id=32160
+
+        * inspector/cookie-resource-match-expected.txt: Added.
+        * inspector/cookie-resource-match.html: Added.
+
 2009-12-08  Nikolas Zimmermann  <nzimmermann@rim.com>
 
         Rubber-stamped by Maciej Stachowiak.
diff --git a/LayoutTests/inspector/cookie-resource-match-expected.txt b/LayoutTests/inspector/cookie-resource-match-expected.txt
new file mode 100644 (file)
index 0000000..2dc129c
--- /dev/null
@@ -0,0 +1,18 @@
+Tests that cookies are matched up with resources correctly.
+
+[0,2,4,6,8,10,12,14]
+[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
+[2,3,6,7,10,11,14,15]
+[6,14]
+[4,5,6,7,12,13,14,15]
+[6,7,14,15]
+[8,10,12,14]
+[8,9,10,11,12,13,14,15]
+[10,11,14,15]
+[14]
+[12,13,14,15]
+[14,15]
+[]
+[]
+[]
+
diff --git a/LayoutTests/inspector/cookie-resource-match.html b/LayoutTests/inspector/cookie-resource-match.html
new file mode 100644 (file)
index 0000000..8ee06d1
--- /dev/null
@@ -0,0 +1,100 @@
+<html>
+<head>
+<script src="inspector-test.js"></script>
+<script>
+
+function doit() {
+    function callback(result)
+    {
+        for (var i = 0; i < result.length; ++i)
+            output("[" + result[i] + "]");
+        notifyDone();
+    }
+    evaluateInWebInspector("frontend_doitAndDump", callback);
+}
+
+function frontend_doitAndDump()
+{
+    var cookies = [
+        frontend_createCookie("insecureOnlyWebkit", "1234567890", false, "webkit.org", "/"),
+        frontend_createCookie("insecureAllWebkit", "1234567890123456", false, ".webkit.org", "/"),
+        frontend_createCookie("insecureAllWebkitPath", "1234567890123456", false, ".webkit.org", "/path"),
+        frontend_createCookie("secureOnlyWebkitPath", "bar", true, "webkit.org", "/path"),
+        frontend_createCookie("secureAllWebkit", "foo", true, ".webkit.org", "/"),
+        frontend_createCookie("secureAllWebkitPath", "foo", true, ".webkit.org", "/path"),
+        frontend_createCookie("insecureOnlyWebkitPort", "1234567890", false, "webkit.org", "/", 80),
+        frontend_createCookie("insecureAllWebkitPort", "1234567890123456", false, ".webkit.org", "/", 80),
+        frontend_createCookie("insecureAllWebkitPathPort", "1234567890123456", false, ".webkit.org", "/path", 80),
+        frontend_createCookie("secureOnlyWebkitPathPort", "bar", true, "webkit.org", "/path", 80),
+        frontend_createCookie("secureAllWebkitPort", "foo", true, ".webkit.org", "/", 80),
+        frontend_createCookie("secureAllWebkitPathPort", "foo", true, ".webkit.org", "/path", 80),
+        frontend_createCookie("nonMatching1", "bar", false, "webkit.zoo", "/"),
+        frontend_createCookie("nonMatching2", "bar", false, "webkit.org", "/badPath"),
+        frontend_createCookie("nonMatching3", "bar", true, ".moo.com", "/")
+    ];
+
+    var resourceURLs = [
+        "http://webkit.org", // 0
+        "http://www.webkit.org:81", // 1
+        "http://webkit.org/path", // 2
+        "http://www.webkit.org/path", // 3
+        "https://webkit.org/", // 4
+        "https://www.webkit.org/", // 5
+        "https://webkit.org:81/path", // 6
+        "https://www.webkit.org/path", // 7
+
+        "http://webkit.org:80", // 8
+        "http://www.webkit.org:80", // 9
+        "http://webkit.org:80/path", // 10
+        "http://www.webkit.org:80/path", // 11
+        "https://webkit.org:80/", // 12
+        "https://www.webkit.org:80/", // 13
+        "https://webkit.org:80/path", // 14
+        "https://www.webkit.org:80/path", // 15
+
+        "http://www.boo.com:80", // 16
+        "https://www.boo.com:80/path", // 17
+        "http://www.moo.com:80/", // 18
+        "http://www.boo.com:80", // 19
+        "https://www.boo.com:80/path", // 20
+        "http://www.moo.com:80/" // 21
+    ];
+
+    var result = [];
+    for (var i = 0; i < cookies.length; ++i) {
+        var cookieResult = [];
+        for (var j = 0; j < resourceURLs.length; ++j) {
+            if (WebInspector.Cookies.cookieMatchesResourceURL(cookies[i], resourceURLs[j]))
+                cookieResult.push(j);
+        }
+        result.push(cookieResult);
+    }
+    return result;
+}
+
+function frontend_createCookie(name, value, secure, domain, path, port)
+{
+    return {
+        name: name,
+        value: value,
+        domain: domain,
+        port: port,
+        path: path,
+        expires: "Thu Jan 01 1970 00:00:00 GMT",
+        size: name.length + value.length,
+        httpOnly: false,
+        secure: secure,
+        session: true
+    };
+}
+
+</script>
+</head>
+
+<body onload="onload()">
+<p>
+Tests that cookies are matched up with resources correctly.
+</p>
+
+</body>
+</html>
index 88dbb43..1c24c6d 100644 (file)
@@ -1,3 +1,38 @@
+2009-12-08  Alexander Pavlov  <apavlov@chromium.org>
+
+        Reviewed by Pavel Feldman.
+
+        Change the way cookies are retrieved in the WebInspector frontend.
+
+        Moved the cookie filtering from the native code into the frontend so that
+        all cookies can be retrieved regardless of the associated domain
+        (required for certain audits to run.)
+        https://bugs.webkit.org/show_bug.cgi?id=32160
+
+        Test: inspector/cookie-resource-match.html
+
+        * inspector/InspectorBackend.cpp:
+        (WebCore::InspectorBackend::getCookies):
+        * inspector/InspectorBackend.h:
+        * inspector/InspectorBackend.idl:
+        * inspector/InspectorController.cpp:
+        (WebCore::InspectorController::getCookies):
+        * inspector/InspectorController.h:
+        * inspector/front-end/CookieItemsView.js:
+        (WebInspector.CookieItemsView.prototype.update.callback):
+        (WebInspector.CookieItemsView.prototype.update):
+        (WebInspector.CookieItemsView.prototype._cookiesForDomain):
+        * inspector/front-end/DOMAgent.js:
+        (WebInspector.Cookies.getCookiesAsync):
+        (WebInspector.Cookies.cookieMatchesResourceURL):
+        (WebInspector.Cookies.cookieDomainMatchesResourceDomain):
+        * inspector/front-end/Resource.js:
+        (WebInspector.Resource):
+        (WebInspector.Resource.prototype.get documentURL):
+        (WebInspector.Resource.prototype.set documentURL):
+        * inspector/front-end/inspector.js:
+        (WebInspector.addResource):
+
 2009-12-08  Nikolas Zimmermann  <nzimmermann@rim.com>
 
         Not reviewed. Touch svgtags.in, in order to force SVGNames.* regeneration. Praying for gtk bot to be fixed :-)
index 6b3268d..11f58c7 100644 (file)
@@ -357,11 +357,11 @@ void InspectorBackend::hideDOMNodeHighlight()
         m_inspectorController->hideHighlight();
 }
 
-void InspectorBackend::getCookies(long callId, const String& domain)
+void InspectorBackend::getCookies(long callId)
 {
     if (!m_inspectorController)
         return;
-    m_inspectorController->getCookies(callId, domain);
+    m_inspectorController->getCookies(callId);
 }
 
 void InspectorBackend::deleteCookie(const String& cookieName, const String& domain)
index 8026294..d6e89fa 100644 (file)
@@ -114,7 +114,7 @@ public:
     void highlightDOMNode(long nodeId);
     void hideDOMNodeHighlight();
 
-    void getCookies(long callId, const String& domain);
+    void getCookies(long callId);
     void deleteCookie(const String& cookieName, const String& domain);
 
     // Generic code called from custom implementations.
index e436e6b..61c76d6 100644 (file)
@@ -87,7 +87,7 @@ module core {
         void highlightDOMNode(in long nodeId);
         void hideDOMNodeHighlight();
 
-        void getCookies(in long callId, in DOMString domain);
+        void getCookies(in long callId);
         void deleteCookie(in DOMString cookieName, in DOMString domain);
 
         void releaseWrapperObjectGroup(in DOMString objectGroup);
index c269825..fd319a4 100644 (file)
@@ -1149,46 +1149,44 @@ void InspectorController::didOpenDatabase(Database* database, const String& doma
 }
 #endif
 
-void InspectorController::getCookies(long callId, const String& host)
+void InspectorController::getCookies(long callId)
 {
     if (!m_frontend)
         return;
-    
+
     // If we can get raw cookies.
     ListHashSet<Cookie> rawCookiesList;
-    
+
     // If we can't get raw cookies - fall back to String representation
     String stringCookiesList;
-    
+
     // Return value to getRawCookies should be the same for every call because
     // the return value is platform/network backend specific, and the call will
     // always return the same true/false value.
     bool rawCookiesImplemented = false;
-    
+
     ResourcesMap::iterator resourcesEnd = m_resources.end();
     for (ResourcesMap::iterator it = m_resources.begin(); it != resourcesEnd; ++it) {
         Document* document = it->second->frame()->document();
-        if (document->url().host() == host) {
-            Vector<Cookie> docCookiesList;
-            rawCookiesImplemented = getRawCookies(document, document->cookieURL(), docCookiesList);
-            
-            if (!rawCookiesImplemented) {
-                // FIXME: We need duplication checking for the String representation of cookies.
-                ExceptionCode ec = 0;
-                stringCookiesList += document->cookie(ec);
-                // Exceptions are thrown by cookie() in sandboxed frames. That won't happen here
-                // because "document" is the document of the main frame of the page.
-                ASSERT(!ec);
-            } else {
-                int cookiesSize = docCookiesList.size();
-                for (int i = 0; i < cookiesSize; i++) {
-                    if (!rawCookiesList.contains(docCookiesList[i]))
-                        rawCookiesList.add(docCookiesList[i]);
-                }
+        Vector<Cookie> docCookiesList;
+        rawCookiesImplemented = getRawCookies(document, document->cookieURL(), docCookiesList);
+
+        if (!rawCookiesImplemented) {
+            // FIXME: We need duplication checking for the String representation of cookies.
+            ExceptionCode ec = 0;
+            stringCookiesList += document->cookie(ec);
+            // Exceptions are thrown by cookie() in sandboxed frames. That won't happen here
+            // because "document" is the document of the main frame of the page.
+            ASSERT(!ec);
+        } else {
+            int cookiesSize = docCookiesList.size();
+            for (int i = 0; i < cookiesSize; i++) {
+                if (!rawCookiesList.contains(docCookiesList[i]))
+                    rawCookiesList.add(docCookiesList[i]);
             }
         }
     }
-    
+
     if (!rawCookiesImplemented)
         m_frontend->didGetCookies(callId, m_frontend->newScriptArray(), stringCookiesList);
     else
index 0dd6fb1..bb4e1f3 100644 (file)
@@ -186,7 +186,7 @@ public:
     void mainResourceFiredLoadEvent(DocumentLoader*, const KURL&);
     void mainResourceFiredDOMContentEvent(DocumentLoader*, const KURL&);
                                                         
-    void getCookies(long callId, const String& url);
+    void getCookies(long callId);
 
 #if ENABLE(DATABASE)
     void didOpenDatabase(Database*, const String& domain, const String& name, const String& version);
index 0caa1b7..b31b7ea 100644 (file)
@@ -67,7 +67,8 @@ WebInspector.CookieItemsView.prototype = {
         this.element.removeChildren();
 
         var self = this;
-        function callback(cookies, isAdvanced) {
+        function callback(allCookies, isAdvanced) {
+            var cookies = self._cookiesForDomain(allCookies);
             var dataGrid = (isAdvanced ? self.dataGridForCookies(cookies) : self.simpleDataGridForCookies(cookies));
             if (dataGrid) {
                 self._dataGrid = dataGrid;
@@ -85,7 +86,31 @@ WebInspector.CookieItemsView.prototype = {
             }
         }
 
-        WebInspector.Cookies.getCookiesAsync(callback, this._cookieDomain);
+        WebInspector.Cookies.getCookiesAsync(callback);
+    },
+
+    _cookiesForDomain: function(allCookies)
+    {
+        var cookiesForDomain = [];
+        var resourceURLsForDocumentURL = [];
+
+        for (var id in WebInspector.resources) {
+            var resource = WebInspector.resources[id];
+            var match = resource.documentURL.match(WebInspector.URLRegExp);
+            if (match && match[2] === this._cookieDomain)
+                resourceURLsForDocumentURL.push(resource.url);
+        }
+
+        for (var i = 0; i < allCookies.length; ++i) {
+            for (var j = 0; j < resourceURLsForDocumentURL.length; ++j) {
+                var resourceURL = resourceURLsForDocumentURL[j];
+                if (WebInspector.Cookies.cookieMatchesResourceURL(allCookies[i], resourceURL)) {
+                    cookiesForDomain.push(allCookies[i]);
+                    break;
+                }
+            }
+        }
+        return cookiesForDomain;
     },
 
     dataGridForCookies: function(cookies)
index 28dafeb..4ccf843 100644 (file)
@@ -439,7 +439,7 @@ WebInspector.DOMAgent.prototype = {
 
 WebInspector.Cookies = {}
 
-WebInspector.Cookies.getCookiesAsync = function(callback, cookieDomain)
+WebInspector.Cookies.getCookiesAsync = function(callback)
 {
     function mycallback(cookies, cookiesString) {
         if (cookiesString)
@@ -448,7 +448,7 @@ WebInspector.Cookies.getCookiesAsync = function(callback, cookieDomain)
             callback(cookies, true);
     }
     var callId = WebInspector.Callback.wrap(mycallback);
-    InspectorBackend.getCookies(callId, cookieDomain);
+    InspectorBackend.getCookies(callId);
 }
 
 WebInspector.Cookies.buildCookiesFromString = function(rawCookieString)
@@ -470,6 +470,28 @@ WebInspector.Cookies.buildCookiesFromString = function(rawCookieString)
     return cookies;
 }
 
+WebInspector.Cookies.cookieMatchesResourceURL = function(cookie, resourceURL)
+{
+    var match = resourceURL.match(WebInspector.URLRegExp);
+    if (!match)
+        return false;
+    // See WebInspector.URLRegExp for definitions of the group index constants.
+    if (!this.cookieDomainMatchesResourceDomain(cookie.domain, match[2]))
+        return false;
+    var resourcePort = match[3] ? match[3] : undefined;
+    var resourcePath = match[4] ? match[4] : '/';
+    return (resourcePath.indexOf(cookie.path) === 0
+        && (!cookie.port || resourcePort == cookie.port)
+        && (!cookie.secure || match[1].toLowerCase() === 'https'));
+}
+
+WebInspector.Cookies.cookieDomainMatchesResourceDomain = function(cookieDomain, resourceDomain)
+{
+    if (cookieDomain.charAt(0) !== '.')
+        return resourceDomain === cookieDomain;
+    return !!resourceDomain.match(new RegExp("^([^\\.]+\\.)?" + cookieDomain.substring(1).escapeForRegExp() + "$"), "i");
+}
+
 WebInspector.EventListeners = {}
 
 WebInspector.EventListeners.getEventListenersForNodeAsync = function(node, callback)
index 728f2ac..d23b5da 100644 (file)
@@ -26,7 +26,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-WebInspector.Resource = function(requestHeaders, url, domain, path, lastPathComponent, identifier, mainResource, cached, requestMethod, requestFormData)
+WebInspector.Resource = function(requestHeaders, url, documentURL, domain, path, lastPathComponent, identifier, mainResource, cached, requestMethod, requestFormData)
 {
     this.identifier = identifier;
 
@@ -35,6 +35,7 @@ WebInspector.Resource = function(requestHeaders, url, domain, path, lastPathComp
     this.mainResource = mainResource;
     this.requestHeaders = requestHeaders;
     this.url = url;
+    this.documentURL = documentURL;
     this.domain = domain;
     this.path = path;
     this.lastPathComponent = lastPathComponent;
@@ -162,6 +163,18 @@ WebInspector.Resource.prototype = {
         this.dispatchEventToListeners("url changed");
     },
 
+    get documentURL()
+    {
+        return this._documentURL;
+    },
+
+    set documentURL(x)
+    {
+        if (this._documentURL === x)
+            return;
+        this._documentURL = x;
+    },
+
     get domain()
     {
         return this._domain;
index 2fd076c..9fcc657 100644 (file)
@@ -74,6 +74,14 @@ var WebInspector = {
     missingLocalizedStrings: {},
     pendingDispatches: 0,
 
+    // RegExp groups:
+    // 1 - scheme
+    // 2 - hostname
+    // 3 - ?port
+    // 4 - ?path
+    // 5 - ?fragment
+    URLRegExp: /^(http[s]?|file):\/\/([^\/:]+)(?::([\d]+))?(?:(\/[^#]*)(?:#(.*))?)?$/i,
+
     get platform()
     {
         if (!("_platform" in this))
@@ -1009,6 +1017,7 @@ WebInspector.addResource = function(identifier, payload)
     var resource = new WebInspector.Resource(
         payload.requestHeaders,
         payload.requestURL,
+        payload.documentURL,
         payload.host,
         payload.path,
         payload.lastPathComponent,