| 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;
|
|
|
|
|