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 IPC::MessageFilter). 30 class PepperHungPluginFilter 31 : public ppapi::proxy::HostDispatcher::SyncMessageStatusObserver, 32 public IPC::MessageFilter { 33 public: 34 // The |frame_routing_id| is the ID of the render_frame so that this class can 35 // send messages to the browser via that frame's route. The |plugin_child_id| 36 // is the ID in the browser process of the pepper plugin process host. We use 37 // this to identify the proper plugin process to terminate. 38 PepperHungPluginFilter(const base::FilePath& plugin_path, 39 int frame_routing_id, 40 int plugin_child_id); 41 42 // SyncMessageStatusReceiver implementation. 43 virtual void BeginBlockOnSyncMessage() OVERRIDE; 44 virtual void EndBlockOnSyncMessage() OVERRIDE; 45 46 // MessageFilter implementation. 47 virtual void OnFilterAdded(IPC::Sender* sender) OVERRIDE; 48 virtual void OnFilterRemoved() OVERRIDE; 49 virtual void OnChannelError() OVERRIDE; 50 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; 51 52 protected: 53 virtual ~PepperHungPluginFilter(); 54 55 private: 56 // Makes sure that the hung timer is scheduled. 57 void EnsureTimerScheduled(); 58 59 // Checks whether the plugin could have transitioned from hung to unhung and 60 // notifies the browser if so. 61 void MayHaveBecomeUnhung(); 62 63 // Calculate the point at which the plugin could next be considered hung. 64 base::TimeTicks GetHungTime() const; 65 66 // Checks if the plugin is considered hung based on whether it has been 67 // blocked for long enough. 68 bool IsHung() const; 69 70 // Timer handler that checks for a hang after a timeout. 71 void OnHangTimer(); 72 73 // Sends the hung/unhung message to the browser process. 74 void SendHungMessage(bool is_hung); 75 76 base::Lock lock_; 77 78 base::FilePath plugin_path_; 79 int frame_routing_id_; 80 int plugin_child_id_; 81 82 // Used to post messages to the renderer <-> browser message channel from 83 // other threads without having to worry about the lifetime of that object. 84 // We don't actually use the "sync" feature of this filter. 85 scoped_refptr<IPC::SyncMessageFilter> filter_; 86 87 scoped_refptr<base::MessageLoopProxy> io_loop_; 88 89 // The time when we start being blocked on a sync message. If there are 90 // nested ones, this is the time of the outermost one. 91 // 92 // This will be is_null() if we've never blocked. 93 base::TimeTicks began_blocking_time_; 94 95 // Time that the last message was received from the plugin. 96 // 97 // This will be is_null() if we've never received any messages. 98 base::TimeTicks last_message_received_; 99 100 // Number of nested sync messages that we're blocked on. 101 int pending_sync_message_count_; 102 103 // True when we've sent the "plugin is hung" message to the browser. We track 104 // this so we know to look for it becoming unhung and send the corresponding 105 // message to the browser. 106 bool hung_plugin_showing_; 107 108 bool timer_task_pending_; 109 110 DISALLOW_COPY_AND_ASSIGN(PepperHungPluginFilter); 111 }; 112 113 } // namespace content 114 115 #endif // CONTENT_RENDERER_PEPPER_PEPPER_HUNG_PLUGIN_FILTER_H_ 116