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
nsJSContext::GarbageCollectNow(js::gcreason::DOM_UTILS);
nsJSContext::GarbageCollectNow(js::gcreason::DOM_UTILS, nsGCNormal, true);
nsJSContext::CycleCollectNow(aListener, aExtraForgetSkippableCalls);
return NS_OK;

View File

@ -135,6 +135,8 @@ static PRLogModuleInfo* gJSDiagnostics;
// doing the first GC.
#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)
// and doing the actual CC.
#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
static nsITimer *sGCTimer;
static nsITimer *sFullGCTimer;
static nsITimer *sShrinkGCBuffersTimer;
static nsITimer *sCCTimer;
@ -166,6 +169,7 @@ static bool sLoadingInProgress;
static PRUint32 sCCollectedWaitingForGC;
static bool sPostGCEventsToConsole;
static bool sDisableExplicitCompartmentGC;
static PRUint32 sCCTimerFireCount = 0;
static PRUint32 sMinForgetSkippableTime = PR_UINT32_MAX;
static PRUint32 sMaxForgetSkippableTime = 0;
@ -173,9 +177,15 @@ static PRUint32 sTotalForgetSkippableTime = 0;
static PRUint32 sRemovedPurples = 0;
static PRUint32 sForgetSkippableBeforeCC = 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;
PRUint32 nsJSContext::sGlobalGCEpoch = 0;
nsScriptNameSpaceManager *gNameSpaceManager;
static nsIJSRuntimeService *sRuntimeService;
@ -216,7 +226,8 @@ nsMemoryPressureObserver::Observe(nsISupports* aSubject, const char* aTopic,
const PRUnichar* aData)
{
if (sGCOnMemoryPressure) {
nsJSContext::GarbageCollectNow(js::gcreason::MEM_PRESSURE, nsGCShrinking);
nsJSContext::GarbageCollectNow(js::gcreason::MEM_PRESSURE, nsGCShrinking,
true);
nsJSContext::CycleCollectNow();
}
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_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_disable_explicit_compartment_gc[] =
JS_OPTIONS_DOT_STR "disable_explicit_compartment_gc";
int
nsJSContext::JSOptionChangedCallback(const char *pref, void *data)
@ -947,6 +960,8 @@ nsJSContext::JSOptionChangedCallback(const char *pref, void *data)
PRUint32 newDefaultJSOptions = oldDefaultJSOptions;
sPostGCEventsToConsole = Preferences::GetBool(js_memlog_option_str);
sDisableExplicitCompartmentGC =
Preferences::GetBool(js_disable_explicit_compartment_gc);
bool strict = Preferences::GetBool(js_strict_option_str);
if (strict)
@ -1048,6 +1063,9 @@ nsJSContext::JSOptionChangedCallback(const char *pref, void *data)
nsJSContext::nsJSContext(JSRuntime *aRuntime)
: mGCOnDestruction(true),
mChromeComp(false),
mGlobalGCEpoch(0),
mEvaluationCount(0),
mExecuteDepth(0)
{
@ -1098,6 +1116,9 @@ nsJSContext::~nsJSContext()
DestroyJSContext();
--sContextCount;
if (sTopEvaluator == this) {
sTopEvaluator = nsnull;
}
if (!sContextCount && sDidShutdown) {
// The last context is being deleted, and we're already in the
@ -1124,6 +1145,7 @@ nsJSContext::DestroyJSContext()
js_options_dot_str, this);
if (mGCOnDestruction) {
sContextDeleted = true;
PokeGC(js::gcreason::NSJSCONTEXT_DESTROY);
}
@ -2237,6 +2259,7 @@ nsJSContext::CreateNativeGlobalForInner(
{
nsIXPConnect *xpc = nsContentUtils::XPConnect();
PRUint32 flags = aIsChrome? nsIXPConnect::FLAG_SYSTEM_GLOBAL_OBJECT : 0;
mChromeComp = aIsChrome;
nsCOMPtr<nsIPrincipal> systemPrincipal;
if (aIsChrome) {
@ -3159,6 +3182,12 @@ nsJSContext::ScriptEvaluated(bool aTerminated)
if (aTerminated && mExecuteDepth == 0 && !JS_IsRunning(mContext)) {
mOperationCallbackTime = 0;
mModalStateTime = 0;
IncreaseEvaluationCount(this);
if (EvaluationCount(sTopEvaluator) < EvaluationCount(this) &&
(!mChromeComp || !sPreviousWasChromeCompGC)) {
sTopEvaluator = this;
}
}
}
@ -3231,9 +3260,20 @@ nsJSContext::ScriptExecuted()
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
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);
SAMPLE_LABEL("GC", "GarbageCollectNow");
@ -3250,9 +3290,44 @@ nsJSContext::GarbageCollectNow(js::gcreason::Reason reason, PRUint32 gckind)
sPendingLoadCount = 0;
sLoadingInProgress = false;
if (nsContentUtils::XPConnect()) {
nsContentUtils::XPConnect()->GarbageCollect(reason, gckind);
if (!nsContentUtils::XPConnect()) {
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
@ -3356,7 +3431,8 @@ GCTimerFired(nsITimer *aTimer, void *aClosure)
NS_RELEASE(sGCTimer);
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
@ -3524,6 +3600,16 @@ nsJSContext::KillGCTimer()
}
}
void
nsJSContext::KillFullGCTimer()
{
if (sFullGCTimer) {
sFullGCTimer->Cancel();
NS_RELEASE(sFullGCTimer);
}
}
//static
void
nsJSContext::KillShrinkGCBuffersTimer()
@ -3552,8 +3638,8 @@ nsJSContext::GC(js::gcreason::Reason aReason)
PokeGC(aReason);
}
static void
DOMGCFinishedCallback(JSRuntime *rt, JSCompartment *comp, const char *status)
void
nsJSContext::DOMGCFinishedCallback(JSRuntime *rt, JSCompartment *comp, const char *status)
{
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;
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 we were waiting for a GC to happen, kill the timer.
nsJSContext::KillGCTimer();
@ -3699,13 +3798,14 @@ void
nsJSRuntime::Startup()
{
// initialize all our statics, so that we can restart XPCOM
sGCTimer = sCCTimer = nsnull;
sGCTimer = sFullGCTimer = sCCTimer = nsnull;
sGCHasRun = false;
sLastCCEndTime = 0;
sPendingLoadCount = 0;
sLoadingInProgress = false;
sCCollectedWaitingForGC = 0;
sPostGCEventsToConsole = false;
sDisableExplicitCompartmentGC = false;
gNameSpaceManager = nsnull;
sRuntimeService = 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.
NS_ASSERTION(NS_IsMainThread(), "bad");
::JS_SetGCFinishedCallback(sRuntime, DOMGCFinishedCallback);
::JS_SetGCFinishedCallback(sRuntime, nsJSContext::DOMGCFinishedCallback);
JSSecurityCallbacks *callbacks = JS_GetRuntimeSecurityCallbacks(sRuntime);
NS_ASSERTION(callbacks, "SecMan should have set security callbacks!");
@ -3947,6 +4047,7 @@ void
nsJSRuntime::Shutdown()
{
nsJSContext::KillGCTimer();
nsJSContext::KillFullGCTimer();
nsJSContext::KillShrinkGCBuffersTimer();
nsJSContext::KillCCTimer();

View File

@ -181,7 +181,9 @@ public:
static void LoadStart();
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();
// If aExtraForgetSkippableCalls is -1, forgetSkippable won't be
// called even if the previous collection was GC.
@ -190,6 +192,7 @@ public:
static void PokeGC(js::gcreason::Reason aReason);
static void KillGCTimer();
static void KillFullGCTimer();
static void PokeShrinkGCBuffers();
static void KillShrinkGCBuffersTimer();
@ -208,6 +211,29 @@ public:
JSObject* global = JS_GetGlobalObject(mContext);
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:
nsresult InitializeExternalClasses();
@ -296,7 +322,9 @@ private:
bool mScriptsEnabled;
bool mGCOnDestruction;
bool mProcessingScriptTag;
bool mChromeComp;
PRUint32 mGlobalGCEpoch;
PRUint32 mEvaluationCount;
PRUint32 mExecuteDepth;
PRUint32 mDefaultJSOptions;
PRTime mOperationCallbackTime;
@ -308,6 +336,8 @@ private:
// context does. It is eventually collected by the cycle collector.
nsCOMPtr<nsIScriptGlobalObject> mGlobalObjectRef;
static PRUint32 sGlobalGCEpoch;
static int JSOptionChangedCallback(const char *pref, void *data);
static JSBool DOMOperationCallback(JSContext *cx);

View File

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

View File

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

View File

@ -47,7 +47,7 @@ Cu.import("resource://gre/modules/Services.jsm");
var 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 =
Components.ID("{2d831c8d-6017-435b-a80c-e5d422810cea}");
@ -241,7 +241,9 @@ RadioInterfaceLayer.prototype = {
handleCallStateChange: function handleCallStateChange(call) {
debug("handleCallStateChange: " + JSON.stringify(call));
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._activeCall = call;
}

View File

@ -62,7 +62,7 @@
"use strict";
importScripts("ril_consts.js");
importScripts("ril_consts.js", "systemlibs.js");
let DEBUG = false;
@ -72,6 +72,8 @@ const UINT16_SIZE = 2;
const UINT32_SIZE = 4;
const PARCEL_SIZE_SIZE = UINT32_SIZE;
let RILQUIRKS_CALLSTATE_EXTRA_UINT32 = false;
/**
* This object contains helpers buffering incoming data & deconstructing it
* into parcels as well as buffering outgoing data & constructing parcels.
@ -432,7 +434,6 @@ let Buf = {
/**
* Process one parcel.
*/
processParcel: function processParcel() {
let response_type = this.readUint32();
let length = this.readIncoming - UINT32_SIZE;
@ -445,20 +446,24 @@ let Buf = {
request_type = this.tokenRequestMap[token];
if (error) {
//TODO
if (DEBUG) {
debug("Received error " + error + " for solicited parcel type " +
request_type);
}
return;
}
if (DEBUG) {
debug("Solicited response for request type " + request_type +
", token " + token);
}
delete this.tokenRequestMap[token];
this.lastSolicitedToken = token;
} else if (response_type == RESPONSE_TYPE_UNSOLICITED) {
request_type = this.readUint32();
length -= UINT32_SIZE;
debug("Unsolicited response for request type " + request_type);
if (DEBUG) debug("Unsolicited response for request type " + request_type);
} else {
debug("Unknown response type: " + response_type);
if (DEBUG) debug("Unknown response type: " + response_type);
return;
}
@ -483,9 +488,8 @@ let Buf = {
},
/**
* Communication with the RIL IPC thread.
* Communicate with the RIL IPC thread.
*/
sendParcel: function sendParcel() {
// 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
@ -496,7 +500,7 @@ let Buf = {
// This assumes that postRILMessage will make a copy of the ArrayBufferView
// right away!
let parcel = this.outgoingBytes.subarray(0, this.outgoingIndex);
debug("Outgoing parcel: " + Array.slice(parcel));
if (DEBUG) debug("Outgoing parcel: " + Array.slice(parcel));
postRILMessage(parcel);
this.outgoingIndex = PARCEL_SIZE_SIZE;
},
@ -516,6 +520,25 @@ let Buf = {
*/
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.
*
@ -865,7 +888,7 @@ let RIL = {
handleParcel: function handleParcel(request_type, length) {
let method = this[request_type];
if (typeof method == "function") {
debug("Handling parcel as " + method.name);
if (DEBUG) debug("Handling parcel as " + method.name);
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_ENTER_NETWORK_DEPERSONALIZATION] = null;
RIL[REQUEST_GET_CURRENT_CALLS] = function REQUEST_GET_CURRENT_CALLS(length) {
if (!this.rilQuirksInitialized) {
this.initRILQuirks();
}
let calls_length = 0;
// 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.
@ -928,22 +955,24 @@ RIL[REQUEST_GET_CURRENT_CALLS] = function REQUEST_GET_CURRENT_CALLS(length) {
let calls = {};
for (let i = 0; i < calls_length; i++) {
let call = {
state: Buf.readUint32(), // CALL_STATE_*
callIndex: Buf.readUint32(), // GSM index (1-based)
toa: Buf.readUint32(),
isMpty: Boolean(Buf.readUint32()),
isMT: Boolean(Buf.readUint32()),
als: Buf.readUint32(),
isVoice: Boolean(Buf.readUint32()),
isVoicePrivacy: Boolean(Buf.readUint32()),
somethingOrOther: Buf.readUint32(), //XXX TODO whatziz? not in ril.h, but it's in the output...
number: Buf.readString(), //TODO munge with TOA
numberPresentation: Buf.readUint32(), // CALL_PRESENTATION_*
name: Buf.readString(),
namePresentation: Buf.readUint32(),
uusInfo: null
};
let call = {};
call.state = Buf.readUint32(); // CALL_STATE_*
call.callIndex = Buf.readUint32(); // GSM index (1-based)
call.toa = Buf.readUint32();
call.isMpty = Boolean(Buf.readUint32());
call.isMT = Boolean(Buf.readUint32());
call.als = Buf.readUint32();
call.isVoice = Boolean(Buf.readUint32());
call.isVoicePrivacy = Boolean(Buf.readUint32());
if (RILQUIRKS_CALLSTATE_EXTRA_UINT32) {
Buf.readUint32();
}
call.number = Buf.readString(); //TODO munge with TOA
call.numberPresentation = Buf.readUint32(); // CALL_PRESENTATION_*
call.name = Buf.readString();
call.namePresentation = Buf.readUint32();
call.uusInfo = null;
let uusInfoPresent = Buf.readUint32();
if (uusInfoPresent == 1) {
call.uusInfo = {
@ -952,6 +981,7 @@ RIL[REQUEST_GET_CURRENT_CALLS] = function REQUEST_GET_CURRENT_CALLS(length) {
userData: null //XXX TODO byte array?!?
};
}
calls[call.callIndex] = call;
}
Phone.onCurrentCalls(calls);
@ -1218,9 +1248,6 @@ RIL[UNSOLICITED_RESEND_INCALL_MUTE] = null;
*/
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.
*/
@ -1313,7 +1340,9 @@ let Phone = {
*/
onRadioStateChanged: function onRadioStateChanged(newState) {
if (DEBUG) {
debug("Radio state changed from " + this.radioState + " to " + newState);
}
if (this.radioState == newState) {
// No change in state, return.
return;
@ -1455,7 +1484,7 @@ let Phone = {
},
onNetworkStateChanged: function onNetworkStateChanged() {
debug("Network state changed, re-requesting phone state.");
if (DEBUG) debug("Network state changed, re-requesting phone state.");
this.requestNetworkInfo();
},

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_WORKER) \
D(INTER_SLICE_GC) \
D(REFRESH_FRAME)
D(REFRESH_FRAME) \
D(FULL_GC_TIMER)
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
#
# 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
try:
import json
@ -8,41 +14,49 @@ import re
import urllib2
import urlparse
import sys
import os
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.add_option("--talos-json-url", dest="talos_json_url", type="string",
help="It indicates from where to download the talos.json file.")
(options, args) = parser.parse_args()
# 1) check that the url was passed
if options.talos_json_url == None:
print "You need to specify --talos-json-url."
sys.exit(1)
# json file with info on which talos.zip to use
# the json file URL should look like this:
# %(repo_path)s/raw-file/%(revision)s/testing/talos/talos.json
# 2) try to download the talos.json file
try:
jsonFilename = download_file(options.talos_json_url)
except Exception, e:
print "ERROR: We have been unable to download the talos.zip indicated " + \
"in the talos.json file."
print "ERROR: We tried to download the talos.json file but something failed."
print "ERROR: %s" % str(e)
sys.exit(1)
# 3) download the necessary files
print "INFO: talos.json URL: %s" % options.talos_json_url
talos_zip_url = get_value(jsonFilename, "talos_zip")
print "INFO: talos.zip URL: '%s'" % talos_zip_url
try:
if passesRestrictions(options.talos_json_url, talos_zip_url) == False:
print "ERROR: You have tried to download a talos.zip from a location " + \
"different than http://build.mozilla.org/talos/zips"
print "ERROR: This is only allowed for the 'try' branch."
for key in ('talos.zip', 'pageloader.xpi',):
entity = get_value(jsonFilename, key)
if passesRestrictions(options.talos_json_url, entity["url"]):
# the key is at the same time the filename e.g. talos.zip
download_file(entity["url"], entity["path"], key)
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)
download_file(talos_zip_url, "talos.zip")
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)
sys.exit(1)
@ -73,15 +87,21 @@ def get_filename_from_url(url):
"but the URL seems to be incorrect."
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
a different name if needed.
It downloads a file from URL to the indicated path
'''
req = urllib2.Request(url)
filename = get_filename_from_url(url)
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.close()
return filename

View File

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

View File

@ -72,7 +72,6 @@ _TEST_FILES = findbar_window.xul \
test_bug570192.xul \
test_bug624329.xul \
bug624329_window.xul \
test_bug649840.xul \
test_popup_preventdefault_chrome.xul \
window_popup_preventdefault_chrome.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>