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 mozilla_nsDumpUtils_h
8 #define mozilla_nsDumpUtils_h
9 
10 #include "nsIObserver.h"
11 #include "base/message_loop.h"
12 #include "nsXULAppAPI.h"
13 #include "nsThreadUtils.h"
14 #include "mozilla/Mutex.h"
15 #include "mozilla/StaticPtr.h"
16 #include "nsTArray.h"
17 
18 #ifdef LOG
19 #  undef LOG
20 #endif
21 
22 #ifdef ANDROID
23 #  include "android/log.h"
24 #  define LOG(...) \
25     __android_log_print(ANDROID_LOG_INFO, "Gecko:DumpUtils", ##__VA_ARGS__)
26 #else
27 #  define LOG(...)
28 #endif
29 
30 #ifdef XP_UNIX  // {
31 
32 /**
33  * Abstract base class for something which watches an fd and takes action when
34  * we can read from it without blocking.
35  */
36 class FdWatcher : public MessageLoopForIO::Watcher, public nsIObserver {
37  protected:
38   MessageLoopForIO::FileDescriptorWatcher mReadWatcher;
39   int mFd;
40 
~FdWatcher()41   virtual ~FdWatcher() {
42     // StopWatching should have run.
43     MOZ_ASSERT(mFd == -1);
44   }
45 
46  public:
FdWatcher()47   FdWatcher() : mFd(-1) { MOZ_ASSERT(NS_IsMainThread()); }
48 
49   /**
50    * Open the fd to watch.  If we encounter an error, return -1.
51    */
52   virtual int OpenFd() = 0;
53 
54   /**
55    * Called when you can read() from the fd without blocking.  Note that this
56    * function is also called when you're at eof (read() returns 0 in this case).
57    */
58   virtual void OnFileCanReadWithoutBlocking(int aFd) override = 0;
OnFileCanWriteWithoutBlocking(int aFd)59   virtual void OnFileCanWriteWithoutBlocking(int aFd) override{};
60 
61   NS_DECL_THREADSAFE_ISUPPORTS
62 
63   /**
64    * Initialize this object.  This should be called right after the object is
65    * constructed.  (This would go in the constructor, except we interact with
66    * XPCOM, which we can't do from a constructor because our refcount is 0 at
67    * that point.)
68    */
69   void Init();
70 
71   // Implementations may call this function multiple times if they ensure that
72 
73   virtual void StartWatching();
74 
75   // Since implementations can call StartWatching() multiple times, they can of
76   // course call StopWatching() multiple times.
77   virtual void StopWatching();
78 
Observe(nsISupports * aSubject,const char * aTopic,const char16_t * aData)79   NS_IMETHOD Observe(nsISupports* aSubject, const char* aTopic,
80                      const char16_t* aData) override {
81     MOZ_ASSERT(NS_IsMainThread());
82     MOZ_ASSERT(!strcmp(aTopic, "xpcom-shutdown"));
83 
84     XRE_GetIOMessageLoop()->PostTask(mozilla::NewRunnableMethod(
85         "FdWatcher::StopWatching", this, &FdWatcher::StopWatching));
86 
87     return NS_OK;
88   }
89 };
90 
91 typedef void (*FifoCallback)(const nsCString& aInputStr);
92 struct FifoInfo {
93   nsCString mCommand;
94   FifoCallback mCallback;
95 };
96 typedef nsTArray<FifoInfo> FifoInfoArray;
97 
98 class FifoWatcher : public FdWatcher {
99  public:
100   /**
101    * The name of the preference used to enable/disable the FifoWatcher.
102    */
103   // The length of this array must match the size of the string constant in
104   // the definition in nsDumpUtils.cpp. A mismatch will result in a compile-time
105   // error.
106   static const char kPrefName[38];
107 
108   static FifoWatcher* GetSingleton();
109 
110   static bool MaybeCreate();
111 
112   void RegisterCallback(const nsCString& aCommand, FifoCallback aCallback);
113 
114   virtual ~FifoWatcher();
115 
116   virtual int OpenFd() override;
117 
118   virtual void OnFileCanReadWithoutBlocking(int aFd) override;
119 
120  private:
121   nsAutoCString mDirPath;
122 
123   static mozilla::StaticRefPtr<FifoWatcher> sSingleton;
124 
FifoWatcher(nsCString aPath)125   explicit FifoWatcher(nsCString aPath)
126       : mDirPath(aPath), mFifoInfoLock("FifoWatcher.mFifoInfoLock") {}
127 
128   mozilla::Mutex mFifoInfoLock;  // protects mFifoInfo
129   FifoInfoArray mFifoInfo;
130 };
131 
132 typedef void (*PipeCallback)(const uint8_t aRecvSig);
133 struct SignalInfo {
134   uint8_t mSignal;
135   PipeCallback mCallback;
136 };
137 typedef nsTArray<SignalInfo> SignalInfoArray;
138 
139 class SignalPipeWatcher : public FdWatcher {
140  public:
141   static SignalPipeWatcher* GetSingleton();
142 
143   void RegisterCallback(uint8_t aSignal, PipeCallback aCallback);
144 
145   void RegisterSignalHandler(uint8_t aSignal = 0);
146 
147   virtual ~SignalPipeWatcher();
148 
149   virtual int OpenFd() override;
150 
151   virtual void StopWatching() override;
152 
153   virtual void OnFileCanReadWithoutBlocking(int aFd) override;
154 
155  private:
156   static mozilla::StaticRefPtr<SignalPipeWatcher> sSingleton;
157 
SignalPipeWatcher()158   SignalPipeWatcher() : mSignalInfoLock("SignalPipeWatcher.mSignalInfoLock") {
159     MOZ_ASSERT(NS_IsMainThread());
160   }
161 
162   mozilla::Mutex mSignalInfoLock;  // protects mSignalInfo
163   SignalInfoArray mSignalInfo;
164 };
165 
166 #endif  // XP_UNIX }
167 
168 class nsDumpUtils {
169  public:
170   enum Mode { CREATE, CREATE_UNIQUE };
171 
172   /**
173    * This function creates a new unique file based on |aFilename| in a
174    * world-readable temp directory. This is the system temp directory
175    * or, in the case of Android, the downloads directory. If |aFile| is
176    * non-null, it is assumed to point to a folder, and that folder is used
177    * instead.
178    */
179   static nsresult OpenTempFile(const nsACString& aFilename, nsIFile** aFile,
180                                const nsACString& aFoldername = ""_ns,
181                                Mode aMode = CREATE_UNIQUE);
182 };
183 
184 #endif
185