Merge mozilla-central to inbound

This commit is contained in:
Matt Brubeck 2012-02-02 20:49:06 -08:00
commit 41d849e98d
15 changed files with 355 additions and 141 deletions

View File

@ -318,3 +318,12 @@ nsBrowserAccess.prototype = {
} }
}; };
// Pipe `console` log messages to the nsIConsoleService which writes them
// to logcat.
Services.obs.addObserver(function onConsoleAPILogEvent(subject, topic, data) {
let message = subject.wrappedJSObject;
let prefix = "Content JS " + message.level.toUpperCase() +
" at " + message.filename + ":" + message.lineNumber +
" in " + (message.functionName || "anonymous") + ": ";
Services.console.logStringMessage(prefix + Array.join(message.arguments, " "));
}, "console-api-log-event", false);

View File

@ -817,7 +817,7 @@ nsDOMWindowUtils::GarbageCollect(nsICycleCollectorListener *aListener,
} }
#endif #endif
nsJSContext::GarbageCollectNow(js::gcreason::DOM_UTILS); nsJSContext::GarbageCollectNow(js::gcreason::DOM_UTILS, nsGCNormal, true);
nsJSContext::CycleCollectNow(aListener, aExtraForgetSkippableCalls); nsJSContext::CycleCollectNow(aListener, aExtraForgetSkippableCalls);
return NS_OK; return NS_OK;

View File

