1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#ifndef CONTENT_RENDERER_PEPPER_PEPPER_HUNG_PLUGIN_FILTER_H_ 6#define CONTENT_RENDERER_PEPPER_PEPPER_HUNG_PLUGIN_FILTER_H_ 7 8#include "base/files/file_path.h" 9#include "base/memory/ref_counted.h" 10#include "base/message_loop/message_loop_proxy.h" 11#include "base/synchronization/lock.h" 12#include "ipc/ipc_channel_proxy.h" 13#include "ipc/ipc_sync_message_filter.h" 14#include "ppapi/proxy/host_dispatcher.h" 15 16namespace content { 17 18// This class monitors a renderer <-> pepper plugin channel on the I/O thread 19// of the renderer for a hung plugin. 20// 21// If the plugin is not responding to sync messages, it will notify the browser 22// process and give the user the option to kill the hung plugin. 23// 24// Note that this class must be threadsafe since it will get the begin/end 25// block notifications on the main thread, but the filter is run on the I/O 26// thread. This is important since when we're blocked on a sync message to a 27// hung plugin, the main thread is frozen. 28// 29// NOTE: This class is refcounted (via SyncMessageStatusReceiver). 30class PepperHungPluginFilter 31 : public ppapi::proxy::HostDispatcher::SyncMessageStatusReceiver { 32 public: 33 // The |view_routing_id| is the ID of the render_view so that this class can 34 // send messages to the browser via that view's route. The |plugin_child_id| 35 // is the ID in the browser process of the pepper plugin process host. We use 36 // this to identify the proper plugin process to terminate. 37 PepperHungPluginFilter(const base::FilePath& plugin_path, 38 int view_routing_id, 39 int plugin_child_id); 40 41 // SyncMessageStatusReceiver implementation. 42 virtual void BeginBlockOnSyncMessage() OVERRIDE; 43 virtual void EndBlockOnSyncMessage() OVERRIDE; 44 45 // MessageFilter implementation. 46 virtual void OnFilterAdded(IPC::Channel* channel) OVERRIDE; 47 virtual void OnFilterRemoved() OVERRIDE; 48 virtual void OnChannelError() OVERRIDE; 49 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; 50 51 protected: 52 virtual ~PepperHungPluginFilter(); 53 54 private: 55 // Makes sure that the hung timer is scheduled. 56 void EnsureTimerScheduled(); 57 58 // Checks whether the plugin could have transitioned from hung to unhung and 59 // notifies the browser if so. 60 void MayHaveBecomeUnhung(); 61 62 // Calculate the point at which the plugin could next be considered hung. 63 base::TimeTicks GetHungTime() const; 64 65 // Checks if the plugin is considered hung based on whether it has been 66 // blocked for long enough. 67 bool IsHung() const; 68 69 // Timer handler that checks for a hang after a timeout. 70 void OnHangTimer(); 71 72 // Sends the hung/unhung message to the browser process. 73 void SendHungMessage(bool is_hung); 74 75 base::Lock lock_; 76 77 base::FilePath plugin_path_; 78 int view_routing_id_; 79 int plugin_child_id_; 80 81 // Used to post messages to the renderer <-> browser message channel from 82 // other threads without having to worry about the lifetime of that object. 83 // We don't actually use the "sync" feature of this filter. 84 scoped_refptr<IPC::SyncMessageFilter> filter_; 85 86 scoped_refptr<base::MessageLoopProxy> io_loop_; 87 88 // The time when we start being blocked on a sync message. If there are 89 // nested ones, this is the time of the outermost one. 90 // 91 // This will be is_null() if we've never blocked. 92 base::TimeTicks began_blocking_time_; 93 94 // Time that the last message was received from the plugin. 95 // 96 // This will be is_null() if we've never received any messages. 97 base::TimeTicks last_message_received_; 98 99 // Number of nested sync messages that we're blocked on. 100 int pending_sync_message_count_; 101 102 // True when we've sent the "plugin is hung" message to the browser. We track 103 // this so we know to look for it becoming unhung and send the corresponding 104 // message to the browser. 105 bool hung_plugin_showing_; 106 107 bool timer_task_pending_; 108 109 DISALLOW_COPY_AND_ASSIGN(PepperHungPluginFilter); 110}; 111 112} // namespace content 113 114#endif // CONTENT_RENDERER_PEPPER_PEPPER_HUNG_PLUGIN_FILTER_H_ 115