Commit efccd59c authored by ap@webkit.org's avatar ap@webkit.org

2008-12-03 Dmitry Titov <dimich@chromium.org>

        Reviewed by Alexey Proskuryakov.

        Using ActiveDOMObject as base class for DOMTimer.
        https://bugs.webkit.org/show_bug.cgi?id=22620

        Using ActiveDOMObject simplifies the code because ActiveDOMObject
        is wired for stop/pause/resume on loading/unloading/caching the page etc
        so the timer-specific code that does the same can be removed.
        In addition, timers can be now paused/resumed 'in place' which
        makes it unnecessary to 'serialize' them into special PausedTimeouts
        instance, so pause/resumeTimeouts implementation in JSDOMWindowBase can also be removed.
        Also, moving TimeoutMap from JSDOMWindowBase to Document matches lifetime
        of timeouts and makes it possible to not roundtrip them via PausedTimeouts 
        every time when JSDOMWindow wrapper is destroyed while the page is in the b/f cache.

        Timeouts are now paused with other ActiveDOMObjects:
        - before creating CachedPage in FrameLoader::commitProvisionalLoad()
        - in JavaScriptDebugServer::setJavaScriptPaused
        - during modal UI operations in Chrome::*
        this is equivalent to previous usage of JSDOMWindowBase::pauseTimeouts()

        Timeouts are stopped to prevent future firing from:
        - FrameLoader::clear()
        - FrameLoader::frameDetached()
        this is equivalent to previous usage of JSDOMWindowBase::clearAllTimeouts()

        This is also one of the steps to having timers in Workers. See the plan of
        the next steps in the bug above.

        * bindings/js/DOMTimer.cpp:
        (WebCore::DOMTimer::DOMTimer):
        (WebCore::DOMTimer::fired):
        (WebCore::DOMTimer::hasPendingActivity):
        (WebCore::DOMTimer::contextDestroyed):
        (WebCore::DOMTimer::stop):
        (WebCore::DOMTimer::suspend):
        (WebCore::DOMTimer::resume):
        (WebCore::DOMTimer::canSuspend): Implemented ActiveDOMObject methods.

        * bindings/js/DOMTimer.h:
        * bindings/js/JSDOMBinding.cpp: ActiveDOMObject can have no JS wrapper
        (WebCore::markActiveObjectsForContext): 

        * bindings/js/JSDOMWindowBase.cpp:
        (WebCore::JSDOMWindowBase::~JSDOMWindowBase):
        (WebCore::JSDOMWindowBase::clear):
        (WebCore::JSDOMWindowBase::installTimeout):
        (WebCore::JSDOMWindowBase::removeTimeout):
        (WebCore::JSDOMWindowBase::timerFired):
        (WebCore::JSDOMWindowBase::disconnectFrame):
        * bindings/js/JSDOMWindowBase.h:
        * bindings/js/ScriptController.cpp:
        * bindings/js/ScriptController.h:

        * dom/Document.cpp: Document now holds a hash map id->timeout
        (WebCore::Document::addTimeout):
        (WebCore::Document::removeTimeout):
        (WebCore::Document::findTimeout):
        * dom/Document.h:
        * history/CachedPage.cpp:
        (WebCore::CachedPage::CachedPage):
        (WebCore::CachedPage::restore):
        (WebCore::CachedPage::clear):
        * history/CachedPage.h:
        * inspector/JavaScriptDebugServer.cpp:
        (WebCore::JavaScriptDebugServer::~JavaScriptDebugServer):
        (WebCore::JavaScriptDebugServer::setJavaScriptPaused):
        * inspector/JavaScriptDebugServer.h:

        * loader/FrameLoader.cpp:
        (WebCore::FrameLoader::commitProvisionalLoad): 
        removed clearAllTimeouts since all ActiveDOMObjects will be stopped in FrameLoader::clear();
        I don't see how the old comment can be correct - the code in the same method proceeds to invoke 'onunload'
        and then calls into client which can be external code and can cause any active object created in onunload
        to fire. We can stop them all before firing onunload but it does not make a lot of sense.
        I have a test to go with the next patch which verifies that timers set in onunload do not fire.

        (WebCore::FrameLoader::open):
        * page/Chrome.cpp:
        (WebCore::PageGroupLoadDeferrer::PageGroupLoadDeferrer):
        (WebCore::PageGroupLoadDeferrer::~PageGroupLoadDeferrer):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@38985 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent e367b001
