michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim: set ts=8 sts=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_nsDumpUtils_h michael@0: #define mozilla_nsDumpUtils_h michael@0: michael@0: #include "nsIObserver.h" michael@0: #include "base/message_loop.h" michael@0: #include "nsXULAppAPI.h" michael@0: #include "nsThreadUtils.h" michael@0: #include "mozilla/Mutex.h" michael@0: #include "mozilla/StaticPtr.h" michael@0: #include "nsTArray.h" michael@0: michael@0: #ifdef LOG michael@0: #undef LOG michael@0: #endif michael@0: michael@0: #ifdef ANDROID michael@0: #include "android/log.h" michael@0: #define LOG(...) __android_log_print(ANDROID_LOG_INFO, "Gecko:DumpUtils", ## __VA_ARGS__) michael@0: #else michael@0: #define LOG(...) michael@0: #endif michael@0: michael@0: using namespace mozilla; michael@0: michael@0: #ifdef XP_UNIX // { michael@0: michael@0: /** michael@0: * Abstract base class for something which watches an fd and takes action when michael@0: * we can read from it without blocking. michael@0: */ michael@0: class FdWatcher : public MessageLoopForIO::Watcher michael@0: , public nsIObserver michael@0: { michael@0: protected: michael@0: MessageLoopForIO::FileDescriptorWatcher mReadWatcher; michael@0: int mFd; michael@0: michael@0: public: michael@0: FdWatcher() michael@0: : mFd(-1) michael@0: { michael@0: MOZ_ASSERT(NS_IsMainThread()); michael@0: } michael@0: michael@0: virtual ~FdWatcher() michael@0: { michael@0: // StopWatching should have run. michael@0: MOZ_ASSERT(mFd == -1); michael@0: } michael@0: michael@0: /** michael@0: * Open the fd to watch. If we encounter an error, return -1. michael@0: */ michael@0: virtual int OpenFd() = 0; michael@0: michael@0: /** michael@0: * Called when you can read() from the fd without blocking. Note that this michael@0: * function is also called when you're at eof (read() returns 0 in this case). michael@0: */ michael@0: virtual void OnFileCanReadWithoutBlocking(int aFd) = 0; michael@0: virtual void OnFileCanWriteWithoutBlocking(int aFd) {}; michael@0: michael@0: NS_DECL_THREADSAFE_ISUPPORTS michael@0: michael@0: /** michael@0: * Initialize this object. This should be called right after the object is michael@0: * constructed. (This would go in the constructor, except we interact with michael@0: * XPCOM, which we can't do from a constructor because our refcount is 0 at michael@0: * that point.) michael@0: */ michael@0: void Init(); michael@0: michael@0: // Implementations may call this function multiple times if they ensure that michael@0: michael@0: virtual void StartWatching(); michael@0: michael@0: // Since implementations can call StartWatching() multiple times, they can of michael@0: // course call StopWatching() multiple times. michael@0: virtual void StopWatching(); michael@0: michael@0: NS_IMETHOD Observe(nsISupports* aSubject, const char* aTopic, michael@0: const char16_t* aData) michael@0: { michael@0: MOZ_ASSERT(NS_IsMainThread()); michael@0: MOZ_ASSERT(!strcmp(aTopic, "xpcom-shutdown")); michael@0: michael@0: XRE_GetIOMessageLoop()->PostTask( michael@0: FROM_HERE, michael@0: NewRunnableMethod(this, &FdWatcher::StopWatching)); michael@0: michael@0: return NS_OK; michael@0: } michael@0: }; michael@0: michael@0: typedef void (* FifoCallback)(const nsCString& inputStr); michael@0: struct FifoInfo { michael@0: nsCString mCommand; michael@0: FifoCallback mCallback; michael@0: }; michael@0: typedef nsTArray FifoInfoArray; michael@0: michael@0: class FifoWatcher : public FdWatcher michael@0: { michael@0: public: michael@0: /** michael@0: * The name of the preference used to enable/disable the FifoWatcher. michael@0: */ michael@0: static const char* const kPrefName; michael@0: michael@0: static FifoWatcher* GetSingleton(); michael@0: michael@0: static bool MaybeCreate(); michael@0: michael@0: void RegisterCallback(const nsCString& aCommand, FifoCallback aCallback); michael@0: michael@0: virtual ~FifoWatcher(); michael@0: michael@0: virtual int OpenFd(); michael@0: michael@0: virtual void OnFileCanReadWithoutBlocking(int aFd); michael@0: michael@0: private: michael@0: nsAutoCString mDirPath; michael@0: michael@0: static StaticRefPtr sSingleton; michael@0: michael@0: FifoWatcher(nsCString aPath) michael@0: : mDirPath(aPath) michael@0: , mFifoInfoLock("FifoWatcher.mFifoInfoLock") michael@0: {} michael@0: michael@0: mozilla::Mutex mFifoInfoLock; // protects mFifoInfo michael@0: FifoInfoArray mFifoInfo; michael@0: }; michael@0: michael@0: typedef void (* PipeCallback)(const uint8_t recvSig); michael@0: struct SignalInfo { michael@0: uint8_t mSignal; michael@0: PipeCallback mCallback; michael@0: }; michael@0: typedef nsTArray SignalInfoArray; michael@0: michael@0: class SignalPipeWatcher : public FdWatcher michael@0: { michael@0: public: michael@0: static SignalPipeWatcher* GetSingleton(); michael@0: michael@0: void RegisterCallback(uint8_t aSignal, PipeCallback aCallback); michael@0: michael@0: void RegisterSignalHandler(uint8_t aSignal = 0); michael@0: michael@0: virtual ~SignalPipeWatcher(); michael@0: michael@0: virtual int OpenFd(); michael@0: michael@0: virtual void StopWatching(); michael@0: michael@0: virtual void OnFileCanReadWithoutBlocking(int aFd); michael@0: michael@0: private: michael@0: static StaticRefPtr sSingleton; michael@0: michael@0: SignalPipeWatcher() michael@0: : mSignalInfoLock("SignalPipeWatcher.mSignalInfoLock") michael@0: { michael@0: MOZ_ASSERT(NS_IsMainThread()); michael@0: } michael@0: michael@0: mozilla::Mutex mSignalInfoLock; // protects mSignalInfo michael@0: SignalInfoArray mSignalInfo; michael@0: }; michael@0: michael@0: #endif // XP_UNIX } michael@0: michael@0: michael@0: class nsDumpUtils michael@0: { michael@0: public: michael@0: /** michael@0: * This function creates a new unique file based on |aFilename| in a michael@0: * world-readable temp directory. This is the system temp directory michael@0: * or, in the case of Android, the downloads directory. If |aFile| is michael@0: * non-null, it is assumed to point to a folder, and that folder is used michael@0: * instead. michael@0: */ michael@0: static nsresult OpenTempFile(const nsACString& aFilename, michael@0: nsIFile** aFile, michael@0: const nsACString& aFoldername = EmptyCString()); michael@0: }; michael@0: michael@0: #endif