1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef __IPC_GLUE_MESSAGEPUMP_H__
8 #define __IPC_GLUE_MESSAGEPUMP_H__
9 
10 #include "base/message_pump_default.h"
11 #if defined(XP_WIN)
12 #include "base/message_pump_win.h"
13 #endif
14 
15 #include "base/time.h"
16 #include "mozilla/Attributes.h"
17 #include "mozilla/Mutex.h"
18 #include "nsCOMPtr.h"
19 #include "nsIThreadInternal.h"
20 
21 class nsIEventTarget;
22 class nsITimer;
23 
24 namespace mozilla {
25 namespace ipc {
26 
27 class DoWorkRunnable;
28 
29 class MessagePump : public base::MessagePumpDefault {
30   friend class DoWorkRunnable;
31 
32  public:
33   explicit MessagePump(nsIEventTarget* aEventTarget);
34 
35   // From base::MessagePump.
36   virtual void Run(base::MessagePump::Delegate* aDelegate) override;
37 
38   // From base::MessagePump.
39   virtual void ScheduleWork() override;
40 
41   // From base::MessagePump.
42   virtual void ScheduleWorkForNestedLoop() override;
43 
44   // From base::MessagePump.
45   virtual void ScheduleDelayedWork(
46       const base::TimeTicks& aDelayedWorkTime) override;
47 
48   virtual nsIEventTarget* GetXPCOMThread() override;
49 
50  protected:
51   virtual ~MessagePump();
52 
53  private:
54   // Only called by DoWorkRunnable.
55   void DoDelayedWork(base::MessagePump::Delegate* aDelegate);
56 
57  protected:
58   nsIEventTarget* mEventTarget;
59 
60   // mDelayedWorkTimer and mEventTarget are set in Run() by this class or its
61   // subclasses.
62   nsCOMPtr<nsITimer> mDelayedWorkTimer;
63 
64  private:
65   // Only accessed by this class.
66   RefPtr<DoWorkRunnable> mDoWorkEvent;
67 };
68 
69 class MessagePumpForChildProcess final : public MessagePump {
70  public:
MessagePumpForChildProcess()71   MessagePumpForChildProcess() : MessagePump(nullptr), mFirstRun(true) {}
72 
73   virtual void Run(base::MessagePump::Delegate* aDelegate) override;
74 
75  private:
~MessagePumpForChildProcess()76   ~MessagePumpForChildProcess() {}
77 
78   bool mFirstRun;
79 };
80 
81 class MessagePumpForNonMainThreads final : public MessagePump {
82  public:
MessagePumpForNonMainThreads(nsIEventTarget * aEventTarget)83   explicit MessagePumpForNonMainThreads(nsIEventTarget* aEventTarget)
84       : MessagePump(aEventTarget) {}
85 
86   virtual void Run(base::MessagePump::Delegate* aDelegate) override;
87 
88  private:
~MessagePumpForNonMainThreads()89   ~MessagePumpForNonMainThreads() {}
90 };
91 
92 #if defined(XP_WIN)
93 // Extends the TYPE_UI message pump to process xpcom events. Currently only
94 // implemented for Win.
95 class MessagePumpForNonMainUIThreads final : public base::MessagePumpForUI,
96                                              public nsIThreadObserver {
97  public:
98   // We don't want xpcom refing, chromium controls our lifetime via
99   // RefCountedThreadSafe.
NS_IMETHOD_(MozExternalRefCountType)100   NS_IMETHOD_(MozExternalRefCountType) AddRef(void) override { return 2; }
Release(void)101   NS_IMETHOD_(MozExternalRefCountType) Release(void) override { return 1; }
102   NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
103 
104   NS_DECL_NSITHREADOBSERVER
105 
106  public:
MessagePumpForNonMainUIThreads(nsIEventTarget * aEventTarget)107   explicit MessagePumpForNonMainUIThreads(nsIEventTarget* aEventTarget)
108       : mInWait(false), mWaitLock("mInWait") {}
109 
110   // The main run loop for this thread.
111   virtual void DoRunLoop() override;
112 
GetXPCOMThread()113   virtual nsIEventTarget* GetXPCOMThread() override {
114     return nullptr;  // not sure what to do with this one
115   }
116 
117  protected:
SetInWait()118   void SetInWait() {
119     MutexAutoLock lock(mWaitLock);
120     mInWait = true;
121   }
122 
ClearInWait()123   void ClearInWait() {
124     MutexAutoLock lock(mWaitLock);
125     mInWait = false;
126   }
127 
GetInWait()128   bool GetInWait() {
129     MutexAutoLock lock(mWaitLock);
130     return mInWait;
131   }
132 
133  private:
~MessagePumpForNonMainUIThreads()134   ~MessagePumpForNonMainUIThreads() {}
135 
136   bool mInWait;
137   mozilla::Mutex mWaitLock;
138 };
139 #endif  // defined(XP_WIN)
140 
141 #if defined(MOZ_WIDGET_ANDROID)
142 /*`
143  * The MessagePumpForAndroidUI exists to enable IPDL in the Android UI thread.
144  * The Android UI thread event loop is controlled by Android. This prevents
145  * running an existing MessagePump implementation in the Android UI thread. In
146  * order to enable IPDL on the Android UI thread it is necessary to have a
147  * non-looping MessagePump. This class enables forwarding of nsIRunnables from
148  * MessageLoop::PostTask_Helper to the registered nsIEventTarget with out the
149  * need to control the event loop. The only member function that should be
150  * invoked is GetXPCOMThread. All other member functions will invoke MOZ_CRASH
151  */
152 class MessagePumpForAndroidUI : public base::MessagePump {
153  public:
MessagePumpForAndroidUI(nsIEventTarget * aEventTarget)154   MessagePumpForAndroidUI(nsIEventTarget* aEventTarget)
155       : mEventTarget(aEventTarget) {}
156 
157   virtual void Run(Delegate* delegate);
158   virtual void Quit();
159   virtual void ScheduleWork();
160   virtual void ScheduleDelayedWork(const base::TimeTicks& delayed_work_time);
GetXPCOMThread()161   virtual nsIEventTarget* GetXPCOMThread() { return mEventTarget; }
162 
163  private:
~MessagePumpForAndroidUI()164   ~MessagePumpForAndroidUI() {}
MessagePumpForAndroidUI()165   MessagePumpForAndroidUI() {}
166 
167   nsIEventTarget* mEventTarget;
168 };
169 #endif  // defined(MOZ_WIDGET_ANDROID)
170 
171 } /* namespace ipc */
172 } /* namespace mozilla */
173 
174 #endif /* __IPC_GLUE_MESSAGEPUMP_H__ */
175