mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 13:34:03 +00:00
import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1224810 - "TraceLogger: Add the script information for the event created by BytecodeCompiler". r=hv1989 (12b6891fa7)
- Bug 1227677 - Simplify emitting of comprehension variables. r=shu (4e9ea2fee7)
- bug 1223529 - remove ipc/chromium/Makefile.in. r=gps (8d71334ca0)
- Bug 1225682 - Don't use nsAuto{,C}String as class member variables in widget/. r=roc (4355625107)
- Bug 1225188. Implement window.onstorage. r=smaug (50168cdffb)
- Bug 1286158 - Add Android 64bit support for libevent. r=billm (b33cb1fccf)
- Bug 1162524: Fix error handling |UnixSocketWatcher::Connect|, r=kmachulis (04e67535b4)
- Bug 1178514 - Mark one-argument constructors in IPDL tests as 'explicit'. r=bent (cc6fde1e1c)
- some warnings stuff (68ecef6622)
- Bug 1170231: Part 1 - Remove condition that may cause deadlock in IPC when mediating interrupt races; r=dvander (79dd6902a2)
- Bug 1170231: Part 2 - Regression test for IPC race mediation deadlock; r=dvander (eabe33218f)
- Bug 1167396 - Make ProtocolCloneContext::mContentParent a smart pointer. r=bent (519ad9f47e)
- Bug 1213567: Prevent neutering from occurring during CreateWindow(Ex) calls; r=jimm (6550685051)
- Bug 1177013 - Bug fixes for CPOW cancelation (r=dvander) (b50da43c07)
- Bug 1217640 - MessageChannel::Call() should delete aMsg when the channel is not connected. r=jld (899b0e6349)
- Bug 1159037: Ensure correct parent and child message are passed to MessageListener::MediateInterruptRace; r=dvander (96c1f42029)
- Bug 1177013 - Telemetry for CPOW cancelation (r=dvander) (ec704af72c)
- Bug 1050122 - Part 2: Disable preallocate when proc loader is not initialized. r=khuey (2d35b8e25e)
This commit is contained in:
@@ -911,6 +911,7 @@ GK_ATOM(onstatechange, "onstatechange")
|
||||
GK_ATOM(onstatuschanged, "onstatuschanged")
|
||||
GK_ATOM(onstkcommand, "onstkcommand")
|
||||
GK_ATOM(onstksessionend, "onstksessionend")
|
||||
GK_ATOM(onstorage, "onstorage")
|
||||
GK_ATOM(onstorageareachanged, "onstorageareachanged")
|
||||
GK_ATOM(onsubmit, "onsubmit")
|
||||
GK_ATOM(onsuccess, "onsuccess")
|
||||
|
||||
@@ -531,8 +531,10 @@ WINDOW_EVENT(popstate,
|
||||
eBasicEventClass)
|
||||
// Not supported yet
|
||||
// WINDOW_EVENT(redo)
|
||||
// Not supported yet
|
||||
// WINDOW_EVENT(storage)
|
||||
WINDOW_EVENT(storage,
|
||||
eStorage,
|
||||
EventNameType_HTMLBodyOrFramesetOnly,
|
||||
eBasicEventClass)
|
||||
// Not supported yet
|
||||
// WINDOW_EVENT(undo)
|
||||
WINDOW_EVENT(unload,
|
||||
|
||||
-1
@@ -25,7 +25,6 @@
|
||||
"Window attribute: onclose": true,
|
||||
"Window attribute: oncuechange": true,
|
||||
"Window attribute: onmousewheel": true,
|
||||
"Window attribute: onstorage": true,
|
||||
"Window unforgeable attribute: window": true,
|
||||
"Window unforgeable attribute: document": true,
|
||||
"Window unforgeable attribute: top": true
|
||||
|
||||
@@ -18,6 +18,10 @@
|
||||
#include "ipc/Nuwa.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_B2G_LOADER
|
||||
#include "ProcessUtils.h"
|
||||
#endif
|
||||
|
||||
// This number is fairly arbitrary ... the intention is to put off
|
||||
// launching another app process until the last one has finished
|
||||
// loading its content, to reduce CPU/memory/IO contention.
|
||||
@@ -133,7 +137,14 @@ PreallocatedProcessManagerImpl::Init()
|
||||
os->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID,
|
||||
/* weakRef = */ false);
|
||||
}
|
||||
RereadPrefs();
|
||||
#ifdef MOZ_B2G_LOADER
|
||||
if (!mozilla::ipc::ProcLoaderIsInitialized()) {
|
||||
Disable();
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
RereadPrefs();
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
||||
@@ -136,7 +136,7 @@ interface WindowEventHandlers {
|
||||
attribute EventHandler onpagehide;
|
||||
attribute EventHandler onpageshow;
|
||||
attribute EventHandler onpopstate;
|
||||
//(Not implemented)attribute EventHandler onstorage;
|
||||
attribute EventHandler onstorage;
|
||||
attribute EventHandler onunload;
|
||||
};
|
||||
|
||||
|
||||
+1
-1
@@ -73,7 +73,7 @@ if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_TARGET'] in ('Linux', 'Android'):
|
||||
# from the function using it which breaks the build. Work around that by
|
||||
# forcing there to be only one partition.
|
||||
if '-flto' in CONFIG['OS_CXXFLAGS'] and not CONFIG['CLANG_CXX']:
|
||||
LDFLAGS += ['--param lto-partitions=1']
|
||||
LDFLAGS += ['--param lto-partitions=1']
|
||||
|
||||
if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_TARGET'] == 'Darwin':
|
||||
# For sandbox includes and the include dependencies those have
|
||||
|
||||
@@ -29,4 +29,5 @@ if CONFIG['MOZ_SANDBOX']:
|
||||
|
||||
LDFLAGS += ['-pie']
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
||||
if CONFIG['GNU_CXX']:
|
||||
CXXFLAGS += ['-Wshadow']
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
OS_CXXFLAGS := $(filter-out -fshort-wchar,$(OS_CXXFLAGS))
|
||||
|
||||
ACDEFINES =
|
||||
|
||||
ifndef MOZ_NATIVE_LIBEVENT # {
|
||||
vpath %.c \
|
||||
$(srcdir)/src/third_party/libevent \
|
||||
$(NULL)
|
||||
endif # }
|
||||
|
||||
vpath %.cc \
|
||||
$(srcdir)/src/base \
|
||||
$(srcdir)/src/chrome/common \
|
||||
$(NULL)
|
||||
|
||||
vpath %.mm \
|
||||
$(srcdir)/src/base \
|
||||
$(srcdir)/src/chrome/common \
|
||||
$(NULL)
|
||||
|
||||
OS_CXXFLAGS += $(TK_CFLAGS)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
ifdef MOZ_NATIVE_LIBEVENT # {
|
||||
|
||||
export-preqs = \
|
||||
$(call mkdir_deps,$(CURDIR)/third_party/libevent) \
|
||||
$(NULL)
|
||||
|
||||
export:: $(DIST)/third_party/libevent/event.h
|
||||
|
||||
$(DIST)/third_party/libevent/event.h:: $(export-preqs)
|
||||
echo '#include <event.h>' > $(CURDIR)/third_party/libevent/event.h
|
||||
|
||||
endif # }
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "base/scoped_nsautorelease_pool.h"
|
||||
#include "base/time.h"
|
||||
#include "nsDependentSubstring.h"
|
||||
#include "third_party/libevent/event.h"
|
||||
#include "event.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
// This macro checks that the _EVENT_SIZEOF_* constants defined in
|
||||
|
||||
+5
-3
@@ -14,9 +14,10 @@ environment indicated by the first path component. You have to run
|
||||
then be found in "include/event2/".
|
||||
|
||||
You then need to modify the _EVENT_SIZEOF_* constants in the generated linux,
|
||||
mac and bsd headers to be appropriate for both 32-bit and 64-bit platforms. Use
|
||||
__LP64__ to distinguish the two cases. If you get something wrong the
|
||||
CHECK_EVENT_SIZEOF static assertions in message_pump_libevent.cc will fail.
|
||||
android, mac and bsd headers to be appropriate for both 32-bit and 64-bit
|
||||
platforms. Use __LP64__ to distinguish the two cases. If you get something
|
||||
wrong the CHECK_EVENT_SIZEOF static assertions in message_pump_libevent.cc will
|
||||
fail.
|
||||
|
||||
2. This is ugly, prepare yourself. OS X has a weird problem with how the
|
||||
"TAILQ_END(head)" is used, causing a linking error. Just replace all use of the
|
||||
@@ -39,5 +40,6 @@ ipc/chromium/src/third_party/libevent/patches/:
|
||||
|
||||
- "avoid-empty-sighandler.patch". This fixes some OS X crashes.
|
||||
|
||||
- "android64_support.patch". This fixes Android 64-bit support.
|
||||
|
||||
7. Apply "libevent-backport-upstream-fixes.patch", which incorporates some upstream fixes from 2.1.*
|
||||
|
||||
@@ -398,26 +398,47 @@
|
||||
your system. */
|
||||
/* #undef _EVENT_PTHREAD_CREATE_JOINABLE */
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* MOZILLA NOTE: the following constants are hand-modified to be suitable */
|
||||
/* for both 32-bit and 64-bit platforms. See README.mozilla for details. */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
/* The size of `int', as computed by sizeof. */
|
||||
#define _EVENT_SIZEOF_INT 4
|
||||
|
||||
/* The size of `long', as computed by sizeof. */
|
||||
#ifdef __LP64__
|
||||
#define _EVENT_SIZEOF_LONG 8
|
||||
#else
|
||||
#define _EVENT_SIZEOF_LONG 4
|
||||
#endif
|
||||
|
||||
/* The size of `long long', as computed by sizeof. */
|
||||
#define _EVENT_SIZEOF_LONG_LONG 8
|
||||
|
||||
/* The size of `pthread_t', as computed by sizeof. */
|
||||
#ifdef __LP64__
|
||||
#define _EVENT_SIZEOF_PTHREAD_T 8
|
||||
#else
|
||||
#define _EVENT_SIZEOF_PTHREAD_T 4
|
||||
#endif
|
||||
|
||||
/* The size of `short', as computed by sizeof. */
|
||||
#define _EVENT_SIZEOF_SHORT 2
|
||||
|
||||
/* The size of `size_t', as computed by sizeof. */
|
||||
#ifdef __LP64__
|
||||
#define _EVENT_SIZEOF_SIZE_T 8
|
||||
#else
|
||||
#define _EVENT_SIZEOF_SIZE_T 4
|
||||
#endif
|
||||
|
||||
/* The size of `void *', as computed by sizeof. */
|
||||
#ifdef __LP64__
|
||||
#define _EVENT_SIZEOF_VOID_P 8
|
||||
#else
|
||||
#define _EVENT_SIZEOF_VOID_P 4
|
||||
#endif
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#define _EVENT_STDC_HEADERS 1
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
diff --git a/ipc/chromium/src/third_party/libevent/android/event2/event-config.h b/ipc/chromium/src/third_party/libevent/android/event2/event-config.h
|
||||
--- a/ipc/chromium/src/third_party/libevent/android/event2/event-config.h
|
||||
+++ b/ipc/chromium/src/third_party/libevent/android/event2/event-config.h
|
||||
@@ -397,32 +397,48 @@
|
||||
/* Define to necessary symbol if this constant uses a non-standard name on
|
||||
your system. */
|
||||
/* #undef _EVENT_PTHREAD_CREATE_JOINABLE */
|
||||
|
||||
/* The size of `int', as computed by sizeof. */
|
||||
#define _EVENT_SIZEOF_INT 4
|
||||
|
||||
/* The size of `long', as computed by sizeof. */
|
||||
+#ifdef __LP64__
|
||||
+#define _EVENT_SIZEOF_LONG 8
|
||||
+#else
|
||||
#define _EVENT_SIZEOF_LONG 4
|
||||
+#endif
|
||||
|
||||
/* The size of `long long', as computed by sizeof. */
|
||||
#define _EVENT_SIZEOF_LONG_LONG 8
|
||||
|
||||
/* The size of `pthread_t', as computed by sizeof. */
|
||||
+#ifdef __LP64__
|
||||
+#define _EVENT_SIZEOF_PTHREAD_T 8
|
||||
+#else
|
||||
#define _EVENT_SIZEOF_PTHREAD_T 4
|
||||
+#endif
|
||||
|
||||
/* The size of `short', as computed by sizeof. */
|
||||
#define _EVENT_SIZEOF_SHORT 2
|
||||
|
||||
/* The size of `size_t', as computed by sizeof. */
|
||||
+#ifdef __LP64__
|
||||
+#define _EVENT_SIZEOF_SIZE_T 8
|
||||
+#else
|
||||
#define _EVENT_SIZEOF_SIZE_T 4
|
||||
+#endif
|
||||
|
||||
/* The size of `void *', as computed by sizeof. */
|
||||
+#ifdef __LP64__
|
||||
+#define _EVENT_SIZEOF_VOID_P 8
|
||||
+#else
|
||||
#define _EVENT_SIZEOF_VOID_P 4
|
||||
+#endif
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#define _EVENT_STDC_HEADERS 1
|
||||
|
||||
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
|
||||
#define _EVENT_TIME_WITH_SYS_TIME 1
|
||||
|
||||
/* Version number of package */
|
||||
+1
@@ -54,6 +54,7 @@ if os_linux:
|
||||
'libevent/epoll_sub.c',
|
||||
]
|
||||
|
||||
# We allow warnings for third-party code that can be updated from upstream.
|
||||
ALLOW_COMPILER_WARNINGS = True
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
+34
-28
@@ -14,6 +14,7 @@
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/SizePrintfMacros.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsContentUtils.h"
|
||||
@@ -864,7 +865,8 @@ MessageChannel::Send(Message* aMsg, Message* aReply)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (DispatchingSyncMessagePriority() == IPC::Message::PRIORITY_NORMAL &&
|
||||
if (mCurrentTransaction &&
|
||||
DispatchingSyncMessagePriority() == IPC::Message::PRIORITY_NORMAL &&
|
||||
msg->priority() > IPC::Message::PRIORITY_NORMAL)
|
||||
{
|
||||
// Don't allow sending CPOWs while we're dispatching a sync message.
|
||||
@@ -874,22 +876,23 @@ MessageChannel::Send(Message* aMsg, Message* aReply)
|
||||
|
||||
if (mCurrentTransaction &&
|
||||
(msg->priority() < DispatchingSyncMessagePriority() ||
|
||||
mAwaitingSyncReplyPriority > msg->priority() ||
|
||||
DispatchingSyncMessagePriority() == IPC::Message::PRIORITY_URGENT ||
|
||||
DispatchingAsyncMessagePriority() == IPC::Message::PRIORITY_URGENT))
|
||||
mAwaitingSyncReplyPriority > msg->priority()))
|
||||
{
|
||||
CancelCurrentTransactionInternal();
|
||||
mLink->SendMessage(new CancelMessage());
|
||||
}
|
||||
|
||||
IPC_ASSERT(msg->is_sync(), "can only Send() sync messages here");
|
||||
IPC_ASSERT(msg->priority() >= DispatchingSyncMessagePriority(),
|
||||
"can't send sync message of a lesser priority than what's being dispatched");
|
||||
IPC_ASSERT(AwaitingSyncReplyPriority() <= msg->priority(),
|
||||
"nested sync message sends must be of increasing priority");
|
||||
|
||||
IPC_ASSERT(DispatchingSyncMessagePriority() != IPC::Message::PRIORITY_URGENT,
|
||||
"not allowed to send messages while dispatching urgent messages");
|
||||
if (mCurrentTransaction) {
|
||||
IPC_ASSERT(msg->priority() >= DispatchingSyncMessagePriority(),
|
||||
"can't send sync message of a lesser priority than what's being dispatched");
|
||||
IPC_ASSERT(AwaitingSyncReplyPriority() <= msg->priority(),
|
||||
"nested sync message sends must be of increasing priority");
|
||||
IPC_ASSERT(DispatchingSyncMessagePriority() != IPC::Message::PRIORITY_URGENT,
|
||||
"not allowed to send messages while dispatching urgent messages");
|
||||
}
|
||||
|
||||
IPC_ASSERT(DispatchingAsyncMessagePriority() != IPC::Message::PRIORITY_URGENT,
|
||||
"not allowed to send messages while dispatching urgent messages");
|
||||
|
||||
@@ -985,6 +988,7 @@ MessageChannel::Send(Message* aMsg, Message* aReply)
|
||||
bool
|
||||
MessageChannel::Call(Message* aMsg, Message* aReply)
|
||||
{
|
||||
nsAutoPtr<Message> msg(aMsg);
|
||||
AssertWorkerThread();
|
||||
mMonitor->AssertNotCurrentThreadOwns();
|
||||
|
||||
@@ -994,7 +998,7 @@ MessageChannel::Call(Message* aMsg, Message* aReply)
|
||||
|
||||
// This must come before MonitorAutoLock, as its destructor acquires the
|
||||
// monitor lock.
|
||||
CxxStackFrame cxxframe(*this, OUT_MESSAGE, aMsg);
|
||||
CxxStackFrame cxxframe(*this, OUT_MESSAGE, msg);
|
||||
|
||||
// mMonitor can be NULL in some conditions
|
||||
if (!mMonitor) {
|
||||
@@ -1004,7 +1008,7 @@ MessageChannel::Call(Message* aMsg, Message* aReply)
|
||||
|
||||
MonitorAutoLock lock(*mMonitor);
|
||||
if (!Connected()) {
|
||||
ReportConnectionError("MessageChannel::Call", aMsg);
|
||||
ReportConnectionError("MessageChannel::Call", msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1013,9 +1017,7 @@ MessageChannel::Call(Message* aMsg, Message* aReply)
|
||||
"cannot issue Interrupt call while blocked on sync request");
|
||||
IPC_ASSERT(!DispatchingSyncMessage(),
|
||||
"violation of sync handler invariant");
|
||||
IPC_ASSERT(aMsg->is_interrupt(), "can only Call() Interrupt messages here");
|
||||
|
||||
nsAutoPtr<Message> msg(aMsg);
|
||||
IPC_ASSERT(msg->is_interrupt(), "can only Call() Interrupt messages here");
|
||||
|
||||
msg->set_seqno(NextSeqno());
|
||||
msg->set_interrupt_remote_stack_depth_guess(mRemoteStackDepthGuess);
|
||||
@@ -1334,11 +1336,6 @@ MessageChannel::DispatchSyncMessage(const Message& aMsg, Message*& aReply)
|
||||
MOZ_ASSERT_IF(prio > IPC::Message::PRIORITY_NORMAL, NS_IsMainThread());
|
||||
MaybeScriptBlocker scriptBlocker(this, prio > IPC::Message::PRIORITY_NORMAL);
|
||||
|
||||
IPC_ASSERT(prio >= DispatchingSyncMessagePriority(),
|
||||
"priority inversion while dispatching sync message");
|
||||
IPC_ASSERT(prio >= mAwaitingSyncReplyPriority,
|
||||
"dispatching a message of lower priority while waiting for a response");
|
||||
|
||||
MessageChannel* dummy;
|
||||
MessageChannel*& blockingVar = ShouldBlockScripts() ? gParentProcessBlocker : dummy;
|
||||
|
||||
@@ -1412,8 +1409,9 @@ MessageChannel::DispatchInterruptMessage(const Message& aMsg, size_t stackDepth)
|
||||
// processing of the other side's in-call.
|
||||
bool defer;
|
||||
const char* winner;
|
||||
switch (mListener->MediateInterruptRace((mSide == ChildSide) ? aMsg : mInterruptStack.top(),
|
||||
(mSide != ChildSide) ? mInterruptStack.top() : aMsg))
|
||||
const Message& parentMsg = (mSide == ChildSide) ? aMsg : mInterruptStack.top();
|
||||
const Message& childMsg = (mSide == ChildSide) ? mInterruptStack.top() : aMsg;
|
||||
switch (mListener->MediateInterruptRace(parentMsg, childMsg))
|
||||
{
|
||||
case RIPChildWins:
|
||||
winner = "child";
|
||||
@@ -1490,9 +1488,6 @@ MessageChannel::MaybeUndeferIncall()
|
||||
IPC_ASSERT(mDeferred.top().interrupt_remote_stack_depth_guess() <= stackDepth,
|
||||
"fatal logic error");
|
||||
|
||||
if (mDeferred.top().interrupt_remote_stack_depth_guess() < RemoteViewOfStackDepth(stackDepth))
|
||||
return;
|
||||
|
||||
// maybe time to process this message
|
||||
Message call = mDeferred.top();
|
||||
mDeferred.pop();
|
||||
@@ -2042,22 +2037,33 @@ MessageChannel::CancelCurrentTransactionInternal()
|
||||
// tampered with (by us). If so, they don't reset the variable to the old
|
||||
// value.
|
||||
|
||||
MOZ_ASSERT(!mCurrentTransaction);
|
||||
MOZ_ASSERT(mCurrentTransaction);
|
||||
mCurrentTransaction = 0;
|
||||
|
||||
mAwaitingSyncReply = false;
|
||||
mAwaitingSyncReplyPriority = 0;
|
||||
|
||||
// We could also zero out mDispatchingSyncMessage here. However, that would
|
||||
// cause a race because mDispatchingSyncMessage is a worker-thread-only
|
||||
// field and we can be called on the I/O thread. Luckily, we can check to
|
||||
// see if mCurrentTransaction is 0 before examining DispatchSyncMessage.
|
||||
}
|
||||
|
||||
void
|
||||
MessageChannel::CancelCurrentTransaction()
|
||||
{
|
||||
MonitorAutoLock lock(*mMonitor);
|
||||
CancelCurrentTransactionInternal();
|
||||
mLink->SendMessage(new CancelMessage());
|
||||
if (mCurrentTransaction) {
|
||||
CancelCurrentTransactionInternal();
|
||||
mLink->SendMessage(new CancelMessage());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CancelCPOWs()
|
||||
{
|
||||
if (gParentProcessBlocker) {
|
||||
mozilla::Telemetry::Accumulate(mozilla::Telemetry::IPC_TRANSACTION_CANCEL, true);
|
||||
gParentProcessBlocker->CancelCurrentTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -570,7 +570,7 @@ class MessageChannel : HasResultCodes
|
||||
public:
|
||||
explicit AutoEnterTransaction(MessageChannel *aChan, int32_t aMsgSeqno)
|
||||
: mChan(aChan),
|
||||
mNewTransaction(0),
|
||||
mNewTransaction(INT32_MAX),
|
||||
mOldTransaction(mChan->mCurrentTransaction)
|
||||
{
|
||||
mChan->mMonitor->AssertCurrentThreadOwns();
|
||||
|
||||
@@ -57,6 +57,21 @@ private:
|
||||
bool mReneuter;
|
||||
};
|
||||
|
||||
class MOZ_RAII SuppressedNeuteringRegion
|
||||
{
|
||||
public:
|
||||
SuppressedNeuteringRegion(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM);
|
||||
~SuppressedNeuteringRegion();
|
||||
|
||||
static inline bool IsNeuteringSuppressed() { return sSuppressNeutering; }
|
||||
|
||||
private:
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
bool mReenable;
|
||||
|
||||
static bool sSuppressNeutering;
|
||||
};
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ void SetThisProcessName(const char *aName);
|
||||
#ifdef MOZ_B2G_LOADER
|
||||
// see ProcessUtils_linux.cpp for explaination.
|
||||
void ProcLoaderClientGeckoInit();
|
||||
|
||||
bool ProcLoaderIsInitialized();
|
||||
bool ProcLoaderLoad(const char *aArgv[],
|
||||
const char *aEnvp[],
|
||||
const base::file_handle_mapping_vector &aFdsRemap,
|
||||
|
||||
@@ -227,6 +227,11 @@ ProcLoaderClientGeckoInit()
|
||||
sProcLoaderLoop = MessageLoop::current();
|
||||
}
|
||||
|
||||
bool ProcLoaderIsInitialized()
|
||||
{
|
||||
return sProcLoaderPid != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdown and destroy the client of B2G loader service.
|
||||
*/
|
||||
|
||||
@@ -26,6 +26,18 @@ using base::ProcessId;
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
ProtocolCloneContext::ProtocolCloneContext()
|
||||
: mNeckoParent(nullptr)
|
||||
{}
|
||||
|
||||
ProtocolCloneContext::~ProtocolCloneContext()
|
||||
{}
|
||||
|
||||
void ProtocolCloneContext::SetContentParent(ContentParent* aContentParent)
|
||||
{
|
||||
mContentParent = aContentParent;
|
||||
}
|
||||
|
||||
static StaticMutex gProtocolMutex;
|
||||
|
||||
IToplevelProtocol::IToplevelProtocol(ProtocolId aProtoId)
|
||||
|
||||
@@ -131,19 +131,15 @@ class ProtocolCloneContext
|
||||
typedef mozilla::dom::ContentParent ContentParent;
|
||||
typedef mozilla::net::NeckoParent NeckoParent;
|
||||
|
||||
ContentParent* mContentParent;
|
||||
RefPtr<ContentParent> mContentParent;
|
||||
NeckoParent* mNeckoParent;
|
||||
|
||||
public:
|
||||
ProtocolCloneContext()
|
||||
: mContentParent(nullptr)
|
||||
, mNeckoParent(nullptr)
|
||||
{}
|
||||
ProtocolCloneContext();
|
||||
|
||||
void SetContentParent(ContentParent* aContentParent)
|
||||
{
|
||||
mContentParent = aContentParent;
|
||||
}
|
||||
~ProtocolCloneContext();
|
||||
|
||||
void SetContentParent(ContentParent* aContentParent);
|
||||
|
||||
ContentParent* GetContentParent() { return mContentParent; }
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsString.h"
|
||||
#include "nsIXULAppInfo.h"
|
||||
#include "nsWindowsDllInterceptor.h"
|
||||
#include "WinUtils.h"
|
||||
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
@@ -436,6 +437,93 @@ ProcessOrDeferMessage(HWND hwnd,
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* It is bad to subclass a window when neutering is active because you'll end
|
||||
* up subclassing the *neutered* window procedure instead of the real window
|
||||
* procedure. Since CreateWindow* fires WM_CREATE (and could thus trigger
|
||||
* neutering), we intercept these calls and suppress neutering for the duration
|
||||
* of the call. This ensures that any subsequent subclassing replaces the
|
||||
* correct window procedure.
|
||||
*/
|
||||
WindowsDllInterceptor sUser32Interceptor;
|
||||
typedef HWND (WINAPI *CreateWindowExWPtr)(DWORD,LPCWSTR,LPCWSTR,DWORD,int,int,int,int,HWND,HMENU,HINSTANCE,LPVOID);
|
||||
typedef HWND (WINAPI *CreateWindowExAPtr)(DWORD,LPCSTR,LPCSTR,DWORD,int,int,int,int,HWND,HMENU,HINSTANCE,LPVOID);
|
||||
typedef HWND (WINAPI *CreateWindowWPtr)(LPCWSTR,LPCWSTR,DWORD,int,int,int,int,HWND,HMENU,HINSTANCE,LPVOID);
|
||||
typedef HWND (WINAPI *CreateWindowAPtr)(LPCSTR,LPCSTR,DWORD,int,int,int,int,HWND,HMENU,HINSTANCE,LPVOID);
|
||||
|
||||
CreateWindowExWPtr sCreateWindowExWStub = nullptr;
|
||||
CreateWindowExAPtr sCreateWindowExAStub = nullptr;
|
||||
CreateWindowWPtr sCreateWindowWStub = nullptr;
|
||||
CreateWindowAPtr sCreateWindowAStub = nullptr;
|
||||
|
||||
HWND WINAPI
|
||||
CreateWindowExWHook(DWORD aExStyle, LPCWSTR aClassName, LPCWSTR aWindowName,
|
||||
DWORD aStyle, int aX, int aY, int aWidth, int aHeight,
|
||||
HWND aParent, HMENU aMenu, HINSTANCE aInstance,
|
||||
LPVOID aParam)
|
||||
{
|
||||
SuppressedNeuteringRegion doNotNeuterThisWindowYet;
|
||||
return sCreateWindowExWStub(aExStyle, aClassName, aWindowName, aStyle, aX, aY,
|
||||
aWidth, aHeight, aParent, aMenu, aInstance, aParam);
|
||||
}
|
||||
|
||||
HWND WINAPI
|
||||
CreateWindowExAHook(DWORD aExStyle, LPCSTR aClassName, LPCSTR aWindowName,
|
||||
DWORD aStyle, int aX, int aY, int aWidth, int aHeight,
|
||||
HWND aParent, HMENU aMenu, HINSTANCE aInstance,
|
||||
LPVOID aParam)
|
||||
{
|
||||
SuppressedNeuteringRegion doNotNeuterThisWindowYet;
|
||||
return sCreateWindowExAStub(aExStyle, aClassName, aWindowName, aStyle, aX, aY,
|
||||
aWidth, aHeight, aParent, aMenu, aInstance, aParam);
|
||||
}
|
||||
|
||||
HWND WINAPI
|
||||
CreateWindowWHook(LPCWSTR aClassName, LPCWSTR aWindowName, DWORD aStyle, int aX,
|
||||
int aY, int aWidth, int aHeight, HWND aParent, HMENU aMenu,
|
||||
HINSTANCE aInstance, LPVOID aParam)
|
||||
{
|
||||
SuppressedNeuteringRegion doNotNeuterThisWindowYet;
|
||||
return sCreateWindowWStub(aClassName, aWindowName, aStyle, aX, aY, aWidth,
|
||||
aHeight, aParent, aMenu, aInstance, aParam);
|
||||
}
|
||||
|
||||
HWND WINAPI
|
||||
CreateWindowAHook(LPCSTR aClassName, LPCSTR aWindowName, DWORD aStyle, int aX,
|
||||
int aY, int aWidth, int aHeight, HWND aParent, HMENU aMenu,
|
||||
HINSTANCE aInstance, LPVOID aParam)
|
||||
{
|
||||
SuppressedNeuteringRegion doNotNeuterThisWindowYet;
|
||||
return sCreateWindowAStub(aClassName, aWindowName, aStyle, aX, aY, aWidth,
|
||||
aHeight, aParent, aMenu, aInstance, aParam);
|
||||
}
|
||||
|
||||
void
|
||||
InitCreateWindowHook()
|
||||
{
|
||||
sUser32Interceptor.Init("user32.dll");
|
||||
if (!sCreateWindowExWStub) {
|
||||
sUser32Interceptor.AddHook("CreateWindowExW",
|
||||
reinterpret_cast<intptr_t>(CreateWindowExWHook),
|
||||
(void**) &sCreateWindowExWStub);
|
||||
}
|
||||
if (!sCreateWindowExAStub) {
|
||||
sUser32Interceptor.AddHook("CreateWindowExA",
|
||||
reinterpret_cast<intptr_t>(CreateWindowExAHook),
|
||||
(void**) &sCreateWindowExAStub);
|
||||
}
|
||||
if (!sCreateWindowWStub) {
|
||||
sUser32Interceptor.AddHook("CreateWindowW",
|
||||
reinterpret_cast<intptr_t>(CreateWindowWHook),
|
||||
(void**) &sCreateWindowWStub);
|
||||
}
|
||||
if (!sCreateWindowAStub) {
|
||||
sUser32Interceptor.AddHook("CreateWindowA",
|
||||
reinterpret_cast<intptr_t>(CreateWindowAHook),
|
||||
(void**) &sCreateWindowAStub);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// We need the pointer value of this in PluginInstanceChild.
|
||||
@@ -610,7 +698,9 @@ CallWindowProcedureHook(int nCode,
|
||||
|
||||
HWND hWnd = reinterpret_cast<CWPSTRUCT*>(lParam)->hwnd;
|
||||
|
||||
if (!gNeuteredWindows->Contains(hWnd) && NeuterWindowProcedure(hWnd)) {
|
||||
if (!gNeuteredWindows->Contains(hWnd) &&
|
||||
!SuppressedNeuteringRegion::IsNeuteringSuppressed() &&
|
||||
NeuterWindowProcedure(hWnd)) {
|
||||
if (!gNeuteredWindows->AppendElement(hWnd)) {
|
||||
NS_ERROR("Out of memory!");
|
||||
RestoreWindowProcedure(hWnd);
|
||||
@@ -710,6 +800,8 @@ InitUIThread()
|
||||
gCOMWindow = FindCOMWindow();
|
||||
}
|
||||
MOZ_ASSERT(gWinEventHook);
|
||||
|
||||
InitCreateWindowHook();
|
||||
}
|
||||
|
||||
} // namespace windows
|
||||
@@ -943,6 +1035,26 @@ DeneuteredWindowRegion::~DeneuteredWindowRegion()
|
||||
}
|
||||
}
|
||||
|
||||
SuppressedNeuteringRegion::SuppressedNeuteringRegion(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL)
|
||||
: mReenable(::gUIThreadId == ::GetCurrentThreadId() && ::gWindowHook)
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
if (mReenable) {
|
||||
MOZ_ASSERT(!sSuppressNeutering);
|
||||
sSuppressNeutering = true;
|
||||
}
|
||||
}
|
||||
|
||||
SuppressedNeuteringRegion::~SuppressedNeuteringRegion()
|
||||
{
|
||||
if (mReenable) {
|
||||
MOZ_ASSERT(sSuppressNeutering);
|
||||
sSuppressNeutering = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool SuppressedNeuteringRegion::sSuppressNeutering = false;
|
||||
|
||||
bool
|
||||
MessageChannel::WaitForSyncNotify(bool aHandleWindowsMessages)
|
||||
{
|
||||
@@ -997,6 +1109,8 @@ MessageChannel::WaitForSyncNotify(bool aHandleWindowsMessages)
|
||||
NS_ASSERTION(timerId, "SetTimer failed!");
|
||||
}
|
||||
|
||||
NeuteredWindowRegion neuteredRgn(true);
|
||||
|
||||
{
|
||||
while (1) {
|
||||
MSG msg = { 0 };
|
||||
|
||||
@@ -16,7 +16,7 @@ class IPDLUnitTestProcessChild : public mozilla::ipc::ProcessChild
|
||||
typedef mozilla::ipc::ProcessChild ProcessChild;
|
||||
|
||||
public:
|
||||
IPDLUnitTestProcessChild(ProcessId aParentPid) :
|
||||
explicit IPDLUnitTestProcessChild(ProcessId aParentPid) :
|
||||
ProcessChild(aParentPid)
|
||||
{ }
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
intr protocol PTestRaceDeadlock {
|
||||
both:
|
||||
async StartRace();
|
||||
|
||||
parent:
|
||||
intr Lose();
|
||||
|
||||
child:
|
||||
intr Win();
|
||||
intr Rpc();
|
||||
async __delete__();
|
||||
|
||||
/* Tests that race resolution does not cause deadlocks */
|
||||
};
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
@@ -42,7 +42,7 @@ class TestBridgeMainSubParent :
|
||||
public PTestBridgeMainSubParent
|
||||
{
|
||||
public:
|
||||
TestBridgeMainSubParent(Transport* aTransport)
|
||||
explicit TestBridgeMainSubParent(Transport* aTransport)
|
||||
: mTransport(aTransport)
|
||||
{}
|
||||
virtual ~TestBridgeMainSubParent() {}
|
||||
@@ -126,7 +126,7 @@ class TestBridgeMainSubChild :
|
||||
public PTestBridgeMainSubChild
|
||||
{
|
||||
public:
|
||||
TestBridgeMainSubChild(Transport* aTransport)
|
||||
explicit TestBridgeMainSubChild(Transport* aTransport)
|
||||
: mGotHi(false)
|
||||
, mTransport(aTransport)
|
||||
{}
|
||||
|
||||
@@ -20,7 +20,7 @@ class TestDataStructuresSub :
|
||||
public PTestDataStructuresSubChild
|
||||
{
|
||||
public:
|
||||
TestDataStructuresSub(uint32_t i) : mI(i)
|
||||
explicit TestDataStructuresSub(uint32_t i) : mI(i)
|
||||
{ }
|
||||
virtual ~TestDataStructuresSub()
|
||||
{ }
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace _ipdltest2 {
|
||||
class TestOpensOpenedParent : public PTestOpensOpenedParent
|
||||
{
|
||||
public:
|
||||
TestOpensOpenedParent(Transport* aTransport)
|
||||
explicit TestOpensOpenedParent(Transport* aTransport)
|
||||
: mTransport(aTransport)
|
||||
{}
|
||||
virtual ~TestOpensOpenedParent() {}
|
||||
@@ -83,7 +83,7 @@ namespace _ipdltest2 {
|
||||
class TestOpensOpenedChild : public PTestOpensOpenedChild
|
||||
{
|
||||
public:
|
||||
TestOpensOpenedChild(Transport* aTransport)
|
||||
explicit TestOpensOpenedChild(Transport* aTransport)
|
||||
: mGotHi(false)
|
||||
, mTransport(aTransport)
|
||||
{}
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
#include "TestRaceDeadlock.h"
|
||||
|
||||
#include "IPDLUnitTests.h" // fail etc.
|
||||
|
||||
// #define TEST_TIMEOUT 5000
|
||||
|
||||
using namespace mozilla::ipc;
|
||||
typedef mozilla::ipc::MessageChannel::Message Message;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
static RacyInterruptPolicy
|
||||
MediateRace(const Message& parent, const Message& child)
|
||||
{
|
||||
return (PTestRaceDeadlock::Msg_Win__ID == parent.type()) ?
|
||||
RIPParentWins : RIPChildWins;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// parent
|
||||
|
||||
TestRaceDeadlockParent::TestRaceDeadlockParent()
|
||||
{
|
||||
MOZ_COUNT_CTOR(TestRaceDeadlockParent);
|
||||
}
|
||||
|
||||
TestRaceDeadlockParent::~TestRaceDeadlockParent()
|
||||
{
|
||||
MOZ_COUNT_DTOR(TestRaceDeadlockParent);
|
||||
}
|
||||
|
||||
void
|
||||
TestRaceDeadlockParent::Main()
|
||||
{
|
||||
Test1();
|
||||
|
||||
Close();
|
||||
}
|
||||
|
||||
bool
|
||||
TestRaceDeadlockParent::ShouldContinueFromReplyTimeout()
|
||||
{
|
||||
fail("This test should not hang");
|
||||
GetIPCChannel()->CloseWithTimeout();
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
TestRaceDeadlockParent::Test1()
|
||||
{
|
||||
#if defined(TEST_TIMEOUT)
|
||||
SetReplyTimeoutMs(TEST_TIMEOUT);
|
||||
#endif
|
||||
if (!SendStartRace()) {
|
||||
fail("sending StartRace");
|
||||
}
|
||||
if (!CallRpc()) {
|
||||
fail("calling Rpc");
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
TestRaceDeadlockParent::AnswerLose()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
RacyInterruptPolicy
|
||||
TestRaceDeadlockParent::MediateInterruptRace(const Message& parent,
|
||||
const Message& child)
|
||||
{
|
||||
return MediateRace(parent, child);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// child
|
||||
|
||||
TestRaceDeadlockChild::TestRaceDeadlockChild()
|
||||
{
|
||||
MOZ_COUNT_CTOR(TestRaceDeadlockChild);
|
||||
}
|
||||
|
||||
TestRaceDeadlockChild::~TestRaceDeadlockChild()
|
||||
{
|
||||
MOZ_COUNT_DTOR(TestRaceDeadlockChild);
|
||||
}
|
||||
|
||||
bool
|
||||
TestRaceDeadlockParent::RecvStartRace()
|
||||
{
|
||||
if (!CallWin()) {
|
||||
fail("calling Win");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TestRaceDeadlockChild::RecvStartRace()
|
||||
{
|
||||
if (!SendStartRace()) {
|
||||
fail("calling SendStartRace");
|
||||
}
|
||||
if (!CallLose()) {
|
||||
fail("calling Lose");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TestRaceDeadlockChild::AnswerWin()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TestRaceDeadlockChild::AnswerRpc()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
RacyInterruptPolicy
|
||||
TestRaceDeadlockChild::MediateInterruptRace(const Message& parent,
|
||||
const Message& child)
|
||||
{
|
||||
return MediateRace(parent, child);
|
||||
}
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
@@ -0,0 +1,75 @@
|
||||
#ifndef mozilla__ipdltest_TestRaceDeadlock_h
|
||||
#define mozilla__ipdltest_TestRaceDeadlock_h 1
|
||||
|
||||
#include "mozilla/_ipdltest/IPDLUnitTests.h"
|
||||
|
||||
#include "mozilla/_ipdltest/PTestRaceDeadlockParent.h"
|
||||
#include "mozilla/_ipdltest/PTestRaceDeadlockChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
class TestRaceDeadlockParent :
|
||||
public PTestRaceDeadlockParent
|
||||
{
|
||||
public:
|
||||
TestRaceDeadlockParent();
|
||||
virtual ~TestRaceDeadlockParent();
|
||||
|
||||
static bool RunTestInProcesses() { return true; }
|
||||
static bool RunTestInThreads() { return true; }
|
||||
|
||||
void Main();
|
||||
|
||||
protected:
|
||||
virtual bool ShouldContinueFromReplyTimeout() override;
|
||||
|
||||
void Test1();
|
||||
|
||||
virtual bool RecvStartRace() override;
|
||||
virtual bool AnswerLose() override;
|
||||
|
||||
virtual mozilla::ipc::RacyInterruptPolicy
|
||||
MediateInterruptRace(const Message& parent, const Message& child) override;
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override
|
||||
{
|
||||
if (NormalShutdown != why)
|
||||
fail("unexpected destruction!");
|
||||
passed("ok");
|
||||
QuitParent();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class TestRaceDeadlockChild :
|
||||
public PTestRaceDeadlockChild
|
||||
{
|
||||
public:
|
||||
TestRaceDeadlockChild();
|
||||
virtual ~TestRaceDeadlockChild();
|
||||
|
||||
protected:
|
||||
virtual bool RecvStartRace() override;
|
||||
|
||||
virtual bool AnswerWin() override;
|
||||
|
||||
virtual bool AnswerRpc() override;
|
||||
|
||||
virtual mozilla::ipc::RacyInterruptPolicy
|
||||
MediateInterruptRace(const Message& parent, const Message& child) override;
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override
|
||||
{
|
||||
if (NormalShutdown != why)
|
||||
fail("unexpected destruction!");
|
||||
QuitChild();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
|
||||
|
||||
#endif // ifndef mozilla__ipdltest_TestRaceDeadlock_h
|
||||
@@ -22,7 +22,7 @@ class TestShutdownSubsubParent :
|
||||
public PTestShutdownSubsubParent
|
||||
{
|
||||
public:
|
||||
TestShutdownSubsubParent(bool expectParentDeleted) :
|
||||
explicit TestShutdownSubsubParent(bool expectParentDeleted) :
|
||||
mExpectParentDeleted(expectParentDeleted)
|
||||
{
|
||||
}
|
||||
@@ -44,7 +44,7 @@ class TestShutdownSubParent :
|
||||
public PTestShutdownSubParent
|
||||
{
|
||||
public:
|
||||
TestShutdownSubParent(bool expectCrash) :
|
||||
explicit TestShutdownSubParent(bool expectCrash) :
|
||||
mExpectCrash(expectCrash),
|
||||
mDeletedCount(0)
|
||||
{
|
||||
@@ -131,7 +131,7 @@ class TestShutdownSubsubChild :
|
||||
public PTestShutdownSubsubChild
|
||||
{
|
||||
public:
|
||||
TestShutdownSubsubChild(bool expectParentDeleted) :
|
||||
explicit TestShutdownSubsubChild(bool expectParentDeleted) :
|
||||
mExpectParentDeleted(expectParentDeleted)
|
||||
{
|
||||
}
|
||||
@@ -152,7 +152,7 @@ class TestShutdownSubChild :
|
||||
public PTestShutdownSubChild
|
||||
{
|
||||
public:
|
||||
TestShutdownSubChild(bool expectCrash) : mExpectCrash(expectCrash)
|
||||
explicit TestShutdownSubChild(bool expectCrash) : mExpectCrash(expectCrash)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ SOURCES += [
|
||||
'TestMultiMgrs.cpp',
|
||||
'TestNestedLoops.cpp',
|
||||
'TestOpens.cpp',
|
||||
'TestRaceDeadlock.cpp',
|
||||
'TestRaceDeferral.cpp',
|
||||
'TestRacyInterruptReplies.cpp',
|
||||
'TestRacyReentry.cpp',
|
||||
@@ -102,6 +103,7 @@ IPDL_SOURCES += [
|
||||
'PTestNestedLoops.ipdl',
|
||||
'PTestOpens.ipdl',
|
||||
'PTestOpensOpened.ipdl',
|
||||
'PTestRaceDeadlock.ipdl',
|
||||
'PTestRaceDeferral.ipdl',
|
||||
'PTestRacyInterruptReplies.ipdl',
|
||||
'PTestRacyReentry.ipdl',
|
||||
|
||||
@@ -29,14 +29,14 @@ UnixSocketWatcher::Connect(const struct sockaddr* aAddr, socklen_t aAddrLen)
|
||||
MOZ_ASSERT(IsOpen());
|
||||
MOZ_ASSERT(aAddr || !aAddrLen);
|
||||
|
||||
if (connect(GetFd(), aAddr, aAddrLen) < 0) {
|
||||
if (TEMP_FAILURE_RETRY(connect(GetFd(), aAddr, aAddrLen) < 0)) {
|
||||
if (errno == EINPROGRESS) {
|
||||
mConnectionStatus = SOCKET_IS_CONNECTING;
|
||||
// Set up a write watch to receive the connect signal
|
||||
AddWatchers(WRITE_WATCHER, false);
|
||||
} else {
|
||||
OnError("connect", errno);
|
||||
return NS_OK;
|
||||
}
|
||||
OnError("connect", errno);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,8 @@ using mozilla::Maybe;
|
||||
class MOZ_STACK_CLASS AutoCompilationTraceLogger
|
||||
{
|
||||
public:
|
||||
AutoCompilationTraceLogger(ExclusiveContext* cx, const TraceLoggerTextId id);
|
||||
AutoCompilationTraceLogger(ExclusiveContext* cx, const TraceLoggerTextId id,
|
||||
const ReadOnlyCompileOptions& options);
|
||||
|
||||
private:
|
||||
TraceLoggerThread* logger;
|
||||
@@ -117,10 +118,11 @@ class MOZ_STACK_CLASS BytecodeCompiler
|
||||
Maybe<BytecodeEmitter> emitter;
|
||||
};
|
||||
|
||||
AutoCompilationTraceLogger::AutoCompilationTraceLogger(ExclusiveContext* cx, const TraceLoggerTextId id)
|
||||
AutoCompilationTraceLogger::AutoCompilationTraceLogger(ExclusiveContext* cx,
|
||||
const TraceLoggerTextId id, const ReadOnlyCompileOptions& options)
|
||||
: logger(cx->isJSContext() ? TraceLoggerForMainThread(cx->asJSContext()->runtime())
|
||||
: TraceLoggerForCurrentThread()),
|
||||
event(logger, TraceLogger_AnnotateScripts),
|
||||
event(logger, TraceLogger_AnnotateScripts, options),
|
||||
scriptLogger(logger, event),
|
||||
typeLogger(logger, id)
|
||||
{}
|
||||
@@ -131,7 +133,7 @@ BytecodeCompiler::BytecodeCompiler(ExclusiveContext* cx,
|
||||
SourceBufferHolder& sourceBuffer,
|
||||
Handle<ScopeObject*> enclosingStaticScope,
|
||||
TraceLoggerTextId logId)
|
||||
: traceLogger(cx, logId),
|
||||
: traceLogger(cx, logId, options),
|
||||
keepAtoms(cx->perThreadData),
|
||||
cx(cx),
|
||||
alloc(alloc),
|
||||
@@ -785,7 +787,7 @@ frontend::CompileLazyFunction(JSContext* cx, Handle<LazyScript*> lazy, const cha
|
||||
.setNoScriptRval(false)
|
||||
.setSelfHostingMode(false);
|
||||
|
||||
AutoCompilationTraceLogger traceLogger(cx, TraceLogger_ParserCompileLazy);
|
||||
AutoCompilationTraceLogger traceLogger(cx, TraceLogger_ParserCompileLazy, options);
|
||||
|
||||
Parser<FullParseHandler> parser(cx, &cx->tempLifoAlloc(), options, chars, length,
|
||||
/* foldConstants = */ true, nullptr, lazy);
|
||||
|
||||
@@ -5938,38 +5938,32 @@ BytecodeEmitter::emitFor(ParseNode* pn)
|
||||
bool
|
||||
BytecodeEmitter::emitComprehensionForInOrOfVariables(ParseNode* pn, bool* letBlockScope)
|
||||
{
|
||||
// ES6 specifies that loop variables get a fresh binding in each iteration.
|
||||
// This is currently implemented for C-style for(;;) loops, but not
|
||||
// for-in/of loops, though a similar approach should work. See bug 449811.
|
||||
//
|
||||
// In `for (let x in/of EXPR)`, ES6 specifies that EXPR is evaluated in a
|
||||
// scope containing an uninitialized `x`. If EXPR accesses `x`, we should
|
||||
// get a ReferenceError due to the TDZ violation. This is not yet
|
||||
// implemented. See bug 1069480.
|
||||
// ES6 specifies that lexical for-loop variables get a fresh binding each
|
||||
// iteration, and that evaluation of the expression looped over occurs with
|
||||
// these variables uninitialized. But these rules only apply to *standard*
|
||||
// for-in/of loops, and we haven't extended these requirements to
|
||||
// comprehension syntax.
|
||||
|
||||
*letBlockScope = pn->isKind(PNK_LEXICALSCOPE);
|
||||
MOZ_ASSERT_IF(*letBlockScope, pn->isLexical());
|
||||
if (*letBlockScope) {
|
||||
// This is initially-ES7-tracked syntax, now with considerably
|
||||
// murkier outlook. The |enterBlockScope()| precipitated by the
|
||||
// outparam-set here initializes the let-binding in
|
||||
// |emitComprehensionFor{In,Of}| with |undefined|, so there's nothing
|
||||
// to do here.
|
||||
MOZ_ASSERT(pn->isLexical());
|
||||
} else {
|
||||
// This is legacy comprehension syntax. We'll have PNK_LET here, using
|
||||
// a lexical scope provided by/for the entire comprehension. Name
|
||||
// analysis assumes declarations initialize lets, but as we're handling
|
||||
// this declaration manually, we must also initialize manually to avoid
|
||||
// triggering dead zone checks.
|
||||
MOZ_ASSERT(pn->isKind(PNK_LET));
|
||||
MOZ_ASSERT(pn->pn_count == 1);
|
||||
|
||||
// If the left part is 'var x', emit code to define x if necessary using a
|
||||
// prologue opcode, but do not emit a pop. If it is 'let x', enterBlockScope
|
||||
// will initialize let bindings in emitForOf and emitForIn with
|
||||
// undefineds.
|
||||
//
|
||||
// Due to the horror of legacy comprehensions, there is a third case where
|
||||
// we have PNK_LET without a lexical scope, because those expressions are
|
||||
// parsed with single lexical scope for the entire comprehension. In this
|
||||
// case we must initialize the lets to not trigger dead zone checks via
|
||||
// InitializeVars.
|
||||
if (!*letBlockScope) {
|
||||
emittingForInit = true;
|
||||
if (pn->isKind(PNK_VAR)) {
|
||||
if (!emitVariables(pn, DefineVars))
|
||||
return false;
|
||||
} else {
|
||||
MOZ_ASSERT(pn->isKind(PNK_LET));
|
||||
if (!emitVariables(pn, InitializeVars))
|
||||
return false;
|
||||
}
|
||||
if (!emitVariables(pn, InitializeVars))
|
||||
return false;
|
||||
emittingForInit = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,3 @@
|
||||
[Window attribute: onmousewheel]
|
||||
expected: FAIL
|
||||
|
||||
[Window attribute: onstorage]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
@@ -655,12 +655,6 @@
|
||||
[HTMLLinkElement interface: document.createElement("link") must inherit property "crossOrigin" with the proper type (1)]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLBodyElement interface: attribute onstorage]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLBodyElement interface: document.createElement("body") must inherit property "onstorage" with the proper type (17)]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLPreElement must be primary interface of document.createElement("listing")]
|
||||
expected: FAIL
|
||||
|
||||
@@ -2104,9 +2098,6 @@
|
||||
[Window interface: attribute ontoggle]
|
||||
expected: FAIL
|
||||
|
||||
[Window interface: attribute onstorage]
|
||||
expected: FAIL
|
||||
|
||||
[Window interface: operation setTimeout(Function,long,any)]
|
||||
expected: FAIL
|
||||
|
||||
@@ -2158,9 +2149,6 @@
|
||||
[Window interface: window must inherit property "ontoggle" with the proper type (98)]
|
||||
expected: FAIL
|
||||
|
||||
[Window interface: window must inherit property "onstorage" with the proper type (112)]
|
||||
expected: FAIL
|
||||
|
||||
[Window interface: calling createImageBitmap(ImageBitmapSource,long,long,long,long) on window with too few arguments must throw TypeError]
|
||||
expected: FAIL
|
||||
|
||||
@@ -2620,12 +2608,6 @@
|
||||
[HTMLMarqueeElement interface: document.createElement("marquee") must inherit property "stop" with the proper type (15)]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLFrameSetElement interface: attribute onstorage]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLFrameSetElement interface: document.createElement("frameset") must inherit property "onstorage" with the proper type (13)]
|
||||
expected: FAIL
|
||||
|
||||
[Document interface: iframe.contentDocument must inherit property "styleSheetSets" with the proper type (31)]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
[event_body_attribute.html]
|
||||
type: testharness
|
||||
[localStorage mutations fire StorageEvents that are caught by the event listener specified as an attribute on the body.]
|
||||
expected: FAIL
|
||||
|
||||
disabled:
|
||||
if e10s: https://bugzilla.mozilla.org/show_bug.cgi?id=1205675
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
iframe = document.createElement("IFRAME");
|
||||
iframe.src = "about:blank";
|
||||
document.body.appendChild(iframe);
|
||||
iframe.contentWindow.document.body.textContent = "Nothing to see here.";
|
||||
|
||||
storageEventList = new Array();
|
||||
iframe.contentWindow.onstorage = function(e) {
|
||||
window.parent.storageEventList.push(e);
|
||||
};
|
||||
|
||||
function runAfterNStorageEvents(callback, expectedNumEvents)
|
||||
{
|
||||
countStorageEvents(callback, expectedNumEvents, 0)
|
||||
}
|
||||
|
||||
function countStorageEvents(callback, expectedNumEvents, times)
|
||||
{
|
||||
function onTimeout()
|
||||
{
|
||||
var currentCount = storageEventList.length;
|
||||
if (currentCount == expectedNumEvents) {
|
||||
callback();
|
||||
} else if (currentCount > expectedNumEvents) {
|
||||
msg = "got at least " + currentCount + ", expected only " + expectedNumEvents + " events";
|
||||
callback(msg);
|
||||
} else if (times > 50) {
|
||||
msg = "Timeout: only got " + currentCount + ", expected " + expectedNumEvents + " events";
|
||||
callback(msg);
|
||||
} else {
|
||||
countStorageEvents(callback, expectedNumEvents, times+1);
|
||||
}
|
||||
}
|
||||
setTimeout(onTimeout, 20);
|
||||
}
|
||||
|
||||
function clearStorage(storageName, callback)
|
||||
{
|
||||
if (window[storageName].length === 0) {
|
||||
storageEventList = [];
|
||||
setTimeout(callback, 0);
|
||||
} else {
|
||||
window[storageName].clear();
|
||||
runAfterNStorageEvents(function() {
|
||||
storageEventList = [];
|
||||
callback();
|
||||
}, 1);
|
||||
}
|
||||
}
|
||||
|
||||
function testStorages(testCallback)
|
||||
{
|
||||
testCallback("sessionStorage");
|
||||
var hit = false;
|
||||
add_result_callback(function() {
|
||||
if (!hit) {
|
||||
hit = true;
|
||||
testCallback("localStorage");
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
testStorages(function(storageString) {
|
||||
async_test(function(t) {
|
||||
assert_true(storageString in window, storageString + " exist");
|
||||
var storage = window[storageString];
|
||||
t.add_cleanup(function() { storage.clear() });
|
||||
|
||||
clearStorage(storageString, t.step_func(step0));
|
||||
assert_equals(storage.length, 0, "storage.length");
|
||||
|
||||
function step0(msg)
|
||||
{
|
||||
iframe.onload = t.step_func(step1);
|
||||
// Null out the existing handler eventTestHarness.js set up;
|
||||
// otherwise this test won't be testing much of anything useful.
|
||||
iframe.contentWindow.onstorage = null;
|
||||
iframe.src = "resources/event_body_handler.html";
|
||||
}
|
||||
|
||||
function step1(msg)
|
||||
{
|
||||
storageEventList = new Array();
|
||||
storage.setItem('FOO', 'BAR');
|
||||
|
||||
runAfterNStorageEvents(t.step_func(step2), 1);
|
||||
}
|
||||
|
||||
function step2(msg)
|
||||
{
|
||||
if (msg != undefined) {
|
||||
assert_unreached(msg);
|
||||
}
|
||||
assert_equals(storageEventList.length, 1);
|
||||
assert_equals(storageEventList[0].key, "FOO");
|
||||
assert_equals(storageEventList[0].oldValue, null);
|
||||
assert_equals(storageEventList[0].newValue, "BAR");
|
||||
|
||||
storage.setItem('FU', 'BAR');
|
||||
storage.setItem('a', '1');
|
||||
storage.setItem('b', '2');
|
||||
storage.setItem('b', '3');
|
||||
|
||||
runAfterNStorageEvents(t.step_func(step3), 5);
|
||||
}
|
||||
|
||||
function step3(msg)
|
||||
{
|
||||
if (msg != undefined) {
|
||||
assert_unreached(msg);
|
||||
}
|
||||
assert_equals(storageEventList.length, 5);
|
||||
assert_equals(storageEventList[1].key, "FU");
|
||||
assert_equals(storageEventList[1].oldValue, null);
|
||||
assert_equals(storageEventList[1].newValue, "BAR");
|
||||
|
||||
assert_equals(storageEventList[2].key, "a");
|
||||
assert_equals(storageEventList[2].oldValue, null);
|
||||
assert_equals(storageEventList[2].newValue, "1");
|
||||
|
||||
assert_equals(storageEventList[3].key, "b");
|
||||
assert_equals(storageEventList[3].oldValue, null);
|
||||
assert_equals(storageEventList[3].newValue, "2");
|
||||
|
||||
assert_equals(storageEventList[4].key, "b");
|
||||
assert_equals(storageEventList[4].oldValue, "2");
|
||||
assert_equals(storageEventList[4].newValue, "3");
|
||||
|
||||
storage.removeItem('FOO');
|
||||
|
||||
runAfterNStorageEvents(t.step_func(step4), 6);
|
||||
}
|
||||
|
||||
function step4(msg)
|
||||
{
|
||||
if(msg != undefined) {
|
||||
assert_unreached(msg);
|
||||
}
|
||||
assert_equals(storageEventList.length, 6);
|
||||
assert_equals(storageEventList[5].key, "FOO");
|
||||
assert_equals(storageEventList[5].oldValue, "BAR");
|
||||
assert_equals(storageEventList[5].newValue, null);
|
||||
|
||||
storage.removeItem('FU');
|
||||
|
||||
runAfterNStorageEvents(t.step_func(step5), 7);
|
||||
}
|
||||
|
||||
function step5(msg)
|
||||
{
|
||||
if(msg != undefined) {
|
||||
assert_unreached(msg);
|
||||
}
|
||||
assert_equals(storageEventList.length, 7);
|
||||
assert_equals(storageEventList[6].key, "FU");
|
||||
assert_equals(storageEventList[6].oldValue, "BAR");
|
||||
assert_equals(storageEventList[6].newValue, null);
|
||||
|
||||
storage.clear();
|
||||
|
||||
runAfterNStorageEvents(t.step_func(step6), 8);
|
||||
}
|
||||
|
||||
function step6(msg)
|
||||
{
|
||||
if(msg != undefined) {
|
||||
assert_unreached(msg);
|
||||
}
|
||||
assert_equals(storageEventList.length, 8);
|
||||
assert_equals(storageEventList[7].key, null);
|
||||
assert_equals(storageEventList[7].oldValue, null);
|
||||
assert_equals(storageEventList[7].newValue, null);
|
||||
|
||||
t.done();
|
||||
}
|
||||
|
||||
}, storageString + " mutations fire StorageEvents that are caught by the event listener specified as an attribute on the body.");
|
||||
});
|
||||
@@ -0,0 +1,14 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<script>
|
||||
|
||||
function handleStorageEvent(e) {
|
||||
window.parent.storageEventList.push(e);
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body onstorage="handleStorageEvent(event);">
|
||||
</body>
|
||||
</html>
|
||||
@@ -5172,6 +5172,12 @@
|
||||
"keyed" : true,
|
||||
"description" : "Exceptions thrown by add-ons"
|
||||
},
|
||||
"IPC_TRANSACTION_CANCEL": {
|
||||
"alert_emails": ["billm@mozilla.com"],
|
||||
"expires_in_version": "never",
|
||||
"kind": "boolean",
|
||||
"description": "True when an IPC transaction is canceled"
|
||||
},
|
||||
"IPC_SAME_PROCESS_MESSAGE_COPY_OOM_KB": {
|
||||
"expires_in_version": "50",
|
||||
"kind": "exponential",
|
||||
|
||||
@@ -98,6 +98,7 @@ NS_EVENT_MESSAGE(eHashChange)
|
||||
NS_EVENT_MESSAGE(eImageAbort)
|
||||
NS_EVENT_MESSAGE(eLoadError)
|
||||
NS_EVENT_MESSAGE(ePopState)
|
||||
NS_EVENT_MESSAGE(eStorage)
|
||||
NS_EVENT_MESSAGE(eBeforeUnload)
|
||||
NS_EVENT_MESSAGE(eReadyStateChange)
|
||||
|
||||
|
||||
@@ -1136,7 +1136,7 @@ nsresult GfxInfoBase::GetInfo(JSContext* aCx, JS::MutableHandle<JS::Value> aResu
|
||||
const nsCString&
|
||||
GfxInfoBase::GetApplicationVersion()
|
||||
{
|
||||
static nsAutoCString version;
|
||||
static nsCString version;
|
||||
static bool versionInitialized = false;
|
||||
if (!versionInitialized) {
|
||||
// If we fail to get the version, we will not try again.
|
||||
|
||||
@@ -269,7 +269,7 @@ private:
|
||||
void Clear();
|
||||
|
||||
private:
|
||||
nsAutoString mString;
|
||||
nsString mString;
|
||||
RefPtr<TextRangeArray> mClauses;
|
||||
TextRange mCaret;
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ private:
|
||||
void InhibitFailed();
|
||||
void InhibitSucceeded(uint32_t aInhibitRequest);
|
||||
|
||||
nsAutoCString mTopic;
|
||||
nsCString mTopic;
|
||||
DBusConnection* mConnection;
|
||||
|
||||
DesktopEnvironment mDesktopEnvironment;
|
||||
|
||||
Reference in New Issue
Block a user