<rdar://problem/7908830> and https://bugs.webkit.org/show_bug.cgi?id=34679 Location...
authorbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 13 Mar 2012 15:57:37 +0000 (15:57 +0000)
committerbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 13 Mar 2012 15:57:37 +0000 (15:57 +0000)
Reviewed by Adam Barth.

Source/WebCore:

Test: fast/loader/window-properties-restored-from-page-cache.html

Give DOMWindowProperties the ability to reconnect to their Frame:
* page/DOMWindowProperty.cpp:
(WebCore::DOMWindowProperty::reconnectFrame):
* page/DOMWindowProperty.h:
(DOMWindowProperty):

Let ApplicationCache do some extra work when reconnecting:
* loader/appcache/DOMApplicationCache.cpp:
(WebCore::DOMApplicationCache::reconnectFrame):
(WebCore):
* loader/appcache/DOMApplicationCache.h:
(DOMApplicationCache):

Let IndexDB do some extra work when reconnecting:
* Modules/indexeddb/DOMWindowIndexedDatabase.cpp:
(WebCore::DOMWindowIndexedDatabase::disconnectFrame):
(WebCore::DOMWindowIndexedDatabase::reconnectFrame):
(WebCore::DOMWindowIndexedDatabase::webkitIndexedDB):
* Modules/indexeddb/DOMWindowIndexedDatabase.h:
(DOMWindowIndexedDatabase):

Tell the DOMWindow to suspend to the page cache:
* history/CachedFrame.cpp:
(WebCore::CachedFrame::CachedFrame):

Tell the DOMWindow to resume from the page cache:
* loader/FrameLoader.cpp:
(WebCore::FrameLoader::open):

* page/DOMWindow.cpp:
(WebCore::DOMWindow::DOMWindow):
(WebCore::DOMWindow::~DOMWindow): Call clearDOMWindowProperties directly instead of clear()
(WebCore::DOMWindow::frameDestroyed): Ditto.
(WebCore::DOMWindow::clear): Only clear if the DOMWindow is not suspended for the page cache.
(WebCore::DOMWindow::suspendForPageCache): Disconnect properties and set the page cache flag.
(WebCore::DOMWindow::resumeFromPageCache): Reconnect properties and revert the page cache flag.
(WebCore::DOMWindow::disconnectDOMWindowProperties): Only disconnect the registered properties.
(WebCore::DOMWindow::reconnectDOMWindowProperties):
(WebCore::DOMWindow::clearDOMWindowProperties): Disconnect the registered properties then clear them out.

For all of the following, if the DOMWindow is not displayed in a frame (i.e., it is suspended), do nothing:
(WebCore::DOMWindow::screen):
(WebCore::DOMWindow::history):
(WebCore::DOMWindow::crypto):
(WebCore::DOMWindow::locationbar):
(WebCore::DOMWindow::menubar):
(WebCore::DOMWindow::personalbar):
(WebCore::DOMWindow::scrollbars):
(WebCore::DOMWindow::statusbar):
(WebCore::DOMWindow::toolbar):
(WebCore::DOMWindow::console):
(WebCore::DOMWindow::applicationCache):
(WebCore::DOMWindow::navigator):
(WebCore::DOMWindow::performance):
(WebCore::DOMWindow::location):
(WebCore::DOMWindow::sessionStorage):
(WebCore::DOMWindow::localStorage):
(WebCore::DOMWindow::webkitNotifications):
(WebCore::DOMWindow::postMessageTimerFired):
(WebCore::DOMWindow::getSelection):
(WebCore::DOMWindow::styleMedia):
(WebCore::DOMWindow::webkitStorageInfo):
* page/DOMWindow.h:

LayoutTests:

* fast/loader/window-properties-restored-from-page-cache-expected.txt: Added.
* fast/loader/window-properties-restored-from-page-cache.html: Added.

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

14 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/loader/window-properties-restored-from-page-cache-expected.txt [new file with mode: 0644]
LayoutTests/fast/loader/window-properties-restored-from-page-cache.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/Modules/indexeddb/DOMWindowIndexedDatabase.cpp
Source/WebCore/Modules/indexeddb/DOMWindowIndexedDatabase.h
Source/WebCore/history/CachedFrame.cpp
Source/WebCore/loader/FrameLoader.cpp
Source/WebCore/loader/appcache/DOMApplicationCache.cpp
Source/WebCore/loader/appcache/DOMApplicationCache.h
Source/WebCore/page/DOMWindow.cpp
Source/WebCore/page/DOMWindow.h
Source/WebCore/page/DOMWindowProperty.cpp
Source/WebCore/page/DOMWindowProperty.h

