Index: Source/WebKit/chromium/src/StorageAreaProxy.cpp |
=================================================================== |
--- Source/WebKit/chromium/src/StorageAreaProxy.cpp (revision 117067) |
+++ Source/WebKit/chromium/src/StorageAreaProxy.cpp (working copy) |
@@ -80,29 +80,42 @@ |
return String(); |
} |
-void StorageAreaProxy::setItem(const String& key, const String& value, ExceptionCode& ec, Frame* frame) |
+String StorageAreaProxy::setItem(const String& key, const String& value, ExceptionCode& ec, Frame* frame) |
{ |
+ WebKit::WebStorageArea::Result result = WebKit::WebStorageArea::ResultOK; |
+ WebKit::WebString oldValue; |
if (!canAccessStorage(frame)) |
ec = QUOTA_EXCEEDED_ERR; |
else { |
- WebKit::WebStorageArea::Result result = WebKit::WebStorageArea::ResultOK; |
- m_storageArea->setItem(key, value, frame->document()->url(), result); |
+ m_storageArea->setItem(key, value, frame->document()->url(), result, oldValue); |
ec = (result == WebKit::WebStorageArea::ResultOK) ? 0 : QUOTA_EXCEEDED_ERR; |
+ String oldValueString = oldValue; |
+ if (oldValueString != value && result == WebKit::WebStorageArea::ResultOK) |
+ storageEvent(key, oldValue, value, m_storageType, frame->document()->securityOrigin(), frame); |
} |
+ return oldValue; |
} |
-void StorageAreaProxy::removeItem(const String& key, Frame* frame) |
+String StorageAreaProxy::removeItem(const String& key, Frame* frame) |
{ |
if (!canAccessStorage(frame)) |
- return; |
- m_storageArea->removeItem(key, frame->document()->url()); |
+ return String(); |
+ WebKit::WebString oldValue; |
+ m_storageArea->removeItem(key, frame->document()->url(), oldValue); |
+ if (!oldValue.isNull()) |
+ storageEvent(key, oldValue, String(), m_storageType, frame->document()->securityOrigin(), frame); |
+ return oldValue; |
} |
-void StorageAreaProxy::clear(Frame* frame) |
+bool StorageAreaProxy::clear(Frame* frame) |
{ |
if (!canAccessStorage(frame)) |
- return; |
- m_storageArea->clear(frame->document()->url()); |
+ return false; |
+ bool clearedSomething; |
+ m_storageArea->clear(frame->document()->url(), clearedSomething); |
+ if (clearedSomething) |
+ storageEvent(String(), String(), String(), m_storageType, frame->document()->securityOrigin(), frame); |
+ return clearedSomething; |
} |
bool StorageAreaProxy::contains(const String& key, Frame* frame) const |
@@ -110,6 +123,54 @@ |
return !getItem(key, frame).isNull(); |
} |
+// FIXME: remove this method and the calls to it from our setters after multi-side patch landing is done. |
+// Copied from WebCore/storage/StorageEventDispatcher.cpp out of necessity. It's probably best to keep it current. |
+void StorageAreaProxy::storageEvent(const String& key, const String& oldValue, const String& newValue, StorageType storageType, SecurityOrigin* securityOrigin, Frame* sourceFrame) |
+{ |
+ Page* page = sourceFrame->page(); |
+ if (!page) |
+ return; |
+ |
+ // We need to copy all relevant frames from every page to a vector since sending the event to one frame might mutate the frame tree |
+ // of any given page in the group or mutate the page group itself. |
+ Vector<RefPtr<Frame> > frames; |
+ if (storageType == SessionStorage) { |
+ // Send events only to our page. |
+ for (Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext()) { |
+ if (sourceFrame != frame && frame->document()->securityOrigin()->equal(securityOrigin)) |
+ frames.append(frame); |
+ } |
+ |
+ for (unsigned i = 0; i < frames.size(); ++i) { |
+ // FIXME: maybe only raise if the window has an onstorage listener |
+ // attached to avoid creating the Storage instance. |
+ ExceptionCode ec = 0; |
+ Storage* storage = frames[i]->domWindow()->sessionStorage(ec); |
+ if (!ec) |
+ frames[i]->document()->enqueueWindowEvent(StorageEvent::create(eventNames().storageEvent, key, oldValue, newValue, sourceFrame->document()->url(), storage)); |
+ } |
+ } else { |
+ // Send events to every page. |
+ const HashSet<Page*>& pages = page->group().pages(); |
+ HashSet<Page*>::const_iterator end = pages.end(); |
+ for (HashSet<Page*>::const_iterator it = pages.begin(); it != end; ++it) { |
+ for (Frame* frame = (*it)->mainFrame(); frame; frame = frame->tree()->traverseNext()) { |
+ if (sourceFrame != frame && frame->document()->securityOrigin()->equal(securityOrigin)) |
+ frames.append(frame); |
+ } |
+ } |
+ |
+ for (unsigned i = 0; i < frames.size(); ++i) { |
+ // FIXME: maybe only raise if the window has an onstorage listener |
+ // attached to avoid creating the Storage instance. |
+ ExceptionCode ec = 0; |
+ Storage* storage = frames[i]->domWindow()->localStorage(ec); |
+ if (!ec) |
+ frames[i]->document()->enqueueWindowEvent(StorageEvent::create(eventNames().storageEvent, key, oldValue, newValue, sourceFrame->document()->url(), storage)); |
+ } |
+ } |
+} |
+ |
bool StorageAreaProxy::canAccessStorage(Frame* frame) const |
{ |
if (!frame->page()) |
@@ -119,10 +180,18 @@ |
return !webView->permissionClient() || webView->permissionClient()->allowStorage(webFrame, m_storageType == LocalStorage); |
} |
-void StorageAreaProxy::dispatchLocalStorageEvent(PageGroup* pageGroup, const String& key, const String& oldValue, const String& newValue, |
+void StorageAreaProxy::dispatchLocalStorageEvent(const String& pageGroupName, const String& key, const String& oldValue, const String& newValue, |
SecurityOrigin* securityOrigin, const KURL& pageURL, WebKit::WebStorageArea* sourceAreaInstance, bool originatedInProcess) |
{ |
- const HashSet<Page*>& pages = pageGroup->pages(); |
+ // FIXME: Multi-sided patch engineering alert ! |
+ // step 1: this method gets defined and implemented in webkit/webcore with the early return. |
+ // step 2: this method starts getting called by chromium still with the early return. |
+ // step 3: This class's setters are modified to no longer raise SessionStorage |
+ // events for inprocess changes and this early return is removed. |
+ if (originatedInProcess) |
+ return; |
+ |
+ const HashSet<Page*>& pages = PageGroup::pageGroup(pageGroupName)->pages(); |
for (HashSet<Page*>::const_iterator it = pages.begin(); it != pages.end(); ++it) { |
for (Frame* frame = (*it)->mainFrame(); frame; frame = frame->tree()->traverseNext()) { |
if (frame->document()->securityOrigin()->equal(securityOrigin) && !isEventSource(frame->domWindow()->optionalLocalStorage(), sourceAreaInstance)) { |
@@ -136,9 +205,9 @@ |
} |
} |
-static Page* findPageWithSessionStorageNamespace(PageGroup* pageGroup, const WebKit::WebStorageNamespace& sessionNamespace) |
+static Page* findPageWithSessionStorageNamespace(const String& pageGroupName, const WebKit::WebStorageNamespace& sessionNamespace) |
{ |
- const HashSet<Page*>& pages = pageGroup->pages(); |
+ const HashSet<Page*>& pages = PageGroup::pageGroup(pageGroupName)->pages(); |
for (HashSet<Page*>::const_iterator it = pages.begin(); it != pages.end(); ++it) { |
const bool createIfNeeded = true; |
StorageNamespaceProxy* proxy = static_cast<StorageNamespaceProxy*>((*it)->sessionStorage(createIfNeeded)); |
@@ -148,11 +217,19 @@ |
return 0; |
} |
-void StorageAreaProxy::dispatchSessionStorageEvent(PageGroup* pageGroup, const String& key, const String& oldValue, const String& newValue, |
+void StorageAreaProxy::dispatchSessionStorageEvent(const String& pageGroupName, const String& key, const String& oldValue, const String& newValue, |
SecurityOrigin* securityOrigin, const KURL& pageURL, const WebKit::WebStorageNamespace& sessionNamespace, |
WebKit::WebStorageArea* sourceAreaInstance, bool originatedInProcess) |
{ |
- Page* page = findPageWithSessionStorageNamespace(pageGroup, sessionNamespace); |
+ // FIXME: Multi-sided patch engineering alert ! |
+ // step 1: this method gets defined and implemented in webkit/webcore with the early return. |
+ // step 2: this method starts getting called by chromium still with the early return. |
+ // step 3: This class's setters are modified to no longer raise SessionStorage |
+ // events for inprocess changes and this early return is removed. |
+ if (originatedInProcess) |
+ return; |
+ |
+ Page* page = findPageWithSessionStorageNamespace(pageGroupName, sessionNamespace); |
if (!page) |
return; |