Log which ActiveDOMObject(s) can't be suspended for PageCache.
authorakling@apple.com <akling@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 10 Jan 2015 00:43:48 +0000 (00:43 +0000)
committerakling@apple.com <akling@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 10 Jan 2015 00:43:48 +0000 (00:43 +0000)
<https://webkit.org/b/139697>

Reviewed by Chris Dumez.

Give ActiveDOMObject a pure virtual activeDOMObjectName() so we can
find their names.

Dump the names of all the ActiveDOMObjects that fail to suspend when
we're trying to put a page into PageCache.

* Modules/encryptedmedia/MediaKeySession.h:
* Modules/geolocation/Geolocation.h:
* Modules/indexeddb/IDBDatabase.h:
* Modules/indexeddb/IDBRequest.h:
* Modules/indexeddb/IDBTransaction.h:
* Modules/mediasource/MediaSource.h:
* Modules/mediasource/SourceBuffer.h:
* Modules/mediastream/MediaStreamTrack.h:
* Modules/mediastream/RTCDTMFSender.h:
* Modules/mediastream/RTCPeerConnection.h:
* Modules/mediastream/RTCSessionDescriptionRequestImpl.h:
* Modules/mediastream/RTCStatsRequestImpl.h:
* Modules/mediastream/RTCVoidRequestImpl.h:
* Modules/notifications/Notification.h:
* Modules/notifications/NotificationCenter.h:
* Modules/webaudio/AudioContext.h:
* Modules/webdatabase/DatabaseContext.h:
* Modules/websockets/WebSocket.h:
* WebCore.exp.in:
* css/FontLoader.h:
* dom/ActiveDOMObject.h:
* dom/ScriptExecutionContext.cpp:
(WebCore::ScriptExecutionContext::canSuspendActiveDOMObjects):
* dom/ScriptExecutionContext.h:
* fileapi/FileReader.h:
* history/PageCache.cpp:
(WebCore::logCanCacheFrameDecision):
* html/HTMLMarqueeElement.h:
* html/HTMLMediaElement.h:
* html/PublicURLManager.h:
* html/canvas/WebGLRenderingContext.h:
* page/EventSource.h:
* page/SuspendableTimer.h:
* workers/AbstractWorker.h:
* xml/XMLHttpRequest.h:

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

35 files changed:
Source/WebCore/ChangeLog
Source/WebCore/Modules/battery/BatteryManager.h
Source/WebCore/Modules/encryptedmedia/MediaKeySession.h
Source/WebCore/Modules/geolocation/Geolocation.h
Source/WebCore/Modules/indexeddb/IDBDatabase.h
Source/WebCore/Modules/indexeddb/IDBRequest.h
Source/WebCore/Modules/indexeddb/IDBTransaction.h
Source/WebCore/Modules/mediasource/MediaSource.h
Source/WebCore/Modules/mediasource/SourceBuffer.h
Source/WebCore/Modules/mediastream/MediaStreamTrack.h
Source/WebCore/Modules/mediastream/RTCDTMFSender.h
Source/WebCore/Modules/mediastream/RTCPeerConnection.h
Source/WebCore/Modules/mediastream/RTCSessionDescriptionRequestImpl.h
Source/WebCore/Modules/mediastream/RTCStatsRequestImpl.h
Source/WebCore/Modules/mediastream/RTCVoidRequestImpl.h
Source/WebCore/Modules/notifications/Notification.h
Source/WebCore/Modules/notifications/NotificationCenter.h
Source/WebCore/Modules/webaudio/AudioContext.h
Source/WebCore/Modules/webdatabase/DatabaseContext.h
Source/WebCore/Modules/websockets/WebSocket.h
Source/WebCore/WebCore.exp.in
Source/WebCore/css/FontLoader.h
Source/WebCore/dom/ActiveDOMObject.h
Source/WebCore/dom/ScriptExecutionContext.cpp
Source/WebCore/dom/ScriptExecutionContext.h
Source/WebCore/fileapi/FileReader.h
Source/WebCore/history/PageCache.cpp
Source/WebCore/html/HTMLMarqueeElement.h
Source/WebCore/html/HTMLMediaElement.h
Source/WebCore/html/PublicURLManager.h
Source/WebCore/html/canvas/WebGLRenderingContext.h
Source/WebCore/page/EventSource.h
Source/WebCore/page/SuspendableTimer.h
Source/WebCore/workers/AbstractWorker.h
Source/WebCore/xml/XMLHttpRequest.h