index a29ab1d..b0014d7 100644 (file)
@@ -1,3 +1,13 @@
+2012-03-12  Brady Eidson  <beidson@apple.com>
+
+        <rdar://problem/7908830> and https://bugs.webkit.org/show_bug.cgi?id=34679
+        Location and other objects are dysfunctional after a document gets restored from page cache
+
+        Reviewed by Adam Barth.
+
+        * fast/loader/window-properties-restored-from-page-cache-expected.txt: Added.
+        * fast/loader/window-properties-restored-from-page-cache.html: Added.
+
 2012-03-13  ChangSeok Oh  <shivamidow@gmail.com>
 
         [EFL] [DRT] Implement scheduleAsynchronousKeyDown.
diff --git a/LayoutTests/fast/loader/window-properties-restored-from-page-cache-expected.txt b/LayoutTests/fast/loader/window-properties-restored-from-page-cache-expected.txt
new file mode 100644 (file)
index 0000000..fccbaed
--- /dev/null
@@ -0,0 +1,20 @@
+This test makes sure that various properties on the window object are correctly reconnected after restoring a page from the page cache.
+[object DOMApplicationCache] 
+[object Console] 
+[object Crypto] 
+[object History] 
+[object Storage] 
+true 
+[object BarInfo] 
+[object StyleMedia] 
+[object BarInfo] 
+[object Navigator] 
+[object BarInfo] 
+[object Screen] 
+[object BarInfo] 
+true 
+[object Storage] 
+[object BarInfo] 
+[object BarInfo] 
+
+All tests passed.
diff --git a/LayoutTests/fast/loader/window-properties-restored-from-page-cache.html b/LayoutTests/fast/loader/window-properties-restored-from-page-cache.html
new file mode 100644 (file)
index 0000000..58bf47f
--- /dev/null
@@ -0,0 +1,110 @@
+<script>
+if (window.layoutTestController) {
+       layoutTestController.dumpAsText();
+       layoutTestController.waitUntilDone();
+       layoutTestController.overridePreference("WebKitUsesPageCachePreferenceKey", 1);
+}
+
+var cachedApplicationCache = window.applicationCache;
+var cachedConsole = window.console;
+var cachedCrypto = window.crypto;
+var cachedHistory = window.history;
+var cachedLocalStorage = window.localStorage;
+var cachedLocation = window.location;
+var cachedLocationbar = window.locationbar;
+var cachedMedia = window.styleMedia;
+var cachedMenubar = window.menubar;
+var cachedNavigator = window.navigator;
+var cachedPersonalbar = window.personalbar;
+var cachedScreen = window.screen;
+var cachedScrollbars = window.scrollbars;
+var cachedSelection = window.getSelection();
+var cachedSessionStorage = window.sessionStorage;
+var cachedStatusbar = window.statusbar;
+var cachedToolbar = window.toolbar;
+
+function logMessage(msg)
+{
+       document.getElementById("outputDiv").innerText += msg + " \n";
+}
+
+function logErrorMessage(msg)
+{
+       document.getElementById("errorDiv").innerText += msg + " \n";
+}
+
+window.onpageshow = function(evt) {
+       if (!evt.persisted) {
+               window.setTimeout("window.location.href = 'resources/empty-document-goes-back.html'", 0);
+               return;
+       }
+       
+       // First alert all of the objects to make sure we get a valid toString()-ification
+       // instead of "undefined", "null", or "Object"
+       logMessage(window.applicationCache);
+       logMessage(window.console);
+       logMessage(window.crypto);
+       logMessage(window.history);
+       logMessage(window.localStorage);
+       logMessage(window.location != null && window.location != undefined);
+       logMessage(window.locationbar);
+       logMessage(window.styleMedia);
+       logMessage(window.menubar);
+       logMessage(window.navigator);
+       logMessage(window.personalbar);
+       logMessage(window.screen);
+       logMessage(window.scrollbars);
+       logMessage(window.getSelection() != null && window.getSelection() != undefined);
+       logMessage(window.sessionStorage);
+       logMessage(window.statusbar);
+       logMessage(window.toolbar);
+       
+       // Then make sure the window properties match the cached references from the initial page load
+       if (cachedApplicationCache != window.applicationCache)
+               logErrorMessage("applicationCache");
+       if (cachedConsole != window.console)
+               logErrorMessage("console");
+       if (cachedCrypto != window.crypto)
+               logErrorMessage("crypto");
+       if (cachedHistory != window.history)
+               logErrorMessage("history");
+       if (cachedLocalStorage != window.localStorage)
+               logErrorMessage("localStorage");
+       if (cachedLocation != window.location)
+               logErrorMessage("location");
+       if (cachedLocationbar != window.locationbar)
+               logErrorMessage("locationbar");
+       if (cachedMedia != window.styleMedia)
+               logErrorMessage("styleMedia");
+       if (cachedMenubar != window.menubar)
+               logErrorMessage("menubar");
+       if (cachedNavigator != window.navigator)
+               logErrorMessage("navigator");
+       if (cachedPersonalbar != window.personalbar)
+               logErrorMessage("personalbar");
+       if (cachedScreen != window.screen)
+               logErrorMessage("screen");
+       if (cachedScrollbars != window.scrollbars)
+               logErrorMessage("scrollbars");
+       if (cachedSelection != window.getSelection())
+               logErrorMessage("getSelection");
+       if (cachedSessionStorage != window.sessionStorage)
+               logErrorMessage("sessionStorage");
+       if (cachedStatusbar != window.statusbar)
+               logErrorMessage("statusbar");
+       if (cachedToolbar != window.toolbar)
+               logErrorMessage("toolbar");
+
+       if (document.getElementById("errorDiv").innerText == "")
+               document.getElementById("errorDiv").innerText = "All tests passed.";
+
+       if (window.layoutTestController)
+               layoutTestController.notifyDone();
+}
+
+</script>
+<body>
+This test makes sure that various properties on the window object are correctly reconnected after restoring a page from the page cache.<br>
+<div id="outputDiv"></div><br>
+<div id="errorDiv"></div>
+</body>
\ No newline at end of file
index 2acc1ea..d9b78b1 100644 (file)
@@ -1,3 +1,78 @@
+2012-03-12  Brady Eidson  <beidson@apple.com>
+
+        <rdar://problem/7908830> and https://bugs.webkit.org/show_bug.cgi?id=34679
+        Location and other objects are dysfunctional after a document gets restored from page cache
+
+        Reviewed by Adam Barth.
+
+        Test: fast/loader/window-properties-restored-from-page-cache.html
+
+        Give DOMWindowProperties the ability to reconnect to their Frame:
+        * page/DOMWindowProperty.cpp:
+        (WebCore::DOMWindowProperty::reconnectFrame):
+        * page/DOMWindowProperty.h:
+        (DOMWindowProperty):
+
+        Let ApplicationCache do some extra work when reconnecting:
+        * loader/appcache/DOMApplicationCache.cpp:
+        (WebCore::DOMApplicationCache::reconnectFrame):
+        (WebCore):
+        * loader/appcache/DOMApplicationCache.h:
+        (DOMApplicationCache):
+
+        Let IndexDB do some extra work when reconnecting:
+        * Modules/indexeddb/DOMWindowIndexedDatabase.cpp:
+        (WebCore::DOMWindowIndexedDatabase::disconnectFrame):
+        (WebCore::DOMWindowIndexedDatabase::reconnectFrame):
+        (WebCore::DOMWindowIndexedDatabase::webkitIndexedDB):
+        * Modules/indexeddb/DOMWindowIndexedDatabase.h:
+        (DOMWindowIndexedDatabase):
+
+        Tell the DOMWindow to suspend to the page cache:
+        * history/CachedFrame.cpp:
+        (WebCore::CachedFrame::CachedFrame):
+
+        Tell the DOMWindow to resume from the page cache:
+        * loader/FrameLoader.cpp:
+        (WebCore::FrameLoader::open):
+
+        * page/DOMWindow.cpp:
+        (WebCore::DOMWindow::DOMWindow):
+        (WebCore::DOMWindow::~DOMWindow): Call clearDOMWindowProperties directly instead of clear()
+        (WebCore::DOMWindow::frameDestroyed): Ditto.
+        (WebCore::DOMWindow::clear): Only clear if the DOMWindow is not suspended for the page cache.
+        (WebCore::DOMWindow::suspendForPageCache): Disconnect properties and set the page cache flag.
+        (WebCore::DOMWindow::resumeFromPageCache): Reconnect properties and revert the page cache flag.
+        (WebCore::DOMWindow::disconnectDOMWindowProperties): Only disconnect the registered properties.
+        (WebCore::DOMWindow::reconnectDOMWindowProperties):
+        (WebCore::DOMWindow::clearDOMWindowProperties): Disconnect the registered properties then clear them out.
+
+        For all of the following, if the DOMWindow is not displayed in a frame (i.e., it is suspended), do nothing:
+        (WebCore::DOMWindow::screen):
+        (WebCore::DOMWindow::history):
+        (WebCore::DOMWindow::crypto):
+        (WebCore::DOMWindow::locationbar):
+        (WebCore::DOMWindow::menubar):
+        (WebCore::DOMWindow::personalbar):
+        (WebCore::DOMWindow::scrollbars):
+        (WebCore::DOMWindow::statusbar):
+        (WebCore::DOMWindow::toolbar):
+        (WebCore::DOMWindow::console):
+        (WebCore::DOMWindow::applicationCache):
+        (WebCore::DOMWindow::navigator):
+        (WebCore::DOMWindow::performance):
+        (WebCore::DOMWindow::location):
+        (WebCore::DOMWindow::sessionStorage):
+        (WebCore::DOMWindow::localStorage):
+        (WebCore::DOMWindow::webkitNotifications):
+        (WebCore::DOMWindow::postMessageTimerFired):
+        (WebCore::DOMWindow::getSelection):
+        (WebCore::DOMWindow::styleMedia):
+        (WebCore::DOMWindow::webkitStorageInfo):
+        * page/DOMWindow.h:
+
+
+
 2012-03-13  Dana Jansens  <danakj@chromium.org>
 
         [chromium] Use projectQuad to apply inverse mapRect
