| // Copyright (c) 2010 The Chromium OS 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 WINDOW_MANAGER_CHROME_WATCHDOG_H_ |
| #define WINDOW_MANAGER_CHROME_WATCHDOG_H_ |
| |
| #include <set> |
| |
| #include <sys/types.h> |
| |
| #include <gtest/gtest_prod.h> // for FRIEND_TEST() macro |
| |
| #include "base/memory/scoped_ptr.h" |
| #include "base/time.h" |
| #include "window_manager/event_consumer.h" |
| #include "window_manager/x11/x_types.h" |
| |
| namespace window_manager { |
| |
| class EventConsumerRegistrar; |
| class WindowManager; |
| class Window; |
| |
| // ChromeWatchdog sends _NET_WM_PING client messages to Chrome windows and |
| // kills them if they don't respond soon enough. |
| class ChromeWatchdog : public EventConsumer { |
| public: |
| explicit ChromeWatchdog(WindowManager* wm); |
| virtual ~ChromeWatchdog(); |
| |
| // Begin EventConsumer implementation. |
| virtual bool IsInputWindow(XWindow xid) { return false; } |
| virtual void HandleScreenResize() {} |
| virtual void HandleLoggedInStateChange() {} |
| virtual bool HandleWindowMapRequest(Window* win) { return false; } |
| virtual void HandleWindowMap(Window* win); |
| virtual void HandleWindowUnmap(Window* win); |
| virtual void HandleWindowPixmapFetch(Window* win) {} |
| virtual void HandleWindowConfigureRequest(Window* win, |
| const Rect& requested_bounds) {} |
| virtual void HandleButtonPress(XWindow xid, |
| const Point& relative_pos, |
| const Point& absolute_pos, |
| int button, |
| XTime timestamp) {} |
| virtual void HandleButtonRelease(XWindow xid, |
| const Point& relative_pos, |
| const Point& absolute_pos, |
| int button, |
| XTime timestamp) {} |
| virtual void HandlePointerEnter(XWindow xid, |
| const Point& relative_pos, |
| const Point& absolute_pos, |
| XTime timestamp) {} |
| virtual void HandlePointerLeave(XWindow xid, |
| const Point& relative_pos, |
| const Point& absolute_pos, |
| XTime timestamp) {} |
| virtual void HandlePointerMotion(XWindow xid, |
| const Point& relative_pos, |
| const Point& absolute_pos, |
| XTime timestamp) {} |
| virtual void HandleChromeMessage(const WmIpc::Message& msg) {} |
| virtual void HandleClientMessage(XWindow xid, |
| XAtom message_type, |
| const long data[5]); |
| virtual void HandleWindowPropertyChange(XWindow xid, XAtom xatom) {} |
| virtual void OwnDestroyedWindow(DestroyedWindow* destroyed_win, XWindow xid) { |
| NOTREACHED(); |
| } |
| // End EventConsumer implementation. |
| |
| // Send a _NET_WM_PING client message event to a Chrome window. If |
| // there's an outstanding ping, we abort it first. |
| bool SendPingToChrome(XTime timestamp, int timeout_ms); |
| |
| private: |
| FRIEND_TEST(ChromeWatchdogTest, Basic); |
| |
| bool is_pid_valid(pid_t pid) const { return pid > 1; } |
| |
| bool has_outstanding_ping() const { return pinged_chrome_xid_ != 0; } |
| |
| // If we have an outstanding timeout, abort it. We cancel the timeout |
| // and clear the related fields. |
| void AbortTimeout(); |
| |
| // Handle the timeout firing, meaning that Chrome didn't respond to our |
| // ping in time. |
| void HandleTimeout(); |
| |
| WindowManager* wm_; // not owned |
| |
| // Our machine's hostname. |
| std::string local_hostname_; |
| |
| scoped_ptr<EventConsumerRegistrar> registrar_; |
| |
| // IDs of all currently-mapped Chrome windows that we can ping (i.e. ones |
| // that support the _NET_WM_PING protocol, and were created by clients |
| // that are running on the local machine and have supplied their PIDs). |
| std::set<XWindow> usable_chrome_xids_; |
| |
| // The Chrome window to which an outstanding ping has been sent, or 0 if |
| // we're not currently waiting for a reply. |
| XWindow pinged_chrome_xid_; |
| |
| // X timestamp in the last ping that we sent. We expect to receive this in |
| // the reply. |
| XTime ping_timestamp_; |
| |
| // Time at which we sent the last ping (used for metrics). |
| base::TimeTicks monotonic_time_from_last_ping_; |
| |
| // ID of the timeout that will run HandleTimeout(), or |
| // EventLoop::kUnsetTimeoutId if no timeout is currently registered. |
| int timeout_id_; |
| |
| // PID of the last process that we killed, or -1 if we've never killed a |
| // process. Used for testing. |
| pid_t last_killed_pid_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ChromeWatchdog); |
| }; |
| |
| } // namespace window_manager |
| |
| #endif // WINDOW_MANAGER_CHROME_WATCHDOG_H_ |