/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ #include "SandboxTestingChild.h" #include "SandboxTestingThread.h" #include "nsXULAppAPI.h" #ifdef XP_UNIX # include # include # include # include # include #endif namespace mozilla { SandboxTestingChild* SandboxTestingChild::sInstance = nullptr; bool SandboxTestingChild::IsTestThread() { return mThread->IsOnThread(); } void SandboxTestingChild::PostToTestThread( already_AddRefed&& runnable) { mThread->Dispatch(std::move(runnable)); } /* static */ bool SandboxTestingChild::Initialize( Endpoint&& aSandboxTestingEndpoint) { MOZ_ASSERT(!sInstance); SandboxTestingThread* thread = SandboxTestingThread::Create(); if (!thread) { return false; } sInstance = new SandboxTestingChild(thread, std::move(aSandboxTestingEndpoint)); return true; } /* static */ SandboxTestingChild* SandboxTestingChild::GetInstance() { MOZ_ASSERT(sInstance, "Must initialize SandboxTestingChild before using it"); return sInstance; } SandboxTestingChild::SandboxTestingChild( SandboxTestingThread* aThread, Endpoint&& aEndpoint) : mThread(aThread) { MOZ_ASSERT(aThread); PostToTestThread(NewNonOwningRunnableMethod&&>( "SandboxTestingChild::Bind", this, &SandboxTestingChild::Bind, std::move(aEndpoint))); } void SandboxTestingChild::Bind(Endpoint&& aEndpoint) { MOZ_RELEASE_ASSERT(mThread->IsOnThread()); DebugOnly ok = aEndpoint.Bind(this); MOZ_ASSERT(ok); if (XRE_IsContentProcess()) { #ifdef XP_UNIX struct stat st; static const char kAllowedPath[] = "/usr/lib"; ErrnoTest("fstatat_as_stat"_ns, true, [&] { return fstatat(AT_FDCWD, kAllowedPath, &st, 0); }); ErrnoTest("fstatat_as_lstat"_ns, true, [&] { return fstatat(AT_FDCWD, kAllowedPath, &st, AT_SYMLINK_NOFOLLOW); }); # ifdef XP_LINUX ErrnoTest("fstatat_as_fstat"_ns, true, [&] { return fstatat(0, "", &st, AT_EMPTY_PATH); }); # endif // XP_LINUX const struct timespec usec = {0, 1000}; ErrnoTest("nanosleep"_ns, true, [&] { return nanosleep(&usec, nullptr); }); struct timespec res = {0, 0}; ErrnoTest("clock_getres"_ns, true, [&] { return clock_getres(CLOCK_REALTIME, &res); }); #else // XP_UNIX SendReportTestResults("dummy_test"_ns, /* shouldSucceed */ true, /* didSucceed */ true, "The test framework fails if there are no cases."_ns); #endif // XP_UNIX } // Tell SandboxTest that this process is done with all tests. SendTestCompleted(); } void SandboxTestingChild::ActorDestroy(ActorDestroyReason aWhy) { MOZ_ASSERT(mThread->IsOnThread()); NS_DispatchToMainThread(NS_NewRunnableFunction( "SandboxChildDestroyer", []() { SandboxTestingChild::Destroy(); })); } void SandboxTestingChild::Destroy() { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(sInstance); delete sInstance; sInstance = nullptr; } bool SandboxTestingChild::RecvShutDown() { Close(); return true; } #ifdef XP_UNIX template void SandboxTestingChild::ErrnoTest(const nsCString& aName, bool aExpectSuccess, F&& aFunction) { int status = aFunction() >= 0 ? 0 : errno; PosixTest(aName, aExpectSuccess, status); } void SandboxTestingChild::PosixTest(const nsCString& aName, bool aExpectSuccess, int aStatus) { bool succeeded = aStatus == 0; nsAutoCString message; if (succeeded) { message = "Succeeded"_ns; } else { message.AppendPrintf("Error: %s", strerror(aStatus)); } SendReportTestResults(aName, aExpectSuccess, succeeded, message); } #endif // XP_UNIX } // namespace mozilla