index 40bacde..4dd79be 100644 (file)
@@ -1,3 +1,52 @@
+2015-01-09  Andreas Kling  <akling@apple.com>
+
+        Log which ActiveDOMObject(s) can't be suspended for PageCache.
+        <https://webkit.org/b/139697>
+
+        Reviewed by Chris Dumez.
+
+        Give ActiveDOMObject a pure virtual activeDOMObjectName() so we can
+        find their names.
+
+        Dump the names of all the ActiveDOMObjects that fail to suspend when
+        we're trying to put a page into PageCache.
+
+        * Modules/encryptedmedia/MediaKeySession.h:
+        * Modules/geolocation/Geolocation.h:
+        * Modules/indexeddb/IDBDatabase.h:
+        * Modules/indexeddb/IDBRequest.h:
+        * Modules/indexeddb/IDBTransaction.h:
+        * Modules/mediasource/MediaSource.h:
+        * Modules/mediasource/SourceBuffer.h:
+        * Modules/mediastream/MediaStreamTrack.h:
+        * Modules/mediastream/RTCDTMFSender.h:
+        * Modules/mediastream/RTCPeerConnection.h:
+        * Modules/mediastream/RTCSessionDescriptionRequestImpl.h:
+        * Modules/mediastream/RTCStatsRequestImpl.h:
+        * Modules/mediastream/RTCVoidRequestImpl.h:
+        * Modules/notifications/Notification.h:
+        * Modules/notifications/NotificationCenter.h:
+        * Modules/webaudio/AudioContext.h:
+        * Modules/webdatabase/DatabaseContext.h:
+        * Modules/websockets/WebSocket.h:
+        * WebCore.exp.in:
+        * css/FontLoader.h:
+        * dom/ActiveDOMObject.h:
+        * dom/ScriptExecutionContext.cpp:
+        (WebCore::ScriptExecutionContext::canSuspendActiveDOMObjects):
+        * dom/ScriptExecutionContext.h:
+        * fileapi/FileReader.h:
+        * history/PageCache.cpp:
+        (WebCore::logCanCacheFrameDecision):
+        * html/HTMLMarqueeElement.h:
+        * html/HTMLMediaElement.h:
+        * html/PublicURLManager.h:
+        * html/canvas/WebGLRenderingContext.h:
+        * page/EventSource.h:
+        * page/SuspendableTimer.h:
+        * workers/AbstractWorker.h:
+        * xml/XMLHttpRequest.h:
+
 2015-01-09  Anders Carlsson  <andersca@apple.com>
 
         Get rid of the database strategy
index ba02b00..32e2152 100644 (file)
@@ -75,6 +75,8 @@ private:
     virtual void refEventTarget() override { ref(); }
     virtual void derefEventTarget() override { deref(); }
 
+    virtual const char* activeDOMObjectName() const override { return "BatteryManager"; }
+
     BatteryController* m_batteryController;
     EventTargetData m_eventTargetData;
     RefPtr<BatteryStatus> m_batteryStatus;
index 4f5732b..64d3092 100644 (file)
@@ -112,6 +112,8 @@ protected:
 private:
     virtual void refEventTarget() override { ref(); }
     virtual void derefEventTarget() override { deref(); }
+
+    virtual const char* activeDOMObjectName() const override { return "MediaKeySession"; }
 };
 
 }