2008-12-03 Dmitry Titov <dimich@chromium.org>
Reviewed by Alexey Proskuryakov.
Using ActiveDOMObject as base class for DOMTimer.
https://bugs.webkit.org/show_bug.cgi?id=22620
Using ActiveDOMObject simplifies the code because ActiveDOMObject
is wired for stop/pause/resume on loading/unloading/caching the page etc
so the timer-specific code that does the same can be removed.
In addition, timers can be now paused/resumed 'in place' which
makes it unnecessary to 'serialize' them into special PausedTimeouts
instance, so pause/resumeTimeouts implementation in JSDOMWindowBase can also be removed.
Also, moving TimeoutMap from JSDOMWindowBase to Document matches lifetime
of timeouts and makes it possible to not roundtrip them via PausedTimeouts
every time when JSDOMWindow wrapper is destroyed while the page is in the b/f cache.
Timeouts are now paused with other ActiveDOMObjects:
- before creating CachedPage in FrameLoader::commitProvisionalLoad()
- in JavaScriptDebugServer::setJavaScriptPaused
- during modal UI operations in Chrome::*
this is equivalent to previous usage of JSDOMWindowBase::pauseTimeouts()
Timeouts are stopped to prevent future firing from:
- FrameLoader::clear()
- FrameLoader::frameDetached()
this is equivalent to previous usage of JSDOMWindowBase::clearAllTimeouts()
This is also one of the steps to having timers in Workers. See the plan of
the next steps in the bug above.
* bindings/js/DOMTimer.cpp:
(WebCore::DOMTimer::DOMTimer):
(WebCore::DOMTimer::fired):
(WebCore::DOMTimer::hasPendingActivity):
(WebCore::DOMTimer::contextDestroyed):
(WebCore::DOMTimer::stop):
(WebCore::DOMTimer::suspend):
(WebCore::DOMTimer::resume):
(WebCore::DOMTimer::canSuspend): Implemented ActiveDOMObject methods.
* bindings/js/DOMTimer.h:
* bindings/js/JSDOMBinding.cpp: ActiveDOMObject can have no JS wrapper
(WebCore::markActiveObjectsForContext):
* bindings/js/JSDOMWindowBase.cpp:
(WebCore::JSDOMWindowBase::~JSDOMWindowBase):
(WebCore::JSDOMWindowBase::clear):
(WebCore::JSDOMWindowBase::installTimeout):
(WebCore::JSDOMWindowBase::removeTimeout):
(WebCore::JSDOMWindowBase::timerFired):
(WebCore::JSDOMWindowBase::disconnectFrame):
* bindings/js/JSDOMWindowBase.h:
* bindings/js/ScriptController.cpp:
* bindings/js/ScriptController.h:
* dom/Document.cpp: Document now holds a hash map id->timeout
(WebCore::Document::addTimeout):
(WebCore::Document::removeTimeout):
(WebCore::Document::findTimeout):
* dom/Document.h:
* history/CachedPage.cpp:
(WebCore::CachedPage::CachedPage):
(WebCore::CachedPage::restore):
(WebCore::CachedPage::clear):
* history/CachedPage.h:
* inspector/JavaScriptDebugServer.cpp:
(WebCore::JavaScriptDebugServer::~JavaScriptDebugServer):
(WebCore::JavaScriptDebugServer::setJavaScriptPaused):
* inspector/JavaScriptDebugServer.h:
* loader/FrameLoader.cpp:
(WebCore::FrameLoader::commitProvisionalLoad):
removed clearAllTimeouts since all ActiveDOMObjects will be stopped in FrameLoader::clear();
I don't see how the old comment can be correct - the code in the same method proceeds to invoke 'onunload'
and then calls into client which can be external code and can cause any active object created in onunload
to fire. We can stop them all before firing onunload but it does not make a lot of sense.
I have a test to go with the next patch which verifies that timers set in onunload do not fire.
(WebCore::FrameLoader::open):
* page/Chrome.cpp:
(WebCore::PageGroupLoadDeferrer::PageGroupLoadDeferrer):
(WebCore::PageGroupLoadDeferrer::~PageGroupLoadDeferrer):
2008-12-03 Justin Garcia <justin.garcia@apple.com>
Reviewed by Beth Dakin.
......@@ -27,17 +27,21 @@
#include "config.h"
#include "DOMTimer.h"
#include "JSDOMWindowBase.h"
#include "Document.h"
#include "JSDOMWindow.h"
#include "ScheduledAction.h"
#include "ScriptExecutionContext.h"
#include <runtime/JSLock.h>
namespace WebCore {
int DOMTimer::m_timerNestingLevel = 0;
DOMTimer::DOMTimer(JSDOMWindowBase* object, ScheduledAction* action)
: m_object(object)
DOMTimer::DOMTimer(ScriptExecutionContext* context, ScheduledAction* action)
: ActiveDOMObject(context, this)
, m_action(action)
, m_nextFireInterval(0)
, m_repeatInterval(0)
{
static int lastUsedTimeoutId = 0;
++lastUsedTimeoutId;
......@@ -49,16 +53,6 @@ DOMTimer::DOMTimer(JSDOMWindowBase* object, ScheduledAction* action)
m_nestingLevel = m_timerNestingLevel + 1;
}
DOMTimer::DOMTimer(int timeoutId, int nestingLevel, JSDOMWindowBase* object, ScheduledAction* action)
: m_timeoutId(timeoutId)
, m_nestingLevel(nestingLevel)
, m_object(object)
, m_action(action)
{
ASSERT(timeoutId > 0);
ASSERT(nestingLevel > 0);
}
DOMTimer::~DOMTimer()
{
JSC::JSLock lock(false);
......@@ -67,9 +61,53 @@ DOMTimer::~DOMTimer()
void DOMTimer::fired()
{
m_timerNestingLevel = m_nestingLevel;
m_object->timerFired(this);
m_timerNestingLevel = 0;
ScriptExecutionContext* context = scriptExecutionContext();
// FIXME: make it work with Workers SEC too.
if (context->isDocument()) {
Document* document = static_cast<Document*>(context);
if (JSDOMWindow* window = toJSDOMWindow(document->frame())) {
m_timerNestingLevel = m_nestingLevel;
window->timerFired(this);
m_timerNestingLevel = 0;
}
}
}
bool DOMTimer::hasPendingActivity() const
{
return isActive();
}
void DOMTimer::contextDestroyed()
{
ActiveDOMObject::contextDestroyed();
delete this;
}
void DOMTimer::stop()
{
TimerBase::stop();
}
void DOMTimer::suspend()
{
ASSERT(m_nextFireInterval == 0 && m_repeatInterval == 0);
m_nextFireInterval = nextFireInterval();
m_repeatInterval = repeatInterval();
TimerBase::stop();
}
void DOMTimer::resume()
{
start(m_nextFireInterval, m_repeatInterval);
m_nextFireInterval = 0;
m_repeatInterval = 0;
}
bool DOMTimer::canSuspend() const
{
return true;
}
} // namespace WebCore
......@@ -27,6 +27,7 @@
#ifndef DOMTimer_h
#define DOMTimer_h
#include "ActiveDOMObject.h"
#include "Timer.h"
namespace WebCore {
......@@ -34,12 +35,10 @@ namespace WebCore {
class JSDOMWindowBase;
class ScheduledAction;
class DOMTimer : public TimerBase {
class DOMTimer : public TimerBase, public ActiveDOMObject {
public:
// Creates a new timer with the next id and nesting level.
DOMTimer(JSDOMWindowBase*, ScheduledAction*);
// Creates a timer from PausedTimeout, takes timeoutId and nestingLevel as they were persisted.
DOMTimer(int timeoutId, int nestingLevel, JSDOMWindowBase*, ScheduledAction*);
DOMTimer(ScriptExecutionContext*, ScheduledAction*);
virtual ~DOMTimer();
int timeoutId() const { return m_timeoutId; }
......@@ -50,14 +49,23 @@ public:
ScheduledAction* action() const { return m_action; }
ScheduledAction* takeAction() { ScheduledAction* a = m_action; m_action = 0; return a; }
// ActiveDOMObject
virtual bool hasPendingActivity() const;
virtual void contextDestroyed();
virtual void stop();
virtual bool canSuspend() const;
virtual void suspend();
virtual void resume();
private:
virtual void fired();
int m_timeoutId;
int m_nestingLevel;
JSDOMWindowBase* m_object;
ScheduledAction* m_action;
static int m_timerNestingLevel;
double m_nextFireInterval;
double m_repeatInterval;
};
} // namespace WebCore
......
......@@ -298,8 +298,10 @@ void markActiveObjectsForContext(JSGlobalData& globalData, ScriptExecutionContex
for (HashMap<ActiveDOMObject*, void*>::const_iterator iter = activeObjects.begin(); iter != activeObjectsEnd; ++iter) {
if (iter->first->hasPendingActivity()) {
DOMObject* wrapper = getCachedDOMObjectWrapper(globalData, iter->second);
// An object with pending activity must have a wrapper to mark its listeners, so no null check.
if (!wrapper->marked())
// Generally, an active object with pending activity must have a wrapper to mark its listeners.
// However, some ActiveDOMObjects don't have JS wrappers (timers created by setTimeout is one example).
// FIXME: perhaps need to make sure even timers have a markable 'wrapper'.
if (wrapper && !wrapper->marked())
wrapper->mark();
}
}
......
......@@ -53,7 +53,6 @@
#include "Logging.h"
#include "MediaPlayer.h"
#include "Page.h"
#include "PausedTimeouts.h"
#include "PlatformScreen.h"
#include "PluginInfoStore.h"
#include "RenderView.h"
......@@ -159,8 +158,6 @@ JSDOMWindowBase::~JSDOMWindowBase()
{
if (d()->impl->frame())
d()->impl->frame()->script()->clearFormerWindow(asJSDOMWindow(this));
clearAllTimeouts();
}
ScriptExecutionContext* JSDOMWindowBase::scriptExecutionContext() const
......@@ -700,7 +697,6 @@ void JSDOMWindowBase::clear()
if (d()->returnValueSlot && !*d()->returnValueSlot)
*d()->returnValueSlot = getDirect(Identifier(globalExec(), "returnValue"));
clearAllTimeouts();
clearHelperObjectProperties();
}
......@@ -826,18 +822,14 @@ void JSDOMWindowBase::setReturnValueSlot(JSValue** slot)
////////////////////// timeouts ////////////////////////
void JSDOMWindowBase::clearAllTimeouts()
{
deleteAllValues(d()->timeouts);
d()->timeouts.clear();
}
int JSDOMWindowBase::installTimeout(ScheduledAction* a, int t, bool singleShot)
{
DOMTimer* timer = new DOMTimer(this, a);
DOMTimer* timer = new DOMTimer(scriptExecutionContext(), a);
int timeoutId = timer->timeoutId();
ASSERT(!d()->timeouts.get(timeoutId));
d()->timeouts.set(timeoutId, timer);
ASSERT(d()->impl->document());
d()->impl->document()->addTimeout(timeoutId, timer);
// Use a minimum interval of 10 ms to match other browsers, but only once we've
// nested enough to notice that we're repeating.
// Faster timers might be "better", but they're incompatible.
......@@ -861,50 +853,7 @@ int JSDOMWindowBase::installTimeout(ExecState* exec, JSValue* func, const ArgLis
return installTimeout(new ScheduledAction(exec, func, args), t, singleShot);
}
void JSDOMWindowBase::pauseTimeouts(OwnPtr<PausedTimeouts>& result)
{
size_t timeoutsCount = d()->timeouts.size();
if (!timeoutsCount) {
result.clear();
return;
}
PausedTimeout* t = new PausedTimeout[timeoutsCount];
result.set(new PausedTimeouts(t, timeoutsCount));
JSDOMWindowBaseData::TimeoutsMap::iterator it = d()->timeouts.begin();
for (size_t i = 0; i != timeoutsCount; ++i, ++it) {
int timeoutId = it->first;
DOMTimer* timer = it->second;
t[i].timeoutId = timeoutId;
t[i].nestingLevel = timer->nestingLevel();
t[i].nextFireInterval = timer->nextFireInterval();
t[i].repeatInterval = timer->repeatInterval();
t[i].action = timer->takeAction();
}
ASSERT(it == d()->timeouts.end());
deleteAllValues(d()->timeouts);
d()->timeouts.clear();
}
void JSDOMWindowBase::resumeTimeouts(OwnPtr<PausedTimeouts>& timeouts)
{
if (!timeouts)
return;
size_t count = timeouts->numTimeouts();
PausedTimeout* array = timeouts->takeTimeouts();
for (size_t i = 0; i != count; ++i) {
int timeoutId = array[i].timeoutId;
DOMTimer* timer = new DOMTimer(timeoutId, array[i].nestingLevel, this, array[i].action);
d()->timeouts.set(timeoutId, timer);
timer->start(array[i].nextFireInterval, array[i].repeatInterval);
}
delete [] array;
timeouts.clear();
}
void JSDOMWindowBase::removeTimeout(int timeoutId, bool delAction)
void JSDOMWindowBase::removeTimeout(int timeoutId)
{
// timeout IDs have to be positive, and 0 and -1 are unsafe to
// even look up since they are the empty and deleted value
......@@ -912,7 +861,8 @@ void JSDOMWindowBase::removeTimeout(int timeoutId, bool delAction)
if (timeoutId <= 0)
return;
delete d()->timeouts.take(timeoutId);
ASSERT(d()->impl->document());
d()->impl->document()->removeTimeout(timeoutId);
}
void JSDOMWindowBase::timerFired(DOMTimer* timer)
......@@ -924,7 +874,8 @@ void JSDOMWindowBase::timerFired(DOMTimer* timer)
timer->action()->execute(shell());
// The DOMTimer object may have been deleted or replaced during execution,
// so we re-fetch it.
timer = d()->timeouts.get(timeoutId);
ASSERT(d()->impl->document());
timer = d()->impl->document()->findTimeout(timeoutId);
if (!timer)
return;
......@@ -938,8 +889,7 @@ void JSDOMWindowBase::timerFired(DOMTimer* timer)
// Delete timer before executing the action for one-shot timers.
ScheduledAction* action = timer->takeAction();
d()->timeouts.remove(timer->timeoutId());
delete timer;
removeTimeout(timer->timeoutId());
action->execute(shell());
JSLock lock(false);
......@@ -948,7 +898,6 @@ void JSDOMWindowBase::timerFired(DOMTimer* timer)
void JSDOMWindowBase::disconnectFrame()
{
clearAllTimeouts();
}
JSValue* toJS(ExecState*, DOMWindow* domWindow)
......
......@@ -38,7 +38,6 @@ namespace WebCore {
class JSEventListener;
class JSLocation;
class JSUnprotectedEventListener;
class PausedTimeouts;
class ScheduledAction;
class SecurityOrigin;
......@@ -67,10 +66,7 @@ namespace WebCore {
int installTimeout(const JSC::UString& handler, int t, bool singleShot);
int installTimeout(JSC::ExecState*, JSC::JSValue* function, const JSC::ArgList& args, int t, bool singleShot);
void removeTimeout(int timerId, bool delAction = true);
void pauseTimeouts(OwnPtr<PausedTimeouts>&);
void resumeTimeouts(OwnPtr<PausedTimeouts>&);
void removeTimeout(int timeoutId);
void timerFired(DOMTimer*);
......@@ -102,8 +98,6 @@ namespace WebCore {
static JSC::JSGlobalData* commonJSGlobalData();
void clearAllTimeouts();
private:
struct JSDOMWindowBaseData : public JSDOMGlobalObjectData {
JSDOMWindowBaseData(PassRefPtr<DOMWindow>, JSDOMWindowShell*);
......@@ -112,9 +106,6 @@ namespace WebCore {
JSC::JSValue** returnValueSlot;
JSDOMWindowShell* shell;
typedef HashMap<int, DOMTimer*> TimeoutsMap;
TimeoutsMap timeouts;
};
static JSC::JSValue* childFrameGetter(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&);
......
......@@ -351,25 +351,4 @@ void ScriptController::clearScriptObjects()
clearPlatformScriptObjects();
}
void ScriptController::pauseTimeouts(OwnPtr<PausedTimeouts>& result)
{
if (!haveWindowShell()) {
result.clear();
return;
}
windowShell()->window()->pauseTimeouts(result);
}
void ScriptController::resumeTimeouts(OwnPtr<PausedTimeouts>& pausedTimeouts)
{
if (!haveWindowShell()) {
// Callers can assume we will always clear the passed in timeouts
pausedTimeouts.clear();
return;
}
windowShell()->window()->resumeTimeouts(pausedTimeouts);
}
} // namespace WebCore
......@@ -103,9 +103,6 @@ public:
void clearFormerWindow(JSDOMWindow* window) { m_liveFormerWindows.remove(window); }
void updateDocument();
void pauseTimeouts(OwnPtr<PausedTimeouts>&);
void resumeTimeouts(OwnPtr<PausedTimeouts>&);
void clearScriptObjects();
void cleanupScriptObjectsForPlugin(void*);
......
......@@ -42,6 +42,12 @@ namespace WebCore {
virtual void contextDestroyed();
// canSuspend() is used by the caller if there is a choice between suspending and stopping.
// For example, a page won't be suspended and placed in the back/forward cache if it has
// the objects that can not be suspended.
// However, 'suspend' can be called even if canSuspend() would return 'false'. That
// happens in step-by-step JS debugging for example - in this case it would be incorrect
// to stop the object. Exact semantics of suspend is up to the object then.
virtual bool canSuspend() const;
virtual void suspend();
virtual void resume();
......
......@@ -40,6 +40,7 @@
#include "Console.h"
#include "CookieJar.h"
#include "DOMImplementation.h"
#include "DOMTimer.h"
#include "DOMWindow.h"
#include "DocLoader.h"
#include "DocumentFragment.h"
......@@ -4239,6 +4240,23 @@ void Document::parseDNSPrefetchControlHeader(const String& dnsPrefetchControl)
m_haveExplicitlyDisabledDNSPrefetch = true;
}
void Document::addTimeout(int timeoutId, DOMTimer* timer)
{
ASSERT(!m_timeouts.get(timeoutId));
m_timeouts.set(timeoutId, timer);
}
void Document::removeTimeout(int timeoutId)
{
DOMTimer* timer = m_timeouts.take(timeoutId);
delete timer;
}
DOMTimer* Document::findTimeout(int timeoutId)
{
return m_timeouts.get(timeoutId);
}
void Document::reportException(const String& errorMessage, int lineNumber, const String& sourceURL)
{
if (DOMWindow* window = domWindow())
......
......@@ -65,6 +65,7 @@ namespace WebCore {
class Database;
class DOMImplementation;
class DOMSelection;
class DOMTimer;
class DOMWindow;
class DatabaseThread;
class DocLoader;
......@@ -777,6 +778,10 @@ public:
virtual void reportException(const String& errorMessage, int lineNumber, const String& sourceURL);
void addTimeout(int timeoutId, DOMTimer*);
void removeTimeout(int timeoutId);
DOMTimer* findTimeout(int timeoutId);
protected:
Document(Frame*, bool isXHTML);
......@@ -1085,6 +1090,9 @@ private:
#if USE(LOW_BANDWIDTH_DISPLAY)
bool m_inLowBandwidthDisplay;
#endif
typedef HashMap<int, DOMTimer*> TimeoutsMap;
TimeoutsMap m_timeouts;
};
inline bool Document::hasElementWithId(AtomicStringImpl* id) const
......
......@@ -56,6 +56,8 @@ namespace WebCore {
// Active objects are not garbage collected even if inaccessible, e.g. because their activity may result in callbacks being invoked.
bool canSuspendActiveDOMObjects();
// Active objects can be asked to suspend even if canSuspendActiveDOMObjects() returns 'false' -
// step-by-step JS debugging is one example.
void suspendActiveDOMObjects();
void resumeActiveDOMObjects();
void stopActiveDOMObjects();
......
......@@ -42,7 +42,6 @@
#include "Logging.h"
#include "Page.h"
#include "PageGroup.h"
#include "PausedTimeouts.h"
#include "SystemTime.h"
#include "ScriptController.h"
#include <runtime/JSLock.h>
......@@ -86,7 +85,6 @@ CachedPage::CachedPage(Page* page)
ScriptController* proxy = mainFrame->script();
if (proxy->haveWindowShell()) {
m_window = proxy->windowShell()->window();
m_window->pauseTimeouts(m_pausedTimeouts);
}
m_document->setInPageCache(true);
......@@ -114,7 +112,6 @@ void CachedPage::restore(Page* page)
JSDOMWindowShell* windowShell = proxy->windowShell();
if (m_window) {
windowShell->setWindow(m_window.get());
windowShell->window()->resumeTimeouts(m_pausedTimeouts);
} else {
windowShell->setWindow(mainFrame->domWindow());
proxy->attachDebugger(page->debugger());
......@@ -170,7 +167,6 @@ void CachedPage::clear()
m_URL = KURL();
JSLock lock(false);
m_pausedTimeouts.clear();
m_window = 0;
m_cachedPagePlatformData.clear();
......
......@@ -28,7 +28,6 @@
#include "KURL.h"
#include <wtf/OwnPtr.h>
#include "PausedTimeouts.h"
#include <runtime/Protect.h>
namespace WebCore {
......@@ -40,7 +39,6 @@ namespace WebCore {
class JSDOMWindow;
class Node;
class Page;
class PausedTimeouts;
class CachedPage : public RefCounted<CachedPage> {
public:
......@@ -73,7 +71,6 @@ private:
RefPtr<Node> m_mousePressNode;
KURL m_URL;
JSC::ProtectedPtr<JSDOMWindow> m_window;
OwnPtr<PausedTimeouts> m_pausedTimeouts;
OwnPtr<CachedPagePlatformData> m_cachedPagePlatformData;
};
......
......@@ -39,7 +39,6 @@
#include "JavaScriptDebugListener.h"
#include "Page.h"
#include "PageGroup.h"
#include "PausedTimeouts.h"
#include "PluginView.h"
#include "ScrollView.h"
#include "Widget.h"
......@@ -79,7 +78,6 @@ JavaScriptDebugServer::~JavaScriptDebugServer()
{
deleteAllValues(m_pageListenersMap);
deleteAllValues(m_breakpoints);
deleteAllValues(m_pausedTimeouts);
}
void JavaScriptDebugServer::addListener(JavaScriptDebugListener* listener)
......@@ -365,15 +363,11 @@ void JavaScriptDebugServer::setJavaScriptPaused(Frame* frame, bool paused)
frame->script()->setPaused(paused);
if (JSDOMWindow* window = toJSDOMWindow(frame)) {
if (paused) {
OwnPtr<PausedTimeouts> timeouts;
window->pauseTimeouts(timeouts);
m_pausedTimeouts.set(frame, timeouts.release());
} else {
OwnPtr<PausedTimeouts> timeouts(m_pausedTimeouts.take(frame));
window->resumeTimeouts(timeouts);
}
if (Document* document = frame->document()) {
if (paused)
document->suspendActiveDOMObjects();
else
document->resumeActiveDOMObjects();
}
setJavaScriptPaused(frame->view(), paused);
......
......@@ -45,7 +45,6 @@ namespace WebCore {
class FrameView;
class Page;
class PageGroup;
class PausedTimeouts;
class JavaScriptCallFrame;
class JavaScriptDebugListener;
......@@ -122,7 +121,6 @@ namespace WebCore {
bool m_doneProcessingDebuggerEvents;
JavaScriptCallFrame* m_pauseOnCallFrame;
RefPtr<JavaScriptCallFrame> m_currentCallFrame;
HashMap<RefPtr<Frame>, PausedTimeouts*> m_pausedTimeouts;
HashMap<intptr_t, HashSet<unsigned>*> m_breakpoints;
Timer<JavaScriptDebugServer> m_recompileTimer;
};
......
......@@ -2690,17 +2690,6 @@ void FrameLoader::commitProvisionalLoad(PassRefPtr<CachedPage> prpCachedPage)
if (Document* document = m_frame->document())
document->suspendActiveDOMObjects();
cachePageForHistoryItem(m_currentHistoryItem.get());
} else {
if (m_frame->page() && m_frame == m_frame->page()->mainFrame()) {
// If the main frame installs a timeout late enough (for example in its onunload handler)
// it could sometimes fire when transitioning to a non-HTML document representation (such as the Mac bookmarks view).
// To avoid this, we clear all timeouts if the page is not to be cached in the back forward list.
// Cached pages have their timers paused so they are fine.
// FIXME: Integrate clearing timeouts into stopActiveDOMObjects().
ScriptController* proxy = m_frame->script();
if (proxy->haveWindowShell())
proxy->windowShell()->window()->clearAllTimeouts();
}
}
if (m_loadType != FrameLoadTypeReplace)
......@@ -2963,7 +2952,8 @@ void FrameLoader::open(CachedPage& cachedPage)
updatePolicyBaseURL();
cachedPage.restore(m_frame->page());
document->resumeActiveDOMObjects();
checkCompleted();
}
......
......@@ -466,10 +466,8 @@ PageGroupLoadDeferrer::PageGroupLoadDeferrer(Page* page, bool deferSelf)
#if !PLATFORM(MAC)
for (Frame* frame = otherPage->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
OwnPtr<PausedTimeouts> timeouts;
frame->script()->pauseTimeouts(timeouts);