This commit is contained in:
Phil Ringnalda 2016-06-25 16:23:43 -07:00
Родитель 0068c10f19 703e02d24b
Коммит 98d7a9d9c5
321 изменённых файлов: 739 добавлений и 3376 удалений

Просмотреть файл

@ -9,7 +9,6 @@
#include "mozilla/Assertions.h"
#include "jsapi.h"
#include "xpcprivate.h" // For AutoCxPusher guts
#include "xpcpublic.h"
#include "nsIGlobalObject.h"
#include "nsIDocShell.h"
@ -38,8 +37,13 @@ public:
static void Push(ScriptSettingsStackEntry *aEntry) {
MOZ_ASSERT(!aEntry->mOlder);
// Whenever JSAPI use is disabled, the next stack entry pushed must
// always be a candidate entry point.
MOZ_ASSERT_IF(!Top() || Top()->NoJSAPI(), aEntry->mIsCandidateEntryPoint);
// not be an AutoIncumbentScript.
MOZ_ASSERT_IF(!Top() || Top()->NoJSAPI(),
!aEntry->IsIncumbentScript());
// Whenever the top entry is not an incumbent canidate, the next stack entry
// pushed must not be an AutoIncumbentScript.
MOZ_ASSERT_IF(Top() && !Top()->IsIncumbentCandidate(),
!aEntry->IsIncumbentScript());
aEntry->mOlder = Top();
sScriptSettingsTLS.set(aEntry);
@ -52,23 +56,24 @@ public:
static nsIGlobalObject* IncumbentGlobal() {
ScriptSettingsStackEntry *entry = Top();
if (!entry) {
return nullptr;
while (entry) {
if (entry->IsIncumbentCandidate()) {
return entry->mGlobalObject;
}
entry = entry->mOlder;
}
return entry->mGlobalObject;
return nullptr;
}
static ScriptSettingsStackEntry* EntryPoint() {
ScriptSettingsStackEntry *entry = Top();
if (!entry) {
return nullptr;
}
while (entry) {
if (entry->mIsCandidateEntryPoint)
if (entry->IsEntryCandidate()) {
return entry;
}
entry = entry->mOlder;
}
MOZ_CRASH("Non-empty stack should always have an entry point");
return nullptr;
}
static nsIGlobalObject* EntryGlobal() {
@ -79,6 +84,19 @@ public:
return entry->mGlobalObject;
}
#ifdef DEBUG
static ScriptSettingsStackEntry* TopNonIncumbentScript() {
ScriptSettingsStackEntry *entry = Top();
while (entry) {
if (!entry->IsIncumbentScript()) {
return entry;
}
entry = entry->mOlder;
}
return nullptr;
}
#endif // DEBUG
};
static unsigned long gRunToCompletionListeners = 0;
@ -123,35 +141,23 @@ ScriptSettingsInitialized()
}
ScriptSettingsStackEntry::ScriptSettingsStackEntry(nsIGlobalObject *aGlobal,
bool aCandidate)
Type aType)
: mGlobalObject(aGlobal)
, mIsCandidateEntryPoint(aCandidate)
, mType(aType)
, mOlder(nullptr)
{
MOZ_ASSERT(mGlobalObject);
MOZ_ASSERT(mGlobalObject->GetGlobalJSObject(),
MOZ_ASSERT_IF(IsIncumbentCandidate() && !NoJSAPI(), mGlobalObject);
MOZ_ASSERT(!mGlobalObject || mGlobalObject->GetGlobalJSObject(),
"Must have an actual JS global for the duration on the stack");
MOZ_ASSERT(JS_IsGlobalObject(mGlobalObject->GetGlobalJSObject()),
MOZ_ASSERT(!mGlobalObject ||
JS_IsGlobalObject(mGlobalObject->GetGlobalJSObject()),
"No outer windows allowed");
ScriptSettingsStack::Push(this);
}
// This constructor is only for use by AutoNoJSAPI.
ScriptSettingsStackEntry::ScriptSettingsStackEntry()
: mGlobalObject(nullptr)
, mIsCandidateEntryPoint(true)
, mOlder(nullptr)
{
ScriptSettingsStack::Push(this);
}
ScriptSettingsStackEntry::~ScriptSettingsStackEntry()
{
// We must have an actual JS global for the entire time this is on the stack.
MOZ_ASSERT_IF(mGlobalObject, mGlobalObject->GetGlobalJSObject());
ScriptSettingsStack::Pop(this);
}
// If the entry or incumbent global ends up being something that the subject
@ -271,8 +277,16 @@ GetWebIDLCallerPrincipal()
return aes->mWebIDLCallerPrincipal;
}
bool
IsJSAPIActive()
{
ScriptSettingsStackEntry* topEntry = ScriptSettingsStack::Top();
return topEntry && !topEntry->NoJSAPI();
}
AutoJSAPI::AutoJSAPI()
: mCx(nullptr)
: ScriptSettingsStackEntry(nullptr, eJSAPI)
, mCx(nullptr)
, mIsMainThread(false) // For lack of anything better
{
}
@ -282,7 +296,9 @@ AutoJSAPI::~AutoJSAPI()
if (!mCx) {
// No need to do anything here: we never managed to Init, so can't have an
// exception on our (nonexistent) JSContext. We also don't need to restore
// any state on it.
// any state on it. Finally, we never made it to pushing outselves onto the
// ScriptSettingsStack, so shouldn't pop.
MOZ_ASSERT(ScriptSettingsStack::Top() != this);
return;
}
@ -291,6 +307,13 @@ AutoJSAPI::~AutoJSAPI()
if (mOldWarningReporter.isSome()) {
JS::SetWarningReporter(JS_GetRuntime(cx()), mOldWarningReporter.value());
}
// Leave the request before popping.
if (mIsMainThread) {
mAutoRequest.reset();
}
ScriptSettingsStack::Pop(this);
}
void
@ -313,16 +336,14 @@ AutoJSAPI::InitInternal(nsIGlobalObject* aGlobalObject, JSObject* aGlobal,
mIsMainThread = aIsMainThread;
mGlobalObject = aGlobalObject;
if (aIsMainThread) {
// This Rooted<> is necessary only as long as AutoCxPusher::AutoCxPusher
// can GC, which is only possible because XPCJSContextStack::Push calls
// nsIPrincipal.Equals. Once that is removed, the Rooted<> will no longer
// be necessary.
JS::Rooted<JSObject*> global(JS_GetRuntime(aCx), aGlobal);
mCxPusher.emplace(mCx);
mAutoNullableCompartment.emplace(mCx, global);
} else {
mAutoNullableCompartment.emplace(mCx, aGlobal);
// We _could_ just unconditionally emplace mAutoRequest here. It's just not
// needed on worker threads, and we're hoping to kill it on the main thread
// too.
mAutoRequest.emplace(mCx);
}
mAutoNullableCompartment.emplace(mCx, aGlobal);
ScriptSettingsStack::Push(this);
JSRuntime* rt = JS_GetRuntime(aCx);
mOldWarningReporter.emplace(JS::GetWarningReporter(rt));
@ -398,8 +419,10 @@ AutoJSAPI::InitInternal(nsIGlobalObject* aGlobalObject, JSObject* aGlobal,
AutoJSAPI::AutoJSAPI(nsIGlobalObject* aGlobalObject,
bool aIsMainThread,
JSContext* aCx)
: mIsMainThread(aIsMainThread)
JSContext* aCx,
Type aType)
: ScriptSettingsStackEntry(aGlobalObject, aType)
, mIsMainThread(aIsMainThread)
{
MOZ_ASSERT(aGlobalObject);
MOZ_ASSERT(aGlobalObject->GetGlobalJSObject(), "Must have a JS global");
@ -583,7 +606,7 @@ AutoJSAPI::ReportException()
bool
AutoJSAPI::PeekException(JS::MutableHandle<JS::Value> aVal)
{
MOZ_ASSERT_IF(mIsMainThread, CxPusherIsStackTop());
MOZ_ASSERT_IF(mIsMainThread, IsStackTop());
MOZ_ASSERT(HasException());
MOZ_ASSERT(js::GetContextCompartment(cx()));
if (!JS_GetPendingException(cx(), aVal)) {
@ -602,13 +625,21 @@ AutoJSAPI::StealException(JS::MutableHandle<JS::Value> aVal)
return true;
}
#ifdef DEBUG
bool
AutoJSAPI::IsStackTop() const
{
return ScriptSettingsStack::TopNonIncumbentScript() == this;
}
#endif // DEBUG
AutoEntryScript::AutoEntryScript(nsIGlobalObject* aGlobalObject,
const char *aReason,
bool aIsMainThread,
JSContext* aCx)
: AutoJSAPI(aGlobalObject, aIsMainThread,
aCx ? aCx : nsContentUtils::GetSafeJSContext())
, ScriptSettingsStackEntry(aGlobalObject, /* aCandidate = */ true)
aCx ? aCx : nsContentUtils::GetSafeJSContext(),
eEntryScript)
, mWebIDLCallerPrincipal(nullptr)
{
MOZ_ASSERT(aGlobalObject);
@ -712,66 +743,28 @@ AutoEntryScript::DocshellEntryMonitor::Exit(JSContext* aCx)
}
AutoIncumbentScript::AutoIncumbentScript(nsIGlobalObject* aGlobalObject)
: ScriptSettingsStackEntry(aGlobalObject, /* aCandidate = */ false)
: ScriptSettingsStackEntry(aGlobalObject, eIncumbentScript)
, mCallerOverride(nsContentUtils::GetCurrentJSContextForThread())
{
ScriptSettingsStack::Push(this);
}
AutoNoJSAPI::AutoNoJSAPI(bool aIsMainThread)
: ScriptSettingsStackEntry()
AutoIncumbentScript::~AutoIncumbentScript()
{
if (aIsMainThread) {
mCxPusher.emplace(static_cast<JSContext*>(nullptr),
/* aAllowNull = */ true);
}
ScriptSettingsStack::Pop(this);
}
danger::AutoCxPusher::AutoCxPusher(JSContext* cx, bool allowNull)
AutoNoJSAPI::AutoNoJSAPI()
: ScriptSettingsStackEntry(nullptr, eNoJSAPI)
{
MOZ_ASSERT_IF(!allowNull, cx);
XPCJSContextStack *stack = XPCJSRuntime::Get()->GetJSContextStack();
stack->Push(cx);
#ifdef DEBUG
mStackDepthAfterPush = stack->Count();
mPushedContext = cx;
mCompartmentDepthOnEntry = cx ? js::GetEnterCompartmentDepth(cx) : 0;
#endif
// Enter a request and a compartment for the duration that the cx is on the
// stack if non-null.
if (cx) {
mAutoRequest.emplace(cx);
}
ScriptSettingsStack::Push(this);
}
danger::AutoCxPusher::~AutoCxPusher()
AutoNoJSAPI::~AutoNoJSAPI()
{
// Leave the request before popping.
mAutoRequest.reset();
// When we push a context, we may save the frame chain and pretend like we
// haven't entered any compartment. This gets restored on Pop(), but we can
// run into trouble if a Push/Pop are interleaved with a
// JSAutoEnterCompartment. Make sure the compartment depth right before we
// pop is the same as it was right after we pushed.
MOZ_ASSERT_IF(mPushedContext, mCompartmentDepthOnEntry ==
js::GetEnterCompartmentDepth(mPushedContext));
MOZ_ASSERT(mPushedContext == nsXPConnect::XPConnect()->GetCurrentJSContext());
XPCJSRuntime::Get()->GetJSContextStack()->Pop();
ScriptSettingsStack::Pop(this);
}
#ifdef DEBUG
bool
danger::AutoCxPusher::IsStackTop() const
{
uint32_t currentDepth = XPCJSRuntime::Get()->GetJSContextStack()->Count();
MOZ_ASSERT(currentDepth >= mStackDepthAfterPush);
return currentDepth == mStackDepthAfterPush;
}
#endif
} // namespace dom
AutoJSContext::AutoJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL)
@ -779,13 +772,13 @@ AutoJSContext::AutoJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL)
{
JS::AutoSuppressGCAnalysis nogc;
MOZ_ASSERT(!mCx, "mCx should not be initialized!");
MOZ_ASSERT(NS_IsMainThread());
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
nsXPConnect *xpc = nsXPConnect::XPConnect();
mCx = xpc->GetCurrentJSContext();
if (!mCx) {
if (IsJSAPIActive()) {
mCx = nsContentUtils::GetSafeJSContext();
} else {
mJSAPI.Init();
mCx = mJSAPI.cx();
}

Просмотреть файл

@ -27,34 +27,6 @@ class nsIDocShell;
namespace mozilla {
namespace dom {
// For internal use only - use AutoJSAPI instead.
namespace danger {
/**
* Fundamental cx pushing class. All other cx pushing classes are implemented
* in terms of this class.
*/
class MOZ_STACK_CLASS AutoCxPusher
{
public:
explicit AutoCxPusher(JSContext *aCx, bool aAllowNull = false);
~AutoCxPusher();
// Returns true if this AutoCxPusher performed the push that is currently at
// the top of the cx stack.
bool IsStackTop() const;
private:
mozilla::Maybe<JSAutoRequest> mAutoRequest;
#ifdef DEBUG
uint32_t mStackDepthAfterPush;
JSContext* mPushedContext;
unsigned mCompartmentDepthOnEntry;
#endif
};
} /* namespace danger */
/*
* System-wide setup/teardown routines. Init and Destroy should be invoked
* once each, at startup and shutdown (respectively).
@ -150,6 +122,11 @@ inline JSObject& IncumbentJSGlobal()
return *GetIncumbentGlobal()->GetGlobalJSObject();
}
// Returns whether JSAPI is active right now. If it is not, working with a
// JSContext you grab from somewhere random is not OK and you should be doing
// AutoJSAPI or AutoEntryScript to get yourself a properly set up JSContext.
bool IsJSAPIActive();
class ScriptSettingsStack;
class ScriptSettingsStackEntry {
friend class ScriptSettingsStack;
@ -157,19 +134,28 @@ class ScriptSettingsStackEntry {
public:
~ScriptSettingsStackEntry();
bool NoJSAPI() { return !mGlobalObject; }
bool NoJSAPI() const { return mType == eNoJSAPI; }
bool IsEntryCandidate() const {
return mType == eEntryScript || mType == eNoJSAPI;
}
bool IsIncumbentCandidate() { return mType != eJSAPI; }
bool IsIncumbentScript() { return mType == eIncumbentScript; }
protected:
ScriptSettingsStackEntry(nsIGlobalObject *aGlobal, bool aCandidate);
enum Type {
eEntryScript,
eIncumbentScript,
eJSAPI,
eNoJSAPI
};
ScriptSettingsStackEntry(nsIGlobalObject *aGlobal,
Type aEntryType);
nsCOMPtr<nsIGlobalObject> mGlobalObject;
bool mIsCandidateEntryPoint;
Type mType;
private:
// This constructor is only for use by AutoNoJSAPI.
friend class AutoNoJSAPI;
ScriptSettingsStackEntry();
ScriptSettingsStackEntry *mOlder;
};
@ -186,19 +172,15 @@ private:
* the JSContext stack.
* * Entering an initial (possibly null) compartment, to ensure that the
* previously entered compartment for that JSContext is not used by mistake.
* * Reporting any exceptions left on the JSRuntime, unless the caller steals
* or silences them.
* * On main thread, entering a JSAutoRequest.
*
* Additionally, the following duties are planned, but not yet implemented:
*
* * De-poisoning the JSRuntime to allow manipulation of JSAPI. We can't
* actually implement this poisoning until all the JSContext pushing in the
* system goes through AutoJSAPI (see bug 951991). For now, this de-poisoning
* * De-poisoning the JSRuntime to allow manipulation of JSAPI. This requires
* implementing the poisoning first. For now, this de-poisoning
* effectively corresponds to having a non-null cx on the stack.
* * Reporting any exceptions left on the JSRuntime, unless the caller steals
* or silences them.
* * Entering a JSAutoRequest. At present, this is handled by the cx pushing
* on the main thread, and by other code on workers. Depending on the order
* in which various cleanup lands, this may never be necessary, because
* JSAutoRequests may go away.
*
* In situations where the consumer expects to run script, AutoEntryScript
* should be used, which does additional manipulation of the script settings
@ -207,7 +189,7 @@ private:
* fail. This prevents system code from accidentally triggering script
* execution at inopportune moments via surreptitious getters and proxies.
*/
class MOZ_STACK_CLASS AutoJSAPI {
class MOZ_STACK_CLASS AutoJSAPI : protected ScriptSettingsStackEntry {
public:
// Trivial constructor. One of the Init functions must be called before
// accessing the JSContext through cx().
@ -258,19 +240,19 @@ public:
JSContext* cx() const {
MOZ_ASSERT(mCx, "Must call Init before using an AutoJSAPI");
MOZ_ASSERT_IF(mIsMainThread, CxPusherIsStackTop());
MOZ_ASSERT(IsStackTop());
return mCx;
}
#ifdef DEBUG
bool CxPusherIsStackTop() const { return mCxPusher->IsStackTop(); }
bool IsStackTop() const;
#endif
// If HasException, report it. Otherwise, a no-op.
void ReportException();
bool HasException() const {
MOZ_ASSERT_IF(NS_IsMainThread(), CxPusherIsStackTop());
MOZ_ASSERT(IsStackTop());
return JS_IsExceptionPending(cx());
};
@ -291,7 +273,7 @@ public:
bool PeekException(JS::MutableHandle<JS::Value> aVal);
void ClearException() {
MOZ_ASSERT_IF(NS_IsMainThread(), CxPusherIsStackTop());
MOZ_ASSERT(IsStackTop());
JS_ClearPendingException(cx());
}
@ -301,15 +283,11 @@ protected:
// called on subclasses that use this.
// If aGlobalObject, its associated JS global or aCx are null this will cause
// an assertion, as will setting aIsMainThread incorrectly.
AutoJSAPI(nsIGlobalObject* aGlobalObject, bool aIsMainThread, JSContext* aCx);
AutoJSAPI(nsIGlobalObject* aGlobalObject, bool aIsMainThread, JSContext* aCx,
Type aType);
private:
// We need to hold a strong ref to our global object, so it won't go away
// while we're being used. This _could_ become a JS::Rooted<JSObject*> if we
// grabbed our JSContext in our constructor instead of waiting for Init(), so
// we could construct this at that point. It might be worth it do to that.
RefPtr<nsIGlobalObject> mGlobalObject;
mozilla::Maybe<danger::AutoCxPusher> mCxPusher;
mozilla::Maybe<JSAutoRequest> mAutoRequest;
mozilla::Maybe<JSAutoNullableCompartment> mAutoNullableCompartment;
JSContext *mCx;
@ -331,8 +309,7 @@ private:
* invoking JavaScript code: "setTimeout", "event", and so on. The devtools use
* these strings to label JS execution in timeline and profiling displays.
*/
class MOZ_STACK_CLASS AutoEntryScript : public AutoJSAPI,
protected ScriptSettingsStackEntry {
class MOZ_STACK_CLASS AutoEntryScript : public AutoJSAPI {
public:
AutoEntryScript(nsIGlobalObject* aGlobalObject,
const char *aReason,
@ -407,6 +384,8 @@ private:
class AutoIncumbentScript : protected ScriptSettingsStackEntry {
public:
explicit AutoIncumbentScript(nsIGlobalObject* aGlobalObject);
~AutoIncumbentScript();
private:
JS::AutoHideScriptedCaller mCallerOverride;
};
@ -421,9 +400,8 @@ private:
*/
class AutoNoJSAPI : protected ScriptSettingsStackEntry {
public:
explicit AutoNoJSAPI(bool aIsMainThread = NS_IsMainThread());
private:
mozilla::Maybe<danger::AutoCxPusher> mCxPusher;
explicit AutoNoJSAPI();
~AutoNoJSAPI();
};
} // namespace dom

Просмотреть файл

@ -5469,7 +5469,10 @@ nsContentUtils::GetCurrentJSContext()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(IsInitialized());
return sXPConnect->GetCurrentJSContext();
if (!IsJSAPIActive()) {
return nullptr;
}
return GetSafeJSContext();
}
/* static */

Просмотреть файл

@ -1338,7 +1338,6 @@ GK_ATOM(zeroDigit, "zero-digit")
GK_ATOM(percentage, "%")
GK_ATOM(A, "A")
GK_ATOM(alignment_baseline, "alignment-baseline")
GK_ATOM(allowReorder, "allowReorder")
GK_ATOM(amplitude, "amplitude")
GK_ATOM(animate, "animate")
GK_ATOM(animateColor, "animateColor")

Просмотреть файл

@ -1991,6 +1991,13 @@ ContentParent::RecvDeallocateLayerTreeId(const uint64_t& aId)
namespace {
void
DelayedDeleteSubprocess(GeckoChildProcessHost* aSubprocess)
{
RefPtr<DeleteTask<GeckoChildProcessHost>> task = new DeleteTask<GeckoChildProcessHost>(aSubprocess);
XRE_GetIOMessageLoop()->PostTask(task.forget());
}
// This runnable only exists to delegate ownership of the
// ContentParent to this runnable, until it's deleted by the event
// system.
@ -2122,10 +2129,9 @@ ContentParent::ActorDestroy(ActorDestroyReason why)
}
mIdleListeners.Clear();
if (mSubprocess) {
mSubprocess->DissociateActor();
mSubprocess = nullptr;
}
MessageLoop::current()->
PostTask(NewRunnableFunction(DelayedDeleteSubprocess, mSubprocess));
mSubprocess = nullptr;
// IPDL rules require actors to live on past ActorDestroy, but it
// may be that the kungFuDeathGrip above is the last reference to
@ -3321,7 +3327,7 @@ ContentParent::AllocPCompositorBridgeParent(mozilla::ipc::Transport* aTransport,
base::ProcessId aOtherProcess)
{
return GPUProcessManager::Get()->CreateTabCompositorBridge(
aTransport, aOtherProcess, mSubprocess);
aTransport, aOtherProcess);
}
gfx::PVRManagerParent*
@ -3335,7 +3341,7 @@ PImageBridgeParent*
ContentParent::AllocPImageBridgeParent(mozilla::ipc::Transport* aTransport,
base::ProcessId aOtherProcess)
{
return ImageBridgeParent::Create(aTransport, aOtherProcess, mSubprocess);
return ImageBridgeParent::Create(aTransport, aOtherProcess);
}
PBackgroundParent*

Просмотреть файл

@ -11,7 +11,6 @@
#include "base/basictypes.h"
#include "base/file_path.h"
#include "base/thread.h"
#include "base/waitable_event.h"
#include "chrome/common/child_process_host.h"
#include "mozilla/ipc/GeckoChildProcessHost.h"
@ -35,7 +34,6 @@ public:
bool CanShutdown() override { return true; }
const std::string& GetPluginFilePath() { return mGMPPath; }
using mozilla::ipc::GeckoChildProcessHost::GetShutDownEvent;
using mozilla::ipc::GeckoChildProcessHost::GetChannel;
using mozilla::ipc::GeckoChildProcessHost::GetChildProcessHandle;

Просмотреть файл

@ -23,6 +23,16 @@ add_task(function*() {
ok(time > 2000, "Interval is throttled with no webaudio (" + time + " ms)");
// Set up a listener for the oscillator's demise
let oscillatorDemisePromise = ContentTask.spawn(browser, null, function() {
return new Promise(resolve => {
let observer = () => resolve();
// Record the observer on the content object so we can throw it out later
content.__bug1181073_observer = observer;
Services.obs.addObserver(observer, "webaudio-node-demise", false);
});
});
time = yield ContentTask.spawn(browser, null, function () {
return new Promise(resolve => {
// Start playing audio, save it on the window so it doesn't get GCed
@ -46,6 +56,7 @@ add_task(function*() {
// Destroy the oscillator, but not the audio context
yield new Promise(resolve => SpecialPowers.exactGC(browser.contentWindow, resolve));
yield oscillatorDemisePromise;
time = yield ContentTask.spawn(browser, null, function () {
return new Promise(resolve => {

Просмотреть файл

@ -13,7 +13,6 @@
#include "base/file_path.h"
#include "base/task.h"
#include "base/thread.h"
#include "base/waitable_event.h"
#include "chrome/common/child_process_host.h"
#include "mozilla/ipc/GeckoChildProcessHost.h"
@ -66,7 +65,6 @@ public:
const std::string& GetPluginFilePath() { return mPluginFilePath; }
using mozilla::ipc::GeckoChildProcessHost::GetShutDownEvent;
using mozilla::ipc::GeckoChildProcessHost::GetChannel;
void SetCallRunnableImmediately(bool aCallImmediately);

Просмотреть файл

@ -127,14 +127,10 @@ SVGSwitchElement::IsAttributeMapped(const nsIAtom* name) const
nsIContent *
SVGSwitchElement::FindActiveChild() const
{
bool allowReorder = AttrValueIs(kNameSpaceID_None,
nsGkAtoms::allowReorder,
nsGkAtoms::yes, eCaseMatters);
const nsAdoptingString& acceptLangs =
Preferences::GetLocalizedString("intl.accept_languages");
if (allowReorder && !acceptLangs.IsEmpty()) {
if (!acceptLangs.IsEmpty()) {
int32_t bestLanguagePreferenceRank = -1;
nsIContent *bestChild = nullptr;
nsIContent *defaultChild = nullptr;

Просмотреть файл

@ -58,21 +58,7 @@ function run1()
var second = doc.getElementById("second");
var third = doc.getElementById("third");
/* test for an exact match */
second.setAttribute("systemLanguage", "en-gb");
checkBounds(s, 75, 100, 50, 50);
/* test for a close match i.e. the same language prefix */
second.setAttribute("systemLanguage", "en-us");
checkWidth(s, 50);
/* test that we pick the first match */
first.setAttribute("systemLanguage", "it");
checkWidth(s, 70);
/* this time with reordering */
first.setAttribute("systemLanguage", "fr");
s.setAttribute("allowReorder", "yes");
/* test for an exact match */
second.setAttribute("systemLanguage", "en-gb");

Просмотреть файл

@ -32,13 +32,17 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(PlaceholderTxn)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(PlaceholderTxn,
EditAggregateTxn)
ImplCycleCollectionUnlink(*tmp->mStartSel);
if (tmp->mStartSel) {
ImplCycleCollectionUnlink(*tmp->mStartSel);
}
NS_IMPL_CYCLE_COLLECTION_UNLINK(mEndSel);
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(PlaceholderTxn,
EditAggregateTxn)
ImplCycleCollectionTraverse(cb, *tmp->mStartSel, "mStartSel", 0);
if (tmp->mStartSel) {
ImplCycleCollectionTraverse(cb, *tmp->mStartSel, "mStartSel", 0);
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEndSel);
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END

Просмотреть файл

@ -192,6 +192,13 @@ GPUProcessHost::KillHard(const char* aReason)
NewRunnableFunction(&ProcessWatcher::EnsureProcessTerminated, handle, /*force=*/true));
}
static void
DelayedDeleteSubprocess(GeckoChildProcessHost* aSubprocess)
{
XRE_GetIOMessageLoop()->
PostTask(mozilla::MakeAndAddRef<DeleteTask<GeckoChildProcessHost>>(aSubprocess));
}
void
GPUProcessHost::DestroyProcess()
{
@ -202,7 +209,8 @@ GPUProcessHost::DestroyProcess()
mTaskFactory.RevokeAll();
}
DissociateActor();
MessageLoop::current()->
PostTask(NewRunnableFunction(DelayedDeleteSubprocess, this));
}
} // namespace gfx

Просмотреть файл

@ -170,10 +170,9 @@ GPUProcessManager::CreateTopLevelCompositor(widget::CompositorWidgetProxy* aProx
PCompositorBridgeParent*
GPUProcessManager::CreateTabCompositorBridge(ipc::Transport* aTransport,
base::ProcessId aOtherProcess,
ipc::GeckoChildProcessHost* aSubprocess)
base::ProcessId aOtherProcess)
{
return CompositorBridgeParent::Create(aTransport, aOtherProcess, aSubprocess);
return CompositorBridgeParent::Create(aTransport, aOtherProcess);
}
already_AddRefed<APZCTreeManager>

Просмотреть файл

@ -70,8 +70,7 @@ public:
layers::PCompositorBridgeParent* CreateTabCompositorBridge(
ipc::Transport* aTransport,
base::ProcessId aOtherProcess,
ipc::GeckoChildProcessHost* aSubprocess);
base::ProcessId aOtherProcess);
// This returns a reference to the APZCTreeManager to which
// pan/zoom-related events can be sent.

Просмотреть файл

@ -68,7 +68,6 @@
#endif
#include "GeckoProfiler.h"
#include "mozilla/ipc/ProtocolTypes.h"
#include "mozilla/ipc/GeckoChildProcessHost.h"
#include "mozilla/unused.h"
#include "mozilla/Hal.h"
#include "mozilla/HalTypes.h"
@ -1819,7 +1818,6 @@ public:
explicit CrossProcessCompositorBridgeParent(Transport* aTransport)
: CompositorBridgeParentIPCAllocator("CrossProcessCompositorBridgeParent")
, mTransport(aTransport)
, mSubprocess(nullptr)
, mNotifyAfterRemotePaint(false)
, mDestroyCalled(false)
{
@ -1998,7 +1996,6 @@ private:
// ourself. This is released (deferred) in ActorDestroy().
RefPtr<CrossProcessCompositorBridgeParent> mSelfRef;
Transport* mTransport;
ipc::GeckoChildProcessHost* mSubprocess;
RefPtr<CompositorThreadHolder> mCompositorThreadHolder;
// If true, we should send a RemotePaintIsReady message when the layer transaction
@ -2158,18 +2155,13 @@ OpenCompositor(CrossProcessCompositorBridgeParent* aCompositor,
}
/*static*/ PCompositorBridgeParent*
CompositorBridgeParent::Create(Transport* aTransport, ProcessId aOtherPid, GeckoChildProcessHost* aProcessHost)
CompositorBridgeParent::Create(Transport* aTransport, ProcessId aOtherPid)
{
gfxPlatform::InitLayersIPC();
RefPtr<CrossProcessCompositorBridgeParent> cpcp =
new CrossProcessCompositorBridgeParent(aTransport);
if (aProcessHost) {
cpcp->mSubprocess = aProcessHost;
aProcessHost->AssociateActor();
}
cpcp->mSelfRef = cpcp;
CompositorLoop()->PostTask(
NewRunnableFunction(OpenCompositor, cpcp.get(),
@ -2277,11 +2269,6 @@ CrossProcessCompositorBridgeParent::ActorDestroy(ActorDestroyReason aWhy)
RefPtr<CompositorLRU> lru = CompositorLRU::GetSingleton();
lru->Remove(this);
if (mSubprocess) {
mSubprocess->DissociateActor();
mSubprocess = nullptr;
}
// We must keep this object alive untill the code handling message
// reception is finished on this thread.
MessageLoop::current()->PostTask(NewRunnableMethod(this, &CrossProcessCompositorBridgeParent::DeferredDestroy));
@ -2758,7 +2745,7 @@ CrossProcessCompositorBridgeParent::CloneToplevel(
Transport* transport = OpenDescriptor(aFds[i].fd(),
Transport::MODE_SERVER);
PCompositorBridgeParent* compositor =
CompositorBridgeParent::Create(transport, base::GetProcId(aPeerProcess), mSubprocess);
CompositorBridgeParent::Create(transport, base::GetProcId(aPeerProcess));
compositor->CloneManagees(this, aCtx);
compositor->IToplevelProtocol::SetTransport(transport);
// The reference to the compositor thread is held in OnChannelConnected().

Просмотреть файл

@ -51,7 +51,6 @@ class GPUProcessManager;
} // namespace gfx
namespace ipc {
class GeckoChildProcessHost;
class Shmem;
} // namespace ipc
@ -400,7 +399,7 @@ public:
* directly to us. Transport is to its thread context.
*/
static PCompositorBridgeParent*
Create(Transport* aTransport, ProcessId aOtherProcess, mozilla::ipc::GeckoChildProcessHost* aProcessHost);
Create(Transport* aTransport, ProcessId aOtherProcess);
struct LayerTreeState {
LayerTreeState();

Просмотреть файл

@ -16,7 +16,6 @@
#include "mozilla/ipc/MessageChannel.h" // for MessageChannel, etc
#include "mozilla/ipc/ProtocolUtils.h"
#include "mozilla/ipc/Transport.h" // for Transport
#include "mozilla/ipc/GeckoChildProcessHost.h"
#include "mozilla/media/MediaSystemResourceManagerParent.h" // for MediaSystemResourceManagerParent
#include "mozilla/layers/CompositableTransactionParent.h"
#include "mozilla/layers/LayerManagerComposite.h"
@ -58,7 +57,6 @@ ImageBridgeParent::ImageBridgeParent(MessageLoop* aLoop,
, mTransport(aTransport)
, mSetChildThreadPriority(false)
, mClosed(false)
, mSubprocess(nullptr)
{
MOZ_ASSERT(NS_IsMainThread());
sMainLoop = MessageLoop::current();
@ -100,11 +98,6 @@ ImageBridgeParent::ActorDestroy(ActorDestroyReason aWhy)
// Can't alloc/dealloc shmems from now on.
mClosed = true;
if (mSubprocess) {
mSubprocess->DissociateActor();
mSubprocess = nullptr;
}
MessageLoop::current()->PostTask(NewRunnableMethod(this, &ImageBridgeParent::DeferredDestroy));
// It is very important that this method gets called at shutdown (be it a clean
@ -203,16 +196,11 @@ ConnectImageBridgeInParentProcess(ImageBridgeParent* aBridge,
}
/*static*/ PImageBridgeParent*
ImageBridgeParent::Create(Transport* aTransport, ProcessId aChildProcessId, GeckoChildProcessHost* aProcessHost)
ImageBridgeParent::Create(Transport* aTransport, ProcessId aChildProcessId)
{
MessageLoop* loop = CompositorThreadHolder::Loop();
RefPtr<ImageBridgeParent> bridge = new ImageBridgeParent(loop, aTransport, aChildProcessId);
if (aProcessHost) {
bridge->mSubprocess = aProcessHost;
aProcessHost->AssociateActor();
}
loop->PostTask(NewRunnableFunction(ConnectImageBridgeInParentProcess,
bridge.get(), aTransport, aChildProcessId));
return bridge.get();
@ -369,7 +357,7 @@ ImageBridgeParent::CloneToplevel(const InfallibleTArray<ProtocolFdMapping>& aFds
if (aFds[i].protocolId() == unsigned(GetProtocolId())) {
Transport* transport = OpenDescriptor(aFds[i].fd(),
Transport::MODE_SERVER);
PImageBridgeParent* bridge = Create(transport, base::GetProcId(aPeerProcess), mSubprocess);
PImageBridgeParent* bridge = Create(transport, base::GetProcId(aPeerProcess));
bridge->CloneManagees(this, aCtx);
bridge->IToplevelProtocol::SetTransport(transport);
// The reference to the compositor thread is held in OnChannelConnected().

Просмотреть файл

@ -28,7 +28,6 @@ class Thread;
namespace mozilla {
namespace ipc {
class Shmem;
class GeckoChildProcessHost;
} // namespace ipc
namespace layers {
@ -55,7 +54,7 @@ public:
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
static PImageBridgeParent*
Create(Transport* aTransport, ProcessId aChildProcessId, ipc::GeckoChildProcessHost* aProcessHost);
Create(Transport* aTransport, ProcessId aChildProcessId);
// CompositableParentManager
virtual void SendAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessage) override;
@ -155,8 +154,6 @@ private:
bool mSetChildThreadPriority;
bool mClosed;
ipc::GeckoChildProcessHost* mSubprocess;
/**
* Map of all living ImageBridgeParent instances
*/

Просмотреть файл

@ -16,7 +16,11 @@ namespace mozilla {
namespace gfx {
# if defined(MOZILLA_MAY_SUPPORT_NEON)
# if defined(__clang__)
void __attribute((noinline))
# else
void __attribute((noinline,optimize("-fomit-frame-pointer")))
# endif
yuv42x_to_rgb565_row_neon(uint16 *dst,
const uint8 *y,
const uint8 *u,

Просмотреть файл

@ -27,12 +27,10 @@ UNIFIED_SOURCES += [
'src/base/timer.cc',
'src/chrome/common/child_process.cc',
'src/chrome/common/child_process_host.cc',
'src/chrome/common/child_process_info.cc',
'src/chrome/common/child_thread.cc',
'src/chrome/common/chrome_switches.cc',
'src/chrome/common/ipc_channel.cc',
'src/chrome/common/ipc_message.cc',
'src/chrome/common/notification_service.cc',
]
if os_win:
@ -54,7 +52,6 @@ if os_win:
'src/base/thread_local_storage_win.cc',
'src/base/thread_local_win.cc',
'src/base/time_win.cc',
'src/base/waitable_event_watcher_win.cc',
'src/base/waitable_event_win.cc',
'src/base/win_util.cc',
'src/chrome/common/ipc_channel_win.cc',
@ -82,7 +79,6 @@ if os_posix:
'src/base/thread_local_posix.cc',
'src/base/thread_local_storage_posix.cc',
'src/base/waitable_event_posix.cc',
'src/base/waitable_event_watcher_posix.cc',
'src/chrome/common/file_descriptor_set_posix.cc',
'src/chrome/common/ipc_channel_posix.cc',
'src/chrome/common/process_watcher_posix_sigchld.cc',

Просмотреть файл

@ -54,16 +54,6 @@ class WaitableEvent {
// waiting thread has been released.
WaitableEvent(bool manual_reset, bool initially_signaled);
#if defined(OS_WIN)
// Create a WaitableEvent from an Event HANDLE which has already been
// created. This objects takes ownership of the HANDLE and will close it when
// deleted.
explicit WaitableEvent(HANDLE event_handle);
// Releases ownership of the handle from this object.
HANDLE Release();
#endif
~WaitableEvent();
// Put the event in the un-signaled state.

Просмотреть файл

@ -1,156 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_WAITABLE_EVENT_WATCHER_H_
#define BASE_WAITABLE_EVENT_WATCHER_H_
#include "build/build_config.h"
#if defined(OS_WIN)
#include "base/object_watcher.h"
#else
#include "base/message_loop.h"
#include "base/waitable_event.h"
#include "nsAutoPtr.h"
#endif
namespace base {
class Flag;
class AsyncWaiter;
class AsyncCallbackTask;
class WaitableEvent;
// -----------------------------------------------------------------------------
// This class provides a way to wait on a WaitableEvent asynchronously.
//
// Each instance of this object can be waiting on a single WaitableEvent. When
// the waitable event is signaled, a callback is made in the thread of a given
// MessageLoop. This callback can be deleted by deleting the waiter.
//
// Typical usage:
//
// class MyClass : public base::WaitableEventWatcher::Delegate {
// public:
// void DoStuffWhenSignaled(WaitableEvent *waitable_event) {
// watcher_.StartWatching(waitable_event, this);
// }
// virtual void OnWaitableEventSignaled(WaitableEvent* waitable_event) {
// // OK, time to do stuff!
// }
// private:
// base::WaitableEventWatcher watcher_;
// };
//
// In the above example, MyClass wants to "do stuff" when waitable_event
// becomes signaled. WaitableEventWatcher makes this task easy. When MyClass
// goes out of scope, the watcher_ will be destroyed, and there is no need to
// worry about OnWaitableEventSignaled being called on a deleted MyClass
// pointer.
//
// BEWARE: With automatically reset WaitableEvents, a signal may be lost if it
// occurs just before a WaitableEventWatcher is deleted. There is currently no
// safe way to stop watching an automatic reset WaitableEvent without possibly
// missing a signal.
//
// NOTE: you /are/ allowed to delete the WaitableEvent while still waiting on
// it with a Watcher. It will act as if the event was never signaled.
// -----------------------------------------------------------------------------
class WaitableEventWatcher
#if defined(OS_POSIX)
: public MessageLoop::DestructionObserver
#endif
{
public:
WaitableEventWatcher();
~WaitableEventWatcher();
class Delegate {
public:
virtual ~Delegate() { }
// -------------------------------------------------------------------------
// This is called on the MessageLoop thread when WaitableEvent has been
// signaled.
//
// Note: the event may not be signaled by the time that this function is
// called. This indicates only that it has been signaled at some point in
// the past.
// -------------------------------------------------------------------------
virtual void OnWaitableEventSignaled(WaitableEvent* waitable_event) = 0;
};
// ---------------------------------------------------------------------------
// When @event is signaled, the given delegate is called on the thread of the
// current message loop when StartWatching is called. The delegate is not
// deleted.
// ---------------------------------------------------------------------------
bool StartWatching(WaitableEvent* event, Delegate* delegate);
// ---------------------------------------------------------------------------
// Cancel the current watch. Must be called from the same thread which
// started the watch.
//
// Does nothing if no event is being watched, nor if the watch has completed.
// The delegate will *not* be called for the current watch after this
// function returns. Since the delegate runs on the same thread as this
// function, it cannot be called during this function either.
// ---------------------------------------------------------------------------
void StopWatching();
// ---------------------------------------------------------------------------
// Return the currently watched event, or NULL if no object is currently being
// watched.
// ---------------------------------------------------------------------------
WaitableEvent* GetWatchedEvent();
private:
WaitableEvent* event_;
#if defined(OS_WIN)
// ---------------------------------------------------------------------------
// The helper class exists because, if WaitableEventWatcher were to inherit
// from ObjectWatcher::Delegate, then it couldn't also have an inner class
// called Delegate (at least on Windows). Thus this object exists to proxy
// the callback function
// ---------------------------------------------------------------------------
class ObjectWatcherHelper : public ObjectWatcher::Delegate {
public:
ObjectWatcherHelper(WaitableEventWatcher* watcher);
// -------------------------------------------------------------------------
// Implementation of ObjectWatcher::Delegate
// -------------------------------------------------------------------------
void OnObjectSignaled(HANDLE h);
private:
WaitableEventWatcher *const watcher_;
};
void OnObjectSignaled();
Delegate* delegate_;
ObjectWatcherHelper helper_;
ObjectWatcher watcher_;
#else
// ---------------------------------------------------------------------------
// Implementation of MessageLoop::DestructionObserver
// ---------------------------------------------------------------------------
void WillDestroyCurrentMessageLoop();
MessageLoop* message_loop_;
RefPtr<Flag> cancel_flag_;
AsyncWaiter* waiter_;
RefPtr<AsyncCallbackTask> callback_task_;
RefPtr<WaitableEvent::WaitableEventKernel> kernel_;
#endif
};
} // namespace base
#endif // BASE_WAITABLE_EVENT_WATCHER_H_

Просмотреть файл

@ -1,287 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/waitable_event_watcher.h"
#include "base/condition_variable.h"
#include "base/lock.h"
#include "base/message_loop.h"
#include "base/waitable_event.h"
#include "nsISupportsImpl.h"
#include "nsAutoPtr.h"
#include "mozilla/Attributes.h"
namespace base {
// -----------------------------------------------------------------------------
// WaitableEventWatcher (async waits).
//
// The basic design is that we add an AsyncWaiter to the wait-list of the event.
// That AsyncWaiter has a pointer to MessageLoop, and a Task to be posted to it.
// The MessageLoop ends up running the task, which calls the delegate.
//
// Since the wait can be canceled, we have a thread-safe Flag object which is
// set when the wait has been canceled. At each stage in the above, we check the
// flag before going onto the next stage. Since the wait may only be canceled in
// the MessageLoop which runs the Task, we are assured that the delegate cannot
// be called after canceling...
// -----------------------------------------------------------------------------
// A thread-safe, reference-counted, write-once flag.
// -----------------------------------------------------------------------------
class Flag final {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Flag)
Flag() { flag_ = false; }
void Set() {
AutoLock locked(lock_);
flag_ = true;
}
bool value() const {
AutoLock locked(lock_);
return flag_;
}
protected:
~Flag() {}
private:
mutable Lock lock_;
bool flag_;
};
// -----------------------------------------------------------------------------
// This is an asynchronous waiter which posts a task to a MessageLoop when
// fired. An AsyncWaiter may only be in a single wait-list.
// -----------------------------------------------------------------------------
class AsyncWaiter final : public WaitableEvent::Waiter {
public:
AsyncWaiter(MessageLoop* message_loop,
already_AddRefed<mozilla::Runnable> task, Flag* flag)
: message_loop_(message_loop),
cb_task_(task),
flag_(flag) { }
bool Fire(WaitableEvent* event) {
if (flag_->value()) {
// If the callback has been canceled, we don't enqueue the task, we just
// delete it instead.
cb_task_ = nullptr;
} else {
message_loop_->PostTask(cb_task_.forget());
}
// We are removed from the wait-list by the WaitableEvent itself. It only
// remains to delete ourselves.
delete this;
// We can always return true because an AsyncWaiter is never in two
// different wait-lists at the same time.
return true;
}
// See StopWatching for discussion
bool Compare(void* tag) {
return tag == flag_.get();
}
private:
MessageLoop *const message_loop_;
RefPtr<mozilla::Runnable> cb_task_;
RefPtr<Flag> flag_;
};
// -----------------------------------------------------------------------------
// For async waits we need to make a callback in a MessageLoop thread. We do
// this by posting this task, which calls the delegate and keeps track of when
// the event is canceled.
// -----------------------------------------------------------------------------
class AsyncCallbackTask : public mozilla::Runnable {
public:
AsyncCallbackTask(Flag* flag, WaitableEventWatcher::Delegate* delegate,
WaitableEvent* event)
: flag_(flag),
delegate_(delegate),
event_(event) {
}
NS_IMETHOD Run() override {
// Runs in MessageLoop thread.
if (!flag_->value()) {
// This is to let the WaitableEventWatcher know that the event has occured
// because it needs to be able to return NULL from GetWatchedObject
flag_->Set();
delegate_->OnWaitableEventSignaled(event_);
}
return NS_OK;
// We are deleted by the MessageLoop
}
private:
RefPtr<Flag> flag_;
WaitableEventWatcher::Delegate *const delegate_;
WaitableEvent *const event_;
};
WaitableEventWatcher::WaitableEventWatcher()
: event_(NULL),
message_loop_(NULL),
cancel_flag_(NULL) {
}
WaitableEventWatcher::~WaitableEventWatcher() {
StopWatching();
}
// -----------------------------------------------------------------------------
// The Handle is how the user cancels a wait. After deleting the Handle we
// insure that the delegate cannot be called.
// -----------------------------------------------------------------------------
bool WaitableEventWatcher::StartWatching
(WaitableEvent* event, WaitableEventWatcher::Delegate* delegate) {
MessageLoop *const current_ml = MessageLoop::current();
DCHECK(current_ml) << "Cannot create WaitableEventWatcher without a "
"current MessageLoop";
// A user may call StartWatching from within the callback function. In this
// case, we won't know that we have finished watching, expect that the Flag
// will have been set in AsyncCallbackTask::Run()
if (cancel_flag_.get() && cancel_flag_->value()) {
if (message_loop_) {
message_loop_->RemoveDestructionObserver(this);
message_loop_ = NULL;
}
cancel_flag_ = NULL;
}
DCHECK(!cancel_flag_.get()) << "StartWatching called while still watching";
cancel_flag_ = new Flag;
callback_task_ = new AsyncCallbackTask(cancel_flag_, delegate, event);
WaitableEvent::WaitableEventKernel* kernel = event->kernel_.get();
AutoLock locked(kernel->lock_);
if (kernel->signaled_) {
if (!kernel->manual_reset_)
kernel->signaled_ = false;
// No hairpinning - we can't call the delegate directly here. We have to
// enqueue a task on the MessageLoop as normal.
RefPtr<AsyncCallbackTask> addrefedTask = callback_task_;
current_ml->PostTask(addrefedTask.forget());
return true;
}
message_loop_ = current_ml;
current_ml->AddDestructionObserver(this);
event_ = event;
kernel_ = kernel;
RefPtr<AsyncCallbackTask> addrefedTask = callback_task_;
waiter_ = new AsyncWaiter(current_ml, addrefedTask.forget(), cancel_flag_);
event->Enqueue(waiter_);
return true;
}
void WaitableEventWatcher::StopWatching() {
if (message_loop_) {
message_loop_->RemoveDestructionObserver(this);
message_loop_ = NULL;
}
if (!cancel_flag_.get()) // if not currently watching...
return;
if (cancel_flag_->value()) {
// In this case, the event has fired, but we haven't figured that out yet.
// The WaitableEvent may have been deleted too.
cancel_flag_ = NULL;
return;
}
if (!kernel_.get()) {
// We have no kernel. This means that we never enqueued a Waiter on an
// event because the event was already signaled when StartWatching was
// called.
//
// In this case, a task was enqueued on the MessageLoop and will run.
// We set the flag in case the task hasn't yet run. The flag will stop the
// delegate getting called. If the task has run then we have the last
// reference to the flag and it will be deleted immedately after.
cancel_flag_->Set();
cancel_flag_ = NULL;
return;
}
AutoLock locked(kernel_->lock_);
// We have a lock on the kernel. No one else can signal the event while we
// have it.
// We have a possible ABA issue here. If Dequeue was to compare only the
// pointer values then it's possible that the AsyncWaiter could have been
// fired, freed and the memory reused for a different Waiter which was
// enqueued in the same wait-list. We would think that that waiter was our
// AsyncWaiter and remove it.
//
// To stop this, Dequeue also takes a tag argument which is passed to the
// virtual Compare function before the two are considered a match. So we need
// a tag which is good for the lifetime of this handle: the Flag. Since we
// have a reference to the Flag, its memory cannot be reused while this object
// still exists. So if we find a waiter with the correct pointer value, and
// which shares a Flag pointer, we have a real match.
if (kernel_->Dequeue(waiter_, cancel_flag_.get())) {
// Case 2: the waiter hasn't been signaled yet; it was still on the wait
// list. We've removed it, thus we can delete it and the task (which cannot
// have been enqueued with the MessageLoop because the waiter was never
// signaled)
delete waiter_;
callback_task_ = nullptr;
cancel_flag_ = NULL;
return;
}
// Case 3: the waiter isn't on the wait-list, thus it was signaled. It may
// not have run yet, so we set the flag to tell it not to bother enqueuing the
// task on the MessageLoop, but to delete it instead. The Waiter deletes
// itself once run.
cancel_flag_->Set();
cancel_flag_ = NULL;
// If the waiter has already run then the task has been enqueued. If the Task
// hasn't yet run, the flag will stop the delegate from getting called. (This
// is thread safe because one may only delete a Handle from the MessageLoop
// thread.)
//
// If the delegate has already been called then we have nothing to do. The
// task has been deleted by the MessageLoop.
}
WaitableEvent* WaitableEventWatcher::GetWatchedEvent() {
if (!cancel_flag_.get())
return NULL;
if (cancel_flag_->value())
return NULL;
return event_;
}
// -----------------------------------------------------------------------------
// This is called when the MessageLoop which the callback will be run it is
// deleted. We need to cancel the callback as if we had been deleted, but we
// will still be deleted at some point in the future.
// -----------------------------------------------------------------------------
void WaitableEventWatcher::WillDestroyCurrentMessageLoop() {
StopWatching();
}
} // namespace base

Просмотреть файл

@ -1,62 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/waitable_event_watcher.h"
#include "base/compiler_specific.h"
#include "base/object_watcher.h"
#include "base/waitable_event.h"
namespace base {
WaitableEventWatcher::ObjectWatcherHelper::ObjectWatcherHelper(
WaitableEventWatcher* watcher)
: watcher_(watcher) {
};
void WaitableEventWatcher::ObjectWatcherHelper::OnObjectSignaled(HANDLE h) {
watcher_->OnObjectSignaled();
}
WaitableEventWatcher::WaitableEventWatcher()
: event_(NULL),
ALLOW_THIS_IN_INITIALIZER_LIST(helper_(this)),
delegate_(NULL) {
}
WaitableEventWatcher::~WaitableEventWatcher() {
}
bool WaitableEventWatcher::StartWatching(WaitableEvent* event,
Delegate* delegate) {
delegate_ = delegate;
event_ = event;
return watcher_.StartWatching(event->handle(), &helper_);
}
void WaitableEventWatcher::StopWatching() {
delegate_ = NULL;
event_ = NULL;
watcher_.StopWatching();
}
WaitableEvent* WaitableEventWatcher::GetWatchedEvent() {
return event_;
}
void WaitableEventWatcher::OnObjectSignaled() {
WaitableEvent* event = event_;
Delegate* delegate = delegate_;
event_ = NULL;
delegate_ = NULL;
DCHECK(event);
delegate->OnWaitableEventSignaled(event);
}
} // namespace base

Просмотреть файл

@ -21,21 +21,10 @@ WaitableEvent::WaitableEvent(bool manual_reset, bool signaled)
CHECK(handle_);
}
WaitableEvent::WaitableEvent(HANDLE handle)
: handle_(handle) {
CHECK(handle) << "Tried to create WaitableEvent from NULL handle";
}
WaitableEvent::~WaitableEvent() {
CloseHandle(handle_);
}
HANDLE WaitableEvent::Release() {
HANDLE rv = handle_;
handle_ = INVALID_HANDLE_VALUE;
return rv;
}
void WaitableEvent::Reset() {
ResetEvent(handle_);
}

Просмотреть файл

@ -13,9 +13,7 @@
ChildProcess* ChildProcess::child_process_;
ChildProcess::ChildProcess(ChildThread* child_thread)
: child_thread_(child_thread),
ref_count_(0),
shutdown_event_(true, false) {
: child_thread_(child_thread) {
DCHECK(!child_process_);
child_process_ = this;
if (child_thread_.get()) // null in unittests.
@ -25,37 +23,8 @@ ChildProcess::ChildProcess(ChildThread* child_thread)
ChildProcess::~ChildProcess() {
DCHECK(child_process_ == this);
// Signal this event before destroying the child process. That way all
// background threads can cleanup.
// For example, in the renderer the RenderThread instances will be able to
// notice shutdown before the render process begins waiting for them to exit.
shutdown_event_.Signal();
if (child_thread_.get())
child_thread_->Stop();
child_process_ = NULL;
}
void ChildProcess::AddRefProcess() {
DCHECK(!child_thread_.get() || // null in unittests.
MessageLoop::current() == child_thread_->message_loop());
ref_count_++;
}
void ChildProcess::ReleaseProcess() {
DCHECK(!child_thread_.get() || // null in unittests.
MessageLoop::current() == child_thread_->message_loop());
DCHECK(ref_count_);
DCHECK(child_process_);
if (--ref_count_)
return;
if (child_thread_.get()) // null in unittests.
child_thread_->OnProcessFinalRelease();
}
base::WaitableEvent* ChildProcess::GetShutDownEvent() {
DCHECK(child_process_);
return &child_process_->shutdown_event_;
}

Просмотреть файл

@ -29,24 +29,6 @@ class ChildProcess {
// Getter for this process' main thread.
ChildThread* child_thread() { return child_thread_.get(); }
// A global event object that is signalled when the main thread's message
// loop exits. This gives background threads a way to observe the main
// thread shutting down. This can be useful when a background thread is
// waiting for some information from the browser process. If the browser
// process goes away prematurely, the background thread can at least notice
// the child processes's main thread exiting to determine that it should give
// up waiting.
// For example, see the renderer code used to implement
// webkit_glue::GetCookies.
base::WaitableEvent* GetShutDownEvent();
// These are used for ref-counting the child process. The process shuts
// itself down when the ref count reaches 0.
// For example, in the renderer process, generally each tab managed by this
// process will hold a reference to the process, and release when closed.
void AddRefProcess();
void ReleaseProcess();
// Getter for the one ChildProcess object for this process.
static ChildProcess* current() { return child_process_; }
@ -55,11 +37,6 @@ class ChildProcess {
// it depends on it (indirectly through IPC::SyncChannel).
mozilla::UniquePtr<ChildThread> child_thread_;
int ref_count_;
// An event that will be signalled when we shutdown.
base::WaitableEvent shutdown_event_;
// The singleton instance for this process.
static ChildProcess* child_process_;

Просмотреть файл

@ -16,64 +16,17 @@
#include "mozilla/ipc/BrowserProcessSubThread.h"
#include "mozilla/ipc/Transport.h"
typedef mozilla::ipc::BrowserProcessSubThread ChromeThread;
#include "chrome/common/notification_service.h"
#include "chrome/common/notification_type.h"
#include "chrome/common/process_watcher.h"
#include "chrome/common/result_codes.h"
using mozilla::ipc::FileDescriptor;
namespace {
typedef std::list<ChildProcessHost*> ChildProcessList;
// The NotificationTask is used to notify about plugin process connection/
// disconnection. It is needed because the notifications in the
// NotificationService must happen in the main thread.
class ChildNotificationTask : public mozilla::Runnable {
public:
ChildNotificationTask(
NotificationType notification_type, ChildProcessInfo* info)
: notification_type_(notification_type), info_(*info) { }
NS_IMETHOD Run() {
NotificationService::current()->
Notify(notification_type_, NotificationService::AllSources(),
Details<ChildProcessInfo>(&info_));
return NS_OK;
}
private:
NotificationType notification_type_;
ChildProcessInfo info_;
};
} // namespace
ChildProcessHost::ChildProcessHost(ProcessType type)
:
ChildProcessInfo(type),
ALLOW_THIS_IN_INITIALIZER_LIST(listener_(this)),
opening_channel_(false),
process_event_(nullptr) {
Singleton<ChildProcessList>::get()->push_back(this);
ChildProcessHost::ChildProcessHost()
: ALLOW_THIS_IN_INITIALIZER_LIST(listener_(this)),
opening_channel_(false) {
}
ChildProcessHost::~ChildProcessHost() {
Singleton<ChildProcessList>::get()->remove(this);
if (handle()) {
watcher_.StopWatching();
ProcessWatcher::EnsureProcessTerminated(handle());
#if defined(OS_WIN)
// Above call took ownership, so don't want WaitableEvent to assert because
// the handle isn't valid anymore.
process_event_->Release();
#endif
}
}
bool ChildProcessHost::CreateChannel() {
@ -104,79 +57,18 @@ bool ChildProcessHost::CreateChannel(FileDescriptor& aFileDescriptor) {
return true;
}
void ChildProcessHost::SetHandle(base::ProcessHandle process) {
#if defined(OS_WIN)
process_event_.reset(new base::WaitableEvent(process));
DCHECK(!handle());
set_handle(process);
watcher_.StartWatching(process_event_.get(), this);
#endif
}
void ChildProcessHost::InstanceCreated() {
Notify(NotificationType(NotificationType::CHILD_INSTANCE_CREATED));
}
bool ChildProcessHost::Send(IPC::Message* msg) {
if (!channel_.get()) {
delete msg;
return false;
}
return channel_->Send(msg);
}
void ChildProcessHost::Notify(NotificationType type) {
MessageLoop* loop = ChromeThread::GetMessageLoop(ChromeThread::IO);
if (!loop)
loop = mozilla::ipc::ProcessChild::message_loop();
if (!loop)
loop = MessageLoop::current();
RefPtr<ChildNotificationTask> task = new ChildNotificationTask(type, this);
loop->PostTask(task.forget());
}
void ChildProcessHost::OnWaitableEventSignaled(base::WaitableEvent *event) {
#if defined(OS_WIN)
HANDLE object = event->handle();
DCHECK(handle());
DCHECK_EQ(object, handle());
bool did_crash = base::DidProcessCrash(NULL, object);
if (did_crash) {
// Report that this child process crashed.
Notify(NotificationType(NotificationType::CHILD_PROCESS_CRASHED));
}
// Notify in the main loop of the disconnection.
Notify(NotificationType(NotificationType::CHILD_PROCESS_HOST_DISCONNECTED));
#endif
}
ChildProcessHost::ListenerHook::ListenerHook(ChildProcessHost* host)
: host_(host) {
}
void ChildProcessHost::ListenerHook::OnMessageReceived(
IPC::Message&& msg) {
bool msg_is_ok = true;
bool handled = false;
if (!handled) {
host_->OnMessageReceived(mozilla::Move(msg));
}
if (!msg_is_ok)
base::KillProcess(host_->handle(), ResultCodes::KILLED_BAD_MESSAGE, false);
host_->OnMessageReceived(mozilla::Move(msg));
}
void ChildProcessHost::ListenerHook::OnChannelConnected(int32_t peer_pid) {
host_->opening_channel_ = false;
host_->OnChannelConnected(peer_pid);
// Notify in the main loop of the connection.
host_->Notify(NotificationType(NotificationType::CHILD_PROCESS_HOST_CONNECTED));
}
void ChildProcessHost::ListenerHook::OnChannelError() {
@ -187,33 +79,3 @@ void ChildProcessHost::ListenerHook::OnChannelError() {
void ChildProcessHost::ListenerHook::GetQueuedMessages(std::queue<IPC::Message>& queue) {
host_->GetQueuedMessages(queue);
}
ChildProcessHost::Iterator::Iterator() : all_(true) {
iterator_ = Singleton<ChildProcessList>::get()->begin();
}
ChildProcessHost::Iterator::Iterator(ProcessType type)
: all_(false), type_(type) {
iterator_ = Singleton<ChildProcessList>::get()->begin();
if (!Done() && (*iterator_)->type() != type_)
++(*this);
}
ChildProcessHost* ChildProcessHost::Iterator::operator++() {
do {
++iterator_;
if (Done())
break;
if (!all_ && (*iterator_)->type() != type_)
continue;
return *iterator_;
} while (true);
return NULL;
}
bool ChildProcessHost::Iterator::Done() {
return iterator_ == Singleton<ChildProcessList>::get()->end();
}

Просмотреть файл

@ -12,8 +12,6 @@
#include <list>
#include "base/basictypes.h"
#include "base/waitable_event_watcher.h"
#include "chrome/common/child_process_info.h"
#include "chrome/common/ipc_channel.h"
#include "mozilla/UniquePtr.h"
@ -23,43 +21,14 @@ class FileDescriptor;
}
}
class NotificationType;
// Plugins/workers and other child processes that live on the IO thread should
// derive from this class.
class ChildProcessHost :
public IPC::Message::Sender,
public ChildProcessInfo,
public base::WaitableEventWatcher::Delegate,
public IPC::Channel::Listener {
class ChildProcessHost : public IPC::Channel::Listener {
public:
virtual ~ChildProcessHost();
// ResourceDispatcherHost::Receiver implementation:
virtual bool Send(IPC::Message* msg);
// The Iterator class allows iteration through either all child processes, or
// ones of a specific type, depending on which constructor is used. Note that
// this should be done from the IO thread and that the iterator should not be
// kept around as it may be invalidated on subsequent event processing in the
// event loop.
class Iterator {
public:
Iterator();
explicit Iterator(ProcessType type);
ChildProcessHost* operator->() { return *iterator_; }
ChildProcessHost* operator*() { return *iterator_; }
ChildProcessHost* operator++();
bool Done();
private:
bool all_;
ProcessType type_;
std::list<ChildProcessHost*>::iterator iterator_;
};
protected:
explicit ChildProcessHost(ProcessType type);
explicit ChildProcessHost();
// Derived classes return true if it's ok to shut down the child process.
virtual bool CanShutdown() = 0;
@ -69,13 +38,6 @@ class ChildProcessHost :
bool CreateChannel(mozilla::ipc::FileDescriptor& aFileDescriptor);
// Once the subclass gets a handle to the process, it needs to tell
// ChildProcessHost using this function.
void SetHandle(base::ProcessHandle handle);
// Notifies us that an instance has been created on this child process.
void InstanceCreated();
// IPC::Channel::Listener implementation:
virtual void OnMessageReceived(IPC::Message&& msg) { }
virtual void OnChannelConnected(int32_t peer_pid) { }
@ -84,19 +46,9 @@ class ChildProcessHost :
bool opening_channel() { return opening_channel_; }
const std::wstring& channel_id() { return channel_id_; }
base::WaitableEvent* GetProcessEvent() { return process_event_.get(); }
const IPC::Channel& channel() const { return *channel_; }
IPC::Channel* channelp() const { return channel_.get(); }
private:
// Sends the given notification to the notification service on the UI thread.
void Notify(NotificationType type);
protected:
// WaitableEventWatcher::Delegate implementation:
virtual void OnWaitableEventSignaled(base::WaitableEvent *event);
private:
// By using an internal class as the IPC::Channel::Listener, we can intercept
// OnMessageReceived/OnChannelConnected and do our own processing before
@ -122,11 +74,6 @@ class ChildProcessHost :
// IPC Channel's id.
std::wstring channel_id_;
// Used to watch the child process handle.
base::WaitableEventWatcher watcher_;
mozilla::UniquePtr<base::WaitableEvent> process_event_;
};
#endif // CHROME_COMMON_CHILD_PROCESS_HOST_H_

Просмотреть файл

@ -1,46 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/common/child_process_info.h"
#include <limits>
#include "base/logging.h"
std::wstring ChildProcessInfo::GetTypeNameInEnglish(
ChildProcessInfo::ProcessType type) {
switch (type) {
case BROWSER_PROCESS:
return L"Browser";
case RENDER_PROCESS:
return L"Tab";
case PLUGIN_PROCESS:
return L"Plug-in";
case WORKER_PROCESS:
return L"Web Worker";
case UNKNOWN_PROCESS:
default:
DCHECK(false) << "Unknown child process type!";
return L"Unknown";
}
}
std::wstring ChildProcessInfo::GetLocalizedTitle() const {
return name_;
}
ChildProcessInfo::ChildProcessInfo(ProcessType type) {
// This constructor is only used by objects which derive from this class,
// which means *this* is a real object that refers to a child process, and not
// just a simple object that contains information about it. So add it to our
// list of running processes.
type_ = type;
pid_ = -1;
}
ChildProcessInfo::~ChildProcessInfo() {
}

Просмотреть файл

@ -1,103 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_COMMON_CHILD_PROCESS_INFO_H_
#define CHROME_COMMON_CHILD_PROCESS_INFO_H_
#include <string>
#include "base/process.h"
// Holds information about a child process.
class ChildProcessInfo {
public:
enum ProcessType {
BROWSER_PROCESS,
RENDER_PROCESS,
PLUGIN_PROCESS,
WORKER_PROCESS,
UNKNOWN_PROCESS
};
// Returns the type of the process.
ProcessType type() const { return type_; }
// Returns the name of the process. i.e. for plugins it might be Flash, while
// for workers it might be the domain that it's from.
std::wstring name() const { return name_; }
// Getter to the process handle.
base::ProcessHandle handle() const { return process_.handle(); }
virtual int GetProcessId() const {
if (pid_ != -1)
return pid_;
pid_ = process_.pid();
return pid_;
}
void SetProcessBackgrounded() const { process_.SetProcessBackgrounded(true); }
// Returns an English name of the process type, should only be used for non
// user-visible strings, or debugging pages like about:memory.
static std::wstring GetTypeNameInEnglish(ProcessType type);
// Returns a localized title for the child process. For example, a plugin
// process would be "Plug-in: Flash" when name is "Flash".
std::wstring GetLocalizedTitle() const;
ChildProcessInfo(const ChildProcessInfo& original) {
type_ = original.type_;
name_ = original.name_;
process_ = original.process_;
pid_ = original.pid_;
}
ChildProcessInfo& operator=(const ChildProcessInfo& original) {
if (&original != this) {
type_ = original.type_;
name_ = original.name_;
process_ = original.process_;
pid_ = original.pid_;
}
return *this;
}
virtual ~ChildProcessInfo();
// We define the < operator so that the ChildProcessInfo can be used as a key
// in a std::map.
bool operator <(const ChildProcessInfo& rhs) const {
if (process_.handle() != rhs.process_.handle())
return process_ .handle() < rhs.process_.handle();
return false;
}
bool operator ==(const ChildProcessInfo& rhs) const {
return process_.handle() == rhs.process_.handle();
}
protected:
void set_type(ProcessType aType) { type_ = aType; }
void set_name(const std::wstring& aName) { name_ = aName; }
void set_handle(base::ProcessHandle aHandle) {
process_.set_handle(aHandle);
pid_ = -1;
}
// Derived objects need to use this constructor so we know what type we are.
explicit ChildProcessInfo(ProcessType type);
private:
ProcessType type_;
std::wstring name_;
mutable int pid_; // Cache of the process id.
// The handle to the process.
mutable base::Process process_;
};
#endif // CHROME_COMMON_CHILD_PROCESS_INFO_H_

Просмотреть файл

@ -11,14 +11,10 @@
#include "chrome/common/child_process.h"
#include "chrome/common/chrome_switches.h"
// V8 needs a 1MB stack size.
const size_t ChildThread::kV8StackSize = 1024 * 1024;
ChildThread::ChildThread(Thread::Options options)
: Thread("Chrome_ChildThread"),
owner_loop_(MessageLoop::current()),
options_(options),
check_with_browser_before_shutdown_(false) {
options_(options) {
DCHECK(owner_loop_);
channel_name_ = CommandLine::ForCurrentProcess()->GetSwitchValue(
switches::kProcessChannelID);
@ -55,19 +51,7 @@ void ChildThread::MarkThread() {
}
#endif
bool ChildThread::Send(IPC::Message* msg) {
if (!channel_.get()) {
delete msg;
return false;
}
return channel_->Send(msg);
}
void ChildThread::OnMessageReceived(IPC::Message&& msg) {
if (msg.routing_id() == MSG_ROUTING_CONTROL) {
OnControlMessageReceived(msg);
}
}
ChildThread* ChildThread::current() {
@ -86,11 +70,3 @@ void ChildThread::CleanUp() {
// it caches a pointer to this thread.
channel_ = nullptr;
}
void ChildThread::OnProcessFinalRelease() {
if (!check_with_browser_before_shutdown_) {
RefPtr<mozilla::Runnable> task = new MessageLoop::QuitTask();
owner_loop_->PostTask(task.forget());
return;
}
}

Просмотреть файл

@ -15,40 +15,19 @@ class ResourceDispatcher;
// Child processes's background thread should derive from this class.
class ChildThread : public IPC::Channel::Listener,
public IPC::Message::Sender,
public base::Thread {
public:
// Creates the thread.
explicit ChildThread(Thread::Options options);
virtual ~ChildThread();
// IPC::Message::Sender implementation:
virtual bool Send(IPC::Message* msg);
// See documentation on MessageRouter for AddRoute and RemoveRoute
void AddRoute(int32_t routing_id, IPC::Channel::Listener* listener);
void RemoveRoute(int32_t routing_id);
MessageLoop* owner_loop() { return owner_loop_; }
protected:
friend class ChildProcess;
// Starts the thread.
bool Run();
// Overrides the channel name. Used for --single-process mode.
void SetChannelName(const std::wstring& name) { channel_name_ = name; }
// Called when the process refcount is 0.
void OnProcessFinalRelease();
protected:
// The required stack size if V8 runs on a thread.
static const size_t kV8StackSize;
virtual void OnControlMessageReceived(const IPC::Message& msg) { }
// Returns the one child thread.
static ChildThread* current();
@ -75,11 +54,6 @@ class ChildThread : public IPC::Channel::Listener,
Thread::Options options_;
// If true, checks with the browser process before shutdown. This avoids race
// conditions if the process refcount is 0 but there's an IPC message inflight
// that would addref it.
bool check_with_browser_before_shutdown_;
DISALLOW_EVIL_CONSTRUCTORS(ChildThread);
};

Просмотреть файл

@ -16,7 +16,7 @@ namespace IPC {
//------------------------------------------------------------------------------
class Channel : public Message::Sender {
class Channel {
// Security tests need access to the pipe handle.
friend class ChannelTest;
@ -105,7 +105,7 @@ class Channel : public Message::Sender {
//
// If you Send() a message on a Close()'d channel, we delete the message
// immediately.
virtual bool Send(Message* message) override;
bool Send(Message* message);
// Unsound_IsClosed() and Unsound_NumQueuedMessages() are safe to call from
// any thread, but the value returned may be out of date, because we don't

Просмотреть файл

@ -38,18 +38,6 @@ class Message : public Pickle {
public:
typedef uint32_t msgid_t;
// Implemented by objects that can send IPC messages across a channel.
class Sender {
public:
virtual ~Sender() {}
// Sends the given IPC message. The implementor takes ownership of the
// given Message regardless of whether or not this method succeeds. This
// is done to make this method easier to use. Returns true on success and
// false otherwise.
virtual bool Send(Message* msg) = 0;
};
enum PriorityValue {
PRIORITY_NORMAL = 1,
PRIORITY_HIGH = 2,

Просмотреть файл

@ -1,54 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This file defines the type used to provide details for NotificationService
// notifications.
#ifndef CHROME_COMMON_NOTIFICATION_DETAILS_H__
#define CHROME_COMMON_NOTIFICATION_DETAILS_H__
#include "base/basictypes.h"
// Do not declare a NotificationDetails directly--use either
// "Details<detailsclassname>(detailsclasspointer)" or
// NotificationService::NoDetails().
class NotificationDetails {
public:
NotificationDetails() : ptr_(NULL) {}
NotificationDetails(const NotificationDetails& other) : ptr_(other.ptr_) {}
~NotificationDetails() {}
// NotificationDetails can be used as the index for a map; this method
// returns the pointer to the current details as an identifier, for use as a
// map index.
uintptr_t map_key() const { return reinterpret_cast<uintptr_t>(ptr_); }
bool operator!=(const NotificationDetails& other) const {
return ptr_ != other.ptr_;
}
bool operator==(const NotificationDetails& other) const {
return ptr_ == other.ptr_;
}
protected:
explicit NotificationDetails(void* ptr) : ptr_(ptr) {}
void* ptr_;
};
template <class T>
class Details : public NotificationDetails {
public:
explicit Details(T* ptr) : NotificationDetails(ptr) {}
explicit Details(const NotificationDetails& other)
: NotificationDetails(other) {}
T* operator->() const { return ptr(); }
T* ptr() const { return static_cast<T*>(ptr_); }
};
#endif // CHROME_COMMON_NOTIFICATION_DETAILS_H__

Просмотреть файл

@ -1,25 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_COMMON_NOTIFICATION_OBSERVER_H_
#define CHROME_COMMON_NOTIFICATION_OBSERVER_H_
class NotificationDetails;
class NotificationSource;
class NotificationType;
// This is the base class for notification observers. When a matching
// notification is posted to the notification service, Observe is called.
class NotificationObserver {
public:
virtual ~NotificationObserver();
virtual void Observe(NotificationType type,
const NotificationSource& source,
const NotificationDetails& details) = 0;
};
#endif // CHROME_COMMON_NOTIFICATION_OBSERVER_H_

Просмотреть файл

@ -1,55 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_COMMON_NOTIFICATION_REGISTRAR_H_
#define CHROME_COMMON_NOTIFICATION_REGISTRAR_H_
#include <vector>
#include "base/basictypes.h"
#include "chrome/common/notification_observer.h"
// Aids in registering for notifications and ensures that all registered
// notifications are unregistered when the class is destroyed.
//
// The intended use is that you make a NotificationRegistrar member in your
// class and use it to register your notifications instead of going through the
// notification service directly. It will automatically unregister them for
// you.
class NotificationRegistrar {
public:
// This class must not be derived from (we don't have a virtual destructor so
// it won't work). Instead, use it as a member in your class.
NotificationRegistrar();
~NotificationRegistrar();
// Wrappers around NotificationService::[Add|Remove]Observer.
void Add(NotificationObserver* observer,
NotificationType type,
const NotificationSource& source);
void Remove(NotificationObserver* observer,
NotificationType type,
const NotificationSource& source);
// Unregisters all notifications.
void RemoveAll();
private:
struct Record;
// We keep registered notifications in a simple vector. This means we'll do
// brute-force searches when removing them individually, but individual
// removal is uncommon, and there will typically only be a couple of
// notifications anyway.
typedef std::vector<Record> RecordVector;
// Lists all notifications we're currently registered for.
RecordVector registered_;
DISALLOW_COPY_AND_ASSIGN(NotificationRegistrar);
};
#endif // CHROME_COMMON_NOTIFICATION_REGISTRAR_H_

Просмотреть файл

@ -1,145 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/common/notification_service.h"
#include "base/thread_local.h"
static base::ThreadLocalPointer<NotificationService>& get_tls_ptr() {
static base::ThreadLocalPointer<NotificationService> tls_ptr;
return tls_ptr;
}
// static
NotificationService* NotificationService::current() {
return get_tls_ptr().Get();
}
// static
bool NotificationService::HasKey(const NotificationSourceMap& map,
const NotificationSource& source) {
return map.find(source.map_key()) != map.end();
}
NotificationService::NotificationService() {
DCHECK(current() == NULL);
#ifndef NDEBUG
memset(observer_counts_, 0, sizeof(observer_counts_));
#endif
get_tls_ptr().Set(this);
}
void NotificationService::AddObserver(NotificationObserver* observer,
NotificationType type,
const NotificationSource& source) {
DCHECK(type.value < NotificationType::NOTIFICATION_TYPE_COUNT);
// We have gotten some crashes where the observer pointer is NULL. The problem
// is that this happens when we actually execute a notification, so have no
// way of knowing who the bad observer was. We want to know when this happens
// in release mode so we know what code to blame the crash on (since this is
// guaranteed to crash later).
CHECK(observer);
NotificationObserverList* observer_list;
if (HasKey(observers_[type.value], source)) {
observer_list = observers_[type.value][source.map_key()];
} else {
observer_list = new NotificationObserverList;
observers_[type.value][source.map_key()] = observer_list;
}
observer_list->AddObserver(observer);
#ifndef NDEBUG
++observer_counts_[type.value];
#endif
}
void NotificationService::RemoveObserver(NotificationObserver* observer,
NotificationType type,
const NotificationSource& source) {
DCHECK(type.value < NotificationType::NOTIFICATION_TYPE_COUNT);
DCHECK(HasKey(observers_[type.value], source));
NotificationObserverList* observer_list =
observers_[type.value][source.map_key()];
if (observer_list) {
observer_list->RemoveObserver(observer);
#ifndef NDEBUG
--observer_counts_[type.value];
#endif
}
// TODO(jhughes): Remove observer list from map if empty?
}
void NotificationService::Notify(NotificationType type,
const NotificationSource& source,
const NotificationDetails& details) {
DCHECK(type.value > NotificationType::ALL) <<
"Allowed for observing, but not posting.";
DCHECK(type.value < NotificationType::NOTIFICATION_TYPE_COUNT);
// There's no particular reason for the order in which the different
// classes of observers get notified here.
// Notify observers of all types and all sources
if (HasKey(observers_[NotificationType::ALL], AllSources()) &&
source != AllSources()) {
FOR_EACH_OBSERVER(NotificationObserver,
*observers_[NotificationType::ALL][AllSources().map_key()],
Observe(type, source, details));
}
// Notify observers of all types and the given source
if (HasKey(observers_[NotificationType::ALL], source)) {
FOR_EACH_OBSERVER(NotificationObserver,
*observers_[NotificationType::ALL][source.map_key()],
Observe(type, source, details));
}
// Notify observers of the given type and all sources
if (HasKey(observers_[type.value], AllSources()) &&
source != AllSources()) {
FOR_EACH_OBSERVER(NotificationObserver,
*observers_[type.value][AllSources().map_key()],
Observe(type, source, details));
}
// Notify observers of the given type and the given source
if (HasKey(observers_[type.value], source)) {
FOR_EACH_OBSERVER(NotificationObserver,
*observers_[type.value][source.map_key()],
Observe(type, source, details));
}
}
NotificationService::~NotificationService() {
get_tls_ptr().Set(NULL);
#ifndef NDEBUG
for (int i = 0; i < NotificationType::NOTIFICATION_TYPE_COUNT; i++) {
if (observer_counts_[i] > 0) {
// This may not be completely fixable -- see
// http://code.google.com/p/chromium/issues/detail?id=11010 .
// But any new leaks should be fixed.
CHROMIUM_LOG(WARNING) << observer_counts_[i] << " notification observer(s) leaked"
<< " of notification type " << i;
}
}
#endif
for (int i = 0; i < NotificationType::NOTIFICATION_TYPE_COUNT; i++) {
NotificationSourceMap omap = observers_[i];
for (NotificationSourceMap::iterator it = omap.begin();
it != omap.end(); ++it) {
delete it->second;
}
}
}
NotificationObserver::~NotificationObserver() {}

Просмотреть файл

@ -1,102 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This file describes a central switchboard for notifications that might
// happen in various parts of the application, and allows users to register
// observers for various classes of events that they're interested in.
#ifndef CHROME_COMMON_NOTIFICATION_SERVICE_H_
#define CHROME_COMMON_NOTIFICATION_SERVICE_H_
#include <map>
#include "base/observer_list.h"
#include "chrome/common/notification_details.h"
#include "chrome/common/notification_observer.h"
#include "chrome/common/notification_source.h"
#include "chrome/common/notification_type.h"
class NotificationObserver;
class NotificationService {
public:
// Returns the NotificationService object for the current thread, or NULL if
// none.
static NotificationService* current();
// Normally instantiated when the thread is created. Not all threads have
// a NotificationService. Only one instance should be created per thread.
NotificationService();
~NotificationService();
// Registers a NotificationObserver to be called whenever a matching
// notification is posted. Observer is a pointer to an object subclassing
// NotificationObserver to be notified when an event matching the other two
// parameters is posted to this service. Type is the type of events to
// be notified about (or NOTIFY_ALL to receive events of all types).
// Source is a NotificationSource object (created using
// "Source<classname>(pointer)"), if this observer only wants to
// receive events from that object, or NotificationService::AllSources()
// to receive events from all sources.
//
// A given observer can be registered only once for each combination of
// type and source. If the same object is registered more than once,
// it must be removed for each of those combinations of type and source later.
//
// The caller retains ownership of the object pointed to by observer.
void AddObserver(NotificationObserver* observer,
NotificationType type, const NotificationSource& source);
// Removes the object pointed to by observer from receiving notifications
// that match type and source. If no object matching the parameters is
// currently registered, this method is a no-op.
void RemoveObserver(NotificationObserver* observer,
NotificationType type, const NotificationSource& source);
// Synchronously posts a notification to all interested observers.
// Source is a reference to a NotificationSource object representing
// the object originating the notification (can be
// NotificationService::AllSources(), in which case
// only observers interested in all sources will be notified).
// Details is a reference to an object containing additional data about
// the notification. If no additional data is needed, NoDetails() is used.
// There is no particular order in which the observers will be notified.
void Notify(NotificationType type,
const NotificationSource& source,
const NotificationDetails& details);
// Returns a NotificationSource that represents all notification sources
// (for the purpose of registering an observer for events from all sources).
static Source<void> AllSources() { return Source<void>(NULL); }
// Returns a NotificationDetails object that represents a lack of details
// associated with a notification. (This is effectively a null pointer.)
static Details<void> NoDetails() { return Details<void>(NULL); }
private:
typedef base::ObserverList<NotificationObserver> NotificationObserverList;
typedef std::map<uintptr_t, NotificationObserverList*> NotificationSourceMap;
// Convenience function to determine whether a source has a
// NotificationObserverList in the given map;
static bool HasKey(const NotificationSourceMap& map,
const NotificationSource& source);
// Keeps track of the observers for each type of notification.
// Until we get a prohibitively large number of notification types,
// a simple array is probably the fastest way to dispatch.
NotificationSourceMap observers_[NotificationType::NOTIFICATION_TYPE_COUNT];
#ifndef NDEBUG
// Used to check to see that AddObserver and RemoveObserver calls are
// balanced.
int observer_counts_[NotificationType::NOTIFICATION_TYPE_COUNT];
#endif
DISALLOW_COPY_AND_ASSIGN(NotificationService);
};
#endif // CHROME_COMMON_NOTIFICATION_SERVICE_H_

Просмотреть файл

@ -1,53 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This file defines the type used to provide sources for NotificationService
// notifications.
#ifndef CHROME_COMMON_NOTIFICATION_SOURCE_H__
#define CHROME_COMMON_NOTIFICATION_SOURCE_H__
#include "base/basictypes.h"
// Do not declare a NotificationSource directly--use either
// "Source<sourceclassname>(sourceclasspointer)" or
// NotificationService::AllSources().
class NotificationSource {
public:
NotificationSource(const NotificationSource& other) : ptr_(other.ptr_) { }
~NotificationSource() {}
// NotificationSource can be used as the index for a map; this method
// returns the pointer to the current source as an identifier, for use as a
// map index.
uintptr_t map_key() const { return reinterpret_cast<uintptr_t>(ptr_); }
bool operator!=(const NotificationSource& other) const {
return ptr_ != other.ptr_;
}
bool operator==(const NotificationSource& other) const {
return ptr_ == other.ptr_;
}
protected:
explicit NotificationSource(void* ptr) : ptr_(ptr) {}
void* ptr_;
};
template <class T>
class Source : public NotificationSource {
public:
explicit Source(T* ptr) : NotificationSource(ptr) {}
explicit Source(const NotificationSource& other)
: NotificationSource(other) {}
T* operator->() const { return ptr(); }
T* ptr() const { return static_cast<T*>(ptr_); }
};
#endif // CHROME_COMMON_NOTIFICATION_SOURCE_H__

Просмотреть файл

@ -1,576 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_COMMON_NOTIFICATION_TYPE_H_
#define CHROME_COMMON_NOTIFICATION_TYPE_H_
// This file describes various types used to describe and filter notifications
// that pass through the NotificationService.
//
// It is written as an enum inside a class so that it can be forward declared.
// You're not allowed to forward declare an enum, and we want to forward
// declare this since it's required by NotificationObserver which is included
// by a lot of header files.
//
// Since this class encapsulates an integral value, it should be passed by
// value.
class NotificationType {
public:
enum Type {
// General -----------------------------------------------------------------
// Special signal value to represent an interest in all notifications.
// Not valid when posting a notification.
ALL = 0,
// The app is done processing user actions, now is a good time to do
// some background work.
IDLE,
// Means that the app has just started doing something in response to a
// user action, and that background processes shouldn't run if avoidable.
BUSY,
// This is sent when the user does a gesture resulting in a noteworthy
// action taking place. This is typically used for logging. The source is
// the profile, and the details is a wstring identifying the action.
USER_ACTION,
// NavigationController ----------------------------------------------------
// A new pending navigation has been created. Pending entries are created
// when the user requests the navigation. We don't know if it will actually
// happen until it does (at this point, it will be "committed." Note that
// renderer- initiated navigations such as link clicks will never be
// pending.
//
// This notification is called after the pending entry is created, but
// before we actually try to navigate. The source will be the
// NavigationController that owns the pending entry, and there are no
// details.
NAV_ENTRY_PENDING,
// A new non-pending navigation entry has been created. This will
// correspond to one NavigationController entry being created (in the case
// of new navigations) or renavigated to (for back/forward navigations).
//
// The source will be the navigation controller doing the commit. The
// details will be NavigationController::LoadCommittedDetails.
NAV_ENTRY_COMMITTED,
// Indicates that the NavigationController given in the Source has
// decreased its back/forward list count by removing entries from either
// the front or back of its list. This is usually the result of going back
// and then doing a new navigation, meaning all the "forward" items are
// deleted.
//
// This normally happens as a result of a new navigation. It will be
// followed by a NAV_ENTRY_COMMITTED message for the new page that
// caused the pruning. It could also be a result of removing an item from
// the list to fix up after interstitials.
//
// The details are NavigationController::PrunedDetails.
NAV_LIST_PRUNED,
// Indicates that a NavigationEntry has changed. The source will be the
// NavigationController that owns the NavigationEntry. The details will be
// a NavigationController::EntryChangedDetails struct.
//
// This will NOT be sent on navigation, interested parties should also
// listen for NAV_ENTRY_COMMITTED to handle that case. This will be
// sent when the entry is updated outside of navigation (like when a new
// title comes).
NAV_ENTRY_CHANGED,
// Other load-related (not from NavigationController) ----------------------
// A content load is starting. The source will be a
// Source<NavigationController> corresponding to the tab in which the load
// is occurring. No details are expected for this notification.
LOAD_START,
// A content load has stopped. The source will be a
// Source<NavigationController> corresponding to the tab in which the load
// is occurring. Details in the form of a LoadNotificationDetails object
// are optional.
LOAD_STOP,
// A frame is staring a provisional load. The source is a
// Source<NavigationController> corresponding to the tab in which the load
// occurs. Details is a bool specifying if the load occurs in the main
// frame (or a sub-frame if false).
FRAME_PROVISIONAL_LOAD_START,
// Content was loaded from an in-memory cache. The source will be a
// Source<NavigationController> corresponding to the tab in which the load
// occurred. Details in the form of a LoadFromMemoryCacheDetails object
// are provided.
LOAD_FROM_MEMORY_CACHE,
// A provisional content load has failed with an error. The source will be
// a Source<NavigationController> corresponding to the tab in which the
// load occurred. Details in the form of a ProvisionalLoadDetails object
// are provided.
FAIL_PROVISIONAL_LOAD_WITH_ERROR,
// A response has been received for a resource request. The source will be
// a Source<NavigationController> corresponding to the tab in which the
// request was issued. Details in the form of a ResourceRequestDetails
// object are provided.
RESOURCE_RESPONSE_STARTED,
// The response to a resource request has completed. The source will be a
// Source<NavigationController> corresponding to the tab in which the
// request was issued. Details in the form of a ResourceRequestDetails
// object are provided.
RESOURCE_RESPONSE_COMPLETED,
// A redirect was received while requesting a resource. The source will be
// a Source<NavigationController> corresponding to the tab in which the
// request was issued. Details in the form of a ResourceRedirectDetails
// are provided.
RESOURCE_RECEIVED_REDIRECT,
// The SSL state of a page has changed in some visible way. For example,
// if an insecure resource is loaded on a secure page. Note that a
// toplevel load commit will also update the SSL state (since the
// NavigationEntry is new) and this message won't always be sent in that
// case. Listen to this notification if you need to refresh SSL-related UI
// elements.
//
// The source will be the navigation controller associated with the load.
// There are no details. The entry changed will be the active entry of the
// controller.
SSL_VISIBLE_STATE_CHANGED,
// The SSL state of the browser has changed in some internal way. For
// example, the user might have explicitly allowed some broken certificate
// or a secure origin might have included some insecure content. Listen to
// this notifiation if you need to keep track of our internal SSL state.
//
// The source will be the navigation controller associated with the state
// change. There are no details.
SSL_INTERNAL_STATE_CHANGED,
// Lets resource handlers and other interested observers know when the
// message filter is being deleted and can no longer be used.
RESOURCE_MESSAGE_FILTER_SHUTDOWN,
// Views -------------------------------------------------------------------
// Notification that a view was removed from a view hierarchy. The source
// is the view, the details is the parent view.
VIEW_REMOVED,
// Browser-window ----------------------------------------------------------
// This message is sent after a window has been opened. The source is a
// Source<Browser> with a pointer to the new window. No details are
// expected.
BROWSER_OPENED,
// This message is sent after a window has been closed. The source is a
// Source<Browser> with a pointer to the closed window. Details is a
// boolean that if true indicates that the application will be closed as a
// result of this browser window closure (i.e. this was the last opened
// browser window). Note that the boolean pointed to by Details is only
// valid for the duration of this call.
BROWSER_CLOSED,
// This message is sent when the last window considered to be an
// "application window" has been closed. Dependent/dialog/utility windows
// can use this as a way to know that they should also close. No source or
// details are passed.
ALL_APPWINDOWS_CLOSED,
// Indicates a new top window has been created. The source is the
// WindowWin.
WINDOW_CREATED,
// Indicates that a top window has been closed. The source is the HWND
// that was closed, no details are expected.
WINDOW_CLOSED,
// Sent when an info bubble has been created but not yet shown. The source
// is the InfoBubble.
INFO_BUBBLE_CREATED,
// Tabs --------------------------------------------------------------------
// This notification is sent after a tab has been appended to the
// tab_strip. The source is a Source<NavigationController> with a pointer
// to controller for the added tab. There are no details.
TAB_PARENTED,
// This message is sent before a tab has been closed. The source is a
// Source<NavigationController> with a pointer to the controller for the
// closed tab. No details are expected.
//
// See also TAB_CLOSED.
TAB_CLOSING,
// Notification that a tab has been closed. The source is the
// NavigationController with no details.
TAB_CLOSED,
// This notification is sent when a render view host has connected to a
// renderer process. The source is a Source<TabContents> with a pointer to
// the TabContents. A TAB_CONTENTS_DISCONNECTED notification is
// guaranteed before the source pointer becomes junk. No details are
// expected.
TAB_CONTENTS_CONNECTED,
// This notification is sent when a TabContents swaps its render view host
// with another one, possibly changing processes. The source is a
// Source<TabContents> with a pointer to the TabContents. A
// TAB_CONTENTS_DISCONNECTED notification is guaranteed before the
// source pointer becomes junk. No details are expected.
TAB_CONTENTS_SWAPPED,
// This message is sent after a TabContents is disconnected from the
// renderer process. The source is a Source<TabContents> with a pointer to
// the TabContents (the pointer is usable). No details are expected.
TAB_CONTENTS_DISCONNECTED,
// This message is sent when a new InfoBar has been added to a TabContents.
// The source is a Source<TabContents> with a pointer to the TabContents
// the InfoBar was added to. The details is a Details<InfoBarDelegate> with
// a pointer to an object implementing the InfoBarDelegate interface for
// the InfoBar that was added.
TAB_CONTENTS_INFOBAR_ADDED,
// This message is sent when an InfoBar is about to be removed from a
// TabContents. The source is a Source<TabContents> with a pointer to the
// TabContents the InfoBar was removed from. The details is a
// Details<InfoBarDelegate> with a pointer to an object implementing the
// InfoBarDelegate interface for the InfoBar that was removed.
TAB_CONTENTS_INFOBAR_REMOVED,
// This is sent when an externally hosted tab is created. The details
// contain the ExternalTabContainer that contains the tab
EXTERNAL_TAB_CREATED,
// This is sent when an externally hosted tab is closed. No details are
// expected.
EXTERNAL_TAB_CLOSED,
// Indicates that the new page tab has finished loading. This is used for
// performance testing to see how fast we can load it after startup, and is
// only called once for the lifetime of the browser. The source is unused.
// Details is an integer: the number of milliseconds elapsed between
// starting and finishing all painting.
INITIAL_NEW_TAB_UI_LOAD,
// This notification is sent when a TabContents is being hidden, e.g. due
// to switching away from this tab. The source is a Source<TabContents>.
TAB_CONTENTS_HIDDEN,
// This notification is sent when a TabContents is being destroyed. Any
// object holding a reference to a TabContents can listen to that
// notification to properly reset the reference. The source is a
// Source<TabContents>.
TAB_CONTENTS_DESTROYED,
// Stuff inside the tabs ---------------------------------------------------
// This message is sent after a constrained window has been closed. The
// source is a Source<ConstrainedWindow> with a pointer to the closed child
// window. (The pointer isn't usable, except for identification.) No
// details are expected.
CWINDOW_CLOSED,
// Indicates that a RenderProcessHost is destructing. The source will be the
// RenderProcessHost that corresponds to the process.
RENDERER_PROCESS_TERMINATED,
// Indicates that a render process was closed (meaning it exited, but the
// RenderProcessHost might be reused). The source will be the corresponding
// RenderProcessHost. The details will be a bool which is true if the
// process crashed. This may get sent along with
// RENDERER_PROCESS_TERMINATED.
RENDERER_PROCESS_CLOSED,
// Indicates that a render process has become unresponsive for a period of
// time. The source will be the RenderWidgetHost that corresponds to the
// hung view, and no details are expected.
RENDERER_PROCESS_HANG,
// Indicates that a render process is created in the sandbox. The source
// will be the RenderProcessHost that corresponds to the created process
// and the detail is a bool telling us if the process got created on the
// sandbox desktop or not.
RENDERER_PROCESS_IN_SBOX,
// This is sent to notify that the RenderViewHost displayed in a
// TabContents has changed. Source is the TabContents for which the change
// happened, details is the previous RenderViewHost (can be NULL when the
// first RenderViewHost is set).
RENDER_VIEW_HOST_CHANGED,
// This is sent when a RenderWidgetHost is being destroyed. The source is
// the RenderWidgetHost, the details are not used.
RENDER_WIDGET_HOST_DESTROYED,
// Notification from TabContents that we have received a response from the
// renderer after using the dom inspector.
DOM_INSPECT_ELEMENT_RESPONSE,
// Notification from TabContents that we have received a response from the
// renderer in response to a dom automation controller action.
DOM_OPERATION_RESPONSE,
// Sent when the bookmark bubble hides. The source is the profile, the
// details unused.
BOOKMARK_BUBBLE_HIDDEN,
// This notification is sent when the result of a find-in-page search is
// available with the browser process. The source is a Source<TabContents>
// with a pointer to the TabContents. Details encompass a
// FindNotificationDetail object that tells whether the match was found or
// not found.
FIND_RESULT_AVAILABLE,
// This is sent when the users preference for when the bookmark bar should
// be shown changes. The source is the profile, and the details are
// NoDetails.
BOOKMARK_BAR_VISIBILITY_PREF_CHANGED,
// Used to monitor web cache usage by notifying whenever the
// CacheManagerHost observes new UsageStats. The source will be the
// RenderProcessHost that corresponds to the new statistics. Details are a
// UsageStats object sent by the renderer, and should be copied - ptr not
// guaranteed to be valid after the notification.
WEB_CACHE_STATS_OBSERVED,
// Child Processes ---------------------------------------------------------
// This notification is sent when a child process host has connected to a
// child process. There is no usable source, since it is sent from an
// ephemeral task; register for AllSources() to receive this notification.
// The details are in a Details<ChildProcessInfo>.
CHILD_PROCESS_HOST_CONNECTED,
// This message is sent after a ChildProcessHost is disconnected from the
// child process. There is no usable source, since it is sent from an
// ephemeral task; register for AllSources() to receive this notification.
// The details are in a Details<ChildProcessInfo>.
CHILD_PROCESS_HOST_DISCONNECTED,
// This message is sent when a child process disappears unexpectedly.
// There is no usable source, since it is sent from an ephemeral task;
// register for AllSources() to receive this notification. The details are
// in a Details<ChildProcessInfo>.
CHILD_PROCESS_CRASHED,
// This message indicates that an instance of a particular child was
// created in a page. (If one page contains several regions rendered by
// the same child, this notification will occur once for each region
// during the page load.)
//
// There is no usable source, since it is sent from an ephemeral task;
// register for AllSources() to receive this notification. The details are
// in a Details<ChildProcessInfo>.
CHILD_INSTANCE_CREATED,
// This is sent when network interception is disabled for a plugin, or the
// plugin is unloaded. This should only be sent/received on the browser IO
// thread or the plugin thread. The source is the plugin that is disabling
// interception. No details are expected.
CHROME_PLUGIN_UNLOADED,
// This is sent when a login prompt is shown. The source is the
// Source<NavigationController> for the tab in which the prompt is shown.
// Details are a LoginNotificationDetails which provide the LoginHandler
// that should be given authentication.
AUTH_NEEDED,
// This is sent when authentication credentials have been supplied (either
// by the user or by an automation service), but before we've actually
// received another response from the server. The source is the
// Source<NavigationController> for the tab in which the prompt was shown.
// No details are expected.
AUTH_SUPPLIED,
// History -----------------------------------------------------------------
// Sent when a history service is created on the main thread. This is sent
// after history is created, but before it has finished loading. Use
// HISTORY_LOADED is you need to know when loading has completed.
// The source is the profile that the history service belongs to, and the
// details is the pointer to the newly created HistoryService object.
HISTORY_CREATED,
// Sent when a history service has finished loading. The source is the
// profile that the history service belongs to, and the details is the
// HistoryService.
HISTORY_LOADED,
// Sent when a URL that has been typed has been added or modified. This is
// used by the in-memory URL database (used by autocomplete) to track
// changes to the main history system.
//
// The source is the profile owning the history service that changed, and
// the details is history::URLsModifiedDetails that lists the modified or
// added URLs.
HISTORY_TYPED_URLS_MODIFIED,
// Sent when the user visits a URL.
//
// The source is the profile owning the history service that changed, and
// the details is history::URLVisitedDetails.
HISTORY_URL_VISITED,
// Sent when one or more URLs are deleted.
//
// The source is the profile owning the history service that changed, and
// the details is history::URLsDeletedDetails that lists the deleted URLs.
HISTORY_URLS_DELETED,
// Sent by history when the favicon of a URL changes. The source is the
// profile, and the details is history::FavIconChangeDetails (see
// history_notifications.h).
FAVICON_CHANGED,
// Bookmarks ---------------------------------------------------------------
// Sent when the starred state of a URL changes. A URL is starred if there
// is at least one bookmark for it. The source is a Profile and the details
// is history::URLsStarredDetails that contains the list of URLs and
// whether they were starred or unstarred.
URLS_STARRED,
// Sent when the bookmark bar model finishes loading. This source is the
// Profile, and the details aren't used.
BOOKMARK_MODEL_LOADED,
// Sent when the spellchecker object changes. Note that this is not sent
// the first time the spellchecker gets initialized. The source is the
// profile, the details is SpellcheckerReinitializedDetails defined in
// profile.
SPELLCHECKER_REINITIALIZED,
// Sent when the bookmark bubble is shown for a particular URL. The source
// is the profile, the details the URL.
BOOKMARK_BUBBLE_SHOWN,
// Non-history storage services --------------------------------------------
// Notification that the TemplateURLModel has finished loading from the
// database. The source is the TemplateURLModel, and the details are
// NoDetails.
TEMPLATE_URL_MODEL_LOADED,
// Notification triggered when a web application has been installed or
// uninstalled. Any application view should reload its data. The source is
// the profile. No details are provided.
WEB_APP_INSTALL_CHANGED,
// This is sent to a pref observer when a pref is changed.
PREF_CHANGED,
// Sent when a default request context has been created, so calling
// Profile::GetDefaultRequestContext() will not return NULL. This is sent
// on the thread where Profile::GetRequestContext() is first called, which
// should be the UI thread.
DEFAULT_REQUEST_CONTEXT_AVAILABLE,
// Autocomplete ------------------------------------------------------------
// Sent by the autocomplete controller at least once per query, each time
// new matches are available, subject to rate-limiting/coalescing to reduce
// the number of updates. There are no details.
AUTOCOMPLETE_CONTROLLER_RESULT_UPDATED,
// Sent by the autocomplete controller once per query, immediately after
// synchronous matches become available. There are no details.
AUTOCOMPLETE_CONTROLLER_SYNCHRONOUS_MATCHES_AVAILABLE,
// This is sent when an item of the Omnibox popup is selected. The source
// is the profile.
OMNIBOX_OPENED_URL,
// Sent by the autocomplete edit when it is destroyed.
AUTOCOMPLETE_EDIT_DESTROYED,
// Sent when the main Google URL has been updated. Some services cache
// this value and need to update themselves when it changes. See
// google_util::GetGoogleURLAndUpdateIfNecessary().
GOOGLE_URL_UPDATED,
// Printing ----------------------------------------------------------------
// Notification from a PrintedDocument that it has been updated. It may be
// that a printed page has just been generated or that the document's
// number of pages has been calculated. Details is the new page or NULL if
// only the number of pages in the document has been updated.
PRINTED_DOCUMENT_UPDATED,
// Notification from PrintJob that an event occured. It can be that a page
// finished printing or that the print job failed. Details is
// PrintJob::EventDetails.
PRINT_JOB_EVENT,
// Shutdown ----------------------------------------------------------------
// Sent on the browser IO thread when an URLRequestContext is released by
// its owning Profile. The source is a pointer to the URLRequestContext.
URL_REQUEST_CONTEXT_RELEASED,
// Sent when WM_ENDSESSION has been received, after the browsers have been
// closed but before browser process has been shutdown. The source/details
// are all source and no details.
SESSION_END,
// Personalization ---------------------------------------------------------
PERSONALIZATION,
PERSONALIZATION_CREATED,
// User Scripts ------------------------------------------------------------
// Sent when there are new user scripts available. The details are a
// pointer to SharedMemory containing the new scripts.
USER_SCRIPTS_LOADED,
// Extensions --------------------------------------------------------------
// Sent when new extensions are loaded. The details are an ExtensionList*.
EXTENSIONS_LOADED,
// Sent when new extensions are installed. The details are a FilePath.
EXTENSION_INSTALLED,
// Debugging ---------------------------------------------------------------
// Sent from ~RenderViewHost. The source is the RenderViewHost.
RENDER_VIEW_HOST_DELETED,
// Count (must be last) ----------------------------------------------------
// Used to determine the number of notification types. Not valid as
// a type parameter when registering for or posting notifications.
NOTIFICATION_TYPE_COUNT
};
explicit NotificationType(Type v) : value(v) {}
bool operator==(NotificationType t) const { return value == t.value; }
bool operator!=(NotificationType t) const { return value != t.value; }
// Comparison to explicit enum values.
bool operator==(Type v) const { return value == v; }
bool operator!=(Type v) const { return value != v; }
Type value;
};
inline bool operator==(NotificationType::Type a, NotificationType b) {
return a == b.value;
}
inline bool operator!=(NotificationType::Type a, NotificationType b) {
return a != b.value;
}
#endif // CHROME_COMMON_NOTIFICATION_TYPE_H_

Просмотреть файл

@ -9,32 +9,50 @@
#include "base/message_loop.h"
#include "base/object_watcher.h"
#include "base/sys_info.h"
#include "chrome/common/result_codes.h"
// Maximum amount of time (in milliseconds) to wait for the process to exit.
static const int kWaitInterval = 2000;
namespace {
class TimerExpiredTask : public mozilla::Runnable,
public base::ObjectWatcher::Delegate {
class ChildReaper : public mozilla::Runnable,
public base::ObjectWatcher::Delegate,
public MessageLoop::DestructionObserver {
public:
explicit TimerExpiredTask(base::ProcessHandle process) : process_(process) {
explicit ChildReaper(base::ProcessHandle process, bool force)
: process_(process), force_(force) {
watcher_.StartWatching(process_, this);
}
virtual ~TimerExpiredTask() {
virtual ~ChildReaper() {
if (process_) {
KillProcess();
DCHECK(!process_) << "Make sure to close the handle.";
}
}
// MessageLoop::DestructionObserver -----------------------------------------
virtual void WillDestroyCurrentMessageLoop()
{
MOZ_ASSERT(!force_);
if (process_) {
WaitForSingleObject(process_, INFINITE);
base::CloseProcessHandle(process_);
process_ = 0;
MessageLoop::current()->RemoveDestructionObserver(this);
delete this;
}
}
// Task ---------------------------------------------------------------------
NS_IMETHOD Run() override {
if (process_)
MOZ_ASSERT(force_);
if (process_) {
KillProcess();
}
return NS_OK;
}
@ -46,16 +64,23 @@ class TimerExpiredTask : public mozilla::Runnable,
watcher_.StopWatching();
base::CloseProcessHandle(process_);
process_ = NULL;
process_ = 0;
if (!force_) {
MessageLoop::current()->RemoveDestructionObserver(this);
delete this;
}
}
private:
void KillProcess() {
MOZ_ASSERT(force_);
// OK, time to get frisky. We don't actually care when the process
// terminates. We just care that it eventually terminates, and that's what
// TerminateProcess should do for us. Don't check for the result code since
// it fails quite often. This should be investigated eventually.
TerminateProcess(process_, ResultCodes::HUNG);
TerminateProcess(process_, base::PROCESS_END_PROCESS_WAS_HUNG);
// Now, just cleanup as if the process exited normally.
OnObjectSignaled(process_);
@ -66,31 +91,28 @@ class TimerExpiredTask : public mozilla::Runnable,
base::ObjectWatcher watcher_;
DISALLOW_EVIL_CONSTRUCTORS(TimerExpiredTask);
bool force_;
DISALLOW_EVIL_CONSTRUCTORS(ChildReaper);
};
} // namespace
// static
void ProcessWatcher::EnsureProcessTerminated(base::ProcessHandle process
, bool force
) {
void ProcessWatcher::EnsureProcessTerminated(base::ProcessHandle process, bool force) {
DCHECK(process != GetCurrentProcess());
if (!force) {
WaitForSingleObject(process, INFINITE);
base::CloseProcessHandle(process);
return;
}
// If already signaled, then we are done!
if (WaitForSingleObject(process, 0) == WAIT_OBJECT_0) {
base::CloseProcessHandle(process);
return;
}
RefPtr<mozilla::Runnable> task = new TimerExpiredTask(process);
MessageLoop::current()->PostDelayedTask(task.forget(),
kWaitInterval);
MessageLoopForIO* loop = MessageLoopForIO::current();
if (force) {
RefPtr<mozilla::Runnable> task = new ChildReaper(process, force);
loop->PostDelayedTask(task.forget(), kWaitInterval);
} else {
loop->AddDestructionObserver(new ChildReaper(process, force));
}
}

Просмотреть файл

@ -1,50 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_COMMON_RESULT_CODES_H_
#define CHROME_COMMON_RESULT_CODES_H_
#include "base/process_util.h"
// This file consolidates all the return codes for the browser and renderer
// process. The return code is the value that:
// a) is returned by main() or winmain(), or
// b) specified in the call for ExitProcess() or TerminateProcess(), or
// c) the exception value that causes a process to terminate.
//
// It is advisable to not use negative numbers because the Windows API returns
// it as an unsigned long and the exception values have high numbers. For
// example EXCEPTION_ACCESS_VIOLATION value is 0xC0000005.
class ResultCodes {
public:
enum ExitCode {
NORMAL_EXIT = base::PROCESS_END_NORMAL_TERMINATON,
TASKMAN_KILL = base::PROCESS_END_KILLED_BY_USER,
HUNG = base::PROCESS_END_PROCESS_WAS_HUNG,
INVALID_CMDLINE_URL, // An invalid command line url was given.
SBOX_INIT_FAILED, // The sandbox could not be initialized.
GOOGLE_UPDATE_INIT_FAILED, // The Google Update client stub init failed.
GOOGLE_UPDATE_LAUNCH_FAILED,// Google Update could not launch chrome DLL.
BAD_PROCESS_TYPE, // The process is of an unknown type.
MISSING_PATH, // An critical chrome path is missing.
MISSING_DATA, // A critical chrome file is missing.
SHELL_INTEGRATION_FAILED, // Failed to make Chrome default browser.
MACHINE_LEVEL_INSTALL_EXISTS, // Machine level install exists
UNINSTALL_DELETE_FILE_ERROR,// Error while deleting shortcuts.
UNINSTALL_CHROME_ALIVE, // Uninstall detected another chrome instance.
UNINSTALL_NO_SURVEY, // Do not launch survey after uninstall.
UNINSTALL_USER_CANCEL, // The user changed her mind.
UNINSTALL_DELETE_PROFILE, // Delete profile as well during uninstall.
UNSUPPORTED_PARAM, // Command line parameter is not supported.
KILLED_BAD_MESSAGE, // A bad message caused the process termination.
IMPORTER_CANCEL, // The user canceled the browser import.
IMPORTER_HUNG, // Browser import hung and was killed.
EXIT_LAST_CODE // Last return code (keep it last).
};
};
#endif // CHROME_COMMON_RESULT_CODES_H_

Просмотреть файл

@ -5,7 +5,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/ipc/BrowserProcessSubThread.h"
#include "chrome/common/notification_service.h"
#if defined(OS_WIN)
#include <objbase.h>
@ -42,8 +41,7 @@ BrowserProcessSubThread* BrowserProcessSubThread::sBrowserThreads[ID_COUNT] = {
BrowserProcessSubThread::BrowserProcessSubThread(ID aId) :
base::Thread(kBrowserThreadNames[aId]),
mIdentifier(aId),
mNotificationService(nullptr)
mIdentifier(aId)
{
StaticMutexAutoLock lock(sLock);
DCHECK(aId >= 0 && aId < ID_COUNT);
@ -68,15 +66,11 @@ BrowserProcessSubThread::Init()
// Initializes the COM library on the current thread.
CoInitialize(nullptr);
#endif
mNotificationService = new NotificationService();
}
void
BrowserProcessSubThread::CleanUp()
{
delete mNotificationService;
mNotificationService = nullptr;
#if defined(OS_WIN)
// Closes the COM library on the current thread. CoInitialize must
// be balanced by a corresponding call to CoUninitialize.

Просмотреть файл

@ -12,8 +12,6 @@
#include "nsDebug.h"
class NotificationService;
namespace mozilla {
namespace ipc {
@ -54,8 +52,6 @@ private:
// identifier at a given time.
ID mIdentifier;
NotificationService* mNotificationService;
// This lock protects |browser_threads_|. Do not read or modify that array
// without holding this lock. Do not block while holding this lock.

Просмотреть файл

@ -93,8 +93,7 @@ GeckoChildProcessHost::DefaultChildPrivileges()
GeckoChildProcessHost::GeckoChildProcessHost(GeckoProcessType aProcessType,
ChildPrivileges aPrivileges)
: ChildProcessHost(RENDER_PROCESS), // FIXME/cjones: we should own this enum
mProcessType(aProcessType),
: mProcessType(aProcessType),
mPrivileges(aPrivileges),
mMonitor("mozilla.ipc.GeckChildProcessHost.mMonitor"),
mProcessState(CREATING_CHANNEL),
@ -102,12 +101,10 @@ GeckoChildProcessHost::GeckoChildProcessHost(GeckoProcessType aProcessType,
mEnableSandboxLogging(false),
mSandboxLevel(0),
#endif
mDelegate(nullptr),
mChildProcessHandle(0)
#if defined(MOZ_WIDGET_COCOA)
, mChildTask(MACH_PORT_NULL)
#endif
, mAssociatedActors(1)
{
MOZ_COUNT_CTOR(GeckoChildProcessHost);
}
@ -487,26 +484,6 @@ GeckoChildProcessHost::SetAlreadyDead()
mChildProcessHandle = 0;
}
namespace {
void
DelayedDeleteSubprocess(GeckoChildProcessHost* aSubprocess)
{
XRE_GetIOMessageLoop()
->PostTask(mozilla::MakeAndAddRef<DeleteTask<GeckoChildProcessHost>>(aSubprocess));
}
}
void
GeckoChildProcessHost::DissociateActor()
{
if (!--mAssociatedActors) {
MessageLoop::current()->
PostTask(NewRunnableFunction(DelayedDeleteSubprocess, this));
}
}
int32_t GeckoChildProcessHost::mChildCounter = 0;
void
@ -1160,7 +1137,6 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
// NB: on OS X, we block much longer than we need to in order to
// reach this call, waiting for the child process's task_t. The
// best way to fix that is to refactor this file, hard.
SetHandle(process);
#if defined(MOZ_WIDGET_COCOA)
mChildTask = child_task;
#endif
@ -1236,15 +1212,6 @@ GeckoChildProcessHost::GetQueuedMessages(std::queue<IPC::Message>& queue)
// We expect the next listener to take over processing of our queue.
}
void
GeckoChildProcessHost::OnWaitableEventSignaled(base::WaitableEvent *event)
{
if (mDelegate) {
mDelegate->OnWaitableEventSignaled(event);
}
ChildProcessHost::OnWaitableEventSignaled(event);
}
bool GeckoChildProcessHost::sRunSelfAsContentProc(false);
#ifdef MOZ_NUWA_PROCESS

Просмотреть файл

@ -12,7 +12,6 @@
#include "base/waitable_event.h"
#include "chrome/common/child_process_host.h"
#include "mozilla/Atomics.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/ipc/FileDescriptor.h"
#include "mozilla/Monitor.h"
@ -93,16 +92,10 @@ public:
virtual bool CanShutdown() { return true; }
virtual void OnWaitableEventSignaled(base::WaitableEvent *event);
IPC::Channel* GetChannel() {
return channelp();
}
base::WaitableEvent* GetShutDownEvent() {
return GetProcessEvent();
}
// Returns a "borrowed" handle to the child process - the handle returned
// by this function must not be closed by the caller.
ProcessHandle GetChildProcessHandle() {
@ -128,14 +121,6 @@ public:
// For bug 943174: Skip the EnsureProcessTerminated call in the destructor.
void SetAlreadyDead();
// This associates an actor telling the process host to stay alive at least
// until DissociateActor has been called.
void AssociateActor() { mAssociatedActors++; }
// This gets called when actors get destroyed and will schedule the object
// for deletion when all actors have cleared their associations.
void DissociateActor();
static void EnableSameExecutableForContentProc() { sRunSelfAsContentProc = true; }
protected:
@ -183,8 +168,6 @@ protected:
base::file_handle_mapping_vector mFileMap;
#endif
base::WaitableEventWatcher::Delegate* mDelegate;
ProcessHandle mChildProcessHandle;
#if defined(OS_MACOSX)
task_t mChildTask;
@ -218,10 +201,6 @@ private:
// FIXME/cjones: this strongly indicates bad design. Shame on us.
std::queue<IPC::Message> mQueue;
// This tracks how many actors are associated with this process that require
// it to stay alive and have not yet been destroyed.
Atomic<int32_t> mAssociatedActors;
// Remember original env values so we can restore it (there is no other
// simple way how to change environment of a child process than to modify
// the current environment).

Просмотреть файл

@ -10,8 +10,6 @@
#include "base/eintr_wrapper.h"
#include "chrome/common/child_process_info.h"
#include "mozilla/ipc/Transport.h"
#include "mozilla/ipc/FileDescriptor.h"
#include "ProtocolUtils.h"

Просмотреть файл

@ -5,7 +5,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "base/message_loop.h"
#include "chrome/common/child_process_info.h"
#include "mozilla/ipc/Transport.h"
#include "mozilla/ipc/ProtocolUtils.h"

Просмотреть файл

@ -494,8 +494,6 @@ XPCShellEnvironment::Init()
AutoSafeJSContext cx;
JS_SetContextPrivate(cx, this);
nsCOMPtr<nsIXPConnect> xpc =
do_GetService(nsIXPConnect::GetCID());
if (!xpc) {

Просмотреть файл

@ -400,9 +400,9 @@ ToIntWidth(double d)
inline int32_t
ToInt32(double d)
{
// clang crashes compiling this when targeting arm-darwin:
// clang crashes compiling this when targeting arm:
// https://llvm.org/bugs/show_bug.cgi?id=22974
#if defined (__arm__) && defined (__GNUC__) && !defined(__APPLE__)
#if defined (__arm__) && defined (__GNUC__) && !defined(__clang__)
int32_t i;
uint32_t tmp0;
uint32_t tmp1;

Просмотреть файл

@ -2111,10 +2111,25 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer)
case PNK_TYPEOFEXPR:
case PNK_VOID:
case PNK_NOT:
case PNK_COMPUTED_NAME:
MOZ_ASSERT(pn->isArity(PN_UNARY));
return checkSideEffects(pn->pn_kid, answer);
// Even if the name expression is effect-free, performing ToPropertyKey on
// it might not be effect-free:
//
// RegExp.prototype.toString = () => { throw 42; };
// ({ [/regex/]: 0 }); // ToPropertyKey(/regex/) throws 42
//
// function Q() {
// ({ [new.target]: 0 });
// }
// Q.toString = () => { throw 17; };
// new Q; // new.target will be Q, ToPropertyKey(Q) throws 17
case PNK_COMPUTED_NAME:
MOZ_ASSERT(pn->isArity(PN_UNARY));
*answer = true;
return true;
// Looking up or evaluating the associated name could throw.
case PNK_TYPEOFNAME:
MOZ_ASSERT(pn->isArity(PN_UNARY));

Просмотреть файл

@ -223,16 +223,13 @@ AutoGCRooter::trace(JSTracer* trc)
/* static */ void
AutoGCRooter::traceAll(JSTracer* trc)
{
if (JSContext* cx = trc->runtime()->maybeContextFromMainThread())
traceAllInContext(cx, trc);
traceAllInContext(trc->runtime()->contextFromMainThread(), trc);
}
/* static */ void
AutoGCRooter::traceAllWrappers(JSTracer* trc)
{
JSContext* cx = trc->runtime()->maybeContextFromMainThread();
if (!cx)
return;
JSContext* cx = trc->runtime()->contextFromMainThread();
for (AutoGCRooter* gcr = cx->roots.autoGCRooters_; gcr; gcr = gcr->down) {
if (gcr->tag_ == WRAPVECTOR || gcr->tag_ == WRAPPER)
@ -320,8 +317,7 @@ js::gc::GCRuntime::markRuntime(JSTracer* trc, TraceOrMarkRuntime traceOrMark,
if (rt->isHeapMinorCollecting())
jit::JitRuntime::MarkJitcodeGlobalTableUnconditionally(trc);
if (JSContext* cx = rt->maybeContextFromMainThread())
cx->mark(trc);
rt->contextFromMainThread()->mark(trc);
for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next())
c->traceRoots(trc, traceOrMark);

Просмотреть файл

@ -93,10 +93,10 @@ static const int kWordAndSurrogateRanges[] = {
static const int kWordAndSurrogateRangeCount = ArrayLength(kWordAndSurrogateRanges);
static const int kNegatedIgnoreCaseWordAndSurrogateRanges[] = {
0, '0', '9' + 1, 'A',
'K', 'K' + 1, 'S', 'S' + 1,
'Z' + 1, '_', '_' + 1, 'a',
'k', 'k' + 1, 's', 's' + 1,
'z' + 1, unicode::LeadSurrogateMin,
'z' + 1, 0x017F,
0x017F + 1, 0x212A,
0x212A + 1, unicode::LeadSurrogateMin,
unicode::TrailSurrogateMax + 1, 0x10000,
0x10000 };
static const int kNegatedIgnoreCaseWordAndSurrogateRangeCount =

Просмотреть файл

@ -32,7 +32,6 @@ function getTestCaseResult(expected, actual)
function getFailedCases() {
for ( var i = 0; i < gTestcases.length; i++ ) {}
};
function jit(on) {}
var lfcode = new Array();
lfcode.push("\
var summary = 'decompilation of \"let with with\" ';\
@ -47,7 +46,6 @@ function test() {\
var w = 'r'.match(/r/);\
new Function('for (var j = 0; j < 1; ++j) { } ')();\
}\
jit(('Math.log'));\
reportCompare(expect, actual, summary);\
}\
");

Просмотреть файл

@ -1,8 +1,8 @@
function jit(on)
function Q(on)
{
options().match
}
function options() { return "methodjit"; }
gczeal(2);
for (i = 0; i < 100 ; ++i) { jit(jit(42, [])); }
for (i = 0; i < 100 ; ++i) { Q(Q(42, [])); }

Просмотреть файл

@ -6,6 +6,7 @@
#include "jit/arm/MacroAssembler-arm.h"
#include "mozilla/Attributes.h"
#include "mozilla/Casting.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/MathAlgorithms.h"
@ -4906,14 +4907,14 @@ MacroAssembler::callWithABIPost(uint32_t stackAdjust, MoveOp::Type result)
if (!UseHardFpABI()) {
// Move double from r0/r1 to ReturnFloatReg.
ma_vxfer(r0, r1, ReturnDoubleReg);
break;
}
break;
case MoveOp::FLOAT32:
if (!UseHardFpABI()) {
// Move float32 from r0 to ReturnFloatReg.
ma_vxfer(r0, ReturnFloat32Reg.singleOverlay());
break;
}
break;
case MoveOp::GENERAL:
break;

Просмотреть файл

@ -1903,7 +1903,7 @@ Decoder::DecodeSpecialCondition(Instruction* instr)
}
break;
}
// else fall through
MOZ_FALLTHROUGH;
case 0xB:
if ((instr->Bits(22, 20) == 5) && (instr->Bits(15, 12) == 0xf)) {
int Rn = instr->Bits(19, 16);

Просмотреть файл

@ -466,22 +466,14 @@ JS_NewRuntime(uint32_t maxbytes, uint32_t maxNurseryBytes, JSRuntime* parentRunt
while (parentRuntime && parentRuntime->parentRuntime)
parentRuntime = parentRuntime->parentRuntime;
JSRuntime* rt = js_new<JSRuntime>(parentRuntime);
if (!rt)
return nullptr;
if (!rt->init(maxbytes, maxNurseryBytes)) {
JS_DestroyRuntime(rt);
return nullptr;
}
return rt;
return NewContext(maxbytes, maxNurseryBytes, parentRuntime);
}
JS_PUBLIC_API(void)
JS_DestroyRuntime(JSRuntime* rt)
{
js_delete(rt);
JSContext* cx = rt->contextFromMainThread();
DestroyContext(cx);
}
static JS_CurrentEmbedderTimeFunction currentEmbedderTimeFunction;
@ -563,30 +555,6 @@ JS_EndRequest(JSContext* cx)
StopRequest(cx);
}
JS_PUBLIC_API(void*)
JS_GetContextPrivate(JSContext* cx)
{
return cx->data;
}
JS_PUBLIC_API(void)
JS_SetContextPrivate(JSContext* cx, void* data)
{
cx->data = data;
}
JS_PUBLIC_API(void*)
JS_GetSecondContextPrivate(JSContext* cx)
{
return cx->data2;
}
JS_PUBLIC_API(void)
JS_SetSecondContextPrivate(JSContext* cx, void* data)
{
cx->data2 = data;
}
JS_PUBLIC_API(JSRuntime*)
JS_GetRuntime(JSContext* cx)
{

Просмотреть файл

@ -1041,18 +1041,6 @@ class MOZ_RAII JSAutoRequest
#endif
};
extern JS_PUBLIC_API(void*)
JS_GetContextPrivate(JSContext* cx);
extern JS_PUBLIC_API(void)
JS_SetContextPrivate(JSContext* cx, void* data);
extern JS_PUBLIC_API(void*)
JS_GetSecondContextPrivate(JSContext* cx);
extern JS_PUBLIC_API(void)
JS_SetSecondContextPrivate(JSContext* cx, void* data);
extern JS_PUBLIC_API(JSRuntime*)
JS_GetRuntime(JSContext* cx);

Просмотреть файл

@ -209,12 +209,6 @@ ClassName(JSProtoKey key, JSAtomState& atomState)
return (&atomState.Null)[key];
}
inline Handle<PropertyName*>
ClassName(JSProtoKey key, JSRuntime* rt)
{
return ClassName(key, *rt->commonNames);
}
inline Handle<PropertyName*>
ClassName(JSProtoKey key, ExclusiveContext* cx)
{

Просмотреть файл

@ -87,17 +87,27 @@ js::TraceCycleDetectionSet(JSTracer* trc, AutoCycleDetector::Set& set)
TraceRoot(trc, &e.mutableFront(), "cycle detector table entry");
}
JSContext*
js::NewContext(JSRuntime* rt)
bool
JSContext::init(uint32_t maxBytes, uint32_t maxNurseryBytes)
{
MOZ_ASSERT(!rt->maybeContextFromMainThread());
if (!JSRuntime::init(maxBytes, maxNurseryBytes))
return false;
JS_AbortIfWrongThread(rt);
return true;
}
JSContext* cx = js_new<JSContext>(rt);
JSContext*
js::NewContext(uint32_t maxBytes, uint32_t maxNurseryBytes, JSRuntime* parentRuntime)
{
JSContext* cx = js_new<JSContext>(parentRuntime);
if (!cx)
return nullptr;
if (!cx->init(maxBytes, maxNurseryBytes)) {
js_delete(cx);
return nullptr;
}
return cx;
}
@ -858,8 +868,9 @@ ExclusiveContext::recoverFromOutOfMemory()
task->outOfMemory = false;
}
JSContext::JSContext(JSRuntime* rt)
: ExclusiveContext(rt, &rt->mainThread, Context_JS),
JSContext::JSContext(JSRuntime* parentRuntime)
: ExclusiveContext(this, &this->JSRuntime::mainThread, Context_JS),
JSRuntime(this, parentRuntime),
throwing(false),
unwrappedException_(this),
overRecursed_(false),
@ -869,8 +880,6 @@ JSContext::JSContext(JSRuntime* rt)
resolvingList(nullptr),
generatingError(false),
cycleDetectorSet(this),
data(nullptr),
data2(nullptr),
outstandingRequests(0),
jitIsBroken(false)
{
@ -880,6 +889,8 @@ JSContext::JSContext(JSRuntime* rt)
JSContext::~JSContext()
{
destroyRuntime();
/* Free the stuff hanging off of cx. */
MOZ_ASSERT(!resolvingList);
}
@ -1011,22 +1022,21 @@ JSContext::updateJITEnabled()
}
size_t
JSContext::sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
JSContext::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const
{
/*
* There are other JSContext members that could be measured; the following
* ones have been found by DMD to be worth measuring. More stuff may be
* added later.
*/
return mallocSizeOf(this) + cycleDetectorSet.sizeOfExcludingThis(mallocSizeOf);
return cycleDetectorSet.sizeOfExcludingThis(mallocSizeOf);
}
void
JSContext::mark(JSTracer* trc)
{
/* Stack frames and slots are traced by StackSpace::mark. */
TraceCycleDetectionSet(trc, cycleDetectorSet);
if (cycleDetectorSet.initialized())
TraceCycleDetectionSet(trc, cycleDetectorSet);
if (compartment_)
compartment_->mark();

Просмотреть файл

@ -295,11 +295,29 @@ void ReportOverRecursed(JSContext* cx, unsigned errorNumber);
} /* namespace js */
struct JSContext : public js::ExclusiveContext
struct JSContext : public js::ExclusiveContext,
public JSRuntime
{
explicit JSContext(JSRuntime* rt);
explicit JSContext(JSRuntime* parentRuntime);
~JSContext();
bool init(uint32_t maxBytes, uint32_t maxNurseryBytes);
// For names that exist in both ExclusiveContext and JSRuntime, pick the
// ExclusiveContext version.
using ExclusiveContext::atomsCompartment;
using ExclusiveContext::buildIdOp;
using ExclusiveContext::emptyString;
using ExclusiveContext::jitSupportsSimd;
using ExclusiveContext::make_pod_array;
using ExclusiveContext::make_unique;
using ExclusiveContext::new_;
using ExclusiveContext::permanentAtoms;
using ExclusiveContext::pod_calloc;
using ExclusiveContext::pod_malloc;
using ExclusiveContext::staticStrings;
using ExclusiveContext::wellKnownSymbols;
JSRuntime* runtime() const { return runtime_; }
js::PerThreadData& mainThread() const { return runtime()->mainThread; }
@ -343,10 +361,6 @@ struct JSContext : public js::ExclusiveContext
/* State for object and array toSource conversion. */
js::AutoCycleDetector::Set cycleDetectorSet;
/* Client opaque pointers. */
void* data;
void* data2;
public:
/*
@ -438,7 +452,7 @@ struct JSContext : public js::ExclusiveContext
*/
inline bool runningWithTrustedPrincipals() const;
JS_FRIEND_API(size_t) sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
JS_FRIEND_API(size_t) sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
void mark(JSTracer* trc);
@ -495,7 +509,7 @@ struct MOZ_RAII AutoResolving {
* and exclusively owned.
*/
extern JSContext*
NewContext(JSRuntime* rt);
NewContext(uint32_t maxBytes, uint32_t maxNurseryBytes, JSRuntime* parentRuntime);
extern void
DestroyContext(JSContext* cx);
@ -721,6 +735,10 @@ class MOZ_RAII AutoLockForExclusiveAccess
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
init(rt);
}
explicit AutoLockForExclusiveAccess(JSContext* cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM) {
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
init(cx->runtime());
}
~AutoLockForExclusiveAccess() {
if (runtime->numExclusiveThreads) {
#ifdef DEBUG

Просмотреть файл

@ -30,14 +30,6 @@ class CompartmentChecker
explicit CompartmentChecker(ExclusiveContext* cx)
: compartment(cx->compartment())
{
#ifdef DEBUG
// In debug builds, make sure the embedder passed the cx it claimed it
// was going to use.
JSContext* activeContext = nullptr;
if (cx->isJSContext())
activeContext = cx->asJSContext()->runtime()->activeContext;
MOZ_ASSERT_IF(activeContext, cx == activeContext);
#endif
}
/*

Просмотреть файл

@ -522,7 +522,7 @@ js::GetErrorTypeName(JSRuntime* rt, int16_t exnType)
return nullptr;
}
JSProtoKey key = GetExceptionProtoKey(JSExnType(exnType));
return ClassName(key, rt);
return ClassName(key, rt->contextFromMainThread());
}
void

Просмотреть файл

@ -1256,14 +1256,6 @@ js::SetScriptEnvironmentPreparer(JSRuntime* rt, ScriptEnvironmentPreparer* prepa
rt->scriptEnvironmentPreparer = preparer;
}
#ifdef DEBUG
JS_FRIEND_API(void)
js::Debug_SetActiveJSContext(JSRuntime* rt, JSContext* cx)
{
rt->activeContext = cx;
}
#endif
JS_FRIEND_API(void)
js::SetCTypesActivityCallback(JSRuntime* rt, CTypesActivityCallback cb)
{

Просмотреть файл

@ -2691,20 +2691,6 @@ JS_FRIEND_API(void)
SetScriptEnvironmentPreparer(JSRuntime* rt, ScriptEnvironmentPreparer*
preparer);
/**
* To help embedders enforce their invariants, we allow them to specify in
* advance which JSContext should be passed to JSAPI calls. If this is set
* to a non-null value, the assertSameCompartment machinery does double-
* duty (in debug builds) to verify that it matches the cx being used.
*/
#ifdef DEBUG
JS_FRIEND_API(void)
Debug_SetActiveJSContext(JSRuntime* rt, JSContext* cx);
#else
inline void
Debug_SetActiveJSContext(JSRuntime* rt, JSContext* cx) {}
#endif
enum CTypesActivityType {
CTYPES_CALL_BEGIN,
CTYPES_CALL_END,

Просмотреть файл

@ -6996,8 +6996,8 @@ AutoSuppressGC::AutoSuppressGC(JSCompartment* comp)
suppressGC_++;
}
AutoSuppressGC::AutoSuppressGC(JSRuntime* rt)
: suppressGC_(rt->mainThread.suppressGC)
AutoSuppressGC::AutoSuppressGC(JSContext* cx)
: suppressGC_(cx->mainThread().suppressGC)
{
suppressGC_++;
}

Просмотреть файл

@ -1276,7 +1276,7 @@ class MOZ_RAII JS_HAZ_GC_SUPPRESSED AutoSuppressGC
public:
explicit AutoSuppressGC(ExclusiveContext* cx);
explicit AutoSuppressGC(JSCompartment* comp);
explicit AutoSuppressGC(JSRuntime* rt);
explicit AutoSuppressGC(JSContext* cx);
~AutoSuppressGC()
{

Просмотреть файл

@ -3,6 +3,51 @@
* 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/. */
// NOTE: If you're adding new test harness functionality to this file -- first,
// should you at all? Most stuff is better in specific tests, or in
// nested shell.js/browser.js. Second, can you instead add it to
// shell.js? Our goal is to unify these two files for readability, and
// the plan is to empty out this file into that one over time. Third,
// supposing you must add to this file, please add it to this IIFE for
// better modularity/resilience against tests that must do particularly
// bizarre things that might break the harness.
(function(global) {
/****************************
* UTILITY FUNCTION EXPORTS *
****************************/
var newGlobal = global.newGlobal;
if (typeof newGlobal !== "function") {
newGlobal = function newGlobal() {
var iframe = global.document.createElement("iframe");
global.document.documentElement.appendChild(iframe);
var win = iframe.contentWindow;
iframe.remove();
// Shim in "evaluate"
win.evaluate = win.eval;
return win;
};
global.newGlobal = newGlobal;
}
// This function is *only* used in this file! Ultimately it should only be
// used by other exports in this IIFE, but for now just export it so that
// functions not exported within this IIFE (but still in this file) can use
// it.
function DocumentWrite(s) {
try {
var msgDiv = global.document.createElement('div');
msgDiv.innerHTML = s;
global.document.body.appendChild(msgDiv);
} catch (e) {
global.document.write(s + '<br>\n');
}
}
global.DocumentWrite = DocumentWrite;
})(this);
var gPageCompleted;
var GLOBAL = this + '';
@ -48,21 +93,6 @@ function htmlesc(str) {
return str;
}
function DocumentWrite(s)
{
try
{
var msgDiv = document.createElement('div');
msgDiv.innerHTML = s;
document.body.appendChild(msgDiv);
msgDiv = null;
}
catch(excp)
{
document.write(s + '<br>\n');
}
}
function print() {
var s = 'TEST-INFO | ';
var a;
@ -251,10 +281,6 @@ function gczeal(z)
SpecialPowers.setGCZeal(z);
}
function jit(on)
{
}
function jsTestDriverBrowserInit()
{
@ -357,18 +383,6 @@ function jsTestDriverBrowserInit()
gczeal(Number(properties.gczeal));
}
/*
* since the default setting of jit changed from false to true
* in http://hg.mozilla.org/tracemonkey/rev/685e00e68be9
* bisections which depend upon jit settings can be thrown off.
* default jit(false) when not running jsreftests to make bisections
* depending upon jit settings consistent over time. This is not needed
* in shell tests as the default jit setting has not changed there.
*/
if (properties.jit || !document.location.href.match(/jsreftest.html/))
jit(properties.jit);
var testpathparts = properties.test.split(/\//);
if (testpathparts.length < 2)
@ -560,16 +574,6 @@ function closeDialog()
}
}
function newGlobal() {
var iframe = document.createElement("iframe");
document.documentElement.appendChild(iframe);
var win = iframe.contentWindow;
iframe.remove();
// Shim in "evaluate"
win.evaluate = win.eval;
return win;
}
registerDialogCloser();
window.addEventListener('unload', unregisterDialogCloser, true);

Просмотреть файл

@ -24,7 +24,6 @@ var expectedmatches = new Array();
// time, they will not be compiled to native code and we will not
// actually be testing jitted regexps.
jit(true);
status = inSection(1);
string = '@';
@ -57,7 +56,6 @@ print('`'.match(/@/i));
expectedmatch = null;
addThis();
jit(false);
//-----------------------------------------------------------------------------
test();

Просмотреть файл

@ -38,10 +38,8 @@ var expect = is_space.join(',');
var actual = chars.map(function(ch) { return /\s/.test(ch); }).join(',');
reportCompare(expect, actual, summary);
jit(true);
var actual = chars.map(function(ch) { return /\s/.test(ch); }).join(',');
reportCompare(expect, actual, summary);
jit(false);
exitFunc ('test');
}

Просмотреть файл

@ -0,0 +1,35 @@
// Any copyright is dedicated to the Public Domain.
// http://creativecommons.org/licenses/publicdomain/
//-----------------------------------------------------------------------------
var BUGNUMBER = 1199695;
var summary =
"Computed property names must be considered as always effectful even when " +
"the name expression isn't effectful, because calling ToPropertyKey on " +
"some non-effectful expressions has user-modifiable behavior";
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
RegExp.prototype.toString = () => { throw 42; };
assertThrowsValue(function() {
({ [/regex/]: 0 }); // ToPropertyKey(/regex/) throws 42
}, 42);
function Q() {
({ [new.target]: 0 }); // new.target will be Q, ToPropertyKey(Q) throws 17
}
Q.toString = () => { throw 17; };
assertThrowsValue(function() {
new Q;
}, 17);
/******************************************************************************/
if (typeof reportCompare === "function")
reportCompare(true, true);
print("Tests complete");

Просмотреть файл

@ -1,6 +1,10 @@
var BUGNUMBER = 1135377;
var summary = "Implement RegExp unicode flag -- ignoreCase flag with character class escape.";
// \W doesn't match S or K from the change in
// https://github.com/tc39/ecma262/pull/525
// (bug 1281739)
print(BUGNUMBER + ": " + summary);
// LATIN SMALL LETTER LONG S
@ -12,13 +16,27 @@ assertEqArray(/\w/iu.exec("s"),
assertEqArray(/\w/iu.exec("\u017F"),
["\u017F"]);
assertEqArray(/\W/iu.exec("S"),
assertEqArray(/[^\W]/iu.exec("S"),
["S"]);
assertEqArray(/\W/iu.exec("s"),
assertEqArray(/[^\W]/iu.exec("s"),
["s"]);
assertEqArray(/\W/iu.exec("\u017F"),
assertEqArray(/[^\W]/iu.exec("\u017F"),
["\u017F"]);
assertEq(/\W/iu.exec("S"),
null);
assertEq(/\W/iu.exec("s"),
null);
assertEq(/\W/iu.exec("\u017F"),
null);
assertEq(/[^\w]/iu.exec("S"),
null);
assertEq(/[^\w]/iu.exec("s"),
null);
assertEq(/[^\w]/iu.exec("\u017F"),
null);
// KELVIN SIGN
assertEqArray(/\w/iu.exec("k"),
@ -28,12 +46,26 @@ assertEqArray(/\w/iu.exec("k"),
assertEqArray(/\w/iu.exec("\u212A"),
["\u212A"]);
assertEqArray(/\W/iu.exec("k"),
assertEqArray(/[^\W]/iu.exec("k"),
["k"]);
assertEqArray(/\W/iu.exec("k"),
assertEqArray(/[^\W]/iu.exec("k"),
["k"]);
assertEqArray(/\W/iu.exec("\u212A"),
assertEqArray(/[^\W]/iu.exec("\u212A"),
["\u212A"]);
assertEq(/\W/iu.exec("k"),
null);
assertEq(/\W/iu.exec("k"),
null);
assertEq(/\W/iu.exec("\u212A"),
null);
assertEq(/[^\w]/iu.exec("k"),
null);
assertEq(/[^\w]/iu.exec("k"),
null);
assertEq(/[^\w]/iu.exec("\u212A"),
null);
if (typeof reportCompare === "function")
reportCompare(true, true);

Просмотреть файл

@ -20,7 +20,6 @@ function test()
printBugNumber(BUGNUMBER);
printStatus (summary);
jit(true);
try
{
@ -40,11 +39,9 @@ function test()
var x; while (x = popArrs[a].pop()) { }
}
jit(false);
}
catch(ex)
{
jit(false);
actual = ex + '';
}

Просмотреть файл

@ -44,12 +44,10 @@ function test()
}
}
jit(true);
gc();
print("Size\t\Rep.\t\Literal\tnew Arr\tArray()");
print("====\t=====\t=======\t=======\t=======");
main();
jit(false);
reportCompare(expect, actual, summary);

Просмотреть файл

@ -22,10 +22,8 @@ function test()
actual += 'iI\u0130'.replace(/[\u0130]/gi, '#');
actual += ',' + 'iI\u0130'.replace(/\u0130/gi, '#');
jit(true);
actual += ';' + 'iI\u0130'.replace(/[\u0130]/gi, '#');
actual += ',' + 'iI\u0130'.replace(/\u0130/gi, '#');
jit(false);
reportCompare(expect, actual, summary);

Просмотреть файл

@ -14,7 +14,6 @@ var expect = 'No Crash';
printBugNumber(BUGNUMBER);
printStatus (summary);
jit(true);
/************************ BROWSER DETECT (http://www.quirksmode.org/js/detect.html) ************************/
@ -111,6 +110,5 @@ var BrowserDetect = {
BrowserDetect.init();
jit(false);
reportCompare(expect, actual, summary);

Просмотреть файл

@ -24,7 +24,6 @@ function test()
var global;
jit(true);
if (typeof window == 'undefined') {
global = this;
@ -59,7 +58,6 @@ function test()
}
jit(false);
reportCompare(expect, actual, summary);

Просмотреть файл

@ -9,7 +9,6 @@ var summary = 'Crash with JIT and json2.js';
var actual = 'No Crash';
var expect = 'No Crash';
jit(true);
/*
json2.js
@ -280,7 +279,6 @@ replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
test();
//-----------------------------------------------------------------------------
jit(false);
function test()
{

Просмотреть файл

@ -22,7 +22,6 @@ function test()
expect = 100;
jit(true);
function f(i) {
for (var m = 0; m < 20; ++m)
@ -33,15 +32,12 @@ function test()
print(actual = f(1));
jit(false);
reportCompare(expect, actual, summary);
jit(true);
print(actual = f(.5));
jit(false);
reportCompare(expect, actual, summary);

Просмотреть файл

@ -21,7 +21,6 @@ function test()
printBugNumber(BUGNUMBER);
printStatus (summary);
jit(true);
function f() {
for (var i = 0; i < 200000; i++) {
@ -31,7 +30,6 @@ function test()
}
f();
jit(false);
reportCompare(expect, actual, summary);

Просмотреть файл

@ -22,11 +22,9 @@ function test()
print('This test is only valid with SELinux targetted policy with exeheap protection');
jit(true);
var i; for (i = 0; i < 2000000; i++) {;}
jit(false);
reportCompare(expect, actual, summary);

Просмотреть файл

@ -20,7 +20,6 @@ function test()
printBugNumber(BUGNUMBER);
printStatus (summary);
jit(true);
// regression test for Bug 452008 - TM: SRP in Clipperz crypto library fails when JIT (TraceMonkey) is enabled.
@ -142,7 +141,6 @@ function test()
}
print(passed);
jit(false);
expect = true;
actual = passed;

Просмотреть файл

@ -19,11 +19,9 @@ function test()
printBugNumber(BUGNUMBER);
printStatus (summary);
jit(true);
for (var j = 0; j < 4; ++j) { (-0).toString(); }
jit(false);
reportCompare(expect, actual, summary);

Просмотреть файл

@ -19,11 +19,9 @@ function test()
printBugNumber(BUGNUMBER);
printStatus (summary);
jit(true);
(function() { for (var j = 0; j < 5; ++j) { (typeof 3/0); } })();
jit(false);
reportCompare(expect, actual, summary);

Просмотреть файл

@ -19,11 +19,9 @@ function test()
printBugNumber(BUGNUMBER);
printStatus (summary);
jit(true);
for (var j = 0; j < 4; ++j) { [1].x++; }
jit(false);
reportCompare(expect, actual, summary);

Просмотреть файл

@ -12,10 +12,8 @@ var expect = 'No Crash';
printBugNumber(BUGNUMBER);
printStatus (summary);
jit(true);
for (var j = 0; j < 4; ++j) { try { new 1(this); } catch(e) { } }
jit(false);
reportCompare(expect, actual, summary);

Просмотреть файл

@ -19,11 +19,9 @@ function test()
printBugNumber(BUGNUMBER);
printStatus (summary);
jit(true);
for(var j=0;j<5;++j) typeof void /x/;
jit(false);
reportCompare(expect, actual, summary);

Просмотреть файл

@ -19,11 +19,9 @@ function test()
printBugNumber(BUGNUMBER);
printStatus (summary);
jit(true);
for(var j=0;j<5;++j) typeof void 1;
jit(false);
reportCompare(expect, actual, summary);

Просмотреть файл

@ -19,11 +19,9 @@ function test()
printBugNumber(BUGNUMBER);
printStatus (summary);
jit(true);
for (var j = 0; j < 5; ++j) { if (''[-1]) { } }
jit(false);
reportCompare(expect, actual, summary);

Просмотреть файл

@ -19,11 +19,9 @@ function test()
printBugNumber(BUGNUMBER);
printStatus (summary);
jit(true);
(function() { for (var j=0;j<5;++j) { (0/0) in this; } })()
jit(false);
reportCompare(expect, actual, summary);

Просмотреть файл

@ -19,11 +19,9 @@ function test()
printBugNumber(BUGNUMBER);
printStatus (summary);
jit(true);
for (var j=0;j<5;++j) { (0/0) in this; }
jit(false);
reportCompare(expect, actual, summary);

Просмотреть файл

@ -19,11 +19,9 @@ function test()
printBugNumber(BUGNUMBER);
printStatus (summary);
jit(true);
for (var j=0; j<4; ++j) { var a = ["", ""]; a[0] * a[1]; }
jit(false);
reportCompare(expect, actual, summary);

Просмотреть файл

@ -19,11 +19,9 @@ function test()
printBugNumber(BUGNUMBER);
printStatus (summary);
jit(true);
for (var j=0;j<5;++j) { switch(1.1) { case NaN: case 2: } }
jit(false);
reportCompare(expect, actual, summary);

Просмотреть файл

@ -19,11 +19,9 @@ function test()
printBugNumber(BUGNUMBER);
printStatus (summary);
jit(true);
for (var j=0;j<5;++j) { switch(1.1) { case 2: case NaN: } }
jit(false);
reportCompare(expect, actual, summary);

Просмотреть файл

@ -21,11 +21,9 @@ function test()
var i;
jit(true);
for(i=0;i<4;++i) [,];
jit(false);
reportCompare(expect, actual, summary);

Просмотреть файл

@ -20,7 +20,6 @@ function test()
printBugNumber(BUGNUMBER);
printStatus (summary);
jit(true);
function computeEscapeSpeed(real) {
for (var j = 1; j < 4; ++j) {
@ -40,7 +39,6 @@ function test()
}
}
jit(false);
reportCompare(expect, actual, summary);

Просмотреть файл

@ -19,11 +19,9 @@ function test()
printBugNumber(BUGNUMBER);
printStatus (summary);
jit(true);
(function() { for (var j = 0; j < 5; ++j) { (1).hasOwnProperty(""); } })();
jit(false);
reportCompare(expect, actual, summary);

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше