michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim: set ts=2 et sw=2 tw=80: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef mozilla_plugins_PluginHangUIParent_h michael@0: #define mozilla_plugins_PluginHangUIParent_h michael@0: michael@0: #include "nsString.h" michael@0: michael@0: #include "base/process.h" michael@0: #include "base/process_util.h" michael@0: michael@0: #include "mozilla/Mutex.h" michael@0: #include "mozilla/plugins/PluginMessageUtils.h" michael@0: michael@0: #include "MiniShmParent.h" michael@0: michael@0: namespace mozilla { michael@0: namespace plugins { michael@0: michael@0: class PluginModuleParent; michael@0: michael@0: /** michael@0: * This class is responsible for launching and communicating with the michael@0: * plugin-hang-ui process. michael@0: * michael@0: * NOTE: PluginHangUIParent is *not* an IPDL actor! In this case, "Parent" michael@0: * is describing the fact that firefox is the parent process to the michael@0: * plugin-hang-ui process, which is the PluginHangUIChild. michael@0: * PluginHangUIParent and PluginHangUIChild are a matched pair. michael@0: * @see PluginHangUIChild michael@0: */ michael@0: class PluginHangUIParent : public MiniShmObserver michael@0: { michael@0: public: michael@0: PluginHangUIParent(PluginModuleParent* aModule, michael@0: const int32_t aHangUITimeoutPref, michael@0: const int32_t aChildTimeoutPref); michael@0: virtual ~PluginHangUIParent(); michael@0: michael@0: /** michael@0: * Spawn the plugin-hang-ui.exe child process and terminate the given michael@0: * plugin container process if the user elects to stop the hung plugin. michael@0: * michael@0: * @param aPluginName Human-readable name of the affected plugin. michael@0: * @return true if the plugin hang ui process was successfully launched, michael@0: * otherwise false. michael@0: */ michael@0: bool michael@0: Init(const nsString& aPluginName); michael@0: michael@0: /** michael@0: * If the Plugin Hang UI is being shown, send a cancel notification to the michael@0: * Plugin Hang UI child process. michael@0: * michael@0: * @return true if the UI was shown and the cancel command was successfully michael@0: * sent to the child process, otherwise false. michael@0: */ michael@0: bool michael@0: Cancel(); michael@0: michael@0: /** michael@0: * Returns whether the Plugin Hang UI is currently being displayed. michael@0: * michael@0: * @return true if the Plugin Hang UI is showing, otherwise false. michael@0: */ michael@0: bool michael@0: IsShowing() const { return mIsShowing; } michael@0: michael@0: /** michael@0: * Returns whether this Plugin Hang UI instance has been shown. Note michael@0: * that this does not necessarily mean that the UI is showing right now. michael@0: * michael@0: * @return true if the Plugin Hang UI has shown, otherwise false. michael@0: */ michael@0: bool michael@0: WasShown() const { return mIsShowing || mLastUserResponse != 0; } michael@0: michael@0: /** michael@0: * Returns whether the user checked the "Don't ask me again" checkbox. michael@0: * michael@0: * @return true if the user does not want to see the Hang UI again. michael@0: */ michael@0: bool michael@0: DontShowAgain() const; michael@0: michael@0: /** michael@0: * Returns whether the user clicked stop during the last time that the michael@0: * Plugin Hang UI was displayed, if applicable. michael@0: * michael@0: * @return true if the UI was shown and the user chose to stop the michael@0: * plugin, otherwise false michael@0: */ michael@0: bool michael@0: WasLastHangStopped() const; michael@0: michael@0: /** michael@0: * @return unsigned int containing the response bits from the last michael@0: * time the Plugin Hang UI ran. michael@0: */ michael@0: unsigned int michael@0: LastUserResponse() const { return mLastUserResponse; } michael@0: michael@0: /** michael@0: * @return unsigned int containing the number of milliseconds that michael@0: * the Plugin Hang UI was displayed before the user responded. michael@0: * Returns 0 if the Plugin Hang UI has not been shown or was cancelled. michael@0: */ michael@0: unsigned int michael@0: LastShowDurationMs() const; michael@0: michael@0: virtual void michael@0: OnMiniShmEvent(MiniShmBase* aMiniShmObj) MOZ_OVERRIDE; michael@0: michael@0: virtual void michael@0: OnMiniShmConnect(MiniShmBase* aMiniShmObj) MOZ_OVERRIDE; michael@0: michael@0: private: michael@0: nsresult michael@0: GetHangUIOwnerWindowHandle(NativeWindowHandle& windowHandle); michael@0: michael@0: bool michael@0: SendCancel(); michael@0: michael@0: bool michael@0: RecvUserResponse(const unsigned int& aResponse); michael@0: michael@0: bool michael@0: UnwatchHangUIChildProcess(bool aWait); michael@0: michael@0: static michael@0: VOID CALLBACK SOnHangUIProcessExit(PVOID aContext, BOOLEAN aIsTimer); michael@0: michael@0: private: michael@0: Mutex mMutex; michael@0: PluginModuleParent* mModule; michael@0: const uint32_t mTimeoutPrefMs; michael@0: const uint32_t mIPCTimeoutMs; michael@0: MessageLoop* mMainThreadMessageLoop; michael@0: bool mIsShowing; michael@0: unsigned int mLastUserResponse; michael@0: base::ProcessHandle mHangUIProcessHandle; michael@0: NativeWindowHandle mMainWindowHandle; michael@0: HANDLE mRegWait; michael@0: HANDLE mShowEvent; michael@0: DWORD mShowTicks; michael@0: DWORD mResponseTicks; michael@0: MiniShmParent mMiniShm; michael@0: michael@0: DISALLOW_COPY_AND_ASSIGN(PluginHangUIParent); michael@0: }; michael@0: michael@0: } // namespace plugins michael@0: } // namespace mozilla michael@0: michael@0: #endif // mozilla_plugins_PluginHangUIParent_h michael@0: