Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / content / renderer / pepper / pepper_hung_plugin_filter.h
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_