Stop spamming delayed tasks on each input event.
R=mbelshe BUG=2693 Review URL: http://codereview.chromium.org/4262 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@2609 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
@ -66,6 +66,13 @@ class BaseTimer_Helper {
|
||||
return delayed_task_ != NULL;
|
||||
}
|
||||
|
||||
// Returns the current delay for this timer. May only call this method when
|
||||
// the timer is running!
|
||||
TimeDelta GetCurrentDelay() const {
|
||||
DCHECK(IsRunning());
|
||||
return delayed_task_->delay_;
|
||||
}
|
||||
|
||||
protected:
|
||||
BaseTimer_Helper() : delayed_task_(NULL) {}
|
||||
|
||||
|
@ -233,7 +233,7 @@ void RenderViewHost::FirePageBeforeUnload() {
|
||||
// Start the hang monitor in case the renderer hangs in the beforeunload
|
||||
// handler.
|
||||
is_waiting_for_unload_ack_ = true;
|
||||
StartHangMonitorTimeout(kUnloadTimeoutMS);
|
||||
StartHangMonitorTimeout(TimeDelta::FromMilliseconds(kUnloadTimeoutMS));
|
||||
Send(new ViewMsg_ShouldClose(routing_id_));
|
||||
} else {
|
||||
// This RenderViewHost doesn't have a live renderer, so just skip running
|
||||
@ -245,7 +245,7 @@ void RenderViewHost::FirePageBeforeUnload() {
|
||||
void RenderViewHost::FirePageUnload() {
|
||||
// Start the hang monitor in case the renderer hangs in the unload handler.
|
||||
is_waiting_for_unload_ack_ = true;
|
||||
StartHangMonitorTimeout(kUnloadTimeoutMS);
|
||||
StartHangMonitorTimeout(TimeDelta::FromMilliseconds(kUnloadTimeoutMS));
|
||||
ClosePage(site_instance()->process_host_id(),
|
||||
routing_id());
|
||||
}
|
||||
@ -487,7 +487,7 @@ void RenderViewHost::JavaScriptMessageBoxClosed(IPC::Message* reply_msg,
|
||||
bool success,
|
||||
const std::wstring& prompt) {
|
||||
if (is_waiting_for_unload_ack_)
|
||||
StartHangMonitorTimeout(kUnloadTimeoutMS);
|
||||
StartHangMonitorTimeout(TimeDelta::FromMilliseconds(kUnloadTimeoutMS));
|
||||
|
||||
if (--modal_dialog_count_ == 0)
|
||||
ResetEvent(modal_dialog_event_.Get());
|
||||
@ -498,7 +498,7 @@ void RenderViewHost::JavaScriptMessageBoxClosed(IPC::Message* reply_msg,
|
||||
void RenderViewHost::ModalHTMLDialogClosed(IPC::Message* reply_msg,
|
||||
const std::string& json_retval) {
|
||||
if (is_waiting_for_unload_ack_)
|
||||
StartHangMonitorTimeout(kUnloadTimeoutMS);
|
||||
StartHangMonitorTimeout(TimeDelta::FromMilliseconds(kUnloadTimeoutMS));
|
||||
|
||||
if (--modal_dialog_count_ == 0)
|
||||
ResetEvent(modal_dialog_event_.Get());
|
||||
|
@ -273,7 +273,6 @@ RenderWidgetHost::RenderWidgetHost(RenderProcessHost* process, int routing_id)
|
||||
is_hidden_(false),
|
||||
suppress_view_updating_(false),
|
||||
needs_repainting_on_restore_(false),
|
||||
hung_renderer_factory_(this),
|
||||
is_unresponsive_(false),
|
||||
view_being_painted_(false),
|
||||
repaint_ack_pending_(false) {
|
||||
@ -630,7 +629,7 @@ void RenderWidgetHost::ForwardInputEvent(const WebInputEvent& input_event,
|
||||
// any input event cancels a pending mouse move event
|
||||
next_mouse_move_.reset();
|
||||
|
||||
StartHangMonitorTimeout(kHungRendererDelayMs);
|
||||
StartHangMonitorTimeout(TimeDelta::FromMilliseconds(kHungRendererDelayMs));
|
||||
}
|
||||
|
||||
void RenderWidgetHost::Shutdown() {
|
||||
@ -673,7 +672,19 @@ void RenderWidgetHost::Destroy() {
|
||||
delete this;
|
||||
}
|
||||
|
||||
void RenderWidgetHost::RendererIsUnresponsive() {
|
||||
void RenderWidgetHost::CheckRendererIsUnresponsive() {
|
||||
// If we received a call to StopHangMonitorTimeout.
|
||||
if (time_when_considered_hung_.is_null())
|
||||
return;
|
||||
|
||||
// If we have not waited long enough, then wait some more.
|
||||
Time now = Time::Now();
|
||||
if (now < time_when_considered_hung_) {
|
||||
StartHangMonitorTimeout(time_when_considered_hung_ - now);
|
||||
return;
|
||||
}
|
||||
|
||||
// OK, looks like we have a hung renderer!
|
||||
NotificationService::current()->Notify(NOTIFY_RENDERER_PROCESS_HANG,
|
||||
Source<RenderWidgetHost>(this),
|
||||
NotificationService::NoDetails());
|
||||
@ -788,19 +799,31 @@ void RenderWidgetHost::ScrollRect(HANDLE bitmap, const gfx::Rect& bitmap_rect,
|
||||
}
|
||||
|
||||
void RenderWidgetHost::RestartHangMonitorTimeout() {
|
||||
hung_renderer_factory_.RevokeAll();
|
||||
StartHangMonitorTimeout(kHungRendererDelayMs);
|
||||
StartHangMonitorTimeout(TimeDelta::FromMilliseconds(kHungRendererDelayMs));
|
||||
}
|
||||
|
||||
void RenderWidgetHost::StopHangMonitorTimeout() {
|
||||
hung_renderer_factory_.RevokeAll();
|
||||
time_when_considered_hung_ = Time();
|
||||
RendererIsResponsive();
|
||||
|
||||
// We do not bother to stop the hung_renderer_timer_ here in case it will be
|
||||
// started again shortly, which happens to be the common use case.
|
||||
}
|
||||
|
||||
void RenderWidgetHost::StartHangMonitorTimeout(int delay) {
|
||||
MessageLoop::current()->PostDelayedTask(FROM_HERE,
|
||||
hung_renderer_factory_.NewRunnableMethod(
|
||||
&RenderWidgetHost::RendererIsUnresponsive), delay);
|
||||
void RenderWidgetHost::StartHangMonitorTimeout(TimeDelta delay) {
|
||||
time_when_considered_hung_ = Time::Now() + delay;
|
||||
|
||||
// If we already have a timer that will expire at or before the given delay,
|
||||
// then we have nothing more to do now.
|
||||
if (hung_renderer_timer_.IsRunning() &&
|
||||
hung_renderer_timer_.GetCurrentDelay() <= delay)
|
||||
return;
|
||||
|
||||
// Either the timer is not yet running, or we need to adjust the timer to
|
||||
// fire sooner.
|
||||
hung_renderer_timer_.Stop();
|
||||
hung_renderer_timer_.Start(delay, this,
|
||||
&RenderWidgetHost::CheckRendererIsUnresponsive);
|
||||
}
|
||||
|
||||
void RenderWidgetHost::RendererExited() {
|
||||
|
@ -2,13 +2,13 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef CHROME_BROWSER_RENDER_WIDGET_HOST_H__
|
||||
#define CHROME_BROWSER_RENDER_WIDGET_HOST_H__
|
||||
#ifndef CHROME_BROWSER_RENDER_WIDGET_HOST_H_
|
||||
#define CHROME_BROWSER_RENDER_WIDGET_HOST_H_
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "base/task.h"
|
||||
#include "base/gfx/size.h"
|
||||
#include "base/timer.h"
|
||||
#include "chrome/common/ipc_channel.h"
|
||||
|
||||
namespace gfx {
|
||||
@ -180,11 +180,11 @@ class RenderWidgetHost : public IPC::Channel::Listener {
|
||||
// javascript call.
|
||||
virtual bool CanBlur() const { return true; }
|
||||
|
||||
// Restart the active hang monitor timeout. Clears all existing timeouts
|
||||
// and starts with a new one.
|
||||
// This can be because the renderer has become active, the tab is being
|
||||
// hidden, or the user has chosen to wait some more to give the tab a chance
|
||||
// to become active and we don't want to display a warning too soon.
|
||||
// Restart the active hang monitor timeout. Clears all existing timeouts and
|
||||
// starts with a new one. This can be because the renderer has become
|
||||
// active, the tab is being hidden, or the user has chosen to wait some more
|
||||
// to give the tab a chance to become active and we don't want to display a
|
||||
// warning too soon.
|
||||
void RestartHangMonitorTimeout();
|
||||
|
||||
// Stops all existing hang monitor timeouts and assumes the renderer is
|
||||
@ -194,7 +194,7 @@ class RenderWidgetHost : public IPC::Channel::Listener {
|
||||
// Starts a hang monitor timeout. If there's already a hang monitor timeout
|
||||
// the new one will only fire if it has a shorter delay than the time
|
||||
// left on the existing timeouts.
|
||||
void StartHangMonitorTimeout(int delay);
|
||||
void StartHangMonitorTimeout(TimeDelta delay);
|
||||
|
||||
// Called when we receive a notification indicating that the renderer
|
||||
// process has gone.
|
||||
@ -250,7 +250,7 @@ class RenderWidgetHost : public IPC::Channel::Listener {
|
||||
// Callbacks for notification when the renderer becomes unresponsive to user
|
||||
// input events, and subsequently responsive again. The delegate can use
|
||||
// these notifications to show a warning.
|
||||
void RendererIsUnresponsive();
|
||||
void CheckRendererIsUnresponsive();
|
||||
virtual void NotifyRendererUnresponsive() {}
|
||||
void RendererIsResponsive();
|
||||
virtual void NotifyRendererResponsive() {}
|
||||
@ -298,8 +298,12 @@ class RenderWidgetHost : public IPC::Channel::Listener {
|
||||
// itself, a paint message could already be in flight at that point.
|
||||
bool needs_repainting_on_restore_;
|
||||
|
||||
// The following factory is used to detect a hung renderer
|
||||
ScopedRunnableMethodFactory<RenderWidgetHost> hung_renderer_factory_;
|
||||
// The following value indicates a time in the future when we would consider
|
||||
// the renderer hung if it does not generate an appropriate response message.
|
||||
Time time_when_considered_hung_;
|
||||
|
||||
// This timer runs to check if time_when_considered_hung_ has past.
|
||||
base::OneShotTimer<RenderWidgetHost> hung_renderer_timer_;
|
||||
|
||||
// This is true if the renderer is currently unresponsive.
|
||||
bool is_unresponsive_;
|
||||
@ -359,5 +363,4 @@ class RenderWidgetHost::PaintObserver {
|
||||
virtual void RenderWidgetHostDidPaint(RenderWidgetHost* rwh) = 0;
|
||||
};
|
||||
|
||||
#endif // #ifndef CHROME_BROWSER_RENDER_WIDGET_HOST_H__
|
||||
|
||||
#endif // #ifndef CHROME_BROWSER_RENDER_WIDGET_HOST_H_
|
||||
|
Reference in New Issue
Block a user