@ -135,6 +135,8 @@ static PRLogModuleInfo* gJSDiagnostics;
// doing the first GC. // doing the first GC.
#define NS_FIRST_GC_DELAY 10000 // ms #define NS_FIRST_GC_DELAY 10000 // ms
#define NS_FULL_GC_DELAY 60000 // ms
// The amount of time we wait between a request to CC (after GC ran) // The amount of time we wait between a request to CC (after GC ran)
// and doing the actual CC. // and doing the actual CC.
#define NS_CC_DELAY 5000 // ms #define NS_CC_DELAY 5000 // ms
@ -148,6 +150,7 @@ static PRLogModuleInfo* gJSDiagnostics;
// if you add statics here, add them to the list in nsJSRuntime::Startup // if you add statics here, add them to the list in nsJSRuntime::Startup
static nsITimer *sGCTimer; static nsITimer *sGCTimer;
static nsITimer *sFullGCTimer;
static nsITimer *sShrinkGCBuffersTimer; static nsITimer *sShrinkGCBuffersTimer;
static nsITimer *sCCTimer; static nsITimer *sCCTimer;
@ -166,6 +169,7 @@ static bool sLoadingInProgress;
static PRUint32 sCCollectedWaitingForGC; static PRUint32 sCCollectedWaitingForGC;
static bool sPostGCEventsToConsole; static bool sPostGCEventsToConsole;
static bool sDisableExplicitCompartmentGC;
static PRUint32 sCCTimerFireCount = 0; static PRUint32 sCCTimerFireCount = 0;
static PRUint32 sMinForgetSkippableTime = PR_UINT32_MAX; static PRUint32 sMinForgetSkippableTime = PR_UINT32_MAX;
static PRUint32 sMaxForgetSkippableTime = 0; static PRUint32 sMaxForgetSkippableTime = 0;
@ -173,9 +177,15 @@ static PRUint32 sTotalForgetSkippableTime = 0;
static PRUint32 sRemovedPurples = 0; static PRUint32 sRemovedPurples = 0;
static PRUint32 sForgetSkippableBeforeCC = 0; static PRUint32 sForgetSkippableBeforeCC = 0;
static PRUint32 sPreviousSuspectedCount = 0; static PRUint32 sPreviousSuspectedCount = 0;
static PRUint32 sCompartmentGCCount = 0;
static nsJSContext* sTopEvaluator = nsnull;
static bool sContextDeleted = false;
static bool sPreviousWasChromeCompGC = false;
static bool sCleanupSinceLastGC = true; static bool sCleanupSinceLastGC = true;
PRUint32 nsJSContext::sGlobalGCEpoch = 0;
nsScriptNameSpaceManager *gNameSpaceManager; nsScriptNameSpaceManager *gNameSpaceManager;
static nsIJSRuntimeService *sRuntimeService; static nsIJSRuntimeService *sRuntimeService;
@ -216,7 +226,8 @@ nsMemoryPressureObserver::Observe(nsISupports* aSubject, const char* aTopic,
const PRUnichar* aData) const PRUnichar* aData)
{ {
if (sGCOnMemoryPressure) { if (sGCOnMemoryPressure) {
nsJSContext::GarbageCollectNow(js::gcreason::MEM_PRESSURE, nsGCShrinking); nsJSContext::GarbageCollectNow(js::gcreason::MEM_PRESSURE, nsGCShrinking,
true);
nsJSContext::CycleCollectNow(); nsJSContext::CycleCollectNow();
} }
return NS_OK; return NS_OK;
@ -938,6 +949,8 @@ static const char js_pccounts_content_str[] = JS_OPTIONS_DOT_STR "pccounts.con
static const char js_pccounts_chrome_str[] = JS_OPTIONS_DOT_STR "pccounts.chrome"; static const char js_pccounts_chrome_str[] = JS_OPTIONS_DOT_STR "pccounts.chrome";
static const char js_jit_hardening_str[] = JS_OPTIONS_DOT_STR "jit_hardening"; static const char js_jit_hardening_str[] = JS_OPTIONS_DOT_STR "jit_hardening";
static const char js_memlog_option_str[] = JS_OPTIONS_DOT_STR "mem.log"; static const char js_memlog_option_str[] = JS_OPTIONS_DOT_STR "mem.log";
static const char js_disable_explicit_compartment_gc[] =
JS_OPTIONS_DOT_STR "disable_explicit_compartment_gc";
int int
nsJSContext::JSOptionChangedCallback(const char *pref, void *data) nsJSContext::JSOptionChangedCallback(const char *pref, void *data)
@ -947,6 +960,8 @@ nsJSContext::JSOptionChangedCallback(const char *pref, void *data)
PRUint32 newDefaultJSOptions = oldDefaultJSOptions; PRUint32 newDefaultJSOptions = oldDefaultJSOptions;
sPostGCEventsToConsole = Preferences::GetBool(js_memlog_option_str); sPostGCEventsToConsole = Preferences::GetBool(js_memlog_option_str);
sDisableExplicitCompartmentGC =
Preferences::GetBool(js_disable_explicit_compartment_gc);
bool strict = Preferences::GetBool(js_strict_option_str); bool strict = Preferences::GetBool(js_strict_option_str);
if (strict) if (strict)
@ -1048,6 +1063,9 @@ nsJSContext::JSOptionChangedCallback(const char *pref, void *data)
nsJSContext::nsJSContext(JSRuntime *aRuntime) nsJSContext::nsJSContext(JSRuntime *aRuntime)
: mGCOnDestruction(true), : mGCOnDestruction(true),
mChromeComp(false),
mGlobalGCEpoch(0),
mEvaluationCount(0),
mExecuteDepth(0) mExecuteDepth(0)
{ {
@ -1098,6 +1116,9 @@ nsJSContext::~nsJSContext()
DestroyJSContext(); DestroyJSContext();
--sContextCount; --sContextCount;
if (sTopEvaluator == this) {
sTopEvaluator = nsnull;
}
if (!sContextCount && sDidShutdown) { if (!sContextCount && sDidShutdown) {
// The last context is being deleted, and we're already in the // The last context is being deleted, and we're already in the
@ -1124,6 +1145,7 @@ nsJSContext::DestroyJSContext()
js_options_dot_str, this); js_options_dot_str, this);
if (mGCOnDestruction) { if (mGCOnDestruction) {
sContextDeleted = true;
PokeGC(js::gcreason::NSJSCONTEXT_DESTROY); PokeGC(js::gcreason::NSJSCONTEXT_DESTROY);
} }
@ -2237,6 +2259,7 @@ nsJSContext::CreateNativeGlobalForInner(
{ {
nsIXPConnect *xpc = nsContentUtils::XPConnect(); nsIXPConnect *xpc = nsContentUtils::XPConnect();
PRUint32 flags = aIsChrome? nsIXPConnect::FLAG_SYSTEM_GLOBAL_OBJECT : 0; PRUint32 flags = aIsChrome? nsIXPConnect::FLAG_SYSTEM_GLOBAL_OBJECT : 0;
mChromeComp = aIsChrome;
nsCOMPtr<nsIPrincipal> systemPrincipal; nsCOMPtr<nsIPrincipal> systemPrincipal;
if (aIsChrome) { if (aIsChrome) {
@ -3159,6 +3182,12 @@ nsJSContext::ScriptEvaluated(bool aTerminated)
if (aTerminated && mExecuteDepth == 0 && !JS_IsRunning(mContext)) { if (aTerminated && mExecuteDepth == 0 && !JS_IsRunning(mContext)) {
mOperationCallbackTime = 0; mOperationCallbackTime = 0;
mModalStateTime = 0; mModalStateTime = 0;
IncreaseEvaluationCount(this);
if (EvaluationCount(sTopEvaluator) < EvaluationCount(this) &&
(!mChromeComp || !sPreviousWasChromeCompGC)) {
sTopEvaluator = this;
}
} }
} }
@ -3231,9 +3260,20 @@ nsJSContext::ScriptExecuted()
return NS_OK; return NS_OK;
} }
void
FullGCTimerFired(nsITimer* aTimer, void* aClosure)
{
NS_RELEASE(sFullGCTimer);
uintptr_t reason = reinterpret_cast<uintptr_t>(aClosure);
nsJSContext::GarbageCollectNow(static_cast<js::gcreason::Reason>(reason),
nsGCNormal, true);
}
//static //static
void void
nsJSContext::GarbageCollectNow(js::gcreason::Reason reason, PRUint32 gckind) nsJSContext::GarbageCollectNow(js::gcreason::Reason aReason, PRUint32 aGckind,
bool aGlobal)
{ {
NS_TIME_FUNCTION_MIN(1.0); NS_TIME_FUNCTION_MIN(1.0);
SAMPLE_LABEL("GC", "GarbageCollectNow"); SAMPLE_LABEL("GC", "GarbageCollectNow");
@ -3250,9 +3290,44 @@ nsJSContext::GarbageCollectNow(js::gcreason::Reason reason, PRUint32 gckind)
sPendingLoadCount = 0; sPendingLoadCount = 0;
sLoadingInProgress = false; sLoadingInProgress = false;
if (nsContentUtils::XPConnect()) { if (!nsContentUtils::XPConnect()) {
nsContentUtils::XPConnect()->GarbageCollect(reason, gckind); return;
} }
// Use compartment GC when we're not asked to do a shrinking GC nor
// global GC and compartment GC has been called less than 10 times after
// the previous global GC. If a top level browsing context has been
// deleted, we do a global GC.
if (!sDisableExplicitCompartmentGC &&
aGckind != nsGCShrinking && !aGlobal &&
EvaluationCount(sTopEvaluator) > 0 &&
!sContextDeleted && sCompartmentGCCount < 10) {
nsJSContext* top = sTopEvaluator;
sTopEvaluator = nsnull;
ResetEvaluationCount(top);
JSContext* cx = top->GetNativeContext();
if (cx) {
JSObject* global = top->GetNativeGlobal();
if (global) {
if (!sFullGCTimer) {
CallCreateInstance("@mozilla.org/timer;1", &sFullGCTimer);
}
if (sFullGCTimer) {
sFullGCTimer->Cancel();
js::gcreason::Reason reason = js::gcreason::FULL_GC_TIMER;
sFullGCTimer->InitWithFuncCallback(FullGCTimerFired,
reinterpret_cast<void *>(reason),
NS_FULL_GC_DELAY,
nsITimer::TYPE_ONE_SHOT);
}
JSCompartment* comp = js::GetObjectCompartment(global);
js::CompartmentGCForReason(cx, comp, aReason);
return;
}
}
}
nsContentUtils::XPConnect()->GarbageCollect(aReason, aGckind);
} }
//static //static
@ -3356,7 +3431,8 @@ GCTimerFired(nsITimer *aTimer, void *aClosure)
NS_RELEASE(sGCTimer); NS_RELEASE(sGCTimer);
uintptr_t reason = reinterpret_cast<uintptr_t>(aClosure); uintptr_t reason = reinterpret_cast<uintptr_t>(aClosure);
nsJSContext::GarbageCollectNow(static_cast<js::gcreason::Reason>(reason), nsGCNormal); nsJSContext::GarbageCollectNow(static_cast<js::gcreason::Reason>(reason),
nsGCNormal, false);
} }
void void
@ -3524,6 +3600,16 @@ nsJSContext::KillGCTimer()
} }
} }
void
nsJSContext::KillFullGCTimer()
{
if (sFullGCTimer) {
sFullGCTimer->Cancel();
NS_RELEASE(sFullGCTimer);
}
}
//static //static
void void
nsJSContext::KillShrinkGCBuffersTimer() nsJSContext::KillShrinkGCBuffersTimer()
@ -3552,8 +3638,8 @@ nsJSContext::GC(js::gcreason::Reason aReason)
PokeGC(aReason); PokeGC(aReason);
} }
static void void
DOMGCFinishedCallback(JSRuntime *rt, JSCompartment *comp, const char *status) nsJSContext::DOMGCFinishedCallback(JSRuntime *rt, JSCompartment *comp, const char *status)
{ {
NS_ASSERTION(NS_IsMainThread(), "GCs must run on the main thread"); NS_ASSERTION(NS_IsMainThread(), "GCs must run on the main thread");
@ -3579,6 +3665,19 @@ DOMGCFinishedCallback(JSRuntime *rt, JSCompartment *comp, const char *status)
sCCollectedWaitingForGC = 0; sCCollectedWaitingForGC = 0;
sCleanupSinceLastGC = false; sCleanupSinceLastGC = false;
if (!comp) {
sPreviousWasChromeCompGC = false;
sContextDeleted = false;
sCompartmentGCCount = 0;
++sGlobalGCEpoch;
KillFullGCTimer();
} else {
// Only every other compartment GC is allowed to collect a chrome
// compartment. Otherwise we'd collect chrome compartment all the time.
sPreviousWasChromeCompGC = xpc::AccessCheck::isChrome(comp);
++sCompartmentGCCount;
}
if (sGCTimer) { if (sGCTimer) {
// If we were waiting for a GC to happen, kill the timer. // If we were waiting for a GC to happen, kill the timer.
nsJSContext::KillGCTimer(); nsJSContext::KillGCTimer();
@ -3699,13 +3798,14 @@ void
nsJSRuntime::Startup() nsJSRuntime::Startup()
{ {
// initialize all our statics, so that we can restart XPCOM // initialize all our statics, so that we can restart XPCOM
sGCTimer = sCCTimer = nsnull; sGCTimer = sFullGCTimer = sCCTimer = nsnull;
sGCHasRun = false; sGCHasRun = false;
sLastCCEndTime = 0; sLastCCEndTime = 0;
sPendingLoadCount = 0; sPendingLoadCount = 0;
sLoadingInProgress = false; sLoadingInProgress = false;
sCCollectedWaitingForGC = 0; sCCollectedWaitingForGC = 0;
sPostGCEventsToConsole = false; sPostGCEventsToConsole = false;
sDisableExplicitCompartmentGC = false;
gNameSpaceManager = nsnull; gNameSpaceManager = nsnull;
sRuntimeService = nsnull; sRuntimeService = nsnull;
sRuntime = nsnull; sRuntime = nsnull;
@ -3862,7 +3962,7 @@ nsJSRuntime::Init()
// Let's make sure that our main thread is the same as the xpcom main thread. // Let's make sure that our main thread is the same as the xpcom main thread.
NS_ASSERTION(NS_IsMainThread(), "bad"); NS_ASSERTION(NS_IsMainThread(), "bad");
::JS_SetGCFinishedCallback(sRuntime, DOMGCFinishedCallback); ::JS_SetGCFinishedCallback(sRuntime, nsJSContext::DOMGCFinishedCallback);
JSSecurityCallbacks *callbacks = JS_GetRuntimeSecurityCallbacks(sRuntime); JSSecurityCallbacks *callbacks = JS_GetRuntimeSecurityCallbacks(sRuntime);
NS_ASSERTION(callbacks, "SecMan should have set security callbacks!"); NS_ASSERTION(callbacks, "SecMan should have set security callbacks!");
@ -3947,6 +4047,7 @@ void
nsJSRuntime::Shutdown() nsJSRuntime::Shutdown()
{ {
nsJSContext::KillGCTimer(); nsJSContext::KillGCTimer();
nsJSContext::KillFullGCTimer();
nsJSContext::KillShrinkGCBuffersTimer(); nsJSContext::KillShrinkGCBuffersTimer();
nsJSContext::KillCCTimer(); nsJSContext::KillCCTimer();

View File

@ -181,7 +181,9 @@ public:
static void LoadStart(); static void LoadStart();
static void LoadEnd(); static void LoadEnd();
static void GarbageCollectNow(js::gcreason::Reason reason, PRUint32 gckind = nsGCNormal); static void GarbageCollectNow(js::gcreason::Reason aReason,
PRUint32 aGckind,
bool aGlobal);
static void ShrinkGCBuffersNow(); static void ShrinkGCBuffersNow();
// If aExtraForgetSkippableCalls is -1, forgetSkippable won't be // If aExtraForgetSkippableCalls is -1, forgetSkippable won't be
// called even if the previous collection was GC. // called even if the previous collection was GC.
@ -190,6 +192,7 @@ public:
static void PokeGC(js::gcreason::Reason aReason); static void PokeGC(js::gcreason::Reason aReason);
static void KillGCTimer(); static void KillGCTimer();
static void KillFullGCTimer();
static void PokeShrinkGCBuffers(); static void PokeShrinkGCBuffers();
static void KillShrinkGCBuffersTimer(); static void KillShrinkGCBuffersTimer();
@ -208,6 +211,29 @@ public:
JSObject* global = JS_GetGlobalObject(mContext); JSObject* global = JS_GetGlobalObject(mContext);
return global ? mGlobalObjectRef.get() : nsnull; return global ? mGlobalObjectRef.get() : nsnull;
} }
static PRUint32 EvaluationCount(nsJSContext* aCx)
{
return aCx && aCx->mGlobalGCEpoch == sGlobalGCEpoch ?
aCx->mEvaluationCount : 0;
}
static void IncreaseEvaluationCount(nsJSContext* aCx)
{
if (aCx->mGlobalGCEpoch != sGlobalGCEpoch) {
aCx->mEvaluationCount = 0;
aCx->mGlobalGCEpoch = sGlobalGCEpoch;
}
++(aCx->mEvaluationCount);
}
static void ResetEvaluationCount(nsJSContext* aCx)
{
aCx->mEvaluationCount = 0;
}
static void DOMGCFinishedCallback(JSRuntime* aRt, JSCompartment* aComp,
const char* aStatus);
protected: protected:
nsresult InitializeExternalClasses(); nsresult InitializeExternalClasses();
@ -296,7 +322,9 @@ private:
bool mScriptsEnabled; bool mScriptsEnabled;
bool mGCOnDestruction; bool mGCOnDestruction;
bool mProcessingScriptTag; bool mProcessingScriptTag;
bool mChromeComp;
PRUint32 mGlobalGCEpoch;
PRUint32 mEvaluationCount;
PRUint32 mExecuteDepth; PRUint32 mExecuteDepth;
PRUint32 mDefaultJSOptions; PRUint32 mDefaultJSOptions;
PRTime mOperationCallbackTime; PRTime mOperationCallbackTime;
@ -308,6 +336,8 @@ private:
// context does. It is eventually collected by the cycle collector. // context does. It is eventually collected by the cycle collector.
nsCOMPtr<nsIScriptGlobalObject> mGlobalObjectRef; nsCOMPtr<nsIScriptGlobalObject> mGlobalObjectRef;
static PRUint32 sGlobalGCEpoch;
static int JSOptionChangedCallback(const char *pref, void *data); static int JSOptionChangedCallback(const char *pref, void *data);
static JSBool DOMOperationCallback(JSContext *cx); static JSBool DOMOperationCallback(JSContext *cx);

View File

@ -800,14 +800,14 @@ ContentChild::GetIndexedDBPath()
bool bool
ContentChild::RecvGarbageCollect() ContentChild::RecvGarbageCollect()
{ {
nsJSContext::GarbageCollectNow(js::gcreason::DOM_IPC); nsJSContext::GarbageCollectNow(js::gcreason::DOM_IPC, nsGCNormal, true);
return true; return true;
} }
bool bool
ContentChild::RecvCycleCollect() ContentChild::RecvCycleCollect()
{ {
nsJSContext::GarbageCollectNow(js::gcreason::DOM_IPC); nsJSContext::GarbageCollectNow(js::gcreason::DOM_IPC, nsGCNormal, true);
nsJSContext::CycleCollectNow(); nsJSContext::CycleCollectNow();
return true; return true;
} }

View File

@ -83,6 +83,7 @@ EXTRA_COMPONENTS = \
EXTRA_JS_MODULES = \ EXTRA_JS_MODULES = \
ril_consts.js \ ril_consts.js \
ril_worker.js \ ril_worker.js \
systemlibs.js \
$(NULL) $(NULL)
include $(topsrcdir)/config/rules.mk include $(topsrcdir)/config/rules.mk

View File

@ -47,7 +47,7 @@ Cu.import("resource://gre/modules/Services.jsm");
var RIL = {}; var RIL = {};
Cu.import("resource://gre/modules/ril_consts.js", RIL); Cu.import("resource://gre/modules/ril_consts.js", RIL);
const DEBUG = true; // set to false to suppress debug messages const DEBUG = false; // set to true to see debug messages
const RADIOINTERFACELAYER_CID = const RADIOINTERFACELAYER_CID =
Components.ID("{2d831c8d-6017-435b-a80c-e5d422810cea}"); Components.ID("{2d831c8d-6017-435b-a80c-e5d422810cea}");
@ -241,7 +241,9 @@ RadioInterfaceLayer.prototype = {
handleCallStateChange: function handleCallStateChange(call) { handleCallStateChange: function handleCallStateChange(call) {
debug("handleCallStateChange: " + JSON.stringify(call)); debug("handleCallStateChange: " + JSON.stringify(call));
call.state = convertRILCallState(call.state); call.state = convertRILCallState(call.state);
if (call.state == nsIRadioInterfaceLayer.CALL_STATE_CONNECTED) { if (call.state == nsIRadioInterfaceLayer.CALL_STATE_DIALING ||
call.state == nsIRadioInterfaceLayer.CALL_STATE_RINGING ||
call.state == nsIRadioInterfaceLayer.CALL_STATE_CONNECTED) {
// This is now the active call. // This is now the active call.
this._activeCall = call; this._activeCall = call;
} }

View File

@ -62,7 +62,7 @@
"use strict"; "use strict";
importScripts("ril_consts.js"); importScripts("ril_consts.js", "systemlibs.js");
let DEBUG = false; let DEBUG = false;
@ -72,6 +72,8 @@ const UINT16_SIZE = 2;
const UINT32_SIZE = 4; const UINT32_SIZE = 4;
const PARCEL_SIZE_SIZE = UINT32_SIZE; const PARCEL_SIZE_SIZE = UINT32_SIZE;
let RILQUIRKS_CALLSTATE_EXTRA_UINT32 = false;
/** /**
* This object contains helpers buffering incoming data & deconstructing it * This object contains helpers buffering incoming data & deconstructing it
* into parcels as well as buffering outgoing data & constructing parcels. * into parcels as well as buffering outgoing data & constructing parcels.
@ -432,7 +434,6 @@ let Buf = {
/** /**
* Process one parcel. * Process one parcel.
*/ */
processParcel: function processParcel() { processParcel: function processParcel() {
let response_type = this.readUint32(); let response_type = this.readUint32();
let length = this.readIncoming - UINT32_SIZE; let length = this.readIncoming - UINT32_SIZE;
@ -445,20 +446,24 @@ let Buf = {
request_type = this.tokenRequestMap[token]; request_type = this.tokenRequestMap[token];
if (error) { if (error) {
//TODO //TODO
debug("Received error " + error + " for solicited parcel type " + if (DEBUG) {
request_type); debug("Received error " + error + " for solicited parcel type " +
request_type);
}
return; return;
} }
debug("Solicited response for request type " + request_type + if (DEBUG) {
", token " + token); debug("Solicited response for request type " + request_type +
", token " + token);
}
delete this.tokenRequestMap[token]; delete this.tokenRequestMap[token];
this.lastSolicitedToken = token; this.lastSolicitedToken = token;
} else if (response_type == RESPONSE_TYPE_UNSOLICITED) { } else if (response_type == RESPONSE_TYPE_UNSOLICITED) {
request_type = this.readUint32(); request_type = this.readUint32();
length -= UINT32_SIZE; length -= UINT32_SIZE;
debug("Unsolicited response for request type " + request_type); if (DEBUG) debug("Unsolicited response for request type " + request_type);
} else { } else {
debug("Unknown response type: " + response_type); if (DEBUG) debug("Unknown response type: " + response_type);
return; return;
} }
@ -483,9 +488,8 @@ let Buf = {
}, },
/** /**
* Communication with the RIL IPC thread. * Communicate with the RIL IPC thread.
*/ */
sendParcel: function sendParcel() { sendParcel: function sendParcel() {
// Compute the size of the parcel and write it to the front of the parcel // Compute the size of the parcel and write it to the front of the parcel
// where we left room for it. Note that he parcel size does not include // where we left room for it. Note that he parcel size does not include
@ -496,7 +500,7 @@ let Buf = {
// This assumes that postRILMessage will make a copy of the ArrayBufferView // This assumes that postRILMessage will make a copy of the ArrayBufferView
// right away! // right away!
let parcel = this.outgoingBytes.subarray(0, this.outgoingIndex); let parcel = this.outgoingBytes.subarray(0, this.outgoingIndex);
debug("Outgoing parcel: " + Array.slice(parcel)); if (DEBUG) debug("Outgoing parcel: " + Array.slice(parcel));
postRILMessage(parcel); postRILMessage(parcel);
this.outgoingIndex = PARCEL_SIZE_SIZE; this.outgoingIndex = PARCEL_SIZE_SIZE;
}, },
@ -516,6 +520,25 @@ let Buf = {
*/ */
let RIL = { let RIL = {
/**
* Set quirk flags based on the RIL model detected. Note that this
* requires the RIL being "warmed up" first, which happens when on
* an incoming or outgoing call.
*/
rilQuirksInitialized: false,
initRILQuirks: function initRILQuirks() {
// The Samsung Galaxy S2 I-9100 radio sends an extra Uint32 in the
// call state.
let model_id = libcutils.property_get("ril.model_id");
if (DEBUG) debug("Detected RIL model " + model_id);
if (model_id == "I9100") {
if (DEBUG) debug("Enabling RILQUIRKS_CALLSTATE_EXTRA_UINT32 for I9100.");
RILQUIRKS_CALLSTATE_EXTRA_UINT32 = true;
}
this.rilQuirksInitialized = true;
},
/** /**
* Retrieve the ICC's status. * Retrieve the ICC's status.
* *
@ -865,7 +888,7 @@ let RIL = {
handleParcel: function handleParcel(request_type, length) { handleParcel: function handleParcel(request_type, length) {
let method = this[request_type]; let method = this[request_type];
if (typeof method == "function") { if (typeof method == "function") {
debug("Handling parcel as " + method.name); if (DEBUG) debug("Handling parcel as " + method.name);
method.call(this, length); method.call(this, length);
} }
} }
@ -915,6 +938,10 @@ RIL[REQUEST_CHANGE_SIM_PIN] = function REQUEST_CHANGE_SIM_PIN() {
RIL[REQUEST_CHANGE_SIM_PIN2] = null; RIL[REQUEST_CHANGE_SIM_PIN2] = null;
RIL[REQUEST_ENTER_NETWORK_DEPERSONALIZATION] = null; RIL[REQUEST_ENTER_NETWORK_DEPERSONALIZATION] = null;
RIL[REQUEST_GET_CURRENT_CALLS] = function REQUEST_GET_CURRENT_CALLS(length) { RIL[REQUEST_GET_CURRENT_CALLS] = function REQUEST_GET_CURRENT_CALLS(length) {
if (!this.rilQuirksInitialized) {
this.initRILQuirks();
}
let calls_length = 0; let calls_length = 0;
// The RIL won't even send us the length integer if there are no active calls. // The RIL won't even send us the length integer if there are no active calls.
// So only read this integer if the parcel actually has it. // So only read this integer if the parcel actually has it.
@ -928,22 +955,24 @@ RIL[REQUEST_GET_CURRENT_CALLS] = function REQUEST_GET_CURRENT_CALLS(length) {
let calls = {}; let calls = {};
for (let i = 0; i < calls_length; i++) { for (let i = 0; i < calls_length; i++) {
let call = { let call = {};
state: Buf.readUint32(), // CALL_STATE_* call.state = Buf.readUint32(); // CALL_STATE_*
callIndex: Buf.readUint32(), // GSM index (1-based) call.callIndex = Buf.readUint32(); // GSM index (1-based)
toa: Buf.readUint32(), call.toa = Buf.readUint32();
isMpty: Boolean(Buf.readUint32()), call.isMpty = Boolean(Buf.readUint32());
isMT: Boolean(Buf.readUint32()), call.isMT = Boolean(Buf.readUint32());
als: Buf.readUint32(), call.als = Buf.readUint32();
isVoice: Boolean(Buf.readUint32()), call.isVoice = Boolean(Buf.readUint32());
isVoicePrivacy: Boolean(Buf.readUint32()), call.isVoicePrivacy = Boolean(Buf.readUint32());
somethingOrOther: Buf.readUint32(), //XXX TODO whatziz? not in ril.h, but it's in the output... if (RILQUIRKS_CALLSTATE_EXTRA_UINT32) {
number: Buf.readString(), //TODO munge with TOA Buf.readUint32();
numberPresentation: Buf.readUint32(), // CALL_PRESENTATION_* }
name: Buf.readString(), call.number = Buf.readString(); //TODO munge with TOA
namePresentation: Buf.readUint32(), call.numberPresentation = Buf.readUint32(); // CALL_PRESENTATION_*
uusInfo: null call.name = Buf.readString();
}; call.namePresentation = Buf.readUint32();
call.uusInfo = null;
let uusInfoPresent = Buf.readUint32(); let uusInfoPresent = Buf.readUint32();
if (uusInfoPresent == 1) { if (uusInfoPresent == 1) {
call.uusInfo = { call.uusInfo = {
@ -952,6 +981,7 @@ RIL[REQUEST_GET_CURRENT_CALLS] = function REQUEST_GET_CURRENT_CALLS(length) {
userData: null //XXX TODO byte array?!? userData: null //XXX TODO byte array?!?
}; };
} }
calls[call.callIndex] = call; calls[call.callIndex] = call;
} }
Phone.onCurrentCalls(calls); Phone.onCurrentCalls(calls);
@ -1218,9 +1248,6 @@ RIL[UNSOLICITED_RESEND_INCALL_MUTE] = null;
*/ */
let Phone = { let Phone = {
//XXX TODO beware, this is just demo code. It's still missing
// communication with the UI thread.
/** /**
* One of the RADIO_STATE_* constants. * One of the RADIO_STATE_* constants.
*/ */
@ -1313,7 +1340,9 @@ let Phone = {
*/ */
onRadioStateChanged: function onRadioStateChanged(newState) { onRadioStateChanged: function onRadioStateChanged(newState) {
debug("Radio state changed from " + this.radioState + " to " + newState); if (DEBUG) {
debug("Radio state changed from " + this.radioState + " to " + newState);
}
if (this.radioState == newState) { if (this.radioState == newState) {
// No change in state, return. // No change in state, return.
return; return;
@ -1455,13 +1484,13 @@ let Phone = {
}, },
onNetworkStateChanged: function onNetworkStateChanged() { onNetworkStateChanged: function onNetworkStateChanged() {
debug("Network state changed, re-requesting phone state."); if (DEBUG) debug("Network state changed, re-requesting phone state.");
this.requestNetworkInfo(); this.requestNetworkInfo();
}, },
onICCStatus: function onICCStatus(iccStatus) { onICCStatus: function onICCStatus(iccStatus) {
if (DEBUG) { if (DEBUG) {
debug("iccStatus: " + JSON.stringify(iccStatus)); debug("iccStatus: " + JSON.stringify(iccStatus));
} }
this.iccStatus = iccStatus; this.iccStatus = iccStatus;

View File

@ -0,0 +1,79 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
const SYSTEM_PROPERTY_KEY_MAX = 32;
const SYSTEM_PROPERTY_VALUE_MAX = 92;
/**
* Expose some system-level functions.
*/
let libcutils = (function() {
let lib;
try {
lib = ctypes.open("libcutils.so");
} catch(ex) {
// Return a fallback option in case libcutils.so isn't present (e.g.
// when building Firefox with MOZ_B2G_RIL.
dump("Could not load libcutils.so. Using fake propdb.");
let fake_propdb = Object.create(null);
return {
property_get: function fake_property_get(key, defaultValue) {
if (key in fake_propdb) {
return fake_propdb[key];
}
return defaultValue === undefined ? null : defaultValue;
},
property_set: function fake_property_set(key, value) {
fake_propdb[key] = value;
}
};
}
let c_property_get = lib.declare("property_get", ctypes.default_abi,
ctypes.int, // return value: length
ctypes.char.ptr, // key
ctypes.char.ptr, // value
ctypes.char.ptr); // default
let c_property_set = lib.declare("property_set", ctypes.default_abi,
ctypes.int, // return value: success
ctypes.char.ptr, // key
ctypes.char.ptr); // value
let c_value_buf = ctypes.char.array(SYSTEM_PROPERTY_VALUE_MAX)();
return {
/**
* Get a system property.
*
* @param key
* Name of the property
* @param defaultValue [optional]
* Default value to return if the property isn't set (default: null)
*/
property_get: function property_get(key, defaultValue) {
if (defaultValue === undefined) {
defaultValue = null;
}
c_property_get(key, c_value_buf, defaultValue);
return c_value_buf.readString();
},
/**
* Set a system property
*
* @param key
* Name of the property
* @param value
* Value to set the property to.
*/
property_set: function property_set(key, value) {
let rv = c_property_set(key, value);
if (rv) {
throw Error('libcutils.property_set("' + key + '", "' + value +
'") failed with error ' + rv);
}
}
};
})();

View File

@ -657,7 +657,8 @@ SizeOfJSContext();
D(DOM_IPC) \ D(DOM_IPC) \
D(DOM_WORKER) \ D(DOM_WORKER) \
D(INTER_SLICE_GC) \ D(INTER_SLICE_GC) \
D(REFRESH_FRAME) D(REFRESH_FRAME) \
D(FULL_GC_TIMER)
namespace gcreason { namespace gcreason {

View File

@ -1,3 +1,10 @@
{ {
"talos_zip": "http://build.mozilla.org/talos/zips/talos.bug721857.05f01e049452.zip" "talos.zip": {
"url": "http://build.mozilla.org/talos/zips/talos.bug721857.05f01e049452.zip",
"path": ""
},
"pageloader.xpi": {
"url": "http://build.mozilla.org/talos/xpis/pageloader.xpi",
"path": "talos/page_load_test"
}
} }

View File

@ -1,4 +1,10 @@
#! /usr/bin/env python #! /usr/bin/env python
#
# Script name: talos_from_code.py
# Purpose: Read from a talos.json file the different files to download for a talos job
# Author(s): Zambrano Gasparnian, Armen <armenzg@mozilla.com>
# Target: Python 2.5
#
from optparse import OptionParser from optparse import OptionParser
try: try:
import json import json
@ -8,41 +14,49 @@ import re
import urllib2 import urllib2
import urlparse import urlparse
import sys import sys
import os
def main(): def main():
'''
This script downloads a talos.json file which indicates which files to download
for a talos job.
See a talos.json file for a better understand:
http://hg.mozilla.org/mozilla-central/raw-file/default/testing/talos/talos.json
'''
parser = OptionParser() parser = OptionParser()
parser.add_option("--talos-json-url", dest="talos_json_url", type="string", parser.add_option("--talos-json-url", dest="talos_json_url", type="string",
help="It indicates from where to download the talos.json file.") help="It indicates from where to download the talos.json file.")
(options, args) = parser.parse_args() (options, args) = parser.parse_args()
# 1) check that the url was passed
if options.talos_json_url == None: if options.talos_json_url == None:
print "You need to specify --talos-json-url." print "You need to specify --talos-json-url."
sys.exit(1) sys.exit(1)
# json file with info on which talos.zip to use # 2) try to download the talos.json file
# the json file URL should look like this:
# %(repo_path)s/raw-file/%(revision)s/testing/talos/talos.json
try: try:
jsonFilename = download_file(options.talos_json_url) jsonFilename = download_file(options.talos_json_url)
except Exception, e: except Exception, e:
print "ERROR: We have been unable to download the talos.zip indicated " + \ print "ERROR: We tried to download the talos.json file but something failed."
"in the talos.json file."
print "ERROR: %s" % str(e) print "ERROR: %s" % str(e)
sys.exit(1) sys.exit(1)
print "INFO: talos.json URL: %s" % options.talos_json_url # 3) download the necessary files
talos_zip_url = get_value(jsonFilename, "talos_zip") print "INFO: talos.json URL: %s" % options.talos_json_url
print "INFO: talos.zip URL: '%s'" % talos_zip_url
try: try:
if passesRestrictions(options.talos_json_url, talos_zip_url) == False: for key in ('talos.zip', 'pageloader.xpi',):
print "ERROR: You have tried to download a talos.zip from a location " + \ entity = get_value(jsonFilename, key)
"different than http://build.mozilla.org/talos/zips" if passesRestrictions(options.talos_json_url, entity["url"]):
print "ERROR: This is only allowed for the 'try' branch." # the key is at the same time the filename e.g. talos.zip
sys.exit(1) download_file(entity["url"], entity["path"], key)
download_file(talos_zip_url, "talos.zip") print "INFO: %s -> %s" % (entity["url"], os.path.join(entity["path"], key))
else:
print "ERROR: You have tried to download a file " + \
"from: %s " % fileUrl + \
"which is a location different than http://build.mozilla.org/talos/"
print "ERROR: This is only allowed for the certain branches."
sys.exit(1)
except Exception, e: except Exception, e:
print "ERROR: We have been unable to download the talos.zip indicated " + \
"in the talos.json file."
print "ERROR: %s" % str(e) print "ERROR: %s" % str(e)
sys.exit(1) sys.exit(1)
@ -73,15 +87,21 @@ def get_filename_from_url(url):
"but the URL seems to be incorrect." "but the URL seems to be incorrect."
sys.exit(1) sys.exit(1)
def download_file(url, saveAs=None): def download_file(url, path="", saveAs=None):
''' '''
It downloads a file from the URL indicated and can be saved locally with It downloads a file from URL to the indicated path
a different name if needed.
''' '''
req = urllib2.Request(url) req = urllib2.Request(url)
filename = get_filename_from_url(url)
f = urllib2.urlopen(req) f = urllib2.urlopen(req)
local_file = open(saveAs if saveAs else filename, 'wb') if path != "" and not os.path.isdir(path):
try:
os.makedirs(path)
print "INFO: directory %s created" % path
except Exception, e:
print "ERROR: %s" % str(e)
sys.exit(1)
filename = saveAs if saveAs else get_filename_from_url(url)
local_file = open(os.path.join(path, filename), 'wb')
local_file.write(f.read()) local_file.write(f.read())
local_file.close() local_file.close()
return filename return filename

View File

@ -12,7 +12,7 @@ Form History test: form field autocomplete
<p id="display"></p> <p id="display"></p>
<!-- we presumably can't hide the content for this test. --> <!-- we presumably can't hide the content for this test. -->
<div id="content"> <div id="content" style="direction: rtl;">
<!-- unused --> <!-- unused -->
<form id="unused" onsubmit="return false;"> <form id="unused" onsubmit="return false;">
<input type="text" name="field1" value="unused"> <input type="text" name="field1" value="unused">
@ -32,6 +32,7 @@ Form History test: form field autocomplete
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var autocompletePopup = getAutocompletePopup(); var autocompletePopup = getAutocompletePopup();
autocompletePopup.style.direction = "ltr";
var input = $_(1, "field1"); var input = $_(1, "field1");
@ -366,6 +367,7 @@ function runTest(testNum) {
case 211: case 211:
checkPopupOpen(false); checkPopupOpen(false);
checkForm(""); checkForm("");
is(autocompletePopup.style.direction, "rtl", "direction should have been changed from ltr to rtl");
SimpleTest.finish(); SimpleTest.finish();
return; return;

View File

@ -72,7 +72,6 @@ _TEST_FILES = findbar_window.xul \
test_bug570192.xul \ test_bug570192.xul \
test_bug624329.xul \ test_bug624329.xul \
bug624329_window.xul \ bug624329_window.xul \
test_bug649840.xul \
test_popup_preventdefault_chrome.xul \ test_popup_preventdefault_chrome.xul \
window_popup_preventdefault_chrome.xul \ window_popup_preventdefault_chrome.xul \
test_largemenu.xul \ test_largemenu.xul \

View File

@ -1,66 +0,0 @@
<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=649840
-->
<window title="Mozilla Bug 649840"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<textbox id="textLTR" type="autocomplete" autocompletesearch="simple"/>
<textbox id="textRTL" type="autocomplete" autocompletesearch="simple"/>
<!-- test results are displayed in the html:body -->
<body xmlns="http://www.w3.org/1999/xhtml">
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=649840"
target="_blank">Mozilla Bug 649840</a>
</body>
<!-- test code goes here -->
<script type="application/javascript">
<![CDATA[
/** Test for Bug 649840 **/
SimpleTest.waitForExplicitFinish();
addLoadEvent(runTest);
function runTest()
{
var textLTR = $("textLTR");
var textRTL = $("textRTL");
textLTR.style.direction = "ltr";
textRTL.style.direction = "rtl";
textLTR.value="abcd";
textRTL.value="ابجد";
// open and close the popups to update the popupdir attribute value
textLTR.openPopup();
textLTR.closePopup();
textRTL.openPopup();
textRTL.closePopup();
is(textLTR.popup.style.direction, textLTR.style.direction, "LTR textbox test fails");
is(textRTL.popup.style.direction, textRTL.style.direction, "RTL textbox test fails");
// switch directions of the two textboxes
textLTR.style.direction = "rtl";
textRTL.style.direction = "ltr";
// open and close the popups to update the popupdir attribute value
textLTR.openPopup();
textLTR.closePopup();
textRTL.openPopup();
textRTL.closePopup();
is(textLTR.popup.style.direction, textLTR.style.direction, "RTL-switched textbox test fails");
is(textRTL.popup.style.direction, textRTL.style.direction, "LTR-switched textbox test fails");
SimpleTest.finish();
}
]]>
</script>
</window>