forked from mirrors/gecko-dev
Bug 1519636 - Reformat recent changes to the Google coding style r=Ehsan
# ignore-this-changeset Differential Revision: https://phabricator.services.mozilla.com/D58175 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
4a2545c164
commit
c521758c5e
52 changed files with 793 additions and 843 deletions
|
|
@ -31,7 +31,7 @@ class PresShell;
|
||||||
namespace dom {
|
namespace dom {
|
||||||
class DOMStringList;
|
class DOMStringList;
|
||||||
class Element;
|
class Element;
|
||||||
}
|
} // namespace dom
|
||||||
|
|
||||||
namespace a11y {
|
namespace a11y {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -262,7 +262,7 @@ int main(int argc, char* argv[], char* envp[]) {
|
||||||
// argc & argv will be updated with the values passing from the
|
// argc & argv will be updated with the values passing from the
|
||||||
// chrome process. With the new values, this function
|
// chrome process. With the new values, this function
|
||||||
// continues the reset of the code acting as a content process.
|
// continues the reset of the code acting as a content process.
|
||||||
if(gBootstrap->XRE_ForkServer(&argc, &argv)) {
|
if (gBootstrap->XRE_ForkServer(&argc, &argv)) {
|
||||||
// Return from the fork server in the fork server process.
|
// Return from the fork server in the fork server process.
|
||||||
// Stop the fork server.
|
// Stop the fork server.
|
||||||
gBootstrap->NS_LogTerm();
|
gBootstrap->NS_LogTerm();
|
||||||
|
|
|
||||||
|
|
@ -65,11 +65,11 @@ LauncherVoidResultWithLineInfo InitializeDllBlocklistOOP(
|
||||||
// safely make its ntdll calls.
|
// safely make its ntdll calls.
|
||||||
|
|
||||||
HMODULE ourModule;
|
HMODULE ourModule;
|
||||||
#if defined(_MSC_VER)
|
# if defined(_MSC_VER)
|
||||||
ourModule = reinterpret_cast<HMODULE>(&__ImageBase);
|
ourModule = reinterpret_cast<HMODULE>(&__ImageBase);
|
||||||
#else
|
# else
|
||||||
ourModule = ::GetModuleHandleW(nullptr);
|
ourModule = ::GetModuleHandleW(nullptr);
|
||||||
#endif // defined(_MSC_VER)
|
# endif // defined(_MSC_VER)
|
||||||
|
|
||||||
mozilla::nt::PEHeaders ourExeImage(ourModule);
|
mozilla::nt::PEHeaders ourExeImage(ourModule);
|
||||||
if (!ourExeImage) {
|
if (!ourExeImage) {
|
||||||
|
|
@ -84,7 +84,7 @@ LauncherVoidResultWithLineInfo InitializeDllBlocklistOOP(
|
||||||
return importDirRestored;
|
return importDirRestored;
|
||||||
}
|
}
|
||||||
|
|
||||||
Maybe<Span<IMAGE_THUNK_DATA>> ntdllThunks =
|
Maybe<Span<IMAGE_THUNK_DATA> > ntdllThunks =
|
||||||
ourExeImage.GetIATThunksForModule("ntdll.dll");
|
ourExeImage.GetIATThunksForModule("ntdll.dll");
|
||||||
if (!ntdllThunks) {
|
if (!ntdllThunks) {
|
||||||
return LAUNCHER_ERROR_FROM_WIN32(ERROR_INVALID_DATA);
|
return LAUNCHER_ERROR_FROM_WIN32(ERROR_INVALID_DATA);
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,12 @@ class ContentPrincipal final : public BasePrincipal {
|
||||||
|
|
||||||
virtual nsresult PopulateJSONObject(Json::Value& aObject) override;
|
virtual nsresult PopulateJSONObject(Json::Value& aObject) override;
|
||||||
// Serializable keys are the valid enum fields the serialization supports
|
// Serializable keys are the valid enum fields the serialization supports
|
||||||
enum SerializableKeys : uint8_t { eURI = 0, eDomain, eSuffix, eMax = eSuffix };
|
enum SerializableKeys : uint8_t {
|
||||||
|
eURI = 0,
|
||||||
|
eDomain,
|
||||||
|
eSuffix,
|
||||||
|
eMax = eSuffix
|
||||||
|
};
|
||||||
typedef mozilla::BasePrincipal::KeyValT<SerializableKeys> KeyVal;
|
typedef mozilla::BasePrincipal::KeyValT<SerializableKeys> KeyVal;
|
||||||
|
|
||||||
static already_AddRefed<BasePrincipal> FromProperties(
|
static already_AddRefed<BasePrincipal> FromProperties(
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,6 @@ namespace dom {
|
||||||
|
|
||||||
class ChildSHistory : public nsISupports, public nsWrapperCache {
|
class ChildSHistory : public nsISupports, public nsWrapperCache {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ChildSHistory)
|
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ChildSHistory)
|
||||||
nsISupports* GetParentObject() const;
|
nsISupports* GetParentObject() const;
|
||||||
|
|
|
||||||
|
|
@ -615,9 +615,9 @@ ScreenOrientation::VisibleEventListener::HandleEvent(Event* aEvent) {
|
||||||
|
|
||||||
BrowsingContext* bc = doc->GetBrowsingContext();
|
BrowsingContext* bc = doc->GetBrowsingContext();
|
||||||
if (bc && bc->GetCurrentOrientationType() !=
|
if (bc && bc->GetCurrentOrientationType() !=
|
||||||
orientation->DeviceType(CallerType::System)) {
|
orientation->DeviceType(CallerType::System)) {
|
||||||
bc->SetCurrentOrientation(orientation->DeviceType(CallerType::System),
|
bc->SetCurrentOrientation(orientation->DeviceType(CallerType::System),
|
||||||
orientation->DeviceAngle(CallerType::System));
|
orientation->DeviceAngle(CallerType::System));
|
||||||
|
|
||||||
nsCOMPtr<nsIRunnable> runnable =
|
nsCOMPtr<nsIRunnable> runnable =
|
||||||
orientation->DispatchChangeEventAndResolvePromise();
|
orientation->DispatchChangeEventAndResolvePromise();
|
||||||
|
|
|
||||||
|
|
@ -188,19 +188,19 @@ class Optional : public Optional_base<T, T> {
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class Optional<JS::Handle<T> >
|
class Optional<JS::Handle<T>>
|
||||||
: public Optional_base<JS::Handle<T>, JS::Rooted<T> > {
|
: public Optional_base<JS::Handle<T>, JS::Rooted<T>> {
|
||||||
public:
|
public:
|
||||||
MOZ_ALLOW_TEMPORARY Optional()
|
MOZ_ALLOW_TEMPORARY Optional()
|
||||||
: Optional_base<JS::Handle<T>, JS::Rooted<T> >() {}
|
: Optional_base<JS::Handle<T>, JS::Rooted<T>>() {}
|
||||||
|
|
||||||
explicit Optional(JSContext* cx)
|
explicit Optional(JSContext* cx)
|
||||||
: Optional_base<JS::Handle<T>, JS::Rooted<T> >() {
|
: Optional_base<JS::Handle<T>, JS::Rooted<T>>() {
|
||||||
this->Construct(cx);
|
this->Construct(cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional(JSContext* cx, const T& aValue)
|
Optional(JSContext* cx, const T& aValue)
|
||||||
: Optional_base<JS::Handle<T>, JS::Rooted<T> >(cx, aValue) {}
|
: Optional_base<JS::Handle<T>, JS::Rooted<T>>(cx, aValue) {}
|
||||||
|
|
||||||
// Override the const Value() to return the right thing so we're not
|
// Override the const Value() to return the right thing so we're not
|
||||||
// returning references to temporaries.
|
// returning references to temporaries.
|
||||||
|
|
@ -249,7 +249,7 @@ class Optional<JS::Value> {
|
||||||
template <typename U>
|
template <typename U>
|
||||||
class NonNull;
|
class NonNull;
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class Optional<NonNull<T> > : public Optional_base<T, NonNull<T> > {
|
class Optional<NonNull<T>> : public Optional_base<T, NonNull<T>> {
|
||||||
public:
|
public:
|
||||||
// We want our Value to actually return a non-const reference, even
|
// We want our Value to actually return a non-const reference, even
|
||||||
// if we're const. At least for things that are normally pointer
|
// if we're const. At least for things that are normally pointer
|
||||||
|
|
@ -264,7 +264,7 @@ class Optional<NonNull<T> > : public Optional_base<T, NonNull<T> > {
|
||||||
// A specialization of Optional for OwningNonNull that lets us get a
|
// A specialization of Optional for OwningNonNull that lets us get a
|
||||||
// T& from Value()
|
// T& from Value()
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class Optional<OwningNonNull<T> > : public Optional_base<T, OwningNonNull<T> > {
|
class Optional<OwningNonNull<T>> : public Optional_base<T, OwningNonNull<T>> {
|
||||||
public:
|
public:
|
||||||
// We want our Value to actually return a non-const reference, even
|
// We want our Value to actually return a non-const reference, even
|
||||||
// if we're const. At least for things that are normally pointer
|
// if we're const. At least for things that are normally pointer
|
||||||
|
|
@ -412,8 +412,10 @@ template <typename T>
|
||||||
class Sequence : public FallibleTArray<T> {
|
class Sequence : public FallibleTArray<T> {
|
||||||
public:
|
public:
|
||||||
Sequence() : FallibleTArray<T>() {}
|
Sequence() : FallibleTArray<T>() {}
|
||||||
MOZ_IMPLICIT Sequence(FallibleTArray<T>&& aArray) : FallibleTArray<T>(std::move(aArray)) {}
|
MOZ_IMPLICIT Sequence(FallibleTArray<T>&& aArray)
|
||||||
MOZ_IMPLICIT Sequence(nsTArray<T>&& aArray) : FallibleTArray<T>(std::move(aArray)) {}
|
: FallibleTArray<T>(std::move(aArray)) {}
|
||||||
|
MOZ_IMPLICIT Sequence(nsTArray<T>&& aArray)
|
||||||
|
: FallibleTArray<T>(std::move(aArray)) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline nsWrapperCache* GetWrapperCache(nsWrapperCache* cache) { return cache; }
|
inline nsWrapperCache* GetWrapperCache(nsWrapperCache* cache) { return cache; }
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,8 @@ class WrapperCachedNonISupportsTestInterface final : public nsWrapperCache {
|
||||||
public:
|
public:
|
||||||
WrapperCachedNonISupportsTestInterface() {}
|
WrapperCachedNonISupportsTestInterface() {}
|
||||||
|
|
||||||
static already_AddRefed<WrapperCachedNonISupportsTestInterface> Constructor(const GlobalObject& aGlobalObject);
|
static already_AddRefed<WrapperCachedNonISupportsTestInterface> Constructor(
|
||||||
|
const GlobalObject& aGlobalObject);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
~WrapperCachedNonISupportsTestInterface() {}
|
~WrapperCachedNonISupportsTestInterface() {}
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,8 @@ class LSSnapshotInitInfo;
|
||||||
class LSWriteAndNotifyInfo;
|
class LSWriteAndNotifyInfo;
|
||||||
class SnapshotWriteOptimizer;
|
class SnapshotWriteOptimizer;
|
||||||
|
|
||||||
template <typename> class Optional;
|
template <typename>
|
||||||
|
class Optional;
|
||||||
|
|
||||||
class LSSnapshot final : public nsIRunnable {
|
class LSSnapshot final : public nsIRunnable {
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,8 @@
|
||||||
class mozIStorageStatement;
|
class mozIStorageStatement;
|
||||||
|
|
||||||
namespace IPC {
|
namespace IPC {
|
||||||
template <typename> struct ParamTraits;
|
template <typename>
|
||||||
|
struct ParamTraits;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
|
||||||
|
|
@ -114,13 +114,14 @@ void FileBlockCache::Flush() {
|
||||||
// Dispatch a task so we won't clear the arrays while PerformBlockIOs() is
|
// Dispatch a task so we won't clear the arrays while PerformBlockIOs() is
|
||||||
// dropping the data lock and cause InvalidArrayIndex.
|
// dropping the data lock and cause InvalidArrayIndex.
|
||||||
RefPtr<FileBlockCache> self = this;
|
RefPtr<FileBlockCache> self = this;
|
||||||
mBackgroundET->Dispatch(NS_NewRunnableFunction("FileBlockCache::Flush", [self]() {
|
mBackgroundET->Dispatch(
|
||||||
MutexAutoLock mon(self->mDataMutex);
|
NS_NewRunnableFunction("FileBlockCache::Flush", [self]() {
|
||||||
// Just discard pending changes, assume MediaCache won't read from
|
MutexAutoLock mon(self->mDataMutex);
|
||||||
// blocks it hasn't written to.
|
// Just discard pending changes, assume MediaCache won't read from
|
||||||
self->mChangeIndexList.clear();
|
// blocks it hasn't written to.
|
||||||
self->mBlockChanges.Clear();
|
self->mChangeIndexList.clear();
|
||||||
}));
|
self->mBlockChanges.Clear();
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t FileBlockCache::GetMaxBlocks(size_t aCacheSizeInKB) const {
|
size_t FileBlockCache::GetMaxBlocks(size_t aCacheSizeInKB) const {
|
||||||
|
|
@ -175,18 +176,19 @@ void FileBlockCache::Close() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let the thread close the FD, and then trigger its own shutdown.
|
// Let the thread close the FD, and then trigger its own shutdown.
|
||||||
// Note that mBackgroundET is now empty, so no other task will be posted there.
|
// Note that mBackgroundET is now empty, so no other task will be posted
|
||||||
// Also mBackgroundET and mFD are empty and therefore can be reused immediately.
|
// there. Also mBackgroundET and mFD are empty and therefore can be reused
|
||||||
nsresult rv = thread->Dispatch(
|
// immediately.
|
||||||
NS_NewRunnableFunction(
|
nsresult rv = thread->Dispatch(NS_NewRunnableFunction("FileBlockCache::Close",
|
||||||
"FileBlockCache::Close",
|
[thread, fd] {
|
||||||
[thread, fd] {
|
if (fd) {
|
||||||
if (fd) {
|
CloseFD(fd);
|
||||||
CloseFD(fd);
|
}
|
||||||
}
|
// No need to shutdown
|
||||||
// No need to shutdown background task queues.
|
// background task
|
||||||
}),
|
// queues.
|
||||||
NS_DISPATCH_EVENT_MAY_BLOCK);
|
}),
|
||||||
|
NS_DISPATCH_EVENT_MAY_BLOCK);
|
||||||
NS_ENSURE_SUCCESS_VOID(rv);
|
NS_ENSURE_SUCCESS_VOID(rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -363,8 +363,7 @@ void HLSTrackDemuxer::UpdateMediaInfo(int index) {
|
||||||
audioInfo->mBitDepth = audioInfoObj->BitDepth();
|
audioInfo->mBitDepth = audioInfoObj->BitDepth();
|
||||||
audioInfo->mMimeType =
|
audioInfo->mMimeType =
|
||||||
NS_ConvertUTF16toUTF8(audioInfoObj->MimeType()->ToString());
|
NS_ConvertUTF16toUTF8(audioInfoObj->MimeType()->ToString());
|
||||||
audioInfo->mDuration =
|
audioInfo->mDuration = TimeUnit::FromMicroseconds(audioInfoObj->Duration());
|
||||||
TimeUnit::FromMicroseconds(audioInfoObj->Duration());
|
|
||||||
jni::ByteArray::LocalRef csdBytes = audioInfoObj->CodecSpecificData();
|
jni::ByteArray::LocalRef csdBytes = audioInfoObj->CodecSpecificData();
|
||||||
if (csdBytes) {
|
if (csdBytes) {
|
||||||
auto&& csd = csdBytes->GetElements();
|
auto&& csd = csdBytes->GetElements();
|
||||||
|
|
@ -389,11 +388,9 @@ void HLSTrackDemuxer::UpdateMediaInfo(int index) {
|
||||||
videoInfo->mDisplay.height = videoInfoObj->PictureHeight();
|
videoInfo->mDisplay.height = videoInfoObj->PictureHeight();
|
||||||
videoInfo->mMimeType =
|
videoInfo->mMimeType =
|
||||||
NS_ConvertUTF16toUTF8(videoInfoObj->MimeType()->ToString());
|
NS_ConvertUTF16toUTF8(videoInfoObj->MimeType()->ToString());
|
||||||
videoInfo->mDuration =
|
videoInfo->mDuration = TimeUnit::FromMicroseconds(videoInfoObj->Duration());
|
||||||
TimeUnit::FromMicroseconds(videoInfoObj->Duration());
|
HLS_DEBUG("HLSTrackDemuxer", "Update video info (%d) / I(%dx%d) / D(%dx%d)",
|
||||||
HLS_DEBUG("HLSTrackDemuxer",
|
index, videoInfo->mImage.width, videoInfo->mImage.height,
|
||||||
"Update video info (%d) / I(%dx%d) / D(%dx%d)", index,
|
|
||||||
videoInfo->mImage.width, videoInfo->mImage.height,
|
|
||||||
videoInfo->mDisplay.width, videoInfo->mDisplay.height);
|
videoInfo->mDisplay.width, videoInfo->mDisplay.height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,8 @@ typedef mozilla::Pair<nsCString, mozilla::Maybe<nsString>>
|
||||||
|
|
||||||
class nsContentSecurityUtils {
|
class nsContentSecurityUtils {
|
||||||
public:
|
public:
|
||||||
static FilenameTypeAndDetails FilenameToFilenameType(const nsString& fileName);
|
static FilenameTypeAndDetails FilenameToFilenameType(
|
||||||
|
const nsString& fileName);
|
||||||
static bool IsEvalAllowed(JSContext* cx, bool aIsSystemPrincipal,
|
static bool IsEvalAllowed(JSContext* cx, bool aIsSystemPrincipal,
|
||||||
const nsAString& aScript);
|
const nsAString& aScript);
|
||||||
static void NotifyEvalUsage(bool aIsSystemPrincipal,
|
static void NotifyEvalUsage(bool aIsSystemPrincipal,
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,8 @@ struct ScaleFactors2D {
|
||||||
return ScaleFactor<src, dst>(xScale);
|
return ScaleFactor<src, dst>(xScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
ScaleFactors2D<src, dst>& operator=(const ScaleFactors2D<src, dst>&) = default;
|
ScaleFactors2D<src, dst>& operator=(const ScaleFactors2D<src, dst>&) =
|
||||||
|
default;
|
||||||
|
|
||||||
bool operator==(const ScaleFactors2D<src, dst>& aOther) const {
|
bool operator==(const ScaleFactors2D<src, dst>& aOther) const {
|
||||||
return xScale == aOther.xScale && yScale == aOther.yScale;
|
return xScale == aOther.xScale && yScale == aOther.yScale;
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
#include "mozilla/HashFunctions.h" // for HashGeneric
|
#include "mozilla/HashFunctions.h" // for HashGeneric
|
||||||
#include "mozilla/gfx/Logging.h" // for Log
|
#include "mozilla/gfx/Logging.h" // for Log
|
||||||
#include "mozilla/layers/LayersTypes.h" // for LayersId
|
#include "mozilla/layers/LayersTypes.h" // for LayersId
|
||||||
#include "nsHashKeys.h" // for nsPrintfCString
|
#include "nsHashKeys.h" // for nsPrintfCString
|
||||||
#include "nsPrintfCString.h" // for nsPrintfCString
|
#include "nsPrintfCString.h" // for nsPrintfCString
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,8 @@ class ImageDecoderListener final : public nsIStreamListener,
|
||||||
: mURI(aURI),
|
: mURI(aURI),
|
||||||
mImage(nullptr),
|
mImage(nullptr),
|
||||||
mCallback(aCallback),
|
mCallback(aCallback),
|
||||||
mObserver(aObserver ? new NotificationObserverWrapper(aObserver) : nullptr) {
|
mObserver(aObserver ? new NotificationObserverWrapper(aObserver)
|
||||||
|
: nullptr) {
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,7 @@
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
|
|
||||||
static bool
|
static bool UseForkServer(int argc, char* argv[]) {
|
||||||
UseForkServer(int argc, char* argv[]) {
|
|
||||||
#if defined(MOZ_ENABLE_FORKSERVER)
|
#if defined(MOZ_ENABLE_FORKSERVER)
|
||||||
return strcmp(argv[argc - 1], "forkserver") == 0;
|
return strcmp(argv[argc - 1], "forkserver") == 0;
|
||||||
#else
|
#else
|
||||||
|
|
@ -22,8 +21,8 @@ UseForkServer(int argc, char* argv[]) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int RunForkServer(Bootstrap::UniquePtr&& bootstrap, int argc,
|
||||||
RunForkServer(Bootstrap::UniquePtr&& bootstrap, int argc, char* argv[]) {
|
char* argv[]) {
|
||||||
#if defined(MOZ_ENABLE_FORKSERVER)
|
#if defined(MOZ_ENABLE_FORKSERVER)
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
|
@ -38,7 +37,7 @@ RunForkServer(Bootstrap::UniquePtr&& bootstrap, int argc, char* argv[]) {
|
||||||
// argc & argv will be updated with the values passing from the
|
// argc & argv will be updated with the values passing from the
|
||||||
// chrome process. With the new values, this function
|
// chrome process. With the new values, this function
|
||||||
// continues the reset of the code acting as a content process.
|
// continues the reset of the code acting as a content process.
|
||||||
if(bootstrap->XRE_ForkServer(&argc, &argv)) {
|
if (bootstrap->XRE_ForkServer(&argc, &argv)) {
|
||||||
// Return from the fork server in the fork server process.
|
// Return from the fork server in the fork server process.
|
||||||
// Stop the fork server.
|
// Stop the fork server.
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -44,15 +44,15 @@
|
||||||
#include "mozilla/ipc/EnvironmentMap.h"
|
#include "mozilla/ipc/EnvironmentMap.h"
|
||||||
|
|
||||||
#if defined(MOZ_ENABLE_FORKSERVER)
|
#if defined(MOZ_ENABLE_FORKSERVER)
|
||||||
#include "nsString.h"
|
# include "nsString.h"
|
||||||
#include "mozilla/Tuple.h"
|
# include "mozilla/Tuple.h"
|
||||||
#include "mozilla/ipc/FileDescriptorShuffle.h"
|
# include "mozilla/ipc/FileDescriptorShuffle.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace ipc {
|
namespace ipc {
|
||||||
class FileDescriptor;
|
class FileDescriptor;
|
||||||
}
|
}
|
||||||
}
|
} // namespace mozilla
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(OS_MACOSX)
|
#if defined(OS_MACOSX)
|
||||||
|
|
@ -195,7 +195,7 @@ EnvironmentArray BuildEnvironmentArray(const environment_map& env_vars_to_set);
|
||||||
* and second step, that is why two steps.
|
* and second step, that is why two steps.
|
||||||
*/
|
*/
|
||||||
class AppProcessBuilder {
|
class AppProcessBuilder {
|
||||||
public:
|
public:
|
||||||
AppProcessBuilder();
|
AppProcessBuilder();
|
||||||
// This function will fork a new process for use as a
|
// This function will fork a new process for use as a
|
||||||
// content processes.
|
// content processes.
|
||||||
|
|
@ -209,10 +209,10 @@ public:
|
||||||
// The message loop may allocate resources like file descriptors.
|
// The message loop may allocate resources like file descriptors.
|
||||||
// If this function is called before the end of the loop, the
|
// If this function is called before the end of the loop, the
|
||||||
// reosurces may be destroyed while the loop is still alive.
|
// reosurces may be destroyed while the loop is still alive.
|
||||||
void InitAppProcess(int *argcp, char*** argvp);
|
void InitAppProcess(int* argcp, char*** argvp);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ReplaceArguments(int *argcp, char*** argvp);
|
void ReplaceArguments(int* argcp, char*** argvp);
|
||||||
|
|
||||||
mozilla::ipc::FileDescriptorShuffle shuffle_;
|
mozilla::ipc::FileDescriptorShuffle shuffle_;
|
||||||
std::vector<std::string> argv_;
|
std::vector<std::string> argv_;
|
||||||
|
|
|
||||||
|
|
@ -14,18 +14,18 @@
|
||||||
#include "algorithm"
|
#include "algorithm"
|
||||||
|
|
||||||
#if defined(MOZ_ENABLE_FORKSERVER)
|
#if defined(MOZ_ENABLE_FORKSERVER)
|
||||||
#include <stdlib.h>
|
# include <stdlib.h>
|
||||||
#include <sys/types.h>
|
# include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
# include <sys/stat.h>
|
||||||
#include <fcntl.h>
|
# include <fcntl.h>
|
||||||
# if defined(DEBUG)
|
# if defined(DEBUG)
|
||||||
#include "base/message_loop.h"
|
# include "base/message_loop.h"
|
||||||
# endif
|
# endif
|
||||||
#include "mozilla/DebugOnly.h"
|
# include "mozilla/DebugOnly.h"
|
||||||
#include "mozilla/ipc/ForkServiceChild.h"
|
# include "mozilla/ipc/ForkServiceChild.h"
|
||||||
|
|
||||||
#include "mozilla/Unused.h"
|
# include "mozilla/Unused.h"
|
||||||
#include "mozilla/ScopeExit.h"
|
# include "mozilla/ScopeExit.h"
|
||||||
|
|
||||||
using namespace mozilla::ipc;
|
using namespace mozilla::ipc;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -51,16 +51,14 @@ namespace base {
|
||||||
#if defined(MOZ_ENABLE_FORKSERVER)
|
#if defined(MOZ_ENABLE_FORKSERVER)
|
||||||
static mozilla::StaticAutoPtr<std::vector<int> > sNoCloseFDs;
|
static mozilla::StaticAutoPtr<std::vector<int> > sNoCloseFDs;
|
||||||
|
|
||||||
void
|
void RegisterForkServerNoCloseFD(int fd) {
|
||||||
RegisterForkServerNoCloseFD(int fd) {
|
|
||||||
if (!sNoCloseFDs) {
|
if (!sNoCloseFDs) {
|
||||||
sNoCloseFDs = new std::vector<int>();
|
sNoCloseFDs = new std::vector<int>();
|
||||||
}
|
}
|
||||||
sNoCloseFDs->push_back(fd);
|
sNoCloseFDs->push_back(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool IsNoCloseFd(int fd) {
|
||||||
IsNoCloseFd(int fd) {
|
|
||||||
if (!sNoCloseFDs) {
|
if (!sNoCloseFDs) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -68,19 +66,17 @@ IsNoCloseFd(int fd) {
|
||||||
[fd](int regfd) -> bool { return regfd == fd; });
|
[fd](int regfd) -> bool { return regfd == fd; });
|
||||||
}
|
}
|
||||||
|
|
||||||
AppProcessBuilder::AppProcessBuilder() {
|
AppProcessBuilder::AppProcessBuilder() {}
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void ReplaceEnviroment(const LaunchOptions& options) {
|
||||||
ReplaceEnviroment(const LaunchOptions& options) {
|
|
||||||
for (auto& elt : options.env_map) {
|
for (auto& elt : options.env_map) {
|
||||||
setenv(elt.first.c_str(), elt.second.c_str(), 1);
|
setenv(elt.first.c_str(), elt.second.c_str(), 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool AppProcessBuilder::ForkProcess(const std::vector<std::string>& argv,
|
||||||
AppProcessBuilder::ForkProcess(const std::vector<std::string>& argv,
|
const LaunchOptions& options,
|
||||||
const LaunchOptions& options, ProcessHandle* process_handle) {
|
ProcessHandle* process_handle) {
|
||||||
auto cleanFDs = mozilla::MakeScopeExit([&] {
|
auto cleanFDs = mozilla::MakeScopeExit([&] {
|
||||||
for (auto& elt : options.fds_to_remap) {
|
for (auto& elt : options.fds_to_remap) {
|
||||||
auto fd = std::get<0>(elt);
|
auto fd = std::get<0>(elt);
|
||||||
|
|
@ -98,16 +94,16 @@ AppProcessBuilder::ForkProcess(const std::vector<std::string>& argv,
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
|
|
||||||
#ifdef OS_LINUX
|
# ifdef OS_LINUX
|
||||||
pid_t pid = options.fork_delegate ? options.fork_delegate->Fork() : fork();
|
pid_t pid = options.fork_delegate ? options.fork_delegate->Fork() : fork();
|
||||||
// WARNING: if pid == 0, only async signal safe operations are permitted from
|
// WARNING: if pid == 0, only async signal safe operations are permitted from
|
||||||
// here until exec or _exit.
|
// here until exec or _exit.
|
||||||
//
|
//
|
||||||
// Specifically, heap allocation is not safe: the sandbox's fork substitute
|
// Specifically, heap allocation is not safe: the sandbox's fork substitute
|
||||||
// won't run the pthread_atfork handlers that fix up the malloc locks.
|
// won't run the pthread_atfork handlers that fix up the malloc locks.
|
||||||
#else
|
# else
|
||||||
pid_t pid = fork();
|
pid_t pid = fork();
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
if (pid < 0) {
|
if (pid < 0) {
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -127,8 +123,7 @@ AppProcessBuilder::ForkProcess(const std::vector<std::string>& argv,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void AppProcessBuilder::ReplaceArguments(int* argcp, char*** argvp) {
|
||||||
AppProcessBuilder::ReplaceArguments(int *argcp, char*** argvp) {
|
|
||||||
// Change argc & argv of main() with the arguments passing
|
// Change argc & argv of main() with the arguments passing
|
||||||
// through IPC.
|
// through IPC.
|
||||||
char** argv = new char*[argv_.size() + 1];
|
char** argv = new char*[argv_.size() + 1];
|
||||||
|
|
@ -141,8 +136,7 @@ AppProcessBuilder::ReplaceArguments(int *argcp, char*** argvp) {
|
||||||
*argcp = argv_.size();
|
*argcp = argv_.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void AppProcessBuilder::InitAppProcess(int* argcp, char*** argvp) {
|
||||||
AppProcessBuilder::InitAppProcess(int *argcp, char*** argvp) {
|
|
||||||
MOZ_ASSERT(MessageLoop::current() == nullptr,
|
MOZ_ASSERT(MessageLoop::current() == nullptr,
|
||||||
"The message loop of the main thread should have been destroyed");
|
"The message loop of the main thread should have been destroyed");
|
||||||
|
|
||||||
|
|
@ -157,8 +151,7 @@ AppProcessBuilder::InitAppProcess(int *argcp, char*** argvp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
CloseSuperfluousFds(&shuffle_, [](void* ctx, int fd) {
|
CloseSuperfluousFds(&shuffle_, [](void* ctx, int fd) {
|
||||||
return static_cast<decltype(&shuffle_)>(ctx)->MapsTo(fd) ||
|
return static_cast<decltype(&shuffle_)>(ctx)->MapsTo(fd) || IsNoCloseFd(fd);
|
||||||
IsNoCloseFd(fd);
|
|
||||||
});
|
});
|
||||||
// Without this, the destructor of |shuffle_| would try to close FDs
|
// Without this, the destructor of |shuffle_| would try to close FDs
|
||||||
// created by it, but they have been closed by
|
// created by it, but they have been closed by
|
||||||
|
|
@ -168,21 +161,16 @@ AppProcessBuilder::InitAppProcess(int *argcp, char*** argvp) {
|
||||||
ReplaceArguments(argcp, argvp);
|
ReplaceArguments(argcp, argvp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void handle_sigchld(int s) { waitpid(-1, nullptr, WNOHANG); }
|
||||||
handle_sigchld(int s) {
|
|
||||||
waitpid(-1, nullptr, WNOHANG);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void InstallChildSignalHandler() {
|
||||||
InstallChildSignalHandler() {
|
|
||||||
// Since content processes are not children of the chrome process
|
// Since content processes are not children of the chrome process
|
||||||
// any more, the fork server process has to handle SIGCHLD, or
|
// any more, the fork server process has to handle SIGCHLD, or
|
||||||
// content process would remain zombie after dead.
|
// content process would remain zombie after dead.
|
||||||
signal(SIGCHLD, handle_sigchld);
|
signal(SIGCHLD, handle_sigchld);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void ReserveFileDescriptors() {
|
||||||
ReserveFileDescriptors() {
|
|
||||||
// Reserve the lower positions of the file descriptors to make sure
|
// Reserve the lower positions of the file descriptors to make sure
|
||||||
// debug files and other files don't take these positions. So we
|
// debug files and other files don't take these positions. So we
|
||||||
// can keep their file descriptors during CloseSuperfluousFds() with
|
// can keep their file descriptors during CloseSuperfluousFds() with
|
||||||
|
|
@ -193,16 +181,14 @@ ReserveFileDescriptors() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void InitForkServerProcess() {
|
||||||
InitForkServerProcess() {
|
|
||||||
InstallChildSignalHandler();
|
InstallChildSignalHandler();
|
||||||
ReserveFileDescriptors();
|
ReserveFileDescriptors();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool LaunchAppWithForkServer(const std::vector<std::string>& argv,
|
||||||
LaunchAppWithForkServer(const std::vector<std::string>& argv,
|
const LaunchOptions& options,
|
||||||
const LaunchOptions& options,
|
ProcessHandle* process_handle) {
|
||||||
ProcessHandle* process_handle) {
|
|
||||||
MOZ_ASSERT(ForkServiceChild::Get());
|
MOZ_ASSERT(ForkServiceChild::Get());
|
||||||
|
|
||||||
nsTArray<nsCString> _argv(argv.size());
|
nsTArray<nsCString> _argv(argv.size());
|
||||||
|
|
@ -217,13 +203,12 @@ LaunchAppWithForkServer(const std::vector<std::string>& argv,
|
||||||
nsCString(vv.second.c_str())));
|
nsCString(vv.second.c_str())));
|
||||||
}
|
}
|
||||||
for (auto& fdmapping : options.fds_to_remap) {
|
for (auto& fdmapping : options.fds_to_remap) {
|
||||||
fdsremap.AppendElement(mozilla::FdMapping(mozilla::ipc::FileDescriptor(fdmapping.first),
|
fdsremap.AppendElement(mozilla::FdMapping(
|
||||||
fdmapping.second));
|
mozilla::ipc::FileDescriptor(fdmapping.first), fdmapping.second));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ForkServiceChild::Get()->SendForkNewSubprocess(_argv, env,
|
return ForkServiceChild::Get()->SendForkNewSubprocess(_argv, env, fdsremap,
|
||||||
fdsremap,
|
process_handle);
|
||||||
process_handle);
|
|
||||||
}
|
}
|
||||||
#endif // MOZ_ENABLE_FORKSERVER
|
#endif // MOZ_ENABLE_FORKSERVER
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -213,7 +213,7 @@ bool DidProcessCrash(bool* child_exited, ProcessHandle handle) {
|
||||||
// them.
|
// them.
|
||||||
const int r = kill(handle, 0);
|
const int r = kill(handle, 0);
|
||||||
if (r < 0 && errno == ESRCH) {
|
if (r < 0 && errno == ESRCH) {
|
||||||
if (child_exited) *child_exited = true;
|
if (child_exited) *child_exited = true;
|
||||||
} else {
|
} else {
|
||||||
if (child_exited) *child_exited = false;
|
if (child_exited) *child_exited = false;
|
||||||
}
|
}
|
||||||
|
|
@ -261,7 +261,7 @@ bool DidProcessCrash(bool* child_exited, ProcessHandle handle) {
|
||||||
if (WIFEXITED(status)) return WEXITSTATUS(status) != 0;
|
if (WIFEXITED(status)) return WEXITSTATUS(status) != 0;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
#endif // MOZ_ENABLE_FORKSERVER
|
#endif // MOZ_ENABLE_FORKSERVER
|
||||||
}
|
}
|
||||||
|
|
||||||
void FreeEnvVarsArray::operator()(char** array) {
|
void FreeEnvVarsArray::operator()(char** array) {
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ namespace mozilla {
|
||||||
namespace ipc {
|
namespace ipc {
|
||||||
class MiniTransceiver;
|
class MiniTransceiver;
|
||||||
}
|
}
|
||||||
}
|
} // namespace mozilla
|
||||||
|
|
||||||
class FileDescriptorSet;
|
class FileDescriptorSet;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -51,9 +51,7 @@ class FileDescriptorShuffle {
|
||||||
|
|
||||||
// Forget the information, so that it's destructor will not try to
|
// Forget the information, so that it's destructor will not try to
|
||||||
// delete FDs duped by itself.
|
// delete FDs duped by itself.
|
||||||
void Forget() {
|
void Forget() { mTempFds.Clear(); }
|
||||||
mTempFds.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
nsTArray<std::pair<int, int>> mMapping;
|
nsTArray<std::pair<int, int>> mMapping;
|
||||||
|
|
|
||||||
|
|
@ -14,12 +14,11 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
#if defined(XP_LINUX) && defined(MOZ_SANDBOX)
|
#if defined(XP_LINUX) && defined(MOZ_SANDBOX)
|
||||||
#include "mozilla/SandboxLaunch.h"
|
# include "mozilla/SandboxLaunch.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace ipc {
|
namespace ipc {
|
||||||
|
|
||||||
|
|
@ -27,64 +26,59 @@ static const int sClientFd = 3;
|
||||||
|
|
||||||
LazyLogModule gForkServiceLog("ForkService");
|
LazyLogModule gForkServiceLog("ForkService");
|
||||||
|
|
||||||
ForkServer::ForkServer() {
|
ForkServer::ForkServer() {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare an environment for running a fork server.
|
* Prepare an environment for running a fork server.
|
||||||
*/
|
*/
|
||||||
void
|
void ForkServer::InitProcess(int* aArgc, char*** aArgv) {
|
||||||
ForkServer::InitProcess(int* aArgc, char*** aArgv) {
|
base::InitForkServerProcess();
|
||||||
base::InitForkServerProcess();
|
|
||||||
|
|
||||||
int fd = sClientFd;
|
int fd = sClientFd;
|
||||||
int fd_flags = fcntl(sClientFd, F_GETFL, 0);
|
int fd_flags = fcntl(sClientFd, F_GETFL, 0);
|
||||||
fcntl(fd, F_SETFL, fd_flags & ~O_NONBLOCK);
|
fcntl(fd, F_SETFL, fd_flags & ~O_NONBLOCK);
|
||||||
mTcver = MakeUnique<MiniTransceiver>(fd, DataBufferClear::AfterReceiving);
|
mTcver = MakeUnique<MiniTransceiver>(fd, DataBufferClear::AfterReceiving);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start providing the service at the IPC channel.
|
* Start providing the service at the IPC channel.
|
||||||
*/
|
*/
|
||||||
bool
|
bool ForkServer::HandleMessages() {
|
||||||
ForkServer::HandleMessages() {
|
// |sClientFd| is created by an instance of |IPC::Channel|.
|
||||||
// |sClientFd| is created by an instance of |IPC::Channel|.
|
// It sends a HELLO automatically.
|
||||||
// It sends a HELLO automatically.
|
IPC::Message hello;
|
||||||
IPC::Message hello;
|
mTcver->RecvInfallible(
|
||||||
mTcver->RecvInfallible(hello,
|
hello, "Expect to receive a HELLO message from the parent process!");
|
||||||
"Expect to receive a HELLO message from the parent process!");
|
MOZ_ASSERT(hello.type() == kHELLO_MESSAGE_TYPE);
|
||||||
MOZ_ASSERT(hello.type() == kHELLO_MESSAGE_TYPE);
|
|
||||||
|
|
||||||
// Send it back
|
// Send it back
|
||||||
mTcver->SendInfallible(hello, "Fail to ack the received HELLO!");
|
mTcver->SendInfallible(hello, "Fail to ack the received HELLO!");
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
IPC::Message msg;
|
IPC::Message msg;
|
||||||
if (!mTcver->Recv(msg)) {
|
if (!mTcver->Recv(msg)) {
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
OnMessageReceived(std::move(msg));
|
|
||||||
|
|
||||||
if (mAppProcBuilder) {
|
|
||||||
// New process - child
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Stop the server
|
|
||||||
return true;
|
OnMessageReceived(std::move(msg));
|
||||||
|
|
||||||
|
if (mAppProcBuilder) {
|
||||||
|
// New process - child
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Stop the server
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void CleanCString(nsCString& str) {
|
||||||
CleanCString(nsCString& str) {
|
char* data;
|
||||||
char* data;
|
int sz = str.GetMutableData(&data);
|
||||||
int sz = str.GetMutableData(&data);
|
|
||||||
|
|
||||||
memset(data, ' ', sz);
|
memset(data, ' ', sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void CleanString(std::string& str) {
|
||||||
CleanString(std::string& str) {
|
|
||||||
const char deadbeef[] =
|
const char deadbeef[] =
|
||||||
"\xde\xad\xbe\xef\xde\xad\xbe\xef\xde\xad\xbe\xef\xde\xad\xbe\xef"
|
"\xde\xad\xbe\xef\xde\xad\xbe\xef\xde\xad\xbe\xef\xde\xad\xbe\xef"
|
||||||
"\xde\xad\xbe\xef\xde\xad\xbe\xef\xde\xad\xbe\xef\xde\xad\xbe\xef";
|
"\xde\xad\xbe\xef\xde\xad\xbe\xef\xde\xad\xbe\xef\xde\xad\xbe\xef";
|
||||||
|
|
@ -98,97 +92,91 @@ CleanString(std::string& str) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void PrepareArguments(std::vector<std::string>& aArgv,
|
||||||
PrepareArguments(std::vector<std::string>& aArgv,
|
nsTArray<nsCString>& aArgvArray) {
|
||||||
nsTArray<nsCString>& aArgvArray) {
|
for (auto& elt : aArgvArray) {
|
||||||
for (auto& elt : aArgvArray) {
|
aArgv.push_back(elt.get());
|
||||||
aArgv.push_back(elt.get());
|
CleanCString(elt);
|
||||||
CleanCString(elt);
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare aOptions->env_map
|
// Prepare aOptions->env_map
|
||||||
inline void
|
inline void PrepareEnv(base::LaunchOptions* aOptions,
|
||||||
PrepareEnv(base::LaunchOptions* aOptions, nsTArray<EnvVar>& aEnvMap) {
|
nsTArray<EnvVar>& aEnvMap) {
|
||||||
for (auto& elt : aEnvMap) {
|
for (auto& elt : aEnvMap) {
|
||||||
nsCString &var = Get<0>(elt);
|
nsCString& var = Get<0>(elt);
|
||||||
nsCString &val = Get<1>(elt);
|
nsCString& val = Get<1>(elt);
|
||||||
aOptions->env_map[var.get()] = val.get();
|
aOptions->env_map[var.get()] = val.get();
|
||||||
CleanCString(var);
|
CleanCString(var);
|
||||||
CleanCString(val);
|
CleanCString(val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare aOptions->fds_to_remap
|
// Prepare aOptions->fds_to_remap
|
||||||
inline void
|
inline void PrepareFdsRemap(base::LaunchOptions* aOptions,
|
||||||
PrepareFdsRemap(base::LaunchOptions* aOptions,
|
nsTArray<FdMapping>& aFdsRemap) {
|
||||||
nsTArray<FdMapping>& aFdsRemap) {
|
MOZ_LOG(gForkServiceLog, LogLevel::Verbose, ("fds mapping:"));
|
||||||
MOZ_LOG(gForkServiceLog, LogLevel::Verbose, ("fds mapping:"));
|
for (auto& elt : aFdsRemap) {
|
||||||
for (auto& elt : aFdsRemap) {
|
// FDs are duplicated here.
|
||||||
// FDs are duplicated here.
|
int fd = Get<0>(elt).ClonePlatformHandle().release();
|
||||||
int fd = Get<0>(elt).ClonePlatformHandle().release();
|
std::pair<int, int> fdmap(fd, Get<1>(elt));
|
||||||
std::pair<int, int> fdmap(fd, Get<1>(elt));
|
aOptions->fds_to_remap.push_back(fdmap);
|
||||||
aOptions->fds_to_remap.push_back(fdmap);
|
MOZ_LOG(gForkServiceLog, LogLevel::Verbose,
|
||||||
MOZ_LOG(gForkServiceLog, LogLevel::Verbose,
|
("\t%d => %d", fdmap.first, fdmap.second));
|
||||||
("\t%d => %d", fdmap.first, fdmap.second));
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse a Message to get a list of arguments and fill a LaunchOptions.
|
* Parse a Message to get a list of arguments and fill a LaunchOptions.
|
||||||
*/
|
*/
|
||||||
inline bool
|
inline bool ParseForkNewSubprocess(IPC::Message& aMsg,
|
||||||
ParseForkNewSubprocess(IPC::Message& aMsg,
|
std::vector<std::string>& aArgv,
|
||||||
std::vector<std::string>& aArgv,
|
base::LaunchOptions* aOptions) {
|
||||||
base::LaunchOptions* aOptions) {
|
if (aMsg.type() != Msg_ForkNewSubprocess__ID) {
|
||||||
if (aMsg.type() != Msg_ForkNewSubprocess__ID) {
|
MOZ_LOG(gForkServiceLog, LogLevel::Verbose,
|
||||||
MOZ_LOG(gForkServiceLog, LogLevel::Verbose,
|
("unknown message type %d\n", aMsg.type()));
|
||||||
("unknown message type %d\n", aMsg.type()));
|
return false;
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
PickleIterator iter(aMsg);
|
PickleIterator iter(aMsg);
|
||||||
nsTArray<nsCString> argv_array;
|
nsTArray<nsCString> argv_array;
|
||||||
nsTArray<EnvVar> env_map;
|
nsTArray<EnvVar> env_map;
|
||||||
nsTArray<FdMapping> fds_remap;
|
nsTArray<FdMapping> fds_remap;
|
||||||
|
|
||||||
ReadIPDLParamInfallible(&aMsg, &iter, nullptr, &argv_array,
|
ReadIPDLParamInfallible(&aMsg, &iter, nullptr, &argv_array,
|
||||||
"Error deserializing 'nsCString[]'");
|
"Error deserializing 'nsCString[]'");
|
||||||
ReadIPDLParamInfallible(&aMsg, &iter, nullptr, &env_map,
|
ReadIPDLParamInfallible(&aMsg, &iter, nullptr, &env_map,
|
||||||
"Error deserializing 'EnvVar[]'");
|
"Error deserializing 'EnvVar[]'");
|
||||||
ReadIPDLParamInfallible(&aMsg, &iter, nullptr, &fds_remap,
|
ReadIPDLParamInfallible(&aMsg, &iter, nullptr, &fds_remap,
|
||||||
"Error deserializing 'FdMapping[]'");
|
"Error deserializing 'FdMapping[]'");
|
||||||
aMsg.EndRead(iter, aMsg.type());
|
aMsg.EndRead(iter, aMsg.type());
|
||||||
|
|
||||||
PrepareArguments(aArgv, argv_array);
|
PrepareArguments(aArgv, argv_array);
|
||||||
PrepareEnv(aOptions, env_map);
|
PrepareEnv(aOptions, env_map);
|
||||||
PrepareFdsRemap(aOptions, fds_remap);
|
PrepareFdsRemap(aOptions, fds_remap);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void SanitizeBuffers(IPC::Message& aMsg, std::vector<std::string>& aArgv,
|
||||||
SanitizeBuffers(IPC::Message& aMsg,
|
base::LaunchOptions& aOptions) {
|
||||||
std::vector<std::string>& aArgv,
|
// Clean all buffers in the message to make sure content processes
|
||||||
base::LaunchOptions& aOptions) {
|
// not peeking others.
|
||||||
// Clean all buffers in the message to make sure content processes
|
auto& blist = aMsg.Buffers();
|
||||||
// not peeking others.
|
for (auto itr = blist.Iter(); !itr.Done();
|
||||||
auto& blist = aMsg.Buffers();
|
itr.Advance(blist, itr.RemainingInSegment())) {
|
||||||
for (auto itr = blist.Iter();
|
memset(itr.Data(), 0, itr.RemainingInSegment());
|
||||||
!itr.Done();
|
}
|
||||||
itr.Advance(blist, itr.RemainingInSegment())) {
|
|
||||||
memset(itr.Data(), 0, itr.RemainingInSegment());
|
|
||||||
}
|
|
||||||
|
|
||||||
// clean all data string made from the message.
|
// clean all data string made from the message.
|
||||||
for (auto& var : aOptions.env_map) {
|
for (auto& var : aOptions.env_map) {
|
||||||
// Do it anyway since it is not going to be used anymore.
|
// Do it anyway since it is not going to be used anymore.
|
||||||
CleanString(*const_cast<std::string*>(&var.first));
|
CleanString(*const_cast<std::string*>(&var.first));
|
||||||
CleanString(var.second);
|
CleanString(var.second);
|
||||||
}
|
}
|
||||||
for (auto& arg : aArgv) {
|
for (auto& arg : aArgv) {
|
||||||
CleanString(arg);
|
CleanString(arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -198,45 +186,43 @@ SanitizeBuffers(IPC::Message& aMsg,
|
||||||
* It will return in both the fork server process and the new content
|
* It will return in both the fork server process and the new content
|
||||||
* process. |mAppProcBuilder| is null for the fork server.
|
* process. |mAppProcBuilder| is null for the fork server.
|
||||||
*/
|
*/
|
||||||
void
|
void ForkServer::OnMessageReceived(IPC::Message&& message) {
|
||||||
ForkServer::OnMessageReceived(IPC::Message&& message) {
|
IPC::Message msg(std::move(message));
|
||||||
IPC::Message msg(std::move(message));
|
|
||||||
|
|
||||||
std::vector<std::string> argv;
|
std::vector<std::string> argv;
|
||||||
base::LaunchOptions options;
|
base::LaunchOptions options;
|
||||||
if (!ParseForkNewSubprocess(msg, argv, &options)) {
|
if (!ParseForkNewSubprocess(msg, argv, &options)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(XP_LINUX) && defined(MOZ_SANDBOX)
|
#if defined(XP_LINUX) && defined(MOZ_SANDBOX)
|
||||||
mozilla::SandboxLaunchForkServerPrepare(argv, options);
|
mozilla::SandboxLaunchForkServerPrepare(argv, options);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
base::ProcessHandle child_pid = -1;
|
base::ProcessHandle child_pid = -1;
|
||||||
mAppProcBuilder = MakeUnique<base::AppProcessBuilder>();
|
mAppProcBuilder = MakeUnique<base::AppProcessBuilder>();
|
||||||
if (!mAppProcBuilder->ForkProcess(argv, options, &child_pid)) {
|
if (!mAppProcBuilder->ForkProcess(argv, options, &child_pid)) {
|
||||||
MOZ_CRASH("fail to fork");
|
MOZ_CRASH("fail to fork");
|
||||||
}
|
}
|
||||||
MOZ_ASSERT(child_pid >= 0);
|
MOZ_ASSERT(child_pid >= 0);
|
||||||
|
|
||||||
if (child_pid == 0) {
|
if (child_pid == 0) {
|
||||||
// Content process
|
// Content process
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fork server process
|
// Fork server process
|
||||||
|
|
||||||
mAppProcBuilder = nullptr;
|
mAppProcBuilder = nullptr;
|
||||||
|
|
||||||
IPC::Message reply(MSG_ROUTING_CONTROL, Reply_ForkNewSubprocess__ID);
|
IPC::Message reply(MSG_ROUTING_CONTROL, Reply_ForkNewSubprocess__ID);
|
||||||
WriteIPDLParam(&reply, nullptr, child_pid);
|
WriteIPDLParam(&reply, nullptr, child_pid);
|
||||||
mTcver->SendInfallible(reply,
|
mTcver->SendInfallible(reply, "failed to send a reply message");
|
||||||
"failed to send a reply message");
|
|
||||||
|
|
||||||
// Without this, the content processes that is forked later are
|
// Without this, the content processes that is forked later are
|
||||||
// able to read the content of buffers even the buffers have been
|
// able to read the content of buffers even the buffers have been
|
||||||
// released.
|
// released.
|
||||||
SanitizeBuffers(msg, argv, options);
|
SanitizeBuffers(msg, argv, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -250,66 +236,69 @@ ForkServer::OnMessageReceived(IPC::Message&& message) {
|
||||||
* For the later case, aArgc and aArgv are modified to pass the
|
* For the later case, aArgc and aArgv are modified to pass the
|
||||||
* arguments from the chrome process.
|
* arguments from the chrome process.
|
||||||
*/
|
*/
|
||||||
bool
|
bool ForkServer::RunForkServer(int* aArgc, char*** aArgv) {
|
||||||
ForkServer::RunForkServer(int* aArgc, char*** aArgv) {
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (getenv("MOZ_FORKSERVER_WAIT_GDB")) {
|
if (getenv("MOZ_FORKSERVER_WAIT_GDB")) {
|
||||||
printf("Waiting for 30 seconds."
|
printf(
|
||||||
" Attach the fork server with gdb %s %d\n",
|
"Waiting for 30 seconds."
|
||||||
(*aArgv)[0], base::GetCurrentProcId());
|
" Attach the fork server with gdb %s %d\n",
|
||||||
sleep(30);
|
(*aArgv)[0], base::GetCurrentProcId());
|
||||||
}
|
sleep(30);
|
||||||
bool sleep_newproc = !!getenv("MOZ_FORKSERVER_WAIT_GDB_NEWPROC");
|
}
|
||||||
|
bool sleep_newproc = !!getenv("MOZ_FORKSERVER_WAIT_GDB_NEWPROC");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Do this before NS_LogInit() to avoid log files taking lower
|
// Do this before NS_LogInit() to avoid log files taking lower
|
||||||
// FDs.
|
// FDs.
|
||||||
ForkServer forkserver;
|
ForkServer forkserver;
|
||||||
forkserver.InitProcess(aArgc, aArgv);
|
forkserver.InitProcess(aArgc, aArgv);
|
||||||
|
|
||||||
XRE_SetProcessType("forkserver");
|
XRE_SetProcessType("forkserver");
|
||||||
NS_LogInit();
|
NS_LogInit();
|
||||||
mozilla::LogModule::Init(0, nullptr);
|
mozilla::LogModule::Init(0, nullptr);
|
||||||
MOZ_LOG(gForkServiceLog, LogLevel::Verbose, ("Start a fork server"));
|
MOZ_LOG(gForkServiceLog, LogLevel::Verbose, ("Start a fork server"));
|
||||||
{
|
{
|
||||||
DebugOnly<base::ProcessHandle> forkserver_pid = base::GetCurrentProcId();
|
DebugOnly<base::ProcessHandle> forkserver_pid = base::GetCurrentProcId();
|
||||||
if (forkserver.HandleMessages()) {
|
if (forkserver.HandleMessages()) {
|
||||||
// In the fork server process
|
// In the fork server process
|
||||||
// The server has stopped.
|
// The server has stopped.
|
||||||
MOZ_LOG(gForkServiceLog, LogLevel::Verbose, ("Terminate the fork server"));
|
MOZ_LOG(gForkServiceLog, LogLevel::Verbose,
|
||||||
NS_LogTerm();
|
("Terminate the fork server"));
|
||||||
return true;
|
NS_LogTerm();
|
||||||
}
|
return true;
|
||||||
// Now, we are running in a content process just forked from
|
|
||||||
// the fork server process.
|
|
||||||
MOZ_ASSERT(base::GetCurrentProcId() != forkserver_pid);
|
|
||||||
MOZ_LOG(gForkServiceLog, LogLevel::Verbose, ("Fork a new content process"));
|
|
||||||
}
|
}
|
||||||
|
// Now, we are running in a content process just forked from
|
||||||
|
// the fork server process.
|
||||||
|
MOZ_ASSERT(base::GetCurrentProcId() != forkserver_pid);
|
||||||
|
MOZ_LOG(gForkServiceLog, LogLevel::Verbose, ("Fork a new content process"));
|
||||||
|
}
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (sleep_newproc) {
|
if (sleep_newproc) {
|
||||||
printf("Waiting for 30 seconds."
|
printf(
|
||||||
" Attach the new process with gdb %s %d\n",
|
"Waiting for 30 seconds."
|
||||||
(*aArgv)[0], base::GetCurrentProcId());
|
" Attach the new process with gdb %s %d\n",
|
||||||
sleep(30);
|
(*aArgv)[0], base::GetCurrentProcId());
|
||||||
}
|
sleep(30);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
NS_LogTerm();
|
NS_LogTerm();
|
||||||
|
|
||||||
MOZ_ASSERT(forkserver.mAppProcBuilder);
|
MOZ_ASSERT(forkserver.mAppProcBuilder);
|
||||||
// |messageloop| has been destroyed. So, we can intialized the
|
// |messageloop| has been destroyed. So, we can intialized the
|
||||||
// process safely. Message loops may allocates some file
|
// process safely. Message loops may allocates some file
|
||||||
// descriptors. If it is destroyed later, it may mess up this
|
// descriptors. If it is destroyed later, it may mess up this
|
||||||
// content process by closing wrong file descriptors.
|
// content process by closing wrong file descriptors.
|
||||||
forkserver.mAppProcBuilder->InitAppProcess(aArgc, aArgv);
|
forkserver.mAppProcBuilder->InitAppProcess(aArgc, aArgv);
|
||||||
forkserver.mAppProcBuilder.reset();
|
forkserver.mAppProcBuilder.reset();
|
||||||
|
|
||||||
MOZ_ASSERT(NS_LITERAL_CSTRING("tab") == (*aArgv)[*aArgc - 1], "Only |tab| is allowed!");
|
MOZ_ASSERT(NS_LITERAL_CSTRING("tab") == (*aArgv)[*aArgc - 1],
|
||||||
|
"Only |tab| is allowed!");
|
||||||
|
|
||||||
// Open log files again with right names and the new PID.
|
// Open log files again with right names and the new PID.
|
||||||
nsTraceRefcnt::ResetLogFiles((*aArgv)[*aArgc - 1]);
|
nsTraceRefcnt::ResetLogFiles((*aArgv)[*aArgc - 1]);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // namespace ipc
|
||||||
}
|
} // namespace mozilla
|
||||||
|
|
|
||||||
|
|
@ -14,31 +14,31 @@ namespace mozilla {
|
||||||
namespace ipc {
|
namespace ipc {
|
||||||
|
|
||||||
class ForkServer {
|
class ForkServer {
|
||||||
public:
|
public:
|
||||||
static const int kHELLO_MESSAGE_TYPE = 65535;
|
static const int kHELLO_MESSAGE_TYPE = 65535;
|
||||||
|
|
||||||
ForkServer();
|
ForkServer();
|
||||||
~ForkServer() {};
|
~ForkServer(){};
|
||||||
|
|
||||||
void InitProcess(int* aArgc, char*** aArgv);
|
void InitProcess(int* aArgc, char*** aArgv);
|
||||||
bool HandleMessages();
|
bool HandleMessages();
|
||||||
|
|
||||||
// Called when a message is received.
|
// Called when a message is received.
|
||||||
void OnMessageReceived(IPC::Message&& message);
|
void OnMessageReceived(IPC::Message&& message);
|
||||||
|
|
||||||
static bool RunForkServer(int* aArgc, char*** aArgv);
|
static bool RunForkServer(int* aArgc, char*** aArgv);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
UniquePtr<MiniTransceiver> mTcver;
|
UniquePtr<MiniTransceiver> mTcver;
|
||||||
UniquePtr<base::AppProcessBuilder> mAppProcBuilder;
|
UniquePtr<base::AppProcessBuilder> mAppProcBuilder;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
Msg_ForkNewSubprocess__ID = 0x7f0, // a random picked number
|
Msg_ForkNewSubprocess__ID = 0x7f0, // a random picked number
|
||||||
Reply_ForkNewSubprocess__ID,
|
Reply_ForkNewSubprocess__ID,
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace ipc
|
||||||
}
|
} // namespace mozilla
|
||||||
|
|
||||||
#endif // __FORKSERVER_H_
|
#endif // __FORKSERVER_H_
|
||||||
|
|
|
||||||
|
|
@ -19,97 +19,89 @@ extern LazyLogModule gForkServiceLog;
|
||||||
|
|
||||||
mozilla::UniquePtr<ForkServiceChild> ForkServiceChild::sForkServiceChild;
|
mozilla::UniquePtr<ForkServiceChild> ForkServiceChild::sForkServiceChild;
|
||||||
|
|
||||||
void
|
void ForkServiceChild::StartForkServer() {
|
||||||
ForkServiceChild::StartForkServer() {
|
std::vector<std::string> extraArgs;
|
||||||
std::vector<std::string> extraArgs;
|
|
||||||
|
|
||||||
GeckoChildProcessHost *subprocess =
|
GeckoChildProcessHost* subprocess =
|
||||||
new GeckoChildProcessHost(GeckoProcessType_ForkServer, false);
|
new GeckoChildProcessHost(GeckoProcessType_ForkServer, false);
|
||||||
subprocess->LaunchAndWaitForProcessHandle(std::move(extraArgs));
|
subprocess->LaunchAndWaitForProcessHandle(std::move(extraArgs));
|
||||||
|
|
||||||
int fd = subprocess->GetChannel()->GetFileDescriptor();
|
int fd = subprocess->GetChannel()->GetFileDescriptor();
|
||||||
fd = dup(fd); // Dup it because the channel will close it.
|
fd = dup(fd); // Dup it because the channel will close it.
|
||||||
int fs_flags = fcntl(fd, F_GETFL, 0);
|
int fs_flags = fcntl(fd, F_GETFL, 0);
|
||||||
fcntl(fd, F_SETFL, fs_flags & ~O_NONBLOCK);
|
fcntl(fd, F_SETFL, fs_flags & ~O_NONBLOCK);
|
||||||
int fd_flags = fcntl(fd, F_GETFD, 0);
|
int fd_flags = fcntl(fd, F_GETFD, 0);
|
||||||
fcntl(fd, F_SETFD, fd_flags | FD_CLOEXEC);
|
fcntl(fd, F_SETFD, fd_flags | FD_CLOEXEC);
|
||||||
|
|
||||||
sForkServiceChild = mozilla::MakeUnique<ForkServiceChild>(fd, subprocess);
|
sForkServiceChild = mozilla::MakeUnique<ForkServiceChild>(fd, subprocess);
|
||||||
|
|
||||||
// Without doing this, IO thread may intercept messages since the
|
// Without doing this, IO thread may intercept messages since the
|
||||||
// IPC::Channel created by it is still open.
|
// IPC::Channel created by it is still open.
|
||||||
subprocess->GetChannel()->Close();
|
subprocess->GetChannel()->Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void ForkServiceChild::StopForkServer() { sForkServiceChild = nullptr; }
|
||||||
ForkServiceChild::StopForkServer() {
|
|
||||||
sForkServiceChild = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
ForkServiceChild::ForkServiceChild(int aFd, GeckoChildProcessHost* aProcess)
|
ForkServiceChild::ForkServiceChild(int aFd, GeckoChildProcessHost* aProcess)
|
||||||
: mWaitForHello(true)
|
: mWaitForHello(true), mProcess(aProcess) {
|
||||||
, mProcess(aProcess) {
|
mTcver = MakeUnique<MiniTransceiver>(aFd);
|
||||||
mTcver = MakeUnique<MiniTransceiver>(aFd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ForkServiceChild::~ForkServiceChild() {
|
ForkServiceChild::~ForkServiceChild() {
|
||||||
mProcess->Destroy();
|
mProcess->Destroy();
|
||||||
close(mTcver->GetFD());
|
close(mTcver->GetFD());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool ForkServiceChild::SendForkNewSubprocess(
|
||||||
ForkServiceChild::SendForkNewSubprocess(const nsTArray<nsCString>& aArgv,
|
const nsTArray<nsCString>& aArgv, const nsTArray<EnvVar>& aEnvMap,
|
||||||
const nsTArray<EnvVar>& aEnvMap,
|
const nsTArray<FdMapping>& aFdsRemap, pid_t* aPid) {
|
||||||
const nsTArray<FdMapping>& aFdsRemap,
|
if (mWaitForHello) {
|
||||||
pid_t* aPid) {
|
// IPC::Channel created by the GeckoChildProcessHost has
|
||||||
if (mWaitForHello) {
|
// already send a HELLO. It is expected to receive a hello
|
||||||
// IPC::Channel created by the GeckoChildProcessHost has
|
// message from the fork server too.
|
||||||
// already send a HELLO. It is expected to receive a hello
|
IPC::Message hello;
|
||||||
// message from the fork server too.
|
mTcver->RecvInfallible(hello, "Fail to receive HELLO message");
|
||||||
IPC::Message hello;
|
MOZ_ASSERT(hello.type() == ForkServer::kHELLO_MESSAGE_TYPE);
|
||||||
mTcver->RecvInfallible(hello, "Fail to receive HELLO message");
|
mWaitForHello = false;
|
||||||
MOZ_ASSERT(hello.type() == ForkServer::kHELLO_MESSAGE_TYPE);
|
}
|
||||||
mWaitForHello = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
mRecvPid = -1;
|
mRecvPid = -1;
|
||||||
IPC::Message msg(MSG_ROUTING_CONTROL, Msg_ForkNewSubprocess__ID);
|
IPC::Message msg(MSG_ROUTING_CONTROL, Msg_ForkNewSubprocess__ID);
|
||||||
|
|
||||||
WriteIPDLParam(&msg, nullptr, aArgv);
|
WriteIPDLParam(&msg, nullptr, aArgv);
|
||||||
WriteIPDLParam(&msg, nullptr, aEnvMap);
|
WriteIPDLParam(&msg, nullptr, aEnvMap);
|
||||||
WriteIPDLParam(&msg, nullptr, aFdsRemap);
|
WriteIPDLParam(&msg, nullptr, aFdsRemap);
|
||||||
if (!mTcver->Send(msg)) {
|
if (!mTcver->Send(msg)) {
|
||||||
MOZ_LOG(gForkServiceLog, LogLevel::Verbose,
|
MOZ_LOG(gForkServiceLog, LogLevel::Verbose,
|
||||||
("the pipe to the fork server is closed or having errors"));
|
("the pipe to the fork server is closed or having errors"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
IPC::Message reply;
|
IPC::Message reply;
|
||||||
if (!mTcver->Recv(reply)) {
|
if (!mTcver->Recv(reply)) {
|
||||||
MOZ_LOG(gForkServiceLog, LogLevel::Verbose,
|
MOZ_LOG(gForkServiceLog, LogLevel::Verbose,
|
||||||
("the pipe to the fork server is closed or having errors"));
|
("the pipe to the fork server is closed or having errors"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
OnMessageReceived(std::move(reply));
|
OnMessageReceived(std::move(reply));
|
||||||
|
|
||||||
MOZ_ASSERT(mRecvPid != -1);
|
MOZ_ASSERT(mRecvPid != -1);
|
||||||
*aPid = mRecvPid;
|
*aPid = mRecvPid;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void ForkServiceChild::OnMessageReceived(IPC::Message&& message) {
|
||||||
ForkServiceChild::OnMessageReceived(IPC::Message&& message) {
|
if (message.type() != Reply_ForkNewSubprocess__ID) {
|
||||||
if (message.type() != Reply_ForkNewSubprocess__ID) {
|
MOZ_LOG(gForkServiceLog, LogLevel::Verbose,
|
||||||
MOZ_LOG(gForkServiceLog, LogLevel::Verbose,
|
("unknown reply type %d", message.type()));
|
||||||
("unknown reply type %d", message.type()));
|
return;
|
||||||
return;
|
}
|
||||||
}
|
PickleIterator iter__(message);
|
||||||
PickleIterator iter__(message);
|
|
||||||
|
|
||||||
if (!ReadIPDLParam(&message, &iter__, nullptr, &mRecvPid)) {
|
if (!ReadIPDLParam(&message, &iter__, nullptr, &mRecvPid)) {
|
||||||
MOZ_CRASH("Error deserializing 'pid_t'");
|
MOZ_CRASH("Error deserializing 'pid_t'");
|
||||||
}
|
}
|
||||||
message.EndRead(iter__, message.type());
|
message.EndRead(iter__, message.type());
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS(ForkServerLauncher, nsIObserver)
|
NS_IMPL_ISUPPORTS(ForkServerLauncher, nsIObserver)
|
||||||
|
|
@ -117,43 +109,41 @@ NS_IMPL_ISUPPORTS(ForkServerLauncher, nsIObserver)
|
||||||
bool ForkServerLauncher::mHaveStartedClient = false;
|
bool ForkServerLauncher::mHaveStartedClient = false;
|
||||||
StaticRefPtr<ForkServerLauncher> ForkServerLauncher::mSingleton;
|
StaticRefPtr<ForkServerLauncher> ForkServerLauncher::mSingleton;
|
||||||
|
|
||||||
ForkServerLauncher::ForkServerLauncher() {
|
ForkServerLauncher::ForkServerLauncher() {}
|
||||||
}
|
|
||||||
|
|
||||||
ForkServerLauncher::~ForkServerLauncher() {
|
ForkServerLauncher::~ForkServerLauncher() {}
|
||||||
}
|
|
||||||
|
|
||||||
already_AddRefed<ForkServerLauncher>
|
already_AddRefed<ForkServerLauncher> ForkServerLauncher::Create() {
|
||||||
ForkServerLauncher::Create() {
|
if (mSingleton == nullptr) {
|
||||||
if (mSingleton == nullptr) {
|
mSingleton = new ForkServerLauncher();
|
||||||
mSingleton = new ForkServerLauncher();
|
}
|
||||||
}
|
RefPtr<ForkServerLauncher> launcher = mSingleton;
|
||||||
RefPtr<ForkServerLauncher> launcher = mSingleton;
|
return launcher.forget();
|
||||||
return launcher.forget();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
ForkServerLauncher::Observe(nsISupports* aSubject,
|
ForkServerLauncher::Observe(nsISupports* aSubject, const char* aTopic,
|
||||||
const char* aTopic,
|
const char16_t* aData) {
|
||||||
const char16_t* aData) {
|
if (!mHaveStartedClient && strcmp(aTopic, NS_XPCOM_STARTUP_CATEGORY) == 0) {
|
||||||
if (!mHaveStartedClient && strcmp(aTopic, NS_XPCOM_STARTUP_CATEGORY) == 0) {
|
mHaveStartedClient = true;
|
||||||
mHaveStartedClient = true;
|
ForkServiceChild::StartForkServer();
|
||||||
ForkServiceChild::StartForkServer();
|
|
||||||
|
|
||||||
nsCOMPtr<nsIObserverService> obsSvc = mozilla::services::GetObserverService();
|
nsCOMPtr<nsIObserverService> obsSvc =
|
||||||
MOZ_ASSERT(obsSvc != nullptr);
|
mozilla::services::GetObserverService();
|
||||||
obsSvc->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
|
MOZ_ASSERT(obsSvc != nullptr);
|
||||||
}
|
obsSvc->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
|
||||||
|
}
|
||||||
|
|
||||||
if (mHaveStartedClient && strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
|
if (mHaveStartedClient &&
|
||||||
mHaveStartedClient = false;
|
strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
|
||||||
ForkServiceChild::StopForkServer();
|
mHaveStartedClient = false;
|
||||||
|
ForkServiceChild::StopForkServer();
|
||||||
|
|
||||||
// To make leak checker happy!
|
// To make leak checker happy!
|
||||||
mSingleton = nullptr;
|
mSingleton = nullptr;
|
||||||
}
|
}
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // namespace ipc
|
||||||
}
|
} // namespace mozilla
|
||||||
|
|
|
||||||
|
|
@ -26,72 +26,70 @@ class GeckoChildProcessHost;
|
||||||
* pipe and get the PID of the new process from the reply.
|
* pipe and get the PID of the new process from the reply.
|
||||||
*/
|
*/
|
||||||
class ForkServiceChild {
|
class ForkServiceChild {
|
||||||
public:
|
public:
|
||||||
ForkServiceChild(int aFd, GeckoChildProcessHost* aProcess);
|
ForkServiceChild(int aFd, GeckoChildProcessHost* aProcess);
|
||||||
virtual ~ForkServiceChild();
|
virtual ~ForkServiceChild();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ask the fork server to create a new process with given parameters.
|
* Ask the fork server to create a new process with given parameters.
|
||||||
*
|
*
|
||||||
* The fork server uses |base::LaunchApp()| to create a new
|
* The fork server uses |base::LaunchApp()| to create a new
|
||||||
* content process with the following parameters.
|
* content process with the following parameters.
|
||||||
*
|
*
|
||||||
* \param aArgv assigns |argv| of the content process.
|
* \param aArgv assigns |argv| of the content process.
|
||||||
* \param aEnvMap sets |LaunchOptions::env_map|.
|
* \param aEnvMap sets |LaunchOptions::env_map|.
|
||||||
* \param aFdsRemap sets |LaunchOptions::fd_to_remap|.
|
* \param aFdsRemap sets |LaunchOptions::fd_to_remap|.
|
||||||
* \param aPid returns the PID of the content process created.
|
* \param aPid returns the PID of the content process created.
|
||||||
* \return true if success.
|
* \return true if success.
|
||||||
*/
|
*/
|
||||||
bool SendForkNewSubprocess(
|
bool SendForkNewSubprocess(const nsTArray<nsCString>& aArgv,
|
||||||
const nsTArray<nsCString>& aArgv,
|
const nsTArray<EnvVar>& aEnvMap,
|
||||||
const nsTArray<EnvVar>& aEnvMap,
|
const nsTArray<FdMapping>& aFdsRemap, pid_t* aPid);
|
||||||
const nsTArray<FdMapping>& aFdsRemap,
|
|
||||||
pid_t* aPid);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a fork server process and the singleton of this class.
|
* Create a fork server process and the singleton of this class.
|
||||||
*
|
*
|
||||||
* This function uses |GeckoChildProcessHost| to launch the fork
|
* This function uses |GeckoChildProcessHost| to launch the fork
|
||||||
* server, getting the fd of a pipe/socket to the fork server from
|
* server, getting the fd of a pipe/socket to the fork server from
|
||||||
* it's |IPC::Channel|.
|
* it's |IPC::Channel|.
|
||||||
*/
|
*/
|
||||||
static void StartForkServer();
|
static void StartForkServer();
|
||||||
static void StopForkServer();
|
static void StopForkServer();
|
||||||
/**
|
/**
|
||||||
* Return the singleton.
|
* Return the singleton.
|
||||||
*/
|
*/
|
||||||
static ForkServiceChild* Get() { return sForkServiceChild.get(); }
|
static ForkServiceChild* Get() { return sForkServiceChild.get(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Called when a message is received.
|
// Called when a message is received.
|
||||||
void OnMessageReceived(IPC::Message&& message);
|
void OnMessageReceived(IPC::Message&& message);
|
||||||
|
|
||||||
UniquePtr<MiniTransceiver> mTcver;
|
UniquePtr<MiniTransceiver> mTcver;
|
||||||
static UniquePtr<ForkServiceChild> sForkServiceChild;
|
static UniquePtr<ForkServiceChild> sForkServiceChild;
|
||||||
pid_t mRecvPid;
|
pid_t mRecvPid;
|
||||||
bool mWaitForHello;
|
bool mWaitForHello;
|
||||||
GeckoChildProcessHost* mProcess;
|
GeckoChildProcessHost* mProcess;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start a fork server at |xpcom-startup| from the chrome process.
|
* Start a fork server at |xpcom-startup| from the chrome process.
|
||||||
*/
|
*/
|
||||||
class ForkServerLauncher : public nsIObserver {
|
class ForkServerLauncher : public nsIObserver {
|
||||||
public:
|
public:
|
||||||
NS_DECL_ISUPPORTS
|
NS_DECL_ISUPPORTS
|
||||||
NS_DECL_NSIOBSERVER
|
NS_DECL_NSIOBSERVER
|
||||||
|
|
||||||
ForkServerLauncher();
|
ForkServerLauncher();
|
||||||
static already_AddRefed<ForkServerLauncher> Create();
|
static already_AddRefed<ForkServerLauncher> Create();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual ~ForkServerLauncher();
|
virtual ~ForkServerLauncher();
|
||||||
|
|
||||||
static bool mHaveStartedClient;
|
static bool mHaveStartedClient;
|
||||||
static StaticRefPtr<ForkServerLauncher> mSingleton;
|
static StaticRefPtr<ForkServerLauncher> mSingleton;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace ipc
|
||||||
}
|
} // namespace mozilla
|
||||||
|
|
||||||
#endif /* __FORKSERVICE_CHILD_H_ */
|
#endif /* __FORKSERVICE_CHILD_H_ */
|
||||||
|
|
|
||||||
|
|
@ -831,7 +831,8 @@ void BaseProcessLauncher::GetChildLogName(const char* origLogName,
|
||||||
//
|
//
|
||||||
// Fork server needs a dedicated thread for accessing
|
// Fork server needs a dedicated thread for accessing
|
||||||
// |ForkServiceChild|.
|
// |ForkServiceChild|.
|
||||||
#if defined(XP_WIN) || defined(MOZ_WIDGET_ANDROID) || defined(MOZ_ENABLE_FORKSERVER)
|
#if defined(XP_WIN) || defined(MOZ_WIDGET_ANDROID) || \
|
||||||
|
defined(MOZ_ENABLE_FORKSERVER)
|
||||||
|
|
||||||
static mozilla::StaticMutex gIPCLaunchThreadMutex;
|
static mozilla::StaticMutex gIPCLaunchThreadMutex;
|
||||||
static mozilla::StaticRefPtr<nsIThread> gIPCLaunchThread;
|
static mozilla::StaticRefPtr<nsIThread> gIPCLaunchThread;
|
||||||
|
|
@ -884,7 +885,8 @@ nsCOMPtr<nsIEventTarget> GetIPCLauncher() {
|
||||||
return thread;
|
return thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else // defined(XP_WIN) || defined(MOZ_WIDGET_ANDROID) || defined(MOZ_ENABLE_FORKSERVER)
|
#else // defined(XP_WIN) || defined(MOZ_WIDGET_ANDROID) ||
|
||||||
|
// defined(MOZ_ENABLE_FORKSERVER)
|
||||||
|
|
||||||
// Other platforms use an on-demand thread pool.
|
// Other platforms use an on-demand thread pool.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -69,10 +69,9 @@ static MOZ_NEVER_INLINE bool ReadIPDLParam(const IPC::Message* aMsg,
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename P>
|
template <typename P>
|
||||||
static MOZ_NEVER_INLINE bool ReadIPDLParamInfallible(const IPC::Message* aMsg,
|
static MOZ_NEVER_INLINE bool ReadIPDLParamInfallible(
|
||||||
PickleIterator* aIter,
|
const IPC::Message* aMsg, PickleIterator* aIter, IProtocol* aActor,
|
||||||
IProtocol* aActor, P* aResult,
|
P* aResult, const char* aCrashMessage) {
|
||||||
const char* aCrashMessage) {
|
|
||||||
bool ok = ReadIPDLParam(aMsg, aIter, aActor, aResult);
|
bool ok = ReadIPDLParam(aMsg, aIter, aActor, aResult);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
MOZ_CRASH_UNSAFE(aCrashMessage);
|
MOZ_CRASH_UNSAFE(aCrashMessage);
|
||||||
|
|
|
||||||
|
|
@ -32,214 +32,210 @@ MiniTransceiver::MiniTransceiver(int aFd, DataBufferClear aDataBufClear)
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the IO vector for sending data and the control buffer for sending FDs.
|
* Initialize the IO vector for sending data and the control buffer for sending
|
||||||
|
* FDs.
|
||||||
*/
|
*/
|
||||||
static void
|
static void InitMsgHdr(msghdr* aHdr, int aIOVSize, int aMaxNumFds) {
|
||||||
InitMsgHdr(msghdr* aHdr, int aIOVSize, int aMaxNumFds) {
|
aHdr->msg_name = nullptr;
|
||||||
aHdr->msg_name = nullptr;
|
aHdr->msg_namelen = 0;
|
||||||
aHdr->msg_namelen = 0;
|
aHdr->msg_flags = 0;
|
||||||
aHdr->msg_flags = 0;
|
|
||||||
|
|
||||||
// Prepare the IO vector to receive the content of message.
|
// Prepare the IO vector to receive the content of message.
|
||||||
auto iov = new iovec[aIOVSize];
|
auto iov = new iovec[aIOVSize];
|
||||||
aHdr->msg_iov = iov;
|
aHdr->msg_iov = iov;
|
||||||
aHdr->msg_iovlen = aIOVSize;
|
aHdr->msg_iovlen = aIOVSize;
|
||||||
|
|
||||||
// Prepare the control buffer to receive file descriptors.
|
// Prepare the control buffer to receive file descriptors.
|
||||||
auto cbuf = new char[CMSG_SPACE(sizeof(int) * aMaxNumFds)];
|
auto cbuf = new char[CMSG_SPACE(sizeof(int) * aMaxNumFds)];
|
||||||
aHdr->msg_control = cbuf;
|
aHdr->msg_control = cbuf;
|
||||||
aHdr->msg_controllen = CMSG_SPACE(sizeof(int) * aMaxNumFds);
|
aHdr->msg_controllen = CMSG_SPACE(sizeof(int) * aMaxNumFds);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete resources allocated by InitMsgHdr().
|
* Delete resources allocated by InitMsgHdr().
|
||||||
*/
|
*/
|
||||||
static void
|
static void DeinitMsgHdr(msghdr* aHdr) {
|
||||||
DeinitMsgHdr(msghdr* aHdr) {
|
delete aHdr->msg_iov;
|
||||||
delete aHdr->msg_iov;
|
delete static_cast<char*>(aHdr->msg_control);
|
||||||
delete static_cast<char*>(aHdr->msg_control);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void MiniTransceiver::PrepareFDs(msghdr* aHdr, IPC::Message& aMsg) {
|
||||||
|
// Set control buffer to send file descriptors of the Message.
|
||||||
|
int num_fds = aMsg.file_descriptor_set()->size();
|
||||||
|
|
||||||
|
cmsghdr* cmsg = CMSG_FIRSTHDR(aHdr);
|
||||||
|
cmsg->cmsg_level = SOL_SOCKET;
|
||||||
|
cmsg->cmsg_type = SCM_RIGHTS;
|
||||||
|
cmsg->cmsg_len = CMSG_LEN(sizeof(int) * num_fds);
|
||||||
|
aMsg.file_descriptor_set()->GetDescriptors(
|
||||||
|
reinterpret_cast<int*>(CMSG_DATA(cmsg)));
|
||||||
|
|
||||||
|
// This number will be sent in the header of the message. So, we
|
||||||
|
// can check it at the other side.
|
||||||
|
aMsg.header()->num_fds = num_fds;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
size_t MiniTransceiver::PrepareBuffers(msghdr* aHdr, IPC::Message& aMsg) {
|
||||||
MiniTransceiver::PrepareFDs(msghdr* aHdr, IPC::Message& aMsg) {
|
// Set iovec to send for all buffers of the Message.
|
||||||
// Set control buffer to send file descriptors of the Message.
|
iovec* iov = aHdr->msg_iov;
|
||||||
int num_fds = aMsg.file_descriptor_set()->size();
|
size_t iovlen = 0;
|
||||||
|
size_t bytes_to_send = 0;
|
||||||
|
for (Pickle::BufferList::IterImpl iter(aMsg.Buffers()); !iter.Done();
|
||||||
|
iter.Advance(aMsg.Buffers(), iter.RemainingInSegment())) {
|
||||||
|
char* data = iter.Data();
|
||||||
|
size_t size = iter.RemainingInSegment();
|
||||||
|
iov[iovlen].iov_base = data;
|
||||||
|
iov[iovlen].iov_len = size;
|
||||||
|
iovlen++;
|
||||||
|
MOZ_ASSERT(iovlen <= kMaxIOVecSize);
|
||||||
|
bytes_to_send += size;
|
||||||
|
}
|
||||||
|
MOZ_ASSERT(bytes_to_send <= kMaxDataSize);
|
||||||
|
aHdr->msg_iovlen = iovlen;
|
||||||
|
|
||||||
cmsghdr *cmsg = CMSG_FIRSTHDR(aHdr);
|
return bytes_to_send;
|
||||||
cmsg->cmsg_level = SOL_SOCKET;
|
|
||||||
cmsg->cmsg_type = SCM_RIGHTS;
|
|
||||||
cmsg->cmsg_len = CMSG_LEN(sizeof(int) * num_fds);
|
|
||||||
aMsg.file_descriptor_set()->GetDescriptors(
|
|
||||||
reinterpret_cast<int*>(CMSG_DATA(cmsg)));
|
|
||||||
|
|
||||||
// This number will be sent in the header of the message. So, we
|
|
||||||
// can check it at the other side.
|
|
||||||
aMsg.header()->num_fds = num_fds;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
bool MiniTransceiver::Send(IPC::Message& aMsg) {
|
||||||
MiniTransceiver::PrepareBuffers(msghdr* aHdr, IPC::Message& aMsg) {
|
|
||||||
// Set iovec to send for all buffers of the Message.
|
|
||||||
iovec *iov = aHdr->msg_iov;
|
|
||||||
size_t iovlen = 0;
|
|
||||||
size_t bytes_to_send = 0;
|
|
||||||
for (Pickle::BufferList::IterImpl iter(aMsg.Buffers());
|
|
||||||
!iter.Done();
|
|
||||||
iter.Advance(aMsg.Buffers(), iter.RemainingInSegment())) {
|
|
||||||
char* data = iter.Data();
|
|
||||||
size_t size = iter.RemainingInSegment();
|
|
||||||
iov[iovlen].iov_base = data;
|
|
||||||
iov[iovlen].iov_len = size;
|
|
||||||
iovlen++;
|
|
||||||
MOZ_ASSERT(iovlen <= kMaxIOVecSize);
|
|
||||||
bytes_to_send += size;
|
|
||||||
}
|
|
||||||
MOZ_ASSERT(bytes_to_send <= kMaxDataSize);
|
|
||||||
aHdr->msg_iovlen = iovlen;
|
|
||||||
|
|
||||||
return bytes_to_send;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
MiniTransceiver::Send(IPC::Message& aMsg) {
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (mState == STATE_SENDING) {
|
if (mState == STATE_SENDING) {
|
||||||
MOZ_CRASH("STATE_SENDING: It violates of request-response and no concurrent rules");
|
MOZ_CRASH(
|
||||||
}
|
"STATE_SENDING: It violates of request-response and no concurrent "
|
||||||
mState = STATE_SENDING;
|
"rules");
|
||||||
|
}
|
||||||
|
mState = STATE_SENDING;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
auto clean_fdset = MakeScopeExit([&] {
|
auto clean_fdset =
|
||||||
aMsg.file_descriptor_set()->CommitAll();
|
MakeScopeExit([&] { aMsg.file_descriptor_set()->CommitAll(); });
|
||||||
});
|
|
||||||
|
|
||||||
int num_fds = aMsg.file_descriptor_set()->size();
|
int num_fds = aMsg.file_descriptor_set()->size();
|
||||||
msghdr hdr;
|
msghdr hdr;
|
||||||
InitMsgHdr(&hdr, kMaxIOVecSize, num_fds);
|
InitMsgHdr(&hdr, kMaxIOVecSize, num_fds);
|
||||||
|
|
||||||
UniquePtr<msghdr, decltype(&DeinitMsgHdr)> uniq(&hdr, &DeinitMsgHdr);
|
UniquePtr<msghdr, decltype(&DeinitMsgHdr)> uniq(&hdr, &DeinitMsgHdr);
|
||||||
|
|
||||||
PrepareFDs(&hdr, aMsg);
|
PrepareFDs(&hdr, aMsg);
|
||||||
DebugOnly<size_t> bytes_to_send = PrepareBuffers(&hdr, aMsg);
|
DebugOnly<size_t> bytes_to_send = PrepareBuffers(&hdr, aMsg);
|
||||||
|
|
||||||
ssize_t bytes_written = HANDLE_EINTR(sendmsg(mFd, &hdr, 0));
|
ssize_t bytes_written = HANDLE_EINTR(sendmsg(mFd, &hdr, 0));
|
||||||
|
|
||||||
if (bytes_written < 0) {
|
if (bytes_written < 0) {
|
||||||
char error[128];
|
char error[128];
|
||||||
SprintfLiteral(error, "sendmsg: %s", strerror(errno));
|
SprintfLiteral(error, "sendmsg: %s", strerror(errno));
|
||||||
NS_WARNING(error);
|
NS_WARNING(error);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
MOZ_ASSERT(bytes_written == (ssize_t)bytes_to_send, "The message is too big?!");
|
MOZ_ASSERT(bytes_written == (ssize_t)bytes_to_send,
|
||||||
|
"The message is too big?!");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned
|
unsigned MiniTransceiver::RecvFDs(msghdr* aHdr, int* aAllFds,
|
||||||
MiniTransceiver::RecvFDs(msghdr* aHdr, int* aAllFds, unsigned aMaxFds) {
|
unsigned aMaxFds) {
|
||||||
if (aHdr->msg_controllen == 0) {
|
if (aHdr->msg_controllen == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned num_all_fds = 0;
|
unsigned num_all_fds = 0;
|
||||||
for (cmsghdr* cmsg = CMSG_FIRSTHDR(aHdr);
|
for (cmsghdr* cmsg = CMSG_FIRSTHDR(aHdr); cmsg;
|
||||||
cmsg;
|
cmsg = CMSG_NXTHDR(aHdr, cmsg)) {
|
||||||
cmsg = CMSG_NXTHDR(aHdr, cmsg)) {
|
MOZ_ASSERT(cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS,
|
||||||
MOZ_ASSERT(cmsg->cmsg_level == SOL_SOCKET &&
|
"Accept only SCM_RIGHTS to receive file descriptors");
|
||||||
cmsg->cmsg_type == SCM_RIGHTS,
|
|
||||||
"Accept only SCM_RIGHTS to receive file descriptors");
|
|
||||||
|
|
||||||
unsigned payload_sz = cmsg->cmsg_len - CMSG_LEN(0);
|
unsigned payload_sz = cmsg->cmsg_len - CMSG_LEN(0);
|
||||||
MOZ_ASSERT(payload_sz % sizeof(int) == 0);
|
MOZ_ASSERT(payload_sz % sizeof(int) == 0);
|
||||||
|
|
||||||
// Add fds to |aAllFds|
|
// Add fds to |aAllFds|
|
||||||
unsigned num_part_fds = payload_sz / sizeof(int);
|
unsigned num_part_fds = payload_sz / sizeof(int);
|
||||||
int* part_fds = reinterpret_cast<int*>(CMSG_DATA(cmsg));
|
int* part_fds = reinterpret_cast<int*>(CMSG_DATA(cmsg));
|
||||||
MOZ_ASSERT(num_all_fds + num_part_fds <= aMaxFds);
|
MOZ_ASSERT(num_all_fds + num_part_fds <= aMaxFds);
|
||||||
|
|
||||||
memcpy(aAllFds + num_all_fds, part_fds, num_part_fds * sizeof(int));
|
memcpy(aAllFds + num_all_fds, part_fds, num_part_fds * sizeof(int));
|
||||||
num_all_fds += num_part_fds;
|
num_all_fds += num_part_fds;
|
||||||
}
|
}
|
||||||
return num_all_fds;
|
return num_all_fds;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool MiniTransceiver::RecvData(char* aDataBuf, size_t aBufSize,
|
||||||
MiniTransceiver::RecvData(char* aDataBuf, size_t aBufSize, uint32_t* aMsgSize,
|
uint32_t* aMsgSize, int* aFdsBuf,
|
||||||
int* aFdsBuf, unsigned aMaxFds, unsigned* aNumFds) {
|
unsigned aMaxFds, unsigned* aNumFds) {
|
||||||
msghdr hdr;
|
msghdr hdr;
|
||||||
InitMsgHdr(&hdr, 1, aMaxFds);
|
InitMsgHdr(&hdr, 1, aMaxFds);
|
||||||
|
|
||||||
UniquePtr<msghdr, decltype(&DeinitMsgHdr)> uniq(&hdr, &DeinitMsgHdr);
|
UniquePtr<msghdr, decltype(&DeinitMsgHdr)> uniq(&hdr, &DeinitMsgHdr);
|
||||||
|
|
||||||
// The buffer to collect all fds received from the socket.
|
// The buffer to collect all fds received from the socket.
|
||||||
int* all_fds = aFdsBuf;
|
int* all_fds = aFdsBuf;
|
||||||
unsigned num_all_fds = 0;
|
unsigned num_all_fds = 0;
|
||||||
|
|
||||||
size_t total_readed = 0;
|
size_t total_readed = 0;
|
||||||
uint32_t msgsz = 0;
|
uint32_t msgsz = 0;
|
||||||
while (msgsz == 0 || total_readed < msgsz) {
|
while (msgsz == 0 || total_readed < msgsz) {
|
||||||
// Set IO vector with the begin of the unused buffer.
|
// Set IO vector with the begin of the unused buffer.
|
||||||
hdr.msg_iov->iov_base = aDataBuf + total_readed;
|
hdr.msg_iov->iov_base = aDataBuf + total_readed;
|
||||||
hdr.msg_iov->iov_len = (msgsz == 0 ? aBufSize : msgsz) - total_readed;
|
hdr.msg_iov->iov_len = (msgsz == 0 ? aBufSize : msgsz) - total_readed;
|
||||||
|
|
||||||
// Read the socket
|
// Read the socket
|
||||||
ssize_t bytes_readed = HANDLE_EINTR(recvmsg(mFd, &hdr, 0));
|
ssize_t bytes_readed = HANDLE_EINTR(recvmsg(mFd, &hdr, 0));
|
||||||
if (bytes_readed <= 0) {
|
if (bytes_readed <= 0) {
|
||||||
// Closed or error!
|
// Closed or error!
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
total_readed += bytes_readed;
|
total_readed += bytes_readed;
|
||||||
MOZ_ASSERT(total_readed <= aBufSize);
|
MOZ_ASSERT(total_readed <= aBufSize);
|
||||||
|
|
||||||
if (msgsz == 0) {
|
if (msgsz == 0) {
|
||||||
// Parse the size of the message.
|
// Parse the size of the message.
|
||||||
// Get 0 if data in the buffer is no enough to get message size.
|
// Get 0 if data in the buffer is no enough to get message size.
|
||||||
msgsz = IPC::Message::MessageSize(aDataBuf, aDataBuf + total_readed);
|
msgsz = IPC::Message::MessageSize(aDataBuf, aDataBuf + total_readed);
|
||||||
}
|
|
||||||
|
|
||||||
num_all_fds += RecvFDs(&hdr, all_fds + num_all_fds, aMaxFds - num_all_fds);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*aMsgSize = msgsz;
|
num_all_fds += RecvFDs(&hdr, all_fds + num_all_fds, aMaxFds - num_all_fds);
|
||||||
*aNumFds = num_all_fds;
|
}
|
||||||
return true;
|
|
||||||
|
*aMsgSize = msgsz;
|
||||||
|
*aNumFds = num_all_fds;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool MiniTransceiver::Recv(IPC::Message& aMsg) {
|
||||||
MiniTransceiver::Recv(IPC::Message& aMsg) {
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (mState == STATE_RECEIVING) {
|
if (mState == STATE_RECEIVING) {
|
||||||
MOZ_CRASH("STATE_RECEIVING: It violates of request-response and no concurrent rules");
|
MOZ_CRASH(
|
||||||
}
|
"STATE_RECEIVING: It violates of request-response and no concurrent "
|
||||||
mState = STATE_RECEIVING;
|
"rules");
|
||||||
|
}
|
||||||
|
mState = STATE_RECEIVING;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
UniquePtr<char[]> databuf = MakeUnique<char[]>(kMaxDataSize);
|
UniquePtr<char[]> databuf = MakeUnique<char[]>(kMaxDataSize);
|
||||||
uint32_t msgsz = 0;
|
uint32_t msgsz = 0;
|
||||||
int all_fds[kMaxNumFds];
|
int all_fds[kMaxNumFds];
|
||||||
unsigned num_all_fds = 0;
|
unsigned num_all_fds = 0;
|
||||||
|
|
||||||
if (!RecvData(databuf.get(), kMaxDataSize, &msgsz,
|
if (!RecvData(databuf.get(), kMaxDataSize, &msgsz, all_fds, kMaxDataSize,
|
||||||
all_fds, kMaxDataSize, &num_all_fds)) {
|
&num_all_fds)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create Message from databuf & all_fds.
|
// Create Message from databuf & all_fds.
|
||||||
UniquePtr<IPC::Message> msg = MakeUnique<IPC::Message>(databuf.get(), msgsz);
|
UniquePtr<IPC::Message> msg = MakeUnique<IPC::Message>(databuf.get(), msgsz);
|
||||||
msg->file_descriptor_set()->SetDescriptors(all_fds, num_all_fds);
|
msg->file_descriptor_set()->SetDescriptors(all_fds, num_all_fds);
|
||||||
|
|
||||||
if (mDataBufClear == DataBufferClear::AfterReceiving) {
|
if (mDataBufClear == DataBufferClear::AfterReceiving) {
|
||||||
// Avoid content processes from reading the content of
|
// Avoid content processes from reading the content of
|
||||||
// messages.
|
// messages.
|
||||||
memset(databuf.get(), 0, msgsz);
|
memset(databuf.get(), 0, msgsz);
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_ASSERT(msg->header()->num_fds == msg->file_descriptor_set()->size(),
|
MOZ_ASSERT(msg->header()->num_fds == msg->file_descriptor_set()->size(),
|
||||||
"The number of file descriptors in the header is different from"
|
"The number of file descriptors in the header is different from"
|
||||||
" the number actually received");
|
" the number actually received");
|
||||||
|
|
||||||
aMsg = std::move(*msg);
|
aMsg = std::move(*msg);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,10 +14,7 @@ struct msghdr;
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace ipc {
|
namespace ipc {
|
||||||
|
|
||||||
enum class DataBufferClear {
|
enum class DataBufferClear { None, AfterReceiving };
|
||||||
None,
|
|
||||||
AfterReceiving
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This simple implementation handles the transmissions of IPC
|
* This simple implementation handles the transmissions of IPC
|
||||||
|
|
@ -31,89 +28,90 @@ enum class DataBufferClear {
|
||||||
* complexity of asynchronous I/O.
|
* complexity of asynchronous I/O.
|
||||||
*/
|
*/
|
||||||
class MiniTransceiver {
|
class MiniTransceiver {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* \param aFd should be a blocking, no O_NONBLOCK, fd.
|
* \param aFd should be a blocking, no O_NONBLOCK, fd.
|
||||||
* \param aClearDataBuf is true to clear data buffers after
|
* \param aClearDataBuf is true to clear data buffers after
|
||||||
* receiving a message.
|
* receiving a message.
|
||||||
*/
|
*/
|
||||||
explicit MiniTransceiver(int aFd, DataBufferClear aDataBufClear = DataBufferClear::None);
|
explicit MiniTransceiver(
|
||||||
|
int aFd, DataBufferClear aDataBufClear = DataBufferClear::None);
|
||||||
|
|
||||||
bool Send(IPC::Message& aMsg);
|
bool Send(IPC::Message& aMsg);
|
||||||
inline bool SendInfallible(IPC::Message& aMsg, const char* aCrashMessage) {
|
inline bool SendInfallible(IPC::Message& aMsg, const char* aCrashMessage) {
|
||||||
bool Ok = Send(aMsg);
|
bool Ok = Send(aMsg);
|
||||||
if (!Ok) {
|
if (!Ok) {
|
||||||
MOZ_CRASH_UNSAFE(aCrashMessage);
|
MOZ_CRASH_UNSAFE(aCrashMessage);
|
||||||
}
|
|
||||||
return Ok;
|
|
||||||
}
|
}
|
||||||
|
return Ok;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \param aMsg will hold the content of the received message.
|
* \param aMsg will hold the content of the received message.
|
||||||
* \return false if the fd is closed or with an error.
|
* \return false if the fd is closed or with an error.
|
||||||
*/
|
*/
|
||||||
bool Recv(IPC::Message& aMsg);
|
bool Recv(IPC::Message& aMsg);
|
||||||
inline bool RecvInfallible(IPC::Message& aMsg, const char* aCrashMessage) {
|
inline bool RecvInfallible(IPC::Message& aMsg, const char* aCrashMessage) {
|
||||||
bool Ok = Recv(aMsg);
|
bool Ok = Recv(aMsg);
|
||||||
if (!Ok) {
|
if (!Ok) {
|
||||||
MOZ_CRASH_UNSAFE(aCrashMessage);
|
MOZ_CRASH_UNSAFE(aCrashMessage);
|
||||||
}
|
|
||||||
return Ok;
|
|
||||||
}
|
}
|
||||||
|
return Ok;
|
||||||
|
}
|
||||||
|
|
||||||
int GetFD() { return mFd; }
|
int GetFD() { return mFd; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* Set control buffer to make file descriptors ready to be sent
|
* Set control buffer to make file descriptors ready to be sent
|
||||||
* through a socket.
|
* through a socket.
|
||||||
*/
|
*/
|
||||||
void PrepareFDs(msghdr* aHdr, IPC::Message& aMsg);
|
void PrepareFDs(msghdr* aHdr, IPC::Message& aMsg);
|
||||||
/**
|
/**
|
||||||
* Collect buffers of the message and make them ready to be sent.
|
* Collect buffers of the message and make them ready to be sent.
|
||||||
*
|
*
|
||||||
* \param aHdr is the structure going to be passed to sendmsg().
|
* \param aHdr is the structure going to be passed to sendmsg().
|
||||||
* \param aMsg is the Message to send.
|
* \param aMsg is the Message to send.
|
||||||
*/
|
*/
|
||||||
size_t PrepareBuffers(msghdr* aHdr, IPC::Message& aMsg);
|
size_t PrepareBuffers(msghdr* aHdr, IPC::Message& aMsg);
|
||||||
/**
|
/**
|
||||||
* Collect file descriptors received.
|
* Collect file descriptors received.
|
||||||
*
|
*
|
||||||
* \param aAllFds is where to store file descriptors.
|
* \param aAllFds is where to store file descriptors.
|
||||||
* \param aMaxFds is how many file descriptors can be stored in aAllFds.
|
* \param aMaxFds is how many file descriptors can be stored in aAllFds.
|
||||||
* \return the number of received file descriptors.
|
* \return the number of received file descriptors.
|
||||||
*/
|
*/
|
||||||
unsigned RecvFDs(msghdr* aHdr, int* aAllFds, unsigned aMaxFds);
|
unsigned RecvFDs(msghdr* aHdr, int* aAllFds, unsigned aMaxFds);
|
||||||
/**
|
/**
|
||||||
* Received data from the socket.
|
* Received data from the socket.
|
||||||
*
|
*
|
||||||
* \param aDataBuf is where to store the data from the socket.
|
* \param aDataBuf is where to store the data from the socket.
|
||||||
* \param aBufSize is the size of the buffer.
|
* \param aBufSize is the size of the buffer.
|
||||||
* \param aMsgSize returns how many bytes were readed from the socket.
|
* \param aMsgSize returns how many bytes were readed from the socket.
|
||||||
* \param aFdsBuf is the buffer to return file desriptors received.
|
* \param aFdsBuf is the buffer to return file desriptors received.
|
||||||
* \param aMaxFds is the number of file descriptors that can be held.
|
* \param aMaxFds is the number of file descriptors that can be held.
|
||||||
* \param aNumFds returns the number of file descriptors received.
|
* \param aNumFds returns the number of file descriptors received.
|
||||||
* \return true if sucess, or false for error.
|
* \return true if sucess, or false for error.
|
||||||
*/
|
*/
|
||||||
bool RecvData(char* aDataBuf, size_t aBufSize, uint32_t* aMsgSize,
|
bool RecvData(char* aDataBuf, size_t aBufSize, uint32_t* aMsgSize,
|
||||||
int* aFdsBuf, unsigned aMaxFds, unsigned* aNumFds);
|
int* aFdsBuf, unsigned aMaxFds, unsigned* aNumFds);
|
||||||
|
|
||||||
int mFd; // The file descriptor of the socket for IPC.
|
int mFd; // The file descriptor of the socket for IPC.
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
enum State {
|
enum State {
|
||||||
STATE_NONE,
|
STATE_NONE,
|
||||||
STATE_SENDING,
|
STATE_SENDING,
|
||||||
STATE_RECEIVING,
|
STATE_RECEIVING,
|
||||||
};
|
};
|
||||||
State mState;
|
State mState;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Clear all received data in temp buffers to avoid data leaking.
|
// Clear all received data in temp buffers to avoid data leaking.
|
||||||
DataBufferClear mDataBufClear;
|
DataBufferClear mDataBufClear;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // ipc
|
} // namespace ipc
|
||||||
} // mozilla
|
} // namespace mozilla
|
||||||
|
|
||||||
#endif // __MINITRANSCEIVER_H_
|
#endif // __MINITRANSCEIVER_H_
|
||||||
|
|
|
||||||
|
|
@ -1099,7 +1099,8 @@ static bool GetDisplayPortImpl(
|
||||||
result = GetDisplayPortFromRectData(aContent, rectData, aMultiplier);
|
result = GetDisplayPortFromRectData(aContent, rectData, aMultiplier);
|
||||||
} else if (isDisplayportSuppressed ||
|
} else if (isDisplayportSuppressed ||
|
||||||
nsLayoutUtils::ShouldDisableApzForElement(aContent)) {
|
nsLayoutUtils::ShouldDisableApzForElement(aContent)) {
|
||||||
DisplayPortMarginsPropertyData noMargins(ScreenMargin(), 1, /*painted=*/false);
|
DisplayPortMarginsPropertyData noMargins(ScreenMargin(), 1,
|
||||||
|
/*painted=*/false);
|
||||||
result = GetDisplayPortFromMarginsData(aContent, &noMargins, aMultiplier);
|
result = GetDisplayPortFromMarginsData(aContent, &noMargins, aMultiplier);
|
||||||
} else {
|
} else {
|
||||||
result = GetDisplayPortFromMarginsData(aContent, marginsData, aMultiplier);
|
result = GetDisplayPortFromMarginsData(aContent, marginsData, aMultiplier);
|
||||||
|
|
@ -1143,8 +1144,7 @@ bool nsLayoutUtils::GetDisplayPort(
|
||||||
bool usingDisplayPort =
|
bool usingDisplayPort =
|
||||||
GetDisplayPortImpl(aContent, aResult, multiplier,
|
GetDisplayPortImpl(aContent, aResult, multiplier,
|
||||||
MaxSizeExceededBehaviour::Assert, aOutPainted);
|
MaxSizeExceededBehaviour::Assert, aOutPainted);
|
||||||
if (aResult && usingDisplayPort &&
|
if (aResult && usingDisplayPort && aRelativeTo == RelativeTo::ScrollFrame) {
|
||||||
aRelativeTo == RelativeTo::ScrollFrame) {
|
|
||||||
TranslateFromScrollPortToScrollFrame(aContent, aResult);
|
TranslateFromScrollPortToScrollFrame(aContent, aResult);
|
||||||
}
|
}
|
||||||
return usingDisplayPort;
|
return usingDisplayPort;
|
||||||
|
|
|
||||||
|
|
@ -915,7 +915,7 @@ void nsFieldSetFrame::EnsureChildContinuation(nsIFrame* aChild,
|
||||||
}
|
}
|
||||||
if (aStatus.IsOverflowIncomplete()) {
|
if (aStatus.IsOverflowIncomplete()) {
|
||||||
if (nsFrameList* eoc =
|
if (nsFrameList* eoc =
|
||||||
GetPropTableFrames(ExcessOverflowContainersProperty())) {
|
GetPropTableFrames(ExcessOverflowContainersProperty())) {
|
||||||
eoc->AppendFrames(nullptr, nifs);
|
eoc->AppendFrames(nullptr, nifs);
|
||||||
} else {
|
} else {
|
||||||
SetPropTableFrames(new (PresShell()) nsFrameList(nifs),
|
SetPropTableFrames(new (PresShell()) nsFrameList(nifs),
|
||||||
|
|
|
||||||
|
|
@ -485,8 +485,7 @@ bool nsImageFrame::UpdateIntrinsicSize() {
|
||||||
return mIntrinsicSize != oldIntrinsicSize;
|
return mIntrinsicSize != oldIntrinsicSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
static AspectRatio ComputeAspectRatio(imgIContainer* aImage,
|
static AspectRatio ComputeAspectRatio(imgIContainer* aImage, bool aHasRequest,
|
||||||
bool aHasRequest,
|
|
||||||
const nsImageFrame& aFrame) {
|
const nsImageFrame& aFrame) {
|
||||||
const ComputedStyle& style = *aFrame.Style();
|
const ComputedStyle& style = *aFrame.Style();
|
||||||
if (style.StyleDisplay()->IsContainSize()) {
|
if (style.StyleDisplay()->IsContainSize()) {
|
||||||
|
|
@ -718,8 +717,7 @@ void nsImageFrame::UpdateImage(imgIRequest* aRequest, imgIContainer* aImage) {
|
||||||
}
|
}
|
||||||
// NOTE(emilio): Intentionally using `|` instead of `||` to avoid
|
// NOTE(emilio): Intentionally using `|` instead of `||` to avoid
|
||||||
// short-circuiting.
|
// short-circuiting.
|
||||||
bool intrinsicSizeChanged =
|
bool intrinsicSizeChanged = UpdateIntrinsicSize() | UpdateIntrinsicRatio();
|
||||||
UpdateIntrinsicSize() | UpdateIntrinsicRatio();
|
|
||||||
if (!GotInitialReflow()) {
|
if (!GotInitialReflow()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -71,8 +71,7 @@ class nsMathMLContainerFrame : public nsContainerFrame, public nsMathMLFrame {
|
||||||
if (aFlags & (eLineParticipant | eSupportsContainLayoutAndPaint)) {
|
if (aFlags & (eLineParticipant | eSupportsContainLayoutAndPaint)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return nsContainerFrame::IsFrameOfType(
|
return nsContainerFrame::IsFrameOfType(aFlags & ~eMathML);
|
||||||
aFlags & ~eMathML);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void AppendFrames(ChildListID aListID,
|
virtual void AppendFrames(ChildListID aListID,
|
||||||
|
|
@ -419,8 +418,7 @@ class nsMathMLmathBlockFrame final : public nsBlockFrame {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool IsFrameOfType(uint32_t aFlags) const override {
|
virtual bool IsFrameOfType(uint32_t aFlags) const override {
|
||||||
return nsBlockFrame::IsFrameOfType(
|
return nsBlockFrame::IsFrameOfType(aFlags & ~nsIFrame::eMathML);
|
||||||
aFlags & ~nsIFrame::eMathML);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// See nsIMathMLFrame.h
|
// See nsIMathMLFrame.h
|
||||||
|
|
@ -488,8 +486,7 @@ class nsMathMLmathInlineFrame final : public nsInlineFrame,
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool IsFrameOfType(uint32_t aFlags) const override {
|
virtual bool IsFrameOfType(uint32_t aFlags) const override {
|
||||||
return nsInlineFrame::IsFrameOfType(
|
return nsInlineFrame::IsFrameOfType(aFlags & ~nsIFrame::eMathML);
|
||||||
aFlags & ~nsIFrame::eMathML);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsMrowLike() override {
|
bool IsMrowLike() override {
|
||||||
|
|
|
||||||
|
|
@ -272,8 +272,7 @@ class nsMathMLmtdInnerFrame final : public nsBlockFrame, public nsMathMLFrame {
|
||||||
nsReflowStatus& aStatus) override;
|
nsReflowStatus& aStatus) override;
|
||||||
|
|
||||||
virtual bool IsFrameOfType(uint32_t aFlags) const override {
|
virtual bool IsFrameOfType(uint32_t aFlags) const override {
|
||||||
return nsBlockFrame::IsFrameOfType(
|
return nsBlockFrame::IsFrameOfType(aFlags & ~nsIFrame::eMathML);
|
||||||
aFlags & ~nsIFrame::eMathML);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual const nsStyleText* StyleTextForLineLayout() override;
|
virtual const nsStyleText* StyleTextForLineLayout() override;
|
||||||
|
|
|
||||||
|
|
@ -116,8 +116,8 @@ class nsBoxFrame : public nsContainerFrame {
|
||||||
// that contains a block so ReflowInput doesn't tell us to be
|
// that contains a block so ReflowInput doesn't tell us to be
|
||||||
// NS_UNCONSTRAINEDSIZE wide.)
|
// NS_UNCONSTRAINEDSIZE wide.)
|
||||||
return nsContainerFrame::IsFrameOfType(
|
return nsContainerFrame::IsFrameOfType(
|
||||||
aFlags & ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock |
|
aFlags &
|
||||||
eXULBox));
|
~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock | eXULBox));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_FRAME_DUMP
|
#ifdef DEBUG_FRAME_DUMP
|
||||||
|
|
|
||||||
|
|
@ -1407,7 +1407,7 @@ TEST_F(VideoConduitTest, TestVideoEncodeMaxFsNegotiatedThenSinkWants) {
|
||||||
SendVideoFrame(1280, 720, frame++);
|
SendVideoFrame(1280, 720, frame++);
|
||||||
ASSERT_EQ(sink->mVideoFrame.width(), 960);
|
ASSERT_EQ(sink->mVideoFrame.width(), 960);
|
||||||
ASSERT_EQ(sink->mVideoFrame.height(), 540);
|
ASSERT_EQ(sink->mVideoFrame.height(), 540);
|
||||||
ASSERT_EQ(sink->mVideoFrame.timestamp_us(), (frame-1)*1000);
|
ASSERT_EQ(sink->mVideoFrame.timestamp_us(), (frame - 1) * 1000);
|
||||||
ASSERT_EQ(sink->mOnFrameCount, frame);
|
ASSERT_EQ(sink->mOnFrameCount, frame);
|
||||||
|
|
||||||
wants.max_pixel_count = 3600 * 16 * 16;
|
wants.max_pixel_count = 3600 * 16 * 16;
|
||||||
|
|
@ -1416,7 +1416,7 @@ TEST_F(VideoConduitTest, TestVideoEncodeMaxFsNegotiatedThenSinkWants) {
|
||||||
SendVideoFrame(1280, 720, frame++);
|
SendVideoFrame(1280, 720, frame++);
|
||||||
ASSERT_EQ(sink->mVideoFrame.width(), 960);
|
ASSERT_EQ(sink->mVideoFrame.width(), 960);
|
||||||
ASSERT_EQ(sink->mVideoFrame.height(), 540);
|
ASSERT_EQ(sink->mVideoFrame.height(), 540);
|
||||||
ASSERT_EQ(sink->mVideoFrame.timestamp_us(), (frame-1)*1000);
|
ASSERT_EQ(sink->mVideoFrame.timestamp_us(), (frame - 1) * 1000);
|
||||||
ASSERT_EQ(sink->mOnFrameCount, frame);
|
ASSERT_EQ(sink->mOnFrameCount, frame);
|
||||||
|
|
||||||
mVideoConduit->StopTransmitting();
|
mVideoConduit->StopTransmitting();
|
||||||
|
|
@ -1445,7 +1445,7 @@ TEST_F(VideoConduitTest, TestVideoEncodeMaxFsCodecChange) {
|
||||||
SendVideoFrame(1280, 720, frame++);
|
SendVideoFrame(1280, 720, frame++);
|
||||||
ASSERT_EQ(sink->mVideoFrame.width(), 960);
|
ASSERT_EQ(sink->mVideoFrame.width(), 960);
|
||||||
ASSERT_EQ(sink->mVideoFrame.height(), 540);
|
ASSERT_EQ(sink->mVideoFrame.height(), 540);
|
||||||
ASSERT_EQ(sink->mVideoFrame.timestamp_us(), (frame-1)*1000);
|
ASSERT_EQ(sink->mVideoFrame.timestamp_us(), (frame - 1) * 1000);
|
||||||
ASSERT_EQ(sink->mOnFrameCount, frame);
|
ASSERT_EQ(sink->mOnFrameCount, frame);
|
||||||
|
|
||||||
VideoCodecConfig codecConfigVP9(121, "VP9", constraints);
|
VideoCodecConfig codecConfigVP9(121, "VP9", constraints);
|
||||||
|
|
@ -1457,7 +1457,7 @@ TEST_F(VideoConduitTest, TestVideoEncodeMaxFsCodecChange) {
|
||||||
SendVideoFrame(1280, 720, frame++);
|
SendVideoFrame(1280, 720, frame++);
|
||||||
ASSERT_EQ(sink->mVideoFrame.width(), 960);
|
ASSERT_EQ(sink->mVideoFrame.width(), 960);
|
||||||
ASSERT_EQ(sink->mVideoFrame.height(), 540);
|
ASSERT_EQ(sink->mVideoFrame.height(), 540);
|
||||||
ASSERT_EQ(sink->mVideoFrame.timestamp_us(), (frame-1)*1000);
|
ASSERT_EQ(sink->mVideoFrame.timestamp_us(), (frame - 1) * 1000);
|
||||||
ASSERT_EQ(sink->mOnFrameCount, frame);
|
ASSERT_EQ(sink->mOnFrameCount, frame);
|
||||||
|
|
||||||
mVideoConduit->StopTransmitting();
|
mVideoConduit->StopTransmitting();
|
||||||
|
|
@ -1486,7 +1486,7 @@ TEST_F(VideoConduitTest, TestVideoEncodeMaxFsSinkWantsThenCodecChange) {
|
||||||
SendVideoFrame(1280, 720, frame++);
|
SendVideoFrame(1280, 720, frame++);
|
||||||
ASSERT_EQ(sink->mVideoFrame.width(), 960);
|
ASSERT_EQ(sink->mVideoFrame.width(), 960);
|
||||||
ASSERT_EQ(sink->mVideoFrame.height(), 540);
|
ASSERT_EQ(sink->mVideoFrame.height(), 540);
|
||||||
ASSERT_EQ(sink->mVideoFrame.timestamp_us(), (frame-1)*1000);
|
ASSERT_EQ(sink->mVideoFrame.timestamp_us(), (frame - 1) * 1000);
|
||||||
ASSERT_EQ(sink->mOnFrameCount, frame);
|
ASSERT_EQ(sink->mOnFrameCount, frame);
|
||||||
|
|
||||||
VideoCodecConfig codecConfigVP9(121, "VP9", constraints);
|
VideoCodecConfig codecConfigVP9(121, "VP9", constraints);
|
||||||
|
|
@ -1497,7 +1497,7 @@ TEST_F(VideoConduitTest, TestVideoEncodeMaxFsSinkWantsThenCodecChange) {
|
||||||
SendVideoFrame(1280, 720, frame++);
|
SendVideoFrame(1280, 720, frame++);
|
||||||
ASSERT_EQ(sink->mVideoFrame.width(), 960);
|
ASSERT_EQ(sink->mVideoFrame.width(), 960);
|
||||||
ASSERT_EQ(sink->mVideoFrame.height(), 540);
|
ASSERT_EQ(sink->mVideoFrame.height(), 540);
|
||||||
ASSERT_EQ(sink->mVideoFrame.timestamp_us(), (frame-1)*1000);
|
ASSERT_EQ(sink->mVideoFrame.timestamp_us(), (frame - 1) * 1000);
|
||||||
ASSERT_EQ(sink->mOnFrameCount, frame);
|
ASSERT_EQ(sink->mOnFrameCount, frame);
|
||||||
|
|
||||||
mVideoConduit->StopTransmitting();
|
mVideoConduit->StopTransmitting();
|
||||||
|
|
@ -1524,7 +1524,7 @@ TEST_F(VideoConduitTest, TestVideoEncodeMaxFsNegotiated) {
|
||||||
SendVideoFrame(1280, 720, frame++);
|
SendVideoFrame(1280, 720, frame++);
|
||||||
ASSERT_EQ(sink->mVideoFrame.width(), 1280);
|
ASSERT_EQ(sink->mVideoFrame.width(), 1280);
|
||||||
ASSERT_EQ(sink->mVideoFrame.height(), 720);
|
ASSERT_EQ(sink->mVideoFrame.height(), 720);
|
||||||
ASSERT_EQ(sink->mVideoFrame.timestamp_us(), (frame-1)*1000);
|
ASSERT_EQ(sink->mVideoFrame.timestamp_us(), (frame - 1) * 1000);
|
||||||
ASSERT_EQ(sink->mOnFrameCount, frame);
|
ASSERT_EQ(sink->mOnFrameCount, frame);
|
||||||
|
|
||||||
// Ensure that negotiating a new max-fs works
|
// Ensure that negotiating a new max-fs works
|
||||||
|
|
@ -1535,7 +1535,7 @@ TEST_F(VideoConduitTest, TestVideoEncodeMaxFsNegotiated) {
|
||||||
SendVideoFrame(1280, 720, frame++);
|
SendVideoFrame(1280, 720, frame++);
|
||||||
ASSERT_EQ(sink->mVideoFrame.width(), 960);
|
ASSERT_EQ(sink->mVideoFrame.width(), 960);
|
||||||
ASSERT_EQ(sink->mVideoFrame.height(), 540);
|
ASSERT_EQ(sink->mVideoFrame.height(), 540);
|
||||||
ASSERT_EQ(sink->mVideoFrame.timestamp_us(), (frame-1)*1000);
|
ASSERT_EQ(sink->mVideoFrame.timestamp_us(), (frame - 1) * 1000);
|
||||||
ASSERT_EQ(sink->mOnFrameCount, frame);
|
ASSERT_EQ(sink->mOnFrameCount, frame);
|
||||||
|
|
||||||
// Ensure that negotiating max-fs away works
|
// Ensure that negotiating max-fs away works
|
||||||
|
|
@ -1546,7 +1546,7 @@ TEST_F(VideoConduitTest, TestVideoEncodeMaxFsNegotiated) {
|
||||||
SendVideoFrame(1280, 720, frame++);
|
SendVideoFrame(1280, 720, frame++);
|
||||||
ASSERT_EQ(sink->mVideoFrame.width(), 1280);
|
ASSERT_EQ(sink->mVideoFrame.width(), 1280);
|
||||||
ASSERT_EQ(sink->mVideoFrame.height(), 720);
|
ASSERT_EQ(sink->mVideoFrame.height(), 720);
|
||||||
ASSERT_EQ(sink->mVideoFrame.timestamp_us(), (frame-1)*1000);
|
ASSERT_EQ(sink->mVideoFrame.timestamp_us(), (frame - 1) * 1000);
|
||||||
ASSERT_EQ(sink->mOnFrameCount, frame);
|
ASSERT_EQ(sink->mOnFrameCount, frame);
|
||||||
|
|
||||||
mVideoConduit->StopTransmitting();
|
mVideoConduit->StopTransmitting();
|
||||||
|
|
|
||||||
|
|
@ -208,8 +208,9 @@ class WebrtcVideoConduit
|
||||||
*/
|
*/
|
||||||
void AddOrUpdateSink(rtc::VideoSinkInterface<webrtc::VideoFrame>* sink,
|
void AddOrUpdateSink(rtc::VideoSinkInterface<webrtc::VideoFrame>* sink,
|
||||||
const rtc::VideoSinkWants& wants) override;
|
const rtc::VideoSinkWants& wants) override;
|
||||||
void AddOrUpdateSinkNotLocked(rtc::VideoSinkInterface<webrtc::VideoFrame>* sink,
|
void AddOrUpdateSinkNotLocked(
|
||||||
const rtc::VideoSinkWants& wants);
|
rtc::VideoSinkInterface<webrtc::VideoFrame>* sink,
|
||||||
|
const rtc::VideoSinkWants& wants);
|
||||||
|
|
||||||
void RemoveSink(rtc::VideoSinkInterface<webrtc::VideoFrame>* sink) override;
|
void RemoveSink(rtc::VideoSinkInterface<webrtc::VideoFrame>* sink) override;
|
||||||
void RemoveSinkNotLocked(rtc::VideoSinkInterface<webrtc::VideoFrame>* sink);
|
void RemoveSinkNotLocked(rtc::VideoSinkInterface<webrtc::VideoFrame>* sink);
|
||||||
|
|
|
||||||
|
|
@ -12,18 +12,19 @@
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
class RTCStatsIdGenerator {
|
class RTCStatsIdGenerator {
|
||||||
public:
|
public:
|
||||||
RTCStatsIdGenerator();
|
RTCStatsIdGenerator();
|
||||||
nsString Id(const nsString& aKey);
|
nsString Id(const nsString& aKey);
|
||||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RTCStatsIdGenerator);
|
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RTCStatsIdGenerator);
|
||||||
private:
|
|
||||||
virtual ~RTCStatsIdGenerator() {};
|
|
||||||
nsString Generate();
|
|
||||||
|
|
||||||
const uint64_t mSalt;
|
private:
|
||||||
uint64_t mCounter;
|
virtual ~RTCStatsIdGenerator(){};
|
||||||
std::map<nsString, nsString> mAllocated;
|
nsString Generate();
|
||||||
|
|
||||||
|
const uint64_t mSalt;
|
||||||
|
uint64_t mCounter;
|
||||||
|
std::map<nsString, nsString> mAllocated;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace mozilla
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,7 @@ class RangedPtr {
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_IMPLICIT RangedPtr(const RangedPtr<T>& aOther)
|
MOZ_IMPLICIT RangedPtr(const RangedPtr<T>& aOther)
|
||||||
: mPtr(aOther.mPtr)
|
: mPtr(aOther.mPtr)
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
,
|
,
|
||||||
mRangeStart(aOther.mRangeStart),
|
mRangeStart(aOther.mRangeStart),
|
||||||
|
|
|
||||||
|
|
@ -241,9 +241,7 @@ struct MemorySectionNameBuf : public _MEMORY_SECTION_NAME {
|
||||||
mSectionFileName.Buffer = mBuf;
|
mSectionFileName.Buffer = mBuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
MemorySectionNameBuf(const MemorySectionNameBuf& aOther) {
|
MemorySectionNameBuf(const MemorySectionNameBuf& aOther) { *this = aOther; }
|
||||||
*this = aOther;
|
|
||||||
}
|
|
||||||
|
|
||||||
MemorySectionNameBuf(MemorySectionNameBuf&& aOther) {
|
MemorySectionNameBuf(MemorySectionNameBuf&& aOther) {
|
||||||
*this = std::move(aOther);
|
*this = std::move(aOther);
|
||||||
|
|
|
||||||
|
|
@ -1075,7 +1075,7 @@ class OutboundMessage {
|
||||||
class OutboundEnqueuer final : public Runnable {
|
class OutboundEnqueuer final : public Runnable {
|
||||||
public:
|
public:
|
||||||
OutboundEnqueuer(WebSocketChannel* aChannel, OutboundMessage* aMsg)
|
OutboundEnqueuer(WebSocketChannel* aChannel, OutboundMessage* aMsg)
|
||||||
: Runnable("OutboundEnquerer"), mChannel(aChannel), mMessage(aMsg) {}
|
: Runnable("OutboundEnquerer"), mChannel(aChannel), mMessage(aMsg) {}
|
||||||
|
|
||||||
NS_IMETHOD Run() override {
|
NS_IMETHOD Run() override {
|
||||||
mChannel->EnqueueOutgoingMessage(mChannel->mOutgoingMessages, mMessage);
|
mChannel->EnqueueOutgoingMessage(mChannel->mOutgoingMessages, mMessage);
|
||||||
|
|
|
||||||
|
|
@ -204,8 +204,8 @@ void nsAndroidNetworkLinkService::OnLinkStatusKnown() { mStatusIsKnown = true; }
|
||||||
|
|
||||||
void nsAndroidNetworkLinkService::OnDnsSuffixListUpdated() {
|
void nsAndroidNetworkLinkService::OnDnsSuffixListUpdated() {
|
||||||
RefPtr<nsAndroidNetworkLinkService> self = this;
|
RefPtr<nsAndroidNetworkLinkService> self = this;
|
||||||
NS_DispatchToMainThread(
|
NS_DispatchToMainThread(NS_NewRunnableFunction(
|
||||||
NS_NewRunnableFunction("nsAndroidNetworkLinkService::OnDnsSuffixListUpdated", [self]() {
|
"nsAndroidNetworkLinkService::OnDnsSuffixListUpdated", [self]() {
|
||||||
self->NotifyObservers(NS_DNS_SUFFIX_LIST_UPDATED_TOPIC, nullptr);
|
self->NotifyObservers(NS_DNS_SUFFIX_LIST_UPDATED_TOPIC, nullptr);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -169,8 +169,8 @@ void nsNetworkLinkService::OnLinkStatusKnown() { mStatusIsKnown = true; }
|
||||||
|
|
||||||
void nsNetworkLinkService::OnDnsSuffixListUpdated() {
|
void nsNetworkLinkService::OnDnsSuffixListUpdated() {
|
||||||
RefPtr<nsNetworkLinkService> self = this;
|
RefPtr<nsNetworkLinkService> self = this;
|
||||||
NS_DispatchToMainThread(
|
NS_DispatchToMainThread(NS_NewRunnableFunction(
|
||||||
NS_NewRunnableFunction("nsNetworkLinkService::OnDnsSuffixListUpdated", [self]() {
|
"nsNetworkLinkService::OnDnsSuffixListUpdated", [self]() {
|
||||||
self->NotifyObservers(NS_DNS_SUFFIX_LIST_UPDATED_TOPIC, nullptr);
|
self->NotifyObservers(NS_DNS_SUFFIX_LIST_UPDATED_TOPIC, nullptr);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -221,9 +221,8 @@ static int FuzzingRunNetworkHttp(const uint8_t* data, size_t size) {
|
||||||
bool mainPingBack = false;
|
bool mainPingBack = false;
|
||||||
|
|
||||||
NS_DispatchBackgroundTask(NS_NewRunnableFunction("Dummy", [&]() {
|
NS_DispatchBackgroundTask(NS_NewRunnableFunction("Dummy", [&]() {
|
||||||
NS_DispatchToMainThread(NS_NewRunnableFunction("Dummy", [&]() {
|
NS_DispatchToMainThread(
|
||||||
mainPingBack = true;
|
NS_NewRunnableFunction("Dummy", [&]() { mainPingBack = true; }));
|
||||||
}));
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
SpinEventLoopUntil([&]() -> bool { return mainPingBack; });
|
SpinEventLoopUntil([&]() -> bool { return mainPingBack; });
|
||||||
|
|
|
||||||
|
|
@ -209,8 +209,7 @@ static void AttachSandboxReporter(base::file_handle_mapping_vector* aFdMap) {
|
||||||
|
|
||||||
class SandboxFork : public base::LaunchOptions::ForkDelegate {
|
class SandboxFork : public base::LaunchOptions::ForkDelegate {
|
||||||
public:
|
public:
|
||||||
explicit SandboxFork(int aFlags, bool aChroot,
|
explicit SandboxFork(int aFlags, bool aChroot, int aServerFd = -1,
|
||||||
int aServerFd = -1,
|
|
||||||
int aClientFd = -1);
|
int aClientFd = -1);
|
||||||
virtual ~SandboxFork();
|
virtual ~SandboxFork();
|
||||||
|
|
||||||
|
|
@ -335,7 +334,7 @@ void SandboxLaunchPrepare(GeckoProcessType aType,
|
||||||
aOptions->fork_delegate = std::move(forker);
|
aOptions->fork_delegate = std::move(forker);
|
||||||
// Pass to |SandboxLaunchForkServerPrepare()| in the fork server.
|
// Pass to |SandboxLaunchForkServerPrepare()| in the fork server.
|
||||||
aOptions->env_map[kSandboxChrootEnvFlag] =
|
aOptions->env_map[kSandboxChrootEnvFlag] =
|
||||||
std::to_string(canChroot ? 1 : 0) + std::to_string(flags);
|
std::to_string(canChroot ? 1 : 0) + std::to_string(flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -349,11 +348,9 @@ void SandboxLaunchPrepare(GeckoProcessType aType,
|
||||||
*/
|
*/
|
||||||
void SandboxLaunchForkServerPrepare(const std::vector<std::string>& aArgv,
|
void SandboxLaunchForkServerPrepare(const std::vector<std::string>& aArgv,
|
||||||
base::LaunchOptions& aOptions) {
|
base::LaunchOptions& aOptions) {
|
||||||
auto chroot = std::find_if(aOptions.env_map.begin(),
|
auto chroot = std::find_if(
|
||||||
aOptions.env_map.end(),
|
aOptions.env_map.begin(), aOptions.env_map.end(),
|
||||||
[](auto& elt) {
|
[](auto& elt) { return elt.first == kSandboxChrootEnvFlag; });
|
||||||
return elt.first == kSandboxChrootEnvFlag;
|
|
||||||
});
|
|
||||||
if (chroot == aOptions.env_map.end()) {
|
if (chroot == aOptions.env_map.end()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -363,11 +360,9 @@ void SandboxLaunchForkServerPrepare(const std::vector<std::string>& aArgv,
|
||||||
|
|
||||||
// Find chroot server fd. It is supposed to be map to
|
// Find chroot server fd. It is supposed to be map to
|
||||||
// kSandboxChrootServerFd so that we find it out from the mapping.
|
// kSandboxChrootServerFd so that we find it out from the mapping.
|
||||||
auto fdmap = std::find_if(aOptions.fds_to_remap.begin(),
|
auto fdmap = std::find_if(
|
||||||
aOptions.fds_to_remap.end(),
|
aOptions.fds_to_remap.begin(), aOptions.fds_to_remap.end(),
|
||||||
[](auto& elt) {
|
[](auto& elt) { return elt.second == kSandboxChrootServerFd; });
|
||||||
return elt.second == kSandboxChrootServerFd;
|
|
||||||
});
|
|
||||||
MOZ_ASSERT(fdmap != aOptions.fds_to_remap.end(),
|
MOZ_ASSERT(fdmap != aOptions.fds_to_remap.end(),
|
||||||
"ChrootServerFd is not found with sandbox chroot");
|
"ChrootServerFd is not found with sandbox chroot");
|
||||||
int chrootserverfd = fdmap->first;
|
int chrootserverfd = fdmap->first;
|
||||||
|
|
|
||||||
|
|
@ -267,8 +267,7 @@ void XRE_SetAndroidChildFds(JNIEnv* env, const XRE_AndroidChildFds& fds) {
|
||||||
|
|
||||||
void XRE_SetProcessType(const char* aProcessTypeString) {
|
void XRE_SetProcessType(const char* aProcessTypeString) {
|
||||||
static bool called = false;
|
static bool called = false;
|
||||||
if (called &&
|
if (called && sChildProcessType != GeckoProcessType_ForkServer) {
|
||||||
sChildProcessType != GeckoProcessType_ForkServer) {
|
|
||||||
MOZ_CRASH();
|
MOZ_CRASH();
|
||||||
}
|
}
|
||||||
called = true;
|
called = true;
|
||||||
|
|
|
||||||
|
|
@ -29,15 +29,15 @@ namespace mozilla {
|
||||||
namespace widget {
|
namespace widget {
|
||||||
|
|
||||||
typedef ABI::Windows::Foundation::ITypedEventHandler<
|
typedef ABI::Windows::Foundation::ITypedEventHandler<
|
||||||
ABI::Windows::UI::Notifications::ToastNotification *, IInspectable *>
|
ABI::Windows::UI::Notifications::ToastNotification*, IInspectable*>
|
||||||
ToastActivationHandler;
|
ToastActivationHandler;
|
||||||
typedef ABI::Windows::Foundation::ITypedEventHandler<
|
typedef ABI::Windows::Foundation::ITypedEventHandler<
|
||||||
ABI::Windows::UI::Notifications::ToastNotification *,
|
ABI::Windows::UI::Notifications::ToastNotification*,
|
||||||
ABI::Windows::UI::Notifications::ToastDismissedEventArgs *>
|
ABI::Windows::UI::Notifications::ToastDismissedEventArgs*>
|
||||||
ToastDismissedHandler;
|
ToastDismissedHandler;
|
||||||
typedef ABI::Windows::Foundation::ITypedEventHandler<
|
typedef ABI::Windows::Foundation::ITypedEventHandler<
|
||||||
ABI::Windows::UI::Notifications::ToastNotification *,
|
ABI::Windows::UI::Notifications::ToastNotification*,
|
||||||
ABI::Windows::UI::Notifications::ToastFailedEventArgs *>
|
ABI::Windows::UI::Notifications::ToastFailedEventArgs*>
|
||||||
ToastFailedHandler;
|
ToastFailedHandler;
|
||||||
|
|
||||||
using namespace ABI::Windows::Data::Xml::Dom;
|
using namespace ABI::Windows::Data::Xml::Dom;
|
||||||
|
|
@ -49,11 +49,11 @@ using namespace mozilla;
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS(ToastNotificationHandler, nsIAlertNotificationImageListener)
|
NS_IMPL_ISUPPORTS(ToastNotificationHandler, nsIAlertNotificationImageListener)
|
||||||
|
|
||||||
static bool SetNodeValueString(const nsString &aString, IXmlNode *node,
|
static bool SetNodeValueString(const nsString& aString, IXmlNode* node,
|
||||||
IXmlDocument *xml) {
|
IXmlDocument* xml) {
|
||||||
ComPtr<IXmlText> inputText;
|
ComPtr<IXmlText> inputText;
|
||||||
if (NS_WARN_IF(FAILED(xml->CreateTextNode(
|
if (NS_WARN_IF(FAILED(xml->CreateTextNode(
|
||||||
HStringReference(static_cast<const wchar_t *>(aString.get())).Get(),
|
HStringReference(static_cast<const wchar_t*>(aString.get())).Get(),
|
||||||
&inputText)))) {
|
&inputText)))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -69,9 +69,9 @@ static bool SetNodeValueString(const nsString &aString, IXmlNode *node,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool SetAttribute(IXmlElement *element, const HSTRING name,
|
static bool SetAttribute(IXmlElement* element, const HSTRING name,
|
||||||
const nsAString &value) {
|
const nsAString& value) {
|
||||||
HSTRING valueStr = HStringReference(static_cast<const wchar_t *>(
|
HSTRING valueStr = HStringReference(static_cast<const wchar_t*>(
|
||||||
PromiseFlatString(value).get()))
|
PromiseFlatString(value).get()))
|
||||||
.Get();
|
.Get();
|
||||||
if (NS_WARN_IF(FAILED(element->SetAttribute(name, valueStr)))) {
|
if (NS_WARN_IF(FAILED(element->SetAttribute(name, valueStr)))) {
|
||||||
|
|
@ -80,9 +80,9 @@ static bool SetAttribute(IXmlElement *element, const HSTRING name,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool AddActionNode(IXmlDocument *toastXml, IXmlNode *actionsNode,
|
static bool AddActionNode(IXmlDocument* toastXml, IXmlNode* actionsNode,
|
||||||
const nsAString &actionTitle,
|
const nsAString& actionTitle,
|
||||||
const nsAString &actionArgs) {
|
const nsAString& actionArgs) {
|
||||||
ComPtr<IXmlElement> action;
|
ComPtr<IXmlElement> action;
|
||||||
HRESULT hr =
|
HRESULT hr =
|
||||||
toastXml->CreateElement(HStringReference(L"action").Get(), &action);
|
toastXml->CreateElement(HStringReference(L"action").Get(), &action);
|
||||||
|
|
@ -174,8 +174,8 @@ ComPtr<IXmlDocument> ToastNotificationHandler::InitializeXmlForTemplate(
|
||||||
return toastXml;
|
return toastXml;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult ToastNotificationHandler::InitAlertAsync(
|
||||||
ToastNotificationHandler::InitAlertAsync(nsIAlertNotification *aAlert) {
|
nsIAlertNotification* aAlert) {
|
||||||
return aAlert->LoadImage(/* aTimeout = */ 0, this, /* aUserData = */ nullptr,
|
return aAlert->LoadImage(/* aTimeout = */ 0, this, /* aUserData = */ nullptr,
|
||||||
getter_AddRefs(mImageRequest));
|
getter_AddRefs(mImageRequest));
|
||||||
}
|
}
|
||||||
|
|
@ -341,7 +341,7 @@ bool ToastNotificationHandler::ShowAlert() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ToastNotificationHandler::CreateWindowsNotificationFromXml(
|
bool ToastNotificationHandler::CreateWindowsNotificationFromXml(
|
||||||
IXmlDocument *aXml) {
|
IXmlDocument* aXml) {
|
||||||
ComPtr<IToastNotificationFactory> factory;
|
ComPtr<IToastNotificationFactory> factory;
|
||||||
HRESULT hr = GetActivationFactory(
|
HRESULT hr = GetActivationFactory(
|
||||||
HStringReference(RuntimeClass_Windows_UI_Notifications_ToastNotification)
|
HStringReference(RuntimeClass_Windows_UI_Notifications_ToastNotification)
|
||||||
|
|
@ -359,8 +359,8 @@ bool ToastNotificationHandler::CreateWindowsNotificationFromXml(
|
||||||
RefPtr<ToastNotificationHandler> self = this;
|
RefPtr<ToastNotificationHandler> self = this;
|
||||||
|
|
||||||
hr = mNotification->add_Activated(
|
hr = mNotification->add_Activated(
|
||||||
Callback<ToastActivationHandler>([self](IToastNotification *aNotification,
|
Callback<ToastActivationHandler>([self](IToastNotification* aNotification,
|
||||||
IInspectable *aInspectable) {
|
IInspectable* aInspectable) {
|
||||||
return self->OnActivate(aNotification, aInspectable);
|
return self->OnActivate(aNotification, aInspectable);
|
||||||
}).Get(),
|
}).Get(),
|
||||||
&mActivatedToken);
|
&mActivatedToken);
|
||||||
|
|
@ -369,8 +369,8 @@ bool ToastNotificationHandler::CreateWindowsNotificationFromXml(
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = mNotification->add_Dismissed(
|
hr = mNotification->add_Dismissed(
|
||||||
Callback<ToastDismissedHandler>([self](IToastNotification *aNotification,
|
Callback<ToastDismissedHandler>([self](IToastNotification* aNotification,
|
||||||
IToastDismissedEventArgs *aArgs) {
|
IToastDismissedEventArgs* aArgs) {
|
||||||
return self->OnDismiss(aNotification, aArgs);
|
return self->OnDismiss(aNotification, aArgs);
|
||||||
}).Get(),
|
}).Get(),
|
||||||
&mDismissedToken);
|
&mDismissedToken);
|
||||||
|
|
@ -379,8 +379,8 @@ bool ToastNotificationHandler::CreateWindowsNotificationFromXml(
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = mNotification->add_Failed(
|
hr = mNotification->add_Failed(
|
||||||
Callback<ToastFailedHandler>([self](IToastNotification *aNotification,
|
Callback<ToastFailedHandler>([self](IToastNotification* aNotification,
|
||||||
IToastFailedEventArgs *aArgs) {
|
IToastFailedEventArgs* aArgs) {
|
||||||
return self->OnFail(aNotification, aArgs);
|
return self->OnFail(aNotification, aArgs);
|
||||||
}).Get(),
|
}).Get(),
|
||||||
&mFailedToken);
|
&mFailedToken);
|
||||||
|
|
@ -400,7 +400,7 @@ bool ToastNotificationHandler::CreateWindowsNotificationFromXml(
|
||||||
}
|
}
|
||||||
|
|
||||||
HSTRING uidStr =
|
HSTRING uidStr =
|
||||||
HStringReference(static_cast<const wchar_t *>(uid.get())).Get();
|
HStringReference(static_cast<const wchar_t*>(uid.get())).Get();
|
||||||
hr = toastNotificationManagerStatics->CreateToastNotifierWithId(uidStr,
|
hr = toastNotificationManagerStatics->CreateToastNotifierWithId(uidStr,
|
||||||
&mNotifier);
|
&mNotifier);
|
||||||
if (NS_WARN_IF(FAILED(hr))) {
|
if (NS_WARN_IF(FAILED(hr))) {
|
||||||
|
|
@ -419,8 +419,7 @@ bool ToastNotificationHandler::CreateWindowsNotificationFromXml(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void ToastNotificationHandler::SendFinished() {
|
||||||
ToastNotificationHandler::SendFinished() {
|
|
||||||
if (!mSentFinished && mAlertListener) {
|
if (!mSentFinished && mAlertListener) {
|
||||||
mAlertListener->Observe(nullptr, "alertfinished", mCookie.get());
|
mAlertListener->Observe(nullptr, "alertfinished", mCookie.get());
|
||||||
}
|
}
|
||||||
|
|
@ -429,20 +428,20 @@ ToastNotificationHandler::SendFinished() {
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT
|
HRESULT
|
||||||
ToastNotificationHandler::OnActivate(IToastNotification *notification,
|
ToastNotificationHandler::OnActivate(IToastNotification* notification,
|
||||||
IInspectable *inspectable) {
|
IInspectable* inspectable) {
|
||||||
if (mAlertListener) {
|
if (mAlertListener) {
|
||||||
nsAutoString argString;
|
nsAutoString argString;
|
||||||
if (inspectable) {
|
if (inspectable) {
|
||||||
ComPtr<IToastActivatedEventArgs> eventArgs;
|
ComPtr<IToastActivatedEventArgs> eventArgs;
|
||||||
HRESULT hr = inspectable->QueryInterface(
|
HRESULT hr = inspectable->QueryInterface(
|
||||||
__uuidof(IToastActivatedEventArgs), (void **)&eventArgs);
|
__uuidof(IToastActivatedEventArgs), (void**)&eventArgs);
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
HSTRING arguments;
|
HSTRING arguments;
|
||||||
hr = eventArgs->get_Arguments(&arguments);
|
hr = eventArgs->get_Arguments(&arguments);
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
uint32_t len = 0;
|
uint32_t len = 0;
|
||||||
const wchar_t *buffer = WindowsGetStringRawBuffer(arguments, &len);
|
const wchar_t* buffer = WindowsGetStringRawBuffer(arguments, &len);
|
||||||
if (buffer) {
|
if (buffer) {
|
||||||
argString.Assign(buffer, len);
|
argString.Assign(buffer, len);
|
||||||
}
|
}
|
||||||
|
|
@ -480,16 +479,16 @@ ToastNotificationHandler::OnActivate(IToastNotification *notification,
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT
|
HRESULT
|
||||||
ToastNotificationHandler::OnDismiss(IToastNotification *notification,
|
ToastNotificationHandler::OnDismiss(IToastNotification* notification,
|
||||||
IToastDismissedEventArgs *aArgs) {
|
IToastDismissedEventArgs* aArgs) {
|
||||||
SendFinished();
|
SendFinished();
|
||||||
mBackend->RemoveHandler(mName, this);
|
mBackend->RemoveHandler(mName, this);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT
|
HRESULT
|
||||||
ToastNotificationHandler::OnFail(IToastNotification *notification,
|
ToastNotificationHandler::OnFail(IToastNotification* notification,
|
||||||
IToastFailedEventArgs *aArgs) {
|
IToastFailedEventArgs* aArgs) {
|
||||||
SendFinished();
|
SendFinished();
|
||||||
mBackend->RemoveHandler(mName, this);
|
mBackend->RemoveHandler(mName, this);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
@ -504,12 +503,12 @@ nsresult ToastNotificationHandler::TryShowAlert() {
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
ToastNotificationHandler::OnImageMissing(nsISupports *) {
|
ToastNotificationHandler::OnImageMissing(nsISupports*) {
|
||||||
return TryShowAlert();
|
return TryShowAlert();
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
ToastNotificationHandler::OnImageReady(nsISupports *, imgIRequest *aRequest) {
|
ToastNotificationHandler::OnImageReady(nsISupports*, imgIRequest* aRequest) {
|
||||||
nsresult rv = AsyncSaveImage(aRequest);
|
nsresult rv = AsyncSaveImage(aRequest);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
return TryShowAlert();
|
return TryShowAlert();
|
||||||
|
|
@ -517,7 +516,7 @@ ToastNotificationHandler::OnImageReady(nsISupports *, imgIRequest *aRequest) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult ToastNotificationHandler::AsyncSaveImage(imgIRequest *aRequest) {
|
nsresult ToastNotificationHandler::AsyncSaveImage(imgIRequest* aRequest) {
|
||||||
nsresult rv =
|
nsresult rv =
|
||||||
NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(mImageFile));
|
NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(mImageFile));
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
|
@ -580,7 +579,7 @@ nsresult ToastNotificationHandler::AsyncSaveImage(imgIRequest *aRequest) {
|
||||||
nsCOMPtr<nsIRunnable> cbRunnable = NS_NewRunnableFunction(
|
nsCOMPtr<nsIRunnable> cbRunnable = NS_NewRunnableFunction(
|
||||||
"ToastNotificationHandler::AsyncWriteBitmapCb",
|
"ToastNotificationHandler::AsyncWriteBitmapCb",
|
||||||
[self, rv]() -> void {
|
[self, rv]() -> void {
|
||||||
auto handler = const_cast<ToastNotificationHandler *>(self.get());
|
auto handler = const_cast<ToastNotificationHandler*>(self.get());
|
||||||
handler->OnWriteBitmapFinished(rv);
|
handler->OnWriteBitmapFinished(rv);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -619,5 +618,5 @@ nsresult ToastNotificationHandler::OnWriteBitmapSuccess() {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace widget
|
} // namespace widget
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
||||||
|
|
@ -569,10 +569,11 @@ static void DoInitTraceLog(const char* aProcType) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool defined =
|
bool defined = InitLog(ENVVAR("XPCOM_MEM_BLOAT_LOG"), "bloat/leaks",
|
||||||
InitLog(ENVVAR("XPCOM_MEM_BLOAT_LOG"), "bloat/leaks", &gBloatLog, aProcType);
|
&gBloatLog, aProcType);
|
||||||
if (!defined) {
|
if (!defined) {
|
||||||
gLogLeaksOnly = InitLog(ENVVAR("XPCOM_MEM_LEAK_LOG"), "leaks", &gBloatLog, aProcType);
|
gLogLeaksOnly =
|
||||||
|
InitLog(ENVVAR("XPCOM_MEM_LEAK_LOG"), "leaks", &gBloatLog, aProcType);
|
||||||
}
|
}
|
||||||
if (defined || gLogLeaksOnly) {
|
if (defined || gLogLeaksOnly) {
|
||||||
// Use the same bloat view, if there is, to keep it consistent
|
// Use the same bloat view, if there is, to keep it consistent
|
||||||
|
|
@ -1182,9 +1183,7 @@ static void ClearLogs(bool aKeepCounters) {
|
||||||
maybeUnregisterAndCloseFile(gCOMPtrLog);
|
maybeUnregisterAndCloseFile(gCOMPtrLog);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsTraceRefcnt::Shutdown() {
|
void nsTraceRefcnt::Shutdown() { ClearLogs(false); }
|
||||||
ClearLogs(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void nsTraceRefcnt::SetActivityIsLegal(bool aLegal) {
|
void nsTraceRefcnt::SetActivityIsLegal(bool aLegal) {
|
||||||
if (gActivityTLS == BAD_TLS_INDEX) {
|
if (gActivityTLS == BAD_TLS_INDEX) {
|
||||||
|
|
|
||||||
|
|
@ -513,6 +513,6 @@ XRE_API(void, XRE_LibFuzzerSetDriver, (LibFuzzerDriver))
|
||||||
|
|
||||||
XRE_API(int, XRE_ForkServer, (int* aArgc, char*** aArgv))
|
XRE_API(int, XRE_ForkServer, (int* aArgc, char*** aArgv))
|
||||||
|
|
||||||
#endif // MOZ_ENABLE_FORKSERVER
|
#endif // MOZ_ENABLE_FORKSERVER
|
||||||
|
|
||||||
#endif // _nsXULAppAPI_h__
|
#endif // _nsXULAppAPI_h__
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,8 @@ class nsThreadManager : public nsIThreadManager {
|
||||||
nsresult DispatchToBackgroundThread(nsIRunnable* aEvent,
|
nsresult DispatchToBackgroundThread(nsIRunnable* aEvent,
|
||||||
uint32_t aDispatchFlags);
|
uint32_t aDispatchFlags);
|
||||||
|
|
||||||
already_AddRefed<nsISerialEventTarget> CreateBackgroundTaskQueue(const char* aName);
|
already_AddRefed<nsISerialEventTarget> CreateBackgroundTaskQueue(
|
||||||
|
const char* aName);
|
||||||
|
|
||||||
// Returns the maximal number of threads that have been in existence
|
// Returns the maximal number of threads that have been in existence
|
||||||
// simultaneously during the execution of the thread manager.
|
// simultaneously during the execution of the thread manager.
|
||||||
|
|
|
||||||
|
|
@ -534,7 +534,7 @@ nsresult NS_DispatchBackgroundTask(nsIRunnable* aEvent,
|
||||||
nsresult NS_CreateBackgroundTaskQueue(const char* aName,
|
nsresult NS_CreateBackgroundTaskQueue(const char* aName,
|
||||||
nsISerialEventTarget** aTarget) {
|
nsISerialEventTarget** aTarget) {
|
||||||
nsCOMPtr<nsISerialEventTarget> target =
|
nsCOMPtr<nsISerialEventTarget> target =
|
||||||
nsThreadManager::get().CreateBackgroundTaskQueue(aName);
|
nsThreadManager::get().CreateBackgroundTaskQueue(aName);
|
||||||
if (!target) {
|
if (!target) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue