blob: 47c24bc20965df4f7a95f1a04b93fe83eacfd1a5 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_BROWSER_WATCHER_WINDOW_HANG_MONITOR_WIN_H_
#define COMPONENTS_BROWSER_WATCHER_WINDOW_HANG_MONITOR_WIN_H_
#include <windows.h>
#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/process/process.h"
#include "base/strings/string16.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
namespace browser_watcher {
// Monitors a window for hanging by periodically sending it a WM_NULL message
// and timing the response.
class WindowHangMonitor {
public:
enum WindowEvent {
WINDOW_HUNG,
WINDOW_VANISHED,
};
// Called when a hang is detected or when the window has gone away.
// Called precisely zero or one time(s).
typedef base::Callback<void(WindowEvent)> WindowEventCallback;
// Initialize the monitor with an event callback.
explicit WindowHangMonitor(const WindowEventCallback& callback);
~WindowHangMonitor();
// Initializes the watcher to monitor the window answering to |window_name|.
// Returns true on success.
bool Initialize(const base::string16& window_name);
// Testing accessors.
bool IsIdleForTesting() const { return !timer_.IsRunning(); }
void SetPingIntervalForTesting(base::TimeDelta ping_interval);
void SetHangTimeoutForTesting(base::TimeDelta hang_timeout);
HWND window() const { return window_; }
const base::Process& window_process() const { return window_process_; }
private:
struct OutstandingPing {
WindowHangMonitor* monitor;
};
static void CALLBACK
OnPongReceived(HWND window, UINT msg, ULONG_PTR data, LRESULT lresult);
// Checks that |window_| is still valid, and sends it a ping.
// Issues a |WINDOW_VANISHED| callback if the window's no longer valid.
// Schedules OnHangTimeout in case of success.
// Returns true on success, false if the window is no longer valid or other
// failure.
bool MaybeSendPing();
// Runs after a |hang_timeout_| delay after sending a ping. Checks whether
// a pong was received. Either issues a callback or schedules OnRetryTimeout.
void OnHangTimeout();
// Runs periodically at |ping_interval_| interval, as long as the window is
// still valid and not hung.
void OnRetryTimeout();
// Invoked on significant window events.
WindowEventCallback callback_;
// The name of the (message) window to monitor.
base::string16 window_name_;
// The monitored window handle.
HWND window_;
// The process that owned |window_| when Initialize was called.
base::Process window_process_;
// The time the last message was sent.
base::Time last_ping_;
// The ping interval, must be larger than |hang_timeout_|.
base::TimeDelta ping_interval_;
// The time after which |window_| is assumed hung.
base::TimeDelta hang_timeout_;
// The timer used to schedule polls.
base::Timer timer_;
// Non-null when there is an outstanding ping.
// This is intentionally leaked when a hang is detected.
OutstandingPing* outstanding_ping_;
DISALLOW_COPY_AND_ASSIGN(WindowHangMonitor);
};
} // namespace browser_watcher
#endif // COMPONENTS_BROWSER_WATCHER_WINDOW_HANG_MONITOR_WIN_H_
|