Commit 700e2ba1 authored by bweinstein@apple.com's avatar bweinstein@apple.com

2009-10-07 Brian Weinstein <bweinstein@apple.com>

        Reviewed by Timothy Hatcher.

        Fixes <http://webkit.org/b/30104>.
        Inspector should show cookies of sub-resources on the page.
        
        This function implements showing cookies for all sub-resources of a page.
        When the page is loaded, it populates the Storage Panel with a list of all
        domains that were loaded as part of the full page load (iframes, ads, etc).
        When the user selects one of the domains, the inspector calls back into the
        controller, and the controller combines all of the cookies from that domain
        into a list, and sends that list is sent back to the controller to render.
        
        A domain now needs to be passed into CookieItemsView, and CookieSidebarTreeElement.
        
        As a result of a previous patch, we now have detailed cookie information for
        both Windows on CFNetwork and Mac. Additionally, this patch provides deleteCookie
        support on Windows.

        * bindings/js/ScriptObject.cpp:
        (WebCore::ScriptObject::set):
        * bindings/js/ScriptObject.h:
        * inspector/InspectorBackend.cpp:
        (WebCore::InspectorBackend::getCookies):
        (WebCore::InspectorBackend::deleteCookie):
        * inspector/InspectorBackend.h:
        * inspector/InspectorBackend.idl:
        * inspector/InspectorController.cpp:
        (WebCore::InspectorController::populateScriptObjects):
        (WebCore::InspectorController::didFinishLoading):
        (WebCore::InspectorController::getCookies):
        (WebCore::InspectorController::buildArrayForCookies):
        (WebCore::InspectorController::buildObjectForCookie):
        (WebCore::InspectorController::deleteCookie):
        * inspector/InspectorController.h:
        * inspector/InspectorDOMAgent.cpp:
        * inspector/InspectorDOMAgent.h:
        * inspector/InspectorFrontend.cpp:
        (WebCore::InspectorFrontend::addCookieDomainForDocument):
        * inspector/InspectorFrontend.h:
        * inspector/front-end/CookieItemsView.js:
        (WebInspector.CookieItemsView):
        (WebInspector.CookieItemsView.prototype.update):
        (WebInspector.CookieItemsView.prototype._deleteButtonClicked):
        * inspector/front-end/DOMAgent.js:
        (WebInspector.Cookies.getCookiesAsync):
        * inspector/front-end/StoragePanel.js:
        (WebInspector.StoragePanel):
        (WebInspector.StoragePanel.prototype.reset):
        (WebInspector.StoragePanel.prototype.addCookieDomain):
        (WebInspector.StoragePanel.prototype.showCookies):
        (WebInspector.CookieSidebarTreeElement):
        (WebInspector.CookieSidebarTreeElement.prototype.onselect):
        * inspector/front-end/inspector.js:
        (WebInspector.addCookieDomain):
        * platform/Cookie.h:
        (WebCore::CookieHash::hash):
        (WebCore::CookieHash::equal):
        (WTF::):
        * platform/network/win/CookieJarCFNetWin.cpp:
        (WebCore::deleteCookie):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@49263 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 16dd4c28