index 93e14ab..383e309 100644 (file)
@@ -169,6 +169,8 @@ private:
     bool haveSuitableCachedPosition(PositionOptions*);
     void makeCachedPositionCallbacks();
 
+    virtual const char* activeDOMObjectName() const override { return "Geolocation"; }
+
     GeoNotifierSet m_oneShots;
     Watchers m_watchers;
     GeoNotifierSet m_pendingForPermissionNotifiers;
index 5cf6032..b0b42e4 100644 (file)
@@ -113,6 +113,7 @@ private:
 
     // ActiveDOMObject
     virtual void stop() override;
+    virtual const char* activeDOMObjectName() const override { return "IDBDatabase"; }
 
     // EventTarget
     virtual void refEventTarget() override final { ref(); }
index fb5dad3..673f58b 100644 (file)
@@ -132,6 +132,7 @@ protected:
 private:
     // ActiveDOMObject
     virtual void stop() override;
+    virtual const char* activeDOMObjectName() const override { return "IDBRequest"; }
 
     // EventTarget
     virtual void refEventTarget() override final { ref(); }
index e133244..f5cd34d 100644 (file)
@@ -128,6 +128,7 @@ private:
     // ActiveDOMObject
     virtual bool canSuspend() const override;
     virtual void stop() override;
+    virtual const char* activeDOMObjectName() const override { return "IDBTransaction"; }
 
     // EventTarget
     virtual void refEventTarget() override { ref(); }
index 4b4378a..bec2c1b 100644 (file)
@@ -118,6 +118,8 @@ public:
 protected:
     explicit MediaSource(ScriptExecutionContext&);
 
+    virtual const char* activeDOMObjectName() const override { return "MediaSource"; }
+
     void onReadyStateChange(const AtomicString& oldState, const AtomicString& newState);
     Vector<PlatformTimeRanges> activeRanges() const;
 
index 761a2b9..4d335dc 100644 (file)
@@ -134,6 +134,8 @@ protected:
 private:
     SourceBuffer(Ref<SourceBufferPrivate>&&, MediaSource*);
 
+    virtual const char* activeDOMObjectName() const override { return "SourceBuffer"; }
+
     // SourceBufferPrivateClient
     virtual void sourceBufferPrivateDidEndStream(SourceBufferPrivate*, const WTF::AtomicString&) override;
     virtual void sourceBufferPrivateDidReceiveInitializationSegment(SourceBufferPrivate*, const InitializationSegment&) override;
index 427a998..a769a9e 100644 (file)
@@ -119,6 +119,7 @@ private:
 
     // ActiveDOMObject
     virtual void stop() override final;
+    virtual const char* activeDOMObjectName() const override { return "MediaStreamTrack"; }
 
     // EventTarget
     virtual void refEventTarget() override final { ref(); }
index 4d60035..fc717f9 100644 (file)
@@ -71,6 +71,8 @@ public:
 private:
     RTCDTMFSender(ScriptExecutionContext*, PassRefPtr<MediaStreamTrack>, std::unique_ptr<RTCDTMFSenderHandler>);
 
+    virtual const char* activeDOMObjectName() const override { return "RTCDTMFSender"; }
+
     void scheduleDispatchEvent(PassRefPtr<Event>);
     void scheduledEventTimerFired();
 
index d3416ac..e57a4f8 100644 (file)
@@ -146,6 +146,8 @@ private:
     virtual void refEventTarget() override { ref(); }
     virtual void derefEventTarget() override { deref(); }
 
+    virtual const char* activeDOMObjectName() const override { return "RTCPeerConnection"; }
+
     void changeSignalingState(SignalingState);
     void changeIceGatheringState(IceGatheringState);
     void changeIceConnectionState(IceConnectionState);
index c5624b1..5b9433e 100644 (file)
@@ -57,6 +57,8 @@ public:
 private:
     RTCSessionDescriptionRequestImpl(ScriptExecutionContext*, PassRefPtr<RTCSessionDescriptionCallback>, PassRefPtr<RTCPeerConnectionErrorCallback>);
 