index 6ec2dc0..4bade70 100644 (file)
@@ -60,10 +60,16 @@ DOMWindowIndexedDatabase* DOMWindowIndexedDatabase::from(DOMWindow* window)
 
 void DOMWindowIndexedDatabase::disconnectFrame()
 {
-    m_idbFactory = 0;
+    m_suspendedIDBFactory = m_idbFactory.release();
     DOMWindowProperty::disconnectFrame();
 }
 
+void DOMWindowIndexedDatabase::reconnectFrame(Frame* frame)
+{
+    DOMWindowProperty::reconnectFrame(frame);
+    m_idbFactory = m_suspendedIDBFactory.release();
+}
+
 IDBFactory* DOMWindowIndexedDatabase::webkitIndexedDB(DOMWindow* window)
 {
     return from(window)->webkitIndexedDB();
@@ -82,7 +88,10 @@ IDBFactory* DOMWindowIndexedDatabase::webkitIndexedDB()
     if (!document->securityOrigin()->canAccessDatabase())
         return 0;
 
-    if (!m_idbFactory && m_window->isCurrentlyDisplayedInFrame())
+    if (!m_window->isCurrentlyDisplayedInFrame())
+        return 0;
+
+    if (!m_idbFactory)
         m_idbFactory = IDBFactory::create(PageGroupIndexedDatabase::from(page->group())->factoryBackend());
     return m_idbFactory.get();
 }