2009-10-07 Brian Weinstein <bweinstein@apple.com>
Reviewed by Timothy Hatcher.
Fixes <http://webkit.org/b/30104>.
Inspector should show cookies of sub-resources on the page.
This function implements showing cookies for all sub-resources of a page.
When the page is loaded, it populates the Storage Panel with a list of all
domains that were loaded as part of the full page load (iframes, ads, etc).
When the user selects one of the domains, the inspector calls back into the
controller, and the controller combines all of the cookies from that domain
into a list, and sends that list is sent back to the controller to render.
A domain now needs to be passed into CookieItemsView, and CookieSidebarTreeElement.
As a result of a previous patch, we now have detailed cookie information for
both Windows on CFNetwork and Mac. Additionally, this patch provides deleteCookie
support on Windows.
* bindings/js/ScriptObject.cpp:
(WebCore::ScriptObject::set):
* bindings/js/ScriptObject.h:
* inspector/InspectorBackend.cpp:
(WebCore::InspectorBackend::getCookies):
(WebCore::InspectorBackend::deleteCookie):
* inspector/InspectorBackend.h:
* inspector/InspectorBackend.idl:
* inspector/InspectorController.cpp:
(WebCore::InspectorController::populateScriptObjects):
(WebCore::InspectorController::didFinishLoading):
(WebCore::InspectorController::getCookies):
(WebCore::InspectorController::buildArrayForCookies):
(WebCore::InspectorController::buildObjectForCookie):
(WebCore::InspectorController::deleteCookie):
* inspector/InspectorController.h:
* inspector/InspectorDOMAgent.cpp:
* inspector/InspectorDOMAgent.h:
* inspector/InspectorFrontend.cpp:
(WebCore::InspectorFrontend::addCookieDomainForDocument):
* inspector/InspectorFrontend.h:
* inspector/front-end/CookieItemsView.js:
(WebInspector.CookieItemsView):
(WebInspector.CookieItemsView.prototype.update):
(WebInspector.CookieItemsView.prototype._deleteButtonClicked):
* inspector/front-end/DOMAgent.js:
(WebInspector.Cookies.getCookiesAsync):
* inspector/front-end/StoragePanel.js:
(WebInspector.StoragePanel):
(WebInspector.StoragePanel.prototype.reset):
(WebInspector.StoragePanel.prototype.addCookieDomain):
(WebInspector.StoragePanel.prototype.showCookies):
(WebInspector.CookieSidebarTreeElement):
(WebInspector.CookieSidebarTreeElement.prototype.onselect):
* inspector/front-end/inspector.js:
(WebInspector.addCookieDomain):
* platform/Cookie.h:
(WebCore::CookieHash::hash):
(WebCore::CookieHash::equal):
(WTF::):
* platform/network/win/CookieJarCFNetWin.cpp:
(WebCore::deleteCookie):
2009-10-07 Pavel Feldman <pfeldman@chromium.org>
Reviewed by Timothy Hatcher.
......@@ -103,6 +103,14 @@ bool ScriptObject::set(const char* name, int value)
return handleException(m_scriptState);
}
bool ScriptObject::set(const char* name, unsigned value)
{
JSLock lock(SilenceAssertionsOnly);
PutPropertySlot slot;
jsObject()->put(m_scriptState, Identifier(m_scriptState, name), jsNumber(m_scriptState, value), slot);
return handleException(m_scriptState);
}
bool ScriptObject::set(const char* name, bool value)
{
JSLock lock(SilenceAssertionsOnly);
......
......@@ -52,6 +52,7 @@ namespace WebCore {
bool set(const char* name, double);
bool set(const char* name, long long);
bool set(const char* name, int);
bool set(const char* name, unsigned);
bool set(const char* name, bool);
static ScriptObject createNew(ScriptState*);
......
......@@ -456,17 +456,18 @@ void InspectorBackend::copyNode(long nodeId)
Pasteboard::generalPasteboard()->writePlainText(markup);
}
void InspectorBackend::getCookies(long callId)
void InspectorBackend::getCookies(long callId, const String& domain)
{
if (InspectorDOMAgent* domAgent = inspectorDOMAgent())
domAgent->getCookies(callId);
if (!m_inspectorController)
return;
m_inspectorController->getCookies(callId, domain);
}
void InspectorBackend::deleteCookie(const String& cookieName)
void InspectorBackend::deleteCookie(const String& cookieName, const String& domain)
{
if (!m_inspectorController)
return;
m_inspectorController->deleteCookie(cookieName);
m_inspectorController->deleteCookie(cookieName, domain);
}
void InspectorBackend::highlight(long nodeId)
......
......@@ -138,8 +138,8 @@ public:
void getEventListenersForNode(long callId, long nodeId);
void copyNode(long nodeId);
void getCookies(long callId);
void deleteCookie(const String& cookieName);
void getCookies(long callId, const String& domain);
void deleteCookie(const String& cookieName, const String& domain);
// Generic code called from custom implementations.
void highlight(long nodeId);
......
......@@ -110,8 +110,8 @@ module core {
void getEventListenersForNode(in long callId, in long nodeId);
void copyNode(in long nodeId);
void getCookies(in long callId);
void deleteCookie(in DOMString cookieName);
void getCookies(in long callId, in DOMString domain);
void deleteCookie(in DOMString cookieName, in DOMString domain);
// Called from InjectedScript.
// TODO: extract into a separate IDL.
......
......@@ -36,6 +36,7 @@
#include "CachedResource.h"
#include "Console.h"
#include "ConsoleMessage.h"
#include "Cookie.h"
#include "CookieJar.h"
#include "Document.h"
#include "DocumentLoader.h"
......@@ -76,6 +77,7 @@
#include "TextEncoding.h"
#include "TextIterator.h"
#include <wtf/CurrentTime.h>
#include <wtf/ListHashSet.h>
#include <wtf/RefCounted.h>
#include <wtf/StdLibExtras.h>
......@@ -652,9 +654,11 @@ void InspectorController::populateScriptObjects()
m_domAgent->setDocument(m_inspectedPage->mainFrame()->document());
ResourcesMap::iterator resourcesEnd = m_resources.end();
for (ResourcesMap::iterator it = m_resources.begin(); it != resourcesEnd; ++it)
for (ResourcesMap::iterator it = m_resources.begin(); it != resourcesEnd; ++it) {
it->second->createScriptObject(m_frontend.get());
m_frontend->addCookieDomain(it->second->frame()->document()->url().host());
}
unsigned messageCount = m_consoleMessages.size();
for (unsigned i = 0; i < messageCount; ++i)
m_consoleMessages[i]->addToConsole(m_frontend.get());
......@@ -972,8 +976,10 @@ void InspectorController::didFinishLoading(DocumentLoader*, unsigned long identi
addResource(resource.get());
if (m_frontend)
if (m_frontend) {
resource->updateScriptObject(m_frontend.get());
m_frontend->addCookieDomain(resource->frame()->document()->url().host());
}
}
void InspectorController::didFailLoading(DocumentLoader*, unsigned long identifier, const ResourceError& /*error*/)
......@@ -1146,6 +1152,75 @@ void InspectorController::didOpenDatabase(Database* database, const String& doma
}
#endif
void InspectorController::getCookies(long callId, const String& host)
{
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.
stringCookiesList += document->cookie();
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
m_frontend->didGetCookies(callId, buildArrayForCookies(rawCookiesList), String());
}
ScriptArray InspectorController::buildArrayForCookies(ListHashSet<Cookie>& cookiesList)
{
ScriptArray cookies = m_frontend->newScriptArray();
ListHashSet<Cookie>::iterator end = cookiesList.end();
ListHashSet<Cookie>::iterator it = cookiesList.begin();
for (int i = 0; it != end; ++it, i++)
cookies.set(i, buildObjectForCookie(*it));
return cookies;
}
ScriptObject InspectorController::buildObjectForCookie(const Cookie& cookie)
{
ScriptObject value = m_frontend->newScriptObject();
value.set("name", cookie.name);
value.set("value", cookie.value);
value.set("domain", cookie.domain);
value.set("path", cookie.path);
value.set("expires", cookie.expires);
value.set("size", (cookie.name.length() + cookie.value.length()));
value.set("httpOnly", cookie.httpOnly);
value.set("secure", cookie.secure);
value.set("session", cookie.session);
return value;
}
#if ENABLE(DOM_STORAGE)
void InspectorController::didUseDOMStorage(StorageArea* storageArea, bool isLocalStorage, Frame* frame)
{
......@@ -1729,10 +1804,14 @@ void InspectorController::resetInjectedScript()
function.call();
}
void InspectorController::deleteCookie(const String& cookieName)
void InspectorController::deleteCookie(const String& cookieName, const String& domain)
{
Document* document = m_inspectedPage->mainFrame()->document();
WebCore::deleteCookie(document, document->cookieURL(), cookieName);
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() == domain)
WebCore::deleteCookie(document, document->cookieURL(), cookieName);
}
}
} // namespace WebCore
......
......@@ -30,7 +30,9 @@
#define InspectorController_h
#include "Console.h"
#include "Cookie.h"
#include "PlatformString.h"
#include "ScriptArray.h"
#include "ScriptObject.h"
#include "ScriptState.h"
#include "ScriptValue.h"
......@@ -39,6 +41,7 @@
#include <wtf/HashMap.h>
#include <wtf/HashSet.h>
#include <wtf/ListHashSet.h>
#include <wtf/RefCounted.h>
#include <wtf/Vector.h>
......@@ -232,6 +235,8 @@ public:
void mainResourceFiredLoadEvent(DocumentLoader*, const KURL&);
void mainResourceFiredDOMContentEvent(DocumentLoader*, const KURL&);
void getCookies(long callId, const String& url);
#if ENABLE(DATABASE)
void didOpenDatabase(Database*, const String& domain, const String& name, const String& version);
......@@ -307,7 +312,7 @@ private:
void resetInjectedScript();
void deleteCookie(const String& cookieName);
void deleteCookie(const String& cookieName, const String& domain);
#if ENABLE(JAVASCRIPT_DEBUGGER)
void startUserInitiatedProfilingSoon();
......@@ -321,6 +326,9 @@ private:
#if ENABLE(DOM_STORAGE)
InspectorDOMStorageResource* getDOMStorageResourceForId(int storageId);
#endif
ScriptObject buildObjectForCookie(const Cookie&);
ScriptArray buildArrayForCookies(ListHashSet<Cookie>&);
void focusNode();
......
......@@ -438,18 +438,6 @@ void InspectorDOMAgent::getEventListenersForNode(long callId, long nodeId)
m_frontend->didGetEventListenersForNode(callId, nodeId, listenersArray);
}
void InspectorDOMAgent::getCookies(long callId)
{
Document* doc = mainFrameDocument();
Vector<Cookie> cookiesList;
bool isImplemented = getRawCookies(doc, doc->cookieURL(), cookiesList);
if (!isImplemented)
m_frontend->didGetCookies(callId, m_frontend->newScriptArray(), doc->cookie());
else
m_frontend->didGetCookies(callId, buildArrayForCookies(cookiesList), String());
}
ScriptObject InspectorDOMAgent::buildObjectForNode(Node* node, int depth, NodeToIdMap* nodesMap)
{
ScriptObject value = m_frontend->newScriptObject();
......@@ -549,32 +537,6 @@ ScriptObject InspectorDOMAgent::buildObjectForEventListener(const RegisteredEven
return value;
}
ScriptObject InspectorDOMAgent::buildObjectForCookie(const Cookie& cookie)
{
ScriptObject value = m_frontend->newScriptObject();
value.set("name", cookie.name);
value.set("value", cookie.value);
value.set("domain", cookie.domain);
value.set("path", cookie.path);
value.set("expires", cookie.expires);
value.set("size", static_cast<int>(cookie.name.length() + cookie.value.length()));
value.set("httpOnly", cookie.httpOnly);
value.set("secure", cookie.secure);
value.set("session", cookie.session);
return value;
}
ScriptArray InspectorDOMAgent::buildArrayForCookies(const Vector<Cookie>& cookiesList)
{
ScriptArray cookies = m_frontend->newScriptArray();
unsigned length = cookiesList.size();
for (unsigned i = 0; i < length; ++i) {
const Cookie& cookie = cookiesList[i];
cookies.set(i, buildObjectForCookie(cookie));
}
return cookies;
}
Node* InspectorDOMAgent::innerFirstChild(Node* node)
{
if (node->isFrameOwnerElement()) {
......
......@@ -53,8 +53,6 @@ namespace WebCore {
class Node;
class Page;
struct Cookie;
struct EventListenerInfo {
EventListenerInfo(Node* node, const AtomicString& eventType, const EventListenerVector& eventListenerVector)
: node(node)
......@@ -88,7 +86,6 @@ namespace WebCore {
void removeAttribute(long callId, long elementId, const String& name);
void setTextNodeValue(long callId, long nodeId, const String& value);
void getEventListenersForNode(long callId, long nodeId);
void getCookies(long callId);
// Methods called from the InspectorController.
void setDocument(Document* document);
......@@ -116,9 +113,6 @@ namespace WebCore {
ScriptObject buildObjectForEventListener(const RegisteredEventListener& registeredEventListener, const AtomicString& eventType, Node* node);
ScriptObject buildObjectForCookie(const Cookie& cookie);
ScriptArray buildArrayForCookies(const Vector<Cookie>& cookiesList);
// We represent embedded doms as a part of the same hierarchy. Hence we treat children of frame owners differently.
// We also skip whitespace text nodes conditionally. Following methods encapsulate these specifics.
Node* innerFirstChild(Node* node);
......
......@@ -125,6 +125,13 @@ void InspectorFrontend::removeResource(long long identifier)
function->call();
}
void InspectorFrontend::addCookieDomain(String domain)
{
OwnPtr<ScriptFunctionCall> function(newFunctionCall("addCookieDomain"));
function->appendArgument(domain);
function->call();
}
void InspectorFrontend::updateFocusedNode(long long nodeId)
{
OwnPtr<ScriptFunctionCall> function(newFunctionCall("updateFocusedNode"));
......
......@@ -70,6 +70,8 @@ namespace WebCore {
bool updateResource(long long identifier, const ScriptObject& resourceObj);
void removeResource(long long identifier);
void addCookieDomain(String);
void updateFocusedNode(long long nodeId);
void setAttachedWindow(bool attached);
void showPanel(int panel);
......
......@@ -27,7 +27,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
WebInspector.CookieItemsView = function()
WebInspector.CookieItemsView = function(cookieDomain)
{
WebInspector.View.call(this);
......@@ -40,6 +40,8 @@ WebInspector.CookieItemsView = function()
this.refreshButton = new WebInspector.StatusBarButton(WebInspector.UIString("Refresh"), "refresh-storage-status-bar-item");
this.refreshButton.addEventListener("click", this._refreshButtonClicked.bind(this), false);
this._cookieDomain = cookieDomain;
}
WebInspector.CookieItemsView.prototype = {
......@@ -83,7 +85,7 @@ WebInspector.CookieItemsView.prototype = {
}
}
WebInspector.Cookies.getCookiesAsync(callback);
WebInspector.Cookies.getCookiesAsync(callback, this._cookieDomain);
},
dataGridForCookies: function(cookies)
......@@ -260,7 +262,7 @@ WebInspector.CookieItemsView.prototype = {
return;
var cookie = this._dataGrid.selectedNode.cookie;
InspectorController.deleteCookie(cookie.name);
InspectorController.deleteCookie(cookie.name, this._cookieDomain);
this.update();
},
......
......@@ -437,7 +437,7 @@ WebInspector.DOMAgent.prototype = {
WebInspector.Cookies = {}
WebInspector.Cookies.getCookiesAsync = function(callback)
WebInspector.Cookies.getCookiesAsync = function(callback, cookieDomain)
{
function mycallback(cookies, cookiesString) {
if (cookiesString)
......@@ -446,7 +446,7 @@ WebInspector.Cookies.getCookiesAsync = function(callback)
callback(cookies, true);
}
var callId = WebInspector.Callback.wrap(mycallback);
InspectorController.getCookies(callId);
InspectorController.getCookies(callId, cookieDomain);
}
WebInspector.Cookies.buildCookiesFromString = function(rawCookieString)
......
......@@ -63,9 +63,6 @@ WebInspector.StoragePanel = function(database)
this.sidebarTree.appendChild(this.cookieListTreeElement);
this.cookieListTreeElement.expand();
this.cookieTreeElement = new WebInspector.CookieSidebarTreeElement();
this.cookieListTreeElement.appendChild(this.cookieTreeElement);
this.storageViews = document.createElement("div");
this.storageViews.id = "storage-views";
this.element.appendChild(this.storageViews);
......@@ -120,11 +117,14 @@ WebInspector.StoragePanel.prototype = {
this._domStorage = [];
delete this._cookieView;
this._cookieDomains = {};
this._cookieViews = {};
this.databasesListTreeElement.removeChildren();
this.localStorageListTreeElement.removeChildren();
this.sessionStorageListTreeElement.removeChildren();
this.cookieListTreeElement.removeChildren();
this.storageViews.removeChildren();
this.storageViewStatusBarItemsContainer.removeChildren();
......@@ -146,6 +146,17 @@ WebInspector.StoragePanel.prototype = {
database._databasesTreeElement = databaseTreeElement;
this.databasesListTreeElement.appendChild(databaseTreeElement);
},
addCookieDomain: function(domain)
{
// Eliminate duplicate domains from the list.
if (typeof this._cookieDomains[domain] !== "undefined")
return;
var cookieDomainTreeElement = new WebInspector.CookieSidebarTreeElement(domain);
this.cookieListTreeElement.appendChild(cookieDomainTreeElement);
this._cookieDomains[domain] = true;
},
addDOMStorage: function(domStorage)
{
......@@ -240,15 +251,15 @@ WebInspector.StoragePanel.prototype = {
this.storageViewStatusBarItemsContainer.appendChild(statusBarItems[i]);
},
showCookies: function()
showCookies: function(cookieDomain)
{
if (this.visibleView)
this.visibleView.hide();
var view = this._cookieView;
var view = this._cookieViews[cookieDomain];
if (!view) {
view = new WebInspector.CookieItemsView();
this._cookieView = view;
view = new WebInspector.CookieItemsView(cookieDomain);
this._cookieViews[cookieDomain] = view;
}
view.show(this.storageViews);
......@@ -568,9 +579,10 @@ WebInspector.DOMStorageSidebarTreeElement.prototype = {
WebInspector.DOMStorageSidebarTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype;
WebInspector.CookieSidebarTreeElement = function()
WebInspector.CookieSidebarTreeElement = function(cookieDomain)
{
WebInspector.SidebarTreeElement.call(this, "cookie-sidebar-tree-item", null, "", null, false);
WebInspector.SidebarTreeElement.call(this, "cookie-sidebar-tree-item", cookieDomain, "", null, false);
this._cookieDomain = cookieDomain;
this.refreshTitles();
}
......@@ -578,17 +590,7 @@ WebInspector.CookieSidebarTreeElement = function()
WebInspector.CookieSidebarTreeElement.prototype = {
onselect: function()
{
WebInspector.panels.storage.showCookies();
},
get mainTitle()
{
return WebInspector.UIString("Cookies");
},
set mainTitle(x)
{
// Do nothing.
WebInspector.panels.storage.showCookies(this._cookieDomain);
},
get subtitle()
......
......@@ -1041,6 +1041,11 @@ WebInspector.addDatabase = function(payload)
this.panels.storage.addDatabase(database);
}
WebInspector.addCookieDomain = function(domain)
{
this.panels.storage.addCookieDomain(domain);
}
WebInspector.addDOMStorage = function(payload)
{
var domStorage = new WebInspector.DOMStorage(
......
......@@ -27,6 +27,7 @@
#define Cookie_h
#include "PlatformString.h"
#include "StringHash.h"
namespace WebCore {
......@@ -58,6 +59,24 @@ namespace WebCore {
bool session;
};
struct CookieHash {
static unsigned hash(Cookie key)
{
return StringHash::hash(key.name) + StringHash::hash(key.domain) + StringHash::hash(key.path) + key.secure;
}
static bool equal(Cookie a, Cookie b)
{
return a.name == b.name && a.domain == b.domain && a.path == b.path && a.secure == b.secure;
}
};
}
namespace WTF {
template<typename T> struct DefaultHash;
template<> struct DefaultHash<WebCore::Cookie> {
typedef WebCore::CookieHash Hash;
};
}
#endif
......@@ -148,9 +148,26 @@ bool getRawCookies(const Document*, const KURL& url, Vector<Cookie>& rawCookies)
return true;
}
void deleteCookie(const Document*, const KURL&, const String&)
void deleteCookie(const Document*, const KURL& url, const String& name)
{
// FIXME: Not yet implemented