+    virtual const char* activeDOMObjectName() const override { return "RTCSessionDescriptionRequestImpl"; }
+
     void clear();
 
     RefPtr<RTCSessionDescriptionCallback> m_successCallback;
index 5108ca4..973a6ac 100644 (file)
@@ -57,6 +57,8 @@ public:
 private:
     RTCStatsRequestImpl(ScriptExecutionContext*, PassRefPtr<RTCStatsCallback>, PassRefPtr<RTCPeerConnectionErrorCallback>, PassRefPtr<MediaStreamTrackPrivate>);
 
+    virtual const char* activeDOMObjectName() const override { return "RTCStatsRequestImpl"; }
+
     void clear();
 
     RefPtr<RTCStatsCallback> m_successCallback;
index 3c3f34d..748c96c 100644 (file)
@@ -56,6 +56,8 @@ public:
 private:
     RTCVoidRequestImpl(ScriptExecutionContext*, PassRefPtr<VoidCallback>, PassRefPtr<RTCPeerConnectionErrorCallback>);
 
+    virtual const char* activeDOMObjectName() const override { return "RTCVoidRequestImpl"; }
+
     void clear();
 
     RefPtr<VoidCallback> m_successCallback;
index d555611..d17cef8 100644 (file)
@@ -153,6 +153,8 @@ private:
     virtual void refEventTarget() override { ref(); }
     virtual void derefEventTarget() override { deref(); }
 
+    virtual const char* activeDOMObjectName() const override { return "Notification"; }
+
     void startLoadingIcon();
     void finishLoadingIcon();
 
index 200d8af..6f2b808 100644 (file)
@@ -75,6 +75,7 @@ private:
 
     // ActiveDOMObject
     virtual void stop() override;