index d71f82d..d1a10b1 100644 (file)
@@ -44,6 +44,7 @@ public:
     static IDBFactory* webkitIndexedDB(DOMWindow*);
 
     virtual void disconnectFrame() OVERRIDE;
+    virtual void reconnectFrame(Frame*) OVERRIDE;
 
 private:
     explicit DOMWindowIndexedDatabase(DOMWindow*);
@@ -52,6 +53,7 @@ private:
 
     DOMWindow* m_window;
     RefPtr<IDBFactory> m_idbFactory;
+    RefPtr<IDBFactory> m_suspendedIDBFactory;
 };
 
 } // namespace WebCore
index 9b0d2fe..34f913f 100644 (file)
@@ -172,6 +172,9 @@ CachedFrame::CachedFrame(Frame* frame)
     m_document->suspendScriptedAnimationControllerCallbacks();
     m_document->suspendActiveDOMObjects(ActiveDOMObject::DocumentWillBecomeInactive);
     m_cachedFrameScriptData = adoptPtr(new ScriptCachedFrameData(frame));
+    
+    if (DOMWindow* domWindow = m_cachedFrameScriptData->domWindow())
+        domWindow->suspendForPageCache();
 
     frame->loader()->client()->savePlatformDataToCachedFrame(this);
 
index 6776ad7..27810aa 100644 (file)
@@ -2056,6 +2056,7 @@ void FrameLoader::open(CachedFrameBase& cachedFrame)
     
     m_frame->setDocument(document);
     m_frame->setDOMWindow(cachedFrame.domWindow());
