IOThread.cpp (3432B)
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 #include "mozilla/ipc/IOThread.h" 8 #include "mozilla/ipc/NodeController.h" 9 #include "mozilla/Preferences.h" 10 11 #if defined(XP_WIN) 12 # include <objbase.h> 13 #endif 14 15 #if defined(XP_WIN) 16 # include "chrome/common/ipc_channel_win.h" 17 #else 18 # if defined(XP_DARWIN) 19 # include "chrome/common/ipc_channel_mach.h" 20 # endif 21 # include "chrome/common/ipc_channel_posix.h" 22 #endif 23 24 namespace mozilla { 25 namespace ipc { 26 27 // 28 // IOThread 29 // 30 31 /* static */ 32 IOThread* IOThread::sSingleton = nullptr; 33 34 IOThread::IOThread(const char* aName) : base::Thread(aName) { 35 sSingleton = this; 36 } 37 38 IOThread::~IOThread() { 39 MOZ_ASSERT(!IsRunning()); 40 sSingleton = nullptr; 41 } 42 43 void IOThread::Startup() { 44 if (XRE_IsParentProcess()) { 45 // Destroyed in IOThread::Shutdown 46 auto* thread = new IOThreadParent(); 47 MOZ_RELEASE_ASSERT(thread == sSingleton); 48 } 49 MOZ_ASSERT(sSingleton); 50 } 51 52 void IOThread::Shutdown() { 53 if (XRE_IsParentProcess()) { 54 delete static_cast<IOThreadParent*>(sSingleton); 55 MOZ_ASSERT(!sSingleton); 56 } 57 } 58 59 void IOThread::StartThread() { 60 // Failure to create the IPC I/O thread is unrecoverable. 61 // NOTE: This will block if successful for the `Init()` virtual method to have 62 // been run. 63 if (!StartWithOptions( 64 base::Thread::Options{MessageLoop::TYPE_IO, /* stack size */ 0})) { 65 MOZ_CRASH("Failed to create IPC I/O Thread"); 66 } 67 } 68 69 void IOThread::StopThread() { 70 // This will block until CleanUp() has been called, and the IPC I/O thread has 71 // been joined. 72 Stop(); 73 } 74 75 // 76 // IOThreadParent 77 // 78 79 IOThreadParent::IOThreadParent() : IOThread("IPC I/O Parent") { 80 MOZ_RELEASE_ASSERT(XRE_IsParentProcess()); 81 82 // Select which type of channel will be used for IPC. 83 mChannelKind = [] { 84 #if defined(XP_WIN) 85 return &IPC::ChannelWin::sKind; 86 #else 87 # if defined(XP_DARWIN) 88 if (Preferences::GetBool("dom.ipc.backend.mach")) { 89 return &IPC::ChannelMach::sKind; 90 } 91 # endif 92 return &IPC::ChannelPosix::sKind; 93 #endif 94 }(); 95 96 StartThread(); 97 } 98 99 IOThreadParent::~IOThreadParent() { StopThread(); } 100 101 void IOThreadParent::Init() { 102 #if defined(XP_WIN) 103 // Initializes the COM library on the current thread. 104 CoInitialize(nullptr); 105 #endif 106 107 // Initialize the ports library in the current thread. 108 NodeController::InitBrokerProcess(mChannelKind); 109 } 110 111 void IOThreadParent::CleanUp() { 112 NodeController::CleanUp(); 113 114 #if defined(XP_WIN) 115 // Closes the COM library on the current thread. CoInitialize must 116 // be balanced by a corresponding call to CoUninitialize. 117 CoUninitialize(); 118 #endif 119 } 120 121 // 122 // IOThreadChild 123 // 124 125 IOThreadChild::IOThreadChild(IPC::Channel::ChannelHandle aClientHandle, 126 base::ProcessId aParentPid) 127 : IOThread("IPC I/O Child"), 128 mClientHandle(std::move(aClientHandle)), 129 mParentPid(std::move(aParentPid)) { 130 StartThread(); 131 } 132 133 IOThreadChild::~IOThreadChild() { StopThread(); } 134 135 void IOThreadChild::Init() { 136 mInitialPort = 137 NodeController::InitChildProcess(std::move(mClientHandle), mParentPid); 138 } 139 140 void IOThreadChild::CleanUp() { NodeController::CleanUp(); } 141 142 } // namespace ipc 143 } // namespace mozilla