+    virtual const char* activeDOMObjectName() const override { return "NotificationCenter"; }
 
     class NotificationRequestCallback : public RefCounted<NotificationRequestCallback> {
     public:
index 628131d..252dbe1 100644 (file)
@@ -264,6 +264,8 @@ protected:
     static bool isSampleRateRangeGood(float sampleRate);
     
 private:
+    virtual const char* activeDOMObjectName() const override { return "AudioContext"; }
+
     void constructCommon();
 
     void lazyInitialize();
index 1eac294..bd180ed 100644 (file)
@@ -73,6 +73,7 @@ private:
 
     virtual void contextDestroyed() override final;
     virtual void stop() override final;
+    virtual const char* activeDOMObjectName() const override { return "DatabaseContext"; }
 
     RefPtr<DatabaseThread> m_databaseThread;
     bool m_hasOpenDatabases; // This never changes back to false, even after the database thread is closed.
index ffba645..4f3ce72 100644 (file)
@@ -119,6 +119,7 @@ private:
     virtual void suspend(ReasonForSuspension) override;
     virtual void resume() override;
     virtual void stop() override;
+    virtual const char* activeDOMObjectName() const override { return "WebSocket"; }
 
     virtual void refEventTarget() override { ref(); }
     virtual void derefEventTarget() override { deref(); }
index 3a14bc1..1fceadb 100644 (file)
@@ -998,7 +998,7 @@ __ZN7WebCore22MutableStyleProperties25ensureCSSStyleDeclarationEv
 __ZN7WebCore22MutableStylePropertiesD1Ev
 __ZN7WebCore22PlatformCAAnimationMac6createEP19CAPropertyAnimation
 __ZN7WebCore22RuntimeEnabledFeatures14sharedFeaturesEv
-__ZN7WebCore22ScriptExecutionContext26canSuspendActiveDOMObjectsEv
+__ZN7WebCore22ScriptExecutionContext26canSuspendActiveDOMObjectsEPN3WTF6VectorIPNS_15ActiveDOMObjectELm0ENS1_15CrashOnOverflowEEE
 __ZN7WebCore22ScriptExecutionContext2vmEv
 __ZN7WebCore22StorageEventDispatcher26dispatchLocalStorageEventsERKN3WTF6StringES4_S4_PNS_14SecurityOriginEPNS_5FrameE
 __ZN7WebCore22StorageEventDispatcher28dispatchSessionStorageEventsERKN3WTF6StringES4_S4_PNS_14SecurityOriginEPNS_5FrameE
index 37e7a6a..330141e 100644 (file)
@@ -95,6 +95,8 @@ private:
     virtual EventTargetData* eventTargetData() override;
     virtual EventTargetData& ensureEventTargetData() override;
 
+    virtual const char* activeDOMObjectName() const override { return "FontLoader"; }
+
     void pendingEventsTimerFired() { firePendingEvents(); }
     void scheduleEvent(PassRefPtr<Event>);
     void firePendingEvents();
index f350b55..e1ec775 100644 (file)
@@ -35,8 +35,6 @@ namespace WebCore {
 
 class ActiveDOMObject : public ContextDestructionObserver {
 public:
-    explicit ActiveDOMObject(ScriptExecutionContext*);
-
     // The suspendIfNeeded must be called exactly once after object construction to update
     // the suspended state to match that of the ScriptExecutionContext.
     void suspendIfNeeded();
@@ -60,6 +58,8 @@ public:
         DocumentWillBePaused
     };
 
+    virtual const char* activeDOMObjectName() const = 0;
+
     // These three functions must not have a side effect of creating or destroying
     // any ActiveDOMObject. That means they must not result in calls to arbitrary JavaScript.
     virtual bool canSuspend() const;
@@ -86,6 +86,7 @@ public:
     }
 
 protected:
+    explicit ActiveDOMObject(ScriptExecutionContext*);
     virtual ~ActiveDOMObject();
 
 private:
index 1a0637f..c796845 100644 (file)
@@ -177,7 +177,7 @@ void ScriptExecutionContext::didLoadResourceSynchronously(const ResourceRequest&
 {
 }
 
-bool ScriptExecutionContext::canSuspendActiveDOMObjects()
+bool ScriptExecutionContext::canSuspendActiveDOMObjects(Vector<ActiveDOMObject*>* unsuspendableObjects)
 {
     checkConsistency();
 
@@ -195,7 +195,10 @@ bool ScriptExecutionContext::canSuspendActiveDOMObjects()
     for (auto* activeDOMObject : m_activeDOMObjects) {
         if (!activeDOMObject->canSuspend()) {
             canSuspend = false;
-            break;
+            if (unsuspendableObjects)
+                unsuspendableObjects->append(activeDOMObject);
+            else
+                break;
         }
     }
 
index d9bebbe..5bc7ea2 100644 (file)
@@ -86,7 +86,8 @@ public:
     PublicURLManager& publicURLManager();
 
     // Active objects are not garbage collected even if inaccessible, e.g. because their activity may result in callbacks being invoked.
-    WEBCORE_EXPORT bool canSuspendActiveDOMObjects();
+    bool canSuspendActiveDOMObjects(Vector<ActiveDOMObject*>* unsuspendableObjects = nullptr);
+
     // Active objects can be asked to suspend even if canSuspendActiveDOMObjects() returns 'false' -
     // step-by-step JS debugging is one example.
     virtual void suspendActiveDOMObjects(ActiveDOMObject::ReasonForSuspension);
index f002f79..c47562f 100644 (file)
@@ -103,6 +103,7 @@ private:
     explicit FileReader(ScriptExecutionContext&);
 
     // ActiveDOMObject
+    virtual const char* activeDOMObjectName() const override { return "FileReader"; }
     virtual bool canSuspend() const override;
     virtual void stop() override;
 
index cdf4aab..05f387f 100644 (file)
@@ -174,8 +174,14 @@ static unsigned logCanCacheFrameDecision(Frame* frame, int indentLevel)
         FEATURE_COUNTER_INCREMENT_KEY(frame->page(), FeatureCounterPageCacheFailureDocumentLoaderStoppingKey);
         rejectReasons |= 1 << IsStopping;
     }
-    if (!frame->document()->canSuspendActiveDOMObjects()) {
+
+    Vector<ActiveDOMObject*> unsuspendableObjects;
+    if (!frame->document()->canSuspendActiveDOMObjects(&unsuspendableObjects)) {
         PCLOG("   -The document cannot suspend its active DOM Objects");
+        for (auto* activeDOMObject : unsuspendableObjects) {
+            PCLOG("    - Unsuspendable: ", activeDOMObject->activeDOMObjectName());
+            UNUSED_PARAM(activeDOMObject);
+        }
         FEATURE_COUNTER_INCREMENT_KEY(frame->page(), FeatureCounterPageCacheFailureCannotSuspendActiveDOMObjectsKey);
         rejectReasons |= 1 << CannotSuspendActiveDOMObjects;
     }
index 177871b..2579db1 100644 (file)
@@ -60,6 +60,7 @@ private:
     virtual bool canSuspend() const override;
     virtual void suspend(ReasonForSuspension) override;
     virtual void resume() override;
+    virtual const char* activeDOMObjectName() const override { return "HTMLMarqueeElement"; }
 
     RenderMarquee* renderMarquee() const;
 };
index e58c4f6..b19f0cb 100644 (file)
@@ -516,6 +516,7 @@ private:
     virtual void willStopBeingFullscreenElement() override;
 
     // ActiveDOMObject functions.
+    virtual const char* activeDOMObjectName() const override { return "HTMLMediaElement"; }
     virtual bool canSuspend() const override;
     virtual void suspend(ReasonForSuspension) override;
     virtual void resume() override;
index a627f56..51320fa 100644 (file)
@@ -53,6 +53,7 @@ public:
     // ActiveDOMObject interface.
     virtual void stop() override;
 private:
+    virtual const char* activeDOMObjectName() const override { return "PublicURLManager"; }
     
     typedef HashSet<String> URLSet;
     typedef HashMap<URLRegistry*, URLSet > RegistryURLMap;
index ef88c9a..cc9420e 100644 (file)
@@ -355,6 +355,7 @@ private:
     // ActiveDOMObject
     virtual bool hasPendingActivity() const override;
     virtual void stop() override;
+    virtual const char* activeDOMObjectName() const override { return "WebGLRenderingContext"; }
 
     void addSharedObject(WebGLSharedObject*);
     void addContextObject(WebGLContextObject*);
index fac7332..e08ce42 100644 (file)
@@ -92,6 +92,7 @@ private:
     virtual void didFailRedirectCheck() override;
 
     virtual void stop() override;
+    virtual const char* activeDOMObjectName() const override { return "EventSource"; }
 
     void connect();
     void networkRequestEnded();
index 6093a7f..9e29b7f 100644 (file)
@@ -63,6 +63,7 @@ private:
     virtual bool canSuspend() const final override;
     virtual void suspend(ReasonForSuspension) final override;
     virtual void resume() final override;
+    virtual const char* activeDOMObjectName() const override { return "SuspendableTimer"; }
 
     bool m_suspended;
 
index fc5eaeb..bd79368 100644 (file)
@@ -65,6 +65,8 @@ namespace WebCore {
     private:
         virtual void refEventTarget() override final { ref(); }
         virtual void derefEventTarget() override final { deref(); }
+
+        virtual const char* activeDOMObjectName() const override { return "AbstractWorker"; }
     };
 
 } // namespace WebCore
index 644befe..7bedbf7 100644 (file)
@@ -169,6 +169,7 @@ private:
     virtual void suspend(ReasonForSuspension) override;
     virtual void resume() override;
     virtual void stop() override;
+    virtual const char* activeDOMObjectName() const override { return "XMLHttpRequest"; }
 
     virtual void refEventTarget() override { ref(); }
     virtual void derefEventTarget() override { deref(); }