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 16 namespace 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). 30 class PepperHungPluginFilter 31 : public ppapi::proxy::HostDispatcher::SyncMessageStatusReceiver { 32 public: 33 // The |frame_routing_id| is the ID of the render_frame so that this class can 34 // send messages to the browser via that frame'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 frame_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 frame_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