+    m_frame->domWindow()->resumeFromPageCache();
     m_frame->domWindow()->setURL(document->url());
     m_frame->domWindow()->setSecurityOrigin(document->securityOrigin());
 
index 245290b..11dcbb8 100644 (file)
@@ -55,6 +55,14 @@ void DOMApplicationCache::disconnectFrame()
     DOMWindowProperty::disconnectFrame();
 }
 
+void DOMApplicationCache::reconnectFrame(Frame* frame)
+{
+    DOMWindowProperty::reconnectFrame(frame);
+    ApplicationCacheHost* cacheHost = applicationCacheHost();
+    if (cacheHost)
+        cacheHost->setDOMApplicationCache(this);
+}
+
 ApplicationCacheHost* DOMApplicationCache::applicationCacheHost() const
 {
     if (!m_frame || !m_frame->loader()->documentLoader())
index fdb8dab..e3b2a2e 100644 (file)
@@ -48,6 +48,7 @@ public:
     ~DOMApplicationCache() { ASSERT(!m_frame); }
 
     virtual void disconnectFrame() OVERRIDE;
+    virtual void reconnectFrame(Frame*) OVERRIDE;
 
     unsigned short status() const;
     void update(ExceptionCode&);
index 2b30bbe..2e4762f 100644 (file)
@@ -390,44 +390,49 @@ bool DOMWindow::canShowModalDialogNow(const Frame* frame)
 DOMWindow::DOMWindow(Frame* frame)
     : FrameDestructionObserver(frame)
     , m_shouldPrintWhenFinishedLoading(false)
+    , m_suspendedForPageCache(false)
 {
 }
 
 DOMWindow::~DOMWindow()
 {
-    ASSERT(!m_screen);
-    ASSERT(!m_selection);
-    ASSERT(!m_history);
-    ASSERT(!m_crypto);
-    ASSERT(!m_locationbar);
-    ASSERT(!m_menubar);
-    ASSERT(!m_personalbar);
-    ASSERT(!m_scrollbars);
-    ASSERT(!m_statusbar);
-    ASSERT(!m_toolbar);
-    ASSERT(!m_console);
-    ASSERT(!m_navigator);
+#ifndef NDEBUG
+    if (!m_suspendedForPageCache) {
+        ASSERT(!m_screen);
+        ASSERT(!m_selection);
+        ASSERT(!m_history);
+        ASSERT(!m_crypto);
+        ASSERT(!m_locationbar);
+        ASSERT(!m_menubar);
+        ASSERT(!m_personalbar);
+        ASSERT(!m_scrollbars);
+        ASSERT(!m_statusbar);
+        ASSERT(!m_toolbar);
+        ASSERT(!m_console);
+        ASSERT(!m_navigator);
 #if ENABLE(WEB_TIMING)
-    ASSERT(!m_performance);
+        ASSERT(!m_performance);
 #endif
-    ASSERT(!m_location);
-    ASSERT(!m_media);
-    ASSERT(!m_sessionStorage);
-    ASSERT(!m_localStorage);
-    ASSERT(!m_applicationCache);
+        ASSERT(!m_location);
+        ASSERT(!m_media);
+        ASSERT(!m_sessionStorage);
+        ASSERT(!m_localStorage);
+        ASSERT(!m_applicationCache);
 #if ENABLE(NOTIFICATIONS)
-    ASSERT(!m_notifications);
+        ASSERT(!m_notifications);
 #endif
 #if ENABLE(BLOB)
-    ASSERT(!m_domURL);
+        ASSERT(!m_domURL);
 #endif
 #if ENABLE(QUOTA)
-    ASSERT(!m_storageInfo);
+        ASSERT(!m_storageInfo);
+#endif
+    }
 #endif
 
-    // This clear should be unnessary given the ASSERTs above, but we don't
-    // want any of these objects to hang around after we've been destroyed.
-    clear();
+    // As the ASSERTs above indicate, this clear should only be necesary if this DOMWindow is suspended for the page cache.
+    // But we don't want to risk any of these objects hanging around after we've been destroyed.
+    clearDOMWindowProperties();
 
     removeAllUnloadEventListeners(this);
     removeAllBeforeUnloadEventListeners(this);
@@ -466,7 +471,7 @@ Page* DOMWindow::page()
 void DOMWindow::frameDestroyed()
 {
     FrameDestructionObserver::frameDestroyed();
-    clear();
+    clearDOMWindowProperties();
 }
 
 void DOMWindow::willDetachPage()
@@ -496,9 +501,54 @@ void DOMWindow::unregisterProperty(DOMWindowProperty* property)
 
 void DOMWindow::clear()
 {
+    // The main frame will always try to clear its DOMWindow when a new load is committed, even if that
+    // DOMWindow is suspended in the page cache.
+    // In those cases we need to make sure we don't actually clear it.
+    if (m_suspendedForPageCache)
+        return;
+    
+    clearDOMWindowProperties();
+}
+
+void DOMWindow::suspendForPageCache()
+{
+    disconnectDOMWindowProperties();
+    m_suspendedForPageCache = true;
+}
+
+void DOMWindow::resumeFromPageCache()
+{
+    reconnectDOMWindowProperties();
+    m_suspendedForPageCache = false;
+}
+
+void DOMWindow::disconnectDOMWindowProperties()
+{
     HashSet<DOMWindowProperty*>::iterator stop = m_properties.end();
     for (HashSet<DOMWindowProperty*>::iterator it = m_properties.begin(); it != stop; ++it)
         (*it)->disconnectFrame();
+
+#if ENABLE(NOTIFICATIONS)
+    // FIXME: Notifications shouldn't have different disconnection logic than
+    // the rest of the DOMWindowProperties.
+    // There is currently no way to reconnect them in resumeFromPageCache() so
+    // they will be broken after returning to a cached page.
+    // This should be fixed as part of https://bugs.webkit.org/show_bug.cgi?id=79636
+    resetNotifications();
+#endif
+}
+
+void DOMWindow::reconnectDOMWindowProperties()
+{
+    ASSERT(m_suspendedForPageCache);
+    HashSet<DOMWindowProperty*>::iterator stop = m_properties.end();
+    for (HashSet<DOMWindowProperty*>::iterator it = m_properties.begin(); it != stop; ++it)
+        (*it)->reconnectFrame(m_frame);
+}
+
+void DOMWindow::clearDOMWindowProperties()
+{
+    disconnectDOMWindowProperties();
     m_properties.clear();
 
     m_screen = 0;
@@ -551,84 +601,108 @@ int DOMWindow::orientation() const
 
 Screen* DOMWindow::screen() const
 {
-    if (!m_screen && isCurrentlyDisplayedInFrame())
+    if (!isCurrentlyDisplayedInFrame())
+        return 0;
+    if (!m_screen)
         m_screen = Screen::create(m_frame);
     return m_screen.get();
 }
 
 History* DOMWindow::history() const
 {
-    if (!m_history && isCurrentlyDisplayedInFrame())
+    if (!isCurrentlyDisplayedInFrame())
+        return 0;
+    if (!m_history)
         m_history = History::create(m_frame);
     return m_history.get();
 }
 
 Crypto* DOMWindow::crypto() const
 {
-    if (!m_crypto && isCurrentlyDisplayedInFrame())
+    if (!isCurrentlyDisplayedInFrame())
+        return 0;
+    if (!m_crypto)
         m_crypto = Crypto::create();
     return m_crypto.get();
 }
 
 BarInfo* DOMWindow::locationbar() const
 {
-    if (!m_locationbar && isCurrentlyDisplayedInFrame())
+    if (!isCurrentlyDisplayedInFrame())
+        return 0;
+    if (!m_locationbar)
         m_locationbar = BarInfo::create(m_frame, BarInfo::Locationbar);
     return m_locationbar.get();
 }
 
 BarInfo* DOMWindow::menubar() const
 {
-    if (!m_menubar && isCurrentlyDisplayedInFrame())
+    if (!isCurrentlyDisplayedInFrame())
+        return 0;
+    if (!m_menubar)
         m_menubar = BarInfo::create(m_frame, BarInfo::Menubar);
     return m_menubar.get();
 }
 
 BarInfo* DOMWindow::personalbar() const
 {
-    if (!m_personalbar && isCurrentlyDisplayedInFrame())
+    if (!isCurrentlyDisplayedInFrame())
+        return 0;
+    if (!m_personalbar)
         m_personalbar = BarInfo::create(m_frame, BarInfo::Personalbar);
     return m_personalbar.get();
 }
 
 BarInfo* DOMWindow::scrollbars() const
 {
-    if (!m_scrollbars && isCurrentlyDisplayedInFrame())
+    if (!isCurrentlyDisplayedInFrame())
+        return 0;
+    if (!m_scrollbars)
         m_scrollbars = BarInfo::create(m_frame, BarInfo::Scrollbars);
     return m_scrollbars.get();
 }
 
 BarInfo* DOMWindow::statusbar() const
 {
-    if (!m_statusbar && isCurrentlyDisplayedInFrame())
+    if (!isCurrentlyDisplayedInFrame())
+        return 0;
+    if (!m_statusbar)
         m_statusbar = BarInfo::create(m_frame, BarInfo::Statusbar);
     return m_statusbar.get();
 }
 
 BarInfo* DOMWindow::toolbar() const
 {
-    if (!m_toolbar && isCurrentlyDisplayedInFrame())
+    if (!isCurrentlyDisplayedInFrame())
+        return 0;
+    if (!m_toolbar)
         m_toolbar = BarInfo::create(m_frame, BarInfo::Toolbar);
     return m_toolbar.get();
 }
 
 Console* DOMWindow::console() const
 {
-    if (!m_console && isCurrentlyDisplayedInFrame())
+    if (!isCurrentlyDisplayedInFrame())
+        return 0;
+    if (!m_console)
         m_console = Console::create(m_frame);
     return m_console.get();
 }
 
 DOMApplicationCache* DOMWindow::applicationCache() const
 {
-    if (!m_applicationCache && isCurrentlyDisplayedInFrame())
+    if (!isCurrentlyDisplayedInFrame())
+        return 0;
+    if (!m_applicationCache)
         m_applicationCache = DOMApplicationCache::create(m_frame);
     return m_applicationCache.get();
 }
 
 Navigator* DOMWindow::navigator() const
 {
-    if (!m_navigator && isCurrentlyDisplayedInFrame())
+    if (!isCurrentlyDisplayedInFrame())
+        return 0;
+    if (!m_navigator)
         m_navigator = Navigator::create(m_frame);
     return m_navigator.get();
 }
@@ -636,7 +710,9 @@ Navigator* DOMWindow::navigator() const
 #if ENABLE(WEB_TIMING)
 Performance* DOMWindow::performance() const
 {
-    if (!m_performance && isCurrentlyDisplayedInFrame())
+    if (!isCurrentlyDisplayedInFrame())
+        return 0;
+    if (!m_performance)
         m_performance = Performance::create(m_frame);
     return m_performance.get();
 }
@@ -644,14 +720,18 @@ Performance* DOMWindow::performance() const
 
 Location* DOMWindow::location() const
 {
-    if (!m_location && isCurrentlyDisplayedInFrame())
+    if (!isCurrentlyDisplayedInFrame())
+        return 0;
+    if (!m_location)
         m_location = Location::create(m_frame);
     return m_location.get();
 }
 
 Storage* DOMWindow::sessionStorage(ExceptionCode& ec) const
 {
-    if (m_sessionStorage || !isCurrentlyDisplayedInFrame())
+    if (!isCurrentlyDisplayedInFrame())
+        return 0;
+    if (m_sessionStorage)
         return m_sessionStorage.get();
 
     Document* document = this->document();
@@ -676,7 +756,9 @@ Storage* DOMWindow::sessionStorage(ExceptionCode& ec) const
 
 Storage* DOMWindow::localStorage(ExceptionCode& ec) const
 {
-    if (m_localStorage || !isCurrentlyDisplayedInFrame())
+    if (!isCurrentlyDisplayedInFrame())
+        return 0;
+    if (m_localStorage)
         return m_localStorage.get();
 
     Document* document = this->document();
@@ -705,7 +787,9 @@ Storage* DOMWindow::localStorage(ExceptionCode& ec) const
 #if ENABLE(NOTIFICATIONS)
 NotificationCenter* DOMWindow::webkitNotifications() const
 {
-    if (m_notifications || !isCurrentlyDisplayedInFrame())
+    if (!isCurrentlyDisplayedInFrame())
+        return 0;
+    if (m_notifications)
         return m_notifications.get();
 
     Document* document = this->document();
@@ -788,7 +872,7 @@ void DOMWindow::postMessageTimerFired(PassOwnPtr<PostMessageTimer> t)
 {
     OwnPtr<PostMessageTimer> timer(t);
 
-    if (!document())
+    if (!document() || !isCurrentlyDisplayedInFrame())
         return;
 
     RefPtr<MessageEvent> event = timer->event(document());
@@ -796,7 +880,7 @@ void DOMWindow::postMessageTimerFired(PassOwnPtr<PostMessageTimer> t)
     // Give the embedder a chance to intercept this postMessage because this
     // DOMWindow might be a proxy for another in browsers that support
     // postMessage calls across WebKit instances.
-    if (isCurrentlyDisplayedInFrame() && m_frame->loader()->client()->willCheckAndDispatchMessageEvent(timer->targetOrigin(), event.get()))
+    if (m_frame->loader()->client()->willCheckAndDispatchMessageEvent(timer->targetOrigin(), event.get()))
         return;
 
     if (timer->targetOrigin()) {
@@ -814,7 +898,9 @@ void DOMWindow::postMessageTimerFired(PassOwnPtr<PostMessageTimer> t)
 
 DOMSelection* DOMWindow::getSelection()
 {
-    if (!m_selection && isCurrentlyDisplayedInFrame())
+    if (!isCurrentlyDisplayedInFrame())
+        return 0;
+    if (!m_selection)
         m_selection = DOMSelection::create(m_frame);
     return m_selection.get();
 }
@@ -1233,7 +1319,9 @@ Document* DOMWindow::document() const
 
 PassRefPtr<StyleMedia> DOMWindow::styleMedia() const
 {
-    if (!m_media && isCurrentlyDisplayedInFrame())
+    if (!isCurrentlyDisplayedInFrame())
+        return 0;
+    if (!m_media)
         m_media = StyleMedia::create(m_frame);
     return m_media.get();
 }
@@ -1832,7 +1920,9 @@ void DOMWindow::showModalDialog(const String& urlString, const String& dialogFea
 #if ENABLE(QUOTA)
 StorageInfo* DOMWindow::webkitStorageInfo() const
 {
-    if (!m_storageInfo && isCurrentlyDisplayedInFrame())
+    if (!isCurrentlyDisplayedInFrame())
+        return 0;
+    if (!m_storageInfo)
         m_storageInfo = StorageInfo::create();
     return m_storageInfo.get();
 }
index cdfd322..613624f 100644 (file)
@@ -95,6 +95,8 @@ namespace WebCore {
         void unregisterProperty(DOMWindowProperty*);
 
         void clear();
+        void suspendForPageCache();
+        void resumeFromPageCache();
 
         PassRefPtr<MediaQueryList> matchMedia(const String&);
 
@@ -412,10 +414,15 @@ namespace WebCore {
             PrepareDialogFunction = 0, void* functionContext = 0);
         bool isInsecureScriptAccess(DOMWindow* activeWindow, const String& urlString);
 
+        void clearDOMWindowProperties();
+        void disconnectDOMWindowProperties();
+        void reconnectDOMWindowProperties();
+
         RefPtr<SecurityOrigin> m_securityOrigin;
         KURL m_url;
 
         bool m_shouldPrintWhenFinishedLoading;
+        bool m_suspendedForPageCache;
 
         HashSet<DOMWindowProperty*> m_properties;
 
index 82f9316..31ea44e 100644 (file)
@@ -49,6 +49,13 @@ void DOMWindowProperty::disconnectFrame()
     m_frame = 0;
 }
 
+void DOMWindowProperty::reconnectFrame(Frame* frame)
+{
+    ASSERT(frame);
+    ASSERT(!m_frame);
+    m_frame = frame;
+}
+
 void DOMWindowProperty::willDetachPage()
 {
     // Subclasses should override this function to handle this notification.
index cd2d837..bc6600d 100644 (file)
@@ -35,6 +35,7 @@ public:
     explicit DOMWindowProperty(Frame*);
 
     virtual void disconnectFrame();
+    virtual void reconnectFrame(Frame*);
     virtual void willDetachPage();
 
     Frame* frame() const { return m_frame; }