summaryrefslogtreecommitdiff
path: root/dom/plugins/ipc/PluginHangUIParent.h
blob: 8a6b2e6cb6822cfb338347eaa8db3a1fa0afa9d2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef mozilla_plugins_PluginHangUIParent_h
#define mozilla_plugins_PluginHangUIParent_h

#include "nsString.h"

#include "base/process.h"
#include "base/process_util.h"

#include "mozilla/Mutex.h"
#include "mozilla/plugins/PluginMessageUtils.h"

#include "MiniShmParent.h"

namespace mozilla {
namespace plugins {

class PluginModuleChromeParent;

/**
 * This class is responsible for launching and communicating with the 
 * plugin-hang-ui process.
 *
 * NOTE: PluginHangUIParent is *not* an IPDL actor! In this case, "Parent" 
 *       is describing the fact that firefox is the parent process to the 
 *       plugin-hang-ui process, which is the PluginHangUIChild.
 *       PluginHangUIParent and PluginHangUIChild are a matched pair.
 * @see PluginHangUIChild
 */
class PluginHangUIParent : public MiniShmObserver
{
public:
  PluginHangUIParent(PluginModuleChromeParent* aModule,
                     const int32_t aHangUITimeoutPref,
                     const int32_t aChildTimeoutPref);
  virtual ~PluginHangUIParent();

  /**
   * Spawn the plugin-hang-ui.exe child process and terminate the given 
   * plugin container process if the user elects to stop the hung plugin.
   *
   * @param aPluginName Human-readable name of the affected plugin.
   * @return true if the plugin hang ui process was successfully launched,
   *         otherwise false.
   */
  bool
  Init(const nsString& aPluginName);

  /**
   * If the Plugin Hang UI is being shown, send a cancel notification to the 
   * Plugin Hang UI child process.
   *
   * @return true if the UI was shown and the cancel command was successfully
   *              sent to the child process, otherwise false.
   */
  bool
  Cancel();

  /**
   * Returns whether the Plugin Hang UI is currently being displayed.
   *
   * @return true if the Plugin Hang UI is showing, otherwise false.
   */
  bool
  IsShowing() const { return mIsShowing; }

  /**
   * Returns whether this Plugin Hang UI instance has been shown. Note 
   * that this does not necessarily mean that the UI is showing right now.
   *
   * @return true if the Plugin Hang UI has shown, otherwise false.
   */
  bool
  WasShown() const { return mIsShowing || mLastUserResponse != 0; }

  /**
   * Returns whether the user checked the "Don't ask me again" checkbox.
   *
   * @return true if the user does not want to see the Hang UI again.
   */
  bool
  DontShowAgain() const;

  /**
   * Returns whether the user clicked stop during the last time that the 
   * Plugin Hang UI was displayed, if applicable.
   *
   * @return true if the UI was shown and the user chose to stop the 
   *         plugin, otherwise false
   */
  bool
  WasLastHangStopped() const;

  /**
   * @return unsigned int containing the response bits from the last 
   * time the Plugin Hang UI ran.
   */
  unsigned int
  LastUserResponse() const { return mLastUserResponse; }

  /**
   * @return unsigned int containing the number of milliseconds that 
   * the Plugin Hang UI was displayed before the user responded.
   * Returns 0 if the Plugin Hang UI has not been shown or was cancelled.
   */
  unsigned int
  LastShowDurationMs() const;

  virtual void
  OnMiniShmEvent(MiniShmBase* aMiniShmObj) override;

  virtual void
  OnMiniShmConnect(MiniShmBase* aMiniShmObj) override;

private:
  nsresult
  GetHangUIOwnerWindowHandle(NativeWindowHandle& windowHandle);

  bool
  SendCancel();

  bool
  RecvUserResponse(const unsigned int& aResponse);

  bool
  UnwatchHangUIChildProcess(bool aWait);

  static
  VOID CALLBACK SOnHangUIProcessExit(PVOID aContext, BOOLEAN aIsTimer);

private:
  Mutex mMutex;
  PluginModuleChromeParent* mModule;
  const uint32_t mTimeoutPrefMs;
  const uint32_t mIPCTimeoutMs;
  MessageLoop* mMainThreadMessageLoop;
  bool mIsShowing;
  unsigned int mLastUserResponse;
  base::ProcessHandle mHangUIProcessHandle;
  NativeWindowHandle mMainWindowHandle;
  HANDLE mRegWait;
  HANDLE mShowEvent;
  DWORD mShowTicks;
  DWORD mResponseTicks;
  MiniShmParent mMiniShm;

  DISALLOW_COPY_AND_ASSIGN(PluginHangUIParent);
};

} // namespace plugins
} // namespace mozilla

#endif // mozilla_plugins_PluginHangUIParent_h