Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 4 | |
michael@0 | 5 | #ifndef __IPC_GLUE_GECKOCHILDPROCESSHOST_H__ |
michael@0 | 6 | #define __IPC_GLUE_GECKOCHILDPROCESSHOST_H__ |
michael@0 | 7 | |
michael@0 | 8 | #include "base/file_path.h" |
michael@0 | 9 | #include "base/process_util.h" |
michael@0 | 10 | #include "base/scoped_ptr.h" |
michael@0 | 11 | #include "base/waitable_event.h" |
michael@0 | 12 | #include "chrome/common/child_process_host.h" |
michael@0 | 13 | |
michael@0 | 14 | #include "mozilla/DebugOnly.h" |
michael@0 | 15 | #include "mozilla/ipc/FileDescriptor.h" |
michael@0 | 16 | #include "mozilla/Monitor.h" |
michael@0 | 17 | #include "mozilla/StaticPtr.h" |
michael@0 | 18 | |
michael@0 | 19 | #include "nsCOMPtr.h" |
michael@0 | 20 | #include "nsXULAppAPI.h" // for GeckoProcessType |
michael@0 | 21 | #include "nsString.h" |
michael@0 | 22 | |
michael@0 | 23 | class nsIFile; |
michael@0 | 24 | |
michael@0 | 25 | namespace mozilla { |
michael@0 | 26 | namespace ipc { |
michael@0 | 27 | |
michael@0 | 28 | class GeckoChildProcessHost : public ChildProcessHost |
michael@0 | 29 | { |
michael@0 | 30 | protected: |
michael@0 | 31 | typedef mozilla::Monitor Monitor; |
michael@0 | 32 | typedef std::vector<std::string> StringVector; |
michael@0 | 33 | |
michael@0 | 34 | public: |
michael@0 | 35 | typedef base::ChildPrivileges ChildPrivileges; |
michael@0 | 36 | typedef base::ProcessHandle ProcessHandle; |
michael@0 | 37 | |
michael@0 | 38 | static ChildPrivileges DefaultChildPrivileges(); |
michael@0 | 39 | |
michael@0 | 40 | GeckoChildProcessHost(GeckoProcessType aProcessType, |
michael@0 | 41 | ChildPrivileges aPrivileges=base::PRIVILEGES_DEFAULT); |
michael@0 | 42 | |
michael@0 | 43 | ~GeckoChildProcessHost(); |
michael@0 | 44 | |
michael@0 | 45 | static nsresult GetArchitecturesForBinary(const char *path, uint32_t *result); |
michael@0 | 46 | |
michael@0 | 47 | static uint32_t GetSupportedArchitecturesForProcessType(GeckoProcessType type); |
michael@0 | 48 | |
michael@0 | 49 | // Block until the IPC channel for our subprocess is initialized, |
michael@0 | 50 | // but no longer. The child process may or may not have been |
michael@0 | 51 | // created when this method returns. |
michael@0 | 52 | bool AsyncLaunch(StringVector aExtraOpts=StringVector()); |
michael@0 | 53 | |
michael@0 | 54 | // Block until the IPC channel for our subprocess is initialized and |
michael@0 | 55 | // the OS process is created. The subprocess may or may not have |
michael@0 | 56 | // connected back to us when this method returns. |
michael@0 | 57 | // |
michael@0 | 58 | // NB: on POSIX, this method is relatively cheap, and doesn't |
michael@0 | 59 | // require disk IO. On win32 however, it requires at least the |
michael@0 | 60 | // analogue of stat(). This difference induces a semantic |
michael@0 | 61 | // difference in this method: on POSIX, when we return, we know the |
michael@0 | 62 | // subprocess has been created, but we don't know whether its |
michael@0 | 63 | // executable image can be loaded. On win32, we do know that when |
michael@0 | 64 | // we return. But we don't know if dynamic linking succeeded on |
michael@0 | 65 | // either platform. |
michael@0 | 66 | bool LaunchAndWaitForProcessHandle(StringVector aExtraOpts=StringVector()); |
michael@0 | 67 | |
michael@0 | 68 | // Block until the child process has been created and it connects to |
michael@0 | 69 | // the IPC channel, meaning it's fully initialized. (Or until an |
michael@0 | 70 | // error occurs.) |
michael@0 | 71 | bool SyncLaunch(StringVector aExtraOpts=StringVector(), |
michael@0 | 72 | int32_t timeoutMs=0, |
michael@0 | 73 | base::ProcessArchitecture arch=base::GetCurrentProcessArchitecture()); |
michael@0 | 74 | |
michael@0 | 75 | virtual bool PerformAsyncLaunch(StringVector aExtraOpts=StringVector(), |
michael@0 | 76 | base::ProcessArchitecture aArch=base::GetCurrentProcessArchitecture()); |
michael@0 | 77 | |
michael@0 | 78 | virtual void OnChannelConnected(int32_t peer_pid); |
michael@0 | 79 | virtual void OnMessageReceived(const IPC::Message& aMsg); |
michael@0 | 80 | virtual void OnChannelError(); |
michael@0 | 81 | virtual void GetQueuedMessages(std::queue<IPC::Message>& queue); |
michael@0 | 82 | |
michael@0 | 83 | virtual void InitializeChannel(); |
michael@0 | 84 | |
michael@0 | 85 | virtual bool CanShutdown() { return true; } |
michael@0 | 86 | |
michael@0 | 87 | virtual void OnWaitableEventSignaled(base::WaitableEvent *event); |
michael@0 | 88 | |
michael@0 | 89 | IPC::Channel* GetChannel() { |
michael@0 | 90 | return channelp(); |
michael@0 | 91 | } |
michael@0 | 92 | |
michael@0 | 93 | base::WaitableEvent* GetShutDownEvent() { |
michael@0 | 94 | return GetProcessEvent(); |
michael@0 | 95 | } |
michael@0 | 96 | |
michael@0 | 97 | // Returns a "borrowed" handle to the child process - the handle returned |
michael@0 | 98 | // by this function must not be closed by the caller. |
michael@0 | 99 | ProcessHandle GetChildProcessHandle() { |
michael@0 | 100 | return mChildProcessHandle; |
michael@0 | 101 | } |
michael@0 | 102 | |
michael@0 | 103 | // Returns an "owned" handle to the child process - the handle returned |
michael@0 | 104 | // by this function must be closed by the caller. |
michael@0 | 105 | ProcessHandle GetOwnedChildProcessHandle() { |
michael@0 | 106 | ProcessHandle handle; |
michael@0 | 107 | // We use OpenPrivilegedProcessHandle as that is where our |
michael@0 | 108 | // mChildProcessHandle initially came from. |
michael@0 | 109 | bool ok = base::OpenPrivilegedProcessHandle(base::GetProcId(mChildProcessHandle), |
michael@0 | 110 | &handle); |
michael@0 | 111 | NS_ASSERTION(ok, "Failed to get owned process handle"); |
michael@0 | 112 | return ok ? handle : 0; |
michael@0 | 113 | } |
michael@0 | 114 | |
michael@0 | 115 | GeckoProcessType GetProcessType() { |
michael@0 | 116 | return mProcessType; |
michael@0 | 117 | } |
michael@0 | 118 | |
michael@0 | 119 | #ifdef XP_MACOSX |
michael@0 | 120 | task_t GetChildTask() { |
michael@0 | 121 | return mChildTask; |
michael@0 | 122 | } |
michael@0 | 123 | #endif |
michael@0 | 124 | |
michael@0 | 125 | /** |
michael@0 | 126 | * Must run on the IO thread. Cause the OS process to exit and |
michael@0 | 127 | * ensure its OS resources are cleaned up. |
michael@0 | 128 | */ |
michael@0 | 129 | void Join(); |
michael@0 | 130 | |
michael@0 | 131 | // For bug 943174: Skip the EnsureProcessTerminated call in the destructor. |
michael@0 | 132 | void SetAlreadyDead(); |
michael@0 | 133 | |
michael@0 | 134 | void SetSandboxEnabled(bool aSandboxEnabled) { |
michael@0 | 135 | mSandboxEnabled = aSandboxEnabled; |
michael@0 | 136 | } |
michael@0 | 137 | |
michael@0 | 138 | protected: |
michael@0 | 139 | GeckoProcessType mProcessType; |
michael@0 | 140 | bool mSandboxEnabled; |
michael@0 | 141 | ChildPrivileges mPrivileges; |
michael@0 | 142 | Monitor mMonitor; |
michael@0 | 143 | FilePath mProcessPath; |
michael@0 | 144 | |
michael@0 | 145 | // This value must be accessed while holding mMonitor. |
michael@0 | 146 | enum { |
michael@0 | 147 | // This object has been constructed, but the OS process has not |
michael@0 | 148 | // yet. |
michael@0 | 149 | CREATING_CHANNEL = 0, |
michael@0 | 150 | // The IPC channel for our subprocess has been created, but the OS |
michael@0 | 151 | // process has still not been created. |
michael@0 | 152 | CHANNEL_INITIALIZED, |
michael@0 | 153 | // The OS process has been created, but it hasn't yet connected to |
michael@0 | 154 | // our IPC channel. |
michael@0 | 155 | PROCESS_CREATED, |
michael@0 | 156 | // The process is launched and connected to our IPC channel. All |
michael@0 | 157 | // is well. |
michael@0 | 158 | PROCESS_CONNECTED, |
michael@0 | 159 | PROCESS_ERROR |
michael@0 | 160 | } mProcessState; |
michael@0 | 161 | |
michael@0 | 162 | static int32_t mChildCounter; |
michael@0 | 163 | |
michael@0 | 164 | void PrepareLaunch(); |
michael@0 | 165 | |
michael@0 | 166 | #ifdef XP_WIN |
michael@0 | 167 | void InitWindowsGroupID(); |
michael@0 | 168 | nsString mGroupId; |
michael@0 | 169 | #endif |
michael@0 | 170 | |
michael@0 | 171 | #if defined(OS_POSIX) |
michael@0 | 172 | base::file_handle_mapping_vector mFileMap; |
michael@0 | 173 | #endif |
michael@0 | 174 | |
michael@0 | 175 | base::WaitableEventWatcher::Delegate* mDelegate; |
michael@0 | 176 | |
michael@0 | 177 | ProcessHandle mChildProcessHandle; |
michael@0 | 178 | #if defined(OS_MACOSX) |
michael@0 | 179 | task_t mChildTask; |
michael@0 | 180 | #endif |
michael@0 | 181 | |
michael@0 | 182 | void OpenPrivilegedHandle(base::ProcessId aPid); |
michael@0 | 183 | |
michael@0 | 184 | private: |
michael@0 | 185 | DISALLOW_EVIL_CONSTRUCTORS(GeckoChildProcessHost); |
michael@0 | 186 | |
michael@0 | 187 | // Does the actual work for AsyncLaunch, on the IO thread. |
michael@0 | 188 | bool PerformAsyncLaunchInternal(std::vector<std::string>& aExtraOpts, |
michael@0 | 189 | base::ProcessArchitecture arch); |
michael@0 | 190 | |
michael@0 | 191 | bool RunPerformAsyncLaunch(StringVector aExtraOpts=StringVector(), |
michael@0 | 192 | base::ProcessArchitecture aArch=base::GetCurrentProcessArchitecture()); |
michael@0 | 193 | |
michael@0 | 194 | static void GetPathToBinary(FilePath& exePath); |
michael@0 | 195 | static void CacheGreDir(); |
michael@0 | 196 | |
michael@0 | 197 | // In between launching the subprocess and handing off its IPC |
michael@0 | 198 | // channel, there's a small window of time in which *we* might still |
michael@0 | 199 | // be the channel listener, and receive messages. That's bad |
michael@0 | 200 | // because we have no idea what to do with those messages. So queue |
michael@0 | 201 | // them here until we hand off the eventual listener. |
michael@0 | 202 | // |
michael@0 | 203 | // FIXME/cjones: this strongly indicates bad design. Shame on us. |
michael@0 | 204 | std::queue<IPC::Message> mQueue; |
michael@0 | 205 | |
michael@0 | 206 | static StaticRefPtr<nsIFile> sGreDir; |
michael@0 | 207 | static DebugOnly<bool> sGreDirCached; |
michael@0 | 208 | }; |
michael@0 | 209 | |
michael@0 | 210 | #ifdef MOZ_NUWA_PROCESS |
michael@0 | 211 | class GeckoExistingProcessHost MOZ_FINAL : public GeckoChildProcessHost |
michael@0 | 212 | { |
michael@0 | 213 | public: |
michael@0 | 214 | GeckoExistingProcessHost(GeckoProcessType aProcessType, |
michael@0 | 215 | base::ProcessHandle aProcess, |
michael@0 | 216 | const FileDescriptor& aFileDescriptor, |
michael@0 | 217 | ChildPrivileges aPrivileges=base::PRIVILEGES_DEFAULT); |
michael@0 | 218 | |
michael@0 | 219 | ~GeckoExistingProcessHost(); |
michael@0 | 220 | |
michael@0 | 221 | virtual bool PerformAsyncLaunch(StringVector aExtraOpts=StringVector(), |
michael@0 | 222 | base::ProcessArchitecture aArch=base::GetCurrentProcessArchitecture()) MOZ_OVERRIDE; |
michael@0 | 223 | |
michael@0 | 224 | virtual void InitializeChannel() MOZ_OVERRIDE; |
michael@0 | 225 | |
michael@0 | 226 | private: |
michael@0 | 227 | base::ProcessHandle mExistingProcessHandle; |
michael@0 | 228 | mozilla::ipc::FileDescriptor mExistingFileDescriptor; |
michael@0 | 229 | }; |
michael@0 | 230 | #endif /* MOZ_NUWA_PROCESS */ |
michael@0 | 231 | |
michael@0 | 232 | } /* namespace ipc */ |
michael@0 | 233 | } /* namespace mozilla */ |
michael@0 | 234 | |
michael@0 | 235 | #endif /* __IPC_GLUE_GECKOCHILDPROCESSHOST_H